1

スケーラーを使用したかったので、OpenMDAO 0.x ドキュメントの Paraboloid の例を OpenMDAO 1.x でテストすることになりましたが、スケーラーの有無にかかわらず奇妙な結果が得られます。コードは次のとおりです。

from __future__ import print_function
システムをインポート

from openmdao.api import IndepVarComp, Component, Problem, Group, ScipyOptimizer

クラス放物面(コンポーネント):

    def __init__(自己):
        super(放物面、自己).__init__()

        self.add_param('x', 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):

        x = パラメータ['x']
        y = パラメータ['y']

        #unknowns['f_xy'] = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0
        未知数['f_xy'] = (1000.*x-3.)**2 + (1000.*x)*(0.01*y) + (0.01*y+4.)**2 - 3.

    def linearize(self、params、unknowns、resids):
        """ 放物面のヤコビアン"""
        x = パラメータ['x']
        y = パラメータ['y']
        J = {}

        #J['f_xy', 'x'] = 2.0*x - 6.0 + y
        #J['f_xy', 'y'] = 2.0*y + 8.0 + x
        J['f_xy', 'x'] = 2000000.0*x - 6000.0 + 10.0*y
        J['f_xy', 'y'] = 0.0002*y + 0.08 + 10.0*x

        Jを返す

if __name__ == "__main__":

    トップ=問題()

    root = top.root = グループ()

    root.add('p1', IndepVarComp('x', 3.0))
    root.add('p2', IndepVarComp('y', -4.0))
    root.add('p', Paraboloid())

    root.connect('p1.x', 'px')
    root.connect('p2.y', 'py')

    top.driver = ScipyOptimizer()
    top.driver.options['optimizer'] = 'SLSQP'

    top.driver.add_desvar('p1.x', 下限=-1000, 上限=1000, スケーラー=0.001)
    top.driver.add_desvar('p2.y', 下限=-1000, 上限=1000, スケーラー=1000.)
    top.driver.add_objective('p.f_xy')

    top.setup()
    top.run()

    印刷('\n')
    print('Minimum of %f found at (%f, %f)' % (top['p.f_xy'], top['px'], top['py']))

私のシステムで実行すると、次のようになります。

2.7.11 |アナコンダ 2.5.0 (64 ビット)| (デフォルト、2016 年 1 月 29 日 14:26:21) [MSC v.1500 64 ビット (AMD64)]
Python 詳細については、「ヘルプ」、「著作権」、「クレジット」、または「ライセンス」と入力してください。
[paraboloid_optimize_scaled.py を評価]
##############################################
セットアップ: 潜在的な問題を確認しています...

レコーダーが指定されていないため、データは保存されません。

セットアップ: チェック完了。
##############################################

最適化が正常に終了しました。(終了モード 0)
            現在の関数値: [ 8981902.27846645]
            反復: 1
            機能評価: 12
            勾配評価: 1
最適化完了
-----------------------------------


(3.000000、-4.000000) で見つかった 8981902.278466 の最小値

私は何か見落としてますか?

4

2 に答える 2

1

スケーラーは、OpenMDAO 1.x では 0.x とは逆に定義されています。1.x では、次のスケーリング関係が使用されます。

driver_value = (model_value + adder)*scaler

そのため、スケーラーを古いチュートリアルのものと比較して変更する必要がありました。ただし、二次的な問題がありました。分析導関数の間違いであり、これも以下で修正されています。

from __future__ import print_function
import sys

from openmdao.api import IndepVarComp, Component, Problem, Group, ScipyOptimizer

class Paraboloid(Component):

    def __init__(self):
        super(Paraboloid, self).__init__()

        self.add_param('x', 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):

        x = params['x']
        y = params['y']

        #unknowns['f_xy'] = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0
        unknowns['f_xy'] = (1000.*x-3.)**2 + (1000.*x)*(0.01*y) + (0.01*y+4.)**2 - 3.

    def linearize(self, params, unknowns, resids):
        """ Jacobian for our paraboloid."""
        x = params['x']
        y = params['y']
        J = {}

        #J['f_xy', 'x'] = 2.0*x - 6.0 + y
        #J['f_xy', 'y'] = 2.0*y + 8.0 + x
        J['f_xy', 'x'] = 2000000.0*x - 6000.0 + 10.0*y
        J['f_xy', 'y'] = 0.0002*y + 0.08 + 10.0*x

        return J

