Как указать несколько ограничений в форме функции в Mysti c? - PullRequest
2 голосов
/ 26 февраля 2020

Как вы вводите несколько ограничений при использовании решателя Mysti c? Например, у меня есть эти две функции, которые описывают мои два ограничения:

def constraint1(x):
    return x[0]*x[1]*x[2]*x[3]-25.0

def constraint2(x):
    sum_eq = 40.0
    for i in range(4):
        sum_eq = sum_eq - x[i]**2
    return sum_eq

При использовании diffev(...), как правильно вводить эти ограничения?

1 Ответ

0 голосов
/ 04 марта 2020

Я мисти c автор. Я не уверен, что вы хотите ... Вы написали ограничения в виде мягких ограничений (то есть штрафов), поэтому я буду go с этим.

Чтобы связать штрафы, вы можете использовать сопряжение типа mystic.coupler.and_, или вы можете использовать декоратор штрафа, например:

>>> import mystic as my
>>>
>>> def penalty1(x):
...   return x[0]*x[1]*x[2]*x[3] - 25.0
... 
>>> def penalty2(x):
...   return 40.0 - sum(i*i for i in x)
... 
>>> x
[4, 5, 1, 9]
>>> 
>>> @my.penalty.linear_equality(penalty1)
... @my.penalty.linear_equality(penalty2)
... def penalty(x):
...   return 0.0
... 
>>> penalty(x)
23800.0
>>> 

Затем, если все, что вы хотите сделать, это решить, где размер штрафа наименьший, вы можете использовать diffev на непосредственно штраф:

>>> my.solvers.diffev(penalty, [10,10,10,10], npop=100)
Optimization terminated successfully.
         Current function value: 0.001920
         Iterations: 167
         Function evaluations: 16800
array([1.92486578, 0.86032337, 2.89649062, 5.21201382])
>>> 

Если вы хотите применить их в качестве штрафа при решении какой-либо другой функции, то вы бы сделали это следующим образом:

>>> from mystic.models import rosen  # the Rosenbrock test function 
>>> my.solvers.diffev(rosen, [0,0,0,0], penalty=penalty, npop=100)
Optimization terminated successfully.
         Current function value: 2.263629
         Iterations: 182
         Function evaluations: 18300
array([1.24923882, 1.53972652, 2.35201514, 5.5259994 ])

Если вы хотите жесткие ограничения, это другое дело:

>>> def constraint1(x, val=29):
...     res = my.constraints.normalize([i*i for i in x], val)
...     return [i**.5 for i in res]
... 
>>> def constraint2(x, val=24):
...     return my.constraints.impose_product(val, x)
... 
>>> constraint3 = my.constraints.integers()(lambda x:x)
>>> 
>>> constraint = my.constraints.and_(constraint1, constraint2, constraint3)
>>> 
>>> x = [1,2,3]
>>> z = constraint(x)
>>> 
>>> assert constraint1(z) == z
>>> assert constraint2(z) == z
>>> assert constraint3(z) == z
>>> z
[2.0, 3.0, 4.0]

Они применяются к решателям с ключевым словом constraints.

...