Skip to content

Commit

Permalink
Add stim.Circuit.decomposed (#712)
Browse files Browse the repository at this point in the history
- And allow `MPAD` to take a noise argument
  • Loading branch information
Strilanc authored Mar 12, 2024
1 parent dc59667 commit 4040fd8
Show file tree
Hide file tree
Showing 25 changed files with 1,351 additions and 298 deletions.
6 changes: 6 additions & 0 deletions doc/gates.md
Original file line number Diff line number Diff line change
Expand Up @@ -3143,6 +3143,12 @@ This can be useful for ensuring measurements are aligned to word boundaries, or
number of measurement bits produced per circuit layer is always the same even if the number
of measured qubits varies.

Parens Arguments:

If no parens argument is given, the padding bits are recorded perfectly.
If one parens argument is given, the padding bits are recorded noisily.
The argument is the probability of recording the wrong result.

Targets:

Each target is a measurement result to add.
Expand Down
73 changes: 73 additions & 0 deletions doc/python_api_reference_vDev.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ API references for stable versions are kept on the [stim github wiki](https://gi
- [`stim.Circuit.compile_sampler`](#stim.Circuit.compile_sampler)
- [`stim.Circuit.copy`](#stim.Circuit.copy)
- [`stim.Circuit.count_determined_measurements`](#stim.Circuit.count_determined_measurements)
- [`stim.Circuit.decomposed`](#stim.Circuit.decomposed)
- [`stim.Circuit.detecting_regions`](#stim.Circuit.detecting_regions)
- [`stim.Circuit.detector_error_model`](#stim.Circuit.detector_error_model)
- [`stim.Circuit.diagram`](#stim.Circuit.diagram)
Expand Down Expand Up @@ -1273,6 +1274,78 @@ def count_determined_measurements(
"""
```

<a name="stim.Circuit.decomposed"></a>
```python
# stim.Circuit.decomposed

# (in class stim.Circuit)
def decomposed(
self,
) -> stim.Circuit:
"""Recreates the circuit using (mostly) the {H,S,CX,M,R} gate set.
The intent of this method is to simplify the circuit to use fewer gate types,
so it's easier for other tools to consume. Currently, this method performs the
following simplifications:
- Single qubit cliffords are decomposed into {H,S}.
- Multi-qubit cliffords are decomposed into {H,S,CX}.
- Single qubit dissipative gates are decomposed into {H,S,M,R}.
- Multi-qubit dissipative gates are decomposed into {H,S,CX,M,R}.
Currently, the following types of gate *aren't* simplified, but they may be
in the future:
- Noise instructions (like X_ERROR, DEPOLARIZE2, and E).
- Annotations (like TICK, DETECTOR, and SHIFT_COORDS).
- The MPAD instruction.
- Repeat blocks are not flattened.
Returns:
A `stim.Circuit` whose function is equivalent to the original circuit,
but with most gates decomposed into the {H,S,CX,M,R} gate set.
Examples:
>>> import stim
>>> stim.Circuit('''
... SWAP 0 1
... ''').decomposed()
stim.Circuit('''
CX 0 1 1 0 0 1
''')
>>> stim.Circuit('''
... ISWAP 0 1 2 1
... TICK
... MPP !X1*Y2*Z3
... ''').decomposed()
stim.Circuit('''
H 0
CX 0 1 1 0
H 1
S 1 0
H 2
CX 2 1 1 2
H 1
S 1 2
TICK
H 1 2
S 2
H 2
S 2 2
CX 2 1 3 1
M !1
CX 2 1 3 1
H 2
S 2
H 2
S 2 2
H 1
''')
"""
```

<a name="stim.Circuit.detecting_regions"></a>
```python
# stim.Circuit.detecting_regions
Expand Down
65 changes: 65 additions & 0 deletions doc/stim.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,71 @@ class Circuit:
>>> circuit.num_detectors + circuit.num_observables
217
"""
def decomposed(
self,
) -> stim.Circuit:
"""Recreates the circuit using (mostly) the {H,S,CX,M,R} gate set.
The intent of this method is to simplify the circuit to use fewer gate types,
so it's easier for other tools to consume. Currently, this method performs the
following simplifications:
- Single qubit cliffords are decomposed into {H,S}.
- Multi-qubit cliffords are decomposed into {H,S,CX}.
- Single qubit dissipative gates are decomposed into {H,S,M,R}.
- Multi-qubit dissipative gates are decomposed into {H,S,CX,M,R}.
Currently, the following types of gate *aren't* simplified, but they may be
in the future:
- Noise instructions (like X_ERROR, DEPOLARIZE2, and E).
- Annotations (like TICK, DETECTOR, and SHIFT_COORDS).
- The MPAD instruction.
- Repeat blocks are not flattened.
Returns:
A `stim.Circuit` whose function is equivalent to the original circuit,
but with most gates decomposed into the {H,S,CX,M,R} gate set.
Examples:
>>> import stim
>>> stim.Circuit('''
... SWAP 0 1
... ''').decomposed()
stim.Circuit('''
CX 0 1 1 0 0 1
''')
>>> stim.Circuit('''
... ISWAP 0 1 2 1
... TICK
... MPP !X1*Y2*Z3
... ''').decomposed()
stim.Circuit('''
H 0
CX 0 1 1 0
H 1
S 1 0
H 2
CX 2 1 1 2
H 1
S 1 2
TICK
H 1 2
S 2
H 2
S 2 2
CX 2 1 3 1
M !1
CX 2 1 3 1
H 2
S 2
H 2
S 2 2
H 1
''')
"""
def detecting_regions(
self,
*,
Expand Down
65 changes: 65 additions & 0 deletions glue/python/src/stim/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,71 @@ class Circuit:
>>> circuit.num_detectors + circuit.num_observables
217
"""
def decomposed(
self,
) -> stim.Circuit:
"""Recreates the circuit using (mostly) the {H,S,CX,M,R} gate set.
The intent of this method is to simplify the circuit to use fewer gate types,
so it's easier for other tools to consume. Currently, this method performs the
following simplifications:
- Single qubit cliffords are decomposed into {H,S}.
- Multi-qubit cliffords are decomposed into {H,S,CX}.
- Single qubit dissipative gates are decomposed into {H,S,M,R}.
- Multi-qubit dissipative gates are decomposed into {H,S,CX,M,R}.
Currently, the following types of gate *aren't* simplified, but they may be
in the future:
- Noise instructions (like X_ERROR, DEPOLARIZE2, and E).
- Annotations (like TICK, DETECTOR, and SHIFT_COORDS).
- The MPAD instruction.
- Repeat blocks are not flattened.
Returns:
A `stim.Circuit` whose function is equivalent to the original circuit,
but with most gates decomposed into the {H,S,CX,M,R} gate set.
Examples:
>>> import stim
>>> stim.Circuit('''
... SWAP 0 1
... ''').decomposed()
stim.Circuit('''
CX 0 1 1 0 0 1
''')
>>> stim.Circuit('''
... ISWAP 0 1 2 1
... TICK
... MPP !X1*Y2*Z3
... ''').decomposed()
stim.Circuit('''
H 0
CX 0 1 1 0
H 1
S 1 0
H 2
CX 2 1 1 2
H 1
S 1 2
TICK
H 1 2
S 2
H 2
S 2 2
CX 2 1 3 1
M !1
CX 2 1 3 1
H 2
S 2
H 2
S 2 2
H 1
''')
"""
def detecting_regions(
self,
*,
Expand Down
68 changes: 68 additions & 0 deletions src/stim/circuit/circuit.pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2345,6 +2345,74 @@ void stim_pybind::pybind_circuit_methods(pybind11::module &, pybind11::class_<Ci
)DOC")
.data());

c.def(
"decomposed",
&simplified_circuit,
clean_doc_string(R"DOC(
Recreates the circuit using (mostly) the {H,S,CX,M,R} gate set.
The intent of this method is to simplify the circuit to use fewer gate types,
so it's easier for other tools to consume. Currently, this method performs the
following simplifications:
- Single qubit cliffords are decomposed into {H,S}.
- Multi-qubit cliffords are decomposed into {H,S,CX}.
- Single qubit dissipative gates are decomposed into {H,S,M,R}.
- Multi-qubit dissipative gates are decomposed into {H,S,CX,M,R}.
Currently, the following types of gate *aren't* simplified, but they may be
in the future:
- Noise instructions (like X_ERROR, DEPOLARIZE2, and E).
- Annotations (like TICK, DETECTOR, and SHIFT_COORDS).
- The MPAD instruction.
- Repeat blocks are not flattened.
Returns:
A `stim.Circuit` whose function is equivalent to the original circuit,
but with most gates decomposed into the {H,S,CX,M,R} gate set.
Examples:
>>> import stim
>>> stim.Circuit('''
... SWAP 0 1
... ''').decomposed()
stim.Circuit('''
CX 0 1 1 0 0 1
''')
>>> stim.Circuit('''
... ISWAP 0 1 2 1
... TICK
... MPP !X1*Y2*Z3
... ''').decomposed()
stim.Circuit('''
H 0
CX 0 1 1 0
H 1
S 1 0
H 2
CX 2 1 1 2
H 1
S 1 2
TICK
H 1 2
S 2
H 2
S 2 2
CX 2 1 3 1
M !1
CX 2 1 3 1
H 2
S 2
H 2
S 2 2
H 1
''')
)DOC")
.data());

c.def(
"with_inlined_feedback",
&circuit_with_inlined_feedback,
Expand Down
34 changes: 32 additions & 2 deletions src/stim/circuit/circuit_pybind_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pathlib
import re
import tempfile
from typing import cast

Expand Down Expand Up @@ -1695,10 +1695,40 @@ def test_has_flow_shorthands():
assert c.has_flow(stim.Flow("iX_ -> iXX xor rec[1] xor rec[3]"))
assert not c.has_flow(stim.Flow("-iX_ -> iXX xor rec[1] xor rec[3]"))
assert c.has_flow(stim.Flow("-iX_ -> -iXX xor rec[1] xor rec[3]"))
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="Anti-Hermitian"):
stim.Flow("iX_ -> XX")


def test_decomposed():
assert stim.Circuit("""
ISWAP 0 1 2 1
TICK
MPP X1*Z2*Y3
""").decomposed() == stim.Circuit("""
H 0
CX 0 1 1 0
H 1
S 1 0
H 2
CX 2 1 1 2
H 1
S 1 2
TICK
H 1 3
S 3
H 3
S 3 3
CX 2 1 3 1
M 1
CX 2 1 3 1
H 3
S 3
H 3
S 3 3
H 1
""")


def test_detecting_regions():
assert stim.Circuit('''
R 0
Expand Down
Loading

0 comments on commit 4040fd8

Please sign in to comment.