Skip to content

Commit 65e7973

Browse files
committed
Add support for comparing DEMs up to instruction ordering
The current `==` overload of the `DetectorErrorModel` only returns true if the DEMs have the same instruction ordering. It is sometimes useful to be able to compare two DEMs for equality when this is not the case, so I implemented an `equal_up_to_instruction_ordering` member function. I opted not to change the `==` operator because (a) checking for equality up to instruction ordering requires sorting so turns an O(n) op into an O(n log n) op; and (b) it's possible some of the backend simulation code depends on the ordering constraint. Signed-off-by: Abbas Bracken Ziad <abbas.ziad25@imperial.ac.uk>
1 parent a6d5c7f commit 65e7973

3 files changed

Lines changed: 53 additions & 0 deletions

File tree

src/stim/dem/detector_error_model.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <cmath>
2020
#include <iomanip>
2121
#include <limits>
22+
#include <numeric>
2223

2324
#include "stim/util_bot/str_util.h"
2425

@@ -793,3 +794,30 @@ DetectorErrorModel DetectorErrorModel::without_tags() const {
793794
}
794795
return result;
795796
}
797+
798+
bool DetectorErrorModel::equal_up_to_instruction_ordering(const DetectorErrorModel &other) const {
799+
if (instructions.size() != other.instructions.size()) {
800+
return false;
801+
}
802+
803+
auto get_sorted_indices = [](const std::vector<DemInstruction> &ins) {
804+
std::vector<size_t> indices(ins.size());
805+
std::iota(indices.begin(), indices.end(), 0);
806+
std::sort(indices.begin(), indices.end(), [&ins](size_t i, size_t j) {
807+
return ins[i] < ins[j];
808+
});
809+
return indices;
810+
};
811+
812+
// sort the indices to avoid copying instructions
813+
auto sorted_lhs_indices = get_sorted_indices(instructions);
814+
auto sorted_rhs_indices = get_sorted_indices(other.instructions);
815+
816+
for (size_t i = 0; i < sorted_lhs_indices.size(); i++) {
817+
if (!(instructions[sorted_lhs_indices[i]] == other.instructions[sorted_rhs_indices[i]])) {
818+
return false;
819+
}
820+
}
821+
822+
return true;
823+
}

src/stim/dem/detector_error_model.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ struct DetectorErrorModel {
135135

136136
/// Returns an equivalent detector error model with no repeat blocks or detector_shift instructions.
137137
DetectorErrorModel flattened() const;
138+
139+
/// Returns true if the detector error model is equal to the other detector error model up to instruction ordering.
140+
///
141+
/// For example, error(0.01) D0 error(0.002) D1 L0 is considered the same as error(0.002) D1 L0 error(0.01) D0.
142+
///
143+
/// Note: requires O(n log n) time due to sorting. Prefer `==` when you know the instructions are in the same order.
144+
bool equal_up_to_instruction_ordering(const DetectorErrorModel &other) const;
138145
};
139146

140147
void print_detector_error_model(std::ostream &out, const DetectorErrorModel &v, size_t indent);

src/stim/dem/detector_error_model.test.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,3 +894,21 @@ TEST(detector_error_model, parse_windows_newlines) {
894894
DetectorErrorModel("error(0.125) D0\r\ndetector(5) D10\r\n"),
895895
DetectorErrorModel("error(0.125) D0\r\ndetector(5) D10\r\n"));
896896
}
897+
898+
TEST(detector_error_model, equal_up_to_instruction_ordering) {
899+
DetectorErrorModel lhs(R"MODEL(
900+
error(0.01) D0
901+
error(0.002) D1 L0
902+
detector(5, 10) D0
903+
detector(5, 15) D1
904+
logical_observable L0
905+
)MODEL");
906+
DetectorErrorModel rhs(R"MODEL(
907+
error(0.002) D1 L0
908+
error(0.01) D0
909+
detector(5, 15) D1
910+
detector(5, 10) D0
911+
logical_observable L0
912+
)MODEL");
913+
EXPECT_TRUE(lhs.equal_up_to_instruction_ordering(rhs));
914+
}

0 commit comments

Comments
 (0)