Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fail to recover Experiment from the config if the experiment was initialized with an IBM runtime backend #1508

Open
IvanaGyro opened this issue Jan 5, 2025 · 1 comment
Labels
bug Something isn't working

Comments

@IvanaGyro
Copy link

Informations

  • Qiskit Experiments version: 0.8.0
  • Python version: Python 3.12.0b4
  • Operating system: Windows 11

What is the current behavior?

An expectation was raised:

  File "site-packages\qiskit_experiments\framework\json.py", line 338, in _deserialize_object
    return cls(**settings)
           ^^^^^^^^^^^^^^^
TypeError: IBMBackend.__init__() missing 3 required positional arguments: 'configuration', 'service', and 'api_client'

The reason is that the ABC class StoreInitArgs stores all keyword arguments to an argument __init_kwargs__, which will be accessed by BaseExperiment.config() and BaseExperiment.from_config(). However, the instance of IBMBackend cannot be encoded and decoded correctly by ExperimentEncoder and ExperimentDecoder.

Steps to reproduce the problem

Below is the minimal example code for reproducing the problem.

import json

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_experiments.framework import ExperimentDecoder, ExperimentEncoder
from qiskit_experiments.library import T2Ramsey

service = QiskitRuntimeService(
    instance='ibm-q/open/main',
    channel='ibm_quantum',
    token='MY_TOKEN'
)

experiment = T2Ramsey(
    physical_qubits=(0,),
    delays=[0., 1.0e-6],
    backend=service.backend('ibm_sherbrooke'),
    osc_freq=0.0)

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

What is the expected behavior?

BaseExperiment should be able to recover the instance when the instance was initialized with an IBM runtime backend instance.

Suggested solutions

Below is not a suggested solution but a workaround: manually assigning backend instance after init/recover the experiment.

import json

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_experiments.framework import ExperimentDecoder, ExperimentEncoder
from qiskit_experiments.library import T2Ramsey

service = QiskitRuntimeService(
    instance='ibm-q/open/main',
    channel='ibm_quantum',
    token='MY_TOKEN'
)

experiment = T2Ramsey(
    physical_qubits=(0,),
    delays=[0., 1.0e-6],
    osc_freq=0.0)

experiment.backend = service.backend('ibm_sherbrooke')

serialized_exp = json.dumps(experiment.config(), cls=ExperimentEncoder)
recovered_exp = T2Ramsey.from_config(json.loads(serialized_exp, cls=ExperimentDecoder))
recovered_exp.backend = service.backend('ibm_sherbrooke')
@IvanaGyro IvanaGyro added the bug Something isn't working label Jan 5, 2025
IvanaGyro added a commit to IvanaGyro/qiskit-pulse-control that referenced this issue Jan 7, 2025
The JSON encoder and decoder provided by Qiskit Experiments cannot
properly encode and decode the instances of Experiment initialized with
real backends. To cache and recover the tasks of experiments, we have
to delete the backend entry before encoding the task. The issue below
provides an workaround to add the backend back after decoding.

qiskit-community/qiskit-experiments#1508
@wshanks
Copy link
Collaborator

wshanks commented Jan 7, 2025

This issue is similar to #706. We could add a special case to the json encoder to handle IBMBackend or just BackendV2. I think the reason this has not been done so far is that the backend is difficult to serialize in general since it contains a lot of ephemeral data and can also contain user settings (like the complaint in #706). So if you wanted to preserve the backend as it was when the experiment was run (better if you wanted to do further analysis) you would need to save all of that. However, if you wanted to reload the experiment to run again you would want to reload the backend with its current data instead of the historical data (in case gates have changed).

Note that currently the reproducer code does not produce an exception. It produces a warning and drops backend from the experiment kwargs during deserialization. This is similar to what was suggested to do in #706 (set the backend to None) but with a warning for the user. It might be a bit better to warn about the backend being set to None in the encoder instead of the decoder.

I am not sure it is worth trying to support saving and reloading the backend. We could do that for IBMBackend by saving the name and trying to create a QiskitRuntimeService and loading the backend from it, but the user might need to use non-default credentials for the service to load the backend and that is hard to save as well. Also, it would need to be clear to the user that this backend object might have different data from when the experiment was run. More support for saving and reloading backends in qiskit-ibm-runtime would be helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants