@@ -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+ )
0 commit comments