cirq-core 1.7.0.dev20251027232108__py3-none-any.whl → 1.7.0.dev20251028035559__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 CHANGED
@@ -28,4 +28,4 @@ if sys.version_info < (3, 11, 0): # pragma: no cover
28
28
  'of Cirq (e.g. "python -m pip install cirq==1.5.0")'
29
29
  )
30
30
 
31
- __version__ = "1.7.0.dev20251027232108"
31
+ __version__ = "1.7.0.dev20251028035559"
cirq/_version_test.py CHANGED
@@ -3,4 +3,4 @@ import cirq
3
3
 
4
4
 
5
5
  def test_version() -> None:
6
- assert cirq.__version__ == "1.7.0.dev20251027232108"
6
+ assert cirq.__version__ == "1.7.0.dev20251028035559"
@@ -16,11 +16,13 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
+ from enum import Enum
19
20
  from functools import reduce
20
21
  from itertools import cycle
21
22
  from typing import TYPE_CHECKING
22
23
 
23
24
  import numpy as np
25
+ from attrs import frozen
24
26
 
25
27
  from cirq import ops, protocols
26
28
  from cirq.circuits import Circuit, FrozenCircuit, Moment
@@ -133,10 +135,6 @@ def _calc_busy_moment_range_of_each_qubit(circuit: FrozenCircuit) -> dict[ops.Qi
133
135
  return busy_moment_range_by_qubit
134
136
 
135
137
 
136
- def _is_insertable_moment(moment: Moment, single_qubit_gate_moments_only: bool) -> bool:
137
- return not single_qubit_gate_moments_only or _is_single_qubit_gate_moment(moment)
138
-
139
-
140
138
  def _merge_single_qubit_ops_to_phxz(
141
139
  q: ops.Qid, operations: tuple[ops.Operation, ...]
142
140
  ) -> ops.Operation:
@@ -149,34 +147,162 @@ def _merge_single_qubit_ops_to_phxz(
149
147
  return gate.on(q)
150
148
 
151
149
 
152
- def _calc_pulled_through(moment: Moment, input_pauli_ops: ops.PauliString) -> ops.PauliString:
153
- """Calculates the pulled_through such that circuit(input_pauli_ops, moment.clifford_ops) is
154
- equivalent to circuit(moment.clifford_ops, pulled_through).
150
+ def _backward_set_stopping_slots(
151
+ q: ops.Qid,
152
+ from_mid: int,
153
+ mergable: dict[ops.Qid, dict[int, bool]],
154
+ need_to_stop: dict[ops.Qid, dict[int, bool]],
155
+ gate_types: dict[ops.Qid, dict[int, _CellType]],
156
+ circuit: FrozenCircuit,
157
+ ):
158
+ """Sets stopping slots for dynamical decoupling insertion.
159
+
160
+ This function traverses backward from a given moment `from_mid` for a specific qubit `q`.
161
+ It identifies moments where a dynamical decoupling sequence needs to be "stopped".
162
+
163
+ Args:
164
+ q: The qubit for which to set stopping slots.
165
+ from_mid: The moment ID to start the backward traversal from.
166
+ mergable: A dictionary indicating if a single-qubit Clifford gate at (qubit, moment_id)
167
+ can be merged with a Pauli gate.
168
+ need_to_stop: A dictionary to mark moments where a DD sequence must be stopped.
169
+ gate_types: A dictionary indicating the type of gate at each (qubit, moment_id).
170
+ circuit: The original frozen circuit.
155
171
  """
156
- clifford_ops_in_moment: list[ops.Operation] = [
157
- op for op in moment.operations if _is_clifford_op(op)
158
- ]
159
- return input_pauli_ops.after(clifford_ops_in_moment)
172
+ affected_qubits: set[ops.Qid] = {q}
173
+ for back_mid in range(from_mid, -1, -1):
174
+ for back_q in set(affected_qubits):
175
+ if gate_types[back_q][back_mid] == _CellType.WALL:
176
+ affected_qubits.remove(back_q)
177
+ continue
178
+ if mergable[back_q][back_mid]:
179
+ need_to_stop[back_q][back_mid] = True
180
+ affected_qubits.remove(back_q)
181
+ continue
182
+ op_at_q = circuit[back_mid].operation_at(back_q) or ops.I(q)
183
+ affected_qubits.update(op_at_q.qubits)
184
+ if not affected_qubits:
185
+ break
186
+
187
+
188
+ class _CellType(Enum):
189
+ UNKNOWN = '?'
190
+ # Non-insertable gates that cannot be pulled through
191
+ WALL = 'w'
192
+ # Clifford gates where Pauli Gates can be pulled through
193
+ DOOR = 'd'
194
+ # An empty gate can be used to insert Pauli gates from the dd sequence
195
+ INSERTABLE = 'i'
196
+
197
+
198
+ @frozen
199
+ class _Grid:
200
+ """A grid representation of the circuit where each gate position is labeled for
201
+ dynamical decoupling.
202
+
203
+ With this representation, a DD sequence can be automatically navigated in a
204
+ forward-only process. This avoids issues where a partially inserted DD
205
+ sequence encounters a "wall" and a new moment must be inserted because the
206
+ remaining DD sequence cannot be absorbed by nearby gates.
207
+
208
+ This labeled representation pre-calculates where DD pulses can be inserted
209
+ and where leftover DD sequences must be merged, avoiding the need for
210
+ backtracking.
211
+
212
+ An example labeled circuit is shown below:
213
+ | 0 | 1 | 2 | 3 | 4 |
214
+ -----+-----+-----+-----+-----+-----+
215
+ q(0) | d | i | i,s | d | w |
216
+ q(1) | d | i | d,s | w | w |
217
+ q(2) | d | d | d,s | w | w |
218
+ where `w`=WALL, `d`=DOOR, `i`=INSERTABLE. `s` represents a stop gate,
219
+ meaning that any unfinished DD sequences must be merged at this gate.
220
+ """
221
+
222
+ gate_types: dict[ops.Qid, dict[int, _CellType]]
223
+ need_to_stop: dict[ops.Qid, dict[int, bool]]
224
+ circuit: FrozenCircuit
225
+
226
+ @classmethod
227
+ def from_circuit(
228
+ cls, circuit: cirq.FrozenCircuit, single_qubit_gate_moments_only: bool
229
+ ) -> _Grid:
230
+ gate_types: dict[ops.Qid, dict[int, _CellType]] = {
231
+ q: {mid: _CellType.UNKNOWN for mid in range(len(circuit))} for q in circuit.all_qubits()
232
+ }
233
+ mergable: dict[ops.Qid, dict[int, bool]] = {
234
+ q: {mid: False for mid in range(len(circuit))} for q in circuit.all_qubits()
235
+ }
236
+ busy_moment_range_by_qubit = _calc_busy_moment_range_of_each_qubit(circuit)
237
+
238
+ # Set gate types for each (q, mid)
239
+ for mid, moment in enumerate(circuit):
240
+ is_insertable_moment = (
241
+ not single_qubit_gate_moments_only or _is_single_qubit_gate_moment(moment)
242
+ )
243
+ for q in circuit.all_qubits():
244
+ if mid < busy_moment_range_by_qubit[q][0] or mid > busy_moment_range_by_qubit[q][1]:
245
+ gate_types[q][mid] = _CellType.WALL
246
+ continue
247
+ op_at_q = moment.operation_at(q)
248
+ if op_at_q is None:
249
+ if is_insertable_moment:
250
+ gate_types[q][mid] = _CellType.INSERTABLE
251
+ mergable[q][mid] = True
252
+ else:
253
+ gate_types[q][mid] = _CellType.DOOR
254
+ else:
255
+ if _is_clifford_op(op_at_q):
256
+ gate_types[q][mid] = _CellType.DOOR
257
+ mergable[q][mid] = _is_single_qubit_operation(op_at_q)
258
+ else:
259
+ gate_types[q][mid] = _CellType.WALL
260
+
261
+ need_to_stop: dict[ops.Qid, dict[int, bool]] = {
262
+ q: {mid: False for mid in range(len(circuit))} for q in circuit.all_qubits()
263
+ }
264
+ # Reversely find the last mergeable gate of each qubit, set them as need_to_stop.
265
+ for q in circuit.all_qubits():
266
+ _backward_set_stopping_slots(
267
+ q, len(circuit) - 1, mergable, need_to_stop, gate_types, circuit
268
+ )
269
+ # Reversely check for each wall gate, mark the closest mergeable gate as need_to_stop.
270
+ for mid in range(len(circuit)):
271
+ for q in circuit.all_qubits():
272
+ if gate_types[q][mid] == _CellType.WALL:
273
+ _backward_set_stopping_slots(
274
+ q, mid - 1, mergable, need_to_stop, gate_types, circuit
275
+ )
276
+ return cls(circuit=circuit, gate_types=gate_types, need_to_stop=need_to_stop)
160
277
 
278
+ def __str__(self) -> str:
279
+ if not self.gate_types:
280
+ return "Grid(empty)"
161
281
 
162
- def _get_stop_qubits(moment: Moment) -> set[ops.Qid]:
163
- stop_pulling_through_qubits: set[ops.Qid] = set()
164
- for op in moment:
165
- if (not _is_clifford_op(op) and not _is_single_qubit_operation(op)) or not has_unitary(
166
- op
167
- ): # multi-qubit clifford op or non-mergable op.
168
- stop_pulling_through_qubits.update(op.qubits)
169
- return stop_pulling_through_qubits
282
+ qubits = sorted(list(self.gate_types.keys()))
283
+ num_moments = len(self.gate_types[qubits[0]])
170
284
 
285
+ max_qubit_len = max(len(str(q)) for q in qubits) if qubits else 0
171
286
 
172
- def _need_merge_pulled_through(op_at_q: ops.Operation, is_at_last_busy_moment: bool) -> bool:
173
- """With a pulling through pauli gate before op_at_q, need to merge with the
174
- pauli in the conditions below."""
175
- # The op must be mergable and single-qubit
176
- if not (_is_single_qubit_operation(op_at_q) and has_unitary(op_at_q)):
177
- return False
178
- # Either non-Clifford or at the last busy moment
179
- return is_at_last_busy_moment or not _is_clifford_op(op_at_q)
287
+ header = f"{'':>{max_qubit_len}} |"
288
+ for i in range(num_moments):
289
+ header += f" {i:^3} |"
290
+
291
+ separator = f"{'-' * max_qubit_len}-+"
292
+ separator += '-----+' * num_moments
293
+
294
+ lines = ["Grid Repr:", header, separator]
295
+
296
+ for q in qubits:
297
+ row_str = f"{str(q):>{max_qubit_len}} |"
298
+ for mid in range(num_moments):
299
+ gate_type = self.gate_types[q][mid].value
300
+ stop = self.need_to_stop[q][mid]
301
+ cell = f"{gate_type},s" if stop else f" {gate_type} "
302
+ row_str += f" {cell} |"
303
+ lines.append(row_str)
304
+
305
+ return "\n".join(lines)
180
306
 
181
307
 
182
308
  @transformer_api.transformer
@@ -188,7 +314,7 @@ def add_dynamical_decoupling(
188
314
  single_qubit_gate_moments_only: bool = True,
189
315
  ) -> cirq.Circuit:
190
316
  """Adds dynamical decoupling gate operations to a given circuit.
191
- This transformer might add new moments and thus change the structure of the original circuit.
317
+ This transformer preserves the structure of the original circuit.
192
318
 
193
319
  Args:
194
320
  circuit: Input circuit to transform.
@@ -202,11 +328,18 @@ def add_dynamical_decoupling(
202
328
  Returns:
203
329
  A copy of the input circuit with dynamical decoupling operations.
204
330
  """
205
- base_dd_sequence, pauli_map = _parse_dd_sequence(schema)
331
+
332
+ if context is not None and context.deep:
333
+ raise ValueError("Deep transformation is not supported.")
334
+
206
335
  orig_circuit = circuit.freeze()
207
336
 
208
- busy_moment_range_by_qubit = _calc_busy_moment_range_of_each_qubit(orig_circuit)
337
+ grid = _Grid.from_circuit(orig_circuit, single_qubit_gate_moments_only)
338
+
339
+ if context is not None and context.logger is not None:
340
+ context.logger.log("Preprocessed input circuit grid repr:\n%s", str(grid))
209
341
 
342
+ base_dd_sequence, pauli_map = _parse_dd_sequence(schema)
210
343
  # Stores all the moments of the output circuit chronologically.
211
344
  transformed_moments: list[Moment] = []
212
345
  # A PauliString stores the result of 'pulling' Pauli gates past each operations
@@ -215,90 +348,30 @@ def add_dynamical_decoupling(
215
348
  # Iterator of gate to be used in dd sequence for each qubit.
216
349
  dd_iter_by_qubits = {q: cycle(base_dd_sequence) for q in circuit.all_qubits()}
217
350
 
218
- def _update_pulled_through(q: ops.Qid, insert_gate: ops.Gate) -> ops.Operation:
219
- nonlocal pulled_through, pauli_map
220
- pulled_through *= pauli_map[insert_gate].on(q)
221
- return insert_gate.on(q)
222
-
223
- # Insert and pull remaining Pauli ops through the whole circuit.
224
- # General ideas are
225
- # * Pull through Clifford gates.
226
- # * Stop at multi-qubit non-Clifford ops (and other non-mergable ops).
227
- # * Merge to single-qubit non-Clifford ops.
228
- # * Insert a new moment if necessary.
229
- # After pulling through pulled_through at `moment`, we expect a transformation of
230
- # (pulled_through, moment) -> (updated_moment, updated_pulled_through) or
231
- # (pulled_through, moment) -> (new_moment, updated_moment, updated_pulled_through)
232
- # Moments structure changes are split into 3 steps:
233
- # 1, (..., last_moment, pulled_through1, moment, ...)
234
- # -> (..., last_moment, new_moment or None, pulled_through2, moment, ...)
235
- # 2, (..., pulled_through2, moment, ...) -> (..., pulled_through3, updated_moment, ...)
236
- # 3, (..., pulled_through3, updated_moment, ...)
237
- # -> (..., updated_moment, pulled_through4, ...)
238
351
  for moment_id, moment in enumerate(orig_circuit.moments):
239
- # Step 1, insert new_moment if necessary.
240
- # In detail: stop pulling through for multi-qubit non-Clifford ops or gates without
241
- # unitary representation (e.g., measure gates). If there are remaining pulled through ops,
242
- # insert into a new moment before current moment.
243
- stop_pulling_through_qubits: set[ops.Qid] = _get_stop_qubits(moment)
244
- new_moment_ops: list[ops.Operation] = []
245
- for q in stop_pulling_through_qubits:
246
- # Insert the remaining pulled_through
247
- remaining_pulled_through_gate = pulled_through.get(q)
248
- if remaining_pulled_through_gate is not None:
249
- new_moment_ops.append(_update_pulled_through(q, remaining_pulled_through_gate))
250
- # Reset dd sequence
251
- dd_iter_by_qubits[q] = cycle(base_dd_sequence)
252
- # Need to insert a new moment before current moment
253
- if new_moment_ops:
254
- # Fill insertable idle moments in the new moment using dd sequence
255
- for q in orig_circuit.all_qubits() - stop_pulling_through_qubits:
256
- if busy_moment_range_by_qubit[q][0] < moment_id <= busy_moment_range_by_qubit[q][1]:
257
- new_moment_ops.append(_update_pulled_through(q, next(dd_iter_by_qubits[q])))
258
- transformed_moments.append(Moment(new_moment_ops))
259
-
260
- # Step 2, calc updated_moment with insertions / merges.
261
352
  updated_moment_ops: set[cirq.Operation] = set()
262
353
  for q in orig_circuit.all_qubits():
263
- op_at_q = moment.operation_at(q)
264
- remaining_pulled_through_gate = pulled_through.get(q)
265
- updated_op = op_at_q
266
- if op_at_q is None: # insert into idle op
267
- if not _is_insertable_moment(moment, single_qubit_gate_moments_only):
268
- continue
269
- if (
270
- busy_moment_range_by_qubit[q][0] < moment_id < busy_moment_range_by_qubit[q][1]
271
- ): # insert next pauli gate in the dd sequence
272
- updated_op = _update_pulled_through(q, next(dd_iter_by_qubits[q]))
273
- elif ( # insert the remaining pulled through if beyond the ending busy moment
274
- moment_id > busy_moment_range_by_qubit[q][1]
275
- and remaining_pulled_through_gate is not None
276
- ):
277
- updated_op = _update_pulled_through(q, remaining_pulled_through_gate)
278
- elif (
279
- remaining_pulled_through_gate is not None
280
- ): # merge pulled-through of q to op_at_q if needed
281
- if _need_merge_pulled_through(
282
- op_at_q, moment_id == busy_moment_range_by_qubit[q][1]
283
- ):
284
- remaining_op = _update_pulled_through(q, remaining_pulled_through_gate)
285
- updated_op = _merge_single_qubit_ops_to_phxz(q, (remaining_op, op_at_q))
286
- if updated_op is not None:
287
- updated_moment_ops.add(updated_op)
288
-
289
- if updated_moment_ops:
290
- updated_moment = Moment(updated_moment_ops)
291
- transformed_moments.append(updated_moment)
292
-
293
- # Step 3, update pulled through.
294
- # In detail: pulling current `pulled_through` through updated_moment.
295
- pulled_through = _calc_pulled_through(updated_moment, pulled_through)
296
-
297
- # Insert a new moment if there are remaining pulled-through operations.
298
- ending_moment_ops = []
299
- for affected_q, combined_op_in_pauli in pulled_through.items():
300
- ending_moment_ops.append(combined_op_in_pauli.on(affected_q))
301
- if ending_moment_ops:
302
- transformed_moments.append(Moment(ending_moment_ops))
354
+ new_op_at_q = moment.operation_at(q)
355
+ if grid.gate_types[q][moment_id] == _CellType.INSERTABLE:
356
+ new_gate = next(dd_iter_by_qubits[q])
357
+ new_op_at_q = new_gate.on(q)
358
+ pulled_through *= pauli_map[new_gate].on(q)
359
+ if grid.need_to_stop[q][moment_id]:
360
+ to_be_merged = pulled_through.get(q)
361
+ if to_be_merged is not None:
362
+ new_op_at_q = _merge_single_qubit_ops_to_phxz(
363
+ q, (to_be_merged.on(q), new_op_at_q or ops.I(q))
364
+ )
365
+ pulled_through *= to_be_merged.on(q)
366
+ if new_op_at_q is not None:
367
+ updated_moment_ops.add(new_op_at_q)
368
+
369
+ updated_moment = Moment(updated_moment_ops)
370
+ clifford_ops = [op for op in updated_moment if _is_clifford_op(op)]
371
+ pulled_through = pulled_through.after(clifford_ops)
372
+ transformed_moments.append(updated_moment)
373
+
374
+ if len(pulled_through) > 0:
375
+ raise RuntimeError("Expect empty remaining Paulis after the dd insertion.")
303
376
 
304
377
  return Circuit.from_moments(*transformed_moments)
@@ -15,12 +15,14 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  from typing import Sequence
18
+ from unittest import mock
18
19
 
19
20
  import numpy as np
20
21
  import pytest
21
22
 
22
23
  import cirq
23
24
  from cirq import add_dynamical_decoupling, CNOT, CZ, CZPowGate, H, X, Y, Z
25
+ from cirq.transformers.dynamical_decoupling import _CellType, _Grid
24
26
 
25
27
 
26
28
  def assert_sim_eq(circuit1: cirq.AbstractCircuit, circuit2: cirq.AbstractCircuit) -> None:
@@ -163,10 +165,6 @@ def test_pull_through_h_gate_case1(single_qubit_gate_moments_only: bool) -> None
163
165
  a: ───H───────H───────@───
164
166
 
165
167
  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
168
  """
171
169
  a = cirq.NamedQubit('a')
172
170
  b = cirq.NamedQubit('b')
@@ -179,14 +177,11 @@ def test_pull_through_h_gate_case1(single_qubit_gate_moments_only: bool) -> None
179
177
  cirq.Moment(H(b)),
180
178
  cirq.Moment(CNOT(a, b)),
181
179
  ),
182
- expected_circuit=cirq.Circuit(
183
- cirq.Moment(H(a), H(b)),
184
- cirq.Moment(H(b), X(a)),
185
- cirq.Moment(H(a), H(b)),
186
- cirq.Moment(H(b), X(a)),
187
- cirq.Moment(CNOT(a, b)),
188
- cirq.Moment(Y(a), X(b)),
189
- ),
180
+ expected_circuit="""
181
+ a: ───H───X───H───PhXZ(a=-0.5,x=0,z=-1)───@───
182
+
183
+ b: ───H───H───H───H───────────────────────X───
184
+ """,
190
185
  schema="XX_PAIR",
191
186
  single_qubit_gate_moments_only=single_qubit_gate_moments_only,
192
187
  )
@@ -199,10 +194,6 @@ def test_pull_through_h_gate_case2(single_qubit_gate_moments_only: bool) -> None
199
194
  a: ───H───────H───────H───
200
195
 
201
196
  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
197
  """
207
198
  a = cirq.NamedQubit('a')
208
199
  b = cirq.NamedQubit('b')
@@ -215,15 +206,11 @@ def test_pull_through_h_gate_case2(single_qubit_gate_moments_only: bool) -> None
215
206
  cirq.Moment(H(b)),
216
207
  cirq.Moment(H(a), H(b)),
217
208
  ),
218
- expected_circuit=cirq.Circuit(
219
- cirq.Moment(H(a), H(b)),
220
- cirq.Moment(H(b), X(a)),
221
- cirq.Moment(H(a), H(b)),
222
- cirq.Moment(H(b), X(a)),
223
- cirq.Moment(
224
- cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=1).on(a), H(b)
225
- ),
226
- ),
209
+ expected_circuit="""
210
+ a: ───H───X───H───X───PhXZ(a=0.5,x=0.5,z=-1)───
211
+
212
+ b: ───H───H───H───H───H────────────────────────
213
+ """,
227
214
  schema="XX_PAIR",
228
215
  single_qubit_gate_moments_only=single_qubit_gate_moments_only,
229
216
  )
@@ -444,24 +431,6 @@ def test_scattered_circuit2() -> None:
444
431
  7: ───────────────@───@───
445
432
 
446
433
  8: ───────────────────@───
447
- Output:
448
- 0: ───────────────────@───
449
-
450
- 1: ───────────────@───@───
451
-
452
- 2: ───────────@───@───────
453
-
454
- 3: ───────@───@───────────
455
-
456
- 4: ───@───@───────────────
457
-
458
- 5: ───@───X───@───X───────
459
-
460
- 6: ───────────@───@───Z───
461
-
462
- 7: ───────────────@───@───
463
-
464
- 8: ───────────────────@───
465
434
  """
466
435
  qubits = cirq.LineQubit.range(9)
467
436
  assert_dd(
@@ -472,13 +441,25 @@ def test_scattered_circuit2() -> None:
472
441
  cirq.Moment(CZ(*qubits[1:3]), CZ(*qubits[6:8])),
473
442
  cirq.Moment(CZ(*qubits[0:2]), CZ(*qubits[7:])),
474
443
  ),
475
- expected_circuit=cirq.Circuit(
476
- cirq.Moment(CZ(*qubits[4:6])),
477
- cirq.Moment(CZ(*qubits[3:5]), X(qubits[5])),
478
- cirq.Moment(CZ(*qubits[2:4]), CZ(*qubits[5:7])),
479
- cirq.Moment(CZ(*qubits[1:3]), CZ(*qubits[6:8]), X(qubits[5])),
480
- cirq.Moment(CZ(*qubits[0:2]), CZ(*qubits[7:]), Z(qubits[6])),
481
- ),
444
+ expected_circuit="""
445
+ 0: ───────────────────@───
446
+
447
+ 1: ───────────────@───@───
448
+
449
+ 2: ───────────@───@───────
450
+
451
+ 3: ───────@───@───────────
452
+
453
+ 4: ───@───@───────────────
454
+
455
+ 5: ───@───I───@───────────
456
+
457
+ 6: ───────────@───@───────
458
+
459
+ 7: ───────────────@───@───
460
+
461
+ 8: ───────────────────@───
462
+ """,
482
463
  schema="XX_PAIR",
483
464
  single_qubit_gate_moments_only=False,
484
465
  )
