Skip to main content

Quantum Engine

A lightweight quantum circuit simulator that builds, composes, and executes quantum circuits using the gate primitives from CSharpNumerics.Physics.Quantum. State vectors use ComplexVectorN for amplitudes and VectorN for probability distributions.

Namespace: CSharpNumerics.Engines.Quantum

using CSharpNumerics.Physics.Quantum;
using CSharpNumerics.Engines.Quantum;
using CSharpNumerics.Engines.Quantum.Algorithms;
using CSharpNumerics.Engines.Quantum.ErrorCorrection;

๐Ÿš€ Quick Startโ€‹

// Fluent API โ€” build a Bell state in one chain
var circuit = QuantumCircuitBuilder.New(2)
.H(0)
.CNOT(0, 1)
.Build();

// Simulate
var state = new QuantumSimulator().Run(circuit);

// Inspect probabilities
double p00 = state.GetProbability(0); // 0.5 โ€” |00โŸฉ
double p11 = state.GetProbability(3); // 0.5 โ€” |11โŸฉ

VectorN probs = state.GetProbabilities(); // [0.5, 0, 0, 0.5]

// Measurement โ€” collapse to a single outcome
int result = state.Measure(new Random());

// Sampling โ€” statistical distribution without collapse
var counts = state.Sample(shots: 10000, new Random());

๐Ÿ”ง QuantumCircuitโ€‹

Holds a fixed qubit count and an ordered list of instructions.

var circuit = new QuantumCircuit(3);          // 3-qubit register
circuit.AddInstruction(instruction); // append gate + target qubits
int n = circuit.QubitCount; // 3
var list = circuit.Instructions; // List<QuantumInstruction>
Property / MethodTypeDescription
QubitCountintNumber of qubits in the register
InstructionsList<QuantumInstruction>Ordered gate sequence
AddInstruction(instruction)voidAppends an instruction (validates qubit indices)

๐Ÿ”— QuantumInstructionโ€‹

Pairs a QuantumGate with the physical qubit indices it targets.

var instr = new QuantumInstruction(new HadamardGate(), new List<int> { 0 });
var cnot = new QuantumInstruction(new CNOTGate(), new List<int> { 0, 1 }); // control=0, target=1
PropertyTypeDescription
GateQuantumGateThe gate to apply
QubitIndicesList<int>Physical qubit indices (count must match Gate.QubitCount)

๐Ÿ—๏ธ QuantumCircuitBuilderโ€‹

Fluent API for building circuits without manual instruction wiring.

var circuit = QuantumCircuitBuilder.New(3)
.H(0) // Hadamard on qubit 0
.X(1) // Pauli-X on qubit 1
.Ry(2, Math.PI / 4) // Y-rotation on qubit 2
.CNOT(0, 1) // CNOT: control=0, target=1
.CZ(1, 2) // Controlled-Z
.SWAP(0, 2) // Swap qubits 0 and 2
.Gate(new TGate(), 1) // Arbitrary gate
.Build();
MethodDescription
New(int qubits)Create a builder for an n-qubit circuit
H(q), X(q), Y(q), Z(q), S(q), T(q)Single-qubit standard gates
Phase(q, ฮธ)General phase gate P(ฮธ)P(\theta)
Rx(q, ฮธ), Ry(q, ฮธ), Rz(q, ฮธ)Parameterised rotation gates
CNOT(c, t), CZ(c, t), CPhase(c, t, ฮธ), SWAP(a, b)Two-qubit gates
Toffoli(c1, c2, t)Three-qubit CCNOT gate
Fredkin(c, t1, t2)Three-qubit CSWAP gate
ApplyQFT(params qubits)Quantum Fourier Transform on specified qubits
ApplyInverseQFT(params qubits)Inverse QFT (QFTโ€ ) on specified qubits
ApplyGrover(marked, params qubits)Grover search with optimal iterations
ApplyGrover(marked, iters, params qubits)Grover search with explicit iteration count
ApplyQPE(counting[], target[], gate)Quantum Phase Estimation
Controlled(gate, control, params targets)Controlled version of any gate
Gate(gate, params qubits)Arbitrary gate on specified qubits
Build()Returns the constructed QuantumCircuit

๐Ÿ“Š QuantumStateโ€‹

Result of a simulation โ€” a complex amplitude vector with probability queries, measurement, and sampling.

