如何解决计数功能评估
我刚刚完成了有关阅读器和记录器的教程。我想知道是否有一种方法可以计算每个学科的调用次数。下面,我使用全局变量来计算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,这可以帮助对案件进行后处理,以获取通话总数。
如果不清楚,请通知我!
,诸如Coverage或PyTest-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 举报,一经查实,本站将立刻删除。