# Source code for flamingpy.cv.ops

# Copyright 2022 Xanadu Quantum Technologies Inc.

# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# Unless required by applicable law or agreed to in writing, software
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
"""Continuous-variable operations, states, and noise models."""

# pylint: disable=import-outside-toplevel,too-many-instance-attributes

import numpy as np
from scipy.linalg import block_diag
import scipy.sparse as sp
from thewalrus.symplectic import expand, beam_splitter

[docs]def invert_permutation(p):
"""Invert the permutation associated with p."""
p_inverted = np.empty(p.size, p.dtype)
p_inverted[p] = np.arange(p.size)
return p_inverted

"""Return a symplectic matrix corresponding to CZ gate application.

Give the 2N by 2N symplectic matrix for CZ gate application based on the

(q1, ..., qN, p_1, ..., p_N).

Args:
adj (array): N by N binary symmetric matrix. If modes i and j are
linked by a CZ, then entry ij and ji is equal to the weight of the
edge (1 by default); otherwise 0.
sparse (bool): whether to return a sparse or dense array when adj
input is a sparse array.
Returns:
np.array or sp.sparse.csr_matrix: 2N by 2N symplectic matrix.
sparse if the adjacency matrix is sparse.
"""
# Number of modes
identity = np.eye(N, dtype=np.int8)
zeros = np.zeros((N, N), dtype=np.int8)
block_func = np.block
else:
identity = sp.identity(N, dtype=np.int8)
zeros = sp.csr_matrix((N, N), dtype=np.int8)
block_func = sp.bmat
# Construct symplectic
symplectic = block_func([[identity, zeros], [adj, identity]])

if not sparse and isinstance(symplectic, sp.coo_matrix):
return symplectic.toarray()

return symplectic

"""Apply SCZ matrix to one- or two-dimensional array quads.

If one-shot is True, use SCZ_mat to apply a symplectic CZ matrix to
block structure of a symplectic SCZ matrix for a more memory-
efficient matrix multiplication.
"""
if one_shot:
else:
if one_shot:
else:
new_quads = np.block([[c1, block2], [block3, block4]])

[docs]def splitter_symp(n=4):
"""Return the symplectic matrix of a four-splitter.

Return the symplectic matrix of the beamsplitters connecting the four
micronodes in each macronode. n refers to the total number of modes
(so n >= 4). If n = 4, return the matrix in the 'all q's first' convention;
otherwise, return a large block-diagonal matrix in the 'q1p1, ..., qnpn'
convention.

Args:
n (int, optional): the total number of modes on which the beamsplitters
apply (n must be >= 4).

Returns:
numpy.array: the sympletic matrix of the four-splitter.
"""
# 50/50 beamsplitter in the 'all q's first' convention.
bs5050 = beam_splitter(np.pi / 4, 0)
bs1 = expand(bs5050, [1, 0], 4)
bs2 = expand(bs5050, [3, 2], 4)
bs3 = expand(bs5050, [2, 0], 4)
bs4 = expand(bs5050, [3, 1], 4)
bs_network = (bs4 @ bs3 @ bs2 @ bs1).astype(np.single)
if n == 4:
return bs_network
if n > 4:
# Permutation away from 'all q's first' convention for matrices of
# with dimension 4 and the network spanning all the macronoes.
perm_out_4 = [0, 4, 1, 5, 2, 6, 3, 7]
bs_perm = bs_network[:, perm_out_4][perm_out_4, :]
# Symplectic corresponding to the beasmplitter network spanning
# the whole lattice.
bs_full = block_diag(*[bs_perm] * (n // 4))
return bs_full
else:
print("Total number of modes cannot be less than 4.")
raise Exception


Home

Background

Using FlamingPy

Development

Getting Help

Python API