luna-quantum 1.0.1rc10__cp313-cp313-musllinux_1_2_x86_64.whl → 1.0.1rc12__cp313-cp313-musllinux_1_2_x86_64.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/__init__.py +7 -1
- luna_quantum/__init__.pyi +7 -1
- luna_quantum/_core.cpython-313-x86_64-linux-musl.so +0 -0
- luna_quantum/_core.pyi +14 -7
- luna_quantum/errors.pyi +6 -1
- luna_quantum/transformations.py +18 -0
- luna_quantum/transformations.pyi +258 -0
- luna_quantum/translator.pyi +2 -2
- luna_quantum/util/debug_info.py +52 -0
- luna_quantum/util/log_utils.py +15 -11
- luna_quantum/utils.py +1 -70
- luna_quantum/utils.pyi +33 -1
- {luna_quantum-1.0.1rc10.dist-info → luna_quantum-1.0.1rc12.dist-info}/METADATA +1 -1
- {luna_quantum-1.0.1rc10.dist-info → luna_quantum-1.0.1rc12.dist-info}/RECORD +17 -14
- {luna_quantum-1.0.1rc10.dist-info → luna_quantum-1.0.1rc12.dist-info}/WHEEL +0 -0
- {luna_quantum-1.0.1rc10.dist-info → luna_quantum-1.0.1rc12.dist-info}/licenses/LICENSE +0 -0
- {luna_quantum-1.0.1rc10.dist-info → luna_quantum-1.0.1rc12.dist-info}/licenses/NOTICE +0 -0
luna_quantum/__init__.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from luna_quantum._core import __luna_quantum_version__
|
|
1
2
|
from luna_quantum.aqm_overwrites.model import Model
|
|
2
3
|
from luna_quantum.client.controllers import LunaQ, LunaSolve
|
|
3
4
|
from luna_quantum.factories.luna_solve_client_factory import LunaSolveClientFactory
|
|
@@ -19,9 +20,9 @@ from luna_quantum.solve.usecases import (
|
|
|
19
20
|
SolveJobFetchUpdatesUseCase,
|
|
20
21
|
SolveJobGetResultUseCase,
|
|
21
22
|
)
|
|
23
|
+
from luna_quantum.util.debug_info import debug_info
|
|
22
24
|
from luna_quantum.util.log_utils import Logging
|
|
23
25
|
|
|
24
|
-
from . import utils
|
|
25
26
|
from ._core import (
|
|
26
27
|
Bounds,
|
|
27
28
|
Comparator,
|
|
@@ -49,10 +50,13 @@ from ._core import (
|
|
|
49
50
|
Variable,
|
|
50
51
|
Vtype,
|
|
51
52
|
errors,
|
|
53
|
+
transformations,
|
|
52
54
|
translator,
|
|
55
|
+
utils,
|
|
53
56
|
)
|
|
54
57
|
from .utils import quicksum
|
|
55
58
|
|
|
59
|
+
__version__ = __luna_quantum_version__
|
|
56
60
|
UseCaseFactory.set_model_fetch_class(ModelFetchMetadataUseCase)
|
|
57
61
|
UseCaseFactory.set_model_delete_class(ModelDeleteUseCase)
|
|
58
62
|
UseCaseFactory.set_model_get_solution_class(ModelGetSolutionUseCase)
|
|
@@ -100,9 +104,11 @@ __all__ = [
|
|
|
100
104
|
"UseCaseFactory",
|
|
101
105
|
"Variable",
|
|
102
106
|
"Vtype",
|
|
107
|
+
"__version__",
|
|
103
108
|
"algorithms",
|
|
104
109
|
"backends",
|
|
105
110
|
"constants",
|
|
111
|
+
"debug_info",
|
|
106
112
|
"errors",
|
|
107
113
|
"quicksum",
|
|
108
114
|
"transformations",
|
luna_quantum/__init__.pyi
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from . import transformations, utils
|
|
2
1
|
from ._core import (
|
|
3
2
|
Bounds,
|
|
4
3
|
Comparator,
|
|
@@ -27,14 +26,19 @@ from ._core import (
|
|
|
27
26
|
Vtype,
|
|
28
27
|
errors,
|
|
29
28
|
translator,
|
|
29
|
+
utils,
|
|
30
|
+
transformations,
|
|
30
31
|
)
|
|
31
32
|
from .utils import quicksum
|
|
33
|
+
from luna_quantum._core import __luna_quantum_version__
|
|
32
34
|
from luna_quantum.aqm_overwrites.model import Model
|
|
33
35
|
from luna_quantum.client.controllers import LunaQ, LunaSolve
|
|
34
36
|
from luna_quantum.solve import DefaultToken
|
|
35
37
|
from luna_quantum.solve.parameters import algorithms, backends, constants
|
|
38
|
+
from luna_quantum.util.debug_info import debug_info
|
|
36
39
|
from luna_quantum.util.log_utils import Logging
|
|
37
40
|
|
|
41
|
+
__version__ = __luna_quantum_version__
|
|
38
42
|
__all__ = [
|
|
39
43
|
"Bounds",
|
|
40
44
|
"Comparator",
|
|
@@ -66,9 +70,11 @@ __all__ = [
|
|
|
66
70
|
"Unbounded",
|
|
67
71
|
"Variable",
|
|
68
72
|
"Vtype",
|
|
73
|
+
"__version__",
|
|
69
74
|
"algorithms",
|
|
70
75
|
"backends",
|
|
71
76
|
"constants",
|
|
77
|
+
"debug_info",
|
|
72
78
|
"errors",
|
|
73
79
|
"quicksum",
|
|
74
80
|
"transformations",
|
|
Binary file
|
luna_quantum/_core.pyi
CHANGED
|
@@ -3,7 +3,7 @@ from enum import Enum
|
|
|
3
3
|
from types import TracebackType
|
|
4
4
|
from typing import Literal, Self, overload
|
|
5
5
|
from numpy.typing import NDArray
|
|
6
|
-
from . import errors, transformations, translator
|
|
6
|
+
from . import errors, transformations, translator, utils
|
|
7
7
|
from luna_quantum.client.interfaces.services.luna_solve_i import ILunaSolve
|
|
8
8
|
from luna_quantum.solve.domain.model_metadata import ModelMetadata
|
|
9
9
|
from luna_quantum.solve.domain.solve_job import SolveJob
|
|
@@ -106,12 +106,12 @@ class Bounds:
|
|
|
106
106
|
...
|
|
107
107
|
|
|
108
108
|
@property
|
|
109
|
-
def lower(self, /) -> float | Unbounded | None:
|
|
109
|
+
def lower(self, /) -> float | type[Unbounded] | None:
|
|
110
110
|
"""Get the lower bound."""
|
|
111
111
|
...
|
|
112
112
|
|
|
113
113
|
@property
|
|
114
|
-
def upper(self, /) -> float | Unbounded | None:
|
|
114
|
+
def upper(self, /) -> float | type[Unbounded] | None:
|
|
115
115
|
"""Get the upper bound."""
|
|
116
116
|
...
|
|
117
117
|
|
|
@@ -1998,11 +1998,11 @@ class Model:
|
|
|
1998
1998
|
def add_variable(self, name: str, /, vtype: (Vtype | None) = ...) -> Variable: ...
|
|
1999
1999
|
@overload
|
|
2000
2000
|
def add_variable(
|
|
2001
|
-
self, name: str, /, vtype: Vtype, *, lower: (float | type[Unbounded])
|
|
2001
|
+
self, name: str, /, vtype: Vtype, *, lower: (float | type[Unbounded] | None)
|
|
2002
2002
|
) -> Variable: ...
|
|
2003
2003
|
@overload
|
|
2004
2004
|
def add_variable(
|
|
2005
|
-
self, name: str, /, vtype: Vtype, *, upper: (float | type[Unbounded])
|
|
2005
|
+
self, name: str, /, vtype: Vtype, *, upper: (float | type[Unbounded] | None)
|
|
2006
2006
|
) -> Variable: ...
|
|
2007
2007
|
@overload
|
|
2008
2008
|
def add_variable(
|
|
@@ -2011,8 +2011,8 @@ class Model:
|
|
|
2011
2011
|
/,
|
|
2012
2012
|
vtype: Vtype,
|
|
2013
2013
|
*,
|
|
2014
|
-
lower: (float | type[Unbounded]),
|
|
2015
|
-
upper: (float | type[Unbounded]),
|
|
2014
|
+
lower: (float | type[Unbounded] | None),
|
|
2015
|
+
upper: (float | type[Unbounded] | None),
|
|
2016
2016
|
) -> Variable: ...
|
|
2017
2017
|
def add_variable(
|
|
2018
2018
|
self,
|
|
@@ -3656,6 +3656,9 @@ class Constraints:
|
|
|
3656
3656
|
"""
|
|
3657
3657
|
...
|
|
3658
3658
|
|
|
3659
|
+
__version__: str
|
|
3660
|
+
__aq_model_version__: str
|
|
3661
|
+
__luna_quantum_version__: str
|
|
3659
3662
|
__all__ = [
|
|
3660
3663
|
"Bounds",
|
|
3661
3664
|
"Comparator",
|
|
@@ -3677,7 +3680,11 @@ __all__ = [
|
|
|
3677
3680
|
"Timing",
|
|
3678
3681
|
"Variable",
|
|
3679
3682
|
"Vtype",
|
|
3683
|
+
"__aq_model_version__",
|
|
3684
|
+
"__luna_quantum_version__",
|
|
3685
|
+
"__version__",
|
|
3680
3686
|
"errors",
|
|
3681
3687
|
"transformations",
|
|
3682
3688
|
"translator",
|
|
3689
|
+
"utils",
|
|
3683
3690
|
]
|
luna_quantum/errors.pyi
CHANGED
|
@@ -226,11 +226,16 @@ class DuplicateConstraintNameError(Exception):
|
|
|
226
226
|
|
|
227
227
|
def __str__(self, /) -> str: ...
|
|
228
228
|
|
|
229
|
-
class CompilationError(
|
|
229
|
+
class CompilationError(RuntimeError):
|
|
230
230
|
"""Raised when an error occured during compilation of a model in the PassManager."""
|
|
231
231
|
|
|
232
232
|
def __str__(self, /) -> str: ...
|
|
233
233
|
|
|
234
|
+
class StartCannotBeInferredError(TypeError):
|
|
235
|
+
"""To be raised when the start value in the quicksum cannot be inferred."""
|
|
236
|
+
|
|
237
|
+
def __str__(self, /) -> str: ...
|
|
238
|
+
|
|
234
239
|
__all__ = [
|
|
235
240
|
"ComputationError",
|
|
236
241
|
"ComputationError",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Transformations collection.
|
|
2
|
+
|
|
3
|
+
The `transformations` module provides a collection of transformations for converting
|
|
4
|
+
between various representations of optimization problems and their solutions.
|
|
5
|
+
|
|
6
|
+
Transformations generally convert between different representations of an optimization
|
|
7
|
+
model. For example, changing the Sense of a model.
|
|
8
|
+
|
|
9
|
+
Each transformation encapsulates the logic needed for transforming a model to a desired
|
|
10
|
+
output model with changed properties and the logic to convert a solution of the output
|
|
11
|
+
model back to a solution representation matching the input model.
|
|
12
|
+
|
|
13
|
+
In addition to the predefined transformations contained in this module.
|
|
14
|
+
One can implement their own transformations by implementing the `TransformationPass`
|
|
15
|
+
and `AnalysisPass` abstract classes. See the examples for further details.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from ._core.transformations import * # type: ignore[reportMissingImports] # noqa: F403
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any, Literal, overload
|
|
4
|
+
|
|
5
|
+
from aqmodels import Model, Sense, Solution, Timing, Vtype
|
|
6
|
+
|
|
7
|
+
class BasePass:
|
|
8
|
+
@property
|
|
9
|
+
def name(self) -> str:
|
|
10
|
+
"""Get the name of this pass."""
|
|
11
|
+
...
|
|
12
|
+
@property
|
|
13
|
+
def requires(self) -> list[str]:
|
|
14
|
+
"""Get a list of required passes that need to be run before this pass."""
|
|
15
|
+
...
|
|
16
|
+
|
|
17
|
+
class TransformationPass(BasePass):
|
|
18
|
+
@property
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def name(self) -> str:
|
|
21
|
+
"""Get the name of this pass."""
|
|
22
|
+
...
|
|
23
|
+
@property
|
|
24
|
+
def requires(self) -> list[str]:
|
|
25
|
+
"""Get a list of required passes that need to be run before this pass."""
|
|
26
|
+
...
|
|
27
|
+
@property
|
|
28
|
+
def invalidates(self) -> list[str]:
|
|
29
|
+
"""Get a list of passes that are invalidated by this pass."""
|
|
30
|
+
...
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def run(self, model: Model, cache: AnalysisCache) -> tuple[Model, ActionType]:
|
|
33
|
+
"""Run/Execute this transformation pass."""
|
|
34
|
+
...
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def backwards(self, solution: Solution, cache: AnalysisCache) -> Solution:
|
|
37
|
+
"""Convert a solution back to fit this pass' input.
|
|
38
|
+
|
|
39
|
+
Convert a solution from a representation fitting this pass' output to
|
|
40
|
+
a solution representation fitting this pass' input.
|
|
41
|
+
"""
|
|
42
|
+
...
|
|
43
|
+
|
|
44
|
+
class AnalysisCache:
|
|
45
|
+
@overload
|
|
46
|
+
def __getitem__( # type: ignore[reportOverlappingOverload]
|
|
47
|
+
self, key: Literal["max-bias"]
|
|
48
|
+
) -> MaxBias: ...
|
|
49
|
+
@overload
|
|
50
|
+
def __getitem__(self, key: str) -> dict[Any, Any]: ...
|
|
51
|
+
def __getitem__(self, key: str) -> Any:
|
|
52
|
+
"""Get the analysis result for a specific analysis pass."""
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
class AnalysisPass(BasePass):
|
|
56
|
+
@property
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def name(self) -> str:
|
|
59
|
+
"""Get the name of this pass."""
|
|
60
|
+
...
|
|
61
|
+
@property
|
|
62
|
+
def requires(self) -> list[str]:
|
|
63
|
+
"""Get a list of required passes that need to be run before this pass."""
|
|
64
|
+
...
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def run(self, model: Model, cache: AnalysisCache) -> float:
|
|
67
|
+
"""Run/Execute this analysis pass."""
|
|
68
|
+
...
|
|
69
|
+
|
|
70
|
+
class ActionType(Enum):
|
|
71
|
+
DidTransform = ...
|
|
72
|
+
"""Indicate that the pass did transform the model."""
|
|
73
|
+
DidAnalysis = ...
|
|
74
|
+
"""Indicate that the pass did analyse the model."""
|
|
75
|
+
Nothing = ...
|
|
76
|
+
"""Indicate that the pass did NOT do anything."""
|
|
77
|
+
|
|
78
|
+
class ChangeSensePass(BasePass):
|
|
79
|
+
"""A transformation pass to change the model's Sense to a target Sense."""
|
|
80
|
+
|
|
81
|
+
def __init__(self, sense: Sense) -> None:
|
|
82
|
+
"""Transform the model's Sense to a target Sense.
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
sense : Sense
|
|
87
|
+
The target sense of the model after calling the `run` method on it.
|
|
88
|
+
"""
|
|
89
|
+
...
|
|
90
|
+
@property
|
|
91
|
+
def sense(self) -> Sense:
|
|
92
|
+
"""Get the specified target sense of this pass."""
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
class MaxBias:
|
|
96
|
+
"""An analysis pass result storing the max bias (coefficient) of a model."""
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def val(self) -> float:
|
|
100
|
+
"""Get the value of the maxium bias."""
|
|
101
|
+
...
|
|
102
|
+
|
|
103
|
+
class MaxBiasAnalysis(BasePass):
|
|
104
|
+
"""An analysis pass computing the maximum bias contained in the model."""
|
|
105
|
+
|
|
106
|
+
def __init__(self) -> None: ...
|
|
107
|
+
|
|
108
|
+
class BinarySpinAnalysis(BasePass):
|
|
109
|
+
"""An analysis pass noting down which variables need to be transformed."""
|
|
110
|
+
|
|
111
|
+
def __init__(self, vtype: Literal[Vtype.Binary, Vtype.Spin]) -> None: ...
|
|
112
|
+
@property
|
|
113
|
+
def vtype(self) -> Vtype:
|
|
114
|
+
"""Get the target vtype."""
|
|
115
|
+
...
|
|
116
|
+
|
|
117
|
+
class BinarySpinInfo:
|
|
118
|
+
@property
|
|
119
|
+
def old_vtype(self) -> Vtype:
|
|
120
|
+
"""Get the source vtype."""
|
|
121
|
+
...
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def new_vtype(self) -> Vtype:
|
|
125
|
+
"""Get the target vtype."""
|
|
126
|
+
...
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def map(self) -> dict[str, str]:
|
|
130
|
+
"""Get the variable name mapping."""
|
|
131
|
+
...
|
|
132
|
+
|
|
133
|
+
class BinarySpinPass(BasePass):
|
|
134
|
+
"""An transformation pass changing the denoted variables to target."""
|
|
135
|
+
|
|
136
|
+
def __init__(self) -> None: ...
|
|
137
|
+
|
|
138
|
+
class LogElement:
|
|
139
|
+
"""An element of the execution log of an intermediate representation (IR)."""
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def pass_name(self) -> str:
|
|
143
|
+
"""The name of the pass."""
|
|
144
|
+
...
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def timing(self) -> Timing:
|
|
148
|
+
"""Timing information for this log element."""
|
|
149
|
+
...
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def kind(self) -> ActionType | None:
|
|
153
|
+
"""Transformation type information for this log element, if available."""
|
|
154
|
+
...
|
|
155
|
+
|
|
156
|
+
class IR:
|
|
157
|
+
"""The intermediate representation (IR) of a model after transformation.
|
|
158
|
+
|
|
159
|
+
The IR contains the resulting model after transformation (`ir.model`) as well
|
|
160
|
+
as the analysis cache (`ir.cache`) and an execution log (`ir.execution_log`).
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def model(self) -> Model:
|
|
165
|
+
"""Get the model stored in the IR."""
|
|
166
|
+
...
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def cache(self) -> AnalysisCache:
|
|
170
|
+
"""Get the analysis cache stored the IR."""
|
|
171
|
+
...
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def execution_log(self) -> list[LogElement]:
|
|
175
|
+
"""Get the analysis cache stored the IR."""
|
|
176
|
+
...
|
|
177
|
+
|
|
178
|
+
class PassManager:
|
|
179
|
+
"""Manage and execute a sequence of passes on a model.
|
|
180
|
+
|
|
181
|
+
The PassManager implements a compiler-style pass pattern, enabling both
|
|
182
|
+
general-purpose and algorithm-specific manipulations of optimization
|
|
183
|
+
models. Each pass is an atomic operation (for example, ChangeSensePass)
|
|
184
|
+
that transforms the model or its intermediate representation (IR). The
|
|
185
|
+
PassManager runs each pass in order and produces a rich IR that records
|
|
186
|
+
the transformations applied and supports back-transformations.
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
def __init__(
|
|
190
|
+
self, passes: list[BasePass | TransformationPass | AnalysisPass]
|
|
191
|
+
) -> None:
|
|
192
|
+
"""Manage and execute a sequence of passes on a model.
|
|
193
|
+
|
|
194
|
+
The PassManager implements a compiler-style pass pattern, enabling both
|
|
195
|
+
general-purpose and algorithm-specific manipulations of optimization
|
|
196
|
+
models. Each pass is an atomic operation (for example, ChangeSensePass)
|
|
197
|
+
that transforms the model or its intermediate representation (IR). The
|
|
198
|
+
PassManager runs each pass in order and produces a rich IR that records
|
|
199
|
+
the transformations applied and supports back-transformations.
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
passes : list[TransformationPass | AnalysisPass]
|
|
204
|
+
An ordered sequence of Pass instances to apply. Each Pass must conform to
|
|
205
|
+
the `TransformationPass` or `AnalysisPass` interface.
|
|
206
|
+
"""
|
|
207
|
+
...
|
|
208
|
+
|
|
209
|
+
def run(self, model: Model) -> IR:
|
|
210
|
+
"""Apply all configures passes.
|
|
211
|
+
|
|
212
|
+
Apply all configured passes to the given model and return the
|
|
213
|
+
resulting intermediate representation.
|
|
214
|
+
|
|
215
|
+
Parameters
|
|
216
|
+
----------
|
|
217
|
+
model : Model
|
|
218
|
+
The model to be transformed.
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
IR
|
|
223
|
+
The intermediate representation of the model after transformation.
|
|
224
|
+
"""
|
|
225
|
+
...
|
|
226
|
+
|
|
227
|
+
def backwards(self, solution: Solution, ir: IR) -> Solution:
|
|
228
|
+
"""Apply the back transformation to the given solution.
|
|
229
|
+
|
|
230
|
+
Parameters
|
|
231
|
+
----------
|
|
232
|
+
solution : Solution
|
|
233
|
+
The solution to transform back to a representation fitting the original
|
|
234
|
+
(input) model of this `PassManager`.
|
|
235
|
+
ir : IR
|
|
236
|
+
The intermediate representation (IR) resulted from the `run` call.
|
|
237
|
+
|
|
238
|
+
Returns
|
|
239
|
+
-------
|
|
240
|
+
Solution
|
|
241
|
+
A solution object representing a solution to the original problem passed
|
|
242
|
+
to this `PassManager`'s run method.
|
|
243
|
+
"""
|
|
244
|
+
...
|
|
245
|
+
|
|
246
|
+
__all__ = [
|
|
247
|
+
"IR",
|
|
248
|
+
"ActionType",
|
|
249
|
+
"AnalysisCache",
|
|
250
|
+
"AnalysisPass",
|
|
251
|
+
"BasePass",
|
|
252
|
+
"ChangeSensePass",
|
|
253
|
+
"LogElement",
|
|
254
|
+
"MaxBias",
|
|
255
|
+
"MaxBiasAnalysis",
|
|
256
|
+
"PassManager",
|
|
257
|
+
"TransformationPass",
|
|
258
|
+
]
|
luna_quantum/translator.pyi
CHANGED
|
@@ -353,8 +353,8 @@ class NumpyTranslator:
|
|
|
353
353
|
*,
|
|
354
354
|
env: Environment | None = ...,
|
|
355
355
|
) -> Solution:
|
|
356
|
-
"""
|
|
357
|
-
|
|
356
|
+
"""Convert a solution in the format of numpy arrays to our solution format.
|
|
357
|
+
|
|
358
358
|
Note that the optimization sense is always assumed to be minimization.
|
|
359
359
|
|
|
360
360
|
Parameters
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
import sys
|
|
3
|
+
from logging import Logger
|
|
4
|
+
|
|
5
|
+
from rich import box
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
|
|
8
|
+
from luna_quantum._core import __aq_model_version__, __luna_quantum_version__
|
|
9
|
+
from luna_quantum.util.log_utils import Logging
|
|
10
|
+
|
|
11
|
+
_logger: Logger = Logging.get_logger(__name__)
|
|
12
|
+
_pkg_list: list[str] = ["numpy", "pydantic"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def debug_info() -> None:
|
|
16
|
+
"""Print debug information."""
|
|
17
|
+
python_version = (
|
|
18
|
+
f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
19
|
+
)
|
|
20
|
+
os_info = f"{platform.system()} {platform.release()}"
|
|
21
|
+
|
|
22
|
+
# Get additional system information
|
|
23
|
+
architecture = platform.machine()
|
|
24
|
+
python_implementation = platform.python_implementation()
|
|
25
|
+
|
|
26
|
+
table = Table(
|
|
27
|
+
title="Luna Debug Information",
|
|
28
|
+
title_justify="left",
|
|
29
|
+
caption="System and environment details for troubleshooting",
|
|
30
|
+
box=box.MARKDOWN,
|
|
31
|
+
)
|
|
32
|
+
table.add_column("Property", style="cyan", no_wrap=True)
|
|
33
|
+
table.add_column("Version", style="green", no_wrap=True)
|
|
34
|
+
|
|
35
|
+
# Add rows to the table
|
|
36
|
+
table.add_row("Luna Quantum", f"{__luna_quantum_version__}")
|
|
37
|
+
table.add_row("AqModel", f"{__aq_model_version__}")
|
|
38
|
+
table.add_row("Python", f"{python_version}")
|
|
39
|
+
table.add_row("Python Implementation", f"{python_implementation}")
|
|
40
|
+
table.add_row("Operating System", f"{os_info}")
|
|
41
|
+
table.add_row("Architecture", f"{architecture}")
|
|
42
|
+
|
|
43
|
+
for package in _pkg_list:
|
|
44
|
+
try:
|
|
45
|
+
module = __import__(package)
|
|
46
|
+
version = getattr(module, "__version__", "pkg found, version unknown")
|
|
47
|
+
table.add_row(package, version)
|
|
48
|
+
except ImportError:
|
|
49
|
+
table.add_row(package, "pkg not found")
|
|
50
|
+
|
|
51
|
+
# Print the table to console
|
|
52
|
+
Logging.get_console().print(table)
|
luna_quantum/util/log_utils.py
CHANGED
|
@@ -56,6 +56,20 @@ class Logging:
|
|
|
56
56
|
"""
|
|
57
57
|
return Logging._log_level
|
|
58
58
|
|
|
59
|
+
@staticmethod
|
|
60
|
+
def get_console() -> Console:
|
|
61
|
+
"""Return a Rich console instance for use in logging."""
|
|
62
|
+
custom_theme = Theme(
|
|
63
|
+
{
|
|
64
|
+
"logging.level.debug": "bright_blue",
|
|
65
|
+
"logging.level.info": "bright_green",
|
|
66
|
+
"logging.level.warning": "bold bright_yellow",
|
|
67
|
+
"logging.level.error": "bold bright_red",
|
|
68
|
+
"logging.level.critical": "bold bright_magenta",
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
return Console(theme=custom_theme)
|
|
72
|
+
|
|
59
73
|
@staticmethod
|
|
60
74
|
def get_logger(name: str) -> logging.Logger:
|
|
61
75
|
"""Get a logger with the specified name and set up a RichHandler for it.
|
|
@@ -77,18 +91,8 @@ class Logging:
|
|
|
77
91
|
if logger.hasHandlers():
|
|
78
92
|
return logger
|
|
79
93
|
|
|
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
94
|
handler = RichHandler(
|
|
91
|
-
console=
|
|
95
|
+
console=Logging.get_console(),
|
|
92
96
|
rich_tracebacks=True,
|
|
93
97
|
show_time=True,
|
|
94
98
|
show_level=True,
|
luna_quantum/utils.py
CHANGED
|
@@ -1,72 +1,3 @@
|
|
|
1
1
|
"""Utility module containing convenience functions."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
|
|
5
|
-
from ._core import Expression, Variable
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class InvalidStartTypeError(TypeError):
|
|
9
|
-
"""To be raised when an invalid start type is specified in quicksum."""
|
|
10
|
-
|
|
11
|
-
def __init__(self, actual: type) -> None:
|
|
12
|
-
super().__init__(f"start must be of type `Expression`, is '{actual}'")
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class StartCannotBeInferredError(TypeError):
|
|
16
|
-
"""To be raised when the start value in the quicksum cannot be inferred."""
|
|
17
|
-
|
|
18
|
-
def __init__(self) -> None:
|
|
19
|
-
super().__init__(
|
|
20
|
-
"iterable must contain at least one Expression or Variable, "
|
|
21
|
-
"or 'start' needs to be set."
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def quicksum(
|
|
26
|
-
iterable: Iterable[Expression | Variable | int | float],
|
|
27
|
-
/,
|
|
28
|
-
start: Expression | None = None,
|
|
29
|
-
) -> Expression:
|
|
30
|
-
"""Sum over an Iterable of Expression, Variable, int or float values.
|
|
31
|
-
|
|
32
|
-
Create an Expression based on an iterable of Expression, Variable, int or float
|
|
33
|
-
elements. Note that either the `iterable` must contain at least one `Expression`
|
|
34
|
-
or `Variable` or the start parameter is set.
|
|
35
|
-
|
|
36
|
-
Parameters
|
|
37
|
-
----------
|
|
38
|
-
iterable : Iterable[Expression | Variable | int | float]
|
|
39
|
-
The iterable of elements to sum up.
|
|
40
|
-
start : Expression | None, optional
|
|
41
|
-
The starting value for the summation.
|
|
42
|
-
|
|
43
|
-
Returns
|
|
44
|
-
-------
|
|
45
|
-
Expression
|
|
46
|
-
The expression created based on the sum of the iterable elements.
|
|
47
|
-
|
|
48
|
-
Raises
|
|
49
|
-
------
|
|
50
|
-
TypeError (InvalidStartTypeError | StartCannotBeInferredError)
|
|
51
|
-
If the `iterable` does not contain any Expression or Variable.
|
|
52
|
-
If the `start` is not of type Expression.
|
|
53
|
-
"""
|
|
54
|
-
items = list(iterable)
|
|
55
|
-
if start is None:
|
|
56
|
-
for item in items:
|
|
57
|
-
if isinstance(item, Expression | Variable):
|
|
58
|
-
start = Expression(env=item._environment) # noqa: SLF001
|
|
59
|
-
break
|
|
60
|
-
|
|
61
|
-
if start is None:
|
|
62
|
-
raise StartCannotBeInferredError
|
|
63
|
-
|
|
64
|
-
if not isinstance(start, Expression):
|
|
65
|
-
raise InvalidStartTypeError(type(start))
|
|
66
|
-
|
|
67
|
-
_start: Expression = start
|
|
68
|
-
|
|
69
|
-
for item in items:
|
|
70
|
-
_start += item
|
|
71
|
-
|
|
72
|
-
return _start
|
|
3
|
+
from ._core.utils import * # type: ignore[reportMissingImports] # noqa: F403
|
luna_quantum/utils.pyi
CHANGED
|
@@ -1,8 +1,38 @@
|
|
|
1
|
-
from collections.abc import Iterable
|
|
1
|
+
from collections.abc import Generator, Iterable
|
|
2
2
|
from typing import overload
|
|
3
3
|
|
|
4
4
|
from aqmodels import Expression, Variable
|
|
5
5
|
|
|
6
|
+
@overload
|
|
7
|
+
def quicksum(iterable: Generator[Expression], /) -> Expression: ...
|
|
8
|
+
@overload
|
|
9
|
+
def quicksum(iterable: Generator[Variable], /) -> Expression: ...
|
|
10
|
+
@overload
|
|
11
|
+
def quicksum(iterable: Generator[int], /) -> Expression: ...
|
|
12
|
+
@overload
|
|
13
|
+
def quicksum(iterable: Generator[float], /) -> Expression: ...
|
|
14
|
+
@overload
|
|
15
|
+
def quicksum(
|
|
16
|
+
iterable: Generator[Expression], /, start: Expression | None = None
|
|
17
|
+
) -> Expression: ...
|
|
18
|
+
@overload
|
|
19
|
+
def quicksum(
|
|
20
|
+
iterable: Generator[Variable], /, start: Expression | None = None
|
|
21
|
+
) -> Expression: ...
|
|
22
|
+
@overload
|
|
23
|
+
def quicksum(
|
|
24
|
+
iterable: Generator[int], /, start: Expression | None = None
|
|
25
|
+
) -> Expression: ...
|
|
26
|
+
@overload
|
|
27
|
+
def quicksum(
|
|
28
|
+
iterable: Generator[float], /, start: Expression | None = None
|
|
29
|
+
) -> Expression: ...
|
|
30
|
+
@overload
|
|
31
|
+
def quicksum(
|
|
32
|
+
iterable: Generator[Expression | Variable | float | int],
|
|
33
|
+
/,
|
|
34
|
+
start: Expression | None = None,
|
|
35
|
+
) -> Expression: ...
|
|
6
36
|
@overload
|
|
7
37
|
def quicksum(iterable: Iterable[Expression], /) -> Expression: ...
|
|
8
38
|
@overload
|
|
@@ -33,3 +63,5 @@ def quicksum(
|
|
|
33
63
|
/,
|
|
34
64
|
start: Expression | None = None,
|
|
35
65
|
) -> Expression: ...
|
|
66
|
+
|
|
67
|
+
__all__ = ["quicksum"]
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
luna_quantum-1.0.
|
|
2
|
-
luna_quantum-1.0.
|
|
3
|
-
luna_quantum-1.0.
|
|
4
|
-
luna_quantum-1.0.
|
|
1
|
+
luna_quantum-1.0.1rc12.dist-info/METADATA,sha256=pEDnj6mbjx4gb1REdYGhvpjeXA5i9UR78gn9PeAEF3Q,1534
|
|
2
|
+
luna_quantum-1.0.1rc12.dist-info/WHEEL,sha256=jZZY8bQzT_o5crDPUQjeLS44sCW9WfRFzt3T2aga1Ns,107
|
|
3
|
+
luna_quantum-1.0.1rc12.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
4
|
+
luna_quantum-1.0.1rc12.dist-info/licenses/NOTICE,sha256=noPOS8eDj5XoyRO8ZrCxIOh5fSjk0RildIrrqxQlepY,588
|
|
5
5
|
luna_quantum.libs/libgcc_s-02f3f192.so.1,sha256=gjFsHm1qybp9dieBvfXS4hYl26XxiP3ydWHYntFhKVk,189441
|
|
6
|
-
luna_quantum/__init__.py,sha256=
|
|
7
|
-
luna_quantum/__init__.pyi,sha256=
|
|
8
|
-
luna_quantum/_core.cpython-313-x86_64-linux-musl.so,sha256=
|
|
9
|
-
luna_quantum/_core.pyi,sha256=
|
|
6
|
+
luna_quantum/__init__.py,sha256=VVqJBFKl8ET7gJmebXVnTsD33sIFfhxKm7_eB12YVkU,3170
|
|
7
|
+
luna_quantum/__init__.pyi,sha256=dG3-NeEI8ApxHUcVq-Ov9Pa9D3Px_5yWUWkxhLsfL80,1608
|
|
8
|
+
luna_quantum/_core.cpython-313-x86_64-linux-musl.so,sha256=MA-bYPljI05jJgFmZYq4gveMbWUmNq0nLVDoJLj44gM,5123977
|
|
9
|
+
luna_quantum/_core.pyi,sha256=dVgYQVxIfHdWQEYLYAkVUDulGlXQ9ktBdln_V7NnmNc,104258
|
|
10
10
|
luna_quantum/algorithms/__init__.py,sha256=IX9ZpzY3Do3mTgKqto5vAWwdYrZrM-RemYSf64yxefg,69
|
|
11
11
|
luna_quantum/aqm_overwrites/__init__.py,sha256=rteObr5JHDnTnRime0Euq9Qy2iDIp6VMpFNHTGVNBe0,46
|
|
12
12
|
luna_quantum/aqm_overwrites/model.py,sha256=La5mh-aS2LNLaQFp_B1EnhrKUXVRRmIqGnIvX66uc8Y,6099
|
|
@@ -82,7 +82,7 @@ luna_quantum/client/schemas/wrappers/datetime_wrapper.py,sha256=8K2jexTarxGCgD1u
|
|
|
82
82
|
luna_quantum/client/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
83
83
|
luna_quantum/client/utils/qpu_token_utils.py,sha256=xeWIKcBwXGSQ0INfUY3NMTu6H90T03jkT85yHs2QXmk,4768
|
|
84
84
|
luna_quantum/errors.py,sha256=yjeXB3i07LlTuuJ18IKgwsC5wmtJElN8cDwlg3JkcEs,1424
|
|
85
|
-
luna_quantum/errors.pyi,sha256=
|
|
85
|
+
luna_quantum/errors.pyi,sha256=sB9AKnafl1-duUZQPJNGDGBqE41QFhk1BX1jgBkqW6A,8745
|
|
86
86
|
luna_quantum/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
87
87
|
luna_quantum/exceptions/base_luna_quantum_error.py,sha256=qC712QkF04FiY_qwQ5HlIYVhg5P6WzXJ_chJDVTpWXI,89
|
|
88
88
|
luna_quantum/exceptions/patch_class_field_exists_error.py,sha256=3TGKb-MNyjwntrJkbRaBKEvlsj68ROTwCltDt6Zg7Gg,398
|
|
@@ -243,14 +243,17 @@ luna_quantum/solve/usecases/solve_job_create_usecase.py,sha256=IcKN2VWTGw3J3Wgnt
|
|
|
243
243
|
luna_quantum/solve/usecases/solve_job_delete_usecase.py,sha256=hUOLeFLU9NCggWMGuIJG7WYShQjP4H_iZJnPvBJgTpA,1128
|
|
244
244
|
luna_quantum/solve/usecases/solve_job_fetch_updates_usecase.py,sha256=W-Z6Q7IuyodjZmFKEsJGaa9V2fnGMPWj9FRN9gEdPNc,1686
|
|
245
245
|
luna_quantum/solve/usecases/solve_job_get_result_usecase.py,sha256=dk6LSjInOfH5d7LlbUmawnqytKig_vFTCKTDK5KlDlI,3541
|
|
246
|
+
luna_quantum/transformations.py,sha256=AZtGBaJ0PTWsr4mpONoJq5BpNOXPcM85CnWDhPgXx_I,902
|
|
247
|
+
luna_quantum/transformations.pyi,sha256=D71bSXST8vfib-jSez0s5sg8NJpN5obja4Y0BXoqUjA,7795
|
|
246
248
|
luna_quantum/translator.py,sha256=xi5eiIRNv8ATz69GYpUY5kbEIUmQEtK6_dF5t2Mwpec,1134
|
|
247
|
-
luna_quantum/translator.pyi,sha256=
|
|
249
|
+
luna_quantum/translator.pyi,sha256=1kQyDBUWKV6vTyydC_f2K1aQzbW6_8sdcpgxCZJVaM4,26329
|
|
248
250
|
luna_quantum/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
249
251
|
luna_quantum/util/active_waiting.py,sha256=MkLL7UEtWh8jU1Zwd9rYqfcReYPGB7FJLUjQe2v9_Tg,3029
|
|
250
252
|
luna_quantum/util/class_patcher.py,sha256=-vD_7Auh1dQTOJXOKv-4sTQ5EzH3n6I0EsHDFQ_ZPOY,5456
|
|
251
|
-
luna_quantum/util/
|
|
253
|
+
luna_quantum/util/debug_info.py,sha256=UjMcmX5waYEEH51cK8REUOdjpNX0D6HWSR0ns7yQp54,1755
|
|
254
|
+
luna_quantum/util/log_utils.py,sha256=M8Gbt0Pb2CsQsG3fGyuKeT-rl264laEGGXcPCGfBhaQ,4918
|
|
252
255
|
luna_quantum/util/pretty_base.py,sha256=Vv3dYpMsydOPYFOm-0lCCuJIe-62oYkI64Zy_bahl3s,2115
|
|
253
256
|
luna_quantum/util/pydantic_utils.py,sha256=nhl_SdLJVAizrtLVHvnbco84g8CdBVdVxN_jlXiv82w,1263
|
|
254
|
-
luna_quantum/utils.py,sha256=
|
|
255
|
-
luna_quantum/utils.pyi,sha256=
|
|
256
|
-
luna_quantum-1.0.
|
|
257
|
+
luna_quantum/utils.py,sha256=pBOkGXNJXlOzxAwTJv8nCj32Q6WNeh3t6Ka3lmTgy9c,134
|
|
258
|
+
luna_quantum/utils.pyi,sha256=afjDJhGiM9KmN2zqVkd6agP8JAsbwUxJBW9tEyiFrdY,1941
|
|
259
|
+
luna_quantum-1.0.1rc12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|