2.2 Wave Function Overlap by Randomized MeasurementΒΆ


Basic UsageΒΆ

a. Import the instancesΒΆ

from qurry import WaveFunctionOverlap

experiment_randomized = WaveFunctionOverlap()
# It's default method. WaveFunctionOverlap(method='randomized') also works

# or another short name
# from qurry import EchoListen
# experiment_hadamard = EchoListen()

b. Preparing quantum circuitΒΆ

from qiskit import QuantumCircuit
from qurry.recipe import TrivialParamagnet, GHZ
sample01 = TrivialParamagnet(8)
print("| trivial paramagnet in 8 qubits:")
print(sample01)
| trivial paramagnet in 8 qubits:
     β”Œβ”€β”€β”€β”
q_0: ─ H β”œ
     β”œβ”€β”€β”€β”€
q_1: ─ H β”œ
     β”œβ”€β”€β”€β”€
q_2: ─ H β”œ
     β”œβ”€β”€β”€β”€
q_3: ─ H β”œ
     β”œβ”€β”€β”€β”€
q_4: ─ H β”œ
     β”œβ”€β”€β”€β”€
q_5: ─ H β”œ
     β”œβ”€β”€β”€β”€
q_6: ─ H β”œ
     β”œβ”€β”€β”€β”€
q_7: ─ H β”œ
     β””β”€β”€β”€β”˜
sample02 = GHZ(8)
print("| GHZ in 8 qubits:")
print(sample02)
| GHZ in 8 qubits:
     β”Œβ”€β”€β”€β”                                   
q_0: ─ H β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                              
q_1: ────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
          β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                         
q_2: ─────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
               β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                    
q_3: ──────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                    β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”               
q_4: ───────────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                         β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”          
q_5: ────────────────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€
                              β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”     
q_6: ─────────────────────────────── X β”œβ”€β”€β– β”€β”€
                                   β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”
q_7: ──────────────────────────────────── X β”œ
                                        β””β”€β”€β”€β”˜
sample03 = QuantumCircuit(8)
sample03.x(range(0, 8, 2))
print("| Custom circuit:")
print(sample03)
| Custom circuit:
     β”Œβ”€β”€β”€β”
q_0: ─ X β”œ
     β””β”€β”€β”€β”˜
q_1: ─────
     β”Œβ”€β”€β”€β”
q_2: ─ X β”œ
     β””β”€β”€β”€β”˜
q_3: ─────
     β”Œβ”€β”€β”€β”
q_4: ─ X β”œ
     β””β”€β”€β”€β”˜
q_5: ─────
     β”Œβ”€β”€β”€β”
q_6: ─ X β”œ
     β””β”€β”€β”€β”˜
q_7: ─────
          

c. Execute the circuitΒΆ

i. Directly input the circuitΒΆ

After executing, it will return a uuid of experiment. You can use this uuid to get the result of the experiment.

exp1 = experiment_randomized.measure(sample01, sample01, times=100, shots=4096)
exp1
'775dca61-e802-4f30-a9e6-d0d3f333652d'

Each experiment result will be stored in a container .exps.

experiment_randomized.exps[exp1]
<EchoListenRandomizedExperiment(exp_id=775dca61-e802-4f30-a9e6-d0d3f333652d, 
  EchoListenRandomizedArguments(exp_name='experiment.N_U_100.qurrech_randomized', times=100, qubits_measured_1=[0, 1, 2, 3, 4, 5, 6, 7], qubits_measured_2=[0, 1, 2, 3, 4, 5, 6, 7], registers_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, registers_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, actual_num_qubits_1=8, actual_num_qubits_2=8, unitary_located_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, unitary_located_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, second_backend=None, second_transpile_args=None, random_unitary_seeds=None),
  Commonparams(exp_id='775dca61-e802-4f30-a9e6-d0d3f333652d', target_keys=[0, 1], shots=4096, backend=<AerSimulator('aer_simulator')>, run_args={}, transpile_args={}, tags=(), save_location=PosixPath('.'), serial=None, summoner_id=None, summoner_name=None, datetimes=DatetimeDict({'build': '2025-07-08 16:58:26', 'run.001': '2025-07-08 16:58:26'})),
  unused_args_num=0,
  analysis_num=0))>
