Skip to main content

Gurobi logtools Python package

Answered

Comments

3 comments

  • Riley Clement
    • Gurobi Staff Gurobi Staff

    Hi Nan,

    The good news is gurobi-logtools can read logfiles with multi-objective optimization, the bad news is it may not produce all the information you may want it to.

    For example, our multi-objective python example, multiobj.py, produces the following log:

    Gurobi 12.0.1 (mac64[arm]) logging started Tue May 20 15:59:09 2025
    Set parameter LogFile to value "multiobj.log"
    Gurobi Optimizer version 12.0.1 build v12.0.1rc0 (mac64[arm] - Darwin 24.3.0 24D81)
    CPU model: Apple M4 Pro
    Thread count: 12 physical cores, 12 logical processors, using up to 12 threads
    Non-default parameters:
    PoolSolutions  100
    Optimize a model with 1 rows, 20 columns and 20 nonzeros
    Model fingerprint: 0x82f8d485
    Variable types: 0 continuous, 20 integer (20 binary)
    Coefficient statistics:
     Matrix range     [1e+00, 1e+00]
     Objective range  [1e+00, 1e+00]
     Bounds range     [1e+00, 1e+00]
     RHS range        [1e+01, 1e+01]
    ---------------------------------------------------------------------------
    Multi-objectives: starting optimization with 4 objectives (3 combined)...
    ---------------------------------------------------------------------------
    Multi-objectives: applying initial presolve...
    ---------------------------------------------------------------------------
    Presolve time: 0.00s
    Presolved: 1 rows, 20 columns, 20 nonzeros
    Multi-objectives: optimize objective 1 (Set0) ...
    ---------------------------------------------------------------------------
    Found heuristic solution: objective 10.0000000
    Explored 0 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)
    Thread count was 1 (of 12 available processors)
    Solution count 1: 10
    Optimal solution found (tolerance 1.00e-04)
    Best objective 1.000000000000e+01, best bound 1.000000000000e+01, gap 0.0000%
    ---------------------------------------------------------------------------
    Multi-objectives: optimize objective 2 (weighted) ...
    ---------------------------------------------------------------------------
    
    Loaded user MIP start with objective 6.25
    Presolve removed 2 rows and 20 columns
    Presolve time: 0.00s
    Presolve: All rows and columns removed
    Explored 0 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)
    Thread count was 1 (of 12 available processors)
    Solution count 2: 10.5 6.25
    Optimal solution found (tolerance 1.00e-04)
    Best objective 1.050000000000e+01, best bound 1.050000000000e+01, gap 0.0000%
    ---------------------------------------------------------------------------
    Multi-objectives: optimize objective 3 (Set3) ...
    ---------------------------------------------------------------------------
    
    Loaded user MIP start with objective 6
    Presolve removed 3 rows and 20 columns
    Presolve time: 0.00s
    Presolve: All rows and columns removed
    Explored 0 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)
    Thread count was 1 (of 12 available processors)
    Solution count 2: 7 6
    Optimal solution found (tolerance 1.00e-04)
    Best objective 7.000000000000e+00, best bound 7.000000000000e+00, gap 0.0000%
    ---------------------------------------------------------------------------
    Multi-objectives: solved in 0.00 seconds (0.00 work units), solution count 3

     

    And gurobi-logtools will produce the following pandas.Series corresponding to this log:

    Platform                                                      mac64[arm]
    Time                                                 2025-05-20 15:59:09
    PhysicalCores                                                         12
    LogicalProcessors                                                     12
    Threads                                                                1
    NumConstrs                                                             1
    NumVars                                                               20
    NumNZs                                                                20
    Fingerprint                                                   0x82f8d485
    PresolvedNumConVars                                                    0
    PresolvedNumIntVars                                                   20
    PresolvedNumBinVars                                                   20
    MinCoeff                                                             1.0
    MaxCoeff                                                             1.0
    MinObjCoeff                                                          1.0
    MaxObjCoeff                                                          1.0
    MinBound                                                             1.0
    MaxBound                                                             1.0
    MinRHS                                                              10.0
    MaxRHS                                                              10.0
    PresolveTime                                                         0.0
    PresolvedNumConstrs                                                    1
    PresolvedNumVars                                                      20
    PresolvedNumNZs                                                       20
    PreTreeSolutions                                                       1
    NodeCount                                                              0
    IterCount                                                              0
    Runtime                                                              0.0
    Work                                                                 0.0
    ObjVal                                                               7.0
    ObjBound                                                             7.0
    MIPGap                                                               0.0
    Cores                                                                 12
    SolCount                                                               2
    Status                                                           OPTIMAL
    ModelType                                                            MIP
    ChangedParams                                                         {}
    LogFilePath                                         /path/to/logfile.log
    LogNumber                                                              1
    LogFile (Parameter)                                       "multiobj.log"
    Seed                                                                   0
    Version                                                           12.0.1

     

    - Riley

    0
  • Nan D
    • Gurobi-versary
    • Conversationalist
    • Curious

    Hi Riley 

    Thank you for your reply! So, if I understand you correctly, sadly the Gurobi log tools does not provide a timeline data frame for multi-objective problems?

    Do you have advice for logging data per objective? I tried using a callback but a lot of information is often not available. I would like to track the incumbent value at the end of each second for each objective, and I would like to track information like the running time, final gap, final value of the incumbent, best bound, etc. for each objective. 

    Thank you!

    0
  • Riley Clement
    • Gurobi Staff Gurobi Staff

    Hi Nan,

    You can get summary information for each objective in a hierarchical optimization using callbacks specifically the MULTIOBJ callback.

    We can try and hack a solution to work with gurobi-logtools by tricking gurobi-logtools into thinking it is looking at a new log for each objective:

    # define your model m
    
    def cb(model, where):
        if where == gp.GRB.Callback.MULTIOBJ:
            solution_count = int(model.cbGet(gp.GRB.Callback.MULTIOBJ_SOLCNT))
            best_objective = model.cbGet(gp.GRB.Callback.MULTIOBJ_OBJBST)
            best_bound = model.cbGet(gp.GRB.Callback.MULTIOBJ_OBJBND)
            mipgap = model.cbGet(gp.GRB.Callback.MULTIOBJ_MIPGAP)
            iteration_count = int(model.cbGet(gp.GRB.Callback.MULTIOBJ_ITRCNT))
            node_count = int(model.cbGet(gp.GRB.Callback.MULTIOBJ_NODCNT))
            runtime = model.cbGet(gp.GRB.Callback.MULTIOBJ_RUNTIME)
            work = model.cbGet(gp.GRB.Callback.MULTIOBJ_WORK)
    
            model.message("Logging started Time ...")
            model.message(f"Explored {node_count} nodes ({iteration_count} simplex iterations) in {runtime} seconds ({work} work units)")
            model.message(f"Solution count {solution_count}: {best_objective} ...")
            model.message(f"Best objective {best_objective}, best bound {best_bound}, gap {100*mipgap:.4f}%")
            
    m.optimize(cb)

    Notes:

    • This will only work for v12+
    • The last objective looks to be duplicated, so you may need to clean this up
    • There will still be data missing from the dataframe, but you might be able to workaround this with some data wrangling in pandas.

    - Riley

    0

Please sign in to leave a comment.