线性规划-pulp-复杂矩阵

线性规划-pulp-复杂矩阵

1. 简介-线性规划

在数学中,线性规划(Linear Programming,简称LP)特指目标函数和约束条件皆为线性的最优化问题。线性规划是最优化问题中的一个重要领域。在作业研究中所面临的许多实际问题都可以用线性规划来处理,特别是某些特殊情况。最简单情况就,解线性方程组。

举个最简单的例子:

工厂生产A和B两种物品,需要原料配比分别是1:2:1和2:1:3.

现有原料是100,40,8。A和B的价格分别是5和10。

请问如何分配原材料才能获益最大?

求解一个线性方程组即可

2. pulp 包

  • Python中有很多的工具可以解决线性规划问题。由于pulp因其常用和方便性,故这里介绍pulp包的使用。pulp能够解决大部分的线性规划问题,如""整数规划(Integer Program)、01规划(Binary Program)还是混合整数线性规划(MILP),都能很好的解决。

  • pulp的github网址和官方文档,说实话官方文档做的并不好,但是里面介绍的例子还是很好的,如果只做最简单的线性规划可以看看学习一下。

  • 安装:按照一般套路pip install pulp 即可。

3. pulp使用流程

  • 获得问题的描述:求解最大值还是最小值,这个要明确了。输入是的数据是什么。
  • 确定需要的决策变量:需要求解的变量,定义好,大小,数据类型。
  • 制定约束条件:决策变量和输入数据之间存在什么样的约束条件。
  • 输入数据,求解得到结果。

那个实际例子来说明:

  1. 获得问题的描述:我们有矩阵X和矩阵Y,大小是1008*6。如图最上面的例子:是1008个产品,在6+6个指标上的需求。拆分成6+6两部分可以说明更加复杂的关系,以便更具有扩展性。

    目标,我们要求最大值: max ⁡ ∑ j = 1 n φ j = ∑ j = 1 n ∑ r = 1 6 μ j r y j r \max \sum_{j=1}^{n} \varphi_{j}=\sum_{j=1}^{n} \sum_{r=1}^{6} \mu_{j r} y_{j r} maxj=1nφj=j=1nr=16μjryjr其中 n = 1008 n=1008 n=1008,$ \mu_{j r} $是要求解的决策变量

  2. 制定约束条件如下:

    1. ∑ i = 1 6 v j i x j i = 1 , ∀ j \sum_{i=1}^{6} v_{j i} x_{j i}=1, \forall j i=16vjixji=1,j ,$v_{j i} $是要求解的决策变量

    2. ∑ r = 1 6 μ j r y k r − ∑ i = 1 6 v j i x k i ≤ 0 , ∀ j , k \sum_{r=1}^{6} \mu_{j r} y_{k r}-\sum_{i=1}^{6} v_{j i} x_{k i} \leq 0, \forall j, k r=16μjrykri=16vjixki0,j,k,$ \mu_{j r} 和 和 v_{j i} $是要求解的决策变量

    3. 1 / n ∑ j = 1 n v j i = ρ i , i = 1 , … , 6 1 / n \sum_{j=1}^{n} v_{j i}=\rho_{i}, i=1, \ldots, 6 1/nj=1nvji=ρi,i=1,,6 ρ i \rho_{i} ρi是要求解的决策变量

    4. 1 / n ∑ j = 1 n μ j r = 5 ∗ ρ r , r = 1 , … , 6 1 / n \sum_{j=1}^{n} \mu_{j r}=5*\rho_{r}, r=1, \ldots, 6 1/nj=1nμjr=5ρr,r=1,,6 ρ r \rho_{r} ρr是要求解的决策变量

    5. 0.15 &lt; = ρ r &lt; = 0.18 0.15&lt;=\rho_{r}&lt;=0.18 0.15<=ρr<=0.18……

    6. $ \mu_{j r} >=0 和 和 v_{j i}>=0 $

  3. 输入数据矩阵X和Y进行求解,即可。

4. 转换为代码求解

废话不多说,直接上代码。

# -*- coding: UTF-8 -*-
import pulp
import numpy as np

