luna-quantum 1.0.0__cp311-cp311-win_amd64.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.

Files changed (252) hide show
  1. luna_quantum/__init__.py +96 -0
  2. luna_quantum/__init__.pyi +68 -0
  3. luna_quantum/_core.cp311-win_amd64.pyd +0 -0
  4. luna_quantum/_core.pyi +3017 -0
  5. luna_quantum/aqm_overwrites/__init__.py +3 -0
  6. luna_quantum/aqm_overwrites/model.py +184 -0
  7. luna_quantum/client/__init__.py +0 -0
  8. luna_quantum/client/controllers/__init__.py +4 -0
  9. luna_quantum/client/controllers/luna_http_client.py +37 -0
  10. luna_quantum/client/controllers/luna_platform_client.py +153 -0
  11. luna_quantum/client/controllers/luna_q.py +62 -0
  12. luna_quantum/client/controllers/luna_solve.py +125 -0
  13. luna_quantum/client/error/__init__.py +0 -0
  14. luna_quantum/client/error/luna_api_key_invalid_error.py +10 -0
  15. luna_quantum/client/error/luna_api_key_missing_error.py +10 -0
  16. luna_quantum/client/error/luna_error.py +2 -0
  17. luna_quantum/client/error/luna_server_error.py +20 -0
  18. luna_quantum/client/error/timeout_error.py +12 -0
  19. luna_quantum/client/error/transformation_error.py +18 -0
  20. luna_quantum/client/error/utils/__init__.py +0 -0
  21. luna_quantum/client/error/utils/http_error_utils.py +112 -0
  22. luna_quantum/client/interfaces/__init__.py +4 -0
  23. luna_quantum/client/interfaces/clients/__init__.py +25 -0
  24. luna_quantum/client/interfaces/clients/circuit_rest_client_i.py +68 -0
  25. luna_quantum/client/interfaces/clients/info_rest_client_i.py +53 -0
  26. luna_quantum/client/interfaces/clients/model_rest_client_i.py +139 -0
  27. luna_quantum/client/interfaces/clients/qpu_token_rest_client_i.py +364 -0
  28. luna_quantum/client/interfaces/clients/rest_client_i.py +21 -0
  29. luna_quantum/client/interfaces/clients/solve_job_rest_client_i.py +201 -0
  30. luna_quantum/client/interfaces/clients/users_rest_client_i.py +29 -0
  31. luna_quantum/client/interfaces/services/__init__.py +0 -0
  32. luna_quantum/client/interfaces/services/luna_q_i.py +34 -0
  33. luna_quantum/client/interfaces/services/luna_solve_i.py +72 -0
  34. luna_quantum/client/interfaces/services/service_i.py +36 -0
  35. luna_quantum/client/rest_client/__init__.py +15 -0
  36. luna_quantum/client/rest_client/circuit_rest_client.py +107 -0
  37. luna_quantum/client/rest_client/info_rest_client.py +76 -0
  38. luna_quantum/client/rest_client/model_rest_client.py +216 -0
  39. luna_quantum/client/rest_client/qpu_token_rest_client.py +504 -0
  40. luna_quantum/client/rest_client/solve_job_rest_client.py +286 -0
  41. luna_quantum/client/rest_client/users_rest_client.py +35 -0
  42. luna_quantum/client/schemas/__init__.py +26 -0
  43. luna_quantum/client/schemas/circuit.py +49 -0
  44. luna_quantum/client/schemas/create/__init__.py +6 -0
  45. luna_quantum/client/schemas/create/circuit.py +31 -0
  46. luna_quantum/client/schemas/create/optimization.py +39 -0
  47. luna_quantum/client/schemas/create/qpu_token.py +25 -0
  48. luna_quantum/client/schemas/create/qpu_token_time_quota.py +29 -0
  49. luna_quantum/client/schemas/create/qubo.py +19 -0
  50. luna_quantum/client/schemas/create/solve_job_create.py +43 -0
  51. luna_quantum/client/schemas/enums/__init__.py +0 -0
  52. luna_quantum/client/schemas/enums/call_style.py +13 -0
  53. luna_quantum/client/schemas/enums/circuit.py +42 -0
  54. luna_quantum/client/schemas/enums/model_format.py +11 -0
  55. luna_quantum/client/schemas/enums/problem.py +50 -0
  56. luna_quantum/client/schemas/enums/qpu_token_type.py +20 -0
  57. luna_quantum/client/schemas/enums/sense.py +8 -0
  58. luna_quantum/client/schemas/enums/status.py +40 -0
  59. luna_quantum/client/schemas/enums/timeframe.py +11 -0
  60. luna_quantum/client/schemas/error_message.py +14 -0
  61. luna_quantum/client/schemas/model_metadata.py +35 -0
  62. luna_quantum/client/schemas/qpu_token/__init__.py +0 -0
  63. luna_quantum/client/schemas/qpu_token/qpu_token.py +161 -0
  64. luna_quantum/client/schemas/qpu_token/qpu_token_source.py +19 -0
  65. luna_quantum/client/schemas/qpu_token/qpu_token_time_quota.py +28 -0
  66. luna_quantum/client/schemas/qpu_token/token_provider.py +135 -0
  67. luna_quantum/client/schemas/representation.py +19 -0
  68. luna_quantum/client/schemas/solution.py +106 -0
  69. luna_quantum/client/schemas/solve_job.py +47 -0
  70. luna_quantum/client/schemas/solver_info.py +11 -0
  71. luna_quantum/client/schemas/user.py +11 -0
  72. luna_quantum/client/schemas/wrappers/__init__.py +5 -0
  73. luna_quantum/client/schemas/wrappers/datetime_wrapper.py +32 -0
  74. luna_quantum/client/utils/__init__.py +0 -0
  75. luna_quantum/client/utils/qpu_token_utils.py +147 -0
  76. luna_quantum/errors.py +1 -0
  77. luna_quantum/errors.pyi +202 -0
  78. luna_quantum/exceptions/__init__.py +0 -0
  79. luna_quantum/exceptions/base_luna_quantum_error.py +2 -0
  80. luna_quantum/exceptions/patch_class_field_exists_error.py +10 -0
  81. luna_quantum/factories/__init__.py +4 -0
  82. luna_quantum/factories/luna_solve_client_factory.py +75 -0
  83. luna_quantum/factories/usecase_factory.py +457 -0
  84. luna_quantum/py.typed +0 -0
  85. luna_quantum/solve/__init__.py +13 -0
  86. luna_quantum/solve/default_token.py +304 -0
  87. luna_quantum/solve/domain/__init__.py +0 -0
  88. luna_quantum/solve/domain/abstract/__init__.py +4 -0
  89. luna_quantum/solve/domain/abstract/luna_algorithm.py +203 -0
  90. luna_quantum/solve/domain/abstract/qpu_token_backend.py +34 -0
  91. luna_quantum/solve/domain/model_metadata.py +54 -0
  92. luna_quantum/solve/domain/solve_job.py +187 -0
  93. luna_quantum/solve/errors/__init__.py +0 -0
  94. luna_quantum/solve/errors/incompatible_backend_error.py +15 -0
  95. luna_quantum/solve/errors/model_metadata_missing_error.py +11 -0
  96. luna_quantum/solve/errors/solve_base_error.py +5 -0
  97. luna_quantum/solve/errors/token_missing_error.py +11 -0
  98. luna_quantum/solve/interfaces/__init__.py +0 -0
  99. luna_quantum/solve/interfaces/algorithm_i.py +47 -0
  100. luna_quantum/solve/interfaces/backend_i.py +28 -0
  101. luna_quantum/solve/interfaces/usecases/__init__.py +55 -0
  102. luna_quantum/solve/interfaces/usecases/model_delete_usecase_i.py +27 -0
  103. luna_quantum/solve/interfaces/usecases/model_fetch_metadata_usecase_i.py +33 -0
  104. luna_quantum/solve/interfaces/usecases/model_get_solutions_usecase_i.py +33 -0
  105. luna_quantum/solve/interfaces/usecases/model_get_solve_jobs_usecase_i.py +33 -0
  106. luna_quantum/solve/interfaces/usecases/model_load_by_id_usecase_i.py +32 -0
  107. luna_quantum/solve/interfaces/usecases/model_load_by_metadata_usecase_i.py +37 -0
  108. luna_quantum/solve/interfaces/usecases/model_load_metadata_by_hash_usecase_i.py +38 -0
  109. luna_quantum/solve/interfaces/usecases/model_save_usecase_i.py +36 -0
  110. luna_quantum/solve/interfaces/usecases/solve_job_cancel_usecase_i.py +33 -0
  111. luna_quantum/solve/interfaces/usecases/solve_job_create_usecase_i.py +44 -0
  112. luna_quantum/solve/interfaces/usecases/solve_job_delete_usecase_i.py +32 -0
  113. luna_quantum/solve/interfaces/usecases/solve_job_fetch_updates_usecase_i.py +38 -0
  114. luna_quantum/solve/interfaces/usecases/solve_job_get_result_usecase_i.py +63 -0
  115. luna_quantum/solve/parameters/__init__.py +0 -0
  116. luna_quantum/solve/parameters/algorithms/__init__.py +49 -0
  117. luna_quantum/solve/parameters/algorithms/base_params/__init__.py +24 -0
  118. luna_quantum/solve/parameters/algorithms/base_params/decomposer.py +57 -0
  119. luna_quantum/solve/parameters/algorithms/base_params/qaoa_circuit_params.py +95 -0
  120. luna_quantum/solve/parameters/algorithms/base_params/quantum_annealing_params.py +78 -0
  121. luna_quantum/solve/parameters/algorithms/base_params/scipy_optimizer.py +120 -0
  122. luna_quantum/solve/parameters/algorithms/base_params/simulated_annealing_params.py +106 -0
  123. luna_quantum/solve/parameters/algorithms/base_params/tabu_kerberos_params.py +39 -0
  124. luna_quantum/solve/parameters/algorithms/base_params/tabu_search_params.py +129 -0
  125. luna_quantum/solve/parameters/algorithms/flexible_parameter_algorithm.py +59 -0
  126. luna_quantum/solve/parameters/algorithms/genetic_algorithms/__init__.py +4 -0
  127. luna_quantum/solve/parameters/algorithms/genetic_algorithms/qaga.py +131 -0
  128. luna_quantum/solve/parameters/algorithms/genetic_algorithms/saga.py +139 -0
  129. luna_quantum/solve/parameters/algorithms/optimization_solvers/__init__.py +3 -0
  130. luna_quantum/solve/parameters/algorithms/optimization_solvers/scip.py +51 -0
  131. luna_quantum/solve/parameters/algorithms/quantum_annealing/__init__.py +19 -0
  132. luna_quantum/solve/parameters/algorithms/quantum_annealing/kerberos.py +149 -0
  133. luna_quantum/solve/parameters/algorithms/quantum_annealing/leap_hybrid_bqm.py +75 -0
  134. luna_quantum/solve/parameters/algorithms/quantum_annealing/leap_hybrid_cqm.py +75 -0
  135. luna_quantum/solve/parameters/algorithms/quantum_annealing/parallel_tempering_qpu.py +139 -0
  136. luna_quantum/solve/parameters/algorithms/quantum_annealing/population_annealing_qpu.py +109 -0
  137. luna_quantum/solve/parameters/algorithms/quantum_annealing/qbsolv_like_qpu.py +111 -0
  138. luna_quantum/solve/parameters/algorithms/quantum_annealing/quantum_annealing.py +105 -0
  139. luna_quantum/solve/parameters/algorithms/quantum_annealing/repeated_reverse_quantum_annealing.py +174 -0
  140. luna_quantum/solve/parameters/algorithms/quantum_gate/__init__.py +6 -0
  141. luna_quantum/solve/parameters/algorithms/quantum_gate/flex_qaoa/__init__.py +26 -0
  142. luna_quantum/solve/parameters/algorithms/quantum_gate/flex_qaoa/config.py +80 -0
  143. luna_quantum/solve/parameters/algorithms/quantum_gate/flex_qaoa/flex_qaoa.py +226 -0
  144. luna_quantum/solve/parameters/algorithms/quantum_gate/flex_qaoa/optimizers.py +97 -0
  145. luna_quantum/solve/parameters/algorithms/quantum_gate/flex_qaoa/pipeline.py +87 -0
  146. luna_quantum/solve/parameters/algorithms/quantum_gate/qaoa.py +104 -0
  147. luna_quantum/solve/parameters/algorithms/quantum_gate/qaoa_fo.py +69 -0
  148. luna_quantum/solve/parameters/algorithms/quantum_gate/vqe.py +109 -0
  149. luna_quantum/solve/parameters/algorithms/search_algorithms/__init__.py +5 -0
  150. luna_quantum/solve/parameters/algorithms/search_algorithms/dialectic_search.py +152 -0
  151. luna_quantum/solve/parameters/algorithms/search_algorithms/qbsolv_like_tabu_search.py +117 -0
  152. luna_quantum/solve/parameters/algorithms/search_algorithms/tabu_search.py +126 -0
  153. luna_quantum/solve/parameters/algorithms/simulated_annealing/__init__.py +13 -0
  154. luna_quantum/solve/parameters/algorithms/simulated_annealing/parallel_tempering.py +131 -0
  155. luna_quantum/solve/parameters/algorithms/simulated_annealing/population_annealing.py +95 -0
  156. luna_quantum/solve/parameters/algorithms/simulated_annealing/qbsolv_like_simulated_annealing.py +141 -0
  157. luna_quantum/solve/parameters/algorithms/simulated_annealing/repeated_reverse_simulated_annealing.py +172 -0
  158. luna_quantum/solve/parameters/algorithms/simulated_annealing/simulated_annealing.py +126 -0
  159. luna_quantum/solve/parameters/backends/__init__.py +20 -0
  160. luna_quantum/solve/parameters/backends/aqarios.py +17 -0
  161. luna_quantum/solve/parameters/backends/aws/__init__.py +11 -0
  162. luna_quantum/solve/parameters/backends/aws/aws.py +36 -0
  163. luna_quantum/solve/parameters/backends/aws/aws_backend_base.py +74 -0
  164. luna_quantum/solve/parameters/backends/aws/ionq.py +43 -0
  165. luna_quantum/solve/parameters/backends/aws/iqm.py +31 -0
  166. luna_quantum/solve/parameters/backends/aws/rigetti.py +31 -0
  167. luna_quantum/solve/parameters/backends/dwave.py +17 -0
  168. luna_quantum/solve/parameters/backends/dwave_qpu.py +164 -0
  169. luna_quantum/solve/parameters/backends/ibm.py +132 -0
  170. luna_quantum/solve/parameters/backends/qctrl.py +130 -0
  171. luna_quantum/solve/parameters/backends/zib.py +17 -0
  172. luna_quantum/solve/parameters/constants.py +11 -0
  173. luna_quantum/solve/parameters/mixins/__init__.py +0 -0
  174. luna_quantum/solve/parameters/mixins/fujitsu_common_params_mixin.py +239 -0
  175. luna_quantum/solve/parameters/mixins/fujitsu_v2_mixin.py +70 -0
  176. luna_quantum/solve/parameters/mixins/qbsolv_like_mixin.py +60 -0
  177. luna_quantum/solve/use_cases/__init__.py +119 -0
  178. luna_quantum/solve/use_cases/arbitrage_edge_based.py +50 -0
  179. luna_quantum/solve/use_cases/arbitrage_node_based.py +55 -0
  180. luna_quantum/solve/use_cases/base.py +7 -0
  181. luna_quantum/solve/use_cases/binary_integer_linear_programming.py +54 -0
  182. luna_quantum/solve/use_cases/binary_paint_shop_problem.py +37 -0
  183. luna_quantum/solve/use_cases/credit_scoring_feature_selection.py +40 -0
  184. luna_quantum/solve/use_cases/dynamic_portfolio_optimization.py +64 -0
  185. luna_quantum/solve/use_cases/exact_cover.py +51 -0
  186. luna_quantum/solve/use_cases/flight_gate_assignment.py +79 -0
  187. luna_quantum/solve/use_cases/graph_coloring.py +42 -0
  188. luna_quantum/solve/use_cases/graph_isomorphism.py +52 -0
  189. luna_quantum/solve/use_cases/graph_partitioning.py +46 -0
  190. luna_quantum/solve/use_cases/hamiltonian_cycle.py +49 -0
  191. luna_quantum/solve/use_cases/induced_subgraph_isomorphism.py +50 -0
  192. luna_quantum/solve/use_cases/job_shop_scheduling.py +44 -0
  193. luna_quantum/solve/use_cases/k_medoids_clustering.py +49 -0
  194. luna_quantum/solve/use_cases/knapsack_integer_weights.py +56 -0
  195. luna_quantum/solve/use_cases/linear_regression.py +60 -0
  196. luna_quantum/solve/use_cases/lmwcs.py +84 -0
  197. luna_quantum/solve/use_cases/longest_path.py +50 -0
  198. luna_quantum/solve/use_cases/market_graph_clustering.py +61 -0
  199. luna_quantum/solve/use_cases/max2sat.py +54 -0
  200. luna_quantum/solve/use_cases/max3sat.py +55 -0
  201. luna_quantum/solve/use_cases/max_clique.py +60 -0
  202. luna_quantum/solve/use_cases/max_cut.py +48 -0
  203. luna_quantum/solve/use_cases/max_independent_set.py +37 -0
  204. luna_quantum/solve/use_cases/minimal_maximal_matching.py +54 -0
  205. luna_quantum/solve/use_cases/minimal_spanning_tree.py +90 -0
  206. luna_quantum/solve/use_cases/minimum_vertex_cover.py +45 -0
  207. luna_quantum/solve/use_cases/number_partitioning.py +32 -0
  208. luna_quantum/solve/use_cases/portfolio_optimization.py +46 -0
  209. luna_quantum/solve/use_cases/portfolio_optimization_ib_tv.py +63 -0
  210. luna_quantum/solve/use_cases/quadratic_assignment.py +49 -0
  211. luna_quantum/solve/use_cases/quadratic_knapsack.py +48 -0
  212. luna_quantum/solve/use_cases/satellite_scheduling.py +73 -0
  213. luna_quantum/solve/use_cases/sensor_placement.py +58 -0
  214. luna_quantum/solve/use_cases/set_cover.py +56 -0
  215. luna_quantum/solve/use_cases/set_packing.py +54 -0
  216. luna_quantum/solve/use_cases/set_partitioning.py +52 -0
  217. luna_quantum/solve/use_cases/subgraph_isomorphism.py +55 -0
  218. luna_quantum/solve/use_cases/subset_sum.py +37 -0
  219. luna_quantum/solve/use_cases/support_vector_machine.py +64 -0
  220. luna_quantum/solve/use_cases/traffic_flow.py +35 -0
  221. luna_quantum/solve/use_cases/travelling_salesman_problem.py +53 -0
  222. luna_quantum/solve/use_cases/type_aliases.py +9 -0
  223. luna_quantum/solve/use_cases/weighted_max_cut.py +37 -0
  224. luna_quantum/solve/usecases/__init__.py +45 -0
  225. luna_quantum/solve/usecases/model_delete_usecase.py +49 -0
  226. luna_quantum/solve/usecases/model_fetch_metadata_usecase.py +50 -0
  227. luna_quantum/solve/usecases/model_get_solution_usecase.py +56 -0
  228. luna_quantum/solve/usecases/model_get_solve_jobs_usecase.py +62 -0
  229. luna_quantum/solve/usecases/model_load_by_id_usecase.py +47 -0
  230. luna_quantum/solve/usecases/model_load_by_metadata_usecase.py +52 -0
  231. luna_quantum/solve/usecases/model_load_metadata_by_hash_usecase.py +51 -0
  232. luna_quantum/solve/usecases/model_save_usecase.py +63 -0
  233. luna_quantum/solve/usecases/solve_job_cancel_usecase.py +51 -0
  234. luna_quantum/solve/usecases/solve_job_create_usecase.py +112 -0
  235. luna_quantum/solve/usecases/solve_job_delete_usecase.py +38 -0
  236. luna_quantum/solve/usecases/solve_job_fetch_updates_usecase.py +49 -0
  237. luna_quantum/solve/usecases/solve_job_get_result_usecase.py +97 -0
  238. luna_quantum/translator.py +1 -0
  239. luna_quantum/translator.pyi +833 -0
  240. luna_quantum/util/__init__.py +0 -0
  241. luna_quantum/util/active_waiting.py +79 -0
  242. luna_quantum/util/class_patcher.py +164 -0
  243. luna_quantum/util/log_utils.py +167 -0
  244. luna_quantum/util/pretty_base.py +67 -0
  245. luna_quantum/util/pydantic_utils.py +38 -0
  246. luna_quantum/utils.py +54 -0
  247. luna_quantum/utils.pyi +35 -0
  248. luna_quantum-1.0.0.dist-info/METADATA +37 -0
  249. luna_quantum-1.0.0.dist-info/RECORD +252 -0
  250. luna_quantum-1.0.0.dist-info/WHEEL +4 -0
  251. luna_quantum-1.0.0.dist-info/licenses/LICENSE +176 -0
  252. luna_quantum-1.0.0.dist-info/licenses/NOTICE +13 -0
