Skip to the content.

Error Mitigation

Reduce quantum computing errors by 30-90% using advanced error mitigation techniques.

Overview

Quantum computers are inherently noisy - gate errors, decoherence, and measurement errors corrupt results. Error mitigation techniques reduce these errors without requiring error-corrected quantum hardware, providing significant accuracy improvements on today’s NISQ (Noisy Intermediate-Scale Quantum) devices.

Available Techniques:

Key Concepts

Error Sources in Quantum Computing

1. Gate Errors

2. Readout Errors

3. Noise Accumulation

Error Mitigation vs Error Correction

Error Mitigation (Available Today):

Error Correction (Future):


Zero-Noise Extrapolation (ZNE)

What is ZNE?

ZNE reduces errors by running the circuit at increasing noise levels, fitting a polynomial to the results, and extrapolating back to zero noise.

How It Works:

  1. Run circuit at baseline noise (1.0×)
  2. Artificially increase noise (1.5×, 2.0×, 3.0×)
  3. Measure expectation value at each noise level
  4. Fit polynomial curve to measurements
  5. Extrapolate curve to zero noise (x=0)

Result: Estimated zero-noise value with 30-50% error reduction.

When to Use ZNE

Best For:

Not Suitable For:

API Reference

open FSharp.Azure.Quantum.ZeroNoiseExtrapolation

// Configure ZNE for IonQ backend
let config = {
    Method = IdentityInsertion  // Add I·I gate pairs to increase noise
    NoiseLevels = [| 1.0; 1.5; 2.0; 3.0 |]  // Baseline + 50%, 100%, 200%
    PolynomialDegree = 2  // Quadratic extrapolation
    SamplesPerLevel = 1024
}

// Create your circuit
let vqeCircuit = circuit {
    qubits 4
    RY 0 theta1
    CNOT 0 1
    RY 1 theta2
    CNOT 1 2
    RY 2 theta3
}

// Define executor (calls real quantum backend)
let executor (circuit: Circuit) : Async<Result<float, string>> =
    async {
        // Execute circuit on IonQ/Rigetti and measure expectation value
        let! result = backend.Execute(circuit, shots = 1024)
        return Ok result.ExpectationValue
    }

// Apply ZNE
match! ZNE.mitigate vqeCircuit config executor with
| Ok result ->
    printfn "Zero-noise value: %.4f" result.ZeroNoiseValue
    printfn "R² fit quality: %.4f" result.GoodnessOfFit
    printfn "Estimated error reduction: %.1f%%" (result.ErrorReduction * 100.0)
    
    // Check fit quality
    if result.GoodnessOfFit < 0.9 then
        printfn "⚠ Warning: Poor fit quality - consider more noise levels"
    
| Error err -> eprintfn "ZNE failed: %s" err.Message

Configuration Options

// Method 1: Identity Insertion (IonQ, Rigetti)
let ionqConfig = {
    Method = IdentityInsertion  // Insert I·I pairs (identity gates)
    NoiseLevels = [| 1.0; 1.5; 2.0 |]
    PolynomialDegree = 2
    SamplesPerLevel = 1024
}

// Method 2: Circuit Folding (All backends)
let foldingConfig = {
    Method = CircuitFolding  // Fold circuit back on itself
    NoiseLevels = [| 1.0; 2.0; 3.0 |]  // Folding factor
    PolynomialDegree = 2
    SamplesPerLevel = 2048
}

// Method 3: Pulse Stretching (Quantinuum, pulse-level access)
let pulseConfig = {
    Method = PulseStretching  // Stretch gate durations
    NoiseLevels = [| 1.0; 1.2; 1.5; 2.0 |]
    PolynomialDegree = 2
    SamplesPerLevel = 1024
}

Cost Analysis

Circuit Executions:

Example Cost:

ROI: 30-50% error reduction for 3-5× cost = Moderate cost, high value

Choosing Polynomial Degree

Linear (degree=1): Fast, simple, less accurate

PolynomialDegree = 1  // y = a + bx

Quadratic (degree=2): Recommended default

PolynomialDegree = 2  // y = a + bx + cx²

Cubic (degree=3): Complex noise models, needs 5+ noise levels

PolynomialDegree = 3  // y = a + bx + cx² + dx³
NoiseLevels = [| 1.0; 1.5; 2.0; 2.5; 3.0; 4.0 |]  // Need more points

Working Example

See complete example: examples/ErrorMitigation/ZNE_Example.fsx


Probabilistic Error Cancellation (PEC)

What is PEC?

PEC reduces errors by inverting noise channels using quasi-probability decomposition. It actively cancels errors rather than just extrapolating.

How It Works:

  1. Characterize noise model (single-qubit, two-qubit error rates)
  2. Decompose each noisy gate into quasi-probability representation
  3. Sample circuits from the decomposition (some with negative weights)
  4. Combine weighted results to cancel errors

Result: 50-80% error reduction (2-3× accuracy improvement over unmitigated).

When to Use PEC

Best For:

Not Suitable For:

API Reference

open FSharp.Azure.Quantum.ProbabilisticErrorCancellation

