微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

计数功能评估

如何解决计数功能评估

我刚刚完成了有关阅读器和记录器的教程。我想知道是否有一种方法可以计算每个学科的调用次数。下面,我使用全局变量来计算Sellar问题。有什么更好的方法呢?另外,如果问题中没有求解器,建议的方式会改变吗?

import numpy as np
import time
import openmdao.api as om

tic = time.perf_counter()
dc1 = 0
dc2 = 0

class Sellardis1(om.ExplicitComponent):
    def setup(self):
        self.add_input('z',val=np.zeros(2))
        self.add_input('x',val=0.)
        self.add_input('y2',val=1.0)
        self.add_output('y1',val=1.0)
        self.declare_partials('*','*',method='fd')

    def compute(self,inputs,outputs):
        global dc1
        dc1+=1
        z1 = inputs['z'][0]
        z2 = inputs['z'][1]
        x1 = inputs['x']
        y2 = inputs['y2']
        outputs['y1'] = z1**2 + z2 + x1 - 0.2*y2

class Sellardis2(om.ExplicitComponent):

    def setup(self):
        self.add_input('z',val=np.zeros(2))
        self.add_input('y1',val=1.0)
        self.add_output('y2',outputs):
        global dc2
        dc2 +=1
        z1 = inputs['z'][0]
        z2 = inputs['z'][1]
        y1 = inputs['y1']
        if y1.real < 0.0:
            y1 *= -1
        outputs['y2'] = y1**.5 + z1 + z2

class SellarMDF(om.Group):
    def setup(self):
        indeps = self.add_subsystem('indeps',om.IndepVarComp(),promotes=['*'])
        indeps.add_output('x',1.0)
        indeps.add_output('z',np.array([5.0,2.0]))

        cycle = self.add_subsystem('cycle',om.Group(),promotes=['*'])
        cycle.add_subsystem('d1',Sellardis1(),promotes_inputs=['x','z','y2'],promotes_outputs=['y1'])
        cycle.add_subsystem('d2',Sellardis2(),promotes_inputs=['z','y1'],promotes_outputs=['y2'])

        cycle.linear_solver = om.ScipyKrylov()

        cycle.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)
        

        self.add_subsystem('obj_cmp',om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)',z=np.array([0.0,0.0]),x=0.0,y1=0.0,y2=0.0),promotes=['x','y1','y2','obj'])

        self.add_subsystem('con_cmp1',om.ExecComp('con1 = 3.16 - y1'),promotes=['con1','y1'])
        self.add_subsystem('con_cmp2',om.ExecComp('con2 = y2 - 24.0'),promotes=['con2','y2'])

prob = om.Problem()
prob.model = SellarMDF()

driver = prob.driver = om.ScipyOptimizer()
prob.driver.options['optimizer'] = 'SLSQP'

prob.model.add_design_var('x',lower=0,upper=10)
prob.model.add_design_var('z',upper=10)

prob.model.add_objective('obj')
prob.model.add_constraint('con1',upper=0)
prob.model.add_constraint('con2',upper=0)
prob.setup()
prob.set_solver_print(level=0)

prob.run_driver()

print('minimum found at')
print(prob['x'][0])
print(prob['z'])

print('coupling Variables')
print(prob['y1'][0])
print(prob['y2'][0])

print('minumum objective')
print(prob['obj'][0])

toc = time.perf_counter()
print(f"You waited {toc - tic:0.4f} seconds")
print("Function Calls")
print('Sellardis1 : ',dc1)
print('Sellardis2 : ',dc2)

编辑:更好的是,我指的是“ openmdao”方式,例如记录器之类的东西。

解决方法

所有OpenMDAO系统(组件和组的总称)具有iter_count属性。这是documentation page for System,所有组件和组均从中继承。 iter_count是对每个compute()方法的调用总数,而iter_count_without_approx是对compute()方法的调用数量,不包括由于梯度近似而产生的调用。此方法适用于任何求解器层次结构或驱动程序设置。

示例脚本的最后两行将是:

print('SellarDis1 : ',prob.model.cycle.d1.iter_count)
print('SellarDis2 : ',prob.model.cycle.d2.iter_count)

这不像您建议的那样使用记录器。如果您更喜欢使用记录器的解决方案,我们可以找到一种可行的方法。那里有很多灵活性,要开始使用,您可以签出this specific doc page on case reading,这可以帮助对案件进行后处理,以获取通话总数。

如果不清楚,请通知我!

,

诸如CoveragePyTest-Cov的覆盖工具可以在程序执行期间使用python解释器中的钩子来收集有关正在运行的代码的数据,该数据通常包括每个函数或甚至是个别行。如果您只想在程序外输入数字,那么对于您来说已经足够了。

如果您需要脚本本身中使用的数字,则可以自己使用一些基础API。使用sys.settrace,可以注册要在程序中的每个函数调用上调用的函数。该函数的第一个参数是frame object,其中包含可用于检查这是否是您感兴趣的函数的属性。

这是一个简短的例子:

import sys

class A:
    def my_func(self,x):
        return x + 1

my_func_calls = 0

def tracefunc(frame,event,arg):
    global my_func_calls
    if event == 'call' and frame.f_code.co_name == 'my_func':
        my_func_calls += 1

sys.settrace(tracefunc)

if __name__ == '__main__':
    a = A()
    x = a.my_func(0)
    x = a.my_func(x)
    x = a.my_func(x)
    print("my_func_calls:",my_func_calls)

由于我没有找到与之关联的实际函数对象的任何方法(使用__self__.__class__可以给您类,所以您可能需要使用frame.co_firstlineno来区分具有相同功能的方法名称。

此跟踪功能的细节很棘手,您可以参考coverage.py's implementation来启发您的选择和可能的问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。