Sari la conținutul principal
Acest proiect este în versiune beta. Ai găsit o eroare? Deschide un issue pe GitHub. Ai o întrebare sau o idee? Întreabă în Discussions — ne-ar plăcea să aflăm părerea ta!
Cum este calitatea traducerii pe această pagină?

Scalează fluxurile de lucru de chimie SQD cu Fulqrum

Fulqrum este un pachet software care calculează valorile proprii și vectorii proprii ai Hamiltonienilor proiectați într-un subspațiu. El construiește o reprezentare portabilă a Hamiltonianului proiectat, pe care o poți transmite unui solver de valori proprii la alegere, inclusiv solvere standard disponibile gata făcute. Aceste solvere pot oferi o alternativă mult mai rapidă la solverul PySCF implicit pe care addon-ul SQD îl folosește pentru diagonalizare. Pentru informații despre cum se instalează și se folosește Fulqrum, vezi documentația Fulqrum.

Modulul addon_sqd_support al Fulqrum construiește un solver pe care diagonalize_fermionic_hamiltonian îl acceptă direct, astfel încât transmiți aceleași integrale ambelor, iar Fulqrum se ocupă de proiecție și diagonalizare.

Pentru mai multe detalii despre codul SQD folosit în acest exemplu, vezi tutorialul despre Hamiltonianul chimic.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"fulqrum": "fulqrum", "numpy": "numpy", "primme": "primme", "pyscf": "pyscf", "qiskit_addon_sqd": "qiskit-addon-sqd"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import numpy as np
import pyscf
import pyscf.cc
import pyscf.mcscf
from fulqrum.addon_sqd_support import sci_solver_from_integrals
from qiskit_addon_sqd.counts import generate_bit_array_uniform
from qiskit_addon_sqd.fermion import diagonalize_fermionic_hamiltonian

# Build N2 molecule
mol = pyscf.gto.Mole()
mol.build(
atom=[["N", (0, 0, 0)], ["N", (1.0, 0, 0)]],
basis="6-31g",
symmetry="Dooh",
)

# Define active space
n_frozen = 2
active_space = range(n_frozen, mol.nao_nr())

# Get molecular integrals
scf = pyscf.scf.RHF(mol).run()
num_orbitals = len(active_space)
n_electrons = int(sum(scf.mo_occ[active_space]))
num_elec_a = (n_electrons + mol.spin) // 2
num_elec_b = (n_electrons - mol.spin) // 2
cas = pyscf.mcscf.CASCI(scf, num_orbitals, (num_elec_a, num_elec_b))
mo = cas.sort_mo(active_space, base=0)
hcore, nuclear_repulsion_energy = cas.get_h1cas(mo)
eri = pyscf.ao2mo.restore(1, cas.get_h2cas(mo), num_orbitals)

# Compute exact energy
exact_energy = cas.run().e_tot

# Create a seed to control randomness throughout this workflow
rng = np.random.default_rng(24)

# Generate random samples
bit_array = generate_bit_array_uniform(
10_000, num_orbitals * 2, rand_seed=rng
)

# Build a solver that diagonalizes with Fulqrum. It converts the integrals to a
# Fulqrum operator once, then projects onto each subspace the SQD loop requests.
sci_solver = sci_solver_from_integrals(hcore, eri, tol=1e-12)

# Run SQD
result = diagonalize_fermionic_hamiltonian(
hcore,
eri,
bit_array,
samples_per_batch=300,
norb=num_orbitals,
nelec=(num_elec_a, num_elec_b),
num_batches=5,
max_iterations=5,
sci_solver=sci_solver,
symmetrize_spin=True,
seed=rng,
)
WARN: Unable to to identify input symmetry using original axes.
Different symmetry axes will be used.
converged SCF energy = -108.835236570774
CASCI E = -109.046671778080 E(CI) = -32.8155692383188 S^2 = 0.0000000
print(f"Exact energy: {exact_energy}")
print(f"Estimated energy: {result.energy + nuclear_repulsion_energy}")
Exact energy: -109.04667177808024
Estimated energy: -109.03402667559365

Folosește un alt solver de stări proprii​

Deoarece Fulqrum expune Hamiltonianul proiectat ca un scipy.sparse.linalg.LinearOperator standard, îl poți diagonaliza cu orice solver de stări proprii la alegere, fără a fi legat de scipy.sparse.linalg.eigsh. Astfel este simplu să înlocuiești solverul cu unul mai potrivit pentru dimensiunea problemei sau pentru hardware-ul tău.

Transmite solverul de stări proprii dorit ca argument eigensolver. Ca exemplu, acest ghid demonstrează PRIMME, o bibliotecă de solvere de stări proprii de înaltă performanță. Interfața sa Python, primme.eigsh, urmează o convenție de apelare similară cu scipy.sparse.linalg.eigsh, deci o poți folosi ca înlocuitor direct.

import primme

# Build a solver that diagonalizes with PRIMME instead of the default,
# scipy.sparse.linalg.eigsh
sci_solver = sci_solver_from_integrals(
hcore, eri, eigensolver=primme.eigsh, tol=1e-12
)

# Run SQD using the PRIMME-based solver
result = diagonalize_fermionic_hamiltonian(
hcore,
eri,
bit_array,
samples_per_batch=300,
norb=num_orbitals,
nelec=(num_elec_a, num_elec_b),
num_batches=5,
max_iterations=5,
sci_solver=sci_solver,
symmetrize_spin=True,
seed=rng,
)
print(f"Exact energy: {exact_energy}")
print(f"Estimated energy: {result.energy + nuclear_repulsion_energy}")
Exact energy: -109.04667177808024
Estimated energy: -109.03937429196168