0
# Circuits and Moments
1
2
The circuits module provides classes for building, manipulating, and representing quantum circuits. Quantum circuits in Cirq are composed of moments, which represent sets of operations that occur simultaneously.
3
4
## Core Circuit Classes
5
6
### Circuit
7
8
The primary mutable quantum circuit class that contains operations organized in moments.
9
10
```python { .api }
11
class Circuit:
12
"""Mutable quantum circuit containing operations in moments."""
13
14
def __init__(self, *contents: 'cirq.OP_TREE') -> None:
15
"""Initialize a circuit with operations."""
16
17
def append(self, op_tree: 'cirq.OP_TREE',
18
strategy: InsertStrategy = InsertStrategy.NEW_THEN_INLINE) -> None:
19
"""Append operations to the end of the circuit."""
20
21
def insert(self, index: int, op_tree: 'cirq.OP_TREE',
22
strategy: InsertStrategy = InsertStrategy.NEW_THEN_INLINE) -> None:
23
"""Insert operations at the specified moment index."""
24
25
def insert_into_range(self, operations: 'cirq.OP_TREE', start: int, end: int) -> None:
26
"""Insert operations into a range of moments."""
27
28
def clear_operations_touching(self, qubits: Iterable['cirq.Qid'],
29
moment_indices: Iterable[int]) -> None:
30
"""Clear operations touching specified qubits in specified moments."""
31
32
def batch_remove(self, removals: Iterable[Tuple[int, 'cirq.Operation']]) -> None:
33
"""Remove multiple operations specified by (moment_index, operation) pairs."""
34
35
def batch_replace(self, replacements: Iterable[Tuple[int, 'cirq.Operation', 'cirq.OP_TREE']]) -> None:
36
"""Replace multiple operations specified by (moment_index, old_op, new_ops) tuples."""
37
38
# Properties and inspection
39
@property
40
def moments(self) -> List[Moment]:
41
"""List of moments in the circuit."""
42
43
def all_qubits(self) -> FrozenSet['cirq.Qid']:
44
"""All qubits used in the circuit."""
45
46
def all_operations(self) -> Iterator['cirq.Operation']:
47
"""Iterator over all operations in the circuit."""
48
49
def num_qubits(self) -> int:
50
"""Number of qubits used by the circuit."""
51
52
def qid_shape(self) -> Tuple[int, ...]:
53
"""Shape of qids used by the circuit."""
54
55
def are_all_measurements_terminal(self) -> bool:
56
"""Check if all measurements are at the end of the circuit."""
57
58
# Circuit manipulation
59
def with_noise(self, noise: 'cirq.NoiseModel') -> 'Circuit':
60
"""Return a copy of the circuit with noise applied."""
61
62
def reversed(self) -> 'Circuit':
63
"""Return a copy with the order of moments reversed."""
64
65
def transform_qubits(self, qubit_map: Dict['cirq.Qid', 'cirq.Qid']) -> 'Circuit':
66
"""Return a copy with qubits transformed according to the map."""
67
68
def zip(self, *other_circuits: 'Circuit') -> 'Circuit':
69
"""Combine this circuit with others by zipping moments together."""
70
71
# Slicing and indexing
72
def __getitem__(self, key) -> Union['Circuit', Moment]:
73
"""Get moments or slices of moments."""
74
75
def __setitem__(self, key, value) -> None:
76
"""Set moments or slices of moments."""
77
78
def __len__(self) -> int:
79
"""Number of moments in the circuit."""
80
81
# String representations
82
def __str__(self) -> str:
83
"""String representation of the circuit."""
84
85
def to_text_diagram(self, **kwargs) -> str:
86
"""Generate a text diagram of the circuit."""
87
88
# Validation and optimization
89
def _resolve_parameters_(self, resolver: 'cirq.ParamResolver', recursive: bool) -> 'Circuit':
90
"""Resolve parameters in the circuit."""
91
```
92
93
### FrozenCircuit
94
95
Immutable version of a quantum circuit.
96
97
```python { .api }
98
class FrozenCircuit(AbstractCircuit):
99
"""Immutable quantum circuit."""
100
101
def __init__(self, *contents: 'cirq.OP_TREE') -> None:
102
"""Initialize an immutable circuit."""
103
104
# All inspection methods from Circuit (read-only)
105
@property
106
def moments(self) -> Tuple[Moment, ...]:
107
"""Tuple of moments in the circuit."""
108
109
def unfreeze(self, copy: bool = True) -> Circuit:
110
"""Convert to a mutable Circuit."""
111
112
def freeze(self) -> 'FrozenCircuit':
113
"""Return self (already frozen)."""
114
```
115
116
### AbstractCircuit
117
118
Base class for circuit-like objects.
119
120
```python { .api }
121
class AbstractCircuit:
122
"""Abstract base class for quantum circuits."""
123
124
@property
125
@abc.abstractmethod
126
def moments(self) -> Sequence[Moment]:
127
"""Sequence of moments in the circuit."""
128
129
def next_moment_operating_on(self, qubits: Iterable['cirq.Qid'],
130
start_moment_index: int = 0) -> Optional[int]:
131
"""Find the next moment that operates on any of the given qubits."""
132
133
def prev_moment_operating_on(self, qubits: Iterable['cirq.Qid'],
134
end_moment_index: Optional[int] = None) -> Optional[int]:
135
"""Find the previous moment that operates on any of the given qubits."""
136
137
def operation_at(self, qubit: 'cirq.Qid', moment_index: int) -> Optional['cirq.Operation']:
138
"""Return the operation on a qubit at a specific moment."""
139
140
def findall_operations(self, predicate: Callable[['cirq.Operation'], bool]) -> List[Tuple[int, 'cirq.Operation']]:
141
"""Find all operations matching a predicate."""
142
```
143
144
## Moment Class
145
146
Represents operations that occur simultaneously in a quantum circuit.
147
148
```python { .api }
149
class Moment:
150
"""Quantum operations occurring simultaneously."""
151
152
def __init__(self, *operations: 'cirq.Operation') -> None:
153
"""Initialize a moment with operations."""
154
155
@property
156
def operations(self) -> FrozenSet['cirq.Operation']:
157
"""Set of operations in this moment."""
158
159
@property
160
def qubits(self) -> FrozenSet['cirq.Qid']:
161
"""All qubits operated on in this moment."""
162
163
def operates_on_single_qubit(self, qubit: 'cirq.Qid') -> bool:
164
"""Check if this moment has any operations on the given qubit."""
165
166
def operates_on(self, qubits: Iterable['cirq.Qid']) -> bool:
167
"""Check if this moment operates on any of the given qubits."""
168
169
def operation_at(self, qubit: 'cirq.Qid') -> Optional['cirq.Operation']:
170
"""Return the operation on a qubit, or None if no operation."""
171
172
def with_operation(self, operation: 'cirq.Operation') -> 'Moment':
173
"""Return a copy with an additional operation."""
174
175
def without_operations_touching(self, qubits: Iterable['cirq.Qid']) -> 'Moment':
176
"""Return a copy without operations touching the given qubits."""
177
178
def transform_qubits(self, qubit_map: Mapping['cirq.Qid', 'cirq.Qid']) -> 'Moment':
179
"""Return a copy with qubits transformed according to the map."""
180
181
def __len__(self) -> int:
182
"""Number of operations in the moment."""
183
184
def __iter__(self) -> Iterator['cirq.Operation']:
185
"""Iterator over operations in the moment."""
186
```
187
188
## Circuit Operations
189
190
Hierarchical circuit composition through CircuitOperation.
191
192
```python { .api }
193
class CircuitOperation:
194
"""Operation that wraps a circuit for hierarchical composition."""
195
196
def __init__(self, circuit: FrozenCircuit,
197
repetitions: int = 1,
198
qubit_map: Optional[Dict['cirq.Qid', 'cirq.Qid']] = None,
199
measurement_key_map: Optional[Dict[str, str]] = None,
200
param_resolver: 'cirq.ParamResolverOrSimilarType' = None) -> None:
201
"""Initialize a circuit operation."""
202
203
@property
204
def circuit(self) -> FrozenCircuit:
205
"""The wrapped circuit."""
206
207
@property
208
def repetitions(self) -> int:
209
"""Number of times to repeat the circuit."""
210
211
@property
212
def qubits(self) -> Tuple['cirq.Qid', ...]:
213
"""Qubits operated on by this circuit operation."""
214
215
def with_qubits(self, *new_qubits: 'cirq.Qid') -> 'CircuitOperation':
216
"""Return a copy with different qubits."""
217
218
def with_repetitions(self, repetitions: int) -> 'CircuitOperation':
219
"""Return a copy with different repetition count."""
220
221
def with_qubit_mapping(self, qubit_map: Dict['cirq.Qid', 'cirq.Qid']) -> 'CircuitOperation':
222
"""Return a copy with a qubit mapping."""
223
224
def with_measurement_key_mapping(self, measurement_key_map: Dict[str, str]) -> 'CircuitOperation':
225
"""Return a copy with measurement key mapping."""
226
227
def with_params(self, param_resolver: 'cirq.ParamResolverOrSimilarType') -> 'CircuitOperation':
228
"""Return a copy with parameters resolved."""
229
230
def mapped_circuit(self, deep: bool = True) -> FrozenCircuit:
231
"""Get the circuit with mappings applied."""
232
233
def replace(self, **changes) -> 'CircuitOperation':
234
"""Return a copy with specified changes."""
235
```
236
237
## Insert Strategies
238
239
Control how operations are inserted into circuits.
240
241
```python { .api }
242
class InsertStrategy(enum.Enum):
243
"""Strategies for inserting operations into circuits."""
244
245
EARLIEST = "EARLIEST" # Insert at earliest possible moment
246
NEW = "NEW" # Always create new moment
247
INLINE = "INLINE" # Insert inline if possible
248
NEW_THEN_INLINE = "NEW_THEN_INLINE" # Try new moment, then inline
249
```
250
251
## Alignment
252
253
Circuit alignment utilities for organizing operations.
254
255
```python { .api }
256
class Alignment(enum.Enum):
257
"""Circuit alignment strategies."""
258
259
LEFT = "LEFT" # Align operations to the left
260
RIGHT = "RIGHT" # Align operations to the right
261
```
262
263
## Circuit Optimization
264
265
### PointOptimizer
266
267
Base class for circuit optimization passes.
268
269
```python { .api }
270
class PointOptimizer:
271
"""Base class for circuit optimization passes."""
272
273
@abc.abstractmethod
274
def optimization_at(self, circuit: Circuit, index: int, op: 'cirq.Operation') -> Optional['cirq.PointOptimizationSummary']:
275
"""Optimize circuit at a specific point."""
276
277
def optimize_circuit(self, circuit: Circuit) -> None:
278
"""Apply optimization to an entire circuit."""
279
```
280
281
```python { .api }
282
class PointOptimizationSummary:
283
"""Summary of optimization pass results."""
284
285
def __init__(self, clear_span: int,
286
clear_qubits: Iterable['cirq.Qid'],
287
new_operations: 'cirq.OP_TREE') -> None:
288
"""Initialize optimization summary."""
289
290
@property
291
def clear_span(self) -> int:
292
"""Number of moments to clear."""
293
294
@property
295
def clear_qubits(self) -> FrozenSet['cirq.Qid']:
296
"""Qubits to clear operations from."""
297
298
@property
299
def new_operations(self) -> Tuple['cirq.Operation', ...]:
300
"""New operations to insert."""
301
```
302
303
## Circuit Output and Visualization
304
305
### QasmOutput
306
307
QASM circuit output formatting.
308
309
```python { .api }
310
class QasmOutput:
311
"""QASM circuit output formatter."""
312
313
def __init__(self, operations: Iterable['cirq.Operation'],
314
qubits: Iterable['cirq.Qid'],
315
header: str = '',
316
precision: int = 10,
317
version: str = '2.0') -> None:
318
"""Initialize QASM output formatter."""
319
320
def rename_qubits(self, qubit_map: Dict['cirq.Qid', str]) -> 'QasmOutput':
321
"""Return a copy with renamed qubits."""
322
323
def __str__(self) -> str:
324
"""Generate QASM string representation."""
325
326
def save_to_file(self, file_path: str) -> None:
327
"""Save QASM output to file."""
328
```
329
330
### TextDiagramDrawer
331
332
Text-based circuit diagram generation.
333
334
```python { .api }
335
class TextDiagramDrawer:
336
"""Text-based circuit diagram drawer."""
337
338
def __init__(self) -> None:
339
"""Initialize the text diagram drawer."""
340
341
def write(self, x: float, y: float, text: str) -> None:
342
"""Write text at the specified position."""
343
344
def grid_line(self, x1: float, y1: float, x2: float, y2: float,
345
emphasized: bool = False) -> None:
346
"""Draw a grid line between two points."""
347
348
def force_vertical_padding_after(self, y: float, padding: float) -> None:
349
"""Force vertical padding after the specified y position."""
350
351
def render(self, horizontal_spacing: float = 1,
352
vertical_spacing: float = 1,
353
crossing_char: str = None) -> str:
354
"""Render the diagram as a string."""
355
```
356
357
## Usage Examples
358
359
### Basic Circuit Construction
360
361
```python
362
import cirq
363
364
# Create qubits
365
q0, q1, q2 = cirq.LineQubit.range(3)
366
367
# Build circuit step by step
368
circuit = cirq.Circuit()
369
circuit.append(cirq.H(q0))
370
circuit.append(cirq.CNOT(q0, q1))
371
circuit.append(cirq.CNOT(q1, q2))
372
373
# Or build in one step
374
circuit = cirq.Circuit([
375
cirq.H(q0),
376
cirq.CNOT(q0, q1),
377
cirq.CNOT(q1, q2)
378
])
379
380
print("Circuit:")
381
print(circuit)
382
```
383
384
### Moment-by-Moment Construction
385
386
```python
387
import cirq
388
389
qubits = cirq.LineQubit.range(4)
390
391
# Create specific moments
392
moment1 = cirq.Moment([cirq.H(q) for q in qubits[:2]])
393
moment2 = cirq.Moment([cirq.CNOT(qubits[0], qubits[1]),
394
cirq.CNOT(qubits[2], qubits[3])])
395
396
# Build circuit from moments
397
circuit = cirq.Circuit([moment1, moment2])
398
print(f"Circuit has {len(circuit)} moments")
399
```
400
401
### Circuit Manipulation
402
403
```python
404
import cirq
405
406
qubits = cirq.LineQubit.range(3)
407
circuit = cirq.Circuit()
408
409
# Insert operations with different strategies
410
circuit.insert(0, cirq.H(qubits[0]), strategy=cirq.InsertStrategy.NEW)
411
circuit.insert(1, cirq.X(qubits[1]), strategy=cirq.InsertStrategy.INLINE)
412
413
# Transform qubits
414
old_to_new = {old: new for old, new in zip(qubits, cirq.GridQubit.rect(1, 3))}
415
new_circuit = circuit.transform_qubits(old_to_new)
416
417
# Slice circuits
418
first_half = circuit[:len(circuit)//2]
419
second_half = circuit[len(circuit)//2:]
420
```
421
422
### CircuitOperation Usage
423
424
```python
425
import cirq
426
427
# Define a subcircuit
428
qubits = cirq.LineQubit.range(2)
429
bell_circuit = cirq.FrozenCircuit([
430
cirq.H(qubits[0]),
431
cirq.CNOT(qubits[0], qubits[1])
432
])
433
434
# Use as a circuit operation
435
main_qubits = cirq.GridQubit.rect(2, 2)
436
qubit_map = {qubits[i]: main_qubits[0, i] for i in range(2)}
437
438
bell_op = cirq.CircuitOperation(
439
circuit=bell_circuit,
440
qubit_map=qubit_map,
441
repetitions=3
442
)
443
444
# Insert into main circuit
445
main_circuit = cirq.Circuit(bell_op)
446
print("Main circuit with subcircuit:")
447
print(main_circuit)
448
```
449
450
This comprehensive documentation covers the circuits module's capabilities for building, manipulating, and organizing quantum circuits in Cirq.