From fe83b160a6a29cb5cd69184fd3e3ccb8b97bad81 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 3 Oct 2024 10:37:11 +0400 Subject: [PATCH 1/6] api ref --- doc/source/api-reference/qibo.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/source/api-reference/qibo.rst b/doc/source/api-reference/qibo.rst index 8e4d156269..e21f0cc19f 100644 --- a/doc/source/api-reference/qibo.rst +++ b/doc/source/api-reference/qibo.rst @@ -1763,6 +1763,11 @@ Classical Tsallis entropy .. autofunction:: qibo.quantum_info.classical_tsallis_entropy +Classical Tsallis relative entropy +"""""""""""""""""""""""""""""""""" + +.. autofunction:: qibo.quantum_info.classical_relative_tsallis_entropy + von Neumann entropy """"""""""""""""""" From 69542b127372a91c86c1ea5baa0e2e4f07cd9abf Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 3 Oct 2024 10:37:15 +0400 Subject: [PATCH 2/6] function --- src/qibo/quantum_info/entropies.py | 58 +++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/entropies.py b/src/qibo/quantum_info/entropies.py index 31972c4ff5..e9fb8bd41b 100644 --- a/src/qibo/quantum_info/entropies.py +++ b/src/qibo/quantum_info/entropies.py @@ -428,7 +428,57 @@ def classical_tsallis_entropy(prob_dist, alpha: float, base: float = 2, backend= total_sum = prob_dist**alpha total_sum = backend.np.sum(total_sum) - return (1 / (1 - alpha)) * (total_sum - 1) + return (1 / (alpha - 1)) * (1 - total_sum) + + +def classical_relative_tsallis_entropy( + prob_dist_p, prob_dist_q, alpha: float, base: float = 2, backend=None +): + """Calculate the classical relative Tsallis entropy between two discrete probability distributions. + + Given a discrete random variable :math:`\\chi` that has values :math:`x` in the set + :math:`\\mathcal{X}` with probability :math:`\\mathrm{p}(x)` and a discrete random variable + :math:`\\upsilon` that has the values :math:`x` in the same set :math:`\\mathcal{X}` with + probability :math:`\\mathrm{q}(x)`, their relative Tsallis entropy is given by + + .. math:: + D_{\\alpha}^{\\text{ts}}(\\chi \\, \\| \\, \\upsilon) = \\sum_{x \\in \\mathcal{X}} \\, + \\mathrm{p}^{\\alpha}(x) \\, \\ln_{\\alpha} + \\left( \\frac{\\mathrm{p}(x)}{\\mathrm{q}(x)} \\right) \\, , + + where :math:`\\ln_{\\alpha}(x) \\equiv \\frac{x^{1 - \\alpha} - 1}{1 - \\alpha}` + is the so-called :math:`\\alpha`-logarithm. When :math:`\\alpha = 1`, it reduces to + :class:`qibo.quantum_info.entropies.classical_relative_entropy`. + + Args: + prob_dist_p (ndarray or list): discrete probability distribution :math:`p`. + prob_dist_q (ndarray or list): discrete probability distribution :math:`q`. + alpha (float): To be used when + base (float): the base of the log used when :math:`\\alpha = 1`. Defaults to :math:`2`. + 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: Tsallis relative entropy :math:`D_{\\alpha}^{\\text{ts}}`. + """ + if alpha == 1.0: + return classical_relative_entropy(prob_dist_p, prob_dist_q, base, backend) + + backend = _check_backend(backend) + + if isinstance(prob_dist_p, list): + # np.float64 is necessary instead of native float because of tensorflow + prob_dist_p = backend.cast(prob_dist_p, dtype=np.float64) + + if isinstance(prob_dist_q, list): + # np.float64 is necessary instead of native float because of tensorflow + prob_dist_q = backend.cast(prob_dist_q, dtype=np.float64) + + element_wise = prob_dist_p**alpha + element_wise = element_wise * _q_logarithm(prob_dist_p / prob_dist_q) + + return backend.np.sum(element_wise) def von_neumann_entropy( @@ -951,3 +1001,9 @@ def entanglement_entropy( ) return entropy_entanglement + + +def _q_logarithm(x, q: float): + """Generalization of logarithm function necessary for classical (relative) Tsallis entropy.""" + factor = 1 - q + return (x**factor - 1) / factor From fc4673398216bdacecc76884a8697de9a3064719 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 3 Oct 2024 10:40:33 +0400 Subject: [PATCH 3/6] fix bug --- 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 e9fb8bd41b..b6d404b69c 100644 --- a/src/qibo/quantum_info/entropies.py +++ b/src/qibo/quantum_info/entropies.py @@ -476,7 +476,7 @@ def classical_relative_tsallis_entropy( prob_dist_q = backend.cast(prob_dist_q, dtype=np.float64) element_wise = prob_dist_p**alpha - element_wise = element_wise * _q_logarithm(prob_dist_p / prob_dist_q) + element_wise = element_wise * _q_logarithm(prob_dist_p / prob_dist_q, alpha) return backend.np.sum(element_wise) From d644294bea4cca126ea8ceae99de403472d8243b Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 3 Oct 2024 10:55:36 +0400 Subject: [PATCH 4/6] test --- tests/test_quantum_info_entropies.py | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/test_quantum_info_entropies.py b/tests/test_quantum_info_entropies.py index b383effed6..f844146c7e 100644 --- a/tests/test_quantum_info_entropies.py +++ b/tests/test_quantum_info_entropies.py @@ -6,6 +6,7 @@ classical_mutual_information, classical_relative_entropy, classical_relative_renyi_entropy, + classical_relative_tsallis_entropy, classical_renyi_entropy, classical_tsallis_entropy, entanglement_entropy, @@ -382,6 +383,36 @@ def test_classical_tsallis_entropy(backend, alpha, base, kind): ) +@pytest.mark.parametrize("kind", [None, list]) +@pytest.mark.parametrize("base", [2, 10, np.e, 5]) +@pytest.mark.parametrize("alpha", [0, 1, 2, 3]) +def test_classical_relative_tsallis_entropy(backend, alpha, base, kind): + prob_dist_p = np.random.rand(10) + prob_dist_p /= np.sum(prob_dist_p) + + prob_dist_q = np.random.rand(10) + prob_dist_q /= np.sum(prob_dist_q) + + prob_dist_p = backend.np.real(backend.cast(prob_dist_p)) + prob_dist_q = backend.np.real(backend.cast(prob_dist_q)) + + if alpha == 1.0: + target = classical_relative_entropy(prob_dist_p, prob_dist_q, base, backend) + else: + target = ((prob_dist_p / prob_dist_q) ** (1 - alpha) - 1) / (1 - alpha) + target = backend.np.sum(prob_dist_p**alpha * target) + + if kind is not None: + prob_dist_p = kind(prob_dist_p) + prob_dist_q = kind(prob_dist_q) + + value = classical_relative_tsallis_entropy( + prob_dist_p, prob_dist_q, alpha, base, backend + ) + + backend.assert_allclose(value, target) + + @pytest.mark.parametrize("check_hermitian", [False, True]) @pytest.mark.parametrize("base", [2, 10, np.e, 5]) def test_von_neumann_entropy(backend, base, check_hermitian): From 9a9c9e544044489f8d9c8d9ee956fd2b39726ae7 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 3 Oct 2024 07:07:36 +0000 Subject: [PATCH 5/6] Update tests/test_quantum_info_entropies.py Co-authored-by: BrunoLiegiBastonLiegi <45011234+BrunoLiegiBastonLiegi@users.noreply.github.com> --- tests/test_quantum_info_entropies.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_quantum_info_entropies.py b/tests/test_quantum_info_entropies.py index f844146c7e..1f19fdb7ed 100644 --- a/tests/test_quantum_info_entropies.py +++ b/tests/test_quantum_info_entropies.py @@ -393,8 +393,8 @@ def test_classical_relative_tsallis_entropy(backend, alpha, base, kind): prob_dist_q = np.random.rand(10) prob_dist_q /= np.sum(prob_dist_q) - prob_dist_p = backend.np.real(backend.cast(prob_dist_p)) - prob_dist_q = backend.np.real(backend.cast(prob_dist_q)) + prob_dist_p = backend.cast(prob_dist_p, dtype=np.float64) + prob_dist_q = backend.cast(prob_dist_q, dtype=np.float64) if alpha == 1.0: target = classical_relative_entropy(prob_dist_p, prob_dist_q, base, backend) From 823f13e462f60b9a8454e1de57c327b95e75bc91 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Thu, 3 Oct 2024 07:15:46 +0000 Subject: [PATCH 6/6] Apply suggestions from code review --- 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 b6d404b69c..204884c6ef 100644 --- a/src/qibo/quantum_info/entropies.py +++ b/src/qibo/quantum_info/entropies.py @@ -453,7 +453,7 @@ def classical_relative_tsallis_entropy( Args: prob_dist_p (ndarray or list): discrete probability distribution :math:`p`. prob_dist_q (ndarray or list): discrete probability distribution :math:`q`. - alpha (float): To be used when + alpha (float): entropic index. base (float): the base of the log used when :math:`\\alpha = 1`. Defaults to :math:`2`. backend (:class:`qibo.backends.abstract.Backend`, optional): backend to be used in the execution. If ``None``, it uses