Skip to content

Resource estimates

Count the qubits, gates, depth, measurements and memory of a planned computation before running it, and read each count with its label. The Estimate resources guide explains how each count is formed, and Estimate fault-tolerant resources covers compiled Clifford+T counts and physical projections.

import nwqlib
from nwqlib.resources import ResourceContext

nwqlib.estimate(plan) returns a WorkloadEstimate with one quantity per metric and location. Read one with quantity:

import nwqlib
from nwqlib import Eigenproblem
from nwqlib.algorithms import Lanczos
from nwqlib.resources import ResourceContext

problem = Eigenproblem(A=[[1.5, -1], [-1, 0.5]])
method = Lanczos(initial_state=[1, 0], krylov_dimension=2)
selected = nwqlib.plan(problem, method=method, seed=7)
workload = nwqlib.estimate(selected, context=ResourceContext(basis="cx"))

cx = workload.quantity("cx")
width = workload.quantity("logical_width", location="logical_device")
operations = workload.quantity("operations")
print(cx.interpretation, cx.fact.value.numerator, cx.fact.unit.symbol)
print(width.interpretation, width.fact.value.numerator)
print(operations.interpretation)
upper_bound 3 count
exact 2
unavailable

The Plan uses at most 3 CX gates and exactly 2 qubits. No exact gate list, registered CX bound (an upper bound on CX gates that NWQLib records for its own blocks) or cost rule (ResourceLaw) of its circuit blocks, the subroutines of its circuit such as a state preparation, gives a total operation count in this basis, so that count is unavailable rather than zero, and operations.fact.reason says why. print(workload) lists every quantity with its label and conditions. A quantity with a value also keeps its evidence in fact.evidence, whose kind is the weakest among the sources that determined the value, for example a proof, a numerical estimate, an observation or an assertion.

An estimate describes the planned logical circuit. It is not a count of compiled gates, which Prepared.inspect_resources gives for a prepared circuit, and it includes no routing, error correction or provider billing.

Estimate a plan

The entry below is nwqlib.resources.estimate, the lower-level function that nwqlib.estimate(plan) calls on plan.construction. It takes the Plan's SelectedConstruction, not the Plan. Every entry on this page imports from nwqlib.resources.

estimate

estimate(construction: SelectedConstruction, *, context: ResourceContext | None = None, memo: dict | None = None, catalog: str | None = None) -> WorkloadEstimate

Estimate the resources of a planned circuit description without building or running it.

Most callers use nwqlib.estimate(plan), which calls this function on plan.construction. The estimate walks the circuit description once per distinct context and keeps symbolic costs in a compact expression table. It reads no numerical input data, synthesizes no gates and does not unroll repeated parts. Its bookkeeping work is at most 24 * limits.max_steps work units, reported as WorkloadEstimate.work_units, where limits is construction.program.limits (engineering constants).

The result depends only on the construction, the context and catalog. A caller that estimates several points of one Plan can pass one memo dictionary for the duration of its operation, and an equal construction, context and catalog then return the estimate already computed. The memo dictionary belongs to that caller, and there is no process-wide cache.

Parameters:

  • construction (SelectedConstruction) –

    The planned circuit description, plan.construction.

  • context (ResourceContext | None, default: None ) –

    Gate basis, rotation precision, synthesis, resident data and batch schedule. None, the default, means ResourceContext(): the "selected_logical" basis, no resident data and an unspecified schedule.

  • memo (dict | None, default: None ) –

    Optional dictionary owned by the caller, mapping (construction.content_id, context.content_id, catalog) to the estimate already computed for that triple.

  • catalog (str | None, default: None ) –

    Default None, which estimates construction as the workload it describes. Otherwise the reason that the experiments of construction are templates of queries whose parameter values a Run chooses one query at a time, as Method.query_catalog_reason returns it for nwqlib.estimate(plan). The counts of the templates are then not the totals of a Run, and a count is exactly zero only when no query bound from the templates can contribute to it. The conditions for a zero read every definition that the Program declares, including one that the root never runs, because a query can select it. When no block call, measurement, reset or measurement batch is declared, the gate, depth, call, measurement, reset, setting, unique-setting, preparation-component, shot and exact-evaluation counts are zero. shots is zero when the Program declares at least one terminal measurement batch and all of them return exact statistics, and exact_evaluations is zero when it declares at least one and all of them sample counts. A declaration that no experiment selects may prevent a zero but never produces a false one. Every other count and the construction work are unavailable with this reason, except the setting and repetition declarations of a root measurement batch, which keep their values. Each width and byte peak keeps its value, evidence and schedule condition, and its population and fact.scope name it a declared footprint of the templates at their supplied or symbolic parameter values, not a peak over a Run. The reason is added to assumptions.

