OpenMDAO v0.13:将程序集中 nxm 数组的切片连接到 n 个单独组件中的 1xm 数组
OpenMDAO v0.13: connecting slices of an nxm array in an assembly to 1xm arrays in n separate components
我正在尝试将 nxm
数组的行连接到 n
单个组件中的 1xm
数组,或者将 1xn*m
数组的切片连接到 [= n
个单独组件中的 13=] 个数组。然后将原始 nxm
或 1xn*m
数组用作优化参数。问题是当我这样做时,程序集似乎有一些严重的问题。我要么得到明显错误的答案,要么得到大小不匹配错误。
我已经能够通过使用 exec()
传入 n
1xm
数组来使程序集正常工作,但我更喜欢前面解释的方法。如果有人能告诉我如何以正确的方式完成这项工作,我将不胜感激。
我已经提供了一个简化的代码示例,说明哪些有效以及我想做什么。先显示我想使用的方法,然后显示我已经开始工作但非常不喜欢的方法。
我想做什么
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
from pyopt_driver.pyopt_driver import pyOptDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
y = 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
def list_deriv_vars(self):
return ('x',), ('term1',)
def provideJ(self):
x = self.x
a = self.a
dterm1_dx = 2.*a*x
J = np.array([[dterm1_dx]])
print 'In comp1, J = %s' % J
return J
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
f = Float(iotype='out')
q = Array(np.zeros(2), iotype='in', dtype='float')
def execute(self):
y = self.y + self.q[0]
x = self.x + self.q[1]
term1 = self.term1
f = term1 + x + y**2
print 'q = %s' % self.q
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')
def __init__(self, size):
super(assembly, self).__init__()
self.size = size
self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
self.add('q', Array(np.zeros((size, 2)), iotype='in', dtype='float'))
self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))
print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)
def configure(self):
self.add('driver', SLSQPdriver())
# self.add('driver', pyOptDriver())
# self.driver.optimizer = 'SNOPT'
# self.driver.pyopt_diff = True
#create this first, so we can connect to it
self.add('summer', summer(size=len(self.a_vals)))
self.connect('summer.total', 'total')
print 'in configure a_vals = %s' % self.a_vals
# create instances of components
for i in range(0, self.size):
c1 = self.add('comp1_%d' % i, component1())
c1.missing_deriv_policy = 'assume_zero'
c2 = self.add('comp2_%d'%i, component2())
self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
self.connect('x', ['comp1_%d.x' % i, 'comp2_%d.x' % i])
self.connect('y', ['comp1_%d.y' % i, 'comp2_%d.y' % i])
self.connect('comp1_%d.term1' % i, 'comp2_%d.term1' % i)
self.connect('q[%d, :]' % i, 'comp2_%d.q' % i)
self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)
self.driver.workflow.add(['comp1_%d' % i, 'comp2_%d' % i])
# self.connect('summer.fs[:]', 'fs[:]')
self.driver.workflow.add(['summer'])
# 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_parameter('q', low=0., high=5.)
self.driver.add_objective('summer.total')
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
from openmdao.main.api import set_as_top
a_vals = np.array([1., 1., 1., 1.])
test = set_as_top(assembly(size=len(a_vals)))
test.a_vals = a_vals
print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
test.x = 2.
test.y = -5
test.q = np.tile(np.arange(0., 2.), (4, 1))
print test.q
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.summer.total
print '(x, y) = (%s, %s)' % (test.x, test.y)
print 'fs = %s' % test.fs
print test.fs
----------
什么有效
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
from pyopt_driver.pyopt_driver import pyOptDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
y = 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
def list_deriv_vars(self):
return ('x',), ('term1',)
def provideJ(self):
x = self.x
a = self.a
dterm1_dx = 2.*a*x
J = np.array([[dterm1_dx]])
# print 'In comp1, J = %s' % J
return J
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
f = Float(iotype='out')
q = Array(np.zeros(2), iotype='in', dtype='float')
def execute(self):
y = self.y + self.q[0]
x = self.x + self.q[1]
term1 = self.term1
f = term1 + x + y**2
print 'in comp2 q = %s' % self.q
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')
def __init__(self, size):
super(assembly, self).__init__()
self.size = size
self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))
for i in range(0, size):
self.add('q_%d' % i, Array(np.zeros(2), iotype='in', dtype='float'))
print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)
def configure(self):
# self.add('driver', SLSQPdriver())
self.add('driver', pyOptDriver())
self.driver.optimizer = 'SNOPT'
# self.driver.pyopt_diff = True
#create this first, so we can connect to it
self.add('summer', summer(size=len(self.a_vals)))
self.connect('summer.total', 'total')
print 'in configure a_vals = %s' % self.a_vals
# print 'in configure q = %s' % self.q
# create instances of components
for i in range(0, self.size):
c1 = self.add('comp1_%d' % i, component1())
c1.missing_deriv_policy = 'assume_zero'
c2 = self.add('comp2_%d'%i, component2())
self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
self.connect('x', ['comp1_%d.x' % i, 'comp2_%d.x' % i])
self.connect('y', ['comp1_%d.y' % i, 'comp2_%d.y' % i])
self.connect('comp1_%d.term1' % i, 'comp2_%d.term1' % i)
self.connect('q_%d' % i, 'comp2_%d.q' % i)
self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)
self.driver.workflow.add(['comp1_%d' % i, 'comp2_%d' % i])
# self.connect('summer.fs[:]', 'fs[:]')
self.driver.workflow.add(['summer'])
# 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=0., high=5.)
for i in range(0, self.size):
self.driver.add_parameter('q_%d' % i, low=0., high=5.)
self.driver.add_objective('summer.total')
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
from openmdao.main.api import set_as_top
a_vals = np.array([1., 1., 1., 1.])
test = set_as_top(assembly(size=len(a_vals)))
test.a_vals = a_vals
print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
test.x = 2.
test.y = -5
q = np.tile(np.arange(1., 3.), (4, 1))
for i in range(0, len(a_vals)):
exec('test.q_%d = q[%d]' % (i, i))
exec('print test.q_%d' % i)
print test.q_0, test.q_1, test.q_2, test.q_3
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.summer.total
print '(x, y) = (%s, %s)' % (test.x, test.y)
print 'fs = %s' % test.fs
print test.fs
for i in range(0, len(a_vals)):
exec('print test.q_%d' % i)
我可以通过对 q 的连接做一个小的更改来克服设置错误,comp2_.q。
我来自:
self.connect('q[%d, :]' % i, 'comp2_%d.q' % i)
至:
self.connect('q[%d]' % i, 'comp2_%d.q' % i)
然后问题贯穿其第一次评估。不幸的是,它随后会在衍生品计算中的某个地方进行。即使我打开 SNOPT 并使用 pyopt_diff=True,也会发生这种情况。所以这个玩具问题中的其他东西是不对的。但是删除额外的 :
可以让您克服连接错误。
所以,我也看了你的模型,你肯定没有做错任何事。在为顶级优化问题组装网络图时,模型设置中存在错误。它似乎从输入中丢失了 q
变量,并且从不在用于求解总导数的向量中为其分配 space 。我认为它对 q
感到困惑,因为它与任何东西都没有直接的完全连接,只是与编号 comp2s
.
的切片连接
您的第一个解决方法可能是最好的解决方法。不过,我还发现了另一个。我创建了一个名为 fakefake
的虚拟组件;该组件除了允许您将完整的 q
向量直接连接到某物外什么都不做。然后,我获取它的输出 fakefake.out
并在约束中使用它。由于该输出永远不会改变,因此始终满足约束。此解决方法有效,因为完整的 q
连接可防止输入在 p运行ing.
期间被错误地从图形中删除
通过这些更改,我能够将其提升到 运行。我不确定答案是否正确,因为我不知道它们应该是什么。我在下面包含了我的代码。请注意,我还为 component2
和 summer
添加了导数。
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
from pyopt_driver.pyopt_driver import pyOptDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
y = 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
def list_deriv_vars(self):
return ('x',), ('term1',)
def provideJ(self):
x = self.x
a = self.a
dterm1_dx = 2.*a*x
J = np.array([[dterm1_dx]])
print 'In comp1, J = %s' % J
return J
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
q = Array(np.zeros(2), iotype='in', dtype='float')
f = Float(iotype='out')
def execute(self):
y = self.y + self.q[0]
x = self.x + self.q[1]
term1 = self.term1
f = term1 + x + y**2
print 'q = %s' % self.q
self.f = f
print "In comp2", self.name, self.x, self.y, self.term1, self.f
def list_deriv_vars(self):
return ('x', 'y', 'term1', 'q'), ('f',)
def provideJ(self):
# f = (y+q0)**2 + x + q1 + term1
df_dx = 1.0
df_dy = 2.0*self.y + 2.0*self.q[0]
df_dterm1 = 1.0
df_dq = np.array([2.0*self.q[0] + 2.0*self.y, 1.0])
J = np.array([[df_dx, df_dy, df_dterm1, df_dq[0], df_dq[1]]])
return J
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)
def list_deriv_vars(self):
return ('fs',), ('total',)
def provideJ(self):
J = np.ones((1.0, len(self.fs)))
return J
class fakefake(Component):
out = Float(0.0, iotype='out')
def __init__(self, size):
super(fakefake, self).__init__()
self.size = size
self.add('q', Array(np.zeros(size), iotype='in', dtype='float'))
def execute(self):
pass
def list_deriv_vars(self):
return ('q',), ('out',)
def provideJ(self):
J = np.zeros((1.0, 2.0*len(self.q)))
return J
class assembly(Assembly):
x = Float(iotype='in')
y = Float(iotype='in')
total = Float(iotype='out')
def __init__(self, size):
super(assembly, self).__init__()
self.size = size
self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
self.add('q', Array(np.zeros((size, 2)), iotype='in', dtype='float'))
self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))
print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)
def configure(self):
self.add('driver', SLSQPdriver())
# self.add('driver', pyOptDriver())
# self.driver.optimizer = 'SNOPT'
# self.driver.pyopt_diff = True
#create this first, so we can connect to it
self.add('summer', summer(size=len(self.a_vals)))
self.connect('summer.total', 'total')
# Trying something...
self.add('fakefake', fakefake(self.size))
self.connect('q', 'fakefake.q')
print 'in configure a_vals = %s' % self.a_vals
# create instances of components
for i in range(0, self.size):
c1 = self.add('comp1_%d' % i, component1())
c1.missing_deriv_policy = 'assume_zero'
c2 = self.add('comp2_%d'%i, component2())
self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
self.connect('x', ['comp1_%d.x' % i, 'comp2_%d.x' % i])
self.connect('y', ['comp1_%d.y' % i, 'comp2_%d.y' % i])
self.connect('comp1_%d.term1' % i, 'comp2_%d.term1' % i)
#self.connect('q[%d, :]' % i, 'comp2_%d.q' % i)
#self.connect('q[%d]' % i, 'comp2_%d.q' % i)
self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)
self.driver.workflow.add(['comp1_%d' % i, 'comp2_%d' % i])
# self.connect('summer.fs[:]', 'fs[:]')
self.driver.workflow.add(['summer'])
# 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_parameter('q', low=0., high=5.)
#for i in range(0, self.size):
# self.driver.add_parameter('comp2_%d.q' % i, low=0., high=5.)
self.driver.add_objective('summer.total')
self.driver.add_constraint('fakefake.out < 1000')
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
from openmdao.main.api import set_as_top
a_vals = np.array([1., 1., 1., 1.])
test = set_as_top(assembly(size=len(a_vals)))
test.a_vals = a_vals
print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
test.x = 2.
test.y = -5
test.q = np.tile(np.arange(0., 2.), (4, 1))
print test.q
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.summer.total
print '(x, y) = (%s, %s)' % (test.x, test.y)
print 'fs = %s' % test.fs
print test.fs
我正在尝试将 nxm
数组的行连接到 n
单个组件中的 1xm
数组,或者将 1xn*m
数组的切片连接到 [= n
个单独组件中的 13=] 个数组。然后将原始 nxm
或 1xn*m
数组用作优化参数。问题是当我这样做时,程序集似乎有一些严重的问题。我要么得到明显错误的答案,要么得到大小不匹配错误。
我已经能够通过使用 exec()
传入 n
1xm
数组来使程序集正常工作,但我更喜欢前面解释的方法。如果有人能告诉我如何以正确的方式完成这项工作,我将不胜感激。
我已经提供了一个简化的代码示例,说明哪些有效以及我想做什么。先显示我想使用的方法,然后显示我已经开始工作但非常不喜欢的方法。
我想做什么
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
from pyopt_driver.pyopt_driver import pyOptDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
y = 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
def list_deriv_vars(self):
return ('x',), ('term1',)
def provideJ(self):
x = self.x
a = self.a
dterm1_dx = 2.*a*x
J = np.array([[dterm1_dx]])
print 'In comp1, J = %s' % J
return J
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
f = Float(iotype='out')
q = Array(np.zeros(2), iotype='in', dtype='float')
def execute(self):
y = self.y + self.q[0]
x = self.x + self.q[1]
term1 = self.term1
f = term1 + x + y**2
print 'q = %s' % self.q
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')
def __init__(self, size):
super(assembly, self).__init__()
self.size = size
self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
self.add('q', Array(np.zeros((size, 2)), iotype='in', dtype='float'))
self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))
print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)
def configure(self):
self.add('driver', SLSQPdriver())
# self.add('driver', pyOptDriver())
# self.driver.optimizer = 'SNOPT'
# self.driver.pyopt_diff = True
#create this first, so we can connect to it
self.add('summer', summer(size=len(self.a_vals)))
self.connect('summer.total', 'total')
print 'in configure a_vals = %s' % self.a_vals
# create instances of components
for i in range(0, self.size):
c1 = self.add('comp1_%d' % i, component1())
c1.missing_deriv_policy = 'assume_zero'
c2 = self.add('comp2_%d'%i, component2())
self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
self.connect('x', ['comp1_%d.x' % i, 'comp2_%d.x' % i])
self.connect('y', ['comp1_%d.y' % i, 'comp2_%d.y' % i])
self.connect('comp1_%d.term1' % i, 'comp2_%d.term1' % i)
self.connect('q[%d, :]' % i, 'comp2_%d.q' % i)
self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)
self.driver.workflow.add(['comp1_%d' % i, 'comp2_%d' % i])
# self.connect('summer.fs[:]', 'fs[:]')
self.driver.workflow.add(['summer'])
# 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_parameter('q', low=0., high=5.)
self.driver.add_objective('summer.total')
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
from openmdao.main.api import set_as_top
a_vals = np.array([1., 1., 1., 1.])
test = set_as_top(assembly(size=len(a_vals)))
test.a_vals = a_vals
print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
test.x = 2.
test.y = -5
test.q = np.tile(np.arange(0., 2.), (4, 1))
print test.q
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.summer.total
print '(x, y) = (%s, %s)' % (test.x, test.y)
print 'fs = %s' % test.fs
print test.fs
----------
什么有效
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
from pyopt_driver.pyopt_driver import pyOptDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
y = 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
def list_deriv_vars(self):
return ('x',), ('term1',)
def provideJ(self):
x = self.x
a = self.a
dterm1_dx = 2.*a*x
J = np.array([[dterm1_dx]])
# print 'In comp1, J = %s' % J
return J
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
f = Float(iotype='out')
q = Array(np.zeros(2), iotype='in', dtype='float')
def execute(self):
y = self.y + self.q[0]
x = self.x + self.q[1]
term1 = self.term1
f = term1 + x + y**2
print 'in comp2 q = %s' % self.q
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')
def __init__(self, size):
super(assembly, self).__init__()
self.size = size
self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))
for i in range(0, size):
self.add('q_%d' % i, Array(np.zeros(2), iotype='in', dtype='float'))
print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)
def configure(self):
# self.add('driver', SLSQPdriver())
self.add('driver', pyOptDriver())
self.driver.optimizer = 'SNOPT'
# self.driver.pyopt_diff = True
#create this first, so we can connect to it
self.add('summer', summer(size=len(self.a_vals)))
self.connect('summer.total', 'total')
print 'in configure a_vals = %s' % self.a_vals
# print 'in configure q = %s' % self.q
# create instances of components
for i in range(0, self.size):
c1 = self.add('comp1_%d' % i, component1())
c1.missing_deriv_policy = 'assume_zero'
c2 = self.add('comp2_%d'%i, component2())
self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
self.connect('x', ['comp1_%d.x' % i, 'comp2_%d.x' % i])
self.connect('y', ['comp1_%d.y' % i, 'comp2_%d.y' % i])
self.connect('comp1_%d.term1' % i, 'comp2_%d.term1' % i)
self.connect('q_%d' % i, 'comp2_%d.q' % i)
self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)
self.driver.workflow.add(['comp1_%d' % i, 'comp2_%d' % i])
# self.connect('summer.fs[:]', 'fs[:]')
self.driver.workflow.add(['summer'])
# 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=0., high=5.)
for i in range(0, self.size):
self.driver.add_parameter('q_%d' % i, low=0., high=5.)
self.driver.add_objective('summer.total')
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
from openmdao.main.api import set_as_top
a_vals = np.array([1., 1., 1., 1.])
test = set_as_top(assembly(size=len(a_vals)))
test.a_vals = a_vals
print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
test.x = 2.
test.y = -5
q = np.tile(np.arange(1., 3.), (4, 1))
for i in range(0, len(a_vals)):
exec('test.q_%d = q[%d]' % (i, i))
exec('print test.q_%d' % i)
print test.q_0, test.q_1, test.q_2, test.q_3
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.summer.total
print '(x, y) = (%s, %s)' % (test.x, test.y)
print 'fs = %s' % test.fs
print test.fs
for i in range(0, len(a_vals)):
exec('print test.q_%d' % i)
我可以通过对 q 的连接做一个小的更改来克服设置错误,comp2_.q。
我来自:
self.connect('q[%d, :]' % i, 'comp2_%d.q' % i)
至:
self.connect('q[%d]' % i, 'comp2_%d.q' % i)
然后问题贯穿其第一次评估。不幸的是,它随后会在衍生品计算中的某个地方进行。即使我打开 SNOPT 并使用 pyopt_diff=True,也会发生这种情况。所以这个玩具问题中的其他东西是不对的。但是删除额外的 :
可以让您克服连接错误。
所以,我也看了你的模型,你肯定没有做错任何事。在为顶级优化问题组装网络图时,模型设置中存在错误。它似乎从输入中丢失了 q
变量,并且从不在用于求解总导数的向量中为其分配 space 。我认为它对 q
感到困惑,因为它与任何东西都没有直接的完全连接,只是与编号 comp2s
.
您的第一个解决方法可能是最好的解决方法。不过,我还发现了另一个。我创建了一个名为 fakefake
的虚拟组件;该组件除了允许您将完整的 q
向量直接连接到某物外什么都不做。然后,我获取它的输出 fakefake.out
并在约束中使用它。由于该输出永远不会改变,因此始终满足约束。此解决方法有效,因为完整的 q
连接可防止输入在 p运行ing.
通过这些更改,我能够将其提升到 运行。我不确定答案是否正确,因为我不知道它们应该是什么。我在下面包含了我的代码。请注意,我还为 component2
和 summer
添加了导数。
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
from pyopt_driver.pyopt_driver import pyOptDriver
import numpy as np
class component1(Component):
x = Float(iotype='in')
y = 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
def list_deriv_vars(self):
return ('x',), ('term1',)
def provideJ(self):
x = self.x
a = self.a
dterm1_dx = 2.*a*x
J = np.array([[dterm1_dx]])
print 'In comp1, J = %s' % J
return J
class component2(Component):
x = Float(iotype='in')
y = Float(iotype='in')
term1 = Float(iotype='in')
q = Array(np.zeros(2), iotype='in', dtype='float')
f = Float(iotype='out')
def execute(self):
y = self.y + self.q[0]
x = self.x + self.q[1]
term1 = self.term1
f = term1 + x + y**2
print 'q = %s' % self.q
self.f = f
print "In comp2", self.name, self.x, self.y, self.term1, self.f
def list_deriv_vars(self):
return ('x', 'y', 'term1', 'q'), ('f',)
def provideJ(self):
# f = (y+q0)**2 + x + q1 + term1
df_dx = 1.0
df_dy = 2.0*self.y + 2.0*self.q[0]
df_dterm1 = 1.0
df_dq = np.array([2.0*self.q[0] + 2.0*self.y, 1.0])
J = np.array([[df_dx, df_dy, df_dterm1, df_dq[0], df_dq[1]]])
return J
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)
def list_deriv_vars(self):
return ('fs',), ('total',)
def provideJ(self):
J = np.ones((1.0, len(self.fs)))
return J
class fakefake(Component):
out = Float(0.0, iotype='out')
def __init__(self, size):
super(fakefake, self).__init__()
self.size = size
self.add('q', Array(np.zeros(size), iotype='in', dtype='float'))
def execute(self):
pass
def list_deriv_vars(self):
return ('q',), ('out',)
def provideJ(self):
J = np.zeros((1.0, 2.0*len(self.q)))
return J
class assembly(Assembly):
x = Float(iotype='in')
y = Float(iotype='in')
total = Float(iotype='out')
def __init__(self, size):
super(assembly, self).__init__()
self.size = size
self.add('a_vals', Array(np.zeros(size), iotype='in', dtype='float'))
self.add('q', Array(np.zeros((size, 2)), iotype='in', dtype='float'))
self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))
print 'in init a_vals = %s, fs = %s' % (self.a_vals, self.fs)
def configure(self):
self.add('driver', SLSQPdriver())
# self.add('driver', pyOptDriver())
# self.driver.optimizer = 'SNOPT'
# self.driver.pyopt_diff = True
#create this first, so we can connect to it
self.add('summer', summer(size=len(self.a_vals)))
self.connect('summer.total', 'total')
# Trying something...
self.add('fakefake', fakefake(self.size))
self.connect('q', 'fakefake.q')
print 'in configure a_vals = %s' % self.a_vals
# create instances of components
for i in range(0, self.size):
c1 = self.add('comp1_%d' % i, component1())
c1.missing_deriv_policy = 'assume_zero'
c2 = self.add('comp2_%d'%i, component2())
self.connect('a_vals[%d]' % i, 'comp1_%d.a' % i)
self.connect('x', ['comp1_%d.x' % i, 'comp2_%d.x' % i])
self.connect('y', ['comp1_%d.y' % i, 'comp2_%d.y' % i])
self.connect('comp1_%d.term1' % i, 'comp2_%d.term1' % i)
#self.connect('q[%d, :]' % i, 'comp2_%d.q' % i)
#self.connect('q[%d]' % i, 'comp2_%d.q' % i)
self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)
self.driver.workflow.add(['comp1_%d' % i, 'comp2_%d' % i])
# self.connect('summer.fs[:]', 'fs[:]')
self.driver.workflow.add(['summer'])
# 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_parameter('q', low=0., high=5.)
#for i in range(0, self.size):
# self.driver.add_parameter('comp2_%d.q' % i, low=0., high=5.)
self.driver.add_objective('summer.total')
self.driver.add_constraint('fakefake.out < 1000')
if __name__ == "__main__":
""" the result should be -1 at (x, y) = (-0.5, 0) """
import time
from openmdao.main.api import set_as_top
a_vals = np.array([1., 1., 1., 1.])
test = set_as_top(assembly(size=len(a_vals)))
test.a_vals = a_vals
print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
test.x = 2.
test.y = -5
test.q = np.tile(np.arange(0., 2.), (4, 1))
print test.q
tt = time.time()
test.run()
print "Elapsed time: ", time.time()-tt, "seconds"
print 'result = ', test.summer.total
print '(x, y) = (%s, %s)' % (test.x, test.y)
print 'fs = %s' % test.fs
print test.fs