A framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
The primary mutable quantum circuit class that contains operations organized in moments.
class Circuit:
"""Mutable quantum circuit containing operations in moments."""
def __init__(self, *contents: 'cirq.OP_TREE') -> None:
"""Initialize a circuit with operations."""
def append(self, op_tree: 'cirq.OP_TREE',
strategy: InsertStrategy = InsertStrategy.NEW_THEN_INLINE) -> None:
"""Append operations to the end of the circuit."""
def insert(self, index: int, op_tree: 'cirq.OP_TREE',
strategy: InsertStrategy = InsertStrategy.NEW_THEN_INLINE) -> None:
"""Insert operations at the specified moment index."""
def insert_into_range(self, operations: 'cirq.OP_TREE', start: int, end: int) -> None:
"""Insert operations into a range of moments."""
def clear_operations_touching(self, qubits: Iterable['cirq.Qid'],
moment_indices: Iterable[int]) -> None:
"""Clear operations touching specified qubits in specified moments."""
def batch_remove(self, removals: Iterable[Tuple[int, 'cirq.Operation']]) -> None:
"""Remove multiple operations specified by (moment_index, operation) pairs."""
def batch_replace(self, replacements: Iterable[Tuple[int, 'cirq.Operation', 'cirq.OP_TREE']]) -> None:
"""Replace multiple operations specified by (moment_index, old_op, new_ops) tuples."""
# Properties and inspection
@property
def moments(self) -> List[Moment]:
"""List of moments in the circuit."""
def all_qubits(self) -> FrozenSet['cirq.Qid']:
"""All qubits used in the circuit."""
def all_operations(self) -> Iterator['cirq.Operation']:
"""Iterator over all operations in the circuit."""
def num_qubits(self) -> int:
"""Number of qubits used by the circuit."""
def qid_shape(self) -> Tuple[int, ...]:
"""Shape of qids used by the circuit."""
def are_all_measurements_terminal(self) -> bool:
"""Check if all measurements are at the end of the circuit."""
# Circuit manipulation
def with_noise(self, noise: 'cirq.NoiseModel') -> 'Circuit':
"""Return a copy of the circuit with noise applied."""
def reversed(self) -> 'Circuit':
"""Return a copy with the order of moments reversed."""
def transform_qubits(self, qubit_map: Dict['cirq.Qid', 'cirq.Qid']) -> 'Circuit':
"""Return a copy with qubits transformed according to the map."""
def zip(self, *other_circuits: 'Circuit') -> 'Circuit':
"""Combine this circuit with others by zipping moments together."""
# Slicing and indexing
def __getitem__(self, key) -> Union['Circuit', Moment]:
"""Get moments or slices of moments."""
def __setitem__(self, key, value) -> None:
"""Set moments or slices of moments."""
def __len__(self) -> int:
"""Number of moments in the circuit."""
# String representations
def __str__(self) -> str:
"""String representation of the circuit."""
def to_text_diagram(self, **kwargs) -> str:
"""Generate a text diagram of the circuit."""
# Validation and optimization
def _resolve_parameters_(self, resolver: 'cirq.ParamResolver', recursive: bool) -> 'Circuit':
"""Resolve parameters in the circuit."""Immutable version of a quantum circuit.
class FrozenCircuit(AbstractCircuit):
"""Immutable quantum circuit."""
def __init__(self, *contents: 'cirq.OP_TREE') -> None:
"""Initialize an immutable circuit."""
# All inspection methods from Circuit (read-only)
@property
def moments(self) -> Tuple[Moment, ...]:
"""Tuple of moments in the circuit."""
def unfreeze(self, copy: bool = True) -> Circuit:
"""Convert to a mutable Circuit."""
def freeze(self) -> 'FrozenCircuit':
"""Return self (already frozen)."""Base class for circuit-like objects.
class AbstractCircuit:
"""Abstract base class for quantum circuits."""
@property
@abc.abstractmethod
def moments(self) -> Sequence[Moment]:
"""Sequence of moments in the circuit."""
def next_moment_operating_on(self, qubits: Iterable['cirq.Qid'],
start_moment_index: int = 0) -> Optional[int]:
"""Find the next moment that operates on any of the given qubits."""
def prev_moment_operating_on(self, qubits: Iterable['cirq.Qid'],
end_moment_index: Optional[int] = None) -> Optional[int]:
"""Find the previous moment that operates on any of the given qubits."""
def operation_at(self, qubit: 'cirq.Qid', moment_index: int) -> Optional['cirq.Operation']:
"""Return the operation on a qubit at a specific moment."""
def findall_operations(self, predicate: Callable[['cirq.Operation'], bool]) -> List[Tuple[int, 'cirq.Operation']]:
"""Find all operations matching a predicate."""Represents operations that occur simultaneously in a quantum circuit.
class Moment:
"""Quantum operations occurring simultaneously."""
def __init__(self, *operations: 'cirq.Operation') -> None:
"""Initialize a moment with operations."""
@property
def operations(self) -> FrozenSet['cirq.Operation']:
"""Set of operations in this moment."""
@property
def qubits(self) -> FrozenSet['cirq.Qid']:
"""All qubits operated on in this moment."""
def operates_on_single_qubit(self, qubit: 'cirq.Qid') -> bool:
"""Check if this moment has any operations on the given qubit."""
def operates_on(self, qubits: Iterable['cirq.Qid']) -> bool:
"""Check if this moment operates on any of the given qubits."""
def operation_at(self, qubit: 'cirq.Qid') -> Optional['cirq.Operation']:
"""Return the operation on a qubit, or None if no operation."""
def with_operation(self, operation: 'cirq.Operation') -> 'Moment':
"""Return a copy with an additional operation."""
def without_operations_touching(self, qubits: Iterable['cirq.Qid']) -> 'Moment':
"""Return a copy without operations touching the given qubits."""
def transform_qubits(self, qubit_map: Mapping['cirq.Qid', 'cirq.Qid']) -> 'Moment':
"""Return a copy with qubits transformed according to the map."""
def __len__(self) -> int:
"""Number of operations in the moment."""
def __iter__(self) -> Iterator['cirq.Operation']:
"""Iterator over operations in the moment."""Hierarchical circuit composition through CircuitOperation.
class CircuitOperation:
"""Operation that wraps a circuit for hierarchical composition."""
def __init__(self, circuit: FrozenCircuit,
repetitions: int = 1,
qubit_map: Optional[Dict['cirq.Qid', 'cirq.Qid']] = None,
measurement_key_map: Optional[Dict[str, str]] = None,
param_resolver: 'cirq.ParamResolverOrSimilarType' = None) -> None:
"""Initialize a circuit operation."""
@property
def circuit(self) -> FrozenCircuit:
"""The wrapped circuit."""
@property
def repetitions(self) -> int:
"""Number of times to repeat the circuit."""
@property
def qubits(self) -> Tuple['cirq.Qid', ...]:
"""Qubits operated on by this circuit operation."""
def with_qubits(self, *new_qubits: 'cirq.Qid') -> 'CircuitOperation':
"""Return a copy with different qubits."""
def with_repetitions(self, repetitions: int) -> 'CircuitOperation':
"""Return a copy with different repetition count."""
def with_qubit_mapping(self, qubit_map: Dict['cirq.Qid', 'cirq.Qid']) -> 'CircuitOperation':
"""Return a copy with a qubit mapping."""
def with_measurement_key_mapping(self, measurement_key_map: Dict[str, str]) -> 'CircuitOperation':
"""Return a copy with measurement key mapping."""
def with_params(self, param_resolver: 'cirq.ParamResolverOrSimilarType') -> 'CircuitOperation':
"""Return a copy with parameters resolved."""
def mapped_circuit(self, deep: bool = True) -> FrozenCircuit:
"""Get the circuit with mappings applied."""
def replace(self, **changes) -> 'CircuitOperation':
"""Return a copy with specified changes."""Control how operations are inserted into circuits.
class InsertStrategy(enum.Enum):
"""Strategies for inserting operations into circuits."""
EARLIEST = "EARLIEST" # Insert at earliest possible moment
NEW = "NEW" # Always create new moment
INLINE = "INLINE" # Insert inline if possible
NEW_THEN_INLINE = "NEW_THEN_INLINE" # Try new moment, then inlineCircuit alignment utilities for organizing operations.
class Alignment(enum.Enum):
"""Circuit alignment strategies."""
LEFT = "LEFT" # Align operations to the left
RIGHT = "RIGHT" # Align operations to the rightBase class for circuit optimization passes.
class PointOptimizer:
"""Base class for circuit optimization passes."""
@abc.abstractmethod
def optimization_at(self, circuit: Circuit, index: int, op: 'cirq.Operation') -> Optional['cirq.PointOptimizationSummary']:
"""Optimize circuit at a specific point."""
def optimize_circuit(self, circuit: Circuit) -> None:
"""Apply optimization to an entire circuit."""class PointOptimizationSummary:
"""Summary of optimization pass results."""
def __init__(self, clear_span: int,
clear_qubits: Iterable['cirq.Qid'],
new_operations: 'cirq.OP_TREE') -> None:
"""Initialize optimization summary."""
@property
def clear_span(self) -> int:
"""Number of moments to clear."""
@property
def clear_qubits(self) -> FrozenSet['cirq.Qid']:
"""Qubits to clear operations from."""
@property
def new_operations(self) -> Tuple['cirq.Operation', ...]:
"""New operations to insert."""QASM circuit output formatting.
class QasmOutput:
"""QASM circuit output formatter."""
def __init__(self, operations: Iterable['cirq.Operation'],
qubits: Iterable['cirq.Qid'],
header: str = '',
precision: int = 10,
version: str = '2.0') -> None:
"""Initialize QASM output formatter."""
def rename_qubits(self, qubit_map: Dict['cirq.Qid', str]) -> 'QasmOutput':
"""Return a copy with renamed qubits."""
def __str__(self) -> str:
"""Generate QASM string representation."""
def save_to_file(self, file_path: str) -> None:
"""Save QASM output to file."""Text-based circuit diagram generation.
class TextDiagramDrawer:
"""Text-based circuit diagram drawer."""
def __init__(self) -> None:
"""Initialize the text diagram drawer."""
def write(self, x: float, y: float, text: str) -> None:
"""Write text at the specified position."""
def grid_line(self, x1: float, y1: float, x2: float, y2: float,
emphasized: bool = False) -> None:
"""Draw a grid line between two points."""
def force_vertical_padding_after(self, y: float, padding: float) -> None:
"""Force vertical padding after the specified y position."""
def render(self, horizontal_spacing: float = 1,
vertical_spacing: float = 1,
crossing_char: str = None) -> str:
"""Render the diagram as a string."""import cirq
# Create qubits
q0, q1, q2 = cirq.LineQubit.range(3)
# Build circuit step by step
circuit = cirq.Circuit()
circuit.append(cirq.H(q0))
circuit.append(cirq.CNOT(q0, q1))
circuit.append(cirq.CNOT(q1, q2))
# Or build in one step
circuit = cirq.Circuit([
cirq.H(q0),
cirq.CNOT(q0, q1),
cirq.CNOT(q1, q2)
])
print("Circuit:")
print(circuit)import cirq
qubits = cirq.LineQubit.range(4)
# Create specific moments
moment1 = cirq.Moment([cirq.H(q) for q in qubits[:2]])
moment2 = cirq.Moment([cirq.CNOT(qubits[0], qubits[1]),
cirq.CNOT(qubits[2], qubits[3])])
# Build circuit from moments
circuit = cirq.Circuit([moment1, moment2])
print(f"Circuit has {len(circuit)} moments")import cirq
qubits = cirq.LineQubit.range(3)
circuit = cirq.Circuit()
# Insert operations with different strategies
circuit.insert(0, cirq.H(qubits[0]), strategy=cirq.InsertStrategy.NEW)
circuit.insert(1, cirq.X(qubits[1]), strategy=cirq.InsertStrategy.INLINE)
# Transform qubits
old_to_new = {old: new for old, new in zip(qubits, cirq.GridQubit.rect(1, 3))}
new_circuit = circuit.transform_qubits(old_to_new)
# Slice circuits
first_half = circuit[:len(circuit)//2]
second_half = circuit[len(circuit)//2:]import cirq
# Define a subcircuit
qubits = cirq.LineQubit.range(2)
bell_circuit = cirq.FrozenCircuit([
cirq.H(qubits[0]),
cirq.CNOT(qubits[0], qubits[1])
])
# Use as a circuit operation
main_qubits = cirq.GridQubit.rect(2, 2)
qubit_map = {qubits[i]: main_qubits[0, i] for i in range(2)}
bell_op = cirq.CircuitOperation(
circuit=bell_circuit,
qubit_map=qubit_map,
repetitions=3
)
# Insert into main circuit
main_circuit = cirq.Circuit(bell_op)
print("Main circuit with subcircuit:")
print(main_circuit)This comprehensive documentation covers the circuits module's capabilities for building, manipulating, and organizing quantum circuits in Cirq.
Install with Tessl CLI
npx tessl i tessl/pypi-cirq