From 6e86e4ed4c64525e715c18e264cc843c7c8c1e45 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 7 Oct 2024 16:51:04 +0400 Subject: [PATCH 01/10] api ref --- doc/source/api-reference/qibo.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/source/api-reference/qibo.rst b/doc/source/api-reference/qibo.rst index e21f0cc19f..5e3a091819 100644 --- a/doc/source/api-reference/qibo.rst +++ b/doc/source/api-reference/qibo.rst @@ -1867,6 +1867,12 @@ Trace distance raised when using `cupy` backend. +Hilbert-Schmidt inner product +""""""""""""""""""""""""""""" + +.. autofunction:: qibo.quantum_info.hilbert_schmidt_inner_product + + Hilbert-Schmidt distance """""""""""""""""""""""" From 04cbab5ea9ab29881daf3e20c7235b327b165154 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 7 Oct 2024 16:51:11 +0400 Subject: [PATCH 02/10] function --- src/qibo/quantum_info/metrics.py | 36 +++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index b40789831a..ccc1f4d5b4 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -134,8 +134,34 @@ def trace_distance(state, target, check_hermitian: bool = False, backend=None): return distance +def hilbert_schmidt_inner_product(operator_A, operator_B, backend=None): + """Calculate the Hilbert-Schmidt inner product between two operators. + + Given two operators :math:`A, \\, B \\in \\mathcal{H}`, the Hilbert-Schmidt + inner product between the two is given by + + .. math:: + \\braket{A, \\, B}_{\\text{HS}} = \\text{tr}\\left(A^{\\dagger} \\, B\\right) \\, . + + Args: + operator_A (ndarray): operator :math:`A`. + operator_B (ndarray): operator :math:`B`. + backend (:class:`qibo.backends.abstract.Backend`, optional): backend to be used + in the execution. If ``None``, it uses :class:`qibo.backends.GlobalBackend`. + Defaults to ``None``. + + Returns: + float: Hilbert-Schmidt inner product :math:`\\braket{A, \\, B}_{\\text{HS}}`. + """ + backend = _check_backend(backend) + + inner_product = backend.np.trace(backend.conj(operator_A.T) @ operator_B) + + return float(backend.np.real(inner_product)) + + def hilbert_schmidt_distance(state, target, backend=None): - """Hilbert-Schmidt distance between two quantum states: + """Calculate the Hilbert-Schmidt distance between two quantum states: .. math:: \\langle \\rho \\, , \\, \\sigma \\rangle_{\\text{HS}} = @@ -171,10 +197,10 @@ def hilbert_schmidt_distance(state, target, backend=None): state = backend.np.outer(backend.np.conj(state), state) target = backend.np.outer(backend.np.conj(target), target) - distance = backend.np.real(backend.np.trace((state - target) ** 2)) - distance = float(distance) - - return distance + distance = state - target + distance = hilbert_schmidt_inner_product(distance, distance) + + return float(backend.np.real(distance)) def fidelity(state, target, check_hermitian: bool = False, backend=None): From bf3d261c0cce0dd99302387609bcdcf7b5c60ee3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 12:53:13 +0000 Subject: [PATCH 03/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/qibo/quantum_info/metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index ccc1f4d5b4..8e7d0375e5 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -199,7 +199,7 @@ def hilbert_schmidt_distance(state, target, backend=None): distance = state - target distance = hilbert_schmidt_inner_product(distance, distance) - + return float(backend.np.real(distance)) From cabdba9ef207f9bd052d2a98169864cb16c53a99 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Tue, 8 Oct 2024 08:52:34 +0400 Subject: [PATCH 04/10] fix bug --- src/qibo/quantum_info/metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index 8e7d0375e5..676ad2aaa1 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -155,7 +155,7 @@ def hilbert_schmidt_inner_product(operator_A, operator_B, backend=None): """ backend = _check_backend(backend) - inner_product = backend.np.trace(backend.conj(operator_A.T) @ operator_B) + inner_product = backend.np.trace(backend.np.conj(operator_A.T) @ operator_B) return float(backend.np.real(inner_product)) From 36e789347234690f1cabdc4daad11ebfa8137216 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Tue, 8 Oct 2024 09:25:39 +0400 Subject: [PATCH 05/10] fix test --- src/qibo/quantum_info/metrics.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index 676ad2aaa1..44c3cf12be 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -197,10 +197,9 @@ def hilbert_schmidt_distance(state, target, backend=None): state = backend.np.outer(backend.np.conj(state), state) target = backend.np.outer(backend.np.conj(target), target) - distance = state - target - distance = hilbert_schmidt_inner_product(distance, distance) + difference = state - target - return float(backend.np.real(distance)) + return hilbert_schmidt_inner_product(difference, difference, backend=backend) def fidelity(state, target, check_hermitian: bool = False, backend=None): From 2fed9feb28ae19f5993da982ef66b249c3e2eb12 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Tue, 8 Oct 2024 15:47:27 +0400 Subject: [PATCH 06/10] remove float --- src/qibo/quantum_info/metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index 44c3cf12be..a798040cbe 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -157,7 +157,7 @@ def hilbert_schmidt_inner_product(operator_A, operator_B, backend=None): inner_product = backend.np.trace(backend.np.conj(operator_A.T) @ operator_B) - return float(backend.np.real(inner_product)) + return backend.np.real(inner_product) def hilbert_schmidt_distance(state, target, backend=None): From 7e843d81341a9abb33ad03bb0a74b9ead056dcd1 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 9 Oct 2024 14:27:34 +0400 Subject: [PATCH 07/10] fix docstring --- src/qibo/quantum_info/entropies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/entropies.py b/src/qibo/quantum_info/entropies.py index e0c2596a56..e5e667ff64 100644 --- a/src/qibo/quantum_info/entropies.py +++ b/src/qibo/quantum_info/entropies.py @@ -665,7 +665,7 @@ def mutual_information( of state :math:`\\rho` is given by .. math:: - I(\\rho}) \\equiv S(\\rho_{A}) + S(\\rho_{B}) - S(\\rho) \\, , + I(\\rho) \\equiv S(\\rho_{A}) + S(\\rho_{B}) - S(\\rho) \\, , where :math:`B` is the remaining qubits that are not in partition :math:`A`, and :math:`S(\\cdot)` is the :func:`qibo.quantum_info.von_neumann_entropy`. From aed6c8dbf770b4c5d2ba62897df3b8c65e8c4f6a Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 9 Oct 2024 14:29:42 +0400 Subject: [PATCH 08/10] fix docstring --- src/qibo/quantum_info/superoperator_transformations.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index dc52bc00be..bae06d6402 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -20,16 +20,18 @@ def vectorization(state, order: str = "row", backend=None): If ``order="row"``, then: .. math:: - |\\rho) = \\sum_{k, l} \\, \\rho_{kl} \\, \\ket{k} \\otimes \\ket{l} + |\\rho) = \\sum_{k, l} \\, \\rho_{kl} \\, \\ket{k} \\otimes \\ket{l} \\, . If ``order="column"``, then: .. math:: - |\\rho) = \\sum_{k, l} \\, \\rho_{kl} \\, \\ket{l} \\otimes \\ket{k} + |\\rho) = \\sum_{k, l} \\, \\rho_{kl} \\, \\ket{l} \\otimes \\ket{k} \\, . + + If ``state`` is a 3-dimensional tensor, it is interpreted as a batch of states. - If ``state`` is a 3-dimensional tensor it is interpreted as a batch of states. Args: - state: statevector, density matrix, an array of statevectors, or an array of density matrices. + state (ndarray): statevector, density matrix, an array of statevectors, + or an array of density matrices. order (str, optional): If ``"row"``, vectorization is performed row-wise. If ``"column"``, vectorization is performed column-wise. If ``"system"``, a block-vectorization is From 85d5dabde90c45076f755cf084ddae9be36b5c1d Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 9 Oct 2024 14:29:55 +0400 Subject: [PATCH 09/10] fix docstring and add reference --- src/qibo/quantum_info/metrics.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index a798040cbe..6fb1073234 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -164,8 +164,11 @@ def hilbert_schmidt_distance(state, target, backend=None): """Calculate the Hilbert-Schmidt distance between two quantum states: .. math:: - \\langle \\rho \\, , \\, \\sigma \\rangle_{\\text{HS}} = - \\text{tr}\\left((\\rho - \\sigma)^{2}\\right) + \\braket{\\rho - \\sigma, \\, \\rho - \\sigma}_{\\text{HS}} = + \\text{tr}\\left((\\rho - \\sigma)^{2}\\right) \\, , + + where :math:`\\braket{\\cdot, \\, \\cdot}_{\\text{HS}}` is the + :func:`qibo.quantum_info.hilbert_schmidt_inner_product`. Args: state (ndarray): statevector or density matrix. @@ -177,6 +180,11 @@ def hilbert_schmidt_distance(state, target, backend=None): Returns: float: Hilbert-Schmidt distance between ``state`` :math:`\\rho` and ``target`` :math:`\\sigma`. + + References: + 1. P. J. Coles, M. Cerezo, and L. Cincio, *Strong bound between trace distance + and Hilbert-Schmidt distance for low-rank states*, `Phys. Rev. A 100, 022103 + `_ (2019). """ backend = _check_backend(backend) From 95c71fa3b413e30f6d7577c64655626a1ba5b3f1 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Fri, 11 Oct 2024 17:35:10 +0200 Subject: [PATCH 10/10] fix: Avoid logging for missing backends As they may also be part of a backend search loop --- src/qibo/backends/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qibo/backends/__init__.py b/src/qibo/backends/__init__.py index 77aaab3442..136db6e7c5 100644 --- a/src/qibo/backends/__init__.py +++ b/src/qibo/backends/__init__.py @@ -231,8 +231,7 @@ def construct_backend(backend, **kwargs) -> Backend: # pylint: disable=unsupported-membership-test if provider not in e.msg: raise e - raise_error( - MissingBackend, + raise MissingBackend( f"The '{backend}' backends' provider is not available. Check that a Python " f"package named '{provider}' is installed, and it is exposing valid Qibo " "backends.",