Skip to content

Commit

Permalink
Fix a bug in CNF -- was missing the constraints for detectors to be i…
Browse files Browse the repository at this point in the history
…nactive
  • Loading branch information
noajshu committed Feb 28, 2024
1 parent d5a67cc commit da17c79
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
4 changes: 2 additions & 2 deletions src/stim/circuit/circuit_pybind_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -837,9 +837,9 @@ def test_shortest_undetectable_logical_error_wcnf():
DETECTOR rec[-1] rec[-2]
""")
wcnf_str = c.shortest_undetectable_logical_error_wcnf()
assert wcnf_str == 'p wcnf 2 3 4\n1 -1 0\n1 -2 0\n4 2 0\n'
assert wcnf_str == 'p wcnf 2 4 5\n1 -1 0\n1 -2 0\n5 -1 0\n5 2 0\n'
wcnf_str = c.shortest_undetectable_logical_error_wcnf(num_distinct_weights=2)
assert wcnf_str == 'p wcnf 2 3 7\n1 -1 0\n2 -2 0\n7 2 0\n'
assert wcnf_str == 'p wcnf 2 4 9\n1 -1 0\n2 -2 0\n9 -1 0\n9 2 0\n'

def test_shortest_graphlike_error_ignore():
c = stim.Circuit("""
Expand Down
9 changes: 9 additions & 0 deletions src/stim/search/sat/wcnf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,15 @@ std::string stim::shortest_undetectable_logical_error_wcnf(const DetectorErrorMo
}
++error_index;
});
assert(error_index == num_errors);

// Add a hard clause for each detector to be inactive
for (size_t d=0; d<num_detectors; ++d) {
Clause clause;
if (detectors_activated[d].variable == BOOL_LITERAL_FALSE) continue;
clause.add_var(~detectors_activated[d]);
instance.add_clause(clause);
}

// Add a hard clause for any observable to be flipped
Clause clause;
Expand Down
26 changes: 16 additions & 10 deletions src/stim/search/sat/wcnf.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,29 @@ TEST(shortest_undetectable_logical_error_wcnf, single_detector_single_observable
// hard clause x != (0, 1, 0)
// hard clause x != (1, 0, 0)
// hard clause x != (1, 1, 1)
// Plus 1 hard clause to ensure detector is not flipped
// hard clause -x_2
// Plus 1 hard clause to ensure an observable is flipped:
// hard clause x_0
// This gives a total of 7 clauses
// The top value should be at least 1 + 1 + 1 = 3. In our implementation ends up being 8.
// This gives a total of 8 clauses
// The top value should be at least 1 + 1 + 1 = 3. In our implementation ends up being 9.
std::stringstream expected;
// WDIMACS header format: p wcnf nbvar nbclauses top
expected << "p wcnf 3 7 8\n";
expected << "p wcnf 3 8 9\n";
// Soft clause
expected << "1 -0\n";
expected << "1 -1 0\n";
// Hard clauses
expected << "8 0 1 -2\n";
expected << "8 0 -1 2\n";
expected << "8 -0 1 2\n";
expected << "8 -0 -1 -2\n";
expected << "9 1 2 -3 0\n";
expected << "9 1 -2 3 0\n";
expected << "9 -1 2 3 0\n";
expected << "9 -1 -2 -3 0\n";
// Soft clause
expected << "1 -1\n";
expected << "1 -2 0\n";
// Hard clause for the detector not to be flipped
expected << "9 -3 0\n";
// Hard clause for the observable flipped
expected << "8 0\n";
expected << "9 1 0\n";
ASSERT_EQ(wcnf, expected.str());
// The optimal value of this wcnf file should be 2, but we don't have
// a maxSAT solver to be able to test it here.
}

0 comments on commit da17c79

Please sign in to comment.