@@ -494,14 +475,6 @@ def test_pull_through_chain() -> None:
494
475
  2: ───────────────×───×───X───
495
476
 
496
477
  3: ───────────────────×───X───
497
- Output:
498
- 0: ───X───X───×───X───X───X───
499
-
500
- 1: ───────Y───×───×───X───I───
501
-
502
- 2: ───────────────×───×───X───
503
-
504
- 3: ───────────────────×───I───
505
478
  """
506
479
  qubits = cirq.LineQubit.range(4)
507
480
  assert_dd(
@@ -513,14 +486,15 @@ def test_pull_through_chain() -> None:
513
486
  cirq.Moment(cirq.SWAP(*qubits[2:4])),
514
487
  cirq.Moment([X(qubits[i]) for i in range(4)]),
515
488
  ),
516
- expected_circuit=cirq.Circuit(
517
- cirq.Moment(X(qubits[0])),
518
- cirq.Moment(Y(qubits[1]), X(qubits[0])),
519
- cirq.Moment(cirq.SWAP(*qubits[0:2])),
520
- cirq.Moment([cirq.SWAP(*qubits[1:3])] + [X(qubits[0])]),
521
- cirq.Moment([cirq.SWAP(*qubits[2:4])] + [X(qubits[0]), X(qubits[1])]),
522
- cirq.Moment(X(qubits[0]), cirq.I(qubits[1]), X(qubits[2]), cirq.I(qubits[3])),
523
- ),
489
+ expected_circuit="""
490
+ 0: ───X───X───×───X───X───X───
491
+
492
+ 1: ───────Y───×───×───X───I───
493
+
494
+ 2: ───────────────×───×───X───
495
+
496
+ 3: ───────────────────×───I───
497
+ """,
524
498
  schema='XX_PAIR',
525
499
  single_qubit_gate_moments_only=False,
526
500
  )
@@ -532,10 +506,6 @@ def test_multiple_clifford_pieces_case1() -> None:
532
506
  a: ───H───────H───────@───────────H───────H───
533
507
 
534
508
  b: ───H───H───H───H───@^0.5───H───H───H───H───
535
- Output:
536
- a: ───H───X───H───X───Y───@───────X───H───X───PhXZ(a=0.5,x=0.5,z=-1)───
537
-
538
- b: ───H───H───H───H───────@^0.5───H───H───H───H────────────────────────
539
509
  """
540
510
  a = cirq.NamedQubit('a')
541
511
  b = cirq.NamedQubit('b')
@@ -552,9 +522,9 @@ def test_multiple_clifford_pieces_case1() -> None:
552
522
  cirq.Moment(H(a), H(b)),
553
523
  ),
554
524
  expected_circuit="""
555
- a: ───H───X───H───X───Y───@───────X───H───X───PhXZ(a=0.5,x=0.5,z=-1)───
556
-
557
- b: ───H───H───H───H───────@^0.5───H───H───H───H────────────────────────
525
+ a: ───H───X───H───PhXZ(a=-0.5,x=0,z=-1)───@───────X───H───X───PhXZ(a=0.5,x=0.5,z=-1)───
526
+
527
+ b: ───H───H───H───H───────────────────────@^0.5───H───H───H───H────────────────────────
558
528
  """,
559
529
  schema="XX_PAIR",
560
530
  )
@@ -566,10 +536,6 @@ def test_multiple_clifford_pieces_case2() -> None:
566
536
  a: ───@───PhXZ(a=0.3,x=0.2,z=0)───PhXZ(a=0.3,x=0.2,z=0)───PhXZ(a=0.3,x=0.2,z=0)───@───
567
537
  │ │
568
538
  b: ───@───────────────────────────────────────────────────────────────────────────@───
