讲师中心 微信公众号
AI工具推荐 视频效率加速

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

夜婷大大_3456

夜婷大大_3456

发布时间:2025-11-14 12:21:30

|

956人浏览过

|

来源于php中文网

原创

在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

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

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

对于最小值辅助变量 min_val,其正确的Big M约束形式如下: min_val

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

  • 情况一:当 x[j] = 1 时 (项 j 被选中) 约束变为:min_val

  • 情况二:当 x[j] = 0 时 (项 j 未被选中) 约束变为:min_val

通过这种方式,min_val 最终会被迫取到所有被选中项 val[j] 中的最小值,因为如果它取了一个更大的值,就会违反至少一个 min_val

AI舌诊面诊问诊医疗系统+诊疗商城系统源码
AI舌诊面诊问诊医疗系统+诊疗商城系统源码

AI 舌诊面诊问诊医疗系统 + 诊疗商城系统源码是一套结合 AI 辅助诊断与商品转化的健康类程序,基于浩创云、ThinkPHP(PHP)开发,支持微信服务号与 H5 端,适合做中医舌诊面诊问答、健康建议推送以及配套诊疗商品的运营。

下载

选择 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工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

相关专题

更多
Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

20

2026.10.28

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

0

2026.10.28

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

0

2026.10.28

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

120

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

60

2026.10.22

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

60

2026.10.22

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

40

2026.10.22

PHP时间戳漏洞修复教程
PHP时间戳漏洞修复教程

本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。

60

2026.10.22

Golangci-lint配置文件与规则设置
Golangci-lint配置文件与规则设置

本专题聚焦Golangci-lint YAML配置文件,讲清运行参数、规则启停、目录排除、问题过滤及严重级别设置,便于团队统一检查标准。

20

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn