为R语言MIP钢铁切割优化模型添加单库存源约束
钢铁切割优化MIP模型:修正约束并确认工件单库存下料逻辑
你需要实现的“每个工件仅从单个库存件下料”的要求,其实已经通过现有约束1的逻辑覆盖,但当前模型存在约束2的写法错误,导致无法正确限制库存件的总下料长度。以下是修正后的完整代码及说明:
核心逻辑说明
你的二进制变量steel_cut[work, inventory]表示工件work是否从库存件inventory下料,约束1sum_over(steel_cut[work, inventory], inventory = 1:invent_count) == 1直接保证了每个工件只能被分配到一个库存件(所有库存件对应的变量和为1,即只有一个库存件的变量为1),完全满足“单个工件仅从单个库存下料”的需求。
修正后的完整代码
# 加载所需包 library(dplyr) library(ompr) library(ompr.roi) library(ROI) # 定义问题数据 work_tbl <- data.frame(length = c(2500, 500, 700, 1200, 1500, 2000, 2500, 3000, 4000, 5250)) inventory_tbl <- data.frame(length = c(1300, 2000, 1800, 2600, 3000, 2000, 5000, 6000, 7000, 9000, 2000, 500, 4000, 12000, 7400, 13000)) # 定义变量参数 work_count <- nrow(work_tbl) invent_count <- nrow(inventory_tbl) # 优化big_M取值:单个库存最多能放的工件数上限,避免M值过大影响求解效率 big_M <- ceiling(max(inventory_tbl$length) / min(work_tbl$length)) # 初始化MIP模型 steel_model <- ompr::MIPModel() %>% # 二进制变量:工件work是否从库存inventory下料 add_variable(steel_cut[work, inventory], work = 1:work_count, inventory = 1:invent_count, type = "binary") %>% # 二进制变量:是否启用该库存件 add_variable(take_item[inventory], inventory = 1:invent_count, type = "binary") %>% # 约束1:每个工件必须被下料一次(仅对应一个库存件) add_constraint(sum_over(steel_cut[work, inventory], inventory = 1:invent_count) == 1, work = 1:work_count) %>% # 约束2:每个库存件的总下料长度不能超过自身长度(修正原索引错误) add_constraint(sum_over(steel_cut[work, inventory] * work_tbl$length[work], work = 1:work_count) <= inventory_tbl$length[inventory], inventory = 1:invent_count) %>% # 约束3:只要有工件从该库存下料,take_item就必须为1 add_constraint(sum_over(steel_cut[work, inventory], work = 1:work_count) <= big_M * take_item[inventory], inventory = 1:invent_count) %>% # 目标函数:最小化废料 = 启用的库存总长度 - 下料的工件总长度 set_objective( sum_over(take_item[inventory] * inventory_tbl$length[inventory], inventory = 1:invent_count) - sum_over(steel_cut[work, inventory] * work_tbl$length[work], work = 1:work_count, inventory = 1:invent_count), sense = "min" ) # 查看模型结构 steel_model # 求解模型 solution <- ompr::solve_model(steel_model, with_ROI(solver = "glpk", verbose = TRUE)) # 查看目标值(废料长度) solution$objective_value # 提取求解结果 steel_model_soln <- ompr::get_solution(solution, steel_cut[work, inventory]) %>% filter(value > 0) %>% mutate( 工件长度 = work_tbl$length[work], 库存件长度 = inventory_tbl$length[inventory] ) # 查看结果 steel_model_soln
关键修正点
- 修复约束2的索引错误:原代码同时指定
inventory和work索引,生成了大量冗余约束;修正后仅针对每个库存件生成一个总长度约束,符合实际逻辑。 - 优化big_M取值:改用最大库存长度除以最小工件长度的向上取整值,避免过大的M值降低求解效率。
- 增强结果可读性:在输出结果中添加工件和库存件的实际长度,方便直观查看下料分配情况。
内容的提问来源于stack exchange,提问作者RegressionSquirrel
相关产品推荐
相关产品推荐

