如何在 Mystic 中以函数形式指定多个约束?

How to specify multiple constraints in function form in Mystic?

使用Mystic求解器如何输入多个约束?例如,我有这两个函数来描述我的两个约束:

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(...)时,输入这些约束的正确方法是什么?

我是神秘的作者。我不确定你想要什么......你已经以软约束(即惩罚)的形式编写了约束,所以我会接受它。

要耦合惩罚,您可以使用像 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 的求解器。