Предоставление вектора неравенств / ограничений для мистиков - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь предоставить ограничения для минимизации функции, которую я до сих пор успешно выполнял с помощью неограниченного алгоритма, доступного через scipy (scipy.optimize.fmin_l_bfgs_b()).

Читая (см., Например, Нелинейная оптимизация с ограничениями Python ), я обнаружил упаковку минимизации под названием mystic, которая, кажется, мне нужна. Моя ситуация такова. У меня есть функция 3N переменных (представляющих координаты положения xyz N узлов), и я хочу предоставить список ограничений, такой что z/x = const. для каждого узла. Это составляет в общей сложности N ограничений. Как наиболее эффективно определить / предоставить эти ограничения для mystic()? Можно ли использовать один и тот же объект ограничения с scipy.optimize.slsqp()? Так как мои ограничения линейны, это тоже приемлемый вариант.

Я попробовал следующее, но мой компьютер сломался:

import mystic.symbolic as ms
ieqns = ''
for p in range(N):
    ieqns += 'x'+str(p+2) +'/x'+str(p) +" <= 2"

cf = ms.generate_constraint(ms.generate_solvers(ms.simplify(ieqns)))
pf = ms.generate_penalty(ms.generate_conditions(ieqns), k=1e12)

1 Ответ

0 голосов
/ 14 ноября 2018

Я mystic автор. Я полагаю, что вы хотите сделать что-то вроде этого:

>>> import mystic.symbolic as ms
>>> ieqns = ''
>>> for p in range(10):
...   ieqns += 'x{0} <= 2*x{1}\n'.format(p+2,p)
... 
>>> cf = ms.generate_constraint(ms.generate_solvers(ieqns))
>>>
>>> # test that it applies the constraints
>>> cf([1.,3.,5.,7.,9.,11.,13.,15.,17.,19.,21.,23.,25.])
[1.0, 3.0, 2.0, 6.0, 4.0, 11.0, 8.0, 15.0, 16.0, 19.0, 21.0, 23.0, 25.0]

Тогда мы можем минимизировать при применении ограничений (однако, в следующем случае ограничения в основном не имеют значения):

>>> # get an objective
>>> import mystic.models as mm
>>> rosen = mm.dejong.Rosenbrock(12).function
>>> 
>>> # get an optimizer
>>> import mystic.solvers as my
>>> result = my.diffev2(rosen, x0=bounds, bounds=bounds, constrints=cf, npop=40, disp=False, full_output=True, gtol=100)
>>>
>>> # get the solution 
>>> result[0]
array([0.99997179, 1.00005506, 1.00012367, 0.99998539, 0.99984306,
       0.99981495, 0.999951  , 0.99996505, 0.99971107, 0.99925239,
       0.99846259, 0.99692293])
>>> # and the final 'cost'
>>> result[1]
2.2385442425350018e-05
>>> 
...