if __name__ == "__main__":

    top = Problem()

    root = top.root = Group()
    root.fd_options['force_fd'] = True

    root.add('p1', IndepVarComp('x', 3.0))
    root.add('p2', IndepVarComp('y', -4.0))
    root.add('p', Paraboloid())

    root.connect('p1.x', 'p.x')
    root.connect('p2.y', 'p.y')

    top.driver = ScipyOptimizer()
    top.driver.options['optimizer'] = 'SLSQP'

    top.driver.add_desvar('p1.x', lower=-1000, upper=1000, scaler=1000.)
    top.driver.add_desvar('p2.y', lower=-1000, upper=1000,scaler=.001)
    top.driver.add_objective('p.f_xy')

    top.setup()
    top.run()

    print('\n')
    print('Minimum of %f found at (%f, %f)' % (top['p.f_xy'], top['p.x'], top['p.y']))

与えます:

Optimization terminated successfully.    (Exit mode 0)
            Current function value: [-27.333333]
            Iterations: 3
            Function evaluations: 6
            Gradient evaluations: 3
Optimization Complete
-----------------------------------


Minimum of -27.333333 found at (0.006666, -733.299996)
于 2016-02-22T14:33:51.453 に答える
0

あなたの問題を直接再現することはできません。参照しているopenmdao 0.xチュートリアルと比較して、solve_nonlinearおよびlinearizeメソッドに奇妙なスケーリングがあります。しかし、それらをクリーンアップすると、妥当なスケーラー値、およびいくつかの不合理な値 (選択したものは少し極端です) についても、正しい答えが得られます。add_desvar の scaler/adder を使用する場合、モデルを変更する必要はまったくありません。これらの値は、オプティマイザーがスケーリングを支援するために参照する値を変更するだけですが、モデルに渡される前にスケーリングされていない値に適切に変換されます。

from __future__ import print_function
import sys

from openmdao.api import IndepVarComp, Component, Problem, Group, ScipyOptimizer

class Paraboloid(Component):

    def __init__(self):
        super(Paraboloid, self).__init__()

        self.add_param('x', 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):

        x = params['x']
        y = params['y']

        unknowns['f_xy'] = (x-3.0)**2 + x*y + (y+4.0)**2 - 3.0

    def linearize(self, params, unknowns, resids):
        """ Jacobian for our paraboloid."""
        x = params['x']
        y = params['y']
        J = {}

        J['f_xy', 'x'] = 2.0*x - 6.0 + y
        J['f_xy', 'y'] = 2.0*y + 8.0 + x

        return J

if __name__ == "__main__":

    top = Problem()

    root = top.root = Group()

    root.add('p1', IndepVarComp('x', 3.0))
    root.add('p2', IndepVarComp('y', -4.0))
    root.add('p', Paraboloid())

    root.connect('p1.x', 'p.x')
    root.connect('p2.y', 'p.y')

    top.driver = ScipyOptimizer()
    top.driver.options['optimizer'] = 'SLSQP'

    # top.driver.add_desvar('p1.x', lower=-1000, upper=1000)
    # top.driver.add_desvar('p2.y', lower=-1000, upper=1000)

    top.driver.add_desvar('p1.x', lower=-1000, upper=1000, scaler=.001)
    top.driver.add_desvar('p2.y', lower=-1000, upper=1000, scaler=1000.)
    top.driver.add_objective('p.f_xy')

    top.setup()
    top.run()

    print('\n')
    print('Minimum of %f found at (%f, %f)' % (top['p.f_xy'], top['p.x'], top['p.y']))

与えます:

##############################################
Setup: Checking for potential issues...

No recorders have been specified, so no data will be saved.

Setup: Check complete.
##############################################

Optimization terminated successfully.    (Exit mode 0)
            Current function value: [-27.33333333]
            Iterations: 12
            Function evaluations: 15
            Gradient evaluations: 12
Optimization Complete
-----------------------------------
于 2016-02-21T21:47:47.070 に答える