展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > PuLP中用Big M法处理最小最大变量

PuLP中用Big M法处理最小最大变量

本文深入探讨了在PuLP中构建线性规划模型时,如何准确地设置和使用辅助变量来捕捉一组值中的最小值和最大值,特别是针对带有二元选择变量的场景。核心内容在于详细解释并应用“BigM”方法来正确处理最小值约束,克服了直接设置约束时可能遇到的问题,并结合一个实际的货物分配案例,提供了完整的PuLP代码实现及注意事项,旨在帮助读者掌握在复杂约束下建模最小值和最大值的技巧。

在PuLP中利用Big M方法处理线性规划中的最小/最大辅助变量

本文深入探讨了在PuLP中构建线性规划模型时,如何准确地设置和使用辅助变量来捕捉一组值中的最小值和最大值,特别是针对带有二元选择变量的场景。核心内容在于详细解释并应用“Big M”方法来正确处理最小值约束,克服了直接设置约束时可能遇到的问题,并结合一个实际的货物分配案例,提供了完整的PuLP代码实现及注意事项,旨在帮助读者掌握在复杂约束下建模最小值和最大值的技巧。

线性规划中最小/最大辅助变量的建模挑战

在构建线性规划(LP)模型时,我们经常需要引入辅助变量来表示一组值中的最小值或最大值,并以此为基础添加进一步的约束。例如,在资源分配、生产计划或物流优化等问题中,可能需要确保分配给特定实体的某个属性(如重量、成本)的最大值与最小值之间的差异不超过某个阈值。

直接为最大值设置辅助变量相对直观: 对于一个辅助变量 max_val 和一组可能被选中的值 val[j],以及对应的二元选择变量 x[j] (当 j 被选中时为1,否则为0),我们可以简单地设置: max_val >= val[j] * x[j] 对所有 j 成立。 当 x[j] 为1时,max_val 必须大于等于 val[j];当 x[j] 为0时,max_val 必须大于等于0(通常 val[j] 为非负,此约束自动满足)。通过优化目标(例如最小化 max_val 或通过其他方式间接影响),求解器会找到这组选中值中的最大值。

然而,为最小值设置辅助变量则更为复杂。如果采用类似的直接方法: min_val <= val[j] * x[j] 对所有 j 成立。 当 x[j] 为1时,min_val 必须小于等于 val[j],这是我们期望的。但当 x[j] 为0时,约束变为 min_val <= 0。如果所有未选中的项都导致 min_val <= 0,那么求解器很可能将 min_val 设置为0,因为这满足所有条件,但却无法正确反映被选中项中的实际最小值。为了解决这个问题,我们需要引入“Big M”方法。

Big M 方法:处理条件最小值的关键

“Big M”方法是混合整数规划(MIP)中一个常用的技巧,用于处理当某个二元变量为0时,使某些约束变得无效或“松弛”的情况。在设置最小值辅助变量时,它的作用是确保只有当对应的项被选中时,该项的值才会被考虑进最小值的计算。

对于最小值辅助变量 min_val,其正确的Big M约束形式如下: min_val <= val[j] * x[j] + (1 - x[j]) * M

这里的 M 是一个足够大的正数,它必须大于或等于所有可能的 val[j] 的最大值。让我们通过一个“真值表”来理解这个约束:

  • 情况一:当 x[j] = 1 时 (项 j 被选中) 约束变为:min_val <= val[j] * 1 + (1 - 1) * M 简化为:min_val <= val[j] 这正是我们期望的行为:当项 j 被选中时,其值 val[j] 必须是 min_val 的一个上限。

  • 情况二:当 x[j] = 0 时 (项 j 未被选中) 约束变为:min_val <= val[j] * 0 + (1 - 0) * M 简化为:min_val <= M 由于 M 被选择为足够大的数(大于所有可能的 val[j]),这个约束 min_val <= M 几乎总是满足的,因此它有效地“禁用了” val[j] 对 min_val 的影响,使其不参与最小值的计算。

通过这种方式,min_val 最终会被迫取到所有被选中项 val[j] 中的最小值,因为如果它取了一个更大的值,就会违反至少一个 min_val <= val[j] (当 x[j]=1) 的约束;如果它取了一个更小的值,则优化目标(如果存在对 min_val 的间接影响)或模型结构会倾向于使其尽可能大,直到被某个 val[j] 限制。

选择 Big M 值的重要性:M 的选择至关重要。它必须足够大,以确保在 x[j]=0 时约束被正确松弛,但又不能过大,因为过大的 M 值可能导致数值稳定性问题,增加求解器的计算难度。通常,M 可以设置为数据集中相关数值属性(例如本例中的货物重量)的最大可能值。

案例分析:带有重量差异约束的货物分配问题

现在,我们将通过一个具体的货物分配问题来演示如何在PuLP中应用Big M方法。

问题描述: 假设有3辆卡车,每辆卡车只能装载一件货物。每件货物都有价格和重量两个属性。目标是最大化所有卡车分配到的货物总价格,同时满足一个关键约束:所有卡车所载货物的最大重量与最小重量之差不能超过50公斤。

PuLP模型实现

import pulp

# 示例数据
cargo = {
   "truck1":{
      "c1":{
         "price":100,
         "weight":20
      },
      "c2":{
         "price":150,
         "weight":10
      },
      "c3":{
         "price":90,
         "weight":30
      },
      "c4":{
         "price":500,
         "weight":80
      }
   },
   "truck2":{
      "c5":{
         "price":50,
         "weight":10
      },
      "c6":{
         "price":100,
         "weight":80
      },
      "c7":{
         "price":200,
         "weight":150
      },
      "c8":{
         "price":50,
         "weight":30
      }
   },
   "truck3":{
      "c9":{
         "price":100,
         "weight":50
      },
      "c10":{
         "price":200,
         "weight":200
      }
   }
}

# 设置 Big M 值
# M 必须大于所有货物的最大重量。这里最大重量是200,所以300是合适的选择。
M = 300

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

# 2. 定义决策变量
# truck_allocation_vars[truck_idx][cargo_idx] 为二元变量,
# 如果卡车 truck_idx 装载货物 cargo_idx,则为1,否则为0。
truck_allocation_vars = {
    truck: pulp.LpVariable.dicts("cargo_allocation", cargo[truck], 0, 1, pulp.LpBinary)
    for truck in cargo
}

# 辅助变量:用于捕捉分配货物中的最大重量和最小重量
max_weight = pulp.LpVariable("max_allocated_weight", cat=pulp.LpContinuous)
min_weight = pulp.LpVariable("min_allocated_weight", cat=pulp.LpContinuous)

# 3. 添加约束

# 约束1: 每辆卡车只能选择一件货物
for truck_idx in truck_allocation_vars:
    prob += pulp.lpSum(list(truck_allocation_vars[truck_idx].values())) == 1, f"One_Cargo_Per_Truck_{truck_idx}"

# 约束2: 定义 max_weight
# max_weight 必须大于等于所有被选中货物的重量
for truck_idx in truck_allocation_vars:
    for cargo_idx in cargo[truck_idx].keys():
        prob += max_weight >= cargo[truck_idx][cargo_idx]['weight'] * truck_allocation_vars[truck_idx][cargo_idx], \
                f"Max_Weight_Constraint_{truck_idx}_{cargo_idx}"

# 约束3: 定义 min_weight (使用 Big M 方法)
# min_weight 必须小于等于所有被选中货物的重量
for truck_idx in truck_allocation_vars:
    for cargo_idx in cargo[truck_idx].keys():
        prob += min_weight <= cargo[truck_idx][cargo_idx]['weight'] * truck_allocation_vars[truck_idx][cargo_idx] \
                               + (1 - truck_allocation_vars[truck_idx][cargo_idx]) * M, \
                f"Min_Weight_Constraint_{truck_idx}_{cargo_idx}"

# 约束4: 最大重量与最小重量之差不能超过50公斤
prob += (max_weight - min_weight) <= 50, "Weight_Difference_Constraint"

# 4. 定义目标函数
# 目标是最大化所有卡车分配到的货物总价格
prob += pulp.lpSum([cargo[truck_idx][cargo_idx]['price'] * truck_allocation_vars[truck_idx][cargo_idx]
                     for truck_idx in truck_allocation_vars
                     for cargo_idx in truck_allocation_vars[truck_idx]]), "Total_Price"

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

# 6. 打印解决方案
print(f"求解状态: {pulp.LpStatus[prob.status]}\n")
print(f"最大总价格: {pulp.value(prob.objective)}\n")

print("卡车分配详情:")
allocated_weights = []
for truck_idx in cargo:
   for cargo_idx in cargo[truck_idx]:
      if truck_allocation_vars[truck_idx][cargo_idx].varValue > 0.1:  # 浮点数比较,使用阈值
         weight = cargo[truck_idx][cargo_idx]['weight']
         price = cargo[truck_idx][cargo_idx]['price']
         print(f'  卡车 {truck_idx} 装载货物 {cargo_idx} (价格: {price}, 重量: {weight}kg)')
         allocated_weights.append(weight)

print(f'\n分配货物中的最大重量: {max_weight.varValue} kg')
print(f'分配货物中的最小重量: {min_weight.varValue} kg')
print(f'重量差异: {max_weight.varValue - min_weight.varValue} kg (要求 <= 50 kg)')

运行结果示例

求解状态: Optimal

最大总价格: 700.0

卡车分配详情:
  卡车 truck1 装载货物 c4 (价格: 500, 重量: 80kg)
  卡车 truck2 装载货物 c6 (价格: 100, 重量: 80kg)
  卡车 truck3 装载货物 c9 (价格: 100, 重量: 50kg)

分配货物中的最大重量: 80.0 kg
分配货物中的最小重量: 50.0 kg
重量差异: 30.0 kg (要求 <= 50 kg)

从输出结果可以看出,模型成功地找到了一个最优解,使得总价格最大化,并且分配的货物重量差异(80kg - 50kg = 30kg)满足了不超过50kg的约束。min_weight 辅助变量也正确地被设置为50kg,而不是0。

注意事项与总结

  1. Big M 值选择:如前所述,M 的值必须足够大以覆盖所有可能的实际值,但也不宜过大,以避免潜在的数值精度问题。在实际应用中,可以通过分析数据范围来确定一个合适的 M 值。
  2. 约束命名:在PuLP中为每个约束添加描述性名称是一个好习惯,这有助于在调试和分析模型时更好地理解约束的来源和作用。
  3. 浮点数比较:在检查二元变量的值时,由于浮点数计算的特性,通常不直接使用 == 1,而是使用一个小的阈值(如 > 0.1 或 > 0.5)来判断变量是否被选中。
  4. 模型复杂性:引入 Big M 约束会增加模型的复杂性,尤其是在存在大量二元变量时。对于非常大的问题,可能需要考虑更高级的建模技术或专门的求解器。

通过掌握Big M方法,我们能够有效地在PuLP等线性规划工具中处理复杂的条件逻辑,特别是涉及最小值计算的场景,从而构建出更准确、更强大的优化模型。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发
相关文章 更多
精品专题 更多
本月促销

正软商城本月促销专区,汇集办公、设计、安全、影音、系统工具及AI软件等正版软件优惠活动,提供限时折扣、特价授权和优惠购买信息,活动库存及价格以页面实时展示为准。

装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。