Source code for qurry.process.randomized_measure.entangled_entropy.purity_cell_2

"""Post Processing - Randomized Measure - Entangled Entropy - Purity Cell 2
(:mod:`qurry.process.randomized_measure.entangled_entropy.purity_cell_2`)

This version introduces another way to process subsystems.

"""

import warnings
from typing import Union
import numpy as np

from ...utils import (
    ensemble_cell as ensemble_cell_py,
    single_counts_recount as single_counts_under_degree_py,
)
from ...availability import (
    availablility,
    default_postprocessing_backend,
    PostProcessingBackendLabel,
)
from ...exceptions import (
    PostProcessingRustImportError,
    PostProcessingRustUnavailableWarning,
    PostProcessingBackendDeprecatedWarning,
)


try:

    from ....boorust import randomized  # type: ignore

    purity_cell_2_rust_source = randomized.purity_cell_2_rust

    RUST_AVAILABLE = True
    FAILED_RUST_IMPORT = None
except ImportError as err:
    RUST_AVAILABLE = False
    FAILED_RUST_IMPORT = err

    def purity_cell_rust_source(*args, **kwargs):
        """Dummy function for purity_cell_rust."""
        raise PostProcessingRustImportError(
            "Rust is not available, using python to calculate purity cell."
        ) from FAILED_RUST_IMPORT


BACKEND_AVAILABLE = availablility(
    "randomized_measure.entangle_entropy.purity_cell_2",
    [
        ("Rust", RUST_AVAILABLE, FAILED_RUST_IMPORT),
        ("Cython", "Depr.", None),
    ],
)
DEFAULT_PROCESS_BACKEND = default_postprocessing_backend(RUST_AVAILABLE, False)


# Randomized measure
[docs] def purity_cell_2_py( idx: int, single_counts: dict[str, int], selected_classical_registers: list[int], ) -> tuple[int, np.float64, list[int]]: """Calculate the purity cell, one of overlap, of a subsystem by Python. Args: idx (int): Index of the cell (counts). single_counts (dict[str, int]): Counts measured from the single quantum circuit. selected_classical_registers (list[int]): The list of **the index of the selected_classical_registers**. Returns: tuple[int, float, list[int]]: Index, one of overlap purity, The list of **the index of the selected classical registers**. """ num_classical_register = len(list(single_counts.keys())[0]) shots = sum(single_counts.values()) selected_classical_registers_sorted = sorted(selected_classical_registers, reverse=True) subsystem_size = len(selected_classical_registers_sorted) single_counts_under_degree = single_counts_under_degree_py( single_counts, num_classical_register, selected_classical_registers_sorted ) purity_cell_value = np.float64(0) for s_ai, s_ai_meas in single_counts_under_degree.items(): for s_aj, s_aj_meas in single_counts_under_degree.items(): purity_cell_value += ensemble_cell_py( s_ai, s_ai_meas, s_aj, s_aj_meas, subsystem_size, shots ) return idx, purity_cell_value, selected_classical_registers_sorted
[docs] def purity_cell_2_rust( idx: int, single_counts: dict[str, int], selected_classical_registers: list[int], ) -> tuple[int, np.float64, list[int]]: """Calculate the purity cell, one of overlap, of a subsystem by Rust. Args: idx (int): Index of the cell (counts). single_counts (dict[str, int]): Counts measured from the single quantum circuit. selected_classical_registers (list[int]): The list of **the index of the selected_classical_registers**. Returns: tuple[int, float, list[int]]: Index, one of overlap purity, The list of **the index of the selected classical registers**. """ return purity_cell_2_rust_source(idx, single_counts, selected_classical_registers)
[docs] def purity_cell_2( idx: int, single_counts: dict[str, int], selected_classical_registers: list[int], backend: PostProcessingBackendLabel = DEFAULT_PROCESS_BACKEND, ) -> tuple[int, Union[float, np.float64], list[int]]: """Calculate the purity cell, one of overlap, of a subsystem. Args: idx (int): Index of the cell (counts). single_counts (dict[str, int]): Counts measured from the single quantum circuit. selected_bitstrings (list[int]): The list of **the index of the selected classical registers**. backend (ExistingProcessBackendLabel, optional): Backend for the process. Defaults to DEFAULT_PROCESS_BACKEND. Returns: tuple[int, Union[float, np.float64], list[int]]: Index, one of overlap purity, The list of **the index of the selected classical registers**. """ if backend == "Cython": warnings.warn( f"The Cython is deprecated, using {DEFAULT_PROCESS_BACKEND} to calculate purity cell.", PostProcessingBackendDeprecatedWarning, ) backend = DEFAULT_PROCESS_BACKEND if backend == "Rust": if RUST_AVAILABLE: return purity_cell_2_rust(idx, single_counts, selected_classical_registers) warnings.warn( "Rust is not available, using Python to calculate purity cell." + f"Check the error: {FAILED_RUST_IMPORT}", PostProcessingRustUnavailableWarning, ) backend = "Python" return purity_cell_2_py(idx, single_counts, selected_classical_registers)