Quantum-Mechanics
Quantum gates, state representations, fidelity metrics, noise channels, and error-correcting codes for qubit-based computation.
Namespace: CSharpNumerics.Physics.Quantum
using CSharpNumerics.Physics.Quantum;
using CSharpNumerics.Physics.Quantum.NoiseModels;
using CSharpNumerics.Physics.Quantum.ErrorCorrection;
⚛️ Quantum Gates
Namespace: CSharpNumerics.Physics.Quantum
Quantum gates are unitary operators acting on one or more qubits. Each gate is represented by a ComplexMatrix and knows how to apply itself to a ComplexVectorN state vector.
All gates extend the abstract QuantumGate base class:
| Class | Qubits | Matrix | Description |
|---|---|---|---|
HadamardGate | 1 | Creates equal superposition | |
PauliXGate | 1 | Quantum NOT — flips |0⟩ ↔ |1⟩ | |
PauliYGate | 1 | Bit + phase flip, | |
PauliZGate | 1 | Phase flip — |1⟩ → −|1⟩ | |
SGate | 1 | Phase gate (π/2), | |
TGate | 1 | π/8 gate, | |
PhaseGate(θ) | 1 | General phase gate, | |
RxGate(θ) | 1 | Rotation about X-axis | |
RyGate(θ) | 1 | Rotation about Y-axis | |
RzGate(θ) | 1 | Rotation about Z-axis | |
CNOTGate | 2 | 4×4 permutation | Flips target qubit when control is |1⟩ |
CZGate | 2 | Phase flip on |11⟩ | |
CPhaseGate(θ) | 2 | Controlled phase, | |
SWAPGate | 2 | 4×4 permutation | Swaps two qubit states |
ToffoliGate | 3 | 8×8 permutation | CCNOT — flips target when both controls are |1⟩ |
FredkinGate | 3 | 8×8 permutation | CSWAP — swaps targets when control is |1⟩ |
PhaseOracle(n, states) | n | 2ⁿ×2ⁿ diagonal | Flips phase of marked basis states: |w⟩ → −|w⟩ |
ControlledGate(U) | n+1 | 2ⁿ⁺¹×2ⁿ⁺¹ block | Applies U when control qubit is |1⟩ |
ModularMultiplyGate(a,N,n) | n | 2ⁿ×2ⁿ permutation | |y⟩ → |ay mod N⟩, used in Shor's algorithm |
QuantumGate (abstract)
public abstract class QuantumGate
{
public abstract int QubitCount { get; }
public abstract ComplexMatrix GetMatrix();
public ComplexVectorN Apply(ComplexVectorN amplitudes, int[] qubitIndices, int totalQubits);
}
Apply uses the gate's unitary matrix to transform the relevant amplitudes in-place (tensor-product expansion) — works for arbitrary qubit counts and target indices.
Usage
Gates are consumed by QuantumInstruction and QuantumCircuit in the Engines Quantum section:
using CSharpNumerics.Physics.Quantum;
using CSharpNumerics.Engines.Quantum;
var circuit = new QuantumCircuit(2);
circuit.AddInstruction(new QuantumInstruction(new HadamardGate(), new List<int> { 0 }));
circuit.AddInstruction(new QuantumInstruction(new CNOTGate(), new List<int> { 0, 1 }));
var state = new QuantumSimulator().Run(circuit); // Bell state (|00⟩ + |11⟩)/√2
🌐 BlochVector
Represents a single-qubit pure state on the Bloch sphere. Given :
using CSharpNumerics.Physics.Quantum;
using CSharpNumerics.Engines.Quantum;
// From a circuit result
var circuit = new QuantumCircuit(1);
circuit.AddInstruction(new QuantumInstruction(new HadamardGate(), new List<int> { 0 }));
var state = new QuantumSimulator().Run(circuit);
BlochVector bloch = state.GetBlochVector(); // (1, 0, 0) — +X axis
double theta = bloch.Theta; // polar angle θ
double phi = bloch.Phi; // azimuthal angle φ
double r = bloch.Radius; // 1.0 for pure states
Vector v = bloch.ToVector(); // 3D Vector for rendering
// Directly from amplitudes
var b = BlochVector.FromAmplitudes(
new ComplexNumber(1, 0), new ComplexNumber(0, 0)); // |0⟩ → (0, 0, 1)
| Property | Description |
|---|---|
X, Y, Z | Cartesian Bloch coordinates |
Theta | Polar angle from +Z |
Phi | Azimuthal angle |
Radius | Vector length (1 for pure states) |
ToVector() | Returns a 3D Vector for visualization |
Canonical states on the sphere:
| State | Bloch |
|---|---|
| — north pole | |
| — south pole | |
| — +X | |
| — −X | |
| — +Y | |
| — −Y |
📏 QuantumFidelity
Static methods for computing the overlap between quantum states. Fidelity ranges from 0 (orthogonal) to 1 (identical).
State fidelity —
using CSharpNumerics.Physics.Quantum;
using CSharpNumerics.Engines.Quantum;
var sim = new QuantumSimulator();
var s0 = sim.Run(QuantumCircuitBuilder.New(1).Build()); // |0⟩
var sPlus = sim.Run(QuantumCircuitBuilder.New(1).H(0).Build()); // |+⟩
var s1 = sim.Run(QuantumCircuitBuilder.New(1).X(0).Build()); // |1⟩
double f1 = QuantumFidelity.Fidelity(s0, s0); // 1.0 — identical
double f2 = QuantumFidelity.Fidelity(s0, sPlus); // 0.5 — overlap
double f3 = QuantumFidelity.Fidelity(s0, s1); // 0.0 — orthogonal
Vector fidelity — works directly on ComplexVectorN
double f = QuantumFidelity.Fidelity(psi, phi); // |⟨ψ|φ⟩|²
Bloch fidelity — geometric formula for single-qubit states:
var b1 = s1State.GetBlochVector();
var b2 = s2State.GetBlochVector();
double f = QuantumFidelity.BlochFidelity(b1, b2);
// Matches state fidelity for pure single-qubit states
🔊 Noise Models
The Physics.Quantum.NoiseModels namespace provides quantum noise channels using the Kraus operator formalism. Each channel implements INoiseChannel and satisfies the completeness relation .
| Channel | Parameter | Kraus Operators | Physical Model |
|---|---|---|---|
DepolarizingNoise(p) | , | Random Pauli error — qubit replaced by maximally mixed state with probability | |
DephasingNoise(p) | , | Phase-flip error — decoherence | |
AmplitudeDampingNoise(γ) | , | Energy dissipation — decay () |
Usage with NoisyQuantumSimulator (from CSharpNumerics.Engines.Quantum):
using CSharpNumerics.Physics.Quantum.NoiseModels;
using CSharpNumerics.Engines.Quantum;
var circuit = QuantumCircuitBuilder.New(2).H(0).CNOT(0, 1).Build();
// Ideal simulation
var ideal = new QuantumSimulator().Run(circuit);
// Noisy simulation — channels stacked, applied after each gate
var noisy = new NoisyQuantumSimulator(new Random(42))
.WithNoise(new DepolarizingNoise(0.01))
.WithNoise(new AmplitudeDampingNoise(0.005))
.Run(circuit);
double fidelity = QuantumFidelity.Fidelity(ideal, noisy);
INoiseChannel interface
public interface INoiseChannel
{
int QubitCount { get; }
ComplexMatrix[] GetKrausOperators();
}
🛡️ Quantum Error Correction — Code Definitions
Namespace: CSharpNumerics.Physics.Quantum.ErrorCorrection
The ErrorCorrection sub-namespace defines quantum error-correcting codes as mathematical objects — stabilizers, correction maps, and logical operators. The simulation/orchestration layer lives in Engines.Quantum.ErrorCorrection.
IQuantumErrorCorrectionCode
Interface for any [[n, k, d]] stabilizer code:
| Property / Method | Description |
|---|---|
PhysicalQubits | Number of physical qubits (n) |
LogicalQubits | Number of logical qubits (k) |
Distance | Code distance (d) |
SyndromeQubits | Number of ancilla qubits for syndrome extraction |
GetStabilizers() | Returns stabilizer generators as (qubit, Pauli) lists |
GetCorrectionMap() | Syndrome integer → corrective (qubit, Pauli) operations |
GetLogicalX(i) | Logical X̄ operator for logical qubit i |
GetLogicalZ(i) | Logical Z̄ operator for logical qubit i |
BitFlipCode3 — [[3,1,1]]
Encodes into . Corrects any single-qubit X (bit-flip) error.
Stabilizers: ,
| Syndrome | Error | Correction |
|---|---|---|
| 00 | None | — |
| 01 | Apply X to qubit 0 | |
| 10 | Apply X to qubit 2 | |
| 11 | Apply X to qubit 1 |
Logical operators: ,
PhaseFlipCode3 — [[3,1,1]]
Encodes into . Corrects any single-qubit Z (phase-flip) error.
Stabilizers: ,
| Syndrome | Error | Correction |
|---|---|---|
| 00 | None | — |
| 01 | Apply Z to qubit 0 | |
| 10 | Apply Z to qubit 2 | |
| 11 | Apply Z to qubit 1 |
Logical operators: ,
using CSharpNumerics.Physics.Quantum.ErrorCorrection;
var code = new BitFlipCode3();
var stabs = code.GetStabilizers(); // [{(0,'Z'),(1,'Z')}, {(1,'Z'),(2,'Z')}]
var map = code.GetCorrectionMap(); // 0→[], 1→[(0,'X')], 2→[(2,'X')], 3→[(1,'X')]
var logX = code.GetLogicalX(); // [(0,'X'),(1,'X'),(2,'X')]
ShorCode9 — [[9,1,3]]
Shor's 9-qubit code — the first code to correct any single-qubit error (X, Z, or Y). Uses three blocks of three qubits: inner bit-flip repetition within blocks, outer phase-flip repetition across blocks.
8 stabilizer generators:
| Generator | Operator | Type |
|---|---|---|
| within each block | Bit-flip detection | |
| Phase-flip detection (blocks 0–1) | ||
| Phase-flip detection (blocks 1–2) |
Correction: The 8-bit syndrome (256 values) maps to at most one X correction + one Z correction. Each block's 2-bit sub-syndrome identifies bit-flip errors exactly as in BitFlipCode3. The 2-bit phase-flip sub-syndrome identifies which block suffered a Z error.
Logical operators: ,
var shor = new ShorCode9();
var stabs = shor.GetStabilizers(); // 8 generators
var map = shor.GetCorrectionMap(); // 256 syndrome entries
SteaneCode7 — [[7,1,3]]
The Steane code — the smallest CSS (Calderbank-Shor-Steane) code, correcting any single-qubit error using only 7 physical qubits. Built from the classical [7,4,3] Hamming code and its dual [7,3,4] code.
where is the [7,3,4] dual Hamming code and .
6 stabilizer generators:
| Generator | Operator | Type |
|---|---|---|
| X-error detection | ||
| X-error detection | ||
| X-error detection | ||
| Z-error detection | ||
| Z-error detection | ||
| Z-error detection |
Correction: The 6-bit syndrome has two independent 3-bit halves — Z-stabilizer syndrome (bits 0–2) identifies X errors, X-stabilizer syndrome (bits 3–5) identifies Z errors, using the Hamming decoding map: syndrome qubit where column of the parity-check matrix equals the binary expansion of .
Logical operators: ,
var steane = new SteaneCode7();
var stabs = steane.GetStabilizers(); // 6 generators (3 Z-type + 3 X-type)
var map = steane.GetCorrectionMap(); // 64 syndrome entries
🌀 Schrödinger Equation (Wave Mechanics)
Alongside the gate-based model above, the CSharpNumerics.Physics.Quantum namespace provides extension methods for the one-dimensional Schrödinger equation — the wave-mechanics counterpart to the Quantum Gates engine. It covers stationary states (the time-independent eigenvalue problem), wavefunction observables, time evolution, tunnelling, and de Broglie relations. Defaults use natural units (ħ = 1, m = 1); pass explicit constants for SI calculations.
🪜 Stationary States (Time-Independent Schrödinger Equation)
SolveStationaryStates discretises the Hamiltonian on a uniform grid with a three-point Laplacian (Dirichlet walls) and diagonalises it with a dedicated symmetric (Jacobi) eigensolver — returning the lowest energy levels and their normalised wavefunctions.
using CSharpNumerics.Physics.Quantum;
// Harmonic oscillator V(x) = ½x² (ħ = m = ω = 1) → Eₙ = n + ½
Func<double, double> potential = x => 0.5 * x * x;
StationaryStates states = potential.SolveStationaryStates(
xMin: -8, xMax: 8, points: 200, mass: 1, hbar: 1, states: 3);
double e0 = states.GroundStateEnergy; // ≈ 0.5
double[] phi0 = states.WaveFunctions[0]; // normalised ground-state wavefunction
double[] x = states.Grid;
Closed-form energy levels are available directly:
double box = 1.InfiniteSquareWellEnergy(width: 1.0); // E₁ = n²π²ħ²/(2mL²)
double sho = 0.HarmonicOscillatorEnergy(angularFrequency: 1); // Eₙ = ħω(n + ½)
📏 Wavefunction Observables
Operate on a complex wavefunction sampled on a grid (ComplexNumber[] + spacing Δx):
ComplexNumber[] psi = phi0.ToComplexWaveFunction(); // lift a real state to complex
double total = psi.NormSquared(dx); // ∫|ψ|² dx
ComplexNumber[] unit = psi.Normalize(dx); // ∫|ψ|² dx = 1
double[] density = psi.ProbabilityDensity(); // |ψ(x)|²
double meanX = psi.ExpectationPosition(x, dx); // ⟨x⟩
double spread = psi.PositionUncertainty(x, dx); // Δx
double meanP = psi.ExpectationMomentum(dx); // ⟨p⟩ = ∫ψ*(−iħ∂ₓ)ψ dx
⏳ Time Evolution (Spectral Method)
A superposition of stationary states evolves exactly as . The norm is conserved and a single eigenstate keeps a stationary probability density (it only accrues a global phase).
double inv = 1.0 / Math.Sqrt(2.0);
ComplexNumber[] psiT = states.Evolve(new[] { inv, inv, 0.0 }, time: 5.0);
double norm = psiT.NormSquared(states.GridSpacing); // ≈ 1 for all t
🕳️ Quantum Tunnelling
Closed-form transmission/reflection through a rectangular barrier of height V₀ and width a, covering the tunnelling (E < V₀), over-barrier (E > V₀, with resonances) and E = V₀ regimes.
double e = 1.0, v0 = 2.0;
double T = e.RectangularBarrierTransmission(v0, barrierWidth: 1.0); // ∈ (0, 1)
double R = e.RectangularBarrierReflection(v0, barrierWidth: 1.0); // = 1 − T
🌊 de Broglie Relations
double lambda = momentum.DeBroglieWavelength(); // λ = h/p
double lambdaE = energy.DeBroglieWavelengthFromEnergy(mass); // λ = h/√(2mE)
| Method | Description |
|---|---|
SolveStationaryStates | Finite-difference Hamiltonian → energy levels + wavefunctions |
InfiniteSquareWellEnergy / HarmonicOscillatorEnergy | Analytic energy levels |
Evolve | Spectral time evolution of a stationary-state superposition |
NormSquared / Normalize / ProbabilityDensity | Wavefunction probability |
ExpectationPosition / ExpectationMomentum / PositionUncertainty | Observables |
RectangularBarrierTransmission / …Reflection | Tunnelling coefficients |
DeBroglieWavelength / DeBroglieWavelengthFromEnergy | Wave–particle relations |