luna-quantum 1.0.4rc3__cp312-cp312-manylinux_2_34_x86_64.whl → 1.0.5__cp312-cp312-manylinux_2_34_x86_64.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.
Potentially problematic release.
This version of luna-quantum might be problematic. Click here for more details.
- luna_quantum/_core.cpython-312-x86_64-linux-gnu.so +0 -0
- luna_quantum/_core.pyi +56 -2
- luna_quantum/client/controllers/luna_platform_client.py +122 -21
- luna_quantum/client/controllers/luna_q.py +6 -1
- luna_quantum/client/controllers/luna_solve.py +5 -1
- luna_quantum/client/interfaces/services/service_i.py +20 -0
- luna_quantum/client/rest_client/info_rest_client.py +1 -3
- luna_quantum/client/schemas/solve_job.py +3 -0
- luna_quantum/decorators.py +8 -7
- luna_quantum/factories/luna_solve_client_factory.py +28 -3
- luna_quantum/solve/domain/abstract/luna_algorithm.py +5 -3
- luna_quantum/solve/domain/model_metadata.py +3 -1
- luna_quantum/solve/domain/solve_job.py +14 -5
- luna_quantum/solve/interfaces/algorithm_i.py +3 -1
- luna_quantum/solve/parameters/algorithms/__init__.py +4 -0
- luna_quantum/solve/parameters/algorithms/lq_fda/__init__.py +9 -0
- luna_quantum/solve/parameters/algorithms/lq_fda/fujits_da_base.py +85 -0
- luna_quantum/solve/parameters/algorithms/lq_fda/fujitsu_da_cpu.py +125 -0
- luna_quantum/solve/parameters/algorithms/lq_fda/fujitsu_da_v3c.py +155 -0
- luna_quantum/solve/parameters/algorithms/lq_fda/fujitsu_da_v4.py +155 -0
- luna_quantum/solve/parameters/backends/__init__.py +2 -0
- luna_quantum/solve/parameters/backends/fda.py +17 -0
- luna_quantum/transformations.pyi +5 -1
- luna_quantum/util/pretty_base.py +1 -1
- {luna_quantum-1.0.4rc3.dist-info → luna_quantum-1.0.5.dist-info}/METADATA +1 -1
- {luna_quantum-1.0.4rc3.dist-info → luna_quantum-1.0.5.dist-info}/RECORD +29 -23
- {luna_quantum-1.0.4rc3.dist-info → luna_quantum-1.0.5.dist-info}/WHEEL +1 -1
- {luna_quantum-1.0.4rc3.dist-info → luna_quantum-1.0.5.dist-info}/licenses/LICENSE +0 -0
- {luna_quantum-1.0.4rc3.dist-info → luna_quantum-1.0.5.dist-info}/licenses/NOTICE +0 -0
|
Binary file
|
luna_quantum/_core.pyi
CHANGED
|
@@ -854,6 +854,14 @@ class Solution:
|
|
|
854
854
|
"""
|
|
855
855
|
...
|
|
856
856
|
|
|
857
|
+
def repr_html(self, /) -> str:
|
|
858
|
+
"""Represent the solution as a html table.
|
|
859
|
+
|
|
860
|
+
Returns
|
|
861
|
+
-------
|
|
862
|
+
str
|
|
863
|
+
"""
|
|
864
|
+
|
|
857
865
|
def __getitem__(self, item: int, /) -> ResultView:
|
|
858
866
|
"""
|
|
859
867
|
Extract a result view from the `Solution` object.
|
|
@@ -952,6 +960,22 @@ class Solution:
|
|
|
952
960
|
"""Get the names of all variables in the solution."""
|
|
953
961
|
...
|
|
954
962
|
|
|
963
|
+
def cvar(self, /, alpha: float) -> float:
|
|
964
|
+
"""
|
|
965
|
+
Compute the Conditional Value at Rist (CVaR) of the solution.
|
|
966
|
+
|
|
967
|
+
Returns
|
|
968
|
+
-------
|
|
969
|
+
float
|
|
970
|
+
The CVaR.
|
|
971
|
+
|
|
972
|
+
Raises
|
|
973
|
+
------
|
|
974
|
+
ComputationError
|
|
975
|
+
If the computation fails for any reason.
|
|
976
|
+
"""
|
|
977
|
+
...
|
|
978
|
+
|
|
955
979
|
def expectation_value(self, /) -> float:
|
|
956
980
|
"""
|
|
957
981
|
Compute the expectation value of the solution.
|
|
@@ -2907,6 +2931,20 @@ class Expression:
|
|
|
2907
2931
|
"""
|
|
2908
2932
|
...
|
|
2909
2933
|
|
|
2934
|
+
def equal_contents(self, other: Expression, /) -> bool:
|
|
2935
|
+
"""
|
|
2936
|
+
Check whether this expression has equal contents as `other`.
|
|
2937
|
+
|
|
2938
|
+
Parameters
|
|
2939
|
+
----------
|
|
2940
|
+
other : Expression
|
|
2941
|
+
|
|
2942
|
+
Returns
|
|
2943
|
+
-------
|
|
2944
|
+
bool
|
|
2945
|
+
"""
|
|
2946
|
+
...
|
|
2947
|
+
|
|
2910
2948
|
@overload
|
|
2911
2949
|
def encode(self, /) -> bytes: ...
|
|
2912
2950
|
@overload
|
|
@@ -2959,7 +2997,7 @@ class Expression:
|
|
|
2959
2997
|
...
|
|
2960
2998
|
|
|
2961
2999
|
@classmethod
|
|
2962
|
-
def decode(cls, data: bytes) -> Expression:
|
|
3000
|
+
def decode(cls, data: bytes, env: Environment) -> Expression:
|
|
2963
3001
|
"""
|
|
2964
3002
|
Reconstruct an expression from encoded bytes.
|
|
2965
3003
|
|
|
@@ -2967,6 +3005,8 @@ class Expression:
|
|
|
2967
3005
|
----------
|
|
2968
3006
|
data : bytes
|
|
2969
3007
|
Binary blob returned by `encode()`.
|
|
3008
|
+
env : Environment
|
|
3009
|
+
The environment of the expression.
|
|
2970
3010
|
|
|
2971
3011
|
Returns
|
|
2972
3012
|
-------
|
|
@@ -2981,7 +3021,7 @@ class Expression:
|
|
|
2981
3021
|
...
|
|
2982
3022
|
|
|
2983
3023
|
@classmethod
|
|
2984
|
-
def deserialize(cls, data: bytes) -> Expression:
|
|
3024
|
+
def deserialize(cls, data: bytes, env: Environment) -> Expression:
|
|
2985
3025
|
"""
|
|
2986
3026
|
Alias for `decode()`.
|
|
2987
3027
|
|
|
@@ -3549,6 +3589,20 @@ class Environment:
|
|
|
3549
3589
|
"""
|
|
3550
3590
|
...
|
|
3551
3591
|
|
|
3592
|
+
def equal_contents(self, other: Environment, /) -> bool:
|
|
3593
|
+
"""
|
|
3594
|
+
Check whether this environment has equal contents as `other`.
|
|
3595
|
+
|
|
3596
|
+
Parameters
|
|
3597
|
+
----------
|
|
3598
|
+
other : Environment
|
|
3599
|
+
|
|
3600
|
+
Returns
|
|
3601
|
+
-------
|
|
3602
|
+
bool
|
|
3603
|
+
"""
|
|
3604
|
+
...
|
|
3605
|
+
|
|
3552
3606
|
def __eq__(self, other: Environment, /) -> bool: ...
|
|
3553
3607
|
def __str__(self, /) -> str: ...
|
|
3554
3608
|
def __repr__(self, /) -> str: ...
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
from abc import abstractmethod
|
|
4
5
|
from contextlib import suppress
|
|
5
6
|
from enum import Enum
|
|
6
7
|
from http import HTTPStatus
|
|
@@ -42,12 +43,15 @@ def check_httpx_exceptions(response: Response) -> None:
|
|
|
42
43
|
HttpErrorUtils.check_for_error(response)
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
class APIKeyAuth(httpx.Auth):
|
|
46
|
+
class APIKeyAuth(httpx.Auth): # noqa: PLW1641
|
|
46
47
|
"""API key authentication method for luna platform."""
|
|
47
48
|
|
|
48
49
|
def __init__(self, token: str) -> None:
|
|
49
50
|
self.token = token
|
|
50
51
|
|
|
52
|
+
self.dev_header_value = os.getenv("LUNA_DEV_EXTRA_HEADER_VALUE", None)
|
|
53
|
+
self.dev_header_name = os.getenv("LUNA_DEV_EXTRA_HEADER_NAME", None)
|
|
54
|
+
|
|
51
55
|
def auth_flow(self, request: Request) -> Generator[Request, Response]:
|
|
52
56
|
"""
|
|
53
57
|
Authenticate a request to Luna platform.
|
|
@@ -59,20 +63,44 @@ class APIKeyAuth(httpx.Auth):
|
|
|
59
63
|
"""
|
|
60
64
|
request.headers["Luna-API-Key"] = self.token
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if dev_header_name and dev_header_value:
|
|
65
|
-
request.headers[dev_header_name] = dev_header_value
|
|
66
|
+
if self.dev_header_name and self.dev_header_value:
|
|
67
|
+
request.headers[self.dev_header_name] = self.dev_header_value
|
|
66
68
|
yield request
|
|
67
69
|
|
|
70
|
+
def __eq__(self, other: object) -> bool:
|
|
71
|
+
"""
|
|
72
|
+
Check if the object is equal to the current instance.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
other: object
|
|
77
|
+
Object to compare with the current instance.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
bool:
|
|
82
|
+
True if the object is equal to the current instance, False otherwise.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
if self is other:
|
|
86
|
+
return True
|
|
87
|
+
if not isinstance(other, APIKeyAuth):
|
|
88
|
+
return False
|
|
89
|
+
return (
|
|
90
|
+
self.token == other.token
|
|
91
|
+
and self.dev_header_name == other.dev_header_name
|
|
92
|
+
and self.dev_header_value == other.dev_header_value
|
|
93
|
+
)
|
|
94
|
+
|
|
68
95
|
|
|
69
96
|
class LunaPlatformClient(IService):
|
|
70
97
|
"""Luna platform REST client."""
|
|
71
98
|
|
|
72
|
-
_base_url: str
|
|
99
|
+
_base_url: str
|
|
73
100
|
|
|
74
101
|
_httpx_client: httpx.Client
|
|
75
102
|
_api_key: ClassVar[str | None] = None
|
|
103
|
+
_timeout: float | None = None
|
|
76
104
|
|
|
77
105
|
@property
|
|
78
106
|
def client(self) -> httpx.Client:
|
|
@@ -85,9 +113,13 @@ class LunaPlatformClient(IService):
|
|
|
85
113
|
"""
|
|
86
114
|
return self._httpx_client
|
|
87
115
|
|
|
116
|
+
@classmethod
|
|
117
|
+
@abstractmethod
|
|
118
|
+
def get_api(cls) -> LunaPrefixEnum:
|
|
119
|
+
"""Return the api of the client."""
|
|
120
|
+
|
|
88
121
|
def __init__(
|
|
89
122
|
self,
|
|
90
|
-
api: LunaPrefixEnum,
|
|
91
123
|
api_key: str | None = None,
|
|
92
124
|
base_url: str | None = None,
|
|
93
125
|
timeout: float | None = 240.0,
|
|
@@ -116,12 +148,46 @@ class LunaPlatformClient(IService):
|
|
|
116
148
|
itself will time out after 240 seconds.
|
|
117
149
|
Default: 240.0
|
|
118
150
|
"""
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
151
|
+
self._base_url = self._get_base_url(base_url)
|
|
152
|
+
self._timeout = timeout
|
|
153
|
+
|
|
154
|
+
api_key = self._get_api_key(api_key)
|
|
155
|
+
|
|
156
|
+
self.dev_header_value = os.getenv("LUNA_DEV_EXTRA_HEADER_VALUE", None)
|
|
157
|
+
self.dev_header_name = os.getenv("LUNA_DEV_EXTRA_HEADER_NAME", None)
|
|
158
|
+
|
|
159
|
+
self._httpx_client = LunaHTTPClient(
|
|
160
|
+
auth=APIKeyAuth(api_key),
|
|
161
|
+
base_url=self._base_url,
|
|
162
|
+
follow_redirects=True,
|
|
163
|
+
timeout=self._timeout,
|
|
164
|
+
event_hooks={"response": [check_httpx_exceptions]},
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
self._authenticate()
|
|
168
|
+
|
|
169
|
+
def _get_api_key(self, api_key: str | None = None) -> str:
|
|
170
|
+
"""
|
|
171
|
+
Retrieve the API key for authentication.
|
|
172
|
+
|
|
173
|
+
Get the API key from provided arguments, class-specific key, or environment
|
|
174
|
+
variables. Raises an error if no API key is available.
|
|
175
|
+
|
|
176
|
+
Parameters
|
|
177
|
+
----------
|
|
178
|
+
api_key : str or None, optional
|
|
179
|
+
An API key string if provided.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
str
|
|
184
|
+
The API key to be used for authentication.
|
|
185
|
+
|
|
186
|
+
Raises
|
|
187
|
+
------
|
|
188
|
+
LunaApiKeyMissingError
|
|
189
|
+
If no API key is available from any source.
|
|
190
|
+
"""
|
|
125
191
|
if api_key:
|
|
126
192
|
auth_key = api_key
|
|
127
193
|
elif self.__class__._api_key: # noqa: SLF001 Use here self.__class__ so that LunaSolve and LunaQ can have different api keys set
|
|
@@ -130,16 +196,31 @@ class LunaPlatformClient(IService):
|
|
|
130
196
|
auth_key = key
|
|
131
197
|
else:
|
|
132
198
|
raise LunaApiKeyMissingError
|
|
199
|
+
return auth_key
|
|
133
200
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
follow_redirects=True,
|
|
138
|
-
timeout=timeout,
|
|
139
|
-
event_hooks={"response": [check_httpx_exceptions]},
|
|
140
|
-
)
|
|
201
|
+
def _get_base_url(self, base_url: str | None = None) -> str:
|
|
202
|
+
"""
|
|
203
|
+
Get the base url.
|
|
141
204
|
|
|
142
|
-
|
|
205
|
+
Parameters
|
|
206
|
+
----------
|
|
207
|
+
base_url: str
|
|
208
|
+
Base API URL.
|
|
209
|
+
If you want to use API not on your local PC then change it.
|
|
210
|
+
You can do that by setting the environment variable LUNA_BASE_URL.
|
|
211
|
+
Default value https://api.aqarios.com.
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
str
|
|
216
|
+
Base url.
|
|
217
|
+
|
|
218
|
+
"""
|
|
219
|
+
if base_url is None:
|
|
220
|
+
base_url = os.getenv("LUNA_BASE_URL", "https://api.aqarios.com")
|
|
221
|
+
if os.getenv("LUNA_DISABLE_SUFFIX", "false").lower() == "true":
|
|
222
|
+
return f"{base_url}/api/v1"
|
|
223
|
+
return f"{base_url}/{self.get_api().value}/api/v1"
|
|
143
224
|
|
|
144
225
|
def __del__(self) -> None: # noqa: D105
|
|
145
226
|
if hasattr(self, "_httpx_client"):
|
|
@@ -153,3 +234,23 @@ class LunaPlatformClient(IService):
|
|
|
153
234
|
if exception.response.status_code == HTTPStatus.UNAUTHORIZED:
|
|
154
235
|
raise LunaApiKeyInvalidError from exception
|
|
155
236
|
raise
|
|
237
|
+
|
|
238
|
+
def is_same(
|
|
239
|
+
self,
|
|
240
|
+
api_key: str | None = None,
|
|
241
|
+
) -> bool:
|
|
242
|
+
"""
|
|
243
|
+
Whether the service is created with the current environment variables.
|
|
244
|
+
|
|
245
|
+
Returns
|
|
246
|
+
-------
|
|
247
|
+
bool:
|
|
248
|
+
True if the service is created with the current environment variables.
|
|
249
|
+
False otherwise.
|
|
250
|
+
"""
|
|
251
|
+
api_key = self._get_api_key(api_key)
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
self._get_base_url() == self._base_url
|
|
255
|
+
and APIKeyAuth(api_key) == self._httpx_client.auth
|
|
256
|
+
)
|
|
@@ -38,11 +38,16 @@ class LunaQ(LunaPlatformClient, ILunaQ):
|
|
|
38
38
|
itself will time out after 240 seconds.
|
|
39
39
|
Default: 240.0
|
|
40
40
|
"""
|
|
41
|
-
super().__init__(api_key=api_key,
|
|
41
|
+
super().__init__(api_key=api_key, timeout=timeout)
|
|
42
42
|
|
|
43
43
|
self.circuit = CircuitRestClient(self)
|
|
44
44
|
self.qpu_token = QpuTokenRestClient(self)
|
|
45
45
|
|
|
46
|
+
@classmethod
|
|
47
|
+
def get_api(cls) -> LunaPrefixEnum:
|
|
48
|
+
"""Return the api of the client."""
|
|
49
|
+
return LunaPrefixEnum.LUNA_Q
|
|
50
|
+
|
|
46
51
|
@classmethod
|
|
47
52
|
def authenticate(cls, api_key: str) -> None:
|
|
48
53
|
"""
|
|
@@ -53,7 +53,6 @@ class LunaSolve(LunaPlatformClient, ILunaSolve):
|
|
|
53
53
|
"""
|
|
54
54
|
super().__init__(
|
|
55
55
|
api_key=api_key,
|
|
56
|
-
api=LunaPrefixEnum.LUNA_SOLVE,
|
|
57
56
|
timeout=timeout,
|
|
58
57
|
)
|
|
59
58
|
|
|
@@ -62,6 +61,11 @@ class LunaSolve(LunaPlatformClient, ILunaSolve):
|
|
|
62
61
|
self._qpu_token = QpuTokenRestClient(self)
|
|
63
62
|
self._info = InfoRestClient(self)
|
|
64
63
|
|
|
64
|
+
@classmethod
|
|
65
|
+
def get_api(cls) -> LunaPrefixEnum:
|
|
66
|
+
"""Return the api of the client."""
|
|
67
|
+
return LunaPrefixEnum.LUNA_SOLVE
|
|
68
|
+
|
|
65
69
|
@classmethod
|
|
66
70
|
def authenticate(cls, api_key: str) -> None:
|
|
67
71
|
"""
|
|
@@ -34,3 +34,23 @@ class IService(ABC):
|
|
|
34
34
|
None
|
|
35
35
|
This method does not return any value.
|
|
36
36
|
"""
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def is_same(
|
|
40
|
+
self,
|
|
41
|
+
api_key: str | None = None,
|
|
42
|
+
) -> bool:
|
|
43
|
+
"""
|
|
44
|
+
Whether the service is created with the current environment variables.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
api_key: str
|
|
49
|
+
User's API key
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
bool:
|
|
54
|
+
True if the service is created with the current environment variables.
|
|
55
|
+
False otherwise.
|
|
56
|
+
"""
|
|
@@ -49,9 +49,7 @@ class InfoRestClient(IInfoRestClient):
|
|
|
49
49
|
for provider, solvers in json.items():
|
|
50
50
|
to_return[provider] = {}
|
|
51
51
|
for solver in solvers:
|
|
52
|
-
to_return[provider][solver] = SolverInfo.model_validate(
|
|
53
|
-
json[provider][solver]
|
|
54
|
-
)
|
|
52
|
+
to_return[provider][solver] = SolverInfo.model_validate(solvers[solver])
|
|
55
53
|
|
|
56
54
|
return to_return
|
|
57
55
|
|
luna_quantum/decorators.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Decorators."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
-
from typing import Any, Generic,
|
|
4
|
+
from typing import Any, Generic, TypeAlias, TypeVar
|
|
5
|
+
|
|
6
|
+
from typing_extensions import override
|
|
5
7
|
|
|
6
8
|
from . import Model, Solution
|
|
7
9
|
from .transformations import (
|
|
@@ -16,19 +18,18 @@ from .transformations import (
|
|
|
16
18
|
|
|
17
19
|
T = TypeVar("T")
|
|
18
20
|
|
|
21
|
+
AnalysisSignature: TypeAlias = Callable[[Model, AnalysisCache], T]
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type MetaAnalysisSignature[T] = Callable[[list[BasePass], AnalysisCache], T]
|
|
23
|
+
MetaAnalysisSignature: TypeAlias = Callable[[list[BasePass], AnalysisCache], T]
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
Outcome: TypeAlias = (
|
|
25
26
|
TransformationOutcome | tuple[Model, ActionType] | tuple[Model, ActionType, Any]
|
|
26
27
|
)
|
|
27
|
-
|
|
28
|
+
TransformationSignature: TypeAlias = Callable[
|
|
28
29
|
[Model, AnalysisCache],
|
|
29
30
|
Outcome,
|
|
30
31
|
]
|
|
31
|
-
|
|
32
|
+
BackwardsSignature: TypeAlias = Callable[[Solution, AnalysisCache], Solution]
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
def __identity_backwards(solution: Solution, _: AnalysisCache) -> Solution:
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from logging import Logger
|
|
1
2
|
from typing import ClassVar
|
|
2
3
|
|
|
3
4
|
from luna_quantum.client.interfaces.services.luna_solve_i import ILunaSolve
|
|
5
|
+
from luna_quantum.util.log_utils import Logging
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class LunaSolveClientFactory:
|
|
@@ -11,8 +13,11 @@ class LunaSolveClientFactory:
|
|
|
11
13
|
based on class configurations and input specifications.
|
|
12
14
|
"""
|
|
13
15
|
|
|
16
|
+
_logger: Logger = Logging.get_logger(__name__)
|
|
14
17
|
_client_class: ClassVar[type[ILunaSolve]]
|
|
15
18
|
|
|
19
|
+
_client: ClassVar[ILunaSolve | None] = None
|
|
20
|
+
|
|
16
21
|
@staticmethod
|
|
17
22
|
def get_client(client: ILunaSolve | str | None) -> ILunaSolve:
|
|
18
23
|
"""
|
|
@@ -34,10 +39,30 @@ class LunaSolveClientFactory:
|
|
|
34
39
|
An ILunaSolve client instance.
|
|
35
40
|
"""
|
|
36
41
|
if isinstance(client, ILunaSolve):
|
|
42
|
+
LunaSolveClientFactory._logger.debug(
|
|
43
|
+
"Client is already an instance of ILunaSolve"
|
|
44
|
+
)
|
|
37
45
|
return client
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
|
|
47
|
+
if (
|
|
48
|
+
LunaSolveClientFactory._client
|
|
49
|
+
and isinstance(
|
|
50
|
+
LunaSolveClientFactory._client,
|
|
51
|
+
LunaSolveClientFactory.get_client_class(),
|
|
52
|
+
)
|
|
53
|
+
and LunaSolveClientFactory._client.is_same(client)
|
|
54
|
+
):
|
|
55
|
+
LunaSolveClientFactory._logger.debug(
|
|
56
|
+
"Cache hit. Last used default client is the same as the new one."
|
|
57
|
+
)
|
|
58
|
+
return LunaSolveClientFactory._client
|
|
59
|
+
LunaSolveClientFactory._logger.debug(
|
|
60
|
+
"Cache miss. No used default client or configuration changed. "
|
|
61
|
+
"Creating new client."
|
|
62
|
+
)
|
|
63
|
+
client = LunaSolveClientFactory.get_client_class()(client)
|
|
64
|
+
LunaSolveClientFactory._client = client
|
|
65
|
+
return client
|
|
41
66
|
|
|
42
67
|
@staticmethod
|
|
43
68
|
def get_client_class() -> type[ILunaSolve]:
|
|
@@ -2,7 +2,7 @@ from abc import abstractmethod
|
|
|
2
2
|
from logging import Logger
|
|
3
3
|
from typing import TYPE_CHECKING, Any, ClassVar, Generic
|
|
4
4
|
|
|
5
|
-
from pydantic import
|
|
5
|
+
from pydantic import ConfigDict, Field, field_validator
|
|
6
6
|
|
|
7
7
|
from luna_quantum.aqm_overwrites.model import Model
|
|
8
8
|
from luna_quantum.client.controllers.luna_solve import LunaSolve
|
|
@@ -18,7 +18,7 @@ if TYPE_CHECKING:
|
|
|
18
18
|
from luna_quantum.solve.interfaces.usecases import ISolveJobCreateUseCase
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
class LunaAlgorithm(IAlgorithm[BACKEND_TYPE],
|
|
21
|
+
class LunaAlgorithm(IAlgorithm[BACKEND_TYPE], Generic[BACKEND_TYPE]):
|
|
22
22
|
"""
|
|
23
23
|
Class representing a solver for Luna model problems.
|
|
24
24
|
|
|
@@ -133,7 +133,9 @@ class LunaAlgorithm(IAlgorithm[BACKEND_TYPE], BaseModel, Generic[BACKEND_TYPE]):
|
|
|
133
133
|
SolveJob
|
|
134
134
|
The job object containing the information about the solve process.
|
|
135
135
|
"""
|
|
136
|
-
from luna_quantum.factories.usecase_factory import
|
|
136
|
+
from luna_quantum.factories.usecase_factory import ( # noqa: PLC0415
|
|
137
|
+
UseCaseFactory,
|
|
138
|
+
)
|
|
137
139
|
|
|
138
140
|
b: BACKEND_TYPE
|
|
139
141
|
if backend is not None:
|
|
@@ -45,7 +45,9 @@ class ModelMetadata(BaseModel):
|
|
|
45
45
|
"""
|
|
46
46
|
c = LunaSolveClientFactory.get_client(client=client)
|
|
47
47
|
|
|
48
|
-
from luna_quantum.factories.usecase_factory import
|
|
48
|
+
from luna_quantum.factories.usecase_factory import ( # noqa: PLC0415
|
|
49
|
+
UseCaseFactory,
|
|
50
|
+
)
|
|
49
51
|
|
|
50
52
|
aq_model: Model = UseCaseFactory.model_load_by_metadata(client=c).__call__(
|
|
51
53
|
model_metadata=self
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from logging import Logger
|
|
2
|
-
from typing import ClassVar, Literal
|
|
2
|
+
from typing import Any, ClassVar, Literal
|
|
3
3
|
|
|
4
4
|
from pydantic import BaseModel, PrivateAttr
|
|
5
5
|
|
|
@@ -28,6 +28,7 @@ class SolveJob(BaseModel):
|
|
|
28
28
|
is_cancelable: bool = True
|
|
29
29
|
is_cancellation_requested: bool = False
|
|
30
30
|
|
|
31
|
+
metadata: dict[str, Any] | None = None
|
|
31
32
|
_result: Solution | None = PrivateAttr(default=None)
|
|
32
33
|
|
|
33
34
|
_model: Model | None = PrivateAttr(default=None)
|
|
@@ -72,7 +73,9 @@ class SolveJob(BaseModel):
|
|
|
72
73
|
if status_source == "remote":
|
|
73
74
|
c: ILunaSolve = LunaSolveClientFactory.get_client(client)
|
|
74
75
|
|
|
75
|
-
from luna_quantum.factories.usecase_factory import
|
|
76
|
+
from luna_quantum.factories.usecase_factory import ( # noqa: PLC0415
|
|
77
|
+
UseCaseFactory,
|
|
78
|
+
)
|
|
76
79
|
|
|
77
80
|
UseCaseFactory.solve_job_fetch_update(client=c).__call__(solve_job=self)
|
|
78
81
|
|
|
@@ -122,7 +125,9 @@ class SolveJob(BaseModel):
|
|
|
122
125
|
|
|
123
126
|
c: ILunaSolve = LunaSolveClientFactory.get_client(client)
|
|
124
127
|
|
|
125
|
-
from luna_quantum.factories.usecase_factory import
|
|
128
|
+
from luna_quantum.factories.usecase_factory import ( # noqa: PLC0415
|
|
129
|
+
UseCaseFactory,
|
|
130
|
+
)
|
|
126
131
|
|
|
127
132
|
self._result = UseCaseFactory.solve_job_get_result(client=c).__call__(
|
|
128
133
|
solve_job=self,
|
|
@@ -163,7 +168,9 @@ class SolveJob(BaseModel):
|
|
|
163
168
|
"""
|
|
164
169
|
c: ILunaSolve = LunaSolveClientFactory.get_client(client)
|
|
165
170
|
|
|
166
|
-
from luna_quantum.factories.usecase_factory import
|
|
171
|
+
from luna_quantum.factories.usecase_factory import ( # noqa: PLC0415
|
|
172
|
+
UseCaseFactory,
|
|
173
|
+
)
|
|
167
174
|
|
|
168
175
|
UseCaseFactory.solve_job_cancel(client=c).__call__(self)
|
|
169
176
|
|
|
@@ -182,6 +189,8 @@ class SolveJob(BaseModel):
|
|
|
182
189
|
"""
|
|
183
190
|
c: ILunaSolve = LunaSolveClientFactory.get_client(client)
|
|
184
191
|
|
|
185
|
-
from luna_quantum.factories.usecase_factory import
|
|
192
|
+
from luna_quantum.factories.usecase_factory import ( # noqa: PLC0415
|
|
193
|
+
UseCaseFactory,
|
|
194
|
+
)
|
|
186
195
|
|
|
187
196
|
UseCaseFactory.solve_job_delete(client=c).__call__(solve_job_id=self.id)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
from typing import Any, Generic, TypeVar
|
|
3
3
|
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
4
6
|
from luna_quantum.aqm_overwrites.model import Model
|
|
5
7
|
from luna_quantum.solve.domain.solve_job import SolveJob
|
|
6
8
|
from luna_quantum.solve.interfaces.backend_i import IBackend
|
|
@@ -8,7 +10,7 @@ from luna_quantum.solve.interfaces.backend_i import IBackend
|
|
|
8
10
|
BACKEND_TYPE = TypeVar("BACKEND_TYPE", bound=IBackend)
|
|
9
11
|
|
|
10
12
|
|
|
11
|
-
class IAlgorithm(ABC, Generic[BACKEND_TYPE]):
|
|
13
|
+
class IAlgorithm(ABC, BaseModel, Generic[BACKEND_TYPE]):
|
|
12
14
|
"""
|
|
13
15
|
Interface for an algorithm that performs solve tasks based on a given model.
|
|
14
16
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .flexible_parameter_algorithm import FlexibleParameterAlgorithm
|
|
2
2
|
from .genetic_algorithms import QAGA, SAGA
|
|
3
|
+
from .lq_fda import FujitsuDACpu, FujitsuDAv3c, FujitsuDAv4
|
|
3
4
|
from .optimization_solvers import SCIP
|
|
4
5
|
from .quantum_annealing import (
|
|
5
6
|
Kerberos,
|
|
@@ -31,6 +32,9 @@ __all__ = [
|
|
|
31
32
|
"DialecticSearch",
|
|
32
33
|
"FlexQAOA",
|
|
33
34
|
"FlexibleParameterAlgorithm",
|
|
35
|
+
"FujitsuDACpu",
|
|
36
|
+
"FujitsuDAv3c",
|
|
37
|
+
"FujitsuDAv4",
|
|
34
38
|
"Kerberos",
|
|
35
39
|
"LeapHybridBqm",
|
|
36
40
|
"LeapHybridCqm",
|