double p = state.GetProbability(0);          // |ฮฑโ‚€|ยฒ for basis state |0โ€ฆ0โŸฉ
VectorN probs = state.GetProbabilities(); // all |ฮฑแตข|ยฒ as VectorN
int qubits = state.QubitCount; // number of qubits
ComplexVectorN amps = state.Amplitudes; // raw amplitude vector
Property / MethodTypeDescription
AmplitudesComplexVectorNComplex amplitudes (length 2โฟ)
QubitCountintNumber of qubits
GetProbability(int basisState)doubleMeasurement probability of a specific basis state
GetProbabilities()VectorNAll basis-state probabilities
GetBlochVector()BlochVectorBloch sphere coordinates (single-qubit only)
Measure(Random)intFull measurement โ€” collapses state, returns basis index
MeasureQubit(int, Random)intMeasure one qubit (0 or 1), renormalising the rest
Sample(int shots, Random)Dictionary<int,int>Sample distribution without collapse

Measurement (collapse)

var state = sim.Run(QuantumCircuitBuilder.New(1).H(0).Build());
var rng = new Random(42);

// Full measurement โ€” collapses to |0โŸฉ or |1โŸฉ
int result = state.Measure(rng); // 0 or 1
// State is now a basis state: P(result) = 1.0

Single-qubit measurement

// Bell state: (|00โŸฉ+|11โŸฉ)/โˆš2
var state = sim.Run(QuantumCircuitBuilder.New(2).H(0).CNOT(0, 1).Build());

// Measure only qubit 0 โ€” collapses both qubits due to entanglement
int q0 = state.MeasureQubit(0, rng); // 0 or 1

Sampling (no collapse)

// Run 10000 shots โ€” state is NOT modified
var counts = state.Sample(10000, rng);
// counts = { 0: ~5000, 1: ~5000 } for H|0โŸฉ

โšก QuantumSimulatorโ€‹

Stateless simulator: initialises |0โ€ฆ0โŸฉ and applies each instruction in sequence.

var sim = new QuantumSimulator();
QuantumState result = sim.Run(circuit);

๐Ÿ”Š NoisyQuantumSimulatorโ€‹

Simulator with quantum noise channels applied after each gate using Monte Carlo trajectory selection (stochastic Kraus operator sampling). Noise channels come from CSharpNumerics.Physics.Quantum.NoiseModels.

using CSharpNumerics.Physics.Quantum.NoiseModels;

var noisy = new NoisyQuantumSimulator(new Random(42))
.WithNoise(new DepolarizingNoise(0.01)) // 1% depolarizing
.WithNoise(new DephasingNoise(0.02)) // 2% dephasing
.Run(circuit);

double fidelity = QuantumFidelity.Fidelity(idealState, noisy);
MethodDescription
NoisyQuantumSimulator(Random)Constructor with RNG for trajectory sampling
WithNoise(INoiseChannel)Adds a noise channel (fluent, stackable)
Run(QuantumCircuit)Executes with noise after each gate

How it works: After each gate, every registered noise channel is applied independently to each qubit the gate acted on. For each channel the simulator computes pk=โŸจฯˆโˆฃEkโ€ EkโˆฃฯˆโŸฉp_k = \langle\psi|E_k^\dagger E_k|\psi\rangle for all Kraus operators {Ek}\{E_k\}, samples one operator, and renormalises.

Noise channels (from CSharpNumerics.Physics.Quantum.NoiseModels):

ChannelParameterEffect
DepolarizingNoise(p)pโˆˆ[0,1]p \in [0,1]Replaces qubit with maximally mixed state with probability pp
DephasingNoise(p)pโˆˆ[0,1]p \in [0,1]Randomises relative phase (Tโ‚‚ decoherence)
AmplitudeDampingNoise(ฮณ)ฮณโˆˆ[0,1]\gamma \in [0,1]Energy dissipation: |1โŸฉ decays to |0โŸฉ (Tโ‚ decay)

All channels implement INoiseChannel and provide Kraus operators satisfying โˆ‘Ekโ€ Ek=I\sum E_k^\dagger E_k = I.


๐Ÿ’ก Examplesโ€‹

Rotation circuit

var circuit = new QuantumCircuit(1);
circuit.AddInstruction(new QuantumInstruction(new RyGate(Math.PI / 2), new List<int> { 0 }));
// Equivalent to Hadamard on |0โŸฉ โ€” equal superposition

var state = new QuantumSimulator().Run(circuit);
// P(|0โŸฉ) โ‰ˆ 0.5, P(|1โŸฉ) โ‰ˆ 0.5

3-qubit uniform superposition

var circuit = new QuantumCircuit(3);
circuit.AddInstruction(new QuantumInstruction(new HadamardGate(), new List<int> { 0 }));
circuit.AddInstruction(new QuantumInstruction(new HadamardGate(), new List<int> { 1 }));
circuit.AddInstruction(new QuantumInstruction(new HadamardGate(), new List<int> { 2 }));

