Skip to content

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_ij and S_ij as soon as it is prepared, so (M - D) + D measurements.
  • 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, so Q(M - D) max(1, G) + DG settings for G groups, n shots each. Q is 2, or 1 when acquisition resolves 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 of shots=: 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) V and V^dagger V computed directly, with c = 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 StateData accepts. 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_000 bytes). 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, within max_conversion_work and max_bytes.

  • max_conversion_work (PositiveInt) –

    Default 100_000_000. Limit on the counted work of operator-to-Pauli conversion, including the conversion that input_conversion="auto" selects.

  • max_admission_steps (PositiveInt) –

    Default 10_000_000. Upper limit on the planning work of checking each Program that the method builds (NWQLib's description of a circuit as named steps). It caps the number of stored fields of a Program and the work units of one check of it. Summing a Program's resource counts may use up to 24 times this value. A larger Program is 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, so matrix_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 raises ApplicabilityError for pair_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 in plan.reconstruction.acquisition.

  • max_native_two_qubit_depth (Count | None) –

    Default None, which requests no depth limit. None is 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 raises nwqlib.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 its provenance set. 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, and plan.method.analyze(plan, run.data, settings={}) returns a Result that lists the settings without data in missing and 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 by nwqlib.prepare (prepared.run.prepared_artifacts). Under sampling the limit applies to every pilot and main circuit in the same way, and the settings without main-stage data are the missing ones.

  • sampling (PencilSampling | None) –

    Default None, which measures every setting with the shots= of the call. A PencilSampling replaces shots= with a pilot stage and a main stage whose shots per setting the pilot decides, and needs quantum execution. The Result's shot_allocation records 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 is PencilSampling.total_shots.

Raises:

  • ValueError –

    If acquisition requests 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" is ADAPT's comparison construction: one Hadamard test per pair, Pauli term and part, b**2 L + b(b-1) settings with both parts and bL + b(b-1)(L+1)/2 with real parts only. It requires pair_preparation="controlled". FixedGCIM and QFD measure 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. FixedGCIM treats each supplied state as one block, so only two identical preparations share a prefix. QFD uses the powers of its one step V instead: a pair runs the reference and V**b once without control, for the power b of smaller absolute value (of the smaller index on a tie), and controls V**(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 for ADAPT, whose states are phi_i = Q_i B|vac> for the reference preparation B and a generator chain Q_i that maps the all-zero state |vac> to exp(i gamma_i)|vac> with a known vacuum phase gamma_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 and phi_j, "vacuum_reference" applies the Hadamard gate to the ancilla, B controlled on ancilla value 1, Q_j without control, B controlled on ancilla value 0 and the phase gate diag(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_L first and Q_R second, which can reverse their basis order. It applies the Hadamard gate, B controlled on 1, Q_R, the adjoint of Q_L, B controlled on 0, Q_L and diag(1, exp(i(gamma_R - gamma_L))), all without control except B, so it runs m_R + 2 m_L generator exponentials for chains of m_L and m_R generators. The zero branch stays at the vacuum, with the phase exp(i(gamma_R - gamma_L)), until B prepares the reference on it and Q_L makes it phi_L, while the other branch holds the adjoint of Q_L applied to phi_R until the final Q_L restores phi_R. This adjoint reverses the circuit already built for Q_L and 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. ADAPT planning accepts them when the Pauli terms of every pool generator show that its exponential maps |vac> to itself up to a phase (ADAPT's acquisition), and raises ApplicabilityError otherwise. FixedGCIM and QFD raise ApplicabilityError for both values in quantum execution, exact or with shots, unless the Plan measures nothing, because a FixedGCIM state is one supplied preparation and the step V of QFD has 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 that H and S are 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. ADAPT needs 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. For ADAPT, A is the Hamiltonian after its pauli_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 of QFD, which are complex in general even for a real A, so QFD rejects "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, QFD and the default growth of ADAPT measure nothing when A is a multiple of the identity, while ADAPT with 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 any pair_preparation other 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 in scope prove 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 quadratures has 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 ADAPT that is the Hamiltonian after pauli_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 FixedGCIM or QFD Plan, 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 for ADAPT, whose pairs arise during the run and whose joint-state constructions ADAPTResult.pair_preparations reports.

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) with i < j, positions in the basis of the pencil. ADAPT orders 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 first shared_blocks preparation blocks of both states run once without control, "controlled" when both complete preparations are controlled on the ancilla. The two ADAPT routes 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 that pair describes, 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 FixedGCIM preparations, the reference plus the common leading generators for ADAPT, and the reference plus the abs(b) uses of V or its adjoint for the shared power b of QFD. 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. ADAPT requires 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_shots for 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_ij and S_ij with 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 ProjectedPencil with the projected matrices and solve diagnostics, or None for partial data or a scalar identity target. Under PencilSampling it 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. Then estimates, group_moments, sampled_pair_variances, pencil, missing and contribution_ids concern the main stage only, and a Result from before the decision lists every setting in missing. The pilot measurements stay in the Run's observations. None without PencilSampling.

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, normalization and backward_error are the pencil's overlap, overlap_eigenvalues, overlap_normalization_error and projected_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 S of shape (m, m) in the problem's energy unit, from H0 without the identity term c_I I and from S, completed from its upper triangle by conjugation. The solve used H0 and added c_I to its Ritz values.

  • overlap (tuple[tuple[Complex128, ...], ...]) –

    Gram matrix S of 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), before c_I is added, in ascending order, one at kept_rank 1 and two at a larger rank. The first one or two eigenvalues are these values plus c_I, rounded once each. They are therefore equal for c_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 of PencilSampling uses for its per-setting variance estimates v_s (ShotAllocation.variances) and its exact-tie test, and ShotAllocation.gap is their rounded difference e1 - 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, with H = H0 + c_I S when the solve removed an identity coefficient c_I. Rescaling the energy unit leaves it unchanged, but adding an identity term to the operator changes normF(H) and abs(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 operator c 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_rtol times 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_p when settings are measured, or 0 when none is.

  • effective_fraction (Rational | Literal['not_applicable']) –

    B_p/total_shots as an exact ratio in lowest terms (a Rational record), or "not_applicable" when the pencil has no setting to measure, so that both stages have zero shots and pilot_counts, main_counts and variances are empty. For FixedGCIM and QFD this happens when the operator is a multiple of the identity. For ADAPT it 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's failure_reason gives 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_s over 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 - e0 of 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 gap belongs to the offset-free values, not to the physical eigenvalues.

  • pilot (ProjectedPencil | None) –

    The pilot ProjectedPencil, solved at the Method's overlap_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) with left <= 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 hamiltonian and overlap.

  • hamiltonian_bound (Nonnegative | None) –

    Outward error allowance for the reported offset-free Hamiltonian entry H0_ij under 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 ADAPT it is pair for an off-diagonal setting or diagonal.

  • contribution_id (ContentID) –

    Content hash of the count data these moments come from.

  • pair (tuple[Count, Count]) –

    (i, j) with i <= j, positions in the basis of the pencil.

  • quadrature (Literal['real', 'imag']) –

    real (ancilla X) or imag (ancilla Y).

  • group (Count) –

    Index of the qubit-wise commuting group of nonidentity terms, into FixedGCIMReconstruction.groups or AdaptReconstruction.energy_groups.

  • shots (Count) –

    Returned shots N of that count data.

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

    The mean of each member's Z_k in 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_X of that group, otherwise None.

  • mean_covariance (Real | None) –

    C_XY of 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) with i <= 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 S per 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

