假设我有一个矩阵
arr = array([[0.8, 0.2],[-0.1, 0.14]])
具有目标函数
def matr_t(t):
return 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
现在我想在
t[i]
是实数的假设下最小化这个目标函数,比如 t[0]+t[1]=1
.
这个约束
t[0] + t[1] = 1
将是一个等式 (
type='eq'
) 约束,您在其中创建一个必须等于零的函数:
def con(t):
return t[0] + t[1] - 1
然后你对你的约束做一个
dict
(如果有多个则为字典列表):
cons = {'type':'eq', 'fun': con}
我从未尝试过,但我相信要保持
t
真实,您可以使用:
con_real(t):
return np.sum(np.iscomplex(t))
让你的
cons
包括两个约束:
cons = [{'type':'eq', 'fun': con},
{'type':'eq', 'fun': con_real}]
然后你将
cons
喂入 minimize
为:
scipy.optimize.minimize(func, x0, constraints=cons)
无需编写自定义约束函数,您可以构造一个
scipy.optimize.LinearConstraint
对象并将其作为约束传递。它的构造要求上限和下限;自变量向量的长度也必须与传递给目标函数的变量长度相同,因此像t[0] + t[1] = 1
这样的约束应该重新表述如下(因为t
的长度是4,从它可以看出matr_t()
中的操纵):
此外,
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 # array([ 0.83, 0.17, -0.1 , 0.])
minimum = result.fun # 0.0418