@@ -421,13 +421,17 @@ function MOI.optimize!(model::Optimizer)
421421 while needs_solve
422422 needs_solve = false
423423 MOI. optimize! (model. inner)
424- if MOI. get (model, MOI. PrimalStatus ()) == MOI. FEASIBLE_POINT
424+ if MOI. get (model, MOI. TerminationStatus ()) == MOI. DUAL_INFEASIBLE
425+ # The problem is unbounded, but it might not be if we add more
426+ # constraints.
427+ for v in values (model. lazy)
428+ needs_solve |= _add_if_unbounded (model, v)
429+ end
430+ elseif MOI. get (model, MOI. PrimalStatus ()) == MOI. FEASIBLE_POINT
425431 X = Dict (xi => MOI. get (model, MOI. VariablePrimal (), xi) for xi in x)
426- constraints_added = 0
427432 for v in values (model. lazy)
428- constraints_added += _add_if_necessary (model, v, X)
433+ needs_solve |= _add_if_feasible (model, v, X)
429434 end
430- needs_solve = constraints_added > 0
431435 if start && needs_solve
432436 for (xi, v) in X
433437 MOI. set (model, MOI. VariablePrimalStart (), xi, v)
@@ -438,12 +442,31 @@ function MOI.optimize!(model::Optimizer)
438442 return
439443end
440444
441- function _add_if_necessary (
445+ function _add_if_unbounded (model:: Optimizer , data:: _LazyData )
446+ # Strategy: add 1/3 of the total constraints. This is arbitrary. If a model
447+ # is unbounded with lazy constraints, it's not a great model, and it has a
448+ # high likelihood that it requires _all_ the constraints to be added. I'm
449+ # imagining something like 0 <= x <= Lazy(1) in a knapsack problem.
450+ n = div (length (data. data), 3 , RoundUp)
451+ constraints_added = 0
452+ for (i, (f, s)) in enumerate (data. data)
453+ if constraints_added >= n
454+ break
455+ elseif ! data. active[i]
456+ data. index[i] = MOI. add_constraint (model. inner, f, s)
457+ data. active[i] = true
458+ constraints_added += 1
459+ end
460+ end
461+ return constraints_added > 0
462+ end
463+
464+ function _add_if_feasible (
442465 model:: Optimizer ,
443466 data:: _LazyData ,
444467 x:: Dict{MOI.VariableIndex} ,
445468)
446- constraints_added = 0
469+ needs_solve = false
447470 for (i, (f, s)) in enumerate (data. data)
448471 if data. active[i]
449472 continue
@@ -452,10 +475,10 @@ function _add_if_necessary(
452475 if MOI. Utilities. distance_to_set (y, s) > 0
453476 data. index[i] = MOI. add_constraint (model. inner, f, s)
454477 data. active[i] = true
455- constraints_added += 1
478+ needs_solve = true
456479 end
457480 end
458- return constraints_added
481+ return needs_solve
459482end
460483
461484end # module MathOptLazy
0 commit comments