Transformations

Amplifier

The noisy amplifier channel.

Attenuator

The noisy attenuator channel.

BSgate

The beam splitter gate.

Channel

Base class for all CPTP channels.

CXgate

Controlled X gate.

CZgate

Controlled Z gate.

Dgate

The displacement gate.

FockDamping

The Fock damping operator.

Ggate

The generic N-mode Gaussian gate.

GaussianRandomNoise

The Gaussian random noise channel.

Identity

The identity gate.

Interferometer

N-mode interferometer.

Kgate

The Kerr gate.

Map

A CircuitComponent more general than Channel, which are CPTP maps.

MZgate

Mach-Zehnder gate.

Operation

A CircuitComponent with input and output wires on the ket side.

PhaseNoise

The Phase noise channel.

Pgate

Quadratic phase gate.

RealInterferometer

N-mode interferometer parametrized by an NxN orthogonal matrix (or 2N x 2N block-diagonal orthogonal matrix).

Rgate

The rotation gate.

S2gate

The two-mode squeezing gate.

Sgate

The squeezing gate.

Transformation

Base class for all transformations.

Unitary

Base class for all unitary transformations.

Inheritance Diagram

Inheritance diagram of Transformation, Map, Channel, Amplifier, Attenuator, GaussianRandomNoise, PhaseNoise, Operation, FockDamping, Unitary, BSgate, CXgate, CZgate, Dgate, Ggate, Identity, Interferometer, Kgate, MZgate, Pgate, RealInterferometer, Rgate, S2gate, Sgate

Amplifier

class mrmustard.lab.transformations.Amplifier(mode, gain=1.0, name=None)[source]

Bases: Channel

The noisy amplifier channel.

>>> import numpy as np
>>> from mrmustard.lab import Amplifier, Coherent
>>> from mrmustard import settings
>>> amp = Amplifier(0, gain=4)
>>> coh = Coherent(0, alpha=1.0 + 2.0j)
>>> _, mu, _ = (coh >> amp).phase_space(0)
>>> assert np.allclose(mu*np.sqrt(2/settings.HBAR), np.array([4.0, 8.0]))
Parameters:
  • mode (int | tuple[int]) – The mode this gate is applied to.

  • gain (float | Sequence[float] | Parameter) – The gain.

  • name (str | None) – A name for the channel. If not provided, the class name will be used.

The \(N\)-mode attenuator is defined as

\[X = /sqrt{/bar{g}}I_{2N} \text{ , } Y = (/bar{g}-1)I_{2N} \text{ , and } d = O_{4N}\:,\]

where \(/bar{g}\) is the gain and \(\text{diag}_N(\bar{g})\) is the \(N\text{x}N\) matrix with diagonal \(\bar{g}\).

Its (A,b,c) triple is given by

