概述

整数规划的定义

  • 数学规划中的变量部分或者全部限制为整数时,称为整数规划。整数规划又分为整数线性规划和整数非线性规划,现流行的求解整数规划的问题往往只适用于求解整数线性规划,故我们提到整数规划都是指整数线性规划。

整数规划的分类

  • 如不加说明整数规划就是指整数线性规划
  1. 变量全部限制为整数时,称纯(完全)整数规划
  2. 变量部分限制为整数时,称混合整数规划

整数规划特点

  1. 原线性规划有最优解,当自变量限制为整数后,可能无可行解,可能最优解值变差
  2. 整数规划的最优解不能按照实数最优解直接取整得到

求解方法分类

  1. 分支定界法——纯或混合整数规划
  2. 割平面法——纯或混合整数规划
  3. 隐枚举法——0-1整数规划

①过滤隐枚举法
②分支隐枚举法

  1. 匈牙利法——指派问题(0-1规划特殊情形)
  2. 蒙特卡洛法——各种类型规划

0-1型整数规划

  • 在实际问题中,引入0-1型变量,就可以把有各种情况需要分别讨论的数学规划问题统一在一个问题中讨论

相互排斥的约束条件

  1. 两种运输方法只能选择一种,用车运输的约束条件python强化学习求解整数规划 整数规划 python_python,用船运输的约束条件python强化学习求解整数规划 整数规划 python_python强化学习求解整数规划_02,为了统一在一个问题中,引入0-1变量
    python强化学习求解整数规划 整数规划 python_python_03
    则约束条件可改为
    python强化学习求解整数规划 整数规划 python_最优解_04
  2. python强化学习求解整数规划 整数规划 python_约束条件_05,可改写为
    python强化学习求解整数规划 整数规划 python_约束条件_06
  3. 如果有m个约束条件
    python强化学习求解整数规划 整数规划 python_matlab_07
    引入m个0-1变量
    python强化学习求解整数规划 整数规划 python_最优解_08
    则约束条件可改为
    python强化学习求解整数规划 整数规划 python_约束条件_09

Matlab、python线性整数规划求解

  • Matlab求解混合整数线性规划的命令为

[x,fval]=intlinprog(f,intcon,A,b,Aeq,beq,lb,ub)

背包问题

例题

  • 有10件货物从甲地运送到乙地,每件货物的重量(单位:吨)和利润(单位:元)如下表所示:

物品

1

2

3

4

5

6

7

8

9

10

重量

6

3

4

5

1

2

3

5

4

2

利润

540

200

180

350

60

150

280

450

320

120

  • 由于只有一辆载重为30t的火车能用来运送货物,所以只能选择部分货物进行运送
  • 要求确定运送哪些货物,使得运送货物的总利润最大

分析


  • python强化学习求解整数规划 整数规划 python_matlab_10
    python强化学习求解整数规划 整数规划 python_约束条件_11为第python强化学习求解整数规划 整数规划 python_matlab_12件货物的重量,python强化学习求解整数规划 整数规划 python_最优解_13为第python强化学习求解整数规划 整数规划 python_matlab_12件货物的利润

  • python强化学习求解整数规划 整数规划 python_matlab_15

Matlab求解

c = -[540 200 180 350 60 150 280 450 320 120];  % 目标函数的系数矩阵(最大化问题记得加负号)
intcon=[1:10];  % 整数变量的位置(一共10个决策变量,均为0-1整数变量)
A = [6 3 4 5 1 2 3 5 4 2];  b = 30;   % 线性不等式约束的系数矩阵和常数项向量(物品的重量不能超过30)
Aeq = []; beq =[];  % 不存在线性等式约束
lb = zeros(10,1);  % 约束变量的范围下限
ub = ones(10,1);  % 约束变量的范围上限
%最后调用intlinprog()函数
[x,fval]=intlinprog(c,intcon,A,b,Aeq,beq,lb,ub);
fval = -fval

python求解

from pulp import *
#设置对象
my_package=LpProblem(name='package probelm',sense=LpMaximize)
#设置变量
var_num = 10
variables = [LpVariable(name='x%d' % i, lowBound=0,upBound=1,cat=const.LpInteger) for i in range(1, var_num+1)]
#设置目标函数
p=[540,200,180,350,60,150,280,450,320,120]
objective=sum([p[i]*variables[i] for i in range(0, var_num)])
#设置约束条件
constraints = []
w=[6,3,4,5,1,2,3,5,4,20]
constraints.append(sum([w[i]*variables[i] for i in range(0, var_num)]) <= 30)
#载入变量
my_package += objective
for cons in constraints:
    my_package += cons
#求解
status = my_package.solve()#0: 'Not Solved', 1: 'Optimal', -1: 'Infeasible', -2: 'Unbounded', -3: 'Undefined'
#输出结果
if LpStatus[status]=='Optimal':#LpStatus是一字典
    for v in my_package.variables():
        print('%s %d'% (v.name,v.varValue))
    print('目标函数值为:%g'% my_package.objective.value())

结果

x1 1 x10 1 x2 1 x3 0 x4 1 x5 0 x6 1 x7 1 x8 1 x9 1
目标函数值为:2410

指派问题

题目

  • 5名候选人的百米成绩(S)如下,怎么选拔队员组成4×100米混合泳接力队伍?

蝶泳

仰泳

蛙泳

自由泳


66.8

75.6

87

58.6


57.2

66

66.4

53


78

67.8

84.6

59.4


70

74.2

69.6

57.2


67.4

71

83.8

62.4

分析

  • 每个人只能入选4种泳姿之一,每种泳姿有且仅有1人参加,总耗时要最小

  • python强化学习求解整数规划 整数规划 python_matlab_16
    python强化学习求解整数规划 整数规划 python_python_17队员python强化学习求解整数规划 整数规划 python_python强化学习求解整数规划_18参加第python强化学习求解整数规划 整数规划 python_matlab_19种泳姿的耗时

python强化学习求解整数规划 整数规划 python_matlab_20

Matlab求解

c = [66.8 75.6 87 58.6 57.2 66 66.4 53 78 67.8 84.6 59.4 70 74.2 69.6 57.2 67.4 71 83.8 62.4]';  % 目标函数的系数矩阵(先列后行的写法)
intcon = [1:20];  % 整数变量的位置(一共20个决策变量,均为0-1整数变量)
% 线性不等式约束的系数矩阵和常数项向量(每个人只能入选四种泳姿之一,一共五个约束)
A = [1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
       0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0;
       0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0;
       0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0;
       0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1];
% A = zeros(5,20);
% for i = 1:5
%     A(i, (4*i-3): 4*i) = 1;
% end
b = [1;1;1;1;1];
% 线性等式约束的系数矩阵和常数项向量 (每种泳姿有且仅有一人参加,一共四个约束)
Aeq = [1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0;
          0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0;
          0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0;
          0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1];
% Aeq = [eye(4),eye(4),eye(4),eye(4),eye(4)];  % 或者写成 repmat(eye(4),1,5)  
beq = [1;1;1;1];
lb = zeros(20,1);  % 约束变量的范围下限
ub = ones(20,1);  % 约束变量的范围上限
%最后调用intlinprog()函数
[x,fval] = intlinprog(c,intcon,A,b,Aeq,beq,lb,ub)
% reshape(x,4,5)'
%      0     0     0     1    甲自由泳
%      1     0     0     0    乙蝶泳
%      0     1     0     0    丙仰泳
%      0     0     1     0    丁蛙泳
%      0     0     0     0    戊不参加

python求解指派问题

