LCHS¶
Use LinearDynamics(A=..., initial_state=..., time=..., source=...) with LCHS to approximate the solution of du/dt = -A u + b at the final time. Choose the physical solution, a state vector, a norm, an observable or samples through the output quantities. The LCHS guide explains finite quadrature, the evolution backends, scale recovery and the error components.
from nwqlib.algorithms.lchs import LCHS, LCHSRefinement, LCHSVerification
Solve a linear ODE¶
LCHS ¶
Bases: Method
LCHS method for the solution of a linear ODE given by LinearDynamics.
Build it with keyword arguments and pass it as method=, for example
solve(LinearDynamics(A=A, initial_state=u0, time=T), method=LCHS()).
Every argument is optional. The result is an
LCHSAnalysis
whose solution, for the default Solution output, approximates
u(T) = exp(-A T) u0 + (integral_0^T exp(-A s) ds) b, the solution of
du/dt = -A u + b at elapsed time T, with u0 the initial_state and b
the source (An, Childs and Lin, arXiv:2312.03916v2, here ACL,
Eq. (2)).
Linear combination of Hamiltonian simulation (LCHS) writes exp(-A T)
as an integral over real k of g(k) exp(-i T (k L + H)), with
A = L + iH, L = (A + A^dagger)/2 and H = (A - A^dagger)/(2i)
(ACL Eqs. (3)-(4), (6) and (60)), and replaces the integral by a finite
sum over quadrature nodes k_j. L must be positive semidefinite,
or the default make_l_psd=True shifts it. The default kernel is ACL's
near-optimal kernel, Eq. (7), with beta = 0.75, on composite Gauss
quadrature. lchs_kernel also offers the Cauchy kernel (An, Liu and
Lin, doi:10.1103/PhysRevLett.131.150603, restated as ACL Eqs. (5) and
(181)) and the Low–Somma kernel (Low and Somma, arXiv:2508.19238v2,
Eq. (6)), whose integral representation is approximate (their Eq. (8)).
approximation_tolerance bounds only the kernel-integral and
k-quadrature components of the error. It does not bound the total error
of the physical output, which also depends on input scaling, PSD
recovery, state preparation, evolution and floating-point error. The
default dense_exact backend computes each branch matrix
exp(-i t (k_j L + H)) classically and builds one dense SELECT circuit,
which applies branch j when its address register holds j. The
product-formula and qsp_block_encoding backends build more structured
circuits, each with its own limit checks.
Vector outputs (Solution, StateVector) need exact amplitude readout,
so they take no shots. Samples needs execution="quantum" and
positive shots. execution="classical" takes no shots and does not
run the qsp_block_encoding backend. result.analyze() takes no
settings, because the Plan fixes the recovery scale and coordinates.
result.verify(checks=...) takes one
LCHSVerification
or LCHSRefinement,
extra computation that plan, solve and analysis never run. The
LCHS guide explains kernel and quadrature
selection, the evolution backends and each error component.
Examples:
The exact solution of this two-coordinate problem at T = 0.1 is
exp(-0.1 A) [1, 0], approximately [0.96082565, -0.00484022].
The default run on local Aer differs from it by about 0.000821 in
the L2 norm.
>>> import numpy as np
>>> from nwqlib import LinearDynamics, solve
>>> from nwqlib.algorithms.lchs import LCHS
>>> problem = LinearDynamics(A=[[.4, .15], [.05, .25]],
... initial_state=[1, 0], time=.1)
>>> result = solve(problem, method=LCHS())
>>> print(np.round(result.solution, 4))
[ 0.9601-0.j -0.0051+0.j]
Attributes:
-
approximation_tolerance(Real) –Default
0.01, strictly between 0 and 1. Construction tolerance of the kernel-quadrature pair, in the operator norm for a unit input before PSD growth. The default pair gives half to the cutoff tail and half to the k quadrature. QSP synthesis, and each node oftrotter_error_budgeted, separately receives 0.1 times this value. Planning refuses a coefficient table whose binary64 roundingu*alphaexceeds 0.1 times this value, withu = 2**-53and alpha the coefficient 1-norm. It is not a tolerance on the total physical-output error. -
lchs_kernel(Any) –Default
"near_optimal_eq7"withbeta=0.75. Kernel g(k) of the integral, given as a name, as a dict{"implementation": name, "parameters": {...}}or as aProviderConfig."near_optimal_eq7"is ACL Eq. (7) withbetastrictly between 0 and 1."cauchy_density"is the Cauchy kernel and takes no parameters."low_somma_f2"is the Low–Somma kernel with shiftc > 0, default 1, whose coefficient 1-norm grows with c. It requiresapproximation_toleranceat most 4/5 and gives the kernel-integral and quadrature components a third of it each (Low and Somma, Theorems 2-4). -
k_quadrature(Any) –Default
"composite_gauss"withtruncation_multiplier=1. Quadrature rule in k, given likelchs_kernel."composite_gauss"chooses the cutoff and the Gauss–Legendre panels from the tolerance, andtruncation_multiplier, at least 1, enlarges the cutoff."signed_binary_uniform"is a uniform grid of2**num_qubitsnodes with spacing2**lsb_position, both required, and carries no error bound."symmetric_uniform_trapezoid"is the Low–Somma trapezoid rule and takes no parameters. The allowed pairs arenear_optimal_eq7withcomposite_gauss(both component bounds hold) or withsigned_binary_uniform,cauchy_densitywithsigned_binary_uniform, andlow_somma_f2withsymmetric_uniform_trapezoid(both component bounds hold, and the synthesis stages are not budgeted with them). Building the Method refuses any other pair. -
hamiltonian_evolution_backend(Literal['dense_exact', 'trotter', 'trotter_error_budgeted', 'qsp_block_encoding']) –Default
"dense_exact". How each branchexp(-i t (k_j L + H))is built."dense_exact"computes the branch matrix from the node's Hermitian eigensystem and controls its circuit."trotter"uses a sorted-Pauli product formula of ordertrotter_orderwithtrotter_stepssteps."trotter_error_budgeted"gives each node the smallest step count whose product-formula bound plus the Pauli pruning bound fits 0.1 timesapproximation_tolerance(Childs et al., doi:10.1103/PhysRevX.11.011020, Propositions 9-10 and Sec. V B)."qsp_block_encoding"evolves under the joint generator with quantum signal processing on block encodings of L and H (Pocrnic et al., arXiv:2506.20760v2, Section IV) and needs quantum execution. APeriodicStencilA needs"trotter"withtrotter_order=2and quantum execution. -
lcu_select_implementation(Literal['auto', 'multiplexor', 'structured', 'branch_controlled']) –Default
"auto". How the SELECT circuit applies the branches."dense_exact"accepts"auto"or"branch_controlled", and"qsp_block_encoding"accepts only"auto". With"trotter_error_budgeted","auto"gives"multiplexor", and"structured"is refused, because per-node step counts break the affine address structure. With"trotter","auto"gives"structured"only when an affine address structure is eligible, as checked from the k-node addresses and the real Pauli coefficients of the generator, and its CX count is lower than the multiplexor's, and gives"multiplexor"otherwise. An explicit"structured"without that eligibility is refused. APeriodicStencilA accepts"auto"or"structured". -
dense_control_route(Literal['gatewise', 'whole_matrix', 'auto']) –Default
"auto". How a construction controls a dense unitary on two or more qubits. It applies to adense_exactbranch on its address bits and to a dense-dilation QSP child on the combine qubit of the joint generator."gatewise"synthesizes the unitary and lets Qiskit control each synthesized gate,"whole_matrix"synthesizes the controlled matrix, and"auto"takes the whole-matrix route for one control and the gate-wise route for more. On the whole-matrix route a constant-source branch is one unitary, its evolution times the matrix of its input preparation. The QSP pass that holds the generator is controlled gate-wise on every route. -
trotter_steps(PositiveInt | None) –Default
1. Fixed step count of the"trotter"backend, a positive integer at mostmax_trotter_steps, orNonewhentrotter_synthesis_tolerancechooses it. Exactly one of the two is set."trotter_error_budgeted"chooses its own counts and requires the default 1."dense_exact"and"qsp_block_encoding"apply no product formula, so they treat any value as 1, and planning warns about a value other than 1. -
trotter_synthesis_tolerance(Real | None) –Default
None. Positive tolerance on the Strang synthesis bound of aPeriodicStencilA, in the same unit-input operator norm asapproximation_tolerance. Planning chooses the smallest step count r withB/r**2at most this value, whereB = T**3 sum_j |c_j| (2 |k_j| diffusion + |potential|)**3 / 3over the nodes k_j and coefficients c_j (Childs et al., doi:10.1103/PhysRevX.11.011020, Proposition 10, Eq. (121), relaxed by NWQLib). It requireshamiltonian_evolution_backend="trotter"andtrotter_steps=None, and other inputs refuse it. -
trotter_order(Literal[1, 2]) –Default
2. Order of the product formula of the"trotter"and"trotter_error_budgeted"backends, 1 for the Lie formula or 2 for the symmetric Suzuki (Strang) formula."dense_exact"and"qsp_block_encoding"accept only 2. -
max_trotter_steps(PositiveInt) –Default
100_000. Upper limit on the product-formula step count, fixed or chosen automatically. -
duhamel_nodes(PositiveInt) –Default
8. Number of Gauss–Legendre nodes of the time integral of a constant source, one panel on [0, T] (ACL Eq. (72)). It is never reduced automatically to fit a limit. -
make_l_psd(StrictBool) –Default
True. Rule for an eigenvalue of L below-psd_tolerance*||L||_2.Trueshifts L bys = -lambda_min + psd_tolerance*||L||_2and multiplies the result by the growth factorexp(s*T).Falserefuses the input. -
psd_tolerance(Real) –Default
1e-12, positive. Relative window of the PSD check. An eigenvalue of L at or above-psd_tolerance*||L||_2is accepted without a shift. The window is the scale of the eigensolver's rounding (LAPACK Users' Guide, 3rd ed., Sec. 4.7), so the decision does not depend on the time unit. It does not permit a negative eigenvalue below that window. -
initial_state_preparation(Literal['direct', 'mps_circuit']) –Default
"direct", which prepares the initial state exactly."mps_circuit"prepares it approximately with a layered circuit from a matrix-product-state (MPS) compression. Quantum execution with a constant source, or with aPeriodicStencilA, requires"direct". -
initial_state_mps_max_bond_dim(PositiveInt | None) –Default
None, no limit. Upper limit on the kept bond dimension of the initial-state compression. -
initial_state_mps_threshold(Real) –Default
1e-14, positive. Singular-value truncation threshold of the initial-state compression. -
initial_state_mps_num_layers(PositiveInt) –Default
2, positive. Number of layers of the initial-state MPS circuit. -
lcu_state_preparation(Literal['direct', 'mps_circuit']) –Default
"direct". Preparation of the coefficient statesqrt(|c_j|/alpha)that weights the branches, with the same choices and restrictions asinitial_state_preparation. The circuit error of"mps_circuit"stays unevaluated until an explicit validation, even when the compression discards no weight. -
lcu_mps_max_bond_dim(PositiveInt | None) –Default
None, no limit. Upper limit on the kept bond dimension of the coefficient-state compression. -
lcu_mps_threshold(Real) –Default
1e-14, positive. Singular-value truncation threshold of the coefficient-state compression. -
mps_num_layers(PositiveInt) –Default
2, positive. Number of layers of the coefficient-state MPS circuit. -
max_dense_select_slots(PositiveInt) –Default
256. Upper limit on the padded address count, a power of two, of the dense SELECT circuit of"dense_exact". Planning refuses a larger construction and never changes the grid, Duhamel nodes or tolerance to fit. -
max_bytes(PositiveInt) –Default 10 GB (decimal,
10_000_000_000bytes). Upper limit on the known bytes of input and numerical workspace. -
max_svd_work(PositiveInt) –Default
1e8(100_000_000). Upper limit on the counted work of state and coefficient compression, including the construction of an"mps_circuit"layered circuit. -
max_spectral_work(PositiveInt) –Default
1e8. Upper limit on the counted work of the eigenvalue check of L for dense A,d**3for physical dimension d, so the default accepts a dense A of dimension at most 464 when L is nonzero. A periodic stencil has an analytically PSD L and no eigenvalue check. -
max_quadrature_work(PositiveInt) –Default
1e8. Upper limit on the counted work of building the k nodes and weights. For"composite_gauss"it covers the completed panel search plus the construction of the chosen rule, not every scalar probe. -
max_select_work(PositiveInt) –Default
1e8. Upper limit on the counted work of building the SELECT circuit, including the branch matrices and their synthesis for"dense_exact"and the Pauli decomposition of the product-formula backends. The LCHS guide gives the sizes that fit this default. -
max_readout_work(PositiveInt) –Default
2_000_000_000. Upper limit, inclusive, on the comparisons of grouping sampled Pauli terms and the input visits of exact scalar readout (shots=None). Planning checks and records the grouping comparisons. Before the circuits run, each exact readout is checked against what remains, and completed exact readouts count against it. -
max_qsp_degree(PositiveInt) –Default
256. Upper limit on the QSP polynomial degree of"qsp_block_encoding". -
max_qsp_evaluations(PositiveInt) –Default
20_000. Upper limit on the residual evaluations of the QSP phase solver. -
max_admission_steps(PositiveInt) –Default
1_000_000, ten times the shared default. Upper limit on the planning work of checking eachProgramof the Plan (NWQLib's description of a circuit as named steps), counting its stored fields and the structural and lifecycle work of one check. Summing a Program's resource counts may use up to 24 times this value. Raising it changes no quantum operation. See the planning work limit.
Raises:
-
ValueError–If the kernel-quadrature pair is not allowed or a kernel or quadrature parameter is invalid, if both or neither of
trotter_stepsandtrotter_synthesis_toleranceare set, iftrotter_synthesis_toleranceis set without the"trotter"backend, if"trotter_error_budgeted"getstrotter_stepsother than 1, iftrotter_stepsexceedsmax_trotter_steps, or iftrotter_order=1is set without a product-formula backend. -
TypeError–If
lchs_kernelork_quadratureis not a name, a dict or aProviderConfig.
ProviderConfig ¶
ProviderConfig(*, implementation: str, parameters: Mapping[str, ProviderParameter] = dict())
Choice of an LCHS kernel or k-quadrature rule, with its explicit parameters.
Build it with keyword arguments and pass it as lchs_kernel= or
k_quadrature= of LCHS or of
resolve_lchs_coefficient_plan,
for example
LCHS(lchs_kernel=ProviderConfig(implementation="near_optimal_eq7", parameters={"beta": 0.7})).
implementation is the only required argument. LCHS also accepts the
name alone or a dict with these two keys. The lchs_kernel and
k_quadrature rows of LCHS list the names and their parameters.
Attributes:
-
implementation(str) –Required. Kernel or quadrature name. Building this record does not check the name, and
LCHSrefuses an unknown one. -
parameters(Mapping[str, ProviderParameter]) –Default empty. Parameter names mapped to JSON scalars or
None, stored sorted and read-only. The named rule supplies the defaults and range checks whenLCHSresolves it.
ProviderParameter ¶
ProviderParameter: TypeAlias = str | int | float | bool | None
Type of one kernel or quadrature parameter value, a JSON scalar or None.
Read the result¶
LCHSAnalysis ¶
Bases: Result
Solution or requested output of du/dt = -A u + b from an LCHS run.
solve returns it for an LCHS method, and
load_result reopens a saved one. For the default Solution output the
answer is solution, the physical solution u(T) in the original
coordinates, with its norm and phase, in the problem's unit. A
StateVector output is in state_vector. NormSquared,
QuadraticForm and NormalizedExpectation give the scalar value, and
Samples gives samples. Counts do not recover a complex vector. When
the output cannot be recovered, unavailable gives the reason, for
example a normalized output at zero physical mass. print(result)
shows the value with the construction tolerance and the kernel bounds,
each labeled as not a total error bound. result.analyze() takes no
settings. The fields below are read-only. The fields of
Result are present too.
The kernel-integral and k-quadrature bounds are facts of the Plan
(result.plan.facts), and a classical Result also carries them in
result.facts. They are physical L2 bounds of error components, not a
bound on the total error of the output. No reference solution is
computed unless result.verify is called.
Attributes:
-
value(Real | None) –Requested scalar of a
NormSquared,QuadraticFormorNormalizedExpectationoutput, physical or unit-normalized as that output defines it.Nonefor vector andSamplesoutputs and when unavailable. -
unavailable(Text | None) –Reason the requested output cannot be recovered, or
None. -
norm_squared(Nonnegative | None) –Recovered physical norm squared
||u(T)||**2, when available. -
physical_scale(PhysicalScale | None) –Physical scale of the obtained vector, when representable.
-
numerator(Real | None) –Observable value, the normalized ratio for a
NormalizedExpectationand the recovered physical quadratic form for aQuadraticForm. -
numerator_frame(Literal['physical', 'unit'] | None) –Normalization of
numerator,"unit"for the normalized ratio or"physical"for the quadratic form. -
artifact(ArtifactManifest | None) –Description of the stored solution or state array. Printing the result does not load the array, and
solutionandstate_vectorread it. -
applications(tuple[KernelApplication, ...]) –Numerical operator applications of the run, each with its error-component facts.
-
references(Literal['not_run']) –Always
"not_run". An independent reference needsresult.verify(checks=LCHSVerification(...)). -
submitted_shots(Count | None) –Shots requested for a sampled output, if applicable.
-
returned_shots(Count | None) –Shots returned, before selection of the physical coordinates.
-
selected_shots(Count | None) –Returned shots kept for the physical output. For
Samples, the sum of the sample counts. -
samples(LCHSSamples | None) –For a
Samplesoutput, the distinct original-coordinate indices (samples.indices, increasing, padding coordinates excluded) and their positive counts (samples.counts), both int64 arrays. They do not cover all submitted shots. -
reduction(LCHSProjectedMoments | None) –Saved statistics of the exact scalar readout (
shots=None): the complete, success and physical-slice masses and the projected moment, as mantissa-exponent pairs. -
groups(tuple[LCHSGroupMoments, ...]) –Weighted moments of each sampled measurement setting, with its Pauli labels, basis and returned and selected shots.
solution ¶
solution
The physical solution u(T) of a Solution output, a complex array.
It is in the original coordinates and keeps the physical norm and
phase. With no evolution (time equal to initial_time, or a zero
input) it is the supplied initial vector.
Raises:
-
AttributeError–If the requested output was not
Solution. -
ValueError–If the array is unavailable, with the reason.
state_vector ¶
state_vector
The state vector of a StateVector output, a complex array.
It is in the original coordinates, normalized and phased as the
StateVector output requests.
Raises:
-
AttributeError–If the requested output was not
StateVector. -
ValueError–If the array is unavailable, with the reason.
Check a result¶
LCHSVerification compares the physical solution with an independent reference, and LCHSRefinement evaluates error components that planning leaves unknown. Each runs only when passed to result.verify(checks=...).
LCHSVerification ¶
Bases: Record
Reference comparison for the physical solution of an LCHS Result.
Build it with keyword arguments and pass it to
result.verify(checks=...), for example
result.verify(checks=LCHSVerification(reference="expm")). reference
is the only required argument. The call returns (receipt, facts).
facts[0].fact.value.value is the discrepancy between the Result's
physical solution u and the reference u_ref, and the receipt records
every computed value and call count. The check is named name, and
"ivp_closed_form" adds name + ".reference_consistency".
Certificate.with_verification turns facts into PASS when the value
is at most threshold, FAIL when it is larger, and INCONCLUSIVE when
the value or the threshold is missing.
Planning, solving and ordinary analysis never compute a reference.
The Result must hold a physical solution vector with its phase, from a
Solution output or a physical StateVector, and A must be a dense
matrix, never converted from a compact input. The work limits cover the
whole call, including both references of "ivp_closed_form" and every
node of "selected_grid". Dense work is a size-based count, not a
floating-point operation count. Reference arrays are temporary, and only
discrepancies and call counts are kept. A discrepancy is numerical
evidence for this input, not a proven error bound. The
LCHS guide
shows a complete check.
Attributes:
-
reference(Literal['expm', 'ivp', 'closed_form', 'ivp_closed_form', 'selected_grid']) –Required.
"expm"compares withexp(-A T) u0for dynamics without a source (An, Childs and Lin, arXiv:2312.03916v2, here ACL, Eq. (2) with b = 0)."ivp"solvesdu/dt = -A u + bwith SciPy's RK45 under explicitrtol,atolandmax_rhs_calls."closed_form"evaluates ACL Eq. (2) for a constant source with one exponential of[[-A*T, b*T], [0, 0]]."ivp_closed_form"runs both and also reports their signed consistency. These three need a source. A matrix with 1-norm above2**37, or with an exponential that is not finite in binary64, gives an unknown discrepancy."selected_grid"reproduces the saved finite sum, with its nodes and product-formula steps, so its discrepancy excludes the kernel-integral, k- and Duhamel-quadrature and product-formula errors. -
name(Text) –Default
"reference_error". Name of the reported discrepancy and prefix of its companion values. -
metric(Literal['absolute_l2', 'relative_l2']) –Default
"absolute_l2", the norm||u - u_ref||_2without a global-phase fit."relative_l2"divides it by||u_ref||_2. -
threshold(Nonnegative | None) –Default
None. Optional nonnegative pass threshold of the discrepancy check. -
consistency_threshold(Nonnegative | None) –Default
None. Optional nonnegative threshold of the consistency check between the IVP and closed-form references, only for"ivp_closed_form". -
rtol(Real | None) –Default
None. Positive RK45 relative tolerance, at least SciPy's floor of 100 times the binary64 machine epsilon. Required for"ivp"and"ivp_closed_form"and refused otherwise. -
atol(Real | None) –Default
None. Positive RK45 absolute tolerance. Required for"ivp"and"ivp_closed_form"and refused otherwise. -
max_rhs_calls(PositiveInt | None) –Default
None. Upper limit on RK45 right-hand-side evaluations. Required for"ivp"and"ivp_closed_form"and refused otherwise. -
max_bytes(PositiveInt) –Default 10 GB (decimal,
10_000_000_000bytes). Upper limit on the known arrays of this call. -
max_dense_work(PositiveInt) –Default
1e8(100_000_000). Upper limit on the counted dense work of this call. For"selected_grid"it also covers reading the stored product-formula node table and the node actions. -
max_node_evaluations(PositiveInt) –Default
4096. Upper limit on the number of k nodes times operator applications evaluated. -
max_pf_operations(PositiveInt) –Default
100_000. Upper limit on the product-formula rotations or elementary gates that"selected_grid"evaluates.
Raises:
-
ValueError–If an IVP reference lacks
rtol,atolormax_rhs_calls, ifrtolis below SciPy's floor, if these are given for another reference, or ifconsistency_thresholdis given without"ivp_closed_form".result.verifyalso raises for"expm"with a source, for the source references without one, and for a non-dense A.
LCHSRefinement ¶
Bases: Record
Error-component bounds of an LCHS Result at its saved grid and step counts.
Build it with keyword arguments and pass it to
result.verify(checks=...), for example
result.verify(checks=LCHSRefinement(components=("duhamel",))).
components is the only required argument. The call returns
(receipt, facts). facts holds the refined physical L2 components and
their sum carried into the requested output, algorithmic_approximation,
which result.assess can use. A request for "spectral_norms" alone
leaves facts empty. The receipt holds every computed value.
Refinement defines no pass or fail check.
Planning leaves two components unknown for a dense A, the Duhamel
remainder of a constant source and the synthesis error of fixed-step
"trotter". Refinement evaluates them at the saved quadrature, Duhamel
nodes and step counts and replaces the planned values of the same name.
It never computes a solution vector, chooses a new grid or step count,
or converts a compact input to a dense matrix. algorithmic_approximation
stays None while any component is unknown, because a missing term is
not zero. It covers the algorithmic components only. Floating-point
error of the backend run and sampling error remain separate terms.
Attributes:
-
components(tuple[Literal['spectral_norms', 'duhamel', 'fixed_pf'], ...]) –Required. Distinct analyses, at least one.
"spectral_norms"evaluates||A||,||A + shift*I||and||H||and needs a dense A."duhamel"evaluates the Gauss–Legendre remainder of the source time integral (DLMF Eqs. 3.5.19 and 3.5.21)."fixed_pf"evaluates the product-formula commutator bound at the saved step counts (Childs et al., doi:10.1103/PhysRevX.11.011020, Propositions 9-10) and needs the"trotter"or"trotter_error_budgeted"backend. -
name(Text) –Default
"refinement". Prefix of the reported values that are not error components, such as the spectral norms. -
dense_validation(StrictBool) –Default
False. Also evaluate dense commutator norms for"fixed_pf", as a check of the Pauli-triangle bound that does not replace it. Requires"fixed_pf", and a periodic stencil refuses it. -
max_bytes(PositiveInt) –Default 10 GB (decimal,
10_000_000_000bytes). Upper limit on the known arrays of this call. -
max_dense_work(PositiveInt) –Default
1e8(100_000_000). Upper limit on the counted dense work of this call. -
max_structural_work(PositiveInt) –Default
1e8. Upper limit on the counted work of reading the stored node table, preparing the count of Pauli commutator terms and evaluating them. -
max_node_evaluations(PositiveInt) –Default
4096. Upper limit on the number of k nodes times operator applications evaluated. -
max_steps(PositiveInt) –Default
100_000. Largest saved product-formula step count this call accepts.
Raises:
-
ValueError–If
componentsis empty or repeats a name, or ifdense_validationis set without"fixed_pf".
Inspect the coefficient table¶
resolve_lchs_coefficient_plan ¶
resolve_lchs_coefficient_plan(problem_or_plan, *, lchs_kernel=None, k_quadrature=None, approximation_tolerance=None, max_bytes=DEFAULT_INPUT_BYTES)
Return the LCHS coefficient table of a problem without a source, or of an LCHS Plan.
For a LinearDynamics without a source, it computes the k nodes, the
weights and the coefficients c_j of the finite sum
sum_j c_j exp(-i T (k_j L + H)) u0, with L after any PSD shift, from
the given kernel, quadrature and tolerance. It builds no SELECT circuit
or QSP phases, computes no output vector and runs nothing on a backend.
For a Plan made by plan(problem, method=LCHS(...)), it returns the
table that the Plan executes, so an analysis of the coefficient tensor
always describes those coefficients. Call decompose_mps on the result
to study the MPS compression of the coefficient state, as in the
coefficient MPS analysis
of the LCHS guide.
Parameters:
-
problem_or_plan(LinearDynamics | Plan) –A
LinearDynamicswithout a source and with positive elapsed time, or an LCHS Plan with a coefficient table for an input without a source. -
lchs_kernel(ProviderConfig | None, default:None) –Kernel choice.
Noneselects"near_optimal_eq7", as inLCHS. Must beNonefor a Plan. -
k_quadrature(ProviderConfig | None, default:None) –Quadrature choice.
Noneselects"composite_gauss", as inLCHS. Must beNonefor a Plan. -
approximation_tolerance(float | None, default:None) –Construction tolerance, strictly between 0 and 1.
Noneselects0.01, as inLCHS. Must beNonefor a Plan. -
max_bytes(int, default:DEFAULT_INPUT_BYTES) –Default 10 GB (decimal,
10_000_000_000bytes). Upper limit on the arrays of the Cartesian parts and the PSD check, tested before they are formed. APeriodicStencilA forms no matrix and uses the bound||L|| <= mass + 4*diffusion.
Returns:
-
coefficients(LCHSCoefficientPlan) –The nodes, weights, coefficients and component bounds. For a dense A the coefficients include the PSD growth factor
exp(shift*T), divided by2**ewhen the factor exceeds binary64, as recorded inderived_parameters["homogeneous_coefficient_compensation"].
Raises:
-
ValueError–If the problem has a source or zero elapsed time, if
approximation_toleranceis outside (0, 1), or if a Plan is given with any of the three choices or holds no coefficient table for an input without a source. -
TypeError–If
problem_or_planis neither aLinearDynamicsnor a Plan.
LCHSCoefficientPlan ¶
LCHSCoefficientPlan(*, requested_lchs_kernel: ProviderConfig, resolved_lchs_kernel: ResolvedProviderConfig, requested_k_quadrature: ProviderConfig, resolved_k_quadrature: ResolvedProviderConfig, lchs_kernel_formula_id: str, k_quadrature_formula_id: str, lchs_kernel_fixed_parameters: Mapping[str, ProviderParameter], kernel_parameter_selection: Mapping[str, str], derived_parameters: Mapping[str, ProviderParameter], nodes: tuple[float, ...], base_weights: tuple[float, ...], coefficients: tuple[complex, ...], coefficient_l1_norm: float, quadrature: LCHSQuadraturePlan, compatibility: LCHSPairCompatibility, mps_decomposition: object | None = None)
Nodes, weights and coefficients of the finite LCHS sum, shared by every backend.
resolve_lchs_coefficient_plan
returns it. The finite sum is sum_j c_j exp(-i T (k_j L + H)) u0
over the nodes k_j and coefficients c_j. The fields below are
read-only.
Attributes:
-
requested_lchs_kernel(ProviderConfig) –Kernel choice as given, showing which parameters the caller supplied.
-
resolved_lchs_kernel(ResolvedProviderConfig) –Kernel used, with its defaults filled in.
-
requested_k_quadrature(ProviderConfig) –Quadrature choice as given.
-
resolved_k_quadrature(ResolvedProviderConfig) –Quadrature used, or the algebraic reduction for an exactly zero L.
-
lchs_kernel_formula_id(str) –Versioned identifier of the kernel formula.
-
k_quadrature_formula_id(str) –Versioned identifier of the node and weight formula.
-
lchs_kernel_fixed_parameters(Mapping[str, ProviderParameter]) –Constants of the kernel formula that are not user parameters, such as Low–Somma
j=2andy=1. -
kernel_parameter_selection(Mapping[str, str]) –Where each parameter value came from, normally
"user"or"provider_default", with a profile identifier where one applies. -
derived_parameters(Mapping[str, ProviderParameter]) –Quantities derived for the pair, such as the Low–Somma
gamma,R,handJ. A problem without a source also records its PSD-shift compensation here. -
nodes(tuple[float, ...]) –Ordered real k values, as in
quadrature. -
base_weights(tuple[float, ...]) –Integration weights before multiplication by the kernel.
-
coefficients(tuple[complex, ...]) –Complex coefficients c_j in node order. For a problem without a source they include the PSD growth factor
exp(shift*T), divided by2**ewhen the factor exceeds binary64, and the physical recovery carries2**e. Their phases are applied in the SELECT circuit. -
coefficient_l1_norm(float) –sum_j |c_j|, the normalization of the coefficient state. It is neither the physical output norm nor an error estimate. -
quadrature(LCHSQuadraturePlan) –Node and address data of the rule, with its component bounds
approximate_lchs_error_bound(kernel integral, the cutoff tail for the default kernel) andquadrature_error_bound, each for a unit input before PSD growth.Nonemeans unavailable, not zero. -
compatibility(LCHSPairCompatibility) –Pair status,
certificate_status"certified","uncertified","incomplete"or"exact_algebraic"for the zero-L reduction, with itsreasonandunbudgeted_error_stages. None of these alone certifies a complete physical solution. -
mps_decomposition(object | None) –Attached TT-SVD (MPS) decomposition of the normalized, padded coefficient-state amplitudes, or
None.decompose_mpsreuses it only for the same tensor ordering and truncation settings.
prep_amplitudes ¶
prep_amplitudes(*, max_bytes=DEFAULT_INPUT_BYTES)
Return the coefficient-state amplitudes sqrt(|c_j|/alpha), zero-padded.
alpha is coefficient_l1_norm, and the array length is the next
power of two at or above len(coefficients). The complex phases of
c_j are not in this state. The SELECT circuit applies them (An,
Childs and Lin, arXiv:2312.03916v2, Lemma 24, Eq. (178), with the
phases moved from the two preparation oracles into SELECT).
Parameters:
-
max_bytes(int, default:DEFAULT_INPUT_BYTES) –Default 10 GB (decimal,
10_000_000_000bytes). Upper limit on the arrays, 96 bytes per padded address, checked first.
Returns:
-
amplitudes(ndarray) –Read-only amplitudes, one per padded address.
decompose_mps ¶
decompose_mps(max_bond_dim=None, threshold=1e-14, *, reuse=None, max_bytes=DEFAULT_INPUT_BYTES, max_svd_work=100000000)
Return the TT-SVD (MPS) decomposition of the prep_amplitudes tensor.
A stored or supplied decomposition is reused only when it was made
from this exact normalized tensor with the same max_bond_dim and
threshold. Otherwise a new TT-SVD runs under max_bytes and
max_svd_work. No LCHS solve or circuit is run.
Parameters:
-
max_bond_dim(int | None, default:None) –Upper limit on the kept bond dimension.
Nonemeans no limit. -
threshold(float, default:1e-14) –Singular-value truncation threshold.
-
reuse(MPSDecomposition | None, default:None) –Decomposition to reuse instead of the attached
mps_decomposition. -
max_bytes(int, default:DEFAULT_INPUT_BYTES) –Default 10 GB (decimal,
10_000_000_000bytes). Upper limit on the known arrays. -
max_svd_work(int, default:100000000) –Upper limit on the counted TT-SVD work.
Returns:
-
decomposition(MPSDecomposition) –The TT cores, bond dimensions and discarded weight, the sum of the squared singular values discarded.
Raises:
-
TypeError–If
reuseis not anMPSDecomposition. -
ValueError–If
reusedoes not match the tensor or the settings, instead of being replaced silently.
record ¶
record() -> dict[str, Any]
Return the kernel, quadrature and pair choices with their bounds as a plain dict.
The keys name the requested and resolved kernel and quadrature,
their parameters and formula identifiers, the node order, panel
width and address structure, the pair's certificate status, the
component bounds approximate_lchs_error_bound and
quadrature_error_bound, and the unbudgeted_error_stages.
ResolvedProviderConfig ¶
ResolvedProviderConfig(*, implementation: str, parameters: Mapping[str, ProviderParameter])
Kernel or quadrature choice after its defaults and checks are applied.
It appears in the resolved_lchs_kernel and resolved_k_quadrature
fields of an
LCHSCoefficientPlan.
The fields below are read-only.
Attributes:
-
implementation(str) –Name of the rule used. For an exactly zero L the algebraic reduction
"unitary_reduction"replaces the requested quadrature name. -
parameters(Mapping[str, ProviderParameter]) –Every parameter after defaults, stored sorted and read-only. Together with
implementation, they identify the configuration.
Lower-level functions¶
cartesian_decomposition ¶
cartesian_decomposition(matrix: Any, *, eigcheck: bool = True, psd_tolerance: float = DEFAULT_PSD_TOLERANCE, max_bytes=DEFAULT_MAX_BYTES, max_spectral_work=100000000) -> tuple[ndarray, ndarray]
Return the Hermitian parts (L, H) of A = L + iH used by LCHS.
L = (A + A^dagger)/2 and H = (A - A^dagger)/(2i), as in An, Childs
and Lin, arXiv:2312.03916v2, Eqs. (3)-(4). LCHS needs L positive
semidefinite (PSD), which keeps ||exp(-A t)|| <= 1 (same paper,
Lemma 21, Eq. (162)). With eigcheck=True the function also checks that
condition. eigcheck=False only decomposes. It does not establish
the PSD condition or replace the check of LCHS, which tests its own
eigenvalue endpoints.
Parameters:
-
matrix(array_like) –Finite square matrix A.
-
eigcheck(bool, default:True) –Check that L is PSD within
psd_tolerance. -
psd_tolerance(float, default:DEFAULT_PSD_TOLERANCE) –Default
1e-12. Relative window of the check. An eigenvalue of L at or above-psd_tolerance*||L||_2passes. -
max_bytes(int, default:DEFAULT_MAX_BYTES) –Default 10 GB (decimal,
10_000_000_000bytes). Upper limit on the arrays of the check,64 d**2 + 16 dbytes for dimension d, tested before they are formed. The count covers the known NumPy arrays, not the eigensolver's own LAPACK workspace. -
max_spectral_work(int, default:100000000) –Upper limit on the eigenvalue check of a nonzero L, counted as
d**3work units, which are not timings.
Returns:
-
parts(tuple[ndarray, ndarray]) –L and H as complex arrays.
Raises:
-
ValueError–If A is not a finite square matrix, or, with
eigcheck, if L has an eigenvalue below-psd_tolerance*||L||_2or the check exceedsmax_spectral_workormax_bytes.
duhamel_quadrature ¶
duhamel_quadrature(final_time: float, node_count: int) -> tuple[ndarray, ndarray]
Return Gauss–Legendre nodes and weights on [0, T] for the source time integral.
One Gauss–Legendre panel on [0, T] discretizes the Duhamel integral of
An, Childs and Lin, arXiv:2312.03916v2, Eq. (2), the single-panel case
of their Eq. (72). LCHS uses duhamel_nodes of these nodes for a
constant source. The rule is exact for polynomials of degree
2*node_count - 1. Its remainder bound follows DLMF Eqs. 3.5.19 and
3.5.21, and LCHSRefinement(components=("duhamel",)) evaluates it for
a Result.
Parameters:
-
final_time(float) –Positive, finite elapsed time T.
-
node_count(int) –Number of nodes, at least 1.
Returns:
-
rule(tuple[ndarray, ndarray]) –The nodes
T*(x_i + 1)/2and weightsT*w_i/2, from the Gauss–Legendre rule(x_i, w_i)on [-1, 1].
Raises:
-
ValueError–If
final_timeis not positive and finite ornode_countis below 1.
Limits¶
- A and the source are constant in time. General time-dependent A or source is not implemented.
- The Hermitian part L of A must be positive semidefinite, or the default
make_l_psd=Trueshifts it and restores the growth factor. approximation_toleranceand the kernel-integral and k-quadrature bounds are component bounds. They do not bound the total error of the physical output, and floating-point, backend and model errors remain separate.- The default
dense_exactbackend computes its branch matrices classically and accepts at mostmax_dense_select_slots=256padded addresses. - Reference checks need a dense A and a physical solution vector.
Limitations and open work lists the open items. The LCHS source map gives the paper, equation and implementing function of each step. To add a method of your own, see Extending NWQLib.