reference

reference

Reference to this basis by content hash, for Eigenproblem(subspace=...).

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 StateData accepts.

  • pool (Any) –

    Required. A nonempty tuple of anti-Hermitian generators, FermionicGenerator records or operators that operator_input accepts, 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. None for 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 sets T_auto.

  • t_user (PositiveInt) –

    Default 10. Cap T_usr on consecutive flat rounds in the rule min(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 most 2*min(max_iterations, pool size) states, so max_basis_size=64 allows 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. With max_iterations=32, the largest that max_basis_size=64 allows 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's projected_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_000 bytes). 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, within max_conversion_work and max_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 in plan.reconstruction.acquisition. The processed Hamiltonian is the one measured, the operator after pauli_coefficient_cutoff, whose removed coefficient magnitudes sum to plan.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, and quadratures then 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 in i c (XX + YY), while i c X and i (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 raises ApplicabilityError naming the first one by its pool index. Both values apply when joint states are prepared, exactly or with grouped shots, and ADAPTResult.pair_preparations records 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 raises ApplicabilityError before 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. A BoundedRitzGrowth instead grows an explicit list of short generator chains, one scored extension per round, at the fixed angle theta. Each of its added chains counts toward max_iterations, and its basis stops growing at max_basis_size states. It screens no gradients, so gradient_norm_floor has no effect and the commutators [H, A_j] are not formed. ADAPT raises ValueError for it together with optimize_every_m or stop_criterion="residual_norm". With shots it supports the default grouped measurement, and planning raises ValueError when acquisition requests matrix_measurement="termwise". With a scalar processed Hamiltonian and max_basis_size>1, quantum planning still resolves the measurement choices because evaluating extensions can need overlaps. With max_basis_size=1 the Plan measures nothing and keeps the request unused.

  • max_native_two_qubit_depth (Count | None) –

    Default None, which requests no depth limit. None is 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 with stop_reason "native_depth_refused", and pending holds 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 raises nwqlib.backends.inspection.NativeDepthCapRefusal with its provenance set, 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 by nwqlib.prepare (prepared.run.prepared_artifacts).

  • sampling (PencilSampling | None) –

    Default None, with which a run with shots takes eigenvalue and pencil from the same measurements that chose the basis. A PencilSampling measures 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 form eigenvalue, pencil and the group moments of the Result. The stages follow the rules of PencilSampling for the grouped settings of the final basis, and ADAPTResult.shot_allocation records the decision. shots= still sets the shots of every query that grows the basis, and total_shots is a separate budget of the two final stages. When the final basis has settings to measure and both stages complete, the Run spends total_shots in addition to the shots of the growth. A Run that ends during the stages counts the shots already submitted, up to total_shots stage 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. sampling supports quantum execution with a positive shots= and the default grouped measurement. Planning raises ValueError for classical execution in every case. When the Plan measures anything, it also raises it for shots=None and for matrix_measurement="termwise". A quantum Plan that measures nothing, such as the default growth for a multiple of the identity, accepts sampling with shots=None or termwise measurement, runs no stage and records zero pilot and main shots. Before the first query, planning requires at least four of the total_shots for every setting of the largest basis the Plan can reach, 2*min(max_iterations, pool size) states, or min(max_basis_size, max_iterations + 1) with basis_growth, so a run that stops with a smaller basis may have needed fewer shots. It also checks the analysis of one stage of total_shots shots on that basis against max_bytes and max_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_evidence included, and the main stage can still end without an eigenvalue, as when its solve fails. A circuit that max_native_two_qubit_depth refuses, 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, eigenvalue is None and analysis_attempts is 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 through Run.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 theta is zero, if only some of the three optimization settings are given, if an explicit pool is empty or has more than max_pool_size members, or if basis_growth is combined with optimization or stop_criterion="residual_norm", or has no independence_cutoff while overlap_cutoff is 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, or max_iterations once that many chains have been added.
  • flat_counter: consecutive energy changes below energy_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 exceeds basis_depth_limit or 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 examined max_candidate_scans extensions, all already in the basis.
  • no_admissible_candidate: without shots, no evaluated extension passed independence_cutoff with 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 most parent_window - 1 chains 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 pass independence_cutoff with a finite score ends the growth with no_admissible_candidate. With shots, a round whose only evaluated extension fails the sampled eligibility rule ends the growth with noise_inconclusive, and a round whose only evaluated extension passes the rule without a finite score ends the growth with no_admissible_candidate. The GCiM guide describes an adjacent repeat of a generator with A**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 by basis_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 qubits 2(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 raises ValueError for 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 which ADAPT.max_native_two_qubit_depth checks.

  • independence_cutoff (Real | None) –

    Default None, which uses ADAPT's overlap_cutoff and then requires it to be below 1. Otherwise a value in (0, 1). An extension is scored only when eta, 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 AdaptRound per completed projected analysis.

  • pencil (ProjectedPencil | None) –

    The ProjectedPencil of 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_subspace and invalid_sampled_evidence. With BoundedRitzGrowth the scientific stops are max_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_subspace without shots and invalid_sampled_evidence with shots, all operational limits rather than evidence of convergence. When a round finds no extension to evaluate, basis_depth_limit takes precedence over parent_window_exhausted, and that over candidate_scans_exhausted, each describing only the examined extensions (BoundedRitzGrowth). Execution states are running, cancelled, not_started, partial_observation (data that a decision needs are missing or unusable), pending_preparation and pending_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_failed and native_depth_refused (the next circuit's native two-qubit depth exceeds ADAPT.max_native_two_qubit_depth or is unavailable, so it was not submitted, and pending holds 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.sampling included.

  • 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 in FixedGCIMResult. 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). Under pair_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 when matrix_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 when pencil is 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 behind eigenvalue and pencil, the first chains of basis. 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 in basis. 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, the ShotAllocation of 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 and effective_fraction is "not_applicable", while the shots of the growth stay spent. Once the main stage has been analyzed, eigenvalue, pencil, group_moments, sampled_pair_variances and contribution_ids come from the main-stage measurements alone, group_moments in the setting order of the decision, while history keeps the analyses that grew the basis. Loading the Result and result.analyze(...) read the decision as saved. None without sampling and 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, normalization and backward_error are the pencil's overlap, overlap_eigenvalues, overlap_normalization_error and projected_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 BoundedRitzGrowth the 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 energy minus 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 BoundedRitzGrowth it 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, the BoundedCandidate extensions 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" when eta was 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 that basis_depth_limit excluded, 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 of BoundedRitzGrowth does 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" when metric_epsilon is at least 1/2 or a needed quantity is not finite, and "screening_independence_unresolved" when eta_margin is at most independence_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_bound is 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 from A0 and 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_margin must exceed, which is BoundedRitzGrowth.independence_cutoff or, when that is None, ADAPT's overlap_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), where nu_S is 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 and 1/(N + 1)**2 for its N shots. The diagonal and an imaginary part that real-only measurement leaves out contribute nothing.

  • metric_epsilon (Real | None) –

    With shots, beta_S divided 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 eta from 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 with T^dagger S T = I.

  • eta_resolution (Real | None) –

    With shots, R = k eta_sigma + (d + metric_epsilon x)**2/(1 - metric_epsilon) with d = k sqrt(extension_noise) and x the norm of the extension's coordinates in the kept subspace. The second term bounds the change of eta beyond 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 exceeds independence_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-sampled residual_threshold_met classification.

  • reference_spin (Real) –

    Default 0.0. Spin quantum number s, a nonnegative integer or half-integer, whose s(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 empty bindings, 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_000 bytes). 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 comparisons is empty or repeats a check, if reference_spin is not an integer or half-integer, or if "supplied_reference_energy" lacks reference_energy or reference_tolerance, or has them without that comparison. Also if reference_energy is not a concrete real scalar with a source and empty bindings.

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 FermionOperator addition, 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 a coefficient_cutoff below 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)/2 RHF 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" needs active_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" without active_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_method uses 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", which chemistry_reference_diagnostic reads. to_dict omits 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 ADAPT arguments. They override the defaults set here: initial_state (the occupation state of reference_occupations), pool="spin_adapted_sd" and n_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_orbitals zeros 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_qubits qubits when no term remains.

Raises:

  • ValueError –

    If num_qubits is not positive, coefficient_cutoff is negative, or a term acts on a qubit outside num_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 metadata of a GCIMChemistryProblemData.

  • 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 metadata holds 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.lines and the diagnostic in section.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_HF is 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_spin and spin_contamination, with label, evaluation and validation_gate describing 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.