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:
- U(\theta,\varphi) \;=\; i\,e^{i\theta/2}
\begin{pmatrix} e^{i\varphi}\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \\[2pt]
e^{i\varphi}\cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \end{pmatrix};
- the magnitudes of all four entries depend on \theta
alone: light entering port 1 exits with bar power \sin^2(\theta/2)
and cross power \cos^2(\theta/2);
- \varphi adjusts only the phase of one column —
the relative phase between the outputs, the part a lone photodiode cannot see;
- the prefactor i e^{i\theta/2} is a global phase,
common to both outputs and unobservable; modulo it, U(\theta,\varphi)
is an SU(2) rotation with \theta,\varphi as its two angles;
- with one further external phase shifter on an output, the family closes over
every 2×2 unitary up to global phase — and in a mesh, the neighbouring MZIs' own
\varphi shifters supply exactly that.
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:
| Role | MZI (path encoding) | Polarisation (Jones calculus) |
| the two-dimensional state | amplitudes in two waveguides | amplitudes on two field axes E_x, E_y |
| fixed 50:50 mixer | directional coupler B | viewing the field in a basis rotated 45° |
| knob for magnitudes | internal phase \theta | waveplate retardance (quarter-wave, half-wave…) |
| knob for relative phase | external phase \varphi | waveplate orientation angle |
| universality result | MZI + output phase = any 2×2 unitary | quarter–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.