Skip to content

Commit 962ae90

Browse files
authored
Improve type stability of src/iis.jl (#30)
1 parent 5c5b4ce commit 962ae90

File tree

1 file changed

+33
-63
lines changed

1 file changed

+33
-63
lines changed

src/iis.jl

Lines changed: 33 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ struct InfeasibleModel end
7171

7272
function MOI.set(optimizer::Optimizer, ::InfeasibleModel, model::MOI.ModelLike)
7373
optimizer.original_model = model
74-
# this also resets the results
75-
optimizer.results = InfeasibilityData[]
74+
empty!(optimizer.results)
7675
optimizer.status = MOI.COMPUTE_CONFLICT_NOT_CALLED
7776
return
7877
end
@@ -196,13 +195,9 @@ function MOI.get(optimizer::Optimizer, ::ElasticFilterIgnoreIntegrality)
196195
return optimizer.ignore_integrality
197196
end
198197

199-
function MOI.get(optimizer::Optimizer, ::MOI.ConflictStatus)
200-
return optimizer.status
201-
end
198+
MOI.get(optimizer::Optimizer, ::MOI.ConflictStatus) = optimizer.status
202199

203-
function MOI.get(optimizer::Optimizer, ::MOI.ConflictCount)
204-
return length(optimizer.results)
205-
end
200+
MOI.get(optimizer::Optimizer, ::MOI.ConflictCount) = length(optimizer.results)
206201

207202
function MOI.get(
208203
optimizer::Optimizer,
@@ -239,21 +234,17 @@ end
239234

240235
function MOI.compute_conflict!(optimizer::Optimizer)
241236
optimizer.status = MOI.NO_CONFLICT_FOUND
242-
optimizer.results = InfeasibilityData[]
237+
empty!(optimizer.results)
243238
optimizer.start_time = time()
244-
245239
if optimizer.verbose
246240
println("Starting MathOptIIS IIS search.")
247241
end
248-
249242
T = Float64
250-
251-
is_feasible = _feasibility_check(optimizer)
243+
is_feasible = _feasibility_check(optimizer, optimizer.original_model)
252244
if is_feasible && !optimizer.skip_feasibility_check
253245
optimizer.status = MOI.NO_CONFLICT_EXISTS
254246
return optimizer.results
255247
end
256-
257248
if optimizer.verbose
258249
println("Starting bound analysis.")
259250
end
@@ -265,17 +256,15 @@ function MOI.compute_conflict!(optimizer::Optimizer)
265256
"Complete bound analysis found $bound_infeasibilities infeasibilities.",
266257
)
267258
end
268-
if length(optimizer.results) > 0
259+
if !isempty(optimizer.results)
269260
optimizer.status = MOI.CONFLICT_FOUND
270261
end
271-
272262
# check PSD diagonal >= 0 ?
273263
# other cones?
274264
if (!bounds_consistent && optimizer.stop_if_infeasible_bounds) ||
275265
!_in_time(optimizer)
276266
return
277267
end
278-
279268
# second layer of infeasibility analysis is constraint range analysis
280269
if optimizer.verbose
281270
println("Starting range analysis.")
@@ -288,16 +277,13 @@ function MOI.compute_conflict!(optimizer::Optimizer)
288277
"Complete range analysis found $range_infeasibilities infeasibilities.",
289278
)
290279
end
291-
if length(optimizer.results) > 0
280+
if !isempty(optimizer.results)
292281
optimizer.status = MOI.CONFLICT_FOUND
293282
end
294-
295283
if (!range_consistent && optimizer.stop_if_infeasible_ranges) ||
296284
!_in_time(optimizer)
297285
return
298286
end
299-
300-
# check if there is a optimizer
301287
# third layer is an IIS resolver
302288
if optimizer.optimizer === nothing
303289
println(
@@ -311,20 +297,16 @@ function MOI.compute_conflict!(optimizer::Optimizer)
311297
iis = _elastic_filter(optimizer)
312298
# for now, only one iis is computed
313299
if iis !== nothing
314-
maybe_constraints = _get_variables_in_constraints(optimizer, iis)
300+
maybe_constraints =
301+
_get_variables_in_constraints(optimizer.original_model, iis)
315302
push!(
316303
optimizer.results,
317-
InfeasibilityData(
318-
iis,
319-
true,
320-
NoData();
321-
maybe_constraints = maybe_constraints,
322-
),
304+
InfeasibilityData(iis, true, NoData(); maybe_constraints),
323305
)
324306
optimizer.status = MOI.CONFLICT_FOUND
325307
end
326-
iis_infeasibilities = ifelse(iis === nothing, 0, 1)
327308
if optimizer.verbose
309+
iis_infeasibilities = iis === nothing ? 0 : 1
328310
println(
329311
"Complete elastic filter solver found $iis_infeasibilities infeasibilities.",
330312
)
@@ -334,69 +316,57 @@ function MOI.compute_conflict!(optimizer::Optimizer)
334316
end
335317

336318
function _get_variables_in_constraints(
337-
optimizer::Optimizer,
319+
model::MOI.ModelLike,
338320
con::Vector{MOI.ConstraintIndex},
339321
)
340322
variables = Set{MOI.VariableIndex}()
341323
for c in con
342-
_get_variables_in_constraints!(optimizer, c, variables)
324+
_get_variables_in_constraints!(model, c, variables)
343325
end
344-
con_types =
345-
MOI.get(optimizer.original_model, MOI.ListOfConstraintTypesPresent())
346326
variable_constraints = MOI.ConstraintIndex[]
347-
for (F, S) in con_types
348-
if F <: MOI.VariableIndex
349-
_variable_constraints = MOI.get(
350-
optimizer.original_model,
351-
MOI.ListOfConstraintIndices{F,S}(),
352-
)
353-
for con in _variable_constraints
354-
var = MOI.get(
355-
optimizer.original_model,
356-
MOI.ConstraintFunction(),
357-
con,
358-
)
359-
if var in variables
360-
push!(variable_constraints, con)
361-
end
327+
for (F, S) in MOI.get(model, MOI.ListOfConstraintTypesPresent())
328+
if !(F <: MOI.VariableIndex)
329+
continue
330+
end
331+
for con in MOI.get(model, MOI.ListOfConstraintIndices{F,S}())
332+
if MOI.get(model, MOI.ConstraintFunction(), con) in variables
333+
push!(variable_constraints, con)
362334
end
363335
end
364336
end
365337
return variable_constraints
366338
end
367339

368340
function _get_variables_in_constraints!(
369-
optimizer::Optimizer,
370-
con::MOI.ConstraintIndex{F},
341+
model::MOI.ModelLike,
342+
con::MOI.ConstraintIndex{<:MOI.ScalarAffineFunction},
371343
variables::Set{MOI.VariableIndex},
372-
) where {F<:MOI.ScalarAffineFunction}
373-
func = MOI.get(optimizer.original_model, MOI.ConstraintFunction(), con)
374-
for term in func.terms
344+
)
345+
f = MOI.get(model, MOI.ConstraintFunction(), con)
346+
for term in f.terms
375347
push!(variables, term.variable)
376348
end
377349
return
378350
end
379351

