symop.devices.models.beamsplitters

Beamsplitter device models.

This package contains semantic models of beamsplitter devices used in linear optical systems.

Beamsplitters are passive two-mode transformations that mix input modes according to a unitary transformation. At the semantic level, these models describe:

  • how input paths are paired,

  • how output paths are assigned,

  • and how device parameters (e.g., reflectivity, phase) are encoded.

The actual transformation of quantum states is performed by representation-specific kernels. The models defined here only construct semantic device actions and label edits required for execution.

Typical devices in this package include:

  • balanced and unbalanced beamsplitters,

  • parametrized two-mode couplers,

  • components used to build interferometers such as Mach–Zehnder setups.

Notes

These models are backend-agnostic and operate purely at the symbolic or semantic planning level.

class BeamSplitter(theta: float, phi_t: float = 0.0, phi_r: float = 0.0) None

Bases: DeviceBase

Ideal path beamsplitter device.

A beamsplitter acts on matched mode pairs drawn from two input paths. Planning records the participating input modes, output paths, and beamsplitter parameters for backend execution.

The device uses the package Heisenberg convention, where creation operators transform as

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

The angle theta determines the transmission and reflection amplitudes by

\[t = \cos(\theta), \qquad r = \sin(\theta).\]

With phases phi_t and phi_r, the two-mode unitary 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}\]

Thus theta = pi / 4 gives a balanced 50/50 beamsplitter.

In this implementation, transmission corresponds to remaining on the same path index, while reflection corresponds to switching to the opposite path:

  • in0 -> out0: transmission

  • in0 -> out1: reflection

  • in1 -> out1: transmission

  • in1 -> out0: reflection, with the phase determined by the lower-left

unitary element

Thus a fully transmitting beamsplitter (theta = 0) leaves paths unchanged, while a fully reflecting beamsplitter (theta = pi/2) swaps the two paths.

Parameters:
  • theta (float) – Mixing angle of the beamsplitter. The transmission and reflection amplitudes are cos(theta) and sin(theta), respectively.

  • phi_t (float) – Transmission phase.

  • phi_r (float) – Reflection phase.

Examples

Create a balanced (50/50) beamsplitter and apply it to two paths:

>>> import numpy as np
>>> bs = BeamSplitter(theta=np.pi / 4)
>>> state_out = bs(
...     state_in,
...     ports={
...         "in0": Path("a"),
...         "in1": Path("b"),
...         "out0": Path("c"),
...         "out1": Path("d"),
...     },
... )

Notes

Planning does not relabel existing modes. The actual two-mode rewrite, including construction of output-path modes, is delegated to the runtime kernel through action.params["pairs"].

_abc_impl = <_abc._abc_data object>
apply(state: State, *, ports: Mapping[str, Path], selection: object | None = None, runtime: DeviceRuntime | None = None, ctx: ApplyContext | None = None, out_kind: Literal['ket', 'density'] | None = None) State

Apply the device to a state through a runtime.

Parameters:
  • state (State)

  • ports (Mapping[str, Path])

  • selection (object | None)

  • runtime (DeviceRuntime | None)

  • ctx (ApplyContext | None)

  • out_kind (Literal['ket', 'density'] | None)

Return type:

State

property kind: DeviceKind

Return the device kind identifier.

phi_r: float = 0.0
phi_t: float = 0.0
plan(*, state: State, ports: Mapping[str, Path], selection: object | None = None, ctx: ApplyContext | None = None) DeviceAction

Plan beamsplitter mixing on matched mode pairs.

Parameters:
  • state (State) – Input state whose mode labels are inspected.

  • ports (Mapping[str, Path]) – Mapping from device-port names to path labels. Must contain "in0", "in1", "out0", and "out1".

  • selection (object | None) – Optional selection object forwarded by the runtime. It is not used by this device.

  • ctx (ApplyContext | None) – Optional apply context forwarded by the runtime. It is not used by this device.

Returns:

Planned action containing:

  • params["pairs"]: tuple of beamsplitter pair specifications

  • edits: always empty for this device

Return type:

DeviceAction

Raises:
  • TypeError – If the state does not support path-based mode lookup.

  • ValueError – If both inputs are populated but contain incompatible numbers of modes.

Notes

The unitary itself is not applied here. This method only prepares semantic pairing and kernel parameters. If one side is missing, the backend kernel is expected to synthesize a matching vacuum partner.

property port_specs: tuple[PortSpec, ...]

Return the port specification of the device.

theta: float

Modules

beamsplitter

Path beamsplitter device.