cirq-core 1.5.0.dev20240814002711__py3-none-any.whl → 1.5.0.dev20240819032820__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cirq-core might be problematic. Click here for more details.
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/ops/identity.py +8 -1
- cirq/ops/identity_test.py +6 -0
- cirq/transformers/dynamical_decoupling.py +212 -41
- cirq/transformers/dynamical_decoupling_test.py +521 -16
- {cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/METADATA +1 -1
- {cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/RECORD +11 -11
- {cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/LICENSE +0 -0
- {cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/WHEEL +0 -0
- {cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/top_level.txt +0 -0
cirq/_version.py
CHANGED
cirq/_version_test.py
CHANGED
cirq/ops/identity.py
CHANGED
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""IdentityGate."""
|
|
15
15
|
|
|
16
|
-
from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING, Sequence
|
|
16
|
+
from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING, Sequence, Union
|
|
17
17
|
|
|
18
18
|
import numpy as np
|
|
19
19
|
import sympy
|
|
20
20
|
|
|
21
21
|
from cirq import protocols, value
|
|
22
22
|
from cirq._doc import document
|
|
23
|
+
from cirq.type_workarounds import NotImplementedType
|
|
23
24
|
from cirq.ops import raw_types
|
|
24
25
|
|
|
25
26
|
if TYPE_CHECKING:
|
|
@@ -75,6 +76,12 @@ class IdentityGate(raw_types.Gate):
|
|
|
75
76
|
return self
|
|
76
77
|
return NotImplemented
|
|
77
78
|
|
|
79
|
+
def _commutes_(self, other: Any, *, atol: float = 1e-8) -> Union[bool, NotImplementedType]:
|
|
80
|
+
"""The identity gate commutes with all other gates."""
|
|
81
|
+
if not isinstance(other, raw_types.Gate):
|
|
82
|
+
return NotImplemented
|
|
83
|
+
return True
|
|
84
|
+
|
|
78
85
|
def _has_unitary_(self) -> bool:
|
|
79
86
|
return True
|
|
80
87
|
|
cirq/ops/identity_test.py
CHANGED
|
@@ -208,3 +208,9 @@ def test_identity_short_circuits_act_on():
|
|
|
208
208
|
args = mock.Mock(cirq.SimulationState)
|
|
209
209
|
args._act_on_fallback_.side_effect = mock.Mock(side_effect=Exception('No!'))
|
|
210
210
|
cirq.act_on(cirq.IdentityGate(1)(cirq.LineQubit(0)), args)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def test_identity_commutes():
|
|
214
|
+
assert cirq.commutes(cirq.I, cirq.X)
|
|
215
|
+
with pytest.raises(TypeError):
|
|
216
|
+
cirq.commutes(cirq.I, "Gate")
|
|
@@ -15,54 +15,57 @@
|
|
|
15
15
|
"""Transformer pass that adds dynamical decoupling operations to a circuit."""
|
|
16
16
|
|
|
17
17
|
from functools import reduce
|
|
18
|
-
from typing import Dict, Optional,
|
|
18
|
+
from typing import Dict, Optional, Tuple, Union
|
|
19
|
+
from itertools import cycle
|
|
19
20
|
|
|
20
21
|
from cirq.transformers import transformer_api
|
|
22
|
+
from cirq.transformers.analytical_decompositions import single_qubit_decompositions
|
|
23
|
+
from cirq.transformers.analytical_decompositions import unitary_to_pauli_string
|
|
21
24
|
import cirq
|
|
22
25
|
import numpy as np
|
|
23
26
|
|
|
24
27
|
|
|
25
|
-
def
|
|
26
|
-
base_sequence: Sequence['cirq.Gate'], num_idle_moments: int
|
|
27
|
-
) -> Sequence['cirq.Gate']:
|
|
28
|
-
"""Returns the longest possible dynamical decoupling sequence."""
|
|
29
|
-
repeat_times = num_idle_moments // len(base_sequence)
|
|
30
|
-
return list(base_sequence) * repeat_times
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _get_dd_sequence_from_schema_name(schema: str) -> Sequence['cirq.Gate']:
|
|
28
|
+
def _get_dd_sequence_from_schema_name(schema: str) -> Tuple['cirq.Gate', ...]:
|
|
34
29
|
"""Gets dynamical decoupling sequence from a schema name."""
|
|
35
|
-
dd_sequence: Sequence['cirq.Gate']
|
|
36
30
|
match schema:
|
|
31
|
+
case 'DEFAULT':
|
|
32
|
+
return (cirq.X, cirq.Y, cirq.X, cirq.Y)
|
|
37
33
|
case 'XX_PAIR':
|
|
38
|
-
|
|
34
|
+
return (cirq.X, cirq.X)
|
|
39
35
|
case 'X_XINV':
|
|
40
|
-
|
|
36
|
+
return (cirq.X, cirq.X**-1)
|
|
41
37
|
case 'YY_PAIR':
|
|
42
|
-
|
|
38
|
+
return (cirq.Y, cirq.Y)
|
|
43
39
|
case 'Y_YINV':
|
|
44
|
-
|
|
40
|
+
return (cirq.Y, cirq.Y**-1)
|
|
45
41
|
case _:
|
|
46
42
|
raise ValueError('Invalid schema name.')
|
|
47
|
-
return dd_sequence
|
|
48
43
|
|
|
49
44
|
|
|
50
|
-
def
|
|
45
|
+
def _pauli_up_to_global_phase(gate: 'cirq.Gate') -> Union['cirq.Pauli', None]:
|
|
46
|
+
for pauli_gate in [cirq.X, cirq.Y, cirq.Z]:
|
|
47
|
+
if cirq.equal_up_to_global_phase(gate, pauli_gate):
|
|
48
|
+
return pauli_gate
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _validate_dd_sequence(dd_sequence: Tuple['cirq.Gate', ...]) -> None:
|
|
51
53
|
"""Validates a given dynamical decoupling sequence.
|
|
52
54
|
|
|
53
55
|
Args:
|
|
54
56
|
dd_sequence: Input dynamical sequence to be validated.
|
|
55
57
|
|
|
56
|
-
Returns:
|
|
57
|
-
A tuple containing:
|
|
58
|
-
- is_valid (bool): True if the dd sequence is valid, False otherwise.
|
|
59
|
-
- error_message (str): An error message if the dd sequence is invalid, else None.
|
|
60
|
-
|
|
61
58
|
Raises:
|
|
62
59
|
ValueError: If dd_sequence is not valid.
|
|
63
60
|
"""
|
|
64
61
|
if len(dd_sequence) < 2:
|
|
65
62
|
raise ValueError('Invalid dynamical decoupling sequence. Expect more than one gates.')
|
|
63
|
+
for gate in dd_sequence:
|
|
64
|
+
if _pauli_up_to_global_phase(gate) is None:
|
|
65
|
+
raise ValueError(
|
|
66
|
+
'Dynamical decoupling sequence should only contain gates that are essentially'
|
|
67
|
+
' Pauli gates.'
|
|
68
|
+
)
|
|
66
69
|
matrices = [cirq.unitary(gate) for gate in dd_sequence]
|
|
67
70
|
product = reduce(np.matmul, matrices)
|
|
68
71
|
|
|
@@ -73,14 +76,134 @@ def _validate_dd_sequence(dd_sequence: Sequence['cirq.Gate']) -> None:
|
|
|
73
76
|
)
|
|
74
77
|
|
|
75
78
|
|
|
76
|
-
def _parse_dd_sequence(schema: Union[str,
|
|
79
|
+
def _parse_dd_sequence(schema: Union[str, Tuple['cirq.Gate', ...]]) -> Tuple['cirq.Gate', ...]:
|
|
77
80
|
"""Parses and returns dynamical decoupling sequence from schema."""
|
|
78
81
|
if isinstance(schema, str):
|
|
79
|
-
|
|
82
|
+
return _get_dd_sequence_from_schema_name(schema)
|
|
80
83
|
else:
|
|
81
84
|
_validate_dd_sequence(schema)
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
return schema
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _is_single_qubit_operation(operation: 'cirq.Operation') -> bool:
|
|
89
|
+
if len(operation.qubits) != 1:
|
|
90
|
+
return False
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _is_single_qubit_gate_moment(moment: 'cirq.Moment') -> bool:
|
|
95
|
+
for operation in moment:
|
|
96
|
+
if not _is_single_qubit_operation(operation):
|
|
97
|
+
return False
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _is_clifford_moment(moment: 'cirq.Moment') -> bool:
|
|
102
|
+
for op in moment.operations:
|
|
103
|
+
if op.gate is not None and isinstance(op.gate, cirq.MeasurementGate):
|
|
104
|
+
return False
|
|
105
|
+
if not cirq.has_stabilizer_effect(op):
|
|
106
|
+
return False
|
|
107
|
+
return True
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _get_clifford_pieces(circuit: 'cirq.AbstractCircuit') -> list[Tuple[int, int]]:
|
|
111
|
+
clifford_pieces: list[Tuple[int, int]] = []
|
|
112
|
+
left = 0
|
|
113
|
+
for moment_id, moment in enumerate(circuit):
|
|
114
|
+
if not _is_clifford_moment(moment):
|
|
115
|
+
clifford_pieces.append((left, moment_id))
|
|
116
|
+
left = moment_id + 1
|
|
117
|
+
if left < len(circuit):
|
|
118
|
+
clifford_pieces.append((left, len(circuit)))
|
|
119
|
+
return clifford_pieces
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _is_insertable_moment(moment: 'cirq.Moment', single_qubit_gate_moments_only: bool) -> bool:
|
|
123
|
+
return _is_single_qubit_gate_moment(moment) or not single_qubit_gate_moments_only
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _calc_pulled_through(
|
|
127
|
+
moment: 'cirq.Moment', input_pauli_ops: 'cirq.PauliString'
|
|
128
|
+
) -> 'cirq.PauliString':
|
|
129
|
+
"""Calculates the pulled_through after pulling through moment with the input.
|
|
130
|
+
|
|
131
|
+
We assume that the moment is Clifford here. Then, pulling through is essentially
|
|
132
|
+
decomposing a matrix into Pauli operations on each qubit.
|
|
133
|
+
"""
|
|
134
|
+
pulled_through: 'cirq.PauliString' = cirq.PauliString()
|
|
135
|
+
for affected_q, combined_op_in_pauli in input_pauli_ops.items():
|
|
136
|
+
op_at_moment = moment.operation_at(affected_q)
|
|
137
|
+
if op_at_moment is None:
|
|
138
|
+
pulled_through *= combined_op_in_pauli.on(affected_q)
|
|
139
|
+
continue
|
|
140
|
+
prev_circuit = cirq.Circuit(cirq.Moment(op_at_moment))
|
|
141
|
+
new_circuit = cirq.Circuit(
|
|
142
|
+
cirq.Moment(combined_op_in_pauli.on(affected_q)), cirq.Moment(op_at_moment)
|
|
143
|
+
)
|
|
144
|
+
qubit_order = op_at_moment.qubits
|
|
145
|
+
pulled_through_pauli_ops = unitary_to_pauli_string(
|
|
146
|
+
prev_circuit.unitary(qubit_order=qubit_order)
|
|
147
|
+
@ new_circuit.unitary(qubit_order=qubit_order).conj().T
|
|
148
|
+
)
|
|
149
|
+
if pulled_through_pauli_ops is not None:
|
|
150
|
+
for qid, gate in enumerate(pulled_through_pauli_ops):
|
|
151
|
+
pulled_through *= gate.on(qubit_order[qid])
|
|
152
|
+
return pulled_through
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _merge_pulled_through(
|
|
156
|
+
mutable_circuit: 'cirq.Circuit',
|
|
157
|
+
pulled_through: 'cirq.PauliString',
|
|
158
|
+
clifford_piece_range: Tuple[int, int],
|
|
159
|
+
single_qubit_gate_moments_only: bool,
|
|
160
|
+
) -> 'cirq.PauliString':
|
|
161
|
+
"""Merges pulled through Pauli gates into the last single-qubit gate operation or the insert it
|
|
162
|
+
into the first idle moment if idle moments exist.
|
|
163
|
+
Args:
|
|
164
|
+
mutable_circuit: Mutable circuit to transform.
|
|
165
|
+
pulled_through: Pauli gates to be merged.
|
|
166
|
+
clifford_piece_range: Specifies the [l, r) moments within which pulled-through gate merging
|
|
167
|
+
is to be performed.
|
|
168
|
+
single_qubit_gate_moments_only: If set True, dynamical decoupling operation will only be
|
|
169
|
+
added in single-qubit gate moments.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
The remaining pulled through operations after merging.
|
|
173
|
+
"""
|
|
174
|
+
insert_intos: list[Tuple[int, 'cirq.Operation']] = []
|
|
175
|
+
batch_replaces: list[Tuple[int, 'cirq.Operation', 'cirq.Operation']] = []
|
|
176
|
+
remaining_pulled_through = pulled_through
|
|
177
|
+
for affected_q, combined_op_in_pauli in pulled_through.items():
|
|
178
|
+
moment_id = mutable_circuit.prev_moment_operating_on([affected_q], clifford_piece_range[1])
|
|
179
|
+
if moment_id is not None:
|
|
180
|
+
op = mutable_circuit.operation_at(affected_q, moment_id)
|
|
181
|
+
# Try to merge op into an existing single-qubit gate operation.
|
|
182
|
+
if op is not None and _is_single_qubit_operation(op):
|
|
183
|
+
updated_gate_mat = cirq.unitary(combined_op_in_pauli) @ cirq.unitary(op)
|
|
184
|
+
updated_gate: Optional['cirq.Gate'] = (
|
|
185
|
+
single_qubit_decompositions.single_qubit_matrix_to_phxz(updated_gate_mat)
|
|
186
|
+
)
|
|
187
|
+
if updated_gate is None:
|
|
188
|
+
# updated_gate is close to Identity.
|
|
189
|
+
updated_gate = cirq.I
|
|
190
|
+
batch_replaces.append((moment_id, op, updated_gate.on(affected_q)))
|
|
191
|
+
remaining_pulled_through *= combined_op_in_pauli.on(affected_q)
|
|
192
|
+
continue
|
|
193
|
+
# Insert into the first empty moment for the qubit if such moment exists.
|
|
194
|
+
while moment_id < clifford_piece_range[1]:
|
|
195
|
+
if affected_q not in mutable_circuit.moments[
|
|
196
|
+
moment_id
|
|
197
|
+
].qubits and _is_insertable_moment(
|
|
198
|
+
mutable_circuit.moments[moment_id], single_qubit_gate_moments_only
|
|
199
|
+
):
|
|
200
|
+
insert_intos.append((moment_id, combined_op_in_pauli.on(affected_q)))
|
|
201
|
+
remaining_pulled_through *= combined_op_in_pauli.on(affected_q)
|
|
202
|
+
break
|
|
203
|
+
moment_id += 1
|
|
204
|
+
mutable_circuit.batch_insert_into(insert_intos)
|
|
205
|
+
mutable_circuit.batch_replace(batch_replaces)
|
|
206
|
+
return remaining_pulled_through
|
|
84
207
|
|
|
85
208
|
|
|
86
209
|
@transformer_api.transformer
|
|
@@ -88,10 +211,12 @@ def add_dynamical_decoupling(
|
|
|
88
211
|
circuit: 'cirq.AbstractCircuit',
|
|
89
212
|
*,
|
|
90
213
|
context: Optional['cirq.TransformerContext'] = None,
|
|
91
|
-
schema: Union[str,
|
|
214
|
+
schema: Union[str, Tuple['cirq.Gate', ...]] = 'DEFAULT',
|
|
215
|
+
single_qubit_gate_moments_only: bool = True,
|
|
92
216
|
) -> 'cirq.Circuit':
|
|
93
|
-
"""Adds dynamical decoupling gate operations to
|
|
94
|
-
This transformer
|
|
217
|
+
"""Adds dynamical decoupling gate operations to a given circuit.
|
|
218
|
+
This transformer might add a new moment after each piece of Clifford moments, so the original
|
|
219
|
+
moment structure could change.
|
|
95
220
|
|
|
96
221
|
Args:
|
|
97
222
|
circuit: Input circuit to transform.
|
|
@@ -99,24 +224,70 @@ def add_dynamical_decoupling(
|
|
|
99
224
|
schema: Dynamical decoupling schema name or a dynamical decoupling sequence.
|
|
100
225
|
If a schema is specified, provided dynamical decouping sequence will be used.
|
|
101
226
|
Otherwise, customized dynamical decoupling sequence will be applied.
|
|
227
|
+
single_qubit_gate_moments_only: If set True, dynamical decoupling operation will only be
|
|
228
|
+
added in single-qubit gate moments.
|
|
102
229
|
|
|
103
230
|
Returns:
|
|
104
231
|
A copy of the input circuit with dynamical decoupling operations.
|
|
105
232
|
"""
|
|
106
|
-
|
|
107
|
-
|
|
233
|
+
base_dd_sequence: Tuple['cirq.Gate', ...] = _parse_dd_sequence(schema)
|
|
234
|
+
mutable_circuit = circuit.unfreeze(copy=True)
|
|
108
235
|
|
|
109
|
-
|
|
236
|
+
pauli_map: Dict['cirq.Gate', 'cirq.Pauli'] = {}
|
|
237
|
+
for gate in base_dd_sequence:
|
|
238
|
+
pauli_gate = _pauli_up_to_global_phase(gate)
|
|
239
|
+
if pauli_gate is not None:
|
|
240
|
+
pauli_map[gate] = pauli_gate
|
|
110
241
|
|
|
242
|
+
busy_moment_range_by_qubit: Dict['cirq.Qid', list[int]] = {
|
|
243
|
+
q: [len(circuit), -1] for q in circuit.all_qubits()
|
|
244
|
+
}
|
|
111
245
|
for moment_id, moment in enumerate(circuit):
|
|
112
246
|
for q in moment.qubits:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
247
|
+
busy_moment_range_by_qubit[q][0] = min(busy_moment_range_by_qubit[q][0], moment_id)
|
|
248
|
+
busy_moment_range_by_qubit[q][1] = max(busy_moment_range_by_qubit[q][1], moment_id)
|
|
249
|
+
clifford_pieces = _get_clifford_pieces(circuit)
|
|
250
|
+
|
|
251
|
+
insert_intos: list[Tuple[int, 'cirq.Operation']] = []
|
|
252
|
+
insert_moments: list[Tuple[int, 'cirq.Moment']] = []
|
|
253
|
+
for l, r in clifford_pieces: # [l, r)
|
|
254
|
+
# A PauliString stores the result of 'pulling' Pauli gates past each operations
|
|
255
|
+
# right before the current moment.
|
|
256
|
+
pulled_through: 'cirq.PauliString' = cirq.PauliString()
|
|
257
|
+
iter_by_qubits = {q: cycle(base_dd_sequence) for q in circuit.all_qubits()}
|
|
258
|
+
|
|
259
|
+
# Iterate over the Clifford piece.
|
|
260
|
+
for moment_id in range(l, r):
|
|
261
|
+
moment = circuit.moments[moment_id]
|
|
262
|
+
|
|
263
|
+
# Insert
|
|
264
|
+
if _is_insertable_moment(moment, single_qubit_gate_moments_only):
|
|
265
|
+
for q in circuit.all_qubits() - moment.qubits:
|
|
266
|
+
if (
|
|
267
|
+
busy_moment_range_by_qubit[q][0]
|
|
268
|
+
< moment_id
|
|
269
|
+
< busy_moment_range_by_qubit[q][1]
|
|
270
|
+
):
|
|
271
|
+
insert_gate = next(iter_by_qubits[q])
|
|
272
|
+
insert_intos.append((moment_id, insert_gate.on(q)))
|
|
273
|
+
pulled_through *= pauli_map[insert_gate].on(q)
|
|
274
|
+
|
|
275
|
+
# Pull through
|
|
276
|
+
pulled_through = _calc_pulled_through(moment, pulled_through)
|
|
277
|
+
|
|
278
|
+
mutable_circuit.batch_insert_into(insert_intos)
|
|
279
|
+
insert_intos.clear()
|
|
280
|
+
|
|
281
|
+
pulled_through = _merge_pulled_through(
|
|
282
|
+
mutable_circuit, pulled_through, (l, r), single_qubit_gate_moments_only
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# Insert a new moment if there are remaining pulled through operations.
|
|
286
|
+
new_moment_ops = []
|
|
287
|
+
for affected_q, combined_op_in_pauli in pulled_through.items():
|
|
288
|
+
new_moment_ops.append(combined_op_in_pauli.on(affected_q))
|
|
289
|
+
if len(new_moment_ops) != 0:
|
|
290
|
+
insert_moments.append((r, cirq.Moment(new_moment_ops)))
|
|
119
291
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return updated_circuit
|
|
292
|
+
mutable_circuit.batch_insert(insert_moments)
|
|
293
|
+
return mutable_circuit
|
|
@@ -12,26 +12,54 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from typing import Sequence, Union
|
|
15
|
+
from typing import Sequence, Tuple, Union
|
|
16
16
|
import cirq
|
|
17
17
|
from cirq import add_dynamical_decoupling
|
|
18
18
|
import pytest
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def assert_sim_eq(circuit1: 'cirq.AbstractCircuit', circuit2: 'cirq.AbstractCircuit'):
|
|
23
|
+
# Simulate 2 circuits and compare final states.
|
|
24
|
+
sampler = cirq.Simulator(dtype=np.complex128)
|
|
25
|
+
psi0 = sampler.simulate(cirq.drop_terminal_measurements(circuit1)).final_state_vector
|
|
26
|
+
psi1 = sampler.simulate(cirq.drop_terminal_measurements(circuit2)).final_state_vector
|
|
27
|
+
|
|
28
|
+
assert np.isclose(np.abs(np.vdot(psi0, psi1)) ** 2, 1.0)
|
|
19
29
|
|
|
20
30
|
|
|
21
31
|
def assert_dd(
|
|
22
|
-
input_circuit: cirq.
|
|
23
|
-
expected_circuit: cirq.
|
|
24
|
-
schema: Union[str,
|
|
32
|
+
input_circuit: 'cirq.AbstractCircuit',
|
|
33
|
+
expected_circuit: 'cirq.AbstractCircuit',
|
|
34
|
+
schema: Union[str, Tuple['cirq.Gate', ...]] = 'DEFAULT',
|
|
35
|
+
single_qubit_gate_moments_only: bool = True,
|
|
25
36
|
):
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
transformed_circuit = add_dynamical_decoupling(
|
|
38
|
+
input_circuit, schema=schema, single_qubit_gate_moments_only=single_qubit_gate_moments_only
|
|
39
|
+
).freeze()
|
|
40
|
+
cirq.testing.assert_same_circuits(transformed_circuit, expected_circuit)
|
|
41
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
42
|
+
cirq.drop_terminal_measurements(input_circuit),
|
|
43
|
+
cirq.drop_terminal_measurements(transformed_circuit),
|
|
44
|
+
{q: q for q in input_circuit.all_qubits()},
|
|
45
|
+
)
|
|
46
|
+
assert_sim_eq(input_circuit, transformed_circuit)
|
|
28
47
|
|
|
29
48
|
|
|
30
|
-
def
|
|
49
|
+
def test_no_insertion():
|
|
50
|
+
"""Test case diagrams.
|
|
51
|
+
Input:
|
|
52
|
+
a: ───H───@───────
|
|
53
|
+
│
|
|
54
|
+
b: ───────X───H───
|
|
55
|
+
Output:
|
|
56
|
+
a: ───H───@───────
|
|
57
|
+
│
|
|
58
|
+
b: ───────X───H───
|
|
59
|
+
"""
|
|
31
60
|
a = cirq.NamedQubit('a')
|
|
32
61
|
b = cirq.NamedQubit('b')
|
|
33
62
|
|
|
34
|
-
# No insertion as there is no room for a dd sequence.
|
|
35
63
|
assert_dd(
|
|
36
64
|
input_circuit=cirq.Circuit(
|
|
37
65
|
cirq.Moment(cirq.H(a)), cirq.Moment(cirq.CNOT(a, b)), cirq.Moment(cirq.H(b))
|
|
@@ -40,6 +68,7 @@ def test_no_insert_due_to_no_consecutive_moments():
|
|
|
40
68
|
cirq.Moment(cirq.H(a)), cirq.Moment(cirq.CNOT(a, b)), cirq.Moment(cirq.H(b))
|
|
41
69
|
),
|
|
42
70
|
schema='XX_PAIR',
|
|
71
|
+
single_qubit_gate_moments_only=False,
|
|
43
72
|
)
|
|
44
73
|
|
|
45
74
|
|
|
@@ -53,6 +82,14 @@ def test_no_insert_due_to_no_consecutive_moments():
|
|
|
53
82
|
],
|
|
54
83
|
)
|
|
55
84
|
def test_insert_provided_schema(schema: str, inserted_gates: Sequence['cirq.Gate']):
|
|
85
|
+
"""Test case diagrams.
|
|
86
|
+
Input:
|
|
87
|
+
a: ───H───@───────────M───
|
|
88
|
+
│
|
|
89
|
+
b: ───────X───@───@───M───
|
|
90
|
+
│ │
|
|
91
|
+
c: ───────────X───X───M───
|
|
92
|
+
"""
|
|
56
93
|
a = cirq.NamedQubit('a')
|
|
57
94
|
b = cirq.NamedQubit('b')
|
|
58
95
|
c = cirq.NamedQubit('c')
|
|
@@ -62,21 +99,35 @@ def test_insert_provided_schema(schema: str, inserted_gates: Sequence['cirq.Gate
|
|
|
62
99
|
cirq.Moment(cirq.CNOT(a, b)),
|
|
63
100
|
cirq.Moment(cirq.CNOT(b, c)),
|
|
64
101
|
cirq.Moment(cirq.CNOT(b, c)),
|
|
65
|
-
cirq.Moment(cirq.
|
|
102
|
+
cirq.Moment([cirq.M(qubit) for qubit in [a, b, c]]),
|
|
66
103
|
)
|
|
67
104
|
expected_circuit = cirq.Circuit(
|
|
68
105
|
cirq.Moment(cirq.H(a)),
|
|
69
106
|
cirq.Moment(cirq.CNOT(a, b)),
|
|
70
107
|
cirq.Moment(cirq.CNOT(b, c), inserted_gates[0](a)),
|
|
71
108
|
cirq.Moment(cirq.CNOT(b, c), inserted_gates[1](a)),
|
|
72
|
-
cirq.Moment(cirq.
|
|
109
|
+
cirq.Moment([cirq.M(qubit) for qubit in [a, b, c]]),
|
|
73
110
|
)
|
|
74
111
|
|
|
75
112
|
# Insert one dynamical decoupling sequence in idle moments.
|
|
76
|
-
assert_dd(input_circuit, expected_circuit, schema=schema)
|
|
113
|
+
assert_dd(input_circuit, expected_circuit, schema=schema, single_qubit_gate_moments_only=False)
|
|
77
114
|
|
|
78
115
|
|
|
79
116
|
def test_insert_by_customized_dd_sequence():
|
|
117
|
+
"""Test case diagrams.
|
|
118
|
+
Input:
|
|
119
|
+
a: ───H───@───────────────────H───
|
|
120
|
+
│
|
|
121
|
+
b: ───────X───@───@───@───@───H───
|
|
122
|
+
│ │ │ │
|
|
123
|
+
c: ───────────X───X───X───X───H───
|
|
124
|
+
Output:
|
|
125
|
+
a: ───H───@───X───X───Y───Y───H───
|
|
126
|
+
│
|
|
127
|
+
b: ───────X───@───@───@───@───H───
|
|
128
|
+
│ │ │ │
|
|
129
|
+
c: ───────────X───X───X───X───H───
|
|
130
|
+
"""
|
|
80
131
|
a = cirq.NamedQubit('a')
|
|
81
132
|
b = cirq.NamedQubit('b')
|
|
82
133
|
c = cirq.NamedQubit('c')
|
|
@@ -89,7 +140,7 @@ def test_insert_by_customized_dd_sequence():
|
|
|
89
140
|
cirq.Moment(cirq.CNOT(b, c)),
|
|
90
141
|
cirq.Moment(cirq.CNOT(b, c)),
|
|
91
142
|
cirq.Moment(cirq.CNOT(b, c)),
|
|
92
|
-
cirq.Moment(cirq.
|
|
143
|
+
cirq.Moment([cirq.H(qubit) for qubit in [a, b, c]]),
|
|
93
144
|
),
|
|
94
145
|
expected_circuit=cirq.Circuit(
|
|
95
146
|
cirq.Moment(cirq.H(a)),
|
|
@@ -98,9 +149,84 @@ def test_insert_by_customized_dd_sequence():
|
|
|
98
149
|
cirq.Moment(cirq.CNOT(b, c), cirq.X(a)),
|
|
99
150
|
cirq.Moment(cirq.CNOT(b, c), cirq.Y(a)),
|
|
100
151
|
cirq.Moment(cirq.CNOT(b, c), cirq.Y(a)),
|
|
101
|
-
cirq.Moment(cirq.
|
|
152
|
+
cirq.Moment([cirq.H(qubit) for qubit in [a, b, c]]),
|
|
102
153
|
),
|
|
103
154
|
schema=[cirq.X, cirq.X, cirq.Y, cirq.Y],
|
|
155
|
+
single_qubit_gate_moments_only=False,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@pytest.mark.parametrize('single_qubit_gate_moments_only', [True, False])
|
|
160
|
+
def test_pull_through_h_gate_case1(single_qubit_gate_moments_only: bool):
|
|
161
|
+
"""Test case diagrams.
|
|
162
|
+
Input:
|
|
163
|
+
a: ───H───────H───────@───
|
|
164
|
+
│
|
|
165
|
+
b: ───H───H───H───H───X───
|
|
166
|
+
Output:
|
|
167
|
+
a: ───H───X───H───X───@───Y───
|
|
168
|
+
│
|
|
169
|
+
b: ───H───H───H───H───X───X───
|
|
170
|
+
"""
|
|
171
|
+
a = cirq.NamedQubit('a')
|
|
172
|
+
b = cirq.NamedQubit('b')
|
|
173
|
+
|
|
174
|
+
assert_dd(
|
|
175
|
+
input_circuit=cirq.Circuit(
|
|
176
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
177
|
+
cirq.Moment(cirq.H(b)),
|
|
178
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
179
|
+
cirq.Moment(cirq.H(b)),
|
|
180
|
+
cirq.Moment(cirq.CNOT(a, b)),
|
|
181
|
+
),
|
|
182
|
+
expected_circuit=cirq.Circuit(
|
|
183
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
184
|
+
cirq.Moment(cirq.H(b), cirq.X(a)),
|
|
185
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
186
|
+
cirq.Moment(cirq.H(b), cirq.X(a)),
|
|
187
|
+
cirq.Moment(cirq.CNOT(a, b)),
|
|
188
|
+
cirq.Moment(cirq.Y(a), cirq.X(b)),
|
|
189
|
+
),
|
|
190
|
+
schema="XX_PAIR",
|
|
191
|
+
single_qubit_gate_moments_only=single_qubit_gate_moments_only,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@pytest.mark.parametrize('single_qubit_gate_moments_only', [True, False])
|
|
196
|
+
def test_pull_through_h_gate_case2(single_qubit_gate_moments_only: bool):
|
|
197
|
+
"""Test case diagrams.
|
|
198
|
+
Input:
|
|
199
|
+
a: ───H───────H───────H───
|
|
200
|
+
|
|
201
|
+
b: ───H───H───H───H───H───
|
|
202
|
+
Output:
|
|
203
|
+
a: ───H───X───H───X───PhXZ(a=0.5,x=0.5,z=1)───
|
|
204
|
+
|
|
205
|
+
b: ───H───H───H───H───H───────────────────────
|
|
206
|
+
"""
|
|
207
|
+
a = cirq.NamedQubit('a')
|
|
208
|
+
b = cirq.NamedQubit('b')
|
|
209
|
+
|
|
210
|
+
assert_dd(
|
|
211
|
+
input_circuit=cirq.Circuit(
|
|
212
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
213
|
+
cirq.Moment(cirq.H(b)),
|
|
214
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
215
|
+
cirq.Moment(cirq.H(b)),
|
|
216
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
217
|
+
),
|
|
218
|
+
expected_circuit=cirq.Circuit(
|
|
219
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
220
|
+
cirq.Moment(cirq.H(b), cirq.X(a)),
|
|
221
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
222
|
+
cirq.Moment(cirq.H(b), cirq.X(a)),
|
|
223
|
+
cirq.Moment(
|
|
224
|
+
cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=1).on(a),
|
|
225
|
+
cirq.H(b),
|
|
226
|
+
),
|
|
227
|
+
),
|
|
228
|
+
schema="XX_PAIR",
|
|
229
|
+
single_qubit_gate_moments_only=single_qubit_gate_moments_only,
|
|
104
230
|
)
|
|
105
231
|
|
|
106
232
|
|
|
@@ -110,14 +236,393 @@ def test_insert_by_customized_dd_sequence():
|
|
|
110
236
|
('INVALID_SCHEMA', 'Invalid schema name.'),
|
|
111
237
|
([cirq.X], 'Invalid dynamical decoupling sequence. Expect more than one gates.'),
|
|
112
238
|
(
|
|
113
|
-
[cirq.X, cirq.
|
|
239
|
+
[cirq.X, cirq.Y],
|
|
114
240
|
'Invalid dynamical decoupling sequence. Expect sequence production equals identity'
|
|
115
241
|
' up to a global phase, got',
|
|
116
242
|
),
|
|
243
|
+
(
|
|
244
|
+
[cirq.H, cirq.H],
|
|
245
|
+
'Dynamical decoupling sequence should only contain gates that are essentially'
|
|
246
|
+
' Pauli gates.',
|
|
247
|
+
),
|
|
117
248
|
],
|
|
118
249
|
)
|
|
119
|
-
def test_invalid_dd_schema(schema: Union[str,
|
|
250
|
+
def test_invalid_dd_schema(schema: Union[str, Tuple['cirq.Gate', ...]], error_msg_regex):
|
|
120
251
|
a = cirq.NamedQubit('a')
|
|
121
252
|
input_circuit = cirq.Circuit(cirq.H(a))
|
|
122
253
|
with pytest.raises(ValueError, match=error_msg_regex):
|
|
123
|
-
add_dynamical_decoupling(input_circuit, schema=schema)
|
|
254
|
+
add_dynamical_decoupling(input_circuit, schema=schema, single_qubit_gate_moments_only=False)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def test_single_qubit_gate_moments_only_no_updates_succeeds():
|
|
258
|
+
qubits = cirq.LineQubit.range(9)
|
|
259
|
+
input_circuit = cirq.Circuit(
|
|
260
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [3, 4, 5]]),
|
|
261
|
+
cirq.Moment(cirq.CZ(*qubits[4:6])),
|
|
262
|
+
cirq.Moment(cirq.CZ(*qubits[3:5])),
|
|
263
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [2, 3, 5, 6]]),
|
|
264
|
+
cirq.Moment(cirq.CZ(*qubits[2:4]), cirq.CNOT(*qubits[5:7])),
|
|
265
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [1, 2, 6, 7]]),
|
|
266
|
+
cirq.Moment(cirq.CZ(*qubits[1:3]), cirq.CNOT(*qubits[6:8])),
|
|
267
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [0, 1, 7, 8]]),
|
|
268
|
+
cirq.Moment(cirq.CZ(*qubits[0:2]), cirq.CNOT(*qubits[7:])),
|
|
269
|
+
)
|
|
270
|
+
add_dynamical_decoupling(input_circuit, schema='X_XINV', single_qubit_gate_moments_only=True)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def test_scattered_circuit():
|
|
274
|
+
"""Test case diagrams.
|
|
275
|
+
Input:
|
|
276
|
+
0: ───────────────────────────────H───@───H───
|
|
277
|
+
│
|
|
278
|
+
1: ───────────────────────H───@───H───@───H───
|
|
279
|
+
│
|
|
280
|
+
2: ───────────────H───@───H───@───────────H───
|
|
281
|
+
│
|
|
282
|
+
3: ───H───────@───H───@───────────────────H───
|
|
283
|
+
│
|
|
284
|
+
4: ───H───@───@───────────────────────────H───
|
|
285
|
+
│
|
|
286
|
+
5: ───H───@───────H───@───────────────────H───
|
|
287
|
+
│
|
|
288
|
+
6: ───────────────H───@───H───@───────────H───
|
|
289
|
+
│
|
|
290
|
+
7: ───────────────────────H───@───H───@───H───
|
|
291
|
+
│
|
|
292
|
+
8: ───────────────────────────────H───@───H───
|
|
293
|
+
|
|
294
|
+
Output (single_qubit_gate_moment_only_on):
|
|
295
|
+
0: ───────────────────────────────H───@───H────────────────────────
|
|
296
|
+
│
|
|
297
|
+
1: ───────────────────────H───@───H───@───H────────────────────────
|
|
298
|
+
│
|
|
299
|
+
2: ───────────────H───@───H───@───X───────PhXZ(a=-0.5,x=0.5,z=0)───
|
|
300
|
+
│
|
|
301
|
+
3: ───H───────@───H───@───X───────Y───────PhXZ(a=0.5,x=0.5,z=0)────
|
|
302
|
+
│
|
|
303
|
+
4: ───H───@───@───X───────Y───────X───────PhXZ(a=0.5,x=0.5,z=-1)───
|
|
304
|
+
│
|
|
305
|
+
5: ───H───@───────H───@───X───────Y───────PhXZ(a=0.5,x=0.5,z=0)────
|
|
306
|
+
│
|
|
307
|
+
6: ───────────────H───@───H───@───X───────PhXZ(a=-0.5,x=0.5,z=0)───
|
|
308
|
+
│
|
|
309
|
+
7: ───────────────────────H───@───H───@───H────────────────────────
|
|
310
|
+
│
|
|
311
|
+
8: ───────────────────────────────H───@───H────────────────────────
|
|
312
|
+
|
|
313
|
+
Output (single_qubit_gate_moment_only_off):
|
|
314
|
+
0: ───────────────────────────────H───@───H───────────────────────
|
|
315
|
+
│
|
|
316
|
+
1: ───────────────────────H───@───H───@───H───────────────────────
|
|
317
|
+
│
|
|
318
|
+
2: ───────────────H───@───H───@───X───Y───PhXZ(a=0.5,x=0.5,z=0)───
|
|
319
|
+
│
|
|
320
|
+
3: ───H───X───@───H───@───Y───X───Y───X───PhXZ(a=0.5,x=0.5,z=0)───
|
|
321
|
+
│
|
|
322
|
+
4: ───H───@───@───X───Y───X───Y───X───Y───H───────────────────────
|
|
323
|
+
│
|
|
324
|
+
5: ───H───@───X───H───@───Y───X───Y───X───PhXZ(a=0.5,x=0.5,z=0)───
|
|
325
|
+
│
|
|
326
|
+
6: ───────────────H───@───H───@───X───Y───PhXZ(a=0.5,x=0.5,z=0)───
|
|
327
|
+
│
|
|
328
|
+
7: ───────────────────────H───@───H───@───H───────────────────────
|
|
329
|
+
│
|
|
330
|
+
8: ───────────────────────────────H───@───H───────────────────────
|
|
331
|
+
"""
|
|
332
|
+
qubits = cirq.LineQubit.range(9)
|
|
333
|
+
input_circuit = cirq.Circuit(
|
|
334
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [3, 4, 5]]),
|
|
335
|
+
cirq.Moment(cirq.CZ(*qubits[4:6])),
|
|
336
|
+
cirq.Moment(cirq.CZ(*qubits[3:5])),
|
|
337
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [2, 3, 5, 6]]),
|
|
338
|
+
cirq.Moment(cirq.CZ(*qubits[2:4]), cirq.CZ(*qubits[5:7])),
|
|
339
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [1, 2, 6, 7]]),
|
|
340
|
+
cirq.Moment(cirq.CZ(*qubits[1:3]), cirq.CZ(*qubits[6:8])),
|
|
341
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [0, 1, 7, 8]]),
|
|
342
|
+
cirq.Moment(cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[7:])),
|
|
343
|
+
cirq.Moment([cirq.H(q) for q in qubits]),
|
|
344
|
+
)
|
|
345
|
+
expected_circuit_single_qubit_gate_on = cirq.Circuit(
|
|
346
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [3, 4, 5]]),
|
|
347
|
+
cirq.Moment(cirq.CZ(*qubits[4:6])),
|
|
348
|
+
cirq.Moment(cirq.CZ(*qubits[3:5])),
|
|
349
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [2, 3, 5, 6]] + [cirq.X(qubits[4])]),
|
|
350
|
+
cirq.Moment(cirq.CZ(*qubits[2:4]), cirq.CZ(*qubits[5:7])),
|
|
351
|
+
cirq.Moment(
|
|
352
|
+
[cirq.H(qubits[i]) for i in [1, 2, 6, 7]]
|
|
353
|
+
+ [cirq.X(qubits[i]) for i in [3, 5]]
|
|
354
|
+
+ [cirq.Y(qubits[4])]
|
|
355
|
+
),
|
|
356
|
+
cirq.Moment(cirq.CZ(*qubits[1:3]), cirq.CZ(*qubits[6:8])),
|
|
357
|
+
cirq.Moment(
|
|
358
|
+
[cirq.H(qubits[i]) for i in [0, 1, 7, 8]]
|
|
359
|
+
+ [cirq.X(qubits[i]) for i in [2, 4, 6]]
|
|
360
|
+
+ [cirq.Y(qubits[i]) for i in [3, 5]]
|
|
361
|
+
),
|
|
362
|
+
cirq.Moment(cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[7:])),
|
|
363
|
+
cirq.Moment(
|
|
364
|
+
[cirq.H(qubits[i]) for i in [0, 1, 7, 8]]
|
|
365
|
+
+ [
|
|
366
|
+
cirq.PhasedXZGate(axis_phase_exponent=-0.5, x_exponent=0.5, z_exponent=0).on(
|
|
367
|
+
qubits[2]
|
|
368
|
+
),
|
|
369
|
+
cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=0).on(
|
|
370
|
+
qubits[3]
|
|
371
|
+
),
|
|
372
|
+
cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=-1).on(
|
|
373
|
+
qubits[4]
|
|
374
|
+
),
|
|
375
|
+
cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=0).on(
|
|
376
|
+
qubits[5]
|
|
377
|
+
),
|
|
378
|
+
cirq.PhasedXZGate(axis_phase_exponent=-0.5, x_exponent=0.5, z_exponent=0).on(
|
|
379
|
+
qubits[6]
|
|
380
|
+
),
|
|
381
|
+
]
|
|
382
|
+
),
|
|
383
|
+
)
|
|
384
|
+
expected_circuit_single_qubit_gates_off = cirq.Circuit(
|
|
385
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [3, 4, 5]]),
|
|
386
|
+
cirq.Moment(cirq.CZ(*qubits[4:6]), cirq.X(qubits[3])),
|
|
387
|
+
cirq.Moment(cirq.CZ(*qubits[3:5]), cirq.X(qubits[5])),
|
|
388
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [2, 3, 5, 6]] + [cirq.X(qubits[i]) for i in [4]]),
|
|
389
|
+
cirq.Moment(cirq.CZ(*qubits[2:4]), cirq.CZ(*qubits[5:7]), cirq.Y(qubits[4])),
|
|
390
|
+
cirq.Moment(
|
|
391
|
+
[cirq.H(qubits[i]) for i in [1, 2, 6, 7]]
|
|
392
|
+
+ [cirq.Y(qubits[i]) for i in [3, 5]]
|
|
393
|
+
+ [cirq.X(qubits[4])]
|
|
394
|
+
),
|
|
395
|
+
cirq.Moment(
|
|
396
|
+
[cirq.CZ(*qubits[1:3]), cirq.CZ(*qubits[6:8])]
|
|
397
|
+
+ [cirq.X(qubits[i]) for i in [3, 5]]
|
|
398
|
+
+ [cirq.Y(qubits[4])]
|
|
399
|
+
),
|
|
400
|
+
cirq.Moment(
|
|
401
|
+
[cirq.H(qubits[i]) for i in [0, 1, 7, 8]]
|
|
402
|
+
+ [cirq.X(qubits[i]) for i in [2, 4, 6]]
|
|
403
|
+
+ [cirq.Y(qubits[i]) for i in [3, 5]]
|
|
404
|
+
),
|
|
405
|
+
cirq.Moment(
|
|
406
|
+
[cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[7:])]
|
|
407
|
+
+ [cirq.X(qubits[i]) for i in [3, 5]]
|
|
408
|
+
+ [cirq.Y(qubits[i]) for i in [2, 4, 6]]
|
|
409
|
+
),
|
|
410
|
+
cirq.Moment(
|
|
411
|
+
[cirq.H(qubits[i]) for i in [0, 1, 4, 7, 8]]
|
|
412
|
+
+ [
|
|
413
|
+
cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=0).on(
|
|
414
|
+
qubits[i]
|
|
415
|
+
)
|
|
416
|
+
for i in [2, 3, 5, 6]
|
|
417
|
+
]
|
|
418
|
+
),
|
|
419
|
+
)
|
|
420
|
+
assert_dd(
|
|
421
|
+
input_circuit,
|
|
422
|
+
expected_circuit_single_qubit_gate_on,
|
|
423
|
+
schema='DEFAULT',
|
|
424
|
+
single_qubit_gate_moments_only=True,
|
|
425
|
+
)
|
|
426
|
+
assert_dd(
|
|
427
|
+
input_circuit,
|
|
428
|
+
expected_circuit_single_qubit_gates_off,
|
|
429
|
+
schema='DEFAULT',
|
|
430
|
+
single_qubit_gate_moments_only=False,
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def test_scattered_circuit2():
|
|
435
|
+
"""Test case diagrams.
|
|
436
|
+
Input:
|
|
437
|
+
0: ───────────────────@───
|
|
438
|
+
│
|
|
439
|
+
1: ───────────────@───@───
|
|
440
|
+
│
|
|
441
|
+
2: ───────────@───@───────
|
|
442
|
+
│
|
|
443
|
+
3: ───────@───@───────────
|
|
444
|
+
│
|
|
445
|
+
4: ───@───@───────────────
|
|
446
|
+
│
|
|
447
|
+
5: ───@───────@───────────
|
|
448
|
+
│
|
|
449
|
+
6: ───────────@───@───────
|
|
450
|
+
│
|
|
451
|
+
7: ───────────────@───@───
|
|
452
|
+
│
|
|
453
|
+
8: ───────────────────@───
|
|
454
|
+
Output:
|
|
455
|
+
0: ───────────────────@───
|
|
456
|
+
│
|
|
457
|
+
1: ───────────────@───@───
|
|
458
|
+
│
|
|
459
|
+
2: ───────────@───@───────
|
|
460
|
+
│
|
|
461
|
+
3: ───────@───@───────────
|
|
462
|
+
│
|
|
463
|
+
4: ───@───@───────────────
|
|
464
|
+
│
|
|
465
|
+
5: ───@───X───@───X───────
|
|
466
|
+
│
|
|
467
|
+
6: ───────────@───@───Z───
|
|
468
|
+
│
|
|
469
|
+
7: ───────────────@───@───
|
|
470
|
+
│
|
|
471
|
+
8: ───────────────────@───
|
|
472
|
+
"""
|
|
473
|
+
qubits = cirq.LineQubit.range(9)
|
|
474
|
+
assert_dd(
|
|
475
|
+
input_circuit=cirq.Circuit(
|
|
476
|
+
cirq.Moment(cirq.CZ(*qubits[4:6])),
|
|
477
|
+
cirq.Moment(cirq.CZ(*qubits[3:5])),
|
|
478
|
+
cirq.Moment(cirq.CZ(*qubits[2:4]), cirq.CZ(*qubits[5:7])),
|
|
479
|
+
cirq.Moment(cirq.CZ(*qubits[1:3]), cirq.CZ(*qubits[6:8])),
|
|
480
|
+
cirq.Moment(cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[7:])),
|
|
481
|
+
),
|
|
482
|
+
expected_circuit=cirq.Circuit(
|
|
483
|
+
cirq.Moment(cirq.CZ(*qubits[4:6])),
|
|
484
|
+
cirq.Moment(cirq.CZ(*qubits[3:5]), cirq.X(qubits[5])),
|
|
485
|
+
cirq.Moment(cirq.CZ(*qubits[2:4]), cirq.CZ(*qubits[5:7])),
|
|
486
|
+
cirq.Moment(cirq.CZ(*qubits[1:3]), cirq.CZ(*qubits[6:8]), cirq.X(qubits[5])),
|
|
487
|
+
cirq.Moment(cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[7:]), cirq.Z(qubits[6])),
|
|
488
|
+
),
|
|
489
|
+
schema="XX_PAIR",
|
|
490
|
+
single_qubit_gate_moments_only=False,
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def test_pull_through_chain():
|
|
495
|
+
"""Test case diagrams.
|
|
496
|
+
Input:
|
|
497
|
+
0: ───X───────×───────────X───
|
|
498
|
+
│
|
|
499
|
+
1: ───────Y───×───×───────X───
|
|
500
|
+
│
|
|
501
|
+
2: ───────────────×───×───X───
|
|
502
|
+
│
|
|
503
|
+
3: ───────────────────×───X───
|
|
504
|
+
Output:
|
|
505
|
+
0: ───X───X───×───X───X───X───
|
|
506
|
+
│
|
|
507
|
+
1: ───────Y───×───×───X───I───
|
|
508
|
+
│
|
|
509
|
+
2: ───────────────×───×───X───
|
|
510
|
+
│
|
|
511
|
+
3: ───────────────────×───I───
|
|
512
|
+
"""
|
|
513
|
+
qubits = cirq.LineQubit.range(4)
|
|
514
|
+
assert_dd(
|
|
515
|
+
input_circuit=cirq.Circuit(
|
|
516
|
+
cirq.Moment(cirq.X(qubits[0])),
|
|
517
|
+
cirq.Moment(cirq.Y(qubits[1])),
|
|
518
|
+
cirq.Moment(cirq.SWAP(*qubits[0:2])),
|
|
519
|
+
cirq.Moment(cirq.SWAP(*qubits[1:3])),
|
|
520
|
+
cirq.Moment(cirq.SWAP(*qubits[2:4])),
|
|
521
|
+
cirq.Moment([cirq.X(qubits[i]) for i in range(4)]),
|
|
522
|
+
),
|
|
523
|
+
expected_circuit=cirq.Circuit(
|
|
524
|
+
cirq.Moment(cirq.X(qubits[0])),
|
|
525
|
+
cirq.Moment(cirq.Y(qubits[1]), cirq.X(qubits[0])),
|
|
526
|
+
cirq.Moment(cirq.SWAP(*qubits[0:2])),
|
|
527
|
+
cirq.Moment([cirq.SWAP(*qubits[1:3])] + [cirq.X(qubits[0])]),
|
|
528
|
+
cirq.Moment([cirq.SWAP(*qubits[2:4])] + [cirq.X(qubits[0]), cirq.X(qubits[1])]),
|
|
529
|
+
cirq.Moment(cirq.X(qubits[0]), cirq.I(qubits[1]), cirq.X(qubits[2]), cirq.I(qubits[3])),
|
|
530
|
+
),
|
|
531
|
+
schema='XX_PAIR',
|
|
532
|
+
single_qubit_gate_moments_only=False,
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
def test_multiple_clifford_pieces():
|
|
537
|
+
"""Test case diagrams.
|
|
538
|
+
Input:
|
|
539
|
+
a: ───H───────H───────@───────────H───────H───
|
|
540
|
+
│
|
|
541
|
+
b: ───H───H───H───H───@^0.5───H───H───H───H───
|
|
542
|
+
Output:
|
|
543
|
+
a: ───H───X───H───PhXZ(a=0.5,x=0,z=-1)───@───────X───H───X───PhXZ(a=0.5,x=0.5,z=-1)───
|
|
544
|
+
│
|
|
545
|
+
b: ───H───H───H───H──────────────────────@^0.5───H───H───H───H────────────────────────
|
|
546
|
+
"""
|
|
547
|
+
a = cirq.NamedQubit('a')
|
|
548
|
+
b = cirq.NamedQubit('b')
|
|
549
|
+
assert_dd(
|
|
550
|
+
input_circuit=cirq.Circuit(
|
|
551
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
552
|
+
cirq.Moment(cirq.H(b)),
|
|
553
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
554
|
+
cirq.Moment(cirq.H(b)),
|
|
555
|
+
cirq.Moment(cirq.CZPowGate(exponent=0.5).on(a, b)),
|
|
556
|
+
cirq.Moment(cirq.H(b)),
|
|
557
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
558
|
+
cirq.Moment(cirq.H(b)),
|
|
559
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
560
|
+
),
|
|
561
|
+
expected_circuit=cirq.Circuit(
|
|
562
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
563
|
+
cirq.Moment(cirq.H(b), cirq.X(a)),
|
|
564
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
565
|
+
cirq.Moment(
|
|
566
|
+
cirq.H(b),
|
|
567
|
+
cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0, z_exponent=-1).on(a),
|
|
568
|
+
),
|
|
569
|
+
cirq.Moment(cirq.CZPowGate(exponent=0.5).on(a, b)),
|
|
570
|
+
cirq.Moment(cirq.H(b), cirq.X(a)),
|
|
571
|
+
cirq.Moment(cirq.H(a), cirq.H(b)),
|
|
572
|
+
cirq.Moment(cirq.H(b), cirq.X(a)),
|
|
573
|
+
cirq.Moment(
|
|
574
|
+
cirq.H(b),
|
|
575
|
+
cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=-1).on(a),
|
|
576
|
+
),
|
|
577
|
+
),
|
|
578
|
+
schema="XX_PAIR",
|
|
579
|
+
)
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
def test_with_non_clifford_measurements():
|
|
583
|
+
"""Test case diagrams.
|
|
584
|
+
Input:
|
|
585
|
+
0: ───────────H───@───H───M───
|
|
586
|
+
│
|
|
587
|
+
1: ───H───@───────@───────M───
|
|
588
|
+
│
|
|
589
|
+
2: ───H───@───H───@───────M───
|
|
590
|
+
│
|
|
591
|
+
3: ───────────H───@───H───M───
|
|
592
|
+
Output:
|
|
593
|
+
0: ───────────H───@───PhXZ(a=0.5,x=0.5,z=0)───M───
|
|
594
|
+
│
|
|
595
|
+
1: ───H───@───X───@───X───────────────────────M───
|
|
596
|
+
│
|
|
597
|
+
2: ───H───@───H───@───I───────────────────────M───
|
|
598
|
+
│
|
|
599
|
+
3: ───────────H───@───H───────────────────────M───
|
|
600
|
+
"""
|
|
601
|
+
qubits = cirq.LineQubit.range(4)
|
|
602
|
+
assert_dd(
|
|
603
|
+
input_circuit=cirq.Circuit(
|
|
604
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [1, 2]]),
|
|
605
|
+
cirq.Moment(cirq.CZ(*qubits[1:3])),
|
|
606
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [0, 2, 3]]),
|
|
607
|
+
cirq.Moment(cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[2:])),
|
|
608
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [0, 3]]),
|
|
609
|
+
cirq.Moment([cirq.M(qubits[i]) for i in [0, 1, 2, 3]]),
|
|
610
|
+
),
|
|
611
|
+
expected_circuit=cirq.Circuit(
|
|
612
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [1, 2]]),
|
|
613
|
+
cirq.Moment(cirq.CZ(*qubits[1:3])),
|
|
614
|
+
cirq.Moment([cirq.H(qubits[i]) for i in [0, 2, 3]] + [cirq.X(qubits[1])]),
|
|
615
|
+
cirq.Moment(cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[2:])),
|
|
616
|
+
cirq.Moment(
|
|
617
|
+
cirq.H(qubits[3]),
|
|
618
|
+
cirq.I(qubits[2]),
|
|
619
|
+
cirq.X(qubits[1]),
|
|
620
|
+
cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=0).on(
|
|
621
|
+
qubits[0]
|
|
622
|
+
),
|
|
623
|
+
),
|
|
624
|
+
cirq.Moment([cirq.M(qubits[i]) for i in [0, 1, 2, 3]]),
|
|
625
|
+
),
|
|
626
|
+
schema="XX_PAIR",
|
|
627
|
+
single_qubit_gate_moments_only=True,
|
|
628
|
+
)
|
{cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cirq-core
|
|
3
|
-
Version: 1.5.0.
|
|
3
|
+
Version: 1.5.0.dev20240819032820
|
|
4
4
|
Summary: A framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
|
|
5
5
|
Home-page: http://github.com/quantumlib/cirq
|
|
6
6
|
Author: The Cirq Developers
|
{cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/RECORD
RENAMED
|
@@ -4,8 +4,8 @@ cirq/_compat_test.py,sha256=Qq3ZcfgD-Nb81cEppQdJqhAyrVqXKtfXZYGXT0p-Wh0,34718
|
|
|
4
4
|
cirq/_doc.py,sha256=yDyWUD_2JDS0gShfGRb-rdqRt9-WeL7DhkqX7np0Nko,2879
|
|
5
5
|
cirq/_import.py,sha256=p9gMHJscbtDDkfHOaulvd3Aer0pwUF5AXpL89XR8dNw,8402
|
|
6
6
|
cirq/_import_test.py,sha256=6K_v0riZJXOXUphHNkGA8MY-JcmGlezFaGmvrNhm3OQ,1015
|
|
7
|
-
cirq/_version.py,sha256=
|
|
8
|
-
cirq/_version_test.py,sha256=
|
|
7
|
+
cirq/_version.py,sha256=JEiiqQfLizhjNs8BjD9lOU8j3-0umSFic8UR9I580do,1206
|
|
8
|
+
cirq/_version_test.py,sha256=IQENR-y0jVtii_k8k3Y0oD2vWNDQpblccARkug3cXNQ,147
|
|
9
9
|
cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
|
|
10
10
|
cirq/json_resolver_cache.py,sha256=ytePZtNZgKjOF2NiVpUTuotB-JKZmQNOFIFdvXqsxHw,13271
|
|
11
11
|
cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
|
|
@@ -303,8 +303,8 @@ cirq/ops/global_phase_op.py,sha256=XYnzmquhGaVY91oYm9RHo1qbX1eOx2ZqLPzLsl8jyQw,4
|
|
|
303
303
|
cirq/ops/global_phase_op_test.py,sha256=FjtUsohIYabTtiGytvPQw9Rzkqd6dlT7qrj4oltDbTI,9814
|
|
304
304
|
cirq/ops/greedy_qubit_manager.py,sha256=O9qY8GB1KGxm3B7JEjq50sGVD51bNwTSupJpi3WUeAc,4039
|
|
305
305
|
cirq/ops/greedy_qubit_manager_test.py,sha256=iVZDKes-r08raTiJHpYNmP-Dp89ok3hIU-QboL2BHdw,3300
|
|
306
|
-
cirq/ops/identity.py,sha256=
|
|
307
|
-
cirq/ops/identity_test.py,sha256
|
|
306
|
+
cirq/ops/identity.py,sha256=vS4Gown5dJWm89gNKBZ9vXQL3ijwAJZ9JFu7NtfAQw8,5827
|
|
307
|
+
cirq/ops/identity_test.py,sha256=-z5TjxNaD3_z73nGdR3RbHt6ytaYOAyYggCzwZtlQDw,7568
|
|
308
308
|
cirq/ops/kraus_channel.py,sha256=tCPAEzr_GAL5vTwI43rBoiOnT04l-ebZanuuEuYWDo8,5085
|
|
309
309
|
cirq/ops/kraus_channel_test.py,sha256=qH2Y9cngXzKCabd-Mq5xBYcM_wyL8c6KkrXw8kZr7Dc,4726
|
|
310
310
|
cirq/ops/linear_combinations.py,sha256=vK-IKHwdIBbOEaUz92JaA3uC4WTIDgUYCOCa1zZpdkw,39685
|
|
@@ -1029,8 +1029,8 @@ cirq/transformers/drop_empty_moments.py,sha256=Rtn_BrpwkLXyZBdLzwdnsnEGWTdYuf1xO
|
|
|
1029
1029
|
cirq/transformers/drop_empty_moments_test.py,sha256=G8pZmTfi8NG2NpGz_K3LZu5NQoqa-xPMCuZjwEu07xk,1907
|
|
1030
1030
|
cirq/transformers/drop_negligible_operations.py,sha256=8eyOMy7bra2wJAjORbk6QjwHiLdL5SfwRaz8D2Dazbw,2083
|
|
1031
1031
|
cirq/transformers/drop_negligible_operations_test.py,sha256=gqL6RoDPm6Zf4RxtprBenFyIsZQPUxmPur9oRl0Yr3U,3823
|
|
1032
|
-
cirq/transformers/dynamical_decoupling.py,sha256=
|
|
1033
|
-
cirq/transformers/dynamical_decoupling_test.py,sha256=
|
|
1032
|
+
cirq/transformers/dynamical_decoupling.py,sha256=OSaJy55nYJmCVgan0VBlxcXeTKPuiJMJDTnnsaKGBFs,12329
|
|
1033
|
+
cirq/transformers/dynamical_decoupling_test.py,sha256=kXngZhzV_58cPqpx-zhMmabGzaUKEN_9iS3YV7U7fEE,28410
|
|
1034
1034
|
cirq/transformers/eject_phased_paulis.py,sha256=mTgRT5aw5_c9ccTkP4Np_4YTWnLzxsMKRO8pOQ7CtYM,13955
|
|
1035
1035
|
cirq/transformers/eject_phased_paulis_test.py,sha256=-mXsfbi3V0ojC_YqoQM5otzdW4kjGusCx6F-kCv8M98,15834
|
|
1036
1036
|
cirq/transformers/eject_z.py,sha256=0kOyvh6FDfrCrrTCVfpHKNc_kNC_pBdEKoXv11kuqGA,5803
|
|
@@ -1184,8 +1184,8 @@ cirq/work/sampler.py,sha256=JEAeQQRF3bqlO9AkOf4XbrTATDI5f5JgyM_FAUCNxao,19751
|
|
|
1184
1184
|
cirq/work/sampler_test.py,sha256=B2ZsuqGT854gQtBIAh8k0LiG9Vj5wSzcGvkxOUoTcW4,13217
|
|
1185
1185
|
cirq/work/zeros_sampler.py,sha256=x1C7cup66a43n-3tm8QjhiqJa07qcJW10FxNp9jJ59Q,2356
|
|
1186
1186
|
cirq/work/zeros_sampler_test.py,sha256=JIkpBBFPJe5Ba4142vzogyWyboG1Q1ZAm0UVGgOoZn8,3279
|
|
1187
|
-
cirq_core-1.5.0.
|
|
1188
|
-
cirq_core-1.5.0.
|
|
1189
|
-
cirq_core-1.5.0.
|
|
1190
|
-
cirq_core-1.5.0.
|
|
1191
|
-
cirq_core-1.5.0.
|
|
1187
|
+
cirq_core-1.5.0.dev20240819032820.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
|
1188
|
+
cirq_core-1.5.0.dev20240819032820.dist-info/METADATA,sha256=k8f5jgbodK_sJ0g_KjxFH-jPBzF0BpZhHkoXoyfNlc0,1992
|
|
1189
|
+
cirq_core-1.5.0.dev20240819032820.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
|
1190
|
+
cirq_core-1.5.0.dev20240819032820.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
|
|
1191
|
+
cirq_core-1.5.0.dev20240819032820.dist-info/RECORD,,
|
{cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/LICENSE
RENAMED
|
File without changes
|
{cirq_core-1.5.0.dev20240814002711.dist-info → cirq_core-1.5.0.dev20240819032820.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|