diff --git a/src/Utilities/cachingoptimizer.jl b/src/Utilities/cachingoptimizer.jl index cf5b95c280..42b89a5af2 100644 --- a/src/Utilities/cachingoptimizer.jl +++ b/src/Utilities/cachingoptimizer.jl @@ -253,7 +253,10 @@ end function MOI.empty!(m::CachingOptimizer) MOI.empty!(m.model_cache) - if m.state == ATTACHED_OPTIMIZER + if m.state != NO_OPTIMIZER + # We call `empty!` even if the state is already `EMPTY_OPTIMIZER` + # because we may have used to two-argument `optimize!` for a single-shot + # solver. MOI.empty!(m.optimizer) m.state = EMPTY_OPTIMIZER end diff --git a/test/Utilities/cachingoptimizer.jl b/test/Utilities/cachingoptimizer.jl index fa67d79052..b5caa00fe2 100644 --- a/test/Utilities/cachingoptimizer.jl +++ b/test/Utilities/cachingoptimizer.jl @@ -763,20 +763,34 @@ function test_status_codes() return end -struct CopyToAndOptimizer <: MOI.AbstractOptimizer end -MOI.is_empty(::CopyToAndOptimizer) = true -function MOI.optimize!(::CopyToAndOptimizer, src::MOI.ModelLike) +mutable struct CopyToAndOptimizer <: MOI.AbstractOptimizer + is_dirty::Bool +end + +function MOI.empty!(x::CopyToAndOptimizer) + x.is_dirty = false + return +end + +MOI.is_empty(x::CopyToAndOptimizer) = !x.is_dirty + +function MOI.optimize!(x::CopyToAndOptimizer, ::MOI.ModelLike) + x.is_dirty = true return MOI.Utilities.IndexMap(), false end function test_copy_to_and_optimize!() - optimizer = CopyToAndOptimizer() + optimizer = CopyToAndOptimizer(false) model = MOI.Utilities.CachingOptimizer( MOI.Utilities.Model{Float64}(), optimizer, ) MOI.optimize!(model) @test MOI.Utilities.state(model) == MOI.Utilities.EMPTY_OPTIMIZER + @test !MOI.is_empty(optimizer) + MOI.empty!(model) + @test MOI.is_empty(optimizer) + @test MOI.Utilities.state(model) == MOI.Utilities.EMPTY_OPTIMIZER return end