def assignment_problem(matrix_x,matrix_y):
    row_matrix_x = len(matrix_x) 
    col_matrix_x = len(matrix_x[0]) 

    row_matrix_y = len(matrix_x)
    col_matrix_y = len(matrix_x[0])
    
    #这里是将变量拉成一条直线,方便求解
    flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x] 
    
    #这是说明了是求最大值:LpMaximize,如果需要求最小值:LpMinimize。
    m = pulp.LpProblem('task_name', sense=pulp.LpMaximize)    

    #这里是mu和v2个决策变量的定义,是个矩阵形式,所以需要使用的dict这个函数,lowBound说明了下界大于等于0,和约束条件6对应
    #这里的数据类型默认是浮点型,也可以换成Ingredients,cat=’Ingredients‘就是整数, cat=pulp.LpBinary这是离散型数据就是整数了。
    var_mu = pulp.LpVariable.dicts("mu", (range(row_matrix_x), range(col_matrix_x)), lowBound = 0) 
    var_vi = pulp.LpVariable.dicts("vi", (range(row_matrix_x), range(col_matrix_x)), lowBound = 0) 
  
    #这里是6个变量,由于约束条件5中说明了上下届
    rho1 = pulp.LpVariable('rho1', lowBound = 0.15, upBound = 0.18) 
    rho2 = pulp.LpVariable('rho2', lowBound = 0.02, upBound = 0.17) 
    rho3 = pulp.LpVariable('rho3', lowBound = 0.15, upBound = 0.33) 
    rho4 = pulp.LpVariable('rho4', lowBound = 0.25, upBound = 0.33) 
    rho5 = pulp.LpVariable('rho5', lowBound = 0.08, upBound = 0.17) 
    rho6 = pulp.LpVariable('rho6', lowBound = 0.01, upBound = 0.18)  
    

    #对应这求解最大值,即目标。pulp.lpDot相乘操作
    m += pulp.lpDot(matrix_y.flatten(), flatten(var_mu)) 
   
    #对应这约束条件1,pulp.lpSum当成求和用即可。
    for j in range(row_matrix_x):
        m +=(pulp.lpSum(var_vi[j][i]*matrix_x[j][i] for i in range(col_matrix_x))==1)  
    
    #对应这约束条件2,看起来有点长。
    for j in range(row_matrix_x):
        for k in range(row_matrix_x): 
            m+=(pulp.lpSum(var_mu[j][i]*matrix_y[k][i] for i in range(col_matrix_x))-pulp.lpSum(var_vi[j][i]*matrix_x[k][i] for i in  range(col_matrix_x))<=0.0)
    
    #对应这约束条件3和4,为了方便就展开来写了。也可以改成上述的for循环。
    m += (pulp.lpSum(var_mu[j][0] for j in range(row_matrix_x))==rho1*row_matrix_x) 
    m += (pulp.lpSum(var_mu[j][1] for j in range(row_matrix_x))==rho2*row_matrix_x) 
    m += (pulp.lpSum(var_mu[j][2] for j in range(row_matrix_x))==rho3*row_matrix_x) 
    m += (pulp.lpSum(var_mu[j][3] for j in range(row_matrix_x))==rho4*row_matrix_x) 
    m += (pulp.lpSum(var_mu[j][4] for j in range(row_matrix_x))==rho5*row_matrix_x) 
    m += (pulp.lpSum(var_mu[j][5] for j in range(row_matrix_x))==rho6*row_matrix_x)  

    m += (pulp.lpSum(var_vi[j][0] for j in range(row_matrix_x))==row_matrix_x*rho1*5)
    m += (pulp.lpSum(var_vi[j][1] for j in range(row_matrix_x))==row_matrix_x*rho2*5)
    m += (pulp.lpSum(var_vi[j][2] for j in range(row_matrix_x))==row_matrix_x*rho3*5)
    m += (pulp.lpSum(var_vi[j][3] for j in range(row_matrix_x))==row_matrix_x*rho4*5)
    m += (pulp.lpSum(var_vi[j][4] for j in range(row_matrix_x))==row_matrix_x*rho5*5)
    m += (pulp.lpSum(var_vi[j][5] for j in range(row_matrix_x))==row_matrix_x*rho6*5)  
    
    #求解目标,就这么简单。不用怀疑
    m.solve()
    #可以打印出来各个约束条件,拆分开的很多,可以注释掉。
    print(m)
    
    #把求解的值,取出来的操作。 
    result_mu=[[pulp.value(var_mu[i][j]) for j in range(col_matrix_x)] for i in range(row_matrix_x)]
    result_vi=[[pulp.value(var_vi[i][j]) for j in range(col_matrix_x)] for i in range(row_matrix_x)]
    result_rho1=pulp.value(rho1)
    result_rho2=pulp.value(rho2)
    result_rho3=pulp.value(rho3)
    result_rho4=pulp.value(rho4)
    result_rho5=pulp.value(rho5)
    result_rho6=pulp.value(rho6)
 
    return {'objective':pulp.value(m.objective), 'result_mu':result_mu,'result_vi':result_vi}
 