\[\begin{split}A &= \begin{bmatrix} O_N & \text{diag}_N(1/(\sqrt{\bar{g}}) & \text{diag}_N(1-1/\bar{g}) & O_N \\ \text{diag}_N(1/(\sqrt{\bar{g}}) & O_N & O_N & O_N \\ \text{diag}_N(1-1/\bar{g}) & O_N & O_N & \text{diag}_N(1/(\bar{g})\\ O_N & O_N & \text{diag}_N(1/(\sqrt{\bar{g}}) & O_N \end{bmatrix} \\ \\ b &= O_{4N} \\ \\ c &= 1//bar{g}\:.\end{split}\]

Attenuator

class mrmustard.lab.transformations.Attenuator(mode, transmissivity=1.0, name=None)[source]

Bases: Channel

The noisy attenuator channel.

>>> from mrmustard import math
>>> from mrmustard.lab import Attenuator
>>> channel = Attenuator(mode=1, transmissivity=0.1)
>>> assert channel.modes == (1,)
>>> assert channel.parameters.transmissivity.value == 0.1
Parameters:
  • mode (int | tuple[int]) – The mode this gate is applied to.

  • transmissivity (float | Sequence[float] | Parameter) – The transmissivity.

  • name (str | None) – A name for the channel. If not provided, the class name will be used.

The \(N\)-mode attenuator is defined as

\[X = \text{cos}(\theta)I_{2N} \text{ , } Y = \text{sin}^2(\theta)I_{2N} \text{ , and } d = O_{4N}\:,\]

where the \(\theta=\text{arcos}(\sqrt{\bar{\eta}})\), \(\eta\) is the transmissivity, and \(\text{diag}_N(\bar{\eta})\) is the \(N\text{x}N\) matrix with diagonal \(\bar{\eta}\).

Its (A,b,c) triple is given by

\[\begin{split}A &= \begin{bmatrix} O_N & \text{diag}_N(\sqrt{\bar{\eta}}) & O_N & O_N \\ \text{diag}_N(\sqrt{\bar{\eta}}) & O_N & O_N & \text{diag}_N(1-\sqrt{\bar{\eta}})\\ O_N & O_N & O_N & \text{diag}_N(\sqrt{\bar{\eta}})\\ O_N & \text{diag}_N(1-\sqrt{\bar{\eta}}) & \text{diag}_N(\sqrt{\bar{\eta}}) & O_N \end{bmatrix} \\ \\ b &= O_{4N} \\ \\ c &= 1\:.\end{split}\]

BSgate

class mrmustard.lab.transformations.BSgate(modes, theta=0.0, phi=0.0, name=None)[source]

Bases: Unitary

The beam splitter gate.

>>> from mrmustard.lab import BSgate
>>> unitary = BSgate(modes=(1, 2), theta=0.1)
>>> assert unitary.modes == (1, 2)
>>> assert unitary.parameters.theta.value == 0.1
>>> assert unitary.parameters.phi.value == 0.0
Parameters:
  • modes (tuple[int, int]) – The pair of modes of the beam splitter gate.

  • theta (float | Sequence[float] | Parameter) – The transmissivity angle.

  • phi (float | Sequence[float] | Parameter) – The phase angle.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

The beamsplitter gate is a Gaussian gate defined by

\[\begin{split}S = \begin{bmatrix} \text{Re}(U) & -\text{Im}(U)\\ \text{Im}(U) & \text{Re}(U) \end{bmatrix} \text{ and } d = O_4\:,\end{split}\]

with

\[\begin{split}U &= \begin{bmatrix} \text{cos}(\theta) & -e^{-i\phi}\text{sin}(\theta)\\ e^{i\phi}\text{sin}(\theta) & \text{cos}(\theta) \end{bmatrix} \\\end{split}\]

Its (A,b,c) triple is given by

\[\begin{split}A = \begin{bmatrix} O_2 & U \\ U^{T} & O_2 \end{bmatrix} \text{, } b = O_{4} \text{, and } c = 1\end{split}\]
fock_array(shape=None, method='stable')[source]

Returns the unitary representation of the Beam Splitter gate in the Fock basis.

Parameters:
  • shape (int | Sequence[int] | None) – The shape of the returned representation. If shape is given as an int, it is broadcasted to all the dimensions. If not given, it defaults to settings.DEFAULT_FOCK_SIZE.

  • method (str) – The method to use to compute the Fock array. Available methods are: - "vanilla": standard recurrence relation (not numerically stable, but slightly faster than the stable one). - "schwinger": Use the Schwinger representation to compute the Fock array. - "stable": Use the stable implementation of the beamsplitter. (default)

Returns:

The Fock representation of this component.

Return type:

array

Channel

class mrmustard.lab.transformations.Channel(ansatz_factory=None, wires=None, name=None)[source]

Bases: Map

Base class for all CPTP channels.

Parameters:
property is_CP: bool

Whether this channel is completely positive (CP).

>>> from mrmustard.lab import Channel
>>> channel = Channel.random((0, 1, 2))
>>> assert channel.is_CP
property is_TP: bool

Whether this channel is trace preserving (TP).

>>> from mrmustard.lab import Channel
>>> channel = Channel.random((0, 1, 2))
>>> assert channel.is_TP
property is_physical: bool

Whether this channel is physical (i.e. CPTP).

>>> from mrmustard.lab import Channel
>>> channel = Channel.random((0, 1, 2))
>>> assert channel.is_physical
property XY: tuple[mrmustard.utils.typing.ComplexMatrix, mrmustard.utils.typing.ComplexMatrix]

Returns the X and Y matrix corresponding to the channel.

>>> from mrmustard.lab import Channel
>>> channel = Channel.random((0, 1))
>>> X, Y = channel.XY
>>> assert X.shape == (4, 4)
>>> assert Y.shape == (4, 4)
classmethod from_ansatz(modes_out, modes_in, ansatz=None, name=None)[source]

Initializes a transformation of type cls given modes and an ansatz.

Parameters:
  • modes_out (Sequence[int]) – The output modes of this transformation.

  • modes_in (Sequence[int]) – The input modes of this transformation.

  • ansatz (PolyExpAnsatz | ArrayAnsatz | None) – The ansatz of this transformation.

  • name (str | None) – The name of this transformation.

Returns:

A transformation.

Return type:

Channel

classmethod from_XY(modes_out, modes_in, X, Y, d=None, name=None)[source]

Initialize a Channel from its XY representation.

>>> from mrmustard.lab import Attenuator, Channel
>>> X = math.eye(2)
>>> Y = math.zeros((2,2))
>>> channel = Channel.from_XY([0], [0], X,Y)
>>> assert channel == Attenuator(0, transmissivity=1)
Parameters:
  • modes_out (Sequence[int]) – The output modes of the channel.

  • modes_in (Sequence[int]) – The input modes of the channel.

  • X (RealMatrix) – The X matrix of the channel.

  • Y (RealMatrix) – The Y matrix of the channel.

  • d (Vector | None) – The displacement vector of the channel.

  • name (str | None) – A name for the channel. If not provided, the class name will be used.

Raises:

ValueError – If the dimensions of the X,Y matrices and the number of modes don’t match.

Return type:

Channel

Each Gaussian channel transforms a state with covarince matrix \(\Sigma\) and mean \(\mu\) into a state with covariance matrix \(X \Sigma X^T + Y\) and vector of means \(X\mu + d\). This channel has a Bargmann triple that is computed in https://arxiv.org/pdf/2209.06069. We borrow the formulas from the paper to implement the corresponding channel.

classmethod random(modes, max_r=1.0, seed=None, name=None)[source]

A random channel without displacement.

>>> from mrmustard.lab import Channel
>>> channel = Channel.random((0, 1, 2), max_r=1.2)
>>> assert channel.modes == (0, 1, 2)
Parameters:
  • modes (int | tuple[int, ...]) – The modes of the channel.

  • max_r (float) – The maximum squeezing parameter.

  • seed (int | None) – The random seed. If None, the global seed is used.

  • name (str | None) – A name for the channel. If not provided, the class name will be used.

Returns:

The random channel.

Raises:

ValueError – if modes is an empty tuple.

Return type:

Channel

CXgate

class mrmustard.lab.transformations.CXgate(modes, s=0.0, name=None)[source]

Bases: Unitary

Controlled X gate.

>>> from mrmustard.lab import CXgate
>>> gate = CXgate((0, 1), s=0.5)
>>> assert gate.modes == (0, 1)
>>> assert gate.parameters.s.value == 0.5
Parameters:
  • modes (tuple[int, int]) – The pair of modes of the controlled-X gate.

  • s (float | Sequence[float] | Parameter) – The control parameter.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

We have that the controlled-X gate is defined as
\[C_X = \exp(is q_1 \otimes p_2)\]

Reference: https://arxiv.org/pdf/2110.03247.pdf, Equation 9.

CZgate

class mrmustard.lab.transformations.CZgate(modes, s=0.0, name=None)[source]

Bases: Unitary

Controlled Z gate.

>>> from mrmustard.lab import CZgate
>>> gate = CZgate((0, 1), s=0.5)
>>> assert gate.modes == (0, 1)
>>> assert gate.parameters.s.value == 0.5
Parameters:
  • modes (tuple[int, int]) – The pair of modes of the controlled-Z gate.

  • s (float | Sequence[float] | Parameter) – The control parameter.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

We have that the controlled-Z gate is defined as

\[C_Z = \exp(is q_1 \otimes q_2 / \hbar).\]

Reference: https://arxiv.org/pdf/2110.03247.pdf, Equation 8. https://arxiv.org/pdf/1110.3234.pdf, Equation 161.

Dgate

class mrmustard.lab.transformations.Dgate(mode, alpha=0j, name=None)[source]

Bases: Unitary

The displacement gate.

>>> from mrmustard.lab import Dgate
>>> unitary = Dgate(mode=1, alpha=0.1 + 0.2j)
>>> assert unitary.modes == (1,)
>>> assert unitary.parameters.alpha.value == 0.1 + 0.2j
Parameters:
  • mode (int | tuple[int]) – The mode this gate is applied to.

  • alpha (complex | Sequence[complex] | Parameter) – The displacement in the complex phase space.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

For any \(\bar{\alpha} = \bar{x} + i\bar{y}\) of length \(N\), the \(N\)-mode displacement gate is defined by

\[S = I_N \text{ and } r = \sqrt{2\hbar}\big[\text{Re}(\bar{\alpha}), \text{Im}(\bar{\alpha})\big].\]

Its (A,b,c) triple is given by

\[\begin{split}A &= \begin{bmatrix} O_N & I_N\\ I_N & O_N \end{bmatrix} \\ \\ b &= \begin{bmatrix} \bar{\alpha} & -\bar{\alpha}^* \end{bmatrix} \\ \\ c &= \text{exp}\big(-|\bar{\alpha}^2|/2\big).\end{split}\]

FockDamping

class mrmustard.lab.transformations.FockDamping(mode, damping=0.0, name=None)[source]

Bases: Operation

The Fock damping operator.

>>> from mrmustard.lab import FockDamping, Coherent
>>> operator = FockDamping(mode=0, damping=0.1)
>>> input_state = Coherent(mode=0, alpha=1 + 0.5j)
>>> output_state = input_state >> operator
>>> assert operator.modes == (0,)
>>> assert operator.parameters.damping.value == 0.1
>>> assert output_state.L2_norm < 1
Parameters:
  • mode (int | tuple[int]) – The mode this gate is applied to.

  • damping (float | Sequence[float] | Parameter) – The damping parameter.

  • name (str | None) – A name for the operator. If not provided, the class name will be used.

Its (A,b,c) triple is given by

\[ \begin{align}\begin{aligned}\begin{split}A &= e^{-\beta}\begin{bmatrix} O_N & I_N & \\ I_N & O_N &\end{split}\\\begin{split} \end{bmatrix} \\ \\ b &= O_{2N} \\ \\ c &= 1\:.\end{split}\end{aligned}\end{align} \]

Ggate

class mrmustard.lab.transformations.Ggate(modes, symplectic, name=None)[source]

Bases: Unitary

The generic N-mode Gaussian gate.

>>> from mrmustard import math
>>> from mrmustard.lab import Ggate, Vacuum, Identity, Ket
>>> U = Ggate.random(modes=0)
>>> assert isinstance(Vacuum(0) >> U, Ket)
>>> assert U >> U.dual == Identity(0)
Parameters:
  • modes (int | tuple[int, ...]) – The modes this gate is applied to.

  • symplectic (RealMatrix | Parameter) – The symplectic matrix of the gate in the XXPP ordering.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

property symplectic

Returns the symplectic matrix that corresponds to this unitary.

classmethod random(modes, max_r=1.0, seed=None, name=None)[source]

Returns a random Ggate.

Parameters:
  • modes (int | tuple[int, ...]) – The modes of the Ggate.

  • max_r (float) – Maximum squeezing parameter over which we make random choices.

  • seed (int | None) – The random seed. If None, the global seed is used.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

Returns:

The random Ggate.

Raises:

ValueError – if modes is an empty tuple.

Return type:

Ggate

GaussianRandomNoise

class mrmustard.lab.transformations.GaussianRandomNoise(modes, Y, name=None)[source]

Bases: Channel

The Gaussian random noise channel.

>>> import numpy as np
>>> from mrmustard.lab import GaussianRandomNoise
>>> channel = GaussianRandomNoise(modes=(1, 2), Y = 0.2 * np.eye(4))
>>> assert channel.modes == (1, 2)
>>> assert math.allclose(channel.parameters.Y.value, 0.2 * np.eye(4))
Parameters:
  • modes (int | tuple[int, ...]) – The modes the channel is applied to. The number of modes must match half of the size of Y.

  • Y (RealMatrix | Parameter) – The Y matrix of the Gaussian random noise channel.

  • name (str | None) – A name for the channel. If not provided, the class name will be used.

Raises:

ValueError – If the number of modes does not match half of the size of Y.

The Bargmann representation of the channel is computed via the formulas provided in the paper: https://arxiv.org/pdf/2209.06069

The channel maps an inout covariance matrix cov as

\[cov \mapsto cov + Y.\]

Identity

class mrmustard.lab.transformations.Identity(modes, name=None)[source]

Bases: Unitary

The identity gate.

>>> from mrmustard.lab import Identity
>>> unitary = Identity(modes=(1, 2))
>>> assert unitary.modes == (1, 2)
Parameters:
  • modes (int | tuple[int, ...]) – The modes this gate is applied to.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

The Abc parametrization of the identity gate is given by (c.f. https://www.scipost.org/10.21468/SciPostPhys.17.3.082) .. math:

A = \begin{pmatrix}
    0 & 1 \\
    1 & 0
\end{pmatrix},
\quad

b = \begin{pmatrix}
    0 \\
    0
\end{pmatrix},
\quad
c = 1

Interferometer

class mrmustard.lab.transformations.Interferometer(modes, unitary, name=None)[source]

Bases: Unitary

N-mode interferometer.

It corresponds to a Ggate with zero mean and a 2N x 2N unitary symplectic matrix.

>>> from mrmustard import math
>>> from mrmustard.lab import Interferometer
>>> unitary = Interferometer(modes=(1, 2), unitary=math.eye(2))
>>> assert unitary.modes == (1, 2)
>>> assert math.allclose(unitary.symplectic, math.eye(4))
Parameters:
  • modes (int | tuple[int, ...]) – The modes this gate is applied to.

  • unitary (ComplexMatrix | Parameter) – A unitary matrix. For N modes it must have shape (N,N).

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

Raises:

ValueError – If the size of the unitary does not match the number of modes.

classmethod random(modes, seed=None, name=None)[source]

Returns a random Interferometer.

Parameters:
  • modes (int | tuple[int, ...]) – The modes of the Interferometer.

  • seed (int | None) – The random seed. If None, the global seed is used.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

Returns:

The random Interferometer.

Raises:

ValueError – if modes is an empty tuple.

Return type:

Interferometer

Kgate

class mrmustard.lab.transformations.Kgate(mode, kappa=0.0, normal_ordered=True)[source]

Bases: Unitary

The Kerr gate.

A non-Gaussian single-mode unitary, diagonal in the Fock basis. By default the generator is the normal-ordered \(a^\dagger a^\dagger a a = n(n-1)\), giving \(U|n\rangle = e^{i\kappa n(n-1)}|n\rangle\). With normal_ordered=False the generator is \(n^2\), giving \(U|n\rangle = e^{i\kappa n^2}|n\rangle\).

>>> from mrmustard.lab import Kgate, Number
>>> gate = Kgate(mode=0, kappa=0.1)
>>> assert gate.modes == (0,)
Parameters:
  • mode (int | tuple[int]) – The mode the gate is applied to.

  • kappa (float | Parameter) – The Kerr nonlinearity strength.

  • normal_ordered (bool) – If True (default), the generator is \(a^\dagger a^\dagger a a = n(n-1)\). If False, the generator is \(n^2\). The two differ only by a linear rotation \(e^{i\kappa n}\), i.e. an Rgate .

property normal_ordered: bool

Whether the generator is \(n(n-1)\) (True) or \(n^2\) (False).

Map

class mrmustard.lab.transformations.Map(ansatz_factory=None, wires=None, name=None)[source]

Bases: Transformation

A CircuitComponent more general than Channel, which are CPTP maps.

Parameters:
classmethod from_ansatz(modes_out, modes_in, ansatz=None, name=None)[source]

Initializes a transformation of type cls given modes and an ansatz.

Parameters:
  • modes_out (Sequence[int]) – The output modes of this transformation.

  • modes_in (Sequence[int]) – The input modes of this transformation.

  • ansatz (PolyExpAnsatz | ArrayAnsatz | None) – The ansatz of this transformation.

  • name (str | None) – The name of this transformation.

Returns:

A transformation.

Return type:

Map

MZgate

class mrmustard.lab.transformations.MZgate(modes, phi_a=0.0, phi_b=0.0, internal=False, name=None)[source]

Bases: Unitary

Mach-Zehnder gate.

It supports two conventions:
  1. if internal=True, both phases act inside the interferometer: phi_a on the upper arm, phi_b on the lower arm.

  2. if internal = False, both phases act on the upper arm: phi_a before the first BS, phi_b after the first BS.

>>> from mrmustard.lab import MZgate
>>> mz = MZgate((0, 1), phi_a=0.1, phi_b=0.2)
>>> assert mz.modes == (0, 1)
>>> assert mz.parameters.phi_a.value == 0.1
>>> assert mz.parameters.phi_b.value == 0.2
Parameters:
  • modes (tuple[int, int]) – The pair of modes of the MZ gate.

  • phi_a (float | Sequence[float] | Parameter) – The phase in the upper arm of the MZ interferometer.

  • phi_b (float | Sequence[float] | Parameter) – The phase in the lower arm or external of the MZ interferometer.

  • internal (bool) – Whether phases are both in the internal arms.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

Operation

class mrmustard.lab.transformations.Operation(ansatz_factory=None, wires=None, name=None)[source]

Bases: Transformation

A CircuitComponent with input and output wires on the ket side. Operation are allowed to have a different number of input and output wires.

Parameters:
classmethod from_ansatz(modes_out, modes_in, ansatz=None, name=None)[source]

Initializes a transformation of type cls given modes and an ansatz.

Parameters:
  • modes_out (Sequence[int]) – The output modes of this transformation.

  • modes_in (Sequence[int]) – The input modes of this transformation.

  • ansatz (PolyExpAnsatz | ArrayAnsatz | None) – The ansatz of this transformation.

  • name (str | None) – The name of this transformation.

Returns:

A transformation.

Return type:

Operation

PhaseNoise

class mrmustard.lab.transformations.PhaseNoise(mode, phase_stdev=0.0, name=None)[source]

Bases: Channel

The Phase noise channel.

This class represents the application of a random phase. The distributiuon of the phase is assumed to be a Gaussian with mean zero, and standard deviation phase_stdev.

>>> from mrmustard.lab import PhaseNoise, Coherent, DM
>>> phase_noise = PhaseNoise(0, phase_stdev=0.5)
>>> assert isinstance(Coherent(0, 1) >> phase_noise, DM)
Parameters:
  • mode (int | tuple[int]) – The mode the channel is applied to.

  • phase_stdev (float | Parameter) – The standard deviation of the random phase noise.

  • name (str | None) – A name for the channel. If not provided, the class name will be used.

The Fock representation is connected to the Fourier coefficients of the distribution.

Pgate

class mrmustard.lab.transformations.Pgate(mode, shearing=0.0, name=None)[source]

Bases: Unitary

Quadratic phase gate.

Parameters:
  • modes – The modes this gate is applied to.

  • shearing (float | Sequence[float] | Parameter) – The shearing parameter.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

  • mode (int | tuple[int])

The quadratic phase gate is defined as

\[P = \exp(i s q^2 / 2 \hbar)\]

Reference: https://strawberryfields.ai/photonics/conventions/gates.html

RealInterferometer

class mrmustard.lab.transformations.RealInterferometer(modes, orthogonal, name=None)[source]

Bases: Unitary

N-mode interferometer parametrized by an NxN orthogonal matrix (or 2N x 2N block-diagonal orthogonal matrix). Does not mix q’s and p’s.

>>> from mrmustard import math
>>> from mrmustard.lab import RealInterferometer, Identity
>>> ri = RealInterferometer([0, 1], orthogonal = math.eye(2))
>>> assert ri == Identity((0,1))
Parameters:
  • modes (int | tuple[int, ...]) – The modes this gate is applied to.

  • orthogonal (RealMatrix | Parameter) – A real unitary (orthogonal) matrix. For N modes it must have shape (N,N).

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

classmethod random(modes, seed=None, name=None)[source]

Returns a random RealInterferometer.

Parameters:
  • modes (int | tuple[int, ...]) – The modes of the RealInterferometer.

  • seed (int | None) – The random seed. If None, the global seed is used.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

Returns:

The random RealInterferometer.

Raises:

ValueError – if modes is an empty tuple.

Return type:

RealInterferometer

Rgate

class mrmustard.lab.transformations.Rgate(mode, theta=0.0, name=None)[source]

Bases: Unitary

The rotation gate.

>>> from mrmustard.lab import Rgate
>>> unitary = Rgate(mode=1, theta=0.1)
>>> assert unitary.modes == (1,)
Parameters:
  • mode (int | tuple[int]) – The mode this gate is applied to.

  • theta (float | Sequence[float] | Parameter) – The rotation angle.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

S2gate

class mrmustard.lab.transformations.S2gate(modes, r=0.0, phi=0.0, name=None)[source]

Bases: Unitary

The two-mode squeezing gate.

>>> from mrmustard.lab import S2gate
>>> unitary = S2gate(modes=(1, 2), r=1)
>>> assert unitary.modes == (1, 2)
>>> assert unitary.parameters.r.value == 1
>>> assert unitary.parameters.phi.value == 0.0
Parameters:
  • modes (tuple[int, int]) – The pair of modes of the two-mode squeezing gate.

  • r (float | Sequence[float] | Parameter) – The squeezing amplitude.

  • phi (float | Sequence[float] | Parameter) – The phase angle.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

Its (A,b,c) triple is given by

\[\begin{split}A = \begin{bmatrix} O & e^{i\phi}\tanh(r) & \sech(r) & 0 \\ e^{i\phi}\tanh(r) & 0 & 0 & \sech(r) \\ \sech(r) & & 0 & 0 -e^{i\phi}\tanh(r) \\ O & \sech(r) & -e^{i\phi}\tanh(r) & 0 \end{bmatrix} \text{, } b = O_{4} \text{, and } c = \sech(r)\end{split}\]

Sgate

class mrmustard.lab.transformations.Sgate(mode, r=0.0, phi=0.0, name=None)[source]

Bases: Unitary

The squeezing gate.

>>> from mrmustard.lab import Sgate
>>> unitary = Sgate(mode=1, r=0.1, phi=0.2)
>>> assert unitary.modes == (1,)
>>> assert unitary.parameters.r.value == 0.1
>>> assert unitary.parameters.phi.value == 0.2
Parameters:
  • mode (int | tuple[int]) – The mode this gate is applied to.

  • r (float | Sequence[float] | Parameter) – The squeezing magnitude.

  • phi (float | Sequence[float] | Parameter) – The squeezing angle.

  • name (str | None) – A name for the gate. If not provided, the class name will be used.

For any \(\bar{r}\) and \(\bar{\phi}\) of length \(N\), the \(N\)-mode squeezing gate is defined by

\[\begin{split}S = \begin{bmatrix} \text{diag}_N(\text{cosh}(\bar{r})) & \text{diag}_N(e^{-i\bar{\phi}}\text{sinh}(\bar{r}))\\ -\text{diag}_N(e^{i\bar{\phi}}\text{sinh}(\bar{r})) & \text{diag}_N(\text{cosh}(\bar{r})) \end{bmatrix} \text{ and } d = O_{2N},\end{split}\]

where \(\text{diag}_N(\bar{a})\) is the \(N\text{x}N\) matrix with diagonal \(\bar{a}\). Its (A,b,c) triple is given by

\[\begin{split}A &= \begin{bmatrix} -\text{diag}_N(e^{i\bar{\phi}}\text{tanh}(\bar{r})) & \text{diag}_N(\text{sech}(\bar{r}))\\ \text{diag}_N(\text{sech}(\bar{r})) & \text{diag}_N(e^{-i\bar{\phi}}\text{tanh}(\bar{r})) \end{bmatrix} \\ \\ b &= O_{2N} \\ \\ c &= \prod_{i=1}^N\sqrt{\text{sech}{\:r_i}}\:.\end{split}\]

Transformation

class mrmustard.lab.transformations.Transformation(ansatz_factory=None, wires=None, name=None)[source]

Bases: CircuitComponent

Base class for all transformations.

Parameters:
abstract classmethod from_ansatz(modes_out, modes_in, ansatz=None, name=None)[source]

Initializes a transformation of type cls given modes and an ansatz.

Parameters:
  • modes_out (Sequence[int]) – The output modes of this transformation.

  • modes_in (Sequence[int]) – The input modes of this transformation.

  • ansatz (PolyExpAnsatz | ArrayAnsatz | None) – The ansatz of this transformation.

  • name (str | None) – The name of this transformation.

Returns:

A transformation.

Return type:

Self

classmethod from_bargmann(modes_out, modes_in, triple, name=None)[source]

Initialize a Transformation from the given Bargmann triple (A,b,c) which parametrizes the Bargmann function of the transformation as \(c * exp(0.5*z^T A z + b^T z)\).

Parameters:
  • modes_out (Sequence[int])

  • modes_in (Sequence[int])

  • triple (tuple)

  • name (str | None)

Return type:

Self

classmethod from_fock(modes_out, modes_in, array, batch_dims=0, name=None)[source]

Initializes a transformation of type cls given modes and a fock array.

Parameters:
  • modes_out (Sequence[int]) – The output modes of this transformation.

  • modes_in (Sequence[int]) – The input modes of this transformation.

  • array (ComplexTensor) – The fock array of this transformation.

  • batch_dims (int) – The number of batch dimensions in the given array.

  • name (str | None) – The name of this transformation.

Returns:

A transformation in the Fock representation.

Return type:

Self

classmethod from_quadrature(modes_out, modes_in, triple, phi=0, name=None)[source]

Initialize a Transformation from the given quadrature triple (A, b, c). The triple parametrizes the quadrature representation of the transformation as \(c * exp(0.5*x^T A x + b^T x)\).

Parameters:
  • modes_out (Sequence[int])

  • modes_in (Sequence[int])

  • triple (tuple)

  • phi (float)

  • name (str | None)

Return type:

Self

inverse()[source]

Returns the mathematical inverse of the transformation, if it exists. Note that it can be unphysical, for example when the original is not unitary.

>>> from mrmustard.lab import GaussianDM, Identity, Operation
>>> rho = GaussianDM.random(modes=0, seed=1)
>>> rho_as_operator = Operation.from_bargmann([0], [0], rho.ansatz.triple)
>>> assert rho_as_operator >> rho_as_operator.inverse() == Identity([0])
Returns:

The inverse of the transformation.

Raises:
  • NotImplementedError – If the input and output wires have different lengths.

  • NotImplementedError – If the transformation is not in the Bargmann representation.

Return type:

Transformation

Unitary

class mrmustard.lab.transformations.Unitary(ansatz_factory=None, wires=None, name=None)[source]

Bases: Operation

Base class for all unitary transformations.

Parameters:
property symplectic

Returns the symplectic matrix that corresponds to this unitary.

classmethod from_ansatz(modes_out, modes_in, ansatz=None, name=None)[source]

Initializes a transformation of type cls given modes and an ansatz.

Parameters:
  • modes_out (Sequence[int]) – The output modes of this transformation.

  • modes_in (Sequence[int]) – The input modes of this transformation.

  • ansatz (PolyExpAnsatz | ArrayAnsatz | None) – The ansatz of this transformation.

  • name (str | None) – The name of this transformation.

Returns:

A transformation.

Return type:

Unitary

classmethod from_symplectic(modes, S, name=None)[source]

A method for constructing a Unitary from its symplectic representation.

>>> from mrmustard import math
>>> from mrmustard.lab import Unitary, Identity
>>> S = math.eye(2)
>>> U = Unitary.from_symplectic([0], S)
>>> assert U == Identity([0])
Parameters:
  • modes (Sequence[int]) – the modes that we want the unitary to act on (should be a list of int)

  • S (RealMatrix) – the symplectic representation (in XXPP order)

  • name (str | None) – A name for the unitary. If not provided, the class name will be used.

Return type:

Unitary

classmethod random(modes, max_r=1.0, seed=None, name=None)[source]

Returns a random unitary.

>>> from mrmustard.lab import Unitary
>>> U = Unitary.random((0, 1, 2), max_r=1.2)
>>> assert U.modes == (0,1,2)
Parameters:
  • modes (int | tuple[int, ...]) – The modes of the unitary.

  • max_r (float) – The maximum squeezing parameter.

  • seed (int | None) – The random seed. If None, the global seed is used.

  • name (str | None) – A name for the unitary. If not provided, the class name will be used.

Returns:

The random Unitary.

Raises:

ValueError – if modes is an empty tuple.

Return type:

Unitary

inverse()[source]

Returns the inverse of the unitary.

>>> from mrmustard.lab import Unitary, Identity
>>> u = Unitary.random((0, 1, 2))
>>> assert u >> u.inverse() == Identity(u.modes)
Return type:

Unitary