var state = new QuantumSimulator().Run(circuit);
// Each of the 8 basis states has probability 1/8

Bit-flip verification (Xยฒ = I)

var circuit = new QuantumCircuit(1);
circuit.AddInstruction(new QuantumInstruction(new PauliXGate(), new List<int> { 0 }));
circuit.AddInstruction(new QuantumInstruction(new PauliXGate(), new List<int> { 0 }));

var state = new QuantumSimulator().Run(circuit);
// Back to |0โŸฉ with probability 1.0

๐Ÿค– QuantumEnvironment (RL Integration)โ€‹

An IEnvironment implementation for reinforcement learning โ€” the agent learns a gate sequence to prepare a target quantum state from |0โ€ฆ0โŸฉ.

PropertyDescription
ObservationState probabilities (2โฟ values) + normalised step progress
ActionsDiscrete โ€” each index maps to a (gate, qubit) pair
RewardFidelity delta + bonus when threshold reached
DoneMax gates reached or fidelity โ‰ฅ threshold

Quick start

using CSharpNumerics.Engines.Quantum;
using CSharpNumerics.Physics.Quantum;

// Target: Bell state (|00โŸฉ+|11โŸฉ)/โˆš2
var bellCircuit = QuantumCircuitBuilder.New(2).H(0).CNOT(0, 1).Build();

var env = QuantumEnvironment.Create(2)
.WithTargetCircuit(bellCircuit)
.WithMaxGates(20)
.WithFidelityThreshold(0.99)
.Build();

// Use with the RL framework
var result = RLExperiment
.For(env)
.WithAgent(agent)
.WithPolicy(new EpsilonGreedy())
.WithEpisodes(1000)
.Run();

Builder methods

MethodDescription
Create(int qubits)Start building an environment
.WithTargetState(QuantumState)Set the target state directly
.WithTargetCircuit(QuantumCircuit)Set the target by simulating a circuit
.WithMaxGates(int)Maximum gates per episode (default 20)
.WithFidelityThreshold(double)Early termination threshold (default 0.99)
.WithActions(List<QuantumInstruction>)Custom action set
.Build()Construct the environment

Default action set (auto-generated when no custom actions provided):

  • Single-qubit gates: H, X, Z, S, T on each qubit (5 ร— n)
  • Two-qubit gates: CNOT on all ordered qubit pairs (n ร— (nโˆ’1))

Step info dictionary

KeyTypeDescription
"fidelity"doubleCurrent fidelity to target state
"gates"intNumber of gates placed so far

๐Ÿงฎ Algorithmsโ€‹

Namespace: CSharpNumerics.Engines.Quantum.Algorithms

Quantum Fourier Transform (QFT)

Generates a circuit implementing the standard QFT: Hadamard gates, controlled-phase rotations CP(ฯ€/2k)CP(\pi/2^k), and a SWAP cascade to reverse qubit order.

using CSharpNumerics.Engines.Quantum.Algorithms;

// Standalone โ€” returns a QuantumCircuit
var qftCircuit = QFT.CreateCircuit(totalQubits: 3, 0, 1, 2);
var state = new QuantumSimulator().Run(qftCircuit);

// Via builder โ€” inline into a larger circuit
var circuit = QuantumCircuitBuilder.New(4)
.X(0).X(2) // Prepare |0101โŸฉ
.ApplyQFT(0, 1, 2, 3) // QFT on all 4 qubits
.Build();

QFT on โˆฃ0โŸฉโŠ—n|0\rangle^{\otimes n} produces a uniform superposition: each basis state has probability 1/2n1/2^n.

Inverse QFT (QFTโ€ )

Reverses the QFT: SWAP cascade, then reversed controlled-phase rotations with negated angles and Hadamards.

// Round-trip: InverseQFT(QFT(|ฯˆโŸฉ)) = |ฯˆโŸฉ
var circuit = QuantumCircuitBuilder.New(3)
.X(0).X(2) // |101โŸฉ
.ApplyQFT(0, 1, 2)
.ApplyInverseQFT(0, 1, 2)
.Build();

var state = new QuantumSimulator().Run(circuit);
// state โ‰ก |101โŸฉ with fidelity โ‰ˆ 1.0

Grover's Search Algorithm

Amplifies the amplitude of marked basis states in an unstructured search space. Given M marked states in N = 2โฟ, the algorithm finds a marked state with high probability after โ‰ˆ (ฯ€/4)โˆš(N/M) iterations.

using CSharpNumerics.Engines.Quantum.Algorithms;

