0.1 WavesExecuter#


Basic Usage#

This QurriumInstance does not any post-processing feature but provides a workdlow that can execute multiple at once.

a. Import the instances#

from qurry import WavesExecuter

experiment_workflow = WavesExecuter()

b. Preparing quantum circuit#

Remember for any quantum circuit, you need to make sure that they all contain classical registers. Otherwise, WavesExecuter will raise an ValueError when you try to execute the circuit.

from qiskit import QuantumCircuit
from qurry.recipe import TrivialParamagnet, GHZ


def make_neel_circuit(n):
    qc = QuantumCircuit(n)
    for i in range(0, n, 2):
        qc.x(i)
    return qc


circuits_dict = {}

for i in range(2, 13, 2):
    circuits_dict[f"trivial_paramagnet_{i}_ms"] = TrivialParamagnet(i)
    circuits_dict[f"ghz_{i}_ms"] = GHZ(i)
    circuits_dict[f"neel_{i}_ms"] = make_neel_circuit(i)

for name, circuit in circuits_dict.items():
    circuit.measure_all()
no_creq = TrivialParamagnet(2)
print(no_creq.draw())

try:
    experiment_workflow.measure([no_creq], shots=1024)
except ValueError as e:
    print(f"Error: {e}")
     ┌───┐
q_0: ┤ H ├
     ├───┤
q_1: ┤ H ├
     └───┘
Error: | No classical register in ALL circuits, counts will be empty. Please add classical register to the circuit. (Don't be frustrated, I did the same thing on unit test. It made me confused and thought what's wrong for a while before ('_').)

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_workflow.measure(list(circuits_dict.values()), shots=1024)
exp1
'f7fb93b4-d567-4038-87fb-655a906f0c1a'

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

experiment_workflow.exps[exp1]
<WavesExecuterExperiment(exp_id=f7fb93b4-d567-4038-87fb-655a906f0c1a, 
  WavesExecuterArguments(exp_name='experiment.waves_executer'),
  Commonparams(exp_id='f7fb93b4-d567-4038-87fb-655a906f0c1a', target_keys=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], shots=1024, backend=<AerSimulator('aer_simulator')>, run_args={}, transpile_args={}, tags=(), save_location=PosixPath('.'), serial=None, summoner_id=None, summoner_name=None, datetimes=DatetimeDict({'build': '2025-06-26 11:47:19', 'run.001': '2025-06-26 11:47:19'})),
  unused_args_num=0,
  analysis_num=0))>

WavesExecuter does not provide any post-processing feature. So .analyze() will not provide any useful information, but

The Answer to the Ultimate Question of Life, The Universe, and Everything

report01 = experiment_workflow.exps[exp1].analyze()
report01
| ultimate_question: 
<WavesQurryAnalysis(
  serial=0,
  WEAnalysisInput(ultimate_question=''),
  WEAnalysisContent(ultimate_answer=42, dummy=-100)),
  unused_args_num=0
  )>
