Skip to content

Solve, plan and read results

These calls turn a Problem and a configured Method into a Result. solve does it in one step, and plan, prepare and submit do it step by step, with compare, estimate and scan to choose before running. The Plan, compare and solve guide shows them in context, and Choose a problem and output explains the Problems and their outputs.

from nwqlib import (
    Accuracy, ConstrainedOptimization, Eigenproblem, Eigenvalue, Expectation,
    LinearDynamics, LinearSystem, Optimization, SpectralEstimation,
    compare, estimate, load_result, load_run, methods, plan, prepare, scan,
    solve, submit,
)
from nwqlib.core import Record
from nwqlib.execution import ExecutionLimits, Run, RunFailed
from nwqlib.search import Candidate, Objective

The outputs Eigenphase, NormSquared, NormalizedExpectation, OptimizationCandidate, QuadraticForm, Samples, Solution and StateVector also import from nwqlib. The eigenvalues of [[2, 1], [1, 2]] are 1 and 3, and Lanczos with a two-dimensional Krylov space finds the smaller one:

from nwqlib import Eigenproblem, solve
from nwqlib.algorithms import Lanczos

problem = Eigenproblem(A=[[2.0, 1.0], [1.0, 2.0]])
method = Lanczos(initial_state=[1, 0], krylov_dimension=2)
result = solve(problem, method=method, seed=7)
print(round(result.eigenvalue, 10))  # 1.0
Task Entries
Solve a problem in one call solve
Build, copy and identify records Record
State the question Problems and outputs, Accuracy
Read the answer, check it and save it Result and its answer table
Plan, compare or estimate before running plan, compare, estimate
Rank candidate Plans scan
Run step by step, with limits prepare, submit, Run, ExecutionLimits
Reopen a saved Result or Run load_result, load_run

Method authors find the Method protocol, the hooks of Plan and Result and PreparedHandle in Extending NWQLib.

Solve a problem

solve

solve(problem_or_plan, *, method=None, output=None, accuracy=None, backend=None, execution=None, shots=None, seed=None, limits=None, progress=None)

Solve a Problem with a Method and return its Result.

solve plans the computation (when given a Problem), prepares and runs the circuits or the classical model, waits for completion and returns the Method's Result. It does not run a reference check of the answer. Use plan, prepare and submit to control each step, or to save a run and continue it after an interruption.

Parameters:

  • problem_or_plan (object) –

    A Problem such as Eigenproblem, a Plan from plan, or a ComparisonRow from compare. A Plan or row already fixes the method, output and measurement settings, so method, output, accuracy, execution, shots and seed must then be omitted.

  • method (Method | None, default: None ) –

    Configured Method such as Lanczos(), required with a Problem.

  • output (OutputRecord | None, default: None ) –

    Output requested from a Problem, such as Eigenvalue(). Omitted, the Problem's default output is used.

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

    Optional accuracy request. A Method that defines sampling_shots uses it to choose the shots, and any other Method raises ApplicabilityError. It does not assert the accuracy achieved.

  • backend (object | None, default: None ) –

    Backend to run on. Omitted, the local default for the execution mode is used.

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

    "quantum" (the default for a Problem) or "classical", which evaluates that Method's numerical model.

  • shots (int | None, default: None ) –

    Positive number of shots for sampled readout, or None for exact readout. A Method setting can choose the measurement instead, for example Lanczos(sampling=...).

  • seed (int | None, default: None ) –

    Nonnegative seed of the random streams that planning and measurement of a Problem use. A seed does not establish statistical independence.

  • limits (ExecutionLimits | None, default: None ) –

    Optional ExecutionLimits for the Run's preparation and execution.

  • progress (object | None, default: None ) –

    Optional progress callback, called as callback(stage, done, total). False disables progress reports, and None permits the default notebook display.

Returns:

  • result ( Result ) –

    The Method's Result, with its Plan and run data attached. For example, a LanczosResult holds the answer in eigenvalue.

Raises:

  • TypeError –

    If a Problem is given without method.

  • ValueError –

    If a Plan or row is given with method, output, accuracy, execution, shots or seed. Pass them to a new plan(...) instead.

Examples:

The smallest eigenvalue of [[1.5, -1], [-1, 0.5]] is (2 - sqrt(5)) / 2 = -0.1180339887.... Lanczos with a full two-dimensional trial space recovers it from exact probabilities:

>>> from nwqlib import Eigenproblem, solve
>>> from nwqlib.algorithms import Lanczos
>>> problem = Eigenproblem(A=[[1.5, -1], [-1, 0.5]])
>>> method = Lanczos(initial_state=[1, 0], krylov_dimension=2)
>>> result = solve(problem, method=method, seed=7)
>>> print(round(result.eigenvalue, 10))
-0.1180339887

Build, copy and identify records

Every Problem, output, Plan and Result is a Record.

Record

The base of every NWQLib record: immutable, built with keyword arguments and validated when built.

Problems, outputs, Methods, Plans, Results and the other records derive from it. Build a record with keyword arguments. Unknown fields are rejected, and a record cannot be changed after it is built. record.revise(**changes) returns a validated new record with the changes and leaves the old one unchanged. Every construction, including model_validate and model_validate_json from saved JSON, runs the full validation, and model_dump(mode="json") returns a detached JSON description. Unchecked model_construct and Pydantic's legacy copy are disabled.

Each record has a content hash, content_id. A Result names its Plan, an observation its circuit and a resource quantity its evidence by this hash, so data stays attached to the record it came from. The hash covers the record's concrete type, so two record classes with equal fields stay distinct, its schema version, so a format change cannot collide with old data, and its parent_id, so a revision stays distinguishable from a separately built record with the same fields. A content_id given in saved JSON is checked when the record is loaded, so edited JSON cannot keep a stale hash.

Attributes:

  • schema_version (Literal[1]) –

    Version of the record's format, fixed by its type.

  • parent_id (ContentID | None) –

    Content hash of the record that this one revises, or None. revise sets it.

  • content_id (str) –

    The record's content hash, read-only: the SHA-256 digest of compact, sorted-key UTF-8 JSON of the record's fully qualified type and all its declared fields. Tuples keep their order, and numbers use Python's round-trip binary64 JSON form.

revise

revise(**changes) -> Self

Return a validated copy with changes, recording this record as its parent.

The new record's parent_id is this record's content hash, and this record is unchanged. Problems, outputs and Accuracy return a copy without a parent link, because a changed input is a new input with its own content hash.

Parameters:

  • **changes (object, default: {} ) –

    New field values, by field name. content_id and parent_id cannot be given.

Returns:

  • record ( Record ) –

    The new record, of the same type.

Raises:

  • ValueError –

    If content_id or parent_id is given, or the new values fail validation.

Examples:

>>> from nwqlib.core import Unit
>>> hartree = Unit(symbol="Ha", dimension="energy")
>>> revised = hartree.revise(symbol="Hartree")
>>> print(revised.symbol, revised.parent_id == hartree.content_id)
Hartree True

Problems and outputs

Problems, outputs and accuracy requests.

A Problem states a mathematical question with its inputs and units, an output names the quantity to compute, and an Accuracy states a requested tolerance. A Problem holds no Method setting and no run limit. The Method is given to plan or solve, and the limits to prepare or solve. A Problem keeps the numerical data of its inputs. Its JSON form describes them, and a Problem rebuilt from that description alone cannot access the numbers.

ProblemRecord

The optional fields that every Problem accepts besides its own inputs.

Build a Problem class, such as Eigenproblem, with keyword arguments. Every Problem also accepts the optional fields below. A Problem is immutable. problem.revise(**changes) returns a validated copy with the changes, and a Problem with changed inputs has its own content hash. A Problem holds no Method setting.

Attributes:

  • unit (OptionalUnit) –

    Default None, which leaves the unit unspecified. Unit of the primary answer: the eigenvalue, the solution amplitudes, the observable's expectation or the objective. A string such as "Hartree" becomes a Unit of dimension "custom". NWQLib converts no units. Units lists the unit of each output. Without a unit, error evidence about the Problem is stated in an explicitly unspecified unit.

  • scope (Scope | None) –

    Default None, which makes no physical claim. A Scope that states the physical or model meaning of the Problem. Without it, error evidence about the Problem is scoped to the Problem kind in its original input coordinates.

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

    Default None. One label per input coordinate, in the input's index order. Labels do not change the basis or add missing state amplitudes.

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

    Default (). Assumptions stated with the Problem, as text.

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

    Default (). Evidence about the inputs (Fact records). No reference computation is run to produce it.

Raises:

  • TypeError –

    If unit is neither a string, a Unit, a dict of Unit fields nor None.

  • ValueError –

    If coordinates does not label every input coordinate exactly once.

Eigenproblem

The smallest eigenvalue of a Hermitian matrix or operator A.

Build it with keyword arguments, for example Eigenproblem(A=matrix), and pass it to solve or plan with a Method such as Lanczos. A is the only required argument. The other fields below have defaults, and the optional unit, scope, coordinates, assumptions and facts of ProblemRecord are accepted too. Without output=, the requested output is Eigenvalue, in the Problem's unit.

Attributes:

  • A (OperatorData) –

    Required. Finite Hermitian matrix or supported structured operator, in a form that OperatorData accepts.

  • target (Literal['smallest']) –

    Default "smallest", the only accepted value. A Method returns its own estimate of this target.

  • subspace (InputRef | None) –

    Default None. An explicitly defined scientific subspace. A Method's trial basis or initial state does not change the full-space target.

  • sector (Text | None) –

    Default None. A scientific sector, which requires a compatible state preparation.

Raises:

  • ValueError –

    If A is not exactly Hermitian. If the Hermitian part of a matrix A is the intended problem, pass (A + A.conj().T) / 2. For a Qiskit SparsePauliOp named op, pass SparsePauliOp(op.paulis, coeffs=op.coeffs.real), which keeps every Pauli term without tolerance-based simplification.

Examples:

The eigenvalues of [[2, 1], [1, 2]] are 1 and 3. Lanczos with a two-dimensional Krylov space recovers the smallest:

>>> from nwqlib import Eigenproblem, solve
>>> from nwqlib.algorithms import Lanczos
>>> problem = Eigenproblem(A=[[2.0, 1.0], [1.0, 2.0]], unit="Hartree")
>>> method = Lanczos(initial_state=[1, 0], krylov_dimension=2)
>>> result = solve(problem, method=method, seed=7)
>>> print(round(result.eigenvalue, 10))
1.0

dimension

dimension

Number of coordinates of A.

basis

basis

The coordinate basis of A (a Basis record with its dimension and ordering).

LinearDynamics

The solution u(time) of the linear equation du/dt = -A u + source with constant A and source.

Build it with keyword arguments, for example LinearDynamics(A=matrix, initial_state=u0, time=1.0), and pass it to solve or plan with a Method such as LCHS. A, initial_state and time are required. The optional unit, scope, coordinates, assumptions and facts of ProblemRecord are accepted too, and unit labels the solution amplitudes. Without output=, the requested output is Solution: u(time) in the original coordinates, with its magnitude and phase.

Attributes:

  • A (OperatorData) –

    Required. Finite square matrix or supported structured generator, in a form that OperatorData accepts.

  • initial_state (StateData) –

    Required. The vector u(initial_time), with its magnitude and phase, in the coordinates of A and in a form that StateData accepts.

  • time (Real) –

    Required. Final time, at least initial_time.

  • source (StateData | None) –

    Default None, which means zero. Constant source vector, with its magnitude and phase, in the coordinates of A.

  • initial_time (Real) –

    Default 0.0. Initial time.

  • time_unit (OptionalUnit) –

    Default None. Label of the time unit, of dimension "time" or "custom". NWQLib converts no units, so the numerical A*time must be dimensionless.

Raises:

  • ValueError –

    If time is less than initial_time, if initial_state or source has another dimension or coordinate order than A, or if time_unit has another dimension.

Examples:

For A = diag(1, 2) the solution at time=0.5 from u = (1, 1) is (exp(-0.5), exp(-1)) = (0.6065..., 0.3679...). The default LCHS approximation, evaluated classically, gives:

>>> import numpy as np
>>> from nwqlib import LinearDynamics, solve
>>> from nwqlib.algorithms import LCHS
>>> problem = LinearDynamics(A=[[1.0, 0.0], [0.0, 2.0]],
...                          initial_state=[1.0, 1.0], time=0.5)
>>> result = solve(problem, method=LCHS(), execution="classical")
>>> print(np.round(result.solution.real, 2))
[0.61 0.37]

