mirror of
https://github.com/K-Dense-AI/claude-scientific-skills.git
synced 2026-01-26 16:58:56 +08:00
9.9 KiB
9.9 KiB
Circuit Transformations
This guide covers circuit optimization, compilation, and manipulation using Cirq's transformation framework.
Transformer Framework
Basic Transformers
import cirq
# Example circuit
qubits = cirq.LineQubit.range(3)
circuit = cirq.Circuit(
cirq.H(qubits[0]),
cirq.CNOT(qubits[0], qubits[1]),
cirq.CNOT(qubits[1], qubits[2])
)
# Apply built-in transformer
from cirq.transformers import optimize_for_target_gateset
# Optimize to specific gate set
optimized = optimize_for_target_gateset(
circuit,
gateset=cirq.SqrtIswapTargetGateset()
)
Merge Single-Qubit Gates
from cirq.transformers import merge_single_qubit_gates_to_phxz
# Circuit with multiple single-qubit gates
circuit = cirq.Circuit(
cirq.H(q),
cirq.T(q),
cirq.S(q),
cirq.H(q)
)
# Merge into single operation
merged = merge_single_qubit_gates_to_phxz(circuit)
Drop Negligible Operations
from cirq.transformers import drop_negligible_operations
# Remove gates below threshold
circuit_with_small_rotations = cirq.Circuit(
cirq.rz(1e-10)(q), # Very small rotation
cirq.H(q)
)
cleaned = drop_negligible_operations(circuit_with_small_rotations, atol=1e-8)
Custom Transformers
Transformer Decorator
from cirq.transformers import transformer_api
@transformer_api.transformer
def remove_z_gates(circuit: cirq.Circuit) -> cirq.Circuit:
"""Remove all Z gates from circuit."""
new_moments = []
for moment in circuit:
new_ops = [op for op in moment if not isinstance(op.gate, cirq.ZPowGate)]
if new_ops:
new_moments.append(cirq.Moment(new_ops))
return cirq.Circuit(new_moments)
# Use custom transformer
transformed = remove_z_gates(circuit)
Transformer Class
from cirq.transformers import transformer_primitives
class HToRyTransformer(transformer_primitives.Transformer):
"""Replace H gates with Ry(π/2)."""
def __call__(self, circuit: cirq.Circuit, *, context=None) -> cirq.Circuit:
def map_op(op: cirq.Operation, _) -> cirq.OP_TREE:
if isinstance(op.gate, cirq.HPowGate):
return cirq.ry(np.pi/2)(op.qubits[0])
return op
return transformer_primitives.map_operations(
circuit,
map_op,
deep=True
).unfreeze(copy=False)
# Apply transformer
transformer = HToRyTransformer()
result = transformer(circuit)
Gate Decomposition
Decompose to Target Gateset
from cirq.transformers import optimize_for_target_gateset
# Decompose to CZ + single-qubit rotations
target_gateset = cirq.CZTargetGateset()
decomposed = optimize_for_target_gateset(circuit, gateset=target_gateset)
# Decompose to √iSWAP gates
sqrt_iswap_gateset = cirq.SqrtIswapTargetGateset()
decomposed = optimize_for_target_gateset(circuit, gateset=sqrt_iswap_gateset)
Custom Gate Decomposition
class Toffoli(cirq.Gate):
def _num_qubits_(self):
return 3
def _decompose_(self, qubits):
"""Decompose Toffoli into basic gates."""
c1, c2, t = qubits
return [
cirq.H(t),
cirq.CNOT(c2, t),
cirq.T(t)**-1,
cirq.CNOT(c1, t),
cirq.T(t),
cirq.CNOT(c2, t),
cirq.T(t)**-1,
cirq.CNOT(c1, t),
cirq.T(c2),
cirq.T(t),
cirq.H(t),
cirq.CNOT(c1, c2),
cirq.T(c1),
cirq.T(c2)**-1,
cirq.CNOT(c1, c2)
]
# Use decomposition
circuit = cirq.Circuit(Toffoli()(q0, q1, q2))
decomposed = cirq.decompose(circuit)
Circuit Optimization
Eject Z Gates
from cirq.transformers import eject_z
# Move Z gates to end of circuit
circuit = cirq.Circuit(
cirq.H(q0),
cirq.Z(q0),
cirq.CNOT(q0, q1)
)
ejected = eject_z(circuit)
Eject Phase Gates
from cirq.transformers import eject_phased_paulis
# Consolidate phase gates
optimized = eject_phased_paulis(circuit, atol=1e-8)
Drop Empty Moments
from cirq.transformers import drop_empty_moments
# Remove moments with no operations
cleaned = drop_empty_moments(circuit)
Align Measurements
from cirq.transformers import dephase_measurements
# Move measurements to end and remove operations after
aligned = dephase_measurements(circuit)
Circuit Compilation
Compile for Hardware
import cirq_google
# Get device specification
device = cirq_google.Sycamore
# Compile circuit to device
from cirq.transformers import optimize_for_target_gateset
compiled = optimize_for_target_gateset(
circuit,
gateset=cirq_google.SycamoreTargetGateset()
)
# Validate compiled circuit
device.validate_circuit(compiled)
Two-Qubit Gate Compilation
# Compile to specific two-qubit gate
from cirq import two_qubit_to_cz
# Convert all two-qubit gates to CZ
cz_circuit = cirq.Circuit()
for moment in circuit:
for op in moment:
if len(op.qubits) == 2:
cz_circuit.append(two_qubit_to_cz(op))
else:
cz_circuit.append(op)
Qubit Routing
Route Circuit to Device Topology
from cirq.transformers import route_circuit
# Define device connectivity
device_graph = cirq.NamedTopology(
{
(0, 0): [(0, 1), (1, 0)],
(0, 1): [(0, 0), (1, 1)],
(1, 0): [(0, 0), (1, 1)],
(1, 1): [(0, 1), (1, 0)]
}
)
# Route logical qubits to physical qubits
routed_circuit = route_circuit(
circuit,
device_graph=device_graph,
routing_algo=cirq.RouteCQC(device_graph)
)
SWAP Network Insertion
# Manually insert SWAPs for routing
def insert_swaps(circuit, swap_locations):
"""Insert SWAP gates at specified locations."""
new_circuit = cirq.Circuit()
moment_idx = 0
for i, moment in enumerate(circuit):
if i in swap_locations:
q0, q1 = swap_locations[i]
new_circuit.append(cirq.SWAP(q0, q1))
new_circuit.append(moment)
return new_circuit
Advanced Transformations
Unitary Compilation
import scipy.linalg
# Compile arbitrary unitary to gate sequence
def compile_unitary(unitary, qubits):
"""Compile 2x2 unitary using KAK decomposition."""
from cirq.linalg import kak_decomposition
decomp = kak_decomposition(unitary)
operations = []
# Add single-qubit gates before
operations.append(cirq.MatrixGate(decomp.single_qubit_operations_before[0])(qubits[0]))
operations.append(cirq.MatrixGate(decomp.single_qubit_operations_before[1])(qubits[1]))
# Add interaction (two-qubit) part
x, y, z = decomp.interaction_coefficients
operations.append(cirq.XXPowGate(exponent=x/np.pi)(qubits[0], qubits[1]))
operations.append(cirq.YYPowGate(exponent=y/np.pi)(qubits[0], qubits[1]))
operations.append(cirq.ZZPowGate(exponent=z/np.pi)(qubits[0], qubits[1]))
# Add single-qubit gates after
operations.append(cirq.MatrixGate(decomp.single_qubit_operations_after[0])(qubits[0]))
operations.append(cirq.MatrixGate(decomp.single_qubit_operations_after[1])(qubits[1]))
return operations
Circuit Simplification
from cirq.transformers import (
merge_k_qubit_unitaries,
merge_single_qubit_gates_to_phxz
)
# Merge adjacent single-qubit gates
simplified = merge_single_qubit_gates_to_phxz(circuit)
# Merge adjacent k-qubit unitaries
simplified = merge_k_qubit_unitaries(circuit, k=2)
Commutation-Based Optimization
# Commute Z gates through CNOT
def commute_z_through_cnot(circuit):
"""Move Z gates through CNOT gates."""
new_moments = []
for moment in circuit:
ops = list(moment)
# Find Z gates before CNOT
z_ops = [op for op in ops if isinstance(op.gate, cirq.ZPowGate)]
cnot_ops = [op for op in ops if isinstance(op.gate, cirq.CXPowGate)]
# Apply commutation rules
# Z on control commutes, Z on target anticommutes
# (simplified logic here)
new_moments.append(cirq.Moment(ops))
return cirq.Circuit(new_moments)
Transformation Pipelines
Compose Multiple Transformers
from cirq.transformers import transformer_api
# Build transformation pipeline
@transformer_api.transformer
def optimization_pipeline(circuit: cirq.Circuit) -> cirq.Circuit:
# Step 1: Merge single-qubit gates
circuit = merge_single_qubit_gates_to_phxz(circuit)
# Step 2: Drop negligible operations
circuit = drop_negligible_operations(circuit)
# Step 3: Eject Z gates
circuit = eject_z(circuit)
# Step 4: Drop empty moments
circuit = drop_empty_moments(circuit)
return circuit
# Apply pipeline
optimized = optimization_pipeline(circuit)
Validation and Analysis
Circuit Depth Reduction
# Measure circuit depth before and after
print(f"Original depth: {len(circuit)}")
optimized = optimization_pipeline(circuit)
print(f"Optimized depth: {len(optimized)}")
Gate Count Analysis
def count_gates(circuit):
"""Count gates by type."""
counts = {}
for moment in circuit:
for op in moment:
gate_type = type(op.gate).__name__
counts[gate_type] = counts.get(gate_type, 0) + 1
return counts
original_counts = count_gates(circuit)
optimized_counts = count_gates(optimized)
print(f"Original: {original_counts}")
print(f"Optimized: {optimized_counts}")
Best Practices
- Start with high-level transformers: Use built-in transformers before writing custom ones
- Chain transformers: Apply multiple optimizations in sequence
- Validate after transformation: Ensure circuit correctness and device compatibility
- Measure improvement: Track depth and gate count reduction
- Use appropriate gatesets: Match target hardware capabilities
- Consider commutativity: Exploit gate commutation for optimization
- Test on small circuits first: Verify transformers work correctly before scaling