I would like to know whether there are any recommendations in the workflow for the following situation:

I have defined a MIP model along with a solver-independent lazy callback function, and I would like the callback to at least generate “a bunch” of lazy constraints in the root node, and then “normally” during the tree exploration.

To achieve this, what I am doing right now is:

I define the MIP model.

I add the lazy callback.

I relax the MIP model (with relax_integrality), and I solve it many times (with optimize!) iteratively to manually generate new lazy constraints (added through @constraint).

When I am done, I undo the relaxation and call optimize! one last time.

My two questions are:

Is there any way to perform step 3 “less manually”?

Should I be concerned about internal modifications/reductions to my model (e.g., due to presolve maybe) because of solving the LP relaxation first, that could impact the correcteness of the callbacks in the subsequent tree exploration, once I undo the relaxation?

Is there any way to perform step 3 “less manually”?

Not really. Solvers do not support callbacks for continuous problems.

Should I be concerned about internal modifications/reductions to my model

No. If an incorrect solution is returned then that is a bug in the solver. (But you should verify the final solution satisfies all constraints etc because bugs can happen, even in Gurobi.)

I would like the callback to at least generate “a bunch” of lazy constraints in the root node, and then “normally” during the tree exploration.

Any reason why? I’d just add the lazy constraints during the search process.

I am implementing Benders cuts for an integer master problem with continuous subproblem (i.e., the cut-generator LP). I read that good performance can be achieved if “a first wave of cuts” is added considering the linear relaxation of the master problem (i.e., the root node) before restoring integrality requirements (i.e., tree exploration).

Ah so in the MIP solve you’re still doing Benders decomposition with callbacks, you just want to warm-start the solve with initial set of cuts at fractional first-stage points?

Then yes, that’s a reasonable way to go about the problem.