Guide: Tracking quantum experiments

In this guide we will show you how to keep track of your quantum experiments.

First we introduce glossary: - Trial is a tracking class which wraps a single execution of your quantum experiment - Storage is a class responsible for storing trial data

We will show simple example of measuring expectation value of an observable and how to track all information about this experiment.

Let’s start with importing necessary modules.

[1]:
import os
from qiskit.circuit.random import random_circuit
from qiskit.quantum_info.random import random_pauli
from qiskit.primitives import Estimator

from purplecaffeine.core import Trial, LocalStorage

Next we need to define some variables, circuit and observable

[2]:
n_qubits = 4
depth = 3
shots = 2000

circuit = random_circuit(n_qubits, depth)
circuit.draw(fold=-1)
[2]:
                                                      ┌────┐
q_0: ────────────────────────────■────────────────────┤ √X ├──────■────────
     ┌────────────┐              │                    ├───┬┘      │ ┌─────┐
q_1: ┤ Rz(4.2568) ├──────────────┼────────────────────┤ S ├───────┼─┤ Tdg ├
     ├────────────┤              │               ┌────┴───┴─────┐ │ └─────┘
q_2: ┤ Rz(3.9296) ├──────────────┼───────────────┤0             ├─■────────
     └────────────┘┌─────────────┴──────────────┐│  Ryy(5.7992) │ │
q_3: ──────────────┤ U3(0.057242,4.0814,3.8183) ├┤1             ├─■────────
                   └────────────────────────────┘└──────────────┘          
[3]:
obs = random_pauli(n_qubits)
obs
[3]:
Pauli('YIIZ')

We also need a place where we will store data about our trials. In this example we will be using LocalStorage which stores information locally in a folder that you configured. We will set our folder for trials to be ./trials.

[4]:
local_storage = LocalStorage("./trials")
#You could also set the API storage or S3 storage by calling :
#api_storage = ApiStorage(host="http://localhost:8000", username="MY_USERNAME", password="MY_PASS")
#s3_storage = S3Storage("bucket", access_key="MY_KEY", secret_access_key="MY_SECRET")

In order to track our actions we need to work with Trial class, give it a name Example trial, pass our local_storage as storage option and start context (python with statement).

Within this context we can call list of different methods on trial object. Some of them are: - add_parameter adds parameters to the trial, which can be storage names, depth, number of qubits, etc. - add_metric adds metric to the trial, which can represent measurable outcome of this trial. Ex: history of vqe iterations, results of measurement, etc. - add_circuit adds circuit to the trial to understand what circuits where used in your work - add_operator adds operator to the trial to understand what observables/operators where used in your work

[5]:
with Trial("Example trial", storage=local_storage) as trial:
    # track some parameters
    trial.add_parameter("estimator", "qiskit.primitives.Estimator")
    trial.add_parameter("depth", depth)
    trial.add_parameter("n_qubits", n_qubits)
    trial.add_parameter("shots", shots)

    # track objects of interest
    trial.add_circuit("circuit", circuit)
    trial.add_operator("obs", obs)

    # run
    exp_value = Estimator().run(circuit, obs, shots=shots).result().values.item()

    # track results of run
    trial.add_metric("exp_value", exp_value)

We can get list of all experiments by calling list method on storage object.

[6]:
local_storage.list()
[6]:
[<Trial [Example trial] 88b5ef54-a66b-45e1-aed8-c7db7ad82594>,
 <Trial [Example trial] b418c1d2-11d7-424a-bef8-8c5c8d9976aa>,
 <Trial [Example trial] b47737a7-deac-46ae-af11-5bd587c0b688>,
 <Trial [Example trial] 2ef8eaca-0fd5-4e21-9257-1e080ed85ed2>]

We can quiery existing experiments by name by calling get method on storage object and passing name of your example

[7]:
trials = local_storage.list()

random_trial = trials[0]
trial_uuid = random_trial.uuid

local_storage.get(trial_uuid)
[7]:
<Trial [Example trial] 88b5ef54-a66b-45e1-aed8-c7db7ad82594>