Gurobi logtools Python package
AnsweredHi!
I just came across the open-source package “gurobi-logtools” that was made by the Gurobi support team. It seems like it’s the exact thing I am looking for. However, in the tech talk a question is asked whether the timelines functionality also works for multi-objective problems. The speaker is not sure, and says he has to check this.
Do you know whether it works for timelines for multi-objective (MIP) problems? I cannot find any information about this on the open-source GitHub of the package.
Thank you!
-
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 -
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 -
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.
Comments
3 comments