天天看点

使用python求解混合整数规划问题0.例题1.Python代码2.结果3.求解0-1规划问题4.说明

  摘要:当前使用Python求解混合整数规划问题的实例大多使用了cplex库。本文基于教材上的混合整数规划和0-1整数规划两道例题,尝试使用Python语言予以解决,得到的答案与教材上一致。现将有关求解过程及代码附上,以期对运筹学初学者有所裨益。

  关键词:整数规划; 0-1规划; cplex;Python

0.例题

  目标函数:

  M a x   z = 3 x 1 + x 2 + 3 x + 3 \ Max \ z=3x_1+x_2+3x+3  Max z=3x1​+x2​+3x+3

  约束条件: { − x 1 + 2 x 2 + x 3 ≤ 4 4 x 2 − 3 x 3 ≤ 2 x 1 − 3 x 2 + 2 x 3 ≤ 3 x 1 , x 2 , x 3 ≥ 0 x 1 为 整 数 x 3 为 0 − 1 变 量 \left\{\begin{aligned} -x_1+2x_2+x_3\leq 4 \\ 4x_2-3x_3\leq 2\\ x_1-3x_2+2x_3\leq3\\ x_1,x_2,x_3\geq 0\\ x_1为整数\\ x_3为0-1变量\\ \end{aligned}\right. ⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧​−x1​+2x2​+x3​≤44x2​−3x3​≤2x1​−3x2​+2x3​≤3x1​,x2​,x3​≥0x1​为整数x3​为0−1变量​

1.Python代码

#导入cplex
import cplex
from cplex.exceptions import CplexError

my_obj=[3.0,1.0,3.0]#目标函数系数
my_ctype='ICI'#目标函数变量的类型,一般就是C,整数类型就是I就是integer
my_ub=[cplex.infinity, cplex.infinity,1]#变量的约束条件上限
my_lb=[0,0,0]#变量的约束条件下限
my_colnames=['x1','x2','x3']#column names列向量的名字
my_rhs=[4.0,2.0,3.0]#约束条件的值相当于b
my_rownames=['r1','r2','r3']#row names行向量的名字
#是约束条件的形式,L为小于号“less-than”,大于号是‘G’,即'greater than'
my_sense='LLL'

def populatebyrow(prob):
    #设置目标函数类型:求max or min
    prob.objective.set_sense(prob.objective.sense.maximize)
    #设置(增加)变量,明确目标函数,约束条件上限、下限,变量类型,还有变量名称
    prob.variables.add(obj=my_obj,lb=my_lb,ub=my_ub,types=my_ctype,
                      names=my_colnames)
    #对应的约束方程
    rows=[[['x1','x2','x3'],[-1.0,2.0,1.0]],
          [['x2','x3'],[4.0,-3.0]],
          [['x1','x2','x3'],[1.0,-3.0,2.0]]]
    #设置(增加)约束条件
    prob.linear_constraints.add(lin_expr=rows, senses=my_sense,
                         rhs=my_rhs,names=my_rownames)

#初始化模型
my_prob=cplex.Cplex()
#计算
handle=populatebyrow(my_prob)
#求解
my_prob.solve()
#输出结果
print(my_prob.solution.get_objective_value())
x = my_prob.solution.get_values()
print(x) 
           

2.结果

使用python求解混合整数规划问题0.例题1.Python代码2.结果3.求解0-1规划问题4.说明

  可以看到,求得最优解:   z = 16.25 ;   x 1 = 4.0 , x 2 = 1.25 , x 3 = 1.0 \ z=16.25; \ x_1=4.0, x_2=1.25, x_3=1.0  z=16.25; x1​=4.0,x2​=1.25,x3​=1.0

3.求解0-1规划问题

(1)例题

  某公司计划在市区的东、南、西、北四个区建立销售门市部,拟议有10个位置   A i j ( j = 1 , 2 , . . . , 10 ) \ A_{ij}(j=1,2,...,10)  Aij​(j=1,2,...,10)可供选择,考虑到各地居民消费水平及居民居住密集度,规定:

 (1)在东区由   A 1 , A 2 , A 3 \ A_1,A_2,A_3  A1​,A2​,A3​三个点中至多选择两个;

 (2)在西区由   A 4 , A 5 \ A_4,A_5  A4​,A5​两个点中至少选择一个;

 (3)在南区由   A 6 , A 7 \ A_6,A_7  A6​,A7​两个点中至少选择一个;

 (4)在北区由   A 8 , A 9 , A 10 \ A_8,A_9,A_{10}  A8​,A9​,A10​三个点中至少选择两个。

  A 1 \ A_1  A1​   A 2 \ A_2  A2​   A 3 \ A_3  A3​   A 4 \ A_4  A4​   A 5 \ A_5  A5​   A 6 \ A_6  A6​   A 7 \ A_7  A7​   A 8 \ A_8  A8​   A 9 \ A_9  A9​   A 10 \ A_{10}  A10​
投资额 100 120 150 80 70 90 80 140 160 180
利润 36 40 50 22 20 30 25 48 58 61

    A j \ A_j  Aj​各点的设备投资及每年可获利润由于地点不同而不同,预测情况如上表,但总投资金额不超过720万元,问应该选择哪几个销售点,可使利润最大。

(2)求解

  解:设   0 − 1 \ 0-1  0−1变量   x i = 1 ( A i 点 被 选 用 ) \ x_i=1(A_i点被选用)  xi​=1(Ai​点被选用)或   x i = 0 ( A i 点 未 被 选 用 ) \ x_i=0(A_i点未被选用)  xi​=0(Ai​点未被选用),建立数学模型如下:

  目标函数:

  M a x   z = 36 x 1 + 40 x 2 + 50 x 3 + 22 x 4 + 20 x 5 + 30 x 6 + 25 x 7 + 48 x 8 + 58 x 9 + 61 x 10 \ Max\ z=36x_1+40x_2+50x_3+22x_4+20x_5+30x_6+25x_7+48x_8+58x_9+61x_{10}  Max z=36x1​+40x2​+50x3​+22x4​+20x5​+30x6​+25x7​+48x8​+58x9​+61x10​

  约束条件: { 100 x 1 + 120 x 2 + . . . + 160 x 9 + 180 x 10 ≤ 720 x 1 + x 2 + x 3 ≤ 2 x 4 + x 5 ≥ 1 x 6 + x 7 ≥ 1 x 8 + x 9 + x 10 ≥ 2 1 ≥ x i ≥ 0 , i = 1 , 2 , . . . , 10 x i 为 0 − 1 变 量 , i = 1 , 2 , . . . , 10 \left\{\begin{aligned} 100x_1+120x_2+...+160x_9+180x_{10} \leq 720 \\ x_1+x_2+x_3 \leq 2\\ x_4+x_5 \geq 1\\ x_6+x_7 \geq 1\\ x_8+x_9+x_{10} \geq 2\\ 1 \geq x_i \geq 0, i=1,2,...,10\\ x_i为0-1变量,i=1,2,...,10\\ \end{aligned}\right. ⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧​100x1​+120x2​+...+160x9​+180x10​≤720x1​+x2​+x3​≤2x4​+x5​≥1x6​+x7​≥1x8​+x9​+x10​≥21≥xi​≥0,i=1,2,...,10xi​为0−1变量,i=1,2,...,10​

(3)代码

import cplex
from cplex.exceptions import CplexError

my_obj=[36.,40.,50.,22.,20.,30.,25.,48.,58.,61.]
my_ctype='IIIIIIIIII'
my_ub=[1,1,1,1,1,1,1,1,1,1]
my_lb=[0,0,0,0,0,0,0,0,0,0]
my_colnames=['x1','x2','x3','x4','x5','x6','x7','x8','x9','x10']
my_rhs=[720,2,1,1,2]
my_rownames=['r1','r2','r3','r4','r5']
my_sense='LLGGG'
def populatebyrow(prob):
    prob.objective.set_sense(prob.objective.sense.maximize)
    prob.variables.add(obj=my_obj, lb=my_lb, ub=my_ub,
                       types=my_ctype, names=my_colnames)
    rows=[[['x1','x2','x3','x4','x5','x6','x7','x8','x9','x10'],[100.0,120.0,150.0,80.0,70.0,90.0,80.0,140.0,160.0,180.0]],
          [['x1','x2','x3'],[1.0,1.0,1.0]],
          [['x4','x5'],[1.,1.]],
          [['x6','x7'],[1.,1.]],
          [['x8','x9','x10'],[1.,1.,1.]]]
    prob.linear_constraints.add(lin_expr=rows, senses=my_sense,
                         rhs=my_rhs,names=my_rownames)


my_prob=cplex.Cplex()
handle=populatebyrow(my_prob)
my_prob.solve()
print(my_prob.solution.get_objective_value())
x = my_prob.solution.get_values()
print(x) 
           

(4)结果

使用python求解混合整数规划问题0.例题1.Python代码2.结果3.求解0-1规划问题4.说明

4.说明

  (1)以上两个例题均来自韩伯棠老师主编的《管理运筹学》(第四版)教材中,韩老师授课十分有趣、清楚,是初学运筹学者比较好的入门课程。

  (2)网上有很多关于cplex的说明,本人了解不全,很多设置还搞不清楚,请各位批评指正。