#构造数据,我们这里为了方便直接写0,自己进行替换即可。
matrix_x=np.zeros((1008,6))
matrix_y=np.zeros((1008,6))
#输入数据求解,打印结果.  
res = assignment_problem(matrix_x,matrix_y) 
print('{res["objective"]}')
print(res['result_mu'])

5. 思考

  • 在代码中我们在m上加上不同的约束添加,看起来不可思议。pulp为了能够这么方便的使用,使用了操作符重载的操作。感谢大佬,让线性求解如此简单。

  • pulp是做线性规划的,所以不支持2个决策变量相乘。例如: ρ 1 ∗ ρ 2 \rho_{1}*\rho_{2} ρ1ρ2是不支持。查阅了很多发现真的不支持,这样好像就是非线性规划了,所以做不了。

  • 关系式中>=,<=。但是不支持>和<,请注意。

  • 一些参考链接,感谢下列的博客。

    例子很多,适合小白开始,这里举了常见的三个例子,如果不需要我上面这么复杂可以先看这个链接,当然其中代码存在一点问题,就是定义决策变量如果是个矩阵会出错,可能博客中是以前的版本吧。如果需要定义决策变量请参考我的代码,所有的都可以。

    官网数独求解这个例子很有意思。

Windows 7上安装pulp和glpk步骤: 亲测环境: Windows 6.1.7601 Service Pack 1 Build 7601 x64 Python 2.7.11 PuLP 1.6.8 GLPK 4.34 安装步骤: 1、下载PuLP安装包:前提是,已安装python2.6以及2.6以上版本,在网页(https://pythonhosted.org/PuLP/main/installing_pulp_at_home.html)上点击PuLP zipfile下载pulp包,当然,也可以在我的资源里下载 2、安装PuLP:将zipfile解压缩,并在命令行窗口中,进入解压缩的目录,然后输入命令:setup.py install 3、下载glpk安装包:在网页(https://sourceforge.net/projects/gnuwin32/files/glpk/4.34/)上,下载glpk-4.34-setup.exe(也可以在我的资源里下载),然后双击默认安装 4、按照以上步骤,安装完以后,写一个.py的脚本并运行,脚本内容: from pulp import * pulp.pulpTestAll() 然后,会看到以下类似输出结果: D:\002-Task_150524\117-17data_thesis\004-code\testPulp.py Testing zero subtraction Testing inconsistant lp solution Testing continuous LP solution Testing maximize continuous LP solution Testing unbounded continuous LP solution Testing Long Names Testing repeated Names Testing zero constraint Testing zero objective Testing LpVariable (not LpAffineExpression) objective Testing Long lines in LP Testing LpAffineExpression divide Testing MIP solution Testing MIP solution with floats in objective Testing MIP relaxation Testing feasibility problem (no objective) Testing an infeasible problem Testing an integer infeasible problem Testing column based modelling Testing dual variables and slacks reporting Testing fractional constraints Testing elastic constraints (no change) Testing elastic constraints (freebound) Testing elastic constraints (penalty unchanged) Testing elastic constraints (penalty unbounded) * Solver pulp.solvers.PULP_CBC_CMD passed. Solver pulp.solvers.CPLEX_DLL unavailable Solver pulp.solvers.CPLEX_CMD unavailable Solver pulp.solvers.CPLEX_PY unavailable Solver pulp.solvers.COIN_CMD unavailable Solver pulp.solvers.COINMP_DLL unavailable Testing zero subtraction Testing inconsistant lp solut
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值