dimension

dimension

Number of coordinates of A.

basis

basis

The coordinate basis of A (a Basis record with its dimension and ordering).

elapsed_time

elapsed_time

The evolution time, time - initial_time.

LinearSystem

The solution x of the linear system A x = b.

Build it with keyword arguments, LinearSystem(A=matrix, b=vector), and pass it to solve or plan with a Method such as QLS. A and b are required. The optional unit, scope, coordinates, assumptions and facts of ProblemRecord are accepted too, and unit labels the solution. Without output=, the requested output is Solution: x in the original coordinates, with its magnitude and phase. The Method chooses any encoding or dilation of A.

Attributes:

  • A (OperatorData) –

    Required. Finite square matrix or supported structured operator, in a form that OperatorData accepts.

  • b (StateData) –

    Required. Right-hand side, with its magnitude and phase, in the coordinates of A and in a form that StateData accepts.

Raises:

  • ValueError –

    If b has another dimension or coordinate order than A.

Examples:

The solution of this system is (25/28, 5/28) = (0.8929..., 0.1786...). QLS selects its inverse polynomial for its default epsilon_inv=0.01, a construction target that does not bound the total error, and returns an approximation:

>>> import numpy as np
>>> from nwqlib import LinearSystem, solve
>>> from nwqlib.algorithms.qls import QLS
>>> problem = LinearSystem(A=[[1.1, 0.1], [0.1, 0.9]], b=[1.0, 0.25])
>>> result = solve(problem, method=QLS(), seed=7)
>>> print(np.round(result.x.real, 3))
[0.897 0.181]

dimension

dimension

Number of coordinates of A.

basis

basis

The coordinate basis of A (a Basis record with its dimension and ordering).

Expectation

The expectation of a Hermitian observable O in a state u given in the same coordinates.

Build it with keyword arguments, Expectation(state=u, observable=O), and pass it to solve or plan with ExpectationMethod. Both arguments are required. The optional unit, scope, coordinates, assumptions and facts of ProblemRecord are accepted too, and unit labels the normalized expectation. Without output=, the requested output is NormalizedExpectation with this observable, the value u† O u / (u† u). Request QuadraticForm for the unnormalized u† O u.

Attributes:

  • state (StateData) –

    Required. The state u, with its magnitude and phase, in a form that StateData accepts.

  • observable (OperatorData) –

    Required. Exactly Hermitian observable O, with the dimension and coordinate order of state, in a form that OperatorData accepts.

Raises:

  • ValueError –

    If observable is not exactly Hermitian, or state has another dimension or coordinate order. For a Qiskit SparsePauliOp named op whose Hermitian part is the intended observable, pass SparsePauliOp(op.paulis, coeffs=op.coeffs.real).

Examples:

For u = (2, 2) and O = diag(2, 0), the normalized expectation is 8 / 8 = 1 and the quadratic form is 8:

>>> from nwqlib import Expectation, QuadraticForm, solve
>>> from nwqlib.algorithms import ExpectationMethod
>>> problem = Expectation(state=[2.0, 2.0],
...                       observable=[[2.0, 0.0], [0.0, 0.0]])
>>> result = solve(problem, method=ExpectationMethod())
>>> print(round(result.value, 10))
1.0
>>> output = QuadraticForm(observable=problem.observable)
>>> physical = solve(problem, method=ExpectationMethod(),
...                  output=output, execution="classical")
>>> print(round(physical.value, 10))
8.0

dimension

dimension

Number of coordinates of observable.

basis

basis

The coordinate basis of observable (a Basis record with its dimension and ordering).

SpectralEstimation

An eigenphase or energy of a Hamiltonian or unitary, estimated from a prepared initial state.

Build it with keyword arguments, for example SpectralEstimation(hamiltonian=H, initial_state=psi), and pass it to solve or plan with a phase-estimation Method: QCELS, SPE, RFE or RWPE. initial_state is required, and exactly one of hamiltonian and unitary. The optional unit, scope, coordinates, assumptions and facts of ProblemRecord are accepted too. Without output=, the requested output is Eigenphase, a phase in turns. The overlaps of initial_state with the eigenvectors define the spectral population that the measurements sample. The Method chooses its sampling schedule and branch convention. A unitary alone does not define an energy.

The component each Method targets follows from its estimator. SPE, for example, targets the lowest value in the prepared support, which is the lowest energy of a Hamiltonian but the lowest principal eigenphase of a unitary. For U = exp(-i tau H) with tau |E| < pi/2 for every prepared energy E, that eigenphase belongs to the highest energy of the support.

Attributes:

  • hamiltonian (OperatorData | None) –

    Default None. Exactly Hermitian H, in a form that OperatorData accepts. Give it or unitary.

  • unitary (OperatorData | None) –

    Default None. Unitary U, in a form that OperatorData accepts. Give it or hamiltonian. The Method checks that it is unitary.

  • initial_state (StateData) –

    Required. State whose overlaps with the eigenvectors define the sampled spectral population, in the coordinates of the operator and in a form that StateData accepts.

Raises:

  • ValueError –

    If both or neither of hamiltonian and unitary are given, if hamiltonian is not exactly Hermitian, or if initial_state has another dimension or coordinate order than the operator.

Examples:

The initial state (1, 0) is the eigenvector of energy 0.2 of H = diag(0.2, 0.7):

>>> from nwqlib import SpectralEstimation, solve
>>> from nwqlib.algorithms.qpe import QCELS
>>> problem = SpectralEstimation(
...     hamiltonian=[[0.2, 0.0], [0.0, 0.7]], initial_state=[1, 0])
>>> result = solve(problem, method=QCELS(), seed=7)
>>> print(round(result.eigenvalue, 10))
0.2

dimension

dimension

Number of coordinates of the operator.

basis

basis

The coordinate basis of the operator (a Basis record with its dimension and ordering).

operator

operator

The Hamiltonian when one is given, otherwise the unitary.

Optimization

The minimum of a SymPy objective over a finite box of real variables.

Build it with keyword arguments, for example Optimization(objective=(x - 0.2)**2, variables=(x,), bounds=((-1.0, 1.0),)) with x = sympy.Symbol("x", real=True), and pass it to solve or plan with QHD. The three arguments are required. The optional unit, scope, coordinates, assumptions and facts of ProblemRecord are accepted too, and unit labels the objective. Without output=, the requested output is OptimizationCandidate, a candidate point and its objective value, which is not a proof of optimality.

Attributes:

  • objective (SymbolicData) –

    Required. Scalar SymPy expression in the variables, not a string of source code.

  • variables (tuple[SymbolicData, ...]) –

    Required. SymPy symbols with distinct names. Their order is the coordinate order.

  • bounds (tuple[tuple[Real, Real], ...]) –

    Required. One finite (lower, upper) pair with lower < upper per variable, in the order of variables.

Raises:

  • TypeError –

    If objective or a variable is not a SymPy expression.

  • ValueError –

    If bounds does not give one interval per variable, an interval has lower >= upper, two variables share a name, a variable is not a SymPy symbol, or objective contains a symbol that is not in variables.

Examples:

QHD's default grid has two interior points per variable, -1/3 and 1/3 on [-1, 1], and the objective is smaller at 1/3:

>>> import sympy as sp
>>> from nwqlib import Optimization, solve
>>> from nwqlib.algorithms.qhd import QHD
>>> x = sp.Symbol("x", real=True)
>>> problem = Optimization(objective=(x - 0.2)**2, variables=(x,),
...                        bounds=((-1.0, 1.0),))
>>> result = solve(problem, method=QHD(), seed=7)
>>> print([round(value, 10) for value in result.candidate])
[0.3333333333]

dimension

dimension

Number of variables.

variable_names

variable_names

Names of the variables, in their order.

ConstrainedOptimization

The minimum of a SymPy objective over a finite box of real variables, subject to equality and inequality constraints.

Build it with keyword arguments, for example ConstrainedOptimization(objective=..., variables=(x,), bounds=((-1.0, 1.0),), inequalities=(sympy.Le(x, 0.5),)). objective, variables, bounds and at least one constraint are required. The optional unit, scope, coordinates, assumptions and facts of ProblemRecord are accepted too. Without output=, the requested output is OptimizationCandidate. The QHD augmented-Lagrangian layer, solve_augmented_lagrangian, solves it as a sequence of QHD box problems (Constrained problems). This record is not an Optimization, so a Method for box problems alone, such as QHD, rejects it at planning with ApplicabilityError, and no constraint is silently dropped.

The stored constraints are residual expressions with the conventions h_i(x) = 0 for equalities and g_j(x) <= 0 for inequalities, the form of problem (4.1) in Birgin and Martinez, Practical Augmented Lagrangian Methods for Constrained Optimization, SIAM 2014, doi:10.1137/1.9781611973365, with the box as its set Omega. The QHD augmented-Lagrangian layer follows that book, so a residual here enters its multiplier updates and stopping tests with the book's signs. A constraint given as a scalar SymPy expression is the residual itself. Live input may also give Eq(a, b) as an equality, stored as a - b, and Le(a, b) or Ge(a, b) as an inequality, stored as a - b or b - a.

Attributes:

  • objective (SymbolicData) –

    Required. Scalar SymPy expression in the variables, not a string of source code.

  • variables (tuple[SymbolicData, ...]) –

    Required. SymPy symbols with distinct names. Their order is the coordinate order.

  • bounds (tuple[tuple[Real, Real], ...]) –

    Required. One finite (lower, upper) pair with lower < upper per variable, in the order of variables.

  • equalities (tuple[SymbolicData, ...]) –

    Default (). Residuals h_i with the constraint h_i(x) = 0, given as a tuple or list.

  • inequalities (tuple[SymbolicData, ...]) –

    Default (). Residuals g_j with the constraint g_j(x) <= 0, given as a tuple or list.

Raises:

  • TypeError –

    If a constraint field is not a tuple or list, or a constraint is not a SymPy expression or relation.

  • ValueError –

    If no constraint is given, if a constraint is a strict relation (Lt, Gt), an Ne relation, a relation that SymPy has already evaluated to True or False, another Boolean object, a matrix or a relation in the wrong field, if a constraint contains a symbol outside variables, or if the box is invalid as for Optimization. For a strict inequality, give a non-strict form with an explicit margin, for example Le(x, 1 - margin) for x < 1.

Examples:

The inequality x >= 0.5 is stored as the residual 0.5 - x <= 0:

>>> import sympy as sp
>>> from nwqlib import ConstrainedOptimization
>>> x = sp.Symbol("x", real=True)
>>> problem = ConstrainedOptimization(
...     objective=(x - 0.2)**2, variables=(x,), bounds=((-1.0, 1.0),),
...     inequalities=(sp.Ge(x, 0.5),))
>>> print(problem.inequalities)
(0.5 - x,)

dimension

dimension

Number of variables.

variable_names

variable_names

Names of the variables, in their order.

OutputRecord

The optional field that every output accepts.

An output names the quantity to compute, for example Eigenvalue(), and is passed as output= to solve, plan or compare. It holds no measured value and takes its scope from the Problem. The Method's Result holds the value. Build an output class, not this base. Units gives the unit of each output.

Attributes:

  • unit (OptionalUnit) –

    Default None. Label of a quantity whose unit neither the Problem nor the output kind defines, for example an observable of a LinearDynamics Problem. A string becomes a Unit of dimension "custom". It never converts numerical data.

Raises:

  • ValueError –

    At planning, if unit has another symbol than the unit that the Problem defines or the output kind fixes. NWQLib converts no units, so omit the output unit or label the Problem instead.

Eigenvalue

An eigenvalue, in the Problem's unit.

It is the default output of Eigenproblem, whose target is the smallest eigenvalue. Pass Eigenvalue() as output= to request it explicitly. Its error metric is the absolute error.

Eigenphase

A phase phi in turns, with U v = exp(2 pi i phi) v and phi in [0, 1).

It is the default output of SpectralEstimation. Pass Eigenphase() as output= to request it explicitly. Its unit is the turn, fixed by the output kind. For a Hamiltonian input, U is exp(-i tau H) at the time tau that the Method selects, so an energy E has phase (-tau E / (2 pi)) mod 1 and the phase order need not follow the energy order. A Method that targets the lowest principal eigenphase of a supplied unitary exp(-i tau H), as SPE does, therefore reports the phase of the highest prepared energy of H when tau |E| < pi/2 for every prepared E. The error metric of this output is the circular distance min(|d|, 1 - |d|) of the difference d between two phases in [0, 1), so estimates on either side of phase zero are close.

