Matrix decompositions

Module name: strawberryfields.decompositions

This module implements common shared matrix decompositions that are used to perform gate decompositions.

Functions

takagi(N[, tol, rounding]) Autonne-Takagi decomposition of a complex symmetric (not Hermitian!) matrix.
graph_embed(A[, mean_photon_per_mode, …]) Embed a graph into a Gaussian state.
rectangular(V[, tol]) Rectangular decomposition of a unitary matrix, with local phase shifts applied between two interferometers.
rectangular_phase_end(V[, tol]) Rectangular decomposition of a unitary matrix, with all local phase shifts placed after the interferometers.
rectangular_symmetric(V[, tol]) Decomposition of a unitary into an array of symmetric beamsplitters.
triangular(V[, tol]) Triangular decomposition of a unitary matrix due to Reck et al.
williamson(V[, tol]) Williamson decomposition of positive-definite (real) symmetric matrix.
bloch_messiah(S[, tol, rounding]) Bloch-Messiah decomposition of a symplectic matrix.
covmat_to_hamil(V[, tol]) Converts a covariance matrix to a Hamiltonian.
hamil_to_covmat(H[, tol]) Converts a Hamiltonian matrix to a covariance matrix.

Code details

strawberryfields.decompositions.takagi(N, tol=1e-13, rounding=13)[source]

Autonne-Takagi decomposition of a complex symmetric (not Hermitian!) matrix.

Note that singular values of N are considered equal if they are equal after np.round(values, tol).

See [41] and references therein for a derivation.

Parameters:
  • N (array[complex]) – square, symmetric matrix N
  • rounding (int) – the number of decimal places to use when rounding the singular values of N
  • tol (float) – the tolerance used when checking if the input matrix is symmetric: \(|N-N^T| <\) tol
Returns:

(rl, U), where rl are the (rounded) singular values,

and U is the Takagi unitary, such that \(N = U \diag(rl) U^T\).

Return type:

tuple[array, array]

strawberryfields.decompositions.graph_embed_deprecated(A, max_mean_photon=1.0, make_traceless=False, rtol=1e-05, atol=1e-08)[source]

Embed a graph into a Gaussian state.

Note: The default behaviour of graph embedding has been changed; see graph_embed(). This version is deprecated, but has been kept for consistency.

Given a graph in terms of a symmetric adjacency matrix (in general with arbitrary complex off-diagonal and real diagonal entries), returns the squeezing parameters and interferometer necessary for creating the Gaussian state whose off-diagonal parts are proportional to that matrix.

Uses takagi().

Parameters:
  • A (array[complex]) – square, symmetric (weighted) adjacency matrix of the graph
  • max_mean_photon (float) – Threshold value. It guarantees that the mode with the largest squeezing has max_mean_photon as the mean photon number i.e., \(sinh(r_{max})^2 ==\) :code:max_mean_photon.
  • make_traceless (bool) – Removes the trace of the input matrix, by performing the transformation \(\tilde{A} = A-\mathrm{tr}(A) \I/n\). This may reduce the amount of squeezing needed to encode the graph but will lead to different photon number statistics for events with more than one photon in any mode.
  • rtol (float) – relative tolerance used when checking if the input matrix is symmetric
  • atol (float) – absolute tolerance used when checking if the input matrix is symmetric
Returns:

squeezing parameters of the input

state to the interferometer, and the unitary matrix representing the interferometer

Return type:

tuple[array, array]

strawberryfields.decompositions.graph_embed(A, mean_photon_per_mode=1.0, make_traceless=False, rtol=1e-05, atol=1e-08)[source]

Embed a graph into a Gaussian state.

Given a graph in terms of a symmetric adjacency matrix (in general with arbitrary complex entries), returns the squeezing parameters and interferometer necessary for creating the Gaussian state whose off-diagonal parts are proportional to that matrix.

Uses takagi().

Parameters:
  • A (array[complex]) – square, symmetric (weighted) adjacency matrix of the graph
  • mean_photon_per_mode (float) – guarantees that the mean photon number in the pure Gaussian state representing the graph satisfies \(\frac{1}{N}\sum_{i=1}^N sinh(r_{i})^2 ==\) :code:mean_photon
  • make_traceless (bool) – Removes the trace of the input matrix, by performing the transformation \(\tilde{A} = A-\mathrm{tr}(A) \I/n\). This may reduce the amount of squeezing needed to encode the graph but will lead to different photon number statistics for events with more than one photon in any mode.
  • rtol (float) – relative tolerance used when checking if the input matrix is symmetric
  • atol (float) – absolute tolerance used when checking if the input matrix is symmetric
Returns:

squeezing parameters of the input state to the interferometer, and the unitary matrix representing the interferometer

Return type:

tuple[array, array]

strawberryfields.decompositions.bipartite_graph_embed(A, mean_photon_per_mode=1.0, rtol=1e-05, atol=1e-08)[source]

