From 3d872880fb4923de19ba55e1eec6af5b412f8a04 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 12 Oct 2023 10:35:13 +0400 Subject: [PATCH 01/17] fix test --- tests/test_callbacks.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test_callbacks.py b/tests/test_callbacks.py index 76911f3b2e..d2e58b2cc8 100644 --- a/tests/test_callbacks.py +++ b/tests/test_callbacks.py @@ -7,6 +7,7 @@ # Absolute testing tolerance for the cases of zero entanglement entropy from qibo.config import PRECISION_TOL from qibo.models import AdiabaticEvolution, Circuit +from qibo.quantum_info.random_ensembles import random_density_matrix, random_statevector def test_abstract_callback_properties(): @@ -324,17 +325,18 @@ def test_state_callback(backend, density_matrix, copy): backend.assert_allclose(statec[1], target_state1) +@pytest.mark.parametrize("seed", list(range(1, 5 + 1))) @pytest.mark.parametrize("density_matrix", [False, True]) -def test_norm(backend, density_matrix): +def test_norm(backend, density_matrix, seed): norm = callbacks.Norm() if density_matrix: norm.nqubits = 1 - state = np.random.random((2, 2)) + 1j * np.random.random((2, 2)) + state = random_density_matrix(2**norm.nqubits, seed=seed, backend=backend) target_norm = np.trace(state) final_norm = norm.apply_density_matrix(backend, state) else: norm.nqubits = 2 - state = np.random.random(4) + 1j * np.random.random(4) + state = random_statevector(2**norm.nqubits, seed=seed, backend=backend) target_norm = np.sqrt((np.abs(state) ** 2).sum()) final_norm = norm.apply(backend, state) From f45aa2652dacc6dea2c4351131e35a8686f1c7be Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 12 Oct 2023 10:40:23 +0400 Subject: [PATCH 02/17] u[date docstring --- src/qibo/backends/abstract.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/qibo/backends/abstract.py b/src/qibo/backends/abstract.py index 14d1dc752c..4d06d6ef9a 100644 --- a/src/qibo/backends/abstract.py +++ b/src/qibo/backends/abstract.py @@ -326,13 +326,21 @@ def entanglement_entropy(self, rho): # pragma: no cover raise_error(NotImplementedError) @abc.abstractmethod - def calculate_norm(self, state): # pragma: no cover - """Calculate norm of a state vector.""" + def calculate_norm(self, state, ord=None): # pragma: no cover + """Calculate norm of a state vector. + + For specifications on possible values of the parameter `ord`, please refer to + `numpy.linalg.norm `_. + """ raise_error(NotImplementedError) @abc.abstractmethod - def calculate_norm_density_matrix(self, state): # pragma: no cover - """Calculate norm (trace) of a density matrix.""" + def calculate_norm_density_matrix(self, state, ord="nuc"): # pragma: no cover + """Calculate norm (trace) of a density matrix. + + For specifications on possible values of the parameter `ord`, please refer to + `numpy.linalg.norm `_. + """ raise_error(NotImplementedError) @abc.abstractmethod From 6dfd2ca351b55c0aaf1b3f8c14ac18ab843851ed Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 12 Oct 2023 10:40:48 +0400 Subject: [PATCH 03/17] `backenc.calculate_norm` uses `numpy.linalg.norm` --- src/qibo/backends/numpy.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/qibo/backends/numpy.py b/src/qibo/backends/numpy.py index b0447bd56e..96348b6771 100644 --- a/src/qibo/backends/numpy.py +++ b/src/qibo/backends/numpy.py @@ -673,13 +673,14 @@ def entanglement_entropy(self, rho): entropy = self.np.sum(masked_eigvals * spectrum) / self.np.log(2.0) return entropy, spectrum - def calculate_norm(self, state): + def calculate_norm(self, state, order=None): + """""" state = self.cast(state) - return self.np.sqrt(self.np.sum(self.np.abs(state) ** 2)) + return self.np.linalg.norm(state, ord=order) - def calculate_norm_density_matrix(self, state): + def calculate_norm_density_matrix(self, state, order="nuc"): state = self.cast(state) - return self.np.trace(state) + return self.np.linalg.norm(state, ord=order) def calculate_overlap(self, state1, state2): state1 = self.cast(state1) From 9fa6d7906949b195851f7a595b22b3031d687cf7 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 12 Oct 2023 10:42:58 +0400 Subject: [PATCH 04/17] remove empty docstring --- src/qibo/backends/numpy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qibo/backends/numpy.py b/src/qibo/backends/numpy.py index 96348b6771..40fc33b038 100644 --- a/src/qibo/backends/numpy.py +++ b/src/qibo/backends/numpy.py @@ -674,7 +674,6 @@ def entanglement_entropy(self, rho): return entropy, spectrum def calculate_norm(self, state, order=None): - """""" state = self.cast(state) return self.np.linalg.norm(state, ord=order) From 34e1b18f7feb9ad2d360f9b4af74d0c10689e3aa Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 12 Oct 2023 12:29:46 +0400 Subject: [PATCH 05/17] introduce norm functions to tensorflow backend --- src/qibo/backends/tensorflow.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/qibo/backends/tensorflow.py b/src/qibo/backends/tensorflow.py index 9f799c7c69..9a497c4e47 100644 --- a/src/qibo/backends/tensorflow.py +++ b/src/qibo/backends/tensorflow.py @@ -306,6 +306,20 @@ def entanglement_entropy(self, rho): entropy = self.np.sum(masked_eigvals * spectrum) / self.np.log(2.0) return entropy, spectrum + def calculate_norm(self, state, order=None): + state = self.cast(state) + # It is necessary to use np instead of self.np + # because tensorflow.experimental.numpy does not + # have a norm function + return np.linalg.norm(state, ord=order) + + def calculate_norm_density_matrix(self, state, order="nuc"): + state = self.cast(state) + # It is necessary to use np instead of self.np + # because tensorflow.experimental.numpy does not + # have a norm function + return np.linalg.norm(self.to_numpy(state), ord=order) + def calculate_eigenvalues(self, matrix, k=6): return self.tf.linalg.eigvalsh(matrix) From e2d93b35dd4cf7709b6d74c4ee28538b964d4cf3 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Fri, 13 Oct 2023 09:54:49 +0400 Subject: [PATCH 06/17] fix qibo.rst --- doc/source/api-reference/qibo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/api-reference/qibo.rst b/doc/source/api-reference/qibo.rst index f0ebc0f7ff..60d852db5f 100644 --- a/doc/source/api-reference/qibo.rst +++ b/doc/source/api-reference/qibo.rst @@ -655,7 +655,7 @@ Parametric ZX interaction (RZX) :member-order: bysource Parametric XX-YY interaction (RXXYY) -"""""""""""""""""""""""""""""""""" +"""""""""""""""""""""""""""""""""""" .. autoclass:: qibo.gates.RXXYY :members: From 2127dc98c4bf72dc2177d76592cde505337e6361 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Fri, 13 Oct 2023 09:54:58 +0400 Subject: [PATCH 07/17] improve docstring --- src/qibo/backends/abstract.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/qibo/backends/abstract.py b/src/qibo/backends/abstract.py index 4d06d6ef9a..e6140cebb7 100644 --- a/src/qibo/backends/abstract.py +++ b/src/qibo/backends/abstract.py @@ -326,19 +326,27 @@ def entanglement_entropy(self, rho): # pragma: no cover raise_error(NotImplementedError) @abc.abstractmethod - def calculate_norm(self, state, ord=None): # pragma: no cover + def calculate_norm(self, state, order=2): # pragma: no cover """Calculate norm of a state vector. - For specifications on possible values of the parameter `ord`, please refer to + For specifications on possible values of the parameter ``order`` + for the ``tensorflow`` backend, please refer to + `tensorflow.norm `_. + For all other backends, please refer to `numpy.linalg.norm `_. """ raise_error(NotImplementedError) @abc.abstractmethod - def calculate_norm_density_matrix(self, state, ord="nuc"): # pragma: no cover + def calculate_norm_density_matrix(self, state, order="nuc"): # pragma: no cover """Calculate norm (trace) of a density matrix. - For specifications on possible values of the parameter `ord`, please refer to + If ``order="nuc"``, it returns the nuclear norm os ``state``, + assuming ``state`` is Hermitian. For specifications on the other + possible values of the parameter ``order`` for the ``tensorflow`` backend, + please refer to + `tensorflow.norm `_. + For all other backends, please refer to `numpy.linalg.norm `_. """ raise_error(NotImplementedError) From 9e061e9fafc280f6cb839c5ce2f309960a69c354 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Fri, 13 Oct 2023 09:55:12 +0400 Subject: [PATCH 08/17] unify order default value --- src/qibo/backends/numpy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/backends/numpy.py b/src/qibo/backends/numpy.py index 40fc33b038..dc48d71348 100644 --- a/src/qibo/backends/numpy.py +++ b/src/qibo/backends/numpy.py @@ -673,7 +673,7 @@ def entanglement_entropy(self, rho): entropy = self.np.sum(masked_eigvals * spectrum) / self.np.log(2.0) return entropy, spectrum - def calculate_norm(self, state, order=None): + def calculate_norm(self, state, order=2): state = self.cast(state) return self.np.linalg.norm(state, ord=order) From 5f34b260e679dcc1274dbe86bba1d6287e4f9a8c Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Fri, 13 Oct 2023 09:55:26 +0400 Subject: [PATCH 09/17] rely on `tf.norm` --- src/qibo/backends/tensorflow.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/qibo/backends/tensorflow.py b/src/qibo/backends/tensorflow.py index 9a497c4e47..a4811fbc46 100644 --- a/src/qibo/backends/tensorflow.py +++ b/src/qibo/backends/tensorflow.py @@ -306,19 +306,15 @@ def entanglement_entropy(self, rho): entropy = self.np.sum(masked_eigvals * spectrum) / self.np.log(2.0) return entropy, spectrum - def calculate_norm(self, state, order=None): + def calculate_norm(self, state, order=2): state = self.cast(state) - # It is necessary to use np instead of self.np - # because tensorflow.experimental.numpy does not - # have a norm function - return np.linalg.norm(state, ord=order) + return self.tf.norm(state, ord=order) def calculate_norm_density_matrix(self, state, order="nuc"): state = self.cast(state) - # It is necessary to use np instead of self.np - # because tensorflow.experimental.numpy does not - # have a norm function - return np.linalg.norm(self.to_numpy(state), ord=order) + if order == "nuc": + return self.np.trace(state) + return self.tf.norm(state, ord=order) def calculate_eigenvalues(self, matrix, k=6): return self.tf.linalg.eigvalsh(matrix) From 05672f8f879c8f727fac94972ee84e0e0ce6ebf9 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sat, 14 Oct 2023 07:00:41 +0000 Subject: [PATCH 10/17] Update src/qibo/backends/abstract.py Co-authored-by: Matteo Robbiati <62071516+MatteoRobbiati@users.noreply.github.com> --- src/qibo/backends/abstract.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/backends/abstract.py b/src/qibo/backends/abstract.py index e6140cebb7..c6cecca099 100644 --- a/src/qibo/backends/abstract.py +++ b/src/qibo/backends/abstract.py @@ -341,7 +341,7 @@ def calculate_norm(self, state, order=2): # pragma: no cover def calculate_norm_density_matrix(self, state, order="nuc"): # pragma: no cover """Calculate norm (trace) of a density matrix. - If ``order="nuc"``, it returns the nuclear norm os ``state``, + If ``order="nuc"``, it returns the nuclear norm of ``state``, assuming ``state`` is Hermitian. For specifications on the other possible values of the parameter ``order`` for the ``tensorflow`` backend, please refer to From 1d12524379c7120802ea8519a490fb0462cca273 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sat, 14 Oct 2023 11:10:53 +0400 Subject: [PATCH 11/17] update docstring --- src/qibo/backends/abstract.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qibo/backends/abstract.py b/src/qibo/backends/abstract.py index c6cecca099..f133ab4504 100644 --- a/src/qibo/backends/abstract.py +++ b/src/qibo/backends/abstract.py @@ -327,7 +327,7 @@ def entanglement_entropy(self, rho): # pragma: no cover @abc.abstractmethod def calculate_norm(self, state, order=2): # pragma: no cover - """Calculate norm of a state vector. + """Calculate norm of a state vector. Default is :math:`2`-norm. For specifications on possible values of the parameter ``order`` for the ``tensorflow`` backend, please refer to @@ -339,12 +339,12 @@ def calculate_norm(self, state, order=2): # pragma: no cover @abc.abstractmethod def calculate_norm_density_matrix(self, state, order="nuc"): # pragma: no cover - """Calculate norm (trace) of a density matrix. + """Calculate norm of a density matrix. Default is the ``nuclear`` norm. If ``order="nuc"``, it returns the nuclear norm of ``state``, - assuming ``state`` is Hermitian. For specifications on the other - possible values of the parameter ``order`` for the ``tensorflow`` backend, - please refer to + assuming ``state`` is Hermitian (also known as trace norm). + For specifications on the other possible values of the + parameter ``order`` for the ``tensorflow`` backend, please refer to `tensorflow.norm `_. For all other backends, please refer to `numpy.linalg.norm `_. From d1cdf7c231947e30da3db09a11a0892949d3ca82 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 07:11:31 +0000 Subject: [PATCH 12/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/qibo/backends/abstract.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qibo/backends/abstract.py b/src/qibo/backends/abstract.py index f133ab4504..fe7d09195c 100644 --- a/src/qibo/backends/abstract.py +++ b/src/qibo/backends/abstract.py @@ -342,8 +342,8 @@ def calculate_norm_density_matrix(self, state, order="nuc"): # pragma: no cover """Calculate norm of a density matrix. Default is the ``nuclear`` norm. If ``order="nuc"``, it returns the nuclear norm of ``state``, - assuming ``state`` is Hermitian (also known as trace norm). - For specifications on the other possible values of the + assuming ``state`` is Hermitian (also known as trace norm). + For specifications on the other possible values of the parameter ``order`` for the ``tensorflow`` backend, please refer to `tensorflow.norm `_. For all other backends, please refer to From b9144de2b7a0c596f7626fb9d9f86d6fec94cb40 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sat, 14 Oct 2023 12:27:30 +0400 Subject: [PATCH 13/17] fix functions --- src/qibo/quantum_info/metrics.py | 18 +++++++++++------- .../superoperator_transformations.py | 9 +++++---- src/qibo/quantum_info/utils.py | 6 ++---- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index 88e479ef0c..226b2126f0 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -359,7 +359,9 @@ def trace_distance(state, target, check_hermitian: bool = False, backend=None): difference = state - target if check_hermitian is True: hermitian = bool( - backend.calculate_norm(np.transpose(np.conj(difference)) - difference) + float(backend.calculate_norm_density_matrix( + np.transpose(np.conj(difference)) - difference, order=2 + )) <= PRECISION_TOL ) if ( @@ -724,15 +726,15 @@ def process_fidelity(channel, target=None, check_unitary: bool = False, backend= dim = int(np.sqrt(channel.shape[0])) if check_unitary is True: - norm_channel = backend.calculate_norm( + norm_channel = float(backend.calculate_norm_density_matrix( np.dot(np.conj(np.transpose(channel)), channel) - np.eye(dim**2) - ) + )) if target is None and norm_channel > PRECISION_TOL: raise_error(TypeError, "Channel is not unitary and Target is None.") if target is not None: - norm_target = backend.calculate_norm( + norm_target = float(backend.calculate_norm( np.dot(np.conj(np.transpose(target)), target) - np.eye(dim**2) - ) + )) if (norm_channel > PRECISION_TOL) and (norm_target > PRECISION_TOL): raise_error(TypeError, "Neither channel is unitary.") @@ -1131,10 +1133,12 @@ def _check_hermitian_or_not_gpu(matrix, backend=None): if backend is None: # pragma: no cover backend = GlobalBackend() - hermitian = bool( - backend.calculate_norm(np.transpose(np.conj(matrix)) - matrix) < PRECISION_TOL + norm = backend.calculate_norm_density_matrix( + np.transpose(np.conj(matrix)) - matrix, order=2 ) + hermitian = bool(float(norm) <= PRECISION_TOL) + if hermitian is False and backend.__class__.__name__ in [ "CupyBackend", "CuQuantumBackend", diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index 7043e84d6e..3c565031d6 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -453,9 +453,10 @@ def choi_to_kraus( backend = GlobalBackend() if validate_cp: - norm = backend.calculate_norm( - choi_super_op - np.transpose(np.conj(choi_super_op)) - ) + norm = float(backend.calculate_norm_density_matrix( + choi_super_op - np.transpose(np.conj(choi_super_op)), + order=2 + )) if norm > PRECISION_TOL: non_cp = True else: @@ -2065,7 +2066,7 @@ def function(x0, operators): for prob, oper in zip(x0, operators): operator += prob * oper - return float(backend.calculate_norm(target - operator)) + return float(backend.calculate_norm_density_matrix(target - operator, order=2)) # initial parameters as flat distribution x0 = [1.0 / (len(kraus_ops) + 1)] * len(kraus_ops) diff --git a/src/qibo/quantum_info/utils.py b/src/qibo/quantum_info/utils.py index 35a61a99d0..1e6d1e5071 100644 --- a/src/qibo/quantum_info/utils.py +++ b/src/qibo/quantum_info/utils.py @@ -245,11 +245,9 @@ def hellinger_distance(prob_dist_p, prob_dist_q, validate: bool = False, backend if np.abs(np.sum(prob_dist_q) - 1.0) > PRECISION_TOL: raise_error(ValueError, "Second probability array must sum to 1.") - distance = backend.calculate_norm( + distance = float(backend.calculate_norm( np.sqrt(prob_dist_p) - np.sqrt(prob_dist_q) - ) / np.sqrt(2) - - distance = float(distance) + ) / np.sqrt(2)) return distance From 3583a5e932d03e6c8f6161b6ea9fc57f7e0e12a2 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sat, 14 Oct 2023 12:27:34 +0400 Subject: [PATCH 14/17] fix tests --- tests/test_quantum_info_metrics.py | 11 +++------- tests/test_quantum_info_random.py | 35 ++++++++++++++---------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/tests/test_quantum_info_metrics.py b/tests/test_quantum_info_metrics.py index 081bc8e250..9398010463 100644 --- a/tests/test_quantum_info_metrics.py +++ b/tests/test_quantum_info_metrics.py @@ -156,12 +156,7 @@ def test_entropy(backend, base, check_hermitian): test = 0.8613531161467861 backend.assert_allclose( - backend.calculate_norm( - entropy(state, base, check_hermitian=check_hermitian, backend=backend) - - test - ) - < PRECISION_TOL, - True, + entropy(state, base, check_hermitian=check_hermitian, backend=backend), test ) @@ -520,8 +515,8 @@ def test_process_fidelity_and_infidelity(backend): channel = backend.cast(channel, dtype=channel.dtype) test = process_fidelity(channel, check_unitary=True, backend=backend) with pytest.raises(TypeError): - channel = np.random.rand(d**2, d**2) - target = np.random.rand(d**2, d**2) + channel = 10 * np.random.rand(d**2, d**2) + target = 10 * np.random.rand(d**2, d**2) channel = backend.cast(channel, dtype=channel.dtype) target = backend.cast(target, dtype=target.dtype) test = process_fidelity(channel, target, check_unitary=True, backend=backend) diff --git a/tests/test_quantum_info_random.py b/tests/test_quantum_info_random.py index 378cb0e5ad..e078d4d705 100644 --- a/tests/test_quantum_info_random.py +++ b/tests/test_quantum_info_random.py @@ -72,14 +72,14 @@ def test_random_hermitian(backend): dims = 4 matrix = random_hermitian(dims, backend=backend) matrix_dagger = np.transpose(np.conj(matrix)) - norm = backend.calculate_norm(matrix - matrix_dagger) + norm = float(backend.calculate_norm_density_matrix(matrix - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) # test if function returns semidefinite Hermitian operator dims = 4 matrix = random_hermitian(dims, semidefinite=True, backend=backend) matrix_dagger = np.transpose(np.conj(matrix)) - norm = backend.calculate_norm(matrix - matrix_dagger) + norm = float(backend.calculate_norm_density_matrix(matrix - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) eigenvalues = np.linalg.eigvalsh(matrix) @@ -90,7 +90,7 @@ def test_random_hermitian(backend): dims = 4 matrix = random_hermitian(dims, normalize=True, backend=backend) matrix_dagger = np.transpose(np.conj(matrix)) - norm = backend.calculate_norm(matrix - matrix_dagger) + norm = float(backend.calculate_norm_density_matrix(matrix - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) eigenvalues = np.linalg.eigvalsh(matrix) @@ -101,7 +101,7 @@ def test_random_hermitian(backend): dims = 4 matrix = random_hermitian(dims, semidefinite=True, normalize=True, backend=backend) matrix_dagger = np.transpose(np.conj(matrix)) - norm = backend.calculate_norm(matrix - matrix_dagger) + norm = float(backend.calculate_norm(matrix - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) eigenvalues = np.linalg.eigvalsh(matrix) @@ -133,7 +133,7 @@ def test_random_unitary(backend): matrix = random_unitary(dims, backend=backend) matrix_dagger = np.transpose(np.conj(matrix)) matrix_inv = np.linalg.inv(matrix) - norm = backend.calculate_norm(matrix_inv - matrix_dagger) + norm = float(backend.calculate_norm_density_matrix(matrix_inv - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) # tests if operator is unitary (measure == None) @@ -141,7 +141,7 @@ def test_random_unitary(backend): matrix = random_unitary(dims, measure, backend=backend) matrix_dagger = np.transpose(np.conj(matrix)) matrix_inv = np.linalg.inv(matrix) - norm = backend.calculate_norm(matrix_inv - matrix_dagger) + norm = float(backend.calculate_norm(matrix_inv - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) @@ -239,6 +239,7 @@ def test_random_density_matrix(backend, dims, pure, metric, basis, normalize): with pytest.raises(ValueError): test = random_density_matrix(dims=dims, normalize=True) else: + norm_function = backend.calculate_norm_density_matrix if basis is None else backend.calculate_norm state = random_density_matrix( dims, pure=pure, @@ -259,17 +260,13 @@ def test_random_density_matrix(backend, dims, pure, metric, basis, normalize): backend.assert_allclose(purity(state) >= 1.0 - PRECISION_TOL, True) state_dagger = np.transpose(np.conj(state)) - norm = backend.calculate_norm(state - state_dagger) + norm = float(norm_function(state - state_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) else: normalization = 1.0 if normalize is False else 1.0 / np.sqrt(dims) - backend.assert_allclose( - backend.calculate_norm(state[0] - normalization) <= PRECISION_TOL, True - ) - assert all( - backend.calculate_norm(exp_value) <= normalization - for exp_value in state[1:] - ) + print(state) + backend.assert_allclose(state[0], normalization) + assert all(np.abs(exp_value) <= normalization for exp_value in state[1:]) @pytest.mark.parametrize("seed", [10]) @@ -370,7 +367,7 @@ def test_pauli_single(backend): matrix = backend.cast(matrix, dtype=matrix.dtype) backend.assert_allclose( - backend.calculate_norm(matrix - result) < PRECISION_TOL, True + float(backend.calculate_norm_density_matrix(matrix - result, order=2)) < PRECISION_TOL, True ) @@ -406,12 +403,12 @@ def test_random_pauli( matrix = backend.cast(matrix, dtype=matrix.dtype) if subset is None: backend.assert_allclose( - backend.calculate_norm(matrix - result_complete_set) < PRECISION_TOL, + float(backend.calculate_norm_density_matrix(matrix - result_complete_set, order=2)) < PRECISION_TOL, True, ) else: backend.assert_allclose( - backend.calculate_norm(matrix - result_subset) < PRECISION_TOL, True + float(backend.calculate_norm_density_matrix(matrix - result_subset, order=2)) < PRECISION_TOL, True ) else: matrix = np.transpose(matrix, (1, 0, 2, 3)) @@ -420,12 +417,12 @@ def test_random_pauli( if subset is None: backend.assert_allclose( - backend.calculate_norm(matrix - result_complete_set) < PRECISION_TOL, + float(backend.calculate_norm_density_matrix(matrix - result_complete_set, order=2)) < PRECISION_TOL, True, ) else: backend.assert_allclose( - backend.calculate_norm(matrix - result_subset) < PRECISION_TOL, True + float(backend.calculate_norm_density_matrix(matrix - result_subset, order=2)) < PRECISION_TOL, True ) From 1391f48b3e3cdd07cc0eaf647468bd1777e18899 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 14 Oct 2023 08:28:00 +0000 Subject: [PATCH 15/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/qibo/quantum_info/metrics.py | 24 ++++++---- .../superoperator_transformations.py | 9 ++-- src/qibo/quantum_info/utils.py | 6 +-- tests/test_quantum_info_random.py | 44 ++++++++++++++++--- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index 226b2126f0..65a11d7c44 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -359,9 +359,11 @@ def trace_distance(state, target, check_hermitian: bool = False, backend=None): difference = state - target if check_hermitian is True: hermitian = bool( - float(backend.calculate_norm_density_matrix( - np.transpose(np.conj(difference)) - difference, order=2 - )) + float( + backend.calculate_norm_density_matrix( + np.transpose(np.conj(difference)) - difference, order=2 + ) + ) <= PRECISION_TOL ) if ( @@ -726,15 +728,19 @@ def process_fidelity(channel, target=None, check_unitary: bool = False, backend= dim = int(np.sqrt(channel.shape[0])) if check_unitary is True: - norm_channel = float(backend.calculate_norm_density_matrix( - np.dot(np.conj(np.transpose(channel)), channel) - np.eye(dim**2) - )) + norm_channel = float( + backend.calculate_norm_density_matrix( + np.dot(np.conj(np.transpose(channel)), channel) - np.eye(dim**2) + ) + ) if target is None and norm_channel > PRECISION_TOL: raise_error(TypeError, "Channel is not unitary and Target is None.") if target is not None: - norm_target = float(backend.calculate_norm( - np.dot(np.conj(np.transpose(target)), target) - np.eye(dim**2) - )) + norm_target = float( + backend.calculate_norm( + np.dot(np.conj(np.transpose(target)), target) - np.eye(dim**2) + ) + ) if (norm_channel > PRECISION_TOL) and (norm_target > PRECISION_TOL): raise_error(TypeError, "Neither channel is unitary.") diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index 3c565031d6..b91dadbeb1 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -453,10 +453,11 @@ def choi_to_kraus( backend = GlobalBackend() if validate_cp: - norm = float(backend.calculate_norm_density_matrix( - choi_super_op - np.transpose(np.conj(choi_super_op)), - order=2 - )) + norm = float( + backend.calculate_norm_density_matrix( + choi_super_op - np.transpose(np.conj(choi_super_op)), order=2 + ) + ) if norm > PRECISION_TOL: non_cp = True else: diff --git a/src/qibo/quantum_info/utils.py b/src/qibo/quantum_info/utils.py index 1e6d1e5071..de7a73223f 100644 --- a/src/qibo/quantum_info/utils.py +++ b/src/qibo/quantum_info/utils.py @@ -245,9 +245,9 @@ def hellinger_distance(prob_dist_p, prob_dist_q, validate: bool = False, backend if np.abs(np.sum(prob_dist_q) - 1.0) > PRECISION_TOL: raise_error(ValueError, "Second probability array must sum to 1.") - distance = float(backend.calculate_norm( - np.sqrt(prob_dist_p) - np.sqrt(prob_dist_q) - ) / np.sqrt(2)) + distance = float( + backend.calculate_norm(np.sqrt(prob_dist_p) - np.sqrt(prob_dist_q)) / np.sqrt(2) + ) return distance diff --git a/tests/test_quantum_info_random.py b/tests/test_quantum_info_random.py index e078d4d705..5f7331dad9 100644 --- a/tests/test_quantum_info_random.py +++ b/tests/test_quantum_info_random.py @@ -133,7 +133,9 @@ def test_random_unitary(backend): matrix = random_unitary(dims, backend=backend) matrix_dagger = np.transpose(np.conj(matrix)) matrix_inv = np.linalg.inv(matrix) - norm = float(backend.calculate_norm_density_matrix(matrix_inv - matrix_dagger, order=2)) + norm = float( + backend.calculate_norm_density_matrix(matrix_inv - matrix_dagger, order=2) + ) backend.assert_allclose(norm < PRECISION_TOL, True) # tests if operator is unitary (measure == None) @@ -239,7 +241,11 @@ def test_random_density_matrix(backend, dims, pure, metric, basis, normalize): with pytest.raises(ValueError): test = random_density_matrix(dims=dims, normalize=True) else: - norm_function = backend.calculate_norm_density_matrix if basis is None else backend.calculate_norm + norm_function = ( + backend.calculate_norm_density_matrix + if basis is None + else backend.calculate_norm + ) state = random_density_matrix( dims, pure=pure, @@ -367,7 +373,9 @@ def test_pauli_single(backend): matrix = backend.cast(matrix, dtype=matrix.dtype) backend.assert_allclose( - float(backend.calculate_norm_density_matrix(matrix - result, order=2)) < PRECISION_TOL, True + float(backend.calculate_norm_density_matrix(matrix - result, order=2)) + < PRECISION_TOL, + True, ) @@ -403,12 +411,23 @@ def test_random_pauli( matrix = backend.cast(matrix, dtype=matrix.dtype) if subset is None: backend.assert_allclose( - float(backend.calculate_norm_density_matrix(matrix - result_complete_set, order=2)) < PRECISION_TOL, + float( + backend.calculate_norm_density_matrix( + matrix - result_complete_set, order=2 + ) + ) + < PRECISION_TOL, True, ) else: backend.assert_allclose( - float(backend.calculate_norm_density_matrix(matrix - result_subset, order=2)) < PRECISION_TOL, True + float( + backend.calculate_norm_density_matrix( + matrix - result_subset, order=2 + ) + ) + < PRECISION_TOL, + True, ) else: matrix = np.transpose(matrix, (1, 0, 2, 3)) @@ -417,12 +436,23 @@ def test_random_pauli( if subset is None: backend.assert_allclose( - float(backend.calculate_norm_density_matrix(matrix - result_complete_set, order=2)) < PRECISION_TOL, + float( + backend.calculate_norm_density_matrix( + matrix - result_complete_set, order=2 + ) + ) + < PRECISION_TOL, True, ) else: backend.assert_allclose( - float(backend.calculate_norm_density_matrix(matrix - result_subset, order=2)) < PRECISION_TOL, True + float( + backend.calculate_norm_density_matrix( + matrix - result_subset, order=2 + ) + ) + < PRECISION_TOL, + True, ) From 5291a4b17e306569adcda69fe93782f9269502db Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sun, 15 Oct 2023 12:57:57 +0400 Subject: [PATCH 16/17] fix tests --- tests/test_gates_channels.py | 12 ++++++------ tests/test_models_circuit_features.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_gates_channels.py b/tests/test_gates_channels.py index 29de181aab..2a9a8ba743 100644 --- a/tests/test_gates_channels.py +++ b/tests/test_gates_channels.py @@ -94,20 +94,20 @@ def test_kraus_channel(backend, pauli_order): channel = gates.KrausChannel(0, [a_1, a_2]) backend.assert_allclose( - backend.calculate_norm(channel.to_liouville(backend=backend) - test_superop) + float(backend.calculate_norm_density_matrix(channel.to_liouville(backend=backend) - test_superop, order=2)) < PRECISION_TOL, True, ) backend.assert_allclose( - backend.calculate_norm(channel.to_choi(backend=backend) - test_choi) + float(backend.calculate_norm_density_matrix(channel.to_choi(backend=backend) - test_choi, order=2)) < PRECISION_TOL, True, ) backend.assert_allclose( - backend.calculate_norm( + float(backend.calculate_norm( channel.to_pauli_liouville(pauli_order=pauli_order, backend=backend) - test_pauli - ) + )) < PRECISION_TOL, True, ) @@ -212,7 +212,7 @@ def test_pauli_noise_channel(backend, pauli_order): liouville = gates.PauliNoiseChannel(0, list(zip(basis, pnp))).to_pauli_liouville( normalize=True, pauli_order=pauli_order, backend=backend ) - norm = backend.calculate_norm(backend.to_numpy(liouville) - test_representation) + norm = float(backend.calculate_norm_density_matrix(backend.to_numpy(liouville) - test_representation, order=2)) assert norm < PRECISION_TOL @@ -341,7 +341,7 @@ def test_thermal_relaxation_channel(backend, t_1, t_2, time, excpop): target_state = backend.cast(target_state, dtype=target_state.dtype) backend.assert_allclose( - backend.calculate_norm(final_state - target_state) < PRECISION_TOL, True + float(backend.calculate_norm_density_matrix(final_state - target_state, order=2)) < PRECISION_TOL, True ) diff --git a/tests/test_models_circuit_features.py b/tests/test_models_circuit_features.py index 9d22f98ce9..4dd5c0db33 100644 --- a/tests/test_models_circuit_features.py +++ b/tests/test_models_circuit_features.py @@ -352,7 +352,7 @@ def test_repeated_execute_probs_and_freqs(backend, nqubits): test_probabilities = backend.cast(test_probabilities, dtype=float) print(result.probabilities()) backend.assert_allclose( - backend.calculate_norm(result.probabilities() - test_probabilities) + float(backend.calculate_norm(result.probabilities() - test_probabilities)) < PRECISION_TOL, True, ) From 6270d248492be7ec64d0b5f8dbda427904870017 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 08:58:21 +0000 Subject: [PATCH 17/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_gates_channels.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/tests/test_gates_channels.py b/tests/test_gates_channels.py index 2a9a8ba743..d6511f83a5 100644 --- a/tests/test_gates_channels.py +++ b/tests/test_gates_channels.py @@ -94,20 +94,30 @@ def test_kraus_channel(backend, pauli_order): channel = gates.KrausChannel(0, [a_1, a_2]) backend.assert_allclose( - float(backend.calculate_norm_density_matrix(channel.to_liouville(backend=backend) - test_superop, order=2)) + float( + backend.calculate_norm_density_matrix( + channel.to_liouville(backend=backend) - test_superop, order=2 + ) + ) < PRECISION_TOL, True, ) backend.assert_allclose( - float(backend.calculate_norm_density_matrix(channel.to_choi(backend=backend) - test_choi, order=2)) + float( + backend.calculate_norm_density_matrix( + channel.to_choi(backend=backend) - test_choi, order=2 + ) + ) < PRECISION_TOL, True, ) backend.assert_allclose( - float(backend.calculate_norm( - channel.to_pauli_liouville(pauli_order=pauli_order, backend=backend) - - test_pauli - )) + float( + backend.calculate_norm( + channel.to_pauli_liouville(pauli_order=pauli_order, backend=backend) + - test_pauli + ) + ) < PRECISION_TOL, True, ) @@ -212,7 +222,11 @@ def test_pauli_noise_channel(backend, pauli_order): liouville = gates.PauliNoiseChannel(0, list(zip(basis, pnp))).to_pauli_liouville( normalize=True, pauli_order=pauli_order, backend=backend ) - norm = float(backend.calculate_norm_density_matrix(backend.to_numpy(liouville) - test_representation, order=2)) + norm = float( + backend.calculate_norm_density_matrix( + backend.to_numpy(liouville) - test_representation, order=2 + ) + ) assert norm < PRECISION_TOL @@ -341,7 +355,11 @@ def test_thermal_relaxation_channel(backend, t_1, t_2, time, excpop): target_state = backend.cast(target_state, dtype=target_state.dtype) backend.assert_allclose( - float(backend.calculate_norm_density_matrix(final_state - target_state, order=2)) < PRECISION_TOL, True + float( + backend.calculate_norm_density_matrix(final_state - target_state, order=2) + ) + < PRECISION_TOL, + True, )