# Adiabatic theorem
**The adiabatic theorem** says that a quantum system started in an eigenstate of its Hamiltonian stays in the corresponding eigenstate as the Hamiltonian changes, provided the change is slow enough and the level never touches its neighbours. It is the formal version of an idea that is easy to state and easy to get wrong: go slowly and the system keeps up. What counts as slow is set by the energy gap, and that turns out to be the whole story.
## The statement
Let $H(t)$ have instantaneous eigenstates and eigenvalues
$$H(t)\,\lvert n(t)\rangle = E_n(t)\,\lvert n(t)\rangle \tag{1.1}$$
These are defined pointwise in time: at each instant, freeze the Hamiltonian and diagonalise it. Nothing about $\lvert n(t)\rangle$ requires the system to actually be in that state.
If the system starts in $\lvert\psi(0)\rangle = \lvert n(0)\rangle$ and $H$ varies slowly, then at all later times
$$\lvert\psi(t)\rangle \;\approx\; e^{i\theta_n(t)}\,e^{i\gamma_n(t)}\,\lvert n(t)\rangle$$
with two phases out front and nothing else. The state is still the $n$-th eigenstate, just of a different Hamiltonian than it started with.
The first phase is the **dynamical phase**, the one that would be there even if $H$ never changed:
$$\theta_n(t) = -\frac{1}{\hbar}\int_0^t E_n(t')\,dt'$$
The second is the **geometric** or Berry phase, which depends on the path taken through parameter space and not on how long the trip took:
$$\gamma_n(t) = i\int_0^t \big\langle n(t') \big\rvert \partial_{t'} n(t')\big\rangle\,dt'$$
## What "slowly" means
Slowly compared to what is the only question worth asking, and the answer is not "compared to the total run time". Expand the state in the instantaneous basis, $\lvert\psi\rangle = \sum_n c_n e^{i\theta_n}e^{i\gamma_n}\lvert n\rangle$, feed it to the Schrödinger equation, and the coefficients obey
$$\dot c_m = -\sum_{n \neq m} c_n \,\big\langle m \big\rvert \partial_t n \big\rangle\, e^{i(\theta_n - \theta_m)}e^{i(\gamma_n - \gamma_m)}$$
The leakage out of level $m$ is controlled entirely by $\langle m \rvert \partial_t n\rangle$, and differentiating the eigenvalue equation turns that into something measurable:
$$\big\langle m \big\rvert \partial_t n \big\rangle = \frac{\big\langle m \big\rvert \partial_t H \big\rvert n \big\rangle}{E_n - E_m}, \qquad m \neq n$$
There is the gap, in the denominator, where it stays for the rest of the subject. The standard adiabatic condition follows:
$$\hbar\,\frac{\big| \big\langle m \big\rvert \partial_t H \big\rvert n \big\rangle \big|}{\big(E_m - E_n\big)^2} \;\ll\; 1$$
Note the **square**. Halving the gap does not double the time needed, it quadruples it. This single fact is why gap estimates dominate every practical discussion of adiabatic methods, and why a problem with an exponentially small gap is not slow but hopeless.
\documentclass[border=4pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}[line cap=round, line join=round, >=Latex, scale=1.0]
\draw[->, gray!60] (-2.6,0) -- (2.9,0) node[right, black] {$t$};
\draw[->, gray!60] (0,-2.1) -- (0,2.2) node[above, black] {$E$};
% diabatic states: the levels that would cross
\draw[gray!55, dashed, thick] (-2.4,-1.9) -- (2.4,1.9);
\draw[gray!55, dashed, thick] (-2.4,1.9) -- (2.4,-1.9);
% adiabatic branches: sqrt((vt)^2 + D^2), never touching
\draw[blue!65!black, very thick]
plot[domain=-2.4:2.4, samples=80] (\x, {sqrt(0.62*\x*\x + 0.16)});
\draw[orange!85!black, very thick]
plot[domain=-2.4:2.4, samples=80] (\x, {-sqrt(0.62*\x*\x + 0.16)});
% the gap
\draw[<->, black, thick] (0,0.4) -- (0,-0.4);
\node[right=2pt] at (0,0) {\small $\Delta_{\min}$};
\node[blue!65!black] at (2.05,1.35) {\small $E_1$};
\node[orange!85!black] at (2.05,-1.35) {\small $E_0$};
\node[gray!50!black, font=\scriptsize] at (-1.75,0.42) {diabatic};
\end{tikzpicture}
\end{document}
The dashed lines are the states that would have crossed. The solid ones are the true eigenvalues, which repel and leave a gap of $\Delta_{\min}$. Adiabatic evolution is the claim that a system on the lower solid branch stays on it, going in one side and coming out the other having quietly swapped its character.
## Watching it fail
The cleanest model is two levels sweeping through an avoided crossing:
$$H(t) = \begin{pmatrix} v t & \Delta \\ \Delta & -v t \end{pmatrix}, \qquad E_\pm(t) = \pm\sqrt{v^2t^2 + \Delta^2}$$
The gap is smallest at $t = 0$, where it equals $2\Delta$, and the sweep rate $v$ is what the system is being asked to keep up with. Below, the left panel is the spectrum with the state's position on it, and the right panel is the overlap $|\langle 0(t) \lvert \psi(t)\rangle|^2$ with the instantaneous ground state. The Schrödinger equation is integrated live rather than being drawn from a formula.
// Two level sweep through an avoided crossing, integrated directly:
// i dc/dt = H c, H = [[v t, D], [D, -v t]], hbar = 1
const D = 0.55; // half the minimum gap
let v = 1.6; // sweep rate
let t, cr, ci, trace;
function reset() {
t = -6;
// start in the ground state at t = -6, which is nearly (0, 1)
const E = -sqrt(v * v * t * t + D * D);
let a = D, b = E - v * t;
const nrm = sqrt(a * a + b * b);
cr = [a / nrm, b / nrm];
ci = [0, 0];
trace = [];
}
function setup() {
createCanvas(sketchWidth, sketchHeight);
textFont('monospace', 10);
reset();
}
// one Euler step of i dc/dt = H c, i.e. dc/dt = -i H c
function step(dt) {
const h11 = v * t, h22 = -v * t, h12 = D;
const dr = [ h11 * ci[0] + h12 * ci[1], h12 * ci[0] + h22 * ci[1] ];
const di = [-h11 * cr[0] - h12 * cr[1], -h12 * cr[0] - h22 * cr[1] ];
for (let k = 0; k < 2; k++) { cr[k] += dr[k] * dt; ci[k] += di[k] * dt; }
// Euler does not conserve the norm, and over eight thousand steps that
// shows. Projecting back onto the unit sphere each step costs nothing and
// keeps the probabilities meaning what they say.
const n = sqrt(cr[0] * cr[0] + ci[0] * ci[0] + cr[1] * cr[1] + ci[1] * ci[1]);
for (let k = 0; k < 2; k++) { cr[k] /= n; ci[k] /= n; }
t += dt;
}
// overlap with the instantaneous ground state
function groundOverlap() {
const E = -sqrt(v * v * t * t + D * D);
let a = D, b = E - v * t;
const nrm = sqrt(a * a + b * b);
a /= nrm; b /= nrm;
const re = a * cr[0] + b * cr[1];
const im = a * ci[0] + b * ci[1];
return re * re + im * im;
}
function draw() {
background(252);
for (let i = 0; i < 40; i++) if (t < 6) step(0.0015);
const p = groundOverlap();
if (t < 6) trace.push([t, p]);
// left: the spectrum, with the state riding the lower branch
push();
translate(width * 0.26, height * 0.46);
stroke(210); line(-95, 0, 95, 0); line(0, -85, 0, 85);
noFill();
stroke(150); strokeWeight(1);
line(-95, -85, 95, 85); line(-95, 85, 95, -85);
strokeWeight(2);
stroke(70, 120, 210);
beginShape();
for (let x = -95; x <= 95; x += 2) {
const tt = x / 16;
vertex(x, -sqrt(v * v * tt * tt + D * D) * 12);
}
endShape();
stroke(235, 130, 50);
beginShape();
for (let x = -95; x <= 95; x += 2) {
const tt = x / 16;
vertex(x, sqrt(v * v * tt * tt + D * D) * 12);
}
endShape();
const cx = constrain(t * 16, -95, 95);
noStroke(); fill(20);
circle(cx, sqrt(v * v * t * t + D * D) * 12, 7);
fill(60); text('spectrum', -30, 105);
pop();
// right: how much of the instantaneous ground state survives
push();
translate(width * 0.62, height * 0.46);
stroke(210); noFill();
rect(0, -85, 150, 170);
stroke(150); line(0, -85, 150, -85);
noFill(); stroke(30, 150, 110); strokeWeight(2);
beginShape();
for (const [tt, pp] of trace) vertex((tt + 6) * 12.5, 85 - pp * 170);
endShape();
noStroke(); fill(60);
text('ground state overlap', 0, 105);
text('1.0', -22, -80);
text('0.0', -22, 88);
text('P = ' + nf(p, 1, 3), 100, -70);
text('v = ' + nf(v, 1, 2), 100, -55);
pop();
if (t >= 6) { v = v > 4 ? 0.4 : v * 1.9; reset(); }
}
Each pass raises the sweep rate and then starts over, and the reset button takes it back to the slowest pass. At small $v$ the green curve dips at the crossing and comes back to one. At large $v$ it dips and stays down: the system went straight through, keeping its old character rather than its old energy level, and the run has failed.
## Landau and Zener put a number on it
For this model the leaked probability is known exactly and in closed form, which is unusual and useful. The probability of **not** following the adiabatic branch is
$$P_{\text{diabatic}} = \exp\!\left(-\frac{\pi\,\Delta_{\min}^2}{2\hbar\,\alpha}\right)$$
where $\Delta_{\min}$ is the minimum gap and $\alpha$ is the rate at which the two diabatic levels separate. The shape of that expression is the practical content of the whole theorem:
\documentclass[border=4pt]{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
width=8.4cm, height=5.4cm,
xlabel={sweep rate $\alpha$ (gap$^2$ units)},
ylabel={$P_{\text{adiabatic}}$},
domain=0.02:6, samples=180,
ymin=0, ymax=1.05, xmin=0, xmax=6,
grid=major, grid style={gray!22},
legend pos=south west, legend style={font=\small, draw=gray!40},
tick label style={font=\small}, label style={font=\small},
]
\addplot[blue!65!black, very thick] {1 - exp(-pi/(2*x))};
\addlegendentry{$1-e^{-\pi/2\alpha}$}
\addplot[orange!85!black, dashed, thick] coordinates {(0.02,0.5) (6,0.5)};
\addlegendentry{coin flip}
\end{axis}
\end{tikzpicture}
\end{document}
The exponential is the point. Success is not linear in patience: below a threshold set by the gap you get essentially perfect transfer, and above it you fall off a cliff. Doubling the run time of a failing schedule usually does nothing at all.
## Following a field
The oldest version of the theorem is a spin in a magnetic field that slowly changes direction. The spin precesses about $\vec B$ at the Larmor frequency, and if $\vec B$ turns much more slowly than that, the spin's cone of precession is dragged along with it.
Both panels below start with the spin aligned to the field. Only the rotation rate differs. The right panel wanders further the longer it runs, so this one carries a reset button as well: it reloads the sketch and puts both spins back on the field.
// Bloch vector precessing about a field that rotates about z:
// dr/dt = B x r
// |B| = 1, so the Larmor rate is 1 and the only question is how that
// compares with the rate the field itself turns at.
const tilt = 0.85;
const SLOW = 0.05, FAST = 1.5;
let slow, fast, T = 0;
function setup() {
createCanvas(sketchWidth, sketchHeight);
textFont('monospace', 10);
slow = [sin(tilt), 0, cos(tilt)];
fast = [sin(tilt), 0, cos(tilt)];
}
function field(a) {
return [sin(tilt) * cos(a), sin(tilt) * sin(a), cos(tilt)];
}
function precess(r, B, dt) {
const c = [B[1] * r[2] - B[2] * r[1],
B[2] * r[0] - B[0] * r[2],
B[0] * r[1] - B[1] * r[0]];
for (let k = 0; k < 3; k++) r[k] += c[k] * dt;
const n = sqrt(r[0] * r[0] + r[1] * r[1] + r[2] * r[2]);
for (let k = 0; k < 3; k++) r[k] /= n;
}
// a flat drawing of a sphere: x to the right, z up, y into the page
function project(p, s) {
return [p[0] * s + p[1] * s * 0.42, -p[2] * s + p[1] * s * 0.22];
}
function panel(cx, label, r, rate) {
const s = 74;
push();
translate(cx, height * 0.47);
noFill(); stroke(205);
circle(0, 0, s * 2);
ellipse(0, 0, s * 2, s * 0.9);
stroke(225); line(0, -s, 0, s);
const B = field(rate * T);
const bp = project(B, s), rp = project(r, s);
strokeWeight(2); stroke(120, 130, 150);
line(0, 0, bp[0], bp[1]);
noStroke(); fill(120, 130, 150);
circle(bp[0], bp[1], 8);
strokeWeight(2.5); stroke(235, 120, 50);
line(0, 0, rp[0], rp[1]);
noStroke(); fill(235, 120, 50);
circle(rp[0], rp[1], 9);
const dot = B[0] * r[0] + B[1] * r[1] + B[2] * r[2];
fill(60);
text(label, -40, s + 26);
text('B . r = ' + nf(dot, 1, 3), -40, s + 40);
pop();
}
function draw() {
background(252);
for (let i = 0; i < 25; i++) {
precess(slow, field(SLOW * T), 0.02);
precess(fast, field(FAST * T), 0.02);
T += 0.02;
}
panel(width * 0.27, 'slow: follows', slow, SLOW);
panel(width * 0.73, 'fast: left behind', fast, FAST);
}
The grey vector is the field and the orange one is the spin. On the left, $\vec B \cdot \vec r$ stays pinned near one: the spin is still aligned, which is the adiabatic theorem doing its job. On the right the alignment wanders over the whole range, because the field moved out from under the precession before it could be dragged.
## The geometric phase
The dynamical phase is unsurprising: it accumulates energy times time. The geometric phase is the interesting one, because it survives the limit of infinitely slow evolution. Take the parameters around a **closed loop** and the dynamical phase depends on how long you dawdled, while
$$\gamma_n = i\oint_{\mathcal C} \big\langle n(\vec R) \big\rvert \nabla_{\vec R} n(\vec R)\big\rangle \cdot d\vec R$$
does not. It depends on the loop and nothing else. For a spin one-half in a field of fixed magnitude, the answer is famously just geometry:
$$\gamma_\pm = \mp\tfrac{1}{2}\,\Omega$$
with $\Omega$ the solid angle the field's direction traced out on the sphere. This is the same bundle geometry as the [[wiki:hopf-fibration|Hopf fibration]]: the loop lives in the base, the phase lives in the fiber, and the connection is what relates them.
\documentclass[border=4pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}[line cap=round, line join=round, >=Latex, scale=1.5]
\draw[gray!45] (0,0) circle (1);
\draw[gray!35] (0,0) ellipse (1 and 0.34);
% a closed loop of field directions, and the cap it subtends
\fill[blue!55!black, opacity=0.16]
plot[domain=0:360, samples=60] ({0.62*cos(\x)}, {0.55 + 0.21*sin(\x)});
\draw[blue!65!black, very thick]
plot[domain=0:360, samples=60] ({0.62*cos(\x)}, {0.55 + 0.21*sin(\x)});
\draw[->, orange!85!black, very thick] (0,0) -- (0.62,0.76);
\node[orange!85!black, font=\small] at (1.02,0.86) {$\vec B(t)$};
\node[blue!65!black, font=\small] at (0,0.55) {$\Omega$};
\node[gray!50!black, font=\scriptsize] at (0,-1.28) {$\gamma_\pm=\mp\Omega/2$};
\end{tikzpicture}
\end{document}
// The field traces a closed loop; the phase accumulated is half the
// solid angle enclosed, and does not care how fast the loop is walked.
let a = 0;
const tilt = 0.7;
function setup() {
createCanvas(sketchWidth, sketchHeight, WEBGL);
textFont('monospace', 11);
}
function dir(u) {
return [sin(tilt) * cos(u), sin(tilt) * sin(u), cos(tilt)];
}
function draw() {
background(20, 22, 28);
orbitControl(1, 1, 0);
rotateX(-0.5);
rotateZ(0.5);
const R = 95;
a += 0.012;
if (a > TWO_PI) a = 0;
noFill();
stroke(90, 100, 120);
strokeWeight(1);
for (let k = 0; k < 3; k++) {
push();
if (k === 1) rotateX(HALF_PI);
if (k === 2) rotateY(HALF_PI);
circle(0, 0, R * 2);
pop();
}
// the loop, drawn only as far as it has been walked
stroke(90, 170, 255);
strokeWeight(3);
beginShape();
for (let u = 0; u <= a; u += 0.05) {
const d = dir(u);
vertex(d[0] * R, d[1] * R, d[2] * R);
}
endShape();
const d = dir(a);
stroke(255, 160, 60);
strokeWeight(3);
line(0, 0, 0, d[0] * R, d[1] * R, d[2] * R);
}
function mouseDragged() {
if (!isLooping()) redraw();
}
## Adiabatic quantum computation
The theorem stops being a curiosity about slow spins the moment someone notices it is a computational model. Encode a problem so that its answer is the ground state of a Hamiltonian $H_1$ nobody knows how to prepare, start instead in the easy ground state of some $H_0$, and interpolate:
$$H(s) = (1-s)\,H_0 + s\,H_1, \qquad s = t/T \in [0,1]$$
Prepare the ground state of $H_0$, run $s$ from $0$ to $1$ slowly enough, and the adiabatic theorem hands over the ground state of $H_1$, which is the answer. This is **equivalent in power to the circuit model**, not a lesser relative of it, which is not obvious and was not proved until 2004.
The catch is the same square as before. The run time is set by the smallest gap encountered anywhere along the path:
$$T \;\gtrsim\; \frac{\max_s \big| \big\langle 1(s) \big\rvert \partial_s H \big\rvert 0(s)\big\rangle \big|}{\min_s\, g(s)^2}, \qquad g(s) = E_1(s) - E_0(s)$$
So the entire difficulty of the model is pushed into one question, and it is a question about the spectrum rather than about the algorithm:
\documentclass[border=4pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
width=8.6cm, height=5cm,
xlabel={$s$}, ylabel={gap $g(s)$},
domain=0:1, samples=200,
ymin=0, ymax=1.15, xmin=0, xmax=1,
grid=major, grid style={gray!22},
legend style={font=\small, draw=gray!40, at={(0.5,1.28)}, anchor=north},
legend columns=2,
tick label style={font=\small}, label style={font=\small},
]
\addplot[blue!65!black, very thick] {0.25 + 0.75*abs(2*x-1)};
\addlegendentry{benign: polynomial gap}
\addplot[red!75!black, very thick] {0.02 + 1.0*(2*x-1)^2};
\addlegendentry{hard: gap closes}
\end{axis}
\end{tikzpicture}
\end{document}
A gap that shrinks polynomially in the problem size gives a polynomial run time. A gap that shrinks exponentially gives an exponential one, and no amount of engineering rescues it. Proving which case a given problem falls into is, in general, exactly as hard as the problem.
**Quantum annealing** is the practical cousin: the same interpolation, run on hardware, at finite temperature, faster than the theorem strictly allows, and judged on whether the answers are good rather than on whether the premises hold. The adiabatic theorem is where its intuition comes from, not a description of what it does.
## When the theorem does not apply
Worth knowing, because each of these breaks it in a different way.
^ Situation ^ What goes wrong ^
| Level crossing, $g \to 0$ | the condition diverges; no speed is slow enough |
| Degenerate ground state | "the" eigenstate is not well defined; needs the degenerate version |
| Gap closing exponentially in system size | formally fine, practically hopeless |
| Continuous spectrum | no isolated level to follow |
| Open system, coupling to a bath | thermal excitation out of the ground state ignores how slowly you went |
| Resonant driving at the gap frequency | slow in amplitude, not slow in effect |
The first row deserves emphasis. The theorem does not say that slow evolution is safe. It says that slow evolution is safe **when the level stays isolated**, and the whole practical art is in knowing whether it does.
## See also
- [[wiki:schrodinger-equation]]
- [[wiki:eigenstate]]
- [[wiki:hopf-fibration]]
- [[wiki:bloch-sphere]]
- [[wiki:global-phase]]