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.
- quapp_dwave_ocean-0.0.1.dev2/LICENSE +8 -0
- quapp_dwave_ocean-0.0.1.dev2/PKG-INFO +88 -0
- quapp_dwave_ocean-0.0.1.dev2/README.md +53 -0
- quapp_dwave_ocean-0.0.1.dev2/pyproject.toml +32 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/__init__.py +3 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/async_tasks/__init__.py +0 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/async_tasks/d_wave_ocean_circuit_export_task.py +228 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/component/__init__.py +0 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/component/backend/__init__.py +0 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/component/backend/d_wave_ocean_invocation.py +157 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/component/backend/d_wave_ocean_job_fetching.py +28 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/factory/__init__.py +0 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/factory/d_wave_device_factory.py +73 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/factory/d_wave_handler_factory.py +45 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/factory/d_wave_provider_factory.py +74 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/handler/__init__.py +0 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/handler/invocation_handler.py +42 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/handler/job_fetching_handler.py +42 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/__init__.py +0 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/__init__.py +0 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/d_wave_device.py +31 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/d_wave_hybrid_device.py +38 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/d_wave_system_device.py +34 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/device/quapp_d_wave_device.py +191 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/provider/__init__.py +0 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/provider/d_wave_system_provider.py +49 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/model/provider/quapp_d_wave_provider.py +26 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/PKG-INFO +88 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/SOURCES.txt +31 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/dependency_links.txt +1 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/requires.txt +13 -0
- quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean.egg-info/top_level.txt +1 -0
- 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/"
|
|
File without changes
|
quapp_dwave_ocean-0.0.1.dev2/quapp_dwave_ocean/async_tasks/d_wave_ocean_circuit_export_task.py
ADDED
|
@@ -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.")
|
|
File without changes
|
|
File without changes
|
|
@@ -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
|
|
File without changes
|