In some cases, you may be interested in running a heuristic in parallel to the Gurobi optimization and inject a found heuristic solution into Gurobi's solve process. To do so, you need to establish two things:
- Separate processes/threads for the heuristic and for Gurobi
- A queue or shared memory to pass information between the two processes/threads
A Python example of such a process is:
import gurobipy as gp
from gurobipy import GRB
from multiprocessing import Process, Queue
def add_solution(m, where):
if where == GRB.Callback.MIPNODE and not m._new_solution.empty():
m.cbSetSolution(vars, m._new_solution.get())
def run_Gurobi(queue):
m = # Define the model as you would
m._new_solution = queue # Add the queue to the model object
m.optimize(add_solution) # Add the callback
def run_heuristic(queue):
queue.put([<heuristic_solution>])
procs = []
q = Queue()
# Define the Gurobi process
proc = Process(target=run_Gurobi, args=(q,))
procs.append(proc)
proc.start()
# Define the heuristic process
proc = Process(target=run_heuristic, args=(q,))
procs.append(proc)
proc.start()
# Merge the processes
for p in procs:
p.join()
Notes
Here, a queue is used to share data between the processes. Whenever the queue is not empty, the content can be accessed via the Queue.get()
method. For more information, see the Python documentation (note that Queue.Queue
and multiprocessing.Queue
are nearly identical).
Since the cbSetSolution()
method is only available for the MIPNODE
callback, this method is called often. In addition, using Queue
may incur a non-trivial amount of overhead. Gurobi reports how much time is spent in callbacks. If too much time is spent in this callback, more low-level concepts such as shared memory are worth investigating.
Comments
0 comments
Article is closed for comments.