experiment_randomized.exps[exp1].args._asdict()
{'exp_name': 'experiment.N_U_100.qurrech_randomized',
 'times': 100,
 'qubits_measured_1': [0, 1, 2, 3, 4, 5, 6, 7],
 'qubits_measured_2': [0, 1, 2, 3, 4, 5, 6, 7],
 'registers_mapping_1': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7},
 'registers_mapping_2': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7},
 'actual_num_qubits_1': 8,
 'actual_num_qubits_2': 8,
 'unitary_located_mapping_1': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7},
 'unitary_located_mapping_2': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7},
 'second_backend': None,
 'second_transpile_args': None,
 'random_unitary_seeds': None}

And use this uuid to access the experiments to execute post-processing.

report01 = experiment_randomized.exps[exp1].analyze(
    selected_classical_registers=[0, 1, 2, 3],
)
report01
<ELRAnalysis(
  serial=0,
  ELRAnalysisInput(registers_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, registers_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, bitstring_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, bitstring_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, shots=4096, unitary_located_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, unitary_located_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}),
  ELRAnalysisContent(echo=1.0864680528640747, and others)),
  unused_args_num=0
  )>
main01, side_product01 = report01.export()
main01
{'echo': np.float64(1.0864680528640747),
 'echoSD': np.float64(1.300102849432404),
 'num_classical_registers': 8,
 'classical_registers': [0, 1, 2, 3],
 'classical_registers_actually': [0, 1, 2, 3],
 'counts_num': 100,
 'taking_time': 0.002568466,
 'counts_used': None,
 'input': {'registers_mapping_1': {0: 0,
   1: 1,
   2: 2,
   3: 3,
   4: 4,
   5: 5,
   6: 6,
   7: 7},
  'registers_mapping_2': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7},
  'bitstring_mapping_1': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7},
  'bitstring_mapping_2': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7},
  'shots': 4096,
  'unitary_located_mapping_1': {0: 0,
   1: 1,
   2: 2,
   3: 3,
   4: 4,
   5: 5,
   6: 6,
   7: 7},
  'unitary_located_mapping_2': {0: 0,
   1: 1,
   2: 2,
   3: 3,
   4: 4,
   5: 5,
   6: 6,
   7: 7}},
 'header': {'serial': 0, 'datetime': '2025-07-08 16:58:27', 'log': {}}}

ii. Add the circuits to container .waves, then call them later.ΒΆ

Since we have executed an experiment, the circuit we input in exp1 is stored in the container .waves with serial number 0.

experiment_randomized.waves
WaveContainer({
  0: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x76f599bcdbe0>,
  1: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x76f599bcdbe0>})

But we can also add the circuit to the container .waves with a custom name. The name should be unique, otherwise it will be overwritten. The method add will return the actual name of the circuit in the container.

print(experiment_randomized.add(sample02, "ghz_8"))
print(experiment_randomized.waves["ghz_8"])
ghz_8
     β”Œβ”€β”€β”€β”                                   
q_0: ─ H β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                              
q_1: ────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
          β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                         
q_2: ─────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
               β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                    
q_3: ──────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                    β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”               
q_4: ───────────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                         β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”          
q_5: ────────────────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€
                              β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”     
q_6: ─────────────────────────────── X β”œβ”€β”€β– β”€β”€
                                   β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”
q_7: ──────────────────────────────────── X β”œ
                                        β””β”€β”€β”€β”˜

If there is a circuit with the same name, it will be replaced by the new one.

print(experiment_randomized.add(sample03, "ghz_8"))
print(experiment_randomized.waves["ghz_8"])
ghz_8
     β”Œβ”€β”€β”€β”
q_0: ─ X β”œ
     β””β”€β”€β”€β”˜
q_1: ─────
     β”Œβ”€β”€β”€β”
q_2: ─ X β”œ
     β””β”€β”€β”€β”˜
q_3: ─────
     β”Œβ”€β”€β”€β”
q_4: ─ X β”œ
     β””β”€β”€β”€β”˜
q_5: ─────
     β”Œβ”€β”€β”€β”
q_6: ─ X β”œ
     β””β”€β”€β”€β”˜
q_7: ─────
          

Otherwise, you will need to use replace="duplicate" to prevent it from being replaced.

duplicated_case01 = experiment_randomized.add(sample02, "ghz_8", replace="duplicate")
print(duplicated_case01)
print(experiment_randomized.waves[duplicated_case01])
ghz_8.3
     β”Œβ”€β”€β”€β”                                   
q_0: ─ H β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                              
q_1: ────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
          β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                         
q_2: ─────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
               β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”                    
q_3: ──────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                    β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”               
q_4: ───────────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                         β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”          
q_5: ────────────────────────── X β”œβ”€β”€β– β”€β”€β”€β”€β”€β”€β”€
                              β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”     
