From 45f9ca77300a3a180aa82dbcd8938e4cd4524c94 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 21 Feb 2022 10:48:23 +1300 Subject: [PATCH] Fix handling of INVALID_MODEL (#303) --- src/MOI_wrapper.jl | 17 +++++++++++++---- test/MOI_wrapper.jl | 10 ++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index 4d1971b..3c393d9 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -13,6 +13,7 @@ Create a new Ipopt optimizer. """ mutable struct Optimizer <: MOI.AbstractOptimizer inner::Union{Nothing,IpoptProblem} + invalid_model::Bool variables::MOI.Utilities.VariablesContainer{Float64} variable_primal_start::Vector{Union{Nothing,Float64}} variable_lower_start::Vector{Union{Nothing,Float64}} @@ -67,6 +68,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer function Optimizer() return new( nothing, + false, MOI.Utilities.VariablesContainer{Float64}(), Union{Nothing,Float64}[], Union{Nothing,Float64}[], @@ -123,6 +125,7 @@ MOI.eval_hessian_lagrangian(::_EmptyNLPEvaluator, H, x, σ, μ) = nothing function MOI.empty!(model::Optimizer) model.inner = nothing + model.invalid_model = false MOI.empty!(model.variables) empty!(model.variable_primal_start) empty!(model.variable_lower_start) @@ -1119,6 +1122,11 @@ function MOI.optimize!(model::Optimizer) push!(g_U, bound.upper) end start_time = time() + if length(model.variables.lower) == 0 + # Don't attempt to create a problem because Ipopt will error. + model.invalid_model = true + return + end model.inner = CreateIpoptProblem( length(model.variables.lower), model.variables.lower, @@ -1254,7 +1262,9 @@ end ### MOI.TerminationStatus function MOI.get(model::Optimizer, ::MOI.TerminationStatus) - if model.inner === nothing + if model.invalid_model + return MOI.INVALID_MODEL + elseif model.inner === nothing return MOI.OPTIMIZE_NOT_CALLED end status = _STATUS_CODES[model.inner.status] @@ -1292,10 +1302,9 @@ function MOI.get(model::Optimizer, ::MOI.TerminationStatus) return MOI.OTHER_ERROR elseif status == :NonIpopt_Exception_Thrown return MOI.OTHER_ERROR - elseif status == :Insufficient_Memory - return MOI.MEMORY_LIMIT else - error("Unrecognized Ipopt status $status") + @assert status == :Insufficient_Memory + return MOI.MEMORY_LIMIT end end diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl index 25a4342..0f8ec4c 100644 --- a/test/MOI_wrapper.jl +++ b/test/MOI_wrapper.jl @@ -184,12 +184,10 @@ end function test_empty_optimize() model = Ipopt.Optimizer() - err = ErrorException( - "IPOPT: Failed to construct problem because there are 0 variables. " * - "If you intended to construct an empty problem, one work-around is " * - "to add a variable fixed to 0.", - ) - @test_throws err MOI.optimize!(model) + MOI.optimize!(model) + @test MOI.get(model, MOI.TerminationStatus()) == MOI.INVALID_MODEL + @test MOI.get(model, MOI.DualStatus()) == MOI.NO_SOLUTION + @test MOI.get(model, MOI.PrimalStatus()) == MOI.NO_SOLUTION return end