Skip to content

Commit 105d975

Browse files
authored
Adds 2q prep for iswap instead of sqrt_iswap (#6314)
1 parent a98fc61 commit 105d975

File tree

5 files changed

+59
-0
lines changed

5 files changed

+59
-0
lines changed

cirq-core/cirq/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@
372372
optimize_for_target_gateset,
373373
parameterized_2q_op_to_sqrt_iswap_operations,
374374
prepare_two_qubit_state_using_cz,
375+
prepare_two_qubit_state_using_iswap,
375376
prepare_two_qubit_state_using_sqrt_iswap,
376377
quantum_shannon_decomposition,
377378
RouteCQC,

cirq-core/cirq/transformers/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
is_negligible_turn,
2525
parameterized_2q_op_to_sqrt_iswap_operations,
2626
prepare_two_qubit_state_using_cz,
27+
prepare_two_qubit_state_using_iswap,
2728
prepare_two_qubit_state_using_sqrt_iswap,
2829
quantum_shannon_decomposition,
2930
single_qubit_matrix_to_gates,

cirq-core/cirq/transformers/analytical_decompositions/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
from cirq.transformers.analytical_decompositions.two_qubit_state_preparation import (
6767
prepare_two_qubit_state_using_cz,
6868
prepare_two_qubit_state_using_sqrt_iswap,
69+
prepare_two_qubit_state_using_iswap,
6970
)
7071

7172
from cirq.transformers.analytical_decompositions.single_to_two_qubit_isometry import (

cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py

+38
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,41 @@ def prepare_two_qubit_state_using_cz(
106106
return op_list + _1q_matrices_to_ops(
107107
np.dot(u, np.linalg.inv(u_CZ)), np.dot(vh.T, np.linalg.inv(vh_CZ.T)), q0, q1
108108
)
109+
110+
111+
def prepare_two_qubit_state_using_iswap(
112+
q0: 'cirq.Qid', q1: 'cirq.Qid', state: 'cirq.STATE_VECTOR_LIKE', use_iswap_inv: bool = False
113+
) -> List['cirq.Operation']:
114+
"""Prepares the given 2q state from |00> using at-most 1 ISWAP gate + single qubit rotations.
115+
116+
Entangled states are prepared using exactly 1 ISWAP gate while product states are prepared
117+
using only single qubit rotations (0 ISWAP gates)
118+
119+
Args:
120+
q0: The first qubit being operated on.
121+
q1: The other qubit being operated on.
122+
state: 4x1 matrix representing two qubit state vector, ordered as 00, 01, 10, 11.
123+
use_iswap_inv: If True, uses `cirq.ISWAP_INV` instead of `cirq.ISWAP`.
124+
125+
Returns:
126+
List of operations (at-most 1 ISWAP + single qubit rotations) preparing state from |00>.
127+
"""
128+
state_vector = qis.to_valid_state_vector(state, num_qubits=2)
129+
state_vector = state_vector / np.linalg.norm(state_vector)
130+
u, s, vh = np.linalg.svd(state_vector.reshape(2, 2))
131+
if np.isclose(s[0], 1):
132+
# Product state can be prepare with just single qubit unitaries.
133+
return _1q_matrices_to_ops(u, vh.T, q0, q1, True)
134+
alpha = np.arccos(np.clip(s[0], 0, 1))
135+
op_list = [
136+
ops.ry(2 * alpha).on(q0),
137+
ops.H.on(q1),
138+
ops.ISWAP_INV.on(q0, q1) if use_iswap_inv else ops.ISWAP.on(q0, q1),
139+
]
140+
intermediate_state = circuits.Circuit(op_list).final_state_vector(
141+
ignore_terminal_measurements=False, dtype=np.complex64
142+
)
143+
u_CZ, _, vh_CZ = np.linalg.svd(intermediate_state.reshape(2, 2))
144+
return op_list + _1q_matrices_to_ops(
145+
np.dot(u, np.linalg.inv(u_CZ)), np.dot(vh.T, np.linalg.inv(vh_CZ.T)), q0, q1
146+
)

cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py

+18
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,24 @@ def test_prepare_two_qubit_state_using_cz(state):
7171
)
7272

7373

74+
@pytest.mark.parametrize("state", STATES_TO_PREPARE)
75+
@pytest.mark.parametrize("use_iswap_inv", [True, False])
76+
def test_prepare_two_qubit_state_using_iswap(state, use_iswap_inv):
77+
state = cirq.to_valid_state_vector(state, num_qubits=2)
78+
q = cirq.LineQubit.range(2)
79+
circuit = cirq.Circuit(
80+
cirq.prepare_two_qubit_state_using_iswap(*q, state, use_iswap_inv=use_iswap_inv)
81+
)
82+
iswap_gate = cirq.ISWAP_INV if use_iswap_inv else cirq.ISWAP
83+
ops_iswap = [*circuit.findall_operations(lambda op: op.gate == iswap_gate)]
84+
ops_2q = [*circuit.findall_operations(lambda op: cirq.num_qubits(op) > 1)]
85+
assert ops_iswap == ops_2q
86+
assert len(ops_iswap) <= 1
87+
assert cirq.allclose_up_to_global_phase(
88+
circuit.final_state_vector(ignore_terminal_measurements=False, dtype=np.complex64), state
89+
)
90+
91+
7492
@pytest.mark.parametrize("state", STATES_TO_PREPARE)
7593
@pytest.mark.parametrize("use_sqrt_iswap_inv", [True, False])
7694
def test_prepare_two_qubit_state_using_sqrt_iswap(state, use_sqrt_iswap_inv):

0 commit comments

Comments
 (0)