q_6: ─────────────────────────────── X β”œβ”€β”€β– β”€β”€
                                   β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β”
q_7: ──────────────────────────────────── X β”œ
                                        β””β”€β”€β”€β”˜

Now we have prepared the circuit and stored it in the container .waves.

experiment_randomized.waves
WaveContainer({
  0: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x76f599bcdbe0>,
  1: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x76f599bcdbe0>,
  'ghz_8': <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x76f599ab8e90>,
  'ghz_8.3': <qurry.recipe.simple.cat.GHZ object at 0x76f599bcebd0>})

Finally, we can execute the circuit and get the result.

exp2 = experiment_randomized.measure("ghz_8.3", sample01, times=100, shots=4096)
exp2
'0c14579c-4d29-47a3-b528-34c8ecdc5dbe'
experiment_randomized.exps[exp2]
<EchoListenRandomizedExperiment(exp_id=0c14579c-4d29-47a3-b528-34c8ecdc5dbe, 
  EchoListenRandomizedArguments(exp_name='experiment.N_U_100.qurrech_randomized', times=100, qubits_measured_1=[0, 1, 2, 3, 4, 5, 6, 7], qubits_measured_2=[0, 1, 2, 3, 4, 5, 6, 7], registers_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, registers_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, actual_num_qubits_1=8, actual_num_qubits_2=8, unitary_located_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, unitary_located_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, second_backend=None, second_transpile_args=None, random_unitary_seeds=None),
  Commonparams(exp_id='0c14579c-4d29-47a3-b528-34c8ecdc5dbe', target_keys=['ghz_8.3', 4], shots=4096, backend=<AerSimulator('aer_simulator')>, run_args={}, transpile_args={}, tags=(), save_location=PosixPath('.'), serial=None, summoner_id=None, summoner_name=None, datetimes=DatetimeDict({'build': '2025-07-08 16:58:53', 'run.001': '2025-07-08 16:58:53'})),
  unused_args_num=0,
  analysis_num=0))>
report02 = experiment_randomized.exps[exp2].analyze(
    selected_classical_registers=[0, 1, 2, 3],
)
report02
<ELRAnalysis(
  serial=0,
  ELRAnalysisInput(registers_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, registers_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, bitstring_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, bitstring_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, shots=4096, unitary_located_mapping_1={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}, unitary_located_mapping_2={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}),
  ELRAnalysisContent(echo=0.059253928065299985, and others)),
  unused_args_num=0
  )>

d. Export them after allΒΆ

exp1_id, exp1_files_info = experiment_randomized.exps[exp1].write(
    save_location=".",  # where to save files
)
exp1_files_info
{'folder': 'experiment.N_U_100.qurrech_randomized.001',
 'qurryinfo': 'experiment.N_U_100.qurrech_randomized.001/qurryinfo.json',
 'args': 'experiment.N_U_100.qurrech_randomized.001/args/experiment.N_U_100.qurrech_randomized.001.id=775dca61-e802-4f30-a9e6-d0d3f333652d.args.json',
 'advent': 'experiment.N_U_100.qurrech_randomized.001/advent/experiment.N_U_100.qurrech_randomized.001.id=775dca61-e802-4f30-a9e6-d0d3f333652d.advent.json',
 'legacy': 'experiment.N_U_100.qurrech_randomized.001/legacy/experiment.N_U_100.qurrech_randomized.001.id=775dca61-e802-4f30-a9e6-d0d3f333652d.legacy.json',
 'tales.unitaryOP': 'experiment.N_U_100.qurrech_randomized.001/tales/experiment.N_U_100.qurrech_randomized.001.id=775dca61-e802-4f30-a9e6-d0d3f333652d.unitaryOP.json',
 'tales.randomized': 'experiment.N_U_100.qurrech_randomized.001/tales/experiment.N_U_100.qurrech_randomized.001.id=775dca61-e802-4f30-a9e6-d0d3f333652d.randomized.json',
 'reports': 'experiment.N_U_100.qurrech_randomized.001/reports/experiment.N_U_100.qurrech_randomized.001.id=775dca61-e802-4f30-a9e6-d0d3f333652d.reports.json',
 'reports.tales.echoCells': 'experiment.N_U_100.qurrech_randomized.001/tales/experiment.N_U_100.qurrech_randomized.001.id=775dca61-e802-4f30-a9e6-d0d3f333652d.echoCells.reports.json'}

Post-Process Availablities and Version InfoΒΆ

from qurry.process 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>