atoptima / Coluna.jl

Branch-and-Price-and-Cut in Julia
https://www.atoptima.com
Other
193 stars 43 forks source link

MethodError: no method matching isless #558

Closed branchprediction closed 3 years ago

branchprediction commented 3 years ago

Describe the bug Same model as in #557 but after having substituted 1:number_of_machines for the M axis. Also updated to Coluna v0.4.0#master. Model now runs with tree search but produces the following output:

  <it= 95> <et= 2.22> <mst= 0.00> <sp= 0.03> <cols= 0> <al= 0.00> <DB=   30.1514> <mlp=   30.1514> <PB=Inf>
[ Info: Column generation algorithm has converged.
[ Info: Running Restricted Master IP heuristic
ERROR: LoadError: MethodError: no method matching isless(::Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64}, ::Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64})
Closest candidates are:
  isless(::Missing, ::Any) at missing.jl:87
  isless(::BlockDecomposition.AxisId{N,T}, ::T) where {N, T} at /Path/To/src/axis.jl:36
  isless(::Any, ::Missing) at missing.jl:88

To Reproduce

using JuMP, BlockDecomposition, Coluna, Gurobi

optimizer = optimizer_with_attributes(
    Coluna.Optimizer,
    "params" => Coluna.Params(
        # solver = Coluna.Algorithm.ColumnGeneration()
        solver = Coluna.Algorithm.TreeSearchAlgorithm() # default BCP
        # solver = Coluna.Algorithm.SolveIpForm()
    ),
    "default_optimizer" => Gurobi.Optimizer # Gurobi for the master & the sub-problems
)

number_of_machines = 10
number_of_jobs = 21
number_of_nonavailability_periods_per_machine = 1
# Define the decomposition axis
@axis(M, 1:number_of_machines)
# Define the other indices
M_odd = 1:2:number_of_machines
J = 1:number_of_jobs
Q = 1:number_of_nonavailability_periods_per_machine
Qsub = 1:(number_of_nonavailability_periods_per_machine-1)
# Define parameters
big_m = 1000.0
alpha = 0.5
Q_starts = [0.0; 20.0; 0.0; 20.0; 0.0; 20.0; 0.0; 20.0; 0.0; 20.0]
Q_ends = [2.0; 22.0; 2.0; 22.0; 2.0; 22.0; 2.0; 22.0; 2.0; 22.0]
Q_durs = [2.0; 2.0; 2.0; 2.0; 2.0; 2.0; 2.0; 2.0; 2.0; 2.0]
J_durs = [19.0, 19.0, 18.0, 18.0, 17.0, 17.0, 16.0, 16.0, 15.0, 15.0, 14.0, 14.0, 13.0, 13.0, 12.0, 12.0, 11.0, 11.0, 10.0, 10.0, 10.0]

model = BlockModel(optimizer)
@variable(model, x[m in M, j in J], Bin)
@variable(model, y[m in M, q in Q], Bin)
@variable(model, b[m in M, j in J, q in Q], Bin)
@variable(model, 0.0<=w[m in M, q in Q]<=1000.0)
@variable(model, 0.0<=makespan<=1000.0)

@constraint(model, c2[j in J], sum(x[m, j] for m in M) == 1)
@constraint(model, c3[m in M, q in Q], sum(J_durs[j] * x[m, j] for j in J) + sum(alpha * w[m, k] for k in 1:(q-1)) + big_m * y[m, q] <= - sum(Q_durs[m, k] for k in 1:(q-1)) + big_m + Q_starts[m, q])
# @constraint(model, c4[m in M], sum(J_durs[j] * x[m, j] for j in J) - sum(Q_durs[m, q] * y[m, q] for q in Q) + sum(alpha * w[m, q] for q in Q) - makespan <= - sum(Q_durs[m, q] for q in Q))
@constraint(model, c4[m in 1:number_of_machines], sum(J_durs[j] * x[m, j] for j in J) - sum(Q_durs[m, q] * y[m, q] for q in Q) + sum(alpha * w[m, q] for q in Q) - makespan <= - sum(Q_durs[m, q] for q in Q))
@constraint(model, c5[m in M, q in Q], Q_starts[m, q] * y[m, q] + sum(J_durs[j] * b[m, j, q] for j in J) + sum(alpha * w[m, k] for k in 1:(q-1)) + w[m, q] >= Q_starts[m, q] - sum(Q_durs[m, k] for k in 1:(q-1)))
@constraint(model, c6[m in M, q in Q], sum(J_durs[j] * b[m, j, q] for j in J) + sum(alpha * w[m, k] for k in 1:(q-1)) + w[m, q] <= Q_starts[m, q] - sum(Q_durs[m, k] for k in 1:(q-1)))
@constraint(model, c7[m in M, j in J, q in Qsub], b[m, j, q+1] - b[m, j, q] >= 0)
@constraint(model, c8[m in M, j in J, q in Q], b[m, j, q] - x[m, j] <= 0)
@constraint(model, c9[m in M, q in Qsub], sum(J_durs[j] * b[m, j, q+1] for j in J) - sum(J_durs[j] * b[m, j, q] for j in J) - (1.0 - alpha) * w[m, q] <= Q_starts[m, q+1] - Q_ends[m, q])
@constraint(model, c15[m in M_odd], sum(x[m, j] for j in J) + y[m, 1] >= 1)

