Steven GellerQuantum Computing, End to End

Book contents

Current section

Part II. Mathematical Core

  1. Complex Numbers for Quantum Computing
  2. Vectors, Bases, and Amplitudes
  3. Inner Products, Orthogonality, and Projection
  4. Matrices as Gates
  5. Unitary Operations and Reversibility
  6. Tensor Products and State-Space Growth
  7. Observables, Eigenvectors, and Measurement
  8. Density Matrices and Mixed States

Part II. Mathematical Core · Chapter 12

Unitary Operations and Reversibility

One short equation — U † U = I — decides whether a matrix is allowed to be a quantum gate, and it buys something classical computing spent decades throwing away: every legal gate can be run backwards.

Artifact
In this chapter 8 sections

Reader question. What mathematical test decides whether a matrix is a valid closed-system quantum operation?

A matrix is unitary when U†U=I; this preserves inner products, norms, orthogonality, and therefore total probability, while guaranteeing an inverse U†. Nonunitary projection, reset, and loss require measurement or environmental coupling.

Scope and non-goals.
  • This chapter does not claim every physical process is unitary on the subsystem being modeled.
  • It does not derive open-system channels or the thermodynamics of erasure.
A unitary gate and its inverse forming a closed loop What goes forward can come back |ψ⟩ U|ψ⟩ apply U apply U†; the inverse is free U†U = I: length preserved, so an exact inverse always exists
Figure 12.1. Notice that the loop closes exactly. Because U preserves length, U† undoes it with no information lost, no ancilla, and no approximation; a property measurement can never offer.

The adjoint test

Compute U†U for valid and invalid candidates.

A unitary operation preserves the length of every state vector, and it preserves the inner product between any two of them. Valid states stay valid, and distinguishability relationships survive closed-system evolution intact.

The whole doctrine fits in one equation:

UU=IU^\dagger U=I(12.1)

Here UU^\dagger is the conjugate transpose of UU and II is the identity. When the equation holds, the inverse exists and is handed to you:

U1=UU^{-1}=U^\dagger(12.2)

That is the entire reason quantum gates are reversible. Undoing a gate never requires a search or a checkpoint; only the adjoint of the matrix you already used.

Evidence boundary. Unitary operators satisfy U†U=I and preserve inner products. [John Watrous] [Michael A. Nielsen]

What unitarity preserves

Derive norm and inner-product invariance.

Computing UUU^\dagger U and getting the identity certifies norm preservation for every input state, not just the one you tested. Unitarity also preserves overlaps:

UaUb=ab\langle Ua\vert Ub\rangle=\langle a\vert b\rangle(12.3)

The consequence is profound: a closed-system gate can never merge two distinct states into one. If it could, the inner product between them would change from zero to one, and the equation above forbids it. Measurement and noise can destroy that kind of information; which is precisely why they are modeled as different processes, outside the unitary framework.

Evidence boundary. Unitary evolution is reversible with inverse U†. [Michael A. Nielsen] [John Preskill]

Invertibility follows for free

Show U^{-1}=U† and connect to reversible circuits.

Evidence boundary. Measurement and open-system noise are not represented as unitary evolution on the measured subsystem alone. [John Watrous] [Michael A. Nielsen]

UU=Id;U1=UU^\dagger U=I_d;\quad U^{-1}=U^\dagger(12.4)

Notation contract: Adjoint † means conjugate transpose; identity I_d dimension declared; numerical unitarity tolerance uses a specified matrix norm.

Operations outside the closed-system gate set

Classify projection, reset, deletion, and noise.

Unitarity works like a type constraint on quantum operations. A function that is trivial in ordinary code; compare-and-overwrite, say; may be illegal as a direct gate, and implementing it in a circuit typically requires reversible logic, ancilla registers, and a final uncomputation pass to clean the ancillas up.

This has teeth for resource estimates. When a paper treats a complex classical subroutine as a free unitary oracle, the cost has not vanished; it is hiding in the reversible implementation. Ask for it.

Keep the boundary straight: measurement, reset, noise, and discarding information are legitimate parts of a full computation, but they are not unitary gates. A serious circuit description says which layer each operation belongs to, instead of hiding every physical effect inside one box.

A validator for proposed gates

Turn algebraic conditions into a reusable test.

Compute the residual R=U-dagger U-I and report a matrix norm with a declared tolerance. A Boolean-looking truth table is insufficient because complex phases may break orthogonality. If a matrix is uniformly mis-scaled, normalize only after proving its columns are already mutually orthogonal; arbitrary column-by-column repair changes the proposed linear map rather than validating it.

Unitary matrix validator

Acceptance contract for Unitary matrix validator
FieldReader-visible record
FormatCLI and notebook accepting real or complex matrices
VerificationTests exact standard gates, rejects projection/scaling matrices, reports tolerance and maximum deviation from identity.
AvailabilitySource-embedded acceptance record; no separate download is claimed
{
  "artifact": "Unitary matrix validator",
  "format": "CLI and notebook accepting real or complex matrices",
  "acceptance_test": "Tests exact standard gates, rejects projection/scaling matrices, reports tolerance and maximum deviation from identity.",
  "publication_state": "source-embedded contract and worked fixture"
}

