本文主要是介绍python调用SCIP求解下料问题(Cutting Stock Problem),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1. 问题示例
- 2. 数学模型
- 3. python调用开源求解器SCIP代码
- 4. Todo
- 参考文献
1. 问题示例
下料问题(Cutting Stock Problem,CSP)也叫板材切割问题。例如,有一批长度为110cm的板材(且称之为母料),需要切割成不同尺寸的小板材,例如下图所示,20cm的需要48个,45cm的需要35个, …,请问怎样切割,才能最省母料。
2. 数学模型
- 数学模型直接参考《Column Generation》第五章中的Kantorovich Model
3. python调用开源求解器SCIP代码
- python代码
import os
import pandas as pd
import numpy as np
import pyscipopt as opt# ========== 测试算例 ==========
W = 100 # 原料板材的长度
w = [3, 6 ,7, 11] # 制造产品i需要的长度
b = [250, 200, 180, 100] # 产品i的总需求量
I = len(w) # 产品种类的数量
K = 100 # 假设原料板材的个数 (其实这个值可以提前预处理计算)model = opt.Model('MCP')
# ========== 定义变量 ==========
x0 = {}
x = {}
# x0_k: 0-1变量,原料板材k是否被使用
for k in range(K):x0[k] = model.addVar(vtype='B', name='roll_' + str(k))# x_i_k: 在原料板材k中,切割产品i的数量
for i in range(I):for k in range(K):x[i, k] = model.addVar(vtype='C', name='num_' + str(i) + '_' + str(k))# ========== 定义约束 ==========
# 约束1: 所有切割得到产品i,满足需求
for i in range(I):model.addCons(opt.quicksum(x[i, k] for k in range(K)) >= b[i], name='demand_' + str(i))# 约束2: 如果原材料k被使用,则其切割的产品的总长度不能超过板材长度W
for k in range(K):model.addCons(opt.quicksum(x[i, k] * w[i] for i in range(I)) <= x0[k] * W, name='width_' + str(k))# 约束3: 原材料K是一样的,没有类似序列的属性, 可能多个解对应一样的切割方案,让选中的原料板材都在前面序列
for k in range(K-1):model.addCons(x0[k] >= x0[k+1])# ==========定义目标==========
# 目标: 原料板材使用数量最小
model.setObjective(opt.quicksum(x0[k] for k in range(K)))
model.setMinimize()
model.optimize()# ========== 输出结果 ==========
print('model_status = ', model.getGap())
print('model_gap =', model.getStatus())
print('model_obj =', model.getObjVal())roll_lst = []
for k in range(K):if model.getVal(x0[k]) > 0:roll_lst.append(k)
print(roll_lst)
- 结果
4. Todo
- 当算例达到一定规模时,使用求解器求解效率可能会变慢很多,可以使用列生成算法 (Column Generation) 进行求解
参考文献
《Column Generation》Guy Desaulniers (Editor), Jacques Desrosiers (Editor), Marius M. Solomon (Editor), chapter 5
这篇关于python调用SCIP求解下料问题(Cutting Stock Problem)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!