// Standalone โ€” search for |101โŸฉ in a 3-qubit space
var circuit = GroverSearch.CreateCircuit(
totalQubits: 3,
searchQubits: new[] { 0, 1, 2 },
markedStates: new[] { 5 }); // |101โŸฉ = index 5

var state = new QuantumSimulator().Run(circuit);
double pTarget = state.GetProbability(5); // > 0.94

// Via builder
var circuit2 = QuantumCircuitBuilder.New(3)
.ApplyGrover(new[] { 5 }, new[] { 0, 1, 2 })
.Build();

// Multiple targets
var circuit3 = GroverSearch.CreateCircuit(3,
new[] { 0, 1, 2 }, new[] { 3, 5 }); // find |011โŸฉ or |101โŸฉ

// Query optimal iteration count
int iters = GroverSearch.OptimalIterations(
searchSpaceQubits: 3, markedCount: 1); // 2

The algorithm uses a PhaseOracle gate (from CSharpNumerics.Physics.Quantum) โ€” an n-qubit diagonal unitary that flips the phase of specified basis states.

Quantum Phase Estimation (QPE)

Estimates the eigenvalue phase ฯ† of a unitary gate U, where UโˆฃฯˆโŸฉ=e2ฯ€iฯ†โˆฃฯˆโŸฉU|\psi\rangle = e^{2\pi i\varphi}|\psi\rangle. Uses t counting qubits for t bits of precision.

using CSharpNumerics.Engines.Quantum.Algorithms;

// Standalone โ€” estimate phase of PhaseGate(ฯ€/2), eigenstate |1โŸฉ
// ฯ† = 1/4, with 2 counting qubits โ†’ measures 1 (= ฯ†ยท2ยฒ)
int totalQubits = 3;
var circuit = new QuantumCircuit(totalQubits);
circuit.AddInstruction(new QuantumInstruction(new PauliXGate(), new List<int> { 2 })); // |1โŸฉ eigenstate
var qpe = QPE.CreateCircuit(totalQubits,
countingQubits: new[] { 0, 1 },
targetQubits: new[] { 2 },
unitaryGate: new PhaseGate(Math.PI / 2));
foreach (var instr in qpe.Instructions)
circuit.AddInstruction(instr);

var state = new QuantumSimulator().Run(circuit);
// Counting register encodes ฯ†ยท2^t = 1

// Via builder
var circuit2 = QuantumCircuitBuilder.New(3)
.X(2)
.ApplyQPE(new[] { 0, 1 }, new[] { 2 }, new PhaseGate(Math.PI / 2))
.Build();

QPE uses ControlledGate (from CSharpNumerics.Physics.Quantum) to create controlled-U operations automatically. The countingQubits[0] is the MSB of the result.

Shor's Factoring Algorithm

Factors composite integers using quantum order-finding (QPE + modular multiplication).

using CSharpNumerics.Engines.Quantum.Algorithms;

// Factor 15 = 3 ร— 5
var result = ShorAlgorithm.Factor(15, new Random(42));
Console.WriteLine($"{result.Factor1} ร— {result.Factor2}"); // 3 ร— 5
Console.WriteLine($"Success: {result.Success}"); // True
Console.WriteLine($"Base: {result.Base}, Order: {result.Order}");

// Access the quantum circuit directly
var circuit = ShorAlgorithm.CreateOrderFindingCircuit(
a: 2, N: 15, countingQubits: 8, targetQubits: 4);

// Helper utilities
int iters = GroverSearch.OptimalIterations(3); // Grover
long order = ShorAlgorithm.ExtractOrder(4, 4, 15, 2); // continued fractions
long g = ShorAlgorithm.GCD(12, 8); // 4
long p = ShorAlgorithm.ModPow(2, 10, 1000); // 1024 mod 1000 = 24

The quantum core uses ModularMultiplyGate (from CSharpNumerics.Physics.Quantum) โ€” a permutation gate implementing โˆฃyโŸฉโ†’โˆฃayโ€Šmodโ€ŠNโŸฉ|y\rangle \to |ay \bmod N\rangle.

ClassRole
ShorAlgorithmFull factor algorithm (classical + quantum)
ShorResultResult with factors, base, order, attempt count
ModularMultiplyGatePermutation oracle UaโˆฅyโŸฉ=โˆฅayโ€Šmodโ€ŠNโŸฉU_a\|y\rangle = \|ay \bmod N\rangle
ControlledGateWraps any gate with a control qubit

๐Ÿ›ก๏ธ Quantum Error Correction โ€” Simulationโ€‹

Namespace: CSharpNumerics.Engines.Quantum.ErrorCorrection

The ErrorCorrection sub-namespace provides the simulation layer for quantum error-correcting codes defined in Physics.Quantum.ErrorCorrection.

