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 Plans by shots, width or predicted time | 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. If preparing or running
fails, the Run is closed and the error names its saved folder, if any,
which load_run reopens, for example to
analyze the counts of IBM jobs that ran before a native-depth limit
refused a circuit.
Parameters:
-
problem_or_plan(object) –A Problem such as
Eigenproblem, aPlanfromplan, or aComparisonRowfromcompare. A Plan or row already fixes the method, output and measurement settings, somethod,output,accuracy,execution,shotsandseedmust 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_shotsuses it to choose the shots, and any other Method raisesApplicabilityError. 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
Nonefor exact readout, in which a simulator computes probabilities, Pauli expectation values or amplitudes without shot sampling. Numerical rounding remains. A Method setting can choose the measurement instead, for exampleLanczos(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
ExecutionLimitsfor the Run's preparation and execution. -
progress(object | None, default:None) –Optional progress callback, called as
callback(stage, done, total).Falsedisables progress reports, andNonepermits the default notebook display.
Returns:
-
result(Result) –The Method's Result, with its Plan and run data attached. For example, a
LanczosResultholds the answer ineigenvalue.
Raises:
-
TypeError–If a Problem is given without
method. -
ValueError–If a Plan or row is given with
method,output,accuracy,execution,shotsorseed. Pass them to a newplan(...)instead. With a Problem, also for the invalid values thatplanlists. -
ApplicabilityError–As for
plan, if the Method cannot compute this output of this Problem oraccuracyis given to a Method withoutsampling_shots, and as forprepare, if a row without a Plan is given or the Plan lists unmet requirements. -
RunFailed–As for
Run.wait, if the run fails or the outcome of an attempt cannot be recovered.
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. Constructors, model_validate
and model_validate_json validate field data. A field value that is
already an instance of the field's exact declared record type is kept as
it is, without validating it again. model_dump(mode="json") returns a
detached JSON description.
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. The content hash is
computed from the validated fields when first requested.
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.revisesets it. -
content_id(str) –The record's content hash, read-only:
"sha256:"followed by the hexadecimal SHA-256 digest of compact, sorted-key UTF-8 JSON of an object with the keys"identity_encoding"("nwqlib.record/1"),"type"(the record's fully qualified type) and"fields"(all its declared fields inmodel_dump(mode="json")form). 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. The parent link is derived from this record.
Returns:
-
record(Record) –The new record, of the same type.
Raises:
-
ValueError–If 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 aUnitof 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. AScopethat 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, asFactrecords. No reference computation is run to produce it.
Raises:
-
TypeError–If
unitis neither a string, aUnit, a dict ofUnitfields norNone. -
ValueError–If
coordinatesdoes 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:
-
kind(Literal['eigenproblem']) –Fixed
"eigenproblem", the record's type name in its JSON form. -
A(OperatorData) –Required. Finite Hermitian matrix or supported structured operator, in a form that
OperatorDataaccepts. -
target(Literal['smallest']) –Default
"smallest", the only accepted value. A Method returns its own estimate of this target. -
subspace(InputRef | None) –Default
None. AnInputRefthat names an explicitly defined scientific subspace. A Method that works in its own fixed basis, such asFixedGCIM, rejects the Problem withApplicabilityErrorwhen that basis differs from this subspace. A Method's trial basis or initial state does not change the full-space target. -
sector(Text | None) –Default
None. Name of a symmetry sector, as text, which requires a compatible state preparation. A Method that would draw its own random initial state rejects a Problem with a sector withApplicabilityError, so supply an initial state in that sector.
Raises:
-
ValueError–If
Ais not exactly Hermitian. If the Hermitian part of a matrixAis the intended problem, pass(A + A.conj().T) / 2. For a QiskitSparsePauliOpnamedop, passSparsePauliOp(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
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:
-
kind(Literal['linear_dynamics']) –Fixed
"linear_dynamics", the record's type name in its JSON form. -
A(OperatorData) –Required. Finite square matrix or supported structured generator, in a form that
OperatorDataaccepts. -
initial_state(StateData) –Required. The vector
u(initial_time), with its magnitude and phase, in the coordinates ofAand in a form thatStateDataaccepts. -
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 ofA. -
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 numericalA*timemust be dimensionless.
Raises:
-
ValueError–If
timeis less thaninitial_time, ifinitial_stateorsourcehas another dimension or coordinate order thanA, or iftime_unithas 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]
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:
-
kind(Literal['linear_system']) –Fixed
"linear_system", the record's type name in its JSON form. -
A(OperatorData) –Required. Finite square matrix or supported structured operator, in a form that
OperatorDataaccepts. -
b(StateData) –Required. Right-hand side, with its magnitude and phase, in the coordinates of
Aand in a form thatStateDataaccepts.
Raises:
-
ValueError–If
bhas another dimension or coordinate order thanA.
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]
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:
-
kind(Literal['expectation']) –Fixed
"expectation", the record's type name in its JSON form. -
state(StateData) –Required. The state
u, with its magnitude and phase, in a form thatStateDataaccepts. -
observable(OperatorData) –Required. Exactly Hermitian observable
O, with the dimension and coordinate order ofstate, in a form thatOperatorDataaccepts.
Raises:
-
ValueError–If
observableis not exactly Hermitian, orstatehas another dimension or coordinate order. For a QiskitSparsePauliOpnamedopwhose Hermitian part is the intended observable, passSparsePauliOp(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
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.
For the normalized direction psi of initial_state and an
orthonormal eigenbasis v_j of the supplied operator, eigenvector
v_j has spectral weight abs(<v_j|psi>)**2. The measurements
probe these weights. 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:
-
kind(Literal['spectral_estimation']) –Fixed
"spectral_estimation", the record's type name in its JSON form. -
hamiltonian(OperatorData | None) –Default
None. Exactly HermitianH, in a form thatOperatorDataaccepts. Give it orunitary. -
unitary(OperatorData | None) –Default
None. UnitaryU, in a form thatOperatorDataaccepts. Give it orhamiltonian. The Method checks that it is unitary. -
initial_state(StateData) –Required. State whose normalized direction gives the spectral weights probed by the measurements as the squared magnitudes of its overlaps with an orthonormal eigenbasis, in the coordinates of the operator and in a form that
StateDataaccepts.
Raises:
-
ValueError–If both or neither of
hamiltonianandunitaryare given, ifhamiltonianis not exactly Hermitian, or ifinitial_statehas 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
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:
-
kind(Literal['optimization']) –Fixed
"optimization", the record's type name in its JSON form. -
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 withlower < upperper variable, in the order ofvariables.
Raises:
-
TypeError–If
objectiveor a variable is not a SymPy expression. -
ValueError–If
boundsdoes not give one interval per variable, an interval haslower >= upper, two variables share a name, a variable is not a SymPy symbol, orobjectivecontains a symbol that is not invariables.
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]
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 Martínez, 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.
A SymPy relation may also be given: 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:
-
kind(Literal['constrained_optimization']) –Fixed
"constrained_optimization", the record's type name in its JSON form. -
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 withlower < upperper variable, in the order ofvariables. -
equalities(tuple[SymbolicData, ...]) –Default
(). Residualsh_iwith the constrainth_i(x) = 0, given as a tuple or list. -
inequalities(tuple[SymbolicData, ...]) –Default
(). Residualsg_jwith the constraintg_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), anNerelation, 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 outsidevariables, or if the box is invalid as forOptimization. For a strict inequality, give a non-strict form with an explicit margin, for exampleLe(x, 1 - margin)forx < 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,)
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 aLinearDynamicsProblem. A string becomes aUnitof dimension"custom". It never converts numerical data.
Raises:
-
ValueError–At planning, if
unithas 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.
Attributes:
-
kind(Literal['eigenvalue']) –Fixed
"eigenvalue", the record's type name in its JSON form.
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.
Attributes:
-
kind(Literal['eigenphase']) –Fixed
"eigenphase", the record's type name in its JSON form.
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.
Attributes:
-
kind(Literal['solution']) –Fixed
"solution", the record's type name in its JSON form.
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 come from a
simulator, not from a hardware measurement.
Attributes:
-
kind(Literal['state_vector']) –Fixed
"state_vector", the record's type name in its JSON form. -
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.
Attributes:
-
kind(Literal['norm_squared']) –Fixed
"norm_squared", the record's type name in its JSON form.
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:
-
kind(Literal['normalized_expectation']) –Fixed
"normalized_expectation", the record's type name in its JSON form. -
observable(OperatorData) –Required. Exactly Hermitian observable
O, in a form thatOperatorDataaccepts.
Raises:
-
ValueError–If
observableis not exactly Hermitian. For a QiskitSparsePauliOpnamedopwhose Hermitian part is the intended observable, passSparsePauliOp(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:
-
kind(Literal['quadratic_form']) –Fixed
"quadratic_form", the record's type name in its JSON form. -
observable(OperatorData) –Required. Exactly Hermitian observable
O, in a form thatOperatorDataaccepts.
Raises:
-
ValueError–If
observableis not exactly Hermitian. For a QiskitSparsePauliOpnamedopwhose Hermitian part is the intended observable, passSparsePauliOp(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.
Attributes:
-
kind(Literal['samples']) –Fixed
"samples", the record's type name in its JSON form.
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.
Attributes:
-
kind(Literal['optimization_candidate']) –Fixed
"optimization_candidate", the record's type name in its JSON form.
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 |
QFD |
QFDResult |
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
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 circuit description the Result was computed from, either that Plan's
constructionor the construction the Plan chooses for one experiment point. -
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, as
FramedFactrecords, each stated for its quantity, unit and scope.assessreads it. -
origin(AnalysisOrigin | None) –The
AnalysisOriginof the analysis, orNonewhen 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_resultattaches 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.
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 ofAccuracy: exactly one ofabsolute_toleranceandrelative_tolerance,confidence(default0.95) andcomponent("total", the default, or"sampling"). The optional keywordfactsgives error evidence (FramedFactrecords) that replaces the Result's evidence of the same name,referencegives aTargetReferencethat supplies the target's scale for a relative tolerance,absolute_fallbackgives a positive absolute tolerance used when that scale is unavailable or zero, andmax_integer_bits, default4096, limits the integers of the exact arithmetic.
Returns:
-
assessment(ClaimAssessment) –The
ClaimAssessment. Itsstatusis"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"forcomponent="sampling"when the Method's error model has no sampling source.
Raises:
-
ValueError–If
accuracyis 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
checks.verification_checks(result) lists, 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 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 only the records the Result already holds. 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
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(the printed summary),plan,result,trace(the attempt history),observations,receipts(the preparation records),artifacts(the manifest and availability of each saved array),forecast,allocationandcontroller(the iteration state of an adaptive Method). Values that need run data areNonewhen 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
pathalready 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. Itschunksare theObservationChunkrecords, each holding one recorded batch of outputs or the outputs of one trajectory point. -
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 classical computations on this machine that the Method ran. ReadingRunDatabuilds none of them again. -
artifacts(tuple) –The saved arrays, as
ArtifactHandleobjects. Reading one 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
PlanEstimategiven to the Run, orNone. -
allocation(object) –The
Allocationgiven to the Run, orNone.
artifact ¶
artifact(manifest)
Return the ArtifactHandle of one saved array, without copying its data.
Parameters:
-
manifest(ArtifactManifest | str) –The array's manifest, or its content hash.
Returns:
-
handle(ArtifactHandle) –The array's
ArtifactHandle. Read the values withhandle.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
Nonewhen no Method is involved. -
environment(tuple[Source, ...]) –The Python and package versions (
Sourcerecords) 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
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 classical computation, or of the readout description, 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]) –Four text labels of the measurement that produced the array: the Run's
run_id, the attempt, the job and the result or chunk within that job. For a classical computation, the job label repeats the attempt. -
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']) –Element type, little-endian byte order and C (row-major) layout of the saved data:
"complex128-le-c","float64-le-c"or"uint64-le-c", as the output's dtype selects.
ArtifactHandle ¶
ArtifactHandle
A saved array with its manifest.
result.data.artifact(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:
-
manifest(ArtifactManifest) –The array's
ArtifactManifest: content hash, output convention and the measurement that produced it.
array ¶
array
The array, as a read-only NumPy array.
For an array in memory, reading it copies and computes nothing. For a reopened Run, the array is read from the saved data once, at the first access. For a loaded Result, it is a read-only memory map of the saved file, so its values are read from disk as they are used.
Raises:
-
ValueError–If the array data is not available.
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. In the GCiM guide,
chemistry_reference_report_section returns one to show the saved panel
of chemistry reference energies next to a computed energy. Result.report()
does not include such a section, so print or save it beside the report.
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_shotsuses it to choose the shots, and the Plan records the request inselection_accuracy. Any other Method raisesApplicabilityError. It does not assert the accuracy achieved. -
execution(str, default:'quantum') –"quantum"(the default) or"classical", which evaluates the Method's numerical model on this computer. -
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_ididentifies it, and every Result computed from it names it inplan_id.
Raises:
-
TypeError–If
methodis not a Method. -
ValueError–If
executionis neither"quantum"nor"classical", if a suppliedshotscount is below 1, ifseedis negative or not an integer, or ifoutputhas 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
accuracyis given to a Method withoutsampling_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 (Solve the compared
rows). A Plan holds its input
data and the circuit blocks that the Method attached 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
Programof named steps, with the definitions of its circuit blocks and of the classical computations that the Method runs on this computer (SelectedConstruction). -
experiments(tuple[Experiment, ...]) –Default
(). TheExperimentrecords 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 (FramedFactrecords) 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.preparerejects 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
methodis not a configured Method. -
ValueError–If experiment names repeat or
shotsis 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 withoutsampling_shotsthen 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 anallocation. -
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. Omitted, the current time is read once and used for every row. It needs a profile or Allocation.
-
facts(tuple[FramedFact, ...], default:()) –Error 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 forestimate, 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
methodsis not a nonempty list or tuple, orfactsis not a tuple. -
ValueError–If
facts,referenceorassessed_atis given without what it needs, if a profile is given without an Allocation, ifshotsorseedis invalid, or if the forecast needs more thanmax_assessmentsrows.
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
ComparisonRowrecords, 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:
-
row(ComparisonRow) –The row at that position.
Raises:
-
IndexError–If
indexis 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
Nonewhen the Method cannot handle the Problem. -
reason(str | None) –Why the Method cannot handle the Problem, or
Nonefor a row with a Plan. -
estimate(object) –The resource estimate of this Plan: a
WorkloadEstimate, or aPlanEstimatewhen a device profile or Allocation was given, with device predictions when a profile was given.Nonefor a row without a Plan. -
allocation(object) –The Allocation given to
compareorscan, kept with the forecast, orNone. -
facts(tuple) –Error evidence (
FramedFactrecords) supplied for this row. Each keeps the quantity, unit and scope it was stated for and its parameter values, and is not applied to another row. -
reference(object) –The supplied target reference (
TargetReference), orNone. No reference value is computed. -
prior_work(tuple) –Records (
Fact) of work done earlier, as supplied inCandidate.prior_worktoscan, or()for a row fromcompare. 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. When the Method
returns a reason from
Method.query_catalog_reason,
as ADAPT does, the Plan's experiments are templates of queries whose
parameter values its iteration chooses from earlier outcomes. The
estimate then reports a count as zero only when no query can contribute
to it and reports the widths and byte peaks of the templates. It leaves
the other counts unavailable with that reason, except
root_setting_declarations and root_repetitions, the setting
declarations and body repetitions of a MeasurementBatch at the root of
the Program, which keep their values. 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:()) –Error 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) –WorkloadEstimatewithout a profile or Allocation,PlanEstimatewith one. Read a count of aWorkloadEstimatewithestimate.quantity(metric).
Raises:
-
TypeError–If
planis not a Plan orfactsis not a tuple. -
ValueError–If
assessed_at,factsorreferenceis given without a profile or Allocation, iffactsorreferenceis given without the profile, error model and accuracy request it needs, if a profile is given without an Allocation, ifassessed_athas no time zone, or if the forecast needs more thanmax_assessmentsrows.
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']
Rank candidate plans¶
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 with complete objective values
for which no other row is at least as good on every objective and
strictly better on at least one, 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
the estimates and forecasts that its rows hold, 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 limits on rows, values and comparisons 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
Candidaterecords 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 Comparison being rescored. -
max_pair_comparisons(int, default:1000000) –Default
1_000_000. Largest number of coordinate comparisons of the Pareto front,N*(N-1)*kfor 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:
-
result(SearchResult) –The ranked Comparison and its
SearchSelection.
Raises:
-
TypeError–If
objectivesis not a nonempty tuple of Objective records, orcandidatesis 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 Plans of the Candidates belong to different Problems, a profile is given without an Allocation on every Candidate, or a Comparison is rescored with
profile,contextorassessed_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 them to
scan. A Candidate changes nothing in its Plan. A different Method
setting or shot count is a different Plan and needs its own 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:()) –Error evidence (
FramedFactrecords) to assess with the forecast of this Plan. -
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 Plan. Each supplied record is kept, repeated ones included. An empty tuple means that no earlier work is recorded, not that it cost nothing.
Objective ¶
Bases: Record
A quantity that scan minimizes over the Plans it ranks.
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_shotssums the shots that the Plan's readouts request.logical_widthis the largest width, in qubits, of one execution at one location. A location is a name assigned to a Program register, such aslogical_device(resource locations). It is not a sum over executions that run at the same time.predicted_secondssums the predictions of one device timing model and scope over the Plan's executions, under a serial schedule declared withResourceContext(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 forpredicted_seconds. -
scope(TimeScope | None) –Default
None. Timing scope of those predictions:"selected_acquisition","acquisition_overhead"or"native_call_wall". Check device fit and run time says what each scope covers. Required forpredicted_seconds.
Raises:
-
ValueError–If
predicted_secondslacksmodel_idorscope, 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:
-
comparison(Comparison) –The
Comparisonof every row ranked, including rows without a Plan or with unavailable values. -
selection(SearchSelection) –The
SearchSelectionwith every objective value, the Pareto front and the incomparable rows.
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:
-
row(ComparisonRow) –The row at that position.
Raises:
-
IndexError–If
indexis 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
objective values with exact rational arithmetic. 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
ObjectiveValueper row and objective, in row order. -
nondominated(tuple[Count, ...] | None) –Default
None. Indices of the rows on the Pareto front. Validation recomputes them fromvaluesand replaces any value given. -
incomparable(tuple[Count, ...] | None) –Default
None. Indices of the rows with an unavailable objective. Validation recomputes them fromvaluesand replaces any value given. -
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
SearchWorkof 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)*kfor 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:
-
selection(SearchSelection) –This selection, unchanged.
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 row, with what it rests on.
scan computes these values, one per row 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
Objectivethis value answers. -
value(Rational | None) –Exact nonnegative rational value (
Rational), orNonewhen unavailable. -
unit(Unit) –Unit(symbol="count", dimension="count")for shots and width,Unit(symbol="s", dimension="time")for predicted seconds. -
status(Literal['exact', 'conditional', 'unavailable']) –"exact","conditional"or"unavailable". -
sources(tuple[ContentID, ...]) –Content hashes of the 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
Nonefor 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"whenscanreceived Candidate records,"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 Comparison being rescored.
-
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 Comparison being rescored.
Run step by step¶
prepare builds the Plan's first circuit, or every circuit with settings="all", and returns a Prepared that holds the built circuits and 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
compareorscan. 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 this computer runs classical execution.
-
limits(ExecutionLimits | None, default:None) –Limits on the Run's total preparations, circuits, shots and stored data. Omitted, the defaults of
ExecutionLimitsapply. -
progress(object | None, default:None) –Progress callback, called as
callback(stage, done, total).Falsedisables progress reports, andNonepermits 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_runcan reopen it. -
settings(str, default:'first') –A setting is one Plan experiment with the parameter values it is prepared with.
"first"(the default) prepares the setting that the Method submits first, which is the first experiment when the experiments are fixed, andsubmitprepares each later one when it reaches it."all"prepares every setting of fixed experiments now, in Plan order, so thatPrepared.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, andsubmituses 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 execution on this computer. Another backend is rejected 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 withSensitivitySampling, ADAPT) rejects"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
planis neither a Plan nor a row of a comparison. -
ValueError–If
settingsis neither"first"nor"all", or if"all"is requested on another backend or for a Method that rejects it. -
ApplicabilityError–If
planis 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. Classical computations that the Method
runs on this computer 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 incircuitsandsetting_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, andsettings="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 changing 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 incircuits. -
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(a text description of the counted circuit),basis(the gate basis label),compiler(Qiskit version and options, orNone),operations(count by name),total_operations,num_qubits,num_clbitsanddepth(Qiskit's default depth, which skips directives such as barriers and simulator saves).
Raises:
-
ValueError–If 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
preparedis not the return value ofprepare. -
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
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 submits the work, saves its outcomes and counts the work 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
Nonefor a Run whose only computations are classical computations that the Method runs on this computer. -
forecast(object) –The
PlanEstimategiven with the Plan, orNone. -
allocation(object) –The
Allocationgiven with the Plan, orNone. Continuing the Run does not recompute it. -
run_id(str) –Identifier of this execution, distinct from another Run of the same Plan.
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.
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 ExecutionTrace object 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 same observations and trace objects.
observations ¶
observations
The observations that the Method has collected so far, in the order it collected them.
An ObservationView. Its chunks are the
ObservationChunk records, each
holding one recorded batch of outputs or the outputs of one
trajectory point. Outputs that are saved but that the Method has not
yet collected are 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. provider_managed_sampling
counts attempts that return a provider estimate whose sampling the
provider chooses. Their sampling is unknown and is not in shots.
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 classical computations that the Method
runs on this computer 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.
Get the handle of one array with run.artifacts.get(manifest), which
needs the full ArtifactManifest, or take the handles from
run.data.artifacts. Read the values with handle.array.
wait ¶
wait
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.
A retrieval error propagates and keeps the job's locator (a
JobLocator with the provider, the job identifier and the account
context, without credentials), 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, classical 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
cancelwas called on this Run before it completed and no failed or cancelled work is confirmed yet. Its pending work is saved in its folder.
Examples:
See submit.
resume ¶
resume
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.Trueretries an interrupted analysis of a Method that supports it, from its saved data, before continuing. A completed Run is analyzed again withresult.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=Trueis 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
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 rejects 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
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
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
ExecutionLimitsfields, 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.
release_native ¶
release_native
Release the in-memory Qiskit circuits whose results the Method has all collected, that are not in use and that are 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 file (Qiskit's binary circuit format) 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, andkept, 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
8192(MiB, 8 GiB). Memory allowance of the local simulator for the quantum state and its known working arrays. Aer receives it asmax_memory_mb. It is an upper limit that the memory needs of a simulation are checked against, not memory set aside in advance, and it does not bound the memory of the Python process. Raising it does not raisemax_simulation_qubits. -
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_000bytes). 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 classical computation that the Method runs on this computer, in addition to the numeric values, arrays and records of classical computations 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
1_000_000_000work 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. When building the Qiskit circuit adds control to a circuit block, it also counts the exact syntheses needed for that control and Qiskit's work to control the synthesized circuits. The default allows the synthesis of one dense unitary on 8 qubits (5.2e8 units) and rejects 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 rejected preparation still counts againstmax_total_circuitsand 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
ExecutionLimitsbefore the raise. -
new(ExecutionLimits) –The complete
ExecutionLimitsafter 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 saved 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_workso 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 setups of the classical computations that the Method runs on this computer, counted in
host_preparations. -
construction_work_reserved(Count) –Circuit construction work counted in this Run, in work units.
-
events(tuple[ConsumptionEvent, ...]) –Every attempt (
ConsumptionEventrecords), in order, failed and uncertain ones included. -
submissions(tuple[SubmissionRecord, ...]) –The circuit submissions (
SubmissionRecordrecords), with the attempts of each. -
host_preparations(Count) –Number of setup attempts of the classical computations that the Method runs on this computer.
-
host_preparation_work_reserved(Count) –Work of the setups of classical computations counted in this Run.
-
host_invocations(Count) –Number of classical computations started, interrupted ones included.
-
host_work_reserved(Count) –Work of classical 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 saved data when the trace was taken.
-
synthesis_work_reserved(Count) –Work of the exact syntheses of dense unitaries counted against
max_synthesis_workin 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, orNone. 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
ExecutionLimitswhen the trace was taken, orNonefor a trace recorded without them. -
limit_amendments(tuple[LimitAmendment, ...]) –Every raise of the limits so far (
LimitAmendmentrecords), 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. 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 trace and exposure. 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
JobLocatorof the original provider job or remote preparation, with itsjob_id, orNonewhen none was acknowledged. -
failure–The recorded failure text, or
None. -
directory–The Run's folder, or
Nonefor a Run without one. -
trace–The
ExecutionTraceat the time of the error. -
exposure–Read-only copy of
Run.exposureat 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 (a
JobLocator, the provider's identifier of the job) 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
preparedis 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_sequencesdoes not matchprepared.
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
methodis 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=None, 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.saveis not a Run folder. Keep it available and writable while the Run is open, because the Run records its progress there. -
backend(object | None, default:None) –Backend with the configuration that the Run was saved with. Omitted or
None, a classical Run reopens without a backend and a quantum Run reopens on the defaultAerBackend(), as inprepare. A Run saved with any other backend needs that backend. 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,
Falseto disable it, orNonefor the notebook display, as forprepare.
Returns:
-
run(Run) –The open Run. Close it when done, for example with
with load_run(path) as run:.
Raises:
-
ValueError–If the saved records fail their checks, if
backenddiffers from the saved configuration (the message names the saved configuration), or if a Method outside NWQLib is saved andmethodis 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
>>> 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) as run:
... print(run.wait().value)
1.0
A Method family that runs a sequence of Plans documents that sequence on its own page. QHD's augmented-Lagrangian layer and box refinement run one ordinary QHD Plan per round or level, each with prepare and submit. Each Plan draws its own random streams from one root seed, in the same way that compare seeds each Method. With directory=... these Runs are saved as they run. resume_augmented_lagrangian and resume_box_refinement continue an interrupted run. They reopen the unfinished Run with load_run and pass it the progress argument 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:
PreparedHandlePreparedHandle.inspect_circuitPreparedHandle.inspect_resourcesMethodMethod.analyzeMethod.error_modelMethod.executeMethod.planMethod.prepareMethod.prepare_all_refusalMethod.query_catalog_reasonMethod.recover_analysisMethod.verifyPlan.resolveResult.validate_planProblemRecord.default_output
PhysicalScale is documented on Inputs and input types: