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,358 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from io import BufferedReader
|
|
3
|
+
from typing import Any, Dict, List, Optional, Type
|
|
4
|
+
|
|
5
|
+
from dimod import BinaryQuadraticModel, ConstrainedQuadraticModel
|
|
6
|
+
from httpx import Response
|
|
7
|
+
|
|
8
|
+
from luna_sdk.interfaces.optimization_repo_i import IOptimizationRepo
|
|
9
|
+
from luna_sdk.schemas import UseCase
|
|
10
|
+
from luna_sdk.schemas.create import QUBOIn
|
|
11
|
+
from luna_sdk.schemas.create.optimization import OptimizationUseCaseIn
|
|
12
|
+
from luna_sdk.schemas.enums.optimization import InputType
|
|
13
|
+
from luna_sdk.schemas.enums.timeframe import TimeframeEnum
|
|
14
|
+
from luna_sdk.schemas.optimization import (
|
|
15
|
+
Optimization,
|
|
16
|
+
OptimizationBQM,
|
|
17
|
+
OptimizationCQM,
|
|
18
|
+
OptimizationLP,
|
|
19
|
+
OptimizationUseCase,
|
|
20
|
+
)
|
|
21
|
+
from luna_sdk.schemas.optimization_formats.bqm import BQMSchema
|
|
22
|
+
from luna_sdk.schemas.optimization_formats.cqm import CQMSchema
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class OptimizationRepo(IOptimizationRepo):
|
|
26
|
+
@property
|
|
27
|
+
def _endpoint(self) -> str:
|
|
28
|
+
return "/optimizations"
|
|
29
|
+
|
|
30
|
+
def get_all(
|
|
31
|
+
self,
|
|
32
|
+
timeframe: Optional[TimeframeEnum] = None,
|
|
33
|
+
input_type: Optional[InputType] = None,
|
|
34
|
+
limit: int = 50,
|
|
35
|
+
offset: int = 0,
|
|
36
|
+
) -> List[Optimization]:
|
|
37
|
+
"""
|
|
38
|
+
Get a list of all available Models.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
timeframe: Optional[TimeframeEnum]
|
|
43
|
+
Only return QUBOs created within a specified timeframe. Default None.
|
|
44
|
+
input_type: Optional[InputType]
|
|
45
|
+
Only return optimizations of a specified input type. Default None.
|
|
46
|
+
limit: int
|
|
47
|
+
Limit the number of Optimizations to be returned. Default value 50.
|
|
48
|
+
offset: int
|
|
49
|
+
Offset the list of optimizations by this amount. Default value 0.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
List[Model]
|
|
54
|
+
List of Model instances.
|
|
55
|
+
"""
|
|
56
|
+
params = {}
|
|
57
|
+
if timeframe and timeframe != TimeframeEnum.all_time: # no value == all_time
|
|
58
|
+
params["timeframe"] = timeframe.value
|
|
59
|
+
|
|
60
|
+
if input_type:
|
|
61
|
+
params["input_type"] = input_type.value
|
|
62
|
+
|
|
63
|
+
if limit < 1:
|
|
64
|
+
# set the minimum limit to 1
|
|
65
|
+
limit = 1
|
|
66
|
+
|
|
67
|
+
params["limit"] = str(limit)
|
|
68
|
+
params["offset"] = str(offset)
|
|
69
|
+
response: Response = self._client.get(self._endpoint, params=params)
|
|
70
|
+
response.raise_for_status()
|
|
71
|
+
return [Optimization.model_validate(item) for item in response.json()]
|
|
72
|
+
|
|
73
|
+
def get(self, optimization_id: str) -> Optimization:
|
|
74
|
+
response: Response = self._client.get(f"{self._endpoint}/{optimization_id}")
|
|
75
|
+
response.raise_for_status()
|
|
76
|
+
response_data = response.json()
|
|
77
|
+
|
|
78
|
+
model: Type[Optimization] = Optimization
|
|
79
|
+
|
|
80
|
+
optimization_data = response_data.pop("optimization_data", None)
|
|
81
|
+
if optimization_data:
|
|
82
|
+
input_type = response_data["input_type"]
|
|
83
|
+
|
|
84
|
+
if input_type in (InputType.bqm_spin, InputType.bqm_binary):
|
|
85
|
+
model = OptimizationBQM
|
|
86
|
+
elif input_type == InputType.cqm:
|
|
87
|
+
model = OptimizationCQM
|
|
88
|
+
elif input_type == InputType.lp:
|
|
89
|
+
model = OptimizationLP
|
|
90
|
+
elif input_type == InputType.qubo:
|
|
91
|
+
if response_data.get("use_case_name"):
|
|
92
|
+
model = OptimizationUseCase
|
|
93
|
+
else:
|
|
94
|
+
model = OptimizationBQM
|
|
95
|
+
else:
|
|
96
|
+
model = OptimizationBQM
|
|
97
|
+
|
|
98
|
+
response_data.update(optimization_data)
|
|
99
|
+
|
|
100
|
+
return model.validate(response_data)
|
|
101
|
+
|
|
102
|
+
def create_from_qubo(
|
|
103
|
+
self,
|
|
104
|
+
name: str,
|
|
105
|
+
matrix: List[List[float]],
|
|
106
|
+
timeout: Optional[float] = 10800.0,
|
|
107
|
+
) -> Optimization:
|
|
108
|
+
"""
|
|
109
|
+
Create an optimization from a QUBO matrix.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
name: str
|
|
114
|
+
Name of the optimization to be created.
|
|
115
|
+
matrix: List[List[float]]
|
|
116
|
+
QUBO matrix.
|
|
117
|
+
timeout: Optional[float]
|
|
118
|
+
Default = 10800. Timeout for the api request. If set to None,
|
|
119
|
+
there won't be any timeout. Increase or disable the timeout if you face
|
|
120
|
+
issues uploading big QUBO matrices.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
Optimization:
|
|
125
|
+
Created optimization.
|
|
126
|
+
"""
|
|
127
|
+
data_in: Dict[str, Any] = QUBOIn(name=name, matrix=matrix).model_dump()
|
|
128
|
+
|
|
129
|
+
response: Response = self._client.post(
|
|
130
|
+
f"{self._endpoint}/qubo",
|
|
131
|
+
json=data_in,
|
|
132
|
+
timeout=timeout,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
response.raise_for_status()
|
|
136
|
+
|
|
137
|
+
return Optimization.model_validate_json(response.text)
|
|
138
|
+
|
|
139
|
+
def create_from_use_case(
|
|
140
|
+
self,
|
|
141
|
+
name: str,
|
|
142
|
+
use_case: UseCase,
|
|
143
|
+
timeout: Optional[float] = 10800.0,
|
|
144
|
+
) -> Optimization:
|
|
145
|
+
"""
|
|
146
|
+
Create an optimization from a use case.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
name: str
|
|
151
|
+
Name of the optimization to be created.
|
|
152
|
+
use_case: UseCase
|
|
153
|
+
Use case.
|
|
154
|
+
timeout: Optional[float]
|
|
155
|
+
Default = 10800.0. Timeout for the api request. If set to None,
|
|
156
|
+
there won't be any timeout. Increase or disable the timeout if you face
|
|
157
|
+
issues uploading big Problems.
|
|
158
|
+
|
|
159
|
+
Returns
|
|
160
|
+
-------
|
|
161
|
+
Optimization:
|
|
162
|
+
Created optimization.
|
|
163
|
+
"""
|
|
164
|
+
optimization_in = OptimizationUseCaseIn(
|
|
165
|
+
name=name, use_case=use_case, params=None
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
response: Response = self._client.post(
|
|
169
|
+
f"{self._endpoint}/use_case",
|
|
170
|
+
content=optimization_in.model_dump_json(),
|
|
171
|
+
timeout=timeout,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
response.raise_for_status()
|
|
175
|
+
|
|
176
|
+
return Optimization.model_validate_json(response.text)
|
|
177
|
+
|
|
178
|
+
def create_from_bqm(
|
|
179
|
+
self,
|
|
180
|
+
name: str,
|
|
181
|
+
bqm: BinaryQuadraticModel,
|
|
182
|
+
timeout: Optional[float] = 10800.0,
|
|
183
|
+
) -> Optimization:
|
|
184
|
+
"""
|
|
185
|
+
Create an optimization from BQM.
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
name: str
|
|
190
|
+
Name of the optimization to be created.
|
|
191
|
+
bqm: BinaryQuadraticModel
|
|
192
|
+
QUBO in dimod BQM format.
|
|
193
|
+
timeout: Optional[float]
|
|
194
|
+
|
|
195
|
+
Returns
|
|
196
|
+
-------
|
|
197
|
+
Optimization:
|
|
198
|
+
Created optimization.
|
|
199
|
+
"""
|
|
200
|
+
data_in = {"name": name, **BQMSchema.from_bqm(bqm).model_dump()}
|
|
201
|
+
|
|
202
|
+
response: Response = self._client.post(
|
|
203
|
+
f"{self._endpoint}/bqm",
|
|
204
|
+
json=data_in,
|
|
205
|
+
timeout=timeout,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
response.raise_for_status()
|
|
209
|
+
|
|
210
|
+
return Optimization.model_validate_json(response.text)
|
|
211
|
+
|
|
212
|
+
def create_from_cqm(
|
|
213
|
+
self,
|
|
214
|
+
name: str,
|
|
215
|
+
cqm: ConstrainedQuadraticModel,
|
|
216
|
+
timeout: Optional[float] = 10800.0,
|
|
217
|
+
) -> Optimization:
|
|
218
|
+
"""
|
|
219
|
+
Create an optimization from CQM.
|
|
220
|
+
|
|
221
|
+
Parameters
|
|
222
|
+
----------
|
|
223
|
+
name: str
|
|
224
|
+
Name of the optimization to be created.
|
|
225
|
+
cqm: ConstrainedQuadraticModel
|
|
226
|
+
in dimod CQM format.
|
|
227
|
+
timeout: Optional[float]
|
|
228
|
+
|
|
229
|
+
Returns
|
|
230
|
+
-------
|
|
231
|
+
Optimization:
|
|
232
|
+
Created optimization.
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
data_in = {"name": name, **CQMSchema.from_cqm(cqm).model_dump()}
|
|
236
|
+
|
|
237
|
+
response: Response = self._client.post(
|
|
238
|
+
f"{self._endpoint}/cqm",
|
|
239
|
+
json=data_in,
|
|
240
|
+
timeout=timeout,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
response.raise_for_status()
|
|
244
|
+
|
|
245
|
+
return Optimization.model_validate_json(response.text)
|
|
246
|
+
|
|
247
|
+
def create_from_lp_file(
|
|
248
|
+
self,
|
|
249
|
+
name: str,
|
|
250
|
+
lp_file: BufferedReader,
|
|
251
|
+
timeout: Optional[float] = 10800.0,
|
|
252
|
+
) -> Optimization:
|
|
253
|
+
"""
|
|
254
|
+
Create an optimization from LP file.
|
|
255
|
+
|
|
256
|
+
Parameters
|
|
257
|
+
----------
|
|
258
|
+
name: str
|
|
259
|
+
Name of the optimization to be created.
|
|
260
|
+
lp_file: buffer reader.
|
|
261
|
+
timeout: Optional[float]
|
|
262
|
+
Default = 10800. Timeout for the api request. If set to None,
|
|
263
|
+
there won't be any timeout. Increase or disable the timeout if you face
|
|
264
|
+
issues uploading big QUBO matrices.
|
|
265
|
+
|
|
266
|
+
Returns
|
|
267
|
+
-------
|
|
268
|
+
Optimization:
|
|
269
|
+
Created optimization.
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
response: Response = self._client.post(
|
|
273
|
+
f"{self._endpoint}/lp-file",
|
|
274
|
+
data={"optimization_in": json.dumps({"name": name})},
|
|
275
|
+
files={"lp_file": lp_file},
|
|
276
|
+
timeout=timeout,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
response.raise_for_status()
|
|
280
|
+
|
|
281
|
+
return Optimization.model_validate_json(response.text)
|
|
282
|
+
|
|
283
|
+
def create_from_lp_string(
|
|
284
|
+
self,
|
|
285
|
+
name: str,
|
|
286
|
+
lp_string: str,
|
|
287
|
+
timeout: Optional[float] = 10800.0,
|
|
288
|
+
) -> Optimization:
|
|
289
|
+
"""
|
|
290
|
+
Create an optimization from LP string.
|
|
291
|
+
|
|
292
|
+
Parameters
|
|
293
|
+
----------
|
|
294
|
+
name: str
|
|
295
|
+
Name of the optimization to be created.
|
|
296
|
+
lp_string: string.
|
|
297
|
+
timeout: Optional[float]
|
|
298
|
+
Default = 10800. Timeout for the api request. If set to None,
|
|
299
|
+
there won't be any timeout. Increase or disable the timeout if you face
|
|
300
|
+
issues uploading big QUBO matrices.
|
|
301
|
+
|
|
302
|
+
Returns
|
|
303
|
+
-------
|
|
304
|
+
Optimization:
|
|
305
|
+
Created optimization.
|
|
306
|
+
"""
|
|
307
|
+
data_in = {"name": name, "lp_string": lp_string}
|
|
308
|
+
|
|
309
|
+
response: Response = self._client.post(
|
|
310
|
+
f"{self._endpoint}/lp-string",
|
|
311
|
+
json=data_in,
|
|
312
|
+
timeout=timeout,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
response.raise_for_status()
|
|
316
|
+
|
|
317
|
+
return Optimization.model_validate_json(response.text)
|
|
318
|
+
|
|
319
|
+
def rename(self, optimization_id: str, name: str) -> Optimization:
|
|
320
|
+
"""
|
|
321
|
+
Update the name of the optimization
|
|
322
|
+
|
|
323
|
+
Parameters
|
|
324
|
+
----------
|
|
325
|
+
optimization_id: str
|
|
326
|
+
Id of the optimization to be updated.
|
|
327
|
+
name: str
|
|
328
|
+
New name of the optimization
|
|
329
|
+
|
|
330
|
+
Returns
|
|
331
|
+
-------
|
|
332
|
+
Optimization:
|
|
333
|
+
Updated optimization.
|
|
334
|
+
"""
|
|
335
|
+
data: Dict[str, str] = {"name": name}
|
|
336
|
+
|
|
337
|
+
response: Response = self._client.put(
|
|
338
|
+
f"{self._endpoint}/{optimization_id}",
|
|
339
|
+
content=json.dumps(data),
|
|
340
|
+
)
|
|
341
|
+
response.raise_for_status()
|
|
342
|
+
|
|
343
|
+
return Optimization.model_validate_json(response.text)
|
|
344
|
+
|
|
345
|
+
def delete(self, optimization_id: str) -> None:
|
|
346
|
+
"""
|
|
347
|
+
Delete one QUBO by id.
|
|
348
|
+
|
|
349
|
+
Parameters
|
|
350
|
+
----------
|
|
351
|
+
optimization_id: str
|
|
352
|
+
Id of the Model that should be deleted
|
|
353
|
+
|
|
354
|
+
Returns
|
|
355
|
+
-------
|
|
356
|
+
"""
|
|
357
|
+
response: Response = self._client.delete(f"{self._endpoint}/{optimization_id}")
|
|
358
|
+
response.raise_for_status()
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from httpx import Response
|
|
6
|
+
|
|
7
|
+
from luna_sdk.exceptions.encryption_exception import EncryptionNotSetException
|
|
8
|
+
from luna_sdk.interfaces.qpu_token_repo_i import IQpuTokenRepo
|
|
9
|
+
from luna_sdk.schemas import QpuTokenOut
|
|
10
|
+
from luna_sdk.schemas.create import QpuTokenIn
|
|
11
|
+
from luna_sdk.schemas.enums.qpu_token_type import QpuTokenTypeEnum
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class QpuTokenRepo(IQpuTokenRepo):
|
|
15
|
+
@property
|
|
16
|
+
def _endpoint(self) -> str:
|
|
17
|
+
return "/qpu-tokens"
|
|
18
|
+
|
|
19
|
+
def _get_endpoint_by_type(
|
|
20
|
+
self, token_type: Optional[QpuTokenTypeEnum] = None
|
|
21
|
+
) -> str:
|
|
22
|
+
if token_type is None:
|
|
23
|
+
return f"{self._endpoint}"
|
|
24
|
+
elif token_type == QpuTokenTypeEnum.PERSONAL:
|
|
25
|
+
return f"{self._endpoint}/users"
|
|
26
|
+
else:
|
|
27
|
+
return f"{self._endpoint}/organization"
|
|
28
|
+
|
|
29
|
+
def _get_by_name(self, name: str, token_type: QpuTokenTypeEnum) -> QpuTokenOut:
|
|
30
|
+
response: Response = self._client.get(
|
|
31
|
+
f"{self._get_endpoint_by_type(token_type)}/by_name/{name}"
|
|
32
|
+
)
|
|
33
|
+
response.raise_for_status()
|
|
34
|
+
|
|
35
|
+
qpu_token_data = response.json()
|
|
36
|
+
return QpuTokenOut.model_validate(qpu_token_data)
|
|
37
|
+
|
|
38
|
+
def create(
|
|
39
|
+
self,
|
|
40
|
+
name: str,
|
|
41
|
+
provider: str,
|
|
42
|
+
token: str,
|
|
43
|
+
token_type: QpuTokenTypeEnum = QpuTokenTypeEnum.PERSONAL,
|
|
44
|
+
encryption_key: Optional[str] = None,
|
|
45
|
+
) -> QpuTokenOut:
|
|
46
|
+
"""
|
|
47
|
+
Create user QPU token
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
name: str
|
|
52
|
+
Name of the QPU token
|
|
53
|
+
provider: str
|
|
54
|
+
Name of provider
|
|
55
|
+
token: str
|
|
56
|
+
Token
|
|
57
|
+
token_type: QpuTokenTypeEnum
|
|
58
|
+
There are two types of QPU tokens: PERSONAL and ORGANIZATION.
|
|
59
|
+
The default value is PERSONAL.
|
|
60
|
+
All users of an organization can use organization QPU tokens.
|
|
61
|
+
User QPU tokens can only be used by the user who created them.
|
|
62
|
+
encryption_key: Optional[str]
|
|
63
|
+
Encryption key to be used for encryption of QPU tokens.
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
QpuTokenOut
|
|
67
|
+
QpuTokenOut instances.
|
|
68
|
+
"""
|
|
69
|
+
encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
|
|
70
|
+
if encryption_key is None:
|
|
71
|
+
raise EncryptionNotSetException
|
|
72
|
+
qpu_token = QpuTokenIn(
|
|
73
|
+
name=name,
|
|
74
|
+
provider=provider,
|
|
75
|
+
token=token,
|
|
76
|
+
encryption_key=encryption_key,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
response: Response = self._client.post(
|
|
80
|
+
self._get_endpoint_by_type(token_type), content=qpu_token.model_dump_json()
|
|
81
|
+
)
|
|
82
|
+
response.raise_for_status()
|
|
83
|
+
qpu_token_data = response.json()
|
|
84
|
+
return QpuTokenOut.model_validate(qpu_token_data)
|
|
85
|
+
|
|
86
|
+
def get_all(
|
|
87
|
+
self,
|
|
88
|
+
filter_provider: Optional[str] = None,
|
|
89
|
+
name: Optional[str] = None,
|
|
90
|
+
token_type: Optional[QpuTokenTypeEnum] = None,
|
|
91
|
+
) -> Dict[QpuTokenTypeEnum, List[QpuTokenOut]]:
|
|
92
|
+
"""
|
|
93
|
+
Retrieve list of user QPU tokens.
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
filter_provider: Optional[str]
|
|
98
|
+
The provider for which qpu tokens should be retrieved
|
|
99
|
+
name: Optional[str]
|
|
100
|
+
Name of the QPU token that should be retrieved
|
|
101
|
+
token_type: Optional[QpuTokenTypeEnum]
|
|
102
|
+
If you want to retrieve only user or organization QPU tokens
|
|
103
|
+
otherwise all QPU tokens will be retrieved
|
|
104
|
+
token_type: QpuTokenTypeEnum
|
|
105
|
+
There are two types of QPU tokens: PERSONAL and ORGANIZATION.
|
|
106
|
+
The default value is PERSONAL.
|
|
107
|
+
All users of an organization can use organization QPU tokens.
|
|
108
|
+
User QPU tokens can only be used by the user who created them.
|
|
109
|
+
|
|
110
|
+
Returns
|
|
111
|
+
-------
|
|
112
|
+
Dict[QpuTokenTypeEnum, List[QpuTokenOut]]
|
|
113
|
+
List of QpuTokenOut instances.
|
|
114
|
+
"""
|
|
115
|
+
params = {}
|
|
116
|
+
if filter_provider:
|
|
117
|
+
params["filter_provider"] = filter_provider
|
|
118
|
+
|
|
119
|
+
if name:
|
|
120
|
+
params["name"] = name
|
|
121
|
+
|
|
122
|
+
response = self._client.get(self._get_endpoint_by_type(), params=params)
|
|
123
|
+
response.raise_for_status()
|
|
124
|
+
|
|
125
|
+
to_return: Dict[QpuTokenTypeEnum, List[QpuTokenOut]] = {}
|
|
126
|
+
for key, value in response.json().items():
|
|
127
|
+
to_return[QpuTokenTypeEnum(key)] = [
|
|
128
|
+
QpuTokenOut.model_validate(item) for item in value
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
return to_return
|
|
132
|
+
|
|
133
|
+
def get(
|
|
134
|
+
self,
|
|
135
|
+
name: str,
|
|
136
|
+
token_type: QpuTokenTypeEnum = QpuTokenTypeEnum.PERSONAL,
|
|
137
|
+
) -> QpuTokenOut:
|
|
138
|
+
"""
|
|
139
|
+
Retrieve user QPU token by id
|
|
140
|
+
|
|
141
|
+
Parameters
|
|
142
|
+
----------
|
|
143
|
+
name: str
|
|
144
|
+
Name of the QPU token that should be retrieved
|
|
145
|
+
token_type: QpuTokenTypeEnum
|
|
146
|
+
There are two types of QPU tokens: PERSONAL and ORGANIZATION.
|
|
147
|
+
The default value is PERSONAL.
|
|
148
|
+
All users of an organization can use organization QPU tokens.
|
|
149
|
+
User QPU tokens can only be used by the user who created them.
|
|
150
|
+
|
|
151
|
+
Returns
|
|
152
|
+
-------
|
|
153
|
+
QpuTokenOut
|
|
154
|
+
QpuTokenOut instance.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
qpu_token: QpuTokenOut = self._get_by_name(name, token_type)
|
|
158
|
+
|
|
159
|
+
return qpu_token
|
|
160
|
+
|
|
161
|
+
def rename(
|
|
162
|
+
self,
|
|
163
|
+
name: str,
|
|
164
|
+
new_name: str,
|
|
165
|
+
token_type: QpuTokenTypeEnum = QpuTokenTypeEnum.PERSONAL,
|
|
166
|
+
) -> QpuTokenOut:
|
|
167
|
+
"""
|
|
168
|
+
Update user QPU token by id
|
|
169
|
+
|
|
170
|
+
Parameters
|
|
171
|
+
----------
|
|
172
|
+
name: str
|
|
173
|
+
Name of the QPU token that should be updated
|
|
174
|
+
new_name: str
|
|
175
|
+
The new name
|
|
176
|
+
token_type: QpuTokenTypeEnum
|
|
177
|
+
There are two types of QPU tokens: PERSONAL and ORGANIZATION.
|
|
178
|
+
The default value is PERSONAL.
|
|
179
|
+
All users of an organization can use organization QPU tokens.
|
|
180
|
+
User QPU tokens can only be used by the user who created them.
|
|
181
|
+
|
|
182
|
+
Returns
|
|
183
|
+
-------
|
|
184
|
+
QpuTokenOut
|
|
185
|
+
QpuTokenOut instance.
|
|
186
|
+
"""
|
|
187
|
+
qpu_token_update_data = {"name": new_name}
|
|
188
|
+
|
|
189
|
+
token: QpuTokenOut = self.get(name, token_type)
|
|
190
|
+
|
|
191
|
+
response = self._client.put(
|
|
192
|
+
f"{self._get_endpoint_by_type(token_type)}/{token.id}",
|
|
193
|
+
content=json.dumps(qpu_token_update_data),
|
|
194
|
+
)
|
|
195
|
+
response.raise_for_status()
|
|
196
|
+
|
|
197
|
+
qpu_token_data = response.json()
|
|
198
|
+
return QpuTokenOut.model_validate(qpu_token_data)
|
|
199
|
+
|
|
200
|
+
def delete(
|
|
201
|
+
self,
|
|
202
|
+
name: str,
|
|
203
|
+
token_type: QpuTokenTypeEnum = QpuTokenTypeEnum.PERSONAL,
|
|
204
|
+
) -> None:
|
|
205
|
+
"""
|
|
206
|
+
Delete organization QPU token by name
|
|
207
|
+
|
|
208
|
+
Parameters
|
|
209
|
+
----------
|
|
210
|
+
name: str
|
|
211
|
+
Name of the QPU token that should be deleted
|
|
212
|
+
token_type: QpuTokenTypeEnum
|
|
213
|
+
There are two types of QPU tokens: PERSONAL and ORGANIZATION.
|
|
214
|
+
The default value is PERSONAL.
|
|
215
|
+
All users of an organization can use organization QPU tokens.
|
|
216
|
+
User QPU tokens can only be used by the user who created them.
|
|
217
|
+
|
|
218
|
+
Returns
|
|
219
|
+
-------
|
|
220
|
+
"""
|
|
221
|
+
token: QpuTokenOut = self.get(name, token_type)
|
|
222
|
+
|
|
223
|
+
response = self._client.delete(
|
|
224
|
+
f"{self._get_endpoint_by_type(token_type)}/{token.id}"
|
|
225
|
+
)
|
|
226
|
+
response.raise_for_status()
|