@@ -75,32 +75,44 @@ struct _LazyData{F<:MOI.AbstractScalarFunction,S<:MOI.AbstractScalarSet}
7575 end
7676end
7777
78- Base. length (x:: _LazyData ) = length (x. data)
79-
80- Base. isempty (x:: _LazyData ) = isempty (x. data)
81-
8278# ## Optimizer
8379
8480"""
85- Optimizer(inner_fn; kwargs...)
81+ Optimizer(inner_fn; kwargs...) <: MOI.AbstractOptimizer
82+
83+ Construct a new optimizer that wraps the result of
84+ `MOI.instantiate(inner_fn; kwargs...)`.
85+
86+ ## Example
87+
88+ ```julia
89+ julia> import MathOptLazy
90+
91+ julia> import HiGHS
92+
93+ julia> model = MathOptLazy.Optimizer(HiGHS.Optimizer)
94+ MathOptLazy.Optimizer{Float64, HiGHS.Optimizer}
95+ ├ ObjectiveSense: FEASIBILITY_SENSE
96+ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64}
97+ ├ NumberOfVariables: 0
98+ └ NumberOfConstraints: 0
99+
100+ julia> model = MathOptLazy.Optimizer(HiGHS.Optimizer; with_bridge_type = Float64)
101+ MathOptLazy.Optimizer{Float64, MOIB.LazyBridgeOptimizer{HiGHS.Optimizer}}
102+ ├ ObjectiveSense: FEASIBILITY_SENSE
103+ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64}
104+ ├ NumberOfVariables: 0
105+ └ NumberOfConstraints: 0
106+ ```
86107"""
87- struct Optimizer{T, OT} <: MOI.AbstractOptimizer
108+ struct Optimizer{OT} <: MOI.AbstractOptimizer
88109 inner:: OT
89110
90- saf_gt:: _LazyData{MOI.ScalarAffineFunction{T},MOI.GreaterThan{T}}
91- saf_lt:: _LazyData{MOI.ScalarAffineFunction{T},MOI.LessThan{T}}
111+ lazy:: Dict{Tuple{Type,Type},_LazyData}
92112
93- function Optimizer (
94- inner_fn;
95- coefficient_type:: Type{T} = Float64,
96- kwargs... ,
97- ) where {T}
113+ function Optimizer (inner_fn; kwargs... )
98114 inner = MOI. instantiate (inner_fn; kwargs... )
99- return new {T,typeof(inner)} (
100- inner,
101- _LazyData {MOI.ScalarAffineFunction{T},MOI.GreaterThan{T}} (),
102- _LazyData {MOI.ScalarAffineFunction{T},MOI.LessThan{T}} (),
103- )
115+ return new {typeof(inner)} (inner, Dict {Tuple{Type,Type},_LazyData} ())
104116 end
105117end
106118
@@ -141,7 +153,7 @@ function MOI.get(model::Optimizer, attr::_ATTRIBUTES, args...)
141153 return MOI. get (model. inner, attr, args... )
142154end
143155
144- function MOI. get (model:: Optimizer , attr:: _ATTRIBUTES , arg:: Vector{T} ) where {T}
156+ function MOI. get (model:: Optimizer , attr:: _ATTRIBUTES , arg:: Vector )
145157 return MOI. get .(model, attr, arg)
146158end
147159
@@ -248,54 +260,48 @@ MOI.compute_conflict!(model::Optimizer) = MOI.compute_conflict!(model.inner)
248260
249261# ## LazyConstraints
250262
251- _data (:: Optimizer , :: Type{F} , :: Type{S} ) where {F,S} = nothing
252-
253- function _data (
254- model:: Optimizer{T} ,
255- :: Type{MOI.ScalarAffineFunction{T}} ,
256- :: Type{MOI.GreaterThan{T}} ,
257- ) where {T}
258- return model. saf_gt
263+ function _maybe_data (
264+ model:: Optimizer ,
265+ :: Type{F} ,
266+ :: Type{S} ,
267+ ):: Union{Nothing,_LazyData{F,S}} where {F,S}
268+ return get (model. lazy, (F, S), nothing )
259269end
260270
261- function _data (
262- model:: Optimizer{T} ,
263- :: Type{MOI.ScalarAffineFunction{T}} ,
264- :: Type{MOI.LessThan{T}} ,
265- ) where {T}
266- return model. saf_lt
271+ function _data (model:: Optimizer , :: Type{F} , :: Type{S} ) where {F,S}
272+ return get! (_LazyData{F,S}, model. lazy, (F, S))
267273end
268274
269275function MOI. supports_constraint (
270276 model:: Optimizer ,
271277 :: Type{F} ,
272278 :: Type{LazyScalarSet{S}} ,
273279) where {F<: MOI.AbstractScalarFunction ,S<: MOI.AbstractScalarSet }
274- return _data (model, F, S) != = nothing &&
275- MOI. supports_constraint (model, F, S)
280+ return MOI. supports_constraint (model, F, S)
276281end
277282
278283function MOI. is_valid (
279284 model:: Optimizer ,
280285 ci:: MOI.ConstraintIndex{F,LazyScalarSet{S}} ,
281286) where {F,S}
282- data = _data (model, F, S)
283- return data != = nothing && 1 <= ci. value <= length (data)
287+ ret = _maybe_data (model, F, S)
288+ return ret != = nothing && 1 <= ci. value <= length (ret . data)
284289end
285290
286291function MOI. get (
287292 model:: Optimizer ,
288293 :: MOI.ListOfConstraintIndices{F,LazyScalarSet{S}} ,
289294) where {F<: MOI.AbstractScalarFunction ,S<: MOI.AbstractScalarSet }
290- n = length ( _data ( model, F, S ))
295+ n = MOI . get ( model, MOI . NumberOfConstraints {F,LazyScalarSet{S}} ( ))
291296 return [MOI. ConstraintIndex {F,LazyScalarSet{S}} (i) for i in 1 : n]
292297end
293298
294299function MOI. get (
295300 model:: Optimizer ,
296301 :: MOI.NumberOfConstraints{F,LazyScalarSet{S}} ,
297302) where {F<: MOI.AbstractScalarFunction ,S<: MOI.AbstractScalarSet }
298- return length (_data (model, F, S))
303+ ret = _maybe_data (model, F, S)
304+ return ret === nothing ? 0 : length (ret. data)
299305end
300306
301307function MOI. add_constraint (
@@ -307,7 +313,7 @@ function MOI.add_constraint(
307313 push! (data. data, (f, s. set))
308314 push! (data. active, false )
309315 push! (data. index, MOI. ConstraintIndex {F,S} (0 ))
310- return MOI. ConstraintIndex {F,LazyScalarSet{S}} (length (data))
316+ return MOI. ConstraintIndex {F,LazyScalarSet{S}} (length (data. data ))
311317end
312318
313319function MOI. get (
@@ -334,22 +340,10 @@ function MOI.get(
334340 return LazyScalarSet (_data (model, F, S). data[ci. value][2 ])
335341end
336342
337- function MOI. get (
338- model:: Optimizer{T} ,
339- :: MOI.ListOfConstraintTypesPresent ,
340- ) where {T}
343+ function MOI. get (model:: Optimizer , :: MOI.ListOfConstraintTypesPresent )
341344 ret = MOI. get (model. inner, MOI. ListOfConstraintTypesPresent ())
342- if ! isempty (model. saf_gt)
343- push! (
344- ret,
345- (MOI. ScalarAffineFunction{T}, LazyScalarSet{MOI. GreaterThan{T}}),
346- )
347- end
348- if ! isempty (model. saf_lt)
349- push! (
350- ret,
351- (MOI. ScalarAffineFunction{T}, LazyScalarSet{MOI. LessThan{T}}),
352- )
345+ for (F, S) in keys (model. lazy)
346+ push! (ret, (F, LazyScalarSet{S}))
353347 end
354348 return ret
355349end
@@ -359,8 +353,8 @@ function MOI.get(
359353 attr:: MOI.NumberOfConstraints{F,S} ,
360354) where {F<: MOI.AbstractScalarFunction ,S<: MOI.AbstractScalarSet }
361355 n = MOI. get (model. inner, attr)
362- if (data = _data (model, F, S)) != = nothing
363- n -= sum (data. active)
356+ if (data = _maybe_data (model, F, S)) != = nothing
357+ n -= sum (( data) . active)
364358 end
365359 return n
366360end
@@ -406,31 +400,29 @@ end
406400
407401# ## MOI.optimize!
408402
409- function MOI. optimize! (model:: Optimizer{T} ) where {T}
403+ function MOI. optimize! (model:: Optimizer )
410404 needs_solve = true
411405 x = MOI. get (model, MOI. ListOfVariableIndices ())
412- X = Dict {MOI.VariableIndex,T} (xi => zero (T) for xi in x)
413406 while needs_solve
414407 needs_solve = false
415408 MOI. optimize! (model. inner)
416409 if MOI. get (model, MOI. PrimalStatus ()) == MOI. FEASIBLE_POINT
417- for xi in x
418- X[xi] = MOI. get (model, MOI. VariablePrimal (), xi)
410+ X = Dict (xi => MOI. get (model, MOI. VariablePrimal (), xi) for xi in x)
411+ constraints_added = 0
412+ for v in values (model. lazy)
413+ constraints_added += _add_if_necessary (model, v, X)
419414 end
420- constraints_added =
421- _add_if_necessary (model, model. saf_gt, X) +
422- _add_if_necessary (model, model. saf_lt, X)
423415 needs_solve = constraints_added > 0
424416 end
425417 end
426418 return
427419end
428420
429421function _add_if_necessary (
430- model:: Optimizer{T} ,
422+ model:: Optimizer ,
431423 data:: _LazyData ,
432- x:: Dict{MOI.VariableIndex,T } ,
433- ) where {T}
424+ x:: Dict{MOI.VariableIndex} ,
425+ )
434426 constraints_added = 0
435427 for (i, (f, s)) in enumerate (data. data)
436428 if data. active[i]
0 commit comments