Note

This is the documentation for the current state of the development branch of Qiskit Experiments. The documentation or APIs here can change prior to being released.

Rerun analysis for an existing experiment

Problem

You want to rerun the analysis, possibly with different options, and generate a new ExperimentData object for an existing experiment whose jobs have finished execution successfully.

Solution

Note

This guide requires qiskit-ibm-runtime version 0.15 and up, which can be installed with python -m pip install qiskit-ibm-runtime. For how to migrate from the older qiskit-ibm-provider to qiskit-ibm-runtime, consult the migration guide.

Once you recreate the exact experiment you ran and all of its parameters and options, you can call the ExperimentData.add_jobs() method with a list of Job objects to generate the new ExperimentData object. The following example retrieves jobs from a provider that has access to them via their job IDs:

from qiskit_experiments.framework import ExperimentData
from qiskit_ibm_runtime import QiskitRuntimeService

# The experiment you ran
experiment = Experiment(**opts)

# List of job IDs for the experiment
job_ids= ["job1_id", "job2_id", ...]

service = QiskitRuntimeService(channel="ibm_quantum")

expdata = ExperimentData(experiment = experiment)
expdata.add_jobs([service.job(job_id) for job_id in job_ids])
experiment.analysis.run(expdata, replace_results=True)

# Block execution of subsequent code until analysis is complete
expdata.block_for_results()

expdata will be the new experiment data object containing results of the rerun analysis. Note that if replace_results isn’t set, running the analysis will return a new ExperimentData object instead of overwriting the existing one.

If you have the job data in the form of a Result object, you can invoke the ExperimentData.add_data() method instead of ExperimentData.add_jobs():

data.add_data([service.job(job_id).result() for job_id in job_ids])

The remaining workflow remains the same.

Note that for a composite experiment, you only need to run these code snippets for the parent experiment. The child experiment data will automatically populate.

Discussion

This guide is helpful for cases such as a lost connection during experiment execution, where the jobs may have finished running on the remote backends but the ExperimentData class returned upon completion of an experiment does not contain correct results.

In the case where jobs are not directly accessible from the provider but you’ve downloaded the jobs from the IQS dashboard, you can load them from the downloaded directory into Result objects with this code:

import json
from pathlib import Path

from qiskit.result import Result

result_dict = json.loads(next(Path('.').glob("*-result.txt")).read_text())
result = Result.from_dict(result_dict)

Recreation of the experiment object is often done by rerunning the code that you ran previously to create it. It may sometimes be helpful instead to save an experiment and restore it later with the following lines of code:

from qiskit_experiments.framework import ExperimentDecoder, ExperimentEncoder

serialized_exp = json.dumps(Experiment.config(), cls=ExperimentEncoder)
Experiment.from_config(json.loads(serialized_exp), cls=ExperimentDecoder)

Rerunning with different analysis options

You may also want to rerun the analysis with different options of a previously-run experiment when you instantiate this new ExperimentData object. Here’s a code snippet where we reconstruct a parallel experiment consisting of randomized benchmarking experiments, then change the gate error ratio as well as the line plot color of the first component experiment.

pexp = ParallelExperiment([
    StandardRB((i,), np.arange(1, 800, 200), num_samples=10) for i in range(2)])

pexp.analysis.component_analysis(0).options.gate_error_ratio = {
    "x": 10, "sx": 1, "rz": 0
}
pexp.analysis.component_analysis(0).plotter.figure_options.series_params.update(
    {
        "rb_decay": {"color": "r"}
    }
)

data = ExperimentData(experiment=pexp)
data.add_jobs([service.job(job_id) for job_id in job_ids])
pexp.analysis.run(data, replace_results=True)

See Also