Support local execution on simulators#1243
Support local execution on simulators#1243merav-aharoni wants to merge 60 commits intoQiskit:mainfrom
Conversation
|
I wrote the basic flow, including a simple test. However, I encountered quite a few problems/questions:
|
I don't believe so, we can just support V2 for now
No, QASM3 is not currently supported on simulators
No, I don't believe so -
No, sessions don't have any meaning when using simulators - jobs on simulators run the same way, independent of whether
Yes, the user must have an account |
…untime into fake_backends
…untime into fake_backends
…untime into fake_backends
|
On second thought, I am not sure we need to do anything more for executing Results are: What do you think? |
|
|
||
| from qiskit.providers.provider import ProviderV1 | ||
| from qiskit.providers.exceptions import QiskitBackendNotFoundError | ||
| from qiskit.providers.fake_provider.fake_backend import FakeBackendV2 |
There was a problem hiding this comment.
I have recently opened a PR that migrates the fake provider base classes from qiskit (#1270), should it be merged before this PR, this import path would change to from qiskit_ibm_runtime.fake_provider.fake_backend import FakeBackendV2. I'm happy to monitor it on my side, but thought it would make sense to bring it to your attention too.
|
|
||
| from qiskit.primitives.primitive_job import PrimitiveJob | ||
| from qiskit.providers import JobStatus, JobV1 | ||
| from qiskit.providers.fake_provider import FakeBackendV2 as FakeBackend |
There was a problem hiding this comment.
same comment as above regarding the import path
|
|
||
| """Utility functions for options.""" | ||
|
|
||
| from qiskit.providers.fake_provider import fake_backend |
| ) -> None: | ||
| """FakeRuntimeJob constructor.""" | ||
| super().__init__(backend=backend, job_id=job_id) | ||
| # self._service = service # do we need this? |
There was a problem hiding this comment.
I don't think we need service, but it would be nice to have the other ones - creation_date, user_callback, result_decoder, tags
There was a problem hiding this comment.
I added creation_date and tags.
Removed user_callback as you wrote below and also because it refers to interim results.
Removed result_decoder as you wrote below, because results will not be returned encoded.
| inputs=primitive_inputs, | ||
| # are the following relevant for simulators? | ||
| # callback=combined.get("environment", {}).get("callback", None), | ||
| # result_decoder=DEFAULT_DECODERS.get(self._program_id()), |
There was a problem hiding this comment.
I think we can leave these out for simulators
There was a problem hiding this comment.
In terms of the other options, I think it'd be nice to have the run options like:
{'shots': 400, 'init_qubits': True, 'noise_model': None, 'seed_simulator': None}
and
{'max_execution_time': None, 'log_level': 'WARNING', 'job_tags': []}
There was a problem hiding this comment.
shotsandseed_simulatorare already supported.- I couldn't fine
init_qubitsor anything similar in theAerSimulator, so I don't think there is any point of passing it on. Let me know if you know otherwise. I did find it as a parameter ofassemble_circuitsin Terra, but I am not sure how and if this is called. - Same as above for
max_execution_time. noise_model- I think this is only relevant when callingAerSimulatorand not for fake backends, because the latter define their own noise models. For Aer, I pass along all the options that areAerSimulator._default_options().- Regarding
log_level, inTerraand inAer, I only found setting thelog_levelglobally as an environment variable, so I am not sure what we can do here. job_tags- I added toFakeRuntimeJob.
| if isinstance(backend, IBMBackend): | ||
| self._service = backend.service | ||
| self._backend = backend | ||
| elif isinstance(backend, AerSimulator): |
There was a problem hiding this comment.
This should check for both Aer and FakeBackend
There was a problem hiding this comment.
Good comment. I actually only supported FakeBackendV2 when given as a string. I modified here and added to the test TestRunSimulation.test_basic_flow.
| from dataclasses import asdict | ||
| import warnings | ||
|
|
||
| from qiskit_aer import AerSimulator |
There was a problem hiding this comment.
Aer is not a required package, so this import be wrapped with try/except
There was a problem hiding this comment.
Added try and raise exception when attempting to run with a simulator and not aer.
Also added skip for relevant tests.
Please have a look if it is done properly.
| primitive_inputs.update(Options._get_program_inputs(combined)) | ||
|
|
||
| if self._backend and combined["transpilation"]["skip_transpilation"]: | ||
| if self._backend and combined["transpilation"]["skip_transpilation"] and not run_simulator: |
There was a problem hiding this comment.
check_faulty should apply to fake backends as well, if we ever get one that mimics a real backend with faulty edge/qubits
There was a problem hiding this comment.
There is currently no check_faulty method in FakeBackendV2 nor in AerSimulator. To support this, we would need to add such a method to FakeBackendV2 after it is transferred to Runtime. So I suggest we defer this to a separate issue.
| def result(self) -> Any: | ||
| """Return the results of the job.""" | ||
| return self._primitive_job.result() | ||
|
|
||
| def cancel(self) -> None: | ||
| self._primitive_job.cancel() | ||
|
|
||
| def status(self) -> JobStatus: | ||
| return self._primitive_job.status() |
There was a problem hiding this comment.
Why not just inherit PrimitiveJob, then you only need to add methods not already supported.
There was a problem hiding this comment.
I tried, but couldn't manage to do that, because I am receiving primitive_job as an object and couldn't find a way to construct the FakeRuntimeObject with a pre-constructed super() object. I would need something like a copy constructor.
I could simply use PrimitiveJob directly, but then I wouldn't be able to add any fields/methods.
Can you advise how to do this with inheritance?
| is_simulator = ( | ||
| isinstance(backend, fake_backend.FakeBackendV2) or backend.configuration().simulator | ||
| ) |
There was a problem hiding this comment.
There is no need to change optimization_level and resilience_level for fake backends. Fake backends should always have noise model (from the real backend it mimics), so one doesn't have to pass it in. And none supports resilience_level.
There was a problem hiding this comment.
Changed so we don't apply this to a FakeBackend.
| self._service = ( | ||
| QiskitRuntimeService() | ||
| if QiskitRuntimeService.global_service is None | ||
| else QiskitRuntimeService.global_service | ||
| ) |
There was a problem hiding this comment.
Instead of adding all the local logic into QiskitRuntimeService, it'd be much cleaner to just create a new LocalRuntimeService to "mock" any server requests.
There was a problem hiding this comment.
I am not sure I understand your intention in this comment. Do you mean that when running on a simulator, we don't need a real service, and don't need to have a real account?
There was a problem hiding this comment.
Yes, so instead of modifying QiskitRuntimeService, base_primitive can set self._service to a mock (local) service. And its run() method would handle the local operation.
There was a problem hiding this comment.
I will try this. Are you also saying that the local run will not need an account? because in a comment above, @kt474 thought it should have an account.
There was a problem hiding this comment.
We can do it this way, without an account
…untime into fake_backends
…on levels as for other simulators
|
Closing, this was done in #1495 |
Summary
When the
backendis aFakeBackendorAerSimulator, run the program locally, rather than through the IBM Cloud.Details and comments
Fixes #