Extending NWQLib¶
This page lists the classes and functions for adding a method: the Method base class and its hooks, the checker and registry for a new method, the Program (NWQLib's description of a circuit as named steps), the blocks a Program calls, the readouts it requests and the hooks that save its data. Add a Method states every requirement of a Method, and Run your own circuit builds the smallest Method step by step.
from nwqlib.algorithms import AlgorithmDescriptor, ApplicabilityError, Method
from nwqlib.algorithms.authoring import MethodCase, check_method
from nwqlib.blocks import SelectedConstruction, lower_qiskit, select_preparation
from nwqlib.ir import (
Allocate, BlockCall, Definition, Measure, Program, Register, Sequence,
)
A new Method ships a case() function that returns a MethodCase, and check_method runs it. With the reference Hadamard Method of tests/_hadamard_method.py on the import path:
from nwqlib.algorithms.authoring import check_method
from _hadamard_method import case
report = check_method(case())
print(report["status"], report["method"])
# CONFORMANT example.hadamard_pauli_expectation
From a shell, python -m nwqlib check-method my_methods:case runs the same check on the case() of your module my_methods.
| Task | Entries |
|---|---|
| Write the Method class | Method, AlgorithmDescriptor, ApplicabilityError |
| Tie a Plan and a Result to their inputs and data | Plan._bind, Result._attach, Result.validate_plan |
| Inspect a prepared circuit and its resources | PreparedHandle |
| Check a Method against its case | MethodCase, check_method |
| Register a Method and resolve it by name | Registration, AlgorithmRegistry, direct_method |
| Describe the circuit as a Program | Program, registers and block signatures, nodes |
| Give a Program named parameters and expressions | Parameter, Expression |
| Make the blocks a Program calls and build the Qiskit circuit | select_preparation, transform_block, SelectedConstruction, lower_qiskit |
| Request readouts and read the observations | Experiment, ObservationSpec, ObservationChunk, Histogram |
| Save and reload a Method's data | ArchiveFiles, write_blocks, read_blocks |
Implement a method¶
Subclass Method, give it a descriptor, and implement plan and analyze. The other hooks have defaults. Plan and Result have four protected hooks that a Method's code calls or overrides: Plan._bind, Result._attach, Result._validate_common_plan and Result._summary_lines. They keep each input and its data tied to the Plan and run no extra computation, and Supported protected extension hooks states what each must do. A Method's Result type overrides validate_plan, and a new Problem type defines default_output.
Method ¶
Bases: Record
Base class of every method: an immutable configuration that plans, runs and analyzes one kind of problem.
Subclass it to add a method. Declare the class attribute
descriptor: ClassVar[AlgorithmDescriptor] and the method's configuration
fields, and implement plan and analyze. Users pass an instance as
method= to solve, plan or compare. A Method is kept separate from the
Problem it solves, so one problem can be approached with different initial
states, trial spaces, degrees or estimators and compared on equal terms. A
Method is an immutable Record, so its content hash enters every Plan it makes,
and changing a field gives a different Plan. Running, preparation,
submission, saving and reports call the hooks below and never branch on the
method's family, so a new Method needs no change elsewhere in NWQLib.
Add a Method states every requirement,
including the protected hooks of Plan and Result below, and
Run your own circuit shows the smallest Method.
Hooks a Method implements or may override:
plan: choose and bind the Plan. Required.analyze: turn existing run data into the Result. Required.prepareandexecute: defaults for a fixed set of circuits. A Method that chooses later circuits from earlier results overrides them.prepare_all_refusal: whysettings="all"cannot be served, asked before a Run exists.error_model: the known and unavailable error sources of a Plan.verifyandrecover_analysis: explicit extra operations, unavailable by default.reduction_allowance, for a Plan that reduces data while it is collected: check the reduction's workspace and return the Method's remaining work allowance.before_submit: check data collection before its submission is recorded.validate_point,specialize_experimentandselected_kernels: check and derive one resolved point without planning again.
Attributes:
-
descriptor(AlgorithmDescriptor) –Class attribute that every subclass sets: the
AlgorithmDescriptor.
plan ¶
plan(problem, *, output, execution, shots, rng, accuracy=None)
Choose the circuits and readout for a problem and return the bound Plan.
nwqlib.plan calls it. The Plan must keep the original problem, this
Method, the output, the execution mode, the requested accuracy and the
state of each named random stream after the planning draws. nwqlib.plan
rejects a Plan that replaced the problem, Method or output object, or
whose random state or accuracy differs. accuracy is a requested
criterion, and the Plan must not record it as an achieved error bound.
Raise
ApplicabilityError when this
Method cannot solve the problem or output.
Parameters:
-
problem(Record) –The problem.
-
output(Record) –The requested output.
-
execution(str) –The requested execution, such as
"quantum"or"classical". -
shots(int | None) –Requested shots, or
Nonefor exact readout or the Method's default. -
rng(RandomStreams) –The Plan's named random streams. Draw from them, so that one seed reproduces the same choice.
-
accuracy(Accuracy | None, default:None) –Requested accuracy criterion. It is passed only when the caller gives one.
Returns:
-
plan(Plan) –The bound Plan.
analyze ¶
analyze(plan, data, *, settings)
Turn the collected data of a Plan into its Result, with explicit settings and without collecting new data.
Result.analyze and the end of a Run call it. Return an instance of the
Method's Result class attached to this Plan and the exact data used.
Result._attach runs the supported Plan and data checks.
Parameters:
-
plan(Plan) –The Plan.
-
data(RunData) –The collected data.
-
settings(dict) –Analysis settings.
Returns:
-
result(Result) –The Result attached to
plananddata.
prepare ¶
prepare(plan, *, run, settings='first')
Prepare circuits of the Plan in the Run without submitting them.
The default prepares the first setting, or every setting for
settings="all". A Method that chooses its next circuit from earlier results
overrides it to prepare that circuit. The hook receives "all" only after
prepare_all_refusal returned None.
Parameters:
-
plan(Plan) –The Plan.
-
run(Run) –The Run that holds the prepared circuits.
-
settings(str, default:'first') –"first"or"all".
prepare_all_refusal ¶
prepare_all_refusal()
Return why prepare(plan, settings="all") cannot serve this Method, or None when it can.
nwqlib.prepare asks before it creates a Run, so a refusal leaves no Run
folder. A Method whose later settings depend on earlier outcomes overrides
it to return its reason and what can be prepared instead. Otherwise the
inherited preparation would prepare, and count against the Run's limits,
every setting of the Plan, including ones the Method never submits. The
default returns None when prepare accepts the settings keyword, and
otherwise a refusal, because a prepare override without that keyword never
receives "all".
Returns:
-
reason(str | None) –The reason, or
None.
execute ¶
execute(plan, *, run)
Advance the Run's work and return the Result when it is complete, or None while it is pending.
The default runs the Plan's experiments in order, one attempt each, never submits an existing attempt again, and analyzes once every experiment has its data. A Method that chooses later circuits from earlier results overrides it.
Parameters:
-
plan(Plan) –The Plan.
-
run(Run) –The Run.
Returns:
-
result(Result | None) –The Result, or
Nonewhile work is pending.
error_model ¶
error_model(plan)
Return the known and unavailable error sources of a Plan, each with the quantity and unit it refers to.
The default returns the error model stored in the Plan (plan.error_model).
Parameters:
-
plan(Plan) –The Plan.
Returns:
-
model(ErrorModel | None) –The error model, or
None.
verify ¶
verify(plan, result, *, checks)
Run checks the caller selected explicitly on a Result, at their own cost.
Result.verify(checks=...) calls it. Override it only for checks the Method
supports. The default refuses.
Parameters:
-
plan(Plan) –The Plan.
-
result(Result) –The Result to check.
-
checks(object) –The selected checks, as
Result.verifyreceived them.
Raises:
-
ValueError–Always, in the default.
recover_analysis ¶
recover_analysis(plan, *, run)
Finish an analysis that a saved Run interrupted, without submitting earlier work again.
Only a Method that saves an interrupted analysis overrides it. The default raises.
Parameters:
-
plan(Plan) –The Plan.
-
run(Run) –The reopened Run.
Raises:
-
ValueError–Always, in the default.
AlgorithmDescriptor ¶
Bases: Record
What a Method declares about itself: name, version, the problems and outputs it handles, its coverage, limitations and references.
Build it with keyword arguments, for example
AlgorithmDescriptor(method="hadamard_expectation", version="1", problem_families=("expectation",)),
and set it as the class attribute descriptor of a
Method subclass. method and version
are required. The descriptor states scope and references. Whether a Method
applies to a given problem is decided by its plan, and a descriptor neither
proves that nor qualifies a backend.
Attributes:
-
method(Text) –Required. Registered method name, such as
"lchs". -
version(Text) –Required. Method version. The pair (
method,version) identifies the implementation. -
problem_families(tuple[Text, ...]) –Default
(). Problem kinds the Method declares, such as"linear_dynamics". -
output_families(tuple[Text, ...]) –Default
(). Output kinds it declares, such as"solution". -
access_families(tuple[Text, ...]) –Default
(). Input representations it declares, such as"dense". -
resource_coverage(tuple[Text, ...]) –Default
(). What its resource estimates cover. -
evidence_coverage(tuple[Text, ...]) –Default
(). What its error evidence covers. -
limitations(tuple[Text, ...]) –Default
(). Known limitations stated to users. -
references(tuple[Source, ...]) –Default
(). Sources of the implemented method, such as its paper. -
maintenance(Text) –Default
"experimental research method". Maintainer or status label.
source ¶
source
The Source that names this method and version.
Registrations and saved results use it to identify the implementation.
ApplicabilityError ¶
Bases: ValueError
Raised when a configured Method cannot solve the given problem or output.
A Method's plan raises it, for example for an unsupported problem type,
input representation or output. It is a ValueError.
default_output ¶
default_output()
Return the output that plan and compare use when no output is given.
Each built-in Problem returns its default output, such as
Eigenvalue() for an Eigenproblem. A Problem type of a Method
author defines its own, as Run your own circuit
shows. This base raises, so a Problem without its own default needs
an explicit output.
Returns:
-
output(OutputRecord) –The default output.
Raises:
-
TypeError–Always, on this base.
_bind ¶
_bind(*, blocks=(), **native)
Bind the planned circuit blocks and named live inputs to this Plan once, and return the Plan.
A supported hook for Method authors (Add a Method). It compiles nothing, measures nothing and does not rebuild the inputs. An archive reader restores the same blocks with it instead of planning again.
Parameters:
-
blocks(tuple, default:()) –The live circuit blocks of the construction.
-
**native(object, default:{}) –Named live inputs that the Method keeps with the Plan.
Returns:
-
plan(Plan) –This Plan.
Raises:
-
ValueError–If live data is already bound to this Plan.
resolve ¶
resolve(experiment: str, *, bindings: tuple[Binding, ...] = ()) -> Realization
Bind the open Program parameters of one experiment, without changing the Plan.
Only values that pass the Program's checks are bound. The result depends on the Plan and the bindings alone, and nothing is prepared.
Parameters:
-
experiment(str) –Name of one of this Plan's experiments.
-
bindings(tuple[Binding, ...], default:()) –Values for Program parameters that the Plan and the experiment's setting leave unbound, such as a point of a range axis. A value that differs from an existing binding is rejected.
Returns:
-
realization(Realization) –The Plan's content hash, the experiment name and every parameter value, in parameter-name order.
_attach ¶
_attach(plan, data)
Attach the Plan and run data to a Result once, and return the Result.
A supported hook for Method authors (Add a
Method).
It checks that the Result names this Plan and these observations,
that every part of the observations it uses is in the data, and calls
validate_plan before attaching. It measures nothing and creates no
missing observation.
Parameters:
-
plan(Plan) –The Plan the Result was computed from.
-
data(RunData) –The run data the Result was computed from.
Returns:
-
result(Result) –This Result, with
plananddataattached.
Raises:
-
ValueError–If the Result names another Plan or other observations, uses an observation absent from the data, or is already attached to another Plan or data.
validate_plan ¶
validate_plan(plan)
Check that this Result belongs to plan, before the Plan is attached.
The base check compares plan_id with the Plan's content hash. A
Method's Result type overrides it to call _validate_common_plan
and then check its own relation between the Plan and its fields
(Add a Method).
Parameters:
-
plan(Plan) –The Plan to check against.
Raises:
-
ValueError–If the Result names another Plan.
_validate_common_plan ¶
_validate_common_plan(plan, plan_type)
Check the Plan type, the Plan's content hash and the Method that analyzed the Result.
A supported hook for Method authors. Call it from validate_plan
before checking the Method's own relation between the Plan and the
Result (Add a
Method).
Parameters:
-
plan(Plan) –The Plan to check against.
-
plan_type(type) –The exact Plan class that the Method produces.
Raises:
-
TypeError–If
planis not exactly of typeplan_type. -
ValueError–If the Result names another Plan, or its
originnames another Method than the Plan's.
_summary_lines ¶
_summary_lines()
Return the first lines of print(result), built from the Result's stored values.
A supported hook for Method authors (Add a Method). An override must not measure, reanalyze, load arrays or recompute error evidence.
Returns:
-
lines(tuple[str, ...]) –The lines.
PreparedHandle ¶
PreparedHandle()
The prepared circuit of one experiment for one backend, with its preparation record.
Submission uses exactly this circuit, so the circuit that executes is the
one the preparation record describes. After Run.release_native the
circuit is dropped from memory and read back from the Run's saved QPY
when needed, without building or transpiling it again. Method authors
receive handles from the Run's preparation calls. The fields below are
read-only.
Attributes:
-
record(PreparedArtifact) –The preparation record (
PreparedArtifact), with the readout and the backend. -
realization(Realization) –The experiment's concrete parameter values and construction (
Realization).
inspect_circuit ¶
inspect_circuit()
Return a copy of the prepared Qiskit circuit.
QuantumCircuit.copy gives the copy its own instruction list and its
own operation objects (checked against the installed Qiskit), so
changing the copy leaves the circuit that executes unchanged.
Returns:
-
circuit(QuantumCircuit) –The copy.
Raises:
-
ValueError–If this preparation is a host computation without a circuit.
inspect_resources ¶
inspect_resources(*, transpile_options=None, max_operations=100000, max_bytes=DEFAULT_MAX_BYTES)
Count the operations of the prepared circuit, without copying or running it.
Each top-level instruction of the circuit counts once under its
operation name, measurements, barriers, simulator saves, Clifford
objects and user-defined gates included, and names are reported as
they are. Gate definitions and control-flow bodies are not expanded. With transpile_options, a transpiled copy is
counted instead, with the simulator saves removed first. The circuit
that executes is never changed or run.
Parameters:
-
transpile_options(dict | None, default:None) –Options for Qiskit's
transpile.None, the default, counts the prepared circuit as it is. -
max_operations(int, default:100000) –Default
100_000. Largest number of operations of the circuit, and of its transpiled copy. -
max_bytes(int, default:DEFAULT_MAX_BYTES) –Default 10 GB (decimal,
10_000_000_000). Largest size of the known inspection data and options. It does not bound the compiler's own memory.
Returns:
-
inventory(dict) –circuit,basis,compiler(Qiskit version and options, orNone),operations(count by name),total_operations,num_qubits,num_clbitsanddepth(Qiskit's default depth, which skips directives such as barriers and simulator saves).
Raises:
-
ValueError–If this preparation has no circuit or a limit is exceeded.
Check and register a method¶
MethodCase ¶
MethodCase(method: Method, problem: Record, evaluate: Callable[[Plan], Result], accepts: Callable[[Result], bool], invalid_result: Callable[[Result], Result], output: Record | None = None, execution: str = 'quantum', shots: int | None = None, seed: int | None = None)
One small test case for a new Method: a problem, how to run it, an independent check of the answer and a deliberately wrong answer.
Build it with keyword arguments, usually in a case() function next to the
Method, and pass it to check_method
or run python -m nwqlib check-method my_methods:case. method, problem,
evaluate, accepts and invalid_result are required. The checker computes
no reference answer of its own. accepts holds the independent expected
relation, and evaluate decides whether the case prepares and submits
circuits or analyzes data supplied with it. The Method's archive hooks are
trusted code and run under the ordinary archive byte limits. The reference
Hadamard Method, tests/_hadamard_method.py, defines such a case().
Parameters:
-
method(Method) –The configured Method under test.
-
problem(Record) –The problem of this case.
-
evaluate(Callable[[Plan], Result]) –Called with the Plan, returns that Plan's attached Result, for example by
prepare,submitandrun.wait(). -
accepts(Callable[[Result], bool]) –Called with the Result, returns
Truewhen the independent expected relation holds, for exampleabs(result.value - 1.0) < 1e-12. -
invalid_result(Callable[[Result], Result]) –Called with the Result, returns a Result of the same class and Plan with a scientific field changed so that it is valid as a record but wrong for this Plan, for example
result.revise(value=-1.0). -
output(Record | None, default:None) –Requested output, or
Nonefor the problem's default. -
execution(str, default:'quantum') –"quantum"or"classical". -
shots(int | None, default:None) –Requested shots, or
Nonefor exact readout or the Method's default. -
seed(int | None, default:None) –Seed of the Plan's random streams, or
Nonefor fresh entropy.
check_method ¶
check_method(case: MethodCase) -> dict
Check a new Method against its test case: the expected answer, the Plan checks and a saved-result round trip.
The check plans the case through the public plan, evaluates the Plan with
the case's callback, and requires the case's independent relation to accept
the Result. The Method's error_model must equal the Plan's, and its
result_type must name the Result class. The wrong Result from
invalid_result must be a valid record that the Method's validate_plan
rejects, both in memory and after it replaces the legal Result in a saved
archive. The legal Result must then reload unchanged and still pass the
relation. These wrong-answer steps show that the Method's own Plan and Result
check catches a scientifically wrong answer under the same Plan, which a
record's own field checks cannot do. Nothing beyond the case's callback is
computed, neither a reference solve nor extra circuits. "CONFORMANT" means this
one case passed. It does not certify other inputs, physical accuracy,
backend support or cost. The example at the top of
Extending NWQLib runs it on the reference Hadamard Method.
Parameters:
-
case(MethodCase) –The test case.
Returns:
-
report(dict) –A dict with
status("CONFORMANT"),method(the descriptor's method name),plan_id,result_id,scopeandqualification.
Raises:
-
TypeError–If the case, the Method or its Result class does not meet the Method protocol.
-
ValueError–If the expected relation, the wrong-answer check or the saved round trip fails.
Registration ¶
Registration(source: Source, factory: str, descriptor: AlgorithmDescriptor | None = None, method_type: type[Method] | None = None)
An entry that makes a Method findable by name and version: its Source and a trusted factory path.
Build it with keyword arguments, for example
Registration(source=MyMethod.descriptor.source, factory="my_methods:MyMethod"),
in a module that does not import the Method itself, and pass it to
AlgorithmRegistry.
source and factory are required. Building it imports nothing. A saved
Source string never loads code. Only a registration in the running
process does. Explicit trusted registration
shows the metadata module of the reference Method.
Parameters:
-
source(Source) –Source naming the method and version, as
descriptor.sourcegives it. -
factory(str) –"module:attribute"path of a callable that returns the Method, called only byAlgorithmRegistry.resolve. -
descriptor(AlgorithmDescriptor | None, default:None) –The Method's
AlgorithmDescriptorwhen already known, with the same method and version assource.Noneavoids importing the Method to read it. -
method_type(type[Method] | None, default:None) –The Method class when already known. Its
descriptormust equaldescriptor.
Raises:
-
ValueError–If
factoryis not amodule:attributepath, or the descriptor's method and version differ fromsourceor frommethod_type.descriptor. -
TypeError–If
method_typeis not a Method subclass.
AlgorithmRegistry ¶
AlgorithmRegistry(registrations: Iterable[Registration] = ())
A list of trusted Method registrations that finds a Method by name and version and builds it on request.
Build it as AlgorithmRegistry((registration, ...)). Without registrations it is
empty. discover lists the registrations without running any
factory, and resolve runs only the factory of the requested Source. A
registry is not a security sandbox, and a registration does not qualify a
backend.
Parameters:
-
registrations(Iterable[Registration], default:()) –The registrations, at most one per method and version.
Raises:
-
ValueError–If two registrations share a method and version.
discover ¶
discover() -> tuple[Registration, ...]
Return the registrations in method and version order, without importing any factory.
Returns:
-
registrations(tuple[Registration, ...]) –The registrations.
resolve ¶
Build the registered Method for a Source by calling its factory with the given configuration.
Only the factory of that Source runs, with exactly the configuration supplied, and no earlier configuration is reused. The built Method must match the registered method, version, descriptor and class.
Parameters:
-
source(Source) –Source of the method and version, equal to the registered one.
-
expected_type(type, default:Method) –Class the result must be an instance of, which keeps a caller's concrete type.
-
**configuration(object, default:{}) –Keyword arguments for the factory, such as Method settings.
Returns:
-
method(Method) –The configured Method.
Raises:
-
LookupError–If no registration has this method and version.
-
ValueError–If
sourcediffers from the registered Source, or the built Method differs from the registration. -
TypeError–If the built object is not a complete Method of
expected_type.
builtin_registrations ¶
builtin_registrations() -> tuple[Registration, ...]
Return a registration for each built-in Method, without constructing or planning one.
It imports the built-in configuration modules, which can load NumPy, SciPy and their dependencies, but no quantum SDK. Installed extensions are not included. Their configuration fields, defaults and required fields come from each Method class's schema.
Returns:
-
registrations(tuple[Registration, ...]) –The registrations, in method and version order.
third_party_registrations ¶
third_party_registrations(entries: Iterable[EntryPoint] | None = None) -> tuple[Registration, ...]
Return a registration for each installed nwqlib.algorithms entry point, without loading its code.
Each entry point must be named method@version, and its value is the
factory path. The descriptor and Method class of these registrations stay
None until code is loaded explicitly. Builtin inventory does not call this
function, so installed extensions are found only when it is called.
Parameters:
-
entries(Iterable[EntryPoint] | None, default:None) –Entry points to read.
Nonereads the installed entry points of the groupnwqlib.algorithms. Entries of other groups are ignored.
Returns:
-
registrations(tuple[Registration, ...]) –The registrations, sorted by method, version and factory.
Raises:
-
ValueError–If an entry-point name is not
method@version.
direct_method ¶
direct_method(method: object, *, expected_type: type[T] = Method) -> T
Check that an object is a complete Method and return it, without running a factory.
A complete Method has a descriptor and implements plan and analyze.
Parameters:
-
method(object) –The object to check.
-
expected_type(type, default:Method) –Class the object must be an instance of.
Returns:
-
method(Method) –The same object.
Raises:
-
TypeError–If it is not an instance of
expected_type, has no descriptor, or does not implementplanandanalyze.
options_schema ¶
options_schema(registration: Registration) -> dict
Return the JSON schema of a registered Method's configuration, with its required fields and defaults.
nwqlib options METHOD prints it. The schema comes from the Method class
(model_json_schema()), so no required input is guessed.
Parameters:
-
registration(Registration) –A registration whose
method_typeis known.
Returns:
-
schema(dict) –The JSON schema.
Raises:
-
ValueError–If the registration's Method class is not loaded, as for an installed extension found by
third_party_registrations. Select the extension's code explicitly in Python first.
Describe a circuit as a Program¶
A Program lists named nodes: register allocation, block calls, measurements, repeats and their order. It is checked when it is built. Describe a circuit as a Program explains the nodes and Program checks the lifecycle rules.
Program ¶
Bases: Record
A circuit described as named steps: registers, block calls, measurements and their order, checked when it is built.
Build it with keyword arguments and use it in a
SelectedConstruction.
root and definitions are required. Every node is a
Definition with an ID, and nodes refer to
each other by ID, so a shared body is stored once however often it runs, and
the checking work grows with its distinct contexts rather than its run
count. The root starts with no allocated registers or classical values.
Registers still allocated at the end of the root stay available to
code that uses the quantum output, while the body of a measurement batch must
release its registers. Construction runs the full structural check of the
declared effects, so an illegal lifecycle or a graph over its limits is
rejected before anything uses the Program. Unresolved requirements, such as
an unbound width, do not reject it but make it not ready.
One Program is the single description of a construction that the structural check, resource estimate, circuit building and readout all read, so a cost, a circuit and a readout cannot describe different constructions. Its content hash covers every table, binding and limit. Run your own circuit builds a Program around a supplied circuit, and Describe a circuit as a Program explains the nodes.
Attributes:
-
root(Text) –Required. Definition ID of the root node.
-
definitions(tuple[Definition, ...]) –Required. The
Definitionrecords. -
expressions(tuple[Expression, ...]) –Default
().Expressionrecords that widths, counts and arguments refer to. -
parameters(tuple[Parameter, ...]) –Default
(). DeclaredParameterrecords. -
constraints(tuple[ExprRef, ...]) –Default
(). Bool expressions that every bound point must satisfy. -
registers(tuple[Register, ...]) –Default
(). QuantumRegisterrecords. -
classical(tuple[ClassicalValue, ...]) –Default
().ClassicalValuerecords. -
signatures(tuple[BlockSignature, ...]) –Default
().BlockSignaturerecords of the blocks called. -
bindings(tuple[Binding, ...]) –Default
(). Parameter values bound so far. -
limits(AdmissionLimits) –Default
AdmissionLimits(), the defaultAdmissionLimits. -
premises(tuple[Text, ...]) –Default
(). Stated assumptions of the construction.
Raises:
-
ValueError–If the structure breaks a lifecycle rule, refers to an unknown ID, or exceeds
limits.
Examples:
Allocate a two-qubit register and measure it.
>>> from nwqlib.ir import (Allocate, ClassicalValue, Definition, Measure,
... Program, Register, Sequence)
>>> program = Program(
... root="main",
... definitions=(
... Definition(id="allocate", node=Allocate(wire="q")),
... Definition(id="measure", node=Measure(wire="q", result="bits")),
... Definition(id="main",
... node=Sequence(children=("allocate", "measure"))),
... ),
... registers=(Register(name="q", width=2),),
... classical=(ClassicalValue(name="bits", dtype="bits", width=2),),
... )
>>> program.check_readiness().ready
True
check_readiness ¶
check_readiness() -> Readiness
Return the result of this Program's structural check.
The check runs once per Program object, when it is built, and its result is
kept for later calls. Copies and unpickled Programs check again on first
use. It covers every concrete rule and lists unresolved requirements as
blockers. expression_evaluations + lifecycle_steps of the result is the
checking work it measured.
Returns:
-
readiness(Readiness) –The result of the check.
bind ¶
bind(**values)
Return a copy of the Program with parameter values bound, keeping shared bodies.
The copy runs the structural check again.
Parameters:
-
**values(int | Float64, default:{}) –Parameter values by name, an exact integer or a
Float64.
Returns:
-
program(Program) –The bound Program.
Raises:
-
ValueError–If the bound Program fails the structural check.
select_experiment ¶
select_experiment(batch_id: str, setting_index: int, **axis_values)
Return a Program for one experiment of a measurement batch, without expanding any range or product.
The returned Program's root is the batch with the one selected setting and
no axes. It keeps the dependency closure of that batch, every global
constraint and the register layout, and the selected values also bind the
global constraints. It creates no observation or execution ID, because the
original Program identifies the whole source graph. Use it before
lower_qiskit, which builds the
circuit of one static experiment.
Parameters:
-
batch_id(str) –Definition ID of the measurement batch.
-
setting_index(int) –Index of the setting.
-
**axis_values(int, default:{}) –One value for each range axis of the batch.
Returns:
-
program(Program) –The Program of the selected experiment.
Raises:
-
ValueError–If the batch, setting or axis values are invalid.
iter_definitions ¶
iter_definitions()
Return an iterator over the stored definitions, each once in declaration order, without expanding anything.
Returns:
-
definitions(Iterator[Definition]) –The definitions.
Definition ¶
Bases: Record
One node of a Program with its ID. Nodes refer to each other by ID, so a shared body is stored once.
Build it as Definition(id="main", node=Sequence(children=(...))) and pass it
in definitions= of a Program. Both arguments
are required.
Attributes:
-
id(Text) –Required. Unique ID within the Program.
-
node(Node) –Required. One node:
Sequence,Repeat,BlockCall,CoherentRegion,Allocate,Release,Measure,Reset,Branch,ClassicalStage,AdaptiveLoop,MeasurementBatchorParallel.
Readiness ¶
Bases: Record
The result of a Program's structural check: what is still unresolved, and the checking work it took.
Program.check_readiness returns
it. The fields below are read-only. A ready Program is structurally valid. It
is not a check of the blocks' promised actions or an approval to run.
Attributes:
-
blockers(tuple[Text, ...]) –Sorted unresolved requirements, such as an unbound width or an unknown block effect. Empty when the Program is ready.
-
expression_evaluations(NonnegativeInt) –Expression evaluations of this check.
-
lifecycle_steps(NonnegativeInt) –Other checking work units of this check, not quantum events or algorithm costs.
AdmissionLimits ¶
Bases: Record
Limits on the size of a Program's stored structure and on the work of checking it.
Pass it as limits= to Program. Every
argument is optional. A caller can make a Program's metadata arbitrarily
large or deep, and these limits make the structural check and the resource
estimate reject it before their work or memory passes a fixed size. They
limit the stored structure and the checking work, never the size of the
workload the Program describes, and repeat counts and range lengths are not
expanded. A Method with a max_admission_steps setting uses it as
max_steps of its Programs, and Program checks explains how planning
work is counted.
Attributes:
-
max_definitions(PositiveInt) –Default
16384. Positive limit on the stored definitions, expressions, parameters, registers, classical values and signatures together. 16,384 is the smallest power of two with at least a twofold margin over the 5,951 of a sampled FixedGCIM Plan with a 12-qubit, 200-term observable and four basis states (the Program inventory row of Engineering constants). -
max_depth(PositiveInt) –Default
128, also the largest accepted value. Limit on the longest chain of references, which is also the recursion limit of the lifecycle check. -
max_steps(PositiveInt) –Default
100000. Positive limit on the checking work units of one check, and separately on the number of stored fields. -
max_integer_bits(PositiveInt) –Default
4096. Positive limit on the bit length of any integer the check accepts or computes.
Registers, values and block signatures¶
Register ¶
Bases: Record
A quantum register of a Program, allocated explicitly by an Allocate node.
Build it as Register(name="q", width=2) and pass it in registers= of a
Program. name and width are required.
Attributes:
-
name(Text) –Required. Register name, used by ports, allocation and measurement.
-
width(Integer) –Required. Number of qubits, an integer or an
ExprRef. -
location(Text) –Default
"logical_device". Device location on which the resource estimate places the register. -
role(Literal['system', 'clean_ancilla', 'dirty_ancilla']) –Default
"system"."system","clean_ancilla"or"dirty_ancilla", reported separately in memory and qubit counts.
ClassicalValue ¶
Bases: Record
A named classical value of a Program, such as measured bits or a computed scalar.
Build it as ClassicalValue(name="bits", dtype="bits", width=2) and pass it
in classical= of a Program. name and
dtype are required. Bits have a positive width, and the other types have
none.
Attributes:
-
name(Text) –Required. Value name.
-
dtype(Literal['bits', 'bool', 'integer', 'real']) –Required.
"bits","bool","integer"or"real". -
width(Integer | None) –Default
None. Number of bits, positive and required for"bits",Noneotherwise.
Raises:
-
ValueError–If
widthis missing or not positive for bits, or given for another type.
BlockSignature ¶
Bases: Record
The declared interface of a block that a Program calls: its target action, ports and parameters.
Build it with keyword arguments, for example
BlockSignature(name="h", target=source, quantum=(QuantumPort(name="system", width=1),)),
and pass it in signatures= of a Program.
name and target are required. A
BlockCall names the signature, and the
selected definition bound to it supplies the action, its cost rules and the
circuit constructor. The signature declares an interface. It does not prove
that an implementation performs the action.
Attributes:
-
name(Text) –Required. Signature name, used by block calls and by the selected definition.
-
target(Source) –Required. Versioned Source of the action a selection must implement.
-
quantum(tuple[QuantumPort, ...]) –Default
(). OrderedQuantumPortrecords. -
parameters(tuple[Parameter, ...]) –Default
(). ScalarParameterrecords with their domains. -
interface(Literal['declared', 'unknown']) –Default
"declared"."unknown"keeps an undeclared block in the Program, which is then not ready. -
coupling(Literal['joint', 'independent']) –Default
"joint", when the call may correlate its ports, or"independent"when it promises not to. -
obligations(tuple[Text, ...]) –Default
(). Promises that the selected implementation must meet.
QuantumPort ¶
Bases: Record
A port of a block signature: a whole register the block acts on, with the state it needs and the effect it promises.
Build it as QuantumPort(name="system", width=2) and pass it in quantum=
of a BlockSignature. name and width
are required. A call maps each port, in signature order, to a register that
no other port of the call uses. The zero state counts as coherent. A "unitary" effect keeps the register's coherence
epoch but clears a known zero state, and "preserve" promises that the
state is restored exactly. A "zero" or "coherent" output asserts a newly
prepared state, which the block's implementation must guarantee. An
"unknown" effect makes the Program not ready and cannot satisfy a later
state requirement.
Attributes:
-
name(Text) –Required. Port name.
-
width(Integer) –Required. Number of qubits, an integer or an
ExprRef. -
requires(Literal['live', 'zero', 'coherent']) –Default
"live". Input state the port needs: any allocated ("live") state,"zero"or"coherent". -
ensures(Literal['unitary', 'preserve', 'zero', 'coherent', 'unknown']) –Default
"unitary". Effect on the register:"unitary","preserve","zero","coherent"or"unknown".
Nodes¶
Sequence ¶
Parallel ¶
Bases: Record
Runs block calls concurrently on disjoint registers and joins them.
Build it as Parallel(children=("call_a", "call_b")). Every child must be a
direct block call whose ports declare "unitary" or "preserve". Children that
share registers, and classical work or lifetime changes, are rejected. Use
Sequence for serial order.
Attributes:
-
children(tuple[Text, ...]) –Default
(). Definition IDs of the block calls.
Repeat ¶
Bases: Record
Repeats a body a fixed number of times, without unrolling it.
Build it as Repeat(body="step", count=4). Both arguments are required. The
check verifies that the body can be repeated and never expands it, so a
large count costs no more checking work than a small one.
Attributes:
-
body(Text) –Required. Definition ID of the body.
-
count(Integer) –Required. Nonnegative repetition count, an integer or an
ExprRef.
BlockCall ¶
Bases: Record
Calls a declared block signature on whole registers, with ports in signature order.
Build it as BlockCall(signature="h", ports=(PortMap(port="system", wire="q"),)).
signature is required. Each register is used by one port only. The call
names the signature, not an implementation. The selected definition bound to
that signature supplies the action, cost rules and circuit constructor.
Attributes:
-
signature(Text) –Required. Signature name.
-
ports(tuple[PortMap, ...]) –Default
(). OnePortMapper port, in signature order. -
arguments(tuple[Argument, ...]) –Default
().Argumentvalues of the signature's parameters.
PortMap ¶
Argument ¶
Bases: Record
Gives a scalar parameter of a block signature the value of an expression in a block call.
Build it as Argument(parameter="angle", value=ExprRef(expression="theta")).
Both arguments are required.
Attributes:
-
parameter(Text) –Required. Parameter name of the signature.
-
value(ExprRef) –Required. The
ExprRefof the value.
Allocate ¶
Release ¶
Measure ¶
Bases: Record
Measures a whole register into a classical bits value. The register stays allocated in a new epoch.
Build it as Measure(wire="q", result="bits"). wire and result are
required.
Attributes:
-
wire(Text) –Required. Register name.
-
result(Text) –Required. Name of a classical bits value of the same width.
-
basis(Text) –Default
"computational", the only basis thatlower_qiskitand OpenQASM export support.
Reset ¶
CoherentRegion ¶
Bases: Record
Requires the claimed registers to stay in their coherent epochs throughout the body.
Build it as CoherentRegion(body="kernel", claims=(StateClaim(wire="q", epoch=0),)).
Both arguments are required. A measurement, reset or other new preparation
of a claimed register inside the body is rejected.
Attributes:
-
body(Text) –Required. Definition ID of the body.
-
claims(tuple[StateClaim, ...]) –Required. The
StateClaimrecords.
StateClaim ¶
Bases: Record
Claims that a register is still in a given coherent epoch. Measurement and reset start a new epoch.
Use it in claims= of a CoherentRegion.
An epoch numbers the coherence generations of one register. The first
allocation starts it at 0. Every measurement, reset, release, reallocation
and block port that promises a newly prepared zero or coherent output adds
one, to the register it acts on and to every register correlated with it. A
claim therefore names one specific coherent state, and a claim written
before a measurement no longer matches after it.
Program checks gives the full rules.
Attributes:
-
wire(Text) –Required. Register whose coherence is claimed.
-
epoch(NonnegativeInt) –Required. Epoch the register must currently have.
Branch ¶
Bases: Record
Chooses between two bodies on a classical value. Both paths are checked.
Build it as Branch(condition="flag", when_true="a", when_false="b"). Every
argument is required. After the branch, a register state or classical value
is available only as far as both paths make it available.
Attributes:
-
condition(Text) –Required. Name of an available classical value.
-
when_true(Text) –Required. Definition ID of the body for true.
-
when_false(Text) –Required. Definition ID of the body for false.
ClassicalStage ¶
Bases: Record
A classical computation inside the quantum job or on the host. The check runs no code.
Build it with keyword arguments, for example
ClassicalStage(implementation=source, inputs=("bits",), outputs=("value",)).
implementation is required. A host stage requires every register to be
released first and can name the selected kernel that runs it.
Attributes:
-
implementation(Source) –Required. Versioned Source of the computation.
-
inputs(tuple[Text, ...]) –Default
(). Classical values read, which must be available on every path. -
outputs(tuple[Text, ...]) –Default
(). Classical values defined. -
arguments(tuple[Argument, ...]) –Default
(). ScalarArgumentvalues. -
boundary(Literal['in_job', 'host']) –Default
"in_job", processing inside the quantum job, or"host". -
kernel(Text | None) –Default
None. Name of the selected kernel that runs a host stage.
AdaptiveLoop ¶
Bases: Record
Repeats a body zero to max_rounds times, with a classical policy after each round and a declared stopping rule.
Build it with keyword arguments. body, max_rounds, policy and
termination are required. The stopping rule is kept as text and never
executed.
Attributes:
-
body(Text) –Required. Definition ID of one round.
-
max_rounds(Integer) –Required. Upper bound on the rounds, an integer or an
ExprRef. -
policy(ClassicalStage) –Required. Versioned
ClassicalStagerun after each round, which may read that round's results. -
termination(Text) –Required. Declared stopping rule.
-
resource_envelope(Text | None) –Default
None. Stated bound on the cost of every round. WithNone, the resource estimate leaves the loop's cost unknown.
MeasurementBatch ¶
Bases: Record
Independent experiments that share one body. No quantum or classical state passes between them.
Build it with keyword arguments, for example
MeasurementBatch(body="experiment", settings=(setting,), repetitions=1, observation_kind="counts").
body and settings are required. The settings are combined with the range
axes. A requirement that depends on an axis value keeps the Program not ready
until one experiment is selected and bound
(Program.select_experiment).
lower_qiskit builds one circuit of the body, not its repetitions. Every
register the body allocates must be released at its end.
Attributes:
-
body(Text) –Required. Definition ID of the shared body.
-
settings(tuple[Setting, ...]) –Required. At least one
Setting. -
axes(tuple[RangeAxis, ...]) –Default
().RangeAxisranges. -
scope(Literal['independent_experiments']) –Default
"independent_experiments", the only accepted value. -
repetitions(Integer | None) –Default
None. Independent runs of the body, an integer or anExprRef.Noneleaves the planning requirement unknown. Preparing an exact readout kind requires 1. -
observation_kind(ObservationKind | None) –Default
None. For the innermost batch,"counts"for sampled counts,"pauli_expectation"or"probabilities"for exact statistics,"estimated_observable"for a provider estimate, or"trajectory". A"trajectory"is one exact evaluation of the body whose observation points belong to the selected experiment's readout, not to the settings. An outer batch hasNone.
Setting ¶
Bases: Record
One experiment of a measurement batch: a label, parameter values and method metadata.
Build it as Setting(label="z_basis", bindings=(...), metadata=MetadataRef(...)).
label and metadata are required. The label, bindings and metadata
together determine the experiment's content hash.
Attributes:
-
label(Text) –Required. Experiment label.
-
bindings(tuple[Binding, ...]) –Default
().Bindingvalues of this experiment. -
metadata(MetadataRef) –Required. The
MetadataRef.
RangeAxis ¶
Bases: Record
An integer parameter range [start, stop) with a positive step, kept compact and never expanded.
Build it as RangeAxis(parameter="k", start=0, stop=8) and pass it in
axes= of a MeasurementBatch, which
combines every setting with every value. parameter, start and stop are
required.
Attributes:
-
parameter(Text) –Required. Parameter name.
-
start(NonnegativeInt) –Required. Nonnegative first value.
-
stop(NonnegativeInt) –Required. Nonnegative end, excluded and greater than
start. -
step(NonnegativeInt) –Default
1. Positive step.
Raises:
-
ValueError–If the range is empty.
MetadataRef ¶
Bases: Record
A reference to method metadata attached to a setting, in a format the method defines. It is never decoded by the check.
Build it as MetadataRef(format=source, data=input_ref). Both arguments are
required.
Attributes:
-
format(Source) –Required. Source of the metadata format.
-
data(InputRef) –Required.
InputRefof the stored metadata.
Parameters and expressions¶
Parameter ¶
Bases: Record
A named integer or real parameter of a Program, with optional inclusive bounds.
Build it with keyword arguments, for example
Parameter(name="steps", domain="integer", lower=1), and pass it in
parameters= of a Program or a
BlockSignature. name and domain are
required. A real value is a finite binary64 number given as Float64.
Attributes:
-
name(Text) –Required. Parameter name.
-
domain(Literal['integer', 'real']) –Required.
"integer"or"real". -
lower(Value | None) –Default
None. Inclusive lower bound, an exact integer for an integer domain. -
upper(Value | None) –Default
None. Inclusive upper bound, not belowlower.
Raises:
-
ValueError–If an integer domain has a non-integer bound, or
lowerexceedsupper.
admit ¶
admit(value)
Check a value against the parameter's domain and bounds, without rounding, and return it as a number.
Parameters:
-
value(int | Float64) –An exact integer for an integer domain, or a
Float64for a real domain.
Returns:
-
value(int | float) –The value as a number.
Raises:
-
ValueError–If the value has the wrong type or lies outside the bounds.
Binding ¶
Bases: Record
A concrete value for one parameter, part of the content hash of the record that holds it.
Build it as Binding(parameter="steps", value=4) and pass it in
bindings= of a Program, a Setting or a selected definition. Both
arguments are required.
Attributes:
-
parameter(Text) –Required. Parameter name.
-
value(Value) –Required. An exact integer or a
Float64.
Expression ¶
Bases: Record
A named expression of a Program: a constant, a parameter value or an operation on two expressions.
Build it as Expression(id="width", value=Constant(value=3)) and pass it in
expressions= of a Program. Both arguments are
required, and the ID is unique within the Program.
Attributes:
-
id(Text) –Required. Unique ID within the Program.
-
value(Constant | ParameterRef | Binary) –Required. A
Constant, aParameterRefor aBinary.
Constant ¶
Bases: Record
An exact integer or finite Float64 literal, the value of an expression.
Build it as Constant(value=3) and wrap it in an
Expression.
Attributes:
-
value(Value) –Required. An exact integer or a
Float64.
ParameterRef ¶
Bases: Record
The value of a declared parameter, as an expression.
Build it as ParameterRef(parameter="steps") and wrap it in an
Expression. While the parameter is
unbound, the structural check treats the value as unknown and the resource
estimate keeps it symbolic. It is never read as zero.
Attributes:
-
parameter(Text) –Required. Name of a declared parameter.
Binary ¶
Bases: Record
An operation on two expressions of the Program, such as a sum or an exact ceiling division.
Build it as Binary(op="multiply", left="n", right="two") and wrap it in an
Expression. Both operands must have the
same numeric domain. "eq", "lt" and "le" return a bool, and
"ceildiv" is exact, requires integers and a positive denominator.
Attributes:
-
op(Literal['add', 'multiply', 'ceildiv', 'min', 'max', 'eq', 'lt', 'le']) –Required.
"add","multiply","ceildiv","min","max","eq","lt"or"le". -
left(Text) –Required. ID of the left operand's expression.
-
right(Text) –Required. ID of the right operand's expression.
ExprRef ¶
Bases: Record
A reference to an expression of the Program by its ID, used wherever a width, count or argument may be computed.
Build it as ExprRef(expression="width"). The ID names an entry of
Program.expressions. It is never source code.
Attributes:
-
expression(Text) –Required. ID of the expression.
Select and lower blocks¶
A Program calls blocks by signature name. Each select_* function returns a SelectedBlock whose record states the block's promised action, recipe and cost rules, and lower_qiskit builds the Qiskit circuit from the Program and its blocks. Compose blocks composes a Pauli block encoding from these functions.
select_preparation ¶
select_preparation(name: str, state: StateInput, *, choice: str = 'native', per_bit: bool = False) -> SelectedBlock
Build the state preparation block of a state input, U|0> = state, with the cheapest exact recipe its form allows.
Pass a StateInput from state_input or the ingest_*
functions. Selection reads only the stored representation. It never
normalizes, hashes the data again, synthesizes or simulates. An occupation,
basis or uniform state gets an exact gate recipe, with the physical global
phase as a phase gate. A prefix-uniform, general or product state uses the
direct preparation and its CX upper bound, and a product state is counted as
q one-qubit preparations, not one q-qubit vector. A supplied Qiskit circuit
becomes its own block with unknown synthesis cost and error, because its
content cannot be recognized. The block promises only U|0>, the normalized
state, with the physical global phase kept, including under control.
choice="hzh" prepares each occupied site of an occupation input with
H, Z, H instead of X. The two recipes are equal as full operators and are
different choices, with different content hashes and gate counts.
Parameters:
-
name(str) –Signature name of the block.
-
state(StateInput) –The state input.
-
choice(str, default:'native') –"native", or"hzh"for an occupation input. -
per_bit(bool, default:False) –With
True, the block has one one-qubit portsystem_<j>per qubit, in the same order, for a caller that measures or connects single sites.
Returns:
-
block(SelectedBlock) –The preparation block, with port
systemof q qubits, or the per-qubit ports.
Raises:
-
ValueError–If the state's preparation has no circuit constructor,
choiceis unknown, or"hzh"is used for an input that is not an occupation. -
TypeError–If
per_bitis not a bool.
select_block_encoding ¶
select_block_encoding(name, encoding, *, operator, max_bytes=DEFAULT_INPUT_BYTES)
Wrap a block-encoding circuit you built as a block that a Program can call.
Pass a BlockEncoding, for example from
build_block_encoding,
and the operator input A it encodes. The block promises the
(alpha, a, epsilon) block encoding of Gilyén, Su, Low and Wiebe,
arXiv:1806.01838v1, Sec. 4.1, Definition 43 (p. 41),
||A - alpha (<0_a| tensor I) U (|0_a> tensor I)|| <= epsilon, with alpha
and epsilon in the units of A. The formula writes the ancillas first, as the
paper does. NWQLib's encodings place them on the low-order qubits, so in a
Qiskit dense matrix the block is (I tensor <0_a|) U (I tensor |0_a>). The
relation and error are the caller's assertion. Selection checks the widths,
alpha and the error's domain, and does not extract or verify the dense block.
The circuit is copied once, so an encoding with equal shapes or metadata
cannot attach another circuit later. When the encoding's family and gate
counts are known (dense dilation, banded, Pauli LCU or multiplexed Pauli),
the block carries a CX-per-query estimate from them, recorded as the
caller's assertion rather than a verified inventory. Qiskit is imported only
by this call.
Parameters:
-
name(str) –Signature name of the block.
-
encoding(BlockEncoding) –The encoding circuit and its metadata.
-
operator(OperatorInput) –The operator input A.
-
max_bytes(int, default:DEFAULT_INPUT_BYTES) –Default 10 GB (decimal,
10_000_000_000bytes). Limit on the stored data of the copied circuit.
Returns:
-
block(SelectedBlock) –The block, with ports
ancillas(a qubits, omitted when a = 0) andsystem.
Raises:
-
TypeError–If
encodingis not aBlockEncoding. -
ValueError–If the circuit width is not ancillas plus system qubits, the system width is not log2 of A's power-of-two dimension, alpha is not finite and positive, or a given error bound is not finite and nonnegative.
select_signed_pauli ¶
select_signed_pauli(name: str, operator: OperatorInput, *, max_bytes=DEFAULT_INPUT_BYTES) -> SelectedBlock
Build the signed Pauli SELECT block of a Hermitian Pauli operator, the core of its LCU block encoding.
For A = sum_j c_j P_j with real c_j, alpha = sum_j |c_j| and
|G> = PREP|0> = sum_j sqrt(|c_j| / alpha) |j>, SELECT applies
sign(c_j) P_j on label j. Then
(<G| tensor I) SELECT (|G> tensor I) = A / alpha, written with the label
register first as the papers do. The block places the label register on the
low-order qubits, so a Qiskit dense matrix of it, whose qubit 0 is the least
significant index, reads (I tensor <G|) SELECT (I tensor |G>). The recorded
relation string keeps the paper order. This is the LCU relation of An,
Childs and Lin, arXiv:2312.03916v2, Appendix A.3, Lemma 24, Eq. (178), with
each coefficient's sign moved from the two preparation oracles into SELECT.
Both oracles then coincide, so the unpreparation is the exact adjoint of PREP
and a single real preparation serves both sides. Kirby, Motta and
Mezzacapo, arXiv:2208.00567v4, Eqs. (2)-(4), p. 3, use the same form, with
nonnegative weights and each Pauli carrying its sign. Their weights have
unit L1 norm, so their alpha_i, P_i and H are |c_j|/alpha,
sign(c_j) P_j and A/alpha here. Every branch sign(c_j) P_j is
Hermitian and unitary, so SELECT squares to the identity. That is their
Eq. (5), p. 4, the assumption of the Chebyshev walk in their Lemma 1.
Identity terms are included, and no centering or coefficient threshold is
applied. Padding labels apply the identity and get PREP amplitude zero. One
term gives a = 0 and P = 1. The zero operator, and an empty or zero-alpha
input, has no positive-alpha encoding and is rejected. The coefficients are
the real parts of the stored complex128 coefficients, copied bit for bit,
alpha is fsum(abs(c)) over them and each amplitude keeps the operand order
sqrt(abs(c_j)) / sqrt(alpha). A saved block derives them again from the
restored operator in the same way, so alpha, the coefficients and the PREP
amplitudes are equal before saving and after loading. Selection does
O(M*q + 2**a) work.
max_bytes limits the m*(q+16) + 32P bytes, with m = M terms and
P = 2**a >= m, of the label strings with their 16-byte coefficients and of the selection arrays.
The selection arrays stay within 32P because the coefficients are frozen
before the amplitudes are built: coefficients use 8m, amplitudes 8P, and
at most two float64 temporaries 16m, giving 24m + 8P <= 32P. Coefficient
freezing peaks at 16m before amplitudes exist, amplitude freezing at
8m + 16P <= 24P, and these phases are sequential.
Parameters:
-
name(str) –Signature name of the SELECT block in the Program.
-
operator(OperatorInput) –Hermitian Pauli operator A with M terms on q qubits, from
ingest_pauli. -
max_bytes(int, default:DEFAULT_INPUT_BYTES) –Default 10 GB (decimal,
10_000_000_000bytes). Nonnegative limit on the bytes above.
Returns:
-
block(SelectedBlock) –The SELECT, with ports
index(a = ceil(log2 M)qubits, omitted for M = 1) andsystem(q qubits). Itsrecord.semantics.alphaissum_j |c_j|in the units of A.
Raises:
-
ValueError–If the operator has no Hermitian Pauli terms,
max_bytesis negative or too small, or alpha is zero or not finite.
select_pauli_preparation ¶
select_pauli_preparation(name: str, select: SelectedBlock, *, max_bytes=DEFAULT_INPUT_BYTES) -> SelectedBlock
Build the coefficient preparation PREP of a signed Pauli SELECT, PREP|0> = sum_j sqrt(|c_j| / alpha) |j>.
The amplitudes come from the SELECT block, so the PREP is tied to that
SELECT and the pair encodes A/alpha as
select_signed_pauli states.
The PREP's input is the coefficient vector, while the SELECT keeps the
physical operator A. Use the PREP, the SELECT and the adjoint of the PREP
(from transform_block) in that
order on the label register. A single-term SELECT has no label register and
needs no PREP.
Parameters:
-
name(str) –Signature name of the PREP block.
-
select(SelectedBlock) –The untransformed signed Pauli SELECT.
-
max_bytes(int, default:DEFAULT_INPUT_BYTES) –Default 10 GB (decimal,
10_000_000_000bytes). Limit on the bytes of the amplitude vector input.
Returns:
-
block(SelectedBlock) –The PREP block on the label register.
Raises:
-
ValueError–If
selectis not an untransformed signed Pauli SELECT, or it has a single term.
select_pauli_readout ¶
select_pauli_readout(name: str, select: SelectedBlock) -> SelectedBlock
Build the readout block of a signed Pauli SELECT, a label-controlled change to the basis of each Pauli term.
Controlled on the label register, the block V applies H for X, H S^dagger
for Y, and the identity for Z, I and padding labels on each system qubit.
A computational measurement after V is read with the diagonal value D:
the coefficient sign times the parity of the non-identity system qubits
for a used label, and zero for a padding label. Then
V^dagger D V = Pi_used SELECT Pi_used, the SELECT restricted to the used
labels, not the full identity-padded SELECT. No postselection is needed. The label register
is kept and may remain entangled. The block reuses the SELECT's data and
reads no input again. Its gate tables are built when the circuit is
built, and its CX count is bounded by
pauli_readout_cx_bound.
Parameters:
-
name(str) –Signature name of the readout block.
-
select(SelectedBlock) –The untransformed signed Pauli SELECT.
Returns:
-
block(SelectedBlock) –The readout block, with the same ports as
select.
Raises:
-
ValueError–If
selectis not an untransformed signed Pauli SELECT.
select_zero_reflection ¶
select_zero_reflection(name: str, num_qubits: int) -> SelectedBlock
Build the reflection 2|0><0| - I on q qubits, the sign step of the Lanczos Chebyshev walk.
Conjugated by the coefficient PREP G, this block is the reflection
R = (2|G><G| - I) (x) I of Kirby, Motta and Mezzacapo, arXiv:2208.00567v4,
Lemma 1, Eq. (6), p. 4, with the label register written first as in
select_signed_pauli. With the
self-inverse signed SELECT U of an operator A, their Eq. (7) gives
(<G| (x) I)(R U)**k (|G> (x) I) = T_k(A/alpha). Their H has coefficients of
unit L1 norm, which is A/alpha here. The Lanczos method reads expectations
of these Chebyshev polynomials. The sign convention matters under control,
because control makes the global phase relative. The recipe applies X on
every qubit, a multi-controlled Z, X again and a global phase pi, so |0>
gets +1 and every other basis state -1. It uses no extra qubits, and zero
width gives the identity.
Parameters:
-
name(str) –Signature name of the block.
-
num_qubits(int) –Nonnegative width q.
Returns:
-
block(SelectedBlock) –The block, with port
systemof q qubits.
Raises:
-
ValueError–If
num_qubitsis negative or not an integer.
transform_block ¶
transform_block(name: str, block: SelectedBlock, *, control=False, adjoint=False) -> SelectedBlock
Build the controlled version, the adjoint, or both, of a selected block, keeping its global phase.
A block's promise usually fixes only part of the operator, for a
preparation only U|0>. Control and inversion act on the whole selected
circuit, including its global phase, which control makes observable. The new
block therefore keeps the base block's promise as its base_semantics and
declares its own error unknown, because a state or projected-block error of
the base does not bound the transformed operator. A transformed block cannot
be transformed again, so every transform refers to one concrete base. Adding
a control increases the construction work by the controlled cost rule of the
base, and a direct preparation's CX count switches to its controlled form.
The Pauli SELECT and readout counts read the controlled flag instead. A
dense-dilation encoding adds the work of the exact synthesis of its unitary
and of Qiskit's control of the synthesized gates, and a supplied preparation
or encoding adds the same for each dense unitary in its circuit. lower_qiskit
counts these syntheses before they start, against its max_synthesis_work,
or in a Run against ExecutionLimits.max_synthesis_work.
Parameters:
-
name(str) –Signature name of the new block.
-
block(SelectedBlock) –The untransformed base block.
-
control(bool, default:False) –Add one coherent control, as a first port
controlof one qubit. -
adjoint(bool, default:False) –Take the adjoint.
Returns:
-
block(SelectedBlock) –The transformed block.
Raises:
-
ValueError–If neither
controlnoradjointis set,blockis already transformed or has parameters, or its promise does not allow the transformation.
signed_pauli_cx_bound ¶
signed_pauli_cx_bound(index_qubits: int, system_qubits: int, *, controlled=False) -> int
Return an upper bound on the CX gates of a signed Pauli SELECT, optionally with one control.
With a = index_qubits, L = 2**a labels and q = system_qubits, the bound
counts the CX positions of the signed Pauli SELECT construction of
select_signed_pauli:
- Each system qubit receives one uniformly controlled one-qubit gate (UCG)
with a controls. Qiskit's exact
UCGateconstruction (up_to_diagonal=False) uses L one-qubit core gates andL-1CX, followed by an exact completion diagonal ona+1qubits. This core is the decomposition of Bergholm, Vartiainen, Mottonen and Salomaa, arXiv:quant-ph/0410066v2, Sec. III, pp. 3-4, drawn in Fig. 6(a), p. 5, which implements a UCG with k controls by2**kone-qubit gates and2**k - 1CNOTs up to one diagonal(k+1)-qubit gate. In Qiskit 2.5.2, the lower bound of the declared dependency, a random UCGate witha = 1, ..., 4transpiles to exactly3(L-1)CX at optimization level 0, matching the per-UCG total below. - A diagonal on m qubits costs
2**m - 2CX and2**m - 1Rz rotations. Shende, Bullock and Markov, arXiv:quant-ph/0406176v5, Theorem 7 (p. 10) splits a diagonal into a multiplexed Rz withm-1select bits and a diagonal on the remainingm-1qubits. Their Theorem 8 (p. 11) gives2**kCX for a multiplexed rotation with k select bits. Summing overk = 1, ..., m-1gives the count. The completion diagonal (m = a+1) therefore adds2L-2CX, so each UCG costs3(L-1)CX. - The coefficient sign diagonal on the index register (
m = a) adds at mostL-2CX andL-1rotations.
The uncontrolled total is 3q(L-1) + max(0, L-2). With one control, each CX
becomes a Toffoli of 6 CX and one-qubit gates, and each of the
q(3L-1) + L-1 one-qubit operations becomes a controlled one-qubit gate of
at most 2 CX (the two-CX circuit of Shende, Bullock and Markov,
arXiv:quant-ph/0406176v5, Sec. 3.1, p. 9). The six-CX Toffoli is the
textbook circuit reproduced by Shende and Markov, arXiv:0803.2316v1, Fig. 1,
p. 3. Their Theorem 1 shows that no Toffoli circuit of CX and one-qubit
gates uses fewer CX. A global phase becomes a one-qubit phase under control,
which costs zero CX but is not zero work. Removing exact dependencies can
lower these counts, and hardware cost is unknown.
Parameters:
-
index_qubits(int) –Nonnegative width a of the label register.
-
system_qubits(int) –Nonnegative system width q.
-
controlled(bool, default:False) –Count one added coherent control.
Returns:
-
bound(int) –The bound
3q(L-1) + max(0, L-2), or withcontrolled=True6 (3q(L-1) + max(0, L-2)) + 2 (q(3L-1) + L-1).
Raises:
-
ValueError–If a width is negative or not an integer, or
controlledis not a bool.
pauli_readout_cx_bound ¶
pauli_readout_cx_bound(index_qubits: int, system_qubits: int, *, controlled=False) -> int
Return an upper bound on the CX gates of a Pauli label readout block, optionally with one control.
The readout uses the same UCG core and completion diagonal per system qubit
as signed_pauli_cx_bound,
without the coefficient sign diagonal. With L = 2**a, the bound is that
function's value minus max(0, L-2) uncontrolled, or minus
6 max(0, L-2) + 2 (L-1) with one control.
Parameters:
-
index_qubits(int) –Nonnegative width a of the label register.
-
system_qubits(int) –Nonnegative system width q.
-
controlled(bool, default:False) –Count one added coherent control.
Returns:
-
bound(int) –The CX bound.
Raises:
-
ValueError–If a width is negative or not an integer, or
controlledis not a bool.
SelectedBlock ¶
SelectedBlock(*args, **kwargs)
A selected block: its portable record and the trusted code that builds its circuit.
The select_* functions and transform_block return it, and
SelectedBlock.bind builds one
for a new kind of block. A Plan binds the blocks its Program calls, and
lower_qiskit accepts a block only when
its record is exactly the selected definition the Program names, so a record
loaded from JSON or an equal-looking input cannot attach a different circuit.
A controlled or adjoint block keeps its live base block instead of its own
constructor, so the base's gates and global phase remain the single source of
the transformed action. Direct construction raises TypeError.
Attributes:
-
record(SelectedDefinition) –The
SelectedDefinition.
bind ¶
bind(record, *, payload=None, base=None, constructor=None)
Bind trusted code to a selected definition and its inputs, for a new kind of block.
A leaf block gets a constructor that receives (block, arguments,
method_context) and returns a Qiskit circuit, after the common checks of
lower_qiskit. The constructor must implement the record's promised action and work
rule, and must not keep the context getter or the Run. A controlled or
adjoint block gets its base instead of a constructor. Loading a
SelectedDefinition from a file never recreates this binding.
Parameters:
-
record(SelectedDefinition) –The selected definition.
-
payload(object | None, default:None) –The checked input or construction data the constructor reads.
-
base(SelectedBlock | None, default:None) –The base block of a control or adjoint, whose content hash equals
record.base_selection_id. -
constructor(Callable | None, default:None) –The leaf constructor, required unless
recordnames a blocker or a base.
Returns:
-
block(SelectedBlock) –The bound block.
Raises:
-
TypeError–If
recordis not aSelectedDefinitionorconstructoris not callable. -
ValueError–If the base and constructor do not match the record.
SelectedConstruction ¶
Bases: Record
A Program with the selected definition of every block it calls: what estimates, circuit building and OpenQASM export read.
Build it with keyword arguments, for example
SelectedConstruction(program=program, selections=tuple(b.record for b in blocks)),
or read it as plan.construction. program and selections are required.
It is not a Plan, and holds no problem, method or data. Saved JSON keeps the
sharing of Program.definitions, and executable code is bound again by
exact record when the circuit is built, never from saved code.
The checks require exactly one selected definition per Program signature,
with an identical signature, so every block call resolves to one selection,
and every host stage names its exact selected kernel. A Pauli encoding with
a label register must be the ordered PREP, SELECT, PREP-adjoint Sequence on
that register, where the PREP was selected from this SELECT's coefficients
and the adjoint is of that same PREP. A single-term encoding has no label
register and is the SELECT alone. That structure is what makes
<0|U|0> = A/alpha hold for the subgraph.
Attributes:
-
program(Program) –Required. The
Programthat estimates, circuit building and export read. -
selections(tuple[SelectedDefinition, ...]) –Required. One
SelectedDefinitionper Program signature. -
encodings(tuple[PauliEncoding, ...]) –Default
().PauliEncodingsubgraphs, checked as PREP, SELECT and PREP-adjoint. -
kernels(tuple[SelectedKernel, ...]) –Default
(). Host kernel declarations, each named by one hostClassicalStage.
Raises:
-
ValueError–If a signature lacks exactly one matching selection, a host stage and kernel do not match, or an encoding breaks the PREP, SELECT, PREP-adjoint structure.
encoding_semantics ¶
encoding_semantics(root: str) -> BlockSemantics
Return the block-encoding promise of one checked Pauli encoding: A, alpha, label convention and error.
The relation is the LCU block encoding of An, Childs and Lin,
arXiv:2312.03916v2, Appendix A.3, Lemma 24, Eq. (178), in the
real-coefficient form where both preparation oracles equal PREP and
sign(c_j) sits in SELECT. With alpha = sum_j |c_j| the label-zero block is
A/alpha. This is an exact block encoding in the sense of their
Definition 23 (Appendix A.2). Measuring the label register in |0>
succeeds with probability ||A psi||^2 / alpha^2, and the label register is
not restored in general.
Parameters:
-
root(str) –Definition ID of the encoding's Sequence.
Returns:
-
semantics(BlockSemantics) –The SELECT's promise, restated as a block encoding.
Raises:
-
ValueError–If no checked encoding has this root.
PauliEncoding ¶
Bases: Record
Names the PREP, SELECT and PREP-adjoint calls that form one Pauli LCU block encoding in a Program.
Build it with keyword arguments, for example
PauliEncoding(root="encoding", select="select", prepare="prep", unprepare="unprep"),
and pass it in encodings= of
SelectedConstruction, which
checks the structure. root and select are required. The normalization,
the physical operator A and the error come from the checked SELECT, so this
record holds no second copy of them. With the label register in |0> the
subgraph acts as A/alpha.
Attributes:
-
root(Text) –Required. Definition ID of the Sequence that forms the encoding.
-
select(Text) –Required. Signature name of the signed Pauli SELECT.
-
prepare(Text | None) –Default
None. Signature name of the coefficient PREP,Nonefor a single-term encoding. -
unprepare(Text | None) –Default
None. Signature name of the adjoint of that PREP,Nonefor a single-term encoding.
SelectedDefinition ¶
Bases: Record
The portable half of a selected block: its interface, promised action, chosen recipe and cost rules.
Read it as block.record of a SelectedBlock,
or from SelectedConstruction.selections. The select_* functions build it.
It holds everything resource estimates, saved archives and reports need, and
its content hash covers every field. The executable half is the
SelectedBlock that binds trusted code to this exact record. Two recipes for
the same full operator, such as X and HZH, are different selections with
different content hashes and gate counts. decomposition gives the ordered
exact gate recipe when one exists. Otherwise cost_law names the cost rule
of the circuit construction. An unknown cost stays unresolved and never
becomes zero. construction_work counts the documented size rule, not CPU
time or memory. The fields below are read-only.
Attributes:
-
signature(BlockSignature) –Declared interface, equal to the Program's signature of the same name.
-
semantics(BlockSemantics) –The promised action and its approximation: kind, input, relation, normalization
alpha, projectors, errorepsilonand its norm, whether control and adjoint are allowed, and the phase convention. -
implementation(Source) –Versioned Source of the implementation.
-
choice(Text) –Recipe label within the implementation. A supplied circuit gets a fresh unique label.
-
decomposition(tuple[Primitive, ...] | None) –Exact ordered
Primitiverecipe, orNonewhen a cost rule describes the cost. -
cost_law(Source | None) –Source of the size or CX rule, or
Nonewhen there is none. -
cost_parameters(tuple[Binding, ...]) –Exact arguments of that rule for this selection.
-
cost_context(Text) –Scope and limits of the rule, carried into resource quantities.
-
construction_work(Count | None) –Work units of building the block's circuit definition by its size rule, or
Nonewhen unknown. -
controlled(StrictBool) –Whether this selection adds one coherent control to its base.
-
adjoint(StrictBool) –Whether this selection is the adjoint of its base.
-
base_selection_id(Text | None) –Content hash of the base selection of a control or adjoint.
-
coefficient_selection_id(ContentID | None) –Content hash of the SELECT whose coefficients this PREP prepares.
-
blocker(Text | None) –Why the selection cannot run, for a block with a cost rule only or an unsupported block.
-
resource_laws(tuple[ResourceLaw, ...]) –Per-call resource rules.
-
workspace(tuple[Workspace, ...]) –Workspace bytes per call, by location. An empty tuple means unknown, not zero.
Primitive ¶
Bases: Record
One exact gate in a block's recipe. A global phase has no target qubits and becomes observable under control.
SelectedDefinition.decomposition
lists these in order. Build it with keyword arguments, for example
Primitive(gate="cx", qubits=(0, 1)). gate is required.
Attributes:
-
gate(Literal['x', 'h', 'z', 'sdg', 'cx', 'mc_z', 'phase']) –Required.
"x","h","z"or"sdg"on one qubit,"cx"on (control, target),"mc_z"on two or more qubits, or a global"phase"with no qubits. -
qubits(tuple[Count, ...]) –Default
(). Distinct local qubit indices in the block's ports concatenated in signature order, index 0 being the least significant. -
angle(Real) –Default
0.0. Phase angle in radians, nonzero only for"phase", which multiplies the block byexp(i*angle).
Raises:
-
ValueError–If the qubits repeat, their number does not match the gate, or a gate other than
"phase"has an angle.
lower_qiskit ¶
lower_qiskit(construction: SelectedConstruction, *, blocks: tuple[SelectedBlock, ...], max_operations=100000, max_qubits=4096, max_clbits=4096, max_direct_amplitudes=DEFAULT_MAX_DIRECT_AMPLITUDES, max_synthesis_work=1000000000) -> LogicalCircuit
Build the Qiskit circuit of one experiment of a selected construction, after checking its size.
The construction's root must be one static experiment, for example from
Program.select_experiment.
It supports sequences, bound repeats, block calls, coherent regions,
allocation, release, computational measurement and reset. Reallocation and a
register lifetime split across jobs are not supported, and there is no
OpenQASM fallback. A counting pass first checks every reachable binding,
width, direct-preparation size and supported node and counts the repeats
arithmetically, so an oversized or unbound construction is rejected before
Qiskit is imported. It reads the same Program and selected definitions
as the resource estimate, so the circuit and the estimate describe one
construction. Each block call is built by the SelectedBlock whose record
is the selection the Program names. A final measurement batch gives one
circuit, whatever its repetitions or observation kind, and running it is the
Run's task.
Parameters:
-
construction(SelectedConstruction) –The Program and its selected definitions.
-
blocks(tuple[SelectedBlock, ...]) –The bound blocks of the reachable selections, matched to them by their exact records.
-
max_operations(int, default:100000) –Positive, inclusive limit on the Program node visits, repeat counts included.
-
max_qubits(int, default:4096) –Limit on the total declared qubits.
-
max_clbits(int, default:4096) –Limit on the total declared classical bits.
-
max_direct_amplitudes(int, default:DEFAULT_MAX_DIRECT_AMPLITUDES) –Default
65536. Positive limit on the amplitudes of each reachable direct state preparation, whose synthesis work grows asq * 2**q. -
max_synthesis_work(int, default:1000000000) –Positive limit on the total work of the exact dense-unitary syntheses, and Qiskit's control of them, that the controlled blocks of this circuit make, in the work units of the dense synthesis size rule (Circuit-free synthesis laws). Each synthesis is counted before it starts.
Returns:
-
circuit(LogicalCircuit) –The circuit with its register and measurement layouts.
Raises:
-
ValueError–If a limit is invalid or exceeded, the root is not one static experiment, a block is missing or does not match its selection, or a node is outside the supported subset.
LogicalCircuit ¶
LogicalCircuit(construction_id: str, circuit: object, quantum_layout: tuple, measurement_layout: tuple, dynamic_visits: int, construction_work: int, defined_selections: tuple[str, ...])
A Qiskit circuit built from a selected construction, with its register and measurement layouts, before compilation.
lower_qiskit returns it. The fields
below are read-only. Bit and qubit indices are little-endian, index 0 being
the least significant.
Attributes:
-
construction_id(str) –Content hash of the construction the circuit was built from.
-
circuit(object) –The Qiskit circuit. It is not compiled or run.
-
quantum_layout(tuple) –(register, qubit indices)pairs in declaration order. -
measurement_layout(tuple) –(classical value, bit indices)pairs. -
dynamic_visits(int) –Program node visits counted while building the circuit, not a gate count.
-
construction_work(int) –Sum of the size rules of the selected definitions, not measured work or a limit.
-
defined_selections(tuple[str, ...]) –Content hashes of the gate definitions used, base definitions included. Several calls with different arguments can share one definition.
Request readouts and reduce observations¶
A Plan's experiments name the readout each circuit returns. Reducers that turn a saved state into statistics during data collection are registered by name in nwqlib.core.planning.READOUT_REDUCERS, and the modules of the built-in reducers are listed in nwqlib.core.planning.BUILTIN_REDUCER_MODULES. The reduction-allowance row of Add a Method describes the registration.
Experiment ¶
Bases: Record
One measurement of a Plan: a direct readout, or one setting of a measurement batch of the Program.
A Method's planning step builds the experiments of its Plan with keyword
arguments, as Run your own circuit shows.
Experiment(name="ghz", setting="computational", observation=ObservationSpec(kind="counts", shots=shots))
declares a direct readout. An experiment of a measurement batch gives
batch, setting_index and readout instead, and the batch fixes the
readout kind, the setting and the number of repetitions. name is
required.
Attributes:
-
name(Text) –Required. Name of the experiment, unique in the Plan.
-
setting(Text | None) –Default
None. Readout setting label of a direct experiment. A batch experiment takes it from the batch. -
observation(ObservationSpec | None) –Default
None. The readout (ObservationSpec) of a direct experiment. -
readout(ReadoutDetails | None) –Default
None. The Method's readout details of a batch experiment (ReadoutDetails). -
batch(Text | None) –Default
None. Definition id of the Program'sMeasurementBatch, orNonefor a direct experiment. -
setting_index(Count | None) –Default
None. Index of the setting in that batch.
Raises:
-
ValueError–If a direct experiment lacks
settingorobservationor hasreadout, if a batch experiment hassettingorobservationor lacksreadout, or if only one ofbatchandsetting_indexis given.
ObservationSpec ¶
Bases: ReadoutDetails
The readout of one experiment: what is measured and with how many shots.
A Method's planning step builds it with keyword arguments, for example
ObservationSpec(kind="counts", shots=1000), as Run your own
circuit shows. kind is required, and the other
fields below have defaults. Bit and qubit positions count from the least
significant. Each kind accepts only the fields it uses:
counts:1 <= shots <= 2**63 - 1(the int64 count range), no labels, qubits or position, and the unconditional population. The Program's classical bits fix the measured bits.probabilities: distinct qubits for the marginal, with no labels, shots or position.pauli_expectation: distinct Pauli labels over I, X, Y and Z and an optional position, with no qubits or shots.host_scalars: distinct labels naming the statistics, with no qubits, shots or position, and the unconditional population.amplitudes: anamplitudesdeclaration, with no labels, qubits, shots or position, on the unconditional final state.estimated_observable: anestimate, with no amplitudes, labels, qubits, shots or position, on the unconditional final state.trajectory: at least one point inpositions, zero shots and the unconditional population, with the single-readout fields empty. An empty request is algebraic work without a measurement, so it declares no experiment.
Only a trajectory has positions. Pauli expectations are read before
the logical instruction at position, and None means the end. Counts
use the Program's measurements in the computational basis, and
probability marginals are read after the final measurements are removed.
No full state is saved.
An exact trajectory declares readouts that do not disturb one coherent
evolution, at several points of it. Its shot count is zero. Each result
is kept with its point ID and its label or outcome, and the saved values
are reductions of the simulator state at those points. Sampled readouts
describe the Program's measurements and use their declared positive shot
counts. The readouts of a trajectory are deterministic, and its zero
shots do not allow measurement-conditioned, reset, postselected, noisy
or outcome-dependent evolution. Host, amplitude, sampled and
provider-estimate readouts keep their own meanings.
Readout requests are combined only when they have the same body,
position, readout view (a basis change applied for the readout and then
undone), readout kind and population. Two requests share one saved value
only when they also name the same label, outcome or amplitude
declaration, or the same reducer with the same parameters. A union of
distinct requested labels still holds one item per distinct label, and
every association of a point with its result is kept when a value is
shared. The limit check counts the items of every declared point,
N_items = sum_k L_k with L_k the number of items of point k.
Attributes:
-
kind(Literal['pauli_expectation', 'counts', 'probabilities', 'host_scalars', 'amplitudes', 'estimated_observable', 'trajectory']) –Required.
"pauli_expectation","counts","probabilities","host_scalars","amplitudes","estimated_observable"or"trajectory". -
shots(Count) –Default
0. Positive number of shots forcounts, and zero for the readouts without a prescribed number of shots, a trajectory included. -
amplitudes(AmplitudeReadout | None) –Default
None. The amplitude output of theamplitudeskind (AmplitudeReadout). -
estimate(ObservableEstimateSpec | None) –Default
None. The weighted Pauli sum whose expectation a provider estimates, for theestimated_observablekind (ObservableEstimateSpec). -
position(Count | None) –Default
None, which means the end of the body. Number of bound logical operations before the readout point. Zero reads the initial state, and the body length reads the final state. The end is resolved before the circuit is prepared. Building the circuit keeps this boundary when it expands operations and, on a backend that runs readout views, inserts them there. -
labels(tuple[Text, ...]) –Default
(). Pauli or host-scalar labels, in the order of the returned values. -
qubits(tuple[Count, ...]) –Default
(). Measured or marginal qubit positions, least significant first. -
population(Literal['unconditional', 'native_conditioned']) –Default
"unconditional"."unconditional"or"native_conditioned", the measured shots that the readout covers. -
padding(Text) –Default
"no padding; all returned bit patterns belong to the declared registers". Meaning of any padding, and which returned coordinates belong to the system. -
positions(tuple[ObservationPoint, ...]) –Default
(). The points of a trajectory, in order. Each point names a boundary in the planned coherent body, its readout kind and its ordered labels or marginal qubits, and may name a readout view. The points share one preparation and measurement, and their order and payload sizes are part of the Plan.
Raises:
-
ValueError–If a field is given that the kind does not use, a field the kind needs is missing, trajectory point IDs repeat, or the point boundaries decrease.
point_observation ¶
point_observation(point_id)
Return the single-point readout of the trajectory point point_id.
Pauli, probability and amplitude points map to the readout kinds of
the same name, so their saved values keep those kinds' records and
checks. A reduction point's readout is the single-point trajectory of
that point, and its saved values are ReducedValues records.
Parameters:
-
point_id(str) –ID of a point in
positions.
Returns:
-
readout(ObservationSpec) –The point's readout.
Raises:
-
ValueError–If the trajectory has no such point.
point_observations ¶
point_observations()
Return the single-point readout of every point, by point ID, in one pass over the points.
Returns:
-
readouts(dict[str, ObservationSpec]) –Each point's readout, as
point_observationgives it.
point_readout_fields ¶
point_readout_fields(point)
Return the fields of one point's single-point readout, without building an ObservationSpec.
point_observation builds its readout from these fields, so a byte
bound of the stored readout can be computed from the same fields
without building it. It takes the point object itself, so no ID
lookup is needed. Pauli, probability and amplitude points take their
kind, labels, qubits, amplitude declaration and the unconditional
population, and a Pauli point also its position. Their point ID,
readout view and non-Pauli position stay associated only through the
preparation record, the point ID, the boundary and the content hash
of the trajectory. A reduction point's readout is the single-point
trajectory of that entire point, so it copies the point's ID,
declared position, reducer, parameters and readout view. Every other
field keeps its default.
Parameters:
-
point(ObservationPoint) –A point of a trajectory.
Returns:
-
fields(dict) –Keyword arguments of
ObservationSpec.
reject_unsupported_schedule ¶
reject_unsupported_schedule(backend)
Raise if backend cannot run this multi-point schedule, before any circuit is built or submitted.
A backend calls it to keep its supported single-point readouts and reject the multi-point schedules, readout views and reductions that it does not run, before building or submitting a circuit. The error names the backend and the feature.
Parameters:
-
backend(str) –Name of the backend, used in the error message.
Raises:
-
ValueError–If this readout is a trajectory.
unsupported_schedule ¶
unsupported_schedule()
Describe this readout's multi-point schedule, readout views and reductions, or return None.
Backends name this description when they reject a schedule they do
not run. A single-point readout returns None.
Returns:
-
description(str | None) –The description.
ReductionContext ¶
ReductionContext(prepared_id: str, probability_window: float | None, probability_window_exclusions: tuple[str, ...] | None, state_error: float | None = None, state_error_reason: str | None = None, modulo_phase_state_error: float | None = None)
What a reduction of a saved state knows about the preparation that produced the state.
A reducer registered with receives_context=True receives it as the
keyword context when it runs. Its fields are read-only values of the
preparation record (PreparedArtifact)
that produced the saved state.
A saved-state reduction receives a native error estimate modulo the global phase, with its conditions, when its declared outputs do not change under that phase. A state uncertainty defined with the phase is unavailable unless a separate phase-error model supplies it, and the context reports that reason. A host correction of the phase adds its finite multiplication and modulus error to every user of the corrected array. Projected mass checks can use the modulo-phase estimate even when other diagnostics of the same reducer depend on the phase. If an assumption of the native estimate remains unavailable, they use the probability window, propagated through the phase correction, and report the original exclusions.
The preparation record's state error (PreparedArtifact.state_error)
bounds the computed state only up to one common global phase. It does
not bound the exact prefix phase, the summation that accumulates the
prefix phase, the subtraction that forms the correction angle, or an
amplitude defined with its phase, and adding a host term to it gives no
finite estimate for such a quantity. A saved state used by a
phase-sensitive and a phase-invariant reducer is corrected once, and
both see the same array and the same host error bound of the preparation
record (PreparedArtifact.statevector_roundoff). The phase-invariant
reducer therefore includes the error of the phase product, even though
its own registration did not request the phase correction.
Attributes:
-
prepared_id(str) –Content hash of the preparation record that produced the saved state.
-
probability_window(float | None) –The preparation record's
saved_state_probability_window, its probability window propagated through the host correction of the saved state, orNonewhen that correction was not assessed, which gives no finite budget for a mass check. It does not bound a host contraction of the saved state, which has its own accumulated error. -
probability_window_exclusions(tuple[str, ...] | None) –The preparation record's
probability_window_exclusions, the operations, readout path, simulator version or non-default compiler optimization level whose effect the window does not bound. Empty when the whole execution lies inside the window,Nonewhen not assessed. -
state_error(float | None) –The state error bound that matches the reducer's declared phase behavior. For a reducer registered
phase_invariantit ismodulo_phase_state_error. For any other reducer it isNone, since a bound defined with the phase is unavailable. It is alsoNonewhen an assumption of the native estimate remains unavailable. A reducer uses its probability window when this value is unavailable, and the original exclusions stay available inprobability_window_exclusions. -
state_error_reason(str | None) –Why
state_errorisNone. For a reducer that is not registered phase invariant it is the reason a bound defined with the phase is unavailable, and otherwise the preparation record's native or host reason.Nonewhenstate_erroris available. -
modulo_phase_state_error(float | None) –The preparation record's
saved_state_errorafter resolving the labels that the reducer declares, a distance modulo one common global phase that includes the error of the host phase product, orNonewhen an assumption of the native estimate or the host assessment is unavailable. A phase-sensitive reducer may use it only for outputs shown separately to be phase invariant, as the projected mass checks do.
registered_reducer ¶
registered_reducer(name)
Return the reducer registered under name, or None when there is none.
On a miss, each module of BUILTIN_REDUCER_MODULES is imported (an
already imported module is not imported again, and a module registers its
reducers once, at import), and READOUT_REDUCERS is read again.
Parameters:
-
name(str) –The reducer's registered name.
Returns:
-
reducer(Reducer | None) –The registered reducer, with its shape, work and execution functions.
ObservationChunk ¶
Bases: Record
The statistics of one measurement, or of one point of a trajectory, as stored with a Run or Result.
data.observations.chunks holds them, and a Method's analyze reads
them, as Run your own circuit shows. A chunk keeps
the sufficient statistics of its measurement, never one record per
shot. Chunks of different attempts stay distinct even when their values
are equal. Their identifiers record where the data came from and are not
evidence that random measurements are independent.
Read probabilities and counts with histogram(), whose layout
Histogram states, and build such a chunk
with from_histogram. Counts are stored as JSON CountBin records.
Every count, the exact total and the requested shots are at most
2**63 - 1, the int64 maximum of the count weights that the reader
returns, and a chunk outside that range is rejected. A probability
marginal stores its values in binary arrays. The chunk holds one
ProbabilityArrays record with the array manifests and the summary
values computed when the arrays were saved. The arrays live in the array
store of the Run or Result that holds the chunk. A chunk keeps a private
reference to that store, which is not a field. Saving the arrays,
reopening a Run (load_run), loading a Result (load_result) and the
chunk's own revise and copies set or carry it, and histogram() reads
the arrays through it on first use, once per payload for the store's
lifetime. A chunk rebuilt from JSON in any other way has no such
reference, and its histogram() raises an error that names the loader
to use.
A trajectory measurement stores one chunk per observation point. The
chunk names its point and resolved boundary, so a saved value maps to
its body, point and preparation record after reloading. A trajectory
stores one full declaration in its preparation record and one row per
point, with only that point's readout declaration and the content hash
of the shared declaration on the row. Validating the preparation record
and indexing the points visit the schedule once, each chunk validates its
own declaration and values, and readout() returns the stored
single-point readout. Storage and validation are linear in the total
accepted declarations and payloads, with no per-point copy or rescan of
the full schedule. The single-point readout is
ObservationSpec.point_observation of the point, and trajectory_id is
the content hash of the full declaration. Joining the chunk to its
preparation record, in validate_unit_bound and when the Run records the
chunk, checks both. Point chunks share their measurement's completion,
preparation, shots and native work. The chunks of one measurement share
its run, attempt and job, and differ in chunk. A missing point makes
the quantity that depends on it incomplete. It never causes the shared
prefix to be run again in analysis or loading.
Attributes:
-
run_id(Text) –Identifier of the Run that made the measurement.
-
execution(Literal['quantum_circuit', 'host_kernel']) –"quantum_circuit"or"host_kernel", the kind of computation that produced the data. -
plan_id(ContentID) –Content hash of the Plan.
-
realization_id(ContentID) –Content hash of the experiment's concrete parameter values.
-
prepared_id(ContentID) –Content hash of the preparation record of the circuit or host computation that was run.
-
experiment(Text) –Name of the experiment in the Plan.
-
setting(Text) –The readout or batch setting.
-
bindings(tuple[Binding, ...]) –The experiment's parameter values, in order.
-
quantum_layout(tuple[RegisterMap, ...]) –Order of the quantum registers, which fixes how outcome coordinates are read.
-
classical_layout(tuple[RegisterMap, ...]) –Order of the classical registers, which fixes how count labels are read.
-
attempt(Text) –Identifier of the attempt that was set aside for this measurement.
-
job(Text) –Identifier of the job that produced the data, not of a later reduction.
-
chunk(Text) –Position of this part within that job.
-
observation(ObservationSpec) –The readout against which the returned statistics are checked. For a trajectory point, it is that point's single-point readout.
-
population(Literal['unconditional', 'native_conditioned', 'unknown']) –"unconditional","native_conditioned"or"unknown", which shots the statistics cover. -
returned_shots(Count | None) –Total of the returned counts, or None when no shot total is available.
-
trajectories(Count | None) –Number of trajectories, or None when unavailable or not applicable.
-
values(tuple[Statistic, ...]) –Sufficient statistics, each kept with its original label and its physical normalization. Probabilities have one
ProbabilityArraysrecord, and counts oneCountBinper stored outcome. Read both withhistogram(). -
source(Source) –The backend or host code that produced the data (
Source). -
selected_kernel_id(ContentID | None) –Content hash of the host computation's declaration, or None for a circuit.
-
physical_scale(PhysicalScale | None) –Positive factor that restores physical magnitude to this chunk's unit-normalized data, or None. Its meaning belongs to the Method. For LCHS and the QLS
qsvt_inversesolver it is the norm of the output vector, and analysis multiplies the unit solution direction by it. For Expectation, Lanczos and QPE it is the norm of the supplied input state. Expectation's physical quadratic form uses it, and the eigenvalue Methods record it with the input, since an energy does not depend on the state's norm. QHD, FixedGCIM and ADAPT host chunks carry None, because their scalars need no recovery, a QLS shortcut chunk carries None because the shortcut recovers no physical norm, and quantum circuit chunks other than amplitude readout carry None. -
physical_scale_unavailable(Text | None) –Why
physical_scaleis None, because the scale is unavailable or no recovery applies. Host and amplitude chunks set exactly one of the two fields. -
artifacts(tuple[ArtifactManifest, ...]) –Manifests of the arrays saved from this measurement.
-
applications(tuple[KernelApplication, ...]) –Records of the host operator applications.
-
unavailable(tuple[UnavailableOutput, ...]) –Named outputs that could not be produced.
-
point(Text | None) –ID of the trajectory point whose values this chunk holds, or None for a readout without a point schedule.
-
boundary(Count | None) –Resolved boundary of that point in the planned body, or None.
-
trajectory_id(ContentID | None) –Content hash of the trajectory declaration that the point belongs to, held by the preparation record, or None.
acquisition_key ¶
acquisition_key
(run_id, attempt, job, chunk), which identifies the data of one measurement.
A Run stores, deduplicates and joins observations under this key. Two
chunks with equal values but different keys are different
measurements, except that the point chunks of one trajectory
measurement share its run, attempt and job and differ only in
chunk.
declares_readout_of ¶
declares_readout_of(receipt)
Return whether this chunk holds the readout that its preparation record declares.
A point chunk holds the single-point readout of its point in the
preparation record's trajectory, whose content hash is its
trajectory_id. Any other chunk holds the record's readout itself.
The record's point lookup is indexed, so K point chunks join in O(K)
lookups.
Parameters:
-
receipt(PreparedArtifact) –The preparation record.
Returns:
-
declared(bool) –Whether the readouts match.
from_histogram ¶
from_histogram(outcomes, /, **fields)
Build a probabilities or counts chunk from its outcomes.
Validation is that of every other construction path, including the
count range 0 to 2**63 - 1. A probability chunk keeps its
arrays in memory, with manifests that carry the digest of their
bytes. Its stored encoding, dense or sparse, and its sorted order are
those of every saved probability readout.
Parameters:
-
outcomes(Mapping | tuple) –Either a mapping from bit-string key to weight, with keys spelled as the chunk stores them (rightmost character bit 0, no register separators), or a pair
(indices, weights)in the layout ofHistogram: 1-D indices for a width of at most 64 or(entries, words)packed indices for every width, integer counts or float64 probabilities. Empty arrays of shape(0,)or(0, words)describe an empty chunk whatever their dtype. -
**fields(object, default:{}) –The other ObservationChunk fields except
values.observationselects counts or probabilities. The width is the number of its qubits (probabilities) or of the bits ofclassical_layout(counts).
Raises:
-
TypeError–When
valuesis also supplied. -
ValueError–For another readout kind, indices outside the width or in another layout, weights of another type or length, or any check of the chunk itself.
histogram ¶
histogram()
Return the outcomes of this probabilities or counts chunk in the Histogram layout.
The chunk builds its Histogram on the first call and returns the same
read-only object afterwards. The slot that holds it is not a field, so
equality, identity and serialization never see it. A probability chunk
rebuilt from stored JSON returns a Histogram whose width and
entries come from its summaries; its arrays are read through the
artifact store of its Run or Result on the first access to the weights
or indices, once per payload for the store's lifetime, with no
recheck of the values or summaries.
Raises:
-
ValueError–For any other readout kind, or for a probability chunk that has neither its arrays nor a store to read them from.
readout ¶
readout()
The readout whose statistics this chunk holds, its observation.
For a trajectory point chunk that is the point's one-point readout, which the chunk stores, so nothing is rebuilt.
validate_unit_bound ¶
validate_unit_bound(receipt)
Check that exact probabilities, Pauli expectations and branch masses exceed one only within the roundoff window of the executed circuit.
The window follows the native operation count of the preparation record, so this check joins the chunk to its own preparation record. Alone, the chunk accepts nonnegative probabilities and masses and finite expectations. Counts and host scalars have no roundoff endpoint here.
The window is derived from the preparation record rather than stored
on the chunk. A stored copy would change the record format and add
derived data that every reader would have to check against its
record. The cost is that each place where a new chunk meets its
record must call this method. The shared places are the decoding of
backend output and the validation of a standalone Result before it is
saved. Reopening a Run or loading a Result reads chunks that passed
one of them, and it does not call this method again. A Method's
Result validation may add its own calls, as QLS does for its masses.
A new producer of chunks that bypasses both places must add the call.
Engineering constants defines the
window in its exact_probability_window paragraph.
A trajectory point chunk also joins its record's trajectory
declaration: the same trajectory_id, the declared point's
single-point readout and its resolved boundary. A reduction point has
no endpoint here, because host contractions of saved states have
their own accumulated error, which the record's probability and Pauli
readout term does not bound. Amplitude-derived masses use the
record's saved_state_probability_window, which includes the host
correction of the saved state, and are checked for nonnegativity only
when that correction was not assessed.
Parameters:
-
receipt(PreparedArtifact) –The chunk's preparation record.
Raises:
-
ValueError–If the record is not this chunk's, a point chunk does not match its declared point or boundary, or a value exceeds its endpoint by more than the window.
Histogram ¶
Histogram(width, integers, weights)
Outcome indices and weights of one probabilities or counts chunk.
ObservationChunk.histogram() returns it. Code that reads
observations can rely on the layout below. All arrays are read-only.
width: the readout width w, the number of observed qubits (probabilities) or of classical bits over the whole classical layout (counts).entries: the number of stored entries, counting any stored zero weight, so it is not the number of nonzero weights.weights: a 1-D array with one weight per entry, float64 for probabilities and int64 for counts.indices(): for w <= 64, a 1-D uint64 array with one outcome index per entry. Bit 0 of an index is the first observed qubit (probabilities) or classical bit 0 (counts), which is the rightmost character of the chunk's bit-string key. For w > 64 it raises ValueError naming the width.packed_indices(): for every w, a 2-D uint64 array of shape(entries, words)withwords = max(1, ceil(w/64)). Word 0 holds the least significant 64 bits and the padding bits above w are zero.index_list(): the outcome indices as Python integers, for every w.
Entries keep the order in which the chunk stores them; nothing is sorted.
A probability chunk stores a dense marginal by outcome position, every
outcome including exact zeros, or a sparse marginal with strictly
increasing indices of its nonzero values (ProbabilityArrays), so its
entries are in increasing index order; a dense marginal's indices are
formed when they are first requested. For a histogram obtained from a
validated count chunk, every weight and the exact total are in
[0, 2**63 - 1], and the total equals returned_shots and does not
exceed the requested shots. Because the weights are nonnegative, an int64
sum of this single chunk's weights cannot overflow. Totals combined across
acquisitions require an overflow-safe accumulation. An empty chunk gives
indices() of shape (0,) and packed_indices() of shape
(0, words).
Attributes:
-
width–Readout width w.
-
entries–Number of stored entries.
-
weights–Read-only 1-D float64 probabilities or int64 counts.
PreparedArtifact ¶
Bases: Record
The preparation record of one circuit or host computation: what was built, for which target, and its roundoff bounds.
run.data.receipts and result.data.receipts hold one per preparation.
It describes the prepared circuit and holds no executable bytes.
snapshot names a circuit built in this process and is not a verified
file digest. target and compiler are recorded when the circuit is
prepared. The concrete parameter values (realization) survive failed
attempts and the reopening of a saved Run, so recovering them needs no
completed observation and no guess of a default point. Reading this
record loads no circuit data. The fields below are read-only.
Attributes:
-
execution(Literal['quantum_circuit', 'host_kernel']) –"quantum_circuit"or"host_kernel", the kind of preparation. -
plan_id(ContentID) –Content hash of the Plan.
-
realization_id(ContentID) –Content hash of
realization. -
realization(Realization) –The experiment and its concrete parameter values, kept even before any result exists.
-
construction_id(ContentID) –Content hash of the construction used for this preparation.
-
snapshot(Text) –Name of the circuit built in this process, not a digest of its bytes.
-
target(Source) –The backend target (
Source) when the circuit was prepared. -
compiler(Source) –The compiler or preparation code (
Source). -
runtime(RuntimeOptions) –The runtime seed and backend preparation options in effect.
-
observation(ObservationSpec) –The readout (
ObservationSpec). -
quantum_layout(tuple[RegisterMap, ...]) –Layout of the logical quantum registers.
-
classical_layout(tuple[RegisterMap, ...]) –Layout of the logical classical registers.
-
native_basis(tuple[Text, ...]) –The backend's gate names after preparation.
-
environment(tuple[Source, ...]) –Versions of the packages used by the preparation (
Sourcerecords). -
preparation_time(Text) –Time of the preparation.
-
construction_work_reserved(Count) –Circuit construction work counted before execution, in work units.
-
logical(LogicalPreparationReceipt | None) –Record of how the logical circuit was built, or None for a host-only preparation.
-
native_operations(Count | None) –Prepared operation count, or None when unavailable. For a coherent statevector readout on Aer, a trajectory included, it counts the native evolution operations that execute, including every executed forward and inverse view operation, and no save instruction: a save evaluates or copies the current state and inserts no state error into the continuing state. It is not multiplied by the number of saved labels or points, and one whole-trajectory count gives a conservative window for every point. On Aer, a body with control flow and sampled counts count every instruction of the prepared native circuit. Other adapters state their own count.
-
host_preparation_work_reserved(Count) –Host setup work counted for this preparation.
-
selected_kernel_id(ContentID | None) –Content hash of the host computation's declaration, or None for a circuit.
-
transformation(Text) –Description of how the planned circuit was turned into the backend's circuit.
-
population(Literal['unconditional', 'native_conditioned', 'unknown']) –"unconditional","native_conditioned"or"unknown", which shots the measured counts cover. -
payload(PayloadRef | None) –Where the backend's circuit bytes are saved, or None. It holds no bytes itself.
-
native_quantum_layout(tuple[RegisterMap, ...]) –Layout of the compiled quantum registers.
-
native_classical_layout(tuple[RegisterMap, ...]) –Layout of the compiled classical registers.
-
logical_to_native(tuple[Count, ...]) –The compiled wire of each logical wire, in order.
-
backend_configuration_id(ContentID | None) –Content hash of the backend configuration, or None for host execution.
-
counts_sampling(CountsSampling | None) –How the counts are sampled (
CountsSampling), or None for other readouts. -
provider_options_json(Text | None) –The provider settings in effect, saved without credentials.
-
probability_window_exclusions(tuple[Text, ...] | None) –Labels of the native operations, readout path, simulator version or non-default compiler optimization level whose effect the derivation of
probability_windowdoes not bound. An empty tuple means the whole execution lies inside it. None means the preparing backend did not assess it. -
body_length(Count | None) –Number of bound logical operations of the planned body, the largest trajectory boundary, recorded for a trajectory, and None otherwise.
-
boundaries(tuple[Count, ...]) –Resolved boundary of each trajectory point in declaration order, with the end-position shorthand resolved before native preparation; empty for other readouts.
-
template_seed(Count | None) –Seed of the per-construction native template that the backend prepared this circuit from, or None when the backend used no template.
-
statevector_roundoff(tuple[Nonnegative, Nonnegative] | None) –The bound
(t, e)on the error of the host phase correction of this execution's saved statevectors, the componentwise maxima over the record's saved states. It is included in the error of every user of those statevectors (saved_state_errorandsaved_state_probability_window). The pair(t, e)bounds the output phase product on saved statevectors.(0.0, 0.0)denotes an assessed zero-error operation, including no product or multiplication by the represented factor(1.0, ±0.0)under the host arithmetic model.Nonemeans the host correction was not assessed.
probability_window ¶
probability_window: float
The accepted binary64 roundoff between one and the total of an exact probability population of this execution.
It is max(1e-12, (c*G + 2**(n+1) + 10)*u) for G native operations,
the circuit width n, the executing simulator's per-instruction
constant c and u = 2**-53, as Engineering
constants derives. A target without a
derived constant of its own uses Aer's, the larger one. Host and
unknown counts keep the fixed floor 1e-12.
saved_state_probability_window ¶
saved_state_probability_window
probability_window propagated through the host correction of a saved state, or None.
omega_saved = omega + (2t + t**2)(1 + omega) + 2(1 + t)(1 + omega) e
+ e**2 with (t, e) the record's statevector_roundoff. An unassessed correction
gives None, not the uncorrected window, so it yields no finite
mass-check budget.
saved_state_error ¶
saved_state_error(resolved=())
Return (delta_saved, reason): state_error(resolved) after the host correction of a saved state.
delta_saved = delta + t (1 + delta) + e with (t, e) the
record's statevector_roundoff. Like state_error it
is a distance modulo one common global phase, conditional on the
native first-order model. It returns the native unavailable reason
unchanged when delta is unavailable, and an unavailable reason for
the missing premise when the host correction was not assessed. Every
consumer of a saved statevector uses it; direct native probability
and Pauli saves keep state_error, since their buffers undergo no
host correction.
state_error ¶
state_error(resolved=())
Return (delta, None) for this execution's final-state budget, or (None, reason).
delta is native_state_error of the native operation count with the
target's derived per-instruction constant, a first-order bound on
||psi_hat - exp(i phi) psi||_2 against the unitary native circuit.
It describes distance modulo one common global phase. It does not
bound the exact prefix phase, the summation that accumulates the
prefix phase of a saved state, the subtraction forming its correction
angle, or a phase-defined amplitude. The users of a saved statevector
use saved_state_error. It exists only
when the derivation covers the whole execution, that is, for a
circuit on a target with a derived constant, a known operation count
and assessed probability_window_exclusions that are all in
resolved, the labels whose effect the caller's own readout bounds.
Unlike probability_window, an unknown count or target gets no
default constant and no floor. The budget enters the bound on
differences of point probabilities, which QHD uses for the tie window
of its most probable point. The Aer constant that
probability_window takes for an unknown target has no derivation
for that target, and the 1e-12 floor that it keeps for an unknown
count is an input convention for a population total, not a derived
bound, so neither can stand in for delta.
Save and restore a method's data¶
A Method whose Runs or Results are saved implements save_archive(plan, files) and load_archive(saved, files) and names its Result class in result_type. Both hooks receive an ArchiveFiles object, save_archive reads the bound blocks from plan.blocks, and When the archive hooks are required shows them for a small Method.
ArchiveFiles ¶
ArchiveFiles(path, max_bytes)
The folder of a saved Result or Run, as passed to a Method's save_archive and load_archive hooks.
A Method author writes and reads the Method's data through the files
argument of those hooks, as Add a Method and
Run your own circuit show, rather than through a
serializer of its own. Its operations keep each input in its own
representation and count the written bytes against the folder's limit.
Files have readable names, are created new and are never overwritten.
An array or circuit used by several parts is written once per save and
read once per load. Arrays load as read-only NumPy memory maps and are
neither normalized nor content-hashed. The headers of input arrays are
checked against their representation, dimensions and declared encoding.
These checks do not validate every value or restore the digest that the
input had when it was first accepted. Keep the folder available while
using the restored Plan. Circuits use Qiskit's public QPY format. The
memory and CPU use of the SDKs is unknown.
Open the folder path, with a limit of max_bytes on the bytes written.
NWQLib opens the folder and passes it to the hooks, so Method code does not build one.
Parameters:
-
path(str | PathLike) –The folder.
-
max_bytes(int | None) –Positive limit on the bytes written, or
Nonefor a folder without a limit of its own.
Raises:
-
ValueError–If
max_bytesis neither a positive integer norNone.
write_plan ¶
write_plan(plan)
Return the Plan's JSON description.
Its Problem, Method and output entries are descriptions only.
read_plan replaces them with the objects that their own readers
restored.
Parameters:
-
plan(Plan) –The Plan.
Returns:
-
description(dict) –The Plan's JSON description.
read_plan ¶
read_plan(data, *, problem, method, output, reconstruction=None)
Rebuild a Plan from its JSON description and the Problem, Method and output already restored.
Parameters:
-
data(dict) –The description that
write_planreturned. -
problem(ProblemRecord) –The restored Problem.
-
method(Method) –The restored Method.
-
output(OutputRecord) –The restored output.
-
reconstruction(object | None, default:None) –The Method's restored interpretation data, which replaces the saved one when given.
Returns:
-
plan(Plan) –The Plan. A Method that binds circuit blocks binds them with
plan._bind(...)before returning the Plan fromload_archive.
read_problem ¶
read_problem(data)
Rebuild a built-in Problem from its saved description, with its inputs restored.
The Problem class is chosen from a fixed table of the built-in kinds, so saved text never selects an arbitrary class.
Parameters:
-
data(dict) –The description that
write_problemreturned.
Returns:
-
problem(ProblemRecord) –The Problem.
read_output ¶
read_output(data)
Rebuild a built-in output from its saved description.
The output class is chosen from a fixed table of the built-in kinds,
as in read_problem.
Parameters:
-
data(dict) –The description that
write_outputreturned.
Returns:
-
output(OutputRecord) –The output.
write_state ¶
write_state(name, state)
Save a state input, its preparation and its circuit, and return its description.
The vector and its normalized direction are stored as given, without normalizing them again, so scale and phase survive exactly. When the two arrays have the same dtype, shape and bytes (a unit-norm vector is its own direction), one array is written and the direction names its file. The comparison is one pass over the entries.
Parameters:
-
name(str) –Prefix of the file names.
-
state(StateInput) –The state input.
Returns:
-
description(dict) –JSON description that
read_statereads.
write_operator ¶
write_operator(name, operator)
Save an operator in its own representation, never a converted one, and return its description.
Dense, CSR, CSC, Pauli and periodic-stencil inputs keep their arrays or parameters, so saving never turns a sparse or Pauli operator into a dense matrix. A declaration without data is saved as a declaration.
Parameters:
-
name(str) –Prefix of the file names.
-
operator(OperatorInput) –The operator.
Returns:
-
description(dict) –JSON description that
read_operatorreads.
read_path ¶
read_path(name)
Register a file that the Method's saved data depends on, and return its path.
A load_archive hook that restores cached data must call it for
every file it refers to, including files whose contents it reads only
later. Registration reads the file's metadata only, so a missing file
raises FileNotFoundError here, and it keeps the file from being
removed as unused when the Run is reopened. A folder opened with a
limit counts the file's size against it, and a folder opened without
one (max_bytes=None) counts nothing.
Parameters:
-
name(str) –The file name, without a directory part.
Returns:
-
path(Path) –The file's path.
blocks ¶
blocks
The live circuit blocks that the Method bound to this Plan with _bind.
A Method's archive hook saves them, as Run your own circuit shows.
write_blocks ¶
write_blocks(blocks, files)
Return the saved form of a Method's selected blocks, for its save_archive hook.
Call it in save_archive(plan, files) with the archive object files that
the hook receives, and store the returned dict with the saved Plan. Each
block is written once, base blocks before the blocks that transform them.
Only the built-in preparation, Pauli SELECT and readout, reflection and
transformed blocks can be saved. A signed Pauli SELECT or readout saves its
operator and amplitude array only, because loading derives the coefficients
from the operator, and blocks that share an operator or amplitude array
write it once.
The selection limit of
select_signed_pauli does not
bound the whole archive or the live packed operator. For m terms on q qubits,
P = 2**a >= m padded amplitudes and w = ceil(q/64), the packed operator
holds B_op = 16mw + 16m bytes of numerical data and the one shared
amplitude file adds 8P, so
B_archive,data = 16mw + 16m + 8P,
plus four NPY headers, at most 256 bytes each for these fixed-dtype
rank-one and rank-two arrays, and the graph and manifest JSON. The NumPy NPY
writer
(v2.5.2)
writes a contiguous array with at most one data chunk of
min(array.nbytes, 2**24) bytes, and an array that must be copied because
it is not contiguous needs a second such buffer. With contiguous packed and
amplitude arrays, the numerical peak while writing is
B_held,other + B_op + 8m + 8P + min(max(8mw, 16m, 8P), 2**24) + H_archive,
where H_archive, the graph serialization and writer bookkeeping, is not
fixed for an arbitrary block graph. The peak of a save is the larger of this
and the selection peak, counting shared operator bytes once. A transport that
buffers a whole archive needs its own allowance. This function takes no byte
limit, and the archive's byte limits apply to each file it writes.
Parameters:
-
blocks(Iterable[SelectedBlock]) –The blocks to save, usually the Plan's bound blocks.
-
files(ArchiveFiles) –The archive object of the hook.
Returns:
-
saved(dict) –The saved block graph, with its format, nodes and roots, for
read_blocks.
read_blocks ¶
read_blocks(data, records, files)
Restore the blocks saved by write_blocks, for a Method's load_archive hook.
A saved kind selects one constructor from a fixed table of built-in block kinds, so loading never imports or calls code named in the archive. A preparation is checked against its reloaded state input before it is bound, and a transformed block is bound again to its restored base. A signed Pauli SELECT or readout derives its coefficients from the restored operator with the expression selection uses, so alpha, the coefficients and the PREP amplitudes equal those before saving, and a SELECT and its readout share one restored operator.
Parameters:
-
data(dict) –The saved block graph that
write_blocksreturned. -
records(Sequence[SelectedDefinition]) –The selected definitions that the saved root blocks refer to by position. The reference Method passes
plan.construction.selections. -
files(ArchiveFiles) –The archive object of the hook.
Returns:
-
blocks(tuple[SelectedBlock, ...]) –The restored blocks, in the saved order.
Raises:
-
ValueError–If the saved format is not the current block format, or a saved preparation does not match its input.
InputRef ¶
Bases: Record
A declaration of an input and of how it is accessed, without its data.
It names the input and its representation. It does not build an oracle
or a circuit for the input. Eigenproblem.subspace takes one to name an
explicitly defined subspace.
Attributes:
-
identity(Text) –Required. Name of the input.
-
representation(Text) –Required. How the input is represented, for example
"circuit". -
source(Source) –Required. The
Sourceof the input.