// Define noise model (measured from hardware)
let noiseModel = {
    SingleQubitDepolarizing = 0.001  // 0.1% error per gate
    TwoQubitDepolarizing = 0.01      // 1.0% error per CNOT
    ReadoutError = 0.02              // 2% measurement error
}

// Configure PEC
let config = {
    NoiseModel = noiseModel
    NumSamples = 10000  // More samples = better accuracy but higher cost
    Precision = 0.001   // Target precision
    MaxCircuitSamples = 100000  // Safety limit
}

// Create circuit
let h2Circuit = circuit {
    qubits 2
    RY 0 theta
    CNOT 0 1
    RY 1 theta
}

// Define executor
let executor (circuit: Circuit) : Async<Result<float, string>> =
    async {
        let! result = backend.Execute(circuit, shots = 1024)
        return Ok result.ExpectationValue
    }

// Apply PEC
match! PEC.mitigate h2Circuit config executor with
| Ok result ->
    printfn "Mitigated value: %.4f" result.MitigatedValue
    printfn "Unmitigated value: %.4f" result.UnmitigatedValue
    printfn "Error reduction: %.1f%%" (result.ErrorReduction * 100.0)
    printfn "Circuit samples used: %d" result.SamplesUsed
    printfn "Overhead factor: %.1fx" result.OverheadFactor
    
| Error err -> eprintfn "PEC failed: %s" err.Message

Noise Model Characterization

Option 1: Use Published Values

// IonQ Aria (typical values)
let ionqNoise = {
    SingleQubitDepolarizing = 0.0003  // 0.03% error
    TwoQubitDepolarizing = 0.005      // 0.5% error
    ReadoutError = 0.01               // 1% readout error
}

// Rigetti Aspen (typical values)
let rigettiNoise = {
    SingleQubitDepolarizing = 0.001   // 0.1% error
    TwoQubitDepolarizing = 0.01       // 1% error
    ReadoutError = 0.02               // 2% readout error
}

Option 2: Measure Your Own

// Run randomized benchmarking circuits
match! PEC.characterizeNoiseModel backend with
| Ok measured ->
    printfn "Measured noise model:"
    printfn "  Single-qubit: %.4f" measured.SingleQubitDepolarizing
    printfn "  Two-qubit: %.4f" measured.TwoQubitDepolarizing
    printfn "  Readout: %.4f" measured.ReadoutError
| Error err -> eprintfn "Characterization failed: %s" err.Message

Cost Analysis

Circuit Executions:

Example Cost:

ROI: 50-80% error reduction for 10-100× cost = High cost, critical use cases only

Overhead Estimation

Overhead depends on:

Typical Overheads:

Working Example

See complete example: examples/ErrorMitigation/PEC_Example.fsx


Readout Error Mitigation (REM)

What is REM?

REM reduces measurement errors by calibrating a confusion matrix that maps true states to measured states, then applying the inverse transformation.

How It Works:

  1. Calibration (one-time): Prepare known states ( 00⟩, 01⟩, 10⟩, 11⟩)
  2. Measure each state many times to build confusion matrix
  3. Invert matrix to get correction transformation
  4. Runtime: Apply inverse matrix to correct all measurements

Result: 50-90% reduction in readout errors, virtually free after calibration.

When to Use REM

Best For:

Not Suitable For:

API Reference

open FSharp.Azure.Quantum.ReadoutErrorMitigation

// Configure REM
let config = {
    CalibrationShots = 10000  // Shots per calibration state
    ConfidenceLevel = 0.95    // 95% confidence intervals
    ClipNegative = true       // Clip negative counts to 0
}

// Step 1: Calibrate (one-time per backend session)
match! REM.calibrate backend config with
| Ok calibration ->
    printfn "Calibration complete!"
    printfn "Confusion matrix:"
    printfn "  P(measure 0|prepare 0): %.4f" calibration.ConfusionMatrix.[0,0]
    printfn "  P(measure 1|prepare 0): %.4f" calibration.ConfusionMatrix.[0,1]
    printfn "  P(measure 0|prepare 1): %.4f" calibration.ConfusionMatrix.[1,0]
    printfn "  P(measure 1|prepare 1): %.4f" calibration.ConfusionMatrix.[1,1]
    
    // Step 2: Run your circuit
    let circuit = circuit {
        qubits 2
        H 0
        CNOT 0 1
    }
    
    let! rawCounts = backend.Execute(circuit, shots = 10000)
    
    // Step 3: Apply correction
    match REM.correct calibration rawCounts with
    | Ok corrected ->
        printfn "\nRaw counts: %A" rawCounts
        printfn "Corrected counts: %A" corrected.Counts
        printfn "Error reduction: %.1f%%" (corrected.ErrorReduction * 100.0)
    | Error err -> eprintfn "Correction failed: %s" err.Message
    
| Error err -> eprintfn "Calibration failed: %s" err.Message

Multi-Qubit Calibration

For n qubits, need 2ⁿ calibration states:

// 1 qubit: 2 states (|0⟩, |1⟩)
let! cal1 = REM.calibrate backend config

// 2 qubits: 4 states (|00⟩, |01⟩, |10⟩, |11⟩)
let! cal2 = REM.calibrate backend { config with NumQubits = 2 }

// 3 qubits: 8 states (|000⟩, |001⟩, ..., |111⟩)
let! cal3 = REM.calibrate backend { config with NumQubits = 3 }

Calibration Cost:

Handling Negative Counts

Problem: Matrix inversion can produce negative counts (unphysical)

Solutions:

Option 1: Clip to Zero (default)

ClipNegative = true
// Negative counts → 0 (simple, conservative)

Option 2: Redistribute

ClipNegative = false
RedistributeNegative = true
// Negative counts redistributed to positive states (preserves total)

Option 3: Allow Negative (advanced)

ClipNegative = false
// Keep negative counts (for theoretical analysis)

Cost Analysis

Circuit Executions:

Example Cost:

ROI: 50-90% error reduction for free after calibration = Best value in error mitigation!

Working Example

See complete example: examples/ErrorMitigation/REM_Example.fsx


Combined Strategies

Why Combine Techniques?

Error mitigation techniques target different error sources:

Combining techniques multiplicatively reduces errors.

1. REM + ZNE (Best Value)

Cost: Low-Medium (3-5× overhead)
Accuracy: 60-80% total error reduction
Use For: Most applications on real hardware

// Step 1: Calibrate REM (one-time)
let! remCal = REM.calibrate backend remConfig

// Step 2: Run circuit with ZNE
match! ZNE.mitigate circuit zneConfig (fun c -> 
    async {
        let! rawCounts = backend.Execute(c, shots = 1024)
        
        // Step 3: Apply REM correction
        let! corrected = REM.correct remCal rawCounts
        return Ok corrected.ExpectationValue
    }
) with
| Ok result ->
    printfn "Mitigated value: %.4f" result.ZeroNoiseValue
| Error err -> eprintfn "Error: %s" err.Message

Benefits:

2. REM + PEC (Maximum Accuracy)

Cost: High (10-100× overhead)
Accuracy: 70-95% total error reduction
Use For: Critical high-accuracy applications

// Step 1: Calibrate REM
let! remCal = REM.calibrate backend remConfig

// Step 2: Run circuit with PEC
match! PEC.mitigate circuit pecConfig (fun c ->
    async {
        let! rawCounts = backend.Execute(c, shots = 1024)
        
        // Step 3: Apply REM correction
        let! corrected = REM.correct remCal rawCounts
        return Ok corrected.ExpectationValue
    }
) with
| Ok result ->
    printfn "Mitigated value: %.4f" result.MitigatedValue
| Error err -> eprintfn "Error: %s" err.Message

Benefits:

3. All Three (Experimental)

Cost: Very High (30-500× overhead)
Accuracy: Up to 95%+ error reduction
Use For: Research, extremely critical calculations

open FSharp.Azure.Quantum.ErrorMitigation.Combined

// Combined strategy configuration
let strategy = {
    UseZNE = true
    UsePEC = true
    UseREM = true
    ZNEConfig = zneConfig
    PECConfig = pecConfig
    REMConfig = remConfig
}

match! Combined.mitigate circuit strategy backend with
| Ok result ->
    printfn "Final mitigated value: %.4f" result.FinalValue
    printfn "Total error reduction: %.1f%%" (result.TotalErrorReduction * 100.0)
    printfn "Total overhead: %.1fx" result.TotalOverhead
| Error err -> eprintfn "Error: %s" err.Message

Strategy Selection Guide

Application Recommended Strategy Cost Accuracy Improvement
Prototyping REM only Free 50-70%
Production REM + ZNE Low 60-80%
High-value REM + PEC High 70-95%
Research All three Very High 80-95%+

Performance Comparison

Error Reduction Effectiveness

Technique Gate Errors Readout Errors Cost Recommendation
ZNE 30-50% 0% 3-5× Good value
PEC 50-80% 0% 10-100× Critical use only
REM 0% 50-90% Free Always use
REM+ZNE 30-50% 50-90% 3-5× Best default
REM+PEC 50-80% 50-90% 10-100× Maximum accuracy

Circuit Depth Limits

Technique Shallow (≤10 gates) Medium (10-30 gates) Deep (>30 gates)
ZNE ✅ Excellent ✅ Good ⚠️ Moderate
PEC ✅ Excellent ⚠️ Expensive ❌ Impractical
REM ✅ Excellent ✅ Excellent ✅ Excellent

Troubleshooting

Common Issues

1. Poor ZNE Fit Quality (R² < 0.9)

Symptoms: Low goodness-of-fit score

Solutions:

2. PEC Overhead Too High

Symptoms: >100× overhead, cost prohibitive

Solutions:

3. REM Produces Negative Counts

Symptoms: Unphysical negative counts after correction

Solutions:

4. Combined Strategies Don’t Improve Accuracy

Symptoms: Mitigation makes results worse

Solutions:

Working Examples

See complete, runnable examples in examples/ErrorMitigation/:

See Also

References


Last Updated: December 2025