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.

Files changed (160) hide show
  1. luna_quantum-0.0.16.dist-info/LICENSE +201 -0
  2. luna_quantum-0.0.16.dist-info/METADATA +46 -0
  3. luna_quantum-0.0.16.dist-info/RECORD +160 -0
  4. luna_quantum-0.0.16.dist-info/WHEEL +4 -0
  5. luna_sdk/__init__.py +2 -0
  6. luna_sdk/constants.py +1 -0
  7. luna_sdk/controllers/__init__.py +2 -0
  8. luna_sdk/controllers/custom_login_client.py +61 -0
  9. luna_sdk/controllers/luna_platform_client.py +62 -0
  10. luna_sdk/controllers/luna_q.py +36 -0
  11. luna_sdk/controllers/luna_solve.py +49 -0
  12. luna_sdk/controllers/luna_transform.py +41 -0
  13. luna_sdk/error/__init__.py +0 -0
  14. luna_sdk/error/http_error_utils.py +100 -0
  15. luna_sdk/exceptions/__init__.py +1 -0
  16. luna_sdk/exceptions/encryption_exception.py +6 -0
  17. luna_sdk/exceptions/luna_exception.py +7 -0
  18. luna_sdk/exceptions/luna_server_exception.py +18 -0
  19. luna_sdk/exceptions/timeout_exception.py +10 -0
  20. luna_sdk/exceptions/transformation.py +11 -0
  21. luna_sdk/interfaces/__init__.py +5 -0
  22. luna_sdk/interfaces/circuit_repo_i.py +62 -0
  23. luna_sdk/interfaces/clients/__init__.py +0 -0
  24. luna_sdk/interfaces/clients/client_i.py +10 -0
  25. luna_sdk/interfaces/clients/luna_q_i.py +39 -0
  26. luna_sdk/interfaces/clients/luna_solve_i.py +37 -0
  27. luna_sdk/interfaces/clients/luna_transform_i.py +33 -0
  28. luna_sdk/interfaces/cplex_repo_i.py +121 -0
  29. luna_sdk/interfaces/info_repo_i.py +40 -0
  30. luna_sdk/interfaces/lp_repo_i.py +106 -0
  31. luna_sdk/interfaces/optimization_repo_i.py +262 -0
  32. luna_sdk/interfaces/qpu_token_repo_i.py +151 -0
  33. luna_sdk/interfaces/repository_i.py +14 -0
  34. luna_sdk/interfaces/solutions_repo_i.py +219 -0
  35. luna_sdk/py.typed +0 -0
  36. luna_sdk/repositories/__init__.py +4 -0
  37. luna_sdk/repositories/circuit_repo.py +104 -0
  38. luna_sdk/repositories/cplex_repo.py +118 -0
  39. luna_sdk/repositories/info_repo.py +45 -0
  40. luna_sdk/repositories/lp_repo.py +105 -0
  41. luna_sdk/repositories/optimization_repo.py +358 -0
  42. luna_sdk/repositories/qpu_token_repo.py +226 -0
  43. luna_sdk/repositories/solutions_repo.py +347 -0
  44. luna_sdk/schemas/__init__.py +4 -0
  45. luna_sdk/schemas/circuit.py +43 -0
  46. luna_sdk/schemas/create/__init__.py +3 -0
  47. luna_sdk/schemas/create/circuit.py +29 -0
  48. luna_sdk/schemas/create/optimization.py +22 -0
  49. luna_sdk/schemas/create/qpu_token.py +26 -0
  50. luna_sdk/schemas/create/qubo.py +19 -0
  51. luna_sdk/schemas/create/solution.py +15 -0
  52. luna_sdk/schemas/enums/__init__.py +0 -0
  53. luna_sdk/schemas/enums/circuit.py +14 -0
  54. luna_sdk/schemas/enums/optimization.py +10 -0
  55. luna_sdk/schemas/enums/problem.py +48 -0
  56. luna_sdk/schemas/enums/qpu_token_type.py +6 -0
  57. luna_sdk/schemas/enums/solution.py +8 -0
  58. luna_sdk/schemas/enums/status.py +10 -0
  59. luna_sdk/schemas/enums/timeframe.py +11 -0
  60. luna_sdk/schemas/error_message.py +12 -0
  61. luna_sdk/schemas/optimization.py +75 -0
  62. luna_sdk/schemas/optimization_formats/__init__.py +0 -0
  63. luna_sdk/schemas/optimization_formats/bqm.py +34 -0
  64. luna_sdk/schemas/optimization_formats/cqm.py +127 -0
  65. luna_sdk/schemas/optimization_formats/lp.py +9 -0
  66. luna_sdk/schemas/optimization_formats/qm.py +30 -0
  67. luna_sdk/schemas/pretty_base.py +49 -0
  68. luna_sdk/schemas/qpu_token.py +60 -0
  69. luna_sdk/schemas/representation.py +19 -0
  70. luna_sdk/schemas/rest/__init__.py +0 -0
  71. luna_sdk/schemas/rest/qpu_token/__init__.py +0 -0
  72. luna_sdk/schemas/rest/qpu_token/token_provider.py +45 -0
  73. luna_sdk/schemas/solution.py +227 -0
  74. luna_sdk/schemas/solver_info.py +11 -0
  75. luna_sdk/schemas/solver_parameters/aws/__init__.py +1 -0
  76. luna_sdk/schemas/solver_parameters/aws/qaoa.py +24 -0
  77. luna_sdk/schemas/solver_parameters/dwave/__init__.py +72 -0
  78. luna_sdk/schemas/solver_parameters/dwave/base.py +409 -0
  79. luna_sdk/schemas/solver_parameters/dwave/dialectic_search.py +31 -0
  80. luna_sdk/schemas/solver_parameters/dwave/kerberos.py +71 -0
  81. luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_bqm.py +19 -0
  82. luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_cqm.py +22 -0
  83. luna_sdk/schemas/solver_parameters/dwave/parallel_tempering.py +30 -0
  84. luna_sdk/schemas/solver_parameters/dwave/parallel_tempering_qpu.py +37 -0
  85. luna_sdk/schemas/solver_parameters/dwave/population_annealing.py +25 -0
  86. luna_sdk/schemas/solver_parameters/dwave/population_annealing_qpu.py +35 -0
  87. luna_sdk/schemas/solver_parameters/dwave/qaga.py +56 -0
  88. luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_qpu.py +19 -0
  89. luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_simulated_annealing.py +22 -0
  90. luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_tabu_search.py +21 -0
  91. luna_sdk/schemas/solver_parameters/dwave/quantum_annealing.py +20 -0
  92. luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_quantum_annealing.py +82 -0
  93. luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_simulated_annealing.py +89 -0
  94. luna_sdk/schemas/solver_parameters/dwave/saga.py +61 -0
  95. luna_sdk/schemas/solver_parameters/dwave/simulated_annealing.py +74 -0
  96. luna_sdk/schemas/solver_parameters/dwave/tabu_search.py +72 -0
  97. luna_sdk/schemas/solver_parameters/fujitsu/__init__.py +20 -0
  98. luna_sdk/schemas/solver_parameters/fujitsu/base.py +47 -0
  99. luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_cpu.py +129 -0
  100. luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_v2.py +149 -0
  101. luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_v3.py +150 -0
  102. luna_sdk/schemas/solver_parameters/fujitsu/partial_config.py +177 -0
  103. luna_sdk/schemas/solver_parameters/ibm/__init__.py +4 -0
  104. luna_sdk/schemas/solver_parameters/ibm/qaoa.py +64 -0
  105. luna_sdk/schemas/solver_parameters/ibm/standard_parameters.py +27 -0
  106. luna_sdk/schemas/solver_parameters/ibm/vqe.py +49 -0
  107. luna_sdk/schemas/solver_parameters/qctrl/__init__.py +1 -0
  108. luna_sdk/schemas/solver_parameters/qctrl/qaoa.py +47 -0
  109. luna_sdk/schemas/transformations/__init__.py +2 -0
  110. luna_sdk/schemas/transformations/bqm.py +33 -0
  111. luna_sdk/schemas/transformations/matrix.py +12 -0
  112. luna_sdk/schemas/use_cases/__init__.py +54 -0
  113. luna_sdk/schemas/use_cases/arbitrage_edge_based.py +49 -0
  114. luna_sdk/schemas/use_cases/arbitrage_node_based.py +54 -0
  115. luna_sdk/schemas/use_cases/base.py +5 -0
  116. luna_sdk/schemas/use_cases/binary_integer_linear_programming.py +53 -0
  117. luna_sdk/schemas/use_cases/binary_paint_shop_problem.py +36 -0
  118. luna_sdk/schemas/use_cases/credit_scoring_feature_selection.py +39 -0
  119. luna_sdk/schemas/use_cases/dynamic_portfolio_optimization.py +63 -0
  120. luna_sdk/schemas/use_cases/exact_cover.py +50 -0
  121. luna_sdk/schemas/use_cases/flight_gate_assignment.py +78 -0
  122. luna_sdk/schemas/use_cases/graph_coloring.py +41 -0
  123. luna_sdk/schemas/use_cases/graph_isomorphism.py +53 -0
  124. luna_sdk/schemas/use_cases/graph_partitioning.py +45 -0
  125. luna_sdk/schemas/use_cases/hamiltonian_cycle.py +48 -0
  126. luna_sdk/schemas/use_cases/induced_subgraph_isomorphism.py +49 -0
  127. luna_sdk/schemas/use_cases/job_shop_scheduling.py +43 -0
  128. luna_sdk/schemas/use_cases/k_medoids_clustering.py +48 -0
  129. luna_sdk/schemas/use_cases/knapsack_integer_weights.py +55 -0
  130. luna_sdk/schemas/use_cases/linear_regression.py +59 -0
  131. luna_sdk/schemas/use_cases/lmwcs.py +80 -0
  132. luna_sdk/schemas/use_cases/longest_path.py +49 -0
  133. luna_sdk/schemas/use_cases/market_graph_clustering.py +60 -0
  134. luna_sdk/schemas/use_cases/max2sat.py +51 -0
  135. luna_sdk/schemas/use_cases/max3sat.py +52 -0
  136. luna_sdk/schemas/use_cases/max_clique.py +59 -0
  137. luna_sdk/schemas/use_cases/max_cut.py +47 -0
  138. luna_sdk/schemas/use_cases/max_independent_set.py +36 -0
  139. luna_sdk/schemas/use_cases/minimal_maximal_matching.py +53 -0
  140. luna_sdk/schemas/use_cases/minimal_spanning_tree.py +87 -0
  141. luna_sdk/schemas/use_cases/minimum_vertex_cover.py +44 -0
  142. luna_sdk/schemas/use_cases/number_partitioning.py +31 -0
  143. luna_sdk/schemas/use_cases/portfolio_optimization.py +45 -0
  144. luna_sdk/schemas/use_cases/portfolio_optimization_ib_tv.py +62 -0
  145. luna_sdk/schemas/use_cases/quadratic_assignment.py +48 -0
  146. luna_sdk/schemas/use_cases/quadratic_knapsack.py +47 -0
  147. luna_sdk/schemas/use_cases/satellite_scheduling.py +72 -0
  148. luna_sdk/schemas/use_cases/sensor_placement.py +57 -0
  149. luna_sdk/schemas/use_cases/set_cover.py +55 -0
  150. luna_sdk/schemas/use_cases/set_packing.py +53 -0
  151. luna_sdk/schemas/use_cases/set_partitioning.py +51 -0
  152. luna_sdk/schemas/use_cases/subgraph_isomorphism.py +56 -0
  153. luna_sdk/schemas/use_cases/subset_sum.py +36 -0
  154. luna_sdk/schemas/use_cases/support_vector_machine.py +63 -0
  155. luna_sdk/schemas/use_cases/traffic_flow.py +34 -0
  156. luna_sdk/schemas/use_cases/travelling_salesman_problem.py +52 -0
  157. luna_sdk/schemas/use_cases/type_aliases.py +11 -0
  158. luna_sdk/schemas/use_cases/weighted_max_cut.py +36 -0
  159. luna_sdk/utils/__init__.py +0 -0
  160. luna_sdk/utils/qpu_tokens.py +52 -0
@@ -0,0 +1,75 @@
1
+ from datetime import datetime
2
+ from typing import Any, Dict, Generic, List, Optional, TypeVar
3
+
4
+ from pydantic import BaseModel, Extra
5
+
6
+ from luna_sdk.schemas.enums.optimization import InputType
7
+ from luna_sdk.schemas.optimization_formats.bqm import BQMSchema
8
+ from luna_sdk.schemas.optimization_formats.cqm import CQMSchema
9
+ from luna_sdk.schemas.optimization_formats.lp import LPSchema
10
+ from luna_sdk.schemas.pretty_base import PrettyBase
11
+
12
+
13
+ class Optimization(PrettyBase):
14
+ """
15
+ Pydantic model for optimization going OUT.
16
+ Attributes
17
+ ----------
18
+ id: str
19
+ Id of the optimization
20
+ created_date: Optional[datetime]
21
+ Date when optimization was created
22
+ created_by: Optional[str]
23
+ Id of the user who created optimization
24
+ modified_date: Optional[datetime]
25
+ Date when optimization was modified
26
+ modified_by: Optional[str]
27
+ Id of the user who modified optimization
28
+ """
29
+
30
+ id: str
31
+ name: Optional[str] = None
32
+ created_date: datetime
33
+ created_by: str
34
+ modified_date: Optional[datetime] = None
35
+ modified_by: Optional[str] = None
36
+ input_type: Optional[InputType] = None
37
+ use_case_name: Optional[str] = None
38
+ params: Optional[Dict[str, Any]] = None
39
+
40
+ class Config:
41
+ extra = Extra.ignore
42
+ from_attributes = False
43
+
44
+
45
+ class OptimizationQubo(BaseModel):
46
+ id: str
47
+ name: Optional[str] = None
48
+ created_date: datetime
49
+ created_by: str
50
+ modified_date: Optional[datetime] = None
51
+ modified_by: Optional[str] = None
52
+
53
+ matrix: List[List[float]]
54
+
55
+
56
+ class OptimizationBQM(Optimization, BQMSchema): ...
57
+
58
+
59
+ class OptimizationCQM(Optimization, CQMSchema): ...
60
+
61
+
62
+ class OptimizationLP(Optimization, LPSchema): ...
63
+
64
+
65
+ class OptimizationUseCase(Optimization, BQMSchema):
66
+ use_case: Dict[str, Any]
67
+
68
+
69
+ T = TypeVar("T")
70
+
71
+
72
+ class OptimizationCreate(BaseModel, Generic[T]):
73
+ """Pydantic model for optimization coming IN."""
74
+
75
+ instance: T
File without changes
@@ -0,0 +1,34 @@
1
+ from enum import Enum
2
+ from typing import Optional
3
+
4
+ from dimod import BinaryQuadraticModel
5
+
6
+ from luna_sdk.schemas.optimization_formats.qm import QMSchema
7
+
8
+
9
+ class BQMVarType(str, Enum):
10
+ SPIN = "SPIN"
11
+ BINARY = "BINARY"
12
+
13
+
14
+ class BQMSchema(QMSchema):
15
+ vartype: BQMVarType
16
+ offset: Optional[float] = None
17
+
18
+ @classmethod
19
+ def from_bqm(cls, bqm: BinaryQuadraticModel) -> "BQMSchema":
20
+ return cls(
21
+ vartype=BQMVarType(bqm.vartype.name),
22
+ quadratic={k: v for k, v in bqm.quadratic.items()},
23
+ linear={k: v for k, v in bqm.linear.items()},
24
+ offset=float(bqm.offset) if bqm.offset is not None else None,
25
+ )
26
+
27
+ def to_bqm(self) -> BinaryQuadraticModel:
28
+ bqm = BinaryQuadraticModel(
29
+ self.linear,
30
+ self._parsed_quadratic,
31
+ offset=self.offset,
32
+ vartype=self.vartype,
33
+ )
34
+ return bqm
@@ -0,0 +1,127 @@
1
+ from enum import Enum
2
+ from typing import Dict, Tuple, List, Union, Optional
3
+
4
+ from dimod import ConstrainedQuadraticModel, QuadraticModel
5
+ from pydantic import BaseModel
6
+
7
+ from luna_sdk.exceptions.transformation import WeightedConstraintException
8
+ from luna_sdk.schemas.optimization_formats.qm import QMSchema
9
+
10
+
11
+ class CQMVarType(str, Enum):
12
+ SPIN = "SPIN"
13
+ BINARY = "BINARY"
14
+ INTEGER = "INTEGER"
15
+ REAL = "REAL"
16
+
17
+
18
+ class QuadraticModelSchema(QMSchema):
19
+ offset: Union[float, int]
20
+ var_types: Dict[str, CQMVarType]
21
+
22
+
23
+ class CQMSense(str, Enum):
24
+ Le = "<="
25
+ Ge = ">="
26
+ Eq = "=="
27
+
28
+
29
+ class CQMPenaltyEnum(str, Enum):
30
+ linear = "linear"
31
+ quadratic = "quadratic"
32
+
33
+
34
+ class CQMConstraintsSchema(BaseModel):
35
+ qm: QuadraticModelSchema
36
+ sense: CQMSense
37
+ rhs: Union[float, int]
38
+ label: str
39
+ penalty: CQMPenaltyEnum
40
+
41
+
42
+ class CQMVariableSchema(BaseModel):
43
+ var_type: CQMVarType
44
+ name: str
45
+ lower_bound: Optional[float]
46
+ upper_bound: Optional[float]
47
+
48
+
49
+ class CQMSchema(BaseModel):
50
+ constraints: Dict[str, CQMConstraintsSchema]
51
+ objective: QuadraticModelSchema
52
+ variables: List[CQMVariableSchema]
53
+
54
+ @classmethod
55
+ def from_cqm(cls, cqm: ConstrainedQuadraticModel) -> "CQMSchema":
56
+ var_types = {v: CQMVarType[cqm.vartype(v).name] for v in cqm.variables}
57
+ constraints = {}
58
+ for name, constraint in cqm.constraints.items():
59
+ if constraint.lhs.is_soft():
60
+ raise WeightedConstraintException
61
+ constr = CQMConstraintsSchema(
62
+ qm=QuadraticModelSchema(
63
+ linear=constraint.lhs.linear,
64
+ quadratic=constraint.lhs.quadratic,
65
+ offset=constraint.lhs.offset,
66
+ var_types=var_types,
67
+ ),
68
+ sense=CQMSense[constraint.sense.name],
69
+ rhs=constraint.rhs,
70
+ label=name,
71
+ penalty=CQMPenaltyEnum.linear,
72
+ )
73
+ constraints[name] = constr
74
+ objective = QuadraticModelSchema(
75
+ linear=cqm.objective.linear,
76
+ quadratic=cqm.objective.quadratic,
77
+ offset=cqm.objective.offset,
78
+ var_types=var_types,
79
+ )
80
+ variables = []
81
+ for var in cqm.variables:
82
+ variables.append(
83
+ CQMVariableSchema(
84
+ name=var,
85
+ var_type=var_types[var],
86
+ lower_bound=cqm.lower_bound(var),
87
+ upper_bound=cqm.upper_bound(var),
88
+ )
89
+ )
90
+ return cls(
91
+ constraints=constraints,
92
+ objective=objective,
93
+ variables=variables,
94
+ )
95
+
96
+ def to_cqm(self) -> ConstrainedQuadraticModel:
97
+ cqm = ConstrainedQuadraticModel()
98
+ for variable in self.variables:
99
+ cqm.add_variable(vartype=variable.var_type, v=variable.name)
100
+ for name, constraint in self.constraints.items():
101
+ qm = QuadraticModel(
102
+ linear=constraint.qm.linear, # type: ignore[arg-type]
103
+ quadratic=constraint.qm._parsed_quadratic, # type: ignore[arg-type]
104
+ offset=constraint.qm.offset,
105
+ vartypes=constraint.qm.var_types, # type: ignore[arg-type]
106
+ )
107
+ cqm.add_constraint_from_model(
108
+ qm=qm,
109
+ sense=constraint.sense,
110
+ rhs=constraint.rhs,
111
+ label=constraint.label,
112
+ penalty=constraint.penalty,
113
+ )
114
+ objective = QuadraticModel(
115
+ linear=self.objective.linear, # type: ignore[arg-type]
116
+ quadratic=self.objective._parsed_quadratic, # type: ignore[arg-type]
117
+ offset=self.objective.offset,
118
+ vartypes=self.objective.var_types, # type: ignore[arg-type]
119
+ )
120
+ cqm.set_objective(objective)
121
+ for variable in self.variables:
122
+ if variable.var_type not in (CQMVarType.BINARY, CQMVarType.SPIN):
123
+ if variable.upper_bound is not None:
124
+ cqm.set_upper_bound(variable.name, variable.upper_bound)
125
+ if variable.lower_bound is not None:
126
+ cqm.set_lower_bound(variable.name, variable.lower_bound)
127
+ return cqm
@@ -0,0 +1,9 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class LPSchema(BaseModel):
5
+ lp_string: str
6
+
7
+ @classmethod
8
+ def from_lp(cls, lp: str) -> "LPSchema":
9
+ return cls(lp_string=lp)
@@ -0,0 +1,30 @@
1
+ from typing import Any, Dict, Tuple
2
+
3
+ from pydantic import BaseModel, field_validator
4
+
5
+
6
+ class QMSchema(BaseModel):
7
+ quadratic: Dict[str, float]
8
+ linear: Dict[str, float]
9
+
10
+ @property
11
+ def _parsed_quadratic(self) -> Dict[Tuple[str, ...], float]:
12
+ q = {}
13
+ for k, v in self.quadratic.items():
14
+ parsed_key = eval(k) if isinstance(k, str) else k
15
+ formatted_key = tuple(
16
+ str(x) if not isinstance(x, str) else x for x in parsed_key
17
+ )
18
+ q[formatted_key] = v
19
+ return q
20
+
21
+ @field_validator("quadratic", mode="before")
22
+ @classmethod
23
+ def transform_quadratic(cls, quadratic: Dict[Any, Any]) -> Dict[str, Any]:
24
+ if quadratic:
25
+ q = {}
26
+ for k, v in quadratic.items():
27
+ k = str(k) if not isinstance(k, str) else k
28
+ q[k] = v
29
+ return q
30
+ return quadratic
@@ -0,0 +1,49 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class PrettyBase(BaseModel):
5
+ def _pretty_print(self, data: dict, indent: int = 0) -> str:
6
+ """Helper function to pretty print nested dictionaries in a readable yaml inspired format"""
7
+ output = ""
8
+ for key, value in data.items():
9
+ output += " " * indent + str(key) + ":"
10
+ if isinstance(value, dict):
11
+ output += "\n"
12
+ output += self._pretty_print(value, indent + 1)
13
+ else:
14
+ output += " " + str(value) + "\n"
15
+ return output
16
+
17
+ def __str__(self):
18
+ """Overwrite the default object string representation to use the custom pretty print console representation"""
19
+ data = self.model_dump()
20
+
21
+ return self._pretty_print(data)
22
+
23
+ @property
24
+ def head(self):
25
+ """Print a truncated version of the pretty print console representation"""
26
+ limit = 20
27
+
28
+ def truncate(data, limit):
29
+ if data is None:
30
+ return None, False
31
+
32
+ if isinstance(data, dict):
33
+ d = {
34
+ k: truncate(v, limit)[0]
35
+ for i, (k, v) in enumerate(data.items())
36
+ if i < limit
37
+ }
38
+ return d, len(data) > limit
39
+ elif isinstance(data, list):
40
+ d = data[:limit]
41
+ return d, len(data) > limit
42
+ else:
43
+ return data, False
44
+
45
+ data = self.model_dump()
46
+
47
+ data_truncated, is_truncated = truncate(data, limit)
48
+
49
+ return self._pretty_print(data_truncated)
@@ -0,0 +1,60 @@
1
+ from enum import Enum
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, Extra
5
+
6
+
7
+ class QpuTokenSource(str, Enum):
8
+ # token currently passed in from the API call (not stored by us)
9
+ INLINE = "inline"
10
+ # stored token in user account
11
+ PERSONAL = "personal"
12
+ # stored token in group account
13
+ ORGANIZATION = "organization"
14
+
15
+
16
+ class QpuToken(BaseModel):
17
+ source: QpuTokenSource
18
+ # A unique name for a stored token
19
+ name: Optional[str] = None
20
+ # This could be a QPU token, an API key or any token key for a QPU provider.
21
+ # If the token is not passed from this API call, one stored in the user's
22
+ # account will be used.
23
+ token: Optional[str] = None
24
+
25
+
26
+ class TokenProvider(BaseModel):
27
+ dwave: Optional[QpuToken] = None
28
+ ibm: Optional[QpuToken] = None
29
+ fujitsu: Optional[QpuToken] = None
30
+ qctrl: Optional[QpuToken] = None
31
+ aws_access_key: Optional[QpuToken] = None
32
+ aws_secret_access_key: Optional[QpuToken] = None
33
+
34
+ class Config:
35
+ extra = Extra.forbid
36
+
37
+
38
+ class QpuTokenOut(BaseModel):
39
+ """
40
+ Pydantic model for QPU token OUT.
41
+ It contains the data received from the API call.
42
+
43
+ Attributes
44
+ ----------
45
+ id: str
46
+ Id of the QPU token
47
+ name: Optional[str]
48
+ Name of the QPU token
49
+ provider: ProviderEnum
50
+ Name of provider: dwave | ibm
51
+ """
52
+
53
+ id: str
54
+
55
+ name: str
56
+ provider: str
57
+
58
+ class Config:
59
+ extra = Extra.ignore
60
+ from_attributes = True
@@ -0,0 +1,19 @@
1
+ from typing import Any
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class Representation(BaseModel):
7
+ """
8
+ Pydantic model for representation of a solution sample.
9
+
10
+ Attributes
11
+ ----------
12
+ description: str
13
+ Description of the representation
14
+ solution: Any
15
+ matrix of the solution representation
16
+ """
17
+
18
+ description: str
19
+ solution: Any
File without changes
File without changes
@@ -0,0 +1,45 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, Extra
4
+
5
+ from luna_sdk.schemas import QpuToken, TokenProvider
6
+
7
+
8
+ class AWSQpuTokens(BaseModel):
9
+ aws_access_key: QpuToken
10
+ aws_secret_access_key: QpuToken
11
+
12
+
13
+ class RestAPITokenProvider(BaseModel):
14
+ dwave: Optional[QpuToken] = None
15
+ ibm: Optional[QpuToken] = None
16
+ fujitsu: Optional[QpuToken] = None
17
+ qctrl: Optional[QpuToken] = None
18
+ aws: Optional[AWSQpuTokens] = None
19
+
20
+ @classmethod
21
+ def from_sdk_token_provider(
22
+ cls, token_provider: TokenProvider
23
+ ) -> "RestAPITokenProvider":
24
+ aws: Optional[AWSQpuTokens] = None
25
+ if (
26
+ token_provider.aws_access_key is not None
27
+ or token_provider.aws_secret_access_key is not None
28
+ ):
29
+ # Ignoring mypy here to receive validation error, because we always need 2 tokens for aws
30
+ aws = AWSQpuTokens(
31
+ aws_access_key=getattr(token_provider, "aws_access_key", None), # type: ignore[arg-type]
32
+ aws_secret_access_key=getattr( # type: ignore[arg-type]
33
+ token_provider, "aws_secret_access_key", None
34
+ ),
35
+ )
36
+ return cls(
37
+ dwave=token_provider.dwave,
38
+ ibm=token_provider.ibm,
39
+ fujitsu=token_provider.fujitsu,
40
+ qctrl=token_provider.qctrl,
41
+ aws=aws,
42
+ )
43
+
44
+ class Config:
45
+ extra = Extra.forbid
@@ -0,0 +1,227 @@
1
+ from datetime import datetime
2
+ from typing import Any, Dict, List, Optional, Union
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from luna_sdk.schemas.enums.solution import SenseEnum
7
+ from luna_sdk.schemas.enums.status import StatusEnum
8
+ from luna_sdk.schemas.optimization import Optimization
9
+ from luna_sdk.schemas.pretty_base import PrettyBase
10
+
11
+ Numeric = Union[float, int]
12
+ Sample = Dict[str, Numeric]
13
+
14
+
15
+ class Runtime(BaseModel):
16
+ """
17
+ Pydantic model for runtime of a solution.
18
+
19
+ Attributes
20
+ ----------
21
+ total: float
22
+ Total time of solution processing
23
+ overhead: Optional[float]
24
+ Time of the classical computing processes
25
+ qpu: Optional[float]
26
+ Total time of the quantum computing processes
27
+ """
28
+
29
+ total: float
30
+ overhead: Optional[float]
31
+ qpu: Optional[float]
32
+ # ...
33
+
34
+
35
+ class ConstraintResult(BaseModel):
36
+ satisfied: bool
37
+ extra: Optional[Dict[str, Any]]
38
+
39
+
40
+ class Result(PrettyBase):
41
+ """
42
+ A single result of a solution
43
+
44
+ Attributes
45
+ ----------
46
+ sample: List[List[bool]]
47
+ Binary solutions vectors
48
+ energies: List[float]
49
+ Energy corresponding to binary solution vector
50
+ solver: str
51
+ Solver's name
52
+ params: Dict
53
+ Solver params
54
+ runtime: Runtime
55
+ Solution runtime information
56
+ metadata: Optional[Dict]
57
+ Solution's metadata
58
+ """
59
+
60
+ sample: Sample
61
+ obj_value: float
62
+ feasible: bool
63
+ constraints: Dict[str, ConstraintResult]
64
+
65
+
66
+ class Solution(PrettyBase):
67
+ """
68
+ The solution class for Solver return values
69
+
70
+ Attributes
71
+ ----------
72
+ results: List[List[bool]]
73
+ List of binary solutions vectors
74
+ params: Dict
75
+ Solver params
76
+ runtime: Runtime
77
+ Solution runtime information
78
+ sense: SenseEnum
79
+ Optimization sense, can be 'min' or 'max'.
80
+ metadata: Optional[Dict]
81
+ Solution's metadata
82
+ provider: str
83
+ The solver provider
84
+
85
+ error_message: Optional[str]
86
+ Default is none.
87
+ If an error occurs during the solution process,
88
+ the error message is stored here.
89
+ """
90
+
91
+ id: str
92
+ name: Optional[str] = None
93
+ created_date: datetime
94
+ created_by: str
95
+ modified_date: Optional[datetime] = None
96
+ modified_by: Optional[str] = None
97
+
98
+ error_message: Optional[str] = None
99
+
100
+ results: Optional[List[Result]]
101
+ params: Dict[str, Any]
102
+ runtime: Optional[Runtime]
103
+ sense: Optional[SenseEnum]
104
+ metadata: Optional[Dict[str, Any]]
105
+ provider: str
106
+ status: StatusEnum
107
+ optimization: Union[Optimization, str]
108
+ representation: Optional[Any] = None
109
+
110
+ def __str__(self):
111
+ """Overwrite the default object string representation to use the custom pretty print console representation"""
112
+ data = self.model_dump()
113
+ results = data.pop("results") # Extract and remove results from data
114
+ metadata = data.pop("metadata") # Extract and remove metadata from data
115
+ provider = data["provider"]
116
+
117
+ divider = "--------------------------------------------------------------------------------\n"
118
+
119
+ # Build Meta Data section
120
+ output = f"{divider}META DATA:\n{divider}"
121
+ output += self._pretty_print(data)
122
+
123
+ # Build Results section
124
+ if results:
125
+ output += f"\n\n{divider}RESULTS:\n{divider}"
126
+ for i, result in enumerate(results, start=1):
127
+ r = f"Result {i}:\n"
128
+ r += f" {result}\n"
129
+ output += r
130
+ else:
131
+ output += f"\n\n{divider}RESULTS:\n{divider}"
132
+ output += " No results..\n"
133
+ output += " Solution has status: " + str(self.status.value) + "\n"
134
+ if self.error_message:
135
+ output += " Error message: " + str(self.error_message) + "\n"
136
+
137
+ # Build Provider Meta Data section
138
+ output += f"\n\n{divider}{provider.upper()} META DATA:\n{divider}"
139
+ output += (
140
+ self._pretty_print(metadata)
141
+ if metadata
142
+ else " No metadata from provider..\n"
143
+ )
144
+
145
+ return output
146
+
147
+ @property
148
+ def head(self):
149
+ """Print a truncated version of the pretty print console representation"""
150
+ limit = 5
151
+
152
+ def truncate(data, limit):
153
+ if data is None:
154
+ return None, False
155
+
156
+ if isinstance(data, dict):
157
+ d = {
158
+ k: truncate(v, limit)[0]
159
+ for i, (k, v) in enumerate(data.items())
160
+ if i < limit
161
+ }
162
+ return d, len(data) > limit
163
+ elif isinstance(data, list):
164
+ d = data[:limit]
165
+ return d, len(data) > limit
166
+ else:
167
+ return data, False
168
+
169
+ data = self.model_dump()
170
+ results = data.pop("results") # remove results from data
171
+ metadata = data.pop("metadata") # remove metadata from data
172
+ provider = data["provider"]
173
+
174
+ divider = "--------------------------------------------------------------------------------\n"
175
+
176
+ # Build Meta Data section
177
+ output = f"{divider}META DATA:\n{divider}"
178
+ output += self._pretty_print(data)
179
+
180
+ # Build Results section
181
+ if results:
182
+ output += f"\n\n{divider}RESULTS:\n{divider}"
183
+ output += (
184
+ f"{len(results)} results found. Displaying first {limit} results.\n"
185
+ )
186
+ for i, result in enumerate(results, start=1):
187
+ if i > limit:
188
+ output += "....\n"
189
+ break
190
+ r = f"Result {i}:\n"
191
+ r += (
192
+ f" {str(result)[:150]} ....\n"
193
+ if len(str(result)) > 150
194
+ else f" {result}\n"
195
+ )
196
+ output += r
197
+ else:
198
+ output += f"\n\n{divider}RESULTS:\n{divider}"
199
+ output += " No results..\n"
200
+ output += " Solution has status: " + str(self.status.value) + "\n"
201
+ if self.error_message:
202
+ output += " Error message: " + str(self.error_message) + "\n"
203
+
204
+ # Build Provider Meta Data section
205
+ metadata_truncated, is_truncated = truncate(metadata, limit)
206
+ output += f"\n\n{divider}{provider.upper()} META DATA"
207
+ output += " (truncated)" if is_truncated else ""
208
+ output += f":\n{divider}"
209
+ output += (
210
+ self._pretty_print(metadata_truncated)
211
+ if metadata
212
+ else " No metadata from provider..\n"
213
+ )
214
+ output += "...." if is_truncated else ""
215
+
216
+ return output
217
+
218
+
219
+ class UseCaseResult(BaseModel):
220
+ representation: Any
221
+ obj_value: float
222
+
223
+
224
+ class UseCaseRepresentation(PrettyBase):
225
+ sense: Optional[SenseEnum]
226
+ results: List[UseCaseResult]
227
+ description: str
@@ -0,0 +1,11 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class SolverInfo(BaseModel):
7
+ full_name: str
8
+ short_name: str
9
+ available: bool
10
+ params: dict
11
+ description: Optional[str]