メインコンテンツへスキップ

MIPGAP Graph

回答済み

コメント

3件のコメント

  • Riley Clement
    Gurobi Staff Gurobi Staff

    Hi Mahnoor,

    Usually we'd recommend using gurobi-logtools for plotting this sort of information but the requirement that the graph is updated live means it is probably easier to not use gurobi-logtools.

    The following script works for me, when run from the command line (not a Jupyter notebook):

    import gurobipy as gp
    import matplotlib.pyplot as plt
    from matplotlib.ticker import PercentFormatter


    class GapPlotCallback:

        def __init__(self):
            _, self.ax = plt.subplots()
            self.line, = self.ax.plot([],[])
            self.ax.set_xlabel("Time (seconds)")
            self.ax.set_ylabel("MIP Gap")
            self.ax.set_title("MIP Gap vs Time")
            self.ax.yaxis.set_major_formatter(PercentFormatter(1))
            self.ax.legend()
            self.time = []
            self.gap = []

        def __call__(self, model, where):
            if where == gp.GRB.Callback.MIP:
                runtime = model.cbGet(gp.GRB.Callback.RUNTIME)
                objbst = model.cbGet(gp.GRB.Callback.MIP_OBJBST)
                objbnd = model.cbGet(gp.GRB.Callback.MIP_OBJBND)
                gap = abs(objbst - objbnd) / abs(objbst)
                self.time.append(runtime)
                self.gap.append(gap)
            elif where == gp.GRB.Callback.MESSAGE:
                self.line.set_data(self.time, self.gap)
                self.ax.relim()
                self.ax.autoscale_view()
                plt.draw()
                plt.pause(0.01)


    m = gp.read("/path/to/a/model.mps")

    cb = GapPlotCallback()
    m.optimize(cb)

    You could adapt it for your own purposes.  Note though that it will slow down the optimization - my rough estimate is by 10%.  If you wanted to not impact the run time of the optimization then maybe running a gurobi-logtools approach in a separate thread would be the best approach.

    - Riley

     

    2
  • Mahnoor Naseer
    First Comment
    First Question

    Dear Riley,

    Thank you so much for your prompt response and guidance regarding the issue. 
    Previously I have been logging the data directly to a CSV file, during live optimization and then use a separate code to plot it.
    The code I use for logging is as follows:-

    import os
    import gurobipy as gp
    from gurobipy import GRB
    import csv
    import time

    def mycallback(model, where):
    if where == GRB.Callback.MIP:
    current_time = time.time() - model._start_time
    objbnd = float(model.cbGet(GRB.Callback.MIP_OBJBND))
    objbst = float(model.cbGet(GRB.Callback.MIP_OBJBST))

    writer.writerow([f"{current_time:.6f}", f"{objbst:.6f}", f"{objbnd:.6f}"])
    file.flush()

    if model._bests != objbst or model._bounds != objbnd:
    model._bests = objbst
    model._bounds = objbnd
    model._data.append([current_time, objbst, objbnd])


    csv_file_path = '/path/to/a/model.csv'
    if not os.path.exists(csv_file_path):
    with open(csv_file_path, mode='w', newline='') as file:
    writer = csv.writer(file)
    writer.writerow(['Time (s)', 'Upper Bound (Obj Bst)', 'Lower Bound (Obj Bnd)'])

    lp_file_path = '/path/to/a/model.lp'
    model = gp.read(lp_file_path)

    # Initialize attributes to store data
    model._bounds = None
    model._bests = None
    model._data = []
    model._start_time = time.time()


    with open(csv_file_path, mode='a', newline='') as file:
    writer = csv.writer(file)


    model.optimize(callback=mycallback)

    best_obj = model.objVal
    best_bound = model.objBound

    # Write the final best objective and best bound after optimization
    runtime = model.Runtime
    writer.writerow([f"{runtime:.6f}", f"{best_obj:.6f}", f"{best_bound:.6f}"])

     

    Here, since you mentioned about the direct graphing code slowing down the optimization by 10%, do you think the csv logging method I am already using may also slow it down? 

    Thanks again.

    -Mahnoor

     

     

    0
  • Riley Clement
    Gurobi Staff Gurobi Staff

    Hi Mahnoor,

    Yes you would be seeing a slow down, as the solve is paused while the callback executes.  This callback is going to be called many times, so a small amount of time in the callback can translate to a large time in total.

    At the end of the log file you should see a line like this:

    User-callback calls ..., time in user-callback ... sec

    This will tell you exactly how much time was spent in the callback.  If there is a lot of time being used then I think it would be better to just use gurobi-logtools and not worry about callbacks or calculating the gap yourself.  You can loop through code using gurobi-logtools and updating a graph and it could be run completely separately to the optimization.  You may wish to set DisplayInterval=1 so you get more regular logging.

    - Riley

    0

サインインしてコメントを残してください。