Native Lazy Attribute for linear constraints
Would it be possible to expose a generic MOI attribute to expose the solver attribute setting to add constraints lazily without being a callback. Gurobi has the GRB_INT_LAZY and Xpress has the XPRSloaddelayedrows that support lazy constraints natively.
The interfaces aren't the same for the solvers but it would be possible to use MOI to have a generic interface for solvers that support it.
@jd-lara and I discussed this over the phone. Here's a summary:
The attribute
The way to set this with Gurobi is via Gurobi.ConstraintAttribute: https://github.com/jump-dev/Gurobi.jl?tab=readme-ov-file#accessing-gurobi-specific-attributes
Making this attribute generic in MOI is difficult because it's pretty specific to Gurobi.
Delayed rows
We could conceivably have an API like MOI.add_delayed_constraint which was either the usual add_constraint+ConstraintAttribute in Gurobi, or the XPRSloaddelayedrows in Xpress. Other solvers like CPLEX may have something similar.
Open-source solvers like HiGHS don't have this.
Callback
Our current recommended way to implement this would be via a lazy constraint callback: https://jump.dev/JuMP.jl/stable/manual/callbacks/#Lazy-constraints
The downside to this is that you need to significantly refactor your model building code.
MathOptDelayedRows.Optimizer
We could also consider building some sort of MOI layer that delayed adding rows to the inner optimiser, and did a solve-add-solve loop. This would let us fake solvers that didn't natively support lazy constraints.
The massive downside to this is that the solve loop would not restart from an existing branch-and-bound tree, so it's not likely to be peformant.
As an aside: I've wanted this in the LP space for a long time to help me manage cut pools in SDDP.jl; we currently just use a heuristic to decide which cuts to keep and add between resolves.
Summary
There's clearly a need for something like this, but it isn't standardised well enough across multiple solvers to have something generic in MOI.
Step 1 is for @jd-lara to prove that Gurobi are actually doing something clever under the hood with their lazy constraints and that the reported benefits can be replicated in a benchmark. He's going to work on this as a next step.
Hey @jd-lara ! just stumbled upon this while looking for something to contribute.
Other solvers like CPLEX may have something similar.
@odow Cplex does indeed have a cpxxaddlazyconstraints method and it was useful back in early 2010s when I used it last (wow time flies by!). But I suspect it is still useful since its usefulness is application dependent -- as it reduces the LP size while incurring a small verification step for each integer solution candidate and then then the integer solution needs to fixed if it violates a constraint.
If JD's verification is positive, I would be happy to help -- realistically, MathOptDelayedRows.Optimizer is more than I can chew at the moment but I think I can implement a MOI.add_delayed_constraint interface.
Perhaps I should clarify: even if this is a performance win, I'm not convinced we should do anything about it. MOI.add_delayed_constraint is going to make the MOI API much more complicated.