569
- Output:
570
- a: ───@───PhXZ(a=0.3,x=0.2,z=0)───PhXZ(a=0.3,x=0.2,z=0)───PhXZ(a=0.3,x=0.2,z=0)───@───Z───
571
- │ │
572
- b: ───@───X───────────────────────X───────────────────────X───────────────────────@───X───
573
539
  """
574
540
  a = cirq.NamedQubit('a')
575
541
  b = cirq.NamedQubit('b')
@@ -583,20 +549,17 @@ def test_multiple_clifford_pieces_case2() -> None:
583
549
  cirq.Moment(phased_xz_gate.on(a)),
584
550
  cirq.Moment(CZ(a, b)),
585
551
  ),
586
- expected_circuit=cirq.Circuit(
587
- cirq.Moment(CZ(a, b)),
588
- cirq.Moment(phased_xz_gate.on(a), X(b)),
589
- cirq.Moment(phased_xz_gate.on(a), X(b)),
590
- cirq.Moment(phased_xz_gate.on(a), X(b)),
591
- cirq.Moment(CZ(a, b)),
592
- cirq.Moment(Z(a), X(b)),
593
- ),
552
+ expected_circuit="""
553
+ a: ───@───PhXZ(a=0.3,x=0.2,z=0)───PhXZ(a=0.3,x=0.2,z=0)───PhXZ(a=0.3,x=0.2,z=0)───@───
554
+ │ │
555
+ b: ───@───X───────────────────────X───────────────────────I───────────────────────@───
556
+ """,
594
557
  schema='XX_PAIR',
595
558
  single_qubit_gate_moments_only=False,
596
559
  )
597
560
 
598
561
 
599
- def test_insert_new_moment() -> None:
562
+ def test_absorb_remaining_dd_sequence() -> None:
600
563
  """Test case diagrams.
