qilisdk 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl
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.
- qilisdk/__init__.py +2 -32
- qilisdk/__init__.pyi +2 -15
- qilisdk/analog/__init__.py +18 -1
- qilisdk/analog/analog_result.py +1 -1
- qilisdk/common/__init__.py +2 -5
- qilisdk/digital/__init__.py +5 -12
- qilisdk/digital/ansatz.py +18 -1
- qilisdk/digital/digital_result.py +1 -1
- qilisdk/digital/vqe.py +1 -0
- qilisdk/extras/__init__.py +27 -0
- qilisdk/extras/__init__.pyi +18 -0
- qilisdk/extras/cuda/__init__.py +0 -5
- qilisdk/extras/cuda/cuda_backend.py +1 -3
- qilisdk/extras/qaas/models.py +76 -1
- qilisdk/extras/qaas/qaas_analog_result.py +20 -0
- qilisdk/extras/qaas/qaas_backend.py +120 -20
- qilisdk/extras/qaas/qaas_time_evolution_result.py +20 -0
- qilisdk/extras/qaas/qaas_vqe_result.py +20 -0
- qilisdk/yaml.py +34 -2
- qilisdk-0.1.2.dist-info/METADATA +538 -0
- {qilisdk-0.1.0.dist-info → qilisdk-0.1.2.dist-info}/RECORD +23 -19
- qilisdk-0.1.0.dist-info/METADATA +0 -237
- {qilisdk-0.1.0.dist-info → qilisdk-0.1.2.dist-info}/WHEEL +0 -0
- {qilisdk-0.1.0.dist-info → qilisdk-0.1.2.dist-info}/licenses/LICENCE +0 -0
qilisdk/__init__.py
CHANGED
|
@@ -12,36 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import
|
|
16
|
-
from typing import List
|
|
15
|
+
from qilisdk import analog, common, digital, extras, utils
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
from ._optionals import ImportedFeature, OptionalFeature, Symbol, import_optional_dependencies
|
|
21
|
-
|
|
22
|
-
# Put your always-available, core symbols here
|
|
23
|
-
__all__ = ["Algorithm", "Model", "Optimizer", "Result"]
|
|
24
|
-
|
|
25
|
-
# Define your optional features
|
|
26
|
-
OPTIONAL_FEATURES: List[OptionalFeature] = [
|
|
27
|
-
OptionalFeature(
|
|
28
|
-
name="cuda-backend",
|
|
29
|
-
dependencies=["cudaq"],
|
|
30
|
-
symbols=[Symbol(path="qilisdk.extras.cuda.cuda_backend", name="CudaBackend")],
|
|
31
|
-
),
|
|
32
|
-
OptionalFeature(
|
|
33
|
-
name="qaas",
|
|
34
|
-
dependencies=["httpx", "keyring", "pydantic", "pydantic-settings"],
|
|
35
|
-
symbols=[Symbol(path="qilisdk.extras.qaas.qaas_backend", name="QaaSBackend")],
|
|
36
|
-
),
|
|
37
|
-
# Add more OptionalFeature() entries for other extras if needed
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
current_module = sys.modules[__name__]
|
|
41
|
-
|
|
42
|
-
# Dynamically import (or stub) each feature's symbols and attach them
|
|
43
|
-
for feature in OPTIONAL_FEATURES:
|
|
44
|
-
imported_feature: ImportedFeature = import_optional_dependencies(feature)
|
|
45
|
-
for symbol_name, symbol_obj in imported_feature.symbols.items():
|
|
46
|
-
setattr(current_module, symbol_name, symbol_obj)
|
|
47
|
-
__all__ += [symbol_name] # noqa: PLE0604
|
|
17
|
+
__all__ = ["analog", "common", "digital", "extras", "utils"]
|
qilisdk/__init__.pyi
CHANGED
|
@@ -12,19 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from qilisdk
|
|
16
|
-
from qilisdk.common import Algorithm, Model, Optimizer, Result
|
|
17
|
-
from qilisdk.digital import DigitalSimulationMethod
|
|
18
|
-
from qilisdk.extras.cuda import CudaBackend
|
|
19
|
-
from qilisdk.extras.qaas.qaas_backend import QaaSBackend
|
|
15
|
+
from qilisdk import analog, common, digital, extras, utils
|
|
20
16
|
|
|
21
|
-
__all__ = [
|
|
22
|
-
"Algorithm",
|
|
23
|
-
"CudaBackend",
|
|
24
|
-
"DigitalSimulationMethod",
|
|
25
|
-
"Hamiltonian",
|
|
26
|
-
"Model",
|
|
27
|
-
"Optimizer",
|
|
28
|
-
"QaaSBackend",
|
|
29
|
-
"Result",
|
|
30
|
-
]
|
|
17
|
+
__all__ = ["analog", "common", "digital", "extras", "utils"]
|
qilisdk/analog/__init__.py
CHANGED
|
@@ -12,6 +12,23 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from .algorithms import TimeEvolution
|
|
15
16
|
from .hamiltonian import Hamiltonian, I, X, Y, Z
|
|
17
|
+
from .quantum_objects import QuantumObject, basis, bra, expect, ket, tensor
|
|
18
|
+
from .schedule import Schedule
|
|
16
19
|
|
|
17
|
-
__all__ = [
|
|
20
|
+
__all__ = [
|
|
21
|
+
"Hamiltonian",
|
|
22
|
+
"I",
|
|
23
|
+
"QuantumObject",
|
|
24
|
+
"Schedule",
|
|
25
|
+
"TimeEvolution",
|
|
26
|
+
"X",
|
|
27
|
+
"Y",
|
|
28
|
+
"Z",
|
|
29
|
+
"basis",
|
|
30
|
+
"bra",
|
|
31
|
+
"expect",
|
|
32
|
+
"ket",
|
|
33
|
+
"tensor",
|
|
34
|
+
]
|
qilisdk/analog/analog_result.py
CHANGED
qilisdk/common/__init__.py
CHANGED
|
@@ -12,9 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from .
|
|
16
|
-
from .model import Model
|
|
17
|
-
from .optimizer import Optimizer, SciPyOptimizer
|
|
18
|
-
from .result import Result
|
|
15
|
+
from .optimizer import SciPyOptimizer
|
|
19
16
|
|
|
20
|
-
__all__ = ["
|
|
17
|
+
__all__ = ["SciPyOptimizer"]
|
qilisdk/digital/__init__.py
CHANGED
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from .ansatz import HardwareEfficientAnsatz
|
|
15
16
|
from .circuit import Circuit
|
|
16
|
-
from .digital_backend import
|
|
17
|
-
from .digital_result import DigitalResult
|
|
17
|
+
from .digital_backend import DigitalSimulationMethod
|
|
18
18
|
from .gates import (
|
|
19
19
|
CNOT,
|
|
20
20
|
CZ,
|
|
@@ -24,10 +24,6 @@ from .gates import (
|
|
|
24
24
|
U1,
|
|
25
25
|
U2,
|
|
26
26
|
U3,
|
|
27
|
-
Adjoint,
|
|
28
|
-
BasicGate,
|
|
29
|
-
Controlled,
|
|
30
|
-
Exponential,
|
|
31
27
|
Gate,
|
|
32
28
|
H,
|
|
33
29
|
M,
|
|
@@ -37,6 +33,7 @@ from .gates import (
|
|
|
37
33
|
Y,
|
|
38
34
|
Z,
|
|
39
35
|
)
|
|
36
|
+
from .vqe import VQE
|
|
40
37
|
|
|
41
38
|
__all__ = [
|
|
42
39
|
"CNOT",
|
|
@@ -47,16 +44,12 @@ __all__ = [
|
|
|
47
44
|
"U1",
|
|
48
45
|
"U2",
|
|
49
46
|
"U3",
|
|
50
|
-
"
|
|
51
|
-
"BasicGate",
|
|
47
|
+
"VQE",
|
|
52
48
|
"Circuit",
|
|
53
|
-
"Controlled",
|
|
54
|
-
"DigitalBackend",
|
|
55
|
-
"DigitalResult",
|
|
56
49
|
"DigitalSimulationMethod",
|
|
57
|
-
"Exponential",
|
|
58
50
|
"Gate",
|
|
59
51
|
"H",
|
|
52
|
+
"HardwareEfficientAnsatz",
|
|
60
53
|
"M",
|
|
61
54
|
"S",
|
|
62
55
|
"T",
|
qilisdk/digital/ansatz.py
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
from abc import ABC, abstractmethod
|
|
15
|
-
from typing import ClassVar, Literal, Union
|
|
15
|
+
from typing import Any, ClassVar, Literal, Union
|
|
16
16
|
|
|
17
17
|
from qilisdk.digital.circuit import Circuit
|
|
18
18
|
from qilisdk.digital.gates import CNOT, CZ, U1, U2, U3, M
|
|
@@ -103,6 +103,23 @@ class HardwareEfficientAnsatz(Ansatz):
|
|
|
103
103
|
"grouped": self._construct_layer_grouped,
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
def __getstate__(self) -> dict[str, Any]:
|
|
107
|
+
state = self.__dict__.copy()
|
|
108
|
+
# Exclude the mapping that contains bound methods (not serializable).
|
|
109
|
+
state.pop("construct_layer_handlers", None)
|
|
110
|
+
return state
|
|
111
|
+
|
|
112
|
+
def __setstate__(self, state) -> None: # noqa: ANN001
|
|
113
|
+
"""
|
|
114
|
+
Restore the object's state after deserialization and reinitialize any attributes that were omitted.
|
|
115
|
+
"""
|
|
116
|
+
self.__dict__.update(state)
|
|
117
|
+
# Reconstruct the mapping with the proper bound methods.
|
|
118
|
+
self.construct_layer_handlers = {
|
|
119
|
+
"interposed": self._construct_layer_interposed,
|
|
120
|
+
"grouped": self._construct_layer_grouped,
|
|
121
|
+
}
|
|
122
|
+
|
|
106
123
|
@property
|
|
107
124
|
def nparameters(self) -> int:
|
|
108
125
|
"""
|
qilisdk/digital/vqe.py
CHANGED
qilisdk/extras/__init__.py
CHANGED
|
@@ -11,3 +11,30 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
import sys
|
|
15
|
+
|
|
16
|
+
from qilisdk._optionals import ImportedFeature, OptionalFeature, Symbol, import_optional_dependencies
|
|
17
|
+
|
|
18
|
+
__all__ = []
|
|
19
|
+
|
|
20
|
+
OPTIONAL_FEATURES: list[OptionalFeature] = [
|
|
21
|
+
OptionalFeature(
|
|
22
|
+
name="cuda",
|
|
23
|
+
dependencies=["cudaq"],
|
|
24
|
+
symbols=[Symbol(path="qilisdk.extras.cuda.cuda_backend", name="CudaBackend")],
|
|
25
|
+
),
|
|
26
|
+
OptionalFeature(
|
|
27
|
+
name="qaas",
|
|
28
|
+
dependencies=["httpx", "keyring", "pydantic", "pydantic-settings"],
|
|
29
|
+
symbols=[Symbol(path="qilisdk.extras.qaas.qaas_backend", name="QaaSBackend")],
|
|
30
|
+
),
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
current_module = sys.modules[__name__]
|
|
34
|
+
|
|
35
|
+
# Dynamically import (or stub) each feature's symbols and attach them
|
|
36
|
+
for feature in OPTIONAL_FEATURES:
|
|
37
|
+
imported_feature: ImportedFeature = import_optional_dependencies(feature)
|
|
38
|
+
for symbol_name, symbol_obj in imported_feature.symbols.items():
|
|
39
|
+
setattr(current_module, symbol_name, symbol_obj)
|
|
40
|
+
__all__ += [symbol_name] # noqa: PLE0604
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Copyright 2025 Qilimanjaro Quantum Tech
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from .cuda.cuda_backend import CudaBackend
|
|
16
|
+
from .qaas.qaas_backend import QaaSBackend
|
|
17
|
+
|
|
18
|
+
__all__ = ["CudaBackend", "QaaSBackend"]
|
qilisdk/extras/cuda/__init__.py
CHANGED
|
@@ -11,8 +11,3 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
from .cuda_backend import CudaBackend
|
|
16
|
-
from .cuda_digital_result import CudaDigitalResult
|
|
17
|
-
|
|
18
|
-
__all__ = ["CudaBackend", "CudaDigitalResult"]
|
|
@@ -31,10 +31,7 @@ from qilisdk.digital import (
|
|
|
31
31
|
U1,
|
|
32
32
|
U2,
|
|
33
33
|
U3,
|
|
34
|
-
Adjoint,
|
|
35
|
-
BasicGate,
|
|
36
34
|
Circuit,
|
|
37
|
-
Controlled,
|
|
38
35
|
H,
|
|
39
36
|
M,
|
|
40
37
|
S,
|
|
@@ -45,6 +42,7 @@ from qilisdk.digital import (
|
|
|
45
42
|
)
|
|
46
43
|
from qilisdk.digital.digital_backend import DigitalBackend, DigitalSimulationMethod
|
|
47
44
|
from qilisdk.digital.exceptions import UnsupportedGateError
|
|
45
|
+
from qilisdk.digital.gates import Adjoint, BasicGate, Controlled
|
|
48
46
|
|
|
49
47
|
from .cuda_analog_result import CudaAnalogResult
|
|
50
48
|
from .cuda_digital_result import CudaDigitalResult
|
qilisdk/extras/qaas/models.py
CHANGED
|
@@ -16,9 +16,20 @@ from enum import Enum
|
|
|
16
16
|
|
|
17
17
|
from pydantic import BaseModel, ConfigDict, Field
|
|
18
18
|
|
|
19
|
+
from qilisdk.analog import Hamiltonian, QuantumObject, Schedule, TimeEvolution
|
|
20
|
+
from qilisdk.analog.hamiltonian import PauliOperator
|
|
21
|
+
from qilisdk.common.optimizer import Optimizer
|
|
22
|
+
from qilisdk.digital import VQE, Circuit
|
|
23
|
+
from qilisdk.yaml import yaml
|
|
24
|
+
|
|
25
|
+
from .qaas_analog_result import QaaSAnalogResult
|
|
26
|
+
from .qaas_digital_result import QaaSDigitalResult
|
|
27
|
+
from .qaas_time_evolution_result import QaaSTimeEvolutionResult
|
|
28
|
+
from .qaas_vqe_result import QaaSVQEResult
|
|
29
|
+
|
|
19
30
|
|
|
20
31
|
class QaaSModel(BaseModel):
|
|
21
|
-
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
32
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True, arbitrary_types_allowed=True)
|
|
22
33
|
|
|
23
34
|
|
|
24
35
|
class LoginPayload(BaseModel): ...
|
|
@@ -51,7 +62,71 @@ class DeviceStatus(str, Enum):
|
|
|
51
62
|
OFFLINE = "offline"
|
|
52
63
|
|
|
53
64
|
|
|
65
|
+
class DeviceType(str, Enum):
|
|
66
|
+
"""Device type"""
|
|
67
|
+
|
|
68
|
+
QUANTUM_DIGITAL = "quantum_device"
|
|
69
|
+
QUANTUM_ANALOG = "quantum_analog_device"
|
|
70
|
+
SIMULATOR = "simulator_device"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@yaml.register_class
|
|
54
74
|
class Device(QaaSModel):
|
|
55
75
|
id: int = Field(...)
|
|
56
76
|
name: str = Field(...)
|
|
57
77
|
status: DeviceStatus = Field(...)
|
|
78
|
+
type: DeviceType = Field(...)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class ExecutePayloadType(str, Enum):
|
|
82
|
+
DIGITAL = "digital"
|
|
83
|
+
ANALOG = "analog"
|
|
84
|
+
VQE = "vqe"
|
|
85
|
+
TIME_EVOLUTION = "time_evolution"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@yaml.register_class
|
|
89
|
+
class DigitalPayload(QaaSModel):
|
|
90
|
+
circuit: Circuit = Field(...)
|
|
91
|
+
nshots: int = Field(...)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@yaml.register_class
|
|
95
|
+
class AnalogPayload(QaaSModel):
|
|
96
|
+
schedule: Schedule = Field(...)
|
|
97
|
+
initial_state: QuantumObject = Field(...)
|
|
98
|
+
observables: list[PauliOperator | Hamiltonian] = Field(...)
|
|
99
|
+
store_intermediate_results: bool = Field(...)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@yaml.register_class
|
|
103
|
+
class VQEPayload(QaaSModel):
|
|
104
|
+
vqe: VQE = Field(...)
|
|
105
|
+
optimizer: Optimizer = Field(...)
|
|
106
|
+
nshots: int = Field(...)
|
|
107
|
+
store_intermediate_results: bool = Field(...)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@yaml.register_class
|
|
111
|
+
class TimeEvolutionPayload(QaaSModel):
|
|
112
|
+
time_evolution: TimeEvolution = Field()
|
|
113
|
+
store_intermediate_results: bool = Field()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@yaml.register_class
|
|
117
|
+
class ExecutePayload(QaaSModel):
|
|
118
|
+
type: ExecutePayloadType = Field(...)
|
|
119
|
+
device_id: int = Field(...)
|
|
120
|
+
digital_payload: DigitalPayload | None = None
|
|
121
|
+
analog_payload: AnalogPayload | None = None
|
|
122
|
+
vqe_payload: VQEPayload | None = None
|
|
123
|
+
time_evolution_payload: TimeEvolutionPayload | None = None
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@yaml.register_class
|
|
127
|
+
class ExecuteResponse(QaaSModel):
|
|
128
|
+
type: ExecutePayloadType = Field(...)
|
|
129
|
+
digital_result: QaaSDigitalResult | None = None
|
|
130
|
+
analog_result: QaaSAnalogResult | None = None
|
|
131
|
+
vqe_result: QaaSVQEResult | None = None
|
|
132
|
+
time_evolution_result: QaaSTimeEvolutionResult | None = None
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2025 Qilimanjaro Quantum Tech
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from qilisdk.analog.analog_result import AnalogResult
|
|
16
|
+
from qilisdk.yaml import yaml
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@yaml.register_class
|
|
20
|
+
class QaaSAnalogResult(AnalogResult): ...
|
|
@@ -17,27 +17,38 @@ import json
|
|
|
17
17
|
import logging
|
|
18
18
|
from base64 import urlsafe_b64encode
|
|
19
19
|
from datetime import datetime, timezone
|
|
20
|
-
from typing import TYPE_CHECKING
|
|
20
|
+
from typing import TYPE_CHECKING, cast
|
|
21
21
|
|
|
22
22
|
import httpx
|
|
23
|
-
from pydantic import ValidationError
|
|
23
|
+
from pydantic import TypeAdapter, ValidationError
|
|
24
24
|
|
|
25
25
|
from qilisdk.analog.analog_backend import AnalogBackend
|
|
26
26
|
from qilisdk.digital.digital_backend import DigitalBackend
|
|
27
27
|
|
|
28
28
|
from .keyring import delete_credentials, load_credentials, store_credentials
|
|
29
|
-
from .models import
|
|
29
|
+
from .models import (
|
|
30
|
+
AnalogPayload,
|
|
31
|
+
Device,
|
|
32
|
+
DigitalPayload,
|
|
33
|
+
ExecutePayload,
|
|
34
|
+
ExecutePayloadType,
|
|
35
|
+
ExecuteResponse,
|
|
36
|
+
TimeEvolutionPayload,
|
|
37
|
+
Token,
|
|
38
|
+
VQEPayload,
|
|
39
|
+
)
|
|
30
40
|
from .qaas_settings import QaaSSettings
|
|
31
41
|
|
|
32
42
|
if TYPE_CHECKING:
|
|
33
|
-
from qilisdk.analog
|
|
34
|
-
from qilisdk.analog.hamiltonian import
|
|
35
|
-
from qilisdk.
|
|
36
|
-
from qilisdk.
|
|
37
|
-
from qilisdk.common.algorithm import Algorithm
|
|
38
|
-
from qilisdk.digital.circuit import Circuit
|
|
43
|
+
from qilisdk.analog import Hamiltonian, QuantumObject, Schedule, TimeEvolution
|
|
44
|
+
from qilisdk.analog.hamiltonian import PauliOperator
|
|
45
|
+
from qilisdk.common.optimizer import Optimizer
|
|
46
|
+
from qilisdk.digital import VQE, Circuit
|
|
39
47
|
|
|
48
|
+
from .qaas_analog_result import QaaSAnalogResult
|
|
40
49
|
from .qaas_digital_result import QaaSDigitalResult
|
|
50
|
+
from .qaas_time_evolution_result import QaaSTimeEvolutionResult
|
|
51
|
+
from .qaas_vqe_result import QaaSVQEResult
|
|
41
52
|
|
|
42
53
|
logging.basicConfig(
|
|
43
54
|
format="%(levelname)s [%(asctime)s] %(name)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", level=logging.DEBUG
|
|
@@ -55,8 +66,6 @@ class QaaSBackend(DigitalBackend, AnalogBackend):
|
|
|
55
66
|
"""
|
|
56
67
|
|
|
57
68
|
_api_url: str = "https://qilimanjaroqaas.ddns.net:8080/api/v1"
|
|
58
|
-
_authorization_request_url: str = "https://qilimanjaroqaas.ddns.net:8080/api/v1/authorisation-tokens"
|
|
59
|
-
_authorization_refresh_url: str = "https://qilimanjaroqaas.ddns.net:8080/api/v1/authorisation-tokens/refresh"
|
|
60
69
|
|
|
61
70
|
def __init__(self) -> None:
|
|
62
71
|
"""
|
|
@@ -70,6 +79,14 @@ class QaaSBackend(DigitalBackend, AnalogBackend):
|
|
|
70
79
|
"Please call QaaSBackend.login(username, apikey) or ensure environment variables are set."
|
|
71
80
|
)
|
|
72
81
|
self._username, self._token = credentials
|
|
82
|
+
self._selected_device: Device | None = None
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def selected_device(self) -> Device | None:
|
|
86
|
+
return self._selected_device
|
|
87
|
+
|
|
88
|
+
def set_device(self, device: Device) -> None:
|
|
89
|
+
self._selected_device = device
|
|
73
90
|
|
|
74
91
|
@classmethod
|
|
75
92
|
def login(
|
|
@@ -105,7 +122,7 @@ class QaaSBackend(DigitalBackend, AnalogBackend):
|
|
|
105
122
|
encoded_assertion = urlsafe_b64encode(json.dumps(assertion, indent=2).encode("utf-8")).decode("utf-8")
|
|
106
123
|
with httpx.Client(timeout=10.0) as client:
|
|
107
124
|
response = client.post(
|
|
108
|
-
QaaSBackend.
|
|
125
|
+
QaaSBackend._api_url + "/authorisation-tokens",
|
|
109
126
|
json={
|
|
110
127
|
"grantType": "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
111
128
|
"assertion": encoded_assertion,
|
|
@@ -134,12 +151,37 @@ class QaaSBackend(DigitalBackend, AnalogBackend):
|
|
|
134
151
|
headers={"X-Client-Version": "0.23.2", "Authorization": f"Bearer {self._token.access_token}"},
|
|
135
152
|
)
|
|
136
153
|
response.raise_for_status()
|
|
137
|
-
|
|
138
|
-
|
|
154
|
+
|
|
155
|
+
devices_list_adapter = TypeAdapter(list[Device])
|
|
156
|
+
devices = devices_list_adapter.validate_python(response.json()["items"])
|
|
157
|
+
|
|
158
|
+
# Previous two lines are the same as doing:
|
|
159
|
+
# response_json = response.json()
|
|
160
|
+
# devices = [Device(**item) for item in response_json["items"]]
|
|
161
|
+
|
|
139
162
|
return devices
|
|
140
163
|
|
|
164
|
+
def _ensure_device_selected(self) -> Device:
|
|
165
|
+
if self._selected_device is None:
|
|
166
|
+
raise ValueError("Device not selected.")
|
|
167
|
+
return self._selected_device
|
|
168
|
+
|
|
141
169
|
def execute(self, circuit: Circuit, nshots: int = 1000) -> QaaSDigitalResult:
|
|
142
|
-
|
|
170
|
+
device = self._ensure_device_selected()
|
|
171
|
+
payload = ExecutePayload(
|
|
172
|
+
type=ExecutePayloadType.DIGITAL,
|
|
173
|
+
device_id=device.id,
|
|
174
|
+
digital_payload=DigitalPayload(circuit=circuit, nshots=nshots),
|
|
175
|
+
)
|
|
176
|
+
with httpx.Client(timeout=20.0) as client:
|
|
177
|
+
response = client.post(
|
|
178
|
+
QaaSBackend._api_url + "/execute",
|
|
179
|
+
headers={"X-Client-Version": "0.23.2", "Authorization": f"Bearer {self._token.access_token}"},
|
|
180
|
+
json=payload.model_dump_json(),
|
|
181
|
+
)
|
|
182
|
+
response.raise_for_status()
|
|
183
|
+
execute_response = ExecuteResponse(**response.json())
|
|
184
|
+
return cast("QaaSDigitalResult", execute_response.digital_result)
|
|
143
185
|
|
|
144
186
|
def evolve(
|
|
145
187
|
self,
|
|
@@ -147,8 +189,66 @@ class QaaSBackend(DigitalBackend, AnalogBackend):
|
|
|
147
189
|
initial_state: QuantumObject,
|
|
148
190
|
observables: list[PauliOperator | Hamiltonian],
|
|
149
191
|
store_intermediate_results: bool = False,
|
|
150
|
-
) ->
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
192
|
+
) -> QaaSAnalogResult:
|
|
193
|
+
device = self._ensure_device_selected()
|
|
194
|
+
payload = ExecutePayload(
|
|
195
|
+
type=ExecutePayloadType.ANALOG,
|
|
196
|
+
device_id=device.id,
|
|
197
|
+
analog_payload=AnalogPayload(
|
|
198
|
+
schedule=schedule,
|
|
199
|
+
initial_state=initial_state,
|
|
200
|
+
observables=observables,
|
|
201
|
+
store_intermediate_results=store_intermediate_results,
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
with httpx.Client(timeout=20.0) as client:
|
|
205
|
+
response = client.post(
|
|
206
|
+
QaaSBackend._api_url + "/execute",
|
|
207
|
+
headers={"X-Client-Version": "0.23.2", "Authorization": f"Bearer {self._token.access_token}"},
|
|
208
|
+
json=payload.model_dump_json(),
|
|
209
|
+
)
|
|
210
|
+
response.raise_for_status()
|
|
211
|
+
execute_response = ExecuteResponse(**response.json())
|
|
212
|
+
return cast("QaaSAnalogResult", execute_response.analog_result)
|
|
213
|
+
|
|
214
|
+
def run_vqe(
|
|
215
|
+
self, vqe: VQE, optimizer: Optimizer, nshots: int = 1000, store_intermediate_results: bool = False
|
|
216
|
+
) -> QaaSVQEResult:
|
|
217
|
+
device = self._ensure_device_selected()
|
|
218
|
+
payload = ExecutePayload(
|
|
219
|
+
type=ExecutePayloadType.VQE,
|
|
220
|
+
device_id=device.id,
|
|
221
|
+
vqe_payload=VQEPayload(
|
|
222
|
+
vqe=vqe, optimizer=optimizer, nshots=nshots, store_intermediate_results=store_intermediate_results
|
|
223
|
+
),
|
|
224
|
+
)
|
|
225
|
+
with httpx.Client(timeout=20.0) as client:
|
|
226
|
+
response = client.post(
|
|
227
|
+
QaaSBackend._api_url + "/execute",
|
|
228
|
+
headers={"X-Client-Version": "0.23.2", "Authorization": f"Bearer {self._token.access_token}"},
|
|
229
|
+
json=payload.model_dump_json(),
|
|
230
|
+
)
|
|
231
|
+
response.raise_for_status()
|
|
232
|
+
execute_response = ExecuteResponse(**response.json())
|
|
233
|
+
return cast("QaaSVQEResult", execute_response.vqe_result)
|
|
234
|
+
|
|
235
|
+
def run_time_evolution(
|
|
236
|
+
self, time_evolution: TimeEvolution, store_intermediate_results: bool = False
|
|
237
|
+
) -> QaaSTimeEvolutionResult:
|
|
238
|
+
device = self._ensure_device_selected()
|
|
239
|
+
payload = ExecutePayload(
|
|
240
|
+
type=ExecutePayloadType.TIME_EVOLUTION,
|
|
241
|
+
device_id=device.id,
|
|
242
|
+
time_evolution_payload=TimeEvolutionPayload(
|
|
243
|
+
time_evolution=time_evolution, store_intermediate_results=store_intermediate_results
|
|
244
|
+
),
|
|
245
|
+
)
|
|
246
|
+
with httpx.Client(timeout=20.0) as client:
|
|
247
|
+
response = client.post(
|
|
248
|
+
QaaSBackend._api_url + "/execute",
|
|
249
|
+
headers={"X-Client-Version": "0.23.2", "Authorization": f"Bearer {self._token.access_token}"},
|
|
250
|
+
json=payload.model_dump_json(),
|
|
251
|
+
)
|
|
252
|
+
response.raise_for_status()
|
|
253
|
+
execute_response = ExecuteResponse(**response.json())
|
|
254
|
+
return cast("QaaSTimeEvolutionResult", execute_response.time_evolution_result)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2025 Qilimanjaro Quantum Tech
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from qilisdk.analog.analog_result import AnalogResult
|
|
16
|
+
from qilisdk.yaml import yaml
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@yaml.register_class
|
|
20
|
+
class QaaSTimeEvolutionResult(AnalogResult): ...
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2025 Qilimanjaro Quantum Tech
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from qilisdk.digital.vqe import VQEResult
|
|
16
|
+
from qilisdk.yaml import yaml
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@yaml.register_class
|
|
20
|
+
class QaaSVQEResult(VQEResult): ...
|