线性规划问题建模技巧与求解方法

0 引言

数学规划中最简单的一类问题是线性规划问题,它是整数规划及一些非线性规划问题的求解基础;
本篇就详细讲解下线性规划,问题建模的方法和技巧是最重要的部分会重点讲解,因为在解决实际问题时,把问题归结成一个线性规划数学模型是很重要的一步,但往往也是困难的一步,模型建立得是否恰当,直接影响到求解。
文末会用Python和OR-tools工具求解一个线性规划的例子,示范求解工具的使用。

1 定义

由前面一篇《数学建模workflow》已经介绍,优化问题一般包括三个要素:决策变量、目标函数、约束条件;
线性规划是目标函数和约束条件都为线性表达式的数学规划;
线性函数是什么样的呢?
一个函数是线性函数应当是这样的:
f ( X ) = A T X + b = ∑ i = 0 n a i x i + b f(X)=A^TX+b \\ =\sum_{i=0}^na_i x_i+b f(X)=ATX+b=i=0naixi+b
其中A为列向量,X为自变量的列向量,b为常量值;

线性规划问题的标准型一般为:
(1) m i n    z = ∑ j = 1 n c j x j \tag{1} min \ \ z=\sum_{j=1}^{n}c_j x_j min  z=j=1ncjxj(1)
(2) s . t . { f i ( X ) ≤ 0 ,   i = 1 , 2 , . . . , m i h k ( X ) = 0 ,   k = 1 , 2 , . . . o k l b ≤ x j ≤ u b ,   j = 1 , 2 , . . . , n \begin{alignedat}{2} \tag{2}s.t. \begin{cases} & f_i(X)&\leq 0,\ i&=1,2,...,m_i\\ &h_k(X)&= 0,\ k&=1,2,...o_k\\ lb\leq &x_j&\leq ub,\ j&=1,2,...,n \end{cases} \end{alignedat} s.t.lbfi(X)hk(X)xj0, i=0, kub, j=1,2,...,mi=1,2,...ok=1,2,...,n(2)
其中,约束条件(2)构成的集合为可行域;如果我们假设可行域为R,R为有限区域且非空时存在有限最优解,R为无限区域时目标函数值无界,R为空集则目标函数无可行解。如果线性规划存在有限最优解,则最优目标函数值在其可行域R的边界上。

2 建模技巧

一些问题建立初步数学模型之后,目标函数和约束往往含有绝对值、最大值、最小值符号等,这种不是线性规划问题,但是通过一些变换技巧依然可以转化成线性规划问题;

2.1 含有绝对值符号的问题

例如规划问题:
min ∑ i = 1 n ∣ x i ∣ s.t.    A X ≤ b \begin{alignedat}{2} &\text{min} \sum_{i=1}^{n}|x_i| \\ &\text{s.t.} \ \ \ AX\leq b \end{alignedat} mini=1nxis.t.   AXb
其中, X = [ x 1 , . . . , x n ] T X=[x_1,...,x_n]^T X=[x1,...,xn]T, A A A b b b为相应维数的矩阵和向量。
要把上面的问题变换成线性规划问题,可以根据如下事实:
对任意的 x i x_i xi,存在 u i , v i > 0 u_i,v_i>0 ui,vi>0满足
∣ x i ∣ = u i + v i x i = u i − v i \begin{alignedat}{2} |x_i|&=u_i+v_i \\ x_i&=u_i-v_i \end{alignedat} xixi=ui+vi=uivi
并且任意地,只要我们取 u i = ∣ x i ∣ + x i 2 , v i = ∣ x i ∣ − x i 2 u_i=\frac{|x_i|+x_i}{2},v_i=\frac{|x_i|-x_i}{2} ui=2xi+xi,vi=2xixi就能满足要求。

这样,就可以把问题的初始模型转化为如下线性规划模型:
min ∑ i = 1 n ( u i + v i ) s.t. { A ( u − v ) ≤ b u , v ≥ 0 \begin{alignedat}{2} &\text{min} \sum_{i=1}^{n}(u_i+v_i) \\ &\text{s.t.} \begin{cases} A(u-v)\leq b \\ u,v\geq 0 \end{cases} \end{alignedat} mini=1n(ui+vi)s.t.{A(uv)bu,v0
其中, u , = [ u 1 , . . . , u n ] T , v = [ v 1 , . . . , v n ] T u,=[u_1,...,u_n]^T,v=[v_1,...,v_n]^T u,=[u1,...,un]T,v=[v1,...,vn]T

2.2 含有最值符号的问题

例如规划问题:
min x i { max y i ∣ a i x i − b i y i ∣ } ,    i = 1 , 2 , . . . , n \text{min}_{x_i} \{\text{max}_{y_i}|a_ix_i-b_iy_i|\},\ \ i=1,2,...,n minxi{maxyiaixibiyi},  i=1,2,...,n
其中,决策变量 x i , y i x_i,y_i xi,yi取任意值, a i , b i a_i,b_i ai,bi为已知常数。

显然,这个也不是线性规划问题。

对于这个问题,如果我们取
z = max y i ∣ a i x i − b i y i ∣ z=\text{max}_{y_i}|a_ix_i-b_iy_i| z=maxyiaixibiyi
此式等价于
a i x i − b i y i ≤ z a_ix_i-b_iy_i\leq z aixibiyiz
可以标准化为
a i x i − b i y i − z ≤ 0 a_ix_i-b_iy_i-z\leq 0 aixibiyiz0
则原规划问题转化为如下线性规划问题:
min   z s.t.    a i x i − b i y i − z ≤ 0 ,    i = 1 , 2 , . . . , n \begin{alignedat}{2} &\text{min} \ \ z \\ &\text{s.t.} \ \ \ a_ix_i-b_iy_i-z\leq 0,\ \ i=1,2,...,n \end{alignedat} min  zs.t.   aixibiyiz0,  i=1,2,...,n

3 求解方法

我们以一个完整的例子来说明求解过程。该例子的问题及建模过程已经在之前一篇文章《数学建模workflow》介绍过,这里不再重复建模过程细节,不熟悉的同学请先看那一篇文章。
问题如下:
某机床厂生产甲、乙两种机床,每台销售后的利润分别为4000 元与3000 元。
生产甲机床需用 A、B机器加工,加工时间分别为每台 2 小时和 1 小时;生产乙机床
需用 A、B、C三种机器加工,加工时间为每台各一小时。若每天可用于加工的机器时
数分别为A 机器10 小时、B 机器8 小时和C 机器7 小时,问该厂应生产甲、乙机床各
几台,才能使总利润最大?
建立的线性规划模型为:
m a x     z = 4000 x 1 + 3000 x 2 s . t .                                        2 x 1 + x 2 ≤ 10 2 x 1 + x 2 ≤ 10 x 1 + x 2 ≤ 8 x 2 ≤ 7 x 1 ≥ 0 , x 2 ≥ 0 max\ \ \ z=4000x_1+3000x_2 \\ s.t.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ 2x_1 + x_2 \leq 10 \\ 2x_1 +x_2≤10 \\ x_1 + x_2 \leq 8 \\ x_2 \leq 7 \\ x_1 \geq 0,x_2 \geq 0 max   z=4000x1+3000x2s.t.                                      2x1+x2102x1+x210x1+x28x27x10,x20
我们用Python和OR-tools编程求解上述模型,完整的代码贴在下面,:

from ortools.linear_solver import pywraplp

def main():
    # Select a solver according to the type of your problem.
    solver = pywraplp.Solver(name='SolveSimpleSystem',problem_type=pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
    # Create the variables
    x1 = solver.NumVar(0, solver.infinity(), name='x1')
    x2 = solver.NumVar(0, 7, name='x2')
    # create the constraints
    constraint1 = solver.Constraint(-solver.infinity(),10)
    constraint1.SetCoefficient(x1, 2)
    constraint1.SetCoefficient(x2, 1)

    constraint2 = solver.Constraint(-solver.infinity(), 8)
    constraint2.SetCoefficient(x1, 1)
    constraint2.SetCoefficient(x2, 1)

    # Create the objective function
    objective = solver.Objective()
    objective.SetCoefficient(x1,4000)
    objective.SetCoefficient(x2, 3000)
    objective.SetMaximization()
    # Call the solver.
    solver.Solve()
    print('Number of variables =', solver.NumVariables())
    print('Number of constraints =', solver.NumConstraints())
    # The value of each variable in the solution.
    print('Solution:')
    print('x1 = ', x1.solution_value())
    print('x2 = ', x2.solution_value())
    # The objective value of the solution.
    opt_solution = 4 * x1.solution_value() + 3 * x2.solution_value()
    print('Optimal objective value =', opt_solution)

if __name__ == '__main__':
    main()

该代码是覆盖了线性规划中各种表达式的写法,非常具有代表性,仿照此例我们可以写出更复杂的模型的求解程序。程序中已经加了清晰的注释,相信大家不难看懂,就不解释了。
求解的最优方案:
在这里插入图片描述

4 参考资料

[1].https://developers.google.cn/optimization/introduction/python

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值