main01, side_product01 = report01.export()
main01
{'ultimate_answer': 42,
 'dummy': -100,
 'input': {'ultimate_question': ''},
 'header': {'serial': 0, 'datetime': '2025-06-26 11:47:19', '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_workflow.waves
WaveContainer({
  0: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c95f27a0>,
  1: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94bc6e0>,
  2: <qurry.recipe.simple.cat.GHZ object at 0x7632c94bc830>,
  3: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b97f0>,
  4: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9752c10>,
  5: <qurry.recipe.simple.cat.GHZ object at 0x7632c9752d50>,
  6: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b99b0>,
  7: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9752e90>,
  8: <qurry.recipe.simple.cat.GHZ object at 0x7632c9752fd0>,
  9: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b98d0>,
  10: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94715b0>,
  11: <qurry.recipe.simple.cat.GHZ object at 0x7632c94716e0>,
  12: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9a90>,
  13: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9471a70>,
  14: <qurry.recipe.simple.cat.GHZ object at 0x7632c9471ba0>,
  15: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9e10>,
  16: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94c43b0>,
  17: <qurry.recipe.simple.cat.GHZ object at 0x7632c94c4050>,
  18: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9c50>})

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.

for k, v in circuits_dict.items():
    print("| Circuit:", experiment_workflow.add(v, k), "added.")
| Circuit: trivial_paramagnet_2_ms added.
| Circuit: ghz_2_ms added.
| Circuit: neel_2_ms added.
| Circuit: trivial_paramagnet_4_ms added.
| Circuit: ghz_4_ms added.
| Circuit: neel_4_ms added.
| Circuit: trivial_paramagnet_6_ms added.
| Circuit: ghz_6_ms added.
| Circuit: neel_6_ms added.
| Circuit: trivial_paramagnet_8_ms added.
| Circuit: ghz_8_ms added.
| Circuit: neel_8_ms added.
| Circuit: trivial_paramagnet_10_ms added.
| Circuit: ghz_10_ms added.
| Circuit: neel_10_ms added.
| Circuit: trivial_paramagnet_12_ms added.
| Circuit: ghz_12_ms added.
| Circuit: neel_12_ms added.

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

print(experiment_workflow.add(circuits_dict["trivial_paramagnet_2_ms"], "ghz_8_ms"))
print(experiment_workflow.waves["ghz_8_ms"])
ghz_8_ms
        ┌───┐ ░ ┌─┐   
   q_0: ┤ H ├─░─┤M├───
        ├───┤ ░ └╥┘┌─┐
   q_1: ┤ H ├─░──╫─┤M├
        └───┘ ░  ║ └╥┘
meas: 2/═════════╩══╩═
                 0  1 

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

duplicated_case01 = experiment_workflow.add(
    circuits_dict["trivial_paramagnet_2_ms"], "ghz_8_ms", replace="duplicate"
)
print(duplicated_case01)
print(experiment_workflow.waves[duplicated_case01])
ghz_8_ms.37
        ┌───┐ ░ ┌─┐   
   q_0: ┤ H ├─░─┤M├───
        ├───┤ ░ └╥┘┌─┐
   q_1: ┤ H ├─░──╫─┤M├
        └───┘ ░  ║ └╥┘
meas: 2/═════════╩══╩═
                 0  1 

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

experiment_workflow.waves
WaveContainer({
  0: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c95f27a0>,
  1: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94bc6e0>,
  2: <qurry.recipe.simple.cat.GHZ object at 0x7632c94bc830>,
  3: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b97f0>,
  4: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9752c10>,
  5: <qurry.recipe.simple.cat.GHZ object at 0x7632c9752d50>,
  6: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b99b0>,
  7: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9752e90>,
  8: <qurry.recipe.simple.cat.GHZ object at 0x7632c9752fd0>,
  9: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b98d0>,
  10: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94715b0>,
  11: <qurry.recipe.simple.cat.GHZ object at 0x7632c94716e0>,
  12: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9a90>,
  13: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9471a70>,
  14: <qurry.recipe.simple.cat.GHZ object at 0x7632c9471ba0>,
  15: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9e10>,
  16: <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94c43b0>,
  17: <qurry.recipe.simple.cat.GHZ object at 0x7632c94c4050>,
  18: <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9c50>,
  'trivial_paramagnet_2_ms': <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94bc6e0>,
  'ghz_2_ms': <qurry.recipe.simple.cat.GHZ object at 0x7632c94bc830>,
  'neel_2_ms': <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b97f0>,
  'trivial_paramagnet_4_ms': <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9752c10>,
  'ghz_4_ms': <qurry.recipe.simple.cat.GHZ object at 0x7632c9752d50>,
  'neel_4_ms': <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b99b0>,
  'trivial_paramagnet_6_ms': <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9752e90>,
  'ghz_6_ms': <qurry.recipe.simple.cat.GHZ object at 0x7632c9752fd0>,
  'neel_6_ms': <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b98d0>,
  'trivial_paramagnet_8_ms': <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94715b0>,
  'ghz_8_ms': <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94bc6e0>,
  'neel_8_ms': <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9a90>,
  'trivial_paramagnet_10_ms': <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c9471a70>,
  'ghz_10_ms': <qurry.recipe.simple.cat.GHZ object at 0x7632c9471ba0>,
  'neel_10_ms': <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9e10>,
  'trivial_paramagnet_12_ms': <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94c43b0>,
  'ghz_12_ms': <qurry.recipe.simple.cat.GHZ object at 0x7632c94c4050>,
  'neel_12_ms': <qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7632c94b9c50>,
  'ghz_8_ms.37': <qurry.recipe.simple.paramagnet.TrivialParamagnet object at 0x7632c94bc6e0>})

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

exp2 = experiment_workflow.measure(list(circuits_dict.keys()), shots=1024)
exp2
'd0bb1e3c-b586-49ba-8c35-e8c49ad25c0f'
experiment_workflow.exps[exp2]
<WavesExecuterExperiment(exp_id=d0bb1e3c-b586-49ba-8c35-e8c49ad25c0f, 
  WavesExecuterArguments(exp_name='experiment.waves_executer'),
  Commonparams(exp_id='d0bb1e3c-b586-49ba-8c35-e8c49ad25c0f', target_keys=['trivial_paramagnet_2_ms', 'ghz_2_ms', 'neel_2_ms', 'trivial_paramagnet_4_ms', 'ghz_4_ms', 'neel_4_ms', 'trivial_paramagnet_6_ms', 'ghz_6_ms', 'neel_6_ms', 'trivial_paramagnet_8_ms', 'ghz_8_ms', 'neel_8_ms', 'trivial_paramagnet_10_ms', 'ghz_10_ms', 'neel_10_ms', 'trivial_paramagnet_12_ms', 'ghz_12_ms', 'neel_12_ms'], shots=1024, backend=<AerSimulator('aer_simulator')>, run_args={}, transpile_args={}, tags=(), save_location=PosixPath('.'), serial=None, summoner_id=None, summoner_name=None, datetimes=DatetimeDict({'build': '2025-06-26 11:47:25', 'run.001': '2025-06-26 11:47:25'})),
  unused_args_num=0,
  analysis_num=0))>
report02 = experiment_workflow.exps[exp2].analyze(
    "What is the answer to the ultimate question of life, the universe, and everything"
)
report02
| ultimate_question: What is the answer to the ultimate question of life, the universe, and everything
<WavesQurryAnalysis(
  serial=0,
  WEAnalysisInput(ultimate_question='What is the answer to the ultimate question of life, the universe, and everything'),
  WEAnalysisContent(ultimate_answer=42, dummy=-100)),
  unused_args_num=0
  )>

d. take counts#

print("| First 2 counts of the second experiment:")

experiment_workflow.exps[exp2].afterwards.counts[:2]
| First 2 counts of the second experiment:
[{'11': 274, '10': 251, '00': 239, '01': 260}, {'00': 515, '11': 509}]

e. Export them after all#

exp1_id, exp1_files_info = experiment_workflow.exps[exp1].write(
    save_location=".",  # where to save files
)
exp1_files_info
{'folder': 'experiment.waves_executer.001',
 'qurryinfo': 'experiment.waves_executer.001/qurryinfo.json',
 'args': 'experiment.waves_executer.001/args/experiment.waves_executer.001.id=f7fb93b4-d567-4038-87fb-655a906f0c1a.args.json',
 'advent': 'experiment.waves_executer.001/advent/experiment.waves_executer.001.id=f7fb93b4-d567-4038-87fb-655a906f0c1a.advent.json',
 'legacy': 'experiment.waves_executer.001/legacy/experiment.waves_executer.001.id=f7fb93b4-d567-4038-87fb-655a906f0c1a.legacy.json',
 'reports': 'experiment.waves_executer.001/reports/experiment.waves_executer.001.id=f7fb93b4-d567-4038-87fb-655a906f0c1a.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>