Decompositions

The available decompositions in Piquasso.

Clements decomposition

An implementation for the Clements decomposition.

class BS(modes: Tuple[int, int], params: Tuple[np.float64, np.float64])

Beamsplitter gate, implemented as described in arXiv:1603.08788.

The single-particle unitary matrix corresponding to the beamsplitter is

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

Note

This means a different beamsplitter gate as defined by Beamsplitter.

class PS(mode: int, phi: np.float64)

Phaseshifter gate, corresponding to Phaseshifter.

class Decomposition(beamsplitters: List[BS], phaseshifters: List[PS])

The data stucture which holds the decomposed angles from the Clements decomposition.

Example usage:

decomposition = clements(U, connector=pq.NumpyConnector())

with pq.Program() as program:
    ...

    for operation in decomposition.beamsplitters:
        pq.Q(operation.modes[0]) | pq.Phaseshifter(phi=operation.params[1])
        pq.Q(*operation.modes) | pq.Beamsplitter(operation.params[0], 0.0)

    for operation in decomposition.phaseshifters:
        pq.Q(operation.mode) | pq.Phaseshifter(operation.phi)
instructions_from_decomposition(decomposition)

Helper function for using the Clements decomposition.

This function creates the list of Beamsplitter and Phaseshifter instructions to be applied to the program, which is equivalent to the decomposed interferometer.

Example usage:

decomposition = clements(U, connector=pq.NumpyConnector())

with pq.Program() as program:
    ...

    program.instructions.extend(instructions_from_decomposition(decomposition))

Or, one can use it as:

decomposition = clements(U, connector=pq.NumpyConnector())

program_with_decomposition = pq.Program(
    instructions=[...] + instructions_from_decomposition(decomposition)
)
Parameters:

decomposition (Decomposition) – Decomposition created by clements().

Returns:

List of beamsplitter and phaseshifter gates to be applied.

Return type:

list

inverse_clements(decomposition: Decomposition, connector: BaseConnector, dtype: np.dtype) np.ndarray

Inverse of the Clements decomposition.

Returns:

The unitary matrix corresponding to the interferometer.

clements(U: np.ndarray, connector: BaseConnector) Decomposition

Decomposes the specified unitary matrix by application of beamsplitters prescribed by the decomposition.

Parameters:

U (numpy.ndarray) – The unitary matrix to be decomposed.

Returns:

The Clements decomposition. See Decomposition.

get_weights_from_decomposition(decomposition: Decomposition, d: int, connector: BaseConnector) np.ndarray

Concatenates the weight vector from the angles in the Clements decomposition.

Returns:

The Clements decomposition. See Decomposition.

get_decomposition_from_weights(weights: np.ndarray, d: int, connector: BaseConnector) Decomposition

Puts the data in the weight vector into a Clements decompositon.

Returns:

The Clements decomposition. See Decomposition.

get_weights_from_interferometer(U: np.ndarray, connector: BaseConnector) np.ndarray

Creates a vector of weights from the Clements angles.

get_interferometer_from_weights(weights: np.ndarray, d: int, connector: BaseConnector, dtype: np.dtype) np.ndarray

Returns the interferometer matrix corresponding to the specified weights.

It is the inverse of get_weights_from_interferometer().

References:
  • W. R. Clements, P. C. Humphreys, B. J. Metcalf, W. S. Kolthammer, I. A. Walmsley, “An Optimal Design for Universal Multiport Interferometers”, Optica 3, 1460-1465 (2016), arXiv:1603.08788.