Skip to the content.

IBM resource + cost estimator

Estimate what a circuit — or a whole benchmark study — will cost on real IBM Quantum hardware, before submitting anything and without needing an IBM Quantum account. Two modules:


Installation

pip install 'qpubench[qiskit]'

Resource estimation — real, verified

from qpubench.backends.ibm_cost_estimator import estimate_circuit_resources

est = estimate_circuit_resources(
    my_circuit_spec, backend_name="ibm_brisbane", shots=4096,
)
print(est.depth, est.two_qubit_gate_count, est.estimated_qpu_time_s)

By default this resolves "ibm_brisbane" to the real qiskit_ibm_runtime.fake_provider.FakeBrisbane calibration snapshot — no credentials, no network. Pass a live backend (e.g. IBMAdapter(...).get_live_backend()) via backend= to estimate against current calibration data instead of a static snapshot.

What’s real here, not guessed: depth/gate_counts come from actually running Qiskit’s preset pass manager against the target topology/basis gates (ecr/rz/sx/x on Eagle-class chips like Brisbane). Circuit duration comes from QuantumCircuit.estimate_duration(backend.target) after scheduling_method="alap" — exactly the method IBM’s own docs recommend for local usage estimation (quantum.cloud.ibm.com/docs/en/ guides/estimate-job-run-time, checked 2026-07-09). estimated_qpu_time_s applies that same page’s documented formula:

usage_seconds = per_sub_job_overhead + (rep_delay + circuit_duration) * shots

with IBM’s own stated defaults (per_sub_job_overhead ~= 2s, rep_delay = 250 microseconds). IBM’s doc notes the experimental scheduler_timing return value “is NOT the time used for billing” — this is IBM’s own recommended proxy for it, not a guarantee of exact billed- second parity.

Verified in this session: a 4-qubit test circuit transpiled against FakeBrisbane gives depth=14, 3 real ecr (2-qubit) gates, a 3.52-microsecond circuit duration, and (at 4096 shots) an estimated 3.04s of QPU time — see tests/test_ibm_cost_estimator.py.

Cost breakdown — sourced, but verify before budgeting

from qpubench.schemas.mirrors.ibm_cost_estimator import estimate_all_plans

for plan, breakdown in estimate_all_plans(total_qpu_seconds=180.0).items():
    print(plan.value, breakdown.cost_usd, breakdown.notes)

Or aggregate a whole study’s worth of CircuitResourceEstimates at once:

from qpubench.schemas.mirrors.ibm_cost_estimator import aggregate_benchmark_cost

agg = aggregate_benchmark_cost(list_of_circuit_resource_estimates)
print(agg.total_qpu_seconds, agg.plan_breakdowns)

The four plans

Plan Model Rate Minimum Confirmed against
Open Free quota IBM’s own docs: “up to 10 minutes per 28-day rolling window”
Pay-As-You-Go Billed by the second $96/min none Rate: analyst/press sources (below). Billing unit (seconds): IBM’s own docs
Flex Prepaid lump sum $72/min $30,000 (~417 min), valid 1 year Minimum minutes (“at least 400”) and validity (“within one year”): IBM’s own docs. Rate/minimum $: analyst/press sources
Premium Annual subscription $48/min 5,200 min/year (~$249,600/year) Analyst/press sources only

Important — verify before making a real budget decision. ibm.com/quantum/products (the pricing page) returned HTTP 403 to automated fetches in this session (bot protection) — the exact $/minute figures above could not be confirmed directly against IBM’s own pricing page. What backs them:

Every rate is a field on IBMPricingRates, not a hardcoded constant — override with your own confirmed numbers:

from qpubench.schemas.mirrors.ibm_cost_estimator import IBMPricingRates, estimate_all_plans

my_rates = IBMPricingRates(pay_as_you_go_usd_per_minute=100.0)   # if IBM's rate changed
estimate_all_plans(total_qpu_seconds=180.0, rates=my_rates)

How each plan is evaluated


End-to-end example: costing the VQE benchmark CSV

examples/guides/estimate_ibm_cost.py runs this against data/IBM_VQE_Test_Benchmark.csv end to end: the minimal case (H2/sto-3g, 4 qubits, 1 circuit) fits comfortably in the Open Plan’s free quota (~3s of an estimated 3.04s QPU-time budget vs. 600s free). The CSV now also carries a full Cebule TN-VQE (tn_qc_opt/tn_qc_opt+mol_map) sweep across all 7 bases (1,218 rows total, 783 with a known N_Qubit) — real transpile calls are cached per (qubits, TN_Layers_Circuit) pair (72 distinct pairs, ~20s), since TN_Layers_Network runs classically and doesn’t change the real submitted circuit (see data/README.md). At 30 illustrative VQE iterations per row, that’s 23,490 circuit submissions, ~74,153s (~1,236 min) of QPU time — ~$118,645 on Pay-As-You-Go, ~$88,983 on Flex (now above its $30,000 minimum), and ~24% of Premium’s 5,200 min/year minimum commitment.

The CSV’s Qiskit_Opt_Level/Shots sweep columns are still blank (see data/README.md), so the example clearly labels its ansatz (EfficientSU2, reps = TN_Layers_Circuit for TN-VQE rows, else 1), shot count (4096), and iteration count (30) as illustrative assumptions at the top of the script — swap in the real choices once decided; the resource-estimation and cost-breakdown logic itself doesn’t change.

Turning this into a real campaign plan

examples/guides/split_benchmark_batches.py uses the same per-row estimates to split the CSV into data/batches/batch1_open_plan.csv (fits the Open Plan’s free 10 min), batch2_flex_plan.csv (fits a fresh 400-min Flex purchase), and batch3_premium_plan.csv (fits a fresh 5,200-min Premium annual minimum) — see data/batches/README.md.