Circuit Components¶
A base class for the circuit components (states, transformations, measurements, and any component made by combining CircuitComponents). |
CircuitComponent¶
- class mrmustard.lab.circuit_components.CircuitComponent(ansatz_factory=None, wires=None, name=None)[source]¶
A base class for the circuit components (states, transformations, measurements, and any component made by combining CircuitComponents). CircuitComponents are defined by their
ansatzandwires.- Parameters:
ansatz_factory (AnsatzFactory | None) – The AnsatzFactory of this circuit component.
wires (Wires | None) – The wires of this circuit component.
name (str | None) – The name of this circuit component.
- property adjoint: CircuitComponent¶
The adjoint of this component obtained by conjugating the ansatz and swapping the ket and bra wires.
>>> from mrmustard.lab import GaussianKet >>> psi = GaussianKet.random([0]) >>> assert psi.dm() == psi.contract(psi.adjoint)
Note
The resulting CircuitComponent is not in standard order. To get the standard order, call
to_standard_order()on the result.
- property ansatz_factory: AnsatzFactory¶
The ansatz factory of this component.
- Raises:
AttributeError – If the component has no
AnsatzFactory.
- property dual: CircuitComponent¶
The dual of this component obtained by conjugating the ansatz and swapping the input and output wires.
>>> from mrmustard import math >>> from mrmustard.lab import GaussianKet >>> psi = GaussianKet.random([0]) >>> assert math.allclose(1.0, psi >> psi.dual)
Note
The resulting CircuitComponent is not in standard order. To get the standard order, call
to_standard_order()on the result.
- property manual_shape: tuple[int | None, ...]¶
The shape of this Component in the Fock representation in standard order. For each wire, the entry is either an integer or
None. If it is an integer, it is the shape (dimension) of the corresponding Fock space. For a cutoff of n (maximum photon number n), the shape is n + 1 (includes \(\left\vert 0\right\rangle\) through \(\left\vert n\right\rangle\)). If it isNone, it means the best shape is not known yet and will be determined byauto_shape.
- property modes: tuple[int, ...]¶
The sorted tuple of modes of this component.
>>> from mrmustard.lab import GaussianKet >>> ket = GaussianKet.random([0, 1]) >>> assert ket.modes == (0, 1)
- property name: str¶
The name of this component.
>>> from mrmustard.lab import BtoPS >>> assert BtoPS(modes=0, s=0).name == "BtoPS"
- property n_modes: int¶
The number of modes spanned by this component across all wires.
>>> from mrmustard.lab import GaussianKet >>> ket = GaussianKet.random([0, 1]) >>> assert ket.n_modes == 2
- property parameters: ParameterDict¶
The parameters of this component.
- classmethod from_bargmann(triple, modes_out_bra=(), modes_in_bra=(), modes_out_ket=(), modes_in_ket=(), name=None)[source]¶
Initializes a
CircuitComponentobject from its Bargmann (A,b,c) parametrization.>>> from mrmustard import math >>> from mrmustard.lab import CircuitComponent, Identity >>> from mrmustard.physics.ansatz import PolyExpAnsatz >>> A = math.astensor([[0, 1], [1, 0]]) >>> b = math.astensor([0, 0]) >>> c = 1 >>> modes_out_bra = {} >>> modes_in_bra = {} >>> modes_out_ket = {0} >>> modes_in_ket = {0} >>> triple = (A, b, c) >>> cc = CircuitComponent.from_bargmann(triple, modes_out_bra, modes_in_bra, modes_out_ket, modes_in_ket) >>> assert isinstance(cc.ansatz, PolyExpAnsatz) >>> assert cc == Identity(modes = 0)
- Parameters:
triple (tuple) – The Bargmann representation of the component.
modes_out_bra (Sequence[int]) – The output modes on the bra side of this component.
modes_in_bra (Sequence[int]) – The input modes on the bra side of this component.
modes_out_ket (Sequence[int]) – The output modes on the ket side of this component.
modes_in_ket (Sequence[int]) – The input modes on the ket side of this component.
name (str | None) – The name of this component.
- Returns:
A circuit component with the given Bargmann representation.
- Return type:
- classmethod from_fock(array, batch_dims, modes_out_bra=(), modes_in_bra=(), modes_out_ket=(), modes_in_ket=(), name=None)[source]¶
Initializes a
CircuitComponentobject from its Fock parametrization.- Parameters:
array (ComplexTensor) – The Fock array of the component.
batch_dims (int) – The number of batch dimensions in the given array.
modes_out_bra (Sequence[int]) – The output modes on the bra side of this component.
modes_in_bra (Sequence[int]) – The input modes on the bra side of this component.
modes_out_ket (Sequence[int]) – The output modes on the ket side of this component.
modes_in_ket (Sequence[int]) – The input modes on the ket side of this component.
name (str | None) – The name of this component.
- Returns:
A
CircuitComponentwith the given Fock representation.- Raises:
ValueError – If the given array has a shape that is inconsistent with the number of modes.
- Return type:
- classmethod from_quadrature(modes_out_bra, modes_in_bra, modes_out_ket, modes_in_ket, triple, phi=0.0, name=None)[source]¶
Returns a circuit component from the given triple (A,b,c) that parametrizes the quadrature wavefunction of this component in the form \(c * exp(1/2 x^T A x + b^T x)\).
- Parameters:
modes_out_bra (Sequence[int]) – The output modes on the bra side of this component.
modes_in_bra (Sequence[int]) – The input modes on the bra side of this component.
modes_out_ket (Sequence[int]) – The output modes on the ket side of this component.
modes_in_ket (Sequence[int]) – The input modes on the ket side of this component.
triple (tuple) – The (A,b,c) triple that parametrizes the wave function.
phi (float) – The quadrature angle.
0corresponds to the x quadrature,pi/2to the p quadrature.name (str | None) – The name of this component.
- Returns:
A circuit component with the given quadrature representation.
- Return type:
- auto_shape(**_)[source]¶
The shape of the Fock representation of this component. If the component has a Fock representation then it is just the shape of the array. If the component is a
Statein Bargmann then the shape is calculated usingautoshapeusing single-mode marginals. If the component is not aStatethen the shape is a tuple ofsettings.DEFAULT_FOCK_SIZEvalues except where themanual_shapeattribute has been set.- Return type:
tuple[int, …]
- bargmann_triple()[source]¶
The Bargmann parametrization of this component, if available. It returns a triple (A, b, c) such that the Bargmann function of this component is \(F(z) = c \exp\left(\frac{1}{2} z^T A z + b^T z\right)\).
>>> from mrmustard.lab import CircuitComponent, Coherent >>> coh = Coherent(mode=0, alpha=1.0) >>> coh_cc = CircuitComponent.from_bargmann(coh.bargmann_triple(), modes_out_ket=(0,)) >>> assert isinstance(coh_cc, CircuitComponent) >>> assert coh == coh_cc # equality looks at representation and wires
- Returns:
The Bargmann triple of this component.
- Raises:
AttributeError – If the component has no Bargmann data.
- Return type:
tuple[mrmustard.utils.typing.ComplexMatrix, mrmustard.utils.typing.ComplexVector, mrmustard.utils.typing.ComplexScalar]
- contract(other)[source]¶
Contracts
selfandotherwithout adding adjoints. Core index selection is determined solely by the wires; batch dimensions are broadcast automatically by the underlying ansatz implementations.For example, a coherent state can be input to an attenuator, but the attenuator has two inputs: on the ket and the bra side. The
>>operator would automatically add the adjoint of the coherent state on the bra side of the input of the attenuator, butcontractinstead does not.>>> from mrmustard.lab import Coherent, Attenuator >>> coh = Coherent(0, 1.0) >>> att = Attenuator(0, 0.5) >>> assert coh.contract(att).wires.input.bra # the input bra is still uncontracted
- Parameters:
other (CircuitComponent | Scalar) – The other component to contract with.
- Returns:
The contracted component.
- Return type:
- concat(other, axis=0)[source]¶
Concatenates this component with another along the specified batch axis.
The ansatze are concatenated along the given batch axis. The wires must match. Returns an instance of the closest common superclass.
>>> from mrmustard.lab import Coherent >>> state1 = Coherent(mode=0, alpha=1.0) >>> state2 = Coherent(mode=0, alpha=2.0) >>> # Add batch dimension first >>> state1_batched = state1[None] >>> state2_batched = state2[None] >>> concatenated = state1_batched.concat(state2_batched, axis=0) >>> assert concatenated.ansatz.batch_shape == (2,)
- Parameters:
other (CircuitComponent) – The other circuit component to concatenate with.
axis (int) – The batch axis along which to concatenate.
- Returns:
A new CircuitComponent with concatenated ansatze.
- Raises:
ValueError – If wires don’t match or if ansatz types don’t match.
- Return type:
- fock_array(shape=None)[source]¶
Returns an array representation of this component in the Fock basis with the given shape. If the shape is not given, it defaults to the
auto_shapeof the component.- Parameters:
shape (int | Sequence[int] | None) – The shape of the returned representation. If
shapeis given as anint, it is broadcasted to all the dimensions. If not given, it is generated viaauto_shape.- Returns:
The Fock representation of this component.
- Return type:
array
- Raises:
ValueError – If the shape is not valid for the component.
- on(modes)[source]¶
Creates a light copy of this component that acts on the given
modesinstead of the original modes. It only works if the component’s wires are all defined on the same modes. As a light copy, the returned component shares the representation with the original one.If a more general rewiring is needed, while maintaining a light copy to the original, use
._light_copy(new_wires)and pass the desired wires.- Parameters:
modes (int | Sequence[int]) – The new modes that this component acts on.
- Returns:
The component acting on the specified modes.
- Raises:
ValueError – If the component’s wires are not all defined on the same modes or if the length of the given modes is different from the length of the original modes.
- Return type:
- quadrature(*quad, phi=0.0)[source]¶
The (discretized) quadrature basis representation of the circuit component. This method considers the same basis in all the wires. For more fine-grained control, use the BtoQ transformation or a combination of transformations.
- Parameters:
quad (RealVector) – discretized quadrature points to evaluate over in the quadrature representation. One vector of points per wire.
phi (float) – The quadrature angle.
0corresponds to the x quadrature,pi/2to the p quadrature.
- Returns:
A circuit component with the given quadrature representation.
- Return type:
- quadrature_triple(phi=0.0)[source]¶
The quadrature representation triple A,b,c of this circuit component.
- Parameters:
phi (float) – The quadrature angle.
phi=0corresponds to the x quadrature,phi=pi/2to the p quadrature.- Returns:
A,b,c triple of the quadrature representation
- Return type:
tuple[mrmustard.utils.typing.ComplexMatrix, mrmustard.utils.typing.ComplexVector, mrmustard.utils.typing.ComplexScalar]
- stack(other, axis=0)[source]¶
Stacks this component with another along a new batch axis.
The two components must have the same wires and compatible ansatze. A new batch axis is inserted at the specified position.
>>> from mrmustard.lab import Coherent >>> state1 = Coherent(mode=0, alpha=1.0) >>> state2 = Coherent(mode=0, alpha=2.0) >>> stacked = state1.stack(state2, axis=0) >>> assert stacked.ansatz.batch_shape == (2,)
- Parameters:
other (CircuitComponent) – The other circuit component to stack with.
axis (int) – The position where the new batch axis will be inserted.
- Returns:
A new CircuitComponent with stacked ansatze.
- Raises:
ValueError – If wires don’t match, ansatz types don’t match, or axis is out of range.
- Return type:
- to_bargmann()[source]¶
Returns a new
CircuitComponentin theBargmannrepresentation.>>> from mrmustard.lab import Dgate, Number >>> from mrmustard.physics.ansatz import ArrayAnsatz, PolyExpAnsatz >>> d = Dgate(1, alpha=0.1 + 0.1j) >>> d_fock = d.to_fock(shape=3) >>> d_bargmann = d_fock.to_bargmann() >>> num = Number(0, n=2) >>> assert isinstance(num.ansatz, ArrayAnsatz) # in Fock representation >>> num_bargmann = num.to_bargmann() >>> assert isinstance(num_bargmann.ansatz, PolyExpAnsatz) # in Bargmann representation
- Returns:
A new
CircuitComponentin theBargmannrepresentation.- Return type:
- to_fock(shape=None)[source]¶
Returns a new
CircuitComponentin theFockrepresentation.>>> from mrmustard.lab import Dgate >>> from mrmustard.physics.ansatz import ArrayAnsatz, PolyExpAnsatz >>> d = Dgate(1, alpha=0.1 + 0.1j) >>> d_fock = d.to_fock(shape=3) >>> assert d_fock.name == d.name >>> assert isinstance(d.ansatz, PolyExpAnsatz) # in Bargmann representation >>> assert isinstance(d_fock.ansatz, ArrayAnsatz) # in Fock representation
- Parameters:
shape (int | Sequence[int] | None) – The shape of the returned representation. If
shapeis given as anint, it is broadcasted to all dimensions. IfNone, it is generated viaauto_shape.- Returns:
A new
CircuitComponentin theFockrepresentation.- Return type:
- to_quadrature(phi=0.0)[source]¶
Returns a circuit component with the quadrature representation of this component in terms of A,b,c.
- Parameters:
phi (float) – The quadrature angle.
0corresponds to the x quadrature,pi/2to the p quadrature.- Returns:
A circuit component with the given quadrature representation.
- Return type:
- to_standard_order()[source]¶
Reorders the ansatz and wires to the standard order.
- Returns:
A circuit component in the standard order.
- Return type:
- __rshift__(other)[source]¶
Contracts
selfandother(output of self going into input of other). It adds the adjoints when they are missing (e.g. ifselfis aKetandotheris aChannel). An error is raised if these cannot be deduced from the wires of the components. For example this allowsKetto be right-shifted intoChanneland automatically the result is aDM. If the result has no wires left, it returns the (batched) scalar value of the representation. Note that aCircuitComponentis allowed to right-shift into scalars because the scalar part may result from an automated contraction subroutine that involves several components).Note that the resulting component type is coerced based on the wires of the result:
Ket: only output ket wires remainDM: only output bra and ket on the same modes remainUnitary: only bra wires remainChannel: input bra and ket on the same modes and output bra and ket on the same modesCircuitComponent: otherwise
>>> from mrmustard.lab import Coherent, Attenuator, Ket, DM, Channel >>> state = Coherent(0, 1.0) >>> assert issubclass(Coherent, Ket) >>> assert issubclass(Attenuator, Channel) >>> assert isinstance(state >> Attenuator(0, 0.5), DM) >>> assert math.allclose(state >> state.dual, 1+0j)
- Parameters:
other (Scalar | CircuitComponent) – The other component or (batchable) scalar to contract with.
- Returns:
The contracted component or (batched) scalar value of the representation.
- Raises:
ValueError – If the component wires are incompatible with the other component.
- Return type: