Krylov Methods

The krylov subpackage implements sample-based Krylov quantum diagonalization (SKQD) and basis expansion methods.

Core SKQD

class qvartools.krylov.basis.skqd.ClassicalKrylovDiagonalization(hamiltonian, config, initial_state=None)[source]

Bases: object

Classical Krylov subspace diagonalization via exact time evolution.

Constructs Krylov states \(|\psi_k\rangle = (e^{-iH\Delta t})^k |\psi_0\rangle\) using exact matrix exponentiation (no Trotter decomposition), samples computational-basis configurations from each via Born-rule sampling, and solves a projected generalized eigenvalue problem.

For molecular Hamiltonians the algorithm restricts to the particle-number-conserving subspace. For spin Hamiltonians the full Hilbert space is used.

Parameters:
  • hamiltonian (Hamiltonian) – The system Hamiltonian.

  • config (SKQDConfig) – Algorithm hyperparameters.

  • initial_state (np.ndarray or None, optional) – Initial state vector in the full (or subspace) Hilbert space. If None, a default Hartree–Fock-like state is constructed.

hamiltonian

The Hamiltonian instance.

Type:

Hamiltonian

config

The configuration dataclass.

Type:

SKQDConfig

h_dense

Dense Hamiltonian matrix (in the relevant subspace).

Type:

np.ndarray

subspace_configs

Particle-conserving configurations, if applicable.

Type:

torch.Tensor or None

Examples

>>> skqd = ClassicalKrylovDiagonalization(hamiltonian, SKQDConfig())
>>> eigenvalues, info = skqd.run()
>>> info["krylov_dim"]
10
extract_projected_submatrix(configs)[source]

Extract projected H and S from the precomputed dense Hamiltonian.

Maps each configuration in configs to its index in the full particle-conserving subspace and extracts the corresponding submatrix of self.h_dense. Falls back to _build_projected_matrices() if any configuration is not found in the subspace.

Parameters:

configs (torch.Tensor) – Basis configurations, shape (n_basis, num_sites).

Returns:

  • h_proj (np.ndarray) – Projected Hamiltonian, shape (n_basis, n_basis).

  • s_proj (np.ndarray) – Overlap matrix (identity), shape (n_basis, n_basis).

Return type:

tuple[ndarray, ndarray]

run()[source]

Execute the full SKQD algorithm.

Constructs Krylov states iteratively, samples configurations from each, builds projected Hamiltonian and overlap matrices in the sampled basis, and solves the generalized eigenvalue problem.

Returns:

  • eigenvalues (np.ndarray) – Lowest eigenvalues from the projected problem, shape (num_eigenvalues,).

  • info (dict) – Diagnostic information with keys:

    • "basis_size" : int — final number of basis configurations.

    • "krylov_dim" : int — number of Krylov vectors constructed.

    • "energies_per_step" : list of float — ground-state energy estimate after each Krylov expansion step.

    • "basis_configs" : torch.Tensor — final basis configurations.

Return type:

tuple[ndarray, dict[str, Any]]

class qvartools.krylov.basis.skqd.SKQDConfig(max_krylov_dim=10, time_step=0.1, total_evolution_time=1.0, shots_per_krylov=1000, use_cumulative_basis=True, num_eigenvalues=1, which_eigenvalues='SA', regularization=1e-08, use_gpu=False)[source]

Bases: object

Hyperparameters for Sample-Based Krylov Quantum Diagonalization.

Parameters:
  • max_krylov_dim (int) – Maximum number of Krylov vectors to construct.

  • time_step (float) – Time step for real-time evolution e^{-iH dt}.

  • total_evolution_time (float) – Total evolution time budget (informational; the algorithm uses max_krylov_dim * time_step Krylov vectors).

  • shots_per_krylov (int) – Number of measurement shots per Krylov state for sampling computational-basis configurations.

  • use_cumulative_basis (bool) – If True, retain samples from all previous Krylov states (cumulative union). If False, only keep the latest set.

  • num_eigenvalues (int) – Number of lowest eigenvalues to compute from the projected problem.

  • which_eigenvalues (str) – Eigenvalue selection criterion passed to the eigensolver. "SA" = smallest algebraic (default).

  • regularization (float) – Tikhonov regularization added to the overlap matrix diagonal to stabilise the generalized eigenvalue problem.

  • use_gpu (bool) – If True, attempt to use GPU-accelerated linear algebra.

Examples

>>> cfg = SKQDConfig(max_krylov_dim=5, time_step=0.05)
>>> cfg.max_krylov_dim
5
max_krylov_dim: int = 10
time_step: float = 0.1
total_evolution_time: float = 1.0
shots_per_krylov: int = 1000
use_cumulative_basis: bool = True
num_eigenvalues: int = 1
which_eigenvalues: str = 'SA'
regularization: float = 1e-08
use_gpu: bool = False

Flow-Guided SKQD

class qvartools.krylov.basis.flow_guided.FlowGuidedKrylovDiag(hamiltonian, config, nf_basis, nf_basis_weights=None, initial_state=None)[source]

Bases: object

SKQD with normalizing-flow basis seeding.

Combines configurations obtained from a normalizing-flow sampler with the Krylov subspace to accelerate convergence. The NF basis provides an informed starting set of configurations, and Krylov expansion systematically enriches it.

Parameters:
  • hamiltonian (Hamiltonian) – The system Hamiltonian.

  • config (SKQDConfig) – Algorithm hyperparameters.

  • nf_basis (torch.Tensor) – Configurations from the normalizing-flow sampler, shape (n_nf, num_sites).

  • nf_basis_weights (torch.Tensor or None, optional) – Importance weights for the NF configurations. If None, uniform weights are assumed.

  • initial_state (np.ndarray or None, optional) – Initial state for the Krylov expansion. If None, a default Hartree–Fock-like state is constructed.

Examples

>>> skqd = FlowGuidedKrylovDiag(hamiltonian, SKQDConfig(), nf_basis=nf_configs)
>>> results = skqd.run_with_nf(progress=True)
>>> results["energy"]
-1.137
run_with_nf(progress=False)[source]

Run SKQD with NF basis seeding.

Parameters:

progress (bool, optional) – If True, log progress at each Krylov expansion step.

Returns:

Results dictionary with keys:

  • "energy" : float — best stable ground-state energy estimate.

  • "eigenvalues" : np.ndarray — all computed eigenvalues from the final projection.

  • "basis_size" : int — final number of basis configurations.

  • "krylov_dim" : int — number of Krylov vectors used.

  • "energies_per_step" : list of float — ground-state energy estimate after each expansion step.

  • "nf_energy" : float — energy from the NF-only basis.

  • "basis_configs" : torch.Tensor — final basis configurations.

Return type:

dict

Basis Expansion

class qvartools.krylov.expansion.residual_config.ResidualExpansionConfig(max_configs_per_iter=100, residual_threshold=0.0001, max_iterations=10, max_basis_size=5000, min_energy_improvement_mha=0.05, stagnation_patience=3)[source]

Bases: object

Hyperparameters for residual-based and selected-CI basis expansion.

Parameters:
  • max_configs_per_iter (int) – Maximum number of new configurations to add per iteration.

  • residual_threshold (float) – Minimum absolute residual component for a configuration to be considered for inclusion.

  • max_iterations (int) – Maximum number of expansion iterations.

  • max_basis_size (int) – Hard upper limit on the total basis size.

  • min_energy_improvement_mha (float) – Minimum energy improvement in milliHartree per iteration. If the improvement drops below this for stagnation_patience consecutive iterations, expansion terminates.

  • stagnation_patience (int) – Number of consecutive iterations with insufficient energy improvement before early stopping.

Examples

>>> cfg = ResidualExpansionConfig(max_configs_per_iter=50)
>>> cfg.max_configs_per_iter
50
max_configs_per_iter: int = 100
residual_threshold: float = 0.0001
max_iterations: int = 10
max_basis_size: int = 5000
min_energy_improvement_mha: float = 0.05
stagnation_patience: int = 3
class qvartools.krylov.expansion.residual_expander.ResidualBasedExpander(hamiltonian, config)[source]

