使用gurobi求解CTP(Cutting Stock Problem)问题

1.问题背景:

一家企业拥有一批原料棒材,他要将这些棒材进行切割加工成为规定尺寸的产品,然后卖给顾客。这家企业需要设计最优的棒材切割方案,以最小的原材料消耗,生产出规定尺寸的产品,以满足顾客的需求。

2.数学模型:

3.程序:

# -*- coding : utf-8 -*-
# @Time      : 2022/5/2 19:11
# @Author    : wkb
from gurobipy import *
import time
import random
# parameter
Demand_dic = {}   # ID:(long,number)
L = 20
I = 2
K = 20
# for i in range(I):
#     long = random.randint(1,10)
#     number = random.randint(1,10)
#     Demand_dic[i]  = (long,number)
Demand_dic = {0:(6,20),1:(9,15)}
print(Demand_dic)

# declare variable
model = Model("CSP")
x={}
y={}
for i in range(I):
    for k in range(K):
        x[i,k] = model.addVar(0,GRB.INFINITY,vtype=GRB.INTEGER,name="x[{0},{1}]".format(i,k))
for k in range(K):
    y[k] = model.addVar(0, 1, vtype=GRB.BINARY, name="y[{0}]".format(k))

# add constraint_1
for i in range(I):
    expr = LinExpr(0)
    for k in range(K):
        expr.addTerms(1,x[i,k])
    model.addConstr(expr >= Demand_dic[i][1],name="c_1_{0}".format(i+1))
# add constraint_2
for k in range(K):
    expr = LinExpr(0)
    for i in range(I):
        expr.addTerms(Demand_dic[i][0],x[i,k])
    model.addConstr(expr <= L*y[k],name="c_2_{0}".format(k+1))
# set objective
expr = LinExpr(0)
for k in range(K):
    expr.addTerms(1,y[k])
model.setObjective(expr,sense=GRB.MINIMIZE)

#optimal
start_time = time.time()
model.optimize()
end_time = time.time()
cpu_time = end_time - start_time
print("CPU_run time = {0} sec".format(cpu_time))

if model.status == GRB.OPTIMAL:
    soltion_x = {}
    for key in x.keys():
        soltion_x[key] = x[key].x
    solution_y = {}
    for key in y.keys():
        solution_y[key] = y[key].x
    obj = model.getObjective()
    print("obj = ",obj.getValue())
    for i in range(I):
        for k in range(K):
            if soltion_x[i,k] != 0:
                print("x[{0},{1}] = {2}".format(i,k,soltion_x[i,k]))
    for k in range(K):
        if solution_y[k] == 1:
            print("y[{0}]={1}".format(k, solution_y[k]))


    model.write("csp.lp")



4.求解:
Using license file C:\Users\WKB\gurobi.lic
Gurobi Optimizer version 9.1.2 build v9.1.2rc0 (win64)
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads
Optimize a model with 22 rows, 60 columns and 100 nonzeros
Model fingerprint: 0x9c470235
Variable types: 0 continuous, 60 integer (20 binary)
Coefficient statistics:
  Matrix range     [1e+00, 2e+01]
  Objective range  [1e+00, 1e+00]
  Bounds range     [1e+00, 1e+00]
  RHS range        [2e+01, 2e+01]
Presolve time: 0.00s
Presolved: 22 rows, 60 columns, 100 nonzeros
Variable types: 0 continuous, 60 integer (20 binary)
Found heuristic solution: objective 15.0000000

Root relaxation: cutoff, 40 iterations, 0.00 seconds

    Nodes    |    Current Node    |     Objective Bounds      |     Work
 Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time

     0     0     cutoff    0        15.00000   15.00000  0.00%     -    0s

Explored 0 nodes (40 simplex iterations) in 0.00 seconds
Thread count was 8 (of 8 available processors)

Solution count 1: 15 

Optimal solution found (tolerance 1.00e-04)
Best objective 1.500000000000e+01, best bound 1.500000000000e+01, gap 0.0000%
obj =  15.0
5.分析:

对于需求比较少的CTP问题gurobi能快速的进行求解,但是问题规模一旦很大之后,gurobi就很难进行求解了,这个时候就需要新的求解方式和建模方式来解决:CG(Column generation)

6.变量输出:

此时我们看到的只是最佳的目标函数值和CPU的求解时间,我们还需要知道具体的切割方案:也就是我们需要输出x[i,k] 和 y[k].

x[0,5] = 3.0
x[0,6] = 3.0
x[0,7] = 3.0
x[0,8] = 3.0
x[0,9] = 3.0
x[0,10] = 3.0
x[0,11] = 3.0
x[1,12] = 1.0
x[1,13] = 2.0
x[1,14] = 2.0
x[1,15] = 2.0
x[1,16] = 2.0
x[1,17] = 2.0
x[1,18] = 2.0
x[1,19] = 2.0
y[5]=1.0
y[6]=1.0
y[7]=1.0
y[8]=1.0
y[9]=1.0
y[10]=1.0
y[11]=1.0
y[12]=1.0
y[13]=1.0
y[14]=1.0
y[15]=1.0
y[16]=1.0
y[17]=1.0
y[18]=1.0
y[19]=1.0

其中x[0,5]=3表示0号需求在5号钢卷中切了3段出来。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最短路径问题是指从一个起点到一个终点,经过若干个中间节点,使得路径上的边权之和最小。本文将介绍如何使用YALMIP和gurobi求解最短路径问题。 首先,需要安装YALMIP和gurobi,并将它们与MATLAB集成。然后,定义问题的变量和约束条件。假设有n个节点和m条边,其中边e的起点为i(e),终点为j(e),权重为w(e)。定义变量x(e)表示边e是否在路径中出现,即x(e)=1表示边e在路径中,x(e)=0表示边e不在路径中。则问题可以表示为: minimize ∑e∈E w(e)·x(e) subject to x(e)∈{0,1} for all e∈E ∑e∈δ+(i) x(e) - ∑e∈δ-(i) x(e) = {1 if i=s, -1 if i=t, 0 otherwise} for all i∈V-{s,t} 其中,E表示边集,V表示节点集,s表示起点,t表示终点,δ+(i)表示以节点i为起点的边集,δ-(i)表示以节点i为终点的边集。 然后,需要使用YALMIP来定义问题,并使用gurobi求解。代码如下: ```matlab % 定义变量和参数 n = 5; % 节点数 m = 7; % 边数 s = 1; % 起点 t = 5; % 终点 i = [1 1 2 2 3 4 4]; % 边的起点 j = [2 3 3 4 5 5 3]; % 边的终点 w = [2 1 3 2 1 3 1]; % 边的权重 x = binvar(m,1); % 定义变量x(e) obj = w*x; % 定义目标函数 constr = []; for k = 1:n if k == s % 起点 constr = [constr, sum(x(find(i==k))) - sum(x(find(j==k))) == 1]; elseif k == t % 终点 constr = [constr, sum(x(find(i==k))) - sum(x(find(j==k))) == -1]; else % 中间节点 constr = [constr, sum(x(find(i==k))) - sum(x(find(j==k))) == 0]; end end % 定义问题 ops = sdpsettings('solver','gurobi'); optimize(constr,obj,ops); % 输出结果 value(obj) value(x) ``` 运行上述代码,可以得到最优解为4,路径为1->2->4->5。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值