Der Variational Quantum Eigensolver (VQE) ist einer der wichtigsten Quantenalgorithmen für die nahe Zukunft. Er findet die Grundzustandsenergie eines Moleküls oder Materials — eine Berechnung, die für klassische Computer exponentiell schwierig, auf NISQ-Geräten aber handhabbar ist. Dieser Leitfaden führt durch eine vollständige VQE-Implementierung in PennyLane.
Was VQE macht
VQE findet den kleinsten Eigenwert eines Hamiltonians H (der üblicherweise die Energie eines Moleküls repräsentiert). Es funktioniert so:
- Vorbereiten eines parametrisierten Testzustands |ψ(θ)⟩ mit einer Quantenschaltung
- Messen des Erwartungswerts ⟨ψ(θ)|H|ψ(θ)⟩ auf der QPU
- Verwenden eines klassischen Optimierers, um θ zu aktualisieren und die Energie zu minimieren
- Wiederholen bis zur Konvergenz
Das Variationsprinzip garantiert ⟨ψ(θ)|H|ψ(θ)⟩ ≥ E₀ für jeden Zustand — daher liefert die Minimierung dieser Größe eine obere Schranke für die wahre Grundzustandsenergie E₀.
Einrichtung
Installiere PennyLane mit seinem Chemie-Plugin:
pip install pennylane pennylane-qchem
Für das Wasserstoffmolekül (H₂) — den klassischen VQE-Benchmark — benötigen wir zwei Elektronen und vier Spin-Orbitale (4 Qubits):
import pennylane as qml
from pennylane import numpy as np
import pennylane.qchem as qchem
# H2 at equilibrium bond length (Angstrom)
symbols = ["H", "H"]
coordinates = np.array([[0.0, 0.0, -0.6614], [0.0, 0.0, 0.6614]])
# Build the qubit Hamiltonian
H, qubits = qchem.molecular_hamiltonian(
symbols,
coordinates,
basis="sto-3g"
)
print(f"Hamiltonian: {len(H.ops)} terms, {qubits} qubits")
# Hamiltonian: 15 terms, 4 qubits
Den Ansatz definieren
Der Ansatz ist die parametrisierte Schaltung, die den Testzustand vorbereitet. Für Chemieprobleme ist der UCCSD-Ansatz (Unitary Coupled-Cluster Singles and Doubles) der Standard:
# Get UCCSD circuit parameters
electrons = 2
singles, doubles = qchem.excitations(electrons, qubits)
s_wires, d_wires = qchem.excitations_to_wires(singles, doubles, wires=range(qubits))
# Initial Hartree-Fock state (reference state)
hf_state = qchem.hf_state(electrons, qubits)
dev = qml.device("default.qubit", wires=qubits)
@qml.qnode(dev)
def circuit(weights, wires, s_wires=[], d_wires=[], hf_state=hf_state):
# Prepare HF reference state
qml.BasisState(hf_state, wires=wires)
# Apply UCCSD excitations
qml.UCCSD(weights, wires, s_wires=s_wires, d_wires=d_wires, init_state=hf_state)
return qml.expval(H)
Die VQE-Optimierung ausführen
Mit der automatischen Differenzierung von PennyLane können wir gradientenbasierte Optimierer direkt verwenden:
# Initial parameters (all zeros = Hartree-Fock state)
init_params = np.zeros(len(singles) + len(doubles), requires_grad=True)
# Adam optimizer (works well for VQE)
opt = qml.AdamOptimizer(stepsize=0.4)
# Optimization loop
energy_history = []
params = init_params.copy()
for step in range(200):
params, energy = opt.step_and_cost(
lambda p: circuit(p, range(qubits), s_wires=s_wires, d_wires=d_wires),
params
)
energy_history.append(energy)
if step % 20 == 0:
print(f"Step {step:3d}: E = {energy:.6f} Ha")
print(f"\nVQE ground state energy: {energy:.6f} Ha")
print(f"Reference (exact): -1.136189 Ha")
Typische Ausgabe:
Step 0: E = -1.117498 Ha
Step 20: E = -1.133254 Ha
Step 40: E = -1.135901 Ha
Step 60: E = -1.136140 Ha
...
VQE ground state energy: -1.136174 Ha
Reference (exact): -1.136189 Ha
VQE erreicht eine Genauigkeit von ~0,015 mHa gegenüber der exakten Energie — chemische Genauigkeit für H₂.
Einen gradientenfreien Optimierer verwenden
Für verrauschte Hardware sind gradientenfreie Optimierer wie COBYLA oder SPSA oft besser, da Hardware-Gradienten verrauscht sind:
from scipy.optimize import minimize
# Objective function (no gradient needed)
def objective(params):
return float(circuit(params, range(qubits), s_wires=s_wires, d_wires=d_wires))
result = minimize(
objective,
x0=init_params,
method="COBYLA",
options={"maxiter": 500, "rhobeg": 0.1}
)
print(f"COBYLA energy: {result.fun:.6f} Ha")
VQE mit HLQuantum ausführen
HLQuantum enthält eine integrierte VQE-Implementierung, die über alle Backends hinweg funktioniert:
import hlquantum as hlq
# Define the Hamiltonian in HLQuantum's format
H = hlq.hamiltonians.h2_molecule(bond_length=1.32)
# Run VQE on any backend
result = hlq.algorithms.vqe(
hamiltonian=H,
ansatz="uccsd",
optimizer="adam",
max_iterations=200,
backend="pennylane", # or "qiskit", "cudaq"
)
print(f"Ground state energy: {result.energy:.6f} Ha")
print(f"Optimal parameters: {result.params}")
print(f"Converged in {result.iterations} iterations")
Tipps für echte Hardware
Beim Ausführen von VQE auf echten QPUs (IBM Quantum, IonQ) gelten mehrere zusätzliche Überlegungen:
Verwende weniger Shots pro Schritt. 1000 Shots pro Optimierungsschritt reichen normalerweise für die Gradientenschätzung aus. Verwende nicht bei jedem Schritt 10.000 Shots — das verschwendet QPU-Zeit.
Beginne mit flachen Schaltungen. Weniger CNOT-Gatter = weniger Rauschen. Erwäge für Hardware hardware-effiziente Ansatz-Schaltungen anstelle von UCCSD.
Aktiviere die Fehlerminderung. Die Option error_mitigation="zne" von HLQuantum wendet Zero Noise Extrapolation an, was die Ergebnisse auf verrauschter Hardware erheblich verbessern kann:
result = hlq.run(vqe_circuit, backend="qiskit", device="ibm_sherbrooke",
error_mitigation="zne", shots=2048)
Sieh dir den vollständigen PennyLane guide und die HLQuantum algorithms reference für weitere Details zu Quantenchemie-Simulationen an.