- Mathematics
Unitary Operator
A linear operator U satisfying U†U = UU† = I, where U† is the conjugate transpose, which preserves the inner product (and hence probability) of quantum states and represents all reversible quantum operations including quantum gates.
Every quantum gate is a unitary operator. This is a consequence of quantum mechanics: time evolution of a closed system is always unitary, and any reversible quantum operation must preserve probability.
Definition
A square matrix is unitary if:
so . Unitary matrices are closed under multiplication (composing two gates gives another valid gate) and form the group .
Probability conservation
Quantum states are unit vectors: . After applying :
The norm is unchanged, so probabilities still sum to one. Any operation that failed this would create or destroy probability.
Parametrizing single-qubit unitaries
The special unitary group (unitaries with determinant 1) parametrizes all single-qubit gates up to a global phase:
with three real parameters , , . Every single-qubit gate has this form.
Familiar examples
The Pauli matrices , , are both Hermitian and unitary; they are their own inverses:
The Hadamard gate satisfies and , so it too is its own inverse.
The rotation gates , , are the building blocks of variational circuits.
What is not unitary
Measurement is not unitary: it is irreversible. A projective measurement collapses the state and cannot be undone.
Noise channels map pure states to mixed states via Kraus operators , where individual are not unitary.
Connection to Hamiltonians
Every unitary can be written as for some Hermitian . A qubit driven by Hamiltonian for time evolves as . This links gate-level descriptions to pulse-level hardware control.
Code example
import numpy as np
from numpy.linalg import qr
def is_unitary(M, tol=1e-10):
return np.allclose(M.conj().T @ M, np.eye(M.shape[0]), atol=tol)
H = np.array([[1, 1], [1, -1]]) / np.sqrt(2)
print("Hadamard is unitary:", is_unitary(H)) # True
A = np.array([[1, 1], [0, 1]], dtype=complex)
print("Shear matrix is unitary:", is_unitary(A)) # False
# Random unitary via QR decomposition
rng = np.random.default_rng(42)
M = rng.standard_normal((4, 4)) + 1j * rng.standard_normal((4, 4))
Q, R = qr(M)
D = np.diag(R.diagonal() / np.abs(R.diagonal()))
print("Random 4x4 unitary:", is_unitary(Q @ D)) # True