-
Notifications
You must be signed in to change notification settings - Fork 2
Refactoring API structure #19
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
Changes from 18 commits
05ddfc9
cfc7d3d
cc96047
94f5506
edd098b
d704a07
7be6452
4d695d6
edf5f22
66154e7
5621900
9ebab22
ddfaff6
ad49e67
c4748e7
9d9adf1
b153822
409ae3c
9cade0e
5396ce4
fcbfe34
f4353bd
d2b6035
b655ce0
aa713a2
8b533a1
71f4359
c1074ae
c6f94d1
ae3882f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from graphix_ibmq.compiler import IBMQPatternCompiler | ||
| from graphix_ibmq.job import IBMQJob | ||
| from graphix_ibmq.compile_options import IBMQCompileOptions | ||
|
|
||
| from qiskit_aer.noise import NoiseModel | ||
| from qiskit_aer import AerSimulator | ||
| from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager | ||
| from qiskit_ibm_runtime import SamplerV2 as Sampler | ||
|
|
||
| from typing import TYPE_CHECKING | ||
|
|
||
| if TYPE_CHECKING: | ||
| from graphix.pattern import Pattern | ||
| from qiskit import QuantumCircuit | ||
| from qiskit.providers.backend import BackendV2 | ||
|
|
||
|
|
||
| class IBMQBackend: | ||
| """IBMQ backend implementation for compiling and executing quantum patterns.""" | ||
|
|
||
| _options: IBMQCompileOptions | ||
| _compiled_circuit: QuantumCircuit | None | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for the comment. Refactored accordingly in d2b6035 |
||
| _execution_mode: str | None | ||
| _noise_model: NoiseModel | None | ||
| _simulator: AerSimulator | None | ||
| _resource: BackendV2 | None | ||
| _compiler: IBMQPatternCompiler | None | ||
|
|
||
| def __init__(self) -> None: | ||
| self._compiler = None | ||
| self._options = IBMQCompileOptions() | ||
| self._compiled_circuit = None | ||
| self._execution_mode = None | ||
| self._noise_model = None | ||
| self._simulator = None | ||
| self._resource = None | ||
|
|
||
| def compile(self, pattern: Pattern, options: IBMQCompileOptions | None = None) -> None: | ||
| """Compile the assigned pattern using IBMQ options. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| options : CompileOptions, optional | ||
| Compilation options. Must be of type IBMQCompileOptions. | ||
| """ | ||
| if options is None: | ||
| self._options = IBMQCompileOptions() | ||
| elif not isinstance(options, IBMQCompileOptions): | ||
| raise TypeError("Expected IBMQCompileOptions") | ||
| else: | ||
| self._options = options | ||
|
|
||
| self._compiler = IBMQPatternCompiler(pattern) | ||
| self._compiled_circuit = self._compiler.to_qiskit_circuit( | ||
| save_statevector=self._options.save_statevector, | ||
| layout_method=self._options.layout_method, | ||
| ) | ||
|
|
||
| def set_simulator( | ||
| self, | ||
| noise_model: NoiseModel | None = None, | ||
| based_on: BackendV2 | None = None, | ||
| ) -> None: | ||
| """Configure the backend to use a simulator. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| noise_model : NoiseModel, optional | ||
| Noise model to apply to the simulator. | ||
| based_on : BackendV2, optional | ||
| Backend to base the noise model on. | ||
| """ | ||
| if noise_model is None and based_on is not None: | ||
| noise_model = NoiseModel.from_backend(based_on) | ||
|
|
||
| self._execution_mode = "simulation" | ||
| self._noise_model = noise_model | ||
| self._simulator = AerSimulator(noise_model=noise_model) | ||
|
|
||
| def select_device( | ||
| self, | ||
| name: str | None = None, | ||
| least_busy: bool = False, | ||
|
d1ssk marked this conversation as resolved.
Outdated
|
||
| min_qubits: int = 1, | ||
| ) -> None: | ||
| """Select a hardware backend from IBMQ. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| name : str, optional | ||
| Specific device name to use. | ||
| least_busy : bool, optional | ||
| If True, select the least busy device that meets requirements. | ||
| min_qubits : int, optional | ||
| Minimum number of qubits required. | ||
| """ | ||
| from qiskit_ibm_runtime import QiskitRuntimeService | ||
|
|
||
| self._execution_mode = "hardware" | ||
| service = QiskitRuntimeService() | ||
|
|
||
| if least_busy or name is None: | ||
| self._resource = service.least_busy(min_num_qubits=min_qubits, operational=True) | ||
| else: | ||
| self._resource = service.backend(name) | ||
|
|
||
| print(f"Selected device: {self._resource.name}") | ||
|
|
||
| def submit_job(self, shots: int = 1024) -> IBMQJob: | ||
| """Submit the compiled circuit to either simulator or hardware backend. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| shots : int, optional | ||
| Number of execution shots. Defaults to 1024. | ||
|
|
||
| Returns | ||
| ------- | ||
| Job | ||
| A handle to monitor the job status and retrieve results. | ||
|
|
||
| Raises | ||
| ------ | ||
| RuntimeError | ||
| If the pattern has not been compiled or execution mode is not set. | ||
| """ | ||
| if self._compiled_circuit is None: | ||
| raise RuntimeError("Pattern must be compiled before submission.") | ||
|
|
||
| if self._execution_mode is None: | ||
| raise RuntimeError("Execution mode is not configured. Use select_backend() or set_simulator().") | ||
|
|
||
| if not hasattr(self, "_options") or self._options is None: | ||
| raise RuntimeError("Compile options are not set.") | ||
|
|
||
| if self._execution_mode == "simulation": | ||
| pm = generate_preset_pass_manager( | ||
| backend=self._simulator, | ||
| optimization_level=self._options.optimization_level, | ||
|
d1ssk marked this conversation as resolved.
Outdated
|
||
| ) | ||
| transpiled = pm.run(self._compiled_circuit) | ||
| sampler = Sampler(mode=self._simulator) | ||
| job = sampler.run([transpiled], shots=shots) | ||
| return IBMQJob(job, self._compiler) | ||
|
|
||
| elif self._execution_mode == "hardware": | ||
| pm = generate_preset_pass_manager( | ||
| backend=self._resource, | ||
| optimization_level=self._options.optimization_level, | ||
| ) | ||
| transpiled = pm.run(self._compiled_circuit) | ||
| sampler = Sampler(mode=self._resource) | ||
| job = sampler.run([transpiled], shots=shots) | ||
| return IBMQJob(job, self._compiler) | ||
|
|
||
| else: | ||
| raise RuntimeError("Execution mode is not configured. Use select_backend() or set_simulator().") | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These versions of Python are not really used: regardless of the version of Python we test here,
toxinstalls and tests Python3.9,3.10, and3.11in its own environments. That means we run the exact same set of tests four times, and each time we test the three versions of Python listed intox.ini. We probably want to test only one version of Python at this level (and probably even without explicitly specifying a particular version), and lettoxrun the tests in its multiple environments.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comment, but actually I don't think the current setup runs every tox env four times. Each github actions job only invokes its corresponding tox environment (e.g. the 3.10 runner only runs
py310, the 3.11 runner only runspy311, etc.), although runningtoxin local environment indeed execute tests in all the versions.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes, sorry: I was mistaken, you're right. That is the purpose of the
[gh-actions]section intox.ini. Then everything is fine!