Initial commit for cirq
This commit is contained in:
307
references/building.md
Normal file
307
references/building.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# Building Quantum Circuits
|
||||
|
||||
This guide covers circuit construction in Cirq, including qubits, gates, operations, and circuit patterns.
|
||||
|
||||
## Basic Circuit Construction
|
||||
|
||||
### Creating Circuits
|
||||
|
||||
```python
|
||||
import cirq
|
||||
|
||||
# Create a circuit
|
||||
circuit = cirq.Circuit()
|
||||
|
||||
# Create qubits
|
||||
q0 = cirq.GridQubit(0, 0)
|
||||
q1 = cirq.GridQubit(0, 1)
|
||||
q2 = cirq.LineQubit(0)
|
||||
|
||||
# Add gates to circuit
|
||||
circuit.append([
|
||||
cirq.H(q0),
|
||||
cirq.CNOT(q0, q1),
|
||||
cirq.measure(q0, q1, key='result')
|
||||
])
|
||||
```
|
||||
|
||||
### Qubit Types
|
||||
|
||||
**GridQubit**: 2D grid topology for hardware-like layouts
|
||||
```python
|
||||
qubits = cirq.GridQubit.square(2) # 2x2 grid
|
||||
qubit = cirq.GridQubit(row=0, col=1)
|
||||
```
|
||||
|
||||
**LineQubit**: 1D linear topology
|
||||
```python
|
||||
qubits = cirq.LineQubit.range(5) # 5 qubits in a line
|
||||
qubit = cirq.LineQubit(3)
|
||||
```
|
||||
|
||||
**NamedQubit**: Custom-named qubits
|
||||
```python
|
||||
qubit = cirq.NamedQubit('my_qubit')
|
||||
```
|
||||
|
||||
## Common Gates and Operations
|
||||
|
||||
### Single-Qubit Gates
|
||||
|
||||
```python
|
||||
# Pauli gates
|
||||
cirq.X(qubit) # NOT gate
|
||||
cirq.Y(qubit)
|
||||
cirq.Z(qubit)
|
||||
|
||||
# Hadamard
|
||||
cirq.H(qubit)
|
||||
|
||||
# Rotation gates
|
||||
cirq.rx(angle)(qubit) # Rotation around X-axis
|
||||
cirq.ry(angle)(qubit) # Rotation around Y-axis
|
||||
cirq.rz(angle)(qubit) # Rotation around Z-axis
|
||||
|
||||
# Phase gates
|
||||
cirq.S(qubit) # √Z gate
|
||||
cirq.T(qubit) # ⁴√Z gate
|
||||
```
|
||||
|
||||
### Two-Qubit Gates
|
||||
|
||||
```python
|
||||
# CNOT (Controlled-NOT)
|
||||
cirq.CNOT(control, target)
|
||||
cirq.CX(control, target) # Alias
|
||||
|
||||
# CZ (Controlled-Z)
|
||||
cirq.CZ(q0, q1)
|
||||
|
||||
# SWAP
|
||||
cirq.SWAP(q0, q1)
|
||||
|
||||
# iSWAP
|
||||
cirq.ISWAP(q0, q1)
|
||||
|
||||
# Controlled rotations
|
||||
cirq.CZPowGate(exponent=0.5)(q0, q1)
|
||||
```
|
||||
|
||||
### Measurement Operations
|
||||
|
||||
```python
|
||||
# Measure single qubit
|
||||
cirq.measure(qubit, key='m')
|
||||
|
||||
# Measure multiple qubits
|
||||
cirq.measure(q0, q1, q2, key='result')
|
||||
|
||||
# Measure all qubits in circuit
|
||||
circuit.append(cirq.measure(*qubits, key='final'))
|
||||
```
|
||||
|
||||
## Advanced Circuit Construction
|
||||
|
||||
### Parameterized Gates
|
||||
|
||||
```python
|
||||
import sympy
|
||||
|
||||
# Create symbolic parameters
|
||||
theta = sympy.Symbol('theta')
|
||||
phi = sympy.Symbol('phi')
|
||||
|
||||
# Use in gates
|
||||
circuit = cirq.Circuit(
|
||||
cirq.rx(theta)(q0),
|
||||
cirq.ry(phi)(q1),
|
||||
cirq.CNOT(q0, q1)
|
||||
)
|
||||
|
||||
# Resolve parameters later
|
||||
resolved = cirq.resolve_parameters(circuit, {'theta': 0.5, 'phi': 1.2})
|
||||
```
|
||||
|
||||
### Custom Gates via Unitaries
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
|
||||
# Define unitary matrix
|
||||
unitary = np.array([
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 0, 1],
|
||||
[0, 0, 1, 0]
|
||||
]) / np.sqrt(2)
|
||||
|
||||
# Create gate from unitary
|
||||
gate = cirq.MatrixGate(unitary)
|
||||
operation = gate(q0, q1)
|
||||
```
|
||||
|
||||
### Gate Decomposition
|
||||
|
||||
```python
|
||||
# Define custom gate with decomposition
|
||||
class MyGate(cirq.Gate):
|
||||
def _num_qubits_(self):
|
||||
return 1
|
||||
|
||||
def _decompose_(self, qubits):
|
||||
q = qubits[0]
|
||||
return [cirq.H(q), cirq.T(q), cirq.H(q)]
|
||||
|
||||
def _circuit_diagram_info_(self, args):
|
||||
return 'MyGate'
|
||||
|
||||
# Use the custom gate
|
||||
my_gate = MyGate()
|
||||
circuit.append(my_gate(q0))
|
||||
```
|
||||
|
||||
## Circuit Organization
|
||||
|
||||
### Moments
|
||||
|
||||
Circuits are organized into moments (parallel operations):
|
||||
|
||||
```python
|
||||
# Explicit moment construction
|
||||
circuit = cirq.Circuit(
|
||||
cirq.Moment([cirq.H(q0), cirq.H(q1)]),
|
||||
cirq.Moment([cirq.CNOT(q0, q1)]),
|
||||
cirq.Moment([cirq.measure(q0, key='m0'), cirq.measure(q1, key='m1')])
|
||||
)
|
||||
|
||||
# Access moments
|
||||
for i, moment in enumerate(circuit):
|
||||
print(f"Moment {i}: {moment}")
|
||||
```
|
||||
|
||||
### Circuit Operations
|
||||
|
||||
```python
|
||||
# Concatenate circuits
|
||||
circuit3 = circuit1 + circuit2
|
||||
|
||||
# Insert operations
|
||||
circuit.insert(index, operation)
|
||||
|
||||
# Append with strategy
|
||||
circuit.append(operations, strategy=cirq.InsertStrategy.NEW_THEN_INLINE)
|
||||
```
|
||||
|
||||
## Circuit Patterns
|
||||
|
||||
### Bell State Preparation
|
||||
|
||||
```python
|
||||
def bell_state_circuit():
|
||||
q0, q1 = cirq.LineQubit.range(2)
|
||||
return cirq.Circuit(
|
||||
cirq.H(q0),
|
||||
cirq.CNOT(q0, q1)
|
||||
)
|
||||
```
|
||||
|
||||
### GHZ State
|
||||
|
||||
```python
|
||||
def ghz_circuit(qubits):
|
||||
circuit = cirq.Circuit()
|
||||
circuit.append(cirq.H(qubits[0]))
|
||||
for i in range(len(qubits) - 1):
|
||||
circuit.append(cirq.CNOT(qubits[i], qubits[i+1]))
|
||||
return circuit
|
||||
```
|
||||
|
||||
### Quantum Fourier Transform
|
||||
|
||||
```python
|
||||
def qft_circuit(qubits):
|
||||
circuit = cirq.Circuit()
|
||||
for i, q in enumerate(qubits):
|
||||
circuit.append(cirq.H(q))
|
||||
for j in range(i + 1, len(qubits)):
|
||||
circuit.append(cirq.CZPowGate(exponent=1/2**(j-i))(qubits[j], q))
|
||||
|
||||
# Reverse qubit order
|
||||
for i in range(len(qubits) // 2):
|
||||
circuit.append(cirq.SWAP(qubits[i], qubits[len(qubits) - i - 1]))
|
||||
|
||||
return circuit
|
||||
```
|
||||
|
||||
## Circuit Import/Export
|
||||
|
||||
### OpenQASM
|
||||
|
||||
```python
|
||||
# Export to QASM
|
||||
qasm_str = circuit.to_qasm()
|
||||
|
||||
# Import from QASM
|
||||
from cirq.contrib.qasm_import import circuit_from_qasm
|
||||
circuit = circuit_from_qasm(qasm_str)
|
||||
```
|
||||
|
||||
### Circuit JSON
|
||||
|
||||
```python
|
||||
import json
|
||||
|
||||
# Serialize
|
||||
json_str = cirq.to_json(circuit)
|
||||
|
||||
# Deserialize
|
||||
circuit = cirq.read_json(json_text=json_str)
|
||||
```
|
||||
|
||||
## Working with Qudits
|
||||
|
||||
Qudits are higher-dimensional quantum systems (qutrits, ququarts, etc.):
|
||||
|
||||
```python
|
||||
# Create qutrit (3-level system)
|
||||
qutrit = cirq.LineQid(0, dimension=3)
|
||||
|
||||
# Custom qutrit gate
|
||||
class QutritXGate(cirq.Gate):
|
||||
def _qid_shape_(self):
|
||||
return (3,)
|
||||
|
||||
def _unitary_(self):
|
||||
return np.array([
|
||||
[0, 0, 1],
|
||||
[1, 0, 0],
|
||||
[0, 1, 0]
|
||||
])
|
||||
|
||||
gate = QutritXGate()
|
||||
circuit = cirq.Circuit(gate(qutrit))
|
||||
```
|
||||
|
||||
## Observables
|
||||
|
||||
Create observables from Pauli operators:
|
||||
|
||||
```python
|
||||
# Single Pauli observable
|
||||
obs = cirq.Z(q0)
|
||||
|
||||
# Pauli string
|
||||
obs = cirq.X(q0) * cirq.Y(q1) * cirq.Z(q2)
|
||||
|
||||
# Linear combination
|
||||
from cirq import PauliSum
|
||||
obs = 0.5 * cirq.X(q0) + 0.3 * cirq.Z(q1)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use appropriate qubit types**: GridQubit for hardware-like topologies, LineQubit for 1D problems
|
||||
2. **Keep circuits modular**: Build reusable circuit functions
|
||||
3. **Use symbolic parameters**: For parameter sweeps and optimization
|
||||
4. **Label measurements clearly**: Use descriptive keys for measurement results
|
||||
5. **Document custom gates**: Include circuit diagram information for visualization
|
||||
Reference in New Issue
Block a user