601
564
  Input:
602
565
  a: ───H───────H───@───@───────
@@ -604,12 +567,6 @@ def test_insert_new_moment() -> None:
604
567
  b: ───H───H───H───X───@^0.5───
605
568
 
606
569
  c: ───H───────────────H───────
607
- Output:
608
- a: ───H───X───H───@───Z───@────────────────────────
609
- │ │
610
- b: ───H───H───H───X───────@^0.5────────────────────
611
-
612
- c: ───H───X───X───────X───PhXZ(a=-0.5,x=0.5,z=0)───
613
570
  """
614
571
  a = cirq.NamedQubit('a')
615
572
  b = cirq.NamedQubit('b')
@@ -622,17 +579,13 @@ def test_insert_new_moment() -> None:
622
579
  cirq.Moment(CNOT(a, b)),
623
580
  cirq.Moment(CZPowGate(exponent=0.5).on(a, b), H(c)),
624
581
  ),
625
- expected_circuit=cirq.Circuit(
626
- cirq.Moment(H(a), H(b), H(c)),
627
- cirq.Moment(H(b), X(a), X(c)),
628
- cirq.Moment(H(a), H(b), X(c)),
629
- cirq.Moment(CNOT(a, b)),
630
- cirq.Moment(Z(a), X(c)),
631
- cirq.Moment(
632
- CZPowGate(exponent=0.5).on(a, b),
633
- cirq.PhasedXZGate(axis_phase_exponent=-0.5, x_exponent=0.5, z_exponent=0).on(c),
634
- ),
635
- ),
582
+ expected_circuit="""
583
+ a: ───H───X───PhXZ(a=-0.5,x=0.5,z=0)───@───@───────
584
+ │ │
585
+ b: ───H───H───H────────────────────────X───@^0.5───
586
+
587
+ c: ───H───X───X────────────────────────────H───────
588
+ """,
636
589
  schema="XX_PAIR",
637
590
  )
638
591
 
@@ -659,13 +612,13 @@ def test_with_non_clifford_measurements() -> None:
659
612
  cirq.Moment([cirq.M(qubits[i]) for i in [0, 1, 2, 3]]),
660
613
  ),
661
614
  expected_circuit="""
662
- 0: ───────────H───@───H───X───M───
615
+ 0: ───────────H───@───PhXZ(a=0.5,x=0.5,z=0)───M───
663
616
 
664
- 1: ───H───@───X───@───X───────M───
617
+ 1: ───H───@───X───@───X───────────────────────M───
665
618
 
