From 246ea67428ab2efd135e9933e62199d1c51f844c Mon Sep 17 00:00:00 2001 From: tianhao Date: Fri, 3 Jul 2026 12:48:38 +0800 Subject: [PATCH] Handle nonpositive SWIFT selection errors --- dpsynth/discrete_mechanisms/swift.py | 2 +- tests/discrete_mechanisms/swift_test.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/dpsynth/discrete_mechanisms/swift.py b/dpsynth/discrete_mechanisms/swift.py index e5c1d7f..64f67c4 100644 --- a/dpsynth/discrete_mechanisms/swift.py +++ b/dpsynth/discrete_mechanisms/swift.py @@ -380,7 +380,7 @@ def build_best_clique_tree( if len(cl) == 2 and tuple(sorted(cl)) in supported ) - if score > best_score: + if best_tree is None or score > best_score: best_score = score best_tree = tree assert best_tree is not None diff --git a/tests/discrete_mechanisms/swift_test.py b/tests/discrete_mechanisms/swift_test.py index 62d16bc..040cf27 100644 --- a/tests/discrete_mechanisms/swift_test.py +++ b/tests/discrete_mechanisms/swift_test.py @@ -97,6 +97,19 @@ def test_select_queries(self): self.assertAlmostEqual(selected[('a', 'c')], expected_budget_ac) self.assertAlmostEqual(selected[('b', 'c')], expected_budget_bc) + def test_select_queries_nonpositive_errors(self): + errors = {('a', 'b'): 0.0, ('b', 'c'): -1.0, ('a', 'c'): -2.0} + domain = mbi.Domain(['a', 'b', 'c'], [2, 3, 4]) + candidates = {key: 1.0 for key in errors} + gdp_budget = 100.0 + + selected, jtree = swift.select_queries( + errors, candidates, domain, max_clique_size=100, gdp_budget=gdp_budget + ) + + self.assertNotEmpty(jtree.nodes) + self.assertAlmostEqual(sum(selected.values()), gdp_budget) + def test_best_subset_and_allocation(self): candidates = [ swift_utils.Candidate(id='a', error=1.0, size=1.0, weight=1.0),