gpt4 book ai didi

python - scipy.optimize 中的线性约束

转载 作者:太空狗 更新时间:2023-10-30 00:58:29 32 4
gpt4 key购买 nike

我想使用 scipy.optimize 在大量线性不等式上最小化一个函数(最终是非线性的)。作为热身,我试图在 0<=x<=1、0<=y<=1 的方框上最小化 x+y。按照下面 Johnny Drama 的建议,我目前正在使用 dict-comprehesion 生成不等式字典,但没有得到预期的答案(最小值 = 0,最小值在 (0,0))。

新的代码部分(当前相关):

import numpy as np
from scipy.optimize import minimize



#Create initial point.

x0=[.1,.1]

#Create function to be minimized

def obj(x):
return x[0]+x[1]


#Create linear constraints lbnd<= A*(x,y)^T<= upbnd

A=np.array([[1,0],[0,1]])

b1=np.array([0,0])

b2=np.array([1,1])

cons=[{"type": "ineq", "fun": lambda x: np.matmul(A[i, :],x) -b1[i]} for i in range(A.shape[0])]

cons2=[{"type": "ineq", "fun": lambda x: b2[i]-np.matmul(A[i, :], x) } for i in range(A.shape[0])]

cons.extend(cons2)

sol=minimize(obj,x0,constraints=cons)

print(sol)

问题的原始版本:

我想使用 LinearConstraint 对象在 scipy.optimize 中,如教程中所述: "Defining linear constraints"

我尝试做一个更简单的例子,答案应该是显而易见的:在正方形 0<=x<=1, 0<=y<=1 上最小化 x+y。下面是我的代码,它返回错误“‘LinearConstraint’对象不可迭代”,但我看不出我是如何尝试迭代的。

编辑 1:该示例故意过于简单。最终,我想在大量线性约束下最小化非线性函数。我知道我可以使用字典理解将我的约束矩阵转换为字典列表,但我想知道“LinearConstraints”是否可以用作将矩阵转换为约束的现成方法。

编辑 2:正如 Johnny Drama 所指出的,LinearConstraint 是针对特定方法的。因此,在上面,我尝试使用他的建议来代替 dict-comprehension 来产生线性约束,但我仍然没有得到预期的答案。

原始代码部分(现在无关紧要):

from scipy.optimize import minimize
from scipy.optimize import LinearConstraint


#Create initial point.

x0=[.1,.1]

#Create function to be minimized

def obj(x):
return x[0]+x[1]


#Create linear constraints lbnd<= A*
#(x,y)^T<= upbnd

A=[[1,0],[0,1]]

lbnd=[0,0]

upbnd=[0,0]

lin_cons=LinearConstraint(A,lbnd,upbnd)

sol=minimize(obj,x0,constraints=lin_cons)

print(sol)

最佳答案

正如新手所说,使用 scipy.optimize.linprog如果您想解决 LP(线性程序),即您的目标函数您的约束是线性的。如果目标或约束之一不是线性的,我们将面临 NLP(非线性优化问题),可以通过 scipy.optimize.minimize 解决。 :

minimize(obj_fun, x0=xinit, bounds=bnds, constraints=cons)

其中 obj_fun 是您的目标函数,xinit 是初始点,bnds 是变量边界的元组列表,cons 约束指令列表。


这是一个例子。假设我们要解决以下 NLP:

enter image description here

由于所有约束都是线性的,我们可以用仿射线性函数 A*x-b 来表示它们,这样我们就有了不等式 A*x >= b。这里 A 是一个 3x2 矩阵,b 是 3x1 右侧向量:

import numpy as np
from scipy.optimize import minimize

obj_fun = lambda x: (x[0] - 1)**2 + (x[1] - 2.5)**2
A = np.array([[1, -2], [-1, -2], [-1, 2]])
b = np.array([-2, -6, -2])
bnds = [(0, None) for i in range(A.shape[1])] # x_1 >= 0, x_2 >= 0
xinit = [0, 0]

现在唯一剩下要做的就是定义约束,每个约束都必须是形式的字典

{"type": "ineq", "fun": constr_fun}

其中 constr_fun 是一个可调用函数,使得 constr_fun >= 0。因此,我们可以定义每个约束

cons = [{'type': 'ineq', 'fun': lambda x:  x[0] - 2 * x[1] + 2},
{'type': 'ineq', 'fun': lambda x: -x[0] - 2 * x[1] + 6},
{'type': 'ineq', 'fun': lambda x: -x[0] + 2 * x[1] + 2}]

然后我们就完成了。然而,事实上,对于许多约束来说,这可能是相当麻烦的。相反,我们可以通过以下方式直接传递所有约束:

cons = [{"type": "ineq", "fun": lambda x: A @ x - b}]

其中 @ 表示 matrix multiplication operator .放在一起

res = minimize(obj_fun, x0=xinit, bounds=bnds, constraints=cons)
print(res)

产量

     fun: 0.799999999999998
jac: array([ 0.79999999, -1.59999999])
message: 'Optimization terminated successfully.'
nfev: 16
nit: 4
njev: 4
status: 0
success: True
x: array([1.39999999, 1.69999999])

同样,您可以使用 LinearConstraint对象:

from scipy.optimize import LinearConstraint

# lb <= A <= ub. In our case: lb = b, ub = inf
lincon = LinearConstraint(A, b, np.inf*np.ones(3))

# rest as above
res = minimize(obj_fun, x0=xinit, bounds=bnds, constraints=(lincon,))

编辑:回答您的新问题:

# b1    <= A * x   <==>   -b1 >= -A*x        <==>   A*x - b1 >= 0
# A * x <= b2 <==> A*x - b2 <= 0 <==> -Ax + b2 >= 0
cons = [{"type": "ineq", "fun": lambda x: A @ x - b1}, {"type": "ineq", "fun": lambda x: -A @ x + b2}]
sol=minimize(obj,x0,constraints=cons)
print(sol)

关于python - scipy.optimize 中的线性约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52001922/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com