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
…#807)

- Also give `_DiagramHelper` a repr that explains what it is and how to get at its contents
- Also compress DETECTOR and OBSERVABLE_INCLUDE names in crumble URLs
  • Loading branch information
Strilanc authored Jul 31, 2024
1 parent 81c925a commit f66de61
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 170 deletions.
6 changes: 5 additions & 1 deletion src/stim/cmd/command_analyze_errors.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ DETECTOR rec[-2]
[stderr=)OUTPUT"
"\x1B"
R"OUTPUT([31mThe 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(0, 5), filter_coords=['D0', 'D1', ])
or the command line API like this:
stim diagram --in your_circuit_file.stim --type detslice-with-ops-svg --tick 0:5 --filter_coords D0:D1 > output_image.svg
This was discovered while analyzing a Z-basis reset (R) on:
qubit 0
Expand Down
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
34 changes: 29 additions & 5 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((size_t)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 Expand Up @@ -1492,7 +1512,7 @@ void ErrorAnalyzer::do_global_error_decomposition_pass() {
"`--ignore_decomposition_failures` to `stim analyze_errors`.";
if (block_decomposition_from_introducing_remnant_edges) {
ss << "\n\nNote: `block_decomposition_from_introducing_remnant_edges` is ON.\n";
ss << "Turning it off may prevent this error.\n";
ss << "Turning it off may prevent this error.";
}
throw std::invalid_argument(ss.str());
}
Expand Down Expand Up @@ -1538,12 +1558,16 @@ void ErrorAnalyzer::add_error_combinations(
std::stringstream message;
message
<< "An error case in a composite error exceeded the max supported number of symptoms "
"(<=15). ";
"(<=15).";
message << "\nThe " << std::to_string(s)
<< " basis error cases (e.g. X, Z) used to form the combined ";
message << "error cases (e.g. Y = X*Z) are:\n";
for (size_t k2 = 0; k2 < s; k2++) {
message << std::to_string(k2) << ": " << comma_sep_workaround(basis_errors[k2]) << "\n";
message << std::to_string(k2) << ":";
if (!basis_errors[k2].empty()) {
message << ' ';
}
message << comma_sep_workaround(basis_errors[k2]) << "\n";
}
throw std::invalid_argument(message.str());
}
Expand Down
Loading

0 comments on commit f66de61

Please sign in to comment.