OpenMDAO: Solver сходится к неоптимальной точке - PullRequest
0 голосов
/ 25 июня 2018

Я пытаюсь понять ограничения алгоритмов оптимизации OpenMDAO.В частности, я установил следующий тривиальный пример:

from openmdao.api import Problem, ScipyOptimizeDriver, ExecComp, IndepVarComp, ExplicitComponent

class AddComp(ExplicitComponent):

    def setup(self):
        self.add_input("x")
        self.add_input("y")
        self.add_output("obj")

    def compute(self, inputs, outputs):
        outputs['obj'] = inputs["x"] + inputs["y"]

# build the model
prob = Problem()
indeps = prob.model.add_subsystem('indeps', IndepVarComp())
indeps.add_output('x', 3.0)
indeps.add_output('y', -4.0)

prob.model.add_subsystem("simple", AddComp())

prob.model.connect('indeps.x', 'simple.x')
prob.model.connect('indeps.y', 'simple.y')

# setup the optimization
prob.driver = ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'

prob.model.add_design_var('indeps.x', lower=-50, upper=50)
prob.model.add_design_var('indeps.y', lower=-50, upper=50)
prob.model.add_objective('simple.obj')

prob.setup()
prob.run_driver()
# minimum value
print(prob['simple.obj'])
# location of the minimum
print(prob['indeps.x'])
print(prob['indeps.y'])

Распечатка из этого:

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

Однако оптимальным решением, конечно, было бы иметь x = y = -50,Почему это решение не может быть найдено?

Почему-то у меня возникла мысль, что драйвер должен найти правильное решение для выпуклых задач.Но я понимаю, что это звучит как грубое резюме ограничений решателя.Может ли кто-нибудь указать на объяснение того, какие проблемы можно решить какими методами?

1 Ответ

0 голосов
/ 25 июня 2018

Здесь происходит то, что OpenMDAO не вычисляет объективный градиент для оптимизатора, потому что вы должны явно объявить партиалы.

При добавлении следующего в метод настройки компонента будут объявлены постоянные значениячастичных (нам не нужен метод compute_partials в этом случае, потому что цель является линейной функцией входных данных и, следовательно, частичные значения постоянны).

self.declare_partials(of='obj', wrt='x', val=1.0)
self.declare_partials(of='obj', wrt='y', val=1.0)

В качестве альтернативы, вы можете просто сказать OpenMDAOвычислить все частичные для компонента с помощью конечной разности или сложного шага:

self.declare_partials(of='*', wrt='*', method='cs')

Где метод - это один из 'cs' или 'fd'.

С этим изменением ожидаемый оптимум равеннайдено:

Optimization terminated successfully.    (Exit mode 0)
            Current function value: -99.99999999983521
            Iterations: 7
            Function evaluations: 7
            Gradient evaluations: 7
Optimization Complete
-----------------------------------
[-100.]
[-50.]
[-50.]
...