Skip to the content.

Hardware Selection Guide

Choosing the Right Quantum Backend for Your Application

This guide helps you select the appropriate quantum backend (LocalBackend, IonQ, Rigetti, D-Wave) for your specific use case in FSharp.Azure.Quantum. The library also has cloud backends for Quantinuum, Atom Computing and IQM (see Backend Switching); they follow the same pattern as IonQ and Rigetti below.

About the hardware figures: qubit counts, fidelities and prices below are approximate and describe the device generations named in each profile (IonQ Harmony, Rigetti Aspen-M). Providers retire and replace devices often, and current systems are larger; check the Azure Quantum target list before choosing. The library’s own pre-flight checks (CircuitValidator.KnownTargets) use similar figures: 11 qubits for IonQ hardware and 79 for Rigetti Aspen-M-3.


Quick Decision Tree

START: What are you trying to do?
│
├─ Learning / Development / Testing
│  └─→ LocalBackend (memory-derived width, ≤30; solvers run up to 20 by default)
│
├─ Small problem (≤11 qubits) + Need HIGH accuracy
│  └─→ IonQ (trapped ion, high gate fidelity)
│
├─ Medium problem (12-80 qubits) + Can tolerate some noise
│  └─→ Rigetti (superconducting, fast gates)
│
├─ Large optimization problem (100-5000 variables)
│  └─→ D-Wave Advantage (quantum annealer, QUBO/Ising only)
│
└─ Very large problem (>80 qubits gate-based)
   └─→ Wait for future hardware OR use HybridSolver (classical fallback)

Backend Comparison Matrix

Feature LocalBackend IonQ Harmony Rigetti Aspen-M D-Wave Advantage
Type Simulator Trapped Ion Superconducting Quantum Annealer
Qubit Count ≤20 practical, ≤30 in memory 11 ~80 5000+
Connectivity Full All-to-all Limited (grid) Chimera/Pegasus graph
Gate Fidelity Perfect 99.5%+ 97-99% N/A (annealing)
Coherence Time Infinite ~1 second ~50 μs N/A
Gate Time N/A (simulated) ~200 μs ~50 ns N/A
Circuit Depth Unlimited ~100 gates ~50 gates N/A (fixed schedule)
Cost Free $$$ per shot $$ per shot $$ per second
Best For Development High-precision Medium-scale NISQ Large-scale opt.
Algorithms All Gate-based Gate-based QUBO/Ising optimization only

Detailed Backend Profiles

1. LocalBackend (Simulation)

Technology: Classical simulation of quantum state vector

Specifications:

✅ Best For:

❌ NOT Good For:

Code Example:

open System.Threading
open FSharp.Azure.Quantum
open FSharp.Azure.Quantum.GraphColoring

// No configuration needed - always available
let problem = graphColoring {
    node "A" ["B"; "C"]
    node "B" ["A"]
    node "C" ["A"]
    colors ["Red"; "Blue"]
}

// Backend None = the local simulator (3 nodes × 2 colors = 6 qubits)
task {
    match! GraphColoring.solveAsync problem 2 None CancellationToken.None with
    | Ok solution -> printfn "Solution: %A" solution.Assignments
    | Error err -> printfn "Error: %s" err.Message
}

Cost: Free ✅


2. IonQ (Trapped Ion)

Technology: Individual trapped ytterbium ions manipulated by lasers

Specifications (IonQ Harmony):

✅ Best For:

❌ NOT Good For:

Code Example:

open FSharp.Azure.Quantum
open FSharp.Azure.Quantum.Core
open FSharp.Azure.Quantum.Backends.CloudBackends

// Authenticate (DefaultAzureCredential: `az login`, environment variables or managed identity)
let workspaceUrl =
    "https://<location>.quantum.azure.com/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Quantum/workspaces/<ws>"

let credential = Authentication.CredentialProviders.createDefaultCredential ()
let httpClient = Authentication.createAuthenticatedClient credential