Returns:

  • workload ( WorkloadEstimate ) –

    One quantity per metric and location. Every quantity has lifecycle="planned" and keeps its label, location and original evidence. A metric whose value cannot be determined, such as a gate count that no exact gate list, registered CX bound or cost rule (ResourceLaw) of the blocks gives, is present as unavailable, not as zero.

Raises:

  • ValueError –

    If an exact count needs more integer bits than construction.program.limits.max_integer_bits, two applicable cost rules of a block conflict, a block's declared cost rule contradicts its exact gate list, or its bookkeeping work would exceed the limit stated above.

WorkloadEstimate

Bases: Record

Resource estimate of a planned computation: one quantity per metric and location.

nwqlib.estimate(plan) returns it when no device profile is given, and so does estimate. Read one metric with quantity(metric), or a width or byte peak with quantity(metric, location=...), and list everything with quantities or print(workload). A metric whose value cannot be determined, such as a gate count that no exact gate list, registered CX bound or cost rule gives, is present and labeled unavailable, never zero. The estimate is of the logical circuit description, before compilation, routing or error correction.

exact_evaluations counts grouped exact-statistic requests, not returned labels, bins or simulator trajectories. A circuit with no terminal measurement batch declares no measurements, so zero shots and settings there do not mean that running it is free. The fields below are read-only.

Attributes:

  • construction_id (ContentID) –

    Content hash of the planned circuit description that was estimated.

  • context (ResourceContext) –

    The ResourceContext that fixed basis, precision, synthesis and schedule.

  • quantities (tuple[ResourceQuantity, ...]) –

    One ResourceQuantity per (metric, location), including unavailable ones.

  • expressions (tuple[Expression, ...]) –

    Symbolic cost expressions that symbolic quantities name. Repeats and shared parts are not expanded.

  • parameters (tuple[Parameter, ...]) –

    Circuit parameters those expressions may use.

  • sources (tuple[Evidence, ...]) –

    The original evidence records of the cost rules. The arithmetic of the estimate does not make them verified.

  • defined_selections (tuple[ContentID, ...]) –

    Content hashes of the circuit blocks and classical routines the run may reach, not a record of built circuits.

  • work_units (NonnegativeInt) –

    Bookkeeping work of the estimate, not run time, at most 24 * limits.max_steps.

  • evaluated_contexts (NonnegativeInt) –

    Distinct node and call contexts evaluated.

  • limits (AdmissionLimits) –

    The size limits of the planned circuit description.

  • assumptions (tuple[Text, ...]) –

    Conditions of the whole estimate, such as "logical dependency schedule; no physical QEC/routing/factory projection".

  • schema_version (Literal[2]) –

    Format version of the record, 2.

Examples:

A two-dimensional Lanczos Plan, estimated in the CX basis, has an exact width of two qubits and an upper bound of three CX gates. No exact gate list, registered CX bound or cost rule gives its total operation count:

>>> import nwqlib
>>> from nwqlib import Eigenproblem
>>> from nwqlib.algorithms import Lanczos
>>> from nwqlib.resources import ResourceContext
>>> problem = Eigenproblem(A=[[1.5, -1], [-1, 0.5]])
>>> method = Lanczos(initial_state=[1, 0], krylov_dimension=2)
>>> selected = nwqlib.plan(problem, method=method, seed=7)
>>> context = ResourceContext(basis="cx")
>>> workload = nwqlib.estimate(selected, context=context)
>>> cx = workload.quantity("cx")
>>> cx.interpretation, cx.fact.value.numerator
('upper_bound', 3)
>>> width = workload.quantity("logical_width", location="logical_device")
>>> width.interpretation, width.fact.value.numerator
('exact', 2)
>>> workload.quantity("operations").interpretation
'unavailable'

quantity

quantity(metric: str, *, location: str | None = None) -> ResourceQuantity

Return the quantity of one metric at one location, without recomputing anything.

