luna-quantum 0.0.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of luna-quantum might be problematic. Click here for more details.
- luna_quantum-0.0.16.dist-info/LICENSE +201 -0
- luna_quantum-0.0.16.dist-info/METADATA +46 -0
- luna_quantum-0.0.16.dist-info/RECORD +160 -0
- luna_quantum-0.0.16.dist-info/WHEEL +4 -0
- luna_sdk/__init__.py +2 -0
- luna_sdk/constants.py +1 -0
- luna_sdk/controllers/__init__.py +2 -0
- luna_sdk/controllers/custom_login_client.py +61 -0
- luna_sdk/controllers/luna_platform_client.py +62 -0
- luna_sdk/controllers/luna_q.py +36 -0
- luna_sdk/controllers/luna_solve.py +49 -0
- luna_sdk/controllers/luna_transform.py +41 -0
- luna_sdk/error/__init__.py +0 -0
- luna_sdk/error/http_error_utils.py +100 -0
- luna_sdk/exceptions/__init__.py +1 -0
- luna_sdk/exceptions/encryption_exception.py +6 -0
- luna_sdk/exceptions/luna_exception.py +7 -0
- luna_sdk/exceptions/luna_server_exception.py +18 -0
- luna_sdk/exceptions/timeout_exception.py +10 -0
- luna_sdk/exceptions/transformation.py +11 -0
- luna_sdk/interfaces/__init__.py +5 -0
- luna_sdk/interfaces/circuit_repo_i.py +62 -0
- luna_sdk/interfaces/clients/__init__.py +0 -0
- luna_sdk/interfaces/clients/client_i.py +10 -0
- luna_sdk/interfaces/clients/luna_q_i.py +39 -0
- luna_sdk/interfaces/clients/luna_solve_i.py +37 -0
- luna_sdk/interfaces/clients/luna_transform_i.py +33 -0
- luna_sdk/interfaces/cplex_repo_i.py +121 -0
- luna_sdk/interfaces/info_repo_i.py +40 -0
- luna_sdk/interfaces/lp_repo_i.py +106 -0
- luna_sdk/interfaces/optimization_repo_i.py +262 -0
- luna_sdk/interfaces/qpu_token_repo_i.py +151 -0
- luna_sdk/interfaces/repository_i.py +14 -0
- luna_sdk/interfaces/solutions_repo_i.py +219 -0
- luna_sdk/py.typed +0 -0
- luna_sdk/repositories/__init__.py +4 -0
- luna_sdk/repositories/circuit_repo.py +104 -0
- luna_sdk/repositories/cplex_repo.py +118 -0
- luna_sdk/repositories/info_repo.py +45 -0
- luna_sdk/repositories/lp_repo.py +105 -0
- luna_sdk/repositories/optimization_repo.py +358 -0
- luna_sdk/repositories/qpu_token_repo.py +226 -0
- luna_sdk/repositories/solutions_repo.py +347 -0
- luna_sdk/schemas/__init__.py +4 -0
- luna_sdk/schemas/circuit.py +43 -0
- luna_sdk/schemas/create/__init__.py +3 -0
- luna_sdk/schemas/create/circuit.py +29 -0
- luna_sdk/schemas/create/optimization.py +22 -0
- luna_sdk/schemas/create/qpu_token.py +26 -0
- luna_sdk/schemas/create/qubo.py +19 -0
- luna_sdk/schemas/create/solution.py +15 -0
- luna_sdk/schemas/enums/__init__.py +0 -0
- luna_sdk/schemas/enums/circuit.py +14 -0
- luna_sdk/schemas/enums/optimization.py +10 -0
- luna_sdk/schemas/enums/problem.py +48 -0
- luna_sdk/schemas/enums/qpu_token_type.py +6 -0
- luna_sdk/schemas/enums/solution.py +8 -0
- luna_sdk/schemas/enums/status.py +10 -0
- luna_sdk/schemas/enums/timeframe.py +11 -0
- luna_sdk/schemas/error_message.py +12 -0
- luna_sdk/schemas/optimization.py +75 -0
- luna_sdk/schemas/optimization_formats/__init__.py +0 -0
- luna_sdk/schemas/optimization_formats/bqm.py +34 -0
- luna_sdk/schemas/optimization_formats/cqm.py +127 -0
- luna_sdk/schemas/optimization_formats/lp.py +9 -0
- luna_sdk/schemas/optimization_formats/qm.py +30 -0
- luna_sdk/schemas/pretty_base.py +49 -0
- luna_sdk/schemas/qpu_token.py +60 -0
- luna_sdk/schemas/representation.py +19 -0
- luna_sdk/schemas/rest/__init__.py +0 -0
- luna_sdk/schemas/rest/qpu_token/__init__.py +0 -0
- luna_sdk/schemas/rest/qpu_token/token_provider.py +45 -0
- luna_sdk/schemas/solution.py +227 -0
- luna_sdk/schemas/solver_info.py +11 -0
- luna_sdk/schemas/solver_parameters/aws/__init__.py +1 -0
- luna_sdk/schemas/solver_parameters/aws/qaoa.py +24 -0
- luna_sdk/schemas/solver_parameters/dwave/__init__.py +72 -0
- luna_sdk/schemas/solver_parameters/dwave/base.py +409 -0
- luna_sdk/schemas/solver_parameters/dwave/dialectic_search.py +31 -0
- luna_sdk/schemas/solver_parameters/dwave/kerberos.py +71 -0
- luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_bqm.py +19 -0
- luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_cqm.py +22 -0
- luna_sdk/schemas/solver_parameters/dwave/parallel_tempering.py +30 -0
- luna_sdk/schemas/solver_parameters/dwave/parallel_tempering_qpu.py +37 -0
- luna_sdk/schemas/solver_parameters/dwave/population_annealing.py +25 -0
- luna_sdk/schemas/solver_parameters/dwave/population_annealing_qpu.py +35 -0
- luna_sdk/schemas/solver_parameters/dwave/qaga.py +56 -0
- luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_qpu.py +19 -0
- luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_simulated_annealing.py +22 -0
- luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_tabu_search.py +21 -0
- luna_sdk/schemas/solver_parameters/dwave/quantum_annealing.py +20 -0
- luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_quantum_annealing.py +82 -0
- luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_simulated_annealing.py +89 -0
- luna_sdk/schemas/solver_parameters/dwave/saga.py +61 -0
- luna_sdk/schemas/solver_parameters/dwave/simulated_annealing.py +74 -0
- luna_sdk/schemas/solver_parameters/dwave/tabu_search.py +72 -0
- luna_sdk/schemas/solver_parameters/fujitsu/__init__.py +20 -0
- luna_sdk/schemas/solver_parameters/fujitsu/base.py +47 -0
- luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_cpu.py +129 -0
- luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_v2.py +149 -0
- luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_v3.py +150 -0
- luna_sdk/schemas/solver_parameters/fujitsu/partial_config.py +177 -0
- luna_sdk/schemas/solver_parameters/ibm/__init__.py +4 -0
- luna_sdk/schemas/solver_parameters/ibm/qaoa.py +64 -0
- luna_sdk/schemas/solver_parameters/ibm/standard_parameters.py +27 -0
- luna_sdk/schemas/solver_parameters/ibm/vqe.py +49 -0
- luna_sdk/schemas/solver_parameters/qctrl/__init__.py +1 -0
- luna_sdk/schemas/solver_parameters/qctrl/qaoa.py +47 -0
- luna_sdk/schemas/transformations/__init__.py +2 -0
- luna_sdk/schemas/transformations/bqm.py +33 -0
- luna_sdk/schemas/transformations/matrix.py +12 -0
- luna_sdk/schemas/use_cases/__init__.py +54 -0
- luna_sdk/schemas/use_cases/arbitrage_edge_based.py +49 -0
- luna_sdk/schemas/use_cases/arbitrage_node_based.py +54 -0
- luna_sdk/schemas/use_cases/base.py +5 -0
- luna_sdk/schemas/use_cases/binary_integer_linear_programming.py +53 -0
- luna_sdk/schemas/use_cases/binary_paint_shop_problem.py +36 -0
- luna_sdk/schemas/use_cases/credit_scoring_feature_selection.py +39 -0
- luna_sdk/schemas/use_cases/dynamic_portfolio_optimization.py +63 -0
- luna_sdk/schemas/use_cases/exact_cover.py +50 -0
- luna_sdk/schemas/use_cases/flight_gate_assignment.py +78 -0
- luna_sdk/schemas/use_cases/graph_coloring.py +41 -0
- luna_sdk/schemas/use_cases/graph_isomorphism.py +53 -0
- luna_sdk/schemas/use_cases/graph_partitioning.py +45 -0
- luna_sdk/schemas/use_cases/hamiltonian_cycle.py +48 -0
- luna_sdk/schemas/use_cases/induced_subgraph_isomorphism.py +49 -0
- luna_sdk/schemas/use_cases/job_shop_scheduling.py +43 -0
- luna_sdk/schemas/use_cases/k_medoids_clustering.py +48 -0
- luna_sdk/schemas/use_cases/knapsack_integer_weights.py +55 -0
- luna_sdk/schemas/use_cases/linear_regression.py +59 -0
- luna_sdk/schemas/use_cases/lmwcs.py +80 -0
- luna_sdk/schemas/use_cases/longest_path.py +49 -0
- luna_sdk/schemas/use_cases/market_graph_clustering.py +60 -0
- luna_sdk/schemas/use_cases/max2sat.py +51 -0
- luna_sdk/schemas/use_cases/max3sat.py +52 -0
- luna_sdk/schemas/use_cases/max_clique.py +59 -0
- luna_sdk/schemas/use_cases/max_cut.py +47 -0
- luna_sdk/schemas/use_cases/max_independent_set.py +36 -0
- luna_sdk/schemas/use_cases/minimal_maximal_matching.py +53 -0
- luna_sdk/schemas/use_cases/minimal_spanning_tree.py +87 -0
- luna_sdk/schemas/use_cases/minimum_vertex_cover.py +44 -0
- luna_sdk/schemas/use_cases/number_partitioning.py +31 -0
- luna_sdk/schemas/use_cases/portfolio_optimization.py +45 -0
- luna_sdk/schemas/use_cases/portfolio_optimization_ib_tv.py +62 -0
- luna_sdk/schemas/use_cases/quadratic_assignment.py +48 -0
- luna_sdk/schemas/use_cases/quadratic_knapsack.py +47 -0
- luna_sdk/schemas/use_cases/satellite_scheduling.py +72 -0
- luna_sdk/schemas/use_cases/sensor_placement.py +57 -0
- luna_sdk/schemas/use_cases/set_cover.py +55 -0
- luna_sdk/schemas/use_cases/set_packing.py +53 -0
- luna_sdk/schemas/use_cases/set_partitioning.py +51 -0
- luna_sdk/schemas/use_cases/subgraph_isomorphism.py +56 -0
- luna_sdk/schemas/use_cases/subset_sum.py +36 -0
- luna_sdk/schemas/use_cases/support_vector_machine.py +63 -0
- luna_sdk/schemas/use_cases/traffic_flow.py +34 -0
- luna_sdk/schemas/use_cases/travelling_salesman_problem.py +52 -0
- luna_sdk/schemas/use_cases/type_aliases.py +11 -0
- luna_sdk/schemas/use_cases/weighted_max_cut.py +36 -0
- luna_sdk/utils/__init__.py +0 -0
- luna_sdk/utils/qpu_tokens.py +52 -0
|
@@ -0,0 +1,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,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
|