// "ionq.simulator" for the free simulator, or a QPU target such as "ionq.qpu.aria-1"
let ionqBackend = CloudBackendFactory.createIonQ httpClient workspaceUrl "ionq.simulator" 1000

// Run a 3-qubit GHZ circuit on IonQ
let ghz =
    CircuitBuilder.empty 3
    |> CircuitBuilder.addGate (CircuitBuilder.H 0)
    |> CircuitBuilder.addGate (CircuitBuilder.CNOT(0, 1))
    |> CircuitBuilder.addGate (CircuitBuilder.CNOT(1, 2))

match Primitives.sample ionqBackend ghz 1000 with
| Ok counts -> printfn "Counts: %A" counts  // mostly "000" and "111"
| Error err -> printfn "Error: %s" err.Message

Chemistry solvers take the same backend through SolverConfig.Backend. With Method = GroundStateMethod.VQE, GroundStateEnergy.estimateEnergyAsync runs every energy evaluation on that backend. It uses integrals from SolverConfig.IntegralProvider, or STO-3G integrals the library computes for molecules of H and He atoms (see Bring Your Own Hamiltonian). On a simulator that applies gates one at a time, the UCCSD-VQE computes exact expectation values. A backend that accepts only whole circuits, such as IonQ, Quantinuum, Rigetti, IQM, Atom Computing, Braket or NoisyLocalBackend, gets complete circuits instead:

The result says how it was estimated: Estimation = SampledCircuits(circuitsPerEnergy, shotsPerCircuit, circuitsExecuted), against ExactExpectation on the simulator path.

Converged means 30 iterations without an improvement above the shot noise. Every 10 iterations the energy is estimated with its standard error, and the run stops once three such checkpoints in a row have not beaten the best one. The reported energy is a fresh estimate at the best checkpoint. A run that is still improving at MaxIterations, or that did not get below its start, is Converged = false, and Notes says which.

Every circuit is a separate job. A run that would submit more than ChemistryVQE.MaxWholeCircuitJobs (20,000) circuits is refused before it starts, and the error names the largest MaxIterations that fits. On a local whole-circuit simulator without a shot count, such as NoisyLocalBackend, the first circuit’s time projects the run. It is refused when the projection exceeds one hour. Cancellation through the progress reporter is checked before every circuit.

Measured on simulated whole-circuit backends:

System Circuits per energy Shots per circuit Result
H₂ 5 10,000 stopped after 40–50 iterations (about 500 circuits), within 0.7 mHa of FCI at the returned amplitudes
H₂ 5 100,000 stopped after 40–50 iterations (about 500 circuits), within 0.4 mHa of FCI at the returned amplitudes
water CAS(2,2) 9 1,000 all 12 seeds within 2.4 mHa
ethane CAS(4,4), 52 amplitudes 100 exact probabilities 90 iterations, the most the budget allows, reach 5.6 mHa above FCI, reported as not converged

The energy reported for a run carries the shot noise of one estimate.

SolverConfig.ErrorMitigation corrects each group’s counts with the unbiased readout inverse. A strategy that cannot correct anything is an Error.

GroundStateMethod.QPE also runs on a whole-circuit backend: the Hartree-Fock preparation, the controlled Trotter evolutions and the inverse QFT are one circuit, submitted as one job. For H₂ that is 12 qubits and about 146,000 gates, far deeper than today’s hardware keeps coherent, so a hardware run of it is impractical now: use it on simulators, or to see the route work end to end.

The other algorithms take a cloud backend the same way, each as whole-circuit jobs:

