Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
BasedOnStyle: Google
IndentWidth: 2
ColumnLimit: 80
ColumnLimit: 100
AllowShortFunctionsOnASingleLine: Empty
PointerAlignment: Left
Standard: C++20
SortIncludes: true
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,21 @@ jobs:
disk-cache: ${{ github.workflow }}
repository-cache: true

- name: Install clang-format (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y clang-format

- name: Install clang-format (macOS)
if: runner.os == 'macOS'
run: |
brew install clang-format

- name: Check formatting
run: |
clang-format --version
files=$(git ls-files '*.cc' '*.h' '*.cpp' '*.hpp')
[ -z "$files" ] || clang-format --dry-run --Werror $files
- name: Bazel tests
run: bazel test src:all
42 changes: 16 additions & 26 deletions src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,10 @@ common::Error::Error(const stim::DemInstruction& error) {
}

std::string common::Error::str() {
return "Error{cost=" + std::to_string(likelihood_cost) +
", symptom=" + symptom.str() + "}";
return "Error{cost=" + std::to_string(likelihood_cost) + ", symptom=" + symptom.str() + "}";
}

std::vector<stim::DemTarget> common::Symptom::as_dem_instruction_targets()
const {
std::vector<stim::DemTarget> common::Symptom::as_dem_instruction_targets() const {
std::vector<stim::DemTarget> targets;
for (int d : detectors) {
targets.push_back(stim::DemTarget::relative_detector_id(d));
Expand All @@ -72,8 +70,7 @@ std::vector<stim::DemTarget> common::Symptom::as_dem_instruction_targets()
return targets;
}

stim::DetectorErrorModel common::merge_identical_errors(
const stim::DetectorErrorModel& dem) {
stim::DetectorErrorModel common::merge_identical_errors(const stim::DetectorErrorModel& dem) {
stim::DetectorErrorModel out_dem;

// Map to track the distinct symptoms
Expand All @@ -89,11 +86,9 @@ stim::DetectorErrorModel common::merge_identical_errors(
// Merge with existing error with the same symptom (if applicable)
if (errors_by_symptom.find(error.symptom) != errors_by_symptom.end()) {
double p0 = errors_by_symptom[error.symptom].probability;
error.probability =
p0 * (1 - error.probability) + (1 - p0) * error.probability;
error.probability = p0 * (1 - error.probability) + (1 - p0) * error.probability;
}
error.likelihood_cost =
-1 * std::log(error.probability / (1 - error.probability));
error.likelihood_cost = -1 * std::log(error.probability / (1 - error.probability));
errors_by_symptom[error.symptom] = error;
break;
}
Expand All @@ -106,9 +101,9 @@ stim::DetectorErrorModel common::merge_identical_errors(
}
}
for (const auto& it : errors_by_symptom) {
out_dem.append_error_instruction(
it.second.probability, it.second.symptom.as_dem_instruction_targets(),
/*tag=*/"");
out_dem.append_error_instruction(it.second.probability,
it.second.symptom.as_dem_instruction_targets(),
/*tag=*/"");
}
return out_dem;
}
Expand Down Expand Up @@ -136,19 +131,17 @@ stim::DetectorErrorModel common::remove_zero_probability_errors(
return out_dem;
}

stim::DetectorErrorModel common::dem_from_counts(
stim::DetectorErrorModel& orig_dem, const std::vector<size_t>& error_counts,
size_t num_shots) {
stim::DetectorErrorModel common::dem_from_counts(stim::DetectorErrorModel& orig_dem,
const std::vector<size_t>& error_counts,
size_t num_shots) {
if (orig_dem.count_errors() != error_counts.size()) {
throw std::invalid_argument(
"Error hits array must be the same size as the number of errors in the "
"original DEM.");
}

for (const stim::DemInstruction& instruction :
orig_dem.flattened().instructions) {
if (instruction.type == stim::DemInstructionType::DEM_ERROR &&
instruction.arg_data[0] == 0) {
for (const stim::DemInstruction& instruction : orig_dem.flattened().instructions) {
if (instruction.type == stim::DemInstructionType::DEM_ERROR && instruction.arg_data[0] == 0) {
throw std::invalid_argument(
"dem_from_counts requires DEMs without zero-probability errors. Use"
" remove_zero_probability_errors first.");
Expand All @@ -157,17 +150,14 @@ stim::DetectorErrorModel common::dem_from_counts(

stim::DetectorErrorModel out_dem;
size_t ei = 0;
for (const stim::DemInstruction& instruction :
orig_dem.flattened().instructions) {
for (const stim::DemInstruction& instruction : orig_dem.flattened().instructions) {
switch (instruction.type) {
case stim::DemInstructionType::DEM_SHIFT_DETECTORS:
assert(false && "unreachable");
break;
case stim::DemInstructionType::DEM_ERROR: {
double est_probability =
double(error_counts.at(ei)) / double(num_shots);
out_dem.append_error_instruction(est_probability,
instruction.target_data, /*tag=*/"");
double est_probability = double(error_counts.at(ei)) / double(num_shots);
out_dem.append_error_instruction(est_probability, instruction.target_data, /*tag=*/"");
++ei;
break;
}
Expand Down
19 changes: 7 additions & 12 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,9 @@ struct Error {
Symptom symptom;
std::vector<bool> dets_array;
Error() = default;
Error(double likelihood_cost, std::vector<int>& detectors,
ObservablesMask observables, std::vector<bool>& dets_array)
: likelihood_cost(likelihood_cost),
symptom{detectors, observables},
dets_array(dets_array) {}
Error(double likelihood_cost, std::vector<int>& detectors, ObservablesMask observables,
std::vector<bool>& dets_array)
: likelihood_cost(likelihood_cost), symptom{detectors, observables}, dets_array(dets_array) {}
Error(double likelihood_cost, double probability, std::vector<int>& detectors,
ObservablesMask observables, std::vector<bool>& dets_array)
: likelihood_cost(likelihood_cost),
Expand All @@ -68,21 +66,18 @@ struct Error {

// Makes a new (flattened) dem where identical error mechanisms have been
// merged.
stim::DetectorErrorModel merge_identical_errors(
const stim::DetectorErrorModel& dem);
stim::DetectorErrorModel merge_identical_errors(const stim::DetectorErrorModel& dem);

// Returns a copy of the given error model with any zero-probability DEM_ERROR
// instructions removed.
stim::DetectorErrorModel remove_zero_probability_errors(
const stim::DetectorErrorModel& dem);
stim::DetectorErrorModel remove_zero_probability_errors(const stim::DetectorErrorModel& dem);

// Makes a new dem where the probabilities of errors are estimated from the
// fraction of shots they were used in.
// Throws std::invalid_argument if `orig_dem` contains zero-probability errors;
// call remove_zero_probability_errors first.
stim::DetectorErrorModel dem_from_counts(
stim::DetectorErrorModel& orig_dem, const std::vector<size_t>& error_counts,
size_t num_shots);
stim::DetectorErrorModel dem_from_counts(stim::DetectorErrorModel& orig_dem,
const std::vector<size_t>& error_counts, size_t num_shots);

} // namespace common

Expand Down
24 changes: 10 additions & 14 deletions src/common.pybind.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ void add_common_module(py::module &root) {

py::class_<common::Symptom>(m, "Symptom")
.def(py::init<std::vector<int>, common::ObservablesMask>(),
py::arg("detectors") = std::vector<int>(),
py::arg("observables") = 0)
py::arg("detectors") = std::vector<int>(), py::arg("observables") = 0)
.def_readwrite("detectors", &common::Symptom::detectors)
.def_readwrite("observables", &common::Symptom::observables)
.def("__str__", &common::Symptom::str)
Expand All @@ -51,25 +50,22 @@ void add_common_module(py::module &root) {
.def_readwrite("symptom", &common::Error::symptom)
.def("__str__", &common::Error::str)
.def(py::init<>())
.def(py::init<double, std::vector<int> &, common::ObservablesMask,
std::vector<bool> &>(),
py::arg("likelihood_cost"), py::arg("detectors"),
py::arg("observables"), py::arg("dets_array"))
.def(py::init<double, std::vector<int> &, common::ObservablesMask, std::vector<bool> &>(),
py::arg("likelihood_cost"), py::arg("detectors"), py::arg("observables"),
py::arg("dets_array"))
.def(py::init<double, double, std::vector<int> &, common::ObservablesMask,
std::vector<bool> &>(),
py::arg("likelihood_cost"), py::arg("probability"),
py::arg("detectors"), py::arg("observables"), py::arg("dets_array"))
py::arg("likelihood_cost"), py::arg("probability"), py::arg("detectors"),
py::arg("observables"), py::arg("dets_array"))
.def(py::init([](stim_pybind::ExposedDemInstruction edi) {
return new common::Error(edi.as_dem_instruction());
}),
py::arg("error"));

m.def("merge_identical_errors", &common::merge_identical_errors,
py::arg("dem"));
m.def("remove_zero_probability_errors",
&common::remove_zero_probability_errors, py::arg("dem"));
m.def("dem_from_counts", &common::dem_from_counts, py::arg("orig_dem"),
py::arg("error_counts"), py::arg("num_shots"));
m.def("merge_identical_errors", &common::merge_identical_errors, py::arg("dem"));
m.def("remove_zero_probability_errors", &common::remove_zero_probability_errors, py::arg("dem"));
m.def("dem_from_counts", &common::dem_from_counts, py::arg("orig_dem"), py::arg("error_counts"),
py::arg("num_shots"));
}

#endif
28 changes: 9 additions & 19 deletions src/common.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ TEST(common, DemFromCountsRejectsZeroProbabilityErrors) {

std::vector<size_t> counts{1, 7, 4};
size_t num_shots = 10;
EXPECT_THROW({
common::dem_from_counts(dem, counts, num_shots);
}, std::invalid_argument);
EXPECT_THROW({ common::dem_from_counts(dem, counts, num_shots); }, std::invalid_argument);

stim::DetectorErrorModel cleaned = common::remove_zero_probability_errors(dem);
stim::DetectorErrorModel out_dem =
Expand All @@ -50,11 +48,9 @@ TEST(common, DemFromCountsRejectsZeroProbabilityErrors) {
ASSERT_EQ(out_dem.count_errors(), 2);
ASSERT_GE(flat.instructions.size(), 2);

EXPECT_EQ(flat.instructions[0].type,
stim::DemInstructionType::DEM_ERROR);
EXPECT_EQ(flat.instructions[0].type, stim::DemInstructionType::DEM_ERROR);
EXPECT_NEAR(flat.instructions[0].arg_data[0], 0.1, 1e-9);
ASSERT_EQ(flat.instructions[1].type,
stim::DemInstructionType::DEM_ERROR);
ASSERT_EQ(flat.instructions[1].type, stim::DemInstructionType::DEM_ERROR);
EXPECT_NEAR(flat.instructions[1].arg_data[0], 0.4, 1e-9);
}

Expand All @@ -68,18 +64,15 @@ TEST(common, DemFromCountsSimpleTwoErrors) {

std::vector<size_t> counts{5, 7};
size_t num_shots = 20;
stim::DetectorErrorModel out_dem =
common::dem_from_counts(dem, counts, num_shots);
stim::DetectorErrorModel out_dem = common::dem_from_counts(dem, counts, num_shots);

auto flat = out_dem.flattened();
ASSERT_EQ(out_dem.count_errors(), 2);

ASSERT_GE(flat.instructions.size(), 2);
EXPECT_EQ(flat.instructions[0].type,
stim::DemInstructionType::DEM_ERROR);
EXPECT_EQ(flat.instructions[0].type, stim::DemInstructionType::DEM_ERROR);
EXPECT_NEAR(flat.instructions[0].arg_data[0], 0.25, 1e-9);
EXPECT_EQ(flat.instructions[1].type,
stim::DemInstructionType::DEM_ERROR);
EXPECT_EQ(flat.instructions[1].type, stim::DemInstructionType::DEM_ERROR);
EXPECT_NEAR(flat.instructions[1].arg_data[0], 0.35, 1e-9);
}

Expand All @@ -93,15 +86,12 @@ TEST(common, RemoveZeroProbabilityErrors) {
detector(0, 0, 0) D2
)DEM");

stim::DetectorErrorModel cleaned =
common::remove_zero_probability_errors(dem);
stim::DetectorErrorModel cleaned = common::remove_zero_probability_errors(dem);

EXPECT_EQ(cleaned.count_errors(), 2);
auto flat = cleaned.flattened();
ASSERT_EQ(flat.instructions[0].type,
stim::DemInstructionType::DEM_ERROR);
ASSERT_EQ(flat.instructions[0].type, stim::DemInstructionType::DEM_ERROR);
EXPECT_NEAR(flat.instructions[0].arg_data[0], 0.1, 1e-9);
ASSERT_EQ(flat.instructions[1].type,
stim::DemInstructionType::DEM_ERROR);
ASSERT_EQ(flat.instructions[1].type, stim::DemInstructionType::DEM_ERROR);
EXPECT_NEAR(flat.instructions[1].arg_data[0], 0.2, 1e-9);
}
Loading