我有一个最小化问题:
import numpy as np
from scipy.optimize import Bounds, minimize, fmin_cobyla, linprog
A = \
np.array([[ 0.106667, 0.1333, 0.1333, 0.01],
[ 0.02, 0.6667, 0.1333, 0.12],
[0.0933, 0.06667, 0.6, 0.01]])
B = \
np.array([[27],
[57],
[28]])
l = \
np.array([[100],
[40],
[10],
[50]])
u = \
np.array([[200],
[80],
[20],
[150]])
def objfun(x):
return abs(np.sum(x - (u+l)/2))
x0 = \
np.array([[150],
[60],
[15],
[100]])
bounds = Bounds(l, u)
eq_cons1 = {'type': 'eq', 'fun': lambda x: np.matmul(A[0,:],x)-B[0]}
eq_cons2 = {'type': 'eq', 'fun': lambda x: np.matmul(A[1,:],x)-B[1]}
eq_cons3 = {'type': 'eq', 'fun': lambda x: np.matmul(A[2,:],x)-B[2]}
eq_cons = {'type': 'eq', 'fun': lambda x: x%1}
res = minimize(objfun, x0, method='SLSQP',
constraints=[eq_cons1, eq_cons2, eq_cons3, eq_cons],
bounds=bounds)
但添加最后一个约束
eq_cons = {'type': 'eq', 'fun': lambda x: x%1}
使其失败
出现以下错误
等式约束多于自变量(退出模式2)
我们怎样才能恰当地使用scipy来解决这类问题。
例如,我需要x是某个常数k的倍数,这就是为什么我使用模。
谢谢
1条答案
按热度按时间wmomyfyw1#
首先,请注意你的所有向量B,l,u,x0的维数都是2,而你的维数应该是1。这和你上一个问题中的错误是一样的。由于numpy的广播,使用维数错误的np.数组会导致令人惊讶的结果,所以请注意你的数组维数。
一些音符以任意顺序排列:
lambda x: A @ x - B
。这里,@
表示矩阵乘法运算符,它在幕后调用np.matmul。这使得代码不那么冗长。x0
不可行,并且违反了等式约束。长话短说,你基本上有两个选择:
1.将问题重写为整数优化问题,并使用MINLP求解器求解。还应注意,您的问题也可以用混合整数线性优化问题(MILP)来表示,因为您的目标和模约束中的绝对值可以线性化。
1.你可以用一个平滑的近似值(例如this one)来代替模函数,然后用一个NLP来近似求解MINLP。这里,你可以在目标函数中加入一个惩罚项,惩罚违反模约束的行为,从而试图将解推向整数值。然后,你可以将找到的解舍入到最接近的整数值。