From 896557c42f6ab07efed79fa402503628bd75bb23 Mon Sep 17 00:00:00 2001 From: Nicolas Quesada Date: Fri, 23 Apr 2021 14:18:56 -0400 Subject: [PATCH] Removing shared ops (#573) * removes unused variables in test_tdmprogram * updates test_decompositions_integration * updates ops.py * updates decompositions.py * updates backends/__init__py * updates states.py * updates strawberryfields/backends/gaussianbackend/gaussiancircuit.py * updates strawberryfields/backends/bosonicbackend/backend.py * updates strawberryfields/backends/gaussianbackend/backend.py * deletes shared_ops and its tests * Fixes williamson * unused import removed * unused import removed * updates backends/__init__.py * updates requirement.txt setup.py and CHANGELOG * Update strawberryfields/backends/__init__.py * Update .github/CHANGELOG.md * black * update test suite * update changelog * fix * fix * fix * fix * fix Co-authored-by: Josh Izaac --- .github/CHANGELOG.md | 9 ++++ .github/workflows/tests.yaml | 2 +- .readthedocs.yml | 2 +- doc/code/sf_decompositions.rst | 2 +- doc/requirements.txt | 5 +- requirements.txt | 6 +-- setup.py | 2 +- strawberryfields/backends/__init__.py | 11 ----- .../backends/bosonicbackend/backend.py | 6 +-- .../backends/gaussianbackend/backend.py | 7 +-- .../gaussianbackend/gaussiancircuit.py | 14 ++---- strawberryfields/backends/shared_ops.py | 41 ---------------- strawberryfields/backends/states.py | 6 +-- strawberryfields/decompositions.py | 10 ++-- strawberryfields/ops.py | 5 +- tests/backend/test_states_polyquad.py | 7 ++- tests/frontend/test_shared_ops.py | 49 ------------------- .../test_decompositions_integration.py | 41 +++++----------- 18 files changed, 50 insertions(+), 175 deletions(-) delete mode 100644 strawberryfields/backends/shared_ops.py delete mode 100644 tests/frontend/test_shared_ops.py diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 3631b3fdb..d12dbc4d7 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -123,6 +123,15 @@ method. [(#564)](https://github.com/XanaduAI/strawberryfields/pull/564) +* The backend utility module `shared_ops.py` has been removed, with all of its + functionality now provided by The Walrus. + [(#573)](https://github.com/XanaduAI/strawberryfields/pull/573) + +

Breaking changes

+ +* Removes support for Python 3.6. + [(#573)](https://github.com/XanaduAI/strawberryfields/pull/573) +

Bug fixes

* `Connection` objects now send requests to the platform API at version `0.2.0` diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index cf989d50e..a61d80bd0 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -41,7 +41,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.6 + python-version: 3.8 - name: Install dependencies run: | diff --git a/.readthedocs.yml b/.readthedocs.yml index 6daec9bc9..2de688ba5 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -4,7 +4,7 @@ sphinx: configuration: doc/conf.py python: - version: 3.6 + version: 3.8 install: - requirements: doc/requirements.txt - method: pip diff --git a/doc/code/sf_decompositions.rst b/doc/code/sf_decompositions.rst index cdfddb729..f60182356 100644 --- a/doc/code/sf_decompositions.rst +++ b/doc/code/sf_decompositions.rst @@ -15,4 +15,4 @@ sf.decompositions .. automodapi:: strawberryfields.decompositions :no-heading: :include-all-objects: - :skip: block_diag, sqrtm, polar, schur, sympmat, changebasis, adj_scaling + :skip: block_diag, sqrtm, polar, schur, sympmat, xpxp_to_xxpp, adj_scaling diff --git a/doc/requirements.txt b/doc/requirements.txt index 79f8b73e0..fa84097fa 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -4,7 +4,7 @@ ipykernel sphinx==2.2.2 m2r networkx>=2.0 -numpy>=1.16.3 +numpy>=1.20 plotly quantum-blackbird scipy>=1.0.0 @@ -13,6 +13,5 @@ sphinx-autodoc-typehints==1.10.3 sphinx-copybutton sphinx-automodapi sphinxcontrib-bibtex==0.4.2 -tensorflow-tensorboard==0.1.8 -tensorflow==2.0.3 +tensorflow==2.2.0 toml diff --git a/requirements.txt b/requirements.txt index ebb6c641d..467451b9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,12 @@ -numpy>=1.17.4 -scipy==1.4.1 +numpy>=1.20 +scipy sympy>=1.5 tensorflow>=2.0 tensorboard>=2.0 networkx>=2.0 quantum-blackbird>=0.3.0 python-dateutil==2.8.0 -thewalrus>=0.14.0 +thewalrus>=0.15.0 toml appdirs numba>=0.48.0 diff --git a/setup.py b/setup.py index 49dfb3ef1..c98c80a2b 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ "networkx>=2.0", "quantum-blackbird>=0.3.0", "python-dateutil>=2.8.0", - "thewalrus>=0.14.0", + "thewalrus>=0.15.0", "numba", "toml", "appdirs", diff --git a/strawberryfields/backends/__init__.py b/strawberryfields/backends/__init__.py index 04c715f2a..245fe9ede 100644 --- a/strawberryfields/backends/__init__.py +++ b/strawberryfields/backends/__init__.py @@ -66,17 +66,6 @@ BaseGaussian BaseBosonic -Utility modules ---------------- - -The following utility modules are provided for -backend development. - -.. currentmodule:: strawberryfields.backends -.. autosummary:: - :toctree: api - - shared_ops """ from .base import BaseBackend, BaseFock, BaseGaussian, BaseBosonic, ModeMap diff --git a/strawberryfields/backends/bosonicbackend/backend.py b/strawberryfields/backends/bosonicbackend/backend.py index e81be0850..a78219469 100644 --- a/strawberryfields/backends/bosonicbackend/backend.py +++ b/strawberryfields/backends/bosonicbackend/backend.py @@ -23,8 +23,9 @@ from scipy.special import comb from scipy.linalg import block_diag +from thewalrus.symplectic import xxpp_to_xpxp + from strawberryfields.backends import BaseBosonic -from strawberryfields.backends.shared_ops import changebasis from strawberryfields.backends.states import BaseBosonicState from strawberryfields.backends.bosonicbackend.bosoniccircuit import BosonicModes @@ -377,8 +378,7 @@ def prepare_gaussian_state(self, r, V, modes): # convert xp-ordering to symmetric ordering means = np.vstack([r[:N], r[N:]]).reshape(-1, order="F") - C = changebasis(N) - cov = C @ V @ C.T + cov = xxpp_to_xpxp(V) self.circuit.from_covmat(cov, modes) self.circuit.from_mean(means, modes) diff --git a/strawberryfields/backends/gaussianbackend/backend.py b/strawberryfields/backends/gaussianbackend/backend.py index ba9b13acc..bfef2b8b4 100644 --- a/strawberryfields/backends/gaussianbackend/backend.py +++ b/strawberryfields/backends/gaussianbackend/backend.py @@ -20,8 +20,6 @@ concatenate, array, identity, - arctan2, - angle, sqrt, vstack, zeros_like, @@ -29,9 +27,9 @@ ix_, ) from thewalrus.samples import hafnian_sample_state, torontonian_sample_state +from thewalrus.symplectic import xxpp_to_xpxp from strawberryfields.backends import BaseGaussian -from strawberryfields.backends.shared_ops import changebasis from strawberryfields.backends.states import BaseGaussianState from .gaussiancircuit import GaussianModes @@ -199,8 +197,7 @@ def prepare_gaussian_state(self, r, V, modes): # convert xp-ordering to symmetric ordering means = vstack([r[:N], r[N:]]).reshape(-1, order="F") - C = changebasis(N) - cov = C @ V @ C.T + cov = xxpp_to_xpxp(V) self.circuit.fromscovmat(cov, modes) self.circuit.fromsmean(means, modes) diff --git a/strawberryfields/backends/gaussianbackend/gaussiancircuit.py b/strawberryfields/backends/gaussianbackend/gaussiancircuit.py index 948779f17..894da35ed 100644 --- a/strawberryfields/backends/gaussianbackend/gaussiancircuit.py +++ b/strawberryfields/backends/gaussianbackend/gaussiancircuit.py @@ -15,9 +15,9 @@ # pylint: disable=duplicate-code,attribute-defined-outside-init import numpy as np from thewalrus.quantum import Xmat +from thewalrus.symplectic import xxpp_to_xpxp, xpxp_to_xxpp from . import ops -from ..shared_ops import changebasis class GaussianModes: @@ -250,9 +250,6 @@ def scovmatxp(self): The order for the canonical operators is :math:`q_1,..,q_n, p_1,...,p_n`. This differs from the ordering used in [1] which is :math:`q_1,p_1,q_2,p_2,...,q_n,p_n` Note that one ordering can be obtained from the other by using a permutation matrix. - - Said permutation matrix is implemented in the function changebasis(n) where n is - the number of modes. """ mm11 = ( self.nmat @@ -288,9 +285,6 @@ def smeanxp(self): The order for the canonical operators is :math:`q_1, \ldots, q_n, p_1, \ldots, p_n`. This differs from the ordering used in [1] which is :math:`q_1, p_1, q_2, p_2, \ldots, q_n, p_n`. Note that one ordering can be obtained from the other by using a permutation matrix. - - Said permutation matrix is implemented in the function changebasis(n) where n is - the number of modes. """ nmodes = self.nlen r = np.empty(2 * nmodes) @@ -300,8 +294,7 @@ def smeanxp(self): def scovmat(self): """Constructs and returns the symmetric ordered covariance matrix as defined in [1]""" - rotmat = changebasis(self.nlen) - return np.dot(np.dot(rotmat, self.scovmatxp()), np.transpose(rotmat)) + return xxpp_to_xpxp(self.scovmatxp()) def smean(self): r"""the symmetric mean $[q_1,p_1,q_2,p_2,...,q_n,p_n]$""" @@ -347,8 +340,7 @@ def fromscovmat(self, V, modes=None): raise ValueError("Covariance matrix is larger than the number of subsystems.") # convert to xp ordering - rotmat = changebasis(n) - VV = np.dot(np.dot(np.transpose(rotmat), V), rotmat) + VV = xpxp_to_xxpp(V) A = VV[0:n, 0:n] B = VV[0:n, n : 2 * n] diff --git a/strawberryfields/backends/shared_ops.py b/strawberryfields/backends/shared_ops.py deleted file mode 100644 index 959729cb4..000000000 --- a/strawberryfields/backends/shared_ops.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2019 Xanadu Quantum Technologies Inc. - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Common shared operations that can be used by backends""" - -import functools - -import numpy as np - -# ================================+ -# Phase space shared operations | -# ================================+ - - -@functools.lru_cache() -def changebasis(n): - r"""Change of basis matrix between the two Gaussian representation orderings. - - This is the matrix necessary to transform covariances matrices written - in the (x_1,...,x_n,p_1,...,p_n) to the (x_1,p_1,...,x_n,p_n) ordering - - Args: - n (int): number of modes - Returns: - array: :math:`2n\times 2n` matrix - """ - m = np.zeros((2 * n, 2 * n)) - for i in range(n): - m[2 * i, i] = 1 - m[2 * i + 1, i + n] = 1 - return m diff --git a/strawberryfields/backends/states.py b/strawberryfields/backends/states.py index 7367c1eaf..c344847c7 100644 --- a/strawberryfields/backends/states.py +++ b/strawberryfields/backends/states.py @@ -27,13 +27,12 @@ from scipy.integrate import simps from thewalrus.symplectic import rotation as _R +from thewalrus.symplectic import xpxp_to_xxpp import thewalrus.quantum as twq import strawberryfields as sf -from .shared_ops import changebasis - indices = string.ascii_lowercase @@ -1257,8 +1256,7 @@ def poly_quad_expectation(self, A, d=None, k=0, phi=0, **kwargs): if phi != 0: # rotate all modes of the covariance matrix and vector of means R = _R(phi) - C = changebasis(self._modes) - rot = C.T @ block_diag(*([R] * self._modes)) @ C + rot = xpxp_to_xxpp(block_diag(*([R] * self._modes))) mu = rot.T @ mu cov = rot.T @ cov @ rot diff --git a/strawberryfields/decompositions.py b/strawberryfields/decompositions.py index 9f8a2897b..f591609f5 100644 --- a/strawberryfields/decompositions.py +++ b/strawberryfields/decompositions.py @@ -21,9 +21,7 @@ import numpy as np from scipy.linalg import block_diag, sqrtm, polar, schur from thewalrus.quantum import adj_scaling -from thewalrus.symplectic import sympmat - -from .backends.shared_ops import changebasis +from thewalrus.symplectic import sympmat, xpxp_to_xxpp def takagi(N, tol=1e-13, rounding=13): @@ -670,7 +668,6 @@ def williamson(V, tol=1e-11): n = n // 2 omega = sympmat(n) - rotmat = changebasis(n) vals = np.linalg.eigvalsh(V) for val in vals: @@ -698,8 +695,9 @@ def williamson(V, tol=1e-11): p = block_diag(*seq) Kt = K @ p s1t = p @ s1 @ p - dd = np.transpose(rotmat) @ s1t @ rotmat - Ktt = Kt @ rotmat + dd = xpxp_to_xxpp(s1t) + perm_indices = xpxp_to_xxpp(np.arange(2 * n)) + Ktt = Kt[:, perm_indices] Db = np.diag([1 / dd[i, i + n] for i in range(n)] + [1 / dd[i, i + n] for i in range(n)]) S = Mm12 @ Ktt @ sqrtm(Db) return Db, np.linalg.inv(S).T diff --git a/strawberryfields/ops.py b/strawberryfields/ops.py index bb47000a2..9a02e0f8e 100644 --- a/strawberryfields/ops.py +++ b/strawberryfields/ops.py @@ -25,11 +25,12 @@ from scipy.linalg import block_diag import scipy.special as ssp +from thewalrus.symplectic import xxpp_to_xpxp + import strawberryfields as sf import strawberryfields.program_utils as pu import strawberryfields.decompositions as dec from .backends.states import BaseFockState, BaseGaussianState, BaseBosonicState -from .backends.shared_ops import changebasis from .program_utils import Command, RegRef, MergeFailure from .parameters import ( par_regref_deps, @@ -2842,7 +2843,7 @@ def _decompose(self, reg, **kwargs): D = np.diag(V) is_diag = np.all(V == np.diag(D)) - BD = changebasis(self.ns) @ V @ changebasis(self.ns).T + BD = xxpp_to_xpxp(V) BD_modes = [BD[i * 2 : (i + 1) * 2, i * 2 : (i + 1) * 2] for i in range(BD.shape[0] // 2)] is_block_diag = (not is_diag) and np.all(BD == block_diag(*BD_modes)) diff --git a/tests/backend/test_states_polyquad.py b/tests/backend/test_states_polyquad.py index 065cbc4d3..4bec140a6 100644 --- a/tests/backend/test_states_polyquad.py +++ b/tests/backend/test_states_polyquad.py @@ -20,10 +20,10 @@ from scipy.linalg import block_diag from thewalrus.symplectic import rotation as R +from thewalrus.symplectic import xpxp_to_xxpp from strawberryfields import backends from strawberryfields import utils -from strawberryfields.backends.shared_ops import changebasis # some tests require a higher cutoff for accuracy CUTOFF = 12 @@ -453,9 +453,8 @@ def test_three_mode_arbitrary(self, setup_backend, pure, hbar, tol): S1 = block_diag(BS, np.identity(2)) S2 = block_diag(np.identity(2), BS) - C = changebasis(3) - mu = C.T @ S2 @ S1 @ mu - cov = C.T @ S2 @ S1 @ cov @ S1.T @ S2.T @ C + mu = xpxp_to_xxpp(S2 @ S1 @ mu) + cov = xpxp_to_xxpp(S2 @ S1 @ cov @ S1.T @ S2.T) modes = list(np.arange(6).reshape(2, -1).T) diff --git a/tests/frontend/test_shared_ops.py b/tests/frontend/test_shared_ops.py deleted file mode 100644 index 952a8468f..000000000 --- a/tests/frontend/test_shared_ops.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2019 Xanadu Quantum Technologies Inc. - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -r"""Unit tests for the Strawberry Fields shared_ops module""" -import pytest - -pytestmark = pytest.mark.frontend - -import numpy as np - -import strawberryfields.backends.shared_ops as so - -class TestPhaseSpaceFunctions: - """Tests for the shared phase space operations""" - - def test_means_changebasis(self): - """Test the change of basis function applied to vectors. This function - converts from xp to symmetric ordering, and vice versa.""" - C = so.changebasis(3) - means_xp = [1, 2, 3, 4, 5, 6] - means_symmetric = [1, 4, 2, 5, 3, 6] - - assert np.all(C @ means_xp == means_symmetric) - assert np.all(C.T @ means_symmetric == means_xp) - - def test_cov_changebasis(self): - """Test the change of basis function applied to matrices. This function - converts from xp to symmetric ordering, and vice versa.""" - C = so.changebasis(2) - cov_xp = np.array( - [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]] - ) - - cov_symmetric = np.array( - [[0, 2, 1, 3], [8, 10, 9, 11], [4, 6, 5, 7], [12, 14, 13, 15]] - ) - - assert np.all(C @ cov_xp @ C.T == cov_symmetric) - assert np.all(C.T @ cov_symmetric @ C == cov_xp) diff --git a/tests/integration/test_decompositions_integration.py b/tests/integration/test_decompositions_integration.py index 7c68b7cb1..232f70e26 100644 --- a/tests/integration/test_decompositions_integration.py +++ b/tests/integration/test_decompositions_integration.py @@ -18,6 +18,7 @@ from scipy.linalg import qr, block_diag from thewalrus.symplectic import rotation as rot +from thewalrus.symplectic import xpxp_to_xxpp, xxpp_to_xpxp import strawberryfields as sf from strawberryfields import decompositions as dec @@ -28,7 +29,6 @@ squeezed_state, ) from strawberryfields import ops -from strawberryfields.backends.shared_ops import changebasis from strawberryfields.utils import random_interferometer as haar_measure # make the test file deterministic @@ -292,8 +292,7 @@ def test_rotated_squeezed(self, setup_eng, hbar, tol): r = 0.1 phi = 0.2312 v1 = (hbar / 2) * np.diag([np.exp(-r), np.exp(r)]) - A = changebasis(3) - cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A + cov = xpxp_to_xxpp(block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3)) with prog.context as q: ops.Gaussian(cov, decomp=False) | q @@ -301,19 +300,6 @@ def test_rotated_squeezed(self, setup_eng, hbar, tol): state = eng.run(prog).state assert np.allclose(state.cov(), cov, atol=tol) -def from_xp(num_modes): - r"""Provides array of indices to order quadratures as (x1,p1,...,xn,pn) - starting from all x followed by all p i.e., (x1,...,xn,p1,..., pn). - - Args: - num_modes (int): number of modes - - Returns: - list: quadrature ordering for (x1,p1,...,xn,pn) - """ - perm_inds_list = [(i, i + num_modes) for i in range(num_modes)] - perm_inds = [a for tup in perm_inds_list for a in tup] - return perm_inds @pytest.mark.backends("bosonic") class TestBosonicBackendPrepareState: @@ -328,7 +314,7 @@ def test_vacuum(self, setup_eng, hbar, tol): state = eng.run(prog).state - indices = from_xp(3) + indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:,indices][indices,:] assert np.allclose(state.covs(), np.expand_dims(cov,axis=0), atol=tol) assert np.all(state.means() == np.zeros((1,6))) @@ -345,7 +331,7 @@ def test_squeezed(self, setup_eng, hbar, tol): state = eng.run(prog).state - indices = from_xp(3) + indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:,indices][indices,:] assert np.allclose(state.covs(), np.expand_dims(cov,axis=0), atol=tol) @@ -360,7 +346,7 @@ def test_displaced_squeezed(self, setup_eng, hbar, tol): state = eng.run(prog).state - indices = from_xp(3) + indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:,indices][indices,:] means = means[indices] assert np.allclose(state.covs(), np.expand_dims(cov,axis=0), atol=tol) @@ -376,7 +362,7 @@ def test_thermal(self, setup_eng, hbar, tol): state = eng.run(prog).state - indices = from_xp(3) + indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:,indices][indices,:] assert np.allclose(state.covs(), np.expand_dims(cov,axis=0), atol=tol) @@ -387,15 +373,14 @@ def test_rotated_squeezed(self, setup_eng, hbar, tol): r = 0.1 phi = 0.2312 v1 = (hbar / 2) * np.diag([np.exp(-r), np.exp(r)]) - A = changebasis(3) - cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A + cov = xpxp_to_xxpp(block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3)) with prog.context as q: ops.Gaussian(cov, decomp=False) | q state = eng.run(prog).state - indices = from_xp(3) + indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:,indices][indices,:] assert np.allclose(state.covs(), np.expand_dims(cov,axis=0), atol=tol) @@ -462,8 +447,7 @@ def test_rotated_squeezed(self, setup_eng, hbar, tol): r = 0.1 phi = 0.2312 v1 = (hbar / 2) * np.diag([np.exp(-r), np.exp(r)]) - A = changebasis(3) - cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A + cov = xpxp_to_xxpp(block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3)) with prog.context as q: ops.Gaussian(cov) | q @@ -534,8 +518,7 @@ def test_rotated_squeezed(self, setup_eng, cutoff, hbar, tol): in_state = squeezed_state(r, phi, basis="fock", fock_dim=cutoff) v1 = (hbar / 2) * np.diag([np.exp(-2 * r), np.exp(2 * r)]) - A = changebasis(3) - cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A + cov = xpxp_to_xxpp(block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3)) with prog.context as q: ops.Gaussian(cov) | q @@ -615,7 +598,7 @@ def test_CXgate(self, setup_eng, pure, hbar, tol): assert np.allclose(state.means(), rexpected, atol=tol, rtol=0) elif eng.backend_name == "bosonic": - indices = from_xp(2) + indices = xxpp_to_xpxp(np.arange(2 * 2)) Vexpected = Vexpected[:,indices][indices,:] rexpected = rexpected[indices] assert np.allclose(state.covs(), np.expand_dims(Vexpected,axis=0), atol=tol, rtol=0) @@ -653,7 +636,7 @@ def test_CZgate(self, setup_eng, pure, hbar, tol): assert np.allclose(state.means(), rexpected, atol=tol, rtol=0) elif eng.backend_name == "bosonic": - indices = from_xp(2) + indices = xxpp_to_xpxp(np.arange(2 * 2)) Vexpected = Vexpected[:,indices][indices,:] rexpected = rexpected[indices] assert np.allclose(state.covs(), np.expand_dims(Vexpected,axis=0), atol=tol, rtol=0)