quapp-dwave-ocean 0.0.1.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. quapp_dwave_ocean-0.0.1.dev2/LICENSE +8 -0
  2. quapp_dwave_ocean-0.0.1.dev2/PKG-INFO +88 -0
  3. quapp_dwave_ocean-0.0.1.dev2/README.md +53 -0
  4. quapp_dwave_ocean-0.0.1.dev2/pyproject.toml +32 -0
  5. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/__init__.py +3 -0
  6. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/async_tasks/__init__.py +0 -0
  7. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/async_tasks/d_wave_ocean_circuit_export_task.py +228 -0
  8. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/component/__init__.py +0 -0
  9. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/component/backend/__init__.py +0 -0
  10. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/component/backend/d_wave_ocean_invocation.py +157 -0
  11. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/component/backend/d_wave_ocean_job_fetching.py +28 -0
  12. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/factory/__init__.py +0 -0
  13. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/factory/d_wave_device_factory.py +73 -0
  14. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/factory/d_wave_handler_factory.py +45 -0
  15. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/factory/d_wave_provider_factory.py +74 -0
  16. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/handler/__init__.py +0 -0
  17. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/handler/invocation_handler.py +42 -0
  18. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/handler/job_fetching_handler.py +42 -0
  19. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/__init__.py +0 -0
  20. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/__init__.py +0 -0
  21. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/d_wave_device.py +31 -0
  22. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/d_wave_hybrid_device.py +38 -0
  23. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/d_wave_system_device.py +34 -0
  24. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/quapp_d_wave_device.py +191 -0
  25. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/provider/__init__.py +0 -0
  26. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/provider/d_wave_system_provider.py +49 -0
  27. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/provider/quapp_d_wave_provider.py +26 -0
  28. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/PKG-INFO +88 -0
  29. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/SOURCES.txt +31 -0
  30. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/dependency_links.txt +1 -0
  31. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/requires.txt +13 -0
  32. quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/top_level.txt +1 -0
  33. quapp_dwave_ocean-0.0.1.dev2/setup.cfg +4 -0
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright © CITYNOW Co. Ltd. All rights reserved.
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: quapp-dwave-ocean
3
+ Version: 0.0.1.dev2
4
+ Summary: Quapp D-Wave Ocean library supporting Quapp Platform for Quantum Computing
5
+ Author-email: "CITYNOW Co. Ltd. " <corp@citynow.vn>
6
+ License: The MIT License (MIT)
7
+ Copyright © CITYNOW Co. Ltd. All rights reserved.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14
+ Project-URL: Homepage, https://citynow.asia/
15
+ Keywords: quapp,quapp-dwave-ocean,dwave-ocean,quantum
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3
19
+ Requires-Python: >=3.7
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: quapp-common==0.0.11.dev6
23
+ Requires-Dist: dwave-cloud-client==0.13.4
24
+ Requires-Dist: dwave-system==1.30.0
25
+ Requires-Dist: dwave-samplers==1.5.0
26
+ Requires-Dist: dimod==0.12.20
27
+ Requires-Dist: numpy==2.2.4
28
+ Provides-Extra: dev
29
+ Requires-Dist: black; extra == "dev"
30
+ Requires-Dist: bumpver; extra == "dev"
31
+ Requires-Dist: isort; extra == "dev"
32
+ Requires-Dist: pip-tools; extra == "dev"
33
+ Requires-Dist: pytest; extra == "dev"
34
+ Dynamic: license-file
35
+
36
+ # quapp-dwave-ocean
37
+
38
+ Quapp D-Wave Ocean library supporting Quapp Platform for Quantum Computing.
39
+
40
+ ## Overview
41
+
42
+ `quapp-dwave-ocean` provides providers, devices, factories, and async tasks to
43
+ run
44
+ Binary Quadratic Models (BQMs) via D-Wave Ocean within the Quapp Platform. It
45
+ supports
46
+ D-Wave system and hybrid devices as well as a QuaO quantum simulator, featuring
47
+ consistent context-rich logging, robust error handling, and standardized
48
+ project/workspace
49
+ headers for clean integration with backend services.
50
+
51
+ ## Features
52
+
53
+ - Provider and device factories for:
54
+ - D-Wave System devices
55
+ - D-Wave Hybrid devices
56
+ - Quapp D-Wave Ocean simulator
57
+ - Asynchronous circuit export to SVG (BQM visualization) with optional
58
+ compression and upload.
59
+ - Consistent, instance-level logging across provider/device creation, job
60
+ invocation, export, and fetching.
61
+ - Standardized project/workspace header handling for backend invocations.
62
+ - Improved error handling and diagnostics in critical paths (export,
63
+ provider/device creation, job processing).
64
+ - Job fetching workflow encapsulated for clarity and maintainability.
65
+
66
+ ## Installation
67
+
68
+ Install via pip:
69
+
70
+ ```bash
71
+ pip install quapp-dwave-ocean
72
+ ```
73
+
74
+ ## Recently Changes Highlights
75
+
76
+ - chore: Bump a version to `0.0.1.dev2` and update `quapp-common` dependency to
77
+ `0.0.11.dev6`
78
+ - refactor: Replace global logger usage with instance-level logging and enhance
79
+ debug information across D-Wave Ocean modules
80
+ - feature: Create `DWaveOceanJobFetching` class for managing job fetching logic in
81
+ D-Wave Ocean backend
82
+ - feature: Add `DWaveOceanCircuitExportTask` for exporting and processing D-Wave
83
+ Ocean circuit visualizations
84
+ - refactor: Update import paths from `qapp_common` to `quapp_common` for consistency
85
+ across modules
86
+
87
+ For detailed usage and API references, please refer to the in-code documentation
88
+ or contact the maintainers.
@@ -0,0 +1,53 @@
1
+ # quapp-dwave-ocean
2
+
3
+ Quapp D-Wave Ocean library supporting Quapp Platform for Quantum Computing.
4
+
5
+ ## Overview
6
+
7
+ `quapp-dwave-ocean` provides providers, devices, factories, and async tasks to
8
+ run
9
+ Binary Quadratic Models (BQMs) via D-Wave Ocean within the Quapp Platform. It
10
+ supports
11
+ D-Wave system and hybrid devices as well as a QuaO quantum simulator, featuring
12
+ consistent context-rich logging, robust error handling, and standardized
13
+ project/workspace
14
+ headers for clean integration with backend services.
15
+
16
+ ## Features
17
+
18
+ - Provider and device factories for:
19
+ - D-Wave System devices
20
+ - D-Wave Hybrid devices
21
+ - Quapp D-Wave Ocean simulator
22
+ - Asynchronous circuit export to SVG (BQM visualization) with optional
23
+ compression and upload.
24
+ - Consistent, instance-level logging across provider/device creation, job
25
+ invocation, export, and fetching.
26
+ - Standardized project/workspace header handling for backend invocations.
27
+ - Improved error handling and diagnostics in critical paths (export,
28
+ provider/device creation, job processing).
29
+ - Job fetching workflow encapsulated for clarity and maintainability.
30
+
31
+ ## Installation
32
+
33
+ Install via pip:
34
+
35
+ ```bash
36
+ pip install quapp-dwave-ocean
37
+ ```
38
+
39
+ ## Recently Changes Highlights
40
+
41
+ - chore: Bump a version to `0.0.1.dev2` and update `quapp-common` dependency to
42
+ `0.0.11.dev6`
43
+ - refactor: Replace global logger usage with instance-level logging and enhance
44
+ debug information across D-Wave Ocean modules
45
+ - feature: Create `DWaveOceanJobFetching` class for managing job fetching logic in
46
+ D-Wave Ocean backend
47
+ - feature: Add `DWaveOceanCircuitExportTask` for exporting and processing D-Wave
48
+ Ocean circuit visualizations
49
+ - refactor: Update import paths from `qapp_common` to `quapp_common` for consistency
50
+ across modules
51
+
52
+ For detailed usage and API references, please refer to the in-code documentation
53
+ or contact the maintainers.
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel==0.45.1"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "quapp-dwave-ocean"
7
+ version = "0.0.1.dev2"
8
+ description = "Quapp D-Wave Ocean library supporting Quapp Platform for Quantum Computing"
9
+ readme = "README.md"
10
+ authors = [{ name = "CITYNOW Co. Ltd. ", email = "corp@citynow.vn" }]
11
+ license = { file = "LICENSE" }
12
+ classifiers = [
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python",
15
+ "Programming Language :: Python :: 3",
16
+ ]
17
+ keywords = ["quapp", "quapp-dwave-ocean", "dwave-ocean", "quantum"]
18
+ dependencies = [
19
+ "quapp-common==0.0.11.dev6",
20
+ "dwave-cloud-client==0.13.4",
21
+ "dwave-system==1.30.0",
22
+ "dwave-samplers==1.5.0",
23
+ "dimod==0.12.20",
24
+ "numpy==2.2.4"
25
+ ]
26
+ requires-python = ">=3.7"
27
+
28
+ [project.optional-dependencies]
29
+ dev = ["black", "bumpver", "isort", "pip-tools", "pytest"]
30
+
31
+ [project.urls]
32
+ Homepage = "https://citynow.asia/"
@@ -0,0 +1,3 @@
1
+ __version__ = "0.4.9"
2
+
3
+ from .factory.d_wave_handler_factory import DWaveHandlerFactory
@@ -0,0 +1,228 @@
1
+ # Quapp Platform Project
2
+ # d_wave_ocean_circuit_export_task.py
3
+ # Copyright © CITYNOW Co. Ltd. All rights reserved.
4
+ from io import BytesIO
5
+
6
+ import numpy as np
7
+ import requests
8
+ from dimod import BinaryQuadraticModel
9
+ from matplotlib import pyplot as plt
10
+ from quapp_common.async_tasks.export_circuit_task import CircuitExportTask
11
+ from quapp_common.config.logging_config import job_logger
12
+ from quapp_common.data.async_task.circuit_export.backend_holder import \
13
+ BackendDataHolder
14
+ from quapp_common.data.async_task.circuit_export.circuit_holder import \
15
+ CircuitDataHolder
16
+ from quapp_common.data.response.custom_header import CustomHeader
17
+ from quapp_common.enum.media_type import MediaType
18
+ from quapp_common.util.file_utils import FileUtils
19
+ from quapp_common.util.http_utils import create_bearer_header, \
20
+ get_job_id_from_url
21
+
22
+
23
+ class DWaveOceanCircuitExportTask:
24
+ MAX_CIRCUIT_IMAGE_SIZE = 5 * (1024 ** 2)
25
+
26
+ def __init__(self, circuit_data_holder: CircuitDataHolder,
27
+ backend_data_holder: BackendDataHolder,
28
+ project_header: CustomHeader, workspace_header: CustomHeader):
29
+ super().__init__()
30
+ self.project_header = project_header
31
+ self.workspace_header = workspace_header
32
+ self.circuit_data_holder = circuit_data_holder
33
+ self.backend_data_holder = backend_data_holder
34
+ self.logger = job_logger(
35
+ get_job_id_from_url(self.circuit_data_holder.export_url))
36
+
37
+ def do(self):
38
+ """
39
+ Export circuit to svg file, then send it to QuaO server for saving
40
+ """
41
+ self.logger.info("Starting circuit export task...")
42
+
43
+ circuit_export_url = self.circuit_data_holder.export_url
44
+
45
+ if circuit_export_url is None or len(circuit_export_url) < 1:
46
+ self.logger.warning("Export URL is missing. Task will exit.")
47
+ return
48
+
49
+ try:
50
+ self.logger.debug('Converting circuit to SVG')
51
+ figure_buffer = self._render_circuit_svg(self._transpile_circuit())
52
+ except Exception as e:
53
+ self.logger.exception("Error converting circuit to SVG: %s", e,
54
+ exc_info=True)
55
+ return
56
+
57
+ try:
58
+ self.logger.debug('Determining if circuit SVG should be zipped')
59
+ # Use protected helpers from base class (single underscore), not name-mangled privates
60
+ io_buffer_value, content_type = self.__determine_zip(
61
+ figure_buffer=figure_buffer)
62
+ size_bytes = (
63
+ io_buffer_value.getbuffer().nbytes
64
+ if isinstance(io_buffer_value, BytesIO)
65
+ else len(io_buffer_value)
66
+ )
67
+ self.logger.debug("Content type: %s", content_type)
68
+ self.logger.debug("Buffer size: %s bytes", size_bytes)
69
+ except Exception as e:
70
+ self.logger.exception(
71
+ "Error determining if circuit SVG should be zipped: %s", e,
72
+ exc_info=True)
73
+ return
74
+
75
+ try:
76
+ self.logger.debug('Sending circuit to backend')
77
+ self.__send(io_buffer_value=io_buffer_value,
78
+ content_type=content_type)
79
+ self.logger.debug("Circuit sent to backend successfully.")
80
+ return
81
+ except Exception as e:
82
+ self.logger.exception(
83
+ "Error sending exported circuit to backend: %s", e,
84
+ exc_info=True)
85
+ return
86
+
87
+ def _render_circuit_svg(self,
88
+ transpiled_circuit: BinaryQuadraticModel) -> BytesIO:
89
+ """
90
+ Render a BinaryQuadraticModel as an SVG figure and return it as a BytesIO buffer.
91
+
92
+ This matches the transpile output type (BinaryQuadraticModel) from _transpile_circuit.
93
+ """
94
+ self.logger.info("Rendering BinaryQuadraticModel to SVG")
95
+ try:
96
+ linear_items = list(transpiled_circuit.linear.items())
97
+ quadratic_items = list(transpiled_circuit.quadratic.items())
98
+
99
+ # Prepare figure
100
+ fig, axes = plt.subplots(1, 2, figsize=(10, 4))
101
+ fig.suptitle("D-Wave Ocean BQM Visualization", fontsize=12)
102
+
103
+ # Left: Linear biases (bar chart)
104
+ ax0 = axes[0]
105
+ if linear_items:
106
+ vars_, lin_vals = zip(*linear_items)
107
+ x = np.arange(len(vars_))
108
+ ax0.bar(x, lin_vals, color="#1f77b4")
109
+ ax0.set_xticks(x)
110
+ ax0.set_xticklabels([str(v) for v in vars_], rotation=45,
111
+ ha="right", fontsize=8)
112
+ ax0.set_title("Linear biases")
113
+ ax0.set_ylabel("bias")
114
+ else:
115
+ ax0.text(0.5, 0.5, "No linear biases", ha="center", va="center",
116
+ transform=ax0.transAxes)
117
+ ax0.set_axis_off()
118
+
119
+ # Right: Quadratic couplers (scatter)
120
+ ax1 = axes[1]
121
+ if quadratic_items:
122
+ uvs = [f"{u}-{v}" for (u, v), _ in quadratic_items]
123
+ q_vals = [b for _, b in quadratic_items]
124
+ x = np.arange(len(uvs))
125
+ ax1.scatter(x, q_vals, c=np.sign(q_vals), cmap="bwr",
126
+ edgecolor="k")
127
+ ax1.set_xticks(x)
128
+ ax1.set_xticklabels(uvs, rotation=45, ha="right", fontsize=8)
129
+ ax1.set_title("Quadratic couplers")
130
+ ax1.set_ylabel("coupling")
131
+ ax1.axhline(0, color="gray", linewidth=0.8)
132
+ else:
133
+ ax1.text(0.5, 0.5, "No quadratic couplers", ha="center",
134
+ va="center", transform=ax1.transAxes)
135
+ ax1.set_axis_off()
136
+
137
+ fig.tight_layout(rect=[0, 0.03, 1, 0.95])
138
+
139
+ self.logger.debug("Converting rendered figure to SVG buffer")
140
+ figure_buffer = BytesIO()
141
+ try:
142
+ fig.savefig(figure_buffer, format="svg", bbox_inches="tight")
143
+ figure_buffer.seek(0)
144
+ self.logger.debug("SVG export complete. Size: %s bytes",
145
+ figure_buffer.getbuffer().nbytes)
146
+ except Exception as exception:
147
+ self.logger.exception("Error saving BQM figure to SVG: %s",
148
+ exception, exc_info=True)
149
+ raise
150
+ finally:
151
+ plt.close(fig)
152
+
153
+ return figure_buffer
154
+
155
+ except Exception as exception:
156
+ self.logger.exception(
157
+ "Error rendering BinaryQuadraticModel to SVG: %s",
158
+ exception,
159
+ exc_info=True)
160
+ raise
161
+
162
+ def _transpile_circuit(self) -> BinaryQuadraticModel:
163
+ self.logger.info('Transpiling D-Wave Ocean circuit')
164
+ circuit = self.circuit_data_holder.circuit
165
+ self.logger.debug('Fetched circuit from holder: %s', circuit)
166
+
167
+ if circuit is None:
168
+ self.logger.error('Circuit must not be None')
169
+ raise ValueError('Circuit must not be None')
170
+
171
+ if isinstance(circuit, BinaryQuadraticModel):
172
+ self.logger.debug(
173
+ 'Circuit is BinaryQuadraticModel; no transpilation needed')
174
+ return circuit
175
+
176
+ self.logger.error('Expected BinaryQuadraticModel, got %s',
177
+ type(circuit))
178
+ raise ValueError(f'Expected BinaryQuadraticModel, got {type(circuit)}')
179
+
180
+ def __determine_zip(self, figure_buffer):
181
+ """
182
+ Determine if the buffer needs to be zipped; return (buffer, content_type).
183
+ """
184
+ self.logger.debug("Checking if SVG file needs to be zipped.")
185
+ buffer_value = figure_buffer.getvalue()
186
+ content_type = MediaType.SVG_XML
187
+
188
+ self.logger.debug("Checking max file size")
189
+ estimated_file_size = len(buffer_value)
190
+
191
+ if estimated_file_size > CircuitExportTask.MAX_CIRCUIT_IMAGE_SIZE:
192
+ self.logger.debug("Zip file")
193
+ zip_file_buffer = FileUtils.zip(io_buffer_value=buffer_value,
194
+ file_name="circuit_image.svg")
195
+
196
+ buffer_value = zip_file_buffer.getvalue()
197
+ content_type = MediaType.APPLICATION_ZIP
198
+
199
+ return buffer_value, content_type
200
+
201
+ def __send(self, io_buffer_value, content_type: MediaType):
202
+ """
203
+ Send circuit SVG (or zipped SVG) to the backend.
204
+ """
205
+ url = self.circuit_data_holder.export_url
206
+
207
+ self.logger.debug(
208
+ f"Sending circuit svg image to [{url}] with POST method ...")
209
+
210
+ payload = {'circuit': ('circuit_image.svg', io_buffer_value,
211
+ content_type.value)}
212
+
213
+ try:
214
+ response = requests.post(url=url, headers=create_bearer_header(
215
+ self.backend_data_holder.user_token, self.project_header,
216
+ self.workspace_header), files=payload)
217
+ except Exception as exception:
218
+ self.logger.exception(f"HTTP request failed: {exception}",
219
+ exc_info=True)
220
+ raise
221
+
222
+ if response.ok:
223
+ self.logger.info("Request sent to QuaO backend successfully.")
224
+ else:
225
+ self.logger.exception(
226
+ f"Sending request to QuaO backend failed with status {response.status_code}! Response: {response.content}")
227
+
228
+ self.logger.debug("HTTP request complete.")
@@ -0,0 +1,157 @@
1
+ # Quapp Platform Project
2
+ # d_wave_ocean_invocation.py
3
+ # Copyright © CITYNOW Co. Ltd. All rights reserved.
4
+
5
+ from dimod import BinaryQuadraticModel
6
+ from quapp_common.component.backend.invocation import Invocation
7
+ from quapp_common.config.thread_config import circuit_exporting_pool
8
+ from quapp_common.data.async_task.circuit_export.backend_holder import \
9
+ BackendDataHolder
10
+ from quapp_common.data.async_task.circuit_export.circuit_holder import \
11
+ CircuitDataHolder
12
+ from quapp_common.data.request.invocation_request import InvocationRequest
13
+ from quapp_common.model.provider.provider import Provider
14
+
15
+ from quapp_dwave_ocean.async_tasks.d_wave_ocean_circuit_export_task import \
16
+ DWaveOceanCircuitExportTask
17
+ from quapp_dwave_ocean.factory.d_wave_device_factory import DWaveDeviceFactory
18
+ from quapp_dwave_ocean.factory.d_wave_provider_factory import \
19
+ DWaveProviderFactory
20
+
21
+
22
+ class DWaveOceanInvocation(Invocation):
23
+ def __init__(self, request_data: InvocationRequest):
24
+ """
25
+ Initialize DWaveOceanInvocation object
26
+
27
+ Args:
28
+ request_data: InvocationRequest object
29
+ """
30
+ super().__init__(request_data)
31
+ try:
32
+ provider_tag = getattr(self.backend_information, "provider_tag",
33
+ None)
34
+ device_name = getattr(self.backend_information, "device_name", None)
35
+ self.logger.info("[DWaveOceanInvocation] Initialized")
36
+ self.logger.debug(
37
+ "[DWaveOceanInvocation] init details: provider_tag=%s, device_name=%s, sdk=%s, export_url_present=%s",
38
+ provider_tag, device_name, getattr(self, "sdk", None),
39
+ bool(getattr(self, "circuit_export_url", None)), )
40
+ except Exception as e:
41
+ self.logger.exception(
42
+ "[DWaveOceanInvocation] Initialization logging failed: %s",
43
+ e)
44
+
45
+ def _export_circuit(self, circuit):
46
+ """
47
+ Export circuit to svg file then send to QuaO server for saving
48
+
49
+ @param circuit: Circuit was exported
50
+ """
51
+ self.logger.info("[DWaveOceanInvocation] _export_circuit() started")
52
+ try:
53
+ circuit_export_task = DWaveOceanCircuitExportTask(
54
+ circuit_data_holder=CircuitDataHolder(circuit,
55
+ self.circuit_export_url),
56
+ backend_data_holder=BackendDataHolder(
57
+ self.backend_information,
58
+ self.authentication.user_token),
59
+ project_header=self.project_header,
60
+ workspace_header=self.workspace_header, )
61
+ self.logger.debug(
62
+ "[DWaveOceanInvocation] Prepared CircuitExportTask: export_url_present=%s, project_header=%s, workspace_header=%s",
63
+ bool(self.circuit_export_url),
64
+ bool(getattr(self, "project_header", None)),
65
+ bool(getattr(self, "workspace_header", None)), )
66
+
67
+ future = circuit_exporting_pool.submit(circuit_export_task.do)
68
+ self.logger.info(
69
+ "[DWaveOceanInvocation] Circuit export task submitted to thread pool")
70
+
71
+ def _done_callback(fut):
72
+ try:
73
+ fut.result()
74
+ self.logger.info(
75
+ "[DWaveOceanInvocation] Circuit export task completed successfully")
76
+ except Exception as export_err:
77
+ self.logger.exception(
78
+ "[DWaveOceanInvocation] Circuit export task failed: %s",
79
+ export_err)
80
+
81
+ future.add_done_callback(_done_callback)
82
+ except Exception as e:
83
+ self.logger.exception(
84
+ "[DWaveOceanInvocation] Failed to export circuit: %s", e)
85
+ raise
86
+
87
+ def _create_provider(self):
88
+ """
89
+ Create a provider based on the provider type and SDK
90
+
91
+ Return: Provider object
92
+ """
93
+ self.logger.info("[DWaveOceanInvocation] _create_provider()")
94
+ try:
95
+ self.logger.debug(
96
+ "[DWaveOceanInvocation] Creating provider with provider_tag=%s, sdk=%s",
97
+ getattr(self.backend_information, "provider_tag", None),
98
+ getattr(self, "sdk", None), )
99
+ return DWaveProviderFactory.create_provider(
100
+ provider_type=self.backend_information.provider_tag,
101
+ sdk=self.sdk,
102
+ authentication=self.backend_information.authentication, )
103
+ except Exception as e:
104
+ self.logger.exception(
105
+ "[DWaveOceanInvocation] _create_provider failed: %s", e)
106
+ raise
107
+
108
+ def _create_device(self, provider: Provider):
109
+ """
110
+ Create a device based on the provider and device specification
111
+
112
+ Args:
113
+ provider: Provider instance that this device belongs to
114
+ Return:
115
+ A device instance corresponding to the specified provider and device type
116
+ """
117
+ try:
118
+ self.logger.debug(
119
+ f"[DWaveOceanInvocation] Creating device device_name="
120
+ f"{getattr(self.backend_information, 'device_name', None)}"
121
+ f", sdk={getattr(self, 'sdk', None)}")
122
+ return DWaveDeviceFactory.create_device(provider=provider,
123
+ device_specification=self.backend_information.device_name,
124
+ authentication=self.backend_information.authentication,
125
+ sdk=self.sdk, )
126
+ except Exception as exception:
127
+ self.logger.exception(
128
+ f"[DWaveOceanInvocation] _create_device failed: {exception}")
129
+ raise
130
+
131
+ def _get_qubit_amount(self, circuit):
132
+ """
133
+ Get the number of qubits in the given circuit.
134
+
135
+ Args:
136
+ circuit: The quantum circuit for which the qubit count is needed.
137
+ Returns:
138
+ int: The number of qubits in the circuit.
139
+ """
140
+ try:
141
+ if isinstance(circuit, BinaryQuadraticModel):
142
+ qubit_amount = circuit.binary.num_variables
143
+ self.logger.info(
144
+ f"[DWaveOceanInvocation] Circuit is a BinaryQuadraticModel with {qubit_amount} qubits.")
145
+ return qubit_amount
146
+ else:
147
+ qubit_amount = getattr(circuit, "num_qubits", None)
148
+ if qubit_amount is None:
149
+ raise AttributeError(
150
+ "circuit object has no attribute 'num_qubits'")
151
+ self.logger.info(f"[DWaveOceanInvocation] Circuit is not a "
152
+ f"BinaryQuadraticModel; it has {qubit_amount} qubits.")
153
+ return qubit_amount
154
+ except Exception as exception:
155
+ self.logger.exception(
156
+ f"[DWaveOceanInvocation] Failed to get qubit amount: {exception}")
157
+ raise
@@ -0,0 +1,28 @@
1
+ from quapp_common.component.backend.job_fetcher import JobFetcher
2
+ from quapp_common.data.request.job_fetching_request import JobFetchingRequest
3
+
4
+
5
+ class DWaveOceanJobFetching(JobFetcher):
6
+ def __init__(self, request: JobFetchingRequest, ):
7
+ super().__init__(request)
8
+
9
+ def _collect_provider(self):
10
+ pass
11
+
12
+ def _retrieve_job(self, provider):
13
+ pass
14
+
15
+ def _get_job_status(self, job):
16
+ pass
17
+
18
+ def _get_job_result(self, job):
19
+ pass
20
+
21
+ def _produce_histogram_data(self, job_result) -> dict | None:
22
+ pass
23
+
24
+ def _get_execution_time(self, job_result):
25
+ pass
26
+
27
+ def _get_shots(self, job_result):
28
+ pass