Executable reference fixture

Run with Python 3.11 or later. The final assertion is the chapter-level pass condition for this small instance.

import cmath
import math

def validate_square(matrix):
    if not matrix or any(len(row) != len(matrix) for row in matrix):
        raise ValueError("unitary candidate must be a nonempty square matrix")

def adjoint(matrix):
    validate_square(matrix)
    return tuple(tuple(matrix[column][row].conjugate() for column in range(len(matrix)))
                 for row in range(len(matrix)))

def matmul(left, right):
    validate_square(left)
    validate_square(right)
    if len(left) != len(right):
        raise ValueError("matrix dimensions must agree")
    size = len(left)
    return tuple(tuple(sum(left[row][k] * right[k][column] for k in range(size))
                       for column in range(size)) for row in range(size))

def unitary_deviation(matrix):
    product = matmul(adjoint(matrix), matrix)
    return max(abs(product[row][column] - (1 if row == column else 0))
               for row in range(len(matrix)) for column in range(len(matrix)))

def matvec(matrix, vector):
    validate_square(matrix)
    if len(matrix) != len(vector):
        raise ValueError("state dimension mismatch")
    return tuple(sum(matrix[row][column] * vector[column] for column in range(len(vector)))
                 for row in range(len(vector)))

scale = math.sqrt(0.5)
H = ((scale, scale), (scale, -scale))
X = ((0, 1), (1, 0))
S = ((1, 0), (0, 1j))
CNOT = ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0))
phase_gates = tuple(((1, 0), (0, cmath.exp(1j * theta)))
                    for theta in (0.0, 0.2, -1.7, math.pi))
good_gates = (H, X, S, CNOT, *phase_gates)
deviations = [unitary_deviation(gate) for gate in good_gates]
assert max(deviations) < 1e-12

states = ((0.6, 0.8), (scale, 1j * scale), (1, 0))
for gate in (H, X, S, *phase_gates):
    for state in states:
        before = sum(abs(value) ** 2 for value in state)
        after = sum(abs(value) ** 2 for value in matvec(gate, state))
        assert abs(before - after) < 1e-12

bad_gates = (((1, 0), (0, 0)), ((2, 0), (0, 0.5)), ((1, 1), (0, 1)))
bad_deviations = [unitary_deviation(gate) for gate in bad_gates]
assert min(bad_deviations) > 0.5
near = ((1, 0), (0, 1 + 5e-10))
near_deviation = unitary_deviation(near)
assert near_deviation < 1e-8 and near_deviation > 1e-12
ragged_rejected = False
try:
    unitary_deviation(((1, 0), (0,)))
except ValueError:
    ragged_rejected = True
assert ragged_rejected
print(f"PASS: 12 unitary validator accepts {len(good_gates)} gates with max deviation={max(deviations):.2e}, rejects {len(bad_gates)} matrices with min deviation={min(bad_deviations):.2f}, tolerance boundary={near_deviation:.2e}")

Scope boundary

  • This chapter does not claim every physical process is unitary on the subsystem being modeled.
  • It does not derive open-system channels or the thermodynamics of erasure.

Depth commitment. One equivalence derivation, four candidates, one repair, and an executable validator.

Practice problem

Classify four supplied 2×22\times2 matrices as unitary or nonunitary, and repair one scaled candidate if possible.

A = (1/sqrt(2))*[[1,1],[1,-1]]
B = [[1,0],[0,2]]
C = (1/2)*[[1,1],[1,-1]]
D = [[1,0],[0,i]]
Deliverable
Adjoint products, verdicts, and a corrected matrix with proof.
Pass condition
The CLI independently computes ||U†U−I|| and matches all verdicts under the declared tolerance.

Verification record

Expected solution form. Exact algebra for two matrices plus numerical report for all four.

Model answer. A and D are unitary; B and C are not. C has orthogonal columns of norm 1/sqrt(2), so multiplying C by sqrt(2) repairs it and produces A; the identity residual is then zero up to floating-point tolerance.

Model result and check. Tests assert classifications and the corrected candidate's identity residual.

Acceptance test. The CLI independently computes ||U†U−I|| and matches all verdicts under the declared tolerance.

Companion work

Artifacts for this chapter

These entries resolve to checked-in local source. Commands are reproduced exactly from the chapter manifest, and source-embedded fixtures are exported as direct downloads.

  1. Reproduce or test

    python3 tools/validate_briefs.py --briefs data/editorial_briefs_00_35.json --from 0 --through 35 --check-rewritten-sources --execute-artifacts

Provenance

Sources and review

  1. John Watrous. The Theory of Quantum Information. Cambridge University Press / University of Waterloo. 2018textbook
  2. Michael A. Nielsen and Isaac L. Chuang. Quantum Computation and Quantum Information. Cambridge University Press. 2010textbook
  3. John Preskill. Lecture Notes for Physics 219: Quantum Computation. California Institute of Technology. 2018graduate lecture notes

The load-bearing claims in the chapter are mapped inline to this registered source set. A citation supports only the bounded claim beside it.

Cite this chapter