Skip to content

Backends, profiles and export

Choose the backend that runs a Plan's circuits, forecast run time and memory on a device profile before a run, and export circuits as OpenQASM. Import the OpenQASM functions and records from nwqlib.io, TimingObservation from nwqlib.execution, and every other entry on this page from nwqlib.backends, except the forecast records AxisAssessment, AssessmentDetail and TimePrediction, which are defined in nwqlib.backends.assessment.

from nwqlib.backends import AerBackend, Allocation, DeviceProfile, assess
from nwqlib.io import export_qasm, write_qasm3_file

Pass a backend as backend= to solve or prepare. Without one, a quantum Plan runs on AerBackend(). The expectation of Z in the state |0> is exactly 1:

from nwqlib import Expectation, solve
from nwqlib.algorithms import ExpectationMethod
from nwqlib.backends import AerBackend

problem = Expectation(state=[1.0, 0.0], observable=[[1.0, 0.0], [0.0, -1.0]])
result = solve(problem, method=ExpectationMethod(), backend=AerBackend(),
               seed=7)
print(result.value)  # 1.0

Choose a backend

Backend and class Readouts Needs
Qiskit Aer, local: AerBackend Counts, and exact Pauli expectations, probabilities and amplitudes nwqlib[aer]
NWQ-Sim, local: NWQSimBackend Counts. CPU statevector also gives exact Pauli expectations, probabilities and amplitudes A runner built for one backend and method
NWQ-Sim on a Slurm cluster: NWQSimSlurmBackend with SlurmProfile As NWQ-Sim A runner built at the site and a Slurm account
IBM Quantum: IBMRuntimeBackend Counts and provider expectation estimates nwqlib[ibm] and a saved IBM account or a token in NWQLIB_IBM_RUNTIME_TOKEN
IonQ QPU: IonQBackend Raw counts nwqlib[ionq] and an API key in NWQLIB_IONQ_API_KEY
Quantinuum H2 through Nexus: NexusBackend Counts nwqlib[nexus] and an existing qnexus login

Every backend except Aer runs jobs that continue after Python exits. Save the Run to a directory and reopen it with load_run, as Continue an interrupted run describes. NWQLib has checked the cloud and Slurm backends only offline, without a live account, queue or device, and each Run on one of them issues a warning that says so once. Choose a backend compares them, and Backend adapter contract states the rules every backend implements.

AerBackend

Bases: Record

Local Qiskit Aer simulator, the default backend of prepare and solve.

Build it with AerBackend() for noiseless simulation, or with AerBackend.from_noise_model(model) for a Qiskit Aer noise model, and pass it as backend= to solve or prepare. It needs the aer extra (pip install "nwqlib[aer]") and no credentials. A noise model acts on sampled counts only. An exact expectation, probability or amplitude would describe neither the noiseless circuit nor the noisy samples, so those readouts reject a noisy backend before any circuit is built.

The backend holds the caller's NoiseModel object without copying or serializing it, so keep that model unchanged while this backend or its prepared circuits are in use. Run.save saves the model as the SDK's dictionary with NumPy array files, and load_run attaches the rebuilt model to the reopened Run's own copy of this configuration (run.backend), leaving the backend passed to load_run unchanged. revise keeps the attached model while noise_model_id is unchanged. The Aer guide covers readouts, noise and circuit inspection.

Attributes:

  • kind (Literal['qiskit_aer']) –

    Fixed "qiskit_aer", the backend type.

  • noise_model_id (Text | None) –

    Default None, no noise model. from_noise_model sets it to a fresh UUID that identifies the model object this backend holds, not the model's contents. A configuration rebuilt from JSON with this field set holds no model and raises when used.

from_noise_model

from_noise_model(model)

Return an Aer backend that applies a Qiskit Aer noise model to sampled counts.

The model is held without copying, and qiskit_aer is imported only by this call.

Parameters:

  • model (NoiseModel) –

    The noise model to apply.

Returns:

  • backend ( AerBackend ) –

    A new backend whose noise_model_id is a fresh UUID.

Raises:

  • TypeError –

    If model is not a Qiskit Aer NoiseModel.

NWQSimBackend

Bases: Record

NWQ-Sim simulator run locally in a process that outlives Python, with statevector or density-matrix simulation.

Build it with keyword arguments, for example NWQSimBackend(executable=..., spool=..., max_input_bytes=..., max_output_bytes=..., max_buffer_bytes=...), and pass it as backend= to prepare. executable, spool and the three byte limits are required. The executable is a runner built for one backend and method pair with python -m nwqlib.backends.nwqsim (see the NWQ-Sim guide). Construction launches and inspects nothing.

Preparation translates each circuit to Qiskit's U and CX gates. The runner keeps running after the Python process exits, so the computer that runs it must stay on until the job finishes. The guide records the NWQ-Sim revision that NWQLib was tested against and the byte formulas behind max_buffer_bytes.

Attributes:

  • kind (Literal['nwqsim']) –

    Fixed "nwqsim", the backend type.

  • backend (Literal['CPU', 'MPI', 'NVGPU', 'AMDGPU', 'NVGPU_MPI']) –

    Default "CPU". "CPU", "MPI", "NVGPU" or "AMDGPU". "NVGPU_MPI" is rejected, because its constructors read an uninitialized GPU memory counter in the inspected NWQ-Sim sources.

  • method (Literal['SV', 'DM']) –

    Default "SV". "SV" (statevector) or "DM" (density matrix). "MPI" supports "SV" only, because NWQ-Sim's state-creation function silently substitutes SV for DM.

  • ranks (PositiveInt) –

    Default 1. Positive. Number of cooperating MPI processes. Only "MPI" accepts more than one, and it requires a power of two.

  • mpi_launcher (Text) –

    Default "mpirun". Installed launcher for local MPI runs.

  • executable (Text) –

    Required. Absolute path of the built runner.

  • spool (Text) –

    Required. Absolute path of the directory for request and result files. It identifies the job after Python exits, so it cannot be relative.

  • max_input_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on each request file.

  • max_output_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on each result file that NWQLib reads.

  • max_buffer_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on the state, work and sample arrays of known size in each process, including host and device storage on a GPU. It excludes fused gates, SDK workspace and whole-process memory.

  • optimization_level (Count) –

    Default 0. Qiskit transpiler level, 0 to 3, of the translation to U and CX gates. A level other than 0 adds the roundoff exclusion "optimization_level", a label for a condition that the roundoff derivation of exact readouts does not cover, to the preparation record that NWQLib saves for each prepared circuit. PreparedArtifact.state_error() then gives no state budget, the first-order bound on the 2-norm distance, up to a global phase, of the simulated state from the exact state. The probability window, the roundoff window of exact execution, which for circuits that the roundoff derivation covers is a first-order bound on how far binary64 roundoff can move the total probability from one, remains a readout-check convention for that execution, and the operation count describes the compiled circuit. Levels 2 and 3 resynthesize two-qubit blocks with Qiskit's own synthesis. At those levels an exact readout or trajectory is refused when transpilation relabels wires by removing permutations, because the runner reads the output in logical wire order, and a measured circuit can still supply computational-basis probabilities when transpilation reports no layout. Amplitude readouts require level 0 or 1, or a circuit without measurements, because removing terminal diagonal gates can change relative phases.

Raises:

  • ValueError –

    If the backend, method and rank combination is not supported, or if executable or spool is not an absolute path.

NWQSimSlurmBackend

Bases: Record

NWQ-Sim run as a Slurm batch job on a cluster.

Build it with keyword arguments, for example NWQSimSlurmBackend(profile=..., accounting_since=..., accounting_until=..., max_input_bytes=..., max_output_bytes=..., max_buffer_bytes=..., max_response_bytes=..., timeout_seconds=...), and pass it as backend= to prepare. Every argument except optimization_level is required. The profile holds the runner, its build and the shared result directory (spool). Submission calls sbatch once, and a job whose acknowledgement was lost is found again by its job name in Slurm accounting within the configured time window. NWQLib has tested this backend only offline, with scheduler and protocol checks, and has not tested a live site allocation, runner or hardware. The Slurm guide shows a complete run.

Attributes:

  • kind (Literal['slurm']) –

    Fixed "slurm", the backend type.

  • profile (SlurmProfile) –

    Required. The SlurmProfile. Its total rank count and GPU request are checked against its backend and method.

  • accounting_since (Text) –

    Required. Start of the accounting search window, an ISO time without a time zone, read in the site's local time. Choose a window that covers the intended submission period.

  • accounting_until (Text) –

    Required. End of that window, later than accounting_since.

  • max_input_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on each request file, as in NWQSimBackend.

  • max_output_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on each result file.

  • max_buffer_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on the runner's arrays of known size per process, as in NWQSimBackend.

  • max_response_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on the output of each scheduler command. It must cover the sbatch --parsable reply, 12 bytes plus the cluster name's length (22 bytes for perlmutter).

  • timeout_seconds (Real) –

    Required. Positive deadline in seconds for each scheduler command.

  • optimization_level (Count) –

    Default 0. Qiskit transpiler level of the translation to U and CX gates, as in NWQSimBackend. A level other than 0 adds the same roundoff exclusion "optimization_level" to the preparation record.

Raises:

  • ValueError –

    If the rank or GPU request does not fit the profile's backend and method, the accounting window has a time zone or is not increasing, or timeout_seconds is not positive.

SlurmProfile

