【学习笔记】Matlab和python双语言的学习(整数规划和0-1规划)

文章目录


前言

通过模型算法,熟练对Matlab和python的应用。

学习视频链接:
https://www.bilibili.com/video/BV1EK41187QF?p=26&vd_source=67471d3a1b4f517b7a7964093e62f7e6

一、整数规划和0-1规划

  • 在规划问题中,有些最优解可能是分数或小数,但对于某些具体问题,常要求某些变量(全部或部分)的解必须是整数。例如,当变量代表的是机器的台数 ,工作的人数 或装货的车数 等。为了满足整数的要求,初看起来似乎只要把已得的非整数解舍入化整就可以了。实际上化整后的数不见得是可行解和最优解,所以应该有特殊的方法来求解整数规划。在整数规划中,如果所有变量都限制为整数,则称为纯整数规划 ;如果仅一部分变量限制为整数,则称为混合整数规划 。整数规划的一种特殊情形是0-1规划 ,它的变数仅限于0或1
  • 本文讨论的整数规划和0-1规划都在线性规划的范畴

二、典型示例

1.背包问题

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

  • 由于只有一辆最大载重为30t的货车能用来运送货物,所以只能选择部分货物进行运送。

  • 要求确定运送哪些货物,使得运送这些货物的总利润最大。

    记 x i = { 1 , 运送了第 i 件货物 0 , 没有运送第 i 件货物 , i = 1 , 2 , ... , 10 \left.\text{记}\quad x_{i}=\begin{cases}1,\text{运送了第}i\text{件货物}\\0,\text{没有运送第}i\text{件货物}\end{cases}\right.,i=1,2,\ldots,10 记xi={1,运送了第i件货物0,没有运送第i件货物,i=1,2,...,10

    记 w i w_i wi 表示第 i 件物品的重量, p i p_i pi 表示第 i 件物品的利润

    模型建立:
    m a x ∑ i = 1 10 p i x i s . t . { ∑ i = 1 10 w i x i ≤ 30 x i ∈ { 0 , 1 } \begin{aligned}max\sum_{i=1}^{10}p_ix_i\end{aligned}\\s.t.\begin{cases}\sum_{i=1}^{10}w_ix_i\leq30\\x_i\in\{0,1\}\end{cases} maxi=1∑10pixis.t.{∑i=110wixi≤30xi∈{0,1}

2.指派问题

  • 已知5名游泳候选人的百米成绩,怎么选拔队员组成 4×100 米混合泳接力队伍

    (表中的数据是各运动员百米游泳的耗时)

  • 候选人: i = 1 , 2 , 3 , 4 , 5 i = 1,2,3,4,5 i=1,2,3,4,5

  • 泳姿: j = 1 , 2 , 3 , 4 j = 1,2,3,4 j=1,2,3,4

  • x i j = { 1 , 队员 i 参加第 j 种泳姿 0 , 队员 i 不参加第 j 种泳姿 x_{ij}=\begin{cases}&1 ,\text{队员} i\text{参加第}j\text{种泳姿}\\&0 ,\text{队员} i\text{不参加第}j\text{种泳姿}\end{cases} xij={1,队员i参加第j种泳姿0,队员i不参加第j种泳姿

  • t i j t_{ij} tij:队员 i 参加第 j 种泳姿的耗时

    模型建立:
    m i n ∑ j = 1 4 ∑ i = 1 5 t i j x i j s . I . { ∑ j = 1 4 x i j ≤ 1 , i = 1 , 2 , 3 , 4 , 5 (每个人只能入选4种泳姿之一) ∑ i = 1 5 x i j = 1 , 2 , 3 , 4 (每种泳姿有且仅有1人参加) x i j ∈ { 0 , 1 } \begin{aligned}min\quad\sum_{j=1}^{4}\sum_{i=1}^{5}t_{ij}x_{ij}\end{aligned}\\[1em]\\s.I.\begin{cases}\sum_{j=1}^{4}x_{ij}\leq1,i=1,2,3,4,5&\text{(每个人只能入选4种泳姿之一)}\\[0em]\\\sum_{i=1}^{5}x_{ij}=1,2,3,4&\text{(每种泳姿有且仅有1人参加)}\\[0em]\\x_{ij}\in\{0,1\}\end{cases} minj=1∑4i=1∑5tijxijs.I.⎩ ⎨ ⎧∑j=14xij≤1,i=1,2,3,4,5∑i=15xij=1,2,3,4xij∈{0,1}(每个人只能入选4种泳姿之一)(每种泳姿有且仅有1人参加)

三、代码实现----Matlab

1.Matlab 的 intlinprog 函数

intlinprog 是 MATLAB 中用于求解混合整数线性规划(MILP)问题的函数。混合整数线性规划问题是指在线性约束条件下,求解线性目标函数的最优解,其中部分或全部决策变量被限制为整数。

线性整数规划
intlinprog 函数的基本语法如下:

matlab 复制代码
[x, fval] = intlinprog(f, intcon, A, b, Aeq, beq, lb, ub, options)

各参数的含义如下:

  • f:目标函数的系数向量。
  • intcon:一个向量,指定哪些决策变量是整数变量。例如,如果 intcon = [1, 3],则表示第一个和第三个决策变量是整数变量。
  • A:不等式约束矩阵。
  • b:不等式约束向量。
  • Aeq:等式约束矩阵。
  • beq:等式约束向量。
  • lb:决策变量的下界。
  • ub:决策变量的上界。
  • options:一个结构体,包含求解器的选项。

返回值的含义如下:

  • x:最优解。
  • fval:目标函数在最优解处的值。

线性0-1规划

  • 仍然使用intlinprog函数求解,只需要限定 lbub 即可
  • 例如: 三个决策变量: x1,x2,x3, x1 和 x3 是0-1变量,x2 不限制,则 intcon=[1,3],lb=[0;-inf;0],ub =[1;+inf;1]

2.Matlab 代码

背包问题

matlab 复制代码
%% 背包问题

% 线性整数规划
% [x,fval] = intlinprog(f,intcon,A,b,Aeq,beq,lb,ub,x0)
% f :目标函数的系数向量(最小值形式下)
% intcon :intcon中的值指示决策变量x中应取整数值的分量
% A,b :不等式约束条件的变量系数矩阵和常数项矩阵(必须是≤形式)
% Aeq,beq :等式约束条件的系数矩阵和常数项矩阵
% lb,ub :决策变量的最小取值和最大取值
% intcon 的用法:决策变量如果有三个:x1,x2,x3;若x1和x3是整数,则intcon = [1,3]

% 线性0-1规划
% 仍然使用intlinprog函数求解,只需限定lb和ub即可
% 决策变量如果有三个:x1,x2,x3;若x1和x3是0-1变量,x2不限制,则intcon = [1,3],lb = [0;-inf;0],ub = [1;+inf;1]
clc;clear
f = [-540 -200 -180 -350 -60 -150 -280 -450 -320 -120];
A = [6 3 4 5 1 2 3 5 4 2];
b = 30;
intcon = [1:10];
lb = zeros(10,1);
ub = ones(10,1);
[x,fval] = intlinprog(f,intcon,A,b,[],[],lb,ub)
res = -fval

运行结果:


即:运送1、2、4、6、7、8、9、10货物,运送这些货物的总利润最大为 2410 元

指派问题

matlab 复制代码
%% 指派问题

% 线性整数规划
% [x,fval] = intlinprog(f,intcon,A,b,Aeq,beq,lb,ub,x0)
% f :目标函数的系数向量(最小值形式下)
% intcon :intcon中的值指示决策变量x中应取整数值的分量
% A,b :不等式约束条件的变量系数矩阵和常数项矩阵(必须是≤形式)
% Aeq,beq :等式约束条件的系数矩阵和常数项矩阵
% lb,ub :决策变量的最小取值和最大取值
% intcon 的用法:决策变量如果有三个:x1,x2,x3;若x1和x3是整数,则intcon = [1,3]

% 线性0-1规划
% 仍然使用intlinprog函数求解,只需限定lb和ub即可
% 决策变量如果有三个:x1,x2,x3;若x1和x3是0-1变量,x2不限制,则intcon = [1,3],lb = [0;-inf;0],ub = [1;+inf;1]

clc;clear
f = [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];
A = zeros(5,20);
for i = 1:5
    A(i,4*i-3:4*i) = 1;
end
b = ones(5,1);
Aeq = [eye(4), eye(4), eye(4), eye(4), eye(4)];
beq = ones(4,1);
intcon = [1:20];
lb = zeros(20,1);
ub = ones(20,1);
[x,fval] = intlinprog(f,intcon,A,b,Aeq,beq,lb,ub)
reshape(x,4,5)'

运行结果:


即:甲自由泳;乙蝶泳;丙仰泳;丁蛙泳;戊不参加

四、代码实现----python

在Python中,虽然没有直接对应于MATLAB中intlinprog函数的内置函数,但可以使用以下第三方库来解决混合整数线性规划(MILP)问题,这些库提供了类似的功能:

  1. PuLP
  2. ORTools
  3. Gurobi
  4. CVXPY

本文选用 PuLP 库求解

背包问题

python 复制代码
# 背包问题
import pulp
import numpy as np


# 定义问题规模
# 变量数
n_variables = 10
# 限制条件数
n_constraints = 1

# 创建问题实例
prob = pulp.LpProblem("BinaryVectorLP", pulp.LpMaximize)

# 创建0-1变量(向量)
x = [pulp.LpVariable(f'x{i}', cat='Binary') for i in range(n_variables)]

# 定义目标函数向量
c = np.array([540, 200, 180, 350, 60, 150, 280, 450, 320, 120])  # 目标函数系数

# 定义约束矩阵和向量
A = np.array([6, 3, 4, 5, 1, 2, 3, 5, 4, 2])  # 约束矩阵
b = np.array([30])     # 约束向量

# 设置目标函数
prob += pulp.lpSum([c[i] * x[i] for i in range(n_variables)]), "Objective"

# 添加约束条件
prob += (pulp.lpSum([A[j] * x[j] for j in range(n_variables)]) <= b[0]), f"Constraint_{0+1}"

# 求解
prob.solve()

# 输出结果
print("Status:", pulp.LpStatus[prob.status])
for i in range(n_variables):
    print(f"x{i} =", pulp.value(x[i]))
print("Objective =", pulp.value(prob.objective))

运行结果:

指派问题

python 复制代码
# 指派问题

import pulp
import numpy as np


# 定义问题规模
# 变量数
n_variables = 20
# 限制条件数
n_constraints_1 = 5
n_constraints_2 = 4

# 创建问题实例
prob = pulp.LpProblem("BinaryVectorLP", pulp.LpMinimize)

# 创建0-1变量(向量)
x = [pulp.LpVariable(f'x{i}', cat='Binary') for i in range(n_variables)]

# 定义目标函数向量
c = np.array([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])

# 定义约束矩阵和向量
A_1 = np.zeros((5,20))
for i in range(1,6):
    A_1[i-1,4*i-4:4*i] = 1 # 约束矩阵
b_1 = np.ones((5,))     # 约束向量

# 定义约束矩阵和向量
A_2 = np.hstack([np.eye(4), np.eye(4), np.eye(4), np.eye(4), np.eye(4)])# 约束矩阵
b_2 = np.ones((4,))     # 约束向量


# 设置目标函数
prob += pulp.lpSum([c[i] * x[i] for i in range(n_variables)]), "Objective"

# 添加约束条件
for i in range(n_constraints_1):
    prob += (pulp.lpSum([A_1[i, j] * x[j] for j in range(n_variables)]) <= b_1[i]), f"Constraint_{i+1}"

for i in range(n_constraints_2):
    prob += (pulp.lpSum([A_2[i, j] * x[j] for j in range(n_variables)]) == b_2[i]), f"Constraint_{i+6}"

# 求解
prob.solve()

# 输出结果
res = np.zeros((20,1))
print("Status:", pulp.LpStatus[prob.status])
for i in range(n_variables):
    res[i] = pulp.value(x[i])
    print(f"x{i} =", pulp.value(x[i]))
print("Objective =", pulp.value(prob.objective))
res = res.reshape((5,4))
print(res)

运行结果:

总结

本文介绍了整数规划和0-1规划,并通过背包问题和指派问题两个典型示例建立模型,分别使用Matlab和python进行代码编写。

相关推荐
胡西风_foxww5 分钟前
【ES6复习笔记】let 和 const 命令(1)
笔记·学习·es6·const·let
胡西风_foxww6 分钟前
【ES6复习笔记】Spread 扩展运算符(8)
前端·笔记·es6·扩展·运算符·spread
网络安全(king)18 分钟前
网络安全之接入控制
网络·学习·安全·web安全
小王子102419 分钟前
数据结构与算法Python版 二叉查找树
数据结构·python·算法·二叉查找树
编程阿布28 分钟前
Python基础——多线程编程
java·数据库·python
又蓝30 分钟前
使用 Python 操作 MySQL 数据库的实用工具类:MySQLHandler
数据库·python·mysql
dundunmm32 分钟前
机器学习之pandas
人工智能·python·机器学习·数据挖掘·pandas
好学近乎知o32 分钟前
常用的Django模板语言
python·django·sqlite
小火炉Q42 分钟前
16 循环语句——for循环
人工智能·python·网络安全
segwyang1 小时前
Maven 项目模板
java·python·maven