From f615b329b753d33a92223dca7e6b6f4c599bef25 Mon Sep 17 00:00:00 2001 From: odow Date: Tue, 2 Feb 2021 16:00:18 +1300 Subject: [PATCH 1/3] [Utilities] Drop MOI.RawParameters when resetting a CachingOptimizer --- src/Utilities/cachingoptimizer.jl | 13 +++++++++++-- test/Utilities/cachingoptimizer.jl | 25 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/Utilities/cachingoptimizer.jl b/src/Utilities/cachingoptimizer.jl index 4c721ddebc..f503ccf50f 100644 --- a/src/Utilities/cachingoptimizer.jl +++ b/src/Utilities/cachingoptimizer.jl @@ -113,14 +113,23 @@ mode(m::CachingOptimizer) = m.mode """ reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer) -Sets or resets `m` to have the given empty optimizer. Can be called -from any state. The `CachingOptimizer` will be in state `EMPTY_OPTIMIZER` after the call. +Sets or resets `m` to have the given empty optimizer `optimizer`. + +Can be called from any state. An assertion error will be thrown if `optimizer` +is not empty. + +The `CachingOptimizer` `m` will be in state `EMPTY_OPTIMIZER` after the call. """ function reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer) @assert MOI.is_empty(optimizer) m.optimizer = optimizer m.state = EMPTY_OPTIMIZER for attr in MOI.get(m.model_cache, MOI.ListOfOptimizerAttributesSet()) + if attr isa MOI.RawParameter + # Skip RawParameters because they may not apply to the new + # optimizer. + continue + end value = MOI.get(m.model_cache, attr) optimizer_value = map_indices(m.model_to_optimizer_map, value) MOI.set(m.optimizer, attr, optimizer_value) diff --git a/test/Utilities/cachingoptimizer.jl b/test/Utilities/cachingoptimizer.jl index 9c614dc475..41aad9a894 100644 --- a/test/Utilities/cachingoptimizer.jl +++ b/test/Utilities/cachingoptimizer.jl @@ -652,3 +652,28 @@ end MOIU.reset_optimizer(model, optimizer) constrained_variables_test(model) end + +struct Issue1220 <: MOI.AbstractOptimizer + optimizer_attributes::Dict{Any,Any} + Issue1220() = new(Dict{Any,Any}()) +end +MOI.is_empty(model::Issue1220) = isempty(model.optimizer_attributes) +function MOI.get(model::Issue1220, ::MOI.ListOfOptimizerAttributesSet) + return collect(keys(model.optimizer_attributes)) +end +MOI.supports(::Issue1220, ::MOI.AbstractOptimizerAttribute) = true +function MOI.get(model::Issue1220, attr::MOI.AbstractOptimizerAttribute) + return model.optimizer_attributes[attr] +end +function MOI.set(model::Issue1220, attr::MOI.AbstractOptimizerAttribute, value) + model.optimizer_attributes[attr] = value + return value +end +@testset "Issue1220_dont_pass_raw_parameter" begin + model = MOIU.CachingOptimizer(Issue1220(), Issue1220()) + MOI.set(model, MOI.Silent(), true) + MOI.set(model, MOI.RawParameter("foo"), "bar") + MOIU.reset_optimizer(model, Issue1220()) + @test MOI.get(model, MOI.Silent()) == true + @test_throws KeyError MOI.get(model, MOI.RawParameter("foo")) +end From db848fc30191c76f078bc1bb6ee6dcf1b458b61a Mon Sep 17 00:00:00 2001 From: odow Date: Fri, 26 Mar 2021 12:02:20 +1300 Subject: [PATCH 2/3] Only pass supported attributes --- src/Utilities/cachingoptimizer.jl | 5 +++-- test/Utilities/cachingoptimizer.jl | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Utilities/cachingoptimizer.jl b/src/Utilities/cachingoptimizer.jl index f503ccf50f..b1485be25b 100644 --- a/src/Utilities/cachingoptimizer.jl +++ b/src/Utilities/cachingoptimizer.jl @@ -125,9 +125,10 @@ function reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer) m.optimizer = optimizer m.state = EMPTY_OPTIMIZER for attr in MOI.get(m.model_cache, MOI.ListOfOptimizerAttributesSet()) + # Skip attributes which don't apply to the new optimizer. if attr isa MOI.RawParameter - # Skip RawParameters because they may not apply to the new - # optimizer. + continue + elseif !MOI.is_copyable(attr) || !MOI.supports(m.optimizer, attr) continue end value = MOI.get(m.model_cache, attr) diff --git a/test/Utilities/cachingoptimizer.jl b/test/Utilities/cachingoptimizer.jl index 41aad9a894..977486f61e 100644 --- a/test/Utilities/cachingoptimizer.jl +++ b/test/Utilities/cachingoptimizer.jl @@ -662,6 +662,7 @@ function MOI.get(model::Issue1220, ::MOI.ListOfOptimizerAttributesSet) return collect(keys(model.optimizer_attributes)) end MOI.supports(::Issue1220, ::MOI.AbstractOptimizerAttribute) = true +MOI.supports(::Issue1220, ::MOI.NumberOfThreads) = false function MOI.get(model::Issue1220, attr::MOI.AbstractOptimizerAttribute) return model.optimizer_attributes[attr] end @@ -673,7 +674,9 @@ end model = MOIU.CachingOptimizer(Issue1220(), Issue1220()) MOI.set(model, MOI.Silent(), true) MOI.set(model, MOI.RawParameter("foo"), "bar") + MOI.set(model, MOI.NumberOfThreads(), 1) MOIU.reset_optimizer(model, Issue1220()) @test MOI.get(model, MOI.Silent()) == true @test_throws KeyError MOI.get(model, MOI.RawParameter("foo")) + @test_throws KeyError MOI.get(model, MOI.NumberOfThreads()) end From fd78543a5dbc5dae83b56098cde5e4cf96c02436 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 5 Apr 2021 11:04:50 +1200 Subject: [PATCH 3/3] Update cachingoptimizer.jl --- src/Utilities/cachingoptimizer.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Utilities/cachingoptimizer.jl b/src/Utilities/cachingoptimizer.jl index b1485be25b..8cc42c29a8 100644 --- a/src/Utilities/cachingoptimizer.jl +++ b/src/Utilities/cachingoptimizer.jl @@ -127,6 +127,10 @@ function reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer) for attr in MOI.get(m.model_cache, MOI.ListOfOptimizerAttributesSet()) # Skip attributes which don't apply to the new optimizer. if attr isa MOI.RawParameter + # Even if the optimizer claims to `supports` `attr`, the value + # might have a different meaning (e.g., two solvers with `logLevel` + # as a RawParameter). To be on the safe side, just skip all raw + # parameters. continue elseif !MOI.is_copyable(attr) || !MOI.supports(m.optimizer, attr) continue