Bases: Record

Slurm site settings for an NWQ-Sim runner: allocation, runner, binding and shared result directory.

Build it with keyword arguments, for example SlurmProfile(cluster=..., account=..., walltime="00:05:00", nodes=1, ranks_per_node=1, threads=1, executable=..., build_identity=..., spool=...), and pass it as profile= to NWQSimSlurmBackend. cluster, account, walltime, nodes, ranks_per_node, threads, executable, build_identity and spool are required. Node, rank and thread counts describe the requested resources, not measured use. Every option value must be one literal token, so that it cannot end its #SBATCH line and add another directive. The Slurm guide gives Perlmutter and Frontier profiles.

Attributes:

  • cluster (Text) –

    Required. One cluster name, letters, digits, _ and - only. "all" and comma lists are rejected, because job lookups name exactly one cluster.

  • account (Text) –

    Required. Slurm account to charge.

  • partition (Text | None) –

    Default None. Slurm partition.

  • qos (Text | None) –

    Default None. Slurm quality of service.

  • constraint (Text | None) –

    Default None. Slurm node constraint, such as "gpu".

  • walltime (Text) –

    Required. Positive time limit in Slurm's [days-]hours:minutes:seconds form.

  • nodes (PositiveInt) –

    Required. Positive. Number of nodes.

  • ranks_per_node (PositiveInt) –

    Required. Positive. MPI ranks per node.

  • threads (PositiveInt) –

    Required. Positive. Threads per rank.

  • gpus_per_task (PositiveInt | None) –

    Default None. Positive. GPUs per task, given together with gpu_bind. The "NVGPU" and "AMDGPU" backends require exactly 1, and the "CPU" and "MPI" backends require None.

  • gpu_bind (Text | None) –

    Default None. Slurm GPU binding, given together with gpus_per_task.

  • cpu_bind (Text) –

    Default "cores". Slurm CPU binding.

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

    Default (). Environment modules to load before the run.

  • executable (Text) –

    Required. Absolute path of the runner on the compute nodes.

  • build_identity (Text) –

    Required. Source commit of the runner's NWQ-Sim build. It records which build ran and does not show that a GPU or distributed build works.

  • spool (Text) –

    Required. Absolute path of a directory shared with the compute nodes.

  • backend (Literal['CPU', 'MPI', 'NVGPU', 'AMDGPU', 'NVGPU_MPI']) –

    Default "CPU". NWQ-Sim backend, with the values and restrictions of NWQSimBackend.

  • method (Literal['SV', 'DM']) –

    Default "SV". "SV" or "DM", as in NWQSimBackend.

Raises:

  • ValueError –

    If the backend and method combination is not supported, cluster is not one name, an option value is not one token, walltime is malformed or zero, gpus_per_task and gpu_bind are not given together, or a path is not absolute.

script

script(submission_id, *, max_input_bytes)

Return the Slurm batch script for one submission, without running it.

Use it to inspect what a submission would send to sbatch. Rendering a script does not test the site. The job name nwqlib-<submission UUID> is what a lost submission acknowledgement is searched for. --no-requeue keeps Slurm from running the same request a second time after a node failure or preemption, and srun --kill-on-bad-exit stops all ranks when one fails. Batch stdout and stderr go to /dev/null, because only the runner's result file is read.

Parameters:

  • submission_id (str) –

    Submission UUID that names the job and its subdirectory of spool.

  • max_input_bytes (int) –

    Positive limit in bytes on the request file, passed to the runner.

Returns:

  • script ( str ) –

    The script text, ending with a newline.

Raises:

  • ValueError –

    If max_input_bytes is not a positive integer.

  • ValueError –

    If submission_id is not a canonical UUID.

IBMRuntimeBackend

Bases: Record

IBM Quantum Runtime connection for sampled counts and provider expectation estimates.

Build it with keyword arguments, for example IBMRuntimeBackend(device="ibm_example", instance="my-instance", max_input_bytes=65_536), and pass it as backend= to prepare. device, instance and max_input_bytes are required. It needs the ibm extra. Counts use SamplerV2 and a provider estimate uses EstimatorV2. Construction reads no credential and contacts no service. Preparation and retrieval use the saved SDK account named by account_name, or otherwise the token in the environment variable named by token_env, and no credential is saved in the configuration or the Run's files.

Preparation compiles each circuit for the device with the Plan's runtime seed and keeps the logical-to-physical layout. The preparation record also keeps the native two-qubit depth of the compiled circuit (PreparedArtifact.native_depth). It is qualified only for counts whose options keep the provider's dynamical decoupling, gate twirling and measurement twirling off (options_json), and only with qiskit-ibm-runtime 0.49.0, the version whose Sampler options were checked for this. It is never qualified for a provider estimate, because the Estimator measures the observable with circuits that the provider builds from the compiled one. A requested depth limit also refuses a circuit when the installed nwqlib, Qiskit or qiskit-ibm-runtime version differs from the one recorded at its preparation, as after a Run is reopened in another environment (nwqlib.backends.inspection.check_native_depth_cap). The Estimator's resilience level is zero unless options_json selects another, so no error mitigation runs implicitly, and the Plan sets the precision. The Run bounds serialized buffers and decoded arrays. SDK HTTP buffering, retries, compilation memory, wall time and billing are not bounded. When a later result fails to decode, Run.resume, which Run.wait calls on each pass, keeps the results already decoded. A resumed read fetches the whole job payload again, and results already saved skip only the local decoding. NWQLib has tested this backend only offline, with SDK and transport checks, and has not tested live accounts, queues or devices. The IBM Runtime guide describes jobs, retrieval and cancellation.

Attributes:

  • kind (Literal['ibm']) –

    Fixed "ibm", the backend type.

  • device (Text) –

    Required. IBM device name.

  • instance (Text) –

    Required. IBM instance. "auto" is rejected, because retrieval and job recovery compare it with the job's own instance.

  • account_name (Text | None) –

    Default None. Name of a saved IBM SDK account. With None, the token is read from the variable token_env names.

  • token_env (Text) –

    Default "NWQLIB_IBM_RUNTIME_TOKEN". Environment variable that holds the API token, read only during preparation or retrieval.

  • mode (Literal['job', 'batch', 'session']) –

    Default "job". "batch" or "session" attaches every job to the existing Batch or Session whose ID is container_id.

  • container_id (Text | None) –

    Default None. ID of an existing Batch or Session. Required in batch and session mode, and must be None in job mode.

  • calibration_id (Text | None) –

    Default None. Device calibration ID passed to the IBM SDK when the device is opened.

  • options_json (Text) –

    Default "{}". JSON object of the requested primitive options. It states the requested options, not the server's defaults, and the configuration keeps it as given. For counts, preparation sets each of dynamical_decoupling.enable, twirling.enable_gates and twirling.enable_measure that the request leaves unset to false, the Sampler default that qiskit-ibm-runtime 0.49.0 documents. The preparation record keeps these effective options (PreparedArtifact.provider_options_json), and every job of the preparation is sent with them, also from a reopened Run with another installed SDK, whose own validation can still reject them. An option set to true stays on, and the native depth of that preparation is then unqualified. Experimental option overrides are rejected, because they can bypass the requested readout and its uncertainty.

  • optimization_level (Count) –

    Default 1. Qiskit preset pass-manager level, 0 to 3. A level other than 1 adds the roundoff exclusion "optimization_level" to the preparation record, and the operation count describes the compiled circuit. The IBM target has no derived roundoff constant, so PreparedArtifact.state_error() gives no bound at any level.

  • initial_layout (tuple[Count, ...] | None) –

    Default None. Physical qubit for each logical qubit, without repeats.

  • max_input_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on the QPY copy (Qiskit's binary circuit format) of each prepared circuit, which only a Run saved to a directory writes.

Raises:

  • ValueError –

    If container_id is given in job mode or missing in batch or session mode, if instance is "auto", or if initial_layout repeats a qubit.

IonQBackend

Bases: Record

IonQ connection for raw sampled counts on an IonQ QPU, through the v0.4 REST API.

Build it with keyword arguments, for example IonQBackend(device="qpu.forte-1", max_input_bytes=1_000_000, max_response_bytes=1_000_000), and pass it as backend= to prepare. device, max_input_bytes and max_response_bytes are required. It needs the ionq extra. Construction imports no SDK and contacts no service. The API key is read from the environment variable named by token_env only when a job is submitted or retrieved, and it is never saved.

Each operation is one HTTP request, so no SDK retry can create a second job. IonQ's v0.4 API offers no job lookup by name that NWQLib has tested, so a lost submission acknowledgement leaves the outcome uncertain, and Run.wait raises RunFailed without submitting a replacement. Only raw histograms are read, because IonQ's probability results are not counts of shots. The Run bounds decoded data and saved observations. NWQLib has tested this backend only offline, with SDK and API checks, and has not tested live QPU behavior. The IonQ guide gives the API sources, batch limits and histogram decoding.

Attributes:

  • kind (Literal['ionq']) –

    Fixed "ionq", the backend type.

  • device (Text) –

    Required. A v0.4 QPU name starting with qpu.. The ideal simulator is rejected because it ignores the requested shots.

  • gateset (Literal['qis', 'native']) –

    Default "qis". "qis" translates circuits with Qiskit to Rx, Ry, Rz and CX, with angles in radians. "native" passes IonQ native gates unchanged, with angles in turns.

  • token_env (Text) –

    Default "NWQLIB_IONQ_API_KEY". Environment variable that holds the API key.

  • max_input_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on the serialized request and the optional QPY copy of each prepared circuit.

  • max_response_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on each HTTP response body that NWQLib reads. It does not bound network buffers, provider work, billing or process memory.

  • request_timeout_seconds (Real) –

    Default 30.0. Positive. Connect and read timeout of each request in seconds, not a deadline for the whole request.

  • optimization_level (Count) –

    Default 0. Qiskit transpiler level, 0 to 3, of the "qis" translation. The "native" gateset accepts only 0. Levels 2 and 3 resynthesize two-qubit blocks with Qiskit's own synthesis. A level other than 0 adds the roundoff exclusion "optimization_level" to the preparation record, and the operation count describes the compiled circuit. The IonQ target has no derived roundoff constant, so PreparedArtifact.state_error() gives no bound at any level.

Raises:

  • ValueError –

    At preparation, before any request, if device does not start with qpu. or is the ideal simulator, the readout is not counts, the shot count is outside 1 to 1,000,000, the "native" gateset has an optimization_level other than 0, or the circuit has unbound parameters, no measurements, a measurement followed by another operation on its qubit, or two measurements into one classical bit.

NexusBackend

Bases: Record

Quantinuum Nexus connection for sampled counts on an H2 device or emulator.

Build it with keyword arguments, for example NexusBackend(project="<project UUID>", device="H2-1", max_input_bytes=1_000_000), and pass it as backend= to prepare. project, device and max_input_bytes are required. It needs the nexus extra. Construction imports no SDK and does not log in. Authentication uses the user's existing qnexus configuration.

Preparation uploads and compiles each circuit as separate remote steps, and execution sends one job per batch. The Run bounds the data it saves, not HTTP buffering, billing or SDK memory. Run.resume does not wait in the provider queue, but qnexus 0.49 has no public per-request timeout, so one HTTP request can still block indefinitely. NWQLib has tested this backend only offline, with SDK and converter checks, and has not tested live compilation or execution. The Nexus guide gives the upload and compilation steps, costs and the qnexus dependency conflict.

Attributes:

  • kind (Literal['nexus']) –

    Fixed "nexus", the backend type.

  • project (Text) –

    Required. UUID of an existing Nexus project.

  • device (Text) –

    Required. An H2 device name, H2-<n>, with suffix E or LE for the emulators. Helios devices take HUGR or QIR programs, which this backend does not submit.

  • target_region (Literal['us', 'sg']) –

    Default "us". Execution region, "us" or "sg".

  • credential_name (Text | None) –

    Default None. Name of a Nexus-linked credential, never a secret.

  • optimization_level (Count) –

    Default 1. Nexus compile level, 0 to 3. A level other than 1 adds the roundoff exclusion "optimization_level" to the preparation record. The H2 target has no derived roundoff constant, so PreparedArtifact.state_error() gives no bound at any level.

  • max_cost_hqc (Nonnegative | None) –

    Default None, no cap. Nonnegative. Cost cap per submitted program, in Hardware Quantum Credits.

  • max_input_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on the JSON encoding of each prepared pytket circuit.

Raises:

  • ValueError –

    If device is not an H2 device name.

Forecast cost and feasibility

A DeviceProfile describes a machine and its time models, and an Allocation the resources granted to a workload. nwqlib.estimate(plan, profile=profile, allocation=allocation) forecasts every planned execution of the Plan whose parameters are already fixed and returns a PlanEstimate. assess forecasts one such execution, for example the one that selected.resolve("expectation") returns in the example below. Nothing runs, and the numbers below are synthetic, not measurements of a machine. The one-qubit Plan prepares |1> as H, Z, H and reads <Z> exactly, which counts one invocation, one exact evaluation and three logical operations, so the engineering model predicts 0.25 + 0.5 + 3 × 0.125 = 1.125 seconds:

from datetime import datetime, timezone

from nwqlib import Expectation, plan
from nwqlib.algorithms import ExpectationMethod
from nwqlib.backends import (
    AER_STATEVECTOR_TARGET, Allocation, DeviceConfiguration, DeviceProfile,
    ModelDomain, TimeCoefficient, TimeModel, assess,
)
from nwqlib.core import Limit, Source, Unit
from nwqlib.evidence import Evidence
from nwqlib.operators import ingest_pauli
from nwqlib.problems.inputs import ingest_occupation

problem = Expectation(state=ingest_occupation("1", num_qubits=1),
                      observable=ingest_pauli((("Z", 1.0),), num_qubits=1))
selected = plan(problem, method=ExpectationMethod(preparation_choice="hzh"),
                seed=7)

source = Source(name="example profile", version="1",
                domain="synthetic numbers, not a measured machine",
                reference="api/backends.md")
start = datetime(2026, 1, 1, tzinfo=timezone.utc)
end = datetime(2027, 1, 1, tzinfo=timezone.utc)
target = AER_STATEVECTOR_TARGET  # NWQLib's declared Aer statevector target
machine = DeviceConfiguration(
    name="example machine", version="1", target=target, hardware=source,
    runtime=Source(name=target.name, version="1", domain="example runtime",
                   reference="api/backends.md"),
    build=source, compiler=source, precision="complex128",
    representation="statevector")
spec = Evidence(kind="external_specification", source=source)
grant = Allocation(
    name="example grant", configuration_id=machine.content_id,
    locations=("logical_device",), topology="single_device",
    limits=(Limit(stage="execution", metric="memory",
                  unit=Unit(symbol="byte", dimension="bytes"),
                  kind="capacity_stock", value=2**30,
                  scope="logical_device"),),
    recorded_at=start, valid_until=end, evidence=spec)
domain = ModelDomain(
    configuration_id=machine.content_id, allocation_id=grant.content_id,
    basis="selected_logical", batch_schedule="unspecified",
    acquisition="direct_observation", runtime="seed_independent",
    population="unconditional", readouts=("pauli_expectation",),
    selection_ids=(), primitive_gates=("h", "z"),
    min_qubits=1, max_qubits=1, min_operations=0, max_operations=10,
    max_shots=0, max_exact_evaluations=1, max_readout_items=1,
    max_resets=0, max_measurements=0, max_classical_work=0,
    max_adaptive_rounds=0)
model = TimeModel(
    name="example timing", kind="engineering",
    scope="selected_acquisition",
    coefficients=(
        TimeCoefficient(feature="invocations", seconds_per_unit=0.25,
                        unit="s/invocation"),
        TimeCoefficient(feature="exact_evaluations", seconds_per_unit=0.5,
                        unit="s/exact_evaluation"),
        TimeCoefficient(feature="logical_operations", seconds_per_unit=0.125,
                        unit="s/logical_operation")),
    domain=domain, recorded_at=start, valid_until=end,
    evidence=Evidence(kind="numerical_estimate", source=source),
    assumptions=("synthetic coefficients for this example",))
profile = DeviceProfile(configuration=machine, recorded_at=start,
                        valid_until=end, evidence=spec, models=(model,))

forecast = assess(selected, selected.resolve("expectation"),
                  profile=profile, allocation=grant,
                  assessed_at=datetime(2026, 6, 1, tzinfo=timezone.utc))
print(forecast.time.status)                  # conditional
print(forecast.predictions[0].seconds.value)  # 1.125

The machine's target is a BackendTarget, here the built-in AER_STATEVECTOR_TARGET for exact readouts. An engineering model's prediction is conditional on its stated assumptions. The profiles guide defines the five axes, the memory comparison and the time models.

DeviceProfile

Bases: Record

A supplied description of one machine: its configuration, advertised limits and named time models.

Build it with keyword arguments, for example DeviceProfile(configuration=..., recorded_at=..., valid_until=..., evidence=..., models=(model,)), and pass it as profile= to nwqlib.estimate, nwqlib.compare or assess. configuration, recorded_at, valid_until and evidence are required. The profile is data the caller supplies. NWQLib never discovers a machine or refreshes a profile. New calibration makes a new profile with a new content hash, so an earlier assessment is never rewritten. The profiles guide explains the assessment, and the example under Forecast cost and feasibility builds a small profile.

Attributes:

  • configuration (DeviceConfiguration) –

    Required. The DeviceConfiguration.

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

    Default (). Advertised limits as Limit records, at most one per stage, metric and scope.

  • recorded_at (Timestamp) –

    Required. Time zone-aware time the profile was recorded, stored in UTC.

  • valid_until (Timestamp) –

    Required. Time zone-aware end of validity, not before recorded_at.

  • evidence (Evidence) –

    Required. The specification the profile rests on, not a record of an execution.

  • models (tuple[TimeModel, ...]) –

    Default (). TimeModel records with distinct names.

Raises:

  • ValueError –

    If valid_until precedes recorded_at, two limits share a stage, metric and scope, or two models share a name.

DeviceConfiguration

Bases: Record

The machine a device profile describes: target, hardware, runtime, build, compiler and numerical precision.

Build it with keyword arguments and pass it as configuration= to DeviceProfile. name, version, target, hardware, runtime and build are required. Its content hash (content_id) is what an Allocation and a ModelDomain name as their configuration_id, so a time model can refer to the machine without referring to the profile that contains it. An optional field left None stays unknown in an assessment.

Attributes:

  • name (Text) –

    Required. Name of the machine specification.

  • version (Text) –

    Required. Version of the machine specification.

  • target (BackendTarget) –

    Required. The backend target the machine supports, the same target record that backend adapters declare.

  • hardware (Source) –

    Required. Source describing the hardware.

  • runtime (Source) –

    Required. Source of the intended runtime. Its name must equal target.name. It describes what preparation is expected to use, not an observed preparation record.

  • build (Source) –

    Required. Source of the implementation and build configuration.

  • compiler (Source | None) –

    Default None. Source of the intended compiler.

  • precision (Literal['complex64', 'complex128', 'float64'] | None) –

    Default None. "complex64", "complex128" or "float64".

  • representation (Literal['statevector', 'density_matrix', 'tensor', 'hardware', 'classical'] | None) –

    Default None. "statevector", "density_matrix", "tensor", "hardware" or "classical".

Raises:

  • ValueError –

    If runtime.name differs from target.name.

BackendTarget

Bases: Record

What a simulator, cloud provider or export target supports, for profile assessment.

Pass it as target= to a DeviceConfiguration. Start from a built-in target such as AER_STATEVECTOR_TARGET and change fields with revise, or build one with keyword arguments, for example BackendTarget(name="my_target", provider="my_provider"). name and provider are required. For each optional collection, None means unknown and an empty tuple means none, so profile assessment can tell an undeclared subset from an unsupported one. A coarse capability never certifies a readout or instruction that the target does not list. The profiles guide shows how these declarations decide the capability check.

Attributes:

  • name (Text) –

    Required. Backend or target name.

  • provider (Text) –

    Required. Provider family, such as "qiskit_aer" or "ionq".

  • capabilities (tuple[BackendCapability, ...] | None) –

    Default None, unknown. Coarse execution capabilities among "statevector", "counts", "expectation", "estimated_observable", "qasm_export", "hardware_submit", "noise_model", "native_gate_target" and "host_kernel".

  • description (str) –

    Default "". Text for reports.

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

    Default (). Native or preferred basis gates when known, in the given order.

  • max_qubits (Count | None) –

    Default None. Advertised or configured qubit limit.

  • artifacts (tuple[Text, ...] | None) –

    Default None, unknown. Accepted input forms, such as "selected_construction" (a Plan's construction), which profile assessment requires.

  • readouts (tuple[Literal['pauli_expectation', 'counts', 'probabilities', 'host_scalars', 'amplitudes', 'estimated_observable', 'trajectory'], ...] | None) –

    Default None, unknown. Supported observation kinds among "pauli_expectation", "counts", "probabilities", "host_scalars", "amplitudes", "estimated_observable" and "trajectory", declared separately from capabilities. "trajectory" is the exact schedule with several observation points, and each point also needs its own readout kind listed.

  • readout_features (tuple[Literal['multi_position', 'views'], ...] | None) –

    Default None, unknown. Trajectory features the target executes: "multi_position" (several observation points of one coherent state in one execution) and "views" (reversible basis changes before a Pauli or probability point, undone exactly afterwards).

  • reducers (tuple[Text, ...] | Literal['registered'] | None) –

    Default None, unknown. The registered reducers that the target runs at a trajectory point, which turn a saved state into statistics during execution: a tuple of reducer names, or "registered" for every reducer in nwqlib.core.planning.READOUT_REDUCERS.

  • host_dependencies (tuple[Text, ...] | None) –

    Default None, unknown. Packages available to classical routines on this target. Profile assessment requires every dependency that a chosen routine declares to be listed.

  • instructions (tuple[InstructionSupport, ...] | None) –

    Default None, unknown. Exact instruction subset, including controls and adjoints, as InstructionSupport records, each naming one primitive gate or one implementation Source and its width.

  • program_nodes (tuple[Text, ...] | None) –

    Default None, unknown. Supported Program node kinds.

Raises:

  • ValueError –

    If a collection declares a value twice.

InstructionSupport

Bases: Record

One primitive gate or circuit-block implementation that a backend target supports, with its control, adjoint and width.

Build it with keyword arguments and list it in BackendTarget.instructions. Each entry names exactly one of primitive and implementation. Profile assessment counts a circuit block of a Plan as supported when entries with the block's controlled and adjoint form either name the block's exact implementation Source with a max_qubits of at least the block's width, or name every primitive gate of the block's decomposition, each with a max_qubits of at least the gate's width plus one for a controlled block. An entry with only the same implementation name does not match.

Attributes:

  • primitive (Literal['x', 'h', 'z', 'sdg', 'cx', 'mc_z', 'phase'] | None) –

    Default None. Primitive gate among "x", "h", "z", "sdg", "cx", "mc_z" and "phase".

  • implementation (Source | None) –

    Default None. The implementation Source of a circuit block's SelectedDefinition.

  • controlled (StrictBool) –

    Default False. Whether the entry covers the controlled form instead of the uncontrolled one.

  • adjoint (StrictBool) –

    Default False. Whether the entry covers the adjoint form instead of the original one.

  • max_qubits (Count) –

    Required. Largest supported instruction width, controls included.

Raises:

  • ValueError –

    If both or neither of primitive and implementation are given.

AER_STATEVECTOR_TARGET

AER_STATEVECTOR_TARGET = BackendTarget(name='aer_statevector', provider='qiskit_aer', capabilities=(BackendCapability.STATEVECTOR,), description='Qiskit Aer exact statevector simulator.', readouts=('pauli_expectation', 'probabilities', 'amplitudes', 'trajectory'), readout_features=('multi_position', 'views'), reducers='registered')

Built-in target of the Qiskit Aer statevector simulator, for exact readouts.

It declares the statevector capability and the readouts pauli_expectation, probabilities, amplitudes and trajectory, with the trajectory features multi_position and views and every registered reducer. It leaves artifacts, instructions and program_nodes unknown. The capability checks that read these fields report "unknown", so the capability axis of an assessment with this target cannot be "feasible" until revise declares them. Use it as DeviceConfiguration(target=...) for exact readouts, and use AER_COUNTS_TARGET for sampled shots. It is a fixed declaration that imports no SDK, not a description of a live device.

AER_COUNTS_TARGET

AER_COUNTS_TARGET = BackendTarget(name='aer_counts', provider='qiskit_aer', capabilities=(BackendCapability.COUNTS, BackendCapability.NOISE_MODEL), description='Qiskit Aer finite-shot measured circuit simulator.', readouts=('counts',))

Built-in target of the Qiskit Aer simulator with measured shots.

It declares the counts and noise_model capabilities and the counts readout. It leaves readout_features, reducers, artifacts, instructions and program_nodes unknown. The capability checks that read these fields report "unknown", so the capability axis of an assessment with this target cannot be "feasible" until revise declares them. Use it as DeviceConfiguration(target=...) for a Plan with sampled shots. It is a fixed declaration that imports no SDK, not a description of a live device.

TimeModel

Bases: Record

A named linear model of time in seconds, the sum of coefficient times feature count, for one scope.

Build it with keyword arguments and pass it in models= of DeviceProfile. Every field except calibration and uncertainty is required. The model is

seconds = c_invocation * invocations + c_shot * sampled_shots
        + c_exact * exact_evaluations + c_operation * logical_operations

over the feature counts of the resource estimate, so it is evaluated without running anything (Finite time models). An engineering model states assumed coefficients and gives conditional numbers under its assumptions. A calibrated model keeps its supplied calibration sources and uncertainty unchanged. Neither kind collects calibration data. An expired, future-dated or out-of-domain model gives an unavailable prediction with its reason.

Attributes:

  • name (Text) –

    Required. Model name, unique within the profile.

  • kind (Literal['engineering', 'calibrated']) –

    Required. "engineering" for assumed coefficients or "calibrated" for coefficients from a supplied calibration.

  • scope (TimeScope) –

    Required. What the seconds cover: "selected_acquisition" (the seconds of the measurement that the Plan chose), "acquisition_overhead" (the seconds of overhead beyond that measurement) or "native_call_wall". The library's own timings carry only "native_call_wall". The first two are scopes that a supplied profile declares for its coefficients, and they exclude planning, compilation, queue delay, analysis and whole-run cost. "native_call_wall" covers the synchronous backend call, including waiting and result extraction, and excludes preparation and saving. The scopes overlap, so their predictions must not be added, and none covers a whole run.

  • coefficients (tuple[TimeCoefficient, ...]) –

    Required. One to four TimeCoefficient records with distinct features.

  • domain (ModelDomain) –

    Required. The ModelDomain of workloads the model is valid for.

  • recorded_at (Timestamp) –

    Required. Time zone-aware time the model was recorded, stored in UTC.

  • valid_until (Timestamp) –

    Required. Time zone-aware end of validity, not before recorded_at.

  • evidence (Evidence) –

    Required. Evidence of kind "numerical_estimate" for an engineering model or "empirical_prediction" for a calibrated one.

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

    Required. At least one stated assumption.

  • calibration (CalibrationReference | None) –

    Default None. The CalibrationReference, required for a calibrated model and not allowed for an engineering one.

  • uncertainty (ModelUncertainty | None) –

    Default None. The ModelUncertainty, required for a calibrated model.

Raises:

  • ValueError –

    If valid_until precedes recorded_at, a feature repeats, calibration does not match kind, the evidence kind does not match kind, or a calibrated model has no uncertainty.

TimeCoefficient

Bases: Record

One coefficient of a linear time model: seconds per invocation, shot, exact evaluation or logical operation.

Build it with keyword arguments, for example TimeCoefficient(feature="sampled_shots", seconds_per_unit=0.001, unit="s/shot"), and pass it in coefficients= of TimeModel. Every field is required. The unit is kept exactly as supplied and never converted. A zero coefficient states that the feature contributes nothing. A feature left out adds no term either, but the model then makes no statement about its coefficient.

Attributes:

  • feature (TimeFeature) –

    Required. "invocations", "sampled_shots", "exact_evaluations" or "logical_operations".

  • seconds_per_unit (Nonnegative) –

    Required. Nonnegative coefficient in unit.

  • unit (Literal['s/invocation', 's/shot', 's/exact_evaluation', 's/logical_operation']) –

    Required. The one unit of the feature: "s/invocation", "s/shot", "s/exact_evaluation" or "s/logical_operation" respectively.

Raises:

  • ValueError –

    If unit is not the unit of feature.

ModelDomain

Bases: Record

The workloads a time model is valid for: machine, allocation, readout, operation mix and size ranges.

Build it with keyword arguments and pass it as domain= to TimeModel. Every field except rotation_precision, synthesis and bindings is required. An assessment evaluates the model only for a workload inside every range and list here, and reports the prediction as unavailable otherwise. The record selects, fits and extrapolates nothing. An empty list of selections or gates supports none, never any. Size ranges are inclusive, and max_resets, max_measurements, max_classical_work and max_adaptive_rounds each give the inclusive range from 0 to the maximum. A model calibrated without resets, for example, does not apply once resets are added, even when the gate counts match. basis, rotation_precision, synthesis and batch_schedule must equal the basis, precision, synthesis and batch_schedule of the ResourceContext of the estimate. The time-model section of the profiles guide lists every domain check.

Attributes:

  • configuration_id (ContentID) –

    Required. content_id of the DeviceConfiguration: hardware, runtime, build, precision and target.

  • allocation_id (ContentID) –

    Required. content_id of the Allocation: every granted location, limit and topology.

  • basis (MetricBasis) –

    Required. Gate basis in which logical operations are counted: "selected_logical", "cx", "clifford_t" or "toffoli".

  • rotation_precision (Float64 | None) –

    Default None. Positive rotation-synthesis precision the operation counts assume.

  • synthesis (Source | None) –

    Default None. Source of the synthesis rule the operation counts assume.

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

    Required. "unspecified" or "serial".

  • acquisition (Literal['direct_observation', 'measurement_batch']) –

    Required. "direct_observation" for an experiment without a measurement batch, or "measurement_batch" for an experiment with one.

  • runtime (RuntimeOptions | Literal['seed_independent']) –

    Required. The runtime seed the model was measured with, as RuntimeOptions(seed=...), or "seed_independent". A whole-Plan forecast does not guess future seeds, so only a seed-independent model applies there.

  • population (Literal['unconditional', 'native_conditioned']) –

    Required. Whether a measurement or reset before the readout conditions the read state, "unconditional" or "native_conditioned", which must equal the population of the assessed point's readout.

  • readouts (tuple[Literal['pauli_expectation', 'counts', 'probabilities', 'host_scalars', 'amplitudes', 'estimated_observable'], ...]) –

    Required. Distinct supported readouts: "pauli_expectation", "counts", "probabilities", "host_scalars", "amplitudes" or "estimated_observable".

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

    Required. Distinct content hashes of the supported block selections. A planned block that is controlled, adjoint or has no gate decomposition is inside the domain only when its content hash is listed here. Other blocks are checked gate by gate against primitive_gates.

  • primitive_gates (tuple[Literal['x', 'h', 'z', 'sdg', 'cx', 'mc_z', 'phase'], ...]) –

    Required. Distinct supported primitive gates: "x", "h", "z", "sdg", "cx", "mc_z" or "phase".

  • min_qubits (Count) –

    Required. Smallest supported qubit count.

  • max_qubits (Count) –

    Required. Largest supported qubit count, at least min_qubits.

  • min_operations (Count) –

    Required. Smallest supported logical operation count.

  • max_operations (Count) –

    Required. Largest supported logical operation count, at least min_operations.

  • max_shots (Count) –

    Required. Largest supported shot count.

  • max_exact_evaluations (Count) –

    Required. Largest supported number of exact evaluations.

  • max_readout_items (Count) –

    Required. Largest supported number of returned readout items.

  • max_resets (Count) –

    Required. Largest supported reset count.

  • max_measurements (Count) –

    Required. Largest supported measurement count.

  • max_classical_work (Count) –

    Required. Largest supported classical_work count of the resource estimate.

  • max_adaptive_rounds (Count) –

    Required. Largest supported number of adaptive rounds.

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

    Default (). Parameter values the model is restricted to, at most one per parameter.

Raises:

  • ValueError –

    If a minimum exceeds its maximum, rotation_precision is not positive, or a binding, readout, selection or gate is repeated.

ModelUncertainty

Bases: Record

The supplied uncertainty of a time model, as an additive interval in seconds around its prediction.

Build it with keyword arguments, for example ModelUncertainty(kind="future_run_prediction", lower_residual_seconds=-0.25, upper_residual_seconds=0.5, coverage=0.9, source=...), and pass it as uncertainty= to TimeModel. Every field except coverage is required, and coverage is required for the two statistical kinds. The residuals are added to the central prediction prediction, with the lower endpoint clipped at zero, so the example gives the interval [max(0, prediction - 0.25), prediction + 0.5] seconds. The interval keeps the meaning its source states and is never an execution guarantee.

Attributes:

  • kind (Literal['future_run_prediction', 'sample_mean_confidence', 'model_error_envelope']) –

    Required. "future_run_prediction" concerns one future run. "sample_mean_confidence" concerns a mean and does not bound an individual run. "model_error_envelope" states an engineering uncertainty without a probability.

  • lower_residual_seconds (Real) –

    Required. Zero or negative residual in seconds.

  • upper_residual_seconds (Nonnegative) –

    Required. Nonnegative residual in seconds.

  • coverage (Real | None) –

    Default None. Probability in (0, 1] that the interval holds, required for "future_run_prediction" and "sample_mean_confidence" and not allowed for "model_error_envelope", because a coverage would claim more than an engineering uncertainty supports.

  • source (Source) –

    Required. Source of the stated interval.

Raises:

  • ValueError –

    If coverage is missing for a statistical kind or given for "model_error_envelope".

CalibrationReference

Bases: Record

Where a calibrated time model's coefficients came from: training data, validation data and validation errors.

Build it with keyword arguments and pass it as calibration= to TimeModel. Every field is required. Each Source names the exact data or procedure version. NWQLib never opens or fetches a referenced source. A parent_id, the content hash of the record a record was revised from, does not establish which workloads trained the model.

Attributes:

  • source (Source) –

    Required. Source of the calibration procedure.

  • training (Source) –

    Required. Source of the training workloads.

  • validation (Source) –

    Required. Source of the held-out validation workloads.

  • validation_errors (Source) –

    Required. Source of the held-out error report.

Allocation

Bases: Record

The resources granted to one workload: locations, their placement and their capacity limits.

Build it with keyword arguments, for example Allocation(name=..., configuration_id=configuration.content_id, locations=("logical_device",), topology="single_device", limits=(...), recorded_at=..., valid_until=..., evidence=...), and pass it as allocation= to nwqlib.estimate, nwqlib.compare or assess. Every field is required. The record states a grant that the caller supplies. NWQLib never queries a scheduler or device for it, and it never configures ranks, threads or devices. Capacities are never pooled across locations. For example, two 8-GiB devices cannot hold a 10-GiB peak on one device. The device-domain section of the profiles guide explains how capacities are compared.

Attributes:

  • name (Text) –

    Required. Name of the grant.

  • configuration_id (ContentID) –

    Required. content_id of the DeviceConfiguration the grant is for. An assessment applies the grant's limits only when it matches the profile's configuration.

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

    Required. Distinct names of the granted locations, the names the Program's registers and workspaces use, such as "logical_device".

  • topology (Literal['single_device', 'independent_devices', 'distributed'] | None) –

    Required. "single_device" (exactly one location), "independent_devices", "distributed", or None when the placement is unknown.

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

    Required. Capacity, consumption and deadline limits as Limit records, at most one per stage, metric and scope. A limit of kind "capacity_stock" names exactly one granted location as its scope.

  • recorded_at (Timestamp) –

    Required. Time zone-aware time the grant was recorded, stored in UTC.

  • valid_until (Timestamp) –

    Required. Time zone-aware end of the grant's validity, not before recorded_at.

  • evidence (Evidence) –

    Required. Evidence describing the grant, not its use.

Raises:

  • ValueError –

    If the locations are empty or repeated, "single_device" has more than one location, two limits share a stage, metric and scope, a "capacity_stock" limit names a location outside the grant, or valid_until precedes recorded_at.

assess

assess(plan: Plan, realization: Realization, *, profile: DeviceProfile, allocation: Allocation, context: ResourceContext | None = None, runtime: RuntimeOptions | None = None, assessed_at: datetime | None = None, accuracy: Accuracy | None = None, facts: tuple[FramedFact, ...] = (), reference: TargetReference | None = None, max_assessments=4096) -> ProfileAssessment

Forecast one resolved point of a Plan on a device profile and allocation, without running anything.

nwqlib.estimate(plan, profile=..., allocation=...) assesses every point of the Plan whose parameters are fixed. Call assess for one point, for example the point that plan.resolve(experiment_name) returns. The result reports five independent axes: applicability, capability, capacity, time and accuracy. Each axis has the status "feasible", "infeasible", "conditional" or "unknown", and a failure on one axis, such as memory, does not hide what another supports, such as an error bound. Time predictions rest on the supplied coefficients, so none is an execution guarantee. No pilot run, profile refresh, circuit compilation or replay of the computation takes place. The profiles guide defines the axes, and Forecast cost and feasibility assesses a one-qubit Plan.

Parameters:

  • plan (Plan) –

    The Plan whose point is assessed.

  • realization (Realization) –

    One resolved point of plan, such as plan.resolve(experiment_name).

  • profile (DeviceProfile) –

    The device profile.

  • allocation (Allocation) –

    The resources granted to the workload.

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

    Resource-counting context, such as the gate basis. None uses ResourceContext().

  • runtime (RuntimeOptions | None, default: None ) –

    Backend seed of an already known preparation. With None, only seed-independent models apply. Seeds are never guessed.

  • assessed_at (datetime | None, default: None ) –

    Time zone-aware assessment time, against which the validity of the profile, allocation and models is checked. None records the current UTC time once.

  • accuracy (Accuracy | None, default: None ) –

    Accuracy criterion to assess. None uses the Plan's selection_accuracy, and with neither the accuracy axis is unknown. Another criterion changes only this assessment, never the Plan's shots or choices.

  • facts (tuple[FramedFact, ...], default: () ) –

    Supplied error facts, passed unchanged to the Plan's error model. A fact for one point cannot cover another.

  • reference (TargetReference | None, default: None ) –

    Supplied reference value, passed unchanged to the Plan's error model.

  • max_assessments (int, default: 4096 ) –

    Positive limit on assessment and prediction rows, here one plus the number of time models, checked before any model is evaluated.

Returns:

  • assessment ( ProfileAssessment ) –

    The forecast. Its predictions hold the time forecasts in seconds, its capacity the memory comparison and its error the complete accuracy assessment.

Raises:

  • TypeError –

    If profile is not a DeviceProfile or accuracy is not an Accuracy.

  • ValueError –

    If the rows exceed max_assessments, or the stored records do not match the Plan, profile and allocation.

PlanEstimate

Bases: Record

The resource estimate of a whole Plan with the device forecasts of its resolved points.

nwqlib.estimate(plan, profile=profile, allocation=allocation) returns it. Without a profile and allocation, estimate returns the WorkloadEstimate alone. The fields below are read-only. All assessments share one assessment time. Points that an adaptive method has not chosen yet, and points along a range axis that is not expanded, are listed in unpredicted instead of being guessed. When a Run is prepared from a compare or scan row that holds this estimate, as prepare(row, ...), each submission looks up the forecast of its own point, and later timings can be compared with it by align_telemetry.

Attributes:

assessment_for

assessment_for(plan, receipt)

Return this estimate's forecast for a prepared circuit's point, or None, without evaluating anything.

The forecast is checked against the Plan once per estimate, and against the preparation record each time.

Parameters:

  • plan (Plan) –

    The Plan this estimate belongs to.

  • receipt (PreparedArtifact) –

    The preparation record of one prepared circuit.

Returns:

  • assessment ( ProfileAssessment | None ) –

    The forecast of that circuit's point, or None when the estimate has no forecast for it.

Raises:

  • ValueError –

    If the estimate belongs to another Plan, or the forecast does not match the preparation record.

ProfileAssessment

Bases: Record

The forecast of one resolved point of a Plan on a device profile: five independent axes and the time predictions.

A point is the Realization that plan.resolve(experiment, bindings=...) returns.

assess returns it, and PlanEstimate.assessments holds one per point. The fields below are read-only. Each axis is an AxisAssessment whose status summarizes its own details only, so a memory failure cannot hide a supported error bound. No conclusion grants permission to run, configures a backend or changes the computation. A sum of error bounds above the threshold leaves error INCONCLUSIVE and is not evidence that the error exceeds the tolerance.

Attributes:

  • point (AssessmentPoint) –

    Content hashes of the inputs: problem, Plan, point, base and selected construction, resource estimate and context, profile, allocation, expected runtime and compiler sources, known runtime seed, and the assessment time.

  • realization (Realization) –

    The resolved point, with its parameter bindings.

  • resources (WorkloadEstimate) –

    Resource estimate of this point. Capability, capacity and time read the same counts.

  • applicability (AxisAssessment) –

    Whether a stated assumption of the method holds for this problem. The built-in Methods record no such statement, so this axis is unknown, or conditional when the Plan lists assumptions or requirements.

  • capability (AxisAssessment) –

    Whether the target supports the point's circuit form, Program nodes, readout, instructions, classical routine and control or adjoint use.

  • capacity (AxisAssessment) –

    Whether each granted location holds the point's simultaneous memory and storage peaks and its known lower requirements.

  • time (AxisAssessment) –

    The time-model predictions and the matching time limits.

  • accuracy (AxisAssessment) –

    The Plan's error-model assessment of criterion.

  • frame (ErrorFrame) –

    The ErrorFrame of the Plan's output, in which error is stated.

  • criterion (Accuracy | None) –

    The Accuracy criterion assessed, or None.

  • error (ClaimAssessment | None) –

    The complete ClaimAssessment of criterion, or None without a criterion or error model. Before execution it names no observation or result.

  • predictions (tuple[TimePrediction, ...]) –

    One TimePrediction per time model of the profile, in the profile's order.

AxisAssessment

Bases: Record

One axis of a device forecast: its status and every fact behind it.

Read it from the applicability, capability, capacity, time and accuracy fields of a ProfileAssessment. The fields below are read-only. The status summarizes the details of this axis only. A known failure ("infeasible") decides the axis. Otherwise any "conditional" detail makes it conditional, then any "unknown" detail makes it unknown, and it is "feasible" only when every detail is.

Attributes:

  • axis (Axis) –

    "scientific_applicability", "execution_capability", "capacity_materialization", "time_cost" or "accuracy_evidence".

  • status (Outcome) –

    "feasible", "infeasible", "conditional" or "unknown".

  • details (tuple[AssessmentDetail, ...]) –

    The AssessmentDetail records, partial knowledge included.

AssessmentDetail

Bases: Record

One scoped conclusion of a device forecast, with the value and limit it compares.

Read it from AxisAssessment.details. The fields below are read-only. A detail holds either a resource value (fact) or a method statement (statement), never both, because they are different quantities.

Attributes:

  • quantity (Text) –

    The quantity compared, such as a memory peak.

  • scope (Text) –

    Where the quantity applies, such as one granted location.

  • status (Outcome) –

    "feasible", "infeasible", "conditional" or "unknown".

  • reason (Text) –

    Why the detail has its status.

  • fact (Fact | None) –

    The resource value compared, or None.

  • resource_id (ContentID | None) –

    Content hash of the resource quantity in the estimate, or None.

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

    Content hashes of the time predictions this detail summarizes.

  • limit (Limit | None) –

    The supplied Limit it was compared with, unchanged, or None.

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

    Content hashes of the declarations and records used.

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

    Assumptions the conclusion rests on.

  • statement (FramedFact | None) –

    The method's complete stated assumption or claim, or None.

TimePrediction

Bases: Record

The prediction of one time model for one point, in seconds, with its interval and the feature counts it used.

Read it from ProfileAssessment.predictions. The fields below are read-only. The answer is seconds.value, a prediction for the model's scope, not an observed elapsed time and not permission to run. When an input is missing, seconds is None and reasons says why. An interval keeps the kind and coverage of the model's uncertainty, so a confidence interval for a mean never becomes a bound on a single run.

Attributes:

  • model_id (ContentID) –

    Content hash of the time model.

  • point_id (ContentID) –

    Content hash of the assessed point.

  • scope (TimeScope) –

    The model's time scope, copied from the model.

  • seconds (Float64 | None) –

    Nonnegative predicted seconds, or None when unavailable.

  • unit (Unit) –

    Seconds.

  • lower_seconds (Float64 | None) –

    Lower end of the interval, at least zero, or None.

  • upper_seconds (Float64 | None) –

    Upper end of the interval, or None.

  • uncertainty (ModelUncertainty | None) –

    The model's ModelUncertainty, or None.

  • features (tuple[Fact, ...]) –

    The feature counts the prediction used.

  • evidence (Evidence) –

    Evidence that names the model's source.

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

    Why the prediction is unavailable. Empty when it is available.

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

    Assumptions the prediction rests on.

Compare forecasts with observed timings

A Run carries a forecast when prepare receives a ComparisonRow whose estimate is a PlanEstimate, for example a row of compare(problem, methods=..., profile=..., allocation=...). After such a Run finishes, align_telemetry(run) pairs each attempt's forecast with its observed timing.

align_telemetry

align_telemetry(run_or_result=None, *, trace: ExecutionTrace | None = None, assessments: tuple[ProfileAssessment, ...] = (), receipts: tuple[PreparedArtifact, ...] = (), observations: ObservationView | None = None, timings: tuple[AttemptTiming, ...] = (), result: Record | None = None, max_comparisons: int = 100000) -> PredictionLedger

Pair the forecasts of a Run with its observed timings and return the signed residuals.

Pass a Run or a completed Result, for example align_telemetry(run), to read its execution record, preparation records, observations and the forecast it was prepared with. The returned PredictionLedger keeps every attempt, failures and partial collections included. A residual observed_seconds - predicted_seconds is formed only when the attempt was bound to its forecast before it started, its data collection completed, and an exact timing of the forecast's scope exists. Every other attempt keeps its forecast with the reason it has no residual, so a runtime or compiler mismatch, a missing scope or preparation record, a failed collection or a right-censored timing stays visible. A right-censored timing is a lower bound, never an exact residual. Nothing is executed, assessed again or fitted, no provider is contacted, and no histogram or backend payload is copied into it. A residual makes no coverage claim, and a historical residual does not establish that the device calibration was valid when the job ran. The telemetry section of the profiles guide describes the pairing rules.

Parameters:

  • run_or_result (Run | Result | None, default: None ) –

    The Run or Result to read. With None, pass trace and the other records explicitly.

  • trace (ExecutionTrace | None, default: None ) –

    Execution record, when no Run or Result is given.

  • assessments (tuple[ProfileAssessment, ...], default: () ) –

    Forecasts to pair. Empty uses the forecast the Run was prepared with.

  • receipts (tuple[PreparedArtifact, ...], default: () ) –

    Preparation records, when no Run or Result is given.

  • observations (ObservationView | None, default: None ) –

    Observations, when no Run or Result is given.

  • timings (tuple[AttemptTiming, ...], default: () ) –

    Additional supplied timings. Each must belong to an attempt of this run. Identical timings of one attempt count once, and different attempts stay distinct.

  • result (Record | None, default: None ) –

    The analysis Result, when no Run or Result is given. Each row records which collected observations the Result used.

  • max_comparisons (int, default: 100000 ) –

    Positive limit on the forecast and timing pairs formed.

Returns:

Raises:

  • TypeError –

    If no execution record or RunData is available.

  • ValueError –

    If a Run or Result is mixed with explicit records, a timing or record belongs to another run, attempt or Plan, content hashes conflict, or the pairs exceed max_comparisons.

PredictionLedger

Bases: Record

The forecasts of one Run paired with its observed timings, attempt by attempt.

align_telemetry returns it. The fields below are read-only. Each row holds one attempt's execution event, its timings, the observations it collected and its forecast comparisons, where residual_seconds is the signed observed - predicted seconds or None with the reasons. Collected observations and the contributions of the Result stay separate lists. Use revise to record a new version of supplied data. Neither PredictionLedger nor revise fits coefficients or changes the original assessments, model domains, calibration status or coverage. A forecast is valid at its original assessment time, and a historical residual does not establish that calibration was valid when the job ran.

Attributes:

  • trace_id (ContentID) –

    Content hash of the Run's execution record.

  • run_id (Text) –

    ID of the Run.

  • plan_id (ContentID) –

    Content hash of the Plan.

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

    Content hashes of the forecasts used.

  • predictions (tuple[TimePrediction, ...]) –

    The original TimePrediction records.

  • rows (tuple[TelemetryRow, ...]) –

    One row per attempt, failures, partial collections and right-censored timings included. Each row has event (the attempt's execution event), timings, collected_observation_ids, contribution_ids (the collected observations that the Result used), comparisons and reasons. Each comparison has prediction_id, timing_id, residual_seconds (observed minus predicted seconds, or None) and reasons.

  • result_id (ContentID | None) –

    Content hash of the analysis Result, or None. It does not imply that the Result is scientifically valid.

validate_context

validate_context(*, trace, assessments)

Check that a saved PredictionLedger still matches its execution record and forecasts, without recomputing anything.

Parameters:

  • trace (ExecutionTrace) –

    The Run's execution record, run.data.trace.

  • assessments (tuple[ProfileAssessment, ...]) –

    The forecasts the record used, for example run.data.forecast.assessments.

Returns:

Raises:

  • ValueError –

    If the record differs from the execution record, uses a forecast of another Plan or attempt, or changed its predictions.

AttemptTiming

Bases: Record

A timing that the caller measured for one attempt of a Run, to pair with its forecast.

Build it with keyword arguments, for example AttemptTiming(run_id=..., attempt=..., prepared_id=..., timing=...), and pass it in timings= of align_telemetry. Every field is required. The timing is either an exact duration or a right-censored lower bound, with its source. Distinct attempts stay distinct even when their timings agree.

Attributes:

  • run_id (Text) –

    Required. ID of the Run.

  • attempt (Text) –

    Required. ID of the attempt, the attempt of one event in run.data.trace.events.

  • prepared_id (ContentID) –

    Required. Content hash of the preparation record the attempt used, the prepared_id of that event.

  • timing (TimingObservation) –

    Required. A nwqlib.execution.TimingObservation with scope (a TimeModel scope), seconds (nonnegative), censoring ("exact", the default, or "right_censored"), source (a Source) and reason (required for "right_censored", the reason for the cutoff).

TimingObservation

Bases: Record

A measured duration in seconds for one time scope, or a lower bound on it.

The caller supplies one as AttemptTiming.timing to compare with a forecast. A Run records one in the timing field of the event (in run.data.trace.events) of each synchronous backend call or classical computation, an exact duration with scope "native_call_wall". The record is independent of whether the event succeeded and of whether its output is valid.

Attributes:

  • scope (TimeScope) –

    What the seconds cover, one of the scopes of TimeModel: "selected_acquisition", "acquisition_overhead" or "native_call_wall".

  • seconds (Nonnegative) –

    Nonnegative duration in seconds.

  • censoring (Literal['exact', 'right_censored']) –

    Default "exact", an observed duration, possibly the time until a failure. "right_censored" is a lower bound for a target that was still running at the cutoff. It is never an exact residual or a coverage claim.

  • source (Source) –

    Source of the measurement.

  • reason (Text | None) –

    Default None. Required for "right_censored": the reason for the cutoff.

Export OpenQASM

export_qasm converts any Qiskit circuit to OpenQASM 3 or 2. write_qasm3_file and write_qasm3 write a Plan's circuit (plan.construction) as OpenQASM 3 without a quantum SDK, for the constructions listed in Export OpenQASM, and materialize_qasm3_file imports such a file back into Qiskit after checking its bytes.

export_qasm

export_qasm(circuit: QuantumCircuit, *, format: str = 'qasm3', path: str | Path | None = None, max_text_bytes: int = DEFAULT_MAX_BYTES, max_operations: int = 100000) -> str | Path

Return the OpenQASM 3 or 2 text of a Qiskit circuit, or write it to a file.

Use it for any built Qiskit circuit, for example one from prepared.circuit(0) or lower_qiskit. Without path it returns the text. With path it writes a temporary file in the same directory and replaces the destination only after the export succeeds, so a failed export leaves an earlier file unchanged. It does not transpile or simulate. Qiskit's OpenQASM 3 exporter streams the text but still builds a complete syntax tree, and its OpenQASM 2 exporter builds the whole string first, so for OpenQASM 2 max_text_bytes limits only the returned or written text. Neither limit bounds expanded gate definitions or Qiskit's workspace.

Parameters:

  • circuit (QuantumCircuit) –

    The circuit to export.

  • format (str, default: 'qasm3' ) –

    "qasm3" or "qasm2".

  • path (str | Path | None, default: None ) –

    A file path whose parent directory exists, or None to return the text.

  • max_text_bytes (int, default: DEFAULT_MAX_BYTES ) –

    Default 10 GB (decimal, 10_000_000_000 bytes). Positive limit on the UTF-8 bytes of the exported text.

  • max_operations (int, default: 100000 ) –

    Positive limit on the top-level instructions of circuit, checked before export.

Returns:

  • output ( str | Path ) –

    The OpenQASM text, or the destination path when path is given.

Raises:

  • ValueError –

    If format is not "qasm2" or "qasm3", a limit is not a positive integer, the circuit has more than max_operations instructions, or the text exceeds max_text_bytes.

  • TypeError –

    If circuit is not a Qiskit QuantumCircuit.

Examples:

>>> from qiskit import QuantumCircuit
>>> from nwqlib.io import export_qasm
>>> bell = QuantumCircuit(2)
>>> _ = bell.h(0)
>>> _ = bell.cx(0, 1)
>>> print(export_qasm(bell))
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
h q[0];
cx q[0], q[1];

write_qasm3_file

write_qasm3_file(construction, path, *, budget: QasmWriteBudget, cancel=None) -> QasmWriteReceipt

Write a Plan's circuit (plan.construction) as an OpenQASM 3 file, replacing the destination only when the write is complete.

It writes the text as write_qasm3 does, into a temporary file in the destination's directory, and replaces the destination only after the text and its QasmWriteReceipt are complete. On failure or cancellation it removes the temporary file and leaves an existing destination unchanged. It calls no fsync, so the file may not survive a power loss.

Parameters:

  • construction (SelectedConstruction) –

    The Program and its selected definitions, such as plan.construction.

  • path (str | Path) –

    Destination file. Its directory must exist.

  • budget (QasmWriteBudget) –

    The limits.

  • cancel (Callable[[], bool] | None, default: None ) –

    Called between writes. A true result stops the write and raises QasmWriteError.

Returns:

Raises:

  • ValueError –

    If the construction is outside the writer subset or exceeds a limit of budget other than max_bytes, before any file is created.

  • QasmWriteError –

    If writing fails after it started, including when the text exceeds budget.max_bytes or cancel returns true. The destination is left unchanged. Its prefix describes the text already delivered, its temporary names the temporary file if it could not be removed, and secondary holds later cleanup failures. An exception that is not an Exception, such as KeyboardInterrupt, keeps its type, with cleanup failures in its notes.

write_qasm3

write_qasm3(construction, sink, *, budget: QasmWriteBudget, cancel=None) -> QasmWriteReceipt

Write a Plan's circuit (plan.construction) as OpenQASM 3 text to a binary stream, without any quantum SDK.

The construction must use the writer subset of the OpenQASM guide: exact gate recipes, sequences, bound repeats written as loops, allocation, computational measurement and reset, and at most one batch setting. Other constructions, such as generic state preparation or Pauli SELECT blocks, are rejected before any text is written. The sink's write must return a positive integer no larger than the buffer offered, and a partial write is completed before more text is produced. Cancellation is checked between writes, so a blocking write cannot be interrupted.

Parameters:

  • construction (SelectedConstruction) –

    The Program and its selected definitions, such as plan.construction.

  • sink (BinaryIO) –

    Binary stream with a write method.

  • budget (QasmWriteBudget) –

    The limits.

  • cancel (Callable[[], bool] | None, default: None ) –

    Called between writes. A true result stops the write and raises QasmWriteError.

Returns:

Raises:

  • ValueError –

    If the construction is outside the writer subset or exceeds a limit of budget other than max_bytes, before any text is written.

  • QasmWriteError –

    If writing fails after it started, including when the text exceeds budget.max_bytes or cancel returns true. After a cancellation its __cause__ is an InterruptedError. Its prefix describes the text already delivered.

QasmWriteBudget

Bases: Record

Limits for writing a Plan's circuit (plan.construction) as OpenQASM 3 text with write_qasm3 or write_qasm3_file.

Build it with keyword arguments, for example QasmWriteBudget(max_metadata_bytes=1_000_000, max_walk_steps=100_000, max_qubits=1, max_clbits=0, max_bytes=4096, max_instructions=100, max_chunk_bytes=256), and pass it as budget=. Every field is required. The graph and metadata checks run before any text is written. The limits do not grow with the count of a Repeat, which the text writes as one loop.

Attributes:

  • max_metadata_bytes (Count) –

    Required. Limit in bytes on a conservative JSON size of the Program graph and of the final QasmWriteReceipt, each checked before it is used.

  • max_walk_steps (Count) –

    Required. Limit on the steps of each walk over the graph and of the counting and writing passes. A Repeat count is not multiplied in.

  • max_qubits (Count) –

    Required. Limit on the total declared qubits.

  • max_clbits (Count) –

    Required. Limit on the total declared classical bits.

  • max_bytes (Count) –

    Required. Limit on the bytes of text written. It is checked while the text is written, so exceeding it raises QasmWriteError after part of the text has been delivered.

  • max_instructions (Count) –

    Required. Limit on the gate, measurement and reset statements in the text, gate definitions included.

  • max_chunk_bytes (PositiveInt) –

    Required. Positive. Limit in bytes on each buffer offered to the sink. It does not bound how long a blocking sink takes.

QasmWriteReceipt

Bases: Record

The record of a completed OpenQASM 3 file or stream: what was written, its layouts and counts.

write_qasm3 and write_qasm3_file return it, and materialize_qasm3_file imports its written file. The fields below are read-only. The text describes one circuit template. Writing it runs nothing and collects no observation. The counts are syntactic. They count no shots, gate synthesis or SDK memory, and they are not hardware estimates.

Attributes:

  • construction_id (str) –

    Content hash (content_id) of the written construction. materialize_qasm3_file refuses a receipt whose construction_id is not the content_id of the construction passed with it.

  • subset (Literal['nwqlib.direct-qasm3.v1']) –

    "nwqlib.direct-qasm3.v1", the supported subset of OpenQASM 3.0 with stdgates.inc.

  • angle_convention (Literal['binary64-repr']) –

    "binary64-repr", meaning that each angle is the shortest decimal that rounds back to the same binary64 value.

  • selected_definitions (tuple[str, ...]) –

    Content hashes of the block definitions that the written circuit uses.

  • quantum_layout (tuple[tuple[str, str, Count], ...]) –

    (original name, generated name, width) of each quantum register, in declaration order. Qubit index 0 is the least significant bit.

  • classical_layout (tuple[tuple[str, str, Count], ...]) –

    The same for each classical register.

  • batch_repetitions (Count | None) –

    Repetitions of the measurement batch, kept here and not written as a loop, or None.

  • observation_kind (str | None) –

    Observation kind of the batch, or None.

  • setting_label (str | None) –

    Label of the one written setting, or None.

  • bytes_written (Count) –

    Bytes of text written, punctuation included.

  • emitted_instructions (Count) –

    Gate, measurement and reset statements written, counting a definition body once for each time it appears in the text.

  • expanded_operations (Count) –

    Primitive gates plus one per measured or reset bit, after expanding loops and calls.

  • dynamic_visits (Count) –

    Visits to Program nodes, empty calls and loop bodies included.

  • completion (Literal['stream', 'file']) –

    "stream" from write_qasm3 or "file" from write_qasm3_file.

QasmWriteError

QasmWriteError(message, prefix, *, secondary=(), temporary=None)

Bases: RuntimeError

Raised when writing OpenQASM 3 text fails after the limit checks passed.

prefix is the QasmPrefix of the text already delivered, and __cause__ is the original failure. secondary holds the failures of closing or cleaning up, in the order they occurred. temporary names the temporary file of write_qasm3_file that could not be removed, or is None.

QasmPrefix

QasmPrefix(bytes_written: int, emitted_instructions: int)

The text that a failed OpenQASM 3 write had already delivered, never a completed file.

Read it from QasmWriteError.prefix. The fields below are read-only.

Attributes:

  • bytes_written (int) –

    Bytes the sink accepted.

  • emitted_instructions (int) –

    Statements the sink accepted completely.

materialize_qasm3_file

materialize_qasm3_file(construction, path, receipt: QasmWriteReceipt, *, writer_budget: QasmWriteBudget, budget: QasmMaterializationBudget) -> QasmMaterialization

Import an OpenQASM 3 file written by write_qasm3_file into Qiskit within explicit limits.

Use the unchanged file, construction and receipt from the same writer call. Before the file is opened, the receipt’s construction_id is compared with construction.content_id, and the sizes derived again from the construction are checked against budget. The comparison pairs the receipt with the construction and does not compare either with the file’s text. The file’s actual byte size is checked before reading. The text then goes to Qiskit’s OpenQASM 3 importer and the UnrollForLoops pass. Gate definitions stay logical. Z with more than two controls in total is rejected before import, because the installed importer can synthesize such gates eagerly. It needs the qasm extra (pip install "nwqlib[qasm]"). The checked combination is OpenQASM parser 1.0.1, qiskit-qasm3-import 0.6.0 and Qiskit 2.6.0.

Parameters:

  • construction (SelectedConstruction) –

    The construction the file was written from.

  • path (str | Path) –

    The file.

  • receipt (QasmWriteReceipt) –

    The record that write_qasm3_file returned for construction.

  • writer_budget (QasmWriteBudget) –

    The budget the file was written with.

  • budget (QasmMaterializationBudget) –

    The import limits.

Returns:

  • materialization ( QasmMaterialization ) –

    The imported circuit and its writer’s QasmWriteReceipt.

Raises:

  • ValueError –

    If receipt.construction_id is not construction.content_id, the construction exceeds budget, a Z gate has more than two controls, or the actual file exceeds the byte limit.

QasmMaterializationBudget

Bases: Record

Limits for importing an OpenQASM 3 file back into Qiskit with materialize_qasm3_file.

Build it with keyword arguments, for example QasmMaterializationBudget(max_bytes=4096, max_qubits=1, max_clbits=0, max_dynamic_visits=100, max_operations=100), and pass it as budget=. All five fields are required. The counts are derived from the matching construction and checked before the file is opened. Use the unchanged file from that writer call. No limit here estimates the importer's memory.

Attributes:

  • max_bytes (Count) –

    Required. Limit on the bytes of the file text.

  • max_qubits (Count) –

    Required. Limit on the total declared qubits.

  • max_clbits (Count) –

    Required. Limit on the total declared classical bits.

  • max_dynamic_visits (Count) –

    Required. Limit on Program node visits after expanding loops, empty and identity loops included, the count that the writer's QasmWriteReceipt.dynamic_visits reports.

  • max_operations (Count) –

    Required. Limit on primitive gate, measurement and reset applications after expanding loops, the count that QasmWriteReceipt.expanded_operations reports. Gates that Qiskit synthesizes for controls are not counted.

QasmMaterialization

QasmMaterialization(circuit: object, source: QasmWriteReceipt, output_nodes: int)

A Qiskit circuit imported from an OpenQASM 3 file, with its loops unrolled.

materialize_qasm3_file returns it. The fields below are read-only. Gates are not decomposed and nothing is simulated.

Attributes:

  • circuit (object) –

    The imported Qiskit circuit without loops. Gate definitions from the file stay as logical gates.

  • source (QasmWriteReceipt) –

    The QasmWriteReceipt passed as receipt, whose construction_id names the construction.

  • output_nodes (int) –

    Top-level instructions of circuit after unrolling. It can differ from source.expanded_operations.