symop.polynomial.channels.unitaries

Linear-optical unitary helpers.

Provides construction and validation utilities for small unitary matrices commonly used in photonic models, including beamsplitters, phase shifters, mode swaps, interferometers, and embedding operations in larger mode spaces.

beamsplitter_u(*, t: float, r: float, phi_t: float = 0.0, phi_r: float = 0.0) ndarray

Return a 2×2 beamsplitter unitary.

The matrix implements a linear optical beamsplitter under the package Heisenberg convention, where creation operators transform as

\[a^\dagger_{\mathrm{out},k} = \sum_j U_{k j}\, a^\dagger_{\mathrm{in},j}.\]

A convenient SU(2) parameterization is

\[\begin{split}U = \begin{pmatrix} t e^{i\phi_t} & r e^{i\phi_r} \\ -r e^{-i\phi_r} & t e^{-i\phi_t} \end{pmatrix},\end{split}\]

which is unitary when \(t^2 + r^2 = 1\).

Parameters:
  • t (float) – Transmission amplitude.

  • r (float) – Reflection amplitude.

  • phi_t (float) – Phase applied to the transmission amplitude.

  • phi_r (float) – Phase applied to the reflection amplitude.

Returns:

Complex 2×2 unitary matrix representing the beamsplitter.

Return type:

ndarray

Notes

This function does not enforce physical constraints. Callers are responsible for ensuring that \(t^2 + r^2 = 1\) if a unitary transformation is required.

block_diag(*blocks: ndarray) ndarray

Return the block-diagonal concatenation of multiple square matrices.

If blocks are U1, U2, …, then:

\[U = \mathrm{diag}(U_1, U_2, \ldots).\]
Parameters:

blocks (ndarray) – Square matrices.

Returns:

Block-diagonal matrix.

Return type:

ndarray

Raises:

ValueError – If any block is not square.

embed_1(*, n: int, i: int, u1: complex) ndarray

Embed a 1x1 unitary into an n-dimensional identity.

\[U = I, \quad U_{i i} \leftarrow u_1.\]
Parameters:
  • n (int) – Total dimension.

  • i (int) – Index to replace (0-based).

  • u1 (complex) – Complex scalar of modulus 1 (not enforced here).

Returns:

Matrix of shape (n, n).

Return type:

ndarray

embed_2(*, n: int, i: int, j: int, U2: ndarray) ndarray

Embed a 2x2 unitary U2 acting on indices (i, j) into an n-dimensional identity.

The embedding acts on the subspace spanned by basis vectors i and j, leaving all other basis vectors unchanged.

Parameters:
  • n (int) – Total dimension.

  • i (int) – Indices to couple (0-based, distinct).

  • j (int) – Indices to couple (0-based, distinct).

  • U2 (ndarray) – 2x2 matrix.

Returns:

Matrix of shape (n, n).

Return type:

ndarray

embed_u(*, n: int, indices: list[int] | tuple[int, ...], Uk: ndarray, check_unitary: bool = False, atol: float = 1e-10) ndarray

Embed a kxk unitary Uk onto a subset of indices inside an n-dimensional identity.

Parameters:
  • n (int) – Total dimension.

  • indices (list[int] | tuple[int, ...]) – Distinct indices (0-based) where Uk acts, in the order matching Uk.

  • Uk (ndarray) – Square matrix of shape (k, k).

  • check_unitary (bool) – If True, validate Uk is unitary.

  • atol (float) – Tolerance for optional unitary check.

Returns:

Matrix of shape (n, n).

Return type:

ndarray

Raises:

ValueError – If indices are invalid or Uk shape mismatches.

loss_dilation_u(*, eta: float) ndarray

Return the beamsplitter unitary used in pure-loss dilation.

A pure-loss channel with transmissivity \(\eta\) can be modeled as a beamsplitter coupling a signal mode to a vacuum environment mode.

The amplitudes are

\[t = \sqrt{\eta}, \quad r = \sqrt{1-\eta}.\]
Parameters:

eta (float) – Transmissivity of the loss channel in the interval [0, 1].

Returns:

Complex 2×2 unitary implementing the loss dilation.

Return type:

ndarray