@objective(model, Min, makespan)

@dantzig_wolfe_decomposition(model, decomposition, M)

optimize!(model)
for m in M
    a = collect(value.(x[m, j]) for j in J)
    println(a)
end

Expected behavior Expected model to find optimal solution of 33.

Environment (please complete the following information): Julia Version 1.4.1 OS: Linux (x86_64-linux-gnu) BlockDecomposition v1.3.0 #master (https://github.com/atoptima/BlockDecomposition.jl.git) Coluna v0.4.0 #master (https://github.com/atoptima/Coluna.jl.git) ColunaDemos v0.1.0 #master (https://github.com/atoptima/ColunaDemos.jl) Gurobi v0.9.14 JuMP v0.21.8

Additional context: This problem has a known optimal solution of 33.

branchprediction commented 3 years ago
Stacktrace:
 [1] lt(::Base.Order.ForwardOrdering, ::Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64}, ::Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64}) at ./ordering.jl:50
 [2] lt(::Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}, ::Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64}, ::Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64}) at ./ordering.jl:51
 [3] sort! at ./sort.jl:480 [inlined]
 [4] sort!(::Array{Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64},1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}, ::Array{Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64},1}) at ./sort.jl:565
 [5] sort! at ./sort.jl:564 [inlined]
 [6] sort! at ./sort.jl:655 [inlined]
 [7] #sort!#7 at ./sort.jl:715 [inlined]
 [8] sort(::Array{Coluna.ColunaBase.Solution{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.Id{Coluna.MathProg.Variable},Float64},1}; kws::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol},NamedTuple{(:rev,),Tuple{Bool}}}) at ./sort.jl:763
 [9] run!(::Coluna.Algorithm.ColCutGenConquer, ::Env, ::Coluna.MathProg.Reformulation, ::Coluna.Algorithm.ConquerInput) at /Path/To/src/Algorithm/conquer.jl:258
 [10] apply_conquer_alg_to_node!(::Coluna.Algorithm.Node, ::Coluna.Algorithm.ColCutGenConquer, ::Env, ::Coluna.MathProg.Reformulation, ::Coluna.ColunaBase.UnitsUsage, ::Float64, ::Float64) at /Path/To/src/Algorithm/conquer.jl:61
 [11] run_conquer_algorithm!(::Coluna.Algorithm.TreeSearchAlgorithm, ::Env, ::Coluna.Algorithm.TreeSearchRuntimeData{Coluna.MathProg.MinSense}, ::Coluna.MathProg.Reformulation, ::Coluna.Algorithm.Node) at /Path/To/src/Algorithm/treesearch.jl:259
 [12] run!(::Coluna.Algorithm.TreeSearchAlgorithm, ::Env, ::Coluna.MathProg.Reformulation, ::Coluna.Algorithm.OptimizationInput{Coluna.MathProg.Formulation{Coluna.MathProg.DwMaster},Coluna.MathProg.MinSense}) at /Path/To/src/Algorithm/treesearch.jl:338
 [13] optimize!(::Coluna.MathProg.Reformulation, ::Env, ::Coluna.ColunaBase.Bound{Coluna.MathProg.Primal,Coluna.MathProg.MinSense}, ::Coluna.ColunaBase.Bound{Coluna.MathProg.Dual,Coluna.MathProg.MinSense}) at /Path/To/src/optimize.jl:95
 [14] macro expansion at /Path/To/src/optimize.jl:63 [inlined]
 [15] macro expansion at /Path/To/TimerOutputs/..../src/TimerOutput.jl:220 [inlined]
 [16] optimize!(::Env, ::Coluna.MathProg.Problem, ::Coluna.Annotations) at /Path/To/src/optimize.jl:62
 [17] optimize!(::Coluna.Optimizer) at /Path/To/src/MOIwrapper.jl:100
 [18] optimize!(::MathOptInterface.Bridges.LazyBridgeOptimizer{Coluna.Optimizer}) at /Path/To/MathOptInterface/..../src/Bridges/bridge_optimizer.jl:319
 [19] optimize!(::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64,MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}}) at /Path/To/MathOptInterface/.../src/Utilities/cachingoptimizer.jl:252
 [20] optimize!(::Model, ::Nothing; bridge_constraints::Bool, ignore_optimize_hook::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /Path/To/JuMP/.../src/optimizer_interface.jl:185
 [21] optimize!(::Model) at /Path/To/BlockDecomposition/.../src/BlockDecomposition.jl:55
 [22] optimize!(::Model, ::Nothing; bridge_constraints::Bool, ignore_optimize_hook::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /Path/To/JuMP/.../src/optimizer_interface.jl:173
 [23] optimize! at /Path/To/JuMP/.../src/optimizer_interface.jl:157 [inlined] (repeats 2 times)
 [24] top-level scope at /Path/To/model.jl:61
in expression starting at /Path/To/model.jl:61