Skip to content

Commit c80e463

Browse files
authored
Add two-qubit unitary decomposition for (inverse) sqrt-iSWAP (#4213)
- Add the method cirq.two_qubit_matrix_to_sqrt_iswap_operations() to optimally decompose with SQRT_ISWAP or SQRT_ISWAP_INV gates. - Add cirq.SQRT_ISWAP and cirq.SQRT_ISWAP_INV (aliases for cirq.ISWAP**0.5 and cirq.ISWAP**-0.5).
1 parent 24bac55 commit c80e463

12 files changed

+917
-3
lines changed

cirq-core/cirq/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@
271271
SingleQubitCliffordGate,
272272
SingleQubitGate,
273273
SingleQubitPauliStringGateOperation,
274+
SQRT_ISWAP,
275+
SQRT_ISWAP_INV,
274276
SWAP,
275277
SwapPowGate,
276278
T,
@@ -326,6 +328,7 @@
326328
SynchronizeTerminalMeasurements,
327329
two_qubit_matrix_to_operations,
328330
two_qubit_matrix_to_diagonal_and_operations,
331+
two_qubit_matrix_to_sqrt_iswap_operations,
329332
three_qubit_matrix_to_operations,
330333
)
331334

cirq-core/cirq/ops/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@
241241
ISWAP,
242242
ISwapPowGate,
243243
riswap,
244+
SQRT_ISWAP,
245+
SQRT_ISWAP_INV,
244246
SWAP,
245247
SwapPowGate,
246248
)

cirq-core/cirq/ops/swap_gates.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
This module creates Gate instances for the following gates:
1717
SWAP: the swap gate.
1818
ISWAP: a swap gate with a phase on the swapped subspace.
19+
SQRT_ISWAP: square root of the ISWAP gate.
20+
SQRT_ISWAP_INV: inverse square root of the ISWAP gate.
1921
2022
Each of these are implemented as EigenGates, which means that they can be
21-
raised to a power (i.e. cirq.ISWAP**0.5). See the definition in EigenGate.
23+
raised to a power (i.e. SQRT_ISWAP_INV=cirq.ISWAP**-0.5). See the definition in
24+
EigenGate.
2225
"""
2326

2427
from typing import Optional, Tuple, TYPE_CHECKING, List, Sequence
@@ -332,3 +335,33 @@ def riswap(rads: value.TParamVal) -> ISwapPowGate:
332335
```
333336
""",
334337
)
338+
339+
SQRT_ISWAP = ISwapPowGate(exponent=0.5)
340+
document(
341+
SQRT_ISWAP,
342+
"""The square root of iswap gate.
343+
344+
Matrix:
345+
```
346+
[[1, 0, 0, 0],
347+
[0, 1/√2, i/√2, 0],
348+
[0, i/√2, 1/√2, 0],
349+
[0, 0, 0, 1]]
350+
```
351+
""",
352+
)
353+
354+
SQRT_ISWAP_INV = ISwapPowGate(exponent=-0.5)
355+
document(
356+
SQRT_ISWAP_INV,
357+
"""The inverse square root of iswap gate.
358+
359+
Matrix:
360+
```
361+
[[1, 0, 0, 0],
362+
[0, 1/√2, -i/√2, 0],
363+
[0, -i/√2, 1/√2, 0],
364+
[0, 0, 0, 1]]
365+
```
366+
""",
367+
)

cirq-core/cirq/ops/swap_gates_test.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,34 @@ def test_iswap_unitary():
109109
# yapf: enable
110110

111111

112+
def test_sqrt_iswap_unitary():
113+
# yapf: disable
114+
cirq.testing.assert_allclose_up_to_global_phase(
115+
cirq.unitary(cirq.SQRT_ISWAP),
116+
# Reference for the sqrt-iSWAP gate's matrix:
117+
# https://arxiv.org/abs/2105.06074
118+
np.array([[1, 0, 0, 0],
119+
[0, 1/2**0.5, 1j/2**0.5, 0],
120+
[0, 1j/2**0.5, 1/2**0.5, 0],
121+
[0, 0, 0, 1]]),
122+
atol=1e-8)
123+
# yapf: enable
124+
125+
126+
def test_sqrt_iswap_inv_unitary():
127+
# yapf: disable
128+
cirq.testing.assert_allclose_up_to_global_phase(
129+
cirq.unitary(cirq.SQRT_ISWAP_INV),
130+
# Reference for the inv-sqrt-iSWAP gate's matrix:
131+
# https://arxiv.org/abs/2105.06074
132+
np.array([[1, 0, 0, 0],
133+
[0, 1/2**0.5, -1j/2**0.5, 0],
134+
[0, -1j/2**0.5, 1/2**0.5, 0],
135+
[0, 0, 0, 1]]),
136+
atol=1e-8)
137+
# yapf: enable
138+
139+
112140
def test_repr():
113141
assert repr(cirq.SWAP) == 'cirq.SWAP'
114142
assert repr(cirq.SWAP ** 0.5) == '(cirq.SWAP**0.5)'

cirq-core/cirq/optimizers/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@
9090
two_qubit_matrix_to_operations,
9191
two_qubit_matrix_to_diagonal_and_operations,
9292
)
93+
from cirq.optimizers.two_qubit_to_sqrt_iswap import (
94+
two_qubit_matrix_to_sqrt_iswap_operations,
95+
)
9396

9497
from cirq.optimizers.two_qubit_to_fsim import (
9598
decompose_two_qubit_interaction_into_four_fsim_gates,

cirq-core/cirq/optimizers/two_qubit_decompositions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
"""Utility methods related to optimizing quantum circuits."""
1616

17-
from typing import Iterable, List, Tuple, Optional, cast, TYPE_CHECKING
17+
from typing import Iterable, List, Sequence, Tuple, Optional, cast, TYPE_CHECKING
1818

1919
import numpy as np
2020

@@ -161,7 +161,7 @@ def _xx_yy_zz_interaction_via_full_czs(
161161
yield ops.H(q1)
162162

163163

164-
def _cleanup_operations(operations: List[ops.Operation]):
164+
def _cleanup_operations(operations: Sequence[ops.Operation]):
165165
circuit = circuits.Circuit(operations)
166166
merge_single_qubit_gates.merge_single_qubit_gates_into_phased_x_z(circuit)
167167
eject_phased_paulis.EjectPhasedPaulis().optimize_circuit(circuit)

0 commit comments

Comments
 (0)