Solution

The solution vector in the original coordinates, with its magnitude and phase.

It is the default output of LinearDynamics and LinearSystem. Pass Solution() as output= to request it explicitly. Its unit is the Problem's unit, and its error metric is the l2 norm of the difference.

StateVector

The amplitudes of a simulated state, with a declared normalization and phase convention.

Build it with keyword arguments, for example StateVector(normalization="physical"), and pass it as output=. Every argument is optional. With normalization="physical" the vector keeps the magnitude of the solution, in the Problem's unit. With "unit" it has length 1 and is dimensionless. Its error metric is the l2 norm of the difference, or with global_phase="modulo_global_phase" the l2 norm after the global phases are aligned. Full amplitudes are a simulator readout, not a hardware measurement.

Attributes:

  • normalization (Literal['physical', 'unit']) –

    Default "unit". "physical" or "unit".

  • global_phase (Literal['physical', 'modulo_global_phase']) –

    Default "physical". "physical", which compares phases as they are, or "modulo_global_phase", which treats vectors that differ by one global phase factor as equal.

NormSquared

The squared norm u† u of a solution u, using its magnitude.

Pass NormSquared() as output= with a LinearDynamics or LinearSystem Problem. Its unit is the square of the Problem's unit when the Problem has one.

NormalizedExpectation

The normalized expectation u† O u / (u† u) of a Hermitian observable O.

u is the state of an Expectation Problem, or the solution of a LinearDynamics or LinearSystem Problem. The value is undefined when u is zero. Build it with keyword arguments, for example NormalizedExpectation(observable=O), and pass it as output= to solve or plan. An Expectation Problem requests it by default with its own observable. observable is the only required argument. For an Expectation Problem with a unit, the value is in that unit. Otherwise the optional unit of OutputRecord labels it, and without one the unit stays unspecified.

Attributes:

Raises:

  • ValueError –

    If observable is not exactly Hermitian. For a Qiskit SparsePauliOp named op whose Hermitian part is the intended observable, pass SparsePauliOp(op.paulis, coeffs=op.coeffs.real).

QuadraticForm

The quadratic form u† O u of a Hermitian observable O, using the magnitude of u.

u is the state of an Expectation Problem, or the solution of a LinearDynamics or LinearSystem Problem. Build it with keyword arguments, for example QuadraticForm(observable=O), and pass it as output= to solve or plan. observable is the only required argument. The value's unit stays unspecified unless the optional unit of OutputRecord labels it, because NWQLib infers neither the observable's unit nor the unit of the product u† O u. This holds even when the Problem's unit labels u, as it does for LinearDynamics and LinearSystem.

Attributes:

Raises:

  • ValueError –

    If observable is not exactly Hermitian. For a Qiskit SparsePauliOp named op whose Hermitian part is the intended observable, pass SparsePauliOp(op.paulis, coeffs=op.coeffs.real).

Samples

Measured outcomes in the original coordinates, counted over the shots in which the Method succeeded.

Pass Samples() as output=, together with a number of shots. The success event is, for example, the post-selection flag of QLS or LCHS. shots sets the number of shots, and the stored counts include only the shots in which that event occurred. Its unit is 1, and its error metric is the total variation distance between distributions.

OptimizationCandidate

A candidate point of the box and its objective value, with the objective gap as error.

It is the default output of Optimization and ConstrainedOptimization. Pass OptimizationCandidate() as output= to request it explicitly. The objective gap is the candidate's objective value minus a reference minimum in objective units, for example the grid minimum that an explicit QHD check evaluates. A candidate is not an optimality certificate.

Accuracy

A requested accuracy: one tolerance, a confidence and the error component it applies to.

Build it with keyword arguments, for example Accuracy(absolute_tolerance=0.01, component="sampling"). Exactly one of absolute_tolerance and relative_tolerance is required. The quantity and unit it refers to come from the output. Pass it as accuracy= to plan, solve or compare, where only a Method that defines sampling_shots uses it, to choose the shots. ExpectationMethod accepts only an absolute tolerance on the sampling component for finite Pauli counts. Pass it to Result.assess(accuracy=...) to check a Result against it, for the total or the sampling component. An Accuracy states a request and records no achieved accuracy. A total or relative target is not silently interpreted as the narrower sampling request.

Attributes:

  • absolute_tolerance (Real | None) –

    Default None. Positive bound on the error, in the unit of the output.

  • relative_tolerance (Real | None) –

    Default None. Positive bound on the error divided by the magnitude of the target.

  • confidence (Real) –

    Default 0.95. Probability, strictly between 0 and 1, with which the bound must hold.

  • component (Literal['total', 'sampling']) –

    Default "total". "total" for the whole error of the output, or "sampling" for the sampling error only.

Raises:

  • ValueError –

    If both or neither tolerance is given, or a value is out of its range.

Read and check a Result

A Result's answer field depends on its Method, as the table in the Result entry shows. The Save, load and reanalyze results guide covers saved Results and reanalysis, and Check accuracy and verify a result covers assess and verify.

Result

Bases: Record

The answer of a Method, with the Plan and measured data it came from.

solve and Run.wait return a Result, and load_result reopens a saved one. Each Method returns its own Result type, and its fields hold the answer:

Method Result type Answer Unit
ExpectationMethod ExpectationAnalysis value The Problem's unit for the default NormalizedExpectation
Lanczos LanczosResult eigenvalue The Problem's unit
QCELS, SPE, RFE, RWPE QPEAnalysis eigenvalue for a Hamiltonian input, phase The Problem's unit for eigenvalue, turns in [0, 1) for phase
FixedGCIM FixedGCIMResult eigenvalue The Problem's unit
ADAPT ADAPTResult eigenvalue The Problem's unit
LCHS LCHSAnalysis solution for the default Solution, value for a scalar output The Problem's unit for solution
QLS QLSAnalysis x for the default Solution, value for any output The Problem's unit for x
QHD QHDAnalysis candidate, the observed grid point with the smallest objective, and value, the objective there Coordinates of the variables for candidate, the Problem's unit for value

For another requested output, the Result type names the field that holds it, and Choose a problem and output gives its unit. Each Result type states when its answer is unavailable. print(result) shows the answer with its main conditions. analyze recomputes the Result from the same data with other settings, assess compares it with an accuracy criterion, verify runs a named check, report returns its stored values as a dictionary and save writes it to a folder. The Plan (result.plan) and run data (result.data) are attached to the Result rather than stored in its fields, and save writes them with it.

The fields below identify where the answer came from, and they are read-only. A Method author's Result type sets them, as the Run your own circuit guide shows.

Attributes:

  • plan_id (ContentID) –

    Content hash of the Plan the Result was computed from.

  • construction_id (ContentID) –

    Content hash of the construction of that Plan.

  • observation_id (ContentID) –

    Content hash of the observations attached to the Result.

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

    Content hashes of the parts of the observations that this Result uses.

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

    Error evidence that the Method attached (FramedFact records), each stated for its quantity, unit and scope. assess reads it.

  • origin (AnalysisOrigin | None) –

    The AnalysisOrigin of the analysis, or None when it was not recorded.

plan

plan

The Plan this Result was computed from.

Raises:

  • ValueError –

    If no Plan is attached, as for a Result built from its fields alone. load_result attaches the saved Plan.

data

data

The RunData this Result was computed from.

It holds the observations, preparation records, attempt history and saved arrays of the Run.

Raises:

  • ValueError –

    If no run data is attached.

analyze

analyze(**settings)

Recompute the Result from the same measured data with other analysis settings.

The Method analyzes the attached run data again and returns a new Result, attached to the same Plan and data. Nothing is measured, and this Result is unchanged. A loaded Result can be analyzed too. The settings a Method accepts are listed in its guide, for example the overlap_* settings of Lanczos.

Parameters:

  • **settings (object, default: {} ) –

    Analysis settings of the Method. Omitted, the analysis uses the original settings.

Returns:

  • result ( Result ) –

    The new Result.

Raises:

  • ValueError –

    If no Plan or run data is attached. The Method raises its own error for a setting it does not accept.

assess

assess(**criterion)

Check whether the Result's error evidence meets an accuracy criterion.

assess combines the error bounds that the Method attached in facts, and any bounds supplied here, and compares them with the criterion. It measures nothing, reruns nothing and leaves the Result unchanged, so a stricter criterion later is a new assessment of the same data. A known bound on one error component is never counted as a bound on the total error. The Check accuracy and verify a result guide explains the criteria.

Parameters:

  • **criterion (object, default: {} ) –

    The criterion, given either as accuracy=Accuracy(...) or by the fields of Accuracy: exactly one of absolute_tolerance and relative_tolerance, confidence (default 0.95) and component ("total", the default, or "sampling"). The optional keyword facts gives error evidence (FramedFact records) that replaces the Result's evidence of the same name, reference gives a TargetReference that supplies the target's scale for a relative tolerance, absolute_fallback gives a positive absolute tolerance used when that scale is unavailable or zero, and max_integer_bits, default 4096, limits the integers of the exact arithmetic.

Returns:

  • assessment ( ClaimAssessment ) –

    The ClaimAssessment. Its status is "PASS" when every required error source has a supported bound and together they meet the tolerance at the requested confidence, "INCONCLUSIVE" when they do not show it, for example because a bound exceeds the tolerance or a source is unknown, and "NOT_APPLICABLE" for component="sampling" when the Method's error model has no sampling source.

Raises:

  • ValueError –

    If accuracy is given together with the individual fields, or the Method has no error model.

Examples:

An exact classical solve has no sampling error, while its total error stays unproven:

>>> from nwqlib import Eigenproblem, solve
>>> from nwqlib.algorithms import FixedGCIM
>>> problem = Eigenproblem(A=[[1.0, 0.0], [0.0, -1.0]])
>>> method = FixedGCIM(basis=([1.0, 0.0], [0.0, 1.0]))
>>> result = solve(problem, method=method, execution="classical")
>>> print(result.eigenvalue)
-1.0
>>> print(result.assess(absolute_tolerance=0.01,
...                     component="sampling").status)
PASS
>>> print(result.assess(absolute_tolerance=0.01).status)
INCONCLUSIVE

verify

verify(*, checks)

Run a named check of the Result, such as a residual or a comparison with a reference.

The check is described by one options record of a type that the Method supports. It computes what the record names, at the cost the record states, and only when called. Every built-in options type returns (receipt, facts). receipt records the check, its raw values and the numerical calls it made, and facts is a tuple of FramedFact records that cite receipt. The Check accuracy and verify a result guide describes each check.

Method Options types
LCHS LCHSVerification, LCHSRefinement
Lanczos, FixedGCIM ProjectedVerificationOptions, EnergyShiftOptions
ADAPT ProjectedVerificationOptions, AdaptVerificationOptions
QHD NumberSectorOptions, QHDVerification
QLS QLSVerification
QCELS, SPE, RFE, RWPE QPEVerification

Except for LCHSRefinement, facts answers the checks that the options list in verification_checks, and Certificate.with_verification attaches it with the same options. LCHSRefinement returns error components of the output for assess instead.

Parameters:

  • checks (object) –

    One options record from the table.

Returns:

  • verification ( tuple ) –

    (receipt, facts) as described above.

Raises:

  • ValueError –

    If no Plan or run data is attached. The Method raises its own error for an options type it does not support.

Examples:

The Gram matrix of an orthonormal trial basis is the identity, so its deficit from positive semidefiniteness is zero:

>>> from nwqlib import Eigenproblem, solve
>>> from nwqlib.algorithms import FixedGCIM
>>> from nwqlib.evidence.verification import (
...     ProjectedVerificationOptions)
>>> problem = Eigenproblem(A=[[1.0, 0.0], [0.0, -1.0]])
>>> method = FixedGCIM(basis=([1.0, 0.0], [0.0, 1.0]))
>>> result = solve(problem, method=method, execution="classical")
>>> options = ProjectedVerificationOptions(
...     name="projected", comparisons=("gram_psd_deficit",),
...     tolerance=1e-10)
>>> receipt, facts = result.verify(checks=options)
>>> print(facts[0].fact.quantity, facts[0].fact.value.numerator)
projected.gram_psd_deficit 0

report

report()

Return the Result's stored values, Plan and run records as a dictionary.

