Tutorials

Step-by-step guides for CV cluster state design and optimization

Beginner

Tutorial 1 15 min

Your First Cluster State

Create a simple 4-mode square cluster state and verify entanglement through nullifier variance.

from cv_cluster import ClusterCompiler
from cv_cluster.graph import GraphState

# Define square graph
graph = GraphState.square(4)
print(f"Adjacency matrix:\n{graph.adjacency_matrix}")

# Create compiler
compiler = ClusterCompiler(
    graph=graph,
    squeezing_dB=6.0,
    mesh_architecture="clements"
)

# Compute nullifier variances
variances = compiler.compute_nullifier_variances()
print(f"Nullifier variances: {variances}")
print(f"All < 1 SNU: {all(v < 1 for v in variances)}")
You'll learn: Graph definition, nullifier calculation, entanglement witness
Tutorial 2 20 min

Understanding Nullifiers

Deep dive into CV nullifier operators and their physical interpretation for cluster states.

# Nullifier: δ_j = p_j - Σ_k A_jk x_k
# For mode 0 in a square graph:
# δ_0 = p_0 - A_01*x_1 - A_03*x_3

import numpy as np

# Get nullifier coefficients
coeffs = graph.nullifier_coefficients(mode=0)
print(f"c = {coeffs}")  # [0,0,0,0, 1,-1,0,-1]

# Variance: ⟨δ²⟩ = c^T V c
V = compiler.get_covariance_matrix()
variance = coeffs @ V @ coeffs
print(f"⟨δ_0²⟩ = {variance:.4f} SNU")
You'll learn: Nullifier algebra, coefficient vectors, variance calculation
Tutorial 3 25 min

Interferometer Mesh Basics

Learn how Clements and Reck decompositions implement arbitrary unitaries for cluster generation.

from cv_cluster.mesh import MeshOptimizer

# Clements mesh: O(N²) beamsplitters
mesh = MeshOptimizer(num_modes=4, architecture="clements")
print(f"Number of phases: {mesh.num_phases}")

# Get symplectic matrix for random phases
phases = np.random.uniform(0, 2*np.pi, mesh.num_phases)
S = mesh.symplectic_matrix(phases)
print(f"Symplectic shape: {S.shape}")  # (8, 8)

# Verify symplecticity: S Ω S^T = Ω
Omega = mesh.symplectic_form()
check = S @ Omega @ S.T
print(f"Symplectic: {np.allclose(check, Omega)}")
You'll learn: Mesh architectures, phase parametrization, symplectic matrices
Tutorial 4 20 min

Visualizing Cluster States

Plot Wigner functions, covariance matrices, and graph representations for your cluster states.

from cv_cluster.viz import plot_wigner, plot_graph

# Plot single-mode marginal Wigner
plot_wigner(compiler, mode=0, resolution=100)

# Plot two-mode correlations
plot_wigner(compiler, modes=[0, 1], projection="x1-x2")

# Visualize graph structure
plot_graph(graph, show_weights=True)

# Covariance matrix heatmap
V = compiler.get_covariance_matrix()
plot_covariance(V, labels=['x0','p0','x1','p1',...])
You'll learn: Wigner functions, graph visualization, covariance plotting

Intermediate

Tutorial 5 30 min

Phase Optimization

Use gradient-based optimization to find optimal interferometer phases that minimize nullifier variances.

# Define cost function
def cost(phases):
    vars = compiler.compute_nullifier_variances(phases)
    return np.mean(vars)

# Optimize with L-BFGS-B
result = compiler.optimize_phases(
    method="L-BFGS-B",
    tol=1e-8,
    maxiter=1000
)

print(f"Initial variance: {result.initial_cost:.4f}")
print(f"Final variance: {result.final_cost:.4f}")
print(f"Iterations: {result.iterations}")
print(f"Optimal phases: {result.optimal_phases}")
You'll learn: Cost functions, gradient optimization, convergence analysis
Tutorial 6 35 min

Custom Graph Topologies

Design custom graph adjacency matrices for specialized cluster state applications.

# Weighted graph for error correction
adj = np.array([
    [0, 1, 0, 0.5],
    [1, 0, 1, 0],
    [0, 1, 0, 1],
    [0.5, 0, 1, 0]
])

graph = GraphState.from_adjacency(adj)

# Validate graph properties
print(f"Symmetric: {graph.is_symmetric}")
print(f"Connected: {graph.is_connected}")
print(f"Edge count: {graph.num_edges}")

# Build hierarchical graph
g1 = GraphState.line(3)
g2 = GraphState.line(3)
combined = GraphState.connect(g1, g2, [(2, 0)])
You'll learn: Custom adjacency, weighted edges, graph composition
Tutorial 7 40 min

Loss Modeling

Incorporate realistic optical losses and find the critical threshold for entanglement preservation.

from cv_cluster.loss import LossSimulator

# Configure per-layer loss
loss_sim = LossSimulator(
    compiler,
    loss_per_layer_dB=0.5,
    num_layers=4
)

# Analyze mode-wise degradation
result = loss_sim.analyze()
for i, var in enumerate(result.mode_variances):
    status = "✓" if var < 1 else "✗"
    print(f"Mode {i}: {var:.3f} SNU {status}")

# Find critical threshold
threshold = loss_sim.find_critical_loss()
print(f"Critical: {threshold:.2f} dB/layer")
You'll learn: Loss channels, threshold analysis, mode degradation
Tutorial 8 45 min

Monte Carlo Tolerance Analysis

Run statistical simulations to assess fabrication tolerance impact on cluster state quality.

from cv_cluster.analysis import MonteCarloAnalyzer

mc = MonteCarloAnalyzer(compiler)

# Configure error distributions
result = mc.run(
    num_trials=1000,
    phase_error_std=0.5,    # degrees
    bs_imbalance_std=0.02,  # fraction
    threshold=1.2            # SNU
)

print(f"Success rate: {result.success_rate:.1%}")
print(f"Mean variance: {result.mean_variance:.4f}")
print(f"95th percentile: {result.percentile_95:.4f}")

# Sweep phase error
sweep = mc.sweep_phase_error(errors=np.linspace(0,3,31))
plt.plot(sweep.errors, sweep.success_rates)
You'll learn: Monte Carlo sampling, success criteria, parameter sweeps

Advanced

Tutorial 9 50 min

MBQC Gate Implementation

Implement measurement-based quantum gates using CV cluster states with proper basis corrections.

from cv_cluster.mbqc import MBQCGate

# Create wire cluster for identity
wire = GraphState.line(3)
compiler = ClusterCompiler(wire, squeezing_dB=10)

# Implement Fourier transform
fourier = MBQCGate(
    cluster=compiler,
    measurement_bases=["p", "x"],  # First two modes
    feedforward=True
)

# Simulate gate
output = fourier.apply(input_state)
fidelity = fourier.compute_fidelity(ideal_output)
print(f"Gate fidelity: {fidelity:.4f}")
You'll learn: MBQC protocols, homodyne measurement, feedforward
Tutorial 10 60 min

Multi-Objective Optimization

Jointly optimize for minimal variance, loss tolerance, and fabrication robustness.

from cv_cluster.optimize import MultiObjective

# Define objectives
def variance_cost(phases):
    return compiler.compute_nullifier_variances(phases).mean()

def robustness_cost(phases):
    mc = MonteCarloAnalyzer(compiler)
    return 1 - mc.quick_success_rate(phases)

# Pareto optimization
optimizer = MultiObjective(
    objectives=[variance_cost, robustness_cost],
    weights=[0.7, 0.3]
)

pareto_front = optimizer.optimize(population=100, generations=50)
print(f"Pareto solutions: {len(pareto_front)}")
You'll learn: Pareto optimization, objective weighting, genetic algorithms