出于兼容性原因,我使用的是OpenMDAO v0.10.3.2
我正在尝试在OpenMDAO中设置一个优化问题,该问题需要在优化器的工作流程中使用case iterator驱动程序。为了说明,我创建了如下所示的简单示例。代码似乎运行,但优化器似乎没有改变参数并在两次运行工作流后退出。
我正在寻找建议此类问题的建议,并深入了解我目前的配方可能出现的问题。
from openmdao.main.api import Assembly, Component
from openmdao.lib.datatypes.api import Float, Array, List
from openmdao.lib.drivers.api import DOEdriver, SLSQPdriver, CaseIteratorDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
term1 = Float(iotype='out')
a = Float(iotype='in', default_value=1)
def execute(self):
x = self.x
a = self.a
term1 = a*x**2
self.term1 = term1
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
f = Float(iotype='out')
def execute(self):
y = self.y
x = self.x
term1 = self.term1
f = term1 + x + y**2
self.f = f
class summer(Component):
fs = Array(iotype='in', desc='f values from all cases')
total = Float(iotype='out', desc='sum of all f values')
def execute(self):
self.total = sum(self.fs)
print 'In summer, fs = %s and total = %s' % (self.fs, self.total)
class assembly(Assembly):
cases_a = Array(iotype='in', desc='list of cases')
x = Float(iotype='in')
y = Float(iotype='in')
f = Float(iotype='out')
total = Float(iotype='out', default_value=100)
def configure(self):
# create instances of components
self.add('component1', component1())
self.add('component2', component2())
self.add('summer', summer())
# set up main driver (optimizer)
self.add('driver', SLSQPdriver())
self.driver.iprint = 1
self.driver.maxiter = 100
self.driver.accuracy = 1.0e-6
self.driver.add('summer', summer())
self.driver.add_parameter('x', low=-5., high=5.)
self.driver.add_parameter('y', low=-5., high=5.)
self.driver.add_objective('summer.total')
# set up case iterator driver
self.add('case_driver', CaseIteratorDriver())
self.case_driver.workflow.add(['component1', 'component2'])
self.case_driver.add_parameter('component1.a')
self.case_driver.add_response('component2.f')
# Set up connections
self.connect('x', 'component1.x')
self.connect('y', 'component2.y')
self.connect('component1.x', 'component2.x')
self.connect('component1.term1', 'component2.term1')
self.connect('component2.f', 'f')
self.connect('cases_a', 'case_driver.case_inputs.component1.a')
self.connect('case_driver.case_outputs.component2.f', 'summer.fs')
self.connect('summer.total', 'total')
# establish main workflow
self.driver.workflow.add(['case_driver', 'summer'])
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
test = assembly()
values = [1, 1, 1, 1]
test.cases_a = np.array(values)
test.x = 4
test.y = 4
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.total
print '(x, y) = (%s, %s)' % (test.x, test.y)
答案 0 :(得分:1)
在CID驱动程序中传播衍生产品有很多挑战,我们从来没有按照我们想要的方式工作。因此,我建议使用另一种方法,为每个要运行的案例创建一个单独的实例。这将更好地工作,特别是如果您计划在某个时候使用分析衍生物
from openmdao.main.api import Assembly, Component
from openmdao.lib.datatypes.api import Float, Array, List
from openmdao.lib.drivers.api import DOEdriver, SLSQPdriver, COBYLAdriver, CaseIteratorDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
term1 = Float(iotype='out')
a = Float(iotype='in', default_value=1)
def execute(self):
x = self.x
a = self.a
term1 = a*x**2
self.term1 = term1
print "In comp1", self.name, self.a, self.x, self.term1
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
f = Float(iotype='out')
def execute(self):
y = self.y
x = self.x
term1 = self.term1
f = term1 + x + y**2
self.f = f
print "In comp2", self.name, self.x, self.y, self.term1, self.f
class summer(Component):
total = Float(iotype='out', desc='sum of all f values')
def __init__(self, size):
super(summer, self).__init__()
self.size = size
self.add('fs', Array(np.zeros(size), iotype='in', desc='f values from all cases'))
def execute(self):
self.total = sum(self.fs)
print 'In summer, fs = %s and total = %s' % (self.fs, self.total)
class assembly(Assembly):
x = Float(iotype='in')
y = Float(iotype='in')
total = Float(iotype='out', default_value=100)
def __init__(self, a_vals=[1, 1, 1, 1]):
self.a_vals = a_vals
super(assembly, self).__init__()
def configure(self):
#add the driver first, so I don't overwrite the workflow later on
self.add('driver', SLSQPdriver())
#create this first, so we can connect to it
self.add('summer', summer(size=len(self.a_vals)))
self.connect('summer.total', 'total')
# create instances of components
for i, a in enumerate(self.a_vals):
c1 = self.add('comp1_%d'%i, component1())
c1.a = a
c2 = self.add('comp2_%d'%i, component2())
self.connect('x', ['comp1_%d.x'%i,'comp2_%d.x'%i])
self.connect('y', 'comp2_%d.y'%i)
self.connect( 'comp1_%d.term1'%i, 'comp2_%d.term1'%i)
self.connect('comp2_%d.f'%i, 'summer.fs[%d]'%i)
self.driver.workflow.add(['comp1_%d'%i, 'comp2_%d'%i])
# establish main workflow
# set up main driver (optimizer)
self.driver.iprint = 1
self.driver.maxiter = 100
self.driver.accuracy = 1.0e-6
self.driver.add_parameter('x', low=-5., high=5.)
self.driver.add_parameter('y', low=-5., high=5.)
self.driver.add_objective('summer.total')
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
test = assembly([1, 1, 1, 1])
test.x = 2
test.y = 4
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.total
print '(x, y) = (%s, %s)' % (test.x, test.y)