Skip to content

Commit

Permalink
Improve dem anticommutation error message to suggest making a diagram
Browse files Browse the repository at this point in the history
  • Loading branch information
Strilanc committed Jul 31, 2024
1 parent 81c925a commit fe39638
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 78 deletions.
25 changes: 25 additions & 0 deletions src/stim/cmd/command_diagram.pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,31 @@ void stim_pybind::pybind_diagram_methods(pybind11::module &m, pybind11::class_<D
c.def("_repr_pretty_", [](const DiagramHelper &self, pybind11::object p, pybind11::object cycle) -> void {
pybind11::getattr(p, "text")(self.content);
});
c.def("__repr__", [](const DiagramHelper &self) -> std::string {
std::stringstream ss;
ss << "<A stim._DiagramHelper containing ";
switch (self.type) {
case DiagramType::DIAGRAM_TYPE_GLTF:
ss << "a GLTF 3d model";
break;
case DiagramType::DIAGRAM_TYPE_SVG:
ss << "an SVG image";
break;
case DiagramType::DIAGRAM_TYPE_TEXT:
ss << "text";
break;
case DiagramType::DIAGRAM_TYPE_HTML:
ss << "an HTML document";
break;
case DiagramType::DIAGRAM_TYPE_SVG_HTML:
ss << "an HTML SVG image viewer";
break;
default:
ss << "???";
}
ss << " that will display inline in Jupyter notebooks. Use 'str' or 'print' to access the contents as text.>";
return ss.str();
});
c.def("__str__", [](const DiagramHelper &self) -> pybind11::object {
if (self.type == DiagramType::DIAGRAM_TYPE_SVG_HTML) {
return diagram_as_html(self);
Expand Down
24 changes: 22 additions & 2 deletions src/stim/simulators/error_analyzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -414,12 +414,32 @@ void ErrorAnalyzer::check_for_gauge(
has_detectors &= !allow_gauge_detectors;
if (has_observables) {
error_msg << "The circuit contains non-deterministic observables.\n";
error_msg << "(Error analysis requires deterministic observables.)\n";
}
if (has_detectors) {
error_msg << "The circuit contains non-deterministic detectors.\n";
error_msg << "(To allow non-deterministic detectors, use the `allow_gauge_detectors` option.)\n";
}
size_t range_start = num_ticks_in_past - std::min(num_ticks_in_past, size_t{5});
size_t range_end = num_ticks_in_past + 5;
error_msg << "\nTo make an SVG picture of the problem, you can use the python API like this:\n ";
error_msg << "your_circuit.diagram('detslice-with-ops-svg'";
error_msg << ", tick=range(" << range_start << ", " << range_end << ")";
error_msg << ", filter_coords=[";
for (auto d : potential_gauge) {
error_msg << "'" << d << "', ";
}
error_msg << "])";
error_msg << "\nor the command line API like this:\n ";
error_msg << "stim diagram --in your_circuit_file.stim";
error_msg << " --type detslice-with-ops-svg";
error_msg << " --tick " << range_start << ":" << range_end;
error_msg << " --filter_coords ";
for (size_t k = 0; k < potential_gauge.size(); k++) {
if (k) {
error_msg << ':';
}
error_msg << potential_gauge.sorted_items[k];
}
error_msg << " > output_image.svg\n";

std::map<uint64_t, std::vector<double>> qubit_coords_map;
if (current_circuit_being_analyzed != nullptr) {
Expand Down
152 changes: 76 additions & 76 deletions src/stim/simulators/error_analyzer.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2348,6 +2348,17 @@ TEST(ErrorAnalyzer, noisy_measurement_mrz) {
)MODEL"));
}

template <typename TEx>
std::string expect_catch_message(std::function<void(void)> func) {
try {
func();
EXPECT_FALSE(false) << "Function didn't throw an exception.";
return "";
} catch (const TEx &ex) {
return ex.what();
}
}

template <typename TEx>
std::string check_catch(std::string expected_substring, std::function<void(void)> func) {
try {
Expand All @@ -2364,13 +2375,7 @@ std::string check_catch(std::string expected_substring, std::function<void(void)

TEST(ErrorAnalyzer, context_clues_for_errors) {
ASSERT_EQ(
"",
check_catch<std::invalid_argument>(
"Can't analyze over-mixing DEPOLARIZE1 errors (probability > 3/4).\n"
"\n"
"Circuit stack trace:\n"
" at instruction #2 [which is DEPOLARIZE1(1) 0]",
[&] {
expect_catch_message<std::invalid_argument>([&](){
ErrorAnalyzer::circuit_to_detector_error_model(
Circuit(R"CIRCUIT(
X 0
Expand All @@ -2382,7 +2387,11 @@ TEST(ErrorAnalyzer, context_clues_for_errors) {
0.0,
false,
true);
}));
}),
"Can't analyze over-mixing DEPOLARIZE1 errors (probability > 3/4).\n"
"\n"
"Circuit stack trace:\n"
" at instruction #2 [which is DEPOLARIZE1(1) 0]");

ASSERT_EQ(
"",
Expand Down Expand Up @@ -2846,10 +2855,31 @@ TEST(ErrorAnalyzer, mpp_ordering) {
TEST(ErrorAnalyzer, anticommuting_observable_error_message_help) {
for (size_t folding = 0; folding < 2; folding++) {
ASSERT_EQ(
"",
check_catch<std::invalid_argument>(
R"ERROR(The circuit contains non-deterministic observables.
(Error analysis requires deterministic observables.)
expect_catch_message<std::invalid_argument>([&](){
circuit_to_dem(
Circuit(R"CIRCUIT(
QUBIT_COORDS(1, 2, 3) 0
RX 2
REPEAT 10 {
REPEAT 20 {
C_XYZ 0
R 1
M 1
DETECTOR rec[-1]
TICK
}
}
M 0 2
OBSERVABLE_INCLUDE(0) rec[-1] rec[-2]
)CIRCUIT"),
{.flatten_loops = folding != 1});
}),
R"ERROR(The circuit contains non-deterministic observables.
To make an SVG picture of the problem, you can use the python API like this:
your_circuit.diagram('detslice-with-ops-svg', tick=range(0, 5), filter_coords=['L0', ])
or the command line API like this:
stim diagram --in your_circuit_file.stim --type detslice-with-ops-svg --tick 0:5 --filter_coords L0 > output_image.svg
This was discovered while analyzing an X-basis reset (RX) on:
qubit 2
Expand All @@ -2863,39 +2893,42 @@ The backward-propagating error sensitivity for L0 was:
Circuit stack trace:
during TICK layer #1 of 201
at instruction #2 [which is RX 2])ERROR",
[&] {
ErrorAnalyzer::circuit_to_detector_error_model(
Circuit(R"CIRCUIT(
QUBIT_COORDS(1, 2, 3) 0
RX 2
REPEAT 10 {
REPEAT 20 {
C_XYZ 0
R 1
M 1
DETECTOR rec[-1]
TICK
}
}
M 0 2
OBSERVABLE_INCLUDE(0) rec[-1] rec[-2]
)CIRCUIT"),
false,
folding == 1,
false,
0.0,
false,
true);
}));
at instruction #2 [which is RX 2])ERROR");

ASSERT_EQ(
"",
check_catch<std::invalid_argument>(
R"ERROR(The circuit contains non-deterministic observables.
(Error analysis requires deterministic observables.)
expect_catch_message<std::invalid_argument>([&](){
circuit_to_dem(Circuit(R"CIRCUIT(
TICK
SHIFT_COORDS(1000, 2000)
M 0 1
REPEAT 100 {
RX 0
DETECTOR rec[-1]
TICK
}
REPEAT 200 {
TICK
}
REPEAT 100 {
M 0 1
SHIFT_COORDS(0, 100)
DETECTOR(1, 2, 3) rec[-1] rec[-3]
DETECTOR(4, 5, 6) rec[-2] rec[-4]
OBSERVABLE_INCLUDE(0) rec[-1] rec[-2] rec[-3] rec[-4]
TICK
}
REPEAT 1000 {
TICK
}
)CIRCUIT"), {.flatten_loops = folding != 1});
}),
R"ERROR(The circuit contains non-deterministic observables.
The circuit contains non-deterministic detectors.
(To allow non-deterministic detectors, use the `allow_gauge_detectors` option.)
To make an SVG picture of the problem, you can use the python API like this:
your_circuit.diagram('detslice-with-ops-svg', tick=range(95, 105), filter_coords=['D101', 'L0', ])
or the command line API like this:
stim diagram --in your_circuit_file.stim --type detslice-with-ops-svg --tick 95:105 --filter_coords D101:L0 > output_image.svg
This was discovered while analyzing an X-basis reset (RX) on:
qubit 0
Expand All @@ -2914,40 +2947,7 @@ The backward-propagating error sensitivity for L0 was:
Circuit stack trace:
during TICK layer #101 of 1402
at instruction #4 [which is a REPEAT 100 block]
at block's instruction #1 [which is RX 0])ERROR",
[&] {
ErrorAnalyzer::circuit_to_detector_error_model(
Circuit(R"CIRCUIT(
TICK
SHIFT_COORDS(1000, 2000)
M 0 1
REPEAT 100 {
RX 0
DETECTOR rec[-1]
TICK
}
REPEAT 200 {
TICK
}
REPEAT 100 {
M 0 1
SHIFT_COORDS(0, 100)
DETECTOR(1, 2, 3) rec[-1] rec[-3]
DETECTOR(4, 5, 6) rec[-2] rec[-4]
OBSERVABLE_INCLUDE(0) rec[-1] rec[-2] rec[-3] rec[-4]
TICK
}
REPEAT 1000 {
TICK
}
)CIRCUIT"),
false,
folding == 1,
false,
0.0,
false,
true);
}));
at block's instruction #1 [which is RX 0])ERROR");
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/stim/util_top/export_crumble_url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ std::string stim::export_crumble_url(const Circuit &circuit) {
std::string_view s_view = s;
std::vector<std::pair<std::string_view, std::string_view>> replace_rules{
{"QUBIT_COORDS", "Q"},
{"DETECTOR", "DT"},
{"OBSERVABLE_INCLUDE", "OI"},
{", ", ","},
{") ", ")"},
{" ", ""},
Expand Down

0 comments on commit fe39638

Please sign in to comment.