666
- 2: ───H───@───H───@───X───X───M───
619
+ 2: ───H───@───H───@───I───────────────────────M───
667
620
 
668
- 3: ───────────H───@───H───────M───
621
+ 3: ───────────H───@───H───────────────────────M───
669
622
  """,
670
623
  schema="XX_PAIR",
671
624
  single_qubit_gate_moments_only=True,
@@ -688,21 +641,6 @@ def test_cross_clifford_pieces_filling_merge() -> None:
688
641
  5: ───PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───H───
689
642
 
690
643
  6: ───────────────────────────────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)─────────────────────────────@───PhXZ(a=0.2,x=0.2,z=0.1)───H───
691
- Output:
692
-
693
- 0: ─────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)─────H────────────────────────
694
- │ │
695
- 1: ─────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)─────H────────────────────────
696
-
697
- 2: ───PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───X───────────────────────────PhXZ(a=0.5,x=0.5,z=-1)───
698
- │ │ │
699
- 3: ─────────────────────────────┼───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────X─────────────────────────@───Y───────────────────────────PhXZ(a=0.5,x=0.5,z=0)────
700
-
701
- 4: ─────────────────────────────┼─────────────────────────────@─────────────────────────X─────────────────────────────Y───────────────────────────PhXZ(a=0.5,x=0.5,z=0)────
702
- │ │
703
- 5: ───PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=-0.8,x=0.2,z=-0.9)───H────────────────────────
704
-
705
- 6: ───────────────────────────────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───X─────────────────────────@───PhXZ(a=0.8,x=0.8,z=0.5)─────H────────────────────────
706
644
  """ # noqa: E501
707
645
  qubits = cirq.LineQubit.range(7)
708
646
  phased_xz_gate = cirq.PhasedXZGate(axis_phase_exponent=0.2, x_exponent=0.2, z_exponent=0.1)
@@ -721,30 +659,31 @@ def test_cross_clifford_pieces_filling_merge() -> None:
721
659
  cirq.Moment([H.on(q) for q in qubits]),
722
660
  ),
723
661
  expected_circuit="""
724
- 0: ─────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)─────H────────────────────────
662
+ 0: ─────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───H────────────────────────
725
663
  │ │
726
- 1: ─────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)─────H────────────────────────
664
+ 1: ─────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───H────────────────────────
727
665
 
728
- 2: ───PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───X───────────────────────────PhXZ(a=0.5,x=0.5,z=-1)───
666
+ 2: ───PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───X─────────────────────────PhXZ(a=0.5,x=0.5,z=-1)───
729
667
  │ │ │
730
- 3: ─────────────────────────────┼───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────X─────────────────────────@───Y───────────────────────────PhXZ(a=0.5,x=0.5,z=0)────
668
+ 3: ─────────────────────────────┼───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────X─────────────────────────@───Y─────────────────────────PhXZ(a=0.5,x=0.5,z=0)────
731
669
 
732
- 4: ─────────────────────────────┼─────────────────────────────@─────────────────────────X─────────────────────────────Y───────────────────────────PhXZ(a=0.5,x=0.5,z=0)────
670
+ 4: ─────────────────────────────┼─────────────────────────────@─────────────────────────X─────────────────────────────Y─────────────────────────PhXZ(a=0.5,x=0.5,z=0)────
733
671
  │ │
734
- 5: ───PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=-0.8,x=0.2,z=-0.9)───H────────────────────────
672
+ 5: ───PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───H────────────────────────
735
673
 
736
- 6: ───────────────────────────────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───X─────────────────────────@───PhXZ(a=0.8,x=0.8,z=0.5)─────H────────────────────────
674
+ 6: ───────────────────────────────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───I─────────────────────────@───PhXZ(a=0.2,x=0.2,z=0.1)───H────────────────────────
737
675
  """, # noqa: E501
738
676
  )
739
677
 
740
678
 
741
679
  def test_pull_through_phxz_gate_case1() -> None:
742
680
  """Test case diagrams.
743
- Input:
681
+
682
+ Input:
744
683
  a: ───H───────PhXZ(a=0.25,x=-1,z=0)───────@───
745
684
 
746
685
  b: ───H───H───H───────────────────────H───X───
747
- Output: expected circuit diagram below.
686
+ Output: expected circuit diagram below.
748
687
  """
749
688
  a = cirq.NamedQubit('a')
750
689
  b = cirq.NamedQubit('b')
@@ -759,9 +698,9 @@ def test_pull_through_phxz_gate_case1() -> None:
759
698
  cirq.Moment(CNOT(a, b)),
760
699
  ),
761
700
  expected_circuit="""
762
- a: ───H───X───PhXZ(a=0.25,x=-1,z=0)───X───@───Z───
763
-
764
- b: ───H───H───H───────────────────────H───X───────
701
+ a: ───H───X───PhXZ(a=0.25,x=-1,z=0)───PhXZ(a=0.5,x=1,z=0)───@───
702
+
703
+ b: ───H───H───H───────────────────────H─────────────────────X───
765
704
  """,
766
705
  schema="XX_PAIR",
767
706
  )
@@ -769,11 +708,12 @@ b: ───H───H───H───────────────
769
708
 
770
709
  def test_pull_through_phxz_gate_case2() -> None:
771
710
  """Test case diagrams.
772
- Input:
711
+
712
+ Input:
773
713
  a: ───H───────PhXZ(a=0.2,x=-1,z=0)───────@───
774
714
 
775
715
  b: ───H───H───H───────────────────────H───X───
776
- Output: expected circuit diagram below.
716
+ Output: expected circuit diagram below.
777
717
  """
778
718
  a = cirq.NamedQubit('a')
779
719
  b = cirq.NamedQubit('b')
@@ -788,9 +728,9 @@ def test_pull_through_phxz_gate_case2() -> None:
788
728
  cirq.Moment(CNOT(a, b)),
789
729
  ),
790
730
  expected_circuit="""
791
- a: ───H───X───PhXZ(a=0.1,x=0,z=0.4)───X───@───X───
792
-
793
- b: ───H───H───H───────────────────────H───X───X───
731
+ a: ───H───I───PhXZ(a=0.2,x=-1,z=0)───I───@───
732
+
733
+ b: ───H───H───H──────────────────────H───X───
794
734
  """,
795
735
  schema="XX_PAIR",
796
736
  )
