Andersen implemented#1
Conversation
| self.best_assignment = tuple(tuple(row) for row in assignment) | ||
|
|
||
|
|
||
| def solve_branch_and_adjust( |
There was a problem hiding this comment.
The function name solve_branch_and_adjust is a bit misleading after removing the Gurobi implementation. The current code performs a static Piecewise Linear Approximation before starting the solver, rather than a dynamic B&A algorithm (we are not generating cuts/tangents on the fly during the tree search).
Consider renaming it to something like solve_piecewise_linear_scip or updating the docstring to better reflect what is actually happening here.
|
|
||
| min_y_j = sum(val for val in ln_q if val < 0) | ||
|
|
||
| if min_y_j < 0: |
There was a problem hiding this comment.
Great work with manually building these tangent supports! Moving to the open-source SCIP is a fantastic step.
I do have a small note though: the method applied here is a lower bound approximation for a convex function (the tangents lie "under" the
| ) | ||
|
|
||
|
|
||
| class TrueObjectiveTracker(Eventhdlr): |
There was a problem hiding this comment.
Very clever workaround for the approximation error! Using SCIP's Eventhdlr to listen for BESTSOLFOUND and calculating the actual (nonlinear) objective value on the side is a great and architecturally "clean" idea. Well written!
|
|
||
| model = Model("WTA_Branch_and_Adjust_SCIP") | ||
| model.hideOutput(True) | ||
| model.setRealParam("limits/time", time_limit_seconds) |
There was a problem hiding this comment.
I see we are setting a time limit here: model.setRealParam("limits/time", time_limit_seconds). Shouldn't we also explicitly set the multithreading parameter (e.g., parallel/maxnthreads), as is usually done in benchmarks, to ensure reproducible results between Gurobi and SCIP?
I implemented method based on Andersen Paper, and then I runned: uv run python benchmark.py --mode all --exact-limit-seconds 300.0
results I'll send via messenger