当我尝试为Sellar问题实现CO时,根本没有收敛,它最终违反了约束,根据下面的答案:
Minimum target found at (5.000000, 1.964134, 0.821694)
Coupling vars target: 3.514927, 1.876374
('Minimum objective: ', 6.3073869839326475)
('constraints: ', 1.4712589277025103, 5.8788877332794067)
我认为这不是优化问题,因为这是一个简单的数学挑战。但我无法确定错误。
根据初始值,当使用'FD'代替'CS'进行渐变计算时,答案为NAN。
我的代码是(OpenMDAO 1.7):
class SellarDis1(Component):
"""Component containing Discipline 1."""
def __init__(self):
super(SellarDis1, self).__init__()
# Global Design Variable
self.add_param('z', val=np.zeros(2))
# Local Design Variable
self.add_param('x', val=0.)
# Coupling parameter
self.add_param('y2', val=0.)
# Coupling output
self.add_output('y1', val=1.0)
def solve_nonlinear(self, params, unknowns, resids):
"""Evaluates the equation
y1 = z1**2 + z2 + x1 - 0.2*y2"""
z1 = params['z'][0]
z2 = params['z'][1]
x1 = params['x']
y2 = params['y2']
unknowns['y1'] = z1**2 + z2 + x1 - 0.2*y2
def linearize(self, params, unknowns, resids):
""" Jacobian for Sellar discipline 1."""
J = {}
J['y1','y2'] = -0.2
J['y1','z'] = np.array([[2*params['z'][0], 1.0]])
J['y1','x'] = 1.0
return J
class SellarDis2(Component):
"""Component containing Discipline 2."""
def __init__(self):
super(SellarDis2, self).__init__()
# Global Design Variable
self.add_param('z', val=np.zeros(2))
# Coupling parameter
self.add_param('y1', val=0.)
# Coupling output
self.add_output('y2', val=1.0)
def solve_nonlinear(self, params, unknowns, resids):
"""Evaluates the equation
y2 = y1**(.5) + z1 + z2"""
z1 = params['z'][0]
z2 = params['z'][1]
y1 = params['y1']
# Note: this may cause some issues. However, y1 is constrained to be
# above 3.16, so lets just let it converge, and the optimizer will
# throw it out
y1 = abs(y1)
unknowns['y2'] = y1**.5 + z1 + z2
def linearize(self, params, unknowns, resids):
""" Jacobian for Sellar discipline 2."""
J = {}
J['y2', 'y1'] = .5*params['y1']**-.5
J['y2', 'z'] = np.array([[1.0, 1.0]])
return J
class SubOptimization1(Component):
''' minimize differences between target and local variables of the first disipline of the sellar problem '''
def __init__(self):
super(SubOptimization1, self).__init__()
# Inputs to this subprob
self.add_param('z', val=np.array([5.0, 2.0]))
self.add_param('x', val=1.0)
self.add_param('y2', val=1.0)
self.add_param('zt', val=np.array([5.0, 2.0]))
self.add_param('xt', val=1.0)
self.add_param('y2t', val=1.0)
self.add_param('y1t', val=3.16)
# Unknowns for this sub prob
self.add_output('y1', val=1.0)
self.problem = s1prob = Problem()
s1prob.root = Group()
s1prob.root.add('p1x', IndepVarComp('x', 1.0), promotes=['x'])
s1prob.root.add('p1z', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z'])
s1prob.root.add('p1y2', IndepVarComp('y2', 1.0), promotes=['y2'])
s1prob.root.add('d1', SellarDis1(), promotes=['x','z','y2','y1'])
s1prob.root.add('obj_cmp1', ExecComp('obj1 = (xt-x)**2 + (zt[0]-z[0])**2+(zt[1]-z[1])**2+(y1t-y1)**2+(y2t-y2)**2',
z=np.array([5.0, 2.0])), promotes= ['obj1','x','z','y1','y2','xt','zt','y1t','y2t'])
self.deriv_options['type'] = 'cs'
#self.fd_options['force_fd'] = True
s1prob.driver =pyOptSparseDriver()# ScipyOptimizer() #
s1prob.driver.options['optimizer'] = 'SLSQP'
s1prob.driver.add_desvar('x', lower=0., upper=10.0)
s1prob.driver.add_desvar('z', lower=np.array([-10.0, 0.0]),upper=np.array([10.0, 10.0]))
s1prob.driver.add_desvar('y2', lower=-10.00, upper=10.00)
s1prob.driver.add_objective('obj1')
s1prob.driver.add_constraint('y1', lower=3.16)
s1prob.setup()
def solve_nonlinear(self, params, unknowns, resids):
s1prob = self.problem
# Pass values into our problem
s1prob['x'] = params['x']
s1prob['z'] = params['z']
s1prob['y2'] = params['y2']
s1prob['xt'] = params['xt']
s1prob['zt'] = params['zt']
s1prob['y1t'] = params['y1t']
s1prob['y2t'] = params['y2t']
# Run problem
s1prob.run()
# Pull values from problem
unknowns['y1'] = s1prob['y1']
class SubOptimization2(Component):
''' minimize differences between target and local variables of the second disipline of the sellar problem '''
def __init__(self):
super(SubOptimization2, self).__init__()
# Inputs to this subprob
self.add_param('z', val=np.array([5.0, 2.0]))
self.add_param('y1', val=3.16)
self.add_param('zt', val= np.array([5.0,2.0]))
self.add_param('y2t', val=1.0)
self.add_param('y1t', val=3.26)
# Unknowns for this sub prob
self.add_output('y2', val=1.0)
self.problem = s2prob = Problem()
s2prob.root = Group()
s2prob.root.add('p2z', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z'])
s2prob.root.add('p2y1', IndepVarComp('y1', 0.0), promotes=['y1'])
s2prob.root.add('d2', SellarDis2(), promotes=['z','y1','y2'])
s2prob.root.add('obj_cmp2', ExecComp('obj2 =(zt[0]-z[0])**2+(zt[1]-z[1])**2+(y1t-y1)**2+(y2t-y2)**2',
z=np.array([5.0, 2.0])), promotes= ['obj2','z','y1','y2','zt','y1t','y2t'])
self.deriv_options['type'] = 'cs'
#self.fd_options['force_fd'] = True
s2prob.driver =pyOptSparseDriver()# ScipyOptimizer() #
s2prob.driver.options['optimizer'] = 'SLSQP'
s2prob.driver.add_desvar('z', lower=np.array([-10.0, 0.0]),upper=np.array([10.0, 10.0]))
s2prob.driver.add_desvar('y1', lower=-10.00, upper=10.00)
s2prob.driver.add_objective('obj2')
s2prob.driver.add_constraint('y2', upper=24.00)
s2prob.setup()
def solve_nonlinear(self, params, unknowns, resids):
s2prob = self.problem
# Pass values into our problem
s2prob['z'] = params['z']
s2prob['y1'] = params['y1']
s2prob['zt'] = params['zt']
s2prob['y1t'] = params['y1t']
s2prob['y2t'] = params['y2t']
# Run problem
s2prob.run()
# Pull values from problem
unknowns['y2'] = s2prob['y2']
class SellarMDO(Group):
''' optimize top objective function of the sellar problem with the target variables '''
def __init__(self):
super(SellarMDO, self).__init__()
#### target variables initialization ####
self.add('pxt', IndepVarComp('xt', 1.0), promotes= ['xt'])
self.add('pzt', IndepVarComp('zt', np.array([5.0, 2.0])),promotes= ['zt'])
self.add('py2t', IndepVarComp('y2t',1.0),promotes= ['y2t'])
self.add('py1t', IndepVarComp('y1t', 3.16),promotes= ['y1t'])
self.add('d3', SubOptimization1(), promotes= ['xt','zt','y1t','y2t'])
self.add('d4', SubOptimization2(), promotes= ['zt','y1t','y2t'])
#### sellar problem objective function ####
self.add('obj_cmp', ExecComp('obj = xt**2 + zt[1] + y1t + exp(-y2t)',
zt=np.array([5.0, 2.0])), promotes= ['obj','xt','zt','y1t','y2t'])
#### First discipline constraint ####
self.add('con1_cmp', ExecComp('con1 = (xt-x)**2 + (zt[0]-z[0])**2+(zt[1]-z[1])**2+(y1t-y1)**2+(y2t-y2)**2',
z=np.array([5.0, 2.0]), x=1.0, y2=1.0,zt=np.array([5.0, 2.0])), promotes= ['con1','xt','zt','y1t','y2t'])
self.connect("d3.x", "con1_cmp.x")
self.connect("d3.z", "con1_cmp.z")
self.connect("d3.y1", "con1_cmp.y1")
self.connect("d3.y2", "con1_cmp.y2")
#### Second discipline constraint ####
self.add('con2_cmp', ExecComp('con2 = (zt[0]-z[0])**2+(zt[1]-z[1])**2+(y1t-y1)**2+(y2t-y2)**2',
z=np.array([5.0, 2.0]), y1=3.16 ,zt=np.array([5.0, 2.0])), promotes= ['con2','zt','y1t','y2t'])
self.connect("d4.z", "con2_cmp.z")
self.connect("d4.y1", "con2_cmp.y1")
self.connect("d4.y2", "con2_cmp.y2")
self.deriv_options['type'] = 'cs'
#self.fd_options['force_fd'] = True
if __name__ == '__main__':
from openmdao.api import Problem, ScipyOptimizer, SqliteRecorder
top = Problem()
top.root = SellarMDO()
top.driver = pyOptSparseDriver()#ScipyOptimizer() #
top.driver.options['optimizer'] = 'SLSQP'#'NSGA2'
top.driver.add_desvar('zt', lower=np.array([-10.0, 0.0]),upper=np.array([10.0, 10.0]))
top.driver.add_desvar('xt', lower=0.0, upper=10.0)
top.driver.add_desvar('y1t', lower=-10.0, upper=10.0)
top.driver.add_desvar('y2t', lower=-10.0, upper=10.0)
top.driver.add_objective('obj')
top.driver.add_constraint('con1', upper=0.005)
top.driver.add_constraint('con2', upper=0.005)
top.setup()
top.run()
print("\n")
print( "Minimum target found at (%f, %f, %f)" % (top['zt'][0],
top['zt'][1],
top['xt']))
print("Coupling vars target: %f, %f" % (top['y1t'], top['y2t']))
print("Minimum objective: ", top['obj'])
print("constraints: ", top['con1'] , top['con2'])
非常感谢!
答案 0 :(得分:0)
我有一个CO实现为sellar问题工作,但我在OpenMDAO 2.0中做到了。
api有点不同,但如果你愿意,你应该可以回转换为1.0。或者跳转到2.0!
OpenMDAO - CO (Collaborative Optimization) on Sellar test case