整数线性规划模型

整数规划就是将一些决策变量设为整数,再求最优解。以整数变量的个数(全部是、部分是)可以分为纯整数规划和混合整数规划。一般用于求解任务分配工厂生产等问题。接下来,我会以三个算法求解一般的整数线性规划。

1.基本框架

整数线性规划模型相较于线性规划模型只是多出了整数的决策变量限制,所以实现起来只需要在线性规划的代码上增加一些限制就可以实现了。

from pulp import LpMaximize, LpProblem, LpVariable, lpSum

# 1. 创建问题实例(最大化问题)
problem = LpProblem("Maximize_Profit", LpMaximize)

# 2. 创建决策变量,并设置为非负整数
x1 = LpVariable("P1", lowBound=0, cat='Integer')  # P1的生产数量
x2 = LpVariable("P2", lowBound=0, cat='Integer')  # P2的生产数量

# 3. 定义目标函数(最大化利润)
problem += 40 * x1 + 30 * x2, "Total Profit"

# 4. 添加约束条件
problem += 2 * x1 + x2 <= 100, "Labor Constraint"
problem += x1 + 2 * x2 <= 80, "Material Constraint"

# 5. 求解问题
problem.solve()

# 6. 输出结果
print(f"生产 P1 的数量: {x1.varValue}")
print(f"生产 P2 的数量: {x2.varValue}")
print(f"最大利润: {problem.objective.value()} 美元")

可以发现,只要在创建决策变量时将cat(category种类)设为整数型就可以定义整数决策变量了。

2.底层算法

2.1 分支定界

分支定界的本质其实是一种穷举。因为整数线性规划是基于线性规划的,我们可以在求得线性规划最优解后对决策变量增添限制(如将变量范围向上向下取整)。在限制条件所构成的界限内,一个个的枚举所有整数解,算得最终的最优解。

图1

             

例如,将所给范围转换为图解中两条直线与x轴的所连区域,分支定界法就是将所有的白点罗列出来再一个个计算,再取最优。

我们知道画图解决,可是怎么让程序明白呢?求得线性规划的最优解后,如果解的决策变量都是整数,那么就可以直接取;如果不是,就添加限制,如 x1 = 3.125,就添加 x1 < 3或 x1 > 4的限制再求最优解,如果决策变量为整数就可以取了。

图2

2.2 割平面法

顾名思义,就是把不需要的区域平面全部割掉。

如果线性规划的最优解是 x1 = 3.125,x2 = 2.345,就可以把 x1的(3,3.125】和 x2的        (2,2.345】区域割掉再求解(这些区域不含整数解),再求再割,依次类推。

2.3 匈牙利法

匈牙利法其实就是将一个方阵(如果任务与人数不一致要添加0作用的变量补齐)进行某种变换成初等矩阵过程(即最终矩阵元素所在行所在列只有一个1其余全是0)。在任务分配问题中,将任务与执行者分为二分图,得出系数矩阵(如某人画多少时间完成哪个任务的表)。基于KM 定理:若二分图中所有边的权值加上或减去同一个常数,最优匹配的边集不变。类似于数据的离散化处理,进行行规约(所有行减去所在行的最小元素)列规约(所有列减去所在列的最小元素),这样可以得到尽可能多的0。再用最少的竖直或水平的线串起所有的0,若是线数等于秩就求得了解(哪里不为0就派谁完成那个任务),不等于就将整个矩阵减去最小元素值继续串线判断,依次重复。

由此可见解决的是0-1问题:

from pulp import LpMaximize, LpProblem, LpVariable, lpSum

# 1. 创建问题实例(最大化问题)
problem = LpProblem("Investment_Problem", LpMaximize)

# 2. 创建0-1决策变量,表示是否选择某个项目
x1 = LpVariable("P1", cat='Binary')  # 项目P1
x2 = LpVariable("P2", cat='Binary')  # 项目P2
x3 = LpVariable("P3", cat='Binary')  # 项目P3
x4 = LpVariable("P4", cat='Binary')  # 项目P4
x5 = LpVariable("P5", cat='Binary')  # 项目P5

# 3. 定义目标函数(最大化总收益)
problem += 15 * x1 + 25 * x2 + 35 * x3 + 45 * x4 + 55 * x5, "Total Profit"

# 4. 添加预算约束
problem += 10 * x1 + 20 * x2 + 30 * x3 + 40 * x4 + 50 * x5 <= 100, "Budget Constraint"

# 5. 求解问题
problem.solve()

# 6. 输出结果
print(f"是否投资项目P1: {x1.varValue}")
print(f"是否投资项目P2: {x2.varValue}")
print(f"是否投资项目P3: {x3.varValue}")
print(f"是否投资项目P4: {x4.varValue}")
print(f"是否投资项目P5: {x5.varValue}")
print(f"最大总收益: {problem.objective.value()} 万美元")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值