Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/Utilities/cachingoptimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,28 @@ 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())
# Skip attributes which don't apply to the new optimizer.
if attr isa MOI.RawParameter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if I undersand correctly, this is a workaround for solvers not implementing supports correctly for RawParameter? Otherwise, this would we caughr by the second condition

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is it because RawParameter with the same name might have different meaning?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be clarified in a comment

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because RawParameter with the same name might have different meaning?

This.

# 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
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)
Expand Down
28 changes: 28 additions & 0 deletions test/Utilities/cachingoptimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,31 @@ 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
MOI.supports(::Issue1220, ::MOI.NumberOfThreads) = false
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")
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