luna-quantum 0.0.16__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.
Potentially problematic release.
This version of luna-quantum might be problematic. Click here for more details.
- luna_quantum-0.0.16.dist-info/LICENSE +201 -0
- luna_quantum-0.0.16.dist-info/METADATA +46 -0
- luna_quantum-0.0.16.dist-info/RECORD +160 -0
- luna_quantum-0.0.16.dist-info/WHEEL +4 -0
- luna_sdk/__init__.py +2 -0
- luna_sdk/constants.py +1 -0
- luna_sdk/controllers/__init__.py +2 -0
- luna_sdk/controllers/custom_login_client.py +61 -0
- luna_sdk/controllers/luna_platform_client.py +62 -0
- luna_sdk/controllers/luna_q.py +36 -0
- luna_sdk/controllers/luna_solve.py +49 -0
- luna_sdk/controllers/luna_transform.py +41 -0
- luna_sdk/error/__init__.py +0 -0
- luna_sdk/error/http_error_utils.py +100 -0
- luna_sdk/exceptions/__init__.py +1 -0
- luna_sdk/exceptions/encryption_exception.py +6 -0
- luna_sdk/exceptions/luna_exception.py +7 -0
- luna_sdk/exceptions/luna_server_exception.py +18 -0
- luna_sdk/exceptions/timeout_exception.py +10 -0
- luna_sdk/exceptions/transformation.py +11 -0
- luna_sdk/interfaces/__init__.py +5 -0
- luna_sdk/interfaces/circuit_repo_i.py +62 -0
- luna_sdk/interfaces/clients/__init__.py +0 -0
- luna_sdk/interfaces/clients/client_i.py +10 -0
- luna_sdk/interfaces/clients/luna_q_i.py +39 -0
- luna_sdk/interfaces/clients/luna_solve_i.py +37 -0
- luna_sdk/interfaces/clients/luna_transform_i.py +33 -0
- luna_sdk/interfaces/cplex_repo_i.py +121 -0
- luna_sdk/interfaces/info_repo_i.py +40 -0
- luna_sdk/interfaces/lp_repo_i.py +106 -0
- luna_sdk/interfaces/optimization_repo_i.py +262 -0
- luna_sdk/interfaces/qpu_token_repo_i.py +151 -0
- luna_sdk/interfaces/repository_i.py +14 -0
- luna_sdk/interfaces/solutions_repo_i.py +219 -0
- luna_sdk/py.typed +0 -0
- luna_sdk/repositories/__init__.py +4 -0
- luna_sdk/repositories/circuit_repo.py +104 -0
- luna_sdk/repositories/cplex_repo.py +118 -0
- luna_sdk/repositories/info_repo.py +45 -0
- luna_sdk/repositories/lp_repo.py +105 -0
- luna_sdk/repositories/optimization_repo.py +358 -0
- luna_sdk/repositories/qpu_token_repo.py +226 -0
- luna_sdk/repositories/solutions_repo.py +347 -0
- luna_sdk/schemas/__init__.py +4 -0
- luna_sdk/schemas/circuit.py +43 -0
- luna_sdk/schemas/create/__init__.py +3 -0
- luna_sdk/schemas/create/circuit.py +29 -0
- luna_sdk/schemas/create/optimization.py +22 -0
- luna_sdk/schemas/create/qpu_token.py +26 -0
- luna_sdk/schemas/create/qubo.py +19 -0
- luna_sdk/schemas/create/solution.py +15 -0
- luna_sdk/schemas/enums/__init__.py +0 -0
- luna_sdk/schemas/enums/circuit.py +14 -0
- luna_sdk/schemas/enums/optimization.py +10 -0
- luna_sdk/schemas/enums/problem.py +48 -0
- luna_sdk/schemas/enums/qpu_token_type.py +6 -0
- luna_sdk/schemas/enums/solution.py +8 -0
- luna_sdk/schemas/enums/status.py +10 -0
- luna_sdk/schemas/enums/timeframe.py +11 -0
- luna_sdk/schemas/error_message.py +12 -0
- luna_sdk/schemas/optimization.py +75 -0
- luna_sdk/schemas/optimization_formats/__init__.py +0 -0
- luna_sdk/schemas/optimization_formats/bqm.py +34 -0
- luna_sdk/schemas/optimization_formats/cqm.py +127 -0
- luna_sdk/schemas/optimization_formats/lp.py +9 -0
- luna_sdk/schemas/optimization_formats/qm.py +30 -0
- luna_sdk/schemas/pretty_base.py +49 -0
- luna_sdk/schemas/qpu_token.py +60 -0
- luna_sdk/schemas/representation.py +19 -0
- luna_sdk/schemas/rest/__init__.py +0 -0
- luna_sdk/schemas/rest/qpu_token/__init__.py +0 -0
- luna_sdk/schemas/rest/qpu_token/token_provider.py +45 -0
- luna_sdk/schemas/solution.py +227 -0
- luna_sdk/schemas/solver_info.py +11 -0
- luna_sdk/schemas/solver_parameters/aws/__init__.py +1 -0
- luna_sdk/schemas/solver_parameters/aws/qaoa.py +24 -0
- luna_sdk/schemas/solver_parameters/dwave/__init__.py +72 -0
- luna_sdk/schemas/solver_parameters/dwave/base.py +409 -0
- luna_sdk/schemas/solver_parameters/dwave/dialectic_search.py +31 -0
- luna_sdk/schemas/solver_parameters/dwave/kerberos.py +71 -0
- luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_bqm.py +19 -0
- luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_cqm.py +22 -0
- luna_sdk/schemas/solver_parameters/dwave/parallel_tempering.py +30 -0
- luna_sdk/schemas/solver_parameters/dwave/parallel_tempering_qpu.py +37 -0
- luna_sdk/schemas/solver_parameters/dwave/population_annealing.py +25 -0
- luna_sdk/schemas/solver_parameters/dwave/population_annealing_qpu.py +35 -0
- luna_sdk/schemas/solver_parameters/dwave/qaga.py +56 -0
- luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_qpu.py +19 -0
- luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_simulated_annealing.py +22 -0
- luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_tabu_search.py +21 -0
- luna_sdk/schemas/solver_parameters/dwave/quantum_annealing.py +20 -0
- luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_quantum_annealing.py +82 -0
- luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_simulated_annealing.py +89 -0
- luna_sdk/schemas/solver_parameters/dwave/saga.py +61 -0
- luna_sdk/schemas/solver_parameters/dwave/simulated_annealing.py +74 -0
- luna_sdk/schemas/solver_parameters/dwave/tabu_search.py +72 -0
- luna_sdk/schemas/solver_parameters/fujitsu/__init__.py +20 -0
- luna_sdk/schemas/solver_parameters/fujitsu/base.py +47 -0
- luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_cpu.py +129 -0
- luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_v2.py +149 -0
- luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_v3.py +150 -0
- luna_sdk/schemas/solver_parameters/fujitsu/partial_config.py +177 -0
- luna_sdk/schemas/solver_parameters/ibm/__init__.py +4 -0
- luna_sdk/schemas/solver_parameters/ibm/qaoa.py +64 -0
- luna_sdk/schemas/solver_parameters/ibm/standard_parameters.py +27 -0
- luna_sdk/schemas/solver_parameters/ibm/vqe.py +49 -0
- luna_sdk/schemas/solver_parameters/qctrl/__init__.py +1 -0
- luna_sdk/schemas/solver_parameters/qctrl/qaoa.py +47 -0
- luna_sdk/schemas/transformations/__init__.py +2 -0
- luna_sdk/schemas/transformations/bqm.py +33 -0
- luna_sdk/schemas/transformations/matrix.py +12 -0
- luna_sdk/schemas/use_cases/__init__.py +54 -0
- luna_sdk/schemas/use_cases/arbitrage_edge_based.py +49 -0
- luna_sdk/schemas/use_cases/arbitrage_node_based.py +54 -0
- luna_sdk/schemas/use_cases/base.py +5 -0
- luna_sdk/schemas/use_cases/binary_integer_linear_programming.py +53 -0
- luna_sdk/schemas/use_cases/binary_paint_shop_problem.py +36 -0
- luna_sdk/schemas/use_cases/credit_scoring_feature_selection.py +39 -0
- luna_sdk/schemas/use_cases/dynamic_portfolio_optimization.py +63 -0
- luna_sdk/schemas/use_cases/exact_cover.py +50 -0
- luna_sdk/schemas/use_cases/flight_gate_assignment.py +78 -0
- luna_sdk/schemas/use_cases/graph_coloring.py +41 -0
- luna_sdk/schemas/use_cases/graph_isomorphism.py +53 -0
- luna_sdk/schemas/use_cases/graph_partitioning.py +45 -0
- luna_sdk/schemas/use_cases/hamiltonian_cycle.py +48 -0
- luna_sdk/schemas/use_cases/induced_subgraph_isomorphism.py +49 -0
- luna_sdk/schemas/use_cases/job_shop_scheduling.py +43 -0
- luna_sdk/schemas/use_cases/k_medoids_clustering.py +48 -0
- luna_sdk/schemas/use_cases/knapsack_integer_weights.py +55 -0
- luna_sdk/schemas/use_cases/linear_regression.py +59 -0
- luna_sdk/schemas/use_cases/lmwcs.py +80 -0
- luna_sdk/schemas/use_cases/longest_path.py +49 -0
- luna_sdk/schemas/use_cases/market_graph_clustering.py +60 -0
- luna_sdk/schemas/use_cases/max2sat.py +51 -0
- luna_sdk/schemas/use_cases/max3sat.py +52 -0
- luna_sdk/schemas/use_cases/max_clique.py +59 -0
- luna_sdk/schemas/use_cases/max_cut.py +47 -0
- luna_sdk/schemas/use_cases/max_independent_set.py +36 -0
- luna_sdk/schemas/use_cases/minimal_maximal_matching.py +53 -0
- luna_sdk/schemas/use_cases/minimal_spanning_tree.py +87 -0
- luna_sdk/schemas/use_cases/minimum_vertex_cover.py +44 -0
- luna_sdk/schemas/use_cases/number_partitioning.py +31 -0
- luna_sdk/schemas/use_cases/portfolio_optimization.py +45 -0
- luna_sdk/schemas/use_cases/portfolio_optimization_ib_tv.py +62 -0
- luna_sdk/schemas/use_cases/quadratic_assignment.py +48 -0
- luna_sdk/schemas/use_cases/quadratic_knapsack.py +47 -0
- luna_sdk/schemas/use_cases/satellite_scheduling.py +72 -0
- luna_sdk/schemas/use_cases/sensor_placement.py +57 -0
- luna_sdk/schemas/use_cases/set_cover.py +55 -0
- luna_sdk/schemas/use_cases/set_packing.py +53 -0
- luna_sdk/schemas/use_cases/set_partitioning.py +51 -0
- luna_sdk/schemas/use_cases/subgraph_isomorphism.py +56 -0
- luna_sdk/schemas/use_cases/subset_sum.py +36 -0
- luna_sdk/schemas/use_cases/support_vector_machine.py +63 -0
- luna_sdk/schemas/use_cases/traffic_flow.py +34 -0
- luna_sdk/schemas/use_cases/travelling_salesman_problem.py +52 -0
- luna_sdk/schemas/use_cases/type_aliases.py +11 -0
- luna_sdk/schemas/use_cases/weighted_max_cut.py +36 -0
- luna_sdk/utils/__init__.py +0 -0
- luna_sdk/utils/qpu_tokens.py +52 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from time import sleep
|
|
4
|
+
from typing import Dict, List, Optional, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from luna_sdk.exceptions.encryption_exception import EncryptionNotSetException
|
|
9
|
+
from luna_sdk.interfaces.solutions_repo_i import ISolutionsRepo
|
|
10
|
+
from luna_sdk.schemas.create.solution import SolutionIn
|
|
11
|
+
from luna_sdk.schemas.enums.solution import SenseEnum
|
|
12
|
+
from luna_sdk.schemas.enums.status import StatusEnum
|
|
13
|
+
from luna_sdk.schemas.enums.timeframe import TimeframeEnum
|
|
14
|
+
from luna_sdk.schemas.qpu_token import TokenProvider
|
|
15
|
+
from luna_sdk.schemas.rest.qpu_token.token_provider import RestAPITokenProvider
|
|
16
|
+
from luna_sdk.schemas.solution import (
|
|
17
|
+
Result,
|
|
18
|
+
Solution,
|
|
19
|
+
UseCaseRepresentation,
|
|
20
|
+
UseCaseResult,
|
|
21
|
+
)
|
|
22
|
+
from luna_sdk.utils.qpu_tokens import extract_qpu_tokens_from_env
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SolutionsRepo(ISolutionsRepo):
|
|
26
|
+
_endpoint = "/solutions"
|
|
27
|
+
|
|
28
|
+
def get(
|
|
29
|
+
self,
|
|
30
|
+
solution_id: str,
|
|
31
|
+
) -> Solution:
|
|
32
|
+
"""
|
|
33
|
+
Retrieve one solution by id.
|
|
34
|
+
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
solution_id: str
|
|
38
|
+
Id of the solution that should be retrieved
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
Solution
|
|
43
|
+
Solution instance
|
|
44
|
+
"""
|
|
45
|
+
response = self._client.get(
|
|
46
|
+
f"{self._endpoint}/{solution_id}",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
response.raise_for_status()
|
|
50
|
+
|
|
51
|
+
return Solution.model_validate_json(response.text)
|
|
52
|
+
|
|
53
|
+
def get_all(
|
|
54
|
+
self,
|
|
55
|
+
timeframe: Optional[TimeframeEnum] = None,
|
|
56
|
+
limit: int = 50,
|
|
57
|
+
offset: int = 0,
|
|
58
|
+
optimization_id: Optional[str] = None,
|
|
59
|
+
) -> List[Solution]:
|
|
60
|
+
"""
|
|
61
|
+
Get list of available optimizations.
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
timeframe: Optional[TimeframeEnum]
|
|
66
|
+
Only return Solutions created within a specified timeframe. Default None.
|
|
67
|
+
limit:
|
|
68
|
+
Limit the number of Optimizations to be returned. Default value 10.
|
|
69
|
+
offset:
|
|
70
|
+
Offset the list of solutions by this amount. Default value 0.
|
|
71
|
+
optimization_id: Optional[str]
|
|
72
|
+
Show solutions for only this optimization id. Default None.
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
List[SolutionOut]
|
|
77
|
+
List of SolutionOut instances.
|
|
78
|
+
"""
|
|
79
|
+
params = {}
|
|
80
|
+
if timeframe and timeframe != TimeframeEnum.all_time: # no value == all_time
|
|
81
|
+
params["timeframe"] = timeframe.value
|
|
82
|
+
|
|
83
|
+
if limit < 1:
|
|
84
|
+
# set the minimum limit to 1
|
|
85
|
+
limit = 1
|
|
86
|
+
|
|
87
|
+
if optimization_id is not None:
|
|
88
|
+
params["optimization_id"] = str(optimization_id)
|
|
89
|
+
|
|
90
|
+
params["limit"] = str(limit)
|
|
91
|
+
params["offset"] = str(offset)
|
|
92
|
+
response = self._client.get(
|
|
93
|
+
self._endpoint,
|
|
94
|
+
params=params,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
response.raise_for_status()
|
|
98
|
+
|
|
99
|
+
return [Solution.model_validate(i) for i in response.json()]
|
|
100
|
+
|
|
101
|
+
def delete(self, solution_id: str) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Delete one optimization by id.
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
solution_id: str
|
|
108
|
+
Id of the optimization that should be deleted
|
|
109
|
+
|
|
110
|
+
Returns
|
|
111
|
+
-------
|
|
112
|
+
"""
|
|
113
|
+
self._client.delete(
|
|
114
|
+
f"{self._endpoint}/{solution_id}",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
def create(
|
|
118
|
+
self,
|
|
119
|
+
optimization_id: str,
|
|
120
|
+
solver_name: str,
|
|
121
|
+
provider: str,
|
|
122
|
+
qpu_tokens: Optional[TokenProvider] = None,
|
|
123
|
+
solver_parameters: Optional[Union[Dict, BaseModel]] = None,
|
|
124
|
+
encryption_key: Optional[str] = None,
|
|
125
|
+
name: Optional[str] = None,
|
|
126
|
+
) -> Solution:
|
|
127
|
+
"""
|
|
128
|
+
Create a solution for an optimization
|
|
129
|
+
|
|
130
|
+
Parameters
|
|
131
|
+
----------
|
|
132
|
+
optimization_id: str
|
|
133
|
+
The id of the optimization for which solution should be created
|
|
134
|
+
solver_name: str
|
|
135
|
+
The name of the solver to use.
|
|
136
|
+
provider: str
|
|
137
|
+
The name of the QPU provider to use.
|
|
138
|
+
qpu_tokens: Optional[TokenProvider]
|
|
139
|
+
The tokens to be used for the QPU.
|
|
140
|
+
solver_parameters: Optional[Dict]
|
|
141
|
+
Parameters to be passed to the solver.
|
|
142
|
+
encryption_key: Optional[str]
|
|
143
|
+
Encryption key to be used for encryption of QPU tokens.
|
|
144
|
+
name: Optional[str]
|
|
145
|
+
Default: None, The name of the solution to create.
|
|
146
|
+
|
|
147
|
+
Returns
|
|
148
|
+
-------
|
|
149
|
+
SolutionOut
|
|
150
|
+
Returns the location where the solution can be found once solving is complete.
|
|
151
|
+
"""
|
|
152
|
+
if solver_parameters is None:
|
|
153
|
+
solver_parameters = {}
|
|
154
|
+
if qpu_tokens is not None:
|
|
155
|
+
rest_qpu_tokens = RestAPITokenProvider.from_sdk_token_provider(qpu_tokens)
|
|
156
|
+
else:
|
|
157
|
+
rest_qpu_tokens = None
|
|
158
|
+
# try to retrieve qpu tokens from env variables
|
|
159
|
+
if rest_qpu_tokens is None:
|
|
160
|
+
rest_qpu_tokens = extract_qpu_tokens_from_env()
|
|
161
|
+
|
|
162
|
+
encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
|
|
163
|
+
if encryption_key is None:
|
|
164
|
+
raise EncryptionNotSetException
|
|
165
|
+
solution_in = SolutionIn(
|
|
166
|
+
optimization=optimization_id,
|
|
167
|
+
solver_name=solver_name,
|
|
168
|
+
provider=provider,
|
|
169
|
+
parameters=(
|
|
170
|
+
solver_parameters.model_dump()
|
|
171
|
+
if isinstance(solver_parameters, BaseModel)
|
|
172
|
+
else solver_parameters
|
|
173
|
+
),
|
|
174
|
+
qpu_tokens=rest_qpu_tokens,
|
|
175
|
+
encryption_key=encryption_key,
|
|
176
|
+
name=name,
|
|
177
|
+
)
|
|
178
|
+
response = self._client.post(
|
|
179
|
+
self._endpoint, content=solution_in.model_dump_json()
|
|
180
|
+
)
|
|
181
|
+
response.raise_for_status()
|
|
182
|
+
|
|
183
|
+
return Solution.model_validate_json(response.text)
|
|
184
|
+
|
|
185
|
+
def create_blocking(
|
|
186
|
+
self,
|
|
187
|
+
optimization_id: str,
|
|
188
|
+
solver_name: str,
|
|
189
|
+
provider: str,
|
|
190
|
+
qpu_tokens: Optional[TokenProvider] = None,
|
|
191
|
+
solver_parameters: Optional[Union[Dict, BaseModel]] = None,
|
|
192
|
+
sleep_time_max: float = 60.0,
|
|
193
|
+
sleep_time_increment: float = 5.0,
|
|
194
|
+
sleep_time_initial: float = 5.0,
|
|
195
|
+
encryption_key: Optional[str] = None,
|
|
196
|
+
name: Optional[str] = None,
|
|
197
|
+
) -> Solution:
|
|
198
|
+
"""
|
|
199
|
+
Create a solution for optimization. This method will block your code until the solution is ready.
|
|
200
|
+
Depending on the problem size, this can take a long time.
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
optimization_id: str
|
|
205
|
+
The id of the optimization for which solution should be created
|
|
206
|
+
solver_name: str
|
|
207
|
+
The name of the solver to use.
|
|
208
|
+
provider: str
|
|
209
|
+
The name of the provider to use.
|
|
210
|
+
|
|
211
|
+
qpu_tokens: Optional[TokenProvider] = None
|
|
212
|
+
The tokens to be used for the QPU.
|
|
213
|
+
solver_parameters: Optional[Dict]
|
|
214
|
+
Parameters to be passed to the solver.
|
|
215
|
+
|
|
216
|
+
sleep_time_max: float
|
|
217
|
+
Maximum time to sleep between requests.
|
|
218
|
+
sleep_time_increment: float
|
|
219
|
+
Increment of sleep time between requests. Initial sleep time will be
|
|
220
|
+
sleep_time_initial: float
|
|
221
|
+
Initial sleep time.
|
|
222
|
+
encryption_key: Optional[str]
|
|
223
|
+
Encryption key to be used for encryption of QPU tokens.
|
|
224
|
+
name: Optional[str]
|
|
225
|
+
Default: None, The name of the solution to create.
|
|
226
|
+
Returns
|
|
227
|
+
-------
|
|
228
|
+
SolutionOut
|
|
229
|
+
Returns the location where the solution can be found once solving is complete.
|
|
230
|
+
"""
|
|
231
|
+
# First create the solution
|
|
232
|
+
|
|
233
|
+
params: Optional[Union[Dict, BaseModel]] = None
|
|
234
|
+
if solver_parameters is not None:
|
|
235
|
+
params = solver_parameters
|
|
236
|
+
if isinstance(solver_parameters, BaseModel):
|
|
237
|
+
params = solver_parameters.dict()
|
|
238
|
+
|
|
239
|
+
solution: Solution = self.create(
|
|
240
|
+
optimization_id=optimization_id,
|
|
241
|
+
solver_name=solver_name,
|
|
242
|
+
provider=provider,
|
|
243
|
+
solver_parameters=params,
|
|
244
|
+
qpu_tokens=qpu_tokens,
|
|
245
|
+
encryption_key=encryption_key,
|
|
246
|
+
name=name,
|
|
247
|
+
)
|
|
248
|
+
# times are in sec
|
|
249
|
+
|
|
250
|
+
cur_sleep_time: float
|
|
251
|
+
|
|
252
|
+
if sleep_time_initial > 0.0:
|
|
253
|
+
cur_sleep_time = sleep_time_initial
|
|
254
|
+
else:
|
|
255
|
+
cur_sleep_time = 5.0
|
|
256
|
+
logging.warning(
|
|
257
|
+
f"Invalid sleep_time_initial: {sleep_time_initial}, setting it to default value {cur_sleep_time}"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
while (
|
|
261
|
+
solution.status == StatusEnum.REQUESTED
|
|
262
|
+
or solution.status == StatusEnum.IN_PROGRESS
|
|
263
|
+
):
|
|
264
|
+
logging.info(
|
|
265
|
+
f"Waiting for solution {solution.id} to complete, "
|
|
266
|
+
f"current status: {solution.status}"
|
|
267
|
+
f", sleeping for {cur_sleep_time} seconds."
|
|
268
|
+
)
|
|
269
|
+
sleep(cur_sleep_time)
|
|
270
|
+
cur_sleep_time += sleep_time_increment
|
|
271
|
+
if cur_sleep_time > sleep_time_max:
|
|
272
|
+
cur_sleep_time = sleep_time_max
|
|
273
|
+
|
|
274
|
+
solution = self.get(solution_id=solution.id)
|
|
275
|
+
|
|
276
|
+
return solution
|
|
277
|
+
|
|
278
|
+
def get_use_case_representation(self, solution_id: str) -> UseCaseRepresentation:
|
|
279
|
+
"""
|
|
280
|
+
Get the use-case-specific representation of a solution.
|
|
281
|
+
|
|
282
|
+
Parameters
|
|
283
|
+
----------
|
|
284
|
+
solution_id: str
|
|
285
|
+
Id of the solution that should be retrieved
|
|
286
|
+
|
|
287
|
+
Returns
|
|
288
|
+
-------
|
|
289
|
+
UseCaseRepresentation
|
|
290
|
+
The use-case-specific representation
|
|
291
|
+
"""
|
|
292
|
+
response = self._client.get(f"{self._endpoint}/{solution_id}/representation")
|
|
293
|
+
response.raise_for_status()
|
|
294
|
+
return UseCaseRepresentation.model_validate_json(response.text)
|
|
295
|
+
|
|
296
|
+
def get_best_result(self, solution: Solution) -> Optional[Result]:
|
|
297
|
+
"""
|
|
298
|
+
Retrieves the best result from a solution.
|
|
299
|
+
|
|
300
|
+
Parameters
|
|
301
|
+
----------
|
|
302
|
+
solution : Solution
|
|
303
|
+
The solution received via `solutions.get` or `solutions.get_all`.
|
|
304
|
+
|
|
305
|
+
Returns
|
|
306
|
+
-------
|
|
307
|
+
Result | None
|
|
308
|
+
The best result of the solution. If there are several best solutions with
|
|
309
|
+
the same objective value, return only the first. If the solution results are
|
|
310
|
+
not (yet) available or no the solution sense is `None`, return `None`.
|
|
311
|
+
"""
|
|
312
|
+
if solution.results is None or solution.sense is None:
|
|
313
|
+
return None
|
|
314
|
+
|
|
315
|
+
agg = min if solution.sense == SenseEnum.MIN else max
|
|
316
|
+
best_result = agg(solution.results, key=lambda x: x.obj_value)
|
|
317
|
+
|
|
318
|
+
return best_result
|
|
319
|
+
|
|
320
|
+
def get_best_use_case_result(
|
|
321
|
+
self, use_case_representation: UseCaseRepresentation
|
|
322
|
+
) -> Optional[UseCaseResult]:
|
|
323
|
+
"""
|
|
324
|
+
Retrieves the best result from a solution's use case representation.
|
|
325
|
+
|
|
326
|
+
Parameters
|
|
327
|
+
----------
|
|
328
|
+
use_case_representation : UseCaseRepresentation
|
|
329
|
+
A solution's use case representation.
|
|
330
|
+
|
|
331
|
+
Returns
|
|
332
|
+
-------
|
|
333
|
+
UseCaseResult | None
|
|
334
|
+
The best result of the solution. If there are several best solutions with
|
|
335
|
+
the same objective value, return only the first. If the solution results are
|
|
336
|
+
not (yet) available or no the solution sense is `None`, return `None`.
|
|
337
|
+
"""
|
|
338
|
+
if (
|
|
339
|
+
use_case_representation.results is None
|
|
340
|
+
or use_case_representation.sense is None
|
|
341
|
+
):
|
|
342
|
+
return None
|
|
343
|
+
|
|
344
|
+
agg = min if use_case_representation.sense == SenseEnum.MIN else max
|
|
345
|
+
best_result = agg(use_case_representation.results, key=lambda x: x.obj_value)
|
|
346
|
+
|
|
347
|
+
return best_result
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Any, Dict, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from luna_sdk.schemas.enums.circuit import CircuitProviderEnum, CircuitStatusEnum
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CircuitJob(BaseModel):
|
|
9
|
+
"""
|
|
10
|
+
Object responsible of retrieving a circuit solution.
|
|
11
|
+
|
|
12
|
+
Attributes
|
|
13
|
+
----------
|
|
14
|
+
id: str
|
|
15
|
+
Id of the circuit job.
|
|
16
|
+
provider: CircuitProviderEnum
|
|
17
|
+
The provider used to solve this circuit.
|
|
18
|
+
params: Dict[str, Any]
|
|
19
|
+
Additional parameters that were used to create the circuit.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
id: str
|
|
23
|
+
provider: CircuitProviderEnum
|
|
24
|
+
params: Optional[Dict[str, Any]] = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CircuitResult(BaseModel):
|
|
28
|
+
"""
|
|
29
|
+
The result of solving the circuit
|
|
30
|
+
|
|
31
|
+
Attributes
|
|
32
|
+
----------
|
|
33
|
+
result: Optional[Dict[str, Any]]
|
|
34
|
+
The result if the job succeeded. Otherwise None
|
|
35
|
+
error: Optional[str]
|
|
36
|
+
The error message if the job failed. Otherwise None
|
|
37
|
+
status: CircuitStatusEnum
|
|
38
|
+
The job status.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
status: CircuitStatusEnum
|
|
42
|
+
result: Optional[Dict[str, Any]] = None
|
|
43
|
+
error_message: Optional[str] = None
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from typing import Any, Dict, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from luna_sdk.schemas.enums.circuit import CircuitProviderEnum
|
|
6
|
+
from luna_sdk.schemas.rest.qpu_token.token_provider import RestAPITokenProvider
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CircuitIn(BaseModel):
|
|
10
|
+
"""
|
|
11
|
+
Pydantic model for creation of circuits.
|
|
12
|
+
|
|
13
|
+
Attributes
|
|
14
|
+
----------
|
|
15
|
+
provider: str
|
|
16
|
+
The provider for circuit solving
|
|
17
|
+
provider: ProviderEnum
|
|
18
|
+
The QASM circuit
|
|
19
|
+
params: Dict[str, Any]
|
|
20
|
+
Additional parameters
|
|
21
|
+
encryption_key: str
|
|
22
|
+
Encryption key to be used for encryption of QPU tokens.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
provider: CircuitProviderEnum
|
|
26
|
+
circuit: str
|
|
27
|
+
params: Dict[str, Any] = {}
|
|
28
|
+
qpu_tokens: Optional[RestAPITokenProvider] = None
|
|
29
|
+
encryption_key: str
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from typing import Any, Dict, Generic, Optional, TypeVar
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from luna_sdk.schemas import UseCase
|
|
6
|
+
|
|
7
|
+
# This works but is kind of ugly.
|
|
8
|
+
# In the future, we should find another solution for "dumping" a child of UseCase
|
|
9
|
+
# with the name and params.
|
|
10
|
+
# OptimizationUseCaseIn can still be created like this:
|
|
11
|
+
# opt = OptimizationUseCaseIn(name=name, use_case=use_case)
|
|
12
|
+
# Somehow this tricks pydantic into accepting the child of UseCase and adding
|
|
13
|
+
# it to the model_dump_json. Without the Generic[UseCase] only the name will be
|
|
14
|
+
# added to the model_dump_json
|
|
15
|
+
|
|
16
|
+
_UseCase = TypeVar("_UseCase", bound=UseCase)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class OptimizationUseCaseIn(BaseModel, Generic[_UseCase]):
|
|
20
|
+
name: str
|
|
21
|
+
use_case: _UseCase
|
|
22
|
+
params: Optional[Dict[str, Any]]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from pydantic import BaseModel, Extra
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class QpuTokenIn(BaseModel):
|
|
5
|
+
"""
|
|
6
|
+
Pydantic model for creation QPU token.
|
|
7
|
+
|
|
8
|
+
Attributes
|
|
9
|
+
----------
|
|
10
|
+
name: str
|
|
11
|
+
Name of the QPU token
|
|
12
|
+
provider: ProviderEnum
|
|
13
|
+
Name of provider
|
|
14
|
+
token: str
|
|
15
|
+
Token
|
|
16
|
+
encryption_key: str
|
|
17
|
+
Encryption key to be used for encryption of QPU tokens.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
name: str
|
|
21
|
+
provider: str
|
|
22
|
+
token: str
|
|
23
|
+
encryption_key: str
|
|
24
|
+
|
|
25
|
+
class Config:
|
|
26
|
+
extra = Extra.forbid
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class QUBOIn(BaseModel):
|
|
7
|
+
"""
|
|
8
|
+
Pydantic model for QUBO
|
|
9
|
+
|
|
10
|
+
Attributes
|
|
11
|
+
----------
|
|
12
|
+
name: str
|
|
13
|
+
Name of the Model
|
|
14
|
+
matrix: List[List[float]]
|
|
15
|
+
QUBO matrix
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
name: str
|
|
19
|
+
matrix: List[List[float]]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from typing import Dict, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from luna_sdk.schemas.rest.qpu_token.token_provider import RestAPITokenProvider
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SolutionIn(BaseModel):
|
|
9
|
+
optimization: str # id of the optimization
|
|
10
|
+
solver_name: str
|
|
11
|
+
provider: str
|
|
12
|
+
parameters: Dict
|
|
13
|
+
qpu_tokens: Optional[RestAPITokenProvider] = None
|
|
14
|
+
encryption_key: str
|
|
15
|
+
name: Optional[str] = None
|
|
File without changes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class UseCaseEnum(str, Enum):
|
|
5
|
+
AEB = "AEB"
|
|
6
|
+
ANB = "ANB"
|
|
7
|
+
BIP = "BIP"
|
|
8
|
+
BPSP = "BPSP"
|
|
9
|
+
CSFS = "CSFS"
|
|
10
|
+
DPO = "DPO"
|
|
11
|
+
EC = "EC"
|
|
12
|
+
FGO = "FGO"
|
|
13
|
+
GC = "GC"
|
|
14
|
+
GI = "GI"
|
|
15
|
+
GP = "GP"
|
|
16
|
+
HC = "HC"
|
|
17
|
+
ISGI = "ISGI"
|
|
18
|
+
JSS = "JSS"
|
|
19
|
+
KMC = "KMC"
|
|
20
|
+
KIW = "KIW"
|
|
21
|
+
LR = "LR"
|
|
22
|
+
LMWCS = "LMWCS"
|
|
23
|
+
LP = "LP"
|
|
24
|
+
MGC = "MGC"
|
|
25
|
+
M2SAT = "M2SAT"
|
|
26
|
+
M3SAT = "M3SAT"
|
|
27
|
+
MCQ = "MCQ"
|
|
28
|
+
MC = "MC"
|
|
29
|
+
MIS = "MIS"
|
|
30
|
+
MMM = "MMM"
|
|
31
|
+
MST = "MST"
|
|
32
|
+
MVC = "MVC"
|
|
33
|
+
NP = "NP"
|
|
34
|
+
PO = "PO"
|
|
35
|
+
POIBTV = "POIBTV"
|
|
36
|
+
QA = "QA"
|
|
37
|
+
QK = "QK"
|
|
38
|
+
SSC = "SSC"
|
|
39
|
+
SPL = "SPL"
|
|
40
|
+
SC = "SC"
|
|
41
|
+
SP = "SP"
|
|
42
|
+
SPP = "SPP"
|
|
43
|
+
SGI = "SGI"
|
|
44
|
+
SSP = "SSP"
|
|
45
|
+
SVM = "SVM"
|
|
46
|
+
TFO = "TFO"
|
|
47
|
+
TSP = "TSP"
|
|
48
|
+
WMC = "WMC"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ErrorMessage(BaseModel):
|
|
5
|
+
"""
|
|
6
|
+
Error message model. If an error occurs, this model is used to return error messages
|
|
7
|
+
to the client. It contains the internal code and the message that describes
|
|
8
|
+
the error.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
internal_code: str
|
|
12
|
+
message: str
|