Skip to content

Commit e741500

Browse files
authored
Add CZSWAP gate and optimize stim.PauliString.{after,before} (#685)
- Add `CZSWAP` gate with `SWAPCZ` alias - Add specialized `do` and `undo` operations to `stim::PauliStringRef` instead of using generic methods - Measured this as being 10x faster at propagating a stabilizer pauli string through a surface code circuit - Move gate data from `src/circuit/` into `src/gates/` directory - Delete now-unused `stim::GateVTable` (obsoleted by moving to `switch` statements) Fixes #683
1 parent 3e38d12 commit e741500

File tree

78 files changed

+1431
-281
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1431
-281
lines changed

doc/gates.md

+47
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
- [CXSWAP](#CXSWAP)
2727
- [CY](#CY)
2828
- [CZ](#CZ)
29+
- [CZSWAP](#CZSWAP)
2930
- [ISWAP](#ISWAP)
3031
- [ISWAP_DAG](#ISWAP_DAG)
3132
- [SQRT_XX](#SQRT_XX)
@@ -36,6 +37,7 @@
3637
- [SQRT_ZZ_DAG](#SQRT_ZZ_DAG)
3738
- [SWAP](#SWAP)
3839
- [SWAPCX](#SWAPCX)
40+
- [SWAPCZ](#SWAPCZ)
3941
- [XCX](#XCX)
4042
- [XCY](#XCY)
4143
- [XCZ](#XCZ)
@@ -1103,6 +1105,51 @@ Decomposition (into H, S, CX, M, R):
11031105
H 1
11041106

11051107

1108+
<a name="CZSWAP"></a>
1109+
### The 'CZSWAP' Gate
1110+
1111+
Alternate name: <a name="SWAPCZ"></a>`SWAPCZ`
1112+
1113+
A combination CZ-and-SWAP gate.
1114+
This gate is kak-equivalent to the iswap gate.
1115+
1116+
Parens Arguments:
1117+
1118+
This instruction takes no parens arguments.
1119+
1120+
Targets:
1121+
1122+
Qubit pairs to operate on.
1123+
1124+
Example:
1125+
1126+
CZSWAP 5 6
1127+
CZSWAP 42 43
1128+
CZSWAP 5 6 42 43
1129+
1130+
Stabilizer Generators:
1131+
1132+
X_ -> ZX
1133+
Z_ -> _Z
1134+
_X -> XZ
1135+
_Z -> Z_
1136+
1137+
Unitary Matrix (little endian):
1138+
1139+
[+1 , , , ]
1140+
[ , , +1 , ]
1141+
[ , +1 , , ]
1142+
[ , , , -1 ]
1143+
1144+
Decomposition (into H, S, CX, M, R):
1145+
1146+
# The following circuit is equivalent (up to global phase) to `CZSWAP 0 1`
1147+
H 0
1148+
CX 0 1
1149+
CX 1 0
1150+
H 1
1151+
1152+
11061153
<a name="ISWAP"></a>
11071154
### The 'ISWAP' Gate
11081155

file_lists/benchmark_files

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
src/stim/benchmark_main.perf.cc
22
src/stim/benchmark_util.perf.cc
33
src/stim/circuit/circuit.perf.cc
4-
src/stim/circuit/gate_data.perf.cc
4+
src/stim/gates/gates.perf.cc
55
src/stim/io/measure_record_reader.perf.cc
66
src/stim/main_namespaced.perf.cc
77
src/stim/mem/simd_bit_table.perf.cc

file_lists/python_api_files

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
src/stim/circuit/circuit.pybind.cc
22
src/stim/circuit/circuit_instruction.pybind.cc
33
src/stim/circuit/circuit_repeat_block.pybind.cc
4-
src/stim/circuit/gate_data.pybind.cc
54
src/stim/circuit/gate_target.pybind.cc
65
src/stim/cmd/command_diagram.pybind.cc
76
src/stim/dem/detector_error_model.pybind.cc
87
src/stim/dem/detector_error_model_instruction.pybind.cc
98
src/stim/dem/detector_error_model_repeat_block.pybind.cc
109
src/stim/dem/detector_error_model_target.pybind.cc
10+
src/stim/gates/gates.pybind.cc
1111
src/stim/io/read_write.pybind.cc
1212
src/stim/py/base.pybind.cc
1313
src/stim/py/compiled_detector_sampler.pybind.cc

file_lists/source_files_no_main

+14-14
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,6 @@ src/stim/arg_parse.cc
33
src/stim/circuit/circuit.cc
44
src/stim/circuit/circuit_instruction.cc
55
src/stim/circuit/export_qasm.cc
6-
src/stim/circuit/gate_data.cc
7-
src/stim/circuit/gate_data_annotations.cc
8-
src/stim/circuit/gate_data_blocks.cc
9-
src/stim/circuit/gate_data_collapsing.cc
10-
src/stim/circuit/gate_data_controlled.cc
11-
src/stim/circuit/gate_data_hada.cc
12-
src/stim/circuit/gate_data_heralded.cc
13-
src/stim/circuit/gate_data_noisy.cc
14-
src/stim/circuit/gate_data_pair_measure.cc
15-
src/stim/circuit/gate_data_pauli.cc
16-
src/stim/circuit/gate_data_period_3.cc
17-
src/stim/circuit/gate_data_period_4.cc
18-
src/stim/circuit/gate_data_pp.cc
19-
src/stim/circuit/gate_data_swaps.cc
206
src/stim/circuit/gate_decomposition.cc
217
src/stim/circuit/gate_target.cc
228
src/stim/cmd/command_analyze_errors.cc
@@ -51,6 +37,20 @@ src/stim/diagram/lattice_map.cc
5137
src/stim/diagram/timeline/timeline_3d_drawer.cc
5238
src/stim/diagram/timeline/timeline_ascii_drawer.cc
5339
src/stim/diagram/timeline/timeline_svg_drawer.cc
40+
src/stim/gates/gate_data_annotations.cc
41+
src/stim/gates/gate_data_blocks.cc
42+
src/stim/gates/gate_data_collapsing.cc
43+
src/stim/gates/gate_data_controlled.cc
44+
src/stim/gates/gate_data_hada.cc
45+
src/stim/gates/gate_data_heralded.cc
46+
src/stim/gates/gate_data_noisy.cc
47+
src/stim/gates/gate_data_pair_measure.cc
48+
src/stim/gates/gate_data_pauli.cc
49+
src/stim/gates/gate_data_period_3.cc
50+
src/stim/gates/gate_data_period_4.cc
51+
src/stim/gates/gate_data_pp.cc
52+
src/stim/gates/gate_data_swaps.cc
53+
src/stim/gates/gates.cc
5454
src/stim/gen/circuit_gen_params.cc
5555
src/stim/gen/gen_color_code.cc
5656
src/stim/gen/gen_rep_code.cc

file_lists/test_files

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ src/stim.test.cc
22
src/stim/arg_parse.test.cc
33
src/stim/circuit/circuit.test.cc
44
src/stim/circuit/export_qasm.test.cc
5-
src/stim/circuit/gate_data.test.cc
65
src/stim/circuit/gate_decomposition.test.cc
76
src/stim/circuit/gate_target.test.cc
87
src/stim/circuit/stabilizer_flow.test.cc
@@ -26,6 +25,7 @@ src/stim/diagram/json_obj.test.cc
2625
src/stim/diagram/timeline/timeline_3d_drawer.test.cc
2726
src/stim/diagram/timeline/timeline_ascii_drawer.test.cc
2827
src/stim/diagram/timeline/timeline_svg_drawer.test.cc
28+
src/stim/gates/gates.test.cc
2929
src/stim/gen/circuit_gen_params.test.cc
3030
src/stim/gen/gen_color_code.test.cc
3131
src/stim/gen/gen_rep_code.test.cc
@@ -74,6 +74,7 @@ src/stim/stabilizers/conversions.test.cc
7474
src/stim/stabilizers/flex_pauli_string.test.cc
7575
src/stim/stabilizers/pauli_string.test.cc
7676
src/stim/stabilizers/pauli_string_iter.test.cc
77+
src/stim/stabilizers/pauli_string_ref.test.cc
7778
src/stim/stabilizers/tableau.test.cc
7879
src/stim/stabilizers/tableau_iter.test.cc
7980
src/stim/str_util.test.cc

glue/cirq/stimcirq/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
__version__ = '1.13.dev0'
22
from ._cirq_to_stim import cirq_circuit_to_stim_circuit
33
from ._cx_swap_gate import CXSwapGate
4+
from ._cz_swap_gate import CZSwapGate
45
from ._det_annotation import DetAnnotation
56
from ._obs_annotation import CumulativeObservableAnnotation
67
from ._shift_coords_annotation import ShiftCoordsAnnotation
@@ -20,5 +21,6 @@
2021
"SweepPauli": SweepPauli,
2122
"TwoQubitAsymmetricDepolarizingChannel": TwoQubitAsymmetricDepolarizingChannel,
2223
"CXSwapGate": CXSwapGate,
24+
"CZSwapGate": CZSwapGate,
2325
}
2426
JSON_RESOLVER = JSON_RESOLVERS_DICT.get

glue/cirq/stimcirq/_cz_swap_gate.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from typing import Any, Dict, List
2+
3+
import cirq
4+
import stim
5+
6+
7+
@cirq.value_equality
8+
class CZSwapGate(cirq.Gate):
9+
"""Handles explaining stim's CZSWAP gates to cirq."""
10+
11+
def _num_qubits_(self) -> int:
12+
return 2
13+
14+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> List[str]:
15+
return ['ZSWAP', 'ZSWAP']
16+
17+
def _value_equality_values_(self):
18+
return ()
19+
20+
def _decompose_(self, qubits):
21+
a, b = qubits
22+
yield cirq.SWAP(a, b)
23+
yield cirq.CZ(a, b)
24+
25+
def _stim_conversion_(self, edit_circuit: stim.Circuit, targets: List[int], **kwargs):
26+
edit_circuit.append_operation('CZSWAP', targets)
27+
28+
def __pow__(self, power: int) -> 'CZSwapGate':
29+
if power == +1:
30+
return self
31+
if power == -1:
32+
return self
33+
return NotImplemented
34+
35+
def __str__(self) -> str:
36+
return 'CZSWAP'
37+
38+
def __repr__(self):
39+
return f'stimcirq.CZSwapGate()'
40+
41+
@staticmethod
42+
def _json_namespace_() -> str:
43+
return ''
44+
45+
def _json_dict_(self) -> Dict[str, Any]:
46+
return {}

glue/cirq/stimcirq/_cz_swap_test.py

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import cirq
2+
import stim
3+
import stimcirq
4+
5+
6+
def test_stim_conversion():
7+
a, b, c = cirq.LineQubit.range(3)
8+
9+
cirq_circuit = cirq.Circuit(
10+
stimcirq.CZSwapGate().on(a, b),
11+
stimcirq.CZSwapGate().on(b, c),
12+
)
13+
stim_circuit = stim.Circuit(
14+
"""
15+
CZSWAP 0 1
16+
TICK
17+
CZSWAP 1 2
18+
TICK
19+
"""
20+
)
21+
assert stimcirq.cirq_circuit_to_stim_circuit(cirq_circuit) == stim_circuit
22+
assert stimcirq.stim_circuit_to_cirq_circuit(stim_circuit) == cirq_circuit
23+
24+
25+
def test_diagram():
26+
a, b = cirq.LineQubit.range(2)
27+
cirq.testing.assert_has_diagram(
28+
cirq.Circuit(
29+
stimcirq.CZSwapGate()(a, b),
30+
stimcirq.CZSwapGate()(a, b),
31+
),
32+
"""
33+
0: ---ZSWAP---ZSWAP---
34+
| |
35+
1: ---ZSWAP---ZSWAP---
36+
""",
37+
use_unicode_characters=False,
38+
)
39+
40+
41+
def test_inverse():
42+
a = stimcirq.CZSwapGate()
43+
assert a**+1 == a
44+
assert a**-1 == a
45+
46+
47+
def test_repr():
48+
val = stimcirq.CZSwapGate()
49+
assert eval(repr(val), {"stimcirq": stimcirq}) == val
50+
51+
52+
def test_equality():
53+
eq = cirq.testing.EqualsTester()
54+
eq.add_equality_group(stimcirq.CZSwapGate(), stimcirq.CZSwapGate())
55+
56+
57+
def test_json_serialization():
58+
a, b, d = cirq.LineQubit.range(3)
59+
c = cirq.Circuit(
60+
stimcirq.CZSwapGate()(a, b),
61+
stimcirq.CZSwapGate()(b, d),
62+
)
63+
json = cirq.to_json(c)
64+
c2 = cirq.read_json(json_text=json, resolvers=[*cirq.DEFAULT_RESOLVERS, stimcirq.JSON_RESOLVER])
65+
assert c == c2
66+
67+
68+
def test_json_backwards_compat_exact():
69+
raw = stimcirq.CZSwapGate()
70+
packed = '{\n "cirq_type": "CZSwapGate"\n}'
71+
assert cirq.to_json(raw) == packed
72+
assert cirq.read_json(json_text=packed, resolvers=[*cirq.DEFAULT_RESOLVERS, stimcirq.JSON_RESOLVER]) == raw

glue/cirq/stimcirq/_stim_to_cirq.py

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import stim
1717

1818
from ._cx_swap_gate import CXSwapGate
19+
from ._cz_swap_gate import CZSwapGate
1920
from ._det_annotation import DetAnnotation
2021
from ._measure_and_or_reset_gate import MeasureAndOrResetGate
2122
from ._obs_annotation import CumulativeObservableAnnotation
@@ -424,6 +425,7 @@ def handler(
424425
measure=False, reset=True, basis='X', invert_measure=False, key=''
425426
)
426427
),
428+
"CZSWAP": gate(CZSwapGate()),
427429
"CXSWAP": gate(CXSwapGate(inverted=False)),
428430
"SWAPCX": gate(CXSwapGate(inverted=True)),
429431
"RY": gate(

glue/javascript/tableau.js.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <emscripten/bind.h>
44

55
#include "common.js.h"
6-
#include "stim/circuit/gate_data.h"
6+
#include "stim/gates/gates.h"
77

88
using namespace stim;
99

src/stim.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
#include "stim/circuit/circuit.h"
88
#include "stim/circuit/circuit_instruction.h"
99
#include "stim/circuit/export_qasm.h"
10-
#include "stim/circuit/gate_data.h"
11-
#include "stim/circuit/gate_data_table.h"
1210
#include "stim/circuit/gate_decomposition.h"
1311
#include "stim/circuit/gate_target.h"
1412
#include "stim/circuit/stabilizer_flow.h"
@@ -45,6 +43,7 @@
4543
#include "stim/diagram/timeline/timeline_3d_drawer.h"
4644
#include "stim/diagram/timeline/timeline_ascii_drawer.h"
4745
#include "stim/diagram/timeline/timeline_svg_drawer.h"
46+
#include "stim/gates/gates.h"
4847
#include "stim/gen/circuit_gen_params.h"
4948
#include "stim/gen/gen_color_code.h"
5049
#include "stim/gen/gen_rep_code.h"

src/stim/circuit/circuit.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414

1515
#include "stim/circuit/circuit.h"
1616

17+
#include <algorithm>
1718
#include <string>
1819
#include <utility>
1920

20-
#include "stim/circuit/gate_data.h"
2121
#include "stim/circuit/gate_target.h"
22+
#include "stim/gates/gates.h"
2223
#include "stim/str_util.h"
2324

2425
using namespace stim;

src/stim/circuit/circuit.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
#include <vector>
2929

3030
#include "stim/circuit/circuit_instruction.h"
31-
#include "stim/circuit/gate_data.h"
3231
#include "stim/circuit/gate_target.h"
32+
#include "stim/gates/gates.h"
3333
#include "stim/mem/monotonic_buffer.h"
3434
#include "stim/mem/span_ref.h"
3535

src/stim/circuit/circuit.test.cc

+1
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,7 @@ Circuit stim::generate_test_circuit_with_all_operations() {
16191619
ISWAP_DAG 4 5
16201620
SWAP 6 7
16211621
SWAPCX 8 9
1622+
CZSWAP 10 11
16221623
SQRT_XX 0 1
16231624
SQRT_XX_DAG 2 3
16241625
SQRT_YY 4 5

src/stim/circuit/circuit_instruction.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#include <utility>
1818

1919
#include "stim/circuit/circuit.h"
20-
#include "stim/circuit/gate_data.h"
2120
#include "stim/circuit/gate_target.h"
21+
#include "stim/gates/gates.h"
2222

2323
using namespace stim;
2424

src/stim/circuit/circuit_instruction.pybind.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
#include "stim/circuit/circuit_instruction.pybind.h"
1616

17-
#include "stim/circuit/gate_data.h"
1817
#include "stim/circuit/gate_target.pybind.h"
18+
#include "stim/gates/gates.h"
1919
#include "stim/py/base.pybind.h"
2020
#include "stim/str_util.h"
2121

src/stim/circuit/circuit_instruction.pybind.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
#include <pybind11/pybind11.h>
1919

2020
#include "stim/circuit/circuit_instruction.h"
21-
#include "stim/circuit/gate_data.h"
2221
#include "stim/circuit/gate_target.h"
22+
#include "stim/gates/gates.h"
2323

2424
namespace stim_pybind {
2525

0 commit comments

Comments
 (0)