380352
function _get_variables_in_constraints!(
381-
optimizer::Optimizer,
382-
con::MOI.ConstraintIndex{F},
383-
variables::Set{MOI.VariableIndex},
384-
) where {F}
385-
# skip
386-
return
353+
::MOI.ModelLike,
354+
::MOI.ConstraintIndex,
355+
::Set{MOI.VariableIndex},
356+
)
357+
return # skip
387358
end
388359

389-
function _feasibility_check(optimizer::Optimizer)
390-
termination_status =
391-
MOI.get(optimizer.original_model, MOI.TerminationStatus())
360+
function _feasibility_check(optimizer::Optimizer, original_model::MOI.ModelLike)
361+
termination_status = MOI.get(original_model, MOI.TerminationStatus())
392362
if optimizer.verbose
393363
println("Original model termination status: $(termination_status)")
394364
end
395365
if termination_status in
396366
(MOI.OTHER_ERROR, MOI.INVALID_MODEL, MOI.OPTIMIZE_NOT_CALLED)
397367
return false # because we can assert it is feasible
398368
end
399-
primal_status = MOI.get(optimizer.original_model, MOI.PrimalStatus())
369+
primal_status = MOI.get(original_model, MOI.PrimalStatus())
400370
if optimizer.verbose
401371
println("Original model primal status: $(primal_status)")
402372
end

0 commit comments

Comments
 (0)