@@ -819,58 +759,112 @@ def test_merge_before_non_cliffords() -> None:
819
759
  assert_dd(
820
760
  input_circuit=input_circuit,
821
761
  expected_circuit="""
822
- 0: ───X───X───X───────────────────────X──────────────────────X───M───
762
+ 0: ───X───X───X──────────────────────────────────────────M───
823
763
 
824
- 1: ───X───X───PhXZ(a=-1,x=0,z=-0.5)───Y───FSim(0, 0.0637π)───────M───
825
-
826
- 2: ───X───X───S───────────────────────────FSim(0, 0.0637π)───────M───
764
+ 1: ───X───X───PhXZ(a=-1.25,x=1,z=0)───FSim(0, 0.0637π)───M───
765
+
766
+ 2: ───X───X───S───────────────────────FSim(0, 0.0637π)───M───
827
767
  """,
828
768
  schema="XX_PAIR",
829
769
  )
830
770
 
831
771
 
832
- @pytest.mark.parametrize(
833
- 'single_qubit_gate_moments_only, expected_diagram',
834
- [
835
- (
836
- True,
837
- # With single_qubit_gate_moments_only=True, the second DD gate on q2
838
- # is inserted in a new moment after the CZ gate.
839
- """
840
- 0: ───X───X───@───────M───
841
-
842
- 1: ───X───X───@───────M───
772
+ def test_runtime_error_if_pulled_through_not_empty_mocked() -> None:
773
+ """Tests that a RuntimeError is raised if pulled_through is not empty at the end.
843
774
 
844
- 2: ───X───X───────X───M───
845
- """,
846
- ),
847
- (
848
- False,
849
- # With single_qubit_gate_moments_only=False, the second DD gate on q2
850
- # is inserted in the same moment as the CZ gate.
851
- """
852
- 0: ───X───X───@───M───
853
-
854
- 1: ───X───X───@───M───
775
+ This test explicitly mocks the internal state to simulate a scenario where
776
+ the `pulled_through` PauliString is not empty after processing all moments.
777
+ Under normal operation, the `_Grid` and `add_dynamical_decoupling`
778
+ logic should ensure `pulled_through` is always empty at the end, making
779
+ this RuntimeError theoretically unreachable. This test verifies the
780
+ defensive check itself.
781
+ """
782
+ q0: cirq.Qid = cirq.NamedQubit('q0')
783
+ circuit = cirq.FrozenCircuit(cirq.Moment(cirq.I(q0))) # A minimal circuit
855
784
 
856
- 2: ───X───X───X───M───
857
- """,
858
- ),
859
- ],
860
- )
861
- def test_single_qubit_gate_moments_only_true_vs_false(
862
- single_qubit_gate_moments_only, expected_diagram
863
- ) -> None:
785
+ # Create a mock _Grid instance that would lead to an unabsorbed Pauli.
786
+ # We need an INSERTABLE slot, but no STOP label, and no self-cancellation.
787
+ # To achieve this, we'll mock the `pulled_through.after` method to *not* clear it.
788
+ # This is a deep mock to hit the specific RuntimeError line.
789
+
790
+ # First, create a _Grid that allows insertion but no stopping.
791
+ # This is a hypothetical scenario that `_Grid.from_circuit` should prevent.
792
+ mock_gate_types = {q0: {0: _CellType.INSERTABLE}}
793
+ mock_need_to_stop = {q0: {0: False}} # Crucially, no stop gate
794
+
795
+ mock_labeled_circuit = _Grid(
796
+ gate_types=mock_gate_types, need_to_stop=mock_need_to_stop, circuit=circuit
797
+ )
798
+
799
+ # Mock _Grid.from_circuit to return our custom mock
800
+ with mock.patch(
801
+ 'cirq.transformers.dynamical_decoupling._Grid.from_circuit',
802
+ return_value=mock_labeled_circuit,
803
+ ):
804
+ # Mock the PauliString.after method to ensure `pulled_through` remains non-empty.
805
+ with mock.patch('cirq.ops.PauliString.after', return_value=cirq.PauliString({q0: cirq.X})):
806
+ with pytest.raises(
807
+ RuntimeError, match="Expect empty remaining Paulis after the dd insertion."
808
+ ):
809
+ add_dynamical_decoupling(
810
+ circuit, schema='XX_PAIR', single_qubit_gate_moments_only=True
811
+ )
812
+
813
+
814
+ def test_labeled_circuit_str():
815
+ """Input circuit:
816
+ 0: ───X──────────────────────────────────────────────────M───
817
+
818
+ 1: ───X───────PhXZ(a=-1,x=0,z=-0.5)───FSim(0, 0.0637π)───M───
819
+
820
+ 2: ───X───X───S───────────────────────FSim(0, 0.0637π)───M───
821
+ """
864
822
  q0, q1, q2 = cirq.LineQubit.range(3)
865
823
  input_circuit = cirq.Circuit(
866
824
  cirq.Moment([X(q) for q in [q0, q1, q2]]),
867
- cirq.Moment([X(q) for q in [q0, q1]]),
868
- cirq.Moment(CZ(q0, q1)),
825
+ cirq.Moment(X(q2)),
826
+ cirq.Moment(
827
+ cirq.PhasedXZGate(axis_phase_exponent=-1, x_exponent=0, z_exponent=-0.5).on(q1),
828
+ (Z**0.5).on(q2),
829
+ ),
830
+ cirq.Moment(cirq.FSimGate(theta=0, phi=0.2).on(q1, q2)),
869
831
  cirq.Moment([cirq.M(q) for q in [q0, q1, q2]]),
870
832
  )
