当前位置:   article > 正文

使用SciPy.optimize.linprog函数解决线性规划问题指南_scipy linprog

scipy linprog

1、线性规划问题定义

linprog函数可以求解线性等式约束和不等式约束下的最小目标值问题。这类问题就是众所周知的线性规划。线性规划可以解决以下形式的问题:
m i n x   c T x s u c h   t h a t   A u b x ≤ b u b , A e q x = b e q , l ≤ x ≤   u , \mathop{min}\limits_{x} \ c^{T}x \\ {\rm such \ that} \ A_{ub}x \leq b_{ub}, \\ A_{eq}x = b_{eq }, \\ l \leq x \leq \ u, xmin cTxsuch that Aubxbub,Aeqx=beq,lx u,
其中 x x x是一个决策变量向量; c , b u b , b e q , l , u c,b_{ub},b_{eq},l,u c,bub,beq,l,u是向量; A u b , A e q A_{ub},A_{eq} Aub,Aeq是矩阵。在本教程中,我们将尝试使用 linprog 解决一个典型的线性规划问题。

2、线性规划问题示例

考虑下面这个简单的线性规划问题:
m a x x 1 , x 2 , x 3 , x 4 29 x 1 + 45 x 2 s u c h   t h a t   x 1 − x 2 − 3 x 3 ≤ 5 2 x 1 − 3 x 2 − 7 x 3 + 3 x 4 ≥ 10 2 x 1 + 8 x 2 + x 3 = 60 4 x 1 + 4 x 2 + x 4 = 60 0 ≤ x 0 0 ≤ x 1 ≤ 5 x 2 ≤ 0.5 − 3 ≤ x 3 \mathop{max}\limits_{x_{1},x_{2},x_{3},x_{4}} 29x_{1} + 45x_{2} \\ {\rm such \ that} \ x_{1} - x_{2} - 3x_{3} \leq 5 \\ 2x_{1} - 3x_{2} - 7x_{3} + 3x_{4} \geq 10 \\ 2x_{1} + 8x_{2} + x_{3} = 60 \\ 4x_{1} + 4x_{2} + x_{4} = 60 \\ 0 \leq x_{0} \\ 0 \leq x_{1} \leq 5 \\ x_{2} \leq 0.5 \\ -3 \leq x_{3} x1,x2,x3,x4max29x1+45x2such that x1x23x352x13x27x3+3x4102x1+8x2+x3=604x1+4x2+x4=600x00x15x20.53x3
我们需要进行一些数学操作,将目标问题转换成 linprog 可以接受的形式。

首先,我们来看看目标函数。我们希望最大化目标函数,但 linprog 只能接受最小化问题。将最大化 29 x 1 + 45 x 2 29x_{1} + 45x_{2} 29x1+45x2转换为最小化 − 29 x 1 − 45 x 2 -29x_{1} - 45x_{2} 29x145x2,就很容易解决这个问题。另外,目标函数中没有显示 x 3 , x 4 x_{3},x_{4} x3,x4。这意味着与 x 3 , x 4 x_{3},x_{4} x3,x4对应的权重为零。因此,目标函数可以转换为:
m i n x 1 , x 2 , x 3 , x 4 − 29 x 1 − 45 x 2 + 0 x 3 + 0 x 4 \mathop{min}\limits_{x_{1},x_{2},x_{3},x_{4}} -29x_{1} - 45x_{2} + 0x_{3} + 0x_{4} x1,x2,x3,x4min29x145x2+0x3+0x4

如果我们定义决策变量$ x = [x_{1},x_{2},x_{3},x_{4}]^{T} 的向量,那么在这个问题中, l i n p r o g 的目标权重向量 的向量,那么在这个问题中,linprog 的目标权重向量 的向量,那么在这个问题中,linprog的目标权重向量c$应该是
c = [ − 29 , − 45 , 0 , 0 ] T c = [-29,-45,0,0]^{T} c=[29,45,0,0]T

接下来,我们来看看两个不等式约束。第一个不等式是“小于”不等式,所以它已经是 linprog 接受的形式。第二个不等式是“大于”不等式,因此我们需要将两边乘以-1,将其转换为“小于”不等式。明确显示零系数后,我们得到:

x 1 − x 2 − 3 x 3 + 0 x 4 ≤ 5 − 2 x 1 + 3 x 2 + 7 x 3 − 3 x 4 ≤ − 10 x_{1} - x_{2} - 3x_{3} + 0x_{4} \leq 5 \\ -2x_{1} + 3x_{2} + 7x_{3} - 3x_{4} \leq -10 x1x23x3+0x452x1+3x2+7x33x410

