The MZI as a Programmable Unitary

A beamsplitter is a unitary matrix — but a frozen one, its coupling angle cast in silicon the day the wafer was etched. This lesson thaws it. Take the Mach–Zehnder interferometer, give it two phase shifters — one inside the arms, one on an input port — and something remarkable happens: those two knobs sweep out essentially the whole space of 2×2 unitaries. The MZI stops being a component and becomes a programmable matrix: photonics' universal gate, the role the transistor plays in logic and the settable rotation plays in geometry. Every mesh, every photonic neural network, every boson-sampling chip in the remainder of this course is this one object, tiled.

Anatomy: two knobs, four names

The circuit is the familiar MZI with its controls made explicit. By convention the internal phase \theta sits in one arm between the couplers, and the external phase \varphi sits on one input port before the first coupler. (How a phase shifter physically imposes its delay — heat, carriers, or the Pockels effect — was Module 3's story; here they are simply two real numbers we own.)

Intuition before algebra: \theta is the knob you already know — it is the arm-phase difference of the MZI lesson, so it steers how much power crosses. \varphi does something subtler: it acts before the light is mixed, so it cannot move power at this device's own outputs — instead it sets the relative phase between the two output amplitudes, invisible to a photodiode here but decisive the moment those outputs interfere again inside a larger circuit. Amplitude knob and phase knob: between them, a whole complex 2×2 unitary, up to the phases nobody can see.

The derivation: multiply the sandwich out

Write the three fixed pieces in matrix form — 50:50 coupler B, internal phase P_\theta, external phase P_\varphi:

B = \frac{1}{\sqrt 2}\begin{pmatrix} 1 & i \\ i & 1 \end{pmatrix},\qquad P_\theta = \begin{pmatrix} e^{i\theta} & 0 \\ 0 & 1 \end{pmatrix},\qquad P_\varphi = \begin{pmatrix} e^{i\varphi} & 0 \\ 0 & 1 \end{pmatrix}.

The device is the product U = B\,P_\theta\,B\,P_\varphi (rightmost first: light meets \varphi before anything else). Grind the inner sandwich first:

B P_\theta B = \frac{1}{2}\begin{pmatrix} e^{i\theta} - 1 & i\left(e^{i\theta} + 1\right) \\[2pt] i\left(e^{i\theta} + 1\right) & 1 - e^{i\theta} \end{pmatrix} = i e^{i\theta/2}\begin{pmatrix} \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \\[2pt] \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \end{pmatrix},

where the tidy second form uses the half-angle identities e^{i\theta} - 1 = 2i\,e^{i\theta/2}\sin(\theta/2) and e^{i\theta} + 1 = 2\,e^{i\theta/2}\cos(\theta/2) — the same factoring trick that tamed the MZI's transfer function, now applied to the whole matrix. Appending the external phase gives the object this module is built on:

Sanity-check against the last module: at \varphi = 0,\ \theta = 0 the matrix is (up to the global i) the pure swap — all light crosses, exactly the MZI lesson's P_{\text{cross}} = \cos^2(\theta/2) = 1. At \theta = \pi it is diagonal — all bar. The old one-knob transfer function was this matrix's first row, seen through a photodiode.

Worked example: three settings worth memorising

The swap (\theta = 0): U \propto \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} — the MZI vanishes into a waveguide crossing. The identity-with-attitude (\theta = \pi): U \propto \begin{pmatrix} e^{i\varphi} & 0 \\ 0 & -1 \end{pmatrix} — the ports don't mix at all, and the surviving job is \varphi's: a pure, settable phase on one rail. The balanced mixer (\theta = \pi/2):

U\!\left(\tfrac{\pi}{2}, \varphi\right) = \frac{i e^{i\pi/4}}{\sqrt 2}\begin{pmatrix} e^{i\varphi} & 1 \\ e^{i\varphi} & -1 \end{pmatrix} \;\xrightarrow{\;\varphi = \pi/2\;}\; \frac{i e^{i\pi/4}}{\sqrt 2}\begin{pmatrix} i & 1 \\ i & -1 \end{pmatrix},

a 50:50 mixer whose input-side phase you dial at will — the "beamsplitter with a phase trim" that the Reck and Clements constructions will request thousands of times. Run the whole family yourself; the program builds U(\theta,\varphi) numerically, confirms it is unitary at machine precision, and demonstrates the division of labour between the knobs — change \varphi and watch the magnitudes refuse to move:

