Dashboard Core — VQE¶
Real, dynamically-generated VQE ansatz circuits for molecular
Hamiltonians — no fixed/hardcoded rotation angles. Every circuit this
module returns is built from the actual molecule's own qubit count and
Hamiltonian, run through dense_evolution.autodiff's
gradient engine.
Quick start¶
from dashboard_core.vqe import run_vqe
result = run_vqe(
symbols=["H", "H"],
geometry=[[0, 0, 0], [0, 0, 0.7414]],
ansatz_type="hardware_efficient",
n_layers=4,
maxiter=200,
)
print(result["vqe_energy_hartree"]) # -1.137270 (verified against exact_energy_hartree)
run_vqe needs the optional pennylane extra (used internally to build
the molecular Hamiltonian and Hartree-Fock reference state — the native
UCCSD ansatz circuits themselves don't need PennyLane, see
dense_evolution.circuits.uccsd, but Hamiltonian
construction still does). ansatz_type="uccsd" uses that native
implementation instead of "hardware_efficient"'s generic layered
ansatz; n_layers is then ignored, since UCCSD's parameter count comes
from the molecule's own occupied/virtual orbital structure.
vqe ¶
Real, dynamically-generated VQE ansatz circuits for molecular Hamiltonians -- no fixed/hardcoded rotation angles. Every circuit this module returns is produced by an actual classical optimization run against the real molecular Hamiltonian for the requested geometry/mapping, not a stored constant.
Two real ansatz families:
- hardware-efficient (Kandala et al., Nature 2017): a Hartree-Fock computational-basis initial state, then n_layers of single-qubit RY rotations followed by a linear CNOT entangling ladder. Generic -- doesn't know anything about the molecule's own fermionic structure, just a NISQ-friendly template. Optimized entirely on dense_evolution's own engine: the ansatz is built as real OpenQASM, parsed with dense_evolution.QASMParser, and turned into a JAX-differentiable energy function via dense_evolution.autodiff.circuit_to_energy_fn (the exact pattern already used and tested in this project's own feature/streamlit-dashboard history, dashboard_core/vqe_engine.py -- reused here without its unrelated QM/MM-telemetry code, not reinvented). A hand-rolled Adam loop (jax.value_and_grad, jax.jit) optimizes it -- no PennyLane device/QNode/optimizer involved at all for this ansatz; PennyLane's only remaining role anywhere in this module is the real Hartree-Fock + Jordan-Wigner mapping itself (dashboard_core.hamiltonians), which isn't something worth reimplementing (see research/quantum_chemistry_vqe_pipeline.md). Verified to match the PennyLane-optimized version's convergence (same order of residual error against the exact energy, same physics).
- UCCSD (Unitary Coupled-Cluster Singles and Doubles): the standard chemically-motivated VQE ansatz. Built from the molecule's real single/double fermionic excitation operators (dense_evolution.find_excitations -- pure combinatorics, verified to reproduce qml.qchem.excitations exactly), applied to the Hartree-Fock reference via dense_evolution.single_excitation_ops/ double_excitation_ops -- exact closed-form circuits derived directly against dense_evolution's own Jordan-Wigner mapping (physics.fermions.majorana_pauli_terms), not PennyLane's decomposition; see dense_evolution/circuits/uccsd.py for the derivation and the exact scope of the closed form vs. its (also verified exact) per-term fallback. Fewer parameters than hardware-efficient for the same molecule (H2: 3 vs 32), and converges to the exact energy faster because the ansatz form actually matches the physics. Also optimized entirely on dense_evolution's own engine, same as hardware-efficient -- the obstacle was that these excitation circuits reuse the same weight across several RY/RZ gates per excitation (single_excitation_ops' CRY is 2 RY gates; double_excitation_ops' per-term path is up to 8 RZ gates), whereas circuit_to_energy_fn treats every parametric gate occurrence as an independent free parameter. Solved with an affine parameter expansion (_uccsd_native_expansion): probing _uccsd_native_ops at weights=0 and at each basis vector gives a fixed (baseline, expansion_matrix) pair such that full_gate_values = baseline + expansion_matrix @ real_weights exactly reproduces the real per-gate values for any weights (verified by direct probing, not derived from theory) -- composed with circuit_to_energy_fn this is still JAX-differentiable in the small real weight vector by ordinary chain rule, so the same hand-rolled Adam loop optimizes it with no PennyLane device/QNode/optimizer, or PennyLane import of any kind, involved.
The Hartree-Fock initial state (computed via qml.qchem.hf_state) only has a simple X-gate encoding under the Jordan-Wigner mapping, so VQE generation here is JW-only. Bravyi-Kitaev stays available for exact ground-state-energy queries in hamiltonians.py, where the eigenvalue spectrum is mapping-invariant.
PennyLane's only remaining role anywhere in this module is the real Hartree-Fock + Jordan-Wigner Hamiltonian construction itself (dashboard_core.hamiltonians), which isn't something worth reimplementing (see research/quantum_chemistry_vqe_pipeline.md) -- the ansatz circuits themselves (hardware-efficient and UCCSD alike) never touch PennyLane at all.
run_vqe ¶
run_vqe(
symbols,
geometry,
charge=0,
ansatz_type="hardware_efficient",
n_layers=8,
maxiter=200,
step_size=0.1,
beta1=0.9,
beta2=0.999,
active_electrons=None,
active_orbitals=None,
seed=0,
)
Runs a real VQE optimization (hand-rolled Adam over dense_evolution's own JAX-differentiable circuit_to_energy_fn, no PennyLane optimizer/device involved) for the molecule's Jordan-Wigner qubit Hamiltonian. step_size/beta1/beta2 are Adam's own real hyperparameters (learning rate and first/second moment decay), not cosmetic -- they change the real optimization trajectory computed below, the same way they would in any other Adam implementation. ansatz_type is "hardware_efficient" (generic, n_layers deep) or "uccsd" (chemically motivated, real fermionic single/double excitations -- n_layers is ignored, the parameter count comes from the molecule's own occupied/ virtual orbital structure). Returns a dict with the real energy convergence trace, the final variational energy, the exact ground- state energy (dense diagonalization -- feasible for every qubit count this function is meant to be called with, capped by the caller's active-space choice), and the OpenQASM circuit for the converged parameters.
maxiter=0 (or, for hardware_efficient, n_layers=0) is a real fast path, not a special case faked up separately: with zero ansatz parameters there's nothing for Adam to optimize, so this returns the bare Hartree-Fock reference circuit and its (real, exact) HF energy immediately -- the "pick a molecule, get a circuit" mechanic the UI uses before committing to a minutes-long optimization.
Requires the optional pennylane extra (used internally to build the
molecular Hamiltonian and Hartree-Fock reference state -- the native
UCCSD ansatz circuits themselves, see dense_evolution.circuits.uccsd,
do not need PennyLane, but Hamiltonian construction still does):
pip install dense-evolution[pennylane].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbols
|
list of str
|
Atomic symbols, e.g. |
required |
geometry
|
list of [float, float, float]
|
Cartesian coordinates in Angstrom, one triplet per atom, same
order as |
required |
charge
|
int
|
Molecular charge. Defaults to 0. |
0
|
ansatz_type
|
str
|
|
'hardware_efficient'
|
n_layers
|
int
|
Ansatz depth ( |
8
|
maxiter
|
int
|
Adam iterations. Defaults to 200. |
200
|
step_size
|
float
|
Adam hyperparameters (learning rate, first/second moment decay). |
0.1
|
beta1
|
float
|
Adam hyperparameters (learning rate, first/second moment decay). |
0.1
|
beta2
|
float
|
Adam hyperparameters (learning rate, first/second moment decay). |
0.1
|
active_electrons
|
int
|
Active-space restriction, forwarded to PennyLane's Hamiltonian builder. Defaults to the molecule's full space. |
None
|
active_orbitals
|
int
|
Active-space restriction, forwarded to PennyLane's Hamiltonian builder. Defaults to the molecule's full space. |
None
|
seed
|
int
|
RNG seed for the initial ansatz parameters. Defaults to 0. |
0
|
Returns:
| Type | Description |
|---|---|
dict
|
|
Examples:
>>> from dashboard_core.vqe import run_vqe
>>> result = run_vqe(
... symbols=["H", "H"],
... geometry=[[0, 0, 0], [0, 0, 0.7414]],
... ansatz_type="hardware_efficient",
... n_layers=4,
... maxiter=200,
... )
>>> round(result["vqe_energy_hartree"], 4)
-1.1373
Source code in tools/dashboard/core/vqe.py
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | |
scan_hardware_efficient_energy_landscape ¶
scan_hardware_efficient_energy_landscape(
symbols,
geometry,
charge,
n_layers,
hf_occupation,
base_params,
param_i,
param_j,
values_i,
values_j,
active_electrons=None,
active_orbitals=None,
)
Real 2D energy-landscape scan around a converged hardware_efficient
VQE result: re-evaluates
hardware_efficient only: UCCSD's parameter space is an affine expansion over full per-gate values (_uccsd_native_expansion), not a direct one-parameter-per-rotation-gate mapping, so "parameter i" doesn't correspond to a single rotation angle the way it does here.
Returns a (len(values_i), len(values_j)) numpy array of energies in Hartree.
Source code in tools/dashboard/core/vqe.py
See also: dashboard_core.hamiltonians
for where the molecular Hamiltonian this ansatz optimizes against comes
from.