Skip to content

Commit

Permalink
Add CZSWAP gate and optimize stim.PauliString.{after,before} (#685)
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
Strilanc authored Jan 24, 2024
1 parent 3e38d12 commit e741500
Show file tree
Hide file tree
Showing 78 changed files with 1,431 additions and 281 deletions.
47 changes: 47 additions & 0 deletions doc/gates.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- [CXSWAP](#CXSWAP)
- [CY](#CY)
- [CZ](#CZ)
- [CZSWAP](#CZSWAP)
- [ISWAP](#ISWAP)
- [ISWAP_DAG](#ISWAP_DAG)
- [SQRT_XX](#SQRT_XX)
Expand All @@ -36,6 +37,7 @@
- [SQRT_ZZ_DAG](#SQRT_ZZ_DAG)
- [SWAP](#SWAP)
- [SWAPCX](#SWAPCX)
- [SWAPCZ](#SWAPCZ)
- [XCX](#XCX)
- [XCY](#XCY)
- [XCZ](#XCZ)
Expand Down Expand Up @@ -1103,6 +1105,51 @@ Decomposition (into H, S, CX, M, R):
H 1


<a name="CZSWAP"></a>
### The 'CZSWAP' Gate

Alternate name: <a name="SWAPCZ"></a>`SWAPCZ`

A combination CZ-and-SWAP gate.
This gate is kak-equivalent to the iswap gate.

Parens Arguments:

This instruction takes no parens arguments.

Targets:

Qubit pairs to operate on.

Example:

CZSWAP 5 6
CZSWAP 42 43
CZSWAP 5 6 42 43

Stabilizer Generators:

X_ -> ZX
Z_ -> _Z
_X -> XZ
_Z -> Z_

Unitary Matrix (little endian):

[+1 , , , ]
[ , , +1 , ]
[ , +1 , , ]
[ , , , -1 ]

Decomposition (into H, S, CX, M, R):

# The following circuit is equivalent (up to global phase) to `CZSWAP 0 1`
H 0
CX 0 1
CX 1 0
H 1


<a name="ISWAP"></a>
### The 'ISWAP' Gate

Expand Down
2 changes: 1 addition & 1 deletion file_lists/benchmark_files
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
src/stim/benchmark_main.perf.cc
src/stim/benchmark_util.perf.cc
src/stim/circuit/circuit.perf.cc
src/stim/circuit/gate_data.perf.cc
src/stim/gates/gates.perf.cc
src/stim/io/measure_record_reader.perf.cc
src/stim/main_namespaced.perf.cc
src/stim/mem/simd_bit_table.perf.cc
Expand Down
2 changes: 1 addition & 1 deletion file_lists/python_api_files
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
src/stim/circuit/circuit.pybind.cc
src/stim/circuit/circuit_instruction.pybind.cc
src/stim/circuit/circuit_repeat_block.pybind.cc
src/stim/circuit/gate_data.pybind.cc
src/stim/circuit/gate_target.pybind.cc
src/stim/cmd/command_diagram.pybind.cc
src/stim/dem/detector_error_model.pybind.cc
src/stim/dem/detector_error_model_instruction.pybind.cc
src/stim/dem/detector_error_model_repeat_block.pybind.cc
src/stim/dem/detector_error_model_target.pybind.cc
src/stim/gates/gates.pybind.cc
src/stim/io/read_write.pybind.cc
src/stim/py/base.pybind.cc
src/stim/py/compiled_detector_sampler.pybind.cc
Expand Down
28 changes: 14 additions & 14 deletions file_lists/source_files_no_main
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,6 @@ src/stim/arg_parse.cc
src/stim/circuit/circuit.cc
src/stim/circuit/circuit_instruction.cc
src/stim/circuit/export_qasm.cc
src/stim/circuit/gate_data.cc
src/stim/circuit/gate_data_annotations.cc
src/stim/circuit/gate_data_blocks.cc
src/stim/circuit/gate_data_collapsing.cc
src/stim/circuit/gate_data_controlled.cc
src/stim/circuit/gate_data_hada.cc
src/stim/circuit/gate_data_heralded.cc
src/stim/circuit/gate_data_noisy.cc
src/stim/circuit/gate_data_pair_measure.cc
src/stim/circuit/gate_data_pauli.cc
src/stim/circuit/gate_data_period_3.cc
src/stim/circuit/gate_data_period_4.cc
src/stim/circuit/gate_data_pp.cc
src/stim/circuit/gate_data_swaps.cc
src/stim/circuit/gate_decomposition.cc
src/stim/circuit/gate_target.cc
src/stim/cmd/command_analyze_errors.cc
Expand Down Expand Up @@ -51,6 +37,20 @@ src/stim/diagram/lattice_map.cc
src/stim/diagram/timeline/timeline_3d_drawer.cc
src/stim/diagram/timeline/timeline_ascii_drawer.cc
src/stim/diagram/timeline/timeline_svg_drawer.cc
src/stim/gates/gate_data_annotations.cc
src/stim/gates/gate_data_blocks.cc
src/stim/gates/gate_data_collapsing.cc
src/stim/gates/gate_data_controlled.cc
src/stim/gates/gate_data_hada.cc
src/stim/gates/gate_data_heralded.cc
src/stim/gates/gate_data_noisy.cc
src/stim/gates/gate_data_pair_measure.cc
src/stim/gates/gate_data_pauli.cc
src/stim/gates/gate_data_period_3.cc
src/stim/gates/gate_data_period_4.cc
src/stim/gates/gate_data_pp.cc
src/stim/gates/gate_data_swaps.cc
src/stim/gates/gates.cc
src/stim/gen/circuit_gen_params.cc
src/stim/gen/gen_color_code.cc
src/stim/gen/gen_rep_code.cc
Expand Down
3 changes: 2 additions & 1 deletion file_lists/test_files
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ src/stim.test.cc
src/stim/arg_parse.test.cc
src/stim/circuit/circuit.test.cc
src/stim/circuit/export_qasm.test.cc
src/stim/circuit/gate_data.test.cc
src/stim/circuit/gate_decomposition.test.cc
src/stim/circuit/gate_target.test.cc
src/stim/circuit/stabilizer_flow.test.cc
Expand All @@ -26,6 +25,7 @@ src/stim/diagram/json_obj.test.cc
src/stim/diagram/timeline/timeline_3d_drawer.test.cc
src/stim/diagram/timeline/timeline_ascii_drawer.test.cc
src/stim/diagram/timeline/timeline_svg_drawer.test.cc
src/stim/gates/gates.test.cc
src/stim/gen/circuit_gen_params.test.cc
src/stim/gen/gen_color_code.test.cc
src/stim/gen/gen_rep_code.test.cc
Expand Down Expand Up @@ -74,6 +74,7 @@ src/stim/stabilizers/conversions.test.cc
src/stim/stabilizers/flex_pauli_string.test.cc
src/stim/stabilizers/pauli_string.test.cc
src/stim/stabilizers/pauli_string_iter.test.cc
src/stim/stabilizers/pauli_string_ref.test.cc
src/stim/stabilizers/tableau.test.cc
src/stim/stabilizers/tableau_iter.test.cc
src/stim/str_util.test.cc
Expand Down
2 changes: 2 additions & 0 deletions glue/cirq/stimcirq/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
__version__ = '1.13.dev0'
from ._cirq_to_stim import cirq_circuit_to_stim_circuit
from ._cx_swap_gate import CXSwapGate
from ._cz_swap_gate import CZSwapGate
from ._det_annotation import DetAnnotation
from ._obs_annotation import CumulativeObservableAnnotation
from ._shift_coords_annotation import ShiftCoordsAnnotation
Expand All @@ -20,5 +21,6 @@
"SweepPauli": SweepPauli,
"TwoQubitAsymmetricDepolarizingChannel": TwoQubitAsymmetricDepolarizingChannel,
"CXSwapGate": CXSwapGate,
"CZSwapGate": CZSwapGate,
}
JSON_RESOLVER = JSON_RESOLVERS_DICT.get
46 changes: 46 additions & 0 deletions glue/cirq/stimcirq/_cz_swap_gate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from typing import Any, Dict, List

import cirq
import stim


@cirq.value_equality
class CZSwapGate(cirq.Gate):
"""Handles explaining stim's CZSWAP gates to cirq."""

def _num_qubits_(self) -> int:
return 2

def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> List[str]:
return ['ZSWAP', 'ZSWAP']

def _value_equality_values_(self):
return ()

def _decompose_(self, qubits):
a, b = qubits
yield cirq.SWAP(a, b)
yield cirq.CZ(a, b)

def _stim_conversion_(self, edit_circuit: stim.Circuit, targets: List[int], **kwargs):
edit_circuit.append_operation('CZSWAP', targets)

def __pow__(self, power: int) -> 'CZSwapGate':
if power == +1:
return self
if power == -1:
return self
return NotImplemented

def __str__(self) -> str:
return 'CZSWAP'

def __repr__(self):
return f'stimcirq.CZSwapGate()'

@staticmethod
def _json_namespace_() -> str:
return ''

def _json_dict_(self) -> Dict[str, Any]:
return {}
72 changes: 72 additions & 0 deletions glue/cirq/stimcirq/_cz_swap_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import cirq
import stim
import stimcirq


def test_stim_conversion():
a, b, c = cirq.LineQubit.range(3)

cirq_circuit = cirq.Circuit(
stimcirq.CZSwapGate().on(a, b),
stimcirq.CZSwapGate().on(b, c),
)
stim_circuit = stim.Circuit(
"""
CZSWAP 0 1
TICK
CZSWAP 1 2
TICK
"""
)
assert stimcirq.cirq_circuit_to_stim_circuit(cirq_circuit) == stim_circuit
assert stimcirq.stim_circuit_to_cirq_circuit(stim_circuit) == cirq_circuit


def test_diagram():
a, b = cirq.LineQubit.range(2)
cirq.testing.assert_has_diagram(
cirq.Circuit(
stimcirq.CZSwapGate()(a, b),
stimcirq.CZSwapGate()(a, b),
),
"""
0: ---ZSWAP---ZSWAP---
| |
1: ---ZSWAP---ZSWAP---
""",
use_unicode_characters=False,
)


def test_inverse():
a = stimcirq.CZSwapGate()
assert a**+1 == a
assert a**-1 == a


def test_repr():
val = stimcirq.CZSwapGate()
assert eval(repr(val), {"stimcirq": stimcirq}) == val


def test_equality():
eq = cirq.testing.EqualsTester()
eq.add_equality_group(stimcirq.CZSwapGate(), stimcirq.CZSwapGate())


def test_json_serialization():
a, b, d = cirq.LineQubit.range(3)
c = cirq.Circuit(
stimcirq.CZSwapGate()(a, b),
stimcirq.CZSwapGate()(b, d),
)
json = cirq.to_json(c)
c2 = cirq.read_json(json_text=json, resolvers=[*cirq.DEFAULT_RESOLVERS, stimcirq.JSON_RESOLVER])
assert c == c2


def test_json_backwards_compat_exact():
raw = stimcirq.CZSwapGate()
packed = '{\n "cirq_type": "CZSwapGate"\n}'
assert cirq.to_json(raw) == packed
assert cirq.read_json(json_text=packed, resolvers=[*cirq.DEFAULT_RESOLVERS, stimcirq.JSON_RESOLVER]) == raw
2 changes: 2 additions & 0 deletions glue/cirq/stimcirq/_stim_to_cirq.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import stim

from ._cx_swap_gate import CXSwapGate
from ._cz_swap_gate import CZSwapGate
from ._det_annotation import DetAnnotation
from ._measure_and_or_reset_gate import MeasureAndOrResetGate
from ._obs_annotation import CumulativeObservableAnnotation
Expand Down Expand Up @@ -424,6 +425,7 @@ def handler(
measure=False, reset=True, basis='X', invert_measure=False, key=''
)
),
"CZSWAP": gate(CZSwapGate()),
"CXSWAP": gate(CXSwapGate(inverted=False)),
"SWAPCX": gate(CXSwapGate(inverted=True)),
"RY": gate(
Expand Down
2 changes: 1 addition & 1 deletion glue/javascript/tableau.js.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <emscripten/bind.h>

#include "common.js.h"
#include "stim/circuit/gate_data.h"
#include "stim/gates/gates.h"

using namespace stim;

Expand Down
3 changes: 1 addition & 2 deletions src/stim.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#include "stim/circuit/circuit.h"
#include "stim/circuit/circuit_instruction.h"
#include "stim/circuit/export_qasm.h"
#include "stim/circuit/gate_data.h"
#include "stim/circuit/gate_data_table.h"
#include "stim/circuit/gate_decomposition.h"
#include "stim/circuit/gate_target.h"
#include "stim/circuit/stabilizer_flow.h"
Expand Down Expand Up @@ -45,6 +43,7 @@
#include "stim/diagram/timeline/timeline_3d_drawer.h"
#include "stim/diagram/timeline/timeline_ascii_drawer.h"
#include "stim/diagram/timeline/timeline_svg_drawer.h"
#include "stim/gates/gates.h"
#include "stim/gen/circuit_gen_params.h"
#include "stim/gen/gen_color_code.h"
#include "stim/gen/gen_rep_code.h"
Expand Down
3 changes: 2 additions & 1 deletion src/stim/circuit/circuit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@

#include "stim/circuit/circuit.h"

#include <algorithm>
#include <string>
#include <utility>

#include "stim/circuit/gate_data.h"
#include "stim/circuit/gate_target.h"
#include "stim/gates/gates.h"
#include "stim/str_util.h"

using namespace stim;
Expand Down
2 changes: 1 addition & 1 deletion src/stim/circuit/circuit.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
#include <vector>

#include "stim/circuit/circuit_instruction.h"
#include "stim/circuit/gate_data.h"
#include "stim/circuit/gate_target.h"
#include "stim/gates/gates.h"
#include "stim/mem/monotonic_buffer.h"
#include "stim/mem/span_ref.h"

Expand Down
1 change: 1 addition & 0 deletions src/stim/circuit/circuit.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,7 @@ Circuit stim::generate_test_circuit_with_all_operations() {
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
Expand Down
2 changes: 1 addition & 1 deletion src/stim/circuit/circuit_instruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#include <utility>

#include "stim/circuit/circuit.h"
#include "stim/circuit/gate_data.h"
#include "stim/circuit/gate_target.h"
#include "stim/gates/gates.h"

using namespace stim;

Expand Down
2 changes: 1 addition & 1 deletion src/stim/circuit/circuit_instruction.pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

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

#include "stim/circuit/gate_data.h"
#include "stim/circuit/gate_target.pybind.h"
#include "stim/gates/gates.h"
#include "stim/py/base.pybind.h"
#include "stim/str_util.h"

Expand Down
2 changes: 1 addition & 1 deletion src/stim/circuit/circuit_instruction.pybind.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
#include <pybind11/pybind11.h>

#include "stim/circuit/circuit_instruction.h"
#include "stim/circuit/gate_data.h"
#include "stim/circuit/gate_target.h"
#include "stim/gates/gates.h"

namespace stim_pybind {

Expand Down
Loading

0 comments on commit e741500

Please sign in to comment.