The dictionary holds the printed summary and the JSON forms of the Plan, the Result, the attempt history, the observations, the preparation records, the manifests of the saved arrays, the forecast, the Allocation and the iteration state of an adaptive Method. It reads stored records only. It loads no array, runs no check, reassesses no accuracy, reanalyzes nothing and does not refresh a Run. Each array manifest comes with available, which says whether the array can be read, without reading it. A probability observation shows its array manifests and summary values. Each observation is listed with its content_id, the content hash that contribution_ids name. The records nested in an observation, such as its statistics, are listed without their own content hashes, so the report computes none per stored entry. The dictionary describes the Result, and it cannot be loaded back. Save with save, and read a saved folder without loading Method code with nwqlib.saved_evidence.read_report.

Returns:

  • report ( dict ) –

    Keys summary, plan, result, trace, observations, receipts, artifacts, forecast, allocation and controller. Values that need run data are None when none is attached.

Examples:

>>> from nwqlib import Eigenproblem, solve
>>> from nwqlib.algorithms import FixedGCIM
>>> problem = Eigenproblem(A=[[1.0, 0.0], [0.0, -1.0]])
>>> method = FixedGCIM(basis=([1.0, 0.0], [0.0, 1.0]))
>>> result = solve(problem, method=method, execution="classical")
>>> report = result.report()
>>> print(report["summary"].splitlines()[0])
Ritz eigenvalue: -1
>>> print(report["result"]["eigenvalue"])
-1.0

save

save(path)

Save this Result with its Plan and run data to a new directory.

load_result(path) reopens the saved Result, and Result.analyze can then recompute it with other settings without new measurements. Saving checks that the Result, Plan and data belong together before it writes any file. If saving fails, the new directory is removed. The saved files may total at most 10 GB (decimal).

Parameters:

  • path (str | PathLike) –

    Directory to create. Its parent must exist and the directory itself must not.

Returns:

  • path ( Path ) –

    The created directory.

Raises:

  • FileExistsError –

    If path already exists.

RunData

RunData(observations: object, trace: object, receipts: tuple = (), artifacts: tuple = (), controller: object = None, method_context: object = None, forecast: object = None, allocation: object = None)

The measured data of a Run, as attached to its Result.

result.data and run.data return it. It shares the Run's immutable observations, preparation records and arrays, so taking it copies no array and builds no circuit, and it reevaluates no model. The fields below are read-only.

Attributes:

  • observations (object) –

    Every observation the Run collected, as an ObservationView. Its chunks hold the statistics of each measurement.

  • trace (object) –

    The ExecutionTrace: every attempt, its status and the work counted against the limits, failed and uncertain attempts included.

  • receipts (tuple) –

    The preparation records (PreparedArtifact) of the circuits and of the host computations (classical computations that the Method runs on this machine) that ran. Taking the snapshot builds none of them again.

  • artifacts (tuple) –

    Handles of the saved arrays (ArtifactHandle). Reading a handle copies no data.

  • controller (object) –

    The saved iteration state and decision history of an adaptive Method, as JSON text, or None.

  • method_context (object) –

    Analysis data that the Method keeps with the Result, without its private working caches, or None.

  • forecast (object) –

    The PlanEstimate given to the Run, or None.

  • allocation (object) –

    The Allocation given to the Run, or None.

artifact

artifact(manifest)

Return the handle of one saved array, without copying its data.

Parameters:

  • manifest (ArtifactManifest | str) –

    The array's manifest, or its content hash.

Returns:

  • handle ( ArtifactHandle ) –

    The handle. Read the values with handle.array.

Raises:

  • ValueError –

    If this Run's data holds no such array.

AnalysisOrigin

Bases: Record

The analysis call that computed a Result, and its software versions.

A Result records it in origin. Loading a saved Result keeps the original record and does not create a new one. The fields below are read-only.

Attributes:

  • invocation_id (Text) –

    Unique identifier of this analysis call. It does not identify a measurement.

  • analyzer (Source) –

    Name, version and reference of the code that computed the Result (Source).

  • method_id (ContentID | None) –

    Content hash of the configured Method, or None when no Method is involved.

  • environment (tuple[Source, ...]) –

    The Python and package versions (Source records) found when the analysis ran.

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

    Names of requested packages whose version could not be read. A missing version is not version zero.

ArtifactManifest

Bases: Record

The description of a saved array: what it is, where it came from and its content hash.

A Result names its arrays by their manifests, for example LCHSAnalysis.artifact, and result.data.artifact(manifest) returns the array's handle. A manifest gives no access to the array itself. The manifest of a readout array names the preparation record as its construction and the readout declaration in producer_id. The fields below are read-only.

Attributes:

  • plan_id (ContentID) –

    Content hash of the Plan.

  • realization_id (ContentID) –

    Content hash of the concrete parameter values of the experiment.

  • construction_id (ContentID) –

    Content hash of the construction that produced the output, or for a readout array the preparation record of its measurement.

  • producer_id (ContentID) –

    Content hash of the host computation or readout declaration that produced the array.

  • output (ArrayOutput | ReadoutArray) –

    The array's shape, basis and normalization and phase convention (ArrayOutput), or the component of a readout array (ReadoutArray).

  • acquisition (tuple[Text, Text, Text, Text]) –

    The (run, attempt, measurement, slot) that produced the array.

  • source (Source) –

    The code and method that produced the array (Source).

  • digest (ContentID) –

    Content hash of the saved numerical bytes. It does not prove that the values are scientifically correct.

  • data_bytes (Count) –

    Size of the array data in bytes, which matches the output's shape and dtype.

  • encoding (Literal['complex128-le-c', 'float64-le-c', 'uint64-le-c']) –

    Byte order of the saved data, "complex128-le-c", "float64-le-c" or "uint64-le-c", as the output's dtype selects.

ArtifactHandle

ArtifactHandle(*args, **kwargs)

A saved array with its manifest.

result.data.artifact(manifest), run.hydrate(manifest) and result.data.artifacts give handles, and handle.array reads the values as a read-only NumPy array. A handle cannot be built directly. A handle of a reopened Run or loaded Result reads its array from the saved data on first access. The fields below are read-only.

Attributes:

array

array

The array, as a read-only NumPy array.

Reading it copies and computes nothing. A saved array is read once from the saved data, at the first access.

Raises:

  • ValueError –

    If the array data is not available.

available

available

Whether the array's values can be read, checked without reading them.

ReportSection

ReportSection(*, title: str, lines: tuple[str, ...] = (), data: Mapping[str, Any] = dict())

A titled section of a report, with lines of text and machine-readable data.

Build it with keyword arguments, for example ReportSection(title="Reference", lines=("E_ref = -1.0",), data={"E_ref": -1.0}). title is required. The GCiM guide builds one to show a stored reference panel next to an obtained energy.

Parameters:

  • title (str) –

    Section title.

  • lines (tuple[str, ...], default: () ) –

    Lines of text for a printed report.

  • data (Mapping[str, Any], default: dict() ) –

    Machine-readable data of the section.

Plan, compare and estimate before running

plan returns a Plan without running anything, compare plans several Methods and estimates each Plan, and estimate counts the resources of one Plan. estimate adds up counting formulas, and Prepared.inspect_resources counts the operations of the circuits that preparation built.

plan

plan(problem, *, method, output=None, accuracy=None, execution='quantum', shots=None, seed=None)

Plan how a Method computes the requested output of a Problem, without running it.

The Method chooses its construction, circuits and readout once, and the returned Plan fixes the Problem, Method, output, readout and the state of the random streams after the Method's planning draws. solve, prepare and submit run this Plan and never plan again, so a different choice needs a new Plan. Planning computes what the Method needs to build its circuits and takes no measurement. estimate reads the Plan's resource counts.

Parameters:

  • problem (ProblemRecord) –

    A Problem such as Eigenproblem.

  • method (Method) –

    Configured Method such as Lanczos(). Required.

  • output (OutputRecord | None, default: None ) –

    Requested output, such as Eigenvalue(). Omitted, the Problem's default output is used.

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

    Optional accuracy request. A Method that defines sampling_shots uses it to choose the shots, and the Plan records the request in selection_accuracy. Any other Method raises ApplicabilityError. It does not assert the accuracy achieved.

  • execution (str, default: 'quantum' ) –

    "quantum" (the default) or "classical", which evaluates the Method's numerical model on the host.

  • shots (int | None, default: None ) –

    Positive number of shots for sampled readout, or None (the default) for exact readout.

  • seed (int | None, default: None ) –

    Nonnegative seed of the random streams. Omitted, NumPy draws fresh entropy, and the Plan records it in randomness.

Returns:

  • plan ( Plan ) –

    The Plan. Its content_id identifies it, and every Result computed from it names it in plan_id.

Raises:

  • TypeError –

    If method is not a Method.

  • ValueError –

    If execution is neither "quantum" nor "classical", if shots is not a positive integer or None, if seed is negative or not an integer, or if output has a unit whose symbol differs from the one the Problem or the output kind defines.

  • ApplicabilityError –

    If the Method cannot compute this output of this Problem, or if accuracy is given to a Method without sampling_shots.

Examples:

The eigenvalues of [[2, 1], [1, 2]] are 1 and 3:

>>> from nwqlib import Eigenproblem, plan, solve
>>> from nwqlib.algorithms import Lanczos
>>> problem = Eigenproblem(A=[[2.0, 1.0], [1.0, 2.0]])
>>> method = Lanczos(initial_state=[1, 0], krylov_dimension=2)
>>> selected = plan(problem, method=method, seed=7)
>>> print(type(selected.output).__name__, selected.execution, selected.shots)
Eigenvalue quantum None
>>> print(round(solve(selected).eigenvalue, 10))
1.0

Plan

Bases: Record

The computation a Method planned for one Problem: its construction, experiments and error model.

plan returns it, and result.plan holds the Plan that a Result came from. Pass it to solve or prepare to run it, or to estimate to count its resources. print(plan) shows its Method, Problem, output, execution mode, shots and number of experiments.

A Plan is the choice a Method made once for one Problem, output, execution mode, shot request and seed. Preparation, execution, analysis, saving and loading use this Plan and never run the Method's planning again. Any change to a scientific choice, including the shots or a circuit parameter value that conflicts with the planned one, needs a new Plan with a new content hash. This is what lets a Result, its observations and a resource forecast name the Plan they belong to by plan_id. If planning could be repeated silently, data could end up attached to a construction it was not measured from. The limits of a Run, the settings of a later analysis and a later accuracy criterion are not Plan fields, so they do not change its content hash. A row of a comparison or search holds at most one Plan, and selecting a row returns it with the same Plan object (Execute the selected row). A Plan keeps live access to its inputs and to the circuit blocks that the Method bound to it, and its JSON description cannot rebuild them.

A Method author's planning step builds a Plan with keyword arguments, as Run your own circuit shows. The fields below are read-only.

Attributes:

  • problem (ProblemRecord) –

    Required. The Problem, with its inputs.

  • method (Method) –

    Required. The configured Method that planned this computation.

  • output (OutputRecord) –

    Required. The requested output.

  • execution (Literal['quantum', 'classical']) –

    Required. "quantum" or "classical".

  • shots (Count | None) –

    Default None, which means exact readout. Positive number of shots per sampled measurement.

  • selection_accuracy (Accuracy | None) –

    Default None. The accuracy request that chose the shots. It is a request, not an achieved error bound.

  • randomness (RandomState) –

    Required. Root seed and the states of the named random streams after planning.

  • construction (SelectedConstruction) –

    Required. The planned circuit, described as a Program of named steps, with the definitions of its circuit blocks and the host computations it declares (SelectedConstruction).

  • experiments (tuple[Experiment, ...]) –

    Default (). The Experiment records in order, with unique names and the readout of each.

  • reconstruction (Any) –

    Default None. Data the Method needs to interpret the observations.

  • error_model (ErrorModel | None) –

    Default None, which means no error model. The known and unavailable error sources of the output (ErrorModel).

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

    Default (). Evidence (FramedFact records) established during planning, with its conditions.

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

    Default (). Mathematical or experimental assumptions, kept without checking them.

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

    Default (). Unmet operational or scientific requirements that the Method reports. prepare refuses a Plan that has any.

  • content_id (str) –

    The Plan's content hash, read-only. It covers the fields above, with the concrete types of the Problem, Method and output, and not the bound circuit blocks.

Raises:

  • TypeError –

    If method is not a configured Method.

  • ValueError –

    If experiment names repeat or shots is 0.

compare

compare(problem, *, methods, output=None, accuracy=None, execution='quantum', shots=None, seed=None, profile=None, allocation=None, context=None, assessed_at=None, facts=(), reference=None, max_assessments=4096)

Plan one Problem with several Methods and estimate the resources of each Plan.

compare returns a Comparison with one row per Method, in the order given. Each row holds the Method's Plan and its resource estimate, as estimate gives it. A Method that cannot handle the Problem gives a row with a reason and no Plan instead of an error. Nothing is measured, no reference value is computed and the rows are not ranked. Pass a row to solve or prepare to run it, or rank the rows with scan. Each Method plans with its own child of one numpy.random.SeedSequence(seed), so no Method's planning draws shift another's, and with an integer seed every row is reproducible. The Plan, compare and solve guide shows a comparison.

Parameters:

  • problem (ProblemRecord) –

    The Problem every Method plans.

  • methods (list | tuple) –

    Configured Methods, at least one.

  • output (OutputRecord | None, default: None ) –

    Requested output. Omitted, the Problem's default output is used.

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

    Optional accuracy request, as for plan. A Method without sampling_shots then gives a row with a reason.

  • execution (str, default: 'quantum' ) –

    "quantum" (the default) or "classical".

  • shots (int | None, default: None ) –

    Positive number of shots for sampled readout, or None (the default) for exact readout.

  • seed (int | None, default: None ) –

    Nonnegative seed shared by the rows, as described above. Omitted, NumPy draws fresh entropy.

  • profile (DeviceProfile | None, default: None ) –

    Device models to evaluate for every row, as for estimate. It needs an allocation.

  • allocation (Allocation | None, default: None ) –

    The devices granted to a run, kept with every row.

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

    Counting options for the resource estimates. Omitted, ResourceContext() applies.

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

    Time-zone-aware time of the device forecasts. It needs a profile or Allocation.

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

    Accuracy evidence assessed with the forecast of every row and kept with it. It needs a profile and accuracy, and each Plan needs an error model.

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

    Target reference, with the same use and requirements as facts.

  • max_assessments (int, default: 4096 ) –

    Default 4096. Largest number of forecast rows, as for estimate, summed over the rows of the comparison and checked before the first model evaluation.

Returns:

  • comparison ( Comparison ) –

    One row per Method, in the order given.

Raises:

  • TypeError –

    If methods is not a nonempty list or tuple, or facts is not a tuple.

  • ValueError –

    If facts, reference or assessed_at is given without what it needs, if a profile is given without an Allocation, if shots or seed is invalid, or if the forecast needs more than max_assessments rows.

Examples:

For Z + I, Lanczos from the state |+> with one Krylov vector projects onto that state, whose energy is 1. FixedGCIM with the trial states |+> and |+i> spans the whole space, whose eigenvalues are 0 and 2:

>>> from nwqlib import Eigenproblem, compare, solve
>>> from nwqlib.algorithms import FixedGCIM, Lanczos
>>> problem = Eigenproblem(A=[[2.0, 0.0], [0.0, 0.0]])
>>> plus, plus_i = [1.0, 1.0], [1.0, 1j]
>>> comparison = compare(problem, methods=(
...     Lanczos(initial_state=plus, krylov_dimension=1),
...     FixedGCIM(basis=(plus, plus_i)),
... ), seed=7)
>>> for row in comparison.rows:
...     print(row.method.descriptor.method, row.reason)
chebyshev_lanczos None
fixed_gcim None
>>> for index in range(2):
...     result = solve(comparison.select(index))
...     print(round(result.eigenvalue, 10))
1.0
0.0

Comparison

Comparison(problem: object, rows: tuple[ComparisonRow, ...])

The Plans and resource estimates of several Methods for one Problem.

compare returns it, with one row per Method in the order the Methods were given. select(index) returns a row to pass to solve or prepare. A Comparison ranks nothing and names no best Method. scan ranks rows by stated objectives. The fields below are read-only.

Attributes:

  • problem (object) –

    The Problem shared by every row.

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

    The ComparisonRow records, in the order the Methods were given. Selecting a row returns it unchanged, with its Plan, estimate and evidence, and does not rank, plan or run anything.

select

select(index)

Return the row at index, unchanged.

Any row can be selected, including one without a Plan. Running a row without a Plan raises ApplicabilityError with the row's reason.

Parameters:

  • index (int) –

    Row position, from 0 to len(rows) - 1.

Returns:

Raises:

  • IndexError –

    If index is not an integer in that range.

ComparisonRow

ComparisonRow(method: Method, plan: Plan | None, reason: str | None = None, estimate: object = None, allocation: object = None, facts: tuple = (), reference: object = None, prior_work: tuple = ())

One Method of a comparison, with its Plan and resource estimate.

compare and scan build the rows, and Comparison.select(index) returns one. Pass a row to solve or prepare to run its Plan, together with its device forecast and Allocation when it has them. A Method that cannot handle the Problem gives a row with a reason and no Plan, and running that row raises ApplicabilityError. The fields below are read-only. Reading a row evaluates no model and builds no circuit.

Attributes:

  • method (Method) –

    The configured Method. The row's Plan was made by this Method.

  • plan (Plan | None) –

    The Method's Plan, or None when the Method cannot handle the Problem.

  • reason (str | None) –

    Why the Method cannot handle the Problem, or None for a row with a Plan.

  • estimate (object) –

    The resource estimate of this Plan: a WorkloadEstimate, or a PlanEstimate when a device profile or Allocation was given, with device predictions when a profile was given. None for a row without a Plan.

  • allocation (object) –

    The Allocation given to compare or scan, kept with the forecast, or None.

  • facts (tuple) –

    Accuracy evidence (FramedFact records) supplied for this row. Each keeps the subject and point it was stated for and is not applied to another row.

  • reference (object) –

    The supplied target reference (TargetReference), or None. No reference value is computed.

  • prior_work (tuple) –

    Records (Fact) of work done earlier, as supplied. They are kept apart from the work of a later run.

estimate

estimate(plan, *, context=None, profile=None, allocation=None, assessed_at=None, facts=(), reference=None, max_assessments=4096)

Estimate the resources of a Plan, and optionally its run time on a device, without running it.

Without a device profile or Allocation, estimate adds up the counting formulas of the Plan's construction (qubits, operations, shots and the other metrics) and returns a WorkloadEstimate. A metric without a formula is reported as unavailable, never as zero. With a profile, it also evaluates the profile's device models at each planned execution whose parameters are already fixed, and returns a PlanEstimate. With an Allocation and no profile, the PlanEstimate keeps the Allocation and makes no device prediction. Nothing is executed or compiled. The Estimate resources and Check device fit and run time guides explain how to read both.

Parameters:

  • plan (Plan) –

    The Plan to estimate.

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

    Counting options, such as the gate basis (ResourceContext(basis="cx")) and the schedule of independent executions. Omitted, ResourceContext() applies.

  • profile (DeviceProfile | None, default: None ) –

    Device models to evaluate. It needs an allocation.

  • allocation (Allocation | None, default: None ) –

    The devices granted to the run. Given without a profile, it is kept with the estimate and no device prediction is made.

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

    Time-zone-aware time at which the device models are evaluated. Omitted, the current time is used. It needs a profile or Allocation.

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

    Accuracy evidence to assess with the forecast. It needs a profile, an error model in the Plan and an accuracy request in the Plan (plan(..., accuracy=...)).

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

    Target reference to assess with the forecast, with the same requirements as facts.

  • max_assessments (int, default: 4096 ) –

    Default 4096. Largest number of forecast rows, one assessment per planned execution and one prediction per device model for each, checked before the first model evaluation. Adding up the construction's counts is not limited by it.

Returns:

  • estimate ( WorkloadEstimate | PlanEstimate ) –

    WorkloadEstimate without a profile or Allocation, PlanEstimate with one. Read a count of a WorkloadEstimate with estimate.quantity(metric).

Raises:

  • TypeError –

    If plan is not a Plan or facts is not a tuple.

  • ValueError –

    If assessed_at, facts or reference is given without a profile or Allocation, if facts or reference is given without the profile, error model and accuracy request it needs, if a profile is given without an Allocation, if assessed_at has no time zone, or if the forecast needs more than max_assessments rows.

Examples:

The Plan requests 64 shots of a one-qubit circuit:

>>> from nwqlib import Expectation, estimate, plan
>>> from nwqlib.algorithms import ExpectationMethod
>>> problem = Expectation(state=[1.0, 0.0],
...                       observable=[[1.0, 0.0], [0.0, -1.0]])
>>> selected = plan(problem, method=ExpectationMethod(), shots=64,
...                 seed=7)
>>> workload = estimate(selected)
>>> print(workload.quantity("shots").fact.value.numerator)
64
>>> width = workload.quantity("logical_width",
...                           location="logical_device")
>>> print(width.fact.value.numerator)
1

methods

methods()

List the built-in Methods.

Each entry is a registration record. Its source.name and source.version name the Method. A registration declares what the Method is for. It does not establish that the Method or a backend has been validated for a problem. Nothing is run. The command-line algorithms, card and options commands print the same information and each Method's settings (Use the command line).

Returns:

  • registrations ( tuple[Registration, ...] ) –

    One record per built-in Method.

Examples:

>>> from nwqlib import methods
>>> print([entry.source.name for entry in methods()])
['adapt_gcim', 'chebyshev_lanczos', 'finite_pauli_expectation', 'fixed_gcim', 'lchs', 'qcels', 'qhd', 'qls', 'rfe', 'rwpe', 'spe']

scan

scan(candidates, *, objectives, profile=None, context=None, assessed_at=None, max_candidates=256, max_assessments=4096, max_pair_comparisons=1000000, max_values=4096, max_integer_bits=4096)

Rank Plans of one Problem by resource objectives and return their Pareto front.

For each candidate, scan estimates the resources of its Plan, as estimate does, evaluates each objective and returns a SearchResult. Its selection.nondominated lists the rows that no other row beats on every objective, and select(index) returns a row to run. A ranking that rests on conditional values, such as model predictions, is conditional too. Passing an existing Comparison rescores its stored estimates and forecasts, and then nothing is planned, estimated or predicted. Every row is an existing Plan. A different shot count or Method setting is a different Plan, supplied as another candidate. The candidate, value and comparison limits are checked before any estimate, model evaluation or comparison, and a profile's complete set of forecasts is checked before its first model evaluation. The Rank candidate plans guide describes the objectives.

Parameters:

  • candidates (tuple[Candidate, ...] | Comparison) –

    The Candidate records of Plans of one Problem, or a Comparison to rescore.

  • objectives (tuple[Objective, ...]) –

    Distinct objectives, all minimized.

  • profile (DeviceProfile | None, default: None ) –

    Device models for time forecasts. Every candidate then needs an Allocation. Not accepted when rescoring.

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

    Counting options for the resource estimates. Omitted, ResourceContext() applies. Not accepted when rescoring.

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

    Time-zone-aware time of new forecasts. Omitted, the current time is used. Not accepted when rescoring.

  • max_candidates (int, default: 256 ) –

    Default 256. Largest number of rows.

  • max_assessments (int, default: 4096 ) –

    Default 4096. Largest number of forecast rows evaluated, or read from a stored Comparison.

  • max_pair_comparisons (int, default: 1000000 ) –

    Default 1_000_000. Largest number of coordinate comparisons of the Pareto front, N*(N-1)*k for N rows and k objectives.

  • max_values (int, default: 4096 ) –

    Default 4096. Largest number of row and objective values, N*k.

  • max_integer_bits (int, default: 4096 ) –

    Default 4096. Largest bit length of an integer in the exact rational arithmetic.

Returns:

Raises:

  • TypeError –

    If objectives is not a nonempty tuple of Objective records, or candidates is neither a nonempty tuple of Candidate records nor a Comparison.

  • ValueError –

    If the objectives are not distinct, a limit has an invalid value or is exceeded, the candidates plan different Problems, a profile is given without an Allocation on every candidate, or a Comparison is rescored with profile, context or assessed_at.

Examples:

Two Plans that differ only in their shots, ranked by requested shots:

>>> from nwqlib import Expectation, plan, scan
>>> from nwqlib.algorithms import ExpectationMethod
>>> from nwqlib.search import Candidate, Objective
>>> problem = Expectation(state=[1.0, 0.0],
...                       observable=[[1.0, 0.0], [0.0, -1.0]])
>>> plans = tuple(plan(problem, method=ExpectationMethod(), shots=n,
...                    seed=7) for n in (8, 32))
>>> search = scan(tuple(Candidate(p) for p in plans),
...               objectives=(Objective(kind="requested_shots"),))
>>> print(search.selection.nondominated)
(0,)
>>> print(search.select(0).plan.shots)
8

Candidate

Candidate(plan: Plan, *, allocation: Allocation | None = None, facts: tuple[FramedFact, ...] = (), reference: TargetReference | None = None, prior_work: tuple[Fact, ...] = ())

A Plan to rank with scan, with its optional device context.

Build it with the Plan and optional keyword arguments, for example Candidate(plan, allocation=allocation), and pass a tuple of candidates to scan. A Candidate changes nothing in its Plan. A different Method setting or shot count is a different Plan and a separate candidate, and scan neither creates nor tunes Method configurations.

Parameters:

  • plan (Plan) –

    Required, positional. A Plan from plan.

  • allocation (Allocation | None, default: None ) –

    The devices granted to a run of this Plan (Allocation), needed for device forecasts.

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

    Accuracy evidence (FramedFact records) to assess with this candidate's forecast.

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

    Target reference (TargetReference) to assess with it. No reference value is computed.

  • prior_work (tuple[Fact, ...], default: () ) –

    Records (Fact) of work done earlier for this candidate. Each supplied record is kept, repeated ones included. An empty tuple means that no earlier work is recorded, not that it cost nothing.

Raises:

  • TypeError –

    If plan is not a Plan, or another argument has the wrong type.

Objective

Bases: Record

A quantity that scan minimizes over its candidates.

Build it with keyword arguments, for example Objective(kind="requested_shots"), and pass a tuple of objectives to scan. kind is the only argument required. model_id and scope are given for predicted_seconds only, and both are then required.

  • requested_shots sums the shots that the Plan's readouts request.
  • logical_width is the largest width, in qubits, of one execution at one location. It is not a sum over executions that run at the same time.
  • predicted_seconds sums the predictions of one device timing model and scope over the Plan's executions, under a serial schedule declared with ResourceContext(batch_schedule="serial"). The sum stays a prediction that holds only under its model.

Attributes:

  • kind (Literal['requested_shots', 'logical_width', 'predicted_seconds']) –

    Required. "requested_shots", "logical_width" or "predicted_seconds".

  • model_id (ContentID | None) –

    Default None. Content hash of the timing model whose predictions are summed, required for predicted_seconds.

  • scope (TimeScope | None) –

    Default None. Timing scope of those predictions: "selected_acquisition", "acquisition_overhead" or "native_call_wall". Required for predicted_seconds.

Raises:

  • ValueError –

    If predicted_seconds lacks model_id or scope, or another kind has either.

SearchResult

SearchResult(comparison: Comparison, selection: SearchSelection)

The rows that a scan ranked and their Pareto front.

scan returns it. Read the front in selection.nondominated, then pass select(index) to solve or prepare to run one row. Construction checks that the selection was computed for exactly this Comparison. The fields below are read-only.

Attributes:

select

select(index)

Return the row at index, unchanged, as Comparison.select does.

Any row can be selected, including a dominated row or a row without a Plan. Running a row without a Plan raises ApplicabilityError.

Parameters:

  • index (int) –

    Row position, from 0 to the number of rows minus 1.

Returns:

Raises:

  • IndexError –

    If index is not an integer in that range.

SearchSelection

Bases: Record

The objective values of every row and the rows on the Pareto front.

scan returns it in SearchResult.selection. Row i dominates row j when every objective of i is at most that of j and at least one is smaller. The Pareto front, nondominated, is every row whose objectives are all available and that no other such row dominates, so equal rows all stay. A row with any unavailable objective is listed in incomparable instead of being ranked as zero or infinity. The front holds only within the rows given. It is not a feasibility filter or a global optimum. Validation recomputes both lists from the stored values with exact rational arithmetic and rejects supplied lists that differ, so a saved selection cannot claim a front that its values do not support. The fields below are read-only.

Attributes:

  • comparison_id (ContentID) –

    Content hash of the Comparison that this selection ranks, computed from its Problem and rows.

  • objectives (tuple[Objective, ...]) –

    The minimized objectives, in the order given.

  • values (tuple[tuple[ObjectiveValue, ...], ...]) –

    One ObjectiveValue per row and objective, in row order.

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

    Indices of the rows on the Pareto front, recomputed on validation.

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

    Indices of the rows with an unavailable objective, recomputed on validation.

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

    The supplied records of earlier work of each row, each record kept as often as it was supplied.

  • work (SearchWork) –

    The SearchWork of the scan that produced this selection.

  • max_pair_comparisons (Count) –

    Default 1_000_000. Largest number of coordinate comparisons of the front, N*(N-1)*k for N rows and k objectives, checked before any comparison.

  • max_values (Count) –

    Default 4096. Largest number of row and objective values, N*k, checked before any comparison.

  • max_integer_bits (Count) –

    Default 4096. Largest bit length of an integer in the exact rational arithmetic.

validate_comparison

validate_comparison(comparison)

Check that this selection was computed for exactly the rows of comparison.

Use it after loading a saved selection, for example with SearchSelection.model_validate_json(...), to check that it belongs to a Comparison.

Parameters:

  • comparison (Comparison) –

    The Comparison to check against.

Returns:

Raises:

  • ValueError –

    If the selection belongs to another Comparison or has another number of rows.

ObjectiveValue

Bases: Record

The value of one objective for one candidate, with what it rests on.

scan computes these values, one per candidate and objective, in SearchSelection.values. A value is exact, conditional on the assumptions it lists, or unavailable with a reason. A sum of binary64 time predictions is computed exactly but stays a conditional prediction. It does not bound the elapsed time or state that the predictions hold together. The fields below are read-only.

Attributes:

  • objective_id (ContentID) –

    Content hash of the Objective this value answers.

  • value (Rational | None) –

    Exact nonnegative rational value (Rational), or None when unavailable.

  • unit (Unit) –

    count for shots and width, s for predicted seconds.

  • status (Literal['exact', 'conditional', 'unavailable']) –

    "exact", "conditional" or "unavailable".

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

    Content hashes of the stored resource quantities, experiments or predictions that the value is computed from. Nonempty for an available value.

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

    Conditions taken over from those sources.

  • reason (Text | None) –

    Why the value is unavailable, or None for an available value.

SearchWork

Bases: Record

How many resource estimates and device forecasts one scan computed or reused.

scan records it in SearchSelection.work. It counts estimates and forecast points, not CPU time. The fields below are read-only.

Attributes:

  • origin (Literal['evaluated_here', 'stored_comparison']) –

    "evaluated_here" when scan received candidates, "stored_comparison" when it rescored a Comparison.

  • requested_points (Count) –

    Forecast points that the rows need, equal to assessed_points + reused_points.

  • assessed_points (Count) –

    Forecast points evaluated by this call. Zero when rescoring.

  • reused_points (Count) –

    Forecast points taken from an identical earlier row or from the stored Comparison.

  • base_folds (Count) –

    Resource estimates or forecasts computed by this call. Zero when rescoring.

  • reused_folds (Count) –

    Rows whose estimate or forecast came from an identical earlier row or from the stored Comparison.

Run step by step

prepare builds the circuits and returns them with their open Run, submit starts the Run, and Run.wait returns the Result. The Run on a backend guide describes progress, pending jobs, cancellation and limits.

prepare

prepare(plan, *, backend=None, limits=None, progress=None, directory=None, settings='first')

Build the circuits of a Plan for a backend, without submitting them.

prepare creates a new Run for the Plan and builds its first circuit, or every circuit with settings="all". Pass the result to submit to run it, or inspect the circuits first with Prepared.circuits and Prepared.inspect_resources. When the Plan's experiments are fixed in advance, rather than chosen from earlier outcomes, every circuit, shot and preparation of the whole Plan is checked against the Run's limits before anything is built. The returned Prepared holds the open Run, which the caller closes, for example with with prepared.run as run:. If preparation fails, the Run is closed and the error names its saved folder, if any.

Parameters:

  • plan (Plan | ComparisonRow) –

    A Plan, or a row from compare or scan. A row's device forecast and Allocation stay with the Run and its Result.

  • backend (object | None, default: None ) –

    Backend to run on. Omitted, local Aer runs quantum execution and the host runs classical execution.

  • limits (ExecutionLimits | None, default: None ) –

    Limits on the Run's total preparations, circuits, shots and stored data. Omitted, the defaults of ExecutionLimits apply.

  • progress (object | None, default: None ) –

    Progress callback, called as callback(stage, done, total). False disables progress reports, and None permits the default notebook display.

  • directory (str | PathLike | None, default: None ) –

    New folder in which the Run saves its state as it runs, so that load_run can reopen it.

  • settings (str, default: 'first' ) –

    "first" (the default) prepares the setting that the Method submits first, which is the first experiment when the experiments are fixed, and submit prepares each later one when it reaches it. "all" prepares every setting of fixed experiments now, in Plan order, so that Prepared.circuits, Prepared.setting_names, inspection and compilation by index cover the whole Plan. Each setting is prepared and counted once, a Run with a folder saves it, and submit uses these preparations. The limit check above already covers them, so "all" adds nothing to the limits and prepares nothing that a completed submit would not. "all" needs local Aer, local NWQ-Sim or classical host execution. Another backend is refused before a Run exists, because its preparation can be a remote compilation that the provider charges for. This restriction lasts until the cost disclosure and the handling of pending remote preparations are decided (Preparing every setting on remote backends). A Method whose later settings depend on earlier outcomes (RWPE, Lanczos with SensitivitySampling, ADAPT) refuses "all" before a Run exists, and its message says what it can prepare instead.

Returns:

  • prepared ( Prepared ) –

    The prepared circuits and their open Run (prepared.run). Nothing has been submitted.

Raises:

  • TypeError –

    If plan is neither a Plan nor a row of a comparison.

  • ValueError –

    If settings is neither "first" nor "all", or if "all" is requested on another backend or for a Method that refuses it.

  • ApplicabilityError –

    If plan is a row without a Plan, or the Plan lists unmet requirements.

Examples:

See submit.

Prepared

Prepared(run: Run)

The prepared circuits of a Plan and their open Run, before submission.

prepare returns it. Inspect the circuits with circuits, circuit(index), setting_names and inspect_resources, then pass it to submit. The Run holds the preparations, the limits, the measured data and everything that follows. Close it when done, for example with with prepared.run as run:. The field below is read-only.

Attributes:

circuits

circuits

Copies of every prepared Qiskit circuit, in index order.

The index of a circuit is the one that circuit, setting_names and inspect_resources use. Each access copies every circuit, and circuit(index) copies one. Host computations have no circuit and are skipped.

setting_names

setting_names

The Plan experiment of each prepared circuit, in the index order of circuits.

Entry i is the name (Experiment.name in plan.experiments) of the experiment that circuit i implements. After prepare(plan, settings="all") the names of fixed experiments are those of the Plan's circuit experiments, in Plan order. The default settings="first" prepares only the setting that the Method submits first, and an adaptive Method can prepare one experiment several times with different parameter values.

circuit

circuit(index=0)

Return a copy of one prepared Qiskit circuit.

Parameters:

  • index (int, default: 0 ) –

    Default 0. Position of the circuit in circuits and setting_names.

Returns:

  • circuit ( QuantumCircuit ) –

    The copy.

Raises:

  • ValueError –

    If no circuit has this index. After the default prepare(plan, settings="first") only the first setting is prepared, and settings="all" prepares every setting of fixed experiments.

inspect_resources

inspect_resources(*, index=0, transpile_options=None, max_operations=100000, max_bytes=DEFAULT_MAX_BYTES)

Count the operations of one 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:

  • index (int, default: 0 ) –

    Default 0. Position of the circuit in circuits.

  • 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, or None), operations (count by name), total_operations, num_qubits, num_clbits and depth (Qiskit's default depth, which skips directives such as barriers and simulator saves).

Raises:

  • ValueError –

    If no circuit has this index or a limit is exceeded.

submit

submit(prepared)

Start running prepared circuits and return their Run.

The first call starts the Run of prepared and returns it when the run is complete or the Method has to wait for results from the backend. run.result holds the Result once the run is complete, and Run.wait waits for it. The Run stays the caller's through prepared.run, also when submit raises, so enter with prepared.run as run: before submitting to close it. A second call on the same prepared starts a new Run with the same backend, the current limits and the Plan's original random state, because the work counted against a started Run cannot be reset. The new Run draws the same seeds, so its new run_id does not establish that its samples are independent of the first Run's.

Parameters:

  • prepared (Prepared) –

    The return value of prepare.

Returns:

  • run ( Run ) –

    The started Run.

Raises:

  • TypeError –

    If prepared is not the return value of prepare.

  • RunFailed –

    If the run fails or an attempt's outcome cannot be recovered.

Examples:

The state |0> gives <Z> = 1 in every shot:

>>> from nwqlib import Expectation, plan, prepare, submit
>>> from nwqlib.algorithms import ExpectationMethod
>>> problem = Expectation(state=[1.0, 0.0],
...                       observable=[[1.0, 0.0], [0.0, -1.0]])
>>> selected = plan(problem, method=ExpectationMethod(), shots=64,
...                 seed=7)
>>> prepared = prepare(selected)
>>> print(prepared.setting_names)
('group_0',)
>>> with prepared.run:
...     result = submit(prepared).wait()
>>> print(result.value)
1.0

Run

Run(plan, *, backend=None, limits=None, directory=None, progress=None, forecast=None, allocation=None)

One execution of a Plan: its circuits, attempts, measured data, limits and counted work.

prepare creates a Run (prepared.run), submit starts it, and load_run reopens a saved one. wait() returns the Result, and resume() continues the Run once without waiting. Close a Run when done, for example with with prepared.run as run:. Closing cancels no job.

The Run is the only object that sets work aside, submits it, saves its outcomes and counts it against the limits. The limits apply to totals over the Run's whole life, failed and uncertain attempts included, so raising the limits or reopening the Run never gives back work already counted. A Run with a folder records every step in run.sqlite there and holds an exclusive lock on the folder until it is closed. A Run without a folder keeps the same counts in memory and can be saved later with save. Run on a backend and Continue an interrupted run describe both. The fields below are read-only.

Attributes:

  • plan (Plan) –

    The Plan being executed. Continuing the Run never replaces it.

  • backend (object) –

    The backend, or None for a Run of host computations only.

  • forecast (object) –

    The PlanEstimate given with the Plan, or None.

  • allocation (object) –

    The Allocation given with the Plan, or None. Continuing the Run does not recompute it.

  • run_id (str) –

    Identifier of this execution, distinct from another Run of the same Plan.

result

result

The Run's Result once the run is complete, and None before.

directory

directory

The Run's folder, as a pathlib.Path, or None for a Run without one.

A backend that runs jobs outside this process always gets a folder, under ~/.nwqlib/runs/<run_id> when prepare was given no directory, so that a submitted job can be reopened after the process ends.

limits

limits

The Run's current ExecutionLimits.

limit_amendments

limit_amendments

Every raise of the Run's limits so far, in order.

Each is a LimitAmendment with the old and new limits and the Run's counts just before the raise.

trace

trace

The Run's attempts and counted work as they stand, as an ExecutionTrace.

It includes failed, uncertain and unused work, so a Result built from it accounts for all the work of the Run rather than only the measurements it uses. The same snapshot is returned until an attempt, submission, count or limit changes.

data

data

The Run's measured data as it stands, as a RunData.

It holds the collected observations, preparation records, trace and saved arrays, shared rather than copied. Its method_context is set only when the Method keeps analysis data with the Result. Repeated reads reuse the snapshots of observations and trace.

observations

observations

The observations that the Method has collected so far, in the order it collected them.

An ObservationView whose chunks hold the statistics of each measurement. A completed measurement that the Method has not yet collected is absent. The same object is returned until the next collection.

exposure

exposure

The work submitted so far, by outcome: completed, reserved, uncertain and failed.

A dictionary with the keys "completed", "reserved", "uncertain" and "failed", each mapping jobs, circuits, shots and provider_managed_sampling to a count. Jobs are counted per submission. Submissions not yet acknowledged by the backend, or acknowledged and not finished, are reserved. Failed, cancelled and uncertain submissions are all counted as uncertain jobs, because a provider's final status does not state how much work it consumed. Circuits, shots and provider-managed sampling are counted per attempt, by the attempt's status. Only host computations can fail, so the failed category never contains circuits or shots.

warnings

warnings

Notices recorded in this process, such as a disabled progress callback or a backend's notice.

Reading them repeats no work. They are not saved with the Run.

artifacts

artifacts

The store of the arrays this Run has saved, created on first use.

Read one array with hydrate(manifest), or take the handles from run.data.artifacts.

wait

wait(*, timeout=None, poll_interval=1.0)

Continue the Run until it has a Result, and return the Result.

Each pass calls resume, which reads every pending provider job once, and then sleeps poll_interval seconds. A Method may return a valid partial Result from the data it has before a failed job is reported, and the Run never invents scientific output. A retrieval error propagates and keeps the job's locator, so a later resume or wait can read the same job, and an uncertain submission is never resubmitted.

Parameters:

  • timeout (float | None, default: None ) –

    Seconds to wait before raising TimeoutError. None, the default, waits without a limit.

  • poll_interval (float, default: 1.0 ) –

    Default 1.0. Seconds between passes. A longer interval sends fewer status requests to a provider. The default is a polling interval chosen without tuning (Engineering constants).

Returns:

  • result ( Result ) –

    The Run's Result.

Raises:

  • RunFailed –

    If a preparation, host computation or submission ended in failure or cancellation, or an uncertain attempt cannot be recovered.

  • TimeoutError –

    If the Run is still pending after timeout. The same Run can be continued later.

  • RuntimeError –

    If the Run was cancelled before it completed. Its pending work is saved in its folder.

Examples:

See submit.

resume

resume(*, reanalyze=False)

Continue the Run once: retrieve pending results, let the Method go on, and return.

resume reads each pending submission once, then lets the Method continue from where the Run stands, without waiting. When the Method finishes, run.result holds the Result. Otherwise run.result is still None, and a later resume or wait continues. A complete Run returns at once. Work done before an error, such as a computed circuit or numerical intermediate, is kept for the next resume. A Result always accounts for every attempt of the Run, failed and uncertain ones included.

Parameters:

  • reanalyze (bool, default: False ) –

    Default False. True retries an interrupted analysis of a Method that supports it, from its saved data, before continuing. A completed Run is analyzed again with result.analyze(...) instead.

Returns:

  • run ( Run ) –

    This Run.

Raises:

  • RunFailed –

    If no Result is available and an uncertain attempt cannot be retrieved by any route (stage "recovery").

  • ValueError –

    If reanalyze=True is given for a Run that already has its Result.

Examples:

A local Aer run completes in its first pass:

>>> from nwqlib import Expectation, plan, prepare, submit
>>> from nwqlib.algorithms import ExpectationMethod
>>> problem = Expectation(state=[1.0, 0.0],
...                       observable=[[1.0, 0.0], [0.0, -1.0]])
>>> selected = plan(problem, method=ExpectationMethod(), shots=64,
...                 seed=7)
>>> prepared = prepare(selected)
>>> with prepared.run as run:
...     started = submit(prepared)
...     print(started is run, run.resume().result.value)
True 1.0

cancel

cancel(reason='user requested cancellation')

Stop new work in this Run, then ask the backend to cancel its pending jobs.

The request is saved first, so a Run reopened after a crash while contacting the provider still refuses new preparations and measurements. Pending remote preparations and submissions are then refreshed, which sends each job at most one cancellation request. A request does not prove that a job was cancelled, and only a status returned by the provider does. All counted work stays counted. A backend without a cancellation operation, such as local NWQ-Sim, receives no request.

Parameters:

  • reason (str, default: 'user requested cancellation' ) –

    Reason recorded with the request. Default "user requested cancellation".

Returns:

  • run ( Run ) –

    This Run.

close

close()

Close the Run's folder, release its lock and free its working caches. Closing twice is harmless.

Closing cancels no job. The saved files, the Result, the preparation records, the arrays and every count stay, so a later load_run or inspection sees the same work. with prepared.run as run: closes the Run at the end of the block.

save

save(path)

Copy the Run's current state to a new folder. The open Run continues unchanged.

Call it while the Run is open, after a Run call has returned. The copy holds the Plan, the limits and counts, the random state, the preparations, the attempts and the locators of pending jobs, the observations, the arrays and any Result. A Run without a folder gets one this way. load_run reopens the copy. The copy and the original name the same provider jobs, so continue only one of them. The copied files count against max_data_bytes, and a failed copy leaves no new folder.

Parameters:

  • path (str | PathLike) –

    New folder to create.

Returns:

  • path ( Path ) –

    The created folder.

Raises:

  • ValueError –

    If the Run is in the middle of a step, for example while an outcome is being saved.

extend_limits

extend_limits(**changes)

Raise one or more limits of this Run, keeping everything it has counted.

run.extend_limits(max_total_shots=128) sets the Run's total shot limit to 128. It does not add 128 shots, reset any count or change a scientific setting, so raising a limit gives back no work already counted. Limits can only be kept or raised. A call that raises a limit records a LimitAmendment in limit_amendments. The new limits and that record are saved together, so a process that stops before the save reopens with the old limits, and one that stops after it reopens with the new limits and their record. A call that raises nothing records nothing.

Parameters:

  • **changes (int, default: {} ) –

    New values of ExecutionLimits fields, by name, as integers at least the current values.

Returns:

  • run ( Run ) –

    This Run.

Raises:

  • ValueError –

    If no limit is named, a name is not a limit, or a value is not an integer at least the current one.

hydrate

hydrate(manifest)

Return the handle of one saved array, reading its bytes from the Run's folder once.

Nothing is measured or recomputed. The array is read on first use and kept for the life of the Run. A probability observation and an array handle of this Run read through the same store.

Parameters:

  • manifest (ArtifactManifest) –

    The array's manifest.

Returns:

  • handle ( ArtifactHandle ) –

    The array's handle.

Raises:

  • ValueError –

    If the Run has no saved bytes for the array.

release_native

release_native()

Release the in-memory circuits of preparations that are fully collected, idle and saved as QPY.

For a long Run with a folder, this frees the Qiskit circuits that are no longer needed. The preparation records and the order of the prepared circuits stay. Inspecting a released circuit reads its saved QPY once, and nothing is built, transpiled or submitted again. Circuits of other backends, unsaved circuits and circuits still in use are kept. Aer is the backend whose circuits are released. The counts describe released circuits, not measured memory.

Returns:

  • released ( dict ) –

    released, the content hashes of the released preparations, and kept, pairs of a content hash and the reason it was kept.

ExecutionLimits

Bases: Record

Limits on what one Run may prepare, execute and store.

Build it with keyword arguments and pass it as limits= to solve or prepare, for example ExecutionLimits(max_total_shots=10_000_000). Every argument is optional, and every limit is inclusive. The max_total_* limits, max_data_bytes and max_synthesis_work count totals over the whole Run. Planning does not use these limits. A Method checks its own planning limits, such as Lanczos.max_bytes. Raise a limit of an existing Run with Run.extend_limits.

Attributes:

  • max_simulation_qubits (PositiveInt) –

    Default 20. Largest circuit width that a local simulator (Aer or the local NWQ-Sim backend) accepts. A 20-qubit complex128 statevector needs 16 MiB.

  • simulator_memory_mb (PositiveInt) –

    Default 1024 (MiB). Memory allowance of the local simulator for the quantum state and its known working arrays. Aer receives it as max_memory_mb.

  • max_total_circuits (PositiveInt) –

    Default 512. Largest number of circuit preparations, and separately of circuit execution attempts.

  • max_total_shots (PositiveInt) –

    Default 1_000_000. Largest total of shots reserved for circuit executions, including attempts whose outcome is uncertain.

  • max_data_bytes (PositiveInt) –

    Default 10 GB (decimal, 10_000_000_000 bytes). Largest size of the Run's recorded data and numerical arrays. It does not bound the memory of the Python process.

  • max_completion_metadata_bytes (PositiveInt) –

    Default 65_536. JSON metadata allowed for each completed circuit execution or host computation, in addition to the numeric values, arrays and host-computation records that it declares.

  • max_direct_amplitudes (PositiveInt) –

    Default 65_536 (2**16, a 16-qubit state). Largest amplitude count of a direct magnitude and phase state preparation that the Run synthesizes.

  • max_synthesis_work (PositiveInt) –

    Default 1e9 work units. Largest total work of the exact syntheses of dense unitaries that the Run makes while it prepares circuits. It counts the syntheses of a backend that translates a circuit to its gate basis, and the syntheses and Qiskit's control of them when building the Qiskit circuit adds controls to a transformed block. The default allows the synthesis of one dense unitary on 8 qubits (5.2e8 units) and refuses one on 9 qubits (4.0e9 units). The work of a preparation's syntheses is checked against the remaining allowance before the first of them starts. Each distinct matrix is synthesized and counted once while the Run is open, and again after the Run is reopened. A refused preparation still counts against max_total_circuits and leaves its experiment unprepared, so a later call can prepare it after the limit is raised. Syntheses that a Method counts against its own limits at planning are not counted here. The work unit and the synthesis cache are defined in Explicit workflow and reference controls.

LimitAmendment

Bases: Record

One raise of a Run's limits, with the Run's counts just before it.

Run.extend_limits records one in run.limit_amendments for each call that raises a limit. Each raises at least one limit and lowers none, and the counts it records lie within the old limits. The fields below are read-only.

Attributes:

  • sequence (PositiveInt) –

    Position in the Run's history of raises, from 1.

  • recorded_at (AwareDatetime) –

    Time-zone-aware wall-clock time of the raise. It is a timestamp, not a measure of elapsed time.

  • old (ExecutionLimits) –

    The complete ExecutionLimits before the raise.

  • new (ExecutionLimits) –

    The complete ExecutionLimits after the raise.

  • circuit_preparations (Count) –

    Circuit preparations so far, failed and unused ones included.

  • circuit_attempts (Count) –

    Circuit execution attempts so far, reserved and uncertain ones included.

  • raw_shots (Count) –

    Shots requested explicitly so far. Unknown sampling inside an estimate that a provider manages is not included.

  • stored_data_bytes (Count) –

    Bytes of the Run's stored data, without pending_output_bytes. Both byte counts describe the data the Run accounts for, never physical memory.

  • pending_output_bytes (Count) –

    Bytes set aside for outputs not yet received.

  • synthesis_work (Count) –

    Work of the exact syntheses of dense unitaries counted against max_synthesis_work so far.

ExecutionTrace

Bases: Record

The attempts of a Run and the work counted against its limits.

run.trace and result.data.trace return it. It includes failed and uncertain attempts and unused preparations, so a Result built from it accounts for all the work of the Run, not only the measurements it uses. local_prepared_ids names the successful preparations made in this Run. A saved preparation that this Run uses may instead come from another Run that is allowed to use it, and using it counts as execution work, not as a new local preparation. limits and limit_amendments are the limits and their history when the trace was taken, so raising the Run's limits later does not change an earlier Result. The fields below are read-only.

Attributes:

  • run_id (Text) –

    Identifier of the Run.

  • plan_id (ContentID) –

    Content hash of the Run's Plan.

  • preparations (Count) –

    Number of preparation attempts in this Run, failed and interrupted ones included. It includes the host setups counted in host_preparations.

  • construction_work_reserved (Count) –

    Circuit construction work counted in this Run, in work units.

  • events (tuple[ConsumptionEvent, ...]) –

    Every attempt (ConsumptionEvent records), in order, failed and uncertain ones included.

  • submissions (tuple[SubmissionRecord, ...]) –

    The circuit submissions (SubmissionRecord records), with the attempts of each.

  • host_preparations (Count) –

    Number of host setup attempts.

  • host_preparation_work_reserved (Count) –

    Work of host setups counted in this Run.

  • host_invocations (Count) –

    Number of host computations started, interrupted ones included.

  • host_work_reserved (Count) –

    Work of host computations, counted before each starts.

  • data_bytes_reserved (Count) –

    Bytes set aside for outputs, summed over the attempts.

  • data_bytes (Count) –

    Bytes of the Run's stored data when the trace was taken.

  • synthesis_work_reserved (Count) –

    Work of the exact syntheses of dense unitaries counted against max_synthesis_work in this Run.

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

    Content hashes of the successful preparations made in this Run.

  • cancel_requested (Text | None) –

    The reason given to Run.cancel, or None. A request does not prove that the provider cancelled the job.

  • termination_reason (Text | None) –

    Why the Method ended the run early, or None.

  • limits (ExecutionLimits | None) –

    The ExecutionLimits when the trace was taken, or None for a trace recorded without them.

  • limit_amendments (tuple[LimitAmendment, ...]) –

    Every raise of the limits so far (LimitAmendment records), in order.

jobs

jobs: int

Number of circuit submissions, including those whose acknowledgement from the backend has not arrived.

RunFailed

RunFailed(*, stage, status, locator, failure, directory, trace, exposure, attempt=None)

Bases: RuntimeError

Raised when a run fails, or when the outcome of an attempt cannot be recovered.

submit, Run.resume and Run.wait raise it. stage and status describe the outcome. A recovery error (stage="recovery") reports an attempt whose outcome is unavailable, with status "uncertain", even when its submission has ended because its output cannot be retrieved. Status "uncertain" does not claim that the execution failed. locator and directory locate the original job and the saved Run, and failure is the recorded failure text, not an invented local exception. trace and exposure capture the attempts and counted work without another backend call, and attempt names the original attempt of a recovery error, whose record and counted work are in those snapshots. The message names each of these. For a recovery error, it also tells you to inspect the saved data or cancel the Run, and to start a new Run to execute the Plan again, because nothing is resubmitted in this Run and the attempt stays uncertain and counted.

Attributes:

  • stage –

    "prepare", "execute" or "recovery".

  • status –

    The observed outcome, such as "failed", "cancelled" or "uncertain".

  • locator –

    The original provider job or remote-preparation locator, or None when none was acknowledged.

  • failure –

    The recorded failure text, or None.

  • directory –

    The Run's folder, or None for a Run without one.

  • trace –

    The ExecutionTrace at the time of the error.

  • exposure –

    Read-only copy of Run.exposure at the time of the error, the counted work by outcome.

  • attempt –

    The attempt's identifier for a recovery error, otherwise None.

submit and Run.resume call the two functions below for a backend that runs jobs outside this process. The backend guides name them where a direct call helps.

submit_detached

submit_detached(prepared, *, run, checkpoint_sequences=None)

Submit prepared circuits as one job to a backend that runs jobs outside this process, without waiting.

submit and Run.resume call it for such a backend, so most code never does. The IonQ guide calls it directly to submit several circuits with equal shots as one job. The backend checks the whole batch, the submission is saved in the Run's folder, the backend then starts the job, and the job's locator is saved when the backend returns it. If the process ends between the start and the saved locator, the reopened Run has an uncertain submission without a locator, and only the backend's own lookup by the original submission can find the job. An error while starting the job marks the submission and its attempts uncertain, with their work still counted, because the provider may have accepted the request before the error reached this process. The job is never resubmitted or replaced. Read its results with run.resume(), run.wait() or refresh_submissions.

Parameters:

  • prepared (tuple[PreparedHandle, ...]) –

    The prepared circuits of this Run and backend, at least one.

  • run (Run) –

    The Run that holds them. It needs a folder.

  • checkpoint_sequences (tuple | None, default: None ) –

    For an adaptive Method, the iteration checkpoint of each circuit, in order, or None.

Returns:

  • submission ( SubmissionRecord ) –

    The saved submission with its job locator.

Raises:

  • TypeError –

    If prepared is not a nonempty tuple of prepared circuits.

  • ValueError –

    If the Run has no folder, the backend cannot start jobs, a circuit belongs to another backend, or checkpoint_sequences does not match prepared.

refresh_submissions

refresh_submissions(*, run: Run)

Read each pending job of a Run once and save the new results, without submitting anything.

Run.resume and Run.wait call it, so most code never does. Each new result is saved with its attempt in one step and can be collected once. A job read twice still saves each result once, because results that are already saved are skipped. A submission whose locator was lost is read only through the backend's own lookup by the original submission. Items of a job keep their original positions and result keys, and a provider may add a child job or result identifier to an item but cannot replace one. When a provider reports failure, cancellation or an uncertain state, the remaining attempts become uncertain and stay counted. If reading a job fails, the failure is recorded on its submission and the original exception propagates, with the job's locator, counted work and earlier results kept, so a later call can read the same job again.

Parameters:

  • run (Run) –

    The Run whose pending jobs are read.

Returns:

  • observations ( tuple[ObservationChunk, ...] ) –

    The newly saved observations.

Save and reopen

result.save(path) writes a Result with its Plan and data, and load_result reopens it. A Run with a folder saves its state as it runs, run.save(path) copies it, and load_run reopens either to continue the same work. The Continue an interrupted run guide compares the two.

load_result

load_result(path, *, method=None)

Reopen a Result saved with Result.save, with its Plan and run data.

The loaded Result has the same fields as the saved one, and Result.analyze can recompute it from the saved data with other settings, without new measurements. Loading plans nothing, runs nothing and computes no reference. It checks the saved records, the content hash of the Plan and the header of every saved array, and it reads the array values only when they are used, as read-only memory maps, so keep the folder available while using the Result. The Save, load and reanalyze results guide describes the saved folder.

Parameters:

  • path (str | PathLike) –

    Folder written by Result.save.

  • method (type | Method | None, default: None ) –

    The Method class, or an instance of it, for a Method that is not built into NWQLib. Built-in Methods are found from the saved record.

Returns:

  • result ( Result ) –

    The saved Result, of the Method's own Result type, with its Plan and run data attached.

Raises:

  • ValueError –

    If the saved records fail their checks, or a Method outside NWQLib is saved and method is not given or differs from it.

Examples:

>>> import os, tempfile
>>> from nwqlib import Expectation, load_result, solve
>>> from nwqlib.algorithms import ExpectationMethod
>>> problem = Expectation(state=[1.0, 0.0],
...                       observable=[[1.0, 0.0], [0.0, -1.0]])
>>> result = solve(problem, method=ExpectationMethod(), seed=7)
>>> path = result.save(os.path.join(tempfile.mkdtemp(), "result"))
>>> print(load_result(path).value)
1.0

load_run

load_run(path, *, backend, method=None, progress=None)

Reopen a saved Run to inspect it or continue it.

load_run opens the folder of a Run, either the directory given to prepare or a copy written by Run.save, and returns the open Run with its Plan, limits, counted work, random state and the locators of its pending jobs. Loading plans nothing, contacts no backend and runs nothing. run.resume() or run.wait() then continues the same work, and a completed Run returns its saved Result. The Run takes an exclusive lock on the folder until it is closed. The Continue an interrupted run guide describes saving and reopening.

Parameters:

  • path (str | PathLike) –

    A Run folder. A folder written by Result.save is not a Run folder. Keep it available and writable while the Run is open, because the Run records its progress there.

  • backend (object) –

    Backend with the configuration that the Run was saved with. Reopening never submits a replacement for an attempt whose outcome is unknown.

  • method (type | Method | None, default: None ) –

    The Method class, or an instance of it, for a Method that is not built into NWQLib. Built-in Methods are found from the saved record.

  • progress (object | None, default: None ) –

    Progress callback of the reopened Run, False to disable it, or None for the notebook display, as for prepare.

Returns:

  • run ( Run ) –

    The open Run. Close it when done, for example with with load_run(path, backend=backend) as run:.

Raises:

  • TypeError –

    If progress is not None, False or a callable.

  • ValueError –

    If the saved records fail their checks, or a Method outside NWQLib is saved and method is not given or differs from it.

  • BlockingIOError –

    If another open Run holds the folder. Close that Run, for example prepared.run, first.

Examples:

>>> import os, tempfile
>>> from nwqlib import Expectation, load_run, plan, prepare, submit
>>> from nwqlib.algorithms import ExpectationMethod
>>> from nwqlib.backends import AerBackend
>>> problem = Expectation(state=[1.0, 0.0],
...                       observable=[[1.0, 0.0], [0.0, -1.0]])
>>> selected = plan(problem, method=ExpectationMethod(), shots=64,
...                 seed=7)
>>> folder = os.path.join(tempfile.mkdtemp(), "run")
>>> prepared = prepare(selected, directory=folder)
>>> with prepared.run:
...     result = submit(prepared).wait()
>>> with load_run(folder, backend=AerBackend()) as run:
...     print(run.wait().value)
1.0

A Method family that runs a sequence of Plans documents it with the family. QHD's augmented-Lagrangian layer and box refinement run one ordinary QHD Plan per round or level, each planned with its own random streams, as compare plans each Method, and run with prepare and submit. With directory=... these Runs are saved as they run, and resume_augmented_lagrangian and resume_box_refinement continue an interrupted run, reopening an unfinished Run with load_run and the progress of the resume call (QHD constrained problems and box refinement).

Entries on other pages

The Method base class and its hooks, PreparedHandle, and the Plan, Result and Problem hooks are documented on Extending NWQLib:

PhysicalScale is documented on Inputs and input types: