quapp-braket 0.0.11.dev2__tar.gz → 0.0.11.dev4__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_braket-0.0.11.dev2/quapp_braket.egg-info → quapp_braket-0.0.11.dev4}/PKG-INFO +14 -4
- quapp_braket-0.0.11.dev4/README.md +12 -0
- {quapp_braket-0.0.11.dev2 → quapp_braket-0.0.11.dev4}/pyproject.toml +5 -4
- quapp_braket-0.0.11.dev4/quapp_braket/async_tasks/braket_circuit_export_task.py +44 -0
- quapp_braket-0.0.11.dev4/quapp_braket/component/backend/braket_invocation.py +127 -0
- quapp_braket-0.0.11.dev4/quapp_braket/factory/braket_device_factory.py +68 -0
- quapp_braket-0.0.11.dev4/quapp_braket/factory/braket_handler_factory.py +42 -0
- quapp_braket-0.0.11.dev4/quapp_braket/factory/braket_provider_factory.py +45 -0
- quapp_braket-0.0.11.dev4/quapp_braket/handler/invocation_handler.py +32 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/model/device/aws_braket_device.py +30 -27
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/model/device/oqc_cloud_device.py +34 -26
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/model/device/qapp_braket_device.py +26 -22
- quapp_braket-0.0.11.dev4/quapp_braket/model/provider/aws_braket_provider.py +38 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/model/provider/oqc_cloud_provider.py +11 -8
- quapp_braket-0.0.11.dev4/quapp_braket/model/provider/qapp_braket_provider.py +34 -0
- quapp_braket-0.0.11.dev4/quapp_braket/util/circuit_convert_utils.py +31 -0
- {quapp_braket-0.0.11.dev2 → quapp_braket-0.0.11.dev4/quapp_braket.egg-info}/PKG-INFO +14 -4
- quapp_braket-0.0.11.dev4/quapp_braket.egg-info/SOURCES.txt +31 -0
- {quapp_braket-0.0.11.dev2 → quapp_braket-0.0.11.dev4}/quapp_braket.egg-info/requires.txt +2 -1
- quapp_braket-0.0.11.dev4/quapp_braket.egg-info/top_level.txt +1 -0
- quapp_braket-0.0.11.dev2/README.md +0 -3
- quapp_braket-0.0.11.dev2/qapp_braket/async_tasks/braket_circuit_export_task.py +0 -22
- quapp_braket-0.0.11.dev2/qapp_braket/component/backend/braket_invocation.py +0 -61
- quapp_braket-0.0.11.dev2/qapp_braket/factory/braket_device_factory.py +0 -41
- quapp_braket-0.0.11.dev2/qapp_braket/factory/braket_handler_factory.py +0 -25
- quapp_braket-0.0.11.dev2/qapp_braket/factory/braket_provider_factory.py +0 -40
- quapp_braket-0.0.11.dev2/qapp_braket/handler/invocation_handler.py +0 -27
- quapp_braket-0.0.11.dev2/qapp_braket/model/provider/aws_braket_provider.py +0 -37
- quapp_braket-0.0.11.dev2/qapp_braket/model/provider/qapp_braket_provider.py +0 -31
- quapp_braket-0.0.11.dev2/qapp_braket/util/circuit_convert_utils.py +0 -32
- quapp_braket-0.0.11.dev2/quapp_braket.egg-info/SOURCES.txt +0 -31
- quapp_braket-0.0.11.dev2/quapp_braket.egg-info/top_level.txt +0 -1
- {quapp_braket-0.0.11.dev2 → quapp_braket-0.0.11.dev4}/LICENSE +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/async_tasks/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/component/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/component/backend/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/factory/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/handler/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/model/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/model/device/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/model/provider/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2/qapp_braket → quapp_braket-0.0.11.dev4/quapp_braket}/util/__init__.py +0 -0
- {quapp_braket-0.0.11.dev2 → quapp_braket-0.0.11.dev4}/quapp_braket.egg-info/dependency_links.txt +0 -0
- {quapp_braket-0.0.11.dev2 → quapp_braket-0.0.11.dev4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quapp-braket
|
|
3
|
-
Version: 0.0.11.
|
|
3
|
+
Version: 0.0.11.dev4
|
|
4
4
|
Summary: Quapp braket library supporting Quapp Platform for Quantum Computing
|
|
5
5
|
Author-email: "CITYNOW Co. Ltd. " <corp@citynow.vn>
|
|
6
6
|
License: The MIT License (MIT)
|
|
@@ -19,12 +19,13 @@ Classifier: Programming Language :: Python :: 3
|
|
|
19
19
|
Requires-Python: >=3.7
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
-
Requires-Dist: quapp-common==0.0.11.
|
|
22
|
+
Requires-Dist: quapp-common==0.0.11.dev2
|
|
23
23
|
Requires-Dist: amazon-braket-sdk==1.83.0
|
|
24
24
|
Requires-Dist: oqc-qcaas-client==3.7.0
|
|
25
25
|
Requires-Dist: qiskit
|
|
26
26
|
Requires-Dist: pytket
|
|
27
27
|
Requires-Dist: pytket-braket
|
|
28
|
+
Requires-Dist: pymorphous
|
|
28
29
|
Provides-Extra: dev
|
|
29
30
|
Requires-Dist: black; extra == "dev"
|
|
30
31
|
Requires-Dist: bumpver; extra == "dev"
|
|
@@ -33,6 +34,15 @@ Requires-Dist: pip-tools; extra == "dev"
|
|
|
33
34
|
Requires-Dist: pytest; extra == "dev"
|
|
34
35
|
Dynamic: license-file
|
|
35
36
|
|
|
36
|
-
#
|
|
37
|
+
# quapp-braket
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
`quapp-braket` is a logging utility built on top of Loguru, designed to provide enhanced logging
|
|
40
|
+
features such as context binding, colored output, and flexible formatting for quantum application
|
|
41
|
+
projects.
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
Install dependencies (if any) or the package via pip:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install quapp-braket
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# quapp-braket
|
|
2
|
+
|
|
3
|
+
`quapp-braket` is a logging utility built on top of Loguru, designed to provide enhanced logging
|
|
4
|
+
features such as context binding, colored output, and flexible formatting for quantum application
|
|
5
|
+
projects.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Install dependencies (if any) or the package via pip:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install quapp-braket
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools>=70.1.0"]
|
|
2
|
+
requires = ["setuptools>=70.1.0", "wheel>=0.45.1,<0.46.0"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "quapp-braket"
|
|
7
|
-
version = "0.0.11.
|
|
7
|
+
version = "0.0.11.dev4"
|
|
8
8
|
description = "Quapp braket library supporting Quapp Platform for Quantum Computing"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "CITYNOW Co. Ltd. ", email = "corp@citynow.vn" }]
|
|
@@ -16,12 +16,13 @@ classifiers = [
|
|
|
16
16
|
]
|
|
17
17
|
keywords = ["quapp", "quapp-braket", "braket", "quantum"]
|
|
18
18
|
dependencies = [
|
|
19
|
-
"quapp-common==0.0.11.
|
|
19
|
+
"quapp-common==0.0.11.dev2",
|
|
20
20
|
"amazon-braket-sdk==1.83.0",
|
|
21
21
|
"oqc-qcaas-client==3.7.0",
|
|
22
22
|
"qiskit",
|
|
23
23
|
"pytket",
|
|
24
|
-
"pytket-braket"
|
|
24
|
+
"pytket-braket",
|
|
25
|
+
"pymorphous"
|
|
25
26
|
]
|
|
26
27
|
requires-python = ">=3.7"
|
|
27
28
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Quapp Platform Project
|
|
2
|
+
# braket_circuit_export_task.py
|
|
3
|
+
# Copyright © CITYNOW Co. Ltd.All rights reserved.
|
|
4
|
+
|
|
5
|
+
from braket.circuits import Circuit
|
|
6
|
+
from qiskit import QuantumCircuit
|
|
7
|
+
from quapp_common.async_tasks.export_circuit_task import CircuitExportTask
|
|
8
|
+
from quapp_common.config.logging_config import logger
|
|
9
|
+
|
|
10
|
+
from quapp_braket.util.circuit_convert_utils import braket_to_qiskit
|
|
11
|
+
|
|
12
|
+
logger = logger.bind(context='BraketCircuitExportTask')
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BraketCircuitExportTask(CircuitExportTask):
|
|
16
|
+
|
|
17
|
+
def __init__(self, circuit_data_holder, backend_data_holder):
|
|
18
|
+
super().__init__(circuit_data_holder, backend_data_holder)
|
|
19
|
+
|
|
20
|
+
def _transpile_circuit(self) -> QuantumCircuit:
|
|
21
|
+
"""
|
|
22
|
+
Transpiles the circuit held in the circuit_data_holder to a Qiskit quantum circuit.
|
|
23
|
+
|
|
24
|
+
This method checks if the circuit is an instance of Braket's Circuit. If so, it
|
|
25
|
+
converts it to a Qiskit QuantumCircuit using the braket_to_qiskit utility function.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
QuantumCircuit: Transpiled Qiskit quantum circuit.
|
|
29
|
+
|
|
30
|
+
Raises:
|
|
31
|
+
ValueError: If the circuit is not of type Circuit.
|
|
32
|
+
"""
|
|
33
|
+
logger.info(f"Transpiling Braket circuit to Qiskit")
|
|
34
|
+
circuit = self.circuit_data_holder.circuit
|
|
35
|
+
if not circuit:
|
|
36
|
+
logger.error(f"Circuit is None")
|
|
37
|
+
raise ValueError("Circuit must not be None")
|
|
38
|
+
|
|
39
|
+
if isinstance(circuit, Circuit):
|
|
40
|
+
logger.debug(f"Converting Braket circuit")
|
|
41
|
+
return braket_to_qiskit(circuit)
|
|
42
|
+
|
|
43
|
+
logger.error(f"Invalid circuit type: {type(circuit)}")
|
|
44
|
+
raise ValueError(f"Expected Braket Circuit, got {type(circuit)}")
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Quapp Platform Project
|
|
2
|
+
# braket_invocation.py
|
|
3
|
+
# Copyright © CITYNOW Co. Ltd.All rights reserved.
|
|
4
|
+
|
|
5
|
+
from braket.circuits import Circuit
|
|
6
|
+
from quapp_common.component.backend.invocation import Invocation
|
|
7
|
+
from quapp_common.config.logging_config import logger
|
|
8
|
+
from quapp_common.config.thread_config import circuit_exporting_pool
|
|
9
|
+
from quapp_common.data.async_task.circuit_export.backend_holder import BackendDataHolder
|
|
10
|
+
from quapp_common.data.async_task.circuit_export.circuit_holder import CircuitDataHolder
|
|
11
|
+
from quapp_common.data.request.invocation_request import InvocationRequest
|
|
12
|
+
from quapp_common.model.provider.provider import Provider
|
|
13
|
+
|
|
14
|
+
from ...async_tasks.braket_circuit_export_task import BraketCircuitExportTask
|
|
15
|
+
from ...factory.braket_device_factory import create_device
|
|
16
|
+
from ...factory.braket_provider_factory import create_provider
|
|
17
|
+
|
|
18
|
+
logger = logger.bind(context='BraketInvocation')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BraketInvocation(Invocation):
|
|
22
|
+
|
|
23
|
+
def __init__(self, request_data: InvocationRequest):
|
|
24
|
+
super().__init__(request_data)
|
|
25
|
+
|
|
26
|
+
def _export_circuit(self, circuit):
|
|
27
|
+
"""
|
|
28
|
+
Initiates the export of a quantum circuit using BraketCircuitExportTask.
|
|
29
|
+
|
|
30
|
+
This method creates a BraketCircuitExportTask with the provided circuit
|
|
31
|
+
and submits it to the circuit exporting pool for asynchronous execution.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
circuit: The quantum circuit to be exported.
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
ValueError: If circuit_export_url or backend_information is invalid.
|
|
38
|
+
"""
|
|
39
|
+
logger.info("Exporting circuit")
|
|
40
|
+
|
|
41
|
+
if not self.circuit_export_url or not self.backend_information:
|
|
42
|
+
logger.error("Invalid circuit_export_url or backend_information")
|
|
43
|
+
raise ValueError("Circuit export URL and backend information must not be None")
|
|
44
|
+
|
|
45
|
+
circuit_export_task = BraketCircuitExportTask(
|
|
46
|
+
circuit_data_holder=CircuitDataHolder(circuit, self.circuit_export_url),
|
|
47
|
+
backend_data_holder=BackendDataHolder(
|
|
48
|
+
self.backend_information, self.authentication.user_token
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
circuit_exporting_pool.submit(circuit_export_task.do)
|
|
52
|
+
logger.debug("Circuit export task submitted")
|
|
53
|
+
|
|
54
|
+
def _create_provider(self):
|
|
55
|
+
"""
|
|
56
|
+
Creates a provider instance using the specified backend information.
|
|
57
|
+
|
|
58
|
+
This method utilizes the `create_provider` function to generate a provider
|
|
59
|
+
based on the provider tag, SDK, and authentication details from the
|
|
60
|
+
backend information.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Provider: An instance of the provider created using the specified details.
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
ValueError: If backend_information or authentication is invalid.
|
|
67
|
+
"""
|
|
68
|
+
logger.info("Creating provider")
|
|
69
|
+
|
|
70
|
+
provider = create_provider(
|
|
71
|
+
provider_type=self.backend_information.provider_tag,
|
|
72
|
+
sdk=self.sdk,
|
|
73
|
+
authentication=self.backend_information.authentication
|
|
74
|
+
)
|
|
75
|
+
logger.debug("Provider created")
|
|
76
|
+
return provider
|
|
77
|
+
|
|
78
|
+
def _create_device(self, provider: Provider):
|
|
79
|
+
"""
|
|
80
|
+
Creates a device instance using the provider and specified backend information.
|
|
81
|
+
|
|
82
|
+
This method utilizes the `create_device` function to generate a device
|
|
83
|
+
based on the provider instance, device name, authentication details, and
|
|
84
|
+
SDK from the backend information.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
provider (Provider): An instance of the provider used to create the device.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
CustomDevice: An instance of the device created using the specified details.
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
ValueError: If backend_information or authentication is invalid.
|
|
94
|
+
"""
|
|
95
|
+
logger.info("Creating device")
|
|
96
|
+
|
|
97
|
+
device = create_device(
|
|
98
|
+
provider=provider,
|
|
99
|
+
device_specification=self.backend_information.device_name,
|
|
100
|
+
authentication=self.backend_information.authentication,
|
|
101
|
+
sdk=self.sdk
|
|
102
|
+
)
|
|
103
|
+
logger.debug("Device created")
|
|
104
|
+
return device
|
|
105
|
+
|
|
106
|
+
def _get_qubit_amount(self, circuit):
|
|
107
|
+
"""
|
|
108
|
+
Retrieves the number of qubits used in the given quantum circuit.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
circuit: The quantum circuit for which to retrieve the qubit count.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
int: The number of qubits used in the circuit.
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
ValueError: If the circuit is not of type Circuit.
|
|
118
|
+
"""
|
|
119
|
+
logger.info("Retrieving qubit count")
|
|
120
|
+
|
|
121
|
+
if isinstance(circuit, Circuit):
|
|
122
|
+
qubit_count = circuit.qubit_count
|
|
123
|
+
logger.debug(f"Qubit count: {qubit_count}")
|
|
124
|
+
return qubit_count
|
|
125
|
+
|
|
126
|
+
logger.error(f"Invalid circuit type: {type(circuit)}")
|
|
127
|
+
raise ValueError(f"Invalid circuit type: {type(circuit)}")
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Quapp Platform Project
|
|
2
|
+
# braket_device_factory.py
|
|
3
|
+
# Copyright © CITYNOW Co. Ltd.All rights reserved.
|
|
4
|
+
|
|
5
|
+
from quapp_common.config.logging_config import logger
|
|
6
|
+
from quapp_common.enum.provider_tag import ProviderTag
|
|
7
|
+
from quapp_common.enum.sdk import Sdk
|
|
8
|
+
from quapp_common.model.provider.provider import Provider
|
|
9
|
+
|
|
10
|
+
from quapp_braket.constant.authentication_const import BUCKET_NAME, PREFIX
|
|
11
|
+
from quapp_braket.model.device.aws_braket_device import AwsBraketDevice
|
|
12
|
+
from quapp_braket.model.device.oqc_cloud_device import OqcCloudDevice
|
|
13
|
+
from quapp_braket.model.device.qapp_braket_device import QuappBraketDevice
|
|
14
|
+
|
|
15
|
+
logger = logger.bind(context='BraketDeviceFactory')
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def create_device(provider: Provider, device_specification: str, authentication: dict, sdk: Sdk):
|
|
19
|
+
logger.info("Creating device")
|
|
20
|
+
|
|
21
|
+
# Validate inputs
|
|
22
|
+
if not isinstance(provider, Provider):
|
|
23
|
+
logger.error("Invalid provider: %s", type(provider).__name__)
|
|
24
|
+
raise ValueError(f"provider must be a Provider instance, got {type(provider).__name__}")
|
|
25
|
+
if not isinstance(device_specification, str):
|
|
26
|
+
logger.error("Invalid device_specification: %s", type(device_specification).__name__)
|
|
27
|
+
raise ValueError(
|
|
28
|
+
f"device_specification must be a string, got {type(device_specification).__name__}")
|
|
29
|
+
if not isinstance(sdk, Sdk):
|
|
30
|
+
logger.error("Invalid sdk: %s", type(sdk).__name__)
|
|
31
|
+
raise ValueError(f"sdk must be an Sdk instance, got {type(sdk).__name__}")
|
|
32
|
+
|
|
33
|
+
provider_type = ProviderTag.resolve(provider.get_provider_type().value)
|
|
34
|
+
logger.debug(f"Resolved provider_type: {provider_type}")
|
|
35
|
+
|
|
36
|
+
if provider_type == ProviderTag.QUAO_QUANTUM_SIMULATOR and sdk == Sdk.BRAKET:
|
|
37
|
+
logger.info("Creating QuappBraketDevice")
|
|
38
|
+
device = QuappBraketDevice(provider, device_specification)
|
|
39
|
+
logger.info("QuappBraketDevice created successfully")
|
|
40
|
+
return device
|
|
41
|
+
|
|
42
|
+
if provider_type == ProviderTag.AWS_BRAKET:
|
|
43
|
+
if not isinstance(authentication, dict):
|
|
44
|
+
logger.error(f"Invalid authentication: {type(authentication).__name__}")
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"authentication must be a dictionary, got {type(authentication).__name__}")
|
|
47
|
+
|
|
48
|
+
bucket = authentication.get(BUCKET_NAME)
|
|
49
|
+
prefix = authentication.get(PREFIX)
|
|
50
|
+
if bucket is None or prefix is None:
|
|
51
|
+
logger.error("Missing AWS authentication details - bucket: %s, prefix: %s", bucket,
|
|
52
|
+
prefix)
|
|
53
|
+
raise ValueError(
|
|
54
|
+
f"AWS authentication requires {BUCKET_NAME} and {PREFIX}, got bucket={bucket}, prefix={prefix}")
|
|
55
|
+
logger.debug(f"AWS authentication details - bucket: {bucket}, prefix: {prefix}")
|
|
56
|
+
logger.info("Creating AwsBraketDevice")
|
|
57
|
+
device = AwsBraketDevice(provider, device_specification, bucket, prefix)
|
|
58
|
+
logger.info("AwsBraketDevice created successfully")
|
|
59
|
+
return device
|
|
60
|
+
|
|
61
|
+
if provider_type == ProviderTag.OQC_CLOUD:
|
|
62
|
+
logger.info("Creating OqcCloudDevice")
|
|
63
|
+
device = OqcCloudDevice(provider, device_specification)
|
|
64
|
+
logger.info("OqcCloudDevice created successfully")
|
|
65
|
+
return device
|
|
66
|
+
|
|
67
|
+
logger.error(f"Unsupported device for provider_type: {provider_type}, sdk: {sdk}")
|
|
68
|
+
raise ValueError(f"Unsupported device for provider_type={provider_type}, sdk={sdk}")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Quapp Platform Project
|
|
2
|
+
# braket_handler_factory.py
|
|
3
|
+
# Copyright © CITYNOW Co. Ltd.All rights reserved.
|
|
4
|
+
|
|
5
|
+
from quapp_common.config.logging_config import logger
|
|
6
|
+
from quapp_common.factory.handler_factory import HandlerFactory
|
|
7
|
+
from quapp_common.handler.handler import Handler
|
|
8
|
+
|
|
9
|
+
from ..handler.invocation_handler import InvocationHandler
|
|
10
|
+
from ..handler.job_fetching_handler import JobFetchingHandler
|
|
11
|
+
from ..util.provider_job_utils import is_valid_job_arn, is_valid_quantum_task_arn
|
|
12
|
+
|
|
13
|
+
logger = logger.bind(context='BraketHandlerFactory')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BraketHandlerFactory(HandlerFactory):
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def create_handler(event, circuit_preparation_fn, post_processing_fn) -> Handler:
|
|
20
|
+
logger.info("create_handler() started")
|
|
21
|
+
|
|
22
|
+
request_data = event.json()
|
|
23
|
+
logger.debug(f"Parsed request_data: {request_data}")
|
|
24
|
+
|
|
25
|
+
provider_job_id = request_data.get('providerJobId')
|
|
26
|
+
logger.debug(f"providerJobId: {provider_job_id}")
|
|
27
|
+
|
|
28
|
+
if provider_job_id is None:
|
|
29
|
+
logger.debug("No providerJobId found, returning InvocationHandler")
|
|
30
|
+
return InvocationHandler(
|
|
31
|
+
request_data=request_data,
|
|
32
|
+
circuit_preparation_fn=circuit_preparation_fn,
|
|
33
|
+
post_processing_fn=post_processing_fn,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if is_valid_quantum_task_arn(provider_job_id) or is_valid_job_arn(provider_job_id):
|
|
37
|
+
logger.info("Valid providerJobId found, returning JobFetchingHandler")
|
|
38
|
+
return JobFetchingHandler(request_data=request_data,
|
|
39
|
+
post_processing_fn=post_processing_fn)
|
|
40
|
+
|
|
41
|
+
logger.error(f"Invalid providerJobId: {provider_job_id}")
|
|
42
|
+
raise ValueError(f"Invalid providerJobId: {provider_job_id}")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Quapp Platform Project
|
|
2
|
+
# braket_provider_factory.py
|
|
3
|
+
# Copyright © CITYNOW Co. Ltd.All rights reserved.
|
|
4
|
+
|
|
5
|
+
from quapp_common.config.logging_config import logger
|
|
6
|
+
from quapp_common.enum.provider_tag import ProviderTag
|
|
7
|
+
from quapp_common.enum.sdk import Sdk
|
|
8
|
+
|
|
9
|
+
from ..constant.authentication_const import ACCESS_KEY, ACCESS_TOKEN, REGION_NAME, SECRET_KEY, URL
|
|
10
|
+
from ..model.provider.aws_braket_provider import AwsBraketProvider
|
|
11
|
+
from ..model.provider.oqc_cloud_provider import OqcCloudProvider
|
|
12
|
+
from ..model.provider.qapp_braket_provider import QuappBraketProvider
|
|
13
|
+
from ..util.braket_utils import verify_credentials
|
|
14
|
+
|
|
15
|
+
logger = logger.bind(context='BraketProviderFactory')
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def create_provider(provider_type: ProviderTag, sdk: Sdk, authentication: dict):
|
|
19
|
+
logger.info("create_provider()")
|
|
20
|
+
|
|
21
|
+
if ProviderTag.QUAO_QUANTUM_SIMULATOR.__eq__(provider_type) and Sdk.BRAKET.__eq__(sdk):
|
|
22
|
+
logger.debug("Create QuappBraketProvider")
|
|
23
|
+
|
|
24
|
+
return QuappBraketProvider()
|
|
25
|
+
|
|
26
|
+
if ProviderTag.AWS_BRAKET.__eq__(provider_type):
|
|
27
|
+
logger.debug(f"Create AwsBraketProvider with authentication keys: "
|
|
28
|
+
f"ACCESS_KEY={'present' if ACCESS_KEY in authentication else 'missing'}, "
|
|
29
|
+
f"SECRET_KEY={'present' if SECRET_KEY in authentication else 'missing'}, "
|
|
30
|
+
f"REGION_NAME={authentication.get(REGION_NAME)}")
|
|
31
|
+
|
|
32
|
+
verify_credentials(authentication)
|
|
33
|
+
return AwsBraketProvider(authentication.get(ACCESS_KEY), authentication.get(SECRET_KEY),
|
|
34
|
+
authentication.get(REGION_NAME), )
|
|
35
|
+
|
|
36
|
+
if ProviderTag.OQC_CLOUD.__eq__(provider_type):
|
|
37
|
+
logger.debug(f"Create OqcCloudProvider with URL={authentication.get(URL)}, "
|
|
38
|
+
f"ACCESS_TOKEN={'present' if ACCESS_TOKEN in authentication else 'missing'}")
|
|
39
|
+
return OqcCloudProvider(
|
|
40
|
+
authentication.get(URL),
|
|
41
|
+
authentication.get(ACCESS_TOKEN)
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
logger.error(f"Unsupported provider: {provider_type}")
|
|
45
|
+
raise ValueError("Unsupported provider!")
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Quapp Platform Project
|
|
2
|
+
# invocation_handler.py
|
|
3
|
+
# Copyright © CITYNOW Co. Ltd.All rights reserved.
|
|
4
|
+
|
|
5
|
+
from quapp_common.config.logging_config import logger
|
|
6
|
+
from quapp_common.data.request.invocation_request import InvocationRequest
|
|
7
|
+
from quapp_common.handler.handler import Handler
|
|
8
|
+
|
|
9
|
+
from ..component.backend.braket_invocation import BraketInvocation
|
|
10
|
+
|
|
11
|
+
logger = logger.bind(context='InvocationHandler')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InvocationHandler(Handler):
|
|
15
|
+
|
|
16
|
+
def __init__(self, request_data: dict,
|
|
17
|
+
circuit_preparation_fn,
|
|
18
|
+
post_processing_fn):
|
|
19
|
+
super().__init__(request_data, post_processing_fn)
|
|
20
|
+
self.circuit_preparation_fn = circuit_preparation_fn
|
|
21
|
+
|
|
22
|
+
def handle(self):
|
|
23
|
+
logger.debug(f"Creating InvocationRequest with data: {self.request_data.keys()}")
|
|
24
|
+
invocation_request = InvocationRequest(self.request_data)
|
|
25
|
+
|
|
26
|
+
logger.debug("Initializing BraketInvocation backend")
|
|
27
|
+
backend = BraketInvocation(invocation_request)
|
|
28
|
+
|
|
29
|
+
logger.debug(f"Submitting job with circuit_preparation_fn={self.circuit_preparation_fn}, "
|
|
30
|
+
f"post_processing_fn={self.post_processing_fn}")
|
|
31
|
+
backend.submit_job(circuit_preparation_fn=self.circuit_preparation_fn,
|
|
32
|
+
post_processing_fn=self.post_processing_fn)
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# Quapp Platform Project
|
|
2
|
+
# aws_braket_device.py
|
|
3
|
+
# Copyright © CITYNOW Co. Ltd.All rights reserved.
|
|
4
|
+
|
|
4
5
|
from dateutil.parser import parse
|
|
6
|
+
from quapp_common.config.logging_config import logger
|
|
7
|
+
from quapp_common.data.device.circuit_running_option import CircuitRunningOption
|
|
8
|
+
from quapp_common.enum.status.job_status import JobStatus
|
|
9
|
+
from quapp_common.model.device.custom_device import CustomDevice
|
|
10
|
+
from quapp_common.model.provider.provider import Provider
|
|
11
|
+
|
|
12
|
+
from quapp_braket.constant.job_result_const import CREATED_AT, ENDED_AT, SHOTS, TASK_METADATA
|
|
5
13
|
|
|
6
|
-
|
|
7
|
-
from qapp_common.data.device.circuit_running_option import CircuitRunningOption
|
|
8
|
-
from qapp_common.enum.status.job_status import JobStatus
|
|
9
|
-
from qapp_common.model.device.custom_device import CustomDevice
|
|
10
|
-
from qapp_common.model.provider.provider import Provider
|
|
14
|
+
logger = logger.bind(context='AwsBraketDevice')
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class AwsBraketDevice(CustomDevice):
|
|
@@ -20,41 +24,41 @@ class AwsBraketDevice(CustomDevice):
|
|
|
20
24
|
self.s3_folder = (s3_bucket_name, s3_prefix)
|
|
21
25
|
|
|
22
26
|
def _produce_histogram_data(self, job_result) -> dict | None:
|
|
23
|
-
logger.debug("
|
|
27
|
+
logger.debug("_produce_histogram_data()")
|
|
24
28
|
|
|
25
29
|
return dict(job_result.measurement_counts)
|
|
26
30
|
|
|
27
31
|
def _get_provider_job_id(self, job) -> str:
|
|
28
|
-
logger.debug("
|
|
32
|
+
logger.debug("_get_provider_job_id()")
|
|
29
33
|
|
|
30
34
|
return job.id
|
|
31
35
|
|
|
32
36
|
def _get_job_status(self, job) -> str:
|
|
33
|
-
logger.debug("
|
|
37
|
+
logger.debug("_get_job_status()")
|
|
34
38
|
|
|
35
39
|
job_state = job.state()
|
|
36
|
-
logger.debug("
|
|
40
|
+
logger.debug(f"job status: {job_state}")
|
|
37
41
|
|
|
38
42
|
if JobStatus.COMPLETED.value.__eq__(job_state):
|
|
39
43
|
job_state = JobStatus.DONE.value
|
|
40
44
|
return job_state
|
|
41
45
|
|
|
42
46
|
def _calculate_execution_time(self, job_result):
|
|
43
|
-
logger.debug("
|
|
47
|
+
logger.debug("_calculate_execution_time()")
|
|
44
48
|
|
|
45
|
-
if
|
|
49
|
+
if TASK_METADATA not in job_result:
|
|
46
50
|
return
|
|
47
51
|
|
|
48
|
-
task_metadata = job_result[
|
|
52
|
+
task_metadata = job_result[TASK_METADATA]
|
|
49
53
|
|
|
50
54
|
if task_metadata is None \
|
|
51
55
|
or not bool(task_metadata) \
|
|
52
|
-
or
|
|
53
|
-
or
|
|
56
|
+
or CREATED_AT not in task_metadata \
|
|
57
|
+
or ENDED_AT not in task_metadata:
|
|
54
58
|
return
|
|
55
59
|
|
|
56
|
-
created_at = task_metadata[
|
|
57
|
-
ended_at = task_metadata[
|
|
60
|
+
created_at = task_metadata[CREATED_AT]
|
|
61
|
+
ended_at = task_metadata[ENDED_AT]
|
|
58
62
|
|
|
59
63
|
if created_at is None or ended_at is None:
|
|
60
64
|
return
|
|
@@ -66,16 +70,15 @@ class AwsBraketDevice(CustomDevice):
|
|
|
66
70
|
|
|
67
71
|
self.execution_time = offset.total_seconds()
|
|
68
72
|
|
|
69
|
-
logger.debug("
|
|
70
|
-
.format(self.execution_time))
|
|
73
|
+
logger.debug(f"Execution time calculation was: {self.execution_time} seconds")
|
|
71
74
|
|
|
72
75
|
def _get_job_result(self, job):
|
|
73
|
-
logger.debug("
|
|
76
|
+
logger.debug("_get_job_result()")
|
|
74
77
|
|
|
75
78
|
return job.result()
|
|
76
79
|
|
|
77
80
|
def _create_job(self, circuit, options: CircuitRunningOption):
|
|
78
|
-
logger.debug("
|
|
81
|
+
logger.debug("_create_job()")
|
|
79
82
|
|
|
80
83
|
job = self.device.run(task_specification=circuit,
|
|
81
84
|
s3_destination_folder=self.s3_folder,
|
|
@@ -83,7 +86,7 @@ class AwsBraketDevice(CustomDevice):
|
|
|
83
86
|
return job
|
|
84
87
|
|
|
85
88
|
def _is_simulator(self) -> bool:
|
|
86
|
-
logger.debug("
|
|
89
|
+
logger.debug("_is_simulator()")
|
|
87
90
|
|
|
88
91
|
return True
|
|
89
92
|
|
|
@@ -103,7 +106,7 @@ class AwsBraketDevice(CustomDevice):
|
|
|
103
106
|
Returns:
|
|
104
107
|
int | None: The number of shots if available; otherwise, None.
|
|
105
108
|
"""
|
|
106
|
-
logger.debug("
|
|
109
|
+
logger.debug("_get_shots()")
|
|
107
110
|
|
|
108
|
-
return job_result.task_metadata.shots if hasattr(job_result,
|
|
109
|
-
job_result.task_metadata,
|
|
111
|
+
return job_result.task_metadata.shots if hasattr(job_result, TASK_METADATA) and hasattr(
|
|
112
|
+
job_result.task_metadata, SHOTS) else None
|