The Machinery · Topic 26 of 41 · The Workbench: before the tools

The harmonic oscillator and Fock space

How can a computer hold an oscillator that has infinitely many levels, and how do you know where to cut it off?

  1. 01
  2. 02
  3. 03
  4. 04
  5. 05
  6. 06
  7. 07
  8. 08
  9. 09
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
About this section: The Workbench: before the tools

Everything above is mathematics you can do on paper. This part is the other half: what a researcher does on a computer to see how a superconducting qubit behaves. Two free programs do most of it, QuTiP for how a system changes in time and scqubits for the levels of a circuit, and both are taught here from the beginning. This first group builds what they are made of: a state as a list of numbers, the one equation that moves it, and the oscillator that a resonator is. Every number in the part was produced by QuTiP 5.2.0 or scqubits 4.3.1, every example prints what the page says it prints, and each topic has an explorer you can move; all of them are on one page, the Workbench. If you only want to install the programs, start at topic 33.

See it

012345 a† a equal rungs: ħω apart the cutoff: the computer stops cutoff the chance of each rung, an average of 4 photons the tail the cutoff discards n = 0 1 2 3 4 5 6 7 | 8 9 10 11 …
An oscillator is a ladder with no top, and a computer has to cut it somewhere. The operator a† climbs one rung and a descends one. A strong drive spreads the state over many rungs, and anything above the cutoff (violet) is lost.

Try it: move the cutoff until the answer stops changing

Set the strength of a drive on a resonator (the average number of photons it puts in) and the number of levels the computer keeps. The bars show the chance of each level in the truncated space, the dots the exact answer. The readout shows how far the truncated average photon number is from the true one, and the last entry of the commutator.

Honest limits: the state is built the way QuTiP builds it, as the displacement operator acting on the vacuum inside the truncated space. A different recipe (cutting the exact amplitudes and renormalising) gives slightly different numbers below the converged cutoff; both agree once the cutoff is big enough, which is the point.

The intuition

A resonator on a chip, the coil-and-capacitor circuit of the circuits lesson, is a quantum harmonic oscillator: a ladder of energy levels, each rung the same distance ħω above the last, with no top. Its quantum state is a list of amplitudes, one for each rung, and a classical microwave tone shining on it makes a particular spread over the rungs called a coherent state. Every readout resonator, every bus resonator and every cavity in the hardware is one of these, and a transmon is a ladder with the rungs squeezed slightly closer as you climb.

Two operators run the ladder. The lowering operator a moves the state down one rung (and gives zero from the bottom rung); the raising operator a† moves it up. Their product a†a simply reads off the rung number, which is why it is called the number operator. Everything in a circuit simulation is built from these.

A computer cannot keep an infinite ladder. It keeps the first N rungs, numbered 0 to N−1, and pretends nothing is above. That is fine if the state barely reaches the top of what you kept, and wrong if it does. The cut is not harmless: the identity that defines the ladder (aa† − a†a = 1) fails at exactly one place, the top rung, where the truncated matrices give 1 − N instead of 1. A state that reaches that rung feels a wall that is not in the physics.

How to choose N, honestly. You do not look it up. You raise N until the numbers you care about stop changing and then add a margin. For a coherent state the number of photons follows a Poisson law, with average n̄ and spread √n̄, so a first guess is N ≈ n̄ + 5√n̄ + a few. For the average of 4 photons in the explorer that is about 14 to 15, and the table below shows the answer settling there. A drive that is stronger than you think, or a nonlinearity that pushes the state up the ladder, moves the guess. The right test is always to run twice.

The mathematics

The oscillator. H = ħω(a†a + ½), with a|n⟩ = √n |n−1⟩ and a†|n⟩ = √(n+1) |n+1⟩, so that a†a|n⟩ = n|n⟩ and [a, a†] = 1. For an electrical circuit of inductance L and capacitance C, ω = 1/√(LC), and the flux and charge are Φ = Φzpf(a + a†) and Q = i Qzpf(a† − a), where Φzpf = √(ħZ/2), Qzpf = √(ħ/2Z) and Z = √(L/C) is the circuit’s impedance. The subscript means “zero-point fluctuation”: even in the ground state the flux and charge are not exactly zero.

The truncation. In the first N levels a is the N × N matrix with √1, √2, … √(N−1) on the superdiagonal. Then

a a† − a† a = diag(1, 1, …, 1, 1 − N)

For N = 10 the last entry is −9. It is a property of the cut, not of the oscillator.

The coherent state. In the full space |α⟩ = e−|α|²/2 Σn (αn/√n!) |n⟩, so the chance of rung n is the Poisson law

P(n) = e−|α|² |α|2n / n!, ⟨n⟩ = |α|², Δn = |α|

With α = 2 the average is 4 and the chance of being at or above rung N is 5.1 × 10−2 for N = 8, 9.2 × 10−4 for N = 12 and 2.0 × 10−5 for N = 15. In a truncated space QuTiP builds the state as D(α)|0⟩ with D(α) = exp(α a† − α* a) computed from the truncated matrices, which keeps the norm at exactly 1 and changes the average photon number. The values for α = 2 are 3.5919 at N = 6, 3.9894 at N = 10, 4.0000 at N = 15 and 4.0000 at N = 20 against the exact 4. The error is 10% with 6 rungs, 0.3% with 10 and below 10−4 with 15.

Try it in Python. destroy(N) is the lowering operator in an N-level space, coherent builds the state and expect averages an operator over it. Run on QuTiP 5.2.0, 25 October 2026:

import numpy as np
import qutip as qt

N = 10                                           # keep ten Fock states: |0> ... |9>
a = qt.destroy(N)
print(a * qt.basis(N, 3) == np.sqrt(3) * qt.basis(N, 2))     # a|3> = sqrt(3)|2>

comm = a * a.dag() - a.dag() * a                 # on a real oscillator this is exactly the identity
print(np.diag(comm.full()).real)                 # but the last diagonal entry is 1 - N

# a coherent state of amplitude 2 has <n> = 4 in the full space; what does the cutoff do to it?
for N in (6, 10, 15, 20):
    psi = qt.coherent(N, 2.0)
    print(N, round(qt.expect(qt.num(N), psi), 4))
True
[ 1.  1.  1.  1.  1.  1.  1.  1.  1. -9.]
6 3.5919
10 3.9894
15 4.0
20 4.0

Where it actually matters

Readout resonators, and the first reason a simulation goes quietly wrong Dispersive readout (topic 31) fills a resonator with a few photons, and a simulation of it needs a cutoff comfortably above that. The same rule applies to the transmon itself, which a program keeps to three to five levels: the third and higher levels are what make a qubit leak out of its two-level space. The failure to learn is the silent one. A cutoff that is too small does not raise an error; it returns a smooth, plausible, wrong curve. The habit that catches it is to run every simulation at two cutoffs and compare, which the explorer above makes visible and which the verifier behind this page does for every example.