type C = { re: number; im: number }; const c = (re: number, im = 0): C => ({ re, im }); const add = (a: C, b: C): C => c(a.re + b.re, a.im + b.im); const mul = (a: C, b: C): C => c(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re); const expi = (x: number): C => c(Math.cos(x), Math.sin(x)); const mag = (a: C): number => Math.hypot(a.re, a.im); type M = C[][]; const matmul = (p: M, q: M): M => [ [add(mul(p[0][0], q[0][0]), mul(p[0][1], q[1][0])), add(mul(p[0][0], q[0][1]), mul(p[0][1], q[1][1]))], [add(mul(p[1][0], q[0][0]), mul(p[1][1], q[1][0])), add(mul(p[1][0], q[0][1]), mul(p[1][1], q[1][1]))], ]; const s = 1 / Math.sqrt(2); const B: M = [ [c(s), c(0, s)], [c(0, s), c(s)] ]; const phaseTop = (x: number): M => [ [expi(x), c(0)], [c(0), c(1)] ]; // U(theta, phi) = B · P_theta · B · P_phi const mzi = (theta: number, phi: number): M => matmul(matmul(B, phaseTop(theta)), matmul(B, phaseTop(phi))); function show(thetaDeg: number, phiDeg: number): void { const u = mzi((thetaDeg * Math.PI) / 180, (phiDeg * Math.PI) / 180); const mags = u.map((row) => row.map((z) => mag(z).toFixed(3)).join(" ")); console.log("θ=" + thetaDeg + "° φ=" + phiDeg + "° |U| = [" + mags.join(" | ") + "]"); } show(90, 0); // balanced mixer... show(90, 90); // ...same magnitudes: φ moved only phases show(0, 45); // the swap: anti-diagonal show(180, 45); // no mixing: diagonal show(120, 30); // a generic setting: |U11|² should be sin²(60°) = 0.75 // Unitarity check: max deviation of U†U from the identity. const u = mzi(1.234, 0.567); let worst = 0; for (let i = 0; i < 2; i++) for (let j = 0; j < 2; j++) { let g = c(0); for (let k = 0; k < 2; k++) g = add(g, mul(c(u[k][i].re, -u[k][i].im), u[k][j])); worst = Math.max(worst, Math.hypot(g.re - (i === j ? 1 : 0), g.im)); } console.log("unitarity error at a random setting: " + worst.toExponential(2));

Deja vu: you have met this machine in polarisation optics

If U(\theta,\varphi) feels familiar, it should — it is the same mathematics as Jones calculus. There, the two-component complex vector is (E_x, E_y) and the programmable unitary is a waveplate; here the vector is (port 1, port 2) and the unitary is an MZI. The dictionary is exact:

RoleMZI (path encoding)Polarisation (Jones calculus)
the two-dimensional stateamplitudes in two waveguidesamplitudes on two field axes E_x, E_y
fixed 50:50 mixerdirectional coupler Bviewing the field in a basis rotated 45°
knob for magnitudesinternal phase \thetawaveplate retardance (quarter-wave, half-wave…)
knob for relative phaseexternal phase \varphiwaveplate orientation angle
universality resultMZI + output phase = any 2×2 unitaryquarter–half–quarter stack = any polarisation transform

The shared abstraction is the group SU(2): rotations of a two-level complex system. A lab polarimetrist steering a Poincaré sphere with waveplates and a photonic engineer trimming an MZI mesh are pushing the same group elements with different fingers. That, incidentally, is why a single MZI is also exactly a single-qubit gate for a photon encoded across two paths — a fact Module 9 will collect with interest.

Polarisation, photon paths, electron spin, the two lowest levels of an atom, a superconducting qubit: physics keeps handing us systems described by two complex amplitudes, and every lossless manipulation of any of them is an SU(2) element — the same three-parameter family of rotations. This is one of the quiet universalities of quantum mechanics: the hardware differs, the group does not. It has a practical corollary that working engineers exploit shamelessly. Any trick discovered in one two-level technology — composite pulses that cancel calibration error in NMR, polarisation controllers that undo a fibre's random birefringence, geometric phases in optics — can be transplanted to the others by transliterating through the group. Some of the error-tolerant MZI designs used in modern photonic meshes are, almost line for line, NMR composite-pulse sequences from the 1980s wearing waveguides. When this course's later pages fret about phase errors in meshes, remember: half the medicine cabinet was stocked decades ago, in someone else's field.

Two fine-print clauses cause most of the bugs in first mesh simulations. Clause one: the half-angle. The internal phase is \theta, but every magnitude in the matrix runs on \theta/2. To drag a mesh's MZI from full-cross to full-bar you must swing \theta through a whole \pi — set \theta = \pi/2 expecting extinction and you get a cheerful 50:50 instead. Clause two: count your parameters. A general 2×2 unitary has four real parameters; the MZI's two knobs plus one discarded global phase makes three — one short. The missing parameter is an output-side phase, which a lone MZI simply does not have. In a mesh this is harmless — the neighbour's input shifter or the final phase column supplies it — but if your simulation compares U(\theta,\varphi) against a target unitary entry-by-entry and "fails", check whether the discrepancy is exactly a diagonal phase matrix before blaming your code. Equality up to diagonal phases is, for photonic hardware, equality.

Where this goes next

One programmable 2×2 rotation in hand, the obvious ambition is N \times N: can a fabric of these gates realise any unitary on hundreds of waveguides? The next lesson proves yes — constructively, twice: Reck's 1994 triangle and Clements' 2016 rectangle, the two canonical ways to tile U(\theta,\varphi) into a universal linear processor, using exactly N(N-1)/2 copies. The knobs you learned to read today become the entries of a compiler's output.