Transpile to IBM fake backends#437
Conversation
📊 Coverage Summary
Detailed Coverage ReportsC++ Coverage DetailsPython Coverage DetailsPybind11 Coverage Details |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds support for running the Qiskit Aer circuit executor against an IBM “fake” device backend name, transpiling to that backend and using its noise profile.
Changes:
- Added
device_backend_namesupport toQiskitAerSimulator._run_impl, using IBM Runtime fake backends and backend-aware transpilation. - Introduced a new optional-dependency flag for
qiskit_ibm_runtimeand added coverage for the new execution path. - Updated optional dependencies and docs config to include
qiskit_ibm_runtime.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| python/tests/test_interop_qiskit_circuit_executor.py | Adds an integration test for executing with a fake IBM backend name. |
| python/src/qdk_chemistry/plugins/qiskit/circuit_executor.py | Implements backend-name driven transpile + Aer noise modeling via IBM fake backends. |
| python/src/qdk_chemistry/plugins/qiskit/init.py | Adds detection flag for the qiskit_ibm_runtime optional dependency. |
| python/pyproject.toml | Adds qiskit-ibm-runtime to the qiskit-extras optional dependency group. |
| docs/source/conf.py | Includes qiskit_ibm_runtime in the docs import/mocking configuration list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…backend' into feature/agamshayit/transpile_to_backend
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| backend=device_backend, | ||
| optimization_level=opt_level, | ||
| ) | ||
|
|
||
| else: |
There was a problem hiding this comment.
The error message may become extremely large because it includes every available fake backend name. Consider truncating the list (e.g., first N entries + total count) or pointing users to a programmatic way to list available names, to keep exceptions readable and logs manageable.
| assert counts.get("11", 0) > 0 | ||
| assert counts.get("01", 0) + counts.get("10", 0) > 0 # Expect some errors to occur | ||
|
|
||
| @pytest.mark.skipif(not QDK_CHEMISTRY_HAS_QISKIT_IBM_RUNTIME, reason="qiskit_ibm_runtime not installed") |
There was a problem hiding this comment.
All new tests for the device_backend_name behavior are skipped unless qiskit_ibm_runtime is installed. If the default CI/test environment doesn’t include that extra, the new code path won’t be exercised. Consider adding at least one test that doesn’t require the real dependency (e.g., by mocking the fake provider/backend lookup) or ensuring the CI job that runs this suite installs the qiskit-extras (or otherwise includes qiskit-ibm-runtime) so the new behavior is actually covered.
| assert counts.get("01", 0) > 0 | ||
| assert result.total_shots == 100 | ||
|
|
||
| @pytest.mark.skipif(not QDK_CHEMISTRY_HAS_QISKIT_IBM_RUNTIME, reason="qiskit_ibm_runtime not installed") |
There was a problem hiding this comment.
All new tests for the device_backend_name behavior are skipped unless qiskit_ibm_runtime is installed. If the default CI/test environment doesn’t include that extra, the new code path won’t be exercised. Consider adding at least one test that doesn’t require the real dependency (e.g., by mocking the fake provider/backend lookup) or ensuring the CI job that runs this suite installs the qiskit-extras (or otherwise includes qiskit-ibm-runtime) so the new behavior is actually covered.
| @pytest.mark.skipif(not QDK_CHEMISTRY_HAS_QISKIT_IBM_RUNTIME, reason="qiskit_ibm_runtime not installed") |
| with pytest.raises(ValueError, match="Cannot specify both a noise model and a device backend"): | ||
| executor.run(test_circuit_1, shots=10, noise=simple_error_profile, device_backend_name="fake_manila") | ||
|
|
||
| @pytest.mark.skipif(not QDK_CHEMISTRY_HAS_QISKIT_IBM_RUNTIME, reason="qiskit_ibm_runtime not installed") |
There was a problem hiding this comment.
All new tests for the device_backend_name behavior are skipped unless qiskit_ibm_runtime is installed. If the default CI/test environment doesn’t include that extra, the new code path won’t be exercised. Consider adding at least one test that doesn’t require the real dependency (e.g., by mocking the fake provider/backend lookup) or ensuring the CI job that runs this suite installs the qiskit-extras (or otherwise includes qiskit-ibm-runtime) so the new behavior is actually covered.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| available = sorted(b.name for b in provider.backends()) | ||
| available_backends = ", ".join(available) |
There was a problem hiding this comment.
provider.backends() returns backend objects where the name is not consistently exposed as a .name attribute across Qiskit backend versions (some use name() while others use a property). As written, sorted(b.name for b in ...) can end up sorting bound methods and raise a TypeError, masking the intended ValueError. Extract names in a version-tolerant way (e.g., call name() when callable, otherwise use the attribute), and consider truncating the displayed list to avoid extremely large exception messages if many fake backends are present.
| available = sorted(b.name for b in provider.backends()) | |
| available_backends = ", ".join(available) | |
| def _backend_name(backend: object) -> str: | |
| name = getattr(backend, "name", None) | |
| if callable(name): | |
| name = name() | |
| return str(name) | |
| available = sorted(_backend_name(b) for b in provider.backends()) | |
| max_display = 20 | |
| if len(available) > max_display: | |
| available_backends = ", ".join(available[:max_display]) + ", ..." | |
| else: | |
| available_backends = ", ".join(available) |
| if device_backend_name is not None: | ||
| if not qiskit_plugin.QDK_CHEMISTRY_HAS_QISKIT_IBM_RUNTIME: | ||
| raise ImportError( | ||
| "The fake_provider module from qiskit_ibm_runtime is required for device backend simulation. " | ||
| "Install it with: pip install qiskit-ibm-runtime" | ||
| ) |
There was a problem hiding this comment.
This runtime availability check depends on qdk_chemistry.plugins.qiskit.load() having been called earlier to set QDK_CHEMISTRY_HAS_QISKIT_IBM_RUNTIME. If a consumer instantiates QiskitAerSimulator directly (without plugin loading), this will raise ImportError even when qiskit-ibm-runtime is installed. Prefer a local import/ModuleNotFoundError check (or importlib.util.find_spec) inside this branch, or ensure plugin detection is invoked before testing these flags.
Added the ability to pass a device backend string to the Qiskit Aer circuit executor. If received as an argument, the circuit is transpiled to the backend and the simulator uses the backend's noise profile.