luna-quantum 1.0.0__cp312-cp312-macosx_11_0_arm64.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.cpython-312-darwin.so +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
File without changes
@@ -0,0 +1,79 @@
1
+ import logging
2
+ from collections.abc import Callable
3
+ from time import sleep
4
+ from typing import ClassVar
5
+
6
+ from luna_quantum.util.log_utils import Logging
7
+
8
+
9
+ class ActiveWaiting:
10
+ """
11
+ Provides active waiting functionality using a customizable loop.
12
+
13
+ The `ActiveWaiting` class offers a static method to perform a loop with
14
+ a sleep interval that increases iteratively, allowing the user to
15
+ regularly check a condition and optionally perform an additional action.
16
+ """
17
+
18
+ _logger: ClassVar[logging.Logger] = Logging.get_logger(__name__)
19
+
20
+ @staticmethod
21
+ def run(
22
+ loop_check: Callable[[], bool],
23
+ loop_call: Callable[[], None] | None = None,
24
+ sleep_time_max: float = 60.0,
25
+ sleep_time_increment: float = 5.0,
26
+ sleep_time_initial: float = 5.0,
27
+ ) -> None:
28
+ """
29
+ Execute a loop that checks a condition and optionally performs an action.
30
+
31
+ This function executes a loop that repeatedly checks a condition using a
32
+ callback function. If provided, it will also execute another callback after
33
+ each sleep period. The sleep time increases incrementally up to a maximum
34
+ value, starting from an initial sleep time.
35
+
36
+ Parameters
37
+ ----------
38
+ loop_check : Callable[[], bool]
39
+ A callable function that returns a boolean. The loop will continue as
40
+ long as this callable returns True.
41
+ loop_call : Optional[Callable[[], None]]
42
+ An optional callable function to be executed after each sleep period.
43
+ Defaults to None.
44
+ sleep_time_max : float
45
+ The maximum sleep time between condition checks. Defaults to 60.0 seconds.
46
+ sleep_time_increment : float
47
+ The amount of time to increment the sleep period after each iteration.
48
+ Defaults to 5.0 seconds.
49
+ sleep_time_initial : float
50
+ The initial sleep time before the first condition check. Defaults to
51
+ 5.0 seconds. If invalid (< 0.0), it will be adjusted to the default.
52
+
53
+ Raises
54
+ ------
55
+ ValueError
56
+ If `sleep_time_initial`, `sleep_time_increment`, or `sleep_time_max` are
57
+ non-positive values where a positive value is required.
58
+ """
59
+ cur_sleep_time: float
60
+
61
+ if sleep_time_initial > 0.0:
62
+ cur_sleep_time = sleep_time_initial
63
+ else:
64
+ cur_sleep_time = 5.0
65
+ ActiveWaiting._logger.warning(
66
+ f"Invalid sleep_time_initial: {sleep_time_initial},"
67
+ f" setting it to default value {cur_sleep_time}"
68
+ )
69
+
70
+ while loop_check():
71
+ ActiveWaiting._logger.info(
72
+ f"Sleeping for {cur_sleep_time} seconds. "
73
+ f"Waiting and checking a function in a loop."
74
+ )
75
+ sleep(cur_sleep_time)
76
+ cur_sleep_time += sleep_time_increment
77
+ cur_sleep_time = min(cur_sleep_time, sleep_time_max)
78
+ if loop_call:
79
+ loop_call()
@@ -0,0 +1,164 @@
1
+ from collections.abc import Callable
2
+ from functools import wraps
3
+ from typing import Any, Literal, TypeVar
4
+
5
+ from luna_quantum.exceptions.patch_class_field_exists_error import (
6
+ PatchClassFieldExistsError,
7
+ )
8
+
9
+ T = TypeVar("T") # To represent the return type of the decorated function
10
+
11
+
12
+ def add_to_class(
13
+ class_: type[Any],
14
+ method_type: Literal["normal", "static", "class", "property"] = "normal",
15
+ ) -> Callable[[Callable[..., T]], Callable[..., T]]:
16
+ """
17
+ Add a function as a method into a specified class.
18
+
19
+ The decorator facilitates adding a function to a class as a method. The
20
+ method can be of type 'normal' (instance method), 'static', 'class', or
21
+ 'property'. The function metadata is preserved during this process.
22
+
23
+ Parameters
24
+ ----------
25
+ class_ : Type
26
+ The class to which the function will be added.
27
+
28
+ method_type : {"normal", "static", "class", "property"}, optional
29
+ The type of method to integrate into the class. Defaults to "normal".
30
+ - "normal": Adds the function as an instance-level method.
31
+ - "static": Adds the function as a static method.
32
+ - "class": Adds the function as a class-level method.
33
+ - "property": Adds the function as a property.
34
+
35
+ Returns
36
+ -------
37
+ Callable
38
+ A callable decorator that, when applied to a function, integrates it
39
+ as the specified method type into the class.
40
+
41
+ """
42
+
43
+ def decorator(func: Callable[..., T]) -> Callable[..., T]:
44
+ # Preserve function metadata
45
+ @wraps(func)
46
+ def wrapped_func(*args: Any, **kwargs: Any) -> T:
47
+ return func(*args, **kwargs)
48
+
49
+ # Add the function to the class based on the method type
50
+ if method_type == "static":
51
+ setattr(class_, func.__name__, staticmethod(func)) # Add as static method
52
+ elif method_type == "class":
53
+ setattr(class_, func.__name__, classmethod(func)) # Add as class method
54
+ elif method_type == "property":
55
+ setattr(class_, func.__name__, property(func)) # Add as property
56
+ else: # Default is normal (instance-level method)
57
+ setattr(class_, func.__name__, func)
58
+
59
+ return wrapped_func
60
+
61
+ return decorator
62
+
63
+
64
+ def patch_instance(class_: type[Any]) -> Callable[[Callable[..., T]], Callable[..., T]]:
65
+ """
66
+ Patch a class with a "normal" method.
67
+
68
+ This function acts as a decorator that adds a new method to the given class.
69
+ The newly added method behaves as a standard instance method, meaning it
70
+ has access to the instance (`self`) when called.
71
+
72
+ Parameters
73
+ ----------
74
+ class_: The class to which the method will be added.
75
+
76
+ Returns
77
+ -------
78
+ A decorator function that takes the method to be added as its argument.
79
+ """
80
+ return add_to_class(class_, "normal")
81
+
82
+
83
+ def patch_static(class_: type[Any]) -> Callable[[Callable[..., T]], Callable[..., T]]:
84
+ """
85
+ Patch a class with a "static" method.
86
+
87
+ This function acts as a decorator that adds a new static method to the given class.
88
+ The newly added static method does not require an instance of the class to be
89
+ called.
90
+
91
+ Parameters
92
+ ----------
93
+ class_: The class to which the static method will be added.
94
+
95
+ Returns
96
+ -------
97
+ A decorator function that takes the static method to be added as its argument.
98
+ """
99
+ return add_to_class(class_, "static")
100
+
101
+
102
+ def patch_class(class_: type[Any]) -> Callable[[Callable[..., T]], Callable[..., T]]:
103
+ """
104
+ Patch a class with a "class" method.
105
+
106
+ This function acts as a decorator that adds a new class method to the given class.
107
+ The newly added method will have access to the class itself (`cls`) when called.
108
+
109
+ Parameters
110
+ ----------
111
+ class_: The class to which the class method will be added.
112
+
113
+ Returns
114
+ -------
115
+ A decorator function that takes the class method to be added as its argument.
116
+ """
117
+ return add_to_class(class_, "class")
118
+
119
+
120
+ def patch_property(class_: type[Any]) -> Callable[[Callable[..., T]], Callable[..., T]]:
121
+ """
122
+ Patch a class with a "property" method.
123
+
124
+ This function acts as a decorator that adds a new property to the given class.
125
+ The decorator converts the given method into a readable property.
126
+
127
+ Parameters
128
+ ----------
129
+ class_: The class to which the property will be added.
130
+
131
+ Returns
132
+ -------
133
+ A decorator function that takes the method to be added as a property.
134
+ """
135
+ return add_to_class(class_, "property")
136
+
137
+
138
+ def patch_field_to_class(
139
+ class_: type[Any],
140
+ field_name: str,
141
+ default_value: Any = None, # noqa: ANN401 we dont know the type in the decorator
142
+ ) -> None:
143
+ """
144
+ Add a new field to a class.
145
+
146
+ This function allows adding a field with a default value to the given class.
147
+ If the field already exists in the class, a `PatchClassFieldExistsError` is raised.
148
+
149
+ Parameters
150
+ ----------
151
+ class_: The class to which the field will be added.
152
+ field_name: The name of the field to be added.
153
+ default_value: The default value to assign to the field (optional).
154
+
155
+ Raises
156
+ ------
157
+ PatchClassFieldExistsError
158
+ If the class already has a field with the given name.
159
+ """
160
+ if hasattr(class_, field_name):
161
+ raise PatchClassFieldExistsError(
162
+ class_name=class_.__name__, field_name=field_name
163
+ )
164
+ setattr(class_, field_name, default_value)
@@ -0,0 +1,167 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from contextlib import contextmanager
5
+ from functools import wraps
6
+ from typing import TYPE_CHECKING, ClassVar, ParamSpec, TypeVar
7
+
8
+ from rich.console import Console
9
+ from rich.logging import RichHandler
10
+ from rich.progress import Progress, SpinnerColumn, TaskID, TextColumn
11
+ from rich.theme import Theme
12
+
13
+ if TYPE_CHECKING:
14
+ from collections.abc import Callable, Generator
15
+
16
+
17
+ P = ParamSpec("P")
18
+ T = TypeVar("T")
19
+
20
+
21
+ class Logging:
22
+ """Utilities for configuring and accessing Luna SDK loggers.
23
+
24
+ This class provides static methods to:
25
+ - Set and retrieve the global logging level for SDK components
26
+ - Create and configure loggers with Rich formatting
27
+ - Manage consistent logging behavior across the SDK
28
+ """
29
+
30
+ _log_level: ClassVar[int] = logging.INFO
31
+
32
+ @staticmethod
33
+ def set_level(log_level: int) -> None:
34
+ """Set the logging level for all SDK loggers.
35
+
36
+ Parameters
37
+ ----------
38
+ log_level : int
39
+ Logging level to set (e.g., logging.DEBUG, logging.INFO)
40
+ """
41
+ for logger_name in logging.root.manager.loggerDict:
42
+ if logger_name.startswith("luna_quantum"): # Only modify SDK loggers
43
+ logging.getLogger(logger_name).setLevel(log_level)
44
+
45
+ Logging._log_level = log_level
46
+
47
+ @staticmethod
48
+ def get_level() -> int:
49
+ """Return the current logging level for the SDK.
50
+
51
+ Returns
52
+ -------
53
+ int
54
+ Current logging level as defined in the logging module
55
+ (e.g., logging.DEBUG, logging.INFO, etc.)
56
+ """
57
+ return Logging._log_level
58
+
59
+ @staticmethod
60
+ def get_logger(name: str) -> logging.Logger:
61
+ """Get a logger with the specified name and set up a RichHandler for it.
62
+
63
+ Parameters
64
+ ----------
65
+ name : str
66
+ Name of the logger to retrieve or create
67
+
68
+ Returns
69
+ -------
70
+ logging.Logger
71
+ Configured logger instance with appropriate handlers
72
+ """
73
+ logger = logging.getLogger(name)
74
+ logger.setLevel(Logging._log_level)
75
+ logger.propagate = False
76
+
77
+ if logger.hasHandlers():
78
+ return logger
79
+
80
+ custom_theme = Theme(
81
+ {
82
+ "logging.level.debug": "bright_blue",
83
+ "logging.level.info": "bright_green",
84
+ "logging.level.warning": "bold bright_yellow",
85
+ "logging.level.error": "bold bright_red",
86
+ "logging.level.critical": "bold bright_magenta",
87
+ }
88
+ )
89
+ console = Console(theme=custom_theme)
90
+ handler = RichHandler(
91
+ console=console,
92
+ rich_tracebacks=True,
93
+ show_time=True,
94
+ show_level=True,
95
+ show_path=False,
96
+ log_time_format="%Y-%m-%d %H:%M:%S", # ISO 8601 format
97
+ )
98
+
99
+ logger.addHandler(handler)
100
+ return logger
101
+
102
+
103
+ @contextmanager
104
+ def progress_bar(
105
+ total: int | None, desc: str = "", unit: str = "steps"
106
+ ) -> Generator[tuple[Progress, TaskID], None, None]:
107
+ """Create a progress bar using Rich as a context manager.
108
+
109
+ Parameters
110
+ ----------
111
+ total: int | None
112
+ Total number of steps in the progress bar
113
+ desc: str
114
+ Description text to display next to the progress bar
115
+ unit: str
116
+ Unit label for the progress steps, by default "steps"
117
+
118
+ Yields
119
+ ------
120
+ tuple[Progress, TaskID]
121
+ A tuple containing the Progress object and task ID for updating
122
+ """
123
+ with Progress(
124
+ SpinnerColumn(),
125
+ TextColumn("[progress.description]{task.description}"),
126
+ console=Console(
127
+ theme=Theme(
128
+ {
129
+ "bar.back": "blue",
130
+ "bar.pulse": "bright_blue",
131
+ }
132
+ )
133
+ ),
134
+ transient=True,
135
+ ) as progress:
136
+ task = progress.add_task(f"[blue]{desc}", total=total, unit=unit)
137
+ yield progress, task # Yield both progress and task for updates
138
+
139
+
140
+ def progress(
141
+ total: int | None,
142
+ desc: str = "",
143
+ unit: str = "steps",
144
+ ) -> Callable[[Callable[P, T]], Callable[P, T]]:
145
+ """
146
+ Decorate a func with a progress-bar.
147
+
148
+ Parameters
149
+ ----------
150
+ total: int | None
151
+ Total number of steps in the progress bar
152
+ desc: str
153
+ Description text to display next to the progress bar
154
+ unit: str
155
+ Unit label for the progress steps, by default "steps"
156
+
157
+ """
158
+
159
+ def decorated_func(func: Callable[P, T]) -> Callable[P, T]:
160
+ @wraps(func)
161
+ def decorator(*args: P.args, **kwargs: P.kwargs) -> T:
162
+ with progress_bar(total=total, desc=desc, unit=unit):
163
+ return func(*args, **kwargs)
164
+
165
+ return decorator
166
+
167
+ return decorated_func
@@ -0,0 +1,67 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import datetime
4
+
5
+ from pydantic import BaseModel
6
+
7
+
8
+ class PrettyBase(BaseModel):
9
+ """Helper class to implement pretty print."""
10
+
11
+ def _pretty_print(self, data: dict, indent: int = 0) -> str: # type: ignore[type-arg]
12
+ """Return nested dictionaries in a readable YAML-inspired format as a string.
13
+
14
+ This format enhances human readability by using a YAML-like structured style.
15
+
16
+ Parameters
17
+ ----------
18
+ data: dict
19
+ indent: int
20
+ """
21
+ output = ""
22
+ for key, value in data.items():
23
+ output += " " * indent + str(key) + ":"
24
+ if isinstance(value, dict):
25
+ if value == {}:
26
+ output += " {}\n"
27
+ else:
28
+ output += "\n"
29
+ output += self._pretty_print(value, indent + 1)
30
+ elif isinstance(value, datetime):
31
+ output += f" {value.strftime('%Y-%m-%d %H:%M:%S (%Z)')}\n"
32
+ else:
33
+ output += f" {value}\n"
34
+ return output
35
+
36
+ def __str__(self) -> str:
37
+ """Override the default object string representation."""
38
+ data = self.model_dump()
39
+
40
+ return self._pretty_print(data)
41
+
42
+ @property
43
+ def head(self) -> str:
44
+ """Print a truncated version of the pretty print console representation."""
45
+ limit = 20
46
+
47
+ def truncate(data: dict, limit: int) -> tuple[dict, bool]: # type: ignore[type-arg]
48
+ if data is None:
49
+ return None, False
50
+
51
+ if isinstance(data, dict):
52
+ d = {
53
+ k: truncate(v, limit)[0]
54
+ for i, (k, v) in enumerate(data.items())
55
+ if i < limit
56
+ }
57
+ return d, len(data) > limit
58
+ if isinstance(data, list):
59
+ d = data[:limit]
60
+ return d, len(data) > limit
61
+ return data, False
62
+
63
+ data = self.model_dump()
64
+
65
+ data_truncated, is_truncated = truncate(data, limit)
66
+
67
+ return self._pretty_print(data_truncated)
@@ -0,0 +1,38 @@
1
+ from typing import TypeVar
2
+
3
+ from pydantic import BaseModel
4
+
5
+ T = TypeVar("T", bound=BaseModel)
6
+
7
+
8
+ class PydanticUtils:
9
+ """A utility class for operations on Pydantic models."""
10
+
11
+ @staticmethod
12
+ def update_model(to_update: T, other_model: T) -> None:
13
+ """
14
+ Update the attributes of a given pydantic model.
15
+
16
+ This function works by iterating over the attributes
17
+ of the second model (provided as input) and assigns the corresponding values
18
+ to the attributes of the first model.
19
+
20
+ Parameters
21
+ ----------
22
+ to_update : T
23
+ The model instance whose attributes need to be updated. This instance
24
+ will have its attributes overridden with the corresponding values from
25
+ the other model instance.
26
+ other_model : T
27
+ The model instance providing the new values for the update. Its
28
+ attributes are used to overwrite the attributes of the `to_update`
29
+ instance.
30
+
31
+ Returns
32
+ -------
33
+ None
34
+ This function does not return a value. Instead, it updates the
35
+ `to_update` instance in place.
36
+ """
37
+ for key, value in other_model.model_dump().items():
38
+ setattr(to_update, key, value)
luna_quantum/utils.py ADDED
@@ -0,0 +1,54 @@
1
+ from collections.abc import Iterable
2
+
3
+ from ._core import Expression, Variable
4
+
5
+
6
+ def quicksum(
7
+ iterable: Iterable[Expression | Variable | int | float],
8
+ /,
9
+ start: Expression | None = None,
10
+ ) -> Expression:
11
+ """
12
+ Create an Expression based on an iterable of Expression, Variable, int or float elements.
13
+ Note that either the `iterable` must contain at least one `Expression` or `Variable` or
14
+ the start parameter is set.
15
+
16
+ Parameters
17
+ ----------
18
+ iterable : Iterable[Expression | Variable | int | float]
19
+ The iterable of elements to sum up.
20
+ start : Expression | None, optional
21
+ The starting value for the summation.
22
+
23
+ Returns
24
+ -------
25
+ Expression
26
+ The expression created based on the sum of the iterable elements.
27
+
28
+ Raises
29
+ ------
30
+ TypeError
31
+ If the `iterable` does not contain any Expression or Variable.
32
+ If the `start` is not of type Expression.
33
+ """
34
+ items = list(iterable)
35
+ if start is None:
36
+ for item in items:
37
+ if isinstance(item, Expression) or isinstance(item, Variable):
38
+ start = Expression(env=item._environment) # type: ignore
39
+ break
40
+
41
+ if start is None:
42
+ raise TypeError(
43
+ "iterable must contain at least one Expression or Variable,or 'start' needs to be set."
44
+ )
45
+
46
+ if not isinstance(start, Expression):
47
+ raise TypeError("start must be of type `Expression`")
48
+
49
+ _start: Expression = start
50
+
51
+ for item in items:
52
+ _start += item
53
+
54
+ return _start
luna_quantum/utils.pyi ADDED
@@ -0,0 +1,35 @@
1
+ from collections.abc import Iterable
2
+ from typing import overload
3
+
4
+ from aqmodels import Expression, Variable
5
+
6
+ @overload
7
+ def quicksum(iterable: Iterable[Expression], /) -> Expression: ...
8
+ @overload
9
+ def quicksum(iterable: Iterable[Variable], /) -> Expression: ...
10
+ @overload
11
+ def quicksum(iterable: Iterable[int], /) -> Expression: ...
12
+ @overload
13
+ def quicksum(iterable: Iterable[float], /) -> Expression: ...
14
+ @overload
15
+ def quicksum(
16
+ iterable: Iterable[Expression], /, start: Expression | None = None
17
+ ) -> Expression: ...
18
+ @overload
19
+ def quicksum(
20
+ iterable: Iterable[Variable], /, start: Expression | None = None
21
+ ) -> Expression: ...
22
+ @overload
23
+ def quicksum(
24
+ iterable: Iterable[int], /, start: Expression | None = None
25
+ ) -> Expression: ...
26
+ @overload
27
+ def quicksum(
28
+ iterable: Iterable[float], /, start: Expression | None = None
29
+ ) -> Expression: ...
30
+ @overload
31
+ def quicksum(
32
+ iterable: Iterable[Expression | Variable | float | int],
33
+ /,
34
+ start: Expression | None = None,
35
+ ) -> Expression: ...
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: luna-quantum
3
+ Version: 1.0.0
4
+ Classifier: Programming Language :: Python :: 3
5
+ Classifier: License :: OSI Approved :: Apache Software License
6
+ Classifier: Operating System :: OS Independent
7
+ Classifier: Topic :: Scientific/Engineering
8
+ Requires-Dist: httpx>=0.28.1,<0.29
9
+ Requires-Dist: numpy>=1
10
+ Requires-Dist: pydantic[email]>=2.11.3,<3
11
+ Requires-Dist: python-dateutil>=2.9.0,<3
12
+ Requires-Dist: rich>=14.0.0
13
+ Requires-Dist: networkx>=3.4.2,<4 ; extra == 'examples'
14
+ Provides-Extra: examples
15
+ License-File: LICENSE
16
+ License-File: NOTICE
17
+ Summary: Python SDK for Aqarios' Luna Platform
18
+ Keywords: aqarios,luna,quantum computing,quantum optimization,optimization,sdk
19
+ Author-email: Aqarios <pypi@aqarios.com>
20
+ License: Apache-2.0
21
+ Requires-Python: >=3.11.0, <4
22
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
23
+ Project-URL: Homepage, https://aqarios.com/
24
+ Project-URL: Documentation, https://docs.aqarios.com/
25
+
26
+ # Luna Quantum SDK
27
+ Luna is a platform developed by [Aqarios](https://aqarios.com/) designed to facilitate access to and utilization of quantum computing for both industry and academia. The SDK serves as a Python wrapper for interfacing with the API, offering a more intuitive means of engaging with the platform. This library grants access to the LunaSolve and LunaQ services.
28
+
29
+ # Installation
30
+ The package is released on PyPI and can be installed via pip:
31
+ ```
32
+ pip install --upgrade luna-quantum
33
+ ```
34
+
35
+ # Getting Started
36
+ For more details and tutorials on how to use the Luna SDK, refer to the documentation located here: [Aqarios Luna](https://docs.aqarios.com/).
37
+