stimflow 0.1.0__tar.gz → 1.16.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {stimflow-0.1.0 → stimflow-1.16.dev0}/PKG-INFO +3 -3
- {stimflow-0.1.0 → stimflow-1.16.dev0}/README.md +2 -2
- {stimflow-0.1.0 → stimflow-1.16.dev0}/setup.py +1 -1
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/__init__.py +2 -2
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk.py +3 -14
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_compiler.py +2 -2
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_interface.py +2 -2
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_loop.py +2 -2
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_patch.py +8 -5
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_stabilizer_code.py +26 -12
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_flow.py +0 -1
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_pauli_map.py +11 -2
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_circuit.py +7 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/__init__.py +2 -2
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_viz_circuit_html.py +2 -2
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_viz_circuit_html_test.py +1 -1
- stimflow-1.16.dev0/src/stimflow/_viz/_viz_html.py +84 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_viz_patch_svg.py +25 -21
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_viz_patch_svg_test.py +1 -1
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_viz_svg.py +35 -27
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow.egg-info/PKG-INFO +3 -3
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow.egg-info/SOURCES.txt +1 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/requirements.txt +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/setup.cfg +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/__init__.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_builder.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_builder_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_compiler_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_reflow.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_reflow_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_chunk_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_code_util.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_code_util_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_flow_metadata.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_flow_util.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_flow_util_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_patch_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_stabilizer_code_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_test_util.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_weave.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_chunk/_weave_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/__init__.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_circuit_util.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_circuit_util_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_complex_util.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_complex_util_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_flow_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_noise.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_noise_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_pauli_map_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_str_html.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_str_svg.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_tile.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_core/_tile_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/__init__.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_data.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_data_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_circuit_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_det_obs_annotation.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_empty.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_feedback.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_feedback_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_interact.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_interact_swap.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_interact_swap_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_iswap.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_loop.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_measure.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_mpp.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_noise.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_qubit_coord_annotation.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_reset.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_rotation.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_rotation_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_shift_coord_annotation.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_sqrt_pp.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_swap.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_tag.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_layer_tag_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_transpile.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_layers/_transpile_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_3d_model.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_3d_model_test.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_3d_model_text_texture.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_3d_model_viewer.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow/_viz/_viz_circuit_layer_svg.py +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow.egg-info/dependency_links.txt +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow.egg-info/requires.txt +0 -0
- {stimflow-0.1.0 → stimflow-1.16.dev0}/src/stimflow.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stimflow
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.16.dev0
|
|
4
4
|
Summary: A library for creating quantum error correction circuits.
|
|
5
5
|
Home-page: https://github.com/quantumlib/stim
|
|
6
6
|
Author: Craig Gidney
|
|
@@ -38,7 +38,7 @@ stimflow also includes functionality for:
|
|
|
38
38
|
|
|
39
39
|
- Transpiling (`stimflow.transpile_to_z_basis_interaction_circuit(...)`)
|
|
40
40
|
- Adding Noise (`stimflow.NoiseModel.uniform_depolarizing(p).noisy_circuit(...)`)
|
|
41
|
-
- Visualizing (`stimflow.make_3d_model`, `stimflow.
|
|
41
|
+
- Visualizing (`stimflow.make_3d_model`, `stimflow.html_viewer`)
|
|
42
42
|
|
|
43
43
|
# Documentation
|
|
44
44
|
|
|
@@ -153,7 +153,7 @@ def main():
|
|
|
153
153
|
noisy_circuit = sf.NoiseModel.uniform_depolarizing(1e-3).noisy_circuit(circuit)
|
|
154
154
|
distance = len(noisy_circuit.shortest_graphlike_error())
|
|
155
155
|
assert distance == 7
|
|
156
|
-
sf.
|
|
156
|
+
sf.html_viewer(noisy_circuit, background=code).write_to('tmp2.html')
|
|
157
157
|
|
|
158
158
|
|
|
159
159
|
if __name__ == "__main__":
|
|
@@ -16,7 +16,7 @@ stimflow also includes functionality for:
|
|
|
16
16
|
|
|
17
17
|
- Transpiling (`stimflow.transpile_to_z_basis_interaction_circuit(...)`)
|
|
18
18
|
- Adding Noise (`stimflow.NoiseModel.uniform_depolarizing(p).noisy_circuit(...)`)
|
|
19
|
-
- Visualizing (`stimflow.make_3d_model`, `stimflow.
|
|
19
|
+
- Visualizing (`stimflow.make_3d_model`, `stimflow.html_viewer`)
|
|
20
20
|
|
|
21
21
|
# Documentation
|
|
22
22
|
|
|
@@ -131,7 +131,7 @@ def main():
|
|
|
131
131
|
noisy_circuit = sf.NoiseModel.uniform_depolarizing(1e-3).noisy_circuit(circuit)
|
|
132
132
|
distance = len(noisy_circuit.shortest_graphlike_error())
|
|
133
133
|
assert distance == 7
|
|
134
|
-
sf.
|
|
134
|
+
sf.html_viewer(noisy_circuit, background=code).write_to('tmp2.html')
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
if __name__ == "__main__":
|
|
@@ -509,20 +509,9 @@ class Chunk:
|
|
|
509
509
|
tile_color_func: Callable[[Tile], tuple[float, float, float, float]] | None = None,
|
|
510
510
|
known_error: Iterable[stim.ExplainedError] | None = None,
|
|
511
511
|
) -> str_html:
|
|
512
|
-
from stimflow._viz import
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if background is None:
|
|
516
|
-
start = self.start_patch()
|
|
517
|
-
end = self.end_patch()
|
|
518
|
-
if len(start.tiles) == 0:
|
|
519
|
-
background = end
|
|
520
|
-
elif len(end.tiles) == 0:
|
|
521
|
-
background = start
|
|
522
|
-
else:
|
|
523
|
-
background = {0: start, circuit.num_ticks: end}
|
|
524
|
-
return stim_circuit_html_viewer(
|
|
525
|
-
circuit, background=background, tile_color_func=tile_color_func, known_error=known_error
|
|
512
|
+
from stimflow._viz import html_viewer
|
|
513
|
+
return html_viewer(
|
|
514
|
+
self, background=background, tile_color_func=tile_color_func, known_error=known_error
|
|
526
515
|
)
|
|
527
516
|
|
|
528
517
|
def __mul__(self, other: int) -> ChunkLoop:
|
|
@@ -89,9 +89,9 @@ class ChunkCompiler:
|
|
|
89
89
|
copy = self.copy()
|
|
90
90
|
if copy.open_flows:
|
|
91
91
|
copy.append_magic_end_chunk()
|
|
92
|
-
from stimflow._viz import
|
|
92
|
+
from stimflow._viz import html_viewer
|
|
93
93
|
|
|
94
|
-
return
|
|
94
|
+
return html_viewer(
|
|
95
95
|
circuit=copy.finish_circuit(), background=self.cur_end_interface()
|
|
96
96
|
)
|
|
97
97
|
|
|
@@ -64,9 +64,9 @@ class ChunkInterface:
|
|
|
64
64
|
elif other is not None:
|
|
65
65
|
flat.extend(other)
|
|
66
66
|
|
|
67
|
-
from stimflow._viz import
|
|
67
|
+
from stimflow._viz import svg_viewer
|
|
68
68
|
|
|
69
|
-
return
|
|
69
|
+
return svg_viewer(
|
|
70
70
|
objects=flat,
|
|
71
71
|
show_obs=show_obs,
|
|
72
72
|
show_measure_qubits=show_measure_qubits,
|
|
@@ -161,13 +161,13 @@ class ChunkLoop:
|
|
|
161
161
|
known_error: Iterable[stim.ExplainedError] | None = None,
|
|
162
162
|
) -> str_html:
|
|
163
163
|
"""Returns an HTML document containing a viewer for the chunk loop's circuit."""
|
|
164
|
-
from stimflow._viz import
|
|
164
|
+
from stimflow._viz import html_viewer
|
|
165
165
|
|
|
166
166
|
if patch is None:
|
|
167
167
|
patch = self.start_patch()
|
|
168
168
|
if len(patch.tiles) == 0:
|
|
169
169
|
patch = self.end_patch()
|
|
170
|
-
return
|
|
170
|
+
return html_viewer(
|
|
171
171
|
self.to_closed_circuit(),
|
|
172
172
|
background=patch,
|
|
173
173
|
tile_color_func=tile_color_func,
|
|
@@ -5,7 +5,7 @@ import functools
|
|
|
5
5
|
from collections.abc import Callable, Iterable, Iterator
|
|
6
6
|
from typing import Literal, overload, TYPE_CHECKING
|
|
7
7
|
|
|
8
|
-
from stimflow._core import PauliMap, str_svg, Tile
|
|
8
|
+
from stimflow._core import PauliMap, str_svg, Tile, min_max_complex
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from stimflow._chunk._stabilizer_code import StabilizerCode
|
|
@@ -22,7 +22,7 @@ class Patch:
|
|
|
22
22
|
elif isinstance(tile, PauliMap):
|
|
23
23
|
kept_tiles.append(tile.to_tile())
|
|
24
24
|
else:
|
|
25
|
-
raise ValueError(f"Don't know how to
|
|
25
|
+
raise ValueError(f"Don't know how to convert a {type(tile)} into a stimflow.Tile: {tile=}")
|
|
26
26
|
if not do_not_sort:
|
|
27
27
|
kept_tiles = sorted(kept_tiles)
|
|
28
28
|
|
|
@@ -39,6 +39,9 @@ class Patch:
|
|
|
39
39
|
def __getitem__(self, item: slice) -> Patch:
|
|
40
40
|
pass
|
|
41
41
|
|
|
42
|
+
def _min_max_complex_(self) -> tuple[complex, complex]:
|
|
43
|
+
return min_max_complex(self.used_set, default=0)
|
|
44
|
+
|
|
42
45
|
def __getitem__(self, item: int | slice) -> Patch | Tile:
|
|
43
46
|
if isinstance(item, slice):
|
|
44
47
|
return Patch(self.tiles[item])
|
|
@@ -113,12 +116,12 @@ class Patch:
|
|
|
113
116
|
tile_color_func: Callable[[Tile], str] | None = None,
|
|
114
117
|
) -> str_svg:
|
|
115
118
|
from stimflow._chunk._stabilizer_code import StabilizerCode
|
|
116
|
-
from stimflow._viz import
|
|
119
|
+
from stimflow._viz import svg_viewer
|
|
117
120
|
|
|
118
121
|
patches = [self] + ([other] if isinstance(other, (Patch, StabilizerCode)) else list(other))
|
|
119
122
|
|
|
120
|
-
return
|
|
121
|
-
|
|
123
|
+
return svg_viewer(
|
|
124
|
+
patches,
|
|
122
125
|
show_measure_qubits=show_measure_qubits,
|
|
123
126
|
show_data_qubits=show_data_qubits,
|
|
124
127
|
show_order=show_order,
|
|
@@ -355,19 +355,33 @@ class StabilizerCode:
|
|
|
355
355
|
f"\n {loc2.gate_target.pauli_type} at {loc2.coords}"
|
|
356
356
|
)
|
|
357
357
|
|
|
358
|
+
def _min_max_complex_(self) -> tuple[complex, complex]:
|
|
359
|
+
return min_max_complex(self.used_set, default=0)
|
|
360
|
+
|
|
358
361
|
def find_distance(self, *, max_search_weight: int) -> int:
|
|
359
362
|
return len(self.find_logical_error(max_search_weight=max_search_weight))
|
|
360
363
|
|
|
361
|
-
def find_logical_error(self, *, max_search_weight: int) -> list[stim.ExplainedError]:
|
|
364
|
+
def find_logical_error(self, *, max_search_weight: int, return_stim_explained_error: bool = False) -> PauliMap | list[stim.ExplainedError]:
|
|
362
365
|
circuit = self.make_code_capacity_circuit(noise=1e-3)
|
|
363
366
|
if max_search_weight == 2:
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
367
|
+
result = circuit.shortest_graphlike_error(canonicalize_circuit_errors=True)
|
|
368
|
+
else:
|
|
369
|
+
result = circuit.search_for_undetectable_logical_errors(
|
|
370
|
+
dont_explore_edges_with_degree_above=max_search_weight,
|
|
371
|
+
dont_explore_detection_event_sets_with_size_above=max_search_weight,
|
|
372
|
+
dont_explore_edges_increasing_symptom_degree=False,
|
|
373
|
+
canonicalize_circuit_errors=True,
|
|
374
|
+
)
|
|
375
|
+
if return_stim_explained_error:
|
|
376
|
+
return result
|
|
377
|
+
|
|
378
|
+
pauli_map = {}
|
|
379
|
+
for err in result:
|
|
380
|
+
for loc in err.circuit_error_locations:
|
|
381
|
+
for term in loc.flipped_pauli_product:
|
|
382
|
+
real, imag = term.coords
|
|
383
|
+
pauli_map[real + 1j*imag] = term.gate_target.pauli_type
|
|
384
|
+
return PauliMap(pauli_map)
|
|
371
385
|
|
|
372
386
|
def with_observables_from_basis(self, basis: Literal["X", "Y", "Z"]) -> StabilizerCode:
|
|
373
387
|
if basis == "X":
|
|
@@ -459,7 +473,7 @@ class StabilizerCode:
|
|
|
459
473
|
t2 = tile2.to_pauli_map()
|
|
460
474
|
if not t1.commutes(t2):
|
|
461
475
|
raise ValueError(
|
|
462
|
-
f"
|
|
476
|
+
f"The following two stabilizers anticommute:\n {t1}\n {t2}\n\nMore details:\n\n{tile1!r}\n\n{tile2!r}"
|
|
463
477
|
)
|
|
464
478
|
|
|
465
479
|
for tile in self.stabilizers.tiles:
|
|
@@ -538,10 +552,10 @@ class StabilizerCode:
|
|
|
538
552
|
elif other is not None:
|
|
539
553
|
flat.extend(other)
|
|
540
554
|
|
|
541
|
-
from stimflow._viz import
|
|
555
|
+
from stimflow._viz import svg_viewer
|
|
542
556
|
|
|
543
|
-
return
|
|
544
|
-
|
|
557
|
+
return svg_viewer(
|
|
558
|
+
flat,
|
|
545
559
|
title=title,
|
|
546
560
|
show_obs=show_obs,
|
|
547
561
|
canvas_height=canvas_height,
|
|
@@ -281,7 +281,6 @@ class Flow:
|
|
|
281
281
|
start=new_start,
|
|
282
282
|
end=new_end,
|
|
283
283
|
measurement_indices=xor_sorted(self.measurement_indices + other.measurement_indices),
|
|
284
|
-
obs_name=self.obs_name,
|
|
285
284
|
flags=self.flags | other.flags,
|
|
286
285
|
center=new_center,
|
|
287
286
|
sign=(None if self.sign is None else self.sign ^ other.sign),
|
|
@@ -5,7 +5,7 @@ from typing import Any, cast, Literal, TYPE_CHECKING
|
|
|
5
5
|
|
|
6
6
|
import stim
|
|
7
7
|
|
|
8
|
-
from stimflow._core._complex_util import sorted_complex
|
|
8
|
+
from stimflow._core._complex_util import sorted_complex, min_max_complex
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from stimflow._core._tile import Tile
|
|
@@ -122,6 +122,15 @@ class PauliMap:
|
|
|
122
122
|
self._dict = {}
|
|
123
123
|
self._hash = hash((self.obs_name, tuple(self._dict.items())))
|
|
124
124
|
|
|
125
|
+
def _min_max_complex_(self) -> tuple[complex, complex]:
|
|
126
|
+
return min_max_complex(self.keys(), default=0)
|
|
127
|
+
|
|
128
|
+
def _inline_svg_(self, *, q2p: Callable[[complex], complex], out_lines: list[str]):
|
|
129
|
+
scale = abs(q2p(1) - q2p(0))
|
|
130
|
+
for q, p in self.items():
|
|
131
|
+
pt = q2p(q)
|
|
132
|
+
out_lines.append(f'''<text x="{pt.real}" y="{pt.imag}" dominant-baseline="central" text-anchor="middle" font-size="{scale}">{p}</text>''')
|
|
133
|
+
|
|
125
134
|
@staticmethod
|
|
126
135
|
def from_xs(xs: Iterable[complex], *, name: Any = None) -> PauliMap:
|
|
127
136
|
"""Returns a PauliMap mapping the given qubits to the X basis."""
|
|
@@ -203,7 +212,7 @@ class PauliMap:
|
|
|
203
212
|
c = "IXZY"[cx + cz * 2]
|
|
204
213
|
if c != "I":
|
|
205
214
|
result[q] = cast(Literal["X", "Y", "Z"], c)
|
|
206
|
-
return PauliMap(result)
|
|
215
|
+
return PauliMap(result, obs_name=self.obs_name if self.obs_name == other.obs_name else None)
|
|
207
216
|
|
|
208
217
|
def __repr__(self) -> str:
|
|
209
218
|
if self.obs_name is None:
|
|
@@ -5,6 +5,7 @@ from typing import Any, cast, Literal, TypeVar
|
|
|
5
5
|
|
|
6
6
|
import stim
|
|
7
7
|
|
|
8
|
+
from stimflow._core import min_max_complex
|
|
8
9
|
from stimflow._layers._layer_det_obs_annotation import DetObsAnnotationLayer
|
|
9
10
|
from stimflow._layers._layer_empty import LayerEmpty
|
|
10
11
|
from stimflow._layers._layer_feedback import LayerFeedback
|
|
@@ -37,6 +38,12 @@ class LayerCircuit:
|
|
|
37
38
|
|
|
38
39
|
layers: list[Layer] = dataclasses.field(default_factory=list)
|
|
39
40
|
|
|
41
|
+
def _min_max_complex_(self) -> tuple[complex, complex]:
|
|
42
|
+
return min_max_complex(
|
|
43
|
+
v[0] + v[1] * 1j
|
|
44
|
+
for v in obj.to_stim_circuit().get_final_qubit_coordinates().values()
|
|
45
|
+
)
|
|
46
|
+
|
|
40
47
|
def touched(self) -> set[int]:
|
|
41
48
|
result = set()
|
|
42
49
|
for layer in self.layers:
|
|
@@ -2,11 +2,11 @@ from stimflow._viz._3d_model_viewer import (
|
|
|
2
2
|
Viewable3dModelGLTF,
|
|
3
3
|
html_viewer_for_gltf_model,
|
|
4
4
|
)
|
|
5
|
-
from stimflow._viz.
|
|
5
|
+
from stimflow._viz._viz_html import html_viewer
|
|
6
6
|
from stimflow._viz._3d_model import (
|
|
7
7
|
LineDataFor3DModel,
|
|
8
8
|
TriangleDataFor3DModel,
|
|
9
9
|
TextDataFor3DModel,
|
|
10
10
|
make_3d_model,
|
|
11
11
|
)
|
|
12
|
-
from stimflow._viz._viz_svg import
|
|
12
|
+
from stimflow._viz._viz_svg import svg_viewer
|
|
@@ -7,7 +7,7 @@ import math
|
|
|
7
7
|
import random
|
|
8
8
|
import sys
|
|
9
9
|
from collections.abc import Callable, Iterable
|
|
10
|
-
from typing import TYPE_CHECKING
|
|
10
|
+
from typing import TYPE_CHECKING, Any
|
|
11
11
|
|
|
12
12
|
import stim
|
|
13
13
|
|
|
@@ -750,7 +750,7 @@ def append_patch_polygons(
|
|
|
750
750
|
out.append(line)
|
|
751
751
|
|
|
752
752
|
|
|
753
|
-
def
|
|
753
|
+
def _stim_circuit_html_viewer(
|
|
754
754
|
circuit: stim.Circuit,
|
|
755
755
|
*,
|
|
756
756
|
background: (
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable, Iterable
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
import stim
|
|
7
|
+
|
|
8
|
+
from stimflow._viz._viz_circuit_html import _stim_circuit_html_viewer
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
import stimflow
|
|
12
|
+
from stimflow._core import str_html
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def html_viewer(
|
|
16
|
+
obj: stim.Circuit | Any,
|
|
17
|
+
*,
|
|
18
|
+
background: (
|
|
19
|
+
stimflow.Patch
|
|
20
|
+
| stimflow.StabilizerCode
|
|
21
|
+
| stimflow.ChunkInterface
|
|
22
|
+
| dict[int, stimflow.Patch | stimflow.StabilizerCode | stimflow.ChunkInterface]
|
|
23
|
+
| None
|
|
24
|
+
) = None,
|
|
25
|
+
tile_color_func: (
|
|
26
|
+
Callable[[stimflow.Tile], tuple[float, float, float, float] | tuple[float, float, float] | str]
|
|
27
|
+
| None
|
|
28
|
+
) = None,
|
|
29
|
+
width: int = 500,
|
|
30
|
+
height: int = 500,
|
|
31
|
+
known_error: Iterable[stim.ExplainedError] | None = None,
|
|
32
|
+
) -> str_html:
|
|
33
|
+
"""Creates an HTML page for viewing the given object.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
obj: The object to be visualized.
|
|
37
|
+
background: Something to draw in the background of the viewer (e.g. the
|
|
38
|
+
stimflow.StabilizerCode implemented by the circuit being viewed).
|
|
39
|
+
tile_color_func: Customizes how stabilizers and other operators are drawn.
|
|
40
|
+
width: The width of the viewer.
|
|
41
|
+
height: The height of the viewer.
|
|
42
|
+
known_error: An error (e.g. returned from stim.Circuit.shortest_graphlike_error)
|
|
43
|
+
to show as part of the object.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
The HTML string (as a stimflow.str_html, which inherits from python's `str`).
|
|
47
|
+
|
|
48
|
+
(The result is of type stimflow.str_html so that its viewer is shown automatically
|
|
49
|
+
in Jupyter notebooks, and also for convenience methods like `write_to`.)
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
from stimflow._chunk import Chunk
|
|
53
|
+
if isinstance(obj, stim.Circuit):
|
|
54
|
+
return _stim_circuit_html_viewer(
|
|
55
|
+
obj,
|
|
56
|
+
background=background,
|
|
57
|
+
tile_color_func=tile_color_func,
|
|
58
|
+
width=width,
|
|
59
|
+
height=height,
|
|
60
|
+
known_error=known_error,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
elif isinstance(obj, Chunk):
|
|
64
|
+
circuit = obj.to_closed_circuit()
|
|
65
|
+
if background is None:
|
|
66
|
+
start = obj.start_patch()
|
|
67
|
+
end = obj.end_patch()
|
|
68
|
+
if len(start.tiles) == 0:
|
|
69
|
+
background = end
|
|
70
|
+
elif len(end.tiles) == 0:
|
|
71
|
+
background = start
|
|
72
|
+
else:
|
|
73
|
+
background = {0: start, circuit.num_ticks: end}
|
|
74
|
+
return _stim_circuit_html_viewer(
|
|
75
|
+
circuit,
|
|
76
|
+
background=background,
|
|
77
|
+
tile_color_func=tile_color_func,
|
|
78
|
+
known_error=known_error,
|
|
79
|
+
width=width,
|
|
80
|
+
height=height,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
else:
|
|
84
|
+
raise NotImplementedError(f"Don't know how to make an html viewer for {type(obj)=}.")
|
|
@@ -245,6 +245,15 @@ def _draw_patch(
|
|
|
245
245
|
stabilizer_style: Literal["polygon", "circles"] | None,
|
|
246
246
|
observable_style: Literal["label", "polygon", "circles"],
|
|
247
247
|
) -> None:
|
|
248
|
+
from stimflow._chunk import Patch, StabilizerCode, ChunkInterface
|
|
249
|
+
if hasattr(obj, "_inline_svg_"):
|
|
250
|
+
obj._inline_svg_(
|
|
251
|
+
out_lines=out_lines,
|
|
252
|
+
q2p=q2p,
|
|
253
|
+
)
|
|
254
|
+
return
|
|
255
|
+
if not isinstance(obj, (Patch, StabilizerCode, ChunkInterface, stim.Circuit)):
|
|
256
|
+
raise NotImplementedError(f'{type(obj)=}')
|
|
248
257
|
if isinstance(obj, stim.Circuit):
|
|
249
258
|
from stimflow._viz._viz_circuit_layer_svg import append_circuit_layer_to_svg
|
|
250
259
|
|
|
@@ -275,25 +284,20 @@ def _draw_patch(
|
|
|
275
284
|
f"WARNING: No logical error will be drawn.\n Reason: {ex}",
|
|
276
285
|
file=sys.stderr,
|
|
277
286
|
)
|
|
278
|
-
err =
|
|
279
|
-
for
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
"font-size": scale_factor * 1.1,
|
|
293
|
-
"fill": BASE_COLORS_DARK[p],
|
|
294
|
-
},
|
|
295
|
-
)
|
|
296
|
-
)
|
|
287
|
+
err = {}
|
|
288
|
+
for q, p in err.items():
|
|
289
|
+
labels.append(
|
|
290
|
+
(
|
|
291
|
+
q,
|
|
292
|
+
p + "!",
|
|
293
|
+
{
|
|
294
|
+
"text-anchor": "middle",
|
|
295
|
+
"dominant-baseline": "central",
|
|
296
|
+
"font-size": scale_factor * 1.1,
|
|
297
|
+
"fill": BASE_COLORS_DARK[p],
|
|
298
|
+
},
|
|
299
|
+
)
|
|
300
|
+
)
|
|
297
301
|
|
|
298
302
|
if isinstance(obj, StabilizerCode) and show_obs:
|
|
299
303
|
_draw_obs(
|
|
@@ -314,9 +318,9 @@ def _draw_patch(
|
|
|
314
318
|
|
|
315
319
|
all_points = set(system_qubits)
|
|
316
320
|
if show_data_qubits:
|
|
317
|
-
all_points |= obj
|
|
321
|
+
all_points |= getattr(obj, 'data_set', set())
|
|
318
322
|
if show_measure_qubits:
|
|
319
|
-
all_points |= obj
|
|
323
|
+
all_points |= getattr(obj, 'measure_set', set())
|
|
320
324
|
if show_coords and all_points:
|
|
321
325
|
all_x = sorted({q.real for q in all_points})
|
|
322
326
|
all_y = sorted({q.imag for q in all_points})
|
|
@@ -2,9 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import math
|
|
4
4
|
from collections.abc import Callable, Iterable
|
|
5
|
-
from typing import Literal, TYPE_CHECKING
|
|
5
|
+
from typing import Literal, TYPE_CHECKING, Any
|
|
6
6
|
|
|
7
7
|
import stim
|
|
8
|
+
from stimflow import PauliMap
|
|
8
9
|
|
|
9
10
|
from stimflow._viz._viz_patch_svg import _draw_patch
|
|
10
11
|
|
|
@@ -12,10 +13,10 @@ if TYPE_CHECKING:
|
|
|
12
13
|
import stimflow
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
def
|
|
16
|
-
|
|
16
|
+
def svg_viewer(
|
|
17
|
+
obj: stimflow.Patch | stimflow.StabilizerCode | stimflow.ChunkInterface | stim.Circuit | PauliMap | Any | Iterable[stimflow.Patch | stimflow.StabilizerCode | stimflow.ChunkInterface | stim.Circuit | PauliMap | Any],
|
|
17
18
|
*,
|
|
18
|
-
background: stimflow.Patch | stimflow.StabilizerCode | stimflow.ChunkInterface | stim.Circuit | None = None,
|
|
19
|
+
background: stimflow.Patch | stimflow.StabilizerCode | stimflow.ChunkInterface | stim.Circuit | PauliMap | Any | None = None,
|
|
19
20
|
title: str | list[str] | None = None,
|
|
20
21
|
canvas_height: int | None = None,
|
|
21
22
|
show_order: bool = False,
|
|
@@ -41,32 +42,39 @@ def svg(
|
|
|
41
42
|
show_frames: bool = True,
|
|
42
43
|
pad: float | None = None,
|
|
43
44
|
) -> stimflow.str_svg:
|
|
44
|
-
"""Returns an SVG image of the given objects.
|
|
45
|
+
"""Returns an SVG image of the given objects.
|
|
46
|
+
"""
|
|
47
|
+
from stimflow._chunk import Patch, StabilizerCode, ChunkInterface
|
|
48
|
+
if hasattr(obj, '_inline_svg_') or isinstance(obj, (Patch, StabilizerCode, ChunkInterface, stim.Circuit, PauliMap)):
|
|
49
|
+
objects = [obj]
|
|
50
|
+
else:
|
|
51
|
+
objects = obj
|
|
52
|
+
|
|
45
53
|
system_qubits = frozenset(system_qubits)
|
|
46
54
|
if canvas_height is None:
|
|
47
55
|
canvas_height = 500
|
|
48
56
|
|
|
49
57
|
extra_used_coords = frozenset(extra_used_coords)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
v[0] + v[1] * 1j for v in
|
|
58
|
+
|
|
59
|
+
min_max_points: set[complex] = set()
|
|
60
|
+
min_max_points.update(system_qubits)
|
|
61
|
+
min_max_points.update(extra_used_coords)
|
|
62
|
+
for e in [*objects, background]:
|
|
63
|
+
if e is None:
|
|
64
|
+
continue
|
|
65
|
+
elif hasattr(e, '_min_max_complex_'):
|
|
66
|
+
min_max_points.update(e._min_max_complex_())
|
|
67
|
+
elif isinstance(e, stim.Circuit):
|
|
68
|
+
min_max_points.update(
|
|
69
|
+
v[0] + v[1] * 1j for v in e.get_final_qubit_coordinates().values()
|
|
62
70
|
)
|
|
63
71
|
else:
|
|
64
|
-
|
|
72
|
+
raise NotImplementedError(f"Don't know how to determine qubits used by {type(e)=}")
|
|
65
73
|
if show_all_qubits:
|
|
66
|
-
system_qubits = frozenset(
|
|
74
|
+
system_qubits = frozenset(min_max_points)
|
|
67
75
|
from stimflow._core import min_max_complex
|
|
68
76
|
|
|
69
|
-
min_c, max_c = min_max_complex(
|
|
77
|
+
min_c, max_c = min_max_complex(min_max_points, default=0)
|
|
70
78
|
min_c -= 0.5 + 0.5j
|
|
71
79
|
max_c += 0.5 + 0.5j
|
|
72
80
|
offset: complex = 0
|
|
@@ -82,14 +90,14 @@ def svg(
|
|
|
82
90
|
box_x_pitch = box_width + pad
|
|
83
91
|
box_y_pitch = box_height + pad
|
|
84
92
|
if cols is None and rows is None:
|
|
85
|
-
cols = min(len(
|
|
86
|
-
rows = math.ceil(len(
|
|
93
|
+
cols = min(len(objects), math.ceil(math.sqrt(len(objects) * 2)))
|
|
94
|
+
rows = math.ceil(len(objects) / max(1, cols))
|
|
87
95
|
elif cols is None:
|
|
88
|
-
cols = math.ceil(len(
|
|
96
|
+
cols = math.ceil(len(objects) / max(1, rows))
|
|
89
97
|
elif rows is None:
|
|
90
|
-
rows = math.ceil(len(
|
|
98
|
+
rows = math.ceil(len(objects) / max(1, cols))
|
|
91
99
|
else:
|
|
92
|
-
assert cols * rows >= len(
|
|
100
|
+
assert cols * rows >= len(objects)
|
|
93
101
|
total_height = max(1.0, box_y_pitch * rows - pad + offset.imag)
|
|
94
102
|
total_width = max(1.0, box_x_pitch * cols - pad + offset.real)
|
|
95
103
|
scale_factor = canvas_height / max(total_height, 1)
|
|
@@ -132,7 +140,7 @@ def svg(
|
|
|
132
140
|
)
|
|
133
141
|
|
|
134
142
|
clip_path_id_ptr = [0]
|
|
135
|
-
for plan_i, plan in enumerate(
|
|
143
|
+
for plan_i, plan in enumerate(objects):
|
|
136
144
|
layers = [plan]
|
|
137
145
|
if background is not None:
|
|
138
146
|
if isinstance(background, (tuple, list)):
|
|
@@ -160,7 +168,7 @@ def svg(
|
|
|
160
168
|
|
|
161
169
|
# Draw frame outlines
|
|
162
170
|
if show_frames:
|
|
163
|
-
for outline_index in range(len(
|
|
171
|
+
for outline_index in range(len(objects)):
|
|
164
172
|
a = patch_q2p(outline_index, min_c)
|
|
165
173
|
a += offset
|
|
166
174
|
b = patch_q2p(outline_index, max_c)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stimflow
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.16.dev0
|
|
4
4
|
Summary: A library for creating quantum error correction circuits.
|
|
5
5
|
Home-page: https://github.com/quantumlib/stim
|
|
6
6
|
Author: Craig Gidney
|
|
@@ -38,7 +38,7 @@ stimflow also includes functionality for:
|
|
|
38
38
|
|
|
39
39
|
- Transpiling (`stimflow.transpile_to_z_basis_interaction_circuit(...)`)
|
|
40
40
|
- Adding Noise (`stimflow.NoiseModel.uniform_depolarizing(p).noisy_circuit(...)`)
|
|
41
|
-
- Visualizing (`stimflow.make_3d_model`, `stimflow.
|
|
41
|
+
- Visualizing (`stimflow.make_3d_model`, `stimflow.html_viewer`)
|
|
42
42
|
|
|
43
43
|
# Documentation
|
|
44
44
|
|
|
@@ -153,7 +153,7 @@ def main():
|
|
|
153
153
|
noisy_circuit = sf.NoiseModel.uniform_depolarizing(1e-3).noisy_circuit(circuit)
|
|
154
154
|
distance = len(noisy_circuit.shortest_graphlike_error())
|
|
155
155
|
assert distance == 7
|
|
156
|
-
sf.
|
|
156
|
+
sf.html_viewer(noisy_circuit, background=code).write_to('tmp2.html')
|
|
157
157
|
|
|
158
158
|
|
|
159
159
|
if __name__ == "__main__":
|
|
@@ -82,6 +82,7 @@ src/stimflow/_viz/__init__.py
|
|
|
82
82
|
src/stimflow/_viz/_viz_circuit_html.py
|
|
83
83
|
src/stimflow/_viz/_viz_circuit_html_test.py
|
|
84
84
|
src/stimflow/_viz/_viz_circuit_layer_svg.py
|
|
85
|
+
src/stimflow/_viz/_viz_html.py
|
|
85
86
|
src/stimflow/_viz/_viz_patch_svg.py
|
|
86
87
|
src/stimflow/_viz/_viz_patch_svg_test.py
|
|
87
88
|
src/stimflow/_viz/_viz_svg.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|