2.2 Randomized Measurement#

WaveFunction Overlap#

This method is based on Probing Rényi entanglement entropy via randomized measurements with deplorizing error mitigation by Simple mitigation of global depolarizing errors in quantum simulations.

randomized_overlap_echo#

Here, we assume you already have the calculated data. You can call the function randomized_overlap_echo from qurry.process.randomized_measure to calculate the entropy.

This function requires only three arguments: shots, counts, and selected_classical_registers. All other arguments are optional.

Note that selected_classical_registers expects a list of bitstring indices, NOT qubit indices, as these are distinct.

The following is the arguments of the function:


def randomized_overlap_echo(
    shots: int,
    first_counts: list[dict[str, int]],
    second_counts: list[dict[str, int]],
    selected_classical_registers: Optional[Iterable[int]] = None,
    backend: PostProcessingBackendLabel = DEFAULT_PROCESS_BACKEND,
    pbar: Optional[tqdm.tqdm] = None,
) -> WaveFuctionOverlapResult:
    """Calculate wavefunction overlap
    a.k.a. loschmidt echo when processes time evolution system.

    Args:
        shots (int):
            Shots of the experiment on quantum machine.
        first_counts (list[dict[str, int]]):
            Counts of the experiment on quantum machine.
        second_counts (list[dict[str, int]]):
            Counts of the experiment on quantum machine.
        selected_classical_registers (Optional[Iterable[int]], optional):
            The list of **the index of the selected_classical_registers**.
        backend (ExistingProcessBackendLabel, optional):
            Backend for the process. Defaults to DEFAULT_PROCESS_BACKEND.
        pbar (Optional[tqdm.tqdm], optional):
            The progress bar API, you can use put a :cls:`tqdm` object here.
            This function will update the progress bar description.
            Defaults to None.


    Returns:
        WaveFuctionOverlapResult: A dictionary contains purity, entropy,
            a list of each overlap, puritySD, degree, actual measure range, bitstring range.
    """

This function returns a dictionary that contains the echo, echoSD, and other relevant information. The returned dict contains the following information:

class WaveFuctionOverlapResult(TypedDict):
    """The return type of the post-processing for wavefunction overlap."""

    echo: np.float64
    """The overlap value."""
    echoSD: np.float64
    """The overlap standard deviation."""
    echoCells: dict[int, np.float64]
    """The overlap of each single count."""
    num_classical_registers: int
    """The number of classical registers."""
    classical_registers: Optional[list[int]]
    """The list of the index of the selected classical registers."""
    classical_registers_actually: list[int]
    """The list of the index of the selected classical registers which is actually used."""
    # refactored
    counts_num: int
    """The number of first counts and second counts."""
    taking_time: float
    """The calculation time."""

Dummy Data#

from qurry.capsule import quickRead

easy_dummy: dict[str, dict[str, int]] = quickRead("../easy-dummy.json")
large_dummy_list = [easy_dummy["0"] for _ in range(100)]

Simple Example#

from qurry.process.randomized_measure import randomized_overlap_echo

test_result_1_1_1 = randomized_overlap_echo(
    4096, large_dummy_list, large_dummy_list, list(range(6))
)
from pprint import pprint

print("| result of randomized_overlap_echo except for purityCells")
pprint({k: v for k, v in test_result_1_1_1.items() if k != "echoCells"})
# "echoCells" is too long we skip it here

print("| result of randomized_overlap_echo[purityCells]")
print(test_result_1_1_1["echoCells"][0])
print(test_result_1_1_1["echoCells"][1])
| result of randomized_overlap_echo except for purityCells
{'classical_registers': [0, 1, 2, 3, 4, 5],
 'classical_registers_actually': [0, 1, 2, 3, 4, 5],
 'counts_num': 100,
 'echo': np.float64(1.0627930164337158),
 'echoSD': np.float64(0.0),
 'num_classical_registers': 8,
 'taking_time': 0.003986562}
| result of randomized_overlap_echo[purityCells]
1.0627930164337158
1.0627930164337158

Integration with your own progress bar#

from tqdm import tqdm
import time

all_counts_progress_01 = tqdm(
    [
        (4096, large_dummy_list, list(range(6))),
        (4096, large_dummy_list, list(range(2, 8))),
        (4096, large_dummy_list, list(range(7))),
        (4096, large_dummy_list, list(range(0, 7))),
        (4096, large_dummy_list, [0, 1, 2, 6, 7]),
        (4096, large_dummy_list, [3, 4, 5, 6, 7, 0, 1]),
    ],
    bar_format="| {desc} - {elapsed} < {remaining}",
)

test_result_1_1_2 = []
for tmp_shot, tmp_counts, tmp_partition in all_counts_progress_01:
    print(tmp_partition)
    test_result_1_1_2.append(
        randomized_overlap_echo(
            tmp_shot, tmp_counts, tmp_counts, tmp_partition, pbar=all_counts_progress_01
        )
    )
    time.sleep(0.5)
