Dashboard Core — Hamiltonians¶
Real molecular Hamiltonians, built on demand from actual atomic geometry
— no fabricated or hand-picked coefficients. _get_hamiltonian dispatches
per molecule: PennyLane's own qchem pipeline (Hartree-Fock +
Jordan-Wigner) when every requested element is in PennyLane's bundled
STO-3G table (H2/HeH+/H3+/LiH/H2O), or Dense-Evolution's own
native Hartree-Fock engine otherwise — currently backing
Si2 (real equilibrium R = 2.184 Å, Balamurugan & Prasad,
arXiv:cond-mat/0108426), whose
elements PennyLane's dhf can't reach at all (its table stops at Ne).
Both paths hand off to the same PennyLane fermionic_observable +
jordan_wigner step, so the qubit mapping is identical either way. Backs
Composer's molecular-energy panel, dashboard_core.vqe,
and dashboard_core.qmmm.
Honest caveat on Si2: with only 4 active electrons/orbitals (all 20 core electrons frozen across both atoms), this active space is too small to reproduce 2.184 Å as its own energy minimum — a direct 10-point bond-length scan found the minimum at the 1.9 Å edge of the scanned range, not an interior point. Stated in the catalog entry's own comment rather than silently picking a geometry that flatters the active-space choice.
Ground state without the dense matrix: ground_state_energy needs a
dense (2**n_qubits, 2**n_qubits) Hamiltonian, which is exactly what
blocked Si2 in practice (805 MB required, refused by SafeMemoryGuard on
modest hardware). ground_state_energy_sparse never builds it —
scipy.sparse.linalg.eigsh (Lanczos) against a LinearOperator wrapping
pauli_sum_matvec, matrix-free by construction. Purely
additive: ground_state_energy/build_molecular_hamiltonian are
unchanged, this is a separate opt-in path for systems too large to
densify at all — verified to match the dense path to ~1e-15 on H2/HeH+,
and to actually succeed on Si2 where the dense path fails.
from dashboard_core.hamiltonians import build_molecular_hamiltonian, ground_state_energy
H, n_qubits = build_molecular_hamiltonian(["H", "H"], [[0, 0, 0], [0, 0, 0.7414]])
print(n_qubits) # 4
print(ground_state_energy(H)) # -1.1373 Hartree
# For a catalog molecule too large to densify (e.g. Si2), skip the dense matrix entirely:
from dashboard_core.hamiltonians import ground_state_energy_sparse
e = ground_state_energy_sparse(["H", "H"], [[0, 0, 0], [0, 0, 0.7414]])
print(abs(e - ground_state_energy(H)) < 1e-8) # True -- matches the dense path exactly
hamiltonians ¶
Real molecular Hamiltonians, built on demand from actual atomic geometry via PennyLane's qchem module (Hartree-Fock + Jordan-Wigner fermion-to- qubit mapping, method='dhf' -- native to PennyLane, no PySCF/OpenFermion dependency needed).
Ported from feature/streamlit-dashboard (git branch), where this was built and verified against known values before the dashboard rebuild. Only the real molecular catalog comes along here -- the old diagonal "toy model" library and the VQE optimization loop stay out for now (kept minimal on purpose, brought back separately if/when needed).
For elements PennyLane's own bundled STO-3G table doesn't cover (row 3+, e.g. Silicon), this falls back to dense_evolution.native_hf -- a from-scratch, jax-vmap-vectorized Hartree-Fock engine (Obara-Saika integrals, Roothaan-Hall SCF) that sources basis-set data from basis_set_exchange instead, so any element it has STO-3G parameters for works. Only the Hartree-Fock/integral stage is native; the resulting converged result is still handed to PennyLane's own fermionic_observable + jordan_wigner for the qubit mapping (see native_hf/bridge.py), since that stage is already fast and well-tested.
linear_chain_geometry ¶
N atoms on a line, each bond_length_angstrom apart -- the real, general shape behind every diatomic entry in the catalog (H2, HeH+, LiH), extended to any atom count.
Examples:
>>> from dashboard_core.hamiltonians import linear_chain_geometry
>>> linear_chain_geometry(2, 0.7414)
array([[0. , 0. , 0. ],
[0. , 0. , 0.7414]])
Source code in tools/dashboard/core/hamiltonians.py
ring_geometry ¶
N atoms on a regular polygon (equal bond_length_angstrom between neighbors), circumradius R = bond_length / (2*sin(pi/n)) -- standard regular-polygon geometry. At n_atoms=3 this is exactly an equilateral triangle -- the same real D3h geometry H3+'s catalog entry uses, just generalized to any ring size (still only meaningful up to whatever qubit count this simulator's exact diagonalization / VQE range can handle -- this function itself has no such limit, the caller does).
Examples:
>>> from dashboard_core.hamiltonians import ring_geometry
>>> ring_geometry(3, 0.8738).round(4)
array([[ 0.5045, 0. , 0. ],
[-0.2522, 0.4369, 0. ],
[-0.2522, -0.4369, 0. ]])
Source code in tools/dashboard/core/hamiltonians.py
build_molecular_hamiltonian ¶
build_molecular_hamiltonian(
symbols,
geometry,
charge: int = 0,
mapping: str = "jordan_wigner",
active_electrons=None,
active_orbitals=None,
)
Runs real Hartree-Fock + fermion-to-qubit mapping (PennyLane qchem) on the given geometry and returns (H_dense, n_qubits). The eigenvalue spectrum (and therefore the ground-state energy) is mapping-invariant -- Jordan-Wigner and Bravyi-Kitaev represent the identical physical Hamiltonian in a different qubit basis -- so this only changes which qubit operators appear, never the energies this function's callers report. Cached: Hartree-Fock isn't free, and the UI can re-request the same molecule repeatedly.
The dense matrix itself is built by this project's own dense_evolution.pauli_hamiltonian_to_matrix from PennyLane's real Pauli decomposition, not qml.matrix() -- verified to match qml.matrix exactly (same ground-state energy, same matrix, atol=1e-8) for every catalog molecule.
Examples:
>>> from dashboard_core.hamiltonians import build_molecular_hamiltonian, ground_state_energy
>>> H, n_qubits = build_molecular_hamiltonian(['H', 'H'], [[0, 0, 0], [0, 0, 0.7414]])
>>> n_qubits
4
>>> round(ground_state_energy(H), 4)
-1.1373
Source code in tools/dashboard/core/hamiltonians.py
get_molecule_n_qubits ¶
get_molecule_n_qubits(
symbols,
geometry,
charge=0,
mapping="jordan_wigner",
active_electrons=None,
active_orbitals=None,
)
The qubit count a molecule's real Hamiltonian needs, without paying for a dense matrix build -- cheap enough to call for every catalog entry when just listing what's available.
Source code in tools/dashboard/core/hamiltonians.py
get_all_molecules ¶
Every catalog molecule, each annotated with its real qubit count under the given mapping -- unfiltered, so the UI can always show the whole catalog and let the molecule choice drive the circuit's qubit count (not the other way around).
Examples:
>>> from dashboard_core.hamiltonians import get_all_molecules
>>> molecules = get_all_molecules()
>>> molecules['H2 (Idrogeno) - R = 0.7414 A [equilibrio reale]']['n_qubits']
4
Source code in tools/dashboard/core/hamiltonians.py
get_compatible_molecules ¶
Filters MOLECULE_CATALOG down to molecules whose real Hamiltonian needs exactly n_qubits. Kept for callers that want a qubit-filtered view; the main catalog UI uses get_all_molecules instead so every molecule is always visible.
Source code in tools/dashboard/core/hamiltonians.py
get_molecular_hamiltonian_matrix ¶
Resolves a MOLECULE_CATALOG entry by name to its (cached) dense Hermitian Hamiltonian matrix, under the given fermion-to-qubit mapping (spectrum is identical either way, see build_molecular_hamiltonian).
Source code in tools/dashboard/core/hamiltonians.py
ground_state_energy ¶
Exact ground-state energy via dense diagonalization -- a real, checkable number (Hartree) for a Hamiltonian this small (H2/HeH+/H3+ all fit well within exact diagonalization), not an estimate.
Source code in tools/dashboard/core/hamiltonians.py
ground_state_energy_sparse ¶
ground_state_energy_sparse(
symbols,
geometry,
charge: int = 0,
mapping: str = "jordan_wigner",
active_electrons=None,
active_orbitals=None,
) -> float
Ground-state energy without ever materializing the dense (2n_qubits, 2n_qubits) Hamiltonian matrix build_molecular_hamiltonian + ground_state_energy require -- the fix for the PRIORITARIO gap recorded in prog.txt (Sezione 4.1): that pair was blocked concretely on Si2 (12 qubits, 805MB needed, SafeMemoryGuard refused it with only 1.37GB free). This path uses scipy.sparse.linalg.eigsh (Lanczos, ARPACK) against a LinearOperator wrapping dense_evolution.pauli_sum_matvec -- same real Pauli terms _get_hamiltonian/_pennylane_hamiltonian_to_pauli_terms already produce, just never densified. Memory need drops from O(dim**2) to O(dim * ncv) (ncv = ARPACK's Lanczos basis size, a small constant), the same qualitative jump the wormhole/VQE code already relies on elsewhere in this file for anything past ~12-14 qubits on modest hardware.
Same caveat as build_molecular_hamiltonian: mapping choice (Jordan- Wigner vs Bravyi-Kitaev) only changes the qubit basis, never the energy spectrum this returns.
Not a drop-in replacement for ground_state_energy: that function still exists unchanged for callers that already have a small dense H_dense (e.g. an already-built/cached catalog matrix) and want the exact, non-iterative answer -- this is the new, separate opt-in path for systems too large to densify at all, not a behavior change to the existing one.
Examples:
>>> from dashboard_core.hamiltonians import ground_state_energy_sparse, build_molecular_hamiltonian, ground_state_energy
>>> e_sparse = ground_state_energy_sparse(['H', 'H'], [[0, 0, 0], [0, 0, 0.7414]])
>>> H, _ = build_molecular_hamiltonian(['H', 'H'], [[0, 0, 0], [0, 0, 0.7414]])
>>> e_dense = ground_state_energy(H)
>>> abs(e_sparse - e_dense) < 1e-8 # matches the dense path without ever building H_dense
True
Source code in tools/dashboard/core/hamiltonians.py
mix_hamiltonians ¶
Real weighted combination H_mix = weight_aH_a + weight_bH_b of two molecular Hamiltonians acting on the same qubit space (same electron/qubit count -- the only condition that makes the sum mean anything, mirroring the old dashboard's own "mix molecules that share an electron space" behavior). A real-weighted sum of two Hermitian matrices is itself Hermitian, so H_mix is a real, valid Hamiltonian with a real spectrum -- not a fabricated hybrid, just linear algebra applied to two already-real operators.
Examples:
>>> import numpy as np
>>> from dashboard_core.hamiltonians import build_molecular_hamiltonian, mix_hamiltonians
>>> H, _ = build_molecular_hamiltonian(['H', 'H'], [[0, 0, 0], [0, 0, 0.7414]])
>>> H_mix = mix_hamiltonians(H, H, weight_a=0.5, weight_b=0.5)
>>> bool(np.allclose(H_mix, H)) # mixing H with itself in equal parts reproduces H
True
Source code in tools/dashboard/core/hamiltonians.py
See also: dashboard_core.vqe for the
ansatz circuits optimized against these Hamiltonians,
dashboard_core.qmmm for the Hellmann-Feynman
forces derived from them, and Native Hartree-Fock for the
engine backing Si2 and any other element outside PennyLane's own STO-3G
table.