mzi_u(*, theta1: float, theta2: float, phi_internal: float, phi_in0: float = 0.0, phi_in1: float = 0.0, phi_out0: float = 0.0, phi_out1: float = 0.0, check_unitary: bool = False, atol: float = 1e-10) ndarray[tuple[Any, ...], dtype[complex128]]

Return a 2x2 Mach-Zehnder interferometer (MZI) unitary.

This composes two couplers with input/output phase shifters and one internal differential phase between the arms.

Construction

Define two 2x2 couplers U1, U2 (directional-coupler family via beamsplitter_u), and diagonal phase matrices:

\[\begin{split}P_\mathrm{in} = \mathrm{diag}(e^{i\phi_{in,0}}, e^{i\phi_{in,1}}), \\ P_\mathrm{int} = \mathrm{diag}(e^{i\phi_{internal}}, 1), \\ P_\mathrm{out} = \mathrm{diag}(e^{i\phi_{out,0}}, e^{i\phi_{out,1}}).\end{split}\]

Then:

\[U = P_\mathrm{out} \, U_2 \, P_\mathrm{int} \, U_1 \, P_\mathrm{in}.\]
type theta1:

float

param theta1:

Coupler angles that define splitting ratios. We use t=cos(theta), r=sin(theta) with the beamsplitter_u convention.

type theta2:

float

param theta2:

Coupler angles that define splitting ratios. We use t=cos(theta), r=sin(theta) with the beamsplitter_u convention.

type phi_internal:

float

param phi_internal:

Internal phase on arm 0 relative to arm 1.

type phi_in0:

float

param phi_in0:

Input port phases.

type phi_in1:

float

param phi_in1:

Input port phases.

type phi_out0:

float

param phi_out0:

Output port phases.

type phi_out1:

float

param phi_out1:

Output port phases.

type check_unitary:

bool

param check_unitary:

If True, validate unitarity.

type atol:

float

param atol:

Tolerance for optional unitary check.

returns:

Complex matrix of shape (2, 2).

rtype:

numpy.ndarray

Notes

This is a “photonic circuit” convenience constructor. If you prefer a different internal phase placement (arm 1 instead of arm 0), swap the diagonal of P_int.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[complex128]]

phase_u(*, phi: float) ndarray

Return the 1x1 phase-shifter unitary.

\[U = \begin{pmatrix} e^{i\phi} \end{pmatrix}.\]
Returns:

Complex array of shape (1, 1).

Return type:

ndarray

Parameters:

phi (float)

require_dim(U: ndarray, *, n: int) None

Raise ValueError unless U has shape (n, n).

Parameters:
  • U (ndarray) – Candidate matrix.

  • n (int) – Required dimension.

Raises:

ValueError – If shape mismatch.

Return type:

None

require_square(U: ndarray) None

Raise ValueError unless U is a square matrix.

Parameters:

U (ndarray) – Candidate matrix.

Raises:

ValueError – If U is not 2D or not square.

Return type:

None

require_unitary_optional(U: ndarray, *, check_unitary: bool = False, atol: float = 1e-10) None

Optionally validate U is unitary, i.e. U^H U = I.

This is deliberately optional because (a) it costs time, and (b) some uses may pass approximate numerics.

Parameters:
  • U (ndarray) – Candidate matrix.

  • check_unitary (bool) – If True, validate unitarity.

  • atol (float) – Absolute tolerance for np.allclose.

Raises:

ValueError – If check_unitary is True and U is not unitary within atol.

Return type:

None

swap_u(*, check_unitary: bool = False, atol: float = 1e-10) ndarray

Return the 2x2 SWAP unitary.

\[\begin{split}U = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}.\end{split}\]
Parameters:
  • check_unitary (bool) – If True, validate unitarity.

  • atol (float) – Tolerance for optional unitary check.

Returns:

Complex matrix of shape (2, 2).

Return type:

ndarray

Modules

beamsplitter

Unitary matrices for basic two-mode linear optical elements.

blockdiag

Helpers for assembling mode-space unitary matrices.

conventions

Matrix validation utilities.

mzi

Mach–Zehnder interferometer utilities.

phase

Single-mode phase unitary.

swap

Mode-swap unitary.