@@ -0,0 +1,3 @@
1
+ from .model import Model
2
+
3
+ __all__ = ["Model"]
@@ -0,0 +1,184 @@
1
+ from luna_quantum._core import Model, Solution
2
+ from luna_quantum.client.interfaces.services.luna_solve_i import ILunaSolve
3
+ from luna_quantum.factories.luna_solve_client_factory import LunaSolveClientFactory
4
+ from luna_quantum.factories.usecase_factory import UseCaseFactory
5
+ from luna_quantum.solve.domain.model_metadata import ModelMetadata
6
+ from luna_quantum.solve.domain.solve_job import SolveJob
7
+ from luna_quantum.util.class_patcher import (
8
+ patch_instance,
9
+ patch_property,
10
+ patch_static,
11
+ )
12
+
13
+
14
+ @patch_property(Model)
15
+ def metadata(self: Model) -> ModelMetadata | None:
16
+ """
17
+ Return metadata for the current Model instance.
18
+
19
+ If metadata is cached and corresponds to the current hash, returns the cached
20
+ metadata. Otherwise, retrieves metadata via a client and updates the cache.
21
+
22
+ Parameters
23
+ ----------
24
+ self
25
+ Instance of Model.
26
+
27
+ Returns
28
+ -------
29
+ Optional[ModelMetadata]
30
+ Metadata for the current Model instance, or None if an error occurs or
31
+ metadata cannot be retrieved.
32
+ """
33
+ _hash = self.__hash__()
34
+ if (
35
+ "metadata" in self._metadata # type: ignore[attr-defined]
36
+ and "hash" in self._metadata # type: ignore[attr-defined]
37
+ and self._metadata["hash"] == _hash # type: ignore[attr-defined]
38
+ ):
39
+ return self._metadata["metadata"] # type: ignore # noqa: PGH003 # Patched Model
40
+ client = LunaSolveClientFactory.get_client(
41
+ None
42
+ ) # TODO(Llewellyn): is there a way to let the user overwrite # noqa: FIX002
43
+ # set the client here
44
+ try:
45
+ _metadata = UseCaseFactory.model_load_metadata_by_hash(client=client).__call__(
46
+ model_hash=_hash
47
+ )
48
+ except Exception:
49
+ _metadata = None
50
+ self._metadata["metadata"] = _metadata # type: ignore # noqa: PGH003 # Patched Model
51
+ self._metadata["hash"] = _hash # type: ignore # noqa: PGH003 # Patched Model
52
+
53
+ return _metadata
54
+
55
+
56
+ @patch_static(Model)
57
+ def load_luna(model_id: str, client: ILunaSolve | str | None = None) -> Model:
58
+ """
59
+ Load an AQ model using a specific model ID.
60
+
61
+ This function retrieves an AQ model from a client obj. The client can either be
62
+ provided directly or created dynamically if not specified.
63
+
64
+ Parameters
65
+ ----------
66
+ model_id : str
67
+ The identifier of the model that needs to be loaded.
68
+ client : Optional[Union[ILunaSolve, str]]
69
+ The client to use for loading the model. If not provided, a client
70
+ will be created automatically.
71
+
72
+ Returns
73
+ -------
74
+ Model
75
+ The AQ model that was successfully loaded.
76
+ """
77
+ client = LunaSolveClientFactory.get_client(client=client)
78
+ return UseCaseFactory.model_load_by_id(client=client).__call__(model_id=model_id)
79
+
80
+
81
+ @patch_instance(Model)
82
+ def save_luna(self: Model, client: ILunaSolve | str | None = None) -> None:
83
+ """
84
+ Save the model and update its metadata and hash.
85
+
86
+ This function saves the current state of the model using the provided client or
87
+ default client obtained from `ClientFactory`. It also updates the local `metadata`
88
+ attributes of the model after saving.
89
+
90
+ Parameters
91
+ ----------
92
+ self : Model
93
+ The instance of the Model class.
94
+ client : Optional[Union[ILunaSolve, str]], default=None
95
+ The client to facilitate saving the model. Can be an instance of `ILunaSolve`,
96
+ a string representing the client, or left as None to use the default client.
97
+
98
+ Returns
99
+ -------
100
+ None
101
+ This function does not return any values.
102
+
103
+ """
104
+ client = LunaSolveClientFactory.get_client(client=client)
105
+ self._metadata["metadata"] = UseCaseFactory.model_save(client=client).__call__(self) # type: ignore # noqa: PGH003 # Patched Model
106
+ self._metadata["hash"] = self.__hash__() # type: ignore[attr-defined]
107
+
108
+
109
+ @patch_instance(Model)
110
+ def delete_luna(self: Model, client: ILunaSolve | str | None = None) -> None:
111
+ """
112
+ Delete the Luna instance of the Model.
113
+
114
+ Ensure the Model instance is removed properly using the provided client or the
115
+ default client.
116
+
117
+ Parameters
118
+ ----------
119
+ self : Model
120
+ The instance of the model to be deleted.
121
+ client : Optional[Union[ILunaSolve, str]], optional
122
+ The client used to connect to the service. If not provided, the default
123
+ client is used.
124
+
125
+ Returns
126
+ -------
127
+ None
128
+ """
129
+ client = LunaSolveClientFactory.get_client(client=client)
130
+ UseCaseFactory.model_delete(client=client).__call__(self)
131
+
132
+
133
+ @patch_instance(Model)
134
+ def load_solutions(
135
+ self: Model, client: ILunaSolve | str | None = None
136
+ ) -> list[Solution]:
137
+ """
138
+ Load solutions for an Model.
139
+
140
+ Fetch and return the list of all solutions for the patched Model
141
+ using the provided client or the default client.
142
+
143
+ Parameters
144
+ ----------
145
+ self : Model
146
+ The Model for which solutions are to be loaded.
147
+ client : Optional[Union[ILunaSolve, str]], optional
148
+ The client used to interact and retrieve model solutions. If not provided,
149
+ a default client will be created using the `ClientFactory`.
150
+
151
+ Returns
152
+ -------
153
+ List[IAqSolution]
154
+ A list of IAqSolution instances containing the solutions.
155
+
156
+ """
157
+ client = LunaSolveClientFactory.get_client(client=client)
158
+ return UseCaseFactory.model_get_solution(client=client).__call__(self)
159
+
160
+
161
+ @patch_instance(Model)
162
+ def load_solve_jobs(
163
+ self: Model, client: ILunaSolve | str | None = None
164
+ ) -> list[SolveJob]:
165
+ """
166
+ Load and return a list of SolveJob objects for the Model instance.
167
+
168
+ Parameters
169
+ ----------
170
+ self : Model
171
+ The instance of the Model for which solve jobs need to be loaded.
172
+ client : Optional[Union[ILunaSolve, str]], optional
173
+ The client object or client type for fetching solve jobs, by default None.
174
+
175
+ Returns
176
+ -------
177
+ List[SolveJob]
178
+ A list of SolveJob objects related to the Model instance.
179
+ """
180
+ client = LunaSolveClientFactory.get_client(client=client)
181
+ return UseCaseFactory.model_get_solve_job(client=client).__call__(self)
182
+
183
+
184
+ __all__ = ["Model"]
File without changes
@@ -0,0 +1,4 @@
1
+ from luna_quantum.client.controllers.luna_q import LunaQ
2
+ from luna_quantum.client.controllers.luna_solve import LunaSolve
3
+
4
+ __all__ = ["LunaQ", "LunaSolve"]
@@ -0,0 +1,37 @@
1
+ from __future__ import annotations
2
+
3
+ from importlib.metadata import version
4
+ from typing import Any
5
+
6
+ import httpx
7
+ from httpx import Client, Response
8
+
9
+ from luna_quantum.client.error.timeout_error import LunaTimeoutError
10
+ from luna_quantum.client.error.utils.http_error_utils import HttpErrorUtils
11
+
12
+
13
+ class LunaHTTPClient(Client):
14
+ """
15
+ Luna HTTP client.
16
+
17
+ Mainly used to set custom headers.
18
+ """
19
+
20
+ _version: str = version("luna-quantum")
21
+
22
+ _user_agent: str = f"LunaSDK/{_version}"
23
+
24
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
25
+ super().__init__(*args, **kwargs)
26
+
27
+ self.headers["User-Agent"] = self._user_agent
28
+
29
+ def request(self, *args: Any, **kwargs: Any) -> Response:
30
+ """Send request to Luna platform."""
31
+ try:
32
+ response: Response = super().request(*args, **kwargs)
33
+ except httpx.TimeoutException:
34
+ # Handle all possible in httpx timeout exceptions
35
+ raise LunaTimeoutError from None
36
+ HttpErrorUtils.check_for_error(response)
37
+ return response
@@ -0,0 +1,153 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from contextlib import suppress
5
+ from enum import Enum
6
+ from http import HTTPStatus
7
+ from typing import TYPE_CHECKING, ClassVar
8
+
9
+ import httpx
10
+ from httpx import HTTPStatusError, Request, Response
11
+
12
+ from luna_quantum.client.controllers.luna_http_client import LunaHTTPClient
13
+ from luna_quantum.client.error.luna_api_key_invalid_error import LunaApiKeyInvalidError
14
+ from luna_quantum.client.error.luna_api_key_missing_error import LunaApiKeyMissingError
15
+ from luna_quantum.client.error.utils.http_error_utils import HttpErrorUtils
16
+ from luna_quantum.client.interfaces.services.service_i import IService
17
+ from luna_quantum.client.rest_client.users_rest_client import UsersRestClient
18
+
19
+ if TYPE_CHECKING:
20
+ from collections.abc import Generator
21
+
22
+
23
+ class LunaPrefixEnum(str, Enum):
24
+ """Enumeration of Luna services."""
25
+
26
+ LUNA_SOLVE = "luna-solve"
27
+ LUNA_Q = "luna-q"
28
+
29
+
30
+ def check_httpx_exceptions(response: Response) -> None:
31
+ """
32
+ Check if response contains errors from the server.
33
+
34
+ This function examines the HTTP response and raises appropriate SDK exceptions
35
+ if error conditions are detected.
36
+
37
+ Parameters
38
+ ----------
39
+ response: Response
40
+ The HTTP response object to be examined for error conditions.
41
+ """
42
+ HttpErrorUtils.check_for_error(response)
43
+
44
+
45
+ class APIKeyAuth(httpx.Auth):
46
+ """API key authentication method for luna platform."""
47
+
48
+ def __init__(self, token: str) -> None:
49
+ self.token = token
50
+
51
+ def auth_flow(self, request: Request) -> Generator[Request, Response, None]:
52
+ """
53
+ Authenticate a request to Luna platform.
54
+
55
+ Parameters
56
+ ----------
57
+ request: Request
58
+ Request that needs to be authenticated.
59
+ """
60
+ request.headers["Luna-API-Key"] = self.token
61
+
62
+ dev_header_value = os.getenv("LUNA_DEV_EXTRA_HEADER_VALUE", None)
63
+ dev_header_name = os.getenv("LUNA_DEV_EXTRA_HEADER_NAME", None)
64
+ if dev_header_name and dev_header_value:
65
+ request.headers[dev_header_name] = dev_header_value
66
+ yield request
67
+
68
+
69
+ class LunaPlatformClient(IService):
70
+ """Luna platform REST client."""
71
+
72
+ _base_url: str = ""
73
+
74
+ _httpx_client: httpx.Client
75
+ _api_key: ClassVar[str | None] = None
76
+
77
+ @property
78
+ def client(self) -> httpx.Client:
79
+ """
80
+ Return httpx client.
81
+
82
+ Returns
83
+ -------
84
+ httpx.Client
85
+ """
86
+ return self._httpx_client
87
+
88
+ def __init__(
89
+ self,
90
+ api: LunaPrefixEnum,
91
+ api_key: str | None = None,
92
+ base_url: str = os.getenv("LUNA_BASE_URL", "https://api.aqarios.com"),
93
+ timeout: float | None = 240.0,
94
+ ) -> None:
95
+ """
96
+ LunaPlatformClient is a main entrypoint of the SDK.
97
+
98
+ All the operations with entities should be processed using an instance of
99
+ LunaPlatformClient.
100
+
101
+ Parameters
102
+ ----------
103
+ api: LunaPrefixEnum
104
+ Current API with which luna client is working. Can be luna-solve or luna-q.
105
+ api_key: Optional[str]
106
+ Api key to be used to authorize. Default none.
107
+ If its none then the key set by the `authorize` method will be used.
108
+ base_url:
109
+ Base API URL.
110
+ If you want to use API not on your local PC then change it.
111
+ You can do that by setting the environment variable LUNA_BASE_URL.
112
+ Default value https://api.aqarios.com.
113
+ timeout:
114
+ Default timeout in seconds for the requests via the LunaQ client. `None`
115
+ means that the SDK uses no timeouts. Note that either way the Luna platform
116
+ itself will time out after 240 seconds.
117
+ Default: 240.0
118
+ """
119
+ if os.getenv("LUNA_DISABLE_SUFFIX", "false").lower() == "true":
120
+ self._base_url = f"{base_url}/api/v1"
121
+ else:
122
+ self._base_url = f"{base_url}/{api.value}/api/v1"
123
+ if api_key:
124
+ auth_key = api_key
125
+ elif self.__class__._api_key: # noqa: SLF001 Use here self.__class__ so that LunaSolve and LunaQ can have different api keys set
126
+ auth_key = self.__class__._api_key # noqa: SLF001 Use here self.__class__ so that LunaSolve and LunaQ can have different api keys set
127
+ elif key := os.getenv("LUNA_API_KEY", None):
128
+ auth_key = key
129
+ else:
130
+ raise LunaApiKeyMissingError
131
+
132
+ self._httpx_client = LunaHTTPClient(
133
+ auth=APIKeyAuth(auth_key),
134
+ base_url=self._base_url,
135
+ follow_redirects=True,
136
+ timeout=timeout,
137
+ event_hooks={"response": [check_httpx_exceptions]},
138
+ )
139
+
140
+ self._authenticate()
141
+
142
+ def __del__(self) -> None: # noqa: D105
143
+ if hasattr(self, "_httpx_client"):
144
+ with suppress(Exception):
145
+ self._httpx_client.close()
146
+
147
+ def _authenticate(self) -> None:
148
+ try:
149
+ UsersRestClient(service=self).get_me()
150
+ except HTTPStatusError as exception:
151
+ if exception.response.status_code == HTTPStatus.UNAUTHORIZED:
152
+ raise LunaApiKeyInvalidError from exception
153
+ raise
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from luna_quantum.client.controllers.luna_platform_client import (
6
+ LunaPlatformClient,
7
+ LunaPrefixEnum,
8
+ )
9
+ from luna_quantum.client.interfaces.services.luna_q_i import ILunaQ
10
+ from luna_quantum.client.rest_client import CircuitRestClient, QpuTokenRestClient
11
+
12
+ if TYPE_CHECKING:
13
+ from luna_quantum.client.interfaces.clients import ICircuitRestClient
14
+ from luna_quantum.client.interfaces.clients.qpu_token_rest_client_i import (
15
+ IQpuTokenRestClient,
16
+ )
17
+
18
+
19
+ class LunaQ(LunaPlatformClient, ILunaQ):
20
+ """Implementation of LunaQ service."""
21
+
22
+ qpu_token: IQpuTokenRestClient = None # type: ignore[assignment]
23
+ circuit: ICircuitRestClient = None # type: ignore[assignment]
24
+
25
+ def __init__(
26
+ self, api_key: str | None = None, timeout: float | None = 240.0
27
+ ) -> None:
28
+ """
29
+ LunaQ is the main entrypoint for all LunaQ related tasks.
30
+
31
+ Parameters
32
+ ----------
33
+ api_key: str
34
+ User's API key
35
+ timeout: float
36
+ Default timeout in seconds for the requests via the LunaQ client. `None`
37
+ means that the SDK uses no timeouts. Note that either way the Luna platform
38
+ itself will time out after 240 seconds.
39
+ Default: 240.0
40
+ """
41
+ super().__init__(api_key=api_key, api=LunaPrefixEnum.LUNA_Q, timeout=timeout)
42
+
43
+ self.circuit = CircuitRestClient(self)
44
+ self.qpu_token = QpuTokenRestClient(self)
45
+
46
+ @classmethod
47
+ def authenticate(cls, api_key: str) -> None:
48
+ """
49
+ Authenticate the client with the given API key.
50
+
51
+ Parameters
52
+ ----------
53
+ api_key : str
54
+ The API key used to authenticate the client.
55
+
56
+ Returns
57
+ -------
58
+ None
59
+ This method does not return any value.
60
+ """
61
+ cls(api_key=api_key)
62
+ cls._api_key = api_key
@@ -0,0 +1,125 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from luna_quantum.client.controllers.luna_platform_client import (
6
+ LunaPlatformClient,
7
+ LunaPrefixEnum,
8
+ )
9
+ from luna_quantum.client.interfaces.services.luna_solve_i import ILunaSolve
10
+ from luna_quantum.client.rest_client.info_rest_client import InfoRestClient
11
+ from luna_quantum.client.rest_client.model_rest_client import (
12
+ ModelRestClient,
13
+ )
14
+ from luna_quantum.client.rest_client.qpu_token_rest_client import QpuTokenRestClient
15
+ from luna_quantum.client.rest_client.solve_job_rest_client import SolveJobRestClient
16
+
17
+ if TYPE_CHECKING:
18
+ from luna_quantum.client.interfaces.clients import ISolveJobRestClient
19
+ from luna_quantum.client.interfaces.clients.info_rest_client_i import (
20
+ IInfoRestClient,
21
+ )
22
+ from luna_quantum.client.interfaces.clients.model_rest_client_i import (
23
+ IModelRestClient,
24
+ )
25
+ from luna_quantum.client.interfaces.clients.qpu_token_rest_client_i import (
26
+ IQpuTokenRestClient,
27
+ )
28
+
29
+
30
+ class LunaSolve(LunaPlatformClient, ILunaSolve):
31
+ """Implementation of LunaSolve service."""
32
+
33
+ _model: IModelRestClient
34
+ _solve_job: ISolveJobRestClient
35
+ _qpu_token: IQpuTokenRestClient
36
+ _info: IInfoRestClient
37
+
38
+ def __init__(
39
+ self, api_key: str | None = None, timeout: float | None = 240.0
40
+ ) -> None:
41
+ """
42
+ LunaSolve is the main entrypoint for all LunaSolve related tasks.
43
+
44
+ Parameters
45
+ ----------
46
+ api_key: str
47
+ User's API key
48
+ timeout: float
49
+ Default timeout in seconds for the requests via the LunaQ client. `None`
50
+ means that the SDK uses no timeouts. Note that either way the Luna platform
51
+ itself will time out after 240 seconds.
52
+ Default: 240.0
53
+ """
54
+ super().__init__(
55
+ api_key=api_key,
56
+ api=LunaPrefixEnum.LUNA_SOLVE,
57
+ timeout=timeout,
58
+ )
59
+
60
+ self._model = ModelRestClient(self)
61
+ self._solve_job = SolveJobRestClient(self)
62
+ self._qpu_token = QpuTokenRestClient(self)
63
+ self._info = InfoRestClient(self)
64
+
65
+ @classmethod
66
+ def authenticate(cls, api_key: str) -> None:
67
+ """
68
+ Authenticate the client with the given API key.
69
+
70
+ Parameters
71
+ ----------
72
+ api_key : str
73
+ The API key used to authenticate the client.
74
+
75
+ Returns
76
+ -------
77
+ None
78
+ This method does not return any value.
79
+ """
80
+ cls(api_key=api_key)
81
+ cls._api_key = api_key
82
+
83
+ @property
84
+ def model(self) -> IModelRestClient:
85
+ """
86
+ Returns a model rest client.
87
+
88
+ Returns
89
+ -------
90
+ IModelRestClient
91
+ """
92
+ return self._model
93
+
94
+ @property
95
+ def solve_job(self) -> ISolveJobRestClient:
96
+ """
97
+ Returns a solve job rest client.
98
+
99
+ Returns
100
+ -------
101
+ ISolveJobRestClient
102
+ """
103
+ return self._solve_job
104
+
105
+ @property
106
+ def qpu_token(self) -> IQpuTokenRestClient:
107
+ """
108
+ Returns a qpu token rest client.
109
+
110
+ Returns
111
+ -------
112
+ IQpuTokenRestClient
113
+ """
114
+ return self._qpu_token
115
+
116
+ @property
117
+ def info(self) -> IInfoRestClient:
118
+ """
119
+ Returns an info rest client.
120
+
121
+ Returns
122
+ -------
123
+ IInfoRestClient
124
+ """
125
+ return self._info
File without changes
@@ -0,0 +1,10 @@
1
+ from luna_quantum.client.error.luna_error import LunaError
2
+
3
+
4
+ class LunaApiKeyInvalidError(LunaError):
5
+ """Raised when the Luna API key is invalid."""
6
+
7
+ def __init__(self) -> None:
8
+ super().__init__(
9
+ "Luna API key is invalid. Please provide a valid Luna API key."
10
+ )
@@ -0,0 +1,10 @@
1
+ from luna_quantum.client.error.luna_error import LunaError
2
+
3
+
4
+ class LunaApiKeyMissingError(LunaError):
5
+ """Raised when the Luna API key is missing."""
6
+
7
+ def __init__(self) -> None:
8
+ super().__init__(
9
+ "Luna API key is missing. Please set the LUNA_API_KEY environment variable."
10
+ )
@@ -0,0 +1,2 @@
1
+ class LunaError(Exception):
2
+ """Base exception for all exceptions in the Luna SDK."""
@@ -0,0 +1,20 @@
1
+ from luna_quantum.client.error.luna_error import LunaError
2
+ from luna_quantum.client.schemas.error_message import ErrorMessage
3
+
4
+
5
+ class LunaServerError(LunaError):
6
+ """Luna HTTP server error."""
7
+
8
+ http_status_code: int
9
+ error_message: ErrorMessage
10
+
11
+ def __init__(self, http_status_code: int, error_message: ErrorMessage) -> None:
12
+ self.http_status_code = http_status_code
13
+ self.error_message = error_message
14
+ super().__init__(error_message.message)
15
+
16
+ def __str__(self) -> str: # noqa: D105
17
+ return (
18
+ f"The Luna-Server reported the error '{self.error_message.internal_code}' "
19
+ f"with the message:\n {self.error_message.message}"
20
+ )
@@ -0,0 +1,12 @@
1
+ from luna_quantum.client.error.luna_error import LunaError
2
+
3
+
4
+ class LunaTimeoutError(LunaError):
5
+ """Luna timeout error."""
6
+
7
+ def __init__(self) -> None:
8
+ super().__init__(
9
+ "Luna Timeout. The request took too long to complete."
10
+ " Please increase timeout value or try again later."
11
+ " If the problem persists, please contact our support team."
12
+ )
@@ -0,0 +1,18 @@
1
+ from luna_quantum.client.error.luna_error import LunaError
2
+
3
+
4
+ class TransformationError(LunaError):
5
+ """Luna transformation error."""
6
+
7
+ def __str__(self) -> str: # noqa: D105
8
+ return (
9
+ "An unexpected error occurred during transformation,"
10
+ " please contact support or open an issue."
11
+ )
12
+
13
+
14
+ class WeightedConstraintError(LunaError):
15
+ """Error if weighted constraints provided in CQM."""
16
+
17
+ def __str__(self) -> str: # noqa: D105
18
+ return "Weighted constraints for CQM are not supported"
File without changes