1. 仅建模搬运问题
我们不妨假设仓库有3种物料需要搬运到生产线,搬运时间都是3min。
三种物料假设都需要搬运3件,有2个叉车可以进行搬运,每个叉车每次智能搬运一件。
问题建模入下:
using JuMP,HiGHS,GLPK
MAXNUM = 10000
model = Model(HiGHS.Optimizer)
set_silent(model)
# 3种物料,2个agv,一共需要搬运9次,共10个阶段
M = 3
A = 2
moveTime = [1,2,3]
moveNum = [3,3,3]
T = sum(moveNum)
# 状态变量:叉车的剩余工作时间worktime,以及阶段时间stageTime
@variable(model, 0 <= worktime[1:T+1,1:A]);for j in 1:A;fix(worktime[1,j], 0; force=true);end
@variable(model, 0 <= stageTime[1:T+1])
# 决策变量及约束:每次搬运1件;总共搬运3件;叉车有空(worktime==0)时才能pick新的物料
@variable(model, pick[1:T,1:M,1:A]>=0,Bin)
@constraint(model, [t in 1:T],sum(pick[t,:,:])==1)
@constraint(model,[i in 1:M],sum(pick[:,i,:])==moveNum[i])
@constraint(model,[t in 1:T,j in 1:A],worktime[t,j]/MAXNUM<=1-sum(pick[t,:,j]))
# 状态转移函数,以及边界条件
@constraint(model,[t in 1:T,j in 1:A],worktime[t,j]-stageTime[t]+sum([pick[t,i,j]*moveTime[i] for i in 1:M])==worktime[t+1,j])
@constraint(model,[j in 1:A],stageTime[T+1]>=worktime[T+1,j])
# 最小化总时间
@objective(model, Min, sum(stageTime))
optimize!(model)
print("最少需要时间:",Int(round(objective_value(model))))
# 下面时打印结果
function idx(pick,t,j)
if t>T;return " ";end
id = findfirst(x->x==1,value.(pick[t, :, j]))
if id == nothing;return " ";else;return id;end
end
for t in 1:T
println(t,": ",idx(pick,t,1)," ",idx(pick,t,2),", ",value.(worktime)[t,:],
", ",value.(worktime)[t,:]+[sum([value.(pick)[t,i,j]*moveTime[i] for i in 1:M]) for j in 1:A],", ",value.(stageTime)[t])
end
t=T+1
println(t,": ",idx(pick,t,1)," ",idx(pick,t,2),", ",value.(worktime)[t,:],", ",value.(worktime)[t,:],", ",value.(stageTime)[t])
2. 使用SDDP进行建模
需要增加一个delivered状态变量,用于跟踪已搬运的物料数量:
同时解除控制变量pick的整数约束,否则无法求解。
using SDDP,HiGHS
moveTime = [1,2,3]
moveNum = [3,3,3]
T = sum(moveNum)
A = 2
M = 3
MAXNUM = 1000
model = SDDP.LinearPolicyGraph(
stages = T+1,
lower_bound = 0.0,
optimizer = HiGHS.Optimizer,
) do sp, t
@variable(sp, 0 <= stagetime)
@variable(sp, 0 <= worktime[1:A], SDDP.State, initial_value = 0)
@variable(sp, 0 <= delivered[1:M]<=maximum(moveNum), SDDP.State, initial_value = 0)
if t<=T
@variable(sp, 1>=pick[1:M,1:A]>=0);@constraint(sp, sum(pick)==1)
@constraint(sp, [j in 1:A],worktime[j].in/MAXNUM<=1-sum(pick[:,j]))
@constraint(sp, [j in 1:A],worktime[j].in - stagetime +sum([pick[i,j]*moveTime[i] for i in 1:M]) == worktime[j].out)
@constraint(sp, [i in 1:M],delivered[i].in+sum(pick[i,:])==delivered[i].out)
else
@variable(sp, pick[1:M,1:A]==0);
for i in 1:M;fix(delivered[i].in, moveNum[i]; force = true);end
@constraint(sp,[j in 1:A],stagetime>=worktime[j].in)
end
@stageobjective(sp, stagetime)
end
SDDP.train(model; iteration_limit = 100)
print(SDDP.calculate_bound(model))
simulations = SDDP.simulate(
model,
1, #= number of replications =#
[:pick]; #= variables to record =#
skip_undefined_variables = true,
);