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
1 change: 1 addition & 0 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1950,6 +1950,7 @@ end

function MOI.optimize!(model::Optimizer)
if !isempty(model.updated_parameters)
MOI.Utilities.final_touch(model, nothing)
update_parameters!(model)
end
MOI.optimize!(model.optimizer)
Expand Down
26 changes: 21 additions & 5 deletions src/ParametricOptInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,17 @@ include("parametric_cubic_function.jl")
evaluate_duals::Bool = true,
save_original_objective_and_constraints::Bool = true,
with_bridge_type = nothing,
with_cache_type = nothing,
)

Create an `Optimizer`, which allows the handling of parameters in an
optimization model.

If `optimizer` is not a `MOI.ModelLike,` the inner optimizer is constructed
using `MOI.instantiate(optimizer; with_bridge_type)`.
using `MOI.instantiate(optimizer; with_cache_type)`.

If `with_bridge_type !== nothing`, a `MOI.Bridges.full_bridge_optimizer` is
applied as an outer layer.

The `{T}` type parameter is optional; it defaults to `Float64`.

Expand All @@ -82,8 +86,9 @@ The `{T}` type parameter is optional; it defaults to `Float64`.
Note that this might break printing or queries such as
`MOI.get(model, MOI.ConstraintFunction(), c)`. Defaults to `true`.

- `with_bridge_type`: this is ignroed if `optimizer::MOI.ModelLike`, otherwise
it is passed to `MOI.instantiate`.
- `with_bridge_type`: the type passed to `MOI.Bridges.full_bridge_optimizer`

- `with_cache_type`: the type passed to `MOI.instantiate`

## Example

Expand Down Expand Up @@ -276,13 +281,24 @@ Optimizer(arg; kwargs...) = Optimizer{Float64}(arg; kwargs...)
function Optimizer{T}(
optimizer_fn;
with_bridge_type = nothing,
with_cache_type = nothing,
kwargs...,
) where {T}
inner = MOI.instantiate(optimizer_fn; with_bridge_type)
inner = MOI.instantiate(optimizer_fn; with_cache_type)
if !MOI.supports_incremental_interface(inner)
cache = MOI.default_cache(inner, T)
# Don't use `default_cache` for the cache because, for example, SCS's
# default cache doesn't support modifying coefficients of the constraint
# matrix. JuMP uses the default cache with SCS because it has an outer
# layer of caching; we don't have that here, so we can't use the
# default.
#
# We could revert to using the default cache if we fix this in MOI.
cache = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}())
inner = MOI.Utilities.CachingOptimizer(cache, inner)
end
if with_bridge_type !== nothing
inner = MOI.Bridges.full_bridge_optimizer(inner, with_bridge_type)
end
return Optimizer{T}(inner; kwargs...)
end

Expand Down
2 changes: 1 addition & 1 deletion test/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
HiGHS = "1"
Ipopt = "1"
JuMP = "1"
SCS = "1"
SCS = "2"
39 changes: 6 additions & 33 deletions test/test_JuMP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -834,12 +834,7 @@ function test_jump_dual_delete_constraint_2()
end

function test_jump_dual_delete_constraint_3()
cached = MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
SCS.Optimizer(),
)
optimizer = POI.Optimizer(cached)
model = direct_model(optimizer)
model = direct_model(POI.Optimizer(SCS.Optimizer))
set_silent(model)
list = []
@variable(model, α in Parameter(1.0))
Expand Down Expand Up @@ -1211,15 +1206,8 @@ function test_parameter_Cannot_be_inf_2()
end

function test_jump_psd_cone_with_parameter_pv()
cached = MOI.Bridges.full_bridge_optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
SCS.Optimizer(),
),
Float64,
)
optimizer = POI.Optimizer(cached)
model = direct_model(optimizer)
inner = POI.Optimizer(SCS.Optimizer; with_bridge_type = Float64)
model = direct_model(inner)
set_silent(model)
@variable(model, x)
@variable(model, p in Parameter(1.0))
Expand Down Expand Up @@ -1406,18 +1394,8 @@ function test_jump_psd_cone_without_parameter_v_and_vv()
end

function test_variable_and_constraint_not_registered()
cached1 = MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
SCS.Optimizer(),
)
optimizer1 = POI.Optimizer(cached1)
model1 = direct_model(optimizer1)
cached2 = MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
SCS.Optimizer(),
)
optimizer2 = POI.Optimizer(cached2)
model2 = direct_model(optimizer2)
model1 = direct_model(POI.Optimizer(SCS.Optimizer))
model2 = direct_model(POI.Optimizer(SCS.Optimizer))
set_silent(model1)
set_silent(model2)
@variable(model1, x)
Expand Down Expand Up @@ -1505,12 +1483,7 @@ function test_variable_and_constraint_not_registered()
end

function test_jump_errors()
cached1 = MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
SCS.Optimizer(),
)
optimizer1 = POI.Optimizer(cached1)
model = direct_model(optimizer1)
model = direct_model(POI.Optimizer(SCS.Optimizer))
@test_throws MOI.UnsupportedAttribute MOI.get(
backend(model),
MOI.NLPBlock(),
Expand Down
66 changes: 22 additions & 44 deletions test/test_MathOptInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,10 @@ function test_moi_highs()
end

function test_moi_ipopt()
model = MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MOI.Bridges.full_bridge_optimizer(
POI.Optimizer(Ipopt.Optimizer),
Float64,
),
model = POI.Optimizer(
Ipopt.Optimizer;
with_bridge_type = Float64,
with_cache_type = Float64,
)
MOI.set(model, MOI.Silent(), true)
# Without fixed_variable_treatment set, duals are not computed for variables
Expand Down Expand Up @@ -364,6 +362,7 @@ function test_moi_ipopt()
# - CachingOptimizer does not throw if optimizer not attached
"test_model_copy_to_UnsupportedAttribute",
"test_model_copy_to_UnsupportedConstraint",
"test_model_ModelFilter_AbstractConstraintAttribute",
# - POI only supports cubic polynomial ScalarNonlinearFunction
"test_nonlinear_duals",
"test_nonlinear_expression_",
Expand Down Expand Up @@ -570,14 +569,7 @@ function test_production_problem_example_duals()
end

function test_production_problem_example_parameters_for_duals_and_intervals()
cached = MOI.Bridges.full_bridge_optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
HiGHS.Optimizer(),
),
Float64,
)
optimizer = POI.Optimizer(cached)
optimizer = POI.Optimizer(HiGHS.Optimizer; with_bridge_type = Float64)
MOI.set(optimizer, MOI.Silent(), true)
c = [4.0, 3.0]
A1 = [2.0, 1.0, 3.0]
Expand Down Expand Up @@ -639,14 +631,14 @@ function test_production_problem_example_parameters_for_duals_and_intervals()
MOI.set(optimizer, MOI.ConstraintSet(), cz, MOI.Parameter(1.0))
MOI.optimize!(optimizer)
@test ≈(MOI.get(optimizer, MOI.ObjectiveValue()), 7.0, atol = ATOL)
@test MOI.get.(optimizer, MOI.VariablePrimal(), x) == [0.0, 1.0]
@test MOI.get.(optimizer, MOI.VariablePrimal(), x) [0.0, 1.0]
@test ≈(MOI.get(optimizer, MOI.ConstraintDual(), cy), 9.0, atol = ATOL)
@test ≈(MOI.get(optimizer, MOI.ConstraintDual(), cz), 0.0, atol = ATOL)
@test ≈(MOI.get(optimizer, MOI.ConstraintDual(), cw), -2.0, atol = ATOL)
MOI.set(optimizer, MOI.ConstraintSet(), cw, MOI.Parameter(0.0))
MOI.optimize!(optimizer)
@test ≈(MOI.get(optimizer, MOI.ObjectiveValue()), 3.0, atol = ATOL)
@test MOI.get.(optimizer, MOI.VariablePrimal(), x) == [0.0, 1.0]
@test MOI.get.(optimizer, MOI.VariablePrimal(), x) [0.0, 1.0]
@test ≈(MOI.get(optimizer, MOI.ConstraintDual(), cy), 9.0, atol = ATOL)
@test ≈(MOI.get(optimizer, MOI.ConstraintDual(), cz), 0.0, atol = ATOL)
@test ≈(MOI.get(optimizer, MOI.ConstraintDual(), cw), -2.0, atol = ATOL)
Expand Down Expand Up @@ -2035,6 +2027,7 @@ function test_psd_cone_with_parameter()
@test MOI.get(model, MOI.ConstraintName(), c_index) == ""
MOI.set(model, MOI.ConstraintName(), c_index, "psd_cone")
@test MOI.get(model, MOI.ConstraintName(), c_index) == "psd_cone"
return
end

function test_copy_model()
Expand Down Expand Up @@ -2125,15 +2118,13 @@ end
struct VariableAttributeForTest <: MOI.AbstractVariableAttribute end
struct ConstraintAttributeForTest <: MOI.AbstractConstraintAttribute end

function test_variable_attribute_error()
solver = HiGHS.Optimizer()
MOI.set(solver, MOI.Silent(), true)
function test_AA_variable_attribute_error()
model = POI.Optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MOI.Bridges.full_bridge_optimizer(solver, Float64),
),
HiGHS.Optimizer;
with_bridge_type = Float64,
with_cache_type = Float64,
)
MOI.set(model, MOI.Silent(), true)
x = MOI.add_variable(model)
MOI.set(model, VariableAttributeForTest(), x, 1.0)
p, pc = MOI.add_constrained_variable(model, MOI.Parameter(1.0))
Expand All @@ -2148,13 +2139,8 @@ function test_variable_attribute_error()
end

function test_constraint_attribute_error()
solver = MOI.Utilities.Model{Float64}()
model = POI.Optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MOI.Bridges.full_bridge_optimizer(solver, Float64),
),
)
model =
POI.Optimizer(MOI.Utilities.Model{Float64}; with_bridge_type = Float64)
MOI.supports(
model,
ConstraintAttributeForTest(),
Expand All @@ -2170,13 +2156,8 @@ function test_constraint_attribute_error()
end

function test_name_from_bound()
solver = MOI.Utilities.Model{Float64}()
model = POI.Optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MOI.Bridges.full_bridge_optimizer(solver, Float64),
),
)
model =
POI.Optimizer(MOI.Utilities.Model{Float64}; with_bridge_type = Float64)
x = MOI.add_variable(model)
p, pc = MOI.add_constrained_variable(model, MOI.Parameter(1.0))
MOI.set(model, POI.ConstraintsInterpretation(), POI.ONLY_BOUNDS)
Expand All @@ -2200,15 +2181,12 @@ function test_get_constraint_set()
end

function test_quadratic_variable_parameter()
# model = POI.Optimizer(MOI.Utilities.Model{Float64}())
solver = Ipopt.Optimizer()
MOI.set(solver, MOI.Silent(), true)
model = POI.Optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MOI.Bridges.full_bridge_optimizer(solver, Float64),
),
Ipopt.Optimizer;
with_bridge_type = Float64,
with_cache_type = Float64,
)
MOI.set(model, MOI.Silent(), true)
x = MOI.add_variable(model)
p, pc = MOI.add_constrained_variable(model, MOI.Parameter(1.0))
f = 1.0 * x * x - 2.0 * p * p
Expand Down
Loading