我是mystic
作者。我用另一个约束一个函数的输出的最简单方法是使用惩罚(软约束)。
我将展示一个简单的案例,类似于我认为您正在寻找的内容:
"""
2-D input x
1-D output y = f(x)
where y > g(x)
with f(x) = x0^(sin(x0)) + x1^4 + 6x1^3 - 5x1^2 - 40x1 + 35
and g(x) = 7x1 - x0 + 5
in x = [0,10]
"""
让我们找到大于 g 的 f 的最小值。
>>> import numpy as np
>>> import mystic as my
>>>
>>> def f(x):
... x0,x1 = x
... return x0**np.sin(x0) + x1**4 + 6*x1**3 - 5*x1**2 - 40*x1 + 35
...
>>> def g(x):
... x0,x1 = x
... return 7*x1 - x0 + 5
...
>>> def penalty(x):
... return g(x) - f(x)
...
>>> @my.penalty.quadratic_inequality(penalty, k=1e12)
... def p(x):
... return 0.0
...
>>> mon = my.monitors.Monitor()
>>> my.solvers.fmin(f, [5,5], bounds=[(0,10)]*2, penalty=p, itermon=mon, disp=1)
Optimization terminated successfully.
Current function value: 11.898373
Iterations: 89
Function evaluations: 175
STOP("CandidateRelativeTolerance with {'xtol': 0.0001, 'ftol': 0.0001}")
array([7.81765653, 2.10228969])
>>>
>>> my.log_reader(mon)
绘制绘图以可视化受约束的求解器轨迹。
>>> fig = my.model_plotter(f, mon, depth=True, scale=1.0, bounds="0:10, 0:10", out=True)
>>>
>>> from matplotlib import cm
>>> import matplotlib.pyplot as plt
>>>
>>> x,y = my.scripts._parse_axes("0:10, 0:10", grid=True)
>>> x, y = np.meshgrid(x, y)
>>> z = 0*x
>>> s,t = x.shape
>>> for i in range(s):
... for j in range(t):
... xx,yy = x[i,j], y[i,j]
... z[i,j] = g([xx,yy])
...
>>> z = np.log(4*z*1.0+1)+2 # scale=1.0
>>> ax = fig.axes[0]
>>> ax.contour(x, y, z, 50, cmap=cm.cool)
<matplotlib.contour.QuadContourSet object at 0x12bc0d0d0>
>>> plt.show()
从上图中,您可以看到求解器开始最小化f
(color=jet),然后达到g
(color=cool),并沿着交叉点进行追踪,直到达到最小值。