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
-
Official comment
This post is more than two years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum, or try Gurobot, our chatbot interface offering instant, expert-level support. -
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
Post is closed for comments.
Comments
2 comments