From d8c9a1b30a21de800b8a268ee8d85af9517b4f3b Mon Sep 17 00:00:00 2001 From: Alinson S Xavier Date: Thu, 13 Aug 2020 10:21:29 -0500 Subject: [PATCH] Improve error message when instance is infeasible --- src/instance.jl | 10 +++++++--- src/model.jl | 29 +++++++++++++++++++++++------ test/graph_test.jl | 2 +- test/instance_test.jl | 4 ++-- test/model_test.jl | 12 ++++++++++-- 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/instance.jl b/src/instance.jl index f1d0f8f..a8ac440 100644 --- a/src/instance.jl +++ b/src/instance.jl @@ -72,9 +72,13 @@ function validate(json, schema) end -function load(path::String)::Instance +function parsefile(path::String)::Instance + return RELOG.parse(JSON.parsefile(path)) +end + + +function parse(json::Dict)::Instance basedir = dirname(@__FILE__) - json = JSON.parsefile(path) json_schema = JSON.parsefile("$basedir/schemas/input.json") validate(json, Schema(json_schema)) @@ -167,7 +171,7 @@ function load(path::String)::Instance # Capacities for (capacity_name, capacity_dict) in location_dict["capacities (tonne)"] - push!(sizes, PlantSize(parse(Float64, capacity_name), + push!(sizes, PlantSize(Base.parse(Float64, capacity_name), capacity_dict["variable operating cost (\$/tonne)"], capacity_dict["fixed operating cost (\$)"], capacity_dict["opening cost (\$)"])) diff --git a/src/model.jl b/src/model.jl index 024f0e6..a83f742 100644 --- a/src/model.jl +++ b/src/model.jl @@ -192,12 +192,12 @@ function create_process_node_constraints!(model::ManufacturingModel) end end -function solve(filename::String; - milp_optimizer=optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0), - lp_optimizer=optimizer_with_attributes(Clp.Optimizer, "LogLevel" => 0)) - - @info "Reading $filename..." - instance = RELOG.load(filename) +default_milp_optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0) +default_lp_optimizer = optimizer_with_attributes(Clp.Optimizer, "LogLevel" => 0) + +function solve(instance::Instance; + milp_optimizer=default_milp_optimizer, + lp_optimizer=default_lp_optimizer) @info "Building graph..." graph = RELOG.build_graph(instance) @@ -213,6 +213,11 @@ function solve(filename::String; @info "Optimizing MILP..." JuMP.optimize!(model.mip) + if !has_values(model.mip) + @warn "No solution available" + return Dict() + end + @info "Re-optimizing with integer variables fixed..." all_vars = JuMP.all_variables(model.mip) vals = Dict(var => JuMP.value(var) for var in all_vars) @@ -229,6 +234,18 @@ function solve(filename::String; return get_solution(model) end +function solve(filename::String; + milp_optimizer=default_milp_optimizer, + lp_optimizer=default_lp_optimizer) + + @info "Reading $filename..." + instance = RELOG.parsefile(filename) + + return solve(instance, + milp_optimizer=milp_optimizer, + lp_optimizer=lp_optimizer) +end + function get_solution(model::ManufacturingModel) mip, vars, eqs, graph, instance = model.mip, model.vars, model.eqs, model.graph, model.instance T = instance.time diff --git a/test/graph_test.jl b/test/graph_test.jl index 3a8802b..5c2783d 100644 --- a/test/graph_test.jl +++ b/test/graph_test.jl @@ -6,7 +6,7 @@ using RELOG @testset "Graph" begin @testset "build_graph" begin basedir = dirname(@__FILE__) - instance = RELOG.load("$basedir/../instances/s1.json") + instance = RELOG.parsefile("$basedir/../instances/s1.json") graph = RELOG.build_graph(instance) process_node_by_location_name = Dict(n.location.location_name => n for n in graph.process_nodes) diff --git a/test/instance_test.jl b/test/instance_test.jl index 3f712a7..2364e47 100644 --- a/test/instance_test.jl +++ b/test/instance_test.jl @@ -6,7 +6,7 @@ using RELOG @testset "Instance" begin @testset "load" begin basedir = dirname(@__FILE__) - instance = RELOG.load("$basedir/../instances/s1.json") + instance = RELOG.parsefile("$basedir/../instances/s1.json") centers = instance.collection_centers plants = instance.plants @@ -73,7 +73,7 @@ using RELOG end @testset "validate timeseries" begin - @test_throws String RELOG.load("fixtures/s1-wrong-length.json") + @test_throws String RELOG.parsefile("fixtures/s1-wrong-length.json") end end diff --git a/test/model_test.jl b/test/model_test.jl index 0ae2367..ba807cd 100644 --- a/test/model_test.jl +++ b/test/model_test.jl @@ -6,7 +6,7 @@ using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats @testset "Model" begin @testset "build" begin basedir = dirname(@__FILE__) - instance = RELOG.load("$basedir/../instances/s1.json") + instance = RELOG.parsefile("$basedir/../instances/s1.json") graph = RELOG.build_graph(instance) model = RELOG.build_model(instance, graph, Cbc.Optimizer) set_optimizer_attribute(model.mip, "logLevel", 0) @@ -43,7 +43,6 @@ using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats @testset "solve" begin solution = RELOG.solve("$(pwd())/../instances/s1.json") - #JSON.print(stdout, solution, 4) @test "Costs" in keys(solution) @test "Fixed operating (\$)" in keys(solution["Costs"]) @@ -57,6 +56,15 @@ using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats @test "F3" in keys(solution["Plants"]) @test "F4" in keys(solution["Plants"]) end + + @testset "infeasible solve" begin + json = JSON.parsefile("$(pwd())/../instances/s1.json") + for (location_name, location_dict) in json["products"]["P1"]["initial amounts"] + location_dict["amount (tonne)"] *= 1000 + end + RELOG.solve(RELOG.parse(json)) + end + end