871
- assert_dd(
872
- input_circuit=input_circuit,
873
- expected_circuit=expected_diagram,
874
- schema="XX_PAIR",
875
- single_qubit_gate_moments_only=single_qubit_gate_moments_only,
833
+ labeled_circuit = _Grid.from_circuit(input_circuit, single_qubit_gate_moments_only=True)
834
+ assert str(labeled_circuit) == (
835
+ """Grid Repr:
836
+ | 0 | 1 | 2 | 3 | 4 |
837
+ -----+-----+-----+-----+-----+-----+
838
+ q(0) | d | i | i,s | d | w |
839
+ q(1) | d | i | d,s | w | w |
840
+ q(2) | d | d | d,s | w | w |"""
876
841
  )
842
+
843
+
844
+ def test_labeled_circuit_str_empty():
845
+ """Tests the __str__ method of _Grid for empty and no-qubit circuits."""
846
+ # Test case for an empty circuit (no moments, no qubits)
847
+ empty_circuit = cirq.Circuit()
848
+ labeled_empty = _Grid.from_circuit(empty_circuit, single_qubit_gate_moments_only=True)
849
+ assert str(labeled_empty) == "Grid(empty)"
850
+
851
+
852
+ def test_add_dynamical_decoupling_with_deep_context_raises_error():
853
+ """Tests that add_dynamical_decoupling raises an error with deep context."""
854
+ q = cirq.NamedQubit('q')
855
+ circuit = cirq.Circuit(cirq.H(q))
856
+ context = cirq.TransformerContext(deep=True)
857
+ with pytest.raises(ValueError, match="Deep transformation is not supported."):
858
+ add_dynamical_decoupling(circuit, context=context)
859
+
860
+
861
+ def test_context_logger():
862
+ q = cirq.NamedQubit('q')
863
+ circuit = cirq.Circuit(cirq.H(q))
864
+ mock_logger = mock.MagicMock(spec=cirq.TransformerLogger)
865
+ context = cirq.TransformerContext(logger=mock_logger)
866
+
867
+ add_dynamical_decoupling(circuit, context=context)
868
+
869
+ mock_logger.log.assert_called_once()
870
+ assert "Preprocessed input circuit grid repr:" in mock_logger.log.call_args[0][0]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cirq-core
3
- Version: 1.7.0.dev20251027232108
3
+ Version: 1.7.0.dev20251028035559
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
@@ -4,8 +4,8 @@ cirq/_compat_test.py,sha256=emXpdD5ZvwLRlFAoQB8YatmZyU3b4e9jg6FppMTUhkU,33900
4
4
  cirq/_doc.py,sha256=28ZskY9ZtZ_4GS1oXPUgklKnJqmAE-rkUfzcsJ0--nA,2941
5
5
  cirq/_import.py,sha256=ixBu4EyGl46Ram2cP3p5eZVEFDW5L2DS-VyTjz4N9iw,8429
6
6
  cirq/_import_test.py,sha256=oF4izzOVZLc7NZ0aZHFcGv-r01eiFFt_JORx_x7_D4s,1089
7
- cirq/_version.py,sha256=g7O1Eq5OuZdNfYZAn8zHkbwkz3LGcCxJV9msTNsf_x4,1206
8
- cirq/_version_test.py,sha256=t2WylwznRLxqUzopJbbY4CLd39vYN-pd1k3vQAGnfUU,155
7
+ cirq/_version.py,sha256=hwKIrLaPuF0ICgE1qbNArfVRn9cZA8_8VnpdaPSokDM,1206
8
+ cirq/_version_test.py,sha256=kvN_UM8XK-zjfJ6SXpp97upPv198bIXsvNPxFrqa4GI,155
9
9
  cirq/conftest.py,sha256=wSDKNdIQRDfLnXvOCWD3erheOw8JHRhdfQ53EyTUIXg,1239
10
10
  cirq/json_resolver_cache.py,sha256=A5DIgFAY1hUNt9vai_C3-gGBv24116CJMzQxMcXOax4,13726
11
11
  cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
@@ -1078,8 +1078,8 @@ cirq/transformers/drop_empty_moments.py,sha256=uZJG9FpUNyA1Mi0xLDuVuhj_siZhPZ1_s
1078
1078
  cirq/transformers/drop_empty_moments_test.py,sha256=h6Pji0z0o9KOB7fnSHseWpIAhzvxWurF_flg9XWm_YI,1959
1079
1079
  cirq/transformers/drop_negligible_operations.py,sha256=eP2dP_n0BYlr8aZ1wnD8YWsqCtwN0l0O6p45RbXEpfM,2097
1080
1080
  cirq/transformers/drop_negligible_operations_test.py,sha256=LrZDDITL5dskTywIahZqZBWnIXAJqNAjOgd4EYfrYTA,3908
1081
- cirq/transformers/dynamical_decoupling.py,sha256=LP0Hrp7XqfVRmSy_wQX85GKPgK1Vy2_HCt8OyySFL2s,13484
1082
- cirq/transformers/dynamical_decoupling_test.py,sha256=E0dlZ2D7yCFr5a0SndLjr9Kv_-Iu5q-Nj_YIlN7IgYU,45339
1081
+ cirq/transformers/dynamical_decoupling.py,sha256=H0sOVKce3-NV-B8onp_S-mWU50EFJ9GJxJqKpQrYoCU,15113
1082
+ cirq/transformers/dynamical_decoupling_test.py,sha256=Dc0zc2civgbJcj8KXFCNDrvCXRPuZfCetIZ9XgHf5Qc,43029
1083
1083
  cirq/transformers/eject_phased_paulis.py,sha256=gK1XIslsBPFcppUFacbhvzfhcnK5ZSVcyLN1SM5wTEE,14072
1084
1084
  cirq/transformers/eject_phased_paulis_test.py,sha256=CQ5sUmJg9ibgo9RS7265CfOPJ1JgbyGWG9aRRi44dxM,14252
1085
1085
  cirq/transformers/eject_z.py,sha256=890RYmv6qi4KgHi0LD1xEt2EQ4V7WzfS8lkqvZHt0r4,5860
@@ -1246,8 +1246,8 @@ cirq/work/sampler.py,sha256=rxbMWvrhu3gfNSBjZKozw28lLKVvBAS_1EGyPdYe8Xg,19041
1246
1246
  cirq/work/sampler_test.py,sha256=SsMrRvLDYELyOAWLKISjkdEfrBwLYWRsT6D8WrsLM3Q,13533
1247
1247
  cirq/work/zeros_sampler.py,sha256=Fs2JWwq0n9zv7_G5Rm-9vPeHUag7uctcMOHg0JTkZpc,2371
1248
1248
  cirq/work/zeros_sampler_test.py,sha256=lQLgQDGBLtfImryys2HzQ2jOSGxHgc7-koVBUhv8qYk,3345
1249
- cirq_core-1.7.0.dev20251027232108.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1250
- cirq_core-1.7.0.dev20251027232108.dist-info/METADATA,sha256=ic6wyvba6WdjMpxKLPUy8-9HORuJ46ZglP_G_gokOow,4757
1251
- cirq_core-1.7.0.dev20251027232108.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1252
- cirq_core-1.7.0.dev20251027232108.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1253
- cirq_core-1.7.0.dev20251027232108.dist-info/RECORD,,
1249
+ cirq_core-1.7.0.dev20251028035559.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1250
+ cirq_core-1.7.0.dev20251028035559.dist-info/METADATA,sha256=V4zXcqoE990QTFmY9VzWqvWLSCTec-DJVfIMWESOK8s,4757
1251
+ cirq_core-1.7.0.dev20251028035559.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1252
+ cirq_core-1.7.0.dev20251028035559.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1253
+ cirq_core-1.7.0.dev20251028035559.dist-info/RECORD,,