|  - 00:00 < ?
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5]. - 00:00 < ?
[0, 1, 2, 3, 4, 5]
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5]. - 00:00 < 00:02
| Calculate selected classical registers: [2, 3, 4, 5, 6, 7]. - 00:00 < 00:02
[2, 3, 4, 5, 6, 7]
| Calculate selected classical registers: [2, 3, 4, 5, 6, 7]. - 00:01 < 00:02
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5, 6]. - 00:01 < 00:02
[0, 1, 2, 3, 4, 5, 6]
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5, 6]. - 00:01 < 00:01
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5, 6]. - 00:01 < 00:01
[0, 1, 2, 3, 4, 5, 6]
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5, 6]. - 00:02 < 00:01
| Calculate selected classical registers: [0, 1, 2, 6, 7]. - 00:02 < 00:01      
[0, 1, 2, 6, 7]
| Calculate selected classical registers: [0, 1, 2, 6, 7]. - 00:02 < 00:00
| Calculate selected classical registers: [3, 4, 5, 6, 7, 0, 1]. - 00:02 < 00:00
[3, 4, 5, 6, 7, 0, 1]
| Calculate selected classical registers: [3, 4, 5, 6, 7, 0, 1]. - 00:03 < 00:00
| Calculate selected classical registers: [3, 4, 5, 6, 7, 0, 1]. - 00:03 < 00:00

Using Python backend#

It will be slow. You’d better think twice before using it.

all_counts_progress_02 = tqdm(
    [
        (4096, large_dummy_list, list(range(6))),
        (4096, large_dummy_list, list(range(2, 8))),
        (4096, large_dummy_list, list(range(7))),
        (4096, large_dummy_list, list(range(0, 7))),
        (4096, large_dummy_list, [0, 1, 2, 6, 7]),
        (4096, large_dummy_list, [3, 4, 5, 6, 7, 0, 1]),
    ],
    bar_format="| {desc} - {elapsed} < {remaining}",
)


test_result_1_1_2 = []
for tmp_shot, tmp_counts, tmp_partition in all_counts_progress_02:
    print(tmp_partition)
    test_result_1_1_2.append(
        randomized_overlap_echo(
            tmp_shot,
            tmp_counts,
            tmp_counts,
            tmp_partition,
            pbar=all_counts_progress_02,
            backend="Python",
        )
    )
    time.sleep(0.5)
|  - 00:00 < ?
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5]. - 00:00 < ?
[0, 1, 2, 3, 4, 5]
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5]. - 00:02 < 00:12
| Calculate selected classical registers: [2, 3, 4, 5, 6, 7]. - 00:02 < 00:12
[2, 3, 4, 5, 6, 7]
| Calculate selected classical registers: [2, 3, 4, 5, 6, 7]. - 00:05 < 00:12
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5, 6]. - 00:05 < 00:12
[0, 1, 2, 3, 4, 5, 6]
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5, 6]. - 00:09 < 00:10
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5, 6]. - 00:09 < 00:10
[0, 1, 2, 3, 4, 5, 6]
| Calculate selected classical registers: [0, 1, 2, 3, 4, 5, 6]. - 00:13 < 00:07
| Calculate selected classical registers: [0, 1, 2, 6, 7]. - 00:13 < 00:07      
[0, 1, 2, 6, 7]
| Calculate selected classical registers: [0, 1, 2, 6, 7]. - 00:17 < 00:03
| Calculate selected classical registers: [3, 4, 5, 6, 7, 0, 1]. - 00:17 < 00:03
[3, 4, 5, 6, 7, 0, 1]
| Calculate selected classical registers: [3, 4, 5, 6, 7, 0, 1]. - 00:21 < 00:00
| Calculate selected classical registers: [3, 4, 5, 6, 7, 0, 1]. - 00:21 < 00:00

Post-Process Availablities and Version Info#

from qurry.process.status import AVAIBILITY_STATESHEET

AVAIBILITY_STATESHEET
 | Qurrium version: 0.13.0
---------------------------------------------------------------------------
 ### Qurrium Post-Processing
   - Backend Availability ................... Python Cython Rust   JAX   
 - randomized_measure
   - entangled_entropy.entropy_core_2 ....... Yes    Depr.  Yes    No    
   - entangle_entropy.purity_cell_2 ......... Yes    Depr.  Yes    No    
   - entangled_entropy_v1.entropy_core ...... Yes    Depr.  Yes    No    
   - entangle_entropy_v1.purity_cell ........ Yes    Depr.  Yes    No    
   - wavefunction_overlap.echo_core_2 ....... Yes    Depr.  Yes    No    
   - wavefunction_overlap.echo_cell_2 ....... Yes    Depr.  Yes    No    
   - wavefunction_overlap_v1.echo_core ...... Yes    Depr.  Yes    No    
   - wavefunction_overlap_v1.echo_cell ...... Yes    Depr.  Yes    No    
 - hadamard_test
   - purity_echo_core ....................... Yes    No     Yes    No    
 - magnet_square
   - magnsq_core ............................ Yes    No     Yes    No    
 - string_operator
   - strop_core ............................. Yes    No     Yes    No    
 - classical_shadow
   - rho_m_core ............................. Yes    No     No     Yes   
 - utils
   - randomized ............................. Yes    Depr.  Yes    No    
   - counts_process ......................... Yes    No     Yes    No    
   - bit_slice .............................. Yes    No     Yes    No    
   - dummy .................................. Yes    No     Yes    No    
   - test ................................... Yes    No     Yes    No    
---------------------------------------------------------------------------
   + Yes ...... Working normally.
   + Error .... Exception occurred.
   + No ....... Not supported.
   + Depr. .... Deprecated.
---------------------------------------------------------------------------
by <Hoshi>