运筹系列10:线性规划开源软件GLPK和PyMathProg

1. GLPK

GLPK全称GNU Linear Programming Kit,是一个开源的求解线性规划问题的工具套件,由c写成,可以求解大规模线性规划问题、混合整数规划问题。GLPK是免费的,在大规模问题上的性能要逊色于商用软件,求解的性能可以参考安装文件doc目录下的miplib2.txt,miplib3.txt和netlib.txt这三个文件,下面是截图:
在这里插入图片描述

GLPK安装非常简单,在centos系统下,执行:

sudo yum install glpk

GLPK使用MathProg(mathematical programming language)建模语言,可以使用GLPSOL这个cmd应用来进行交互。作为示例,新建一个文件problem.mod,输入:

var x1;
var x2;
maximize obj: 0.6 * x1 + 0.5 * x2;
s.t. c1: x1 + 2 * x2 <= 1;
s.t. c2: 3 * x1 + x2 <= 2;
solve;
display x1, x2;
end;

然后退出文件编辑,输入glpsol -m p.mod,最后输出了求解结果。

GLPSOL: GLPK LP/MIP Solver, v4.65
Parameter(s) specified in the command line:
 --math short.mod
Reading model section from short.mod...
9 lines were read
Generating obj...
Generating c1...
Generating c2...
Model has been successfully generated
GLPK Simplex Optimizer, v4.65
3 rows, 2 columns, 6 non-zeros
Preprocessing...
2 rows, 2 columns, 4 non-zeros
Scaling...
 A: min|aij| =  1.000e+00  max|aij| =  3.000e+00  ratio =  3.000e+00
Problem data seem to be well scaled
Constructing initial basis...
Size of triangular part is 2
*     0: obj =  -0.000000000e+00 inf =   0.000e+00 (2)
*     2: obj =   4.600000000e-01 inf =   0.000e+00 (0)
OPTIMAL LP SOLUTION FOUND
Time used:   0.0 secs
Memory used: 0.1 Mb (102250 bytes)
Display statement at line 8
x1.val = 0.6
x2.val = 0.2
Model has been successfully processed

2. PyMathProg

python环境下可以使用PyMathProg进行建模,背后使用的是GLPK。

pip install pymprog

下面是个简单的例子:

from pymprog import *
begin('bike production')
x, y = var('x, y') # variables
maximize(15 * x + 10 * y, 'profit')
x <= 3 # mountain bike limit
y <= 4 # racer production limit
x + y <= 5 # metal finishing limit
solve()

下面是几种定义变量的方式:

x,y = var('x','y') #默认变量是非负连续变量
z = var('z',3) #非负连续变量数组
a = var('a',kind=bool) #0/1变量。其他还有:float (默认): 连续变量;int: 整数变量;bool: 0/1变量
b = var('b',bounds = (0,5)) #限制上下界的连续变量
cindex = ('c1','c2','c3')
c = var('c',cindex) #使用自定义index set来定义变量

下面是关于index的一些示例:

A = (1, 2, 3) #interable的python类型(比如tuple,list,set……)都可以作为index。
B = (6, 7, 8)
C = iprod(A, B) #可以用这种方式形成更大的index集合。
x = var('x',C) #使用index集合创建变量
x[2,7].name

下面是关于parameter的一些示例:

k = par('k', [2,3,4]) #内容是list/tuple的话,那生成的就是一个parameter的list
p = par('P', {'east':0, 'west':2, 'south':3, 'north':1}) #内容是dict的话,生成的是以dict的key为下标的list
a, b, c = par('a,b,c', 3, (5,2)) #可以一次定义多个参数
r = [{(3,4):3, (1,2):4}, 5]
R = par('R', r) #可以recusive定义参数
x = var('x', 3)
x.value = 10 #可以重新定义参数值

下面是关于contraint的一些示例:

x = var('x', 3)
y = var('y')
c = [6,4,3]
sum(p*q for p,q in zip(c,x)) <= y #可以直接添加约束
st( sum(p*q for p,q in zip(c,x)) <= y ) #也可以用st表明这是一个约束

目标函数定义很简单:

maximize(sum(c[i]*x[i] for i in range(3)), 'Profit')

可以调用的solver有四种,线性规划有simplex、exact、interior三种(默认是simplex),整数规划是intopt,可以显式调用,例如:

solve(simplex)
print(vobj()) #获取目标函数值
print(x.prime) #获取变量求解值

下面是营养问题的综合示例:

from pymprog import *
minlev = group('minlev')
fruits = ('apple', 'pear', 'orange')
nutrit = ('fat', 'fibre', 'vitamin')
ntrmin = ( 10, 50, 30 ) # min nutrition intake
#nutrition ingredients of each fruit
ingred = ('apple': (3,4,5), 'pear': (2,4,1),
          'orange': (2,3,4))
diet = var('diet', fruits, int)
minimize(sum(diet[frt] for frt in fruits), 'mindiet')
for n, ntr in enumerate(nutrit):
   minlev[ntr] = sum( diet[frt] * ingred[frt][n] for frt in fruits) >= ntrmin[n]

点击这里可以参考更多例子。

猜你喜欢

转载自blog.csdn.net/kittyzc/article/details/82789439