Оптимизация openmdao с суррогатом в качестве одной из нескольких моделей связанных дисциплин
Я думал, что понял январскую дискуссию об использовании метамоделей в оптимизации. Но моя попытка пока не удалась. У меня есть немного поворота. Я хочу использовать метамодель одной из нескольких дисциплин, где пример, рассмотренный в январе, оптимизирован только на результатах метамодели. Я построил пример задачи на основе учебного примера по оптимизации параболоидов. Я добавил второй компонент, соединил два компонента в группе и оптимизировал его. Затем я попытался заменить один из компонентов метамоделью этого компонента. Ниже приводится версия с реальной моделью.
from __future__ import print_function
from openmdao.api import IndepVarComp, Component, Problem, Group, ExecComp, NLGaussSeidel, ScipyOptimizer, UniformDriver, DumpRecorder, InMemoryRecorder
import math
import numpy as np
class Paraboloid(Component):
""" Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3 """
def __init__(self):
super(Paraboloid, self).__init__()
self.add_param('z', val=0.0)
self.add_param('y', val=0.0)
self.add_output('f_xy', val=0.0)
def solve_nonlinear(self, params, unknowns, resids):
"""f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3
"""
x = params['z']
y = params['y']
f_xy = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0
unknowns['f_xy'] = f_xy
def linearize(self, params, unknowns, resids):
""" Jacobian for our paraboloid."""
x = params['z']
y = params['y']
J = {}
J['f_xy', 'z'] = 2.0*x - 6.0 + y
J['f_xy', 'y'] = 2.0*y + 8.0 + x
return J
class Sinx(Component):
""" Evaluates the equation f(x) = sin(x) """
def __init__(self):
super(Sinx, self).__init__()
self.C = 50.
self.add_param('x', val=0.0)
self.add_output('z', val=0.0)
def solve_nonlinear(self, params, unknowns, resids):
"""f(x) = 10.* sin(x/C)
"""
x = params['x']
sinx = math.sin(x/self.C) *10.
unknowns['z'] = sinx
def linearize(self, params, unknowns, resids):
""" Jacobian for our paraboloid."""
x = params['x']
J = {}
J['z', 'x'] = math.cos(x/self.C)/self.C *10.
return J
class Mda(Group):
def __init__(self):
super(Mda, self).__init__()
self.f1in=['x']
self.f1out=['z']
self.f2in=['z', 'y']
self.f2out=['f_xy']
self.add('x', IndepVarComp('x', 10.), promotes=['*'])
self.add('y', IndepVarComp('y', 0.), promotes=['*'])
self.add('f1', Sinx(), promotes=self.f1in+self.f1out)
self.add('f2', Paraboloid(), promotes=self.f2in+self.f2out)
self.add('obj_cmp', ExecComp('obj = f_xy'), promotes=['f_xy', 'obj'])
self.nl_solver = NLGaussSeidel()
if __name__ == "__main__":
top = Problem()
root = top.root = Mda()
top.driver = ScipyOptimizer()
top.driver.options['optimizer'] = 'SLSQP'
top.driver.add_desvar('x', lower=-50, upper=50)
top.driver.add_desvar('y', lower=-50, upper=50)
top.driver.add_objective('obj')
top.setup()
top.run()
print('obj =%f at (%f,%f)'%(top['obj'],top['x'],top['y']))
Ниже приведен класс, который, как я думал, будет работать как метамодель.
class SinxSurr(MetaModel):
''' Evaluate surrogate of Sinx '''
def __init__(self):
super(SinxSurr, self).__init__()
self.add_param('x', val=0.)
self.add_output('z', val=0., surrogate=FloatKrigingSurrogate())
И вот часть, чтобы запустить его:
if __name__ == "__main__":
# build training data by sampling
top = Problem()
root = top.root = Group()
root.add('sinx', Sinx())
root.add('p1', IndepVarComp('x', 50.0))
root.connect('p1.x', 'sinx.x')
top.driver = UniformDriver(num_samples=500)
top.driver.add_desvar('p1.x', lower=-50, upper=50)
top.driver.add_objective('sinx.z')
recorder = InMemoryRecorder()
top.driver.add_recorder(recorder)
top.setup()
top.run()
top.cleanup()
# retrieve sampling results from recorder
xlist=[]
slist=[]
for line in recorder.iters:
xlist.append(line['unknowns']['p1.x'])
slist.append(line['unknowns']['sinx.z'])
recorder.close()
if len(xlist) != len(slist):
print('Recorder parse failure')
sys.exit(1)
x=10.
top = Problem()
root = top.root = Mda()
top.driver = ScipyOptimizer()
top.driver.options['optimizer'] = 'SLSQP'
top.driver.add_desvar('x', lower=-50, upper=50)
top.driver.add_desvar('y', lower=-50, upper=50)
top.driver.add_objective('obj')
top.setup()
top.root['f1.train:x'] = xlist
top.root['f1.train:z'] = slist
top.run()
print('obj =%f at (%f,%f)'%(top['obj'],top['x'],top['y']))
Когда я запускаю его, я получаю сообщение об ошибке:
Setup: Checking for potential issues...
No recorders have been specified, so no data will be saved.
The following parameters have no associated unknowns:
f1.train:x
f1.train:z
Setup: Check complete.
##############################################
Traceback (most recent call last):
File "surrDisc.py", line 164, in <module>
top.root['f1.train:x'] = xlist
TypeError: 'Mda' object does not support item assignment
Я не понимаю, как взаимодействовать данные из метамодели с группой (по крайней мере).
1 ответ
Вы хотели переименовать переменную "z" в "z:float", когда сделали суррогат?
self.add_output('z:float', val=0., surrogate=FloatKrigingSurrogate())
Если вы хотите переименовать его, вам придется явно подключить "f1.z:float" к "f2.z", а также не включать "z" в рекламные акции, которые вы перечисляете в self.f1out
а также self.f2in
,