Hey @odow Here is the full code. The optimality cuts work well (in other instances). But the feasibility cuts seem not to cut the solution and keep appearing (the same cut) in the next iteration.
using JuMP, Gurobi, Printf
# Z* = 435
# instance with Benders subproblem infeasible
p =[58 22 67 32;
15 49 87 52;
49 19 48 71;
45 26 40 74;
95 24 81 73]
global (n, m) = size(p)
# control parameters/inicialization
global MAXIMUM_TIME = 3600 # 3600.0
global ABSOLUTE_OPTIMALITY_GAP = 1e-6
global upper_bound = 10^10
global inicio = time()
global H = Int(sum(p))
global Δ = minimum(p)
global B = Int(round(H/Δ))
global P = Array{Int64}(undef, n, m)
[P[j,k] = floor(p[j,k]/Δ)+1 for j=1:n for k=1:m]
global π = Array{Float64}(undef, n, m)
[π[j,k] = P[j,k] - p[j,k]/Δ for j=1:n for k=1:m]
# MASTER PROBLEM
modelo = Model(Gurobi.Optimizer)
set_optimizer_attribute(modelo, "TimeLimit", 3600) # Gurobi
@variables modelo begin
x[j=1:n,k=1:m,b=1:B,l=0:1], Bin
u[j=1:n,k=1:m,b=1:B,l=0:1] >= 0
θ >= 0
end
@objective(modelo, Min, θ)
@constraints modelo begin
c1[j=1:n,k=1:m], sum(sum(x[j,k,b,l] for l=0:1) for b=1:B) == 1
c2[k=1:m,b=1:B], sum(sum(sum(x[j,k,a,l] for a=max(b-P[j,k]-l+2,1):b) for l=0:1) for j=1:n) <= 1
c4[j=1:n,k=2:m], sum(sum((b*Δ*x[j,k-1,b,l]-Δ*u[j,k-1,b,l]+x[j,k-1,b,l]*p[j,k-1]) for b=1:B) for l=0:1) <= sum(sum(b*Δ*x[j,k,b,l]-Δ*u[j,k,b,l] for b=1:B) for l=0:1)
c6[j=1:n,k=1:m,b=1:B,l=0:1], ((1-l)*(1-π[j,k])+(1/Δ))*x[j,k,b,l] <= u[j,k,b,l]
c7[j=1:n,k=1:m,b=1:B,l=0:1], u[j,k,b,l] <= (1-l*π[j,k])*x[j,k,b,l]
end
# SUBPROBLEM
function subproblem(x, u)
modelosub = Model(Gurobi.Optimizer)
set_optimizer_attribute(modelosub, "TimeLimit", 3600) # Gurobi
set_optimizer_attribute(modelosub, "InfUnbdInfo", 1) # to get the UnbdRay attribute (senão dá erro)
@variables modelosub begin
v[j=1:n,k=1:m,b=1:B,l=0:1] >= 0
Cmax >= 0
end
@objective(modelosub, Min, Cmax)
con3 = @constraint(modelosub, [k=1:m,b=1:B], sum(sum(v[j,k,b,l] for j=1:n) for l=0:1) <= 1 - sum(sum(sum(x[j,k,a,l] for a=max(b-P[j,k]-l+2,1):b-1) - u[j,k,b,l] for j=1:n) for l=0:1) )
con5 = @constraint(modelosub, [j=1:n,k=1:m,b=1:B,l=0:1; b+P[j,k]+l-1<=B], v[j,k,b+P[j,k]+l-1,l] == (2-l-π[j,k])*x[j,k,b,l] - u[j,k,b,l])
con8 = @constraint(modelosub, [j=1:n,k=1:m,b=1:B,l=0:1; b+P[j,k]+l-1<=B], - v[j,k,b+P[j,k]+l-1,l] <= (l-1)*(x[j,k,b,l] - π[j,k]*x[j,k,b,l]))
con9 = @constraint(modelosub, [j=1:n,k=1:m,b=1:B,l=0:1; b+P[j,k]+l-1<=B], v[j,k,b+P[j,k]+l-1,l] <= ((1/Δ)- l*π[j,k])*x[j,k,b,l] )
con10 = @constraint(modelosub, [j=1:n], Cmax >= sum(sum(b*Δ*x[j,m,b,l]+x[j,m,b,l]*p[j,m] - Δ*u[j,m,b,l] for b=1:B) for l=0:1))
optimize!(modelosub)
if termination_status(modelosub) == OPTIMAL || termination_status(modelosub) == INFEASIBLE
return (obj = dual_objective_value(modelosub), status = termination_status(modelosub), λ1 = dual.(con3), λ3 = dual.(con5), λ6 = dual.(con8), λ7 = dual.(con9), λ8 = dual.(con10))
end
end
# BENDERS DECOMPOSITION METHOD
iter = 0
cut_opt = 0
cut_fact = 0
tempo = time() - inicio
MAXIMUM_ITER = 10
while iter < MAXIMUM_ITER
global tempo = time() - inicio
global iter += 1
optimize!(modelo)
lower_bound = objective_value(modelo)
x_k = value.(x)
u_k = value.(u)
ret = subproblem(x_k, u_k)
upper_bound_iter = ret.obj
global upper_bound = min(upper_bound_iter, upper_bound)
gap = (upper_bound - lower_bound) / upper_bound
println()
println("===========")
println("Iteration Lower Bound Upper Bound Gap")
println(string(iter), " ", string(lower_bound), "\t", string(upper_bound), " ", "$(@sprintf("%.6f",gap))")
println("===========")
if gap < ABSOLUTE_OPTIMALITY_GAP
println()
println("Terminating with the optimal solution")
break
end
if ret.status == OPTIMAL
cut = @constraint(modelo, θ >=
sum(sum((1 - sum(sum(sum(x[j,k,a,l] for a=max(b-P[j,k]-l+2,1):b-1) - u[j,k,b,l] for j=1:n) for l=0:1))*ret.λ1[k,b] for k=1:m) for b=1:B)
+ sum(sum(sum(sum(((2-l-π[j,k])*x[j,k,b,l] - u[j,k,b,l])*ret.λ3[j,k,b,l] for j=1:n if b+P[j,k]+l-1<=B) for k=1:m) for b=1:B) for l=0:1)
+ sum(sum(sum(sum(((l-1)*(x[j,k,b,l] - π[j,k]*x[j,k,b,l]))*ret.λ6[j,k,b,l] for j=1:n if b+P[j,k]+l-1<=B) for k=1:m) for b=1:B) for l=0:1)
+ sum(sum(sum(sum((((1/Δ)- l*π[j,k])*x[j,k,b,l])*ret.λ7[j,k,b,l] for j=1:n if b+P[j,k]+l-1<=B) for k=1:m) for b=1:B) for l=0:1)
+ sum(sum(sum(b*Δ*x[j,m,b,l]+x[j,m,b,l]*p[j,m] - Δ*u[j,m,b,l] for b=1:B) for l=0:1)*ret.λ8[j] for j=1:n) )
global cut_opt += 1
#@info "Adding the optimality cut $(cut)"
elseif ret.status == INFEASIBLE
cut = @constraint(modelo, 0 <=
sum(sum((1 - sum(sum(sum(x[j,k,a,l] for a=max(b-P[j,k]-l+2,1):b-1) - u[j,k,b,l] for j=1:n) for l=0:1))*ret.λ1[k,b] for k=1:m) for b=1:B)
+ sum(sum(sum(sum(((2-l-π[j,k])*x[j,k,b,l] - u[j,k,b,l])*ret.λ3[j,k,b,l] for j=1:n if b+P[j,k]+l-1<=B) for k=1:m) for b=1:B) for l=0:1)
+ sum(sum(sum(sum(((l-1)*(x[j,k,b,l] - π[j,k]*x[j,k,b,l]))*ret.λ6[j,k,b,l] for j=1:n if b+P[j,k]+l-1<=B) for k=1:m) for b=1:B) for l=0:1)
+ sum(sum(sum(sum((((1/Δ)- l*π[j,k])*x[j,k,b,l])*ret.λ7[j,k,b,l] for j=1:n if b+P[j,k]+l-1<=B) for k=1:m) for b=1:B) for l=0:1)
+ sum(sum(sum(b*Δ*x[j,m,b,l]+x[j,m,b,l]*p[j,m] - Δ*u[j,m,b,l] for b=1:B) for l=0:1)*ret.λ8[j] for j=1:n) )
global cut_fact += 1
@info "Adding the feasibility cut $(cut)"
end
end
#println("Z = ", objective_value(modelo))
tempo = time() - inicio
println()
println("TEMPO TOTAL = ", tempo)
println("Núm iterações = ", iter)
println("Núm cuts opt = ", cut_opt)
println("Núm cuts fact = ", cut_fact)