Bases: object

Iterative basis expansion driven by residual analysis.

Given a current basis and its ground-state eigenpair \((E, |\Phi\rangle)\), computes the residual \(r_x = \langle x | (H - E) | \Phi \rangle\) for candidate configurations \(|x\rangle\) and adds those with the largest \(|r_x|\) to the basis.

Parameters:
  • hamiltonian (Hamiltonian) – The system Hamiltonian.

  • config (ResidualExpansionConfig) – Expansion hyperparameters.

hamiltonian

The Hamiltonian instance.

Type:

Hamiltonian

config

The configuration dataclass.

Type:

ResidualExpansionConfig

Examples

>>> expander = ResidualBasedExpander(hamiltonian, ResidualExpansionConfig())
>>> expanded, stats = expander.expand_basis(basis, energy, eigvec)
>>> stats["iterations"]
3
expand_basis(current_basis, energy, eigenvector)[source]

Iteratively expand the basis using residual analysis.

Parameters:
  • current_basis (torch.Tensor) – Starting basis configurations, shape (n_basis, num_sites).

  • energy (float) – Current ground-state energy estimate.

  • eigenvector (np.ndarray) – Current eigenvector in the basis representation.

Returns:

  • expanded_basis (torch.Tensor) – Expanded basis configurations.

  • stats (dict) – Expansion statistics with keys:

    • "iterations" : int — number of expansion iterations.

    • "initial_energy" : float — energy before expansion.

    • "final_energy" : float — energy after expansion.

    • "energy_improvement_mha" : float — total improvement in mHa.

    • "basis_sizes" : list of int — basis size at each iteration.

    • "energies" : list of float — energy at each iteration.

    • "configs_added" : list of int — configs added per iteration.

Return type:

tuple[Tensor, dict[str, Any]]

class qvartools.krylov.expansion.selected_ci_expander.SelectedCIExpander(hamiltonian, config)[source]

Bases: object

CIPSI-style selected-CI basis expansion.

Uses second-order perturbative importance to select the most significant configurations for basis enrichment:

\[\varepsilon_x = \frac{|\langle x | H | \Phi \rangle|^2}{|E - E_x|}\]

where \(E_x = \langle x | H | x \rangle\) is the diagonal Hamiltonian element and \(E\) is the current variational energy.

Parameters:
  • hamiltonian (Hamiltonian) – The system Hamiltonian.

  • config (ResidualExpansionConfig) – Expansion hyperparameters (shared with residual expansion).

hamiltonian

The Hamiltonian instance.

Type:

Hamiltonian

config

The configuration dataclass.

Type:

ResidualExpansionConfig

Examples

>>> expander = SelectedCIExpander(hamiltonian, ResidualExpansionConfig())
>>> expanded, stats = expander.expand_basis(basis, energy, eigvec)
>>> "pt2_corrections" in stats
True
expand_basis(current_basis, energy, eigenvector)[source]

Iteratively expand the basis using CIPSI-style selection.

Parameters:
  • current_basis (torch.Tensor) – Starting basis configurations, shape (n_basis, num_sites).

  • energy (float) – Current ground-state energy estimate.

  • eigenvector (np.ndarray) – Current eigenvector in the basis representation.

Returns:

  • expanded_basis (torch.Tensor) – Expanded basis configurations.

  • stats (dict) – Expansion statistics with keys:

    • "iterations" : int — number of expansion iterations.

    • "initial_energy" : float — energy before expansion.

    • "final_energy" : float — energy after expansion.

    • "energy_improvement_mha" : float — total improvement in mHa.

    • "basis_sizes" : list of int — basis size at each iteration.

    • "energies" : list of float — energy at each iteration.

    • "configs_added" : list of int — configs added per iteration.

    • "pt2_corrections" : list of float — Epstein–Nesbet PT2 correction at each iteration.

Return type:

tuple[Tensor, dict[str, Any]]

Basis Sampling

class qvartools.krylov.basis.sampler.KrylovBasisSampler(hamiltonian, num_qubits, shots=1000, time_step=0.1)[source]

Bases: object

Interface for sampling configurations from Krylov-evolved states.

Computes time-evolved states \(|\psi_k\rangle = e^{-iH \Delta t \cdot k} |\psi_0\rangle\) and samples computational-basis configurations from the resulting probability distribution \(p(x) = |\langle x | \psi_k \rangle|^2\).

Currently provides a classical simulation backend. The interface is designed to accommodate future quantum-hardware backends (e.g., via Qiskit or CUDA-Q) without changing the calling code.

Parameters:
  • hamiltonian (Hamiltonian) – The system Hamiltonian.

  • num_qubits (int) – Number of qubits (must match hamiltonian.num_sites).

  • shots (int, optional) – Default number of measurement shots per sample call.

  • time_step (float, optional) – Time step \(\Delta t\) for the Krylov evolution.

Raises:

ValueError – If num_qubits does not match the Hamiltonian’s site count, or if shots or time_step are invalid.

Examples

>>> from qvartools.hamiltonians import TransverseFieldIsing
>>> ham = TransverseFieldIsing(num_sites=4, J=1.0, h=0.5)
>>> sampler = KrylovBasisSampler(ham, num_qubits=4, shots=500)
>>> counts = sampler.sample_krylov_state(krylov_power=3)
>>> type(counts)
<class 'dict'>
property h_dense: ndarray

Lazily-constructed dense Hamiltonian matrix.

Returns:

Dense Hamiltonian of shape (hilbert_dim, hilbert_dim).

Return type:

np.ndarray

sample_krylov_state(krylov_power, initial_state=None)[source]

Sample configurations from a Krylov-evolved state.

Computes \(|\psi_k\rangle = e^{-iH \Delta t \cdot k} |\psi_0\rangle\) and samples shots bitstring configurations from the resulting probability distribution.

Parameters:
  • krylov_power (int) – Krylov power index \(k\). k = 0 samples from the initial state directly.

  • initial_state (np.ndarray or None, optional) – Initial state vector of shape (hilbert_dim,). If None, the first computational-basis state |00...0\rangle is used.

Returns:

Mapping from bitstring (e.g., "0110") to the number of times it was observed across shots samples.

Return type:

dict of str to int

Raises:
  • ValueError – If krylov_power is negative or initial_state has the wrong dimension.

  • RuntimeError – If the evolved state has near-zero norm (e.g., due to numerical issues).

Krylov Expansion Utilities

krylov_expand — Basis expansion via Hamiltonian connections

Provides expand_basis_via_connections(), which grows a configuration basis by following the off-diagonal structure of the Hamiltonian. Starting from a set of reference configurations, the function collects all Hamiltonian-connected states, ranks them by coupling strength, and adds unique new configurations up to a specified cap.

Supports two-hop expansion: first hop discovers singles/doubles from seed configs, second hop expands from those to reach up to quadruples.

qvartools.krylov.expansion.krylov_expand.expand_basis_via_connections(basis, hamiltonian, max_new=500, n_ref=None, coupling_rank=True)[source]

Expand a configuration basis by following Hamiltonian connections.

Selects n_ref reference configurations from the basis, collects all states connected to them via the Hamiltonian, ranks by coupling strength, removes duplicates and states already in the basis, and returns the expanded basis with up to max_new new configurations.

Performs a two-hop expansion when budget allows: first hop discovers single/double excitations from seed configs, second hop expands from those to reach quadruples.

Parameters:
  • basis (torch.Tensor) – Current basis configurations, shape (n_basis, n_sites) with integer entries.

  • hamiltonian (Any) – The system Hamiltonian. Must implement diagonal_element and get_connections.

  • max_new (int, optional) – Maximum number of new configurations to add (default 500).

  • n_ref (int or None, optional) – Number of reference configurations. Defaults to min(len(basis), 50).

  • coupling_rank (bool, optional) – If True, rank new configs by max |H_ij| coupling strength and keep top max_new (default True).

Returns:

Expanded basis configurations, shape (n_basis + n_added, n_sites) where n_added <= max_new.

Return type:

torch.Tensor