GCiM and ADAPT¶
Use Eigenproblem(A=...) with FixedGCIM(basis=...) or ADAPT(initial_state=..., pool=...) to estimate the smallest eigenvalue of A by solving the projected problem H f = E S f in a basis of trial states. FixedGCIM uses a basis that you supply, and ADAPT grows one from a generator pool. Both results report projected Ritz values, which do not certify the full-space ground energy.
from nwqlib import Eigenproblem, solve
from nwqlib.algorithms import ADAPT, FixedGCIM
from nwqlib.algorithms.gcim import build_gcim_chemistry_problem
Every object on this page imports from nwqlib.algorithms.gcim, except PairEstimate, GroupMoment, SampledPairVariance, ResolvedAcquisition, PairPreparation and ShotAllocation, which import from nwqlib.algorithms.gcim.fixed_basis. The methods, their results, BoundedRitzGrowth, PencilAcquisition, PencilSampling, ProjectedPencil, FixedGCIMBasis and AdaptVerificationOptions also import from nwqlib.algorithms.
FixedGCIM solves the discretized Hill-Wheeler problem of Zheng et al., Phys. Rev. Research 5, 023200 (2023), arXiv:2212.09205v1, Eq. (13). ADAPT follows Zheng et al., npj Quantum Information 10, 127 (2024), arXiv:2312.07691v3. The GCiM guide explains the matrix elements, their error bounds and the adaptive screening rule, and its source and code map gives the paper location of each step.
Solve in a fixed basis¶
FixedGCIM ¶
Bases: Method
Generator-coordinate (GCiM) method for the smallest eigenvalue in a fixed trial basis.
Build it with keyword arguments and pass it as method=, for example
solve(Eigenproblem(A=matrix), method=FixedGCIM(basis=(phi_1, phi_2))).
basis is the only required argument. The result is a
FixedGCIMResult
whose eigenvalue is the lowest Ritz value of the projected problem
H f = E S f, with H_ij = <phi_i|A|phi_j> and S_ij = <phi_i|phi_j>
for the normalized trial states phi_i. This is the discretized
Hill-Wheeler problem of Zheng et al., Phys. Rev. Research 5, 023200
(2023), arXiv:2212.09205v1, Eq. (13), with matrix elements
Eqs. (14)-(15). The trial states are the supplied states, normalized,
instead of the paper's states exp(Gamma(Z_p))|Phi> at discretized
generator coordinates Z_p (Eq. (10), discretized in Eq. (17)). A
projected Ritz value does not certify the full-space ground energy.
The call chooses how H and S are obtained, for M basis pairs of which D are diagonal:
- Default, exact quantum: one phase-faithful joint state per
off-diagonal pair and one system state per diagonal pair, each reduced
to the offset-free
H0_ijandS_ijas soon as it is prepared, so(M - D) + Dmeasurements. shots=n: the same joint state per off-diagonal pair, with its ancilla measured in X and Y together with each qubit-wise commuting group of system terms, and each diagonal pair's system state per group, soQ(M - D) max(1, G) + DGsettings for G groups, n shots each. Q is 2, or 1 whenacquisitionresolves real-only quadratures, which the default"auto"does exactly when A and every basis state are proved real. Each count table supplies its group's weighted Hamiltonian mean and, for the first group, the overlap and its covariance with that mean.sampling=PencilSampling(...)instead ofshots=: the same settings, measured in a uniform pilot stage and again in a main stage whose shots per setting the pilot pencil decides, with only the main-stage measurements in H and S.execution="classical":V^dagger (A - cI) VandV^dagger Vcomputed directly, withc = trace(A)/d.
Every path solves without the identity term and adds c to the Ritz
values afterwards. Sampled Ritz values are raw estimates, and the
enclosure diagnostic in result.pencil does not certify their physical
accuracy. overlap_cutoff can be changed after the run with
result.analyze(overlap_cutoff=...), which reuses the same matrix
elements. The GCiM guide describes the matrix
elements, their error bounds and the solve.
Attributes:
-
basis(tuple[StateData, ...]) –Required. Trial states phi_i, a nonempty tuple of states in a form that
StateDataaccepts. Each is normalized. -
overlap_cutoff(Real) –Default
1e-12, positive. Overlap eigenvectors with eigenvalues above it are kept for the solve. -
max_basis_size(PositiveInt) –Default
64. Largest accepted number of trial states, checked before pairs are formed. -
max_experiments(PositiveInt) –Default
100_000. Largest number of measurement settings: exact pair reductions, or sampled group settings. -
max_bytes(PositiveInt) –Default 10 GB (decimal,
10_000_000_000bytes). Limit on the known bytes of conversion, the pair table, the grouped count analysis and the projected solve, and on each exact pair reduction's workspace, checked when that pair is prepared. -
max_analysis_work(PositiveInt) –Default
1_000_000_000. Limit on the work of the projected matrices and eigensolve, of the comparisons that form qubit-wise commuting groups, and of each pass of the grouped count analysis. Sampled planning checks the worst-case pass for one measurement per setting before it builds circuits, and analysis checks the stored counts again before decoding them. The default is ten times the other work defaults because that planning bound is conservative (Engineering constants, row "Sampled FixedGCIM analysis admission"). -
max_classical_products(PositiveInt) –Default
100_000_000. Limit on the counted classical work of basis preparation and projection, and on the summed classical work of the exact pair reductions. -
input_conversion(Literal['auto', 'dense_pauli']) –Default
"auto", which keeps Pauli input as it is and, for quantum execution, converts an explicit dense matrix of original dimension at most 16 to Pauli form. Classical execution uses the supplied matrix representation."dense_pauli"also permits the conversion of sparse matrices and of larger dense matrices, withinmax_conversion_workandmax_bytes. -
max_conversion_work(PositiveInt) –Default
100_000_000. Limit on the counted work of operator-to-Pauli conversion, including the conversion thatinput_conversion="auto"selects. -
max_admission_steps(PositiveInt) –Default
10_000_000. Upper limit on the planning work of checking eachProgramthat the method builds (NWQLib's description of a circuit as named steps). It caps the number of stored fields of aProgramand the work units of one check of it. Summing aProgram's resource counts may use up to 24 times this value. A largerProgramis rejected with a ValueError that names this field, the planning stage that exceeded the limit and its count. Raising the limit permits a larger check and changes no quantum operation (planning work limit). -
acquisition(PencilAcquisition) –Default
PencilAcquisition(). How quantum execution measures H and S (PencilAcquisition). FixedGCIM measures grouped joint states only, somatrix_measurement="termwise"is rejected. Each basis state is one supplied preparation, with no generator chain whose action on the all-zero state is known, so quantum planning raisesApplicabilityErrorforpair_preparation="vacuum_reference"and"vacuum_restore". Classical execution and a scalar operator, which prepare no joint state, keep the request without effect. The Plan records the resolved choices inplan.reconstruction.acquisition. -
max_native_two_qubit_depth(Count | None) –Default
None, which requests no depth limit.Noneis neither a depth of 0 nor evidence that the circuits suit a device. A nonnegative integer D requires each submitted quantum circuit, every grouped count setting and every exact pair reduction, to have a native two-qubit depth of at most D, with D itself allowed. This depth is that of the circuit the backend prepared for execution, with the basis-state preparations, their controlled forms, the measurement basis changes and the backend's qubit routing, computed once when the circuit is prepared (PreparedArtifact.native_depth). Each circuit is checked just before its submission, and one whose depth exceeds D or is unavailable is not submitted: the run raisesnwqlib.backends.inspection.NativeDepthCapRefusal, which names the setting, the limit and the depth or why it is unavailable. Of the current backends only IBM Runtime computes this depth, for its compiled circuits, and only when its options keep the provider's dynamical decoupling and twirling off and qiskit-ibm-runtime 0.49.0 is installed (nwqlib.backends.IBMRuntimeBackend). Otherwise the depth is unavailable and an integer limit refuses the first circuit, as it does on every other backend, Aer included. The limit also refuses a circuit whose preparation recorded a version of nwqlib, Qiskit or qiskit-ibm-runtime other than the installed one, as in a Run reopened in another environment, and then the refusal has itsprovenanceset. Such a Run stays resumable. Resumed where the recorded versions are installed, it checks the same circuit's depth against D again and submits it when the depth meets the limit. In the installed environment, a new Run prepares its circuits again, and their preparation records then decide the limit. Execution without the limit is another option. Settings submitted earlier keep their counts and shots in the Run, andplan.method.analyze(plan, run.data, settings={})returns a Result that lists the settings without data inmissingand has no pencil. The limit changes no circuit, setting or Hamiltonian term. No value suits every device, so choose D for the device and the circuits, for example from the depth recorded for a setting prepared bynwqlib.prepare(prepared.run.prepared_artifacts). Undersamplingthe limit applies to every pilot and main circuit in the same way, and the settings without main-stage data are themissingones. -
sampling(PencilSampling | None) –Default
None, which measures every setting with theshots=of the call. APencilSamplingreplacesshots=with a pilot stage and a main stage whose shots per setting the pilot decides, and needs quantum execution. The Result'sshot_allocationrecords that decision.nwqlib.estimate(plan)then reports the totals of the whole Plan, such as its settings and shots, as unavailable, because each setting is measured in a pilot stage and again in a main stage whose shots the pilot decides. One prepared setting, whose stage and shots are fixed, is estimated normally from its preparation record. The shot budget of a Run isPencilSampling.total_shots.
Raises:
-
ValueError–If
acquisitionrequests termwise measurement.
Examples:
H = ZZ + 0.5*(XI + IX) on two qubits has lowest eigenvalue
-sqrt(2) = -1.4142135623..., which this three-state basis
recovers on Aer with exact readout (shots=None, in which the
simulator computes the matrix elements from its statevector without
shot sampling, subject to numerical rounding):
>>> from qiskit.quantum_info import SparsePauliOp
>>> from nwqlib import Eigenproblem, solve
>>> from nwqlib.algorithms import FixedGCIM
>>> H = SparsePauliOp.from_list([("ZZ", 1), ("XI", 0.5), ("IX", 0.5)])
>>> basis = ([1, 0, 0, 0], [0, 0, 0, 1], [0, 1, 1, 0])
>>> result = solve(Eigenproblem(A=H), method=FixedGCIM(basis=basis), seed=7)
>>> print(round(result.eigenvalue, 10))
-1.4142135624
PencilAcquisition ¶
Bases: Record
How FixedGCIM, ADAPT and QFD measure the projected matrices H and S of their trial states.
Build it with keyword arguments and pass it as FixedGCIM(acquisition=...),
ADAPT(acquisition=...) or QFD(acquisition=...). Every field has a
default. The choices change how H_ij = <phi_i|A|phi_j> and
S_ij = <phi_i|phi_j> are measured, not their ideal values: one basis
has the same ideal H and S under every supported combination, while the
circuits, the number of measurement settings and the finite-shot
covariance differ.
Write A = c I + sum_k c_k P_k with real c_k and partition the L
nonidentity Pauli words into G qubit-wise commuting groups. For a pair
i < j the grouped measurement prepares the joint state
chi_ij = (|0>|phi_i> + |1>|phi_j>)/sqrt(2) of one ancilla and the
system. With z = <phi_i|P|phi_j>, the ancilla Pauli operators give
<X_a P> = Re z and <Y_a P> = Im z, with a positive imaginary sign
(Huggins et al., arXiv:1909.09114v2, Sec. II.A, Eqs. (4)-(10)). One
setting measures the ancilla in the X basis (H, then a computational
measurement) or in the Y basis (S^dagger, then H) together with one
group's system basis (H for X, S^dagger then H for Y, nothing for Z). The
ancilla sign times each system parity estimates one term, and the first
group's ancilla sign alone estimates the overlap. A diagonal pair
prepares phi_i alone, because S_ii = 1 and H_ii is real. For b trial
states the complete pencil has b**2 G settings with both parts and
b(b+1)G/2 with real parts only. Reversing a pair conjugates its
entries.
Attributes:
-
matrix_measurement(Literal['grouped', 'termwise']) –Default
"grouped", the joint-state measurement above."termwise"isADAPT's comparison construction: one Hadamard test per pair, Pauli term and part,b**2 L + b(b-1)settings with both parts andbL + b(b-1)(L+1)/2with real parts only. It requirespair_preparation="controlled".FixedGCIMandQFDmeasure grouped joint states only. Only measurement with shots uses this field. -
pair_preparation(Literal['prefix', 'controlled', 'vacuum_reference', 'vacuum_restore']) –Default
"prefix". When the ordered preparations of a pair begin with exactly the same blocks (the same reference preparation, generators, binary64 angles, qubits and phases), those blocks run once without control and only the remaining blocks are controlled on the ancilla, which gives the same joint state. Otherwise, or with"controlled", both complete preparations are controlled.FixedGCIMtreats each supplied state as one block, so only two identical preparations share a prefix.QFDuses the powers of its one step V instead: a pair runs the reference andV**bonce without control, for the power b of smaller absolute value (of the smaller index on a tie), and controlsV**(q - b)for the other power q. Because powers of V commute, this prepares the same joint state as controlling both preparations."vacuum_reference"and"vacuum_restore"are forADAPT, whose states arephi_i = Q_i B|vac>for the reference preparation B and a generator chainQ_ithat maps the all-zero state|vac>toexp(i gamma_i)|vac>with a known vacuum phasegamma_i(Yoshioka et al., arXiv:2407.14431v3, Fig. 1b and pp. 2-3). In the pairs they construct, both control B instead of the generators and run every chain completely, without a shared prefix. For the pair of the reference andphi_j,"vacuum_reference"applies the Hadamard gate to the ancilla, B controlled on ancilla value 1,Q_jwithout control, B controlled on ancilla value 0 and the phase gatediag(1, exp(i gamma_j))on the ancilla. Every other pair uses the"prefix"construction."vacuum_restore"orders the two chains of each pair lexicographically by their(pool index, angle)items, as Python compares tuples,Q_Lfirst andQ_Rsecond, which can reverse their basis order. It applies the Hadamard gate, B controlled on 1,Q_R, the adjoint ofQ_L, B controlled on 0,Q_Landdiag(1, exp(i(gamma_R - gamma_L))), all without control except B, so it runsm_R + 2 m_Lgenerator exponentials for chains ofm_Landm_Rgenerators. The zero branch stays at the vacuum, with the phaseexp(i(gamma_R - gamma_L)), until B prepares the reference on it andQ_Lmakes itphi_L, while the other branch holds the adjoint ofQ_Lapplied tophi_Runtil the finalQ_Lrestoresphi_R. This adjoint reverses the circuit already built forQ_Land inverts each of its gates. When the tuple order reverses the basis order, the pair's entries of H and S are conjugated back to basis order. Both give the same joint state as"controlled", with the phase correction in the circuit for real-only and complex quadratures alike, so H and S, the settings and the count reduction are unchanged.ADAPTplanning accepts them when the Pauli terms of every pool generator show that its exponential maps|vac>to itself up to a phase (ADAPT'sacquisition), and raisesApplicabilityErrorotherwise.FixedGCIMandQFDraiseApplicabilityErrorfor both values in quantum execution, exact or with shots, unless the Plan measures nothing, because aFixedGCIMstate is one supplied preparation and the step V ofQFDhas no known vacuum phase. Quantum execution, with or without shots, uses this field, and the construction of every pair whose entries come from a joint state is recorded. Termwise measurement with shots prepares no joint state, so it records none. -
quadratures(Literal['auto', 'complex', 'real']) –Default
"auto"."complex"measures the real and imaginary part of every off-diagonal pair."real"measures real parts only and records the imaginary parts as exact zeros, which requires a proof that A and every state the Method can prepare are real in the computational basis, so thatHandSare real. The proof reads the stored inputs and needs every nonzero Pauli coefficient of A to be real with an even number of Y letters in its word, and every trial state to be an occupation state, a product state whose stored amplitudes are all real or a vector whose stored amplitudes are all real.ADAPTneeds its reference to qualify and every generator of its pool to have purely imaginary Pauli coefficients on words with an odd number of Y letters, so that each real-angle exponential is a real matrix. A supplied circuit never qualifies. ForADAPT, A is the Hamiltonian after itspauli_coefficient_cutoff, so the proof says nothing about the imaginary parts of matrix elements of the operator before that cutoff. No proof covers the time-evolved states ofQFD, which are complex in general even for a real A, soQFDrejects"real"."auto"chooses"real"exactly when the proof holds and"complex"otherwise. Planning decides once, and resuming or reanalyzing a run keeps that choice. Only measurement with shots uses this field. Exact and classical execution, and a Plan that measures nothing, leave the requested value without effect, so H and S keep both parts.FixedGCIM,QFDand the default growth ofADAPTmeasure nothing when A is a multiple of the identity, whileADAPTwith bounded Ritz growth still measures overlaps for such an A whenever its basis can hold more than the reference. Real-only measurement does not show that an unmeasured imaginary part is zero on a noisy device.
Raises:
-
ValueError–If
matrix_measurement="termwise"is combined with anypair_preparationother than"controlled".
ResolvedAcquisition ¶
Bases: Record
The requested and the resolved PencilAcquisition of one Plan, fixed when the Plan is made.
FixedGCIMReconstruction.acquisition and AdaptReconstruction.acquisition
hold it, and for QFD the FixedGCIMReconstruction in
QFDReconstruction.pencil. Running, resuming and reanalyzing the Plan
read these values and never decide them again. A choice that the Plan's
execution does not use is None: classical execution and a Plan that
measures nothing use none, exact readout only pair_preparation, and
measurement with shots all three. A requested "real" that the
execution does not use has no effect, and H and S keep both parts. A
requested "vacuum_reference" or "vacuum_restore" that the execution
does not use is kept in requested with pair_preparation None. When
the execution uses it, only an ADAPT Plan resolves it, and only when
every pool generator passes the vacuum rule of ADAPT's acquisition,
a check of the generators' Pauli terms.
Attributes:
-
requested(PencilAcquisition) –The Method's
PencilAcquisition. -
matrix_measurement(Literal['grouped', 'termwise'] | None) –The measurement of the matrix elements, or None.
-
pair_preparation(Literal['prefix', 'controlled', 'vacuum_reference', 'vacuum_restore'] | None) –The pair construction rule, one of the four values of
PencilAcquisition.pair_preparation, or None. -
quadratures(Literal['complex', 'real'] | None) –"complex"or"real"as measured, or None. -
real_proof(Literal['proved', 'unknown'] | None) –"proved"when the stored inputs named inscopeprove that the measured Hamiltonian and every preparable state are real,"unknown"when they do not, and None when no proof was needed because"complex"was requested or quadratures are not used. -
reason(Text | None) –Why
quadratureshas its value, naming the first input that failed the proof, or None. -
scope(Text | None) –The inputs the proof covered, or None. Its Hamiltonian is the operator the Plan measures. For
ADAPTthat is the Hamiltonian afterpauli_coefficient_cutoff, whose recorded truncation defines it, and a proof of it says nothing about the imaginary parts of matrix elements of the operator before that cutoff. -
pairs(tuple[PairPreparation, ...]) –The construction of every off-diagonal pair of a quantum
FixedGCIMorQFDPlan, selected at planning before any observation exists, so a record does not show that observations of its pair were obtained. Empty for classical execution, for a Plan that measures nothing and forADAPT, whose pairs arise during the run and whose joint-state constructionsADAPTResult.pair_preparationsreports.
PairPreparation ¶
Bases: Record
The selected construction of the joint state of one off-diagonal pair.
Every route prepares (|0>|phi_i> + |1>|phi_j>)/sqrt(2) with the phases
of the two preparations kept, for ADAPT possibly with phi_i and
phi_j exchanged (pair). ResolvedAcquisition.pairs of a
FixedGCIM or QFD Plan holds one per off-diagonal pair, selected at
planning, and ADAPTResult.pair_preparations holds one per off-diagonal
pair of the value basis when its pencil entries come from joint states.
A record describes the construction and does not show that
observations of the pair were obtained.
Attributes:
-
pair(tuple[Count, Count]) –(i, j)withi < j, positions in the basis of the pencil.ADAPTorders the two chains of the pair lexicographically by their(pool index, angle)items, as Python compares tuples, which can reverse these positions, and then conjugates the pair's entries of H and S back to basis order. -
route(Literal['prefix', 'controlled', 'vacuum_reference', 'vacuum_restore']) –"prefix"when the firstshared_blockspreparation blocks of both states run once without control,"controlled"when both complete preparations are controlled on the ancilla. The twoADAPTroutes control only the reference preparation B (PencilAcquisition)."vacuum_reference"is the construction for the pair of the reference and one other state, which runs B twice under control and that state's generator chain once without control."vacuum_restore"runs B twice under control and, without control, the chain that comes second in the tuple order thatpairdescribes, the adjoint of the first chain and the first chain, so the first chain runs twice, once as its adjoint. Both apply the known vacuum phase on the ancilla. -
shared_blocks(Count) –Number of leading blocks that run once without control: 1 for two identical
FixedGCIMpreparations, the reference plus the common leading generators forADAPT, and the reference plus theabs(b)uses of V or its adjoint for the shared power b ofQFD. Zero exactly for every route other than"prefix".
PencilSampling ¶
Bases: Record
A shot budget that FixedGCIM, QFD or ADAPT splits between a uniform pilot stage and a main stage chosen from it.
Build it with keyword arguments, for example
PencilSampling(total_shots=12000, pilot_fraction=0.2), and pass it as
FixedGCIM(sampling=...), QFD(sampling=...) or ADAPT(sampling=...).
Both arguments are required, and every method needs quantum execution
for it. For FixedGCIM and QFD it replaces shots=, which must then
be omitted. The basis, the grouped settings, their circuits and the
projected pencil stay those of shots=. Only the shots of each setting
change. ADAPT keeps a positive
shots= for the queries that grow its basis and measures the final
basis again in the two stages with this separate budget. A quantum
ADAPT Plan that measures nothing also accepts shots=None or termwise
measurement and runs no stage.
For a complete pencil with m > 0 settings and B = total_shots, the
pilot stage takes B_p = min(B - 2m, max(2m, floor(f B))) shots, with
the exact rational value of the binary64 number f = pilot_fraction, and
the main stage the other B - B_p, so each stage can give every setting
at least two shots. The pilot gives every setting floor(B_p/m) shots
and the first B_p mod m settings one more. Its pencil is solved at
overlap_cutoff, and one decision then fixes the main-stage shots N_s of
each setting s from v_s, the pilot estimate of the per-shot variance of
the first-order change that one shot of s makes in the lowest Ritz
value. Over real-valued N_s of at least 2 that sum to B - B_p, the
proportional rule with that floor, N_s = max(2, sqrt(v_s/lambda)) with
lambda > 0 set by the sum, minimizes the local variance
sum_s v_s/N_s that a linear model at the pilot solution predicts. The
integer N_s round it deterministically. Settings at the floor get 2,
the others their real-valued N_s rounded down, and the remaining shots
go one each to the settings above the floor where one more shot lowers
the local variance the most, ties in setting order. They are at least
2, spend B - B_p exactly and need not be the integer minimum of the
local variance. The local variance is no confidence bound. It
leaves out the noise of the pilot estimates, a change of kept rank at
the cutoff, near-degenerate Ritz values and device bias.
When the pilot solve fails, a pilot Ritz value or coefficient is not
finite, the two lowest offset-free Ritz values of the pilot solve
(ProjectedPencil.offset_free_eigenvalues) are equal, a v_s is unusable
or every v_s is zero, every setting gets the uniform split of B - B_p
instead. The allocation counts every shot at the same cost, whatever its
circuit. The main stage measures every setting afresh, and only its
measurements form the final H and S. The pilot measurements stay in the
Run, and their shots count toward its totals like the main ones. The
result's shot_allocation
(ShotAllocation)
records the decision, and the
GCiM guide
describes the two stages.
For FixedGCIM and QFD, planning refuses a budget below four shots
per setting and gives m in its message. It also checks the grouped
analysis of one stage against max_analysis_work and max_bytes
before any shot, using the larger stage budget max(B_p, B - B_p) for
either stage because the main shots are not known at planning, so it
can refuse a budget whose actual allocation would fit. A refusal names
the limit to raise or the parameters to reduce. ADAPT knows its final
basis only after its growth, so its planning makes both checks before
the first query on the largest basis the Plan can reach. With m grouped
settings in that basis, total_shots must be at least 4m, and the
grouped analysis of one stage of total_shots shots on it is checked
against max_bytes and max_products. The split and the allocation of
an ADAPT run use the m settings of the basis it ends with, and m <= m*.
For FixedGCIM and QFD, because the main stage chooses its shots from
the pilot, prepare(plan, settings="all") is rejected, and
prepare(plan) prepares the next setting.
Attributes:
-
total_shots(PositiveInt) –Required. Positive integer number of shots of both stages and all settings, at least 4m for m settings.
ADAPTrequires at least 4m for the m settings of the largest basis its Plan can reach. -
pilot_fraction(Real) –Required, a finite number strictly between 0 and 1. Requested share of
total_shotsfor the pilot stage, adjusted so that each stage keeps at least two shots per setting.
FixedGCIMResult ¶
Bases: Result
Smallest projected eigenvalue from a FixedGCIM run, with its projected matrices.
solve returns it for a FixedGCIM method,
and load_result reopens a saved one. The answer is eigenvalue, the
lowest kept Ritz value of the projected pencil, in the unit of the
Eigenproblem. It is None when data are missing or the solver
rejected the pencil. It is a projected estimate, not a certified full-space ground
energy. pencil holds the projected matrices H and S and the solve
diagnostics. print(result) shows the value and its scope, and
result.analyze(overlap_cutoff=...) solves the same matrix elements at
another cutoff without new measurement. Whenever a Result is attached to
its Plan and data, as after loading or reanalysis, NWQLib rejects a value
that differs from its own pencil, a pencil built under another
measurement policy, and any estimate formed from incomplete data. The
fields below are read-only. The fields of
Result are present too.
Attributes:
-
eigenvalue(Real | None) –Lowest kept Ritz value in the problem's energy unit, or None when data are missing or the solver rejected the pencil. It is not a certified full-space ground energy.
-
missing(tuple[Text, ...]) –Names of planned measurements with no returned data. A nonempty tuple means no pencil was solved.
-
pairs(tuple[PairEstimate, ...]) –Exact pair measurements: pooled
H0_ijandS_ijwith their reductions and entry error bounds. Empty for sampled and classical Plans. -
estimates(tuple[ScalarEstimate, ...]) –For a sampled Plan, the pooled weighted group means (
ScalarEstimate) with their contributing count data, weights and the estimated variance of each contribution's mean. -
group_moments(tuple[GroupMoment, ...]) –For a sampled Plan, the moments of every count measurement, in measurement order.
-
sampled_pair_variances(tuple[SampledPairVariance, ...]) –For a complete sampled pencil, the pooled sample-mean variances and overlap–H0 covariance of each pair.
-
pencil(ProjectedPencil | None) –The
ProjectedPencilwith the projected matrices and solve diagnostics, or None for partial data or a scalar identity target. UnderPencilSamplingit is formed from the main-stage measurements only. -
analysis_cutoff(Real) –Overlap-eigenvalue cutoff used by this analysis.
-
target_identification(Text) –Fixed statement of what the value does not establish.
-
shot_allocation(ShotAllocation | None) –Under
PencilSampling, the pilot decision (ShotAllocation) as it was decided, or None before it. Thenestimates,group_moments,sampled_pair_variances,pencil,missingandcontribution_idsconcern the main stage only, and a Result from before the decision lists every setting inmissing. The pilot measurements stay in the Run's observations. None withoutPencilSampling.
projected_diagnostics ¶
projected_diagnostics()
Return the stored Gram matrix and solve diagnostics for projected checks.
It reads the stored pencil and runs no new solve.
result.verify(checks=ProjectedVerificationOptions(...)) uses it.
Returns:
-
diagnostics(ProjectedDiagnostics) –Its
overlap,spectrum,normalizationandbackward_errorare the pencil'soverlap,overlap_eigenvalues,overlap_normalization_errorandprojected_backward_error, the last on the physical pencil (H, S). All four are None when there is no pencil.
ProjectedPencil ¶
Bases: Record
Projected matrices H and S of one trial basis and the diagnostics of their solve.
FixedGCIMResult.pencil and ADAPTResult.pencil hold it. The matrices
hold the obtained upper-triangle entries, completed by complex
conjugation, except that quantum execution sets every diagonal overlap
entry to one under the normalized-basis convention. Classical FixedGCIM
computes both triangles and averages them before recording the upper
triangle. No diagonal jitter or positive-semidefinite repair is applied.
The solve
keeps the overlap eigenvectors whose eigenvalues exceed overlap_cutoff
and diagonalizes H in that subspace (canonical orthogonalization,
Epperly, Lin and Nakatsukasa, arXiv:2110.07492v2, Algorithm 1.1, and
Zheng et al., arXiv:2312.07691v3, Appendix F, Eqs. (F1)-(F3)). No
full-space state residual is computed. The fields below are read-only.
Attributes:
-
hamiltonian(tuple[tuple[Complex128, ...], ...]) –Projected Hamiltonian
H = H0 + c_I Sof shape (m, m) in the problem's energy unit, fromH0without the identity termc_I Iand fromS, completed from its upper triangle by conjugation. The solve usedH0and addedc_Ito its Ritz values. -
overlap(tuple[tuple[Complex128, ...], ...]) –Gram matrix
Sof shape (m, m), completed the same way. -
overlap_eigenvalues(tuple[Real, ...]) –Full ascending spectrum of
S, before the cutoff. -
eigenvalues(tuple[Real, ...]) –Ascending Ritz values of the kept subspace.
-
offset_free_eigenvalues(tuple[Real, ...]) –The lowest one or two Ritz values that the solve computed from
(H0, S), beforec_Iis added, in ascending order, one atkept_rank1 and two at a larger rank. The first one or twoeigenvaluesare these values plusc_I, rounded once each. They are therefore equal forc_I = 0, and two Ritz values that round to the same physical value stay distinct here. Empty when the solve failed. These are the energies that the pilot allocation ofPencilSamplinguses for its per-setting variance estimates v_s (ShotAllocation.variances) and its exact-tie test, andShotAllocation.gapis their rounded differencee1 - e0. -
coordinate_vectors(tuple[tuple[Complex128, ...], ...]) –Rows index the m basis states and columns the Ritz pairs. Each column is an S-normalized coefficient vector.
-
kept_rank(Count) –Number of overlap directions above
overlap_cutoff. -
overlap_cutoff(Real) –Absolute overlap-eigenvalue threshold used by this solve.
-
overlap_filter(Literal['deterministic_gram', 'sampled_positive_subspace']) –"deterministic_gram"rejects a negative overlap mode beyond roundoff."sampled_positive_subspace"keeps only positive modes above the cutoff of a sampled, possibly indefinite S. -
overlap_condition_number(Real | None) –Largest over smallest kept overlap eigenvalue.
-
projected_residual(Nonnegative | None) –norm2(Hc - ESc)for the lowest Ritz pair. -
projected_backward_error(Nonnegative | None) –Dimensionless residual scaled by
(normF(H) + abs(E) normF(S)) norm2(c), on the physical pencil (H, S) in the Problem's energy unit, withH = H0 + c_I Swhen the solve removed an identity coefficient c_I. Rescaling the energy unit leaves it unchanged, but adding an identity term to the operator changesnormF(H)andabs(E)and therefore the value. Lanczos states its value on the normalized pencil instead. -
overlap_normalization_error(Nonnegative | None) –abs(c^dagger S c - 1)for the lowest Ritz pair. -
failure_reason(Text | None) –Code of the solver's rejection, or None when the solve completed.
-
sampled_enclosure(tuple[Real, Real] | None) –For sampled quantum data, the outward-rounded interval
[c - sum_k |c_k|, c + sum_k |c_k|]that contains the spectrum of the processed operatorc I + sum_k c_k P_k, or None. -
sampled_enclosure_violation(Nonnegative | None) –Distance of the lowest Ritz value outside that enclosure, zero inside it, or None when unavailable.
-
sampled_enclosure_passed(StrictBool | None) –Whether the violation lies within
sampled_enclosure_rtoltimes the largest enclosure endpoint magnitude. -
sampled_enclosure_rtol(Nonnegative | None) –Relative window used by that comparison.
-
sampled_failure(Text | None) –Solver rejection code or
"ritz_outside_operator_enclosure". -
processing(Literal['raw Hermitian completion; canonical positive-subspace projection']) –Fixed description of the processing applied to the raw pencil.
coefficients ¶
coefficients
Coefficient vector of the lowest Ritz pair, the first column of coordinate_vectors.
It is an empty tuple when no Ritz value exists. In the coordinates of
all columns, the kept pencil is (diag(eigenvalues), I) up to the
reported solve and normalization errors. Reading it performs no new
projection or eigensolve.
ShotAllocation ¶
Bases: Record
The pilot decision of a PencilSampling Run: the two stage budgets, the shots of every setting and the pilot estimates.
FixedGCIMResult.shot_allocation, QFDResult.shot_allocation and
ADAPTResult.shot_allocation hold it. It is decided once, after the
last pilot measurement and before the first main-stage measurement, and
saved with the Run. Resuming, loading and result.analyze(...) then
read it as decided and never solve the pilot again or choose other
shots, so a new overlap_cutoff changes the main pencil only. An
allocation interrupted before its decision was saved is repeated from
the pilot measurements after run.resume(reanalyze=True), without
measuring again. pilot_counts, main_counts and variances are in
the setting order of the pencil. For FixedGCIM and QFD it is the
order of the Plan's experiments. For ADAPT it is the order of the
grouped settings of the final basis, by pair, quadrature and group, in
which ADAPTResult.group_moments lists the records of an analyzed main
stage. The fields below are read-only.
Attributes:
-
sampling(PencilSampling) –The requested
PencilSampling. -
pilot_shots(Count) –Shots of the pilot stage, B_p of
PencilSampling, or 0 when no setting is measured. -
main_shots(Count) –Shots of the main stage,
total_shots - B_pwhen settings are measured, or 0 when none is. -
effective_fraction(Rational | Literal['not_applicable']) –B_p/total_shotsas an exact ratio in lowest terms (aRationalrecord), or"not_applicable"when the pencil has no setting to measure, so that both stages have zero shots andpilot_counts,main_countsandvariancesare empty. ForFixedGCIMandQFDthis happens when the operator is a multiple of the identity. ForADAPTit depends on the final basis rather than on the operator, because bounded growth on a multiple of the identity measures overlaps once its basis has two or more states. The shots that the ADAPT growth already spent stay counted when both stages have zero shots. -
pilot_counts(tuple[PositiveInt, ...]) –Shots of each setting in the pilot stage.
-
main_counts(tuple[PositiveInt, ...]) –Shots of each setting in the main stage, each at least 2, summing to
main_shots. -
variances(tuple[Real | None, ...]) –For each setting, the pilot estimate v_s of the per-shot variance of the first-order change that one shot of the setting makes in the lowest Ritz value, in squared energy units, or None where the pilot moments give no estimate: a setting with one pilot shot, a negative variance estimate or an overflow. A negative v_s from rounding is kept as computed and makes the main stage uniform. Empty when the pilot solve failed or no setting is measured.
-
fallback_reason(Text | None) –Why the main stage takes the uniform split, or None when its shots follow
variances:"pilot_solve_failed"(the pilot pencil'sfailure_reasongives the solver's code),"pilot_solution_nonfinite","pilot_lowest_ritz_degenerate"(the two lowest offset-free Ritz values are equal),"pilot_variance_unusable"or"pilot_variances_all_zero". An all-zero estimate does not mean zero uncertainty. -
local_variance(Nonnegative | None) –sum_s v_s/N_sover the main-stage shots N_s, the variance of the lowest Ritz value that a linear model at the pilot solution predicts for the main stage, or None when a v_s is missing or unusable. It is not a confidence bound. It leaves out the noise of the pilot estimates, a change of kept rank at the cutoff, near-degenerate Ritz values and device bias. -
gap(Nonnegative | None) –The rounded difference
e1 - e0of the two lowest offset-free Ritz values of the pilot solve (ProjectedPencil.offset_free_eigenvalues), or None at kept rank 1, after a failed solve or without a pilot. No tolerance is applied to it, and a nonzero gap does not show that the lowest value is simple. -
gap_frame(Literal['rounded difference of the two lowest offset-free Ritz values of the pilot solve']) –Fixed statement that
gapbelongs to the offset-free values, not to the physicaleigenvalues. -
pilot(ProjectedPencil | None) –The pilot
ProjectedPencil, solved at the Method'soverlap_cutoff, whose offset-free values, coefficients and kept rank the decision used, with the physical Ritz values and enclosure diagnostic of its own solve. None when no setting is measured.
ScalarEstimate ¶
Bases: Record
Pooled mean of one weighted group of Pauli terms in a sampled FixedGCIM or QFD run.
FixedGCIMResult.estimates and QFDResult.estimates hold one per group
setting. Each count measurement of the setting measures
Y = sum_k c_k Z_k from shared shots. value is the shot-weighted mean
of the measurements' means and need not lie in [-1, 1].
chunk_mean_variances contains the sample-mean variance V_Y of each
measurement (GroupMoment.mean_variance) for N > 1 shots and None for
N = 1. The group moments in FixedGCIMResult.group_moments and
QFDResult.group_moments keep the raw moments of each measurement with
these variances. Independent measurements pool
their variances with squared shot weights. The overlap and physical-H
covariance are recorded in the group and pair statistics. These are
sample-mean variance estimates, not a joint bound on the pencil or a
confidence interval for the projected eigenvalue. The fields below are
read-only.
Attributes:
-
experiment(Text) –Name of the group setting.
-
value(Real) –Shot-weighted mean of the measurements' means of Y.
-
contribution_ids(tuple[ContentID, ...]) –Content hashes of the contributing count data.
-
weights(tuple[Real, ...]) –Fraction of the returned shots in each contribution.
-
chunk_mean_variances(tuple[Real | None, ...]) –The sample-mean variance of Y of each contribution, or None for a one-shot contribution.
-
sampled_shots(Count) –Total returned shots.
PairEstimate ¶
Bases: Record
The reported H0_ij and S_ij of one exact pair and the reductions they were pooled from.
Each contribution is one exact reduction (block_matrix_elements) of
the pair's phase-faithful joint state (or of its diagonal system state)
to two raw complex scalars, the offset-free Hamiltonian entry and the
overlap entry in the requested (left, right) orientation, and counts
once in the pooling. A diagonal pair's overlap is its raw squared norm,
kept as evidence while assembly uses unit diagonal overlap. The
individual Pauli-term transitions are not recorded and cannot be
recovered from the weighted sum, so a different Hamiltonian truncation
needs new measurements.
Attributes:
-
experiment(Text) –The pair's experiment name.
-
pair(tuple[Count, Count]) –(left, right)withleft <= right. -
hamiltonian(Complex128) –Pooled offset-free
H0_ij. -
overlap(Complex128) –Pooled
S_ij. -
contribution_ids(tuple[ContentID, ...]) –Content hashes of the contributing exact reductions.
-
weights(tuple[Real, ...]) –Share of each contribution in the pooled
hamiltonianandoverlap. -
hamiltonian_bound(Nonnegative | None) –Outward error allowance for the reported offset-free Hamiltonian entry
H0_ijunder the state-error model of the preparation records. It combines that model with bounds for applying H0 to the right state, taking its complex inner product with the left state, and forming the weighted average of repeated computations of the same pair. None when a preparation record has an unresolved exclusion or no applicable state budget. When a supplied matrix is synthesized under control, this allowance also assumes the exact-to-rounding convention of exact dense synthesis. It does not add an independently certified synthesis residual. -
overlap_bound(Nonnegative | None) –The corresponding allowance for the reported overlap, with state, contraction and pooling terms. The solved diagonal is algebraic one and contributes zero to the Gram allowance. When a supplied matrix is synthesized under control, this allowance also assumes the exact-to-rounding convention of exact dense synthesis. It does not add an independently certified synthesis residual.
GroupMoment ¶
Bases: Record
Moments of one independently measured counts histogram.
Y is the coefficient-weighted group parity, including the ancilla sign on an off-diagonal pair. The optional X is that ancilla sign and is recorded only by group zero. Variances and covariance concern sample means. A one-shot measurement has unavailable variances and covariance (None). label_means preserves each term's first moment from the same histogram.
With N returned shots of one fixed setting, the sample-mean variances
and covariance are the unbiased sample covariance divided again by N,
for N > 1. With w_a = n_a/N the weight of the n_a shots in
stored bin a and the residuals dY_a = Y_a - mean(Y) and
dX_a = X_a - mean(X), they are evaluated as
V_Y = sum_a (w_a dY_a) dY_a/(N - 1),
V_X = sum_a (w_a dX_a) dX_a/(N - 1) and
C_XY = sum_a (w_a dY_a) dX_a/(N - 1). In exact arithmetic these
equal (mean(Y**2) - mean(Y)**2)/(N - 1),
(1 - mean(X)**2)/(N - 1) and
(mean(XY) - mean(X) mean(Y))/(N - 1). In binary64 every term of
V_Y and V_X is a product of two numbers of the same sign, so
neither variance is negative, while C_XY keeps its sign. The
rounding of the mean can still give a constant outcome a tiny positive
variance. Every numeric field must be finite, so a reduction whose
moments overflow raises an error instead of reporting them unavailable.
ADAPT measures each pair of generator chains once in a fixed chain
order and reuses the counts in later bases. When a basis lists the two
chains in the opposite order, the reported imaginary moments are those
of the conjugate entry: label_means, mean and overlap_mean change
sign, while second, overlap_cross, the variances and the covariance
are unchanged.
Attributes:
-
experiment(Text) –The setting's experiment name. For
ADAPTit ispairfor an off-diagonal setting ordiagonal. -
contribution_id(ContentID) –Content hash of the count data these moments come from.
-
pair(tuple[Count, Count]) –(i, j)withi <= j, positions in the basis of the pencil. -
quadrature(Literal['real', 'imag']) –real(ancilla X) orimag(ancilla Y). -
group(Count) –Index of the qubit-wise commuting group of nonidentity terms, into
FixedGCIMReconstruction.groupsorAdaptReconstruction.energy_groups. -
shots(Count) –Returned shots N of that count data.
-
label_means(tuple[Real, ...]) –The mean of each member's
Z_kin group order. -
mean(Real) –mean(Y). -
second(Real) –mean(Y**2). -
mean_variance(Real | None) –V_Y, or None for N = 1. -
overlap_mean(Real | None) –mean(X)for the overlap-supplying group of an off-diagonal pair, otherwise None. -
overlap_cross(Real | None) –mean(XY)of that group, otherwise None. -
overlap_variance(Real | None) –V_Xof that group, otherwise None. -
mean_covariance(Real | None) –C_XYof that group, otherwise None.
SampledPairVariance ¶
Bases: Record
Independent real/imaginary sample-mean variances, including shared-shot covariance.
Entries are (real, imaginary). A diagonal overlap is algebraic one, with zero variance. None means a required measurement has one shot. Negative estimates stay raw and set variance_negative. These estimates are not simultaneous confidence bounds or a Ritz-value certificate.
Under independent measurements of different settings, each quadrature
has V_H0 = sum_g V_(Y_g) and
V_H = sum_g V_(Y_g) + c_I**2 V_X + 2 c_I C_(X,Y_0). The diagonal
uses V_S = 0 and covariance zero because its solved overlap is
algebraic. When c_I = 0, an unavailable overlap variance does not make
the physical-H variance unavailable. Independent real and imaginary
settings give E|error|**2 = V_real + V_imag. When the Plan measures
real parts only (ResolvedAcquisition.quadratures == "real"), the
imaginary H0 and S entries of an off-diagonal pair are exact zeros of a
real pencil, not measurements, and their entries here are zero.
Attributes:
-
pair(tuple[Count, Count]) –(i, j)withi <= j. -
h0(tuple[Real | None, Real | None]) –Variance of the offset-free Hamiltonian entry per quadrature.
-
overlap(tuple[Real | None, Real | None]) –Variance of the overlap entry per quadrature.
-
covariance(tuple[Real | None, Real | None]) –Overlap–H0 sample-mean covariance per quadrature.
-
physical_h(tuple[Real | None, Real | None]) –Variance of
H0 + c_I Sper quadrature. -
variance_negative(StrictBool) –Whether any h0, overlap or physical_h entry is negative.
FixedGCIMBasis ¶
Bases: Record
Record that names a FixedGCIM trial basis as an Eigenproblem subspace.
Build it with keyword arguments from the preparation records of the
trial states, for example
FixedGCIMBasis(preparations=tuple(state_input(v).preparation for v in basis))
with state_input from nwqlib.problems. preparations is the only
required argument. It holds the ordered content hashes and physical
scales of the states, not their data. Pass its reference as
Eigenproblem(subspace=...) to request exactly this trial basis.
FixedGCIM then rejects a basis that differs from it.
Attributes:
-
preparations(tuple[StatePreparationSpec, ...]) –Required, nonempty. One preparation record per trial state, in basis order.
-
convention(Literal['normalized prepared columns']) –Default
"normalized prepared columns", the only accepted value. Each state enters as its normalized preparation column.
Examples:
>>> from nwqlib import Eigenproblem, solve
>>> from nwqlib.algorithms import FixedGCIM, FixedGCIMBasis
>>> from nwqlib.problems import state_input
>>> basis = ([1, 1], [1, 1j])
>>> preparations = tuple(state_input(v).preparation for v in basis)
>>> record = FixedGCIMBasis(preparations=preparations)
>>> problem = Eigenproblem(A=[[1, 0], [0, -1]], subspace=record.reference)
>>> result = solve(problem, method=FixedGCIM(basis=basis), seed=7)
>>> print(round(result.eigenvalue, 10))
-1.0
Grow the basis adaptively¶
ADAPT ¶
Bases: Method
Adaptive GCiM (ADAPT-GCiM) method for the smallest eigenvalue of an Eigenproblem.
It grows its trial basis from a pool of generators. Build it with
keyword arguments and pass it as method=, for example
solve(Eigenproblem(A=H), method=ADAPT(initial_state=psi, pool=generators)).
initial_state and pool are required. The result is an
ADAPTResult whose
eigenvalue is the lowest projected Ritz value in the trial basis the run
built.
The method follows ADAPT-GCiM of Zheng et al., npj Quantum Inf. 10, 127
(2024), arXiv:2312.07691v3. Each round screens the current product state
with the ADAPT gradient <[H, A_i]> of every unselected generator (main
text, "Integration of GCiM with ADAPT approach", p. 4, and Grimsley et
al. (2019), arXiv:1812.11173v2, Sec. II.B, steps 5-7). The selected
generator enters at the fixed angle theta, and the basis grows by two
states per selection (METHODS, p. 9). A selected generator is not
screened again, following the paper's QuGCM adapt_gcim.py
implementation (commit c5efcb0, lines 303-398), whereas Grimsley et al.
step 7 permits reuse in its ADAPT-VQE ansatz. Optimization every
optimize_every_m selections is the intermittent, truncated optimization
of Appendix H, and its extra energy evaluations run through the same Run,
the saved execution of the Plan.
Because the circuits of each round depend on generators selected from
earlier results, prepare(plan, settings="all") is rejected.
The default flat-counter stop follows METHODS, p. 9, and stops after
T = min(T_auto, T_usr) consecutive energy changes below
energy_change_tolerance, with T_auto equal to t_auto_fraction
(20%) of the unselected generators and T_usr = t_user. Counting starts
at the first change from the reference energy. T is recomputed after each
selection from the current number of unselected generators, and the run
stops as soon as the integer count is at least ceil(T). QuGCM's code
instead uses a max rule with 10% and a warmup. With max_iterations=8 and t_user=10, the
flat counter can fire only for pools of at most 42 generators. After k
selections a pool of P generators has P - k unselected members and a
flat count of at most k, so the stop needs k >= 0.2*(P - k). The
iteration cap is checked first and ends the run at the eighth selection,
so k <= 7 and P <= 42. Larger pools reach the iteration cap first
unless another stop applies. Every stop, including the gradient-norm
floor, is an operational rule, not proof of ground-state accuracy.
result.analyze(overlap_cutoff=...) solves the saved basis again at
another cutoff. The GCiM guide describes the
screening rule, the pools and the stopping rules.
For a basis of b states, ADAPT by default measures the projected
matrices of the current basis with the same joint-state construction
and count reduction as FixedGCIM for the same ordered states, and
each round measures only the pairs of generator chains that no earlier
round measured. With shots the default acquisition measures
grouped joint states, b**2 G settings for G qubit-wise commuting
groups of Hamiltonian terms, or b(b+1)G/2 when the processed
Hamiltonian, the reference and every pool generator are proved real.
One Hadamard test per Pauli term, the comparison construction, is
PencilAcquisition(matrix_measurement="termwise", pair_preparation="controlled").
PencilAcquisition(pair_preparation="vacuum_reference") and
"vacuum_restore" prepare the same joint states as the default by
controlling only the reference preparation, for pools whose generators
planning can show, from their Pauli terms, to map the all-zero state to
itself up to a phase (acquisition below).
Attributes:
-
initial_state(StateData) –Required. Reference state in the operator's original basis, in a form that
StateDataaccepts. -
pool(Any) –Required. A nonempty tuple of anti-Hermitian generators,
FermionicGeneratorrecords or operators thatoperator_inputaccepts, or the name of a built-in fermionic pool:"spin_adapted_sd","uccsd_sd","qeb_sd"or"ceo_ovp". Pools other than"spin_adapted_sd"need an occupation-number reference state. -
n_spatial_orbitals(PositiveInt | None) –Default
None. Number of spatial orbitals, required by a named pool, with twice as many qubits.Nonefor an explicit pool. -
theta(Real) –Default
pi/4, nonzero. Angle in radians of each selected generator's exponential. -
gradient_norm_floor(Real) –Default
1e-8, nonnegative. The run stops when the norm of the pool gradients falls below it. -
energy_change_tolerance(Real) –Default
1e-6, positive. Absolute change between consecutive energies below which the flat counter counts a round. -
t_auto_fraction(Real) –Default
0.2, in (0, 1]. Fraction of the unselected pool size that setsT_auto. -
t_user(PositiveInt) –Default
10. CapT_usron consecutive flat rounds in the rulemin(T_auto, T_usr). A fractional round count is rounded up. -
max_iterations(PositiveInt) –Default
8. Largest number of selection rounds. The basis holds at most2*min(max_iterations, pool size)states, somax_basis_size=64allows at most 32 selections for a pool of more than 32 members. The default limits the cost. With exact evaluation and the spin-adapted pool, the H4 chain of the eigenvalue example reaches FCI at the eighth selection, and 10-qubit LiH is then 0.46 mHa above its FCI energy. Withmax_iterations=32, the largest thatmax_basis_size=64allows for these pools, the flat counter stops them at selections 18 and 19 (Engineering constants). -
overlap_cutoff(Real) –Default
1e-12, positive. Overlap eigenvalue cutoff that defines the kept Gram subspace. -
symmetrize_matrices(bool) –Default
True. Request Hermitian averaging in the projected solve. The raw measured values are still checked. -
stop_criterion(Literal['flat_counter', 'residual_norm']) –Default
"flat_counter", which counts repeated small changes."residual_norm"uses the full-state residual||(H - E) psi||of the normalized Ritz state psi of the current basis, which only classical execution can evaluate. It differs from the pencil'sprojected_residual||H c - E S c||in basis coordinates. -
residual_norm_tolerance(Real) –Default
1.6e-3, positive. Threshold on that full-state residual for the residual stop, in the Hamiltonian's energy unit. -
optimize_every_m(PositiveInt | None) –Default
None, no optimization. Optimize the generator angles of the product state every m selected generators. -
optimize_rounds_n(PositiveInt | None) –Default
None. Largest number of BFGS iterations per optimization, required together with the other two optimization settings. -
optimize_max_evaluations(PositiveInt | None) –Default
None. Largest number of energy evaluations when optimization is enabled, counted as distinct evaluated parameter points. A classical point is one energy-and-gradient evaluation, whose work record includes its forward, derivative and reverse Taylor work. -
max_basis_size(PositiveInt) –Default
64. Limit on the size of the growing trial basis, checked before matrix construction. -
max_pool_size(PositiveInt) –Default
1024. Limit on the number of generators, checked before a pool is expanded. -
max_bytes(PositiveInt) –Default 10 GB (decimal,
10_000_000_000bytes). Limit on the known bytes of the pool, matrices, states and readout workspace. -
max_products(PositiveInt) –Default
1_000_000_000. Limit on the counted work of conversion, matrices and operator products. It also limits, separately, the exact synthesis of the dense unitaries in a supplied reference circuit and Qiskit's control of them. Before a classical query (one evaluation of gradients, matrix elements or an energy) starts, its reference, generator, Hamiltonian and scalar work are summed and checked, and each later query is checked afresh. Packed Pauli tables are checked once per Plan. The recorded allowance covers a whole query, while the counters record the actions performed after cache reuse. -
input_conversion(Literal['auto', 'dense_pauli']) –Default
"auto", which keeps Pauli input as it is and converts an explicit dense matrix of original dimension at most 16 to Pauli form. This applies to the Hamiltonian of a quantum run and to custom pool generators that need conversion. A classical run keeps a dense or sparse Hamiltonian in its form, padded when needed."dense_pauli"also permits the conversion of sparse matrices and of larger dense matrices, withinmax_conversion_workandmax_bytes. -
max_conversion_work(PositiveInt) –Default
100_000_000. Separate limit on the work of the chosen input conversion. -
pauli_coefficient_cutoff(Real) –Default
1e-14, nonnegative. Operator coefficients at or below it in magnitude are removed, and the sum of the removed magnitudes is recorded. -
input_symmetry_tolerance(Real) –Default
1e-12, nonnegative. Largest relative Frobenius-norm correction that the anti-Hermitian projection of each pool generator may make. The Hamiltonian has no tolerance and must be exactly Hermitian. -
acquisition(PencilAcquisition) –Default
PencilAcquisition(), grouped joint-state measurement with common-prefix preparation and automatic quadratures (PencilAcquisition). Planning decides real quadratures from a structural proof over the processed Hamiltonian, the reference and every admitted pool generator, not only the generators a run happens to select, and records the resolved choices inplan.reconstruction.acquisition. The processed Hamiltonian is the one measured, the operator afterpauli_coefficient_cutoff, whose removed coefficient magnitudes sum toplan.reconstruction.hamiltonian_dropped_l1. The proof says nothing about the imaginary parts of matrix elements of the original operator. With a scalar processed Hamiltonian the default growth measures nothing, andquadraturesthen has no effect. Bounded Ritz growth on such a Hamiltonian still measures overlaps whenever its basis can hold more than the reference, so its request is resolved as for any measured Plan.pair_preparation="vacuum_reference"and"vacuum_restore"control only the reference preparation B and run the generator chains without control. They need the exponential of every pool generator, the whole pool and not only the generators a run selects, to map the all-zero state|vac>to itself up to a phase, which quantum planning decides from the generators' Pauli terms by the following vacuum rule. A generator whose terms commute qualifies when, for each coefficient magnitude and each nonempty set of X/Y positions, the terms with that magnitude and those positions cancel on|vac>, as ini c (XX + YY), whilei c Xandi (XX + 0.5 YY)do not. Its phase comes from its identity term and its terms of only I and Z letters. A double excitation whose terms do not commute, which planning accepts only in the form the built-in pools build, qualifies with phase 0. The rule concerns the generator chain after B, not B itself, and is sufficient rather than necessary. With a failing generator, planning raisesApplicabilityErrornaming the first one by its pool index. Both values apply when joint states are prepared, exactly or with grouped shots, andADAPTResult.pair_preparationsrecords the construction of each pair. For classical execution and for a Plan that measures nothing, both values are inactive, so the vacuum rule is not required and the request is kept. Before a query runs, the vacuum phase is read from its generator circuits. They are checked for finite angles and global phases, for rotation angles of I/Z terms whose halves are binary64 numbers and, under"vacuum_restore", for definitions from which the adjoints can be formed, and a failing circuit raisesApplicabilityErrorbefore that query is measured. The GCiM guide describes both constructions and their costs. -
basis_growth(BoundedRitzGrowth | None) –Default
None, the gradient screening and basis of ADAPT-GCiM described above. ABoundedRitzGrowthinstead grows an explicit list of short generator chains, one scored extension per round, at the fixed angletheta. Each of its added chains counts towardmax_iterations, and its basis stops growing atmax_basis_sizestates. It screens no gradients, sogradient_norm_floorhas no effect and the commutators[H, A_j]are not formed.ADAPTraisesValueErrorfor it together withoptimize_every_morstop_criterion="residual_norm". With shots it supports the default grouped measurement, and planning raisesValueErrorwhenacquisitionrequestsmatrix_measurement="termwise". With a scalar processed Hamiltonian andmax_basis_size>1, quantum planning still resolves the measurement choices because evaluating extensions can need overlaps. Withmax_basis_size=1the Plan measures nothing and keeps the request unused. -
max_native_two_qubit_depth(Count | None) –Default
None, which requests no depth limit.Noneis neither a depth of 0 nor evidence that the circuits suit a device. A nonnegative integer D requires each submitted quantum circuit, the pencil, screening and energy circuits alike, to have a native two-qubit depth of at most D, with D itself allowed. This depth is that of the circuit the backend prepared for execution, with the reference, the generator exponentials, their controlled forms, the measurement basis changes and the backend's qubit routing, computed once when the circuit is prepared (PreparedArtifact.native_depth). Each circuit is checked just before its submission, and one whose depth exceeds D or is unavailable is not submitted. The run then ends withstop_reason"native_depth_refused", andpendingholds the refusal, which names the circuit's experiment and preparation record, the limit and the depth or why it is unavailable. The Result reports the last pencil solved before the refusal, and the circuits submitted earlier keep their counts and shots in the Run. Of the current backends only IBM Runtime computes this depth, for its compiled circuits, and only when its options keep the provider's dynamical decoupling and twirling off and qiskit-ibm-runtime 0.49.0 is installed (nwqlib.backends.IBMRuntimeBackend). Otherwise the depth is unavailable and an integer limit refuses the first circuit, as it does on every other backend, Aer included. The limit also refuses a circuit whose preparation recorded a version of nwqlib, Qiskit or qiskit-ibm-runtime other than the installed one, as in a Run reopened in another environment. That refusal depends on the installed packages, not on the circuit, so it does not end the run: resuming the run raisesnwqlib.backends.inspection.NativeDepthCapRefusalwith itsprovenanceset, and the Run keeps its iteration state and the prepared circuit. Resumed where the recorded versions are installed, the Run checks that circuit's depth against D again and, when the depth meets the limit, submits it and continues. In the installed environment, a new Run prepares its circuits again, and their preparation records then decide the limit. Execution without the limit is another option. The limit changes no circuit, generator or Hamiltonian term. No value suits every device, so choose D for the device and the circuits, for example from the depth recorded for the first query prepared bynwqlib.prepare(prepared.run.prepared_artifacts). -
sampling(PencilSampling | None) –Default
None, with which a run with shots takeseigenvalueandpencilfrom the same measurements that chose the basis. APencilSamplingmeasures the final basis again once its growth has stopped: a pilot stage with uniform shots, one decision of the shots of every setting from the pilot pencil, and a main stage whose measurements alone formeigenvalue,penciland the group moments of the Result. The stages follow the rules ofPencilSamplingfor the grouped settings of the final basis, andADAPTResult.shot_allocationrecords the decision.shots=still sets the shots of every query that grows the basis, andtotal_shotsis a separate budget of the two final stages. When the final basis has settings to measure and both stages complete, the Run spendstotal_shotsin addition to the shots of the growth. A Run that ends during the stages counts the shots already submitted, up tototal_shotsstage shots. A final basis without settings adds no shots. The main measurements are new, but the basis was chosen from the earlier ones, so the estimate is conditional on that basis.samplingsupports quantum execution with a positiveshots=and the default grouped measurement. Planning raisesValueErrorfor classical execution in every case. When the Plan measures anything, it also raises it forshots=Noneand formatrix_measurement="termwise". A quantum Plan that measures nothing, such as the default growth for a multiple of the identity, acceptssamplingwithshots=Noneor termwise measurement, runs no stage and records zero pilot and main shots. Before the first query, planning requires at least four of thetotal_shotsfor every setting of the largest basis the Plan can reach,2*min(max_iterations, pool size)states, ormin(max_basis_size, max_iterations + 1)withbasis_growth, so a run that stops with a smaller basis may have needed fewer shots. It also checks the analysis of one stage oftotal_shotsshots on that basis againstmax_bytesandmax_products.nwqlib.estimate(plan)still reports the totals of the whole Plan as unavailable, and one prepared query is estimated normally. The stages follow every scientific stop of the growth,invalid_sampled_evidenceincluded, and the main stage can still end without an eigenvalue, as when its solve fails. A circuit thatmax_native_two_qubit_depthrefuses, or a cancellation, ends the Run without the remaining stages. The Result then reports the last pencil that the growth solved, if there is one, together with the decision if it was made. The Run counts every shot already submitted, those of an unfinished stage included. If no projected analysis has started, as when a circuit needed for the first pencil is refused,eigenvalueis None andanalysis_attemptsis 0. A cancellation during the stages returns at once a Result built from the measurements that the Run had collected, without waiting for a submitted stage job. For such a job, data that the Run has retrieved and saved can be read throughRun.completed_observation, including data obtained by a later explicit refresh. These data are not added to that Result. Once the Result exists,run.resume()returns without asking the backend about its jobs again, so a job that completes later enters neither the Run nor the Result by itself.
Raises:
-
ValueError–If
thetais zero, if only some of the three optimization settings are given, if an explicit pool is empty or has more thanmax_pool_sizemembers, or ifbasis_growthis combined with optimization orstop_criterion="residual_norm", or has noindependence_cutoffwhileoverlap_cutoffis at least 1.
Examples:
H = Z has lowest eigenvalue -1. From |+>, ADAPT with the
one-generator pool {iY} returns it after one selection:
>>> from nwqlib import Eigenproblem, solve
>>> from nwqlib.algorithms import ADAPT
>>> from nwqlib.operators import ingest_pauli
>>> pool = (ingest_pauli((("Y", 1j),), num_qubits=1),)
>>> method = ADAPT(initial_state=[1, 1], pool=pool)
>>> result = solve(Eigenproblem(A=[[1, 0], [0, -1]]), method=method, seed=7)
>>> print(result.selected, result.stop_reason, round(result.eigenvalue, 10))
(0,) pool_exhausted -1.0
BoundedRitzGrowth ¶
Bases: Record
Grow the ADAPT basis one short generator chain at a time, adding the best of a few scored extensions each round.
Pass it as ADAPT(basis_growth=BoundedRitzGrowth(max_chain_length=...)).
The basis is then an explicit list of chains instead of the reference,
single-generator states and products of the default ADAPT-GCiM basis. A
chain of generators A_{g_1}, ..., A_{g_k} of the pool is the state
exp(theta A_{g_k}) ... exp(theta A_{g_1})|ref> at ADAPT's fixed angle
theta, and the basis starts with the reference alone. Each round
extends a parent chain of the basis by one generator. The parents are
the reference and the parent_window - 1 chains added last. A round
visits them in turn, repeatedly, in order of basis position, starting
after the parent whose extension the previous round examined last, and
each visit extends a parent by its next pool generator, so each parent
continues through the pool in pool order. A generator may occur more than
once in a chain, also twice in a row, and every occurrence counts
toward max_chain_length and the cost. A chain equal to one already in
the basis is not considered again.
A round examines extensions until candidates_per_round of them are
new to the basis and within basis_depth_limit, max_candidate_scans
have been examined or no parent has a generator left. For each such
extension v it obtains the matrix elements of v with every basis state
and with itself and computes its score when v passes
independence_cutoff, or with shots the sampled eligibility rule
below, then adds the extension with the largest score,
the earliest examined one among equal scores. The enlarged basis is
solved with ADAPT's overlap_cutoff before the next round. With b
basis states a round therefore obtains the matrix
elements of at most candidates_per_round * (b + 1) new pairs of
states. The extensions that are not added stay in the Run's counted
work and saved observations. No coherent Ritz state is prepared, no
full-space residual is computed and no angle is optimized.
The score uses the current lowest Ritz value E and Ritz state psi of
the solved basis. Let q be the normalized part of v outside the kept
overlap subspace, the span of the overlap directions that the solve
keeps above overlap_cutoff, and eta its squared norm before
normalization. With delta = <q|A|q> - E and rho = |<q|A - E|psi>|,
the score is (sqrt(delta**2 + 4 rho**2) - delta)/2, the amount by
which the lowest eigenvalue of A projected on psi and q lies below E.
Projecting on the kept subspace together with q gives a lowest value at
or below that eigenvalue, so the score is a lower bound on the energy
decrease that an exact solve of the kept subspace together with q would
give. It is not a prediction of the next round's
energy, because the solve of the enlarged basis keeps its own subspace,
and it does not rank extensions by the energy of that solve. A score of
zero does not show that an extension cannot lower the energy: an
extension coupled only to an excited Ritz state has rho = 0, while
adding it can lower the lowest Ritz value. The score uses the
Hamiltonian without its identity coefficient, so a large constant term
cannot round it away. ADAPTResult.history records the examined
extensions of each round with their reasons, scores, eta, rho and
delta, and the energy decrease and kept overlap rank that each solve
actually gave, without clipping a rise. The
GCiM guide works
through an example.
With shots, the score divides sampled matrix elements by sqrt(eta)
and eta, which can enlarge their sampling noise without bound, so an
evaluated extension is scored only when it passes a sampled
eligibility rule. The rule reads the sample-mean variances of the
measured overlaps between the current basis states and between them
and the extension, and takes for each measured real or imaginary part
the larger of its variance and 1/(N + 1)**2 for its N shots, so that
a part whose outcomes were all equal still counts as noisy. With the
fixed multiplier k = 3 it forms a first-order spread sigma of the
estimated eta, the ratio epsilon of the noise scale of the current
overlap matrix to its smallest kept eigenvalue, and a second-order
term. An extension passes the rule when epsilon < 1/2 and the margin,
the estimated eta minus k sigma and that term, exceeds
independence_cutoff. The rule is empirical and conditional on
independently measured settings. It is neither a confidence interval
nor a proof that the extension is independent, and an extension that
fails it has not been shown to depend on the basis. It uses only the
measured data and adds no shot. It does not control the noise of the
Hamiltonian elements or of the current Ritz pair, so the score of an
extension that passes is a raw estimate, not a validated energy
decrease, and the round ranks these extensions by it as with exact
elements. More basis states and a smaller kept overlap eigenvalue
enlarge epsilon. As a rough planning estimate, not a recommendation,
overlap variances near 1/N per part need N above
36(b - 1)/lambda**2 shots per setting for epsilon < 1/2 with b
basis states, real parts only and smallest kept eigenvalue lambda, and
72(b - 1)/lambda**2 with both parts, for example 540 for b = 16,
lambda = 1 and real parts only. Each
extension's margin still decides whether it is scored. Sampled bounded
growth reads these variances from the overlap settings of grouped
measurement and is implemented for that measurement only, so planning
raises ValueError for shots with a requested
matrix_measurement="termwise".
These operational limits end the growth, given in
ADAPTResult.stop_reason:
max_basis_size, ormax_iterationsonce that many chains have been added.flat_counter: consecutive energy changes belowenergy_change_tolerance, as in the default growth, with the pool size P in place of the number of unselected generators.basis_depth_limit: the round examined at least one extension that is not already in the basis, and every such extension exceedsbasis_depth_limitor has no CX count.parent_window_exhausted: no parent has a generator left, and every extension the round examined was already in the basis.candidate_scans_exhausted: the round examinedmax_candidate_scansextensions, all already in the basis.no_admissible_candidate: without shots, no evaluated extension passedindependence_cutoffwith a finite score. With shots, at least one evaluated extension passed the sampled eligibility rule and none of these has a finite score.noise_inconclusive: with shots, no evaluated extension passed the sampled eligibility rule. The basis stays as it is, the result reports its last solve, and no shot is added.
When a round finds no extension to evaluate, basis_depth_limit takes
precedence over parent_window_exhausted, and that over
candidate_scans_exhausted. Each reason describes only the extensions
that were examined. None of them shows that the energy has converged or
reached a requested accuracy. Without shots, a solve that keeps no
overlap direction also stops the run with no_usable_overlap_subspace.
With shots, a solve that the eigensolver rejects, including one that
keeps no overlap direction, stops it with invalid_sampled_evidence.
Execution states of ADAPTResult.stop_reason such as pending_acquisition,
cancelled and native_depth_refused remain possible.
Attributes:
-
parent_window(PositiveInt) –Default
4, positive. Number of parent chains of a round: the reference and at mostparent_window - 1chains added last. An engineering choice that bounds the work of a round, not a convergence parameter. -
candidates_per_round(PositiveInt) –Default
4, positive. Largest number of extensions whose matrix elements one round obtains and scores. With 1 and without shots, a round whose only evaluated extension does not passindependence_cutoffwith a finite score ends the growth withno_admissible_candidate. With shots, a round whose only evaluated extension fails the sampled eligibility rule ends the growth withnoise_inconclusive, and a round whose only evaluated extension passes the rule without a finite score ends the growth withno_admissible_candidate. The GCiM guide describes an adjacent repeat of a generator withA**2 = -I, for which this can happen. -
max_candidate_scans(PositiveInt) –Default
256, positive. Largest number of extensions one round examines, including repeated chains and extensions excluded bybasis_depth_limit, which obtain no matrix element. It limits this inexpensive examination, not the number of scored extensions. -
max_chain_length(PositiveInt) –Required, positive. Largest number of generator occurrences in one chain, repeats included. It is not a circuit depth.
-
basis_depth_limit(Count | None) –Default
None, which sets no limit and adds no work. A nonnegative integer D admits only an extension whose CX count bound is at most D, with D itself admitted. The bound is the sum of the CX counts of the reference preparation and of every generator occurrence of the chain, each lowered to one-qubit gates and CX before routing, with no cancellation, so it bounds the CX depth of the chain's preparation. An occupation or product reference counts 0 and every direct vector on q qubits2(2**q - 2), a computational basis state given as a vector included, without reading its amplitudes, so a direct reference can be refused although its actual circuit is shallower. Planning raisesValueErrorfor a supplied or matrix-product-state reference, whose count is unknown, for a reference above D, and for classical execution. The counts are read from the generator circuits that quantum execution builds, so the limit is supported for quantum execution only, and classical bounded growth without a limit is unaffected. A generator circuit is built and its instructions are read when one of its extensions is first examined. An extension whose generator circuit contains an instruction without a known CX count is excluded, as is one above D. The limit changes the trial space. It is not the native two-qubit depth of the executed circuits, whose pair constructions, readout and routing add depth, and whichADAPT.max_native_two_qubit_depthchecks. -
independence_cutoff(Real | None) –Default
None, which uses ADAPT'soverlap_cutoffand then requires it to be below 1. Otherwise a value in (0, 1). An extension is scored only wheneta, the squared norm of its part outside the kept overlap subspace, exceeds it. On its own this floor is no guard against sampling noise, so with shots the margin of the sampled eligibility rule must exceed it instead.
ADAPTResult ¶
Bases: Result
Smallest projected eigenvalue from an ADAPT run, with its history and stop reason.
solve returns it for an ADAPT method, and
load_result reopens a saved one. The answer is eigenvalue, the lowest
projected Ritz value of the processed Hamiltonian in the basis given by
value_selected and value_theta, in the unit of the Eigenproblem. It
establishes neither the ground state nor coverage of the adaptive search.
stop_reason says why the run ended, history holds one round per
projected analysis, and pencil holds the projected matrices. selected
and theta describe the latest generators and angles, while
value_selected and value_theta describe the basis behind eigenvalue
and pencil. They differ when a generator was selected or optimized
after the last projection, and reanalysis always uses the value basis.
With BoundedRitzGrowth
the explicit chains basis and value_basis take their place, and
selected, theta, value_selected and value_theta are empty.
print(result) shows the value, its scope and the stop reason. The
fields below are read-only. The fields of
Result are present too.
Attributes:
-
eigenvalue(Real | None) –Lowest projected Ritz value of the processed Hamiltonian, or None. It establishes neither the ground state nor coverage of the adaptive search.
-
selected(tuple[Count, ...]) –Pool indices chosen so far, in selection order.
-
theta(tuple[Real, ...]) –Current angles of those generators, in radians.
-
value_selected(tuple[Count, ...]) –Pool indices of the basis behind
eigenvalue. -
value_theta(tuple[Real, ...]) –Angles of the basis behind
eigenvalue. -
history(tuple[AdaptRound, ...]) –One
AdaptRoundper completed projected analysis. -
pencil(ProjectedPencil | None) –The
ProjectedPencilof the value basis, or None. -
stop_reason(Text) –Why the run stopped. Scientific stops are
gradient_norm_floor,flat_counter,residual_norm_threshold,pool_exhausted,max_iterations,optimization_evaluation_budget_exhausted,no_usable_overlap_subspaceandinvalid_sampled_evidence. WithBoundedRitzGrowththe scientific stops aremax_basis_size,max_iterations,flat_counter,basis_depth_limit,parent_window_exhausted,candidate_scans_exhausted,no_admissible_candidate,noise_inconclusive(with shots, no evaluated extension of the last round passed the sampled eligibility rule, so the growth ends on its current basis),no_usable_overlap_subspacewithout shots andinvalid_sampled_evidencewith shots, all operational limits rather than evidence of convergence. When a round finds no extension to evaluate,basis_depth_limittakes precedence overparent_window_exhausted, and that overcandidate_scans_exhausted, each describing only the examined extensions (BoundedRitzGrowth). Execution states arerunning,cancelled,not_started,partial_observation(data that a decision needs are missing or unusable),pending_preparationandpending_acquisition(a circuit preparation or a backend job has not finished),uncertain_preparation(an upload or compilation may or may not have completed),uncertain_native_intent(a recorded backend submission may or may not have reached the backend),backend_failedandnative_depth_refused(the next circuit's native two-qubit depth exceedsADAPT.max_native_two_qubit_depthor is unavailable, so it was not submitted, andpendingholds the refusal, which names the circuit's experiment and preparation record, the limit and the depth or why it is unavailable). -
pending(tuple[Text, ...]) –Labels of queries or statuses that blocked further progress.
-
optimizer_attempts(Count) –Number of optimizer invocations started.
-
optimizer_rounds(Count) –Completed BFGS iterations over all invocations.
-
optimizer_restarts(tuple[dict, ...]) –Records of BFGS restarts from the saved best point after the run was resumed.
-
energy_queries(Count) –Energy queries counted against
optimize_max_evaluations. -
analysis_attempts(Count) –Projected analyses started by the run, the pilot analysis of
ADAPT.samplingincluded. -
analysis_cutoff(Real) –Overlap-eigenvalue cutoff of this analysis.
-
group_moments(tuple[GroupMoment, ...]) –For a grouped run with shots, the moments of every count measurement of the value basis's pencil (
GroupMoment), at the positions of that basis, as inFixedGCIMResult. The first group's overlap moments and their covariance with H0 belong to the same counts. Empty otherwise. -
sampled_pair_variances(tuple[SampledPairVariance, ...]) –For a grouped run with shots, the pooled sample-mean variances and overlap–H0 covariance of each pair of the value basis (
SampledPairVariance). Empty otherwise. -
pair_preparations(tuple[PairPreparation, ...]) –For a value basis whose pencil entries come from joint states, computed exactly by quantum execution without shots or measured with grouped shots, the construction of the joint state of each off-diagonal pair (
PairPreparation). Underpair_preparation="vacuum_reference"the pairs of the reference have the route"vacuum_reference"and every other pair the"prefix"route with its shared blocks. Under"vacuum_restore"every pair, those of the reference included, has the route"vacuum_restore", whose circuit for the reference is that of"vacuum_reference". Each pair's vacuum phase correction is determined by its recorded route, the pair's generator chains and the Plan's pool, through the generator circuits built for those chains or, after the Run is reopened, the generator circuits restored with it. Exact execution prepares joint states also whenmatrix_measurement="termwise"is requested, because that choice applies only to shots. Termwise measurement with shots prepares no joint state, because its Hadamard tests place each Pauli term between the two controlled preparations, so the field is then empty. It is also empty for classical execution, for a Plan that measures nothing and whenpencilis None. A one-state value basis has no off-diagonal pair. -
basis(tuple[tuple[tuple[Count, Real], ...], ...]) –With
BoundedRitzGrowth, the chains of the basis so far in basis order, the reference()first. Each chain is a tuple of(pool index, theta)items in the order they act. Empty otherwise. -
value_basis(tuple[tuple[tuple[Count, Real], ...], ...]) –With
BoundedRitzGrowth, the chains of the basis behindeigenvalueandpencil, the first chains ofbasis. Empty otherwise. -
frontier_cursor(tuple[tuple[Count, Count], ...]) –With
BoundedRitzGrowth,(parent position, next pool index)of each parent chain of the last examination, with positions inbasis. The pairs are in cyclic position order ending with the parent of the last examined extension, after which a later round continues the rotation. Empty otherwise. -
shot_allocation(ShotAllocation | None) –With
ADAPT.sampling, theShotAllocationof the pilot and main stages that measure the value basis again after its growth has stopped, decided once before the first main-stage measurement, with the shots of every grouped setting of that basis in its setting order, by pair, quadrature and group. When that basis has no setting to measure, both stages have zero shots, the per-setting lists are empty andeffective_fractionis"not_applicable", while the shots of the growth stay spent. Once the main stage has been analyzed,eigenvalue,pencil,group_moments,sampled_pair_variancesandcontribution_idscome from the main-stage measurements alone,group_momentsin the setting order of the decision, whilehistorykeeps the analyses that grew the basis. Loading the Result andresult.analyze(...)read the decision as saved. None withoutsamplingand before the decision. -
target_identification(Text) –Fixed statement of what the value does not establish.
projected_diagnostics ¶
projected_diagnostics()
Return the stored Gram matrix and solve diagnostics for projected checks.
It reads the stored pencil and runs no new solve.
result.verify(checks=ProjectedVerificationOptions(...)) uses it.
Returns:
-
diagnostics(ProjectedDiagnostics) –Its
overlap,spectrum,normalizationandbackward_errorare the pencil'soverlap,overlap_eigenvalues,overlap_normalization_errorandprojected_backward_error, the last on the physical pencil (H, S). All four are None when there is no pencil.
AdaptRound ¶
Bases: Record
One projected analysis of an ADAPT run and the selection that followed it.
ADAPTResult.history holds one per completed projected analysis. A round
keeps the values that drove its decision, so a later reanalysis of the
Result at another cutoff does not change it. With BoundedRitzGrowth
a round's basis is the reference and the chains that earlier rounds
added (ADAPTResult.basis), selected, theta and gradients are
empty and winner is None, and candidates records the extensions the
round examined. The fields below are read-only.
Attributes:
-
iteration(Count) –Number of selected generators in the basis of this round, or with
BoundedRitzGrowththe number of chains added before it. -
selected(tuple[Count, ...]) –Pool indices of those generators in selection order.
-
theta(tuple[Real, ...]) –Their angles at this analysis, in radians.
-
energy(Real | None) –Lowest projected Ritz value of this round, or None.
-
energy_decrease(Real | None) –The previous round's
energyminus this one, or None for the first round or when either is unavailable, in both growth modes. It is the actual change of the solved value, negative when the energy rose, for example because the overlap cutoff kept other directions of the enlarged basis or sampling noise moved the estimate. -
kept_rank(Count) –Number of overlap directions that this round's solve kept above the overlap cutoff, the rank of its projected problem, in both growth modes, and 0 when the solve kept none.
-
gradient_norm(Real | None) –Euclidean norm of the screened product-state gradients, or None when no screening followed.
-
gradients(tuple[tuple[Count, Real], ...]) –(pool_index, <[H, A_i]>)pairs for the unselected generators. -
winner(Count | None) –Pool index selected next, or None when no screening followed or the gradient-norm floor stopped the run.
-
residual_norm(Real | None) –Full-space residual
||(H - E) psi||of the normalized Ritz state. It is recorded only under"residual_norm"stopping and is None otherwise. -
flat_count(Count) –Consecutive small energy changes counted after this round.
-
contribution_ids(tuple[str, ...]) –Content hashes of the data first collected after the previous round's screening and up to this round's screening, including any optimizer energy queries in between.
-
basis_realization(Text | None) –Content hash of a query that identifies the full product state of this round's basis, or None. It is the shared query on the full product state in an exact quantum run, whose screening values the next screening reuses, the diagonal pair query in a classical run, the first-group diagonal setting of the full product in a grouped sampled run, or the query of the first nonidentity Pauli term of the diagonal pair in a termwise sampled run. With
BoundedRitzGrowthit is the diagonal pair query of the chain added last. The matrix stage of the round, which obtains every matrix element of the current basis, must contain this query. The value is None before any generator is selected and in an exact quantum run whose Hamiltonian has no nonidentity term. -
analysis_attempt(Count) –Analysis attempt of the run that produced this round.
-
optimizer_attempts(Count) –Cumulative optimizer invocations at this round.
-
optimizer_rounds(Count) –Cumulative completed BFGS iterations at this round.
-
energy_queries(Count) –Cumulative energy queries counted against
optimize_max_evaluations. -
sampled_failure(Text | None) –Sampled-pencil failure or enclosure excursion code, or None.
-
sampled_enclosure_violation(Real | None) –Distance of the sampled Ritz value outside the Pauli L1 enclosure of the processed operator, or None.
-
candidates(tuple[BoundedCandidate, ...]) –With
BoundedRitzGrowth, theBoundedCandidateextensions that the round after this analysis examined, in examination order, the added one marked"accepted". Empty otherwise.
BoundedCandidate ¶
Bases: Record
One extension that a BoundedRitzGrowth round examined, with its reason and, when scored, its score.
AdaptRound.candidates holds them in the order the round examined them
(BoundedRitzGrowth).
The energy quantities are in the unit of the Eigenproblem and are
formed without the identity coefficient c of the processed Hamiltonian
A = cI + A0, which cancels from them. The fields below are read-only.
Attributes:
-
chain(tuple[tuple[Count, Real], ...]) –The extension's
(pool index, theta)items in the order they act, its parent chain followed by one generator. -
reason(Literal['accepted', 'ranked', 'below_independence_cutoff', 'nonfinite_score', 'duplicate', 'depth_unknown', 'above_depth_limit', 'candidate', 'screening_noise_unknown', 'screening_metric_unresolved', 'screening_independence_unresolved']) –"accepted"for the extension added to the basis,"ranked"for another scored one,"below_independence_cutoff"whenetawas at most the independence cutoff,"nonfinite_score"when a score quantity was not finite,"duplicate"for a chain already in the basis,"depth_unknown"and"above_depth_limit"for an extension thatbasis_depth_limitexcluded, and"candidate"for an extension chosen for scoring whose matrix elements the run had not finished obtaining when it stopped. With shots, an evaluated extension that the sampled eligibility rule ofBoundedRitzGrowthdoes not pass has"screening_noise_unknown"when an overlap setting has fewer than two shots or no finite nonnegative variance, or when one set of counts serves two different overlap entries,"screening_metric_unresolved"whenmetric_epsilonis at least 1/2 or a needed quantity is not finite, and"screening_independence_unresolved"wheneta_marginis at mostindependence_cutoff. The last one does not show that the extension depends on the basis states. -
depth_bound(Count | None) –Under
basis_depth_limit, the extension's CX count bound, the reference's count plus that of every generator occurrence, or None when it is unknown, no limit is set or the chain is already in the basis. -
depth_reason(Text | None) –Why
depth_boundis unknown, or None. -
eta(Real | None) –Squared norm of the extension's part outside the kept overlap subspace of the current basis, or None when it was not computed. With shots it is the estimate from the sampled overlaps, which can be negative and is not clipped.
-
coupling(Real | None) –rho = |<q|A - E|psi>|for that part q, normalized, and the current lowest Ritz state psi and value E, or None. -
gap(Real | None) –delta = <q|A|q> - E, formed fromA0and the offset-free Ritz value, or None. -
score(Real | None) –(sqrt(delta**2 + 4 rho**2) - delta)/2, a lower bound on the energy decrease that adding q to the kept subspace gives, or None. It is not a prediction of the next solve's energy. With shots it is computed from sampled matrix elements, and the sampled eligibility rule does not control the noise of the Hamiltonian elements or of the Ritz pair, so it is a raw estimate, not a validated energy decrease. -
independence_cutoff(Real | None) –With shots, the floor that
eta_marginmust exceed, which isBoundedRitzGrowth.independence_cutoffor, when that is None, ADAPT'soverlap_cutoff. Without shots it is None, as are the fields below. -
multiplier(PositiveInt | None) –With shots, the fixed multiplier k = 3 of the sampled eligibility rule.
-
metric_beta(Real | None) –With shots,
beta_S = k sqrt(nu_S), wherenu_Sis the largest sum over one row of the current overlap matrix of the variance proxies of its off-diagonal entries. Each measured real or imaginary part contributes the larger of its sample-mean variance and1/(N + 1)**2for its N shots. The diagonal and an imaginary part that real-only measurement leaves out contribute nothing. -
metric_epsilon(Real | None) –With shots,
beta_Sdivided by the smallest overlap eigenvalue that the current solve kept. The extension is scored only when it is below 1/2. -
eta_sigma(Real | None) –With shots, the first-order spread proxy of
etafrom the variance proxies of the current overlap entries and of the extension's overlaps. -
extension_noise(Real | None) –With shots,
b_s, the sum over the extension's overlaps of their real and imaginary variance proxies, each weighted by the squared norm of the matching row of T, the matrix that maps coordinates in the kept subspace of the current solve to the basis withT^dagger S T = I. -
eta_resolution(Real | None) –With shots,
R = k eta_sigma + (d + metric_epsilon x)**2/(1 - metric_epsilon)withd = k sqrt(extension_noise)and x the norm of the extension's coordinates in the kept subspace. The second term bounds the change ofetabeyond first order when the norm conditions in the GCiM guide hold, and its inputs here are variance proxies. It is a conditional empirical resolution, not a confidence bound. -
eta_margin(Real | None) –With shots,
eta - eta_resolution. The extension is scored only when it exceedsindependence_cutoff. -
overlap_cutoff(Real | None) –With shots, the overlap cutoff of the current solve.
-
kept_rank(PositiveInt | None) –With shots, the number of overlap directions that the current solve kept.
AdaptVerificationOptions ¶
Bases: Record
Options for checking the Ritz state of an ADAPT result.
Build it with keyword arguments, for example
AdaptVerificationOptions(name="adapt", comparisons=("residual", "sector")),
and pass it to result.verify(checks=...). name and comparisons are
required. "residual" and "sector" rebuild the Ritz state of the
processed Hamiltonian, and "supplied_reference_energy" compares two
recorded numbers. No reference eigensolve runs. A zero residual can
belong to an excited eigenstate, sector expectations do not prove sector
membership, and the signed spin contamination keeps its sign. The
GCiM guide gives the work limits of these
checks.
Attributes:
-
name(Text) –Required. Prefix for the check names of these options.
-
comparisons(tuple[Literal['residual', 'sector', 'supplied_reference_energy'], ...]) –Required. Distinct nonempty tuple of
"residual","sector"and"supplied_reference_energy". -
residual_tolerance(Real) –Default
1.6e-3, positive. Residual threshold in the problem's energy unit for the non-sampledresidual_threshold_metclassification. -
reference_spin(Real) –Default
0.0. Spin quantum number s, a nonnegative integer or half-integer, whoses(s+1)defines the spin contamination. -
reference_energy(FramedFact | None) –Default
None. Supplied reference energy, with the quantity and unit it refers to and its source, required by"supplied_reference_energy". It must be a concrete real scalar with emptybindings, that is, not restricted to particular parameter values. -
reference_tolerance(Real | None) –Default
None. Positive absolute comparison threshold for that energy, required by"supplied_reference_energy". -
max_bytes(PositiveInt) –Default 10 GB (decimal,
10_000_000_000bytes). Limit on the known bytes of the verification workspace. -
max_products(PositiveInt) –Default
1_000_000_000. Limit on the counted state and operator work of the verification, including the exact synthesis of the dense unitaries in a supplied reference circuit.
Raises:
-
ValueError–If
comparisonsis empty or repeats a check, ifreference_spinis not an integer or half-integer, or if"supplied_reference_energy"lacksreference_energyorreference_tolerance, or has them without that comparison. Also ifreference_energyis not a concrete real scalar with a source and emptybindings.
Build a molecular problem¶
build_gcim_chemistry_problem ¶
build_gcim_chemistry_problem(geometry: Any, *, basis: str = 'sto-3g', charge: int = 0, spin: int = 0, unit: str = 'Angstrom', name: str | None = None, coefficient_cutoff: float = 1e-12, active_space: tuple[int, int] | None = None, reference_methods: tuple[str, ...] = ()) -> GCIMChemistryProblemData
Build a closed-shell molecular Hamiltonian for GCiM and ADAPT from a geometry.
PySCF performs RHF and the molecular-orbital integral transforms, NWQLib
assembles the spin-orbital fermionic operator with OpenFermion's
FermionOperator addition, and OpenFermion performs the Jordan-Wigner
transform. It needs the chemistry extra,
pip install "nwqlib[chemistry]". MP2, CCSD or active-space CASCI
references run only when reference_methods requests them. Integrals
are in the RHF molecular-orbital basis, with each orbital's first AO coefficient above
1e-8 of its largest magnitude made positive.
The Hamiltonian is
E_c + sum h_pq a_p^dagger a_q + 1/2 sum h_pqrs a_p^dagger a_q^dagger a_r a_s
over interleaved spin orbitals, mapped by Jordan-Wigner with spin orbital
j on qubit j.
Parameters:
-
geometry(Any) –PySCF atom specification, for example
"H 0 0 0; H 0 0 0.74". -
basis(str, default:'sto-3g') –PySCF basis name.
-
charge(int, default:0) –Total molecular charge.
-
spin(int, default:0) –2S. Only 0, closed-shell RHF, is supported. -
unit(str, default:'Angstrom') –Unit of the coordinates,
"Angstrom"or"Bohr". -
name(str | None, default:None) –Optional label stored in
metadata. -
coefficient_cutoff(float, default:1e-12) –The library's explicit absolute cutoff in Hartree. Fermionic terms and final Pauli coefficients at or below it are dropped, and an imaginary part at or below it is set to zero. The fermionic terms are added with OpenFermion's
FermionOperatoraddition, and OpenFermion's Jordan-Wigner transform accumulates the Pauli terms the same way. That addition applies OpenFermion's own tolerance as well. In OpenFermion 1.8.1 it deletes a term whenever its running coefficient has absolute value below 1e-8, so acoefficient_cutoffbelow 1e-8 does not keep those terms. A stored Pauli coefficient can therefore differ from the sum of its integral contributions by those deletions. -
active_space(tuple[int, int] | None, default:None) –Optional
(n_active_electrons, n_active_orbitals). For a molecule of N electrons the lowest(N - n_active_electrons)/2RHF orbitals are frozen as doubly occupied core, and PySCF CASCI supplies the effective one- and two-body integrals and the core energy. -
reference_methods(tuple[str, ...], default:()) –Any of
"mp2","ccsd"and"casci"to run as application context."casci"needsactive_space.
Returns:
-
data(GCIMChemistryProblemData) –The Hamiltonian, reference state and integrals of the selected full or active space.
Raises:
-
ValueError–For an open-shell or odd-electron molecule, an invalid active space,
"casci"withoutactive_space, a negative cutoff or an unconverged RHF. -
ImportError–If PySCF or OpenFermion is not installed.
Examples:
H2 in the STO-3G basis at 0.74 Angstrom maps to four qubits. ADAPT
with the default spin-adapted pool returns -1.137284 Hartree, the
lowest eigenvalue of data.hamiltonian by exact diagonalization,
below the RHF energy of -1.116759 Hartree:
>>> from nwqlib import solve
>>> from nwqlib.algorithms.gcim import build_gcim_chemistry_problem
>>> data = build_gcim_chemistry_problem("H 0 0 0; H 0 0 0.74")
>>> print(data.num_qubits, data.reference_occupations)
4 (1, 1, 0, 0)
>>> print(round(data.rhf_energy, 6))
-1.116759
>>> result = solve(data.eigenproblem(), method=data.adapt_method(), seed=7)
>>> print(round(result.eigenvalue, 6))
-1.137284
GCIMChemistryProblemData ¶
GCIMChemistryProblemData
Molecular Hamiltonian, reference state and integrals from build_gcim_chemistry_problem.
build_gcim_chemistry_problem returns it. eigenproblem() gives the
Eigenproblem, and adapt_method(...) an ADAPT method with the
matching reference state. Energies and integral coefficients are in
Hartree. The builder uses the converged closed-shell RHF molecular orbitals
and interleaved alpha/beta spin modes. Each orbital's sign is fixed so
that its first significant AO coefficient is positive. This removes the
dependence on the eigensolver's sign choice, which could flip the
generators that contain the orbital and change a fixed-angle ADAPT-GCiM
trajectory. It fixes signs only. Degenerate orbitals can still be
returned in another rotation of their subspace, and binary64 rounding
can still decide between generators whose gradients tie in exact
arithmetic (GCiM guide).
In tensor shapes below, n is n_spatial_orbitals. Requested reference
calculations give application context and do not certify the solver.
The fields below are read-only.
Attributes:
-
hamiltonian(SparsePauliOp) –Jordan-Wigner SparsePauliOp for the selected full or active space, including its constant offset and the requested coefficient cutoff.
-
reference_preparation(QuantumCircuit) –Computational-basis circuit preparing the recorded closed-shell occupations from zero. Inspecting it runs no chemistry solve.
-
reference_occupations(tuple[int, ...]) –Zero/one occupation per qubit in interleaved spatial-orbital alpha/beta order, which
adapt_methoduses as the reference state. -
n_spatial_orbitals(int) –Number of selected spatial orbitals, reduced to the active orbital count when an active space was requested.
-
num_qubits(int) –Twice n_spatial_orbitals for the Jordan-Wigner spin-orbital register.
-
num_electrons(int) –Electrons in the selected Hamiltonian space, which is the active electron count when frozen-core reduction is used.
-
nuclear_repulsion_energy(float) –Original molecule's nuclear repulsion contribution.
-
constant_energy(float) –Scalar offset before Jordan-Wigner mapping: nuclear repulsion for the full space, or the returned frozen-core energy for an active space. This is not necessarily the entire final Pauli-identity coefficient.
-
rhf_energy(float) –Converged full-molecule RHF total energy, including nuclear repulsion.
-
one_body_integrals(ndarray) –Spatial-orbital tensor of shape (n,n) in the RHF orbital basis, or the active-space effective one-body tensor with frozen-core contributions.
-
two_body_integrals(ndarray) –Spatial-orbital tensor of shape (n,n,n,n), obtained by transposing the chemist-ordered integrals with axes (0,2,3,1). After spin expansion, entries multiply a_p^dagger a_q^dagger a_r a_s with factor 1/2.
-
reference_panel(Mapping[str, Any]) –RHF energy and the energies or statuses of the explicitly requested MP2, CCSD and CASCI references. Unrequested or failed reference energies stay None with their status and reason.
-
metadata(Mapping[str, Any]) –Geometry and basis, charge, ordering, cutoff, active space and dependency versions of this construction, and the reference panel under
"chemistry_reference_panel", whichchemistry_reference_diagnosticreads.to_dictomits the large integral tensors.
eigenproblem ¶
eigenproblem
Return the Eigenproblem of hamiltonian, in Hartree with its constant offset.
adapt_method ¶
adapt_method
Return an ADAPT method with this molecule's reference state and the spin-adapted pool.
Parameters:
-
**settings(object, default:{}) –Further
ADAPTarguments. They override the defaults set here:initial_state(the occupation state ofreference_occupations),pool="spin_adapted_sd"andn_spatial_orbitals.
Returns:
-
method(ADAPT) –The configured method.
to_dict ¶
to_dict
Return a JSON-like summary of the fields, without the integral tensors.
The summary holds the orbital, qubit and electron counts, the
nuclear-repulsion, constant and RHF energies, the reference panel,
the reference occupations, the Pauli term count of hamiltonian and
metadata.
closed_shell_reference_occupations ¶
closed_shell_reference_occupations(*, n_spatial_orbitals: int, num_electrons: int) -> tuple[int, ...]
Return the closed-shell RHF occupation bitstring in interleaved spin-orbital order.
Spin orbitals 2k and 2k + 1 are the alpha and beta orbitals of
spatial orbital k, and the lowest num_electrons/2 spatial orbitals are
doubly occupied.
Parameters:
-
n_spatial_orbitals(int) –Positive number of spatial orbitals.
-
num_electrons(int) –Nonnegative even number of electrons, at most
2*n_spatial_orbitals.
Returns:
-
occupations(tuple[int, ...]) –2*n_spatial_orbitalszeros and ones.
Raises:
-
ValueError–For an odd electron count or more electrons than the orbitals can hold.
Examples:
>>> from nwqlib.algorithms.gcim import closed_shell_reference_occupations
>>> closed_shell_reference_occupations(n_spatial_orbitals=3, num_electrons=2)
(1, 1, 0, 0, 0, 0)
qubit_operator_to_sparse_pauli ¶
qubit_operator_to_sparse_pauli(qubit_operator: Any, *, num_qubits: int, coefficient_cutoff: float = 1e-12) -> SparsePauliOp
Convert an OpenFermion QubitOperator to a Qiskit SparsePauliOp.
In a Qiskit label qubit 0 is the rightmost character, so OpenFermion
qubit j becomes label position num_qubits - 1 - j. Terms with
magnitude at or below coefficient_cutoff are dropped, an imaginary part
at or below it is set to zero, and equal labels are then combined by
SparsePauliOp.simplify with the same absolute tolerance.
Parameters:
-
qubit_operator(Any) –The OpenFermion
QubitOperator. -
num_qubits(int) –Positive number of qubits.
-
coefficient_cutoff(float, default:1e-12) –Nonnegative absolute cutoff on coefficients.
Returns:
-
operator(SparsePauliOp) –The converted operator, or the zero operator on
num_qubitsqubits when no term remains.
Raises:
-
ValueError–If
num_qubitsis not positive,coefficient_cutoffis negative, or a term acts on a qubit outsidenum_qubits.
Compare with chemistry references and spin sectors¶
chemistry_reference_diagnostic ¶
chemistry_reference_diagnostic(metadata: Mapping[str, Any], *, energy: float | None) -> dict[str, Any] | None
Return the stored chemistry reference energies and correlation fractions for an energy.
It reads metadata["chemistry_reference_panel"], which
build_gcim_chemistry_problem stores, and adds the full-space CCSD
correlation fraction (E - E_HF)/(E_CCSD - E_HF) and the active-space
CASCI fraction (E - E_HF)/(E_CASCI - E_HF) when the needed energies
are present. A zero denominator is recorded as the note
"undefined: E_CCSD == E_HF" or "undefined: E_CASCI == E_HF". It runs
no calculation. The values give application context, not a bound on the
error of E or an identification of the ground state. The
GCiM guide
prints the report section of such a diagnostic.
Parameters:
-
metadata(Mapping[str, Any]) –The
metadataof aGCIMChemistryProblemData. -
energy(float | None) –The energy E to compare, for example
result.eigenvalue, or None.
Returns:
-
diagnostic(dict | None) –The reference panel and the fractions, or None when
metadataholds no reference panel.
chemistry_reference_report_section ¶
chemistry_reference_report_section(diagnostic: Mapping[str, Any]) -> ReportSection
Format a chemistry reference diagnostic as a "Chemistry References" report section.
The section lists E_HF, E_MP2 and E_CCSD, plus E_CASCI for an active
space, and the correlation fractions that the diagnostic holds. A
missing energy shows its recorded status and reason, or unavailable.
result.report() does not include this section, so print or store it
beside the report.
Parameters:
-
diagnostic(Mapping[str, Any]) –A diagnostic from
chemistry_reference_diagnostic.
Returns:
-
section(ReportSection) –The formatted lines in
section.linesand the diagnostic insection.data.
correlation_fraction ¶
correlation_fraction(energy: float, e_hf: float, e_ccsd: float) -> float
Return the correlation fraction (E - E_HF) / (E_CCSD - E_HF) of an energy.
The fraction gives application context, not a bound on the error of E.
chemistry_reference_diagnostic uses it with the stored reference
energies.
Parameters:
-
energy(float) –The energy E to compare.
-
e_hf(float) –The Hartree-Fock energy, in the unit of E.
-
e_ccsd(float) –The CCSD energy, or another reference energy such as CASCI, in the unit of E.
Returns:
-
fraction(float) –(E - E_HF) / (E_CCSD - E_HF).
Raises:
-
ValueError–If
E_CCSD - E_HFis zero.
sector_expectations ¶
sector_expectations(state: ndarray, *, num_qubits: int | None = None, reference_spin: float = 0.0) -> dict[str, Any]
Return the exact particle number, spin projection and total spin of a state.
The returned dict holds <N>, <S_z> and <S^2> of the normalized
state and the spin contamination <S^2> - s(s+1) for
s = reference_spin, which keeps its sign. Qubit j is spin orbital j in
the interleaved order of the fermionic pools: even qubits are alpha
(S_z = +1/2) and odd qubits beta. <N> and <S_z> are diagonal in the
occupation basis and come from bit probabilities. <S^2> uses a
matrix-free action of S^2. These expectations describe the state. A
value equal to a sector's eigenvalue does not prove membership in that
sector, and the result is marked "validation_gate": False.
For the computed probability vector p of a q-qubit state,
m_j = sum_(x: x_j = 1) p_x gives <N> = sum_j m_j and
<S_z> = (1/2) sum_j (-1)**j m_j by exchanging two finite sums.
At most q marginal scalars are stored, and fsum then forms the two
weighted sums. Multiplication by one half is exact when it does not
underflow. With N = 2**q entries in p, P = sum p_x, M = N/2,
gamma(r) = r*u/(1 - r*u) and unit roundoff u, each marginal error is
at most gamma(M - 1)*m_j for normal arithmetic. The difference from
the occupation-diagonal dot products on the same p is
T_N <= q*P*[gamma(N) + gamma(M - 1) + u*(1 + gamma(M - 1))] for <N>
and T_{S_z} <= T_N/2 (Higham, Accuracy and Stability of Numerical
Algorithms, 2nd ed., Lemma 3.1 and Chapter 3,
doi:10.1137/1.9780898718027). Absolute underflow terms are added if
reached.
Parameters:
-
state(ndarray) –State vector of length
2**q, nonzero. It is normalized before use. -
num_qubits(int | None, default:None) –Number of qubits q, or None to infer it from the length.
-
reference_spin(float, default:0.0) –Spin quantum number s of the reference sector.
Returns:
-
expectations(dict) –The keys
particle_number,spin_z,spin_squared,reference_spinandspin_contamination, withlabel,evaluationandvalidation_gatedescribing them.
Raises:
-
ValueError–If the state length is not a power of two, does not match
num_qubits, or the state is zero.
Examples:
The two-qubit state |11> doubly occupies spatial orbital 0:
>>> from nwqlib.algorithms.gcim import sector_expectations
>>> v = sector_expectations([0, 0, 0, 1])
>>> print(v["particle_number"], v["spin_z"], v["spin_squared"])
2.0 0.0 0.0
solve calls plan and the other hooks of a Method. Extending NWQLib describes them.