Simple VQE Demo
Track: Quantum Programming · Difficulty: Beginner–Intermediate · Est: 15 min
Simple VQE Demo
Overview
This page teaches a complete, tiny hybrid workflow:
- choose a very small “Hamiltonian” (an observable we want to minimize)
- build a parameterized circuit (ansatz)
- estimate an expectation value from measurement results
- update parameters using a simple classical loop
It matters because this is the core pattern behind many near-term workflows: classical code proposes circuits, quantum execution provides statistics, classical code updates the next step.
This is a learning demo, not chemistry-grade VQE.
Conceptual Mapping
From the Variational & NISQ module:
- VQE minimizes an energy-like objective by tuning circuit parameters
- the objective is an expectation value of an observable
- evaluation is statistical (shots), not exact
From Foundations + Gates:
- measurement is probabilistic (Born rule)
- expectation values come from many samples
- a single-qubit rotation is a simple example of a parameterized circuit
In code, the mapping is:
- Ansatz → a
QuantumCircuitwith a parameter (like a rotation angle) - Hamiltonian (toy) → a measurement rule that assigns a number to outcomes
- Expectation value → average of those numbers over many shots
- Optimizer (toy) → try a few parameter values and pick the best
Code Walkthrough
We’ll use a 1‑qubit toy Hamiltonian that is “measure Z” (conceptually: prefer one computational basis state over the other).
Idea:
- prepare a 1‑qubit state with a rotation parameter
theta - measure many shots
- map outcomes to values (+1 for
0, −1 for1) - average to estimate the expectation value
import math
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
def estimate_z_expectation(theta, shots=500):
qc = QuantumCircuit(1, 1)
qc.ry(theta, 0)
qc.measure(0, 0)
sim = AerSimulator()
counts = sim.run(qc, shots=shots).result().get_counts()
# Map bit outcomes to Z eigenvalues: 0 -> +1, 1 -> -1
p0 = counts.get('0', 0) / shots
p1 = counts.get('1', 0) / shots
return (+1) * p0 + (-1) * p1
# Toy “optimizer”: try a few angles and keep the best
candidates = [0, math.pi/4, math.pi/2, 3*math.pi/4, math.pi]
best_theta = None
best_value = None
for theta in candidates:
value = estimate_z_expectation(theta)
print(theta, value)
if best_value is None or value < best_value:
best_value = value
best_theta = theta
print("best", best_theta, best_value)Line by line (conceptual):
estimate_z_expectationbuilds a circuit with a parametertheta.ry(theta, 0)is the ansatz: a tunable state preparation.shotsrepeats the experiment to estimate probabilities.countsis a histogram of outcomes.- We convert counts into an expectation value by mapping outcomes to numbers and averaging.
- The “optimizer” is a simple loop that tries a few candidate angles.
Results & Interpretation
What you’re looking for is not a specific number. It’s the workflow behavior:
- different parameters produce different measurement distributions
- those distributions imply different expectation values
- the classical loop can improve the objective by choosing better parameters
How to judge correctness (for a learning demo):
- sanity check 1: results fluctuate a bit if you rerun (shot noise)
- sanity check 2: increasing
shotsmakes estimates more stable - sanity check 3: the “best” parameter should be reasonably consistent across reruns
Connection back to amplitudes:
ry(theta)changes amplitudes of|0⟩and|1⟩- probabilities come from those amplitudes
- expectation is a weighted average of outcome values
This is the key VQE lesson: you rarely compute an exact value; you estimate it from repeated measurements.
Turtle Tip
If your VQE demo feels “noisy,” that’s not a bug—it’s the point. The discipline is learning which randomness is expected (shots) and which indicates a real issue (wrong circuit, wrong mapping, wrong measurement).
Common Pitfalls
- Forgetting the outcome-to-value mapping (e.g., treating counts as the objective directly).
- Using too few shots and thinking the optimizer is “unstable.”
- Changing multiple things at once (ansatz + measurement + candidates) and not knowing what caused an effect.
- Treating this toy as a realistic chemistry workflow; real VQE uses multiple Pauli terms and more careful optimizers.
Quick Check
- In this demo, what is the “ansatz” and what is the tunable parameter?
- Why do we need many shots to estimate an expectation value?
- What does the classical loop do conceptually?
What’s Next
Now you’ve seen an end-to-end hybrid loop. Next we’ll focus on debugging: how to use simulators, intermediate inspection, and sanity checks to understand “wrong” results productively.
