From 350eb90dd1a99d8fa38999edc5c4bf475c5f8594 Mon Sep 17 00:00:00 2001 From: David L Woodruff Date: Sat, 15 Aug 2026 14:01:20 -0700 Subject: [PATCH] Fix outer/inner bound assignment for maximization in amalgamator The assignment branched on is_minimizing, but both branches assigned the same values; only the order of the two statements differed. For a maximization model the solver's Upper bound is the relaxation (outer) bound and the Lower bound is the incumbent (inner) bound, so the else branch had them backwards. This mirrors the handling already in spopt.py, which branches correctly. Minimization is unaffected. Fixes #836 Co-Authored-By: Claude Opus 5 --- mpisppy/utils/amalgamator.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mpisppy/utils/amalgamator.py b/mpisppy/utils/amalgamator.py index 7fc6f6b74..ebd2aeddc 100644 --- a/mpisppy/utils/amalgamator.py +++ b/mpisppy/utils/amalgamator.py @@ -328,12 +328,14 @@ def run(self): self.is_minimizing = objs[0].is_minimizing #TBD : Write a function doing this + # The solver's Lower and Upper bounds bracket the optimal value, so + # which one is the outer (relaxation) bound depends on the sense. if self.is_minimizing: self.best_outer_bound = results.Problem[0]['Lower bound'] self.best_inner_bound = results.Problem[0]['Upper bound'] else: - self.best_inner_bound = results.Problem[0]['Upper bound'] - self.best_outer_bound = results.Problem[0]['Lower bound'] + self.best_outer_bound = results.Problem[0]['Upper bound'] + self.best_inner_bound = results.Problem[0]['Lower bound'] self.ef = ef if 'write_solution' in self.cfg: