Skip to content

Commit 5e0dc7f

Browse files
committed
[breaking] change DualOptimizer to not add bridges by default
1 parent 685be6c commit 5e0dc7f

1 file changed

Lines changed: 42 additions & 41 deletions

File tree

src/MOI_wrapper.jl

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,23 @@
77
dual_optimizer(
88
optimizer_constructor;
99
coefficient_type::Type{T} = Float64,
10+
with_cache_type::Union{Nothing,Type{T}} = coefficient_type,
11+
with_bridge_type::Union{Nothing,Type{T}} = coefficient_type,
1012
kwargs...,
1113
) where {T<:Number}
1214
1315
A user-friendly constructor for [`DualOptimizer`](@ref) that can be passed
1416
directly to the JuMP `Model` constructor.
1517
18+
By default, the optimizer is wrapped in both a cache and a bridging layer. To
19+
disable the bridge, to `with_bridge_type = nothing`.
20+
1621
## Example
1722
1823
```julia
1924
julia> using Dualization, JuMP, HiGHS
2025
21-
julia> model = Model(dual_optimizer(HiGHS.Optimizer))
26+
julia> model = Model(dual_optimizer(HiGHS.Optimizer; with_bridge_type = false))
2227
A JuMP Model
2328
Feasibility problem with:
2429
Variables: 0
@@ -28,46 +33,45 @@ Solver name: Dual model with HiGHS attached
2833
```
2934
"""
3035
function dual_optimizer(
31-
optimizer_constructor;
36+
optimizer_fn;
3237
coefficient_type::Type{T} = Float64,
38+
with_cache_type::Union{Nothing,Type{T}} = coefficient_type,
39+
with_bridge_type::Union{Nothing,Type{T}} = coefficient_type,
3340
kwargs...,
3441
) where {T<:Number}
35-
return () ->
36-
DualOptimizer{T}(MOI.instantiate(optimizer_constructor); kwargs...)
37-
end
38-
39-
struct DualOptimizer{T,OT<:MOI.ModelLike} <: MOI.AbstractOptimizer
40-
dual_problem::DualProblem{T,OT}
41-
assume_min_if_feasibility::Bool
42-
43-
function DualOptimizer{T,OT}(
44-
dual_problem::DualProblem{T,OT};
45-
assume_min_if_feasibility::Bool = false,
46-
) where {T,OT<:MOI.ModelLike}
47-
return new{T,OT}(dual_problem, assume_min_if_feasibility)
42+
return () -> begin
43+
inner = MOI.instantiate(optimizer_fn; with_cache_type, with_bridge_type)
44+
return DualOptimizer{T}(inner; kwargs...)
4845
end
4946
end
5047

5148
"""
52-
DualOptimizer(dual_optimizer::OT) where {OT <: MOI.ModelLike}
49+
DualOptimizer{T}(dual_optimizer::MOI.ModelLike; kwargs...) where {T}
5350
54-
The DualOptimizer finds the solution for a problem by solving its dual
55-
representation. It builds the dual model internally and solve it using the
56-
`dual_optimizer` as the solver.
51+
Construct a new `DualOptimizer <: MOI.AbstractOptimizer` that finds the solution
52+
for a problem by solving its dual representation. It builds the dual model
53+
internally and solves it using the `dual_optimizer` as the solver.
5754
5855
Primal results are obtained by querying dual results of the internal problem
5956
solved by `dual_optimizer`. Analogously, dual results are obtained by querying
6057
primal results of the internal problem.
6158
62-
The user can define the model providing the `DualOptimizer` and the solver of
63-
its choice.
59+
## Keyword arguments
60+
61+
* `assume_min_if_feasibility::Bool = false`: if `true`, treat
62+
`MOI.FEASIBILITY_SENSE` as `MOI.MIN_SENSE` with a zero objective function.
6463
6564
## Example
6665
6766
```julia
6867
julia> using Dualization, JuMP, HiGHS
6968
70-
julia> model = Model(dual_optimizer(HiGHS.Optimizer))
69+
julia> model = JuMP.Model() do
70+
return Dualization.DualOptimizer(
71+
HiGHS.Optimizer();
72+
assume_min_if_feasibility = true,
73+
)
74+
end
7175
A JuMP Model
7276
Feasibility problem with:
7377
Variables: 0
@@ -76,27 +80,24 @@ CachingOptimizer state: EMPTY_OPTIMIZER
7680
Solver name: Dual model with HiGHS attached
7781
```
7882
"""
79-
function DualOptimizer(dual_optimizer::OT; kwargs...) where {OT<:MOI.ModelLike}
80-
return DualOptimizer{Float64}(dual_optimizer; kwargs...)
83+
struct DualOptimizer{T,OT<:MOI.ModelLike} <: MOI.AbstractOptimizer
84+
dual_problem::DualProblem{T,OT}
85+
assume_min_if_feasibility::Bool
86+
87+
function DualOptimizer{T,OT}(
88+
dual_problem::DualProblem{T,OT};
89+
assume_min_if_feasibility::Bool = false,
90+
) where {T,OT<:MOI.ModelLike}
91+
return new{T,OT}(dual_problem, assume_min_if_feasibility)
92+
end
8193
end
8294

83-
function DualOptimizer{T}(
84-
dual_optimizer::OT;
85-
kwargs...,
86-
) where {T,OT<:MOI.ModelLike}
87-
dual_problem = DualProblem{T}(
88-
MOI.Bridges.full_bridge_optimizer(
89-
MOI.Utilities.CachingOptimizer(
90-
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}()),
91-
dual_optimizer,
92-
),
93-
T,
94-
),
95-
)
96-
# discover the type of
97-
# MOI.Utilities.CachingOptimizer(MOI.Utilities.Model{T}(), dual_optimizer)
98-
OptimizerType = typeof(dual_problem.dual_model)
99-
return DualOptimizer{T,OptimizerType}(dual_problem; kwargs...)
95+
function DualOptimizer{T}(optimizer::OT; kwargs...) where {T,OT<:MOI.ModelLike}
96+
return DualOptimizer{T,OT}(DualProblem{T}(optimizer); kwargs...)
97+
end
98+
99+
function DualOptimizer(optimizer::MOI.ModelLike; kwargs...)
100+
return DualOptimizer{Float64}(optimizer; kwargs...)
100101
end
101102

102103
DualOptimizer() = error("DualOptimizer must have a solver attached")

0 commit comments

Comments
 (0)