这些方程可以转换成矩阵形式:

A u b x ≤ b u b A_{ub}x \leq b_{ub} Aubxbub

其中

A u b = [ 1 − 1 − 3 0 − 2 3 7 − 3 ] b u b = [ 5 − 10 ] A_{ub} =

[11302373]
\\ b_{ub} =
[510]
Aub=[12133703]bub=[510]

接下来,我们来看看两个相等约束条件。明确显示权重为零的是:

2 x 1 + 8 x 2 + 1 x 3 + 0 x 4 = 60 4 x 1 + 4 x 2 + 0 x 3 + 1 x 4 = 60 2x_{1} + 8x_{2} + 1x_{3} + 0x_{4} = 60 \\ 4x_{1} + 4x_{2} + 0x_{3} + 1x_{4} = 60 2x1+8x2+1x3+0x4=604x1+4x2+0x3+1x4=60

这些方程可以转换成矩阵形式:

A e q x = b e q A_{eq}x = b_{eq} Aeqx=beq

其中

A e q = [ 2 8 1 0 4 4 0 1 ] b e q = [ 60 60 ] A_{eq} =

[28104401]
\\ b_{eq} =
[6060]
Aeq=[24841001]beq=[6060]

最后,让我们考虑对单个决策变量的单独不等式约束,即所谓的“边界约束”或“简单约束”。这些约束可以通过linprog的界限参数来应用。正如linprog文档中所指出的,边界的默认值是0或无,这意味着每个决策变量的下限都是0,而每个决策变量的上限都是无穷大:所有的决策变量都是非负的。我们的界限是不同的,因此需要将每个决策变量的下限和上限指定为一个元组,并将这些元组组合成一个列表。
最后,我们可以使用 linprog 解决转换后的问题。

import numpy as np
from scipy.optimize import linprog
c = np.array([-29.0, -45.0, 0.0, 0.0])
A_ub = np.array([[1.0, -1.0, -3.0, 0.0],
                [-2.0, 3.0, 7.0, -3.0]])
b_ub = np.array([5.0, -10.0])
A_eq = np.array([[2.0, 8.0, 1.0, 0.0],
                [4.0, 4.0, 0.0, 1.0]])
b_eq = np.array([60.0, 60.0])
x0_bounds = (0, None)
x1_bounds = (0, 5.0)
x2_bounds = (-np.inf, 0.5)  # +/- np.inf can be used instead of None
x3_bounds = (-3.0, None)
bounds = [x0_bounds, x1_bounds, x2_bounds, x3_bounds]
result = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq, bounds=bounds)
print(result.message)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
The problem is infeasible. (HiGHS Status 8: model_status is Infeasible; primal_status is At lower/fixed bound)
  • 1

结果表明,我们的问题是不可行的,即没有满足所有约束条件的解向量。这并不一定意味着我们做错了什么,有些问题确实是不可行的。
然而,假设我们决定对 x 1 x_{1} x1的边界约束太紧,可以放宽到 0 ≤ x 1 ≤ 6 0\leq x_{1}\leq 6 0x16。接下来调整我们的代码 x1_bounds = (0,6)以反应更改并再次执行它:

x1_bounds = (0, 6)
bounds = [x0_bounds, x1_bounds, x2_bounds, x3_bounds]
result = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq, bounds=bounds)
print(result.message)
  • 1
  • 2
  • 3
  • 4
Optimization terminated successfully. (HiGHS Status 7: Optimal)
  • 1

结果显示优化成功。我们可以检查目标值(result.fun)是否与 c T x c^{T}x cTx相同:

x = np.array(result.x)
obj = result.fun
print(c @ x)
  • 1
  • 2
  • 3
-505.974358974359
  • 1
print(obj)
  • 1
-505.974358974359
  • 1

我们还可以检查所有约束条件是否在合理的公差范围内得到满足:

print(b_ub - (A_ub @ x).flatten())  # this is equivalent to result.slack
  • 1
[ 0.00000000e+00 -7.10542736e-15]
  • 1
print(b_eq - (A_eq @ x).flatten())  # this is equivalent to result.con
  • 1
[-7.10542736e-15  0.00000000e+00]
  • 1
print([0 <= result.x[0], 0 <= result.x[1] <= 6.0, result.x[2] <= 0.5, -3.0 <= result.x[3]])
  • 1
[True, True, True, True]
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/844202
推荐阅读
相关标签
  

闽ICP备14008679号