本文主要是介绍线性规划-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使用流程
- 获得问题的描述:求解最大值还是最小值,这个要明确了。输入是的数据是什么。
- 确定需要的决策变量:需要求解的变量,定义好,大小,数据类型。
- 制定约束条件:决策变量和输入数据之间存在什么样的约束条件。
- 输入数据,求解得到结果。
那个实际例子来说明:
-
获得问题的描述:我们有矩阵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} max∑j=1nφj=∑j=1n∑r=16μjryjr其中 n = 1008 n=1008 n=1008,$ \mu_{j r} $是要求解的决策变量
-
制定约束条件如下:
-
∑ 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} $是要求解的决策变量
-
∑ 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μjrykr−∑i=16vjixki≤0,∀j,k,$ \mu_{j r} 和 和 和v_{j i} $是要求解的决策变量
-
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/n∑j=1nvji=ρi,i=1,…,6, ρ i \rho_{i} ρi是要求解的决策变量
-
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/n∑j=1nμjr=5∗ρr,r=1,…,6, ρ r \rho_{r} ρr是要求解的决策变量
-
0.15 < = ρ r < = 0.18 0.15<=\rho_{r}<=0.18 0.15<=ρr<=0.18……
-
$ \mu_{j r} >=0 和 和 和v_{j i}>=0 $
-
-
输入数据矩阵X和Y进行求解,即可。
4. 转换为代码求解
废话不多说,直接上代码。
# -*- coding: UTF-8 -*-
import pulp
import numpy as npdef 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是不支持。查阅了很多发现真的不支持,这样好像就是非线性规划了,所以做不了。
-
关系式中>=,<=。但是不支持>和<,请注意。
-
一些参考链接,感谢下列的博客。
例子很多,适合小白开始,这里举了常见的三个例子,如果不需要我上面这么复杂可以先看这个链接,当然其中代码存在一点问题,就是定义决策变量如果是个矩阵会出错,可能博客中是以前的版本吧。如果需要定义决策变量请参考我的代码,所有的都可以。
官网数独求解这个例子很有意思。
这篇关于线性规划-pulp-复杂矩阵的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!