From f790fabdd0fc46095577f462223a4916e76f63c9 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:27:09 +0200 Subject: [PATCH 1/2] Honor forced pairs in Murty subproblems --- src/pyrecest/utils/assignment.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pyrecest/utils/assignment.py b/src/pyrecest/utils/assignment.py index 615cfe332..7aab7bc3e 100644 --- a/src/pyrecest/utils/assignment.py +++ b/src/pyrecest/utils/assignment.py @@ -249,10 +249,17 @@ def _solve_subproblem( # pylint: disable=too-many-locals for row_index, col_index in subproblem.forbidden_pairs: modified_cost_matrix[row_index, col_index] = large_cost + forbidden_pairs = set(subproblem.forbidden_pairs) forced_rows = set() forced_cols = set() for row_index, col_index in subproblem.forced_pairs: - if row_index in forced_rows or col_index in forced_cols: + if ( + row_index in forced_rows + or col_index in forced_cols + or (row_index, col_index) in forbidden_pairs + ): + return None + if bool(augmented_cost_matrix[row_index, col_index] >= large_cost / 2.0): return None forced_rows.add(row_index) forced_cols.add(col_index) From 022c4212ead5d3010340e972c3c0b08f6e53ccb0 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:27:29 +0200 Subject: [PATCH 2/2] Add Murty forced-prefix regression test --- .../test_assignment_murty_forced_prefix.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/utils/test_assignment_murty_forced_prefix.py diff --git a/tests/utils/test_assignment_murty_forced_prefix.py b/tests/utils/test_assignment_murty_forced_prefix.py new file mode 100644 index 000000000..d9e8cea5b --- /dev/null +++ b/tests/utils/test_assignment_murty_forced_prefix.py @@ -0,0 +1,32 @@ +import numpy as np + +from pyrecest.utils.assignment import murty_k_best_assignments + + +def _assignment_tuple(solution): + return tuple(int(index) for index in solution["assignment"]) + + +def test_murty_forced_prefix_subproblems_do_not_repeat_assignments(): + cost_matrix = np.asarray( + [ + [0.0, 100.0], + [1.0, 2.0], + ] + ) + + solutions = murty_k_best_assignments(cost_matrix, k=5) + assignments = [_assignment_tuple(solution) for solution in solutions] + + assert len(assignments) == 5 + assert len(assignments) == len(set(assignments)) + assert set(assignments) == { + (0, -1), + (-1, -1), + (-1, 0), + (0, 1), + (-1, 1), + } + assert [solution["cost"] for solution in solutions] == sorted( + solution["cost"] for solution in solutions + )