Source code for deepquantum.photonic.tdm

"""Time domain multiplexing"""

from typing import Any

import torch

from .circuit import QumodeCircuit


[docs] class QumodeCircuitTDM(QumodeCircuit): r"""Time-domain-multiplexed photonic quantum circuit. Note: When using large squeezing parameters, we recommend using a double data type and a smaller ``eps`` for Homodyne to avoid issues with non-positive definiteness of the covariance matrix. Args: nmode: The number of spatial modes in the circuit. init_state: The initial state of the circuit. It can be a vacuum state with ``'vac'``. For Gaussian backend, it can be arbitrary Gaussian states with ``[cov, mean]``. Use ``xxpp`` convention and :math:`\hbar=2` by default. cutoff: The Fock space truncation. Default: ``None`` backend: Use ``'gaussian'`` for Gaussian backend or ``'bosonic'`` for Bosonic backend. Default: ``'gaussian'`` name: The name of the circuit. Default: ``None`` noise: Whether to introduce Gaussian noise. Default: ``False`` mu: The mean of Gaussian noise. Default: 0 sigma: The standard deviation of Gaussian noise. Default: 0.1 """ def __init__( self, nmode: int, init_state: Any, cutoff: int | None = None, backend: str = 'gaussian', name: str | None = None, noise: bool = False, mu: float = 0, sigma: float = 0.1, ) -> None: assert backend in ('gaussian', 'bosonic') super().__init__( nmode=nmode, init_state=init_state, cutoff=cutoff, backend=backend, basis=False, detector='pnrd', name=name, mps=False, chi=None, noise=noise, mu=mu, sigma=sigma, ) self.samples = None
[docs] def forward( self, data: torch.Tensor | None = None, state: Any = None, nstep: int | None = None ) -> list[torch.Tensor]: r"""Perform a forward pass of the TDM photonic quantum circuit and return the final state. Args: data: The input data for the ``encoders`` with the shape of :math:`(\text{batch}, \text{ntimes}, \text{nfeat})`. Default: ``None`` state: The initial state for the photonic quantum circuit. Default: ``None`` nstep: The number of the evolved time steps. Default: ``None`` Returns: The covariance matrix and displacement vector of the measured final state. """ assert self._with_delay, 'No delay loop.' for i in range(self.nmode): assert i in self.wires_homodyne if data is None: if nstep is None: nstep = 1 else: size = data.size() assert data.ndim == 3 if nstep is None: nstep = size[1] self.state = state samples = [] for i in range(nstep): if data is None: self.state = super().forward(state=self.state) else: data_i = data[:, i % size[1], :] self.state = super().forward(data_i, self.state) samples.append(self.measure_homodyne(shots=1)) self.state = self.state_measured self.samples = torch.stack(samples, dim=-1) # (batch, nwire, nstep) return self.state
[docs] def get_samples(self, wires: int | list[int] | None = None) -> torch.Tensor: """Get the measured samples according to the given ``wires``.""" if wires is None: wires = self.wires wires = sorted(self._convert_indices(wires)) return self.samples[..., wires, :]