Algorithm On a cloud backend
QAOA solvers, Grover and its builders, amplitude amplification, QFT, QPE, quantum arithmetic One circuit per run (QAOA: one per optimizer step)
Shor (QuantumPeriodFinder) One circuit per base tried; FactorSource says whether the factors came from the measured period or from classical preprocessing
HHL One circuit; Readout = MeasuredMagnitudes: the solution holds |xᵢ| from post-selected counts, without signs or phases. HHL.executeWithRelativePhases adds one interference circuit per solution qubit (two for a complex system) and returns the signed/phased solution (Readout = MeasuredRelativePhases)
HHL regression (QuantumRegressionHHL) 1 + log₂(padded dimension) circuits per fit (RegressionResult.Circuits): the magnitudes plus one Hadamard circuit per solution qubit for the signs
Primitives.observe, ADAPT-VQE, ADAPT-QAOA One circuit per commuting group of Pauli terms for every energy; parameter-shift gradients
QML (VQC, quantum kernels) One circuit per forward pass or kernel entry; kernels keep at most 8 in flight
Quantum Monte Carlo, option pricing, risk engine Maximum-likelihood amplitude estimation: one circuit per Grover power (0, 1, 2, 4, …), probabilities from the job’s counts
QRNG.generateWithBackendAsync One job of one shot: create the backend with shots = 1

A cloud backend returns an Error, never a guess, for what a circuit job cannot do: start from a state other than |0…0⟩, read the gates of an opaque custom oracle function, HamiltonianSimulation.simulate of a given state (use simulateFromPreparation), and the Shor 9-qubit and Steane code round trips.

Async alternative: Cloud backends support task { } with CancellationToken. Use backend.ExecuteToStateAsync circuit ct or Primitives.sampleAsync for non-blocking execution. See Backend Switching.

Cost: ~$0.30 per circuit execution (varies by shot count)

When to Choose IonQ: You need the highest quality results and your problem fits on the device.


3. Rigetti (Superconducting)

Technology: Superconducting transmon qubits at ~15 mK temperature

*Physics: Superconducting qubits exploit Josephson junctions—two superconductors separated by a thin insulator. Quantum tunneling of Cooper pairs creates discrete energy levels that encode 0⟩ and 1⟩. First described by Josephson (1962), this earned the Nobel Prize and enabled Google, IBM, and Rigetti hardware.*

Specifications (Rigetti Aspen-M):

✅ Best For:

❌ NOT Good For:

Code Example:

// "rigetti.sim.qvm" for the simulator, or a QPU target such as "rigetti.qpu.ankaa-3"
let rigettiBackend = CloudBackendFactory.createRigetti httpClient workspaceUrl "rigetti.sim.qvm" 1000

// Run QAOA MaxCut on Rigetti
let vertices = ["A"; "B"; "C"; "D"; "E"; "F"]  // 6 vertices = 6 qubits
let edges = [
    ("A", "B", 1.0); ("B", "C", 1.0)
    ("C", "D", 1.0); ("D", "E", 1.0)
    ("E", "F", 1.0); ("F", "A", 1.0)
]

let maxCutProblem = MaxCut.createProblem vertices edges

task {
    match! MaxCut.solveAsync maxCutProblem (Some rigettiBackend) CancellationToken.None with
    | Ok solution ->
        printfn "Max cut value: %.2f" solution.CutValue
        printfn "Partition S: %A" solution.PartitionS
    | Error err ->
        printfn "Error: %s" err.Message
}

For QPUs with limited connectivity, CloudBackendFactory.createRigettiRouted takes the device coupling map and inserts the SWAP gates for you.

Cost: ~$0.10-0.20 per circuit execution (cheaper than IonQ)

When to Choose Rigetti: You need more qubits (12-80) and can tolerate some noise for speed/scale.


4. D-Wave Advantage (Quantum Annealer)

Technology: Quantum annealing with superconducting flux qubits

Specifications:

✅ Best For:

❌ NOT Good For:

Code Example:

The D-Wave backend implements IQuantumBackend, so QUBO-based solvers such as MaxCut.solveAsync accept it: the solver’s QAOA circuit is converted back to a QUBO and annealed.

open System.Threading
open FSharp.Azure.Quantum.Backends
open FSharp.Azure.Quantum.Core.BackendAbstraction

