Crumble is an in-development tool for exploring and inspecting 2D stabilizer circuits, with a focus on quantum error correction. In particular, crumble automates the process of propagating and verifying the flow of Pauli products across the layers of the circuit.
Crumble is still being prototyped and developed. Crumble is not stable. Crumble is not polished.
Crumble can be accessed by installing stim 1.11
or later (e.g. by pip install stim~=1.11
), printing the output of stim.Circuit().diagram("interactive")
to an HTML file, and then opening the HTML file in a browser.
Crumble can also be accessed by building it.
There are two core pieces to using crumble effectively: (1) editing the circuit and (2) propagating Paulis.
Editing the circuit is done by selecting qubits with the mouse and hitting keyboard keys to place gates. The layers of the circuit can be navigated using the Q/E keys.
Propagating Paulis is done by placing markers to indicate where to add terms.
Each marker has a type (X, Y, or Z) and an index (0-9) indicating which indexed
Pauli product the marker is modifying.
For example, to place a Z term after a reset gate into the Pauli product with
index 1, select the reset gate and press Z
+1
. This introduces a Z term into
the Pauli product, and advancing through the circuit will show how the now
non-empty Pauli product changes as it is rewritten by the circuit's stabilizer
operations.
The simplest way to use markers is as a method for seeing how errors propagate through the circuit. But the far more useful case is for seeing how knowledge propagates through the circuit. After a qubit is reset, its Z observable is in a known state. As the circuit executes, this piece of knowledge is transformed into different forms; it may later correspond to knowing a multi-qubit Pauli product or to knowing what the result of a measurement must be. Pauli propagation shows how these pieces of knowledge move through the circuit.
Of particular interest is finding small sets of resets that match small sets of nearby measurements (i.e. resets that prepare knowledge predicting the parity of a set of measurements). These local reset-vs-measurement tautologies correspond to detectors, which can be used to correct errors. The path that the Pauli product takes, starting from the various resets and terminating on the various measurements, forms the detecting region of the detector.
- Bookmarking:
As crumble runs, it constantly updates the web page's address so that it encodes
the current circuit.
For example, for an empty circuit, the URL will end with
#circuit=
whereas a circuit with a single Hadamard gate would end with#circuit=Q(0,0)0;H_0
. Thus, the current circuit can be saved by bookmarking the page and loaded again later by opening the bookmark. - Importing and Exporting: In the top left of the page, there is a button "Show Import/Export". Clicking this button will reveal a large textbox containing the current circuit encoded as a Stim circuit. To save the circuit, copy this text and write it to a text file on your computer. The saved circuit can later be loaded by copying the file's contents to your clipboard, pasting over the contents of the textbox, and hitting the "↓ Import from Stim Circuit ↓" button below the textbox. The import/export text box can be hidden by clicking the "Show Import/Export" button (now labelled "Hide Import/Export") again.
Pauli Propagation
spacebar
: Clear all Pauli propagation markers at current selection.#
: Puts a Pauli propagation marker at the current selection for the indexed Pauli product.#
can be any of 1, 2, 3, etc and determines which of the tracked Pauli products the marker goes into. For example,2
will place a marker that multiplies a Pauli term into tracked Pauli product #2. The basis of the marker is inferred from context (e.g. if anRX
gate is selected, it will be anX
marker).x+#
: Put an X-type Pauli propagation marker at the current selection for the indexed Pauli product.y+#
: Put a Y-type Pauli propagation marker at the current selection for the indexed Pauli product.z+#
: Put a Z-type Pauli propagation marker at the current selection for the indexed Pauli product.d+#
: Converts the indexed Pauli product into a circuitDETECTOR
declaration.o+#
: Converts the indexed Pauli product into a circuitOBSERVABLE_INCLUDE
declaration.j+#
: Picks aDETECTOR
orOBSERVABLE_INCLUDE
declaration touching the current selection and converts it into a tracked Pauli product.k+#
: Add a marker to any dissipative gate that the indexed Pauli product overlaps in the current layer.
Editing
p
: Add a background polygon with corners at the current selection. The color of the polygon is affected by modifier keys: X, Y, Z, alt, shift.e
: Move to next layer.q
: Move to previous layer.shift+e
: Move forward 5 layers.shift+q
: Move backward 5 layers.escape
: Unselect. Set current selection to the empty set.delete
: Delete gates at current selection.backspace
: Delete gates at current selection.ctrl+delete
: Delete current circuit layer.ctrl+backspace
: Delete current circuit layer.ctrl+insert
: Insert empty layer at current circuit layer, pushing current circuit layer ahead in time.ctrl+z
: Undoctrl+y
: Redoctrl+shift+z
: Redoctrl+c
: Copy selection to clipboard (or entire layer if nothing selected).ctrl+v
: Past clipboard contents at current selection (or entire layer if nothing selected).ctrl+x
: Cut selection to clipboard (or entire layer if nothing selected).f
: Reverse direction of selected two qubit gates (e.g. exchange the controls and targets of a CNOT).g
: Reverse order of circuit layers, from the current layer to the next empty layer.home
: Jump to the first layer of the circuit.end
: Jump to the last layer of the circuit.t
: Rotate circuit 45 degrees clockwise.shift+t
: Rotate circuit 45 degrees counter-clockwise.v
: Translate circuit down one step.^
: Translate circuit up one step.>
: Translate circuit right one step.<
: Translate circuit left one step..
: Translate circuit down and right by a half step.
Single Qubit Gates
Note: use shift
to get the inverse of a gate.
h
: Overwrite selection withH
gates
: Overwrite selection withSQRT_Z
gater
: Overwrite selection withR
gatem
: Overwrite selection withM
gateh+z
orh+x+y
: Overwrite selection withH_XY
gateh+x
orh+y+z
: Overwrite selection withH_YZ
gates+x
: Overwrite selection withSQRT_X
gates+y
: Overwrite selection withSQRT_Y
gater+x
: Overwrite selection withRX
gater+y
: Overwrite selection withRY
gatem+x
: Overwrite selection withMX
gatem+y
: Overwrite selection withMY
gatem+r+x
: Overwrite selection withMRX
gatem+r+y
: Overwrite selection withMRY
gatem+r
: Overwrite selection withMR
gatec+t
: Overwrite selection withC_XYZ
gatej+x
: Overwrite selection with just a PauliX
gatej+y
: Overwrite selection with just a PauliY
gatej+z
: Overwrite selection with just a PauliZ
gateshift+c+t
: Overwrite selection withC_ZYX
gate
Two Qubit Gates
Note: when a single qubit is selected and a two qubit gate is placed, the gate spans between the selected qubit and the qubit the mouse is hovering over. When multiple qubits are selected, the difference between the topmost leftmost qubit and the qubit the mouse is hovering over is computed, and then each selected qubit targets its position offset by that difference.
Note: use shift
to get the inverse of a gate.
w
: Overwrite selection withSWAP
gate targeting mousew+i
: Overwrite selection withISWAP
gate targeting mousew+x
: Overwrite selection withCXSWAP
gate targeting mousec+x
: Overwrite selection withCX
gate targeting mousec+y
: Overwrite selection withCY
gate targeting mousec+z
: Overwrite selection withCZ
gate targeting mousec+x+y
: Overwrite selection withXCY
gate targeting mousealt+c+x
: Overwrite selection withXCX
gate targeting mousealt+c+y
: Overwrite selection withYCY
gate targeting mousec+s+x
: Overwrite selection withSQRT_XX
gate targeting mousec+s+y
: Overwrite selection withSQRT_YY
gate targeting mousec+s+z
: Overwrite selection withSQRT_ZZ
gate targeting mousec+m+x
: Overwrite selection withMXX
gate targeting mousec+m+y
: Overwrite selection withMYY
gate targeting mousec+m+z
: Overwrite selection withMZZ
gate targeting mouse
Multi Qubit Gates
m+p+x
: Overwrite selection with a singleMPP
gate targeting the tensor product of X on each selected qubit.m+p+y
: Overwrite selection with a singleMPP
gate targeting the tensor product of Y on each selected qubit.m+p+z
: Overwrite selection with a singleMPP
gate targeting the tensor product of Z on each selected qubit.
Keyboard Buttons as Gate Adjectives
Roughly speaking, the "keyboard language" for gates used by Crumble has the following "adjectives":
x
means "X basis"y
means "Y basis"z
means "Z basis"shift
means "inverse"c
means "controlled gate" or more generally "two qubit variant of gate"s
means "square root"m
means "measure"r
means "reset"w
means "swap"alt
means "no not that one, a different one"
Here are some examples:
r+x
is the X basis variant of the reset operation (i.e. the gateRX 0
).m+r
is the measure (m) and reset (r) operation (i.e. the gateMR 0
).m+r+y
is the Y basis variant of the measure (m) and reset (r) operation (i.e. the gateMRY 0
).c+m+x
is the two qubit variant (c) of measurement (m) in the X basis (x) (i.e. the gateMXX 1 2
).shift+c+s+y
is the inverse (shift) of the two qubit variant (c) of the square root (s) of the Y gate (y) (i.e. the gateSQRT_YY_DAG 1 2
).
Note: to BoxSelect
means to press down the left mouse button, drag the mouse
while holding the button down to outline a rectangular region, and then release
the mouse button.
Note: using shift
modifies how the mouse updates the current selection. When
shift
is being held and selection S1 would be replaced by selection S2, the new
selection will instead be set to the union of S1 and S2.
Note: using ctrl
modifies how the mouse updates the current selection. When
ctrl
is being held and selection S1 would be replaced by selection S2, the new
selection will instead be set to the symmetric difference of S1 and S2.
LeftClick
: Set current selection to clicked qubit (or to nothing, if clicking empty space).BoxSelect
: Set current selection to boxed area.Alt+BoxSelect
: Set current selection to boxed area, but only including the qubits with the same parity as the initially clicked qubit at the start of the box selection action. The specific parity being used depends on context. For example, when selecting a column of qubits, the row parity is used. When selecting a 2d region, the subgrid parity is used.
Crumble's source code can be served directly by a webserver. For example, serve crumble using python's built-in web server:
# from the root of Stim's git repository:
python -m http.server --directory glue/crumble
then open http://localhost:8000/crumble.html in a web browser.
A single-page version of crumble can be created using rollup-js and uglify-js:
# npm install -g rollup uglify-js
# from the root of Stim's git repository:
{
cat glue/crumble/crumble.html | grep -v "^<script";
echo "<script>";
rollup glue/crumble/main.js | uglifyjs -c -m --mangle-props --toplevel;
echo "</script>";
} > crumble_single_page.html
Crumble's unit tests can be executed by opening the page test/test.html
in a
web browser:
# from the root of Stim's git repository:
python -m http.server --directory glue/crumble &
firefox localhost:8000/test/test.html
# if page says "All X tests passed" then tests passed.
# see the browser console for a log of tests that were run
Unit tests can also be run headless using NodeJS. Unit tests for functionality such as canvas drawing will be skipped when running headless:
# from the root of Stim's git repository:
node glue/crumble/run_tests_headless.js
# will end with 'all tests passed' if all tests passed