SyndromeDecoder

Classical lookup table that maps measured syndrome bits to corrective operations:

using CSharpNumerics.Physics.Quantum.ErrorCorrection;
using CSharpNumerics.Engines.Quantum.ErrorCorrection;

var decoder = new SyndromeDecoder(new BitFlipCode3());

// From integer syndrome
var ops = decoder.Decode(0b01); // โ†’ [(0, 'X')] โ€” apply X to qubit 0

// From measurement bit array
var ops2 = decoder.Decode(new[] { 1, 1 }); // โ†’ [(1, 'X')] โ€” apply X to qubit 1

ErrorCorrectionSimulator

Orchestrates the full QEC cycle: encode โ†’ inject error โ†’ extract syndrome โ†’ decode โ†’ correct โ†’ decode โ†’ measure fidelity.

Bit-flip correction:

using CSharpNumerics.Physics.Quantum;
using CSharpNumerics.Physics.Quantum.ErrorCorrection;
using CSharpNumerics.Engines.Quantum.ErrorCorrection;
using CSharpNumerics.Numerics.Objects;

var code = new BitFlipCode3();
var sim = new ErrorCorrectionSimulator();
var rng = new Random(42);

// Prepare a superposition state to protect
var initial = new ComplexVectorN(2);
initial[0] = new ComplexNumber(0.6, 0); // ฮฑ
initial[1] = new ComplexNumber(0, 0.8); // ฮฒ

// Inject a single bit-flip error on qubit 1
var errors = new List<(QuantumGate, int)> { (new PauliXGate(), 1) };

var result = sim.RunBitFlipCorrection(code, initial, errors, rng);

Console.WriteLine(result.Fidelity); // โ‰ˆ 1.0 โ€” error fully corrected
Console.WriteLine(result.Syndrome); // 3 (0b11) โ€” both stabilizers triggered

Phase-flip correction:

var pfCode = new PhaseFlipCode3();
var zError = new List<(QuantumGate, int)> { (new PauliZGate(), 0) };

var pfResult = sim.RunPhaseFlipCorrection(pfCode, initial, zError, rng);
// pfResult.Fidelity โ‰ˆ 1.0

Monte Carlo comparison โ€” protected vs. unprotected:

var (protectedFidelity, unprotectedFidelity) = sim.RunMonteCarloComparison(
code, initial,
errorRate: 0.10, // 10% bit-flip probability per qubit
rounds: 1000,
random: rng);

// protectedFidelity > unprotectedFidelity โ€” QEC provides net benefit

Shor 9-qubit code โ€” corrects any single-qubit error (X, Z, or Y):

using CSharpNumerics.Physics.Quantum;
using CSharpNumerics.Physics.Quantum.ErrorCorrection;
using CSharpNumerics.Engines.Quantum.ErrorCorrection;
using CSharpNumerics.Numerics.Objects;

var shor = new ShorCode9();
var sim = new ErrorCorrectionSimulator();
var rng = new Random(42);

var initial = new ComplexVectorN(2);
initial[0] = new ComplexNumber(0.6, 0);
initial[1] = new ComplexNumber(0, 0.8);

// Y error = combined bit-flip + phase-flip
var errors = new List<(QuantumGate, int)> { (new PauliYGate(), 4) };
var result = sim.RunShorCorrection(shor, initial, errors, rng);
// result.Fidelity โ‰ˆ 1.0 โ€” Y error fully corrected

Steane 7-qubit code โ€” the smallest CSS code correcting any single-qubit error:

using CSharpNumerics.Physics.Quantum;
using CSharpNumerics.Physics.Quantum.ErrorCorrection;
using CSharpNumerics.Engines.Quantum.ErrorCorrection;
using CSharpNumerics.Numerics.Objects;

var steane = new SteaneCode7();
var sim = new ErrorCorrectionSimulator();
var rng = new Random(42);

var initial = new ComplexVectorN(2);
initial[0] = new ComplexNumber(0.6, 0);
initial[1] = new ComplexNumber(0, 0.8);

// Z (phase-flip) error on qubit 3
var errors = new List<(QuantumGate, int)> { (new PauliZGate(), 3) };
var result = sim.RunSteaneCorrection(steane, initial, errors, rng);
// result.Fidelity โ‰ˆ 1.0 โ€” CSS structure detects and corrects Z error
// result.Syndrome bits 3-5 identify the Z error via Hamming decoding
Return TypeFields
ResultFidelity (double), Syndrome (int), Corrections (list), RecoveredState (QuantumState)
Monte Carlo(protectedFidelity, unprotectedFidelity) tuple