不必编写自定义约束函数,您可以构造一个scipy.optimize.LinearConstraint
对象,并将其作为约束传递。它的构造要求上下界;独立变量向量的长度必须与传递给目标函数的变量长度相同,因此像t[0] + t[1] = 1
这样的约束应该被重新表述为以下形式(因为t
的长度为4,可以从其在matr_t()
中的操作中看出):
![constraint](https://istack.dev59.com/3farR.webp)
另外,minimize
也会在实数空间上进行优化,因此 t[i]
是实数的限制已经嵌入到算法中。那么完整代码如下:
import numpy as np
from scipy.optimize import minimize, LinearConstraint
def matr_t(t):
return np.array([[t[0], 0],[t[2]+complex(0,1)*t[3], t[1]]]
def target(t):
arr2 = matr_t(t)
ret = 0
for i, v1 in enumerate(arr):
for j, v2 in enumerate(v1):
ret += abs(arr[i][j]-arr2[i][j])**2
return ret
arr = np.array([[0.8, 0.2],[-0.1, 0.14]])
linear_constraint = LinearConstraint([[1, 1, 0, 0]], [1], [1])
result = minimize(target, x0=[0.5, 0.5, 0, 0], constraints=[linear_constraint])
x_opt = result.x
minimum = result.fun
对于一个更深入的例子,让我们使用经济学中常见的问题Cobb-Douglas效用最大化作为说明性示例。这实际上是一个受限制的最大化问题,但由于minimize
是一个最小化函数,它必须被强制转换为最小化问题(只需否定目标函数)。此外,为了将约束传递为scipy.optimize.LinearConstraint
对象,我们必须编写具有下限和上限的约束条件。因此,优化问题如下所示:
![problem](https://istack.dev59.com/dNJe7.webp)
在这个函数中,有两个变量
x
和
y
;其余的都是超参数,必须从外部提供(alpha、beta、
px
、
py
和
B
)。其中只有 alpha 和 beta 是目标函数的参数,因此它们必须通过
minimize
的
args=
参数传递给它(在下面的示例中为
alphas
)。
优化问题解决了
x
和
y
值,使得目标函数在约束条件下达到最小值。它们必须作为单个对象(在下面的函数中为
variables
)传递给目标函数。如前所述,我们必须对这些变量(目标函数的
x
和
y
)进行合理的猜测,以便算法收敛。
from scipy.optimize import minimize, LinearConstraint
def obj_func(variables, hyperparams):
x, y = variables
alpha, beta = hyperparams
return - x**alpha * y**beta
B, px, py, alphas = 30, 2, 5, [1/3, 2/3]
linear_constraint = LinearConstraint([[px, py], [1, 0], [0, 1]], [-np.inf, 0, 0], [B, np.inf, np.inf])
result = minimize(obj_func, x0=[1, 1], args=alphas, constraints=[linear_constraint])
x_opt, y_opt = result.x
optimum = result.fun
result.x
是最小化值,result.fun
是局部最小值。
Cobb-Douglas 有一个封闭形式的解决方案,在示例输入中,正确的解决方案是 (x_opt, y_opt) = (5, 4)
。 minimize
的结果与此不完全相等,但由于 minimize
是迭代算法,这是它停止之前所能达到的最接近值。
t.imag.sum()
为零,因为我们只将其与实数1进行比较,但我的编辑显示了更明确的限制条件。 - askewchancon
>0,<0,>=0或<=0,该怎么做呢?我发现type
只有两种类型ineq
和eq
。 - wyx