Embed a bipartite graph into a Gaussian state.

Given a bipartite graph in terms of an adjacency matrix (in general with arbitrary complex entries), returns the two-mode squeezing parameters and interferometers necessary for creating the Gaussian state that encodes such adjacency matrix

Uses takagi().

Parameters:
  • A (array[complex]) – square, (weighted) adjacency matrix of the bipartite graph
  • mean_photon_per_mode (float) – guarantees that the mean photon number in the pure Gaussian state representing the graph satisfies \(\frac{1}{N}\sum_{i=1}^N sinh(r_{i})^2 ==\) :code:mean_photon
  • rtol (float) – relative tolerance used when checking if the input matrix is symmetric
  • atol (float) – absolute tolerance used when checking if the input matrix is symmetric
Returns:

squeezing parameters of the input state to the interferometer, and the unitaries matrix representing the interferometer

Return type:

tuple[array, array, array]

strawberryfields.decompositions.T(m, n, theta, phi, nmax)[source]

The Clements T matrix from Eq. 1 of the paper

strawberryfields.decompositions.Ti(m, n, theta, phi, nmax)[source]

The inverse Clements T matrix

strawberryfields.decompositions.nullTi(m, n, U)[source]

Nullifies element m,n of U using Ti

strawberryfields.decompositions.nullT(n, m, U)[source]

Nullifies element n,m of U using T

strawberryfields.decompositions.rectangular(V, tol=1e-11)[source]

Rectangular decomposition of a unitary matrix, with local phase shifts applied between two interferometers.

See Rectangular decomposition or [6] for more details.

This function returns a circuit corresponding to an intermediate step in the decomposition as described in Eq. 4 of the article. In this form, the circuit comprises some T matrices (as in Eq. 1), then phases on all modes, and more T matrices.

The procedure to construct these matrices is detailed in the supplementary material of the article.

Parameters:
  • V (array[complex]) – unitary matrix of size n_size
  • tol (float) – the tolerance used when checking if the matrix is unitary: \(|VV^\dagger-I| \leq\) tol
Returns:

tuple of the form (tilist,np.diag(localV),tlist)

where:

  • tilist: list containing [n,m,theta,phi,n_size] of the Ti unitaries needed
  • tlist: list containing [n,m,theta,phi,n_size] of the T unitaries needed
  • localV: Diagonal unitary sitting sandwiched by Ti’s and the T’s

Return type:

tuple[array]

strawberryfields.decompositions.rectangular_phase_end(V, tol=1e-11)[source]

Rectangular decomposition of a unitary matrix, with all local phase shifts placed after the interferometers.

See [6] for more details.

Final step in the decomposition of a given discrete unitary matrix. The output is of the form given in Eq. 5.

Parameters:
  • V (array[complex]) – unitary matrix of size n_size
  • tol (float) – the tolerance used when checking if the matrix is unitary: \(|VV^\dagger-I| \leq\) tol
Returns:

returns a tuple of the form (tlist, np.diag(localV), None)

where:

  • tlist: list containing [n,m,theta,phi,n_size] of the T unitaries needed
  • localV: Diagonal unitary matrix to be applied at the end of circuit

Return type:

tuple[array]

strawberryfields.decompositions.mach_zehnder(m, n, internal_phase, external_phase, nmax)[source]

A two-mode Mach-Zehnder interferometer section.

This section is constructed by an external phase shifter on the input mode m, a symmetric beamsplitter combining modes m and n, an internal phase shifter on mode m, and another symmetric beamsplitter combining modes m and n.

strawberryfields.decompositions.rectangular_symmetric(V, tol=1e-11)[source]

Decomposition of a unitary into an array of symmetric beamsplitters.

This decomposition starts with the output from rectangular_phase_end() and further decomposes each of the T unitaries into Mach-Zehnder interferometers consisting of two phase-shifters and two symmetric (50:50) beamsplitters.

The two beamsplitters in this decomposition of T are modeled by BSgate with arguments \((\pi/4, \pi/2)\), and the two phase-shifters (see Rgate) act on the input mode with the lower index of the two. The phase imposed by the first phaseshifter (before the first beamsplitter) is named external_phase, while we call the phase shift between the beamsplitters internal_phase.

The algorithm applied in this function makes use of the following identity:

Rgate(alpha) | 1
Rgate(beta) | 2
Rgate(phi) | 1
BSgate(theta, 0) | 1, 2

equals

Rgate(phi+alpha-beta) | 1
BSgate(pi/4, pi/2) | 1, 2
Rgate(2*theta+pi) | 1, 2
BSgate(pi/4, pi/2) | 1, 2
Rgate(beta-theta+pi) | 1
Rgate(beta-theta) | 2

The phase-shifts by alpha and beta are thus pushed consecutively through all the T unitaries of the interferometer and these unitaries are converted into pairs of symmetric beamsplitters with two phase shifts. The phase shifts at the end of the interferometer are added to the ones from the diagonal unitary at the end of the interferometer obtained from rectangular_phase_end().

