diff --git a/src/stim/search/graphlike/algo.cc b/src/stim/search/graphlike/algo.cc index 96a5e234d..3e71102ad 100644 --- a/src/stim/search/graphlike/algo.cc +++ b/src/stim/search/graphlike/algo.cc @@ -15,7 +15,7 @@ #include "stim/search/graphlike/algo.h" #include -#include +#include #include #include @@ -27,7 +27,7 @@ using namespace stim; using namespace stim::impl_search_graphlike; -DetectorErrorModel backtrack_path(const std::map &back_map, const SearchState &final_state) { +DetectorErrorModel backtrack_path(const std::unordered_map &back_map, const SearchState &final_state) { DetectorErrorModel out; auto cur_state = final_state; while (true) { @@ -55,7 +55,7 @@ DetectorErrorModel stim::shortest_graphlike_undetectable_logical_error( } std::queue queue; - std::map back_map; + std::unordered_map back_map; // Mark the vacuous dead-end state as already seen. back_map.emplace(empty_search_state, empty_search_state); diff --git a/src/stim/search/graphlike/algo.perf.cc b/src/stim/search/graphlike/algo.perf.cc index dd297f91a..81f3234f9 100644 --- a/src/stim/search/graphlike/algo.perf.cc +++ b/src/stim/search/graphlike/algo.perf.cc @@ -36,3 +36,21 @@ BENCHMARK(find_graphlike_logical_error_surface_code_d25) { std::cout << "bad"; } } + +BENCHMARK(find_graphlike_logical_error_surface_code_d11_r1000) { + CircuitGenParameters params(1000, 11, "rotated_memory_x"); + params.after_clifford_depolarization = 0.001; + params.before_measure_flip_probability = 0.001; + params.after_reset_flip_probability = 0.001; + params.before_round_data_depolarization = 0.001; + auto circuit = generate_surface_code_circuit(params).circuit; + auto model = ErrorAnalyzer::circuit_to_detector_error_model(circuit, true, true, false, 0.0, false, true); + + size_t total = 0; + benchmark_go([&]() { + total += stim::shortest_graphlike_undetectable_logical_error(model, false).instructions.size(); + }).goal_millis(100); + if (total % 11 != 0 || total == 0) { + std::cout << "bad"; + } +} diff --git a/src/stim/search/graphlike/search_state.h b/src/stim/search/graphlike/search_state.h index 0e99343d3..d36820ad8 100644 --- a/src/stim/search/graphlike/search_state.h +++ b/src/stim/search/graphlike/search_state.h @@ -42,6 +42,22 @@ struct SearchState { }; std::ostream &operator<<(std::ostream &out, const SearchState &v); +inline void hash_combine(size_t &h, uint64_t x) { + h ^= std::hash{}(x) + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2); // mimic Boost's hash-combine function +} + +struct SearchStateHash { + size_t operator()(const SearchState &s) const { + SearchState c = s.canonical(); + size_t h = std::hash{}(c.det_active); + hash_combine(h, c.det_held); + for (size_t i = 0; i < c.obs_mask.num_u64_padded(); i++) { + hash_combine(h, c.obs_mask.u64[i]); + } + return h; + } +}; + } // namespace impl_search_graphlike } // namespace stim diff --git a/src/stim/search/graphlike/search_state.test.cc b/src/stim/search/graphlike/search_state.test.cc index c150e8bff..ec2dc1ded 100644 --- a/src/stim/search/graphlike/search_state.test.cc +++ b/src/stim/search/graphlike/search_state.test.cc @@ -148,3 +148,11 @@ TEST(search_graphlike, DemAdjGraphSearchState_canonical_ordering) { TEST(search_graphlike, DemAdjGraphSearchState_str) { ASSERT_EQ(SearchState(1, 2, obs_mask(3)).str(), "D1 D2 L0 L1 "); } + +TEST(search_graphlike, SearchStateHash_operator) { + ASSERT_EQ(SearchStateHash{}(SearchState(1, 2, obs_mask(3))), SearchStateHash{}(SearchState(2, 1, obs_mask(3)))); + ASSERT_EQ(SearchStateHash{}(SearchState(1, 2, obs_mask(3))), SearchStateHash{}(SearchState(1, 2, obs_mask(3)))); + + ASSERT_NE(SearchStateHash{}(SearchState(1, 2, obs_mask(3))), SearchStateHash{}(SearchState(2, 2, obs_mask(3)))); + ASSERT_NE(SearchStateHash{}(SearchState(1, 2, obs_mask(3))), SearchStateHash{}(SearchState(1, 2, obs_mask(4)))); +}