How to use MIPSOL_SOL in gurobipy callback to write solutions meeting certain criteria
AnsweredHello,
I am trying to write .sol files in an MIPSOL once the solutions meet some criteria. I looked into several posts, like this, that, and this. But none of these helped all that much. Below is a general structure of the code.
class lazy_callback:
def __init__(self, sol_cnt, s, x):
self.sol_cnt = sol_cnt
self.s = s
self.x = x
def __call__(self, model, where):
if where == gp.GRB.Callback.MIPSOL:
try:
self.add_cuts(model)
except Exception:
logging.exception("Exception occurred in MIPSOL callback")
model.terminate()
def add_cuts(self, model):
s_vals = model.cbGetSolution(self.s)
x_vals = model.cbGetSolution(self.x)
sol = gp.GRB.Callback.MIPSOL_SOL
C_lower = model.cbGet(gp.GRB.Callback.MIPSOL_OBJBND)
C_hat = "some_float_value" # Calculating this somehow
solution_gap = 0 if C_hat == 0 else 1 - (C_lower / C_hat)
if solution_gap < 0.8:
# model.write(str(exact_dir / f"solution_count_{self.sol_cnt}.sol"))
write_solutions(self.sol_cnt, s_vals)
self.sol_cnt += 1
for i in I:
if something is True: ## assume something is boolean
model.cbLazy(self.s[i] >= self.x[i])
Before my m.optimize(lazy_callback(sol_cnt, s, x)), I added "m.Params.SolFiles = str(exact_dir / 'solution_count')". It only writes one solution file although the lazy constraints are added several times. I verified this with an external function called write_solutions(self.sol_cnt, s_vals).
Then, I tried "model.write(str(exact_dir / f"solution_count_{self.sol_cnt}.sol"))", but it did not help and threw an error in callback. If there is a better solution, I do not want to create a custom writer.
Another problem is indeed "m.optimize(lazy_callback(sol_cnt, s, x))". In Jupyter Notebook, this throws error: "GurobiError: Callback argument must be a function". Looking into solutions to this, I ended up using something like:
cb = lazy_callback(sol_cnt, s, x)
m.optimize(lambda model, where: cb(model, where))
Is there a more elegant solution to this, and what is wrong with the former implementation?
Thanks,
Taner
-
Hi Taner,
I don't think Model.write can be used in this way to write a solution from within the callback.
Can I suggest casting the solution values to a numpy array and then using numpy.save.
As of Gurobi v11, any callable python object can be used as the callback argument to Model.optimize, so the lambda approach should be unnecessary unless you are using an older version of Gurobi. See tsp.py
- Riley
0
Please sign in to leave a comment.
Comments
1 comment