diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d62a3408a..86dbda126 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -322,6 +322,7 @@ jobs: - run: diff <(python -c "import stim; stim.main(command_line_args=['help', 'gates_markdown'])") doc/gates.md - run: diff <(python -c "import stim; stim.main(command_line_args=['help', 'formats_markdown'])") doc/result_formats.md - run: diff <(python -c "import stim; stim.main(command_line_args=['help', 'commands_markdown'])") doc/usage_command_line.md + - run: diff <(dev/gen_known_gates_for_js.sh) glue/crumble/test/generated_gate_name_list.test.js - run: python doc/stim.pyi - run: npm install -g rollup@3.21.2 uglify-js@3.17.4 - run: diff <(dev/regen_crumble_to_cpp_string_write_to_stdout.sh) src/stim/diagram/crumble_data.cc diff --git a/dev/gen_known_gates_for_js.sh b/dev/gen_known_gates_for_js.sh new file mode 100755 index 000000000..90b0b5503 --- /dev/null +++ b/dev/gen_known_gates_for_js.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +######################################################################### +# Generates javascript exporting a string KNOWN_GATE_NAMES_FROM_STIM. +######################################################################### + +echo "const KNOWN_GATE_NAMES_FROM_STIM = \`" +python -c "import stim; stim.main(command_line_args=['help', 'gates'])" | grep " " | sed 's/^ *//g' +echo "\`" +echo +echo "export {KNOWN_GATE_NAMES_FROM_STIM};" diff --git a/dev/regen_docs.sh b/dev/regen_docs.sh index 5cb916235..3f2266ead 100755 --- a/dev/regen_docs.sh +++ b/dev/regen_docs.sh @@ -16,3 +16,4 @@ python dev/gen_sinter_api_reference.py -dev > doc/sinter_api.md python -c "import stim; stim.main(command_line_args=['help', 'gates_markdown'])" > doc/gates.md python -c "import stim; stim.main(command_line_args=['help', 'formats_markdown'])" > doc/result_formats.md python -c "import stim; stim.main(command_line_args=['help', 'commands_markdown'])" > doc/usage_command_line.md +dev/gen_known_gates_for_js.sh > glue/crumble/test/generated_gate_name_list.test.js diff --git a/glue/crumble/circuit/circuit.js b/glue/crumble/circuit/circuit.js index 61d1f0f87..1e389dd96 100644 --- a/glue/crumble/circuit/circuit.js +++ b/glue/crumble/circuit/circuit.js @@ -1,7 +1,8 @@ import {Operation} from "./operation.js" -import {GATE_MAP} from "../gates/gateset.js" +import {GATE_ALIAS_MAP, GATE_MAP} from "../gates/gateset.js" import {Layer} from "./layer.js" import {make_mpp_gate} from '../gates/gateset_mpp.js'; +import {describe} from "../base/describe.js"; /** * @param {!Iterator}items @@ -92,6 +93,9 @@ function simplifiedMPP(args, combinedTargets) { let bases = ''; let qubits = []; for (let t of combinedTargets) { + if (t[0] === '!') { + t = t.substring(1); + } if (t[0] === 'X' || t[0] === 'Y' || t[0] === 'Z') { bases += t[0]; let v = parseInt(t.substring(1)); @@ -216,32 +220,17 @@ class Circuit { let reverse_pairs = false; if (name === '') { return; - } else if (name === 'XCZ') { - reverse_pairs = true; - name = 'CX'; - } else if (name === 'SWAPCX') { - reverse_pairs = true; - name = 'CXSWAP'; - } else if (name === 'CNOT') { - name = 'CX'; - } else if (name === 'RZ') { - name = 'R'; - } else if (name === 'MZ') { - name = 'M'; - } else if (name === 'MRZ') { - name = 'MR'; - } else if (name === 'ZCX') { - name = 'CX'; - } else if (name === 'ZCY') { - name = 'CY'; - } else if (name === 'ZCZ') { - name = 'CZ'; - } else if (name === 'YCX') { - reverse_pairs = true; - name = 'XCY'; - } else if (name === 'YCZ') { - reverse_pairs = true; - name = 'CY'; + } + let alias = GATE_ALIAS_MAP.get(name); + if (alias !== undefined) { + if (alias.ignore) { + return; + } else if (alias.name !== undefined) { + reverse_pairs = alias.reverse_pairs !== undefined && alias.reverse_pairs; + name = alias.name; + } else { + throw new Error(`Unimplemented alias ${name}: ${describe(alias)}.`); + } } else if (name === 'TICK') { layers.push(new Layer()); return; @@ -258,17 +247,6 @@ class Circuit { } } return; - } else if (name === "X_ERROR" || - name === "Y_ERROR" || - name === "Z_ERROR" || - name === "DETECTOR" || - name === "OBSERVABLE_INCLUDE" || - name === "DEPOLARIZE1" || - name === "DEPOLARIZE2" || - name === "SHIFT_COORDS" || - name === "REPEAT" || - name === "}") { - return; } else if (name.startsWith('QUBIT_COORDS')) { let x = args.length < 1 ? 0 : args[0]; let y = args.length < 2 ? 0 : args[1]; @@ -294,7 +272,6 @@ class Circuit { break; } } - let t = parseInt(targ); if (typeof parseInt(targ) !== 'number') { throw new Error(line); } diff --git a/glue/crumble/circuit/circuit.test.js b/glue/crumble/circuit/circuit.test.js index 744758313..0ffb71eb0 100644 --- a/glue/crumble/circuit/circuit.test.js +++ b/glue/crumble/circuit/circuit.test.js @@ -531,3 +531,120 @@ QUBIT_COORDS(6, 0) 6 MPP Z0*Z1*Z2 Z3*Z4*Z5*X6 `.trim()) }); + +test("circuit.fromStimCircuit_manygates", () => { + let c = Circuit.fromStimCircuit(` + QUBIT_COORDS(1, 2, 3) 0 + + # Pauli gates + I 0 + X 1 + Y 2 + Z 3 + TICK + + # Single Qubit Clifford Gates + C_XYZ 0 + C_ZYX 1 + H_XY 2 + H_XZ 3 + H_YZ 4 + SQRT_X 0 + SQRT_X_DAG 1 + SQRT_Y 2 + SQRT_Y_DAG 3 + SQRT_Z 4 + SQRT_Z_DAG 5 + TICK + + # Two Qubit Clifford Gates + CXSWAP 0 1 + ISWAP 2 3 + ISWAP_DAG 4 5 + SWAP 6 7 + SWAPCX 8 9 + CZSWAP 10 11 + SQRT_XX 0 1 + SQRT_XX_DAG 2 3 + SQRT_YY 4 5 + SQRT_YY_DAG 6 7 + SQRT_ZZ 8 9 + SQRT_ZZ_DAG 10 11 + XCX 0 1 + XCY 2 3 + XCZ 4 5 + YCX 6 7 + YCY 8 9 + YCZ 10 11 + ZCX 12 13 + ZCY 14 15 + ZCZ 16 17 + TICK + + # Noise Channels + CORRELATED_ERROR(0.01) X1 Y2 Z3 + ELSE_CORRELATED_ERROR(0.02) X4 Y7 Z6 + DEPOLARIZE1(0.02) 0 + DEPOLARIZE2(0.03) 1 2 + PAULI_CHANNEL_1(0.01, 0.02, 0.03) 3 + PAULI_CHANNEL_2(0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.010, 0.011, 0.012, 0.013, 0.014, 0.015) 4 5 + X_ERROR(0.01) 0 + Y_ERROR(0.02) 1 + Z_ERROR(0.03) 2 + HERALDED_ERASE(0.04) 3 + HERALDED_PAULI_CHANNEL_1(0.01, 0.02, 0.03, 0.04) 6 + TICK + + # Collapsing Gates + MPP X0*Y1*Z2 Z0*Z1 + MRX 0 + MRY 1 + MRZ 2 + MX 3 + MY 4 + MZ 5 6 + RX 7 + RY 8 + RZ 9 + TICK + + # Pair Measurement Gates + MXX 0 1 2 3 + MYY 4 5 + MZZ 6 7 + TICK + + # Control Flow + REPEAT 3 { + H 0 + CX 0 1 + S 1 + TICK + } + TICK + + # Annotations + MR 0 + X_ERROR(0.1) 0 + MR(0.01) 0 + SHIFT_COORDS(1, 2, 3) + DETECTOR(1, 2, 3) rec[-1] + OBSERVABLE_INCLUDE(0) rec[-1] + MPAD 0 1 0 + TICK + + # Inverted measurements. + MRX !0 + MY !1 + MZZ !2 3 + MYY !4 !5 + MPP X6*!Y7*Z8 + TICK + + # Feedback + CX rec[-1] 0 + CY sweep[0] 1 + CZ 2 rec[-1] + `); + assertThat(c).isNotEqualTo(undefined); +}) diff --git a/glue/crumble/circuit/pauli_frame.js b/glue/crumble/circuit/pauli_frame.js index 4c3bda6ff..ce5b4a5a6 100644 --- a/glue/crumble/circuit/pauli_frame.js +++ b/glue/crumble/circuit/pauli_frame.js @@ -465,6 +465,24 @@ class PauliFrame { } } + /** + * @param {!Array} targets + */ + do_cz_swap(targets) { + for (let k = 0; k < targets.length; k += 2) { + let c = k; + let t = k + 1; + let xc = this.xs[c]; + let zc = this.zs[c]; + let xt = this.xs[t]; + let zt = this.zs[t]; + this.xs[c] = xt; + this.zs[c] = zt ^ xc; + this.xs[t] = xc; + this.zs[t] = zc ^ xt; + } + } + /** * @param {!Array} targets */ diff --git a/glue/crumble/crumble.html b/glue/crumble/crumble.html index 43ed9f8f0..5dfda322b 100644 --- a/glue/crumble/crumble.html +++ b/glue/crumble/crumble.html @@ -7,20 +7,31 @@
- Crumble is a prototype stabilizer circuit editor.
- Read the manual
- Load example: surface code (d=3,r=2)
- Load example: bacon shor code (d=7,r=2)
- Load example: three coupler surface code (d=7,r=4)
+
+
+ Crumble is a prototype stabilizer circuit editor.
+ Read the manual
+
+ Load example: surface code (d=3,r=2)
+ Load example: bacon shor code (d=7,r=2)
+ Load example: three coupler surface code (d=7,r=4)
+ Load example: surface code Y basis transition round (d=7)
+
+
+ + +
+
- +
+
-
- +
+
@@ -41,12 +52,14 @@
+
+
+
+ +
+
-
- - -