Examples¶
This section provides comprehensive examples of using TQC for various quantum computing tasks, from basic operations to advanced algorithms.
Basic Examples¶
Hello Quantum World - Bell State¶
Create and simulate a Bell state using topological compilation:
from tqc import TopologicalCompiler, FibonacciAnyons
from qiskit import QuantumCircuit
import matplotlib.pyplot as plt
# Create a Bell state circuit
qc = QuantumCircuit(2, 2)
qc.h(0) # Hadamard gate on qubit 0
qc.cx(0, 1) # CNOT gate
qc.measure_all() # Measure both qubits
# Initialize TQC with Fibonacci anyons
compiler = TopologicalCompiler(anyon_type=FibonacciAnyons())
# Compile to topological braids
braid_program = compiler.compile(qc)
print(f"Compiled to {len(braid_program.braid_sequence)} braiding operations")
# Simulate the braided computation
result = braid_program.simulate(shots=1000)
print(f"Bell state results: {result.counts}")
# Visualize the braid diagram
braid_program.visualize_braid("bell_state_braid.svg")
Compilation Flow:
flowchart LR
subgraph "Quantum Circuit"
H[H Gate<br/>Qubit 0]
CNOT[CNOT<br/>0→1]
M[Measure<br/>All]
end
subgraph "Anyonic Representation"
H_BRAID[Hadamard<br/>Braiding]
CNOT_BRAID[Entangling<br/>Braids]
FUSION[Fusion<br/>Measurement]
end
H --> H_BRAID
CNOT --> CNOT_BRAID
M --> FUSION
classDef quantumClass fill:#2196f3,stroke:#0d47a1,color:#fff
classDef anyonClass fill:#ff9800,stroke:#ef6c00,color:#fff
class H,CNOT,M quantumClass
class H_BRAID,CNOT_BRAID,FUSION anyonClass
Quantum Phase Estimation¶
Implement quantum phase estimation with topological protection:
from tqc import TopologicalCompiler, IsingAnyons
from qiskit import QuantumCircuit
from qiskit.circuit.library import QFT
import numpy as np
def quantum_phase_estimation(unitary, eigenstate, n_precision=3):
"""Topological quantum phase estimation."""
n_qubits = eigenstate.num_qubits
qc = QuantumCircuit(n_precision + n_qubits, n_precision)
# Initialize precision qubits in superposition
for i in range(n_precision):
qc.h(i)
# Initialize eigenstate
qc.compose(eigenstate, range(n_precision, n_precision + n_qubits), inplace=True)
# Controlled unitary operations
for i in range(n_precision):
for _ in range(2**i):
qc.compose(unitary.control(), [i] + list(range(n_precision, n_precision + n_qubits)), inplace=True)
# Inverse QFT on precision qubits
qc.compose(QFT(n_precision).inverse(), range(n_precision), inplace=True)
# Measure precision qubits
qc.measure(range(n_precision), range(n_precision))
# Compile with Ising anyons for better precision
compiler = TopologicalCompiler(anyon_type=IsingAnyons())
return compiler.compile(qc)
# Example usage
from qiskit.circuit.library import ZGate
eigenstate = QuantumCircuit(1)
eigenstate.ry(np.pi/4, 0) # |+⟩ state
qpe_program = quantum_phase_estimation(ZGate(), eigenstate)
result = qpe_program.simulate(shots=1024)
estimated_phase = max(result.counts, key=result.counts.get) / (2**3)
print(f"Estimated phase: {estimated_phase}")
Advanced Examples¶
Variational Quantum Eigensolver (VQE)¶
Solve molecular electronic structure problems with topological error protection:
from tqc import TopologicalCompiler, FibonacciAnyons
from tqc.optimization import BraidOptimizer
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
import numpy as np
class TopologicalVQE:
def __init__(self, hamiltonian, ansatz, anyon_type=None):
self.hamiltonian = hamiltonian
self.ansatz = ansatz
self.compiler = TopologicalCompiler(
anyon_type=anyon_type or FibonacciAnyons()
)
self.optimizer = BraidOptimizer()
def energy_evaluation(self, params):
"""Evaluate energy using topological simulation."""
# Bind parameters to ansatz
bound_ansatz = self.ansatz.bind_parameters(params)
# Compile to topological braids
braid_program = self.compiler.compile(bound_ansatz)
# Optimize braid sequence
optimized_program = self.optimizer.optimize(braid_program)
# Simulate and measure expectation value
energy = optimized_program.expectation_value(self.hamiltonian)
return energy
def run(self, initial_params=None, max_iterations=100):
"""Run VQE optimization."""
if initial_params is None:
initial_params = np.random.uniform(0, 2*np.pi, self.ansatz.num_parameters)
# Classical optimization loop
current_params = initial_params
for iteration in range(max_iterations):
energy = self.energy_evaluation(current_params)
print(f"Iteration {iteration}: Energy = {energy:.6f}")
# Update parameters (simplified gradient descent)
gradient = self._compute_gradient(current_params)
current_params -= 0.01 * gradient
return current_params, energy
def _compute_gradient(self, params):
"""Compute energy gradient using parameter shift rule."""
gradient = np.zeros_like(params)
for i in range(len(params)):
# Forward and backward shifts
params_plus = params.copy()
params_minus = params.copy()
params_plus[i] += np.pi/2
params_minus[i] -= np.pi/2
gradient[i] = (
self.energy_evaluation(params_plus) -
self.energy_evaluation(params_minus)
) / 2
return gradient
# Example: H2 molecule
def create_h2_hamiltonian():
"""Create H2 molecule Hamiltonian."""
# Simplified H2 Hamiltonian (4 qubits)
# In practice, use PySCF or other quantum chemistry library
from qiskit.quantum_info import SparsePauliOp
pauli_strings = ['IIII', 'IIIZ', 'IIZI', 'IZII', 'ZIII', 'IIZZ', 'IZIZ', 'ZZII']
coefficients = [-1.0523, 0.3979, -0.3979, -0.0113, 0.0113, -0.0113, 0.1809, 0.1809]
return SparsePauliOp.from_list(list(zip(pauli_strings, coefficients)))
def create_uccsd_ansatz(n_qubits=4):
"""Create UCCSD-inspired ansatz."""
qc = QuantumCircuit(n_qubits)
params = [Parameter(f'θ_{i}') for i in range(8)]
# Initial state preparation
qc.ry(params[0], 0)
qc.ry(params[1], 1)
# Entangling layers
for i in range(2):
# CNOT cascade
for j in range(n_qubits-1):
qc.cx(j, j+1)
# Parameterized rotations
for j in range(n_qubits):
qc.ry(params[2 + i*2 + j//2], j)
qc.rz(params[3 + i*2 + j//2], j)
return qc
# Run VQE
hamiltonian = create_h2_hamiltonian()
ansatz = create_uccsd_ansatz()
vqe = TopologicalVQE(hamiltonian, ansatz, FibonacciAnyons())
optimal_params, ground_energy = vqe.run()
print(f"Ground state energy: {ground_energy:.6f} Ha")
VQE Workflow:
flowchart TD
subgraph "Classical Optimization"
PARAMS[Parameters θ]
OPTIMIZER[Classical Optimizer]
GRADIENT[Gradient Computation]
end
subgraph "Quantum Simulation"
ANSATZ[Parameterized Ansatz]
COMPILE[Topological Compilation]
SIMULATE[Anyonic Simulation]
MEASURE[Energy Measurement]
end
PARAMS --> ANSATZ
ANSATZ --> COMPILE
COMPILE --> SIMULATE
SIMULATE --> MEASURE
MEASURE --> GRADIENT
GRADIENT --> OPTIMIZER
OPTIMIZER --> PARAMS
classDef classicalClass fill:#4caf50,stroke:#2e7d32,color:#fff
classDef quantumClass fill:#673ab7,stroke:#4527a0,color:#fff
class PARAMS,OPTIMIZER,GRADIENT classicalClass
class ANSATZ,COMPILE,SIMULATE,MEASURE quantumClass
Quantum Approximate Optimization Algorithm (QAOA)¶
Solve combinatorial optimization problems with topological quantum circuits:
from tqc import TopologicalCompiler, FibonacciAnyons
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
import networkx as nx
import numpy as np
class TopologicalQAOA:
def __init__(self, graph, p_layers=1):
self.graph = graph
self.p_layers = p_layers
self.n_qubits = len(graph.nodes())
self.compiler = TopologicalCompiler(anyon_type=FibonacciAnyons())
def create_qaoa_circuit(self, gamma, beta):
"""Create QAOA circuit with given parameters."""
qc = QuantumCircuit(self.n_qubits, self.n_qubits)
# Initialize in equal superposition
qc.h(range(self.n_qubits))
# Apply p layers of QAOA
for layer in range(self.p_layers):
# Cost Hamiltonian (problem-specific)
for edge in self.graph.edges():
i, j = edge
qc.rzz(gamma[layer], i, j)
# Mixer Hamiltonian
for qubit in range(self.n_qubits):
qc.rx(beta[layer], qubit)
# Measurement
qc.measure_all()
return qc
def evaluate_cut_expectation(self, gamma, beta, shots=1000):
"""Evaluate expected cut value."""
qc = self.create_qaoa_circuit(gamma, beta)
# Compile to topological braids
braid_program = self.compiler.compile(qc)
# Simulate
result = braid_program.simulate(shots=shots)
# Calculate expected cut value
expected_cut = 0
for bitstring, count in result.counts.items():
cut_value = self._calculate_cut(bitstring)
expected_cut += cut_value * count / shots
return expected_cut
def _calculate_cut(self, bitstring):
"""Calculate cut value for given bitstring."""
cut_value = 0
for edge in self.graph.edges():
i, j = edge
if bitstring[i] != bitstring[j]:
cut_value += 1
return cut_value
def optimize(self, max_iterations=50):
"""Optimize QAOA parameters."""
# Random initial parameters
gamma = np.random.uniform(0, np.pi, self.p_layers)
beta = np.random.uniform(0, np.pi, self.p_layers)
best_cut = 0
best_params = (gamma, beta)
for iteration in range(max_iterations):
current_cut = self.evaluate_cut_expectation(gamma, beta)
if current_cut > best_cut:
best_cut = current_cut
best_params = (gamma.copy(), beta.copy())
print(f"Iteration {iteration}: Cut = {current_cut:.3f}")
# Simple parameter update (in practice, use sophisticated optimizers)
gamma += np.random.normal(0, 0.1, self.p_layers)
beta += np.random.normal(0, 0.1, self.p_layers)
# Keep parameters in valid range
gamma = np.clip(gamma, 0, np.pi)
beta = np.clip(beta, 0, np.pi)
return best_params, best_cut
# Example: Max-Cut on random graph
def create_random_graph(n_nodes=6, edge_prob=0.5):
"""Create random graph for Max-Cut problem."""
G = nx.Graph()
G.add_nodes_from(range(n_nodes))
for i in range(n_nodes):
for j in range(i+1, n_nodes):
if np.random.random() < edge_prob:
G.add_edge(i, j)
return G
# Run QAOA
graph = create_random_graph(n_nodes=4)
qaoa = TopologicalQAOA(graph, p_layers=2)
optimal_params, max_cut = qaoa.optimize()
print(f"Maximum cut found: {max_cut}")
print(f"Optimal parameters: γ={optimal_params[0]}, β={optimal_params[1]}")
QAOA Circuit Structure:
flowchart LR
subgraph "Initial State"
INIT[|+⟩^⊗n<br/>Hadamard on all qubits]
end
subgraph "QAOA Layers"
COST1[Cost Hamiltonian<br/>RZZ gates]
MIX1[Mixer Hamiltonian<br/>RX gates]
COST2[Cost Hamiltonian<br/>RZZ gates]
MIX2[Mixer Hamiltonian<br/>RX gates]
end
subgraph "Measurement"
MEAS[Computational Basis<br/>Measurement]
end
INIT --> COST1
COST1 --> MIX1
MIX1 --> COST2
COST2 --> MIX2
MIX2 --> MEAS
classDef initClass fill:#4caf50,stroke:#2e7d32,color:#fff
classDef layerClass fill:#ff9800,stroke:#ef6c00,color:#fff
classDef measClass fill:#673ab7,stroke:#4527a0,color:#fff
class INIT initClass
class COST1,MIX1,COST2,MIX2 layerClass
class MEAS measClass
Performance Comparison¶
Compare topological vs. traditional quantum simulation:
xychart-line
title "Performance Comparison: TQC vs Traditional"
x-axis [2, 4, 6, 8, 10, 12, 14, 16]
y-axis "Execution Time (seconds)" 0 --> 1000
line "Traditional Simulation" [0.1, 0.5, 2.1, 8.4, 33.7, 134.8, 539.2, 2156.8]
line "TQC (Fibonacci)" [0.15, 0.7, 2.8, 11.2, 44.8, 179.2, 716.8, 2867.2]
line "TQC (Ising)" [0.12, 0.6, 2.4, 9.6, 38.4, 153.6, 614.4, 2457.6]
Interactive Examples¶
Try these examples in your local environment:
- Bell State Creation:
python examples/bell_state.py - VQE Optimization:
python examples/vqe_h2.py - QAOA Max-Cut:
python examples/qaoa_maxcut.py - Custom Anyon Types:
python examples/custom_anyons.py
Each example includes detailed comments and can be modified to explore different parameters and configurations.