Parameters:
  • V (array) – unitary matrix of size n_size
  • tol (int) – the number of decimal places to use when determining whether the matrix is unitary
Returns:

returns a tuple of the form (tlist,np.diag(localV), None)

where:

  • tlist: list containing [n,m,internal_phase,external_phase,n_size] of the T unitaries needed
  • localV: Diagonal unitary matrix to be applied at the end of circuit

Return type:

tuple[array]

strawberryfields.decompositions.triangular(V, tol=1e-11)[source]

Triangular decomposition of a unitary matrix due to Reck et al.

See [5] for more details and [6] for details on notation.

Parameters:
  • V (array[complex]) – unitary matrix of size n_size
  • tol (float) – the tolerance used when checking if the matrix is unitary: \(|VV^\dagger-I| \leq\) tol
Returns:

returns a tuple of the form (tlist,np.diag(localV), None)

where:

  • tlist: list containing [n,m,theta,phi,n_size] of the T unitaries needed
  • localV: Diagonal unitary applied at the beginning of circuit

Return type:

tuple[array]

strawberryfields.decompositions.williamson(V, tol=1e-11)[source]

Williamson decomposition of positive-definite (real) symmetric matrix.

See Williamson decomposition.

Note that it is assumed that the symplectic form is

\[\begin{split}\Omega = \begin{bmatrix}0&I\\-I&0\end{bmatrix}\end{split}\]

where \(I\) is the identity matrix and \(0\) is the zero matrix.

See https://math.stackexchange.com/questions/1171842/finding-the-symplectic-matrix-in-williamsons-theorem/2682630#2682630

Parameters:
  • V (array[float]) – positive definite symmetric (real) matrix
  • tol (float) – the tolerance used when checking if the matrix is symmetric: \(|V-V^T| \leq\) tol
Returns:

(Db, S) where Db is a diagonal matrix

and S is a symplectic matrix such that \(V = S^T Db S\)

Return type:

tuple[array,array]

strawberryfields.decompositions.bloch_messiah(S, tol=1e-10, rounding=9)[source]

Bloch-Messiah decomposition of a symplectic matrix.

See Bloch-Messiah (or Euler) decomposition.

Decomposes a symplectic matrix into two symplectic unitaries and squeezing transformation. It automatically sorts the squeezers so that they respect the canonical symplectic form.

Note that it is assumed that the symplectic form is

\[\begin{split}\Omega = \begin{bmatrix}0&I\\-I&0\end{bmatrix}\end{split}\]

where \(I\) is the identity matrix and \(0\) is the zero matrix.

As in the Takagi decomposition, the singular values of N are considered equal if they are equal after np.round(values, rounding).

If S is a passive transformation, then return the S as the first passive transformation, and set the the squeezing and second unitary matrices to identity. This choice is not unique.

For more info see: https://math.stackexchange.com/questions/1886038/finding-euler-decomposition-of-a-symplectic-matrix

Parameters:
  • S (array[float]) – symplectic matrix
  • tol (float) – the tolerance used when checking if the matrix is symplectic: \(|S^T\Omega S-\Omega| \leq tol\)
  • rounding (int) – the number of decimal places to use when rounding the singular values
Returns:

Returns the tuple (ut1, st1, vt1). ut1 and vt1 are symplectic orthogonal,

and st1 is diagonal and of the form \(= \text{diag}(s1,\dots,s_n, 1/s_1,\dots,1/s_n)\) such that \(S = ut1 st1 v1\)

Return type:

tuple[array]

strawberryfields.decompositions.covmat_to_hamil(V, tol=1e-10)[source]

Converts a covariance matrix to a Hamiltonian.

Given a covariance matrix V of a Gaussian state \(\rho\) in the xp ordering, finds a positive matrix \(H\) such that

\[\rho = \exp(-Q^T H Q/2)/Z\]

where \(Q = (x_1,\dots,x_n,p_1,\dots,p_n)\) are the canonical operators, and Z is the partition function.

For more details, see https://arxiv.org/abs/1507.01941

Parameters:
  • V (array) – Gaussian covariance matrix
  • tol (int) – the number of decimal places to use when determining if the matrix is symmetric
Returns:

positive definite Hamiltonian matrix

Return type:

array

strawberryfields.decompositions.hamil_to_covmat(H, tol=1e-10)[source]

Converts a Hamiltonian matrix to a covariance matrix.

Given a Hamiltonian matrix of a Gaussian state H, finds the equivalent covariance matrix V in the xp ordering.

For more details, see https://arxiv.org/abs/1507.01941

Parameters:
  • H (array) – positive definite Hamiltonian matrix
  • tol (int) – the number of decimal places to use when determining if the Hamiltonian is symmetric
Returns:

Gaussian covariance matrix

Return type:

array