// Reads DWAVE_API_TOKEN (required), DWAVE_ENDPOINT and DWAVE_SOLVER (default "Advantage_system6.1")
task {
    match RealDWaveBackend.createFromEnv () with
    | Error err -> printfn "D-Wave not configured: %s" err.Message
    | Ok dwave ->
        use dwave = dwave
        let ring =
            MaxCut.createProblem
                [ for i in 1 .. 20 -> $"N{i}" ]
                [ for i in 1 .. 20 -> ($"N{i}", $"N{i % 20 + 1}", 1.0) ]

        match! MaxCut.solveAsync ring (Some(dwave :> IQuantumBackend)) CancellationToken.None with
        | Ok solution -> printfn "Cut value: %.1f" solution.CutValue
        | Error err -> printfn "Error: %s" err.Message
}

// Offline testing: a mock annealer with the same interface
let mockDWave = DWaveBackend.createDefaultMockBackend () :> IQuantumBackend

Cost: ~$2 per minute of QPU time (cost-effective for large problems)

When to Choose D-Wave: You have a large optimization problem (>100 variables) expressible as QUBO.


Decision Guide by Problem Type

Quantum Algorithm Implementations

Algorithm Recommended Backend Qubit Need Notes
Grover’s Search IonQ (small), Rigetti (medium) 5-50 High fidelity helps accuracy
Shor’s Factoring IonQ counting + 2n + 4, n = ⌈log₂N⌉ (N = 15, 8 counting: 20) One whole circuit per base; far deeper than today’s hardware keeps coherent, so hardware runs demonstrate the route rather than factor reliably
QFT IonQ 3-11 Deep circuit, needs fidelity
QPE IonQ 5-11 High precision critical
VQE (chemistry) IonQ (<4 atoms), Rigetti (4-8 atoms) 4-20 Shallow circuits, noise-resilient; the library’s chemistry path refuses molecules wider than the backend runs
QAOA Rigetti (medium), D-Wave (large) 10-5000 Optimization-focused

Optimization Problems

Problem Type Variables Recommended Backend Why
Graph Coloring <10 LocalBackend or IonQ Small, test locally first
  10-50 Rigetti Medium scale
  50+ D-Wave Annealer excels here
MaxCut <10 LocalBackend or IonQ Small, test locally
  10-80 Rigetti Gate-based QAOA
  80+ D-Wave Annealer optimal
TSP (N² qubits) ≤4 cities LocalBackend Proof of concept; 3 cities also fit an 11-qubit device
  5-8 cities Rigetti 25-64 qubits
  9+ cities D-Wave or classical 81+ variables; annealer or HybridSolver
Portfolio Opt. <10 assets LocalBackend Test first
  10-50 assets Rigetti Medium portfolios
  50+ assets D-Wave Large institutional

Quantum Machine Learning

Task Dataset Size Recommended Backend Notes
Binary Classification (VQC) Small (<100 samples) IonQ High precision
  Medium (100-1000) Rigetti Acceptable noise
Quantum Kernel SVM Any IonQ or Rigetti Depends on feature dimension
Quantum Regression (HHL) Small systems LocalBackend On IonQ or Rigetti QuantumRegressionHHL measures the weights’ signs with one extra Hadamard circuit per solution qubit (1 + log₂N jobs per fit); the HHL solver alone returns magnitudes (Readout = MeasuredMagnitudes) unless run with HHL.executeWithRelativePhases

Cost Considerations

Development Phase

Use LocalBackend exclusively:

Only move to cloud when:

Production Phase

Cost per 1000 runs (approximate):

Backend Cost When Worth It
LocalBackend $0 Always test here first
D-Wave ~$20-50 Large optimization (>100 vars)
Rigetti ~$100-200 Medium NISQ (20-80 qubits)
IonQ ~$300-500 High precision required

Cost Optimization Tips:

  1. Develop on LocalBackend - test all logic before cloud
  2. Use simulators first - ionq.simulator, rigetti.sim.qvm (cheaper)
  3. Batch jobs - submit multiple problems in one QPU session
  4. Start small - validate with 5-10 qubits before scaling
  5. Monitor spending - Azure Cost Management alerts
  6. Cap the job count - every circuit an algorithm submits is a billed job, and iterative algorithms (QAOA, VQE, ADAPT, QML training) submit hundreds or thousands; pass a JobBudget to the backend (see Backend Switching) so a run stops with an Error at the limit

Performance Benchmarks

Circuit Execution Time (Approximate)

Qubits LocalBackend IonQ Rigetti D-Wave
5 <1 ms ~500 ms ~100 ms ~50 ms
10 ~10 ms ~1 sec ~200 ms ~50 ms
20 ~1 sec N/A (>11) ~500 ms ~50 ms
50 Not possible (>30) N/A ~2 sec ~50 ms
100 Not possible N/A N/A (>80) ~50 ms
1000 Not possible N/A N/A ~100 ms

Cloud times exclude queueing, which usually dominates. Key Takeaway: once a QUBO problem is embedded, D-Wave’s annealing time hardly depends on problem size (for QUBO problems only).


Connectivity Matters

IonQ: All-to-All Connectivity ✅

Every qubit can directly interact with every other qubit
No SWAP gates needed → Shorter circuits → Higher fidelity

Example: 5-qubit fully connected problem = 5 qubits on IonQ

Rigetti: Limited Connectivity ⚠️

Grid topology: qubit i can only interact with neighbors
SWAP gates needed for distant qubits → Longer circuits → Lower fidelity

Example: 5-qubit fully connected problem might need 8-10 physical qubits + SWAPs

D-Wave: Graph Connectivity 📊

Pegasus graph: Each qubit connected to ~15 neighbors (fixed topology)
Problem must map to Pegasus graph → May need "minor embedding"
Embedding efficiency varies by problem structure

Example: a 100-variable dense QUBO might use 500-1000 physical qubits after embedding


Error Mitigation Recommendations

Different backends benefit from different error mitigation strategies:

Backend Recommended Mitigation Why
LocalBackend None Perfect simulation
IonQ ZNE (Zero Noise Extrapolation) High fidelity, ZNE works well
Rigetti REM (Readout Error Mitigation) Measurement errors dominant
D-Wave Majority voting, spin-reversal Annealer-specific techniques

Code Example:

ErrorMitigationStrategy.selectStrategy recommends techniques from the circuit size, backend, budget and accuracy target:

let rigettiCriteria : ErrorMitigationStrategy.SelectionCriteria =
    { CircuitDepth = 30
      QubitCount = 6
      Backend = { Id = "rigetti.sim.qvm"; Provider = "Rigetti"; Name = "Rigetti QVM"; Status = "Available" }
      MaxCostUSD = Some 50.0
      RequiredAccuracy = None
      Calibration = None } // supply a ReadoutErrorMitigation calibration to enable REM correction

let mitigationStrategy = ErrorMitigationStrategy.selectStrategy rigettiCriteria
printfn "%s" mitigationStrategy.Reasoning  // medium circuit with budget: ZNE + readout

Mitigation is applied to results, not to a backend: ZNE and PEC run your circuit through an executor (ZeroNoiseExtrapolation.mitigateAsync, ProbabilisticErrorCancellation.mitigateAsync), and REM corrects measured histograms (ReadoutErrorMitigation.correctReadoutErrors). The chemistry solvers accept a strategy in SolverConfig.ErrorMitigation and apply its readout part to their measurement counts. See Error Mitigation for complete examples.


Summary: Quick Selection Table

I want to…

Goal Backend Choice
Learn quantum computing LocalBackend
Develop/debug algorithm LocalBackend
Test small problem (≤20 qubits) LocalBackend (free)
Solve high-precision chemistry (H2, LiH) IonQ (UCCSD-VQE; LiH with integrals from an IntegralProvider or FCIDUMP)
Solve medium NISQ problem (20-80 qubits) Rigetti
Solve large optimization (100-5000 vars) D-Wave Advantage
Minimize cost LocalBackend → Rigetti → IonQ
Maximize accuracy IonQ → Rigetti → D-Wave
Maximize scale D-Wave (QUBO only)
Get fastest results D-Wave (if QUBO) → Rigetti → IonQ

Further Reading


Happy quantum computing! Choose wisely! 🚀