import numpy as np
from scipy import optimize #函数优化器(最小化器)
#指派矩阵
c = [[66.8, 75.6, 87, 58.6],[ 57.2, 66, 66.4, 53],[ 78, 67.8, 84.6, 59.4],[ 70, 74.2, 69.6, 57.2],[67.4, 71, 83.8, 62.4]]
c = np.array(c)
row_id,col_id=optimize.linear_sum_assignment(c)#row_id:array([0, 1, 2, 3], dtype=int64) col_id:array([3, 0, 1, 2])
re=np.zeros((5,4),dtype=int)
re[row_id,col_id]=1
print(re)
print(c[row_id,col_id ].sum())

结果

[[0 0 0 1] [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 0]]
253.20000000000002

钢管切割问题

题目及分析

python强化学习求解整数规划 整数规划 python_约束条件_21

Matlab求解

%% (1)枚举法找出同一个原材料上所有的切割方法
for i = 0: 2  % 2.9m长的圆钢的数量
    for j = 0: 3  % 2.1m长的圆钢的数量
        for k = 0:6   % 1m长的圆钢的数量
            if 2.9*i+2.1*j+1*k >= 6 && 2.9*i+2.1*j+1*k <= 6.9
                disp([i, j, k])
            end
        end
    end
end
%% (2) 线性整数规划问题的求解
c = ones(7,1);  % 目标函数的系数矩阵
intcon=[1:7];  %  整数变量的位置(一共7个决策变量,均为整数变量)
A = -[1 2 0 0 0 0 1;  
         0 0 3 2 1 0 1;
         4 1 0 2 4 6 1];  % 线性不等式约束的系数矩阵
b = -[100 100 100]'; %  线性不等式约束的常数项向量
lb = zeros(7,1); % 约束变量的范围下限
[x,fval]=intlinprog(c,intcon,A,b,[],[],lb)

python求解

#设置对象
from pulp import *
my_tube=LpProblem(name='tube probelm',sense=LpMinimize)
#设置变量
var_num = 7
variables = [LpVariable(name='x%d' % i, lowBound=0,upBound=None,cat=const.LpInteger) for i in range(1, var_num+1)]
#设置目标函数
c=[1]*7
objective=sum([c[i]*variables[i] for i in range(0, var_num)])
#设置约束条件
constraints = []
A=np.array([[1,2,0,0,0,0,1],[0,0,3,2,1,0,1],[4,1,0,2,4,6,1]])
b=np.array([100,100,100])
for i in range(3):
    constraints.append(sum([A[i][j]*variables[j] for j in range(0, var_num)]) >= b[i])
#载入变量
my_tube += objective
for cons in constraints:
    my_tube += cons
#求解
status = my_tube.solve()#0: 'Not Solved', 1: 'Optimal', -1: 'Infeasible', -2: 'Unbounded', -3: 'Undefined'
#输出结果
if LpStatus[status]=='Optimal':#LpStatus是一字典
    for v in my_tube.variables():
        print('%s = %d'% (v.name,v.varValue))
    print('目标函数值为:%g'% my_tube.objective.value())
my_tube
tube_probelm:
MINIMIZE
1*x1 + 1*x2 + 1*x3 + 1*x4 + 1*x5 + 1*x6 + 1*x7 + 0
SUBJECT TO
_C1: x1 + 2 x2 + x7 >= 100

_C2: 3 x3 + 2 x4 + x5 + x7 >= 100

_C3: 4 x1 + x2 + 2 x4 + 4 x5 + 6 x6 + 7 x7 >= 100

VARIABLES
0 <= x1 Integer
0 <= x2 Integer
0 <= x3 Integer
0 <= x4 Integer
0 <= x5 Integer
0 <= x6 Integer
0 <= x7 Integer

结果

  • Matlab求解结果为:

x =

14.0000
43.0000
32.0000
2.0000
0
0
0

fval =

91
  • python求解结果为:

x1 = 8 x2 = 46 x3 = 26 x4 = 11 x5 = 0 x6 = 0 x7 = 0
目标函数值为:91

  • 说明不止一个最优解