我正在使用SLSQP,外部代码,显式补偿和FD区分设置三个组件的优化例程。
更具体地说,Comp2类似于抛物面示例,而Comp3只是一个线性函数。没有限制。
如果我在Comp2上使用中央FD,它会在改变之前用相同的输入值(x)评估外部代码4次,而前向FD则是两次。我模糊地理解优化器正在尝试做什么但是 重复相同的计算只是一个计算负担。
我的补救措施是使用相应的输入名称保存输出文件,并在第二次迭代中检查此文件是否存在,如果是,则跳过计算并从文件读入。这很好用。
我的问题是:
重要说明: 如果Comp2有两个输入,一个输出,则不会发生这种情况。
如果Comp2有两个输入,两个输出
,它会再次发生在前几次迭代的示例输出下面。
ExtInX = [10.], , ExtOutF = 79.0, ExtOutG = 373.0
OBJECTIVE 589362.0
----------------------------------------------------------------------
ExtInX = [10.], , ExtOutF = 79.0, ExtOutG = 373.0
OBJECTIVE 589362.0
----------------------------------------------------------------------
ExtInX = [10.], , ExtOutF = 79.0, ExtOutG = 373.0
ExtInX = [10.], , ExtOutF = 79.0, ExtOutG = 373.0
ExtInX = [10.], , ExtOutF = 79.0, ExtOutG = 373.0
ExtInX = [10.], , ExtOutF = 79.0, ExtOutG = 373.0
ExtInX = [10.000001], , ExtOutF = 79.00001700000098, ExtOutG = 373.0001500000209
ExtInX = [9.999999], , ExtOutF = 78.99998300000101, ExtOutG = 372.9998500000211
ExtInX = [8.07102609], , ExtOutF = 49.928382692675996, ExtOutG = 154.61605669448198
OBJECTIVE 250797.01369955452
----------------------------------------------------------------------
**ExtInX = [8.07102609], , ExtOutF = 49.928382692675996, ExtOutG = 154.61605669448198
ExtInX = [8.07102609], , ExtOutF = 49.928382692675996, ExtOutG = 154.61605669448198
ExtInX = [8.07102609], , ExtOutF = 49.928382692675996, ExtOutG = 154.61605669448198
ExtInX = [8.07102609], , ExtOutF = 49.928382692675996, ExtOutG = 154.61605669448198**
ExtInX = [8.07102709], , ExtOutF = 49.92839583472901, ExtOutG = 154.61613684041134
ExtInX = [8.07102509], , ExtOutF = 49.92836955062501, ExtOutG = 154.61597654858318
ExtInX = [4.88062761], , ExtOutF = 18.178645674383997, ExtOutG = 21.29321703417343
OBJECTIVE 38811.35361617729
第一次回答后
感谢您的回答。 据我所知,在2.2中,缓存必须由用户完成 人们可以用不同的方式做到这一点。这可以。
你在2.3中提到的改进似乎解决了一件事。 一开始就有一个额外的电话。我更关心的是 在迭代期间使用相同输入进行多次调用。
我在下面添加了四个代码补丁。一个人应该能够运行优化器 只要其他人在同一个文件夹中。
在这种情况下,外部代码是纯python。但同时我也是 开发一个使用'实际'外部代码。它又来了 虽然包裹在python中。因此,一些系统调用被发送到可执行文件 和python处理外部代码的输出,python做一些帖子 处理并输出由OpenMDAO外部代码读取的文本文件 零件。所以不确定那个算是纯粹的python。
关于约束:在下面的代码中没有。在其他代码中 我已经解释过,汽车零部件有一些终身限制 (例如xx,lower = 20)。
代码: Optimizer.py:驱动程序 和其他3 .py文件 https://gist.github.com/anonymous/2c9d5d182cbb24a2334c97b57a954802
答案 0 :(得分:0)
在OpenMDAO v2.2中,没有构建处理结果缓存的方法。所以你必须在那里推出自己的解决方案。您可以在内存中执行缓存,而只是存储最后的已知输入值,而不是保存完整的输出文件。如果它们没有改变,您可以将输出值保留在原来的位置。
在OpenMDAO V2.2中,驱动程序被编码为在开始优化之前进行一次额外的函数调用。这是因为OpenMDAO处理线性约束的方式。它将预先计算与线性约束相关的导数并存储它们。
在OpenMDAO V2.3中,我们修改了驱动程序,因此他们只会进行额外的调用,如果您的问题中存在线性约束。所以,至少,解释一个额外的函数调用。
在检查了测试问题之后,OpenMDAO对组件进行有限差分处理方式似乎存在错误。即使您使用正向模式,问题也会出现,并且它似乎与您声明部分的方式有关。 您声明它们的方式没有任何问题,但使用另一种声明方法我能够使其正常运行:
from openmdao.api import ExternalCode
import numpy as np
class ParaboloidExternalCode(ExternalCode):
def setup(self):
self.add_input('x', val=0.0)
self.add_input('y', val=0.0)
self.add_output('f_xy', val=0.0)
self.add_output('g_xy', val=0.0)
self.input_file = 'paraboloid_input.dat'
self.output_file = 'paraboloid_output.dat'
# providing these is optional; the component will verify that any input
# files exist before execution and that the output files exist after.
self.options['external_input_files'] = [self.input_file,]
self.options['external_output_files'] = [self.output_file,]
self.options['command'] = [
'python', 'extcode_paraboloid.py', self.input_file, self.output_file
]
# self.declare_partials(of='*', wrt='*', method='fd', form='central', step=1e-6)
self.declare_partials(of='f_xy', wrt=['x','y'], method='fd', form='central', step=1e-6)
self.declare_partials(of='g_xy', wrt=['x','y'], method='fd', form='central', step=1e-6)
def compute(self, inputs, outputs):
x = inputs['x']
y = inputs['y']
# generate the input file for the paraboloid external code
with open(self.input_file, 'w') as input_file:
input_file.write('%f\n%f\n' % (x,y))
# the parent compute function actually runs the external code
super(ParaboloidExternalCode, self).compute(inputs, outputs)
file_contents = np.loadtxt(self.output_file)
outputs['f_xy'] = file_contents [0]
outputs['g_xy'] = file_contents [1]
print('ExtInX = {}, ExtInY = {},, ExtOutF_XY = {}, ExtOutG_XY = {} '.format(x,y,file_contents [0],file_contents[1]) )
我摆脱了of='*', wrt='*'
并将其替换为两个明确命名变量的独立调用。我还能够在没有外部代码的情况下复制这个问题,使用内存中的抛物面。我已将错误输入到开发积压中,我们将整理出来。与此同时,这种解决方法解决了这个问题。
答案 1 :(得分:0)
请注意,OpenMDAO V2.2中存在导致额外评估的错误。它是通过OpenMDAO PR # 553
修复的