分布式架构

时间:2018-01-22 13:26:19

标签: python openmdao

我正在尝试按照我发现herehere

的提示实施一些分布式MDO架构

当我尝试为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'])

非常感谢!

1 个答案:

答案 0 :(得分:0)

我有一个CO实现为sellar问题工作,但我在OpenMDAO 2.0中做到了。

api有点不同,但如果你愿意,你应该可以回转换为1.0。或者跳转到2.0!

OpenMDAO - CO (Collaborative Optimization) on Sellar test case