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,104 @@
1
+ import os
2
+ from typing import Any, Dict, Optional
3
+
4
+ from luna_sdk.exceptions.encryption_exception import EncryptionNotSetException
5
+ from luna_sdk.interfaces.circuit_repo_i import ICircuitRepo
6
+ from luna_sdk.schemas.circuit import CircuitJob, CircuitResult
7
+ from luna_sdk.schemas.create.circuit import CircuitIn
8
+ from luna_sdk.schemas.enums.circuit import CircuitProviderEnum
9
+ from luna_sdk.schemas.qpu_token import TokenProvider, QpuToken, QpuTokenSource
10
+ from luna_sdk.schemas.rest.qpu_token.token_provider import RestAPITokenProvider
11
+ from luna_sdk.utils.qpu_tokens import extract_qpu_tokens_from_env
12
+
13
+
14
+ class CircuitRepo(ICircuitRepo):
15
+ _endpoint = "/circuits"
16
+
17
+ def create(
18
+ self,
19
+ circuit: str,
20
+ provider: CircuitProviderEnum,
21
+ params: Dict[str, Any] = {},
22
+ qpu_tokens: Optional[TokenProvider] = None,
23
+ timeout: Optional[float] = 10800.0,
24
+ encryption_key: Optional[str] = None,
25
+ ) -> CircuitJob:
26
+ """
27
+ Create a circuit solution.
28
+
29
+ Parameters
30
+ ----------
31
+ circuit: str
32
+ The circuit which to create a solution for.
33
+ provider: CircuitProviderEnum
34
+ Which provider to use to solve the circuit.
35
+ params: Dict[str, Any]
36
+ Additional parameters of the circuit.
37
+ qpu_tokens: Optional[TokenProvider]
38
+ The tokens to be used for the QPU.
39
+ timeout: Optional[float]
40
+ Default = 10800.0. Timeout for the api request. If set to None,
41
+ there won't be any timeout. Increase or disable the timeout if you face
42
+ issues uploading big Problems.
43
+ encryption_key: Optional[str]
44
+ Encryption key to be used for encryption of QPU tokens.
45
+ Returns
46
+ -------
47
+ CircuitJob
48
+ The created circuit job.
49
+ """
50
+ if qpu_tokens is not None:
51
+ rest_qpu_tokens = RestAPITokenProvider.from_sdk_token_provider(qpu_tokens)
52
+ else:
53
+ rest_qpu_tokens = None
54
+
55
+ # try to retrieve qpu tokens from env variables
56
+ if rest_qpu_tokens is None:
57
+ rest_qpu_tokens = extract_qpu_tokens_from_env()
58
+
59
+ encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
60
+ if encryption_key is None:
61
+ raise EncryptionNotSetException
62
+ circuit_in: CircuitIn = CircuitIn(
63
+ provider=provider,
64
+ circuit=circuit,
65
+ params=params,
66
+ qpu_tokens=rest_qpu_tokens,
67
+ encryption_key=encryption_key,
68
+ )
69
+
70
+ response = self._client.post(
71
+ self._endpoint, content=circuit_in.model_dump_json(), timeout=timeout
72
+ )
73
+
74
+ response.raise_for_status()
75
+ return CircuitJob(id=response.json(), provider=provider, params=params)
76
+
77
+ def get(
78
+ self, job: CircuitJob, encryption_key: Optional[str] = None
79
+ ) -> CircuitResult:
80
+ """
81
+ Retrieve a circuit result from a job.
82
+
83
+ Parameters
84
+ ----------
85
+ job: CircuitJob
86
+ The job received upon circuit creation.
87
+ encryption_key: Optional[str]
88
+ The encryption key to be used for the QPU.
89
+ Returns
90
+ -------
91
+ CircuitResult
92
+ The result of solving the circuit.
93
+ """
94
+ url = f"{self._endpoint}/{job.id}/{job.provider.value}"
95
+ encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
96
+ if encryption_key is None:
97
+ raise EncryptionNotSetException
98
+ if job.params is None:
99
+ job.params = {}
100
+ job.params["encryption_key"] = encryption_key
101
+ response = self._client.get(url, params=job.params, timeout=60)
102
+
103
+ response.raise_for_status()
104
+ return CircuitResult.model_validate(response.json())
@@ -0,0 +1,118 @@
1
+ import os
2
+ import pickle
3
+ import tempfile
4
+ from functools import partial
5
+ from typing import Tuple, List, Dict
6
+
7
+ import dimod
8
+ from dimod import ConstrainedQuadraticModel
9
+ from dimod.constrained.constrained import CQMToBQMInverter
10
+ from docplex.mp.model import Model as DOCplexModel
11
+ from qiskit_optimization import QuadraticProgram
12
+
13
+ from luna_sdk.exceptions.transformation import TransformationException
14
+ from luna_sdk.interfaces.cplex_repo_i import ICplexRepo
15
+ from luna_sdk.schemas.transformations.bqm import BQMResultSchema, BQMSchema
16
+ from luna_sdk.schemas.transformations.matrix import MatrixSchema
17
+
18
+
19
+ class CplexRepo(ICplexRepo):
20
+ _endpoint = "/transformations/docplex"
21
+
22
+ def _send_request_with_pickle_file_response(
23
+ self, docplex_model: DOCplexModel, endpoint: str
24
+ ):
25
+ file = tempfile.NamedTemporaryFile(delete=False)
26
+ with open(file.name, "wb") as tmp:
27
+ pickle.dump(docplex_model, tmp)
28
+ response = self._client.post(endpoint, files={"file": (file.name, file.file)})
29
+ os.remove(file.name)
30
+ try:
31
+ parsed_model = pickle.loads(response.content)
32
+ except Exception:
33
+ raise TransformationException()
34
+ return parsed_model
35
+
36
+ def to_qubo_qiskit(self, docplex_model: DOCplexModel) -> QuadraticProgram:
37
+ qubo_qiskit_model = self._send_request_with_pickle_file_response(
38
+ docplex_model, f"{self._endpoint}/to-qubo-qiskit"
39
+ )
40
+ try:
41
+ assert isinstance(qubo_qiskit_model, QuadraticProgram)
42
+ except AssertionError:
43
+ raise TransformationException()
44
+ return qubo_qiskit_model
45
+
46
+ def to_lp_file(self, docplex_model: DOCplexModel, filepath: str) -> None:
47
+ file = tempfile.NamedTemporaryFile(delete=False)
48
+ with open(file.name, "wb") as tmp:
49
+ pickle.dump(docplex_model, tmp)
50
+ response = self._client.post(
51
+ f"{self._endpoint}/to-lp-file", files={"file": (file.name, file.file)}
52
+ )
53
+ with open(filepath, "w") as file: # type: ignore
54
+ file.write(response.content.decode("utf-8")) # type: ignore
55
+
56
+ def to_lp_string(self, docplex_model: DOCplexModel) -> str:
57
+ file = tempfile.NamedTemporaryFile(delete=False)
58
+ with open(file.name, "wb") as tmp:
59
+ pickle.dump(docplex_model, tmp)
60
+ response = self._client.post(
61
+ f"{self._endpoint}/to-lp-file", files={"file": (file.name, file.file)}
62
+ )
63
+ return response.content.decode("utf-8")
64
+
65
+ def to_qubo_matrix(
66
+ self, docplex_model: DOCplexModel
67
+ ) -> Tuple[List[List[float]], partial]:
68
+ file = tempfile.NamedTemporaryFile(delete=False)
69
+ with open(file.name, "wb") as tmp:
70
+ pickle.dump(docplex_model, tmp)
71
+ response = self._client.post(
72
+ f"{self._endpoint}/to-qubo-matrix", files={"file": (file.name, file.file)}
73
+ )
74
+ retrieved_matrix = MatrixSchema.validate(response.json())
75
+ return retrieved_matrix.matrix, partial(
76
+ self.inverter,
77
+ var_indices=retrieved_matrix.variable_indices,
78
+ inverter_bqm=CQMToBQMInverter.from_dict(retrieved_matrix.inverter.dict()),
79
+ )
80
+
81
+ def to_bqm(
82
+ self, docplex_model: DOCplexModel
83
+ ) -> Tuple[dimod.BinaryQuadraticModel, CQMToBQMInverter]:
84
+ file = tempfile.NamedTemporaryFile(delete=False)
85
+ with open(file.name, "wb") as tmp:
86
+ pickle.dump(docplex_model, tmp)
87
+ response = self._client.post(
88
+ f"{self._endpoint}/to-bqm", files={"file": (file.name, file.file)}
89
+ )
90
+ retrieved_bqm = BQMResultSchema.validate(response.json())
91
+
92
+ quadratic: Dict[Tuple[str, str], float] = {}
93
+ for key, value in retrieved_bqm.bqm.quadratic.items():
94
+ split_key = tuple(key.split(","))
95
+ if len(split_key) != 2:
96
+ raise TransformationException
97
+ quadratic[split_key[0], split_key[1]] = value
98
+ try:
99
+ bqm = dimod.BinaryQuadraticModel(
100
+ retrieved_bqm.bqm.linear,
101
+ quadratic,
102
+ offset=retrieved_bqm.bqm.offset,
103
+ vartype=retrieved_bqm.bqm.var_type,
104
+ )
105
+ except Exception:
106
+ raise TransformationException()
107
+ inverter = CQMToBQMInverter.from_dict(retrieved_bqm.inverter.dict())
108
+ return bqm, inverter
109
+
110
+ def to_cqm(self, docplex_model: DOCplexModel) -> ConstrainedQuadraticModel:
111
+ file = tempfile.NamedTemporaryFile(delete=False)
112
+ with open(file.name, "wb") as tmp:
113
+ pickle.dump(docplex_model, tmp)
114
+ response = self._client.post(
115
+ f"{self._endpoint}/to-cqm", files={"file": (file.name, file.file)}
116
+ )
117
+ cqm = ConstrainedQuadraticModel.from_file(response.content)
118
+ return cqm
@@ -0,0 +1,45 @@
1
+ from typing import Any, Dict, List, Optional
2
+
3
+ from luna_sdk.interfaces.info_repo_i import IInfoRepo
4
+ from luna_sdk.schemas.solver_info import SolverInfo
5
+
6
+
7
+ class InfoRepo(IInfoRepo):
8
+ _endpoint = "/"
9
+
10
+ _endpoint_solvers = "/solvers"
11
+ _endpoint_providers = "/providers"
12
+
13
+ def solvers_available(
14
+ self, solver_name: Optional[str] = None
15
+ ) -> Dict[str, Dict[str, SolverInfo]]:
16
+ params = {}
17
+ if solver_name:
18
+ params["solver_name"] = solver_name
19
+
20
+ response = self._client.get(
21
+ f"{self._endpoint_solvers}/available",
22
+ params=params,
23
+ )
24
+
25
+ response.raise_for_status()
26
+
27
+ json: Dict[str, Dict[str, Any]] = response.json()
28
+ to_return: Dict[str, Dict[str, SolverInfo]] = {}
29
+ for provider in json:
30
+ to_return[provider] = {}
31
+ for solver in json[provider]:
32
+ to_return[provider][solver] = SolverInfo.model_validate(
33
+ json[provider][solver]
34
+ )
35
+
36
+ return to_return
37
+
38
+ def providers_available(self) -> List[str]:
39
+ response = self._client.get(
40
+ f"{self._endpoint_providers}/available",
41
+ )
42
+
43
+ response.raise_for_status()
44
+
45
+ return [i for i in response.json()]
@@ -0,0 +1,105 @@
1
+ import os
2
+ import pickle
3
+ import tempfile
4
+ from functools import partial
5
+ from typing import Tuple, List, Dict
6
+
7
+ import dimod
8
+ from dimod import ConstrainedQuadraticModel
9
+ from dimod.constrained.constrained import CQMToBQMInverter
10
+ from docplex.mp.model import Model as DOCplexModel
11
+ from qiskit_optimization import QuadraticProgram
12
+
13
+ from luna_sdk.exceptions.transformation import TransformationException
14
+ from luna_sdk.interfaces.lp_repo_i import ILPRepo
15
+ from luna_sdk.schemas.transformations.bqm import BQMResultSchema, BQMSchema
16
+ from luna_sdk.schemas.transformations.matrix import MatrixSchema
17
+
18
+
19
+ class LPRepo(ILPRepo):
20
+ _endpoint = "/transformations/lp"
21
+
22
+ def _send_request_with_pickle_file_response(self, lp_string: str, endpoint: str):
23
+ file = tempfile.NamedTemporaryFile(delete=False, suffix=".lp")
24
+ with open(file.name, "w") as tmp:
25
+ tmp.write(lp_string)
26
+ response = self._client.post(endpoint, files={"file": (file.name, file.file)})
27
+ os.remove(file.name)
28
+ try:
29
+ parsed_model = pickle.loads(response.content)
30
+ except Exception:
31
+ raise TransformationException()
32
+ return parsed_model
33
+
34
+ def to_qubo_qiskit(self, lp_string: str) -> QuadraticProgram:
35
+ qubo_qiskit_model = self._send_request_with_pickle_file_response(
36
+ lp_string, f"{self._endpoint}/to-qubo-qiskit"
37
+ )
38
+ try:
39
+ assert isinstance(qubo_qiskit_model, QuadraticProgram)
40
+ except AssertionError:
41
+ raise TransformationException()
42
+ return qubo_qiskit_model
43
+
44
+ def to_docplex(self, lp_string: str) -> DOCplexModel:
45
+ docplex_model = self._send_request_with_pickle_file_response(
46
+ lp_string, f"{self._endpoint}/to-docplex"
47
+ )
48
+ try:
49
+ assert isinstance(docplex_model, DOCplexModel)
50
+ except AssertionError:
51
+ raise TransformationException()
52
+ return docplex_model
53
+
54
+ def to_qubo_matrix(self, lp_string: str) -> Tuple[List[List[float]], partial]:
55
+ file = tempfile.NamedTemporaryFile(delete=False, suffix=".lp")
56
+ with open(file.name, "w") as tmp:
57
+ tmp.write(lp_string)
58
+ response = self._client.post(
59
+ f"{self._endpoint}/to-qubo-matrix", files={"file": (file.name, file.file)}
60
+ )
61
+ retrieved_matrix = MatrixSchema.validate(response.json())
62
+ return retrieved_matrix.matrix, partial(
63
+ self.inverter,
64
+ var_indices=retrieved_matrix.variable_indices,
65
+ inverter_bqm=CQMToBQMInverter.from_dict(retrieved_matrix.inverter.dict()),
66
+ )
67
+
68
+ def to_bqm(
69
+ self, lp_string: str
70
+ ) -> Tuple[dimod.BinaryQuadraticModel, CQMToBQMInverter]:
71
+ file = tempfile.NamedTemporaryFile(delete=False, suffix=".lp")
72
+ with open(file.name, "w") as tmp:
73
+ tmp.write(lp_string)
74
+ response = self._client.post(
75
+ f"{self._endpoint}/to-bqm", files={"file": (file.name, file.file)}
76
+ )
77
+ retrieved_bqm = BQMResultSchema.validate(response.json())
78
+
79
+ quadratic: Dict[Tuple[str, str], float] = {}
80
+ for key, value in retrieved_bqm.bqm.quadratic.items():
81
+ split_key = tuple(key.split(","))
82
+ if len(split_key) != 2:
83
+ raise TransformationException
84
+ quadratic[split_key[0], split_key[1]] = value
85
+ try:
86
+ bqm = dimod.BinaryQuadraticModel(
87
+ retrieved_bqm.bqm.linear,
88
+ quadratic,
89
+ offset=retrieved_bqm.bqm.offset,
90
+ vartype=retrieved_bqm.bqm.var_type,
91
+ )
92
+ except Exception:
93
+ raise TransformationException()
94
+ inverter = CQMToBQMInverter.from_dict(retrieved_bqm.inverter.dict())
95
+ return bqm, inverter
96
+
97
+ def to_cqm(self, lp_string: str) -> ConstrainedQuadraticModel:
98
+ file = tempfile.NamedTemporaryFile(delete=False, suffix=".lp")
99
+ with open(file.name, "w") as tmp:
100
+ tmp.write(lp_string)
101
+ response = self._client.post(
102
+ f"{self._endpoint}/to-cqm", files={"file": (file.name, file.file)}
103
+ )
104
+ cqm = ConstrainedQuadraticModel.from_file(response.content)
105
+ return cqm