@@ -16,6 +16,8 @@ mutable struct _CacheModel
1616 constraint_upper:: Vector{Float64}
1717 objective:: Expr
1818 sense:: MOI.OptimizationSense
19+ complements_map:: Dict{Int,Int}
20+
1921 function _CacheModel ()
2022 return new (
2123 false ,
@@ -29,6 +31,7 @@ mutable struct _CacheModel
2931 Float64[],
3032 :(),
3133 MOI. FEASIBILITY_SENSE,
34+ Dict {Int,Int} (),
3235 )
3336 end
3437end
@@ -208,6 +211,7 @@ function _to_model(data::_CacheModel; use_nlp_block::Bool)
208211 MOI. set (model, MOI. ObjectiveSense (), data. sense)
209212 end
210213 if use_nlp_block
214+ @assert isempty (data. complements_map)
211215 nlp = MOI. Nonlinear. Model ()
212216 if data. objective != :()
213217 MOI. Nonlinear. set_objective (nlp, data. objective)
@@ -234,6 +238,16 @@ function _to_model(data::_CacheModel; use_nlp_block::Bool)
234238 MOI. set (model, MOI. ObjectiveFunction {typeof(obj)} (), obj)
235239 end
236240 for (i, expr) in enumerate (data. constraints)
241+ if haskey (data. complements_map, i)
242+ g = MOI. Utilities. operate (
243+ vcat,
244+ Float64,
245+ _expr_to_function (expr),
246+ x[data. complements_map[i]],
247+ )
248+ MOI. add_constraint (model, g, MOI. Complements (2 ))
249+ continue
250+ end
237251 lb, ub = data. constraint_lower[i], data. constraint_upper[i]
238252 f = _expr_to_function (expr)
239253 if lb == ub
@@ -551,11 +565,15 @@ function _parse_section(io::IO, ::Val{'r'}, model::_CacheModel)
551565 model. constraint_lower[i] = _next (Float64, io, model)
552566 elseif type == Cchar (' 3' )
553567 # Free constraint
554- else
555- @assert type == Cchar (' 4' )
568+ elseif type == Cchar (' 4' )
556569 value = _next (Float64, io, model)
557570 model. constraint_lower[i] = value
558571 model. constraint_upper[i] = value
572+ else
573+ @assert type == Cchar (' 5' )
574+ _ = _next (Int, io, model) # k
575+ j = _next (Int, io, model) # variable i-1
576+ push! (model. complements_map, i => j)
559577 end
560578 _read_til_newline (io, model)
561579 end
0 commit comments