Parameters:

  • metric (str) –

    Metric name, such as "cx" or "logical_width".

  • location (str | None, default: None ) –

    Location of a width or byte peak, for example "logical_device" or "host". None, the default, selects a total.

Returns:

Raises:

  • ValueError –

    If no quantity has this metric and location. The message lists up to eight locations of the metric.

ResourceContext

Bases: Record

Settings that fix how a resource estimate counts: gate basis, rotation precision, synthesis, resident data and schedule.

Build it with keyword arguments, for example ResourceContext(basis="cx"), and pass it as context= to nwqlib.estimate or estimate. Every argument is optional, and ResourceContext() counts in the "selected_logical" basis.

Attributes:

  • basis (MetricBasis) –

    Default "selected_logical", which counts the planned construction's own operations. Basis in which gate metrics are counted: "selected_logical", "cx", "clifford_t" or "toffoli". Counts in different bases answer different questions and are never converted into or added to each other.

  • precision (Float64 | None) –

    Default None. Positive rotation synthesis precision, in the sense that synthesis defines. An arbitrary rotation gets a T count only when the precision and the synthesis are known, and a block's ResourceLaw applies only when its precision equals this value.

  • synthesis (Source | None) –

    Default None. Source naming the synthesis method. A block's ResourceLaw applies only under the same choice.

  • resident (tuple[Workspace, ...]) –

    Default (). Workspace entries that stay in memory for the whole workload and are added to every memory peak.

  • capacities (tuple[Limit, ...]) –

    Default (). Device capacities as Limit records, kept for a later device assessment. The estimate itself allocates nothing and queries no device.

  • batch_schedule (Literal['unspecified', 'serial']) –

    Default "unspecified". "serial" declares that the circuit executions of each measurement batch run one after another, so a batch memory peak holds without condition. With "unspecified" such a peak is labeled conditional. The required schedule stays recorded for the execution to follow.

Raises:

  • ValueError –

    If precision is not positive.

Read a quantity

Each ResourceQuantity holds its value in fact.value: an exact Rational (read numerator and denominator) or a Float64 (read value). Its interpretation says how to read that value:

interpretation Meaning
exact The exact count
upper_bound The count is at most this value, for example a CX bound before gate cancellation and routing, or the maximum over the arms of a branch
estimate Derived from observed, empirically predicted or numerically estimated evidence
conditional Holds only under a stated condition, such as a memory peak that needs the circuit executions of each measurement batch to run one after another (required_schedule)
unavailable The value cannot be determined, for example a gate count that no exact gate list, registered CX bound or cost rule of the blocks gives. fact.reason says why, and the value is never read as zero

An exact count or upper bound is only as strong as its evidence, fact.evidence.kind, so a count derived from an asserted rule stays an assertion. The conditions of a value are in fact.assumptions.

Totals over the whole run have location=None. Widths and memory are peaks at a location, so read them with quantity(metric, location=...):

Metrics Value Unit
Gates: operations, single_qubit, two_qubit, controlled, global_phases, clifford, t, toffoli, ccz, arbitrary_rotations, cx Whole run count
Depths: logical_depth, t_depth, non_clifford_depth Whole run count
Calls and measurement: calls, measurements, resets, settings, shots, exact_evaluations, unique_settings, root_setting_declarations, root_repetitions, adaptive_rounds, expected_operations Whole run count
Work: classical_work, construction_work, preparation_components Whole run count
Qubits: logical_width, system, clean_ancilla, dirty_ancilla at a register's location Peak count
Classical registers: classical_registers, classical_bits at "host" Peak count
Memory: memory, known_memory, input_bytes, analysis_bytes, io_bytes, materialization_bytes, stored_bytes at a workspace's location Peak byte

The Estimate resources guide defines what shots, settings, exact_evaluations and the other measurement counts include.

ResourceQuantity

Bases: Record

One count or peak of a resource estimate, with its value, label and sources.

WorkloadEstimate.quantity returns it. The value is fact.value, an exact Rational (read numerator and denominator) or a Float64, in the unit fact.unit: count, or byte for byte metrics. A symbolic value is fact.symbol, and an unavailable one has fact.reason and no value. interpretation says how to read the value (see Read a quantity). print(quantity) shows the value, label and conditions. The fields below are read-only.

Attributes:

  • metric (Metric) –

    Name of the quantity, such as cx, shots or logical_width.

  • fact (Fact) –

    The value, or the reason it is unavailable, with its unit, scope, conditions (fact.assumptions) and the weakest evidence kind among the sources that determined it.

  • population (Text) –

    What is counted, for example "dynamic workload" for a total over the whole run or "simultaneous live footprint" for a peak.

  • lifecycle (Literal['planned', 'prepared', 'submitted', 'observed']) –

    Workflow stage of the quantity: "planned", "prepared", "submitted" or "observed". A planning estimate gives only "planned".

  • basis (Text) –

    Gate basis of the estimate.

  • interpretation (Interpretation) –

    "exact", "upper_bound", "estimate", "conditional" or "unavailable".

  • location (Text | None) –

    Location of a width or byte peak, None for a total.

  • sources (tuple[ContentID, ...]) –

    Content hashes of all evidence attached to the value, including evidence used only to check a block's gate decomposition against a declared rule.

  • derivation_sources (tuple[ContentID, ...]) –

    Content hashes of the evidence that determined the value, a subset of sources.

  • required_schedule (Literal['serial_acquisitions'] | None) –

    "serial_acquisitions" when this peak holds only if the circuit executions of each measurement batch run one after another, otherwise None. Follow it before comparing the peak with a device capacity.

  • schema_version (Literal[2]) –

    Format version of the record, 2.

Raises:

  • ValueError –

    When a record is loaded whose label disagrees with its availability, whose value is negative, not real or, when exact, not an integer (expected_operations may be fractional), whose unit does not match the metric, or whose derivation sources are not among its sources.

Declare costs and memory

A circuit block declares its own costs and memory with these records. The estimate reads them and allocates none of the declared memory.

ResourceLaw

Bases: Record

The cost of one call of a circuit block in one metric, as the block declares it.

A circuit block of a Plan can declare cost rules for its metrics. The estimate uses a rule only for a call whose control and adjoint flags, cost parameters and call arguments, basis, precision and synthesis all match. The value is a number per call, not a formula, so the estimate can check it against the block's known gate decomposition and keep its source without running caller code. Rules in different bases are alternatives, not additions. Build it with keyword arguments when you write a block (see Compose blocks). metric, basis, value, interpretation and evidence are required.

Attributes:

  • metric (Metric) –

    Required. The count metric the rule supplies.

  • basis (MetricBasis) –

    Required. Basis the value is counted in.

  • value (NonnegativeInt | Float64) –

    Required. Nonnegative per-call value, an integer when interpretation is "exact".

  • interpretation (Literal['exact', 'upper_bound', 'estimate']) –

    Required. "exact", "upper_bound" or "estimate".

  • evidence (Evidence) –

    Required. Where the value comes from. Observed, empirically predicted or numerically estimated evidence makes every quantity derived from it an estimate.

  • bindings (tuple[Binding, ...]) –

    Default (). Cost parameters and call arguments that must match exactly for the rule to apply.

  • unbound_parameters (tuple[Text, ...]) –

    Default (). Formal parameters whose whole accepted range the rule covers instead of one value. Empty means exact matching only.

  • controlled (StrictBool) –

    Default False. Whether the rule is for the controlled block.

  • adjoint (StrictBool) –

    Default False. Whether the rule is for the adjoint block.

  • precision (Float64 | None) –

    Default None. Rotation precision the rule assumes.

  • synthesis (Source | None) –

    Default None. Synthesis method the rule assumes.

  • assumptions (tuple[Text, ...]) –

    Default (). Conditions carried into every quantity derived from the rule.

Raises:

  • ValueError –

    If the value is negative, an exact value is not an integer, a binding is repeated, or a parameter is both bound and listed in unbound_parameters.

Workspace

Bases: Record

Bytes needed at the same time at one location, as declared by a block or the caller.

A block's workspace lasts for each call. Entries in ResourceContext.resident last for the whole workload. Sizes are declarations, not observed allocations, and quantum widths are counted separately. Build it with keyword arguments. All four fields are required.

Attributes:

  • location (Text) –

    Where the bytes live, for example "host".

  • purpose (Literal['input', 'preparation', 'analysis', 'io', 'materialization', 'stored', 'workspace']) –

    "input", "preparation", "analysis", "io", "materialization", "stored" or "workspace".

  • bytes (NonnegativeInt | None) –

    Nonnegative byte count, or None when unknown. An unknown size makes the memory peak at that location unavailable, never zero.

  • source (Source) –

    Source of the declaration.