classiq 0.39.0__py3-none-any.whl → 0.40.0__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.
- classiq/__init__.py +1 -0
- classiq/applications/chemistry/chemistry_model_constructor.py +1 -1
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +5 -6
- classiq/applications/combinatorial_helpers/optimization_model.py +7 -6
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -10
- classiq/applications/combinatorial_optimization/__init__.py +2 -0
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +5 -5
- classiq/interface/backend/quantum_backend_providers.py +7 -7
- classiq/interface/executor/execution_preferences.py +4 -9
- classiq/interface/generator/application_apis/chemistry_declarations.py +2 -4
- classiq/interface/generator/application_apis/finance_declarations.py +1 -1
- classiq/interface/generator/arith/arithmetic_expression_validator.py +2 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +82 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +21 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +22 -0
- classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +8 -6
- classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +10 -4
- classiq/interface/generator/functions/builtins/open_lib_functions.py +624 -76
- classiq/interface/generator/functions/classical_type.py +29 -17
- classiq/interface/generator/model/preferences/preferences.py +4 -2
- classiq/interface/model/control.py +104 -8
- classiq/interface/model/quantum_type.py +6 -5
- classiq/interface/model/resolvers/function_call_resolver.py +0 -5
- classiq/interface/model/statement_block.py +1 -4
- classiq/qmod/__init__.py +6 -2
- classiq/qmod/builtins/classical_functions.py +30 -35
- classiq/qmod/builtins/functions.py +213 -153
- classiq/qmod/builtins/operations.py +78 -24
- classiq/qmod/builtins/structs.py +50 -48
- classiq/qmod/declaration_inferrer.py +30 -18
- classiq/qmod/native/expression_to_qmod.py +5 -4
- classiq/qmod/native/pretty_printer.py +7 -14
- classiq/qmod/qmod_constant.py +7 -7
- classiq/qmod/qmod_parameter.py +54 -33
- classiq/qmod/qmod_struct.py +2 -2
- classiq/qmod/qmod_variable.py +40 -29
- classiq/qmod/quantum_callable.py +7 -4
- classiq/qmod/quantum_expandable.py +19 -13
- classiq/qmod/quantum_function.py +25 -2
- classiq/qmod/symbolic.py +78 -68
- classiq/qmod/symbolic_expr.py +1 -1
- classiq/qmod/symbolic_type.py +1 -4
- classiq/qmod/utilities.py +29 -0
- {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/METADATA +1 -1
- {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/RECORD +48 -50
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
- classiq/interface/model/quantum_if_operation.py +0 -94
- {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/WHEEL +0 -0
classiq/qmod/qmod_parameter.py
CHANGED
@@ -26,21 +26,54 @@ _T = TypeVar("_T")
|
|
26
26
|
|
27
27
|
|
28
28
|
if TYPE_CHECKING:
|
29
|
+
SymbolicSuperclass = SymbolicExpr
|
30
|
+
else:
|
31
|
+
SymbolicSuperclass = Symbolic
|
29
32
|
|
30
|
-
class QParam(SymbolicExpr, Generic[_T]):
|
31
|
-
pass
|
32
33
|
|
33
|
-
|
34
|
+
class CParam(SymbolicSuperclass):
|
35
|
+
pass
|
36
|
+
|
37
|
+
|
38
|
+
class QParam(CParam, Generic[_T]):
|
39
|
+
pass
|
40
|
+
|
41
|
+
|
42
|
+
class CInt(CParam):
|
43
|
+
pass
|
44
|
+
|
45
|
+
|
46
|
+
class CReal(CParam):
|
47
|
+
pass
|
48
|
+
|
49
|
+
|
50
|
+
class CBool(CParam):
|
51
|
+
pass
|
52
|
+
|
53
|
+
|
54
|
+
_P = ParamSpec("_P")
|
55
|
+
|
56
|
+
|
57
|
+
class ArrayBase(Generic[_P]):
|
58
|
+
# Support comma-separated generic args in older Python versions
|
59
|
+
if sys.version_info[0:2] < (3, 10):
|
60
|
+
|
61
|
+
def __class_getitem__(cls, args) -> _GenericAlias:
|
62
|
+
return _GenericAlias(cls, args)
|
63
|
+
|
64
|
+
|
65
|
+
class CArray(CParam, ArrayBase[_P]):
|
66
|
+
if TYPE_CHECKING:
|
34
67
|
|
35
|
-
|
36
|
-
|
68
|
+
@property
|
69
|
+
def len(self) -> int: ...
|
37
70
|
|
38
71
|
|
39
|
-
class
|
72
|
+
class CParamScalar(CParam, SymbolicExpr):
|
40
73
|
pass
|
41
74
|
|
42
75
|
|
43
|
-
class
|
76
|
+
class CParamList(CParam):
|
44
77
|
def __init__(
|
45
78
|
self,
|
46
79
|
expr: str,
|
@@ -51,7 +84,7 @@ class QParamList(QParam):
|
|
51
84
|
self._qmodule = qmodule
|
52
85
|
self._list_type = list_type
|
53
86
|
|
54
|
-
def __getitem__(self, key: Any) ->
|
87
|
+
def __getitem__(self, key: Any) -> CParam:
|
55
88
|
return create_param(
|
56
89
|
f"({self})[{key}]",
|
57
90
|
self._list_type.element_type,
|
@@ -64,11 +97,11 @@ class QParamList(QParam):
|
|
64
97
|
)
|
65
98
|
|
66
99
|
@property
|
67
|
-
def len(self) ->
|
68
|
-
return
|
100
|
+
def len(self) -> CParamScalar:
|
101
|
+
return CParamScalar(f"get_field({self}, 'len')")
|
69
102
|
|
70
103
|
|
71
|
-
class
|
104
|
+
class CParamStruct(CParam):
|
72
105
|
def __init__(
|
73
106
|
self, expr: str, struct_type: Struct, *, qmodule: ModelStateContainer
|
74
107
|
) -> None:
|
@@ -76,8 +109,8 @@ class QParamStruct(QParam):
|
|
76
109
|
self._qmodule = qmodule
|
77
110
|
self._struct_type = struct_type
|
78
111
|
|
79
|
-
def __getattr__(self, field_name: str) ->
|
80
|
-
return
|
112
|
+
def __getattr__(self, field_name: str) -> CParam:
|
113
|
+
return CParamStruct.get_field(
|
81
114
|
self._qmodule, str(self), self._struct_type.name, field_name
|
82
115
|
)
|
83
116
|
|
@@ -87,7 +120,7 @@ class QParamStruct(QParam):
|
|
87
120
|
variable_name: str,
|
88
121
|
struct_name: str,
|
89
122
|
field_name: str,
|
90
|
-
) ->
|
123
|
+
) -> CParam:
|
91
124
|
struct_decl = StructDeclaration.BUILTIN_STRUCT_DECLARATIONS.get(
|
92
125
|
struct_name, qmodule.type_decls.get(struct_name)
|
93
126
|
)
|
@@ -105,27 +138,15 @@ class QParamStruct(QParam):
|
|
105
138
|
)
|
106
139
|
|
107
140
|
|
108
|
-
_P = ParamSpec("_P")
|
109
|
-
|
110
|
-
|
111
|
-
class ArrayBase(Generic[_P]):
|
112
|
-
# Support comma-separated generic args in older Python versions
|
113
|
-
if sys.version_info[0:2] < (3, 10):
|
114
|
-
|
115
|
-
def __class_getitem__(cls, args) -> _GenericAlias:
|
116
|
-
return _GenericAlias(cls, args)
|
117
|
-
|
118
|
-
|
119
|
-
class Array(ArrayBase[_P]):
|
120
|
-
pass
|
121
|
-
|
122
|
-
|
123
141
|
def create_param(
|
124
142
|
expr_str: str, ctype: ClassicalType, qmodule: ModelStateContainer
|
125
|
-
) ->
|
143
|
+
) -> CParam:
|
126
144
|
if isinstance(ctype, (ClassicalList, ClassicalArray)):
|
127
|
-
return
|
145
|
+
return CParamList(expr_str, ctype, qmodule=qmodule)
|
128
146
|
elif isinstance(ctype, Struct):
|
129
|
-
return
|
147
|
+
return CParamStruct(expr_str, ctype, qmodule=qmodule)
|
130
148
|
else:
|
131
|
-
return
|
149
|
+
return CParamScalar(expr_str)
|
150
|
+
|
151
|
+
|
152
|
+
Array = CArray
|
classiq/qmod/qmod_struct.py
CHANGED
@@ -3,7 +3,7 @@ from typing import Any, Type
|
|
3
3
|
|
4
4
|
from typing_extensions import dataclass_transform
|
5
5
|
|
6
|
-
from classiq.interface.generator.functions.classical_type import
|
6
|
+
from classiq.interface.generator.functions.classical_type import CStructBase
|
7
7
|
|
8
8
|
|
9
9
|
def _qmod_val_to_expr_str(val: Any) -> str:
|
@@ -30,7 +30,7 @@ def struct(user_class: Type) -> Type:
|
|
30
30
|
|
31
31
|
user_dataclass = type(
|
32
32
|
user_class.__name__,
|
33
|
-
(
|
33
|
+
(CStructBase, dataclasses.dataclass(user_class)),
|
34
34
|
dict(),
|
35
35
|
)
|
36
36
|
user_dataclass.__repr__ = _new_repr # type:ignore[assignment]
|
classiq/qmod/qmod_variable.py
CHANGED
@@ -21,6 +21,7 @@ from typing import ( # type: ignore[attr-defined]
|
|
21
21
|
|
22
22
|
from typing_extensions import Annotated, ParamSpec, Self, _AnnotatedAlias
|
23
23
|
|
24
|
+
from classiq.interface.ast_node import SourceReference
|
24
25
|
from classiq.interface.generator.expressions.expression import Expression
|
25
26
|
from classiq.interface.generator.functions.port_declaration import (
|
26
27
|
PortDeclarationDirection,
|
@@ -45,11 +46,11 @@ from classiq.interface.model.quantum_type import (
|
|
45
46
|
)
|
46
47
|
|
47
48
|
from classiq.exceptions import ClassiqValueError
|
48
|
-
from classiq.qmod.qmod_parameter import ArrayBase,
|
49
|
+
from classiq.qmod.qmod_parameter import ArrayBase, CBool, CInt, CParam, CParamScalar
|
49
50
|
from classiq.qmod.quantum_callable import QCallable
|
50
51
|
from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
|
51
52
|
from classiq.qmod.symbolic_type import SymbolicTypes
|
52
|
-
from classiq.qmod.utilities import version_portable_get_args
|
53
|
+
from classiq.qmod.utilities import get_source_ref, version_portable_get_args
|
53
54
|
|
54
55
|
ILLEGAL_SLICING_STEP_MSG = "Slicing with a step of a quantum variable is not supported"
|
55
56
|
SLICE_OUT_OF_BOUNDS_MSG = "Slice end index out of bounds"
|
@@ -82,8 +83,9 @@ def _no_current_expandable() -> Iterator[None]:
|
|
82
83
|
QCallable.CURRENT_EXPANDABLE = current_expandable
|
83
84
|
|
84
85
|
|
85
|
-
class QVar:
|
86
|
+
class QVar(Symbolic):
|
86
87
|
def __init__(self, name: str) -> None:
|
88
|
+
super().__init__(name)
|
87
89
|
self._name = name
|
88
90
|
if QCallable.CURRENT_EXPANDABLE is not None:
|
89
91
|
QCallable.CURRENT_EXPANDABLE.add_local_handle(
|
@@ -120,6 +122,9 @@ class QVar:
|
|
120
122
|
assert type_hint == cls or get_origin(type_hint) == cls
|
121
123
|
return PortDeclarationDirection.Inout
|
122
124
|
|
125
|
+
def __str__(self) -> str:
|
126
|
+
return str(self.get_handle_binding())
|
127
|
+
|
123
128
|
|
124
129
|
_Q = TypeVar("_Q", bound=QVar)
|
125
130
|
Output = Annotated[_Q, PortDeclarationDirection.Output]
|
@@ -131,7 +136,9 @@ class QScalar(QVar, SymbolicExpr):
|
|
131
136
|
QVar.__init__(self, name)
|
132
137
|
SymbolicExpr.__init__(self, name)
|
133
138
|
|
134
|
-
def _insert_arith_operation(
|
139
|
+
def _insert_arith_operation(
|
140
|
+
self, expr: SymbolicTypes, inplace: bool, source_ref: SourceReference
|
141
|
+
) -> None:
|
135
142
|
# Fixme: Arithmetic operations are not yet supported on slices (see CAD-12670)
|
136
143
|
if TYPE_CHECKING:
|
137
144
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
@@ -140,16 +147,20 @@ class QScalar(QVar, SymbolicExpr):
|
|
140
147
|
expression=Expression(expr=str(expr)),
|
141
148
|
result_var=self.get_handle_binding(),
|
142
149
|
inplace_result=inplace,
|
150
|
+
source_ref=source_ref,
|
143
151
|
)
|
144
152
|
)
|
145
153
|
|
146
|
-
def _insert_amplitude_loading(
|
154
|
+
def _insert_amplitude_loading(
|
155
|
+
self, expr: SymbolicTypes, source_ref: SourceReference
|
156
|
+
) -> None:
|
147
157
|
if TYPE_CHECKING:
|
148
158
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
149
159
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
150
160
|
AmplitudeLoadingOperation(
|
151
161
|
expression=Expression(expr=str(expr)),
|
152
162
|
result_var=self.get_handle_binding(),
|
163
|
+
source_ref=source_ref,
|
153
164
|
)
|
154
165
|
)
|
155
166
|
|
@@ -162,7 +173,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
162
173
|
f"Invalid argument {other!r} for out-of-place arithmetic operation"
|
163
174
|
)
|
164
175
|
|
165
|
-
self._insert_arith_operation(other, False)
|
176
|
+
self._insert_arith_operation(other, False, get_source_ref(sys._getframe(1)))
|
166
177
|
return self
|
167
178
|
|
168
179
|
def __ixor__(self, other: Any) -> Self:
|
@@ -171,7 +182,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
171
182
|
f"Invalid argument {other!r} for in-place arithmetic operation"
|
172
183
|
)
|
173
184
|
|
174
|
-
self._insert_arith_operation(other, True)
|
185
|
+
self._insert_arith_operation(other, True, get_source_ref(sys._getframe(1)))
|
175
186
|
return self
|
176
187
|
|
177
188
|
def __imul__(self, other: Any) -> Self:
|
@@ -180,7 +191,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
180
191
|
f"Invalid argument {other!r} for out of ampltiude encoding operation"
|
181
192
|
)
|
182
193
|
|
183
|
-
self._insert_amplitude_loading(other)
|
194
|
+
self._insert_amplitude_loading(other, get_source_ref(sys._getframe(1)))
|
184
195
|
return self
|
185
196
|
|
186
197
|
|
@@ -207,18 +218,18 @@ class QNum(Generic[_P], QScalar):
|
|
207
218
|
def __init__(
|
208
219
|
self,
|
209
220
|
name: str,
|
210
|
-
size: Union[int,
|
211
|
-
is_signed: Union[bool,
|
212
|
-
fraction_digits: Union[int,
|
221
|
+
size: Union[int, CInt],
|
222
|
+
is_signed: Union[bool, CBool],
|
223
|
+
fraction_digits: Union[int, CInt],
|
213
224
|
):
|
214
225
|
pass
|
215
226
|
|
216
227
|
def __init__(
|
217
228
|
self,
|
218
229
|
name: str,
|
219
|
-
size: Union[int,
|
220
|
-
is_signed: Union[bool,
|
221
|
-
fraction_digits: Union[int,
|
230
|
+
size: Union[int, CInt, None] = None,
|
231
|
+
is_signed: Union[bool, CBool, None] = None,
|
232
|
+
fraction_digits: Union[int, CInt, None] = None,
|
222
233
|
):
|
223
234
|
if (
|
224
235
|
size is None
|
@@ -244,8 +255,8 @@ class QNum(Generic[_P], QScalar):
|
|
244
255
|
type_args = type_args[0]
|
245
256
|
if len(type_args) != 3:
|
246
257
|
raise ClassiqValueError(
|
247
|
-
"QNum receives three type arguments: QNum[size: int |
|
248
|
-
"is_signed: bool |
|
258
|
+
"QNum receives three type arguments: QNum[size: int | CInt, "
|
259
|
+
"is_signed: bool | CBool, fraction_digits: int | CInt]"
|
249
260
|
)
|
250
261
|
return cls.QMOD_TYPE(
|
251
262
|
size=Expression(expr=get_type_hint_expr(type_args[0])),
|
@@ -261,16 +272,16 @@ class QNum(Generic[_P], QScalar):
|
|
261
272
|
)
|
262
273
|
|
263
274
|
@property
|
264
|
-
def size(self) ->
|
265
|
-
return
|
275
|
+
def size(self) -> CParamScalar:
|
276
|
+
return CParamScalar(f"get_field({self._name}, 'size')")
|
266
277
|
|
267
278
|
@property
|
268
|
-
def fraction_digits(self) ->
|
269
|
-
return
|
279
|
+
def fraction_digits(self) -> CParamScalar:
|
280
|
+
return CParamScalar(f"get_field({self._name}, 'fraction_digits')")
|
270
281
|
|
271
282
|
@property
|
272
|
-
def is_signed(self) ->
|
273
|
-
return
|
283
|
+
def is_signed(self) -> CParamScalar:
|
284
|
+
return CParamScalar(f"get_field({self._name}, 'is_signed')")
|
274
285
|
|
275
286
|
# Support comma-separated generic args in older Python versions
|
276
287
|
if sys.version_info[0:2] < (3, 10):
|
@@ -284,10 +295,10 @@ class QArray(ArrayBase[_P], QVar):
|
|
284
295
|
self,
|
285
296
|
name: str,
|
286
297
|
element_type: _GenericAlias = QBit,
|
287
|
-
length: Optional[Union[int,
|
298
|
+
length: Optional[Union[int, CInt]] = None,
|
288
299
|
# TODO [CAD-18620]: improve type hints
|
289
300
|
slice_: Optional[Tuple[int, int]] = None,
|
290
|
-
index_: Optional[Union[int,
|
301
|
+
index_: Optional[Union[int, CInt]] = None,
|
291
302
|
) -> None:
|
292
303
|
if element_type is not QBit:
|
293
304
|
raise ClassiqValueError(UNSUPPORTED_ELEMENT_TYPE)
|
@@ -313,7 +324,7 @@ class QArray(ArrayBase[_P], QVar):
|
|
313
324
|
|
314
325
|
return HandleBinding(name=self._name)
|
315
326
|
|
316
|
-
def __getitem__(self, key: Union[slice, int,
|
327
|
+
def __getitem__(self, key: Union[slice, int, CInt]) -> "QArray":
|
317
328
|
if self._index is not None:
|
318
329
|
raise ClassiqValueError(QARRAY_ELEMENT_NOT_SUBSCRIPTABLE)
|
319
330
|
|
@@ -326,7 +337,7 @@ class QArray(ArrayBase[_P], QVar):
|
|
326
337
|
new_slice = self._get_new_slice(key.start, key.stop)
|
327
338
|
|
328
339
|
else:
|
329
|
-
if isinstance(key,
|
340
|
+
if isinstance(key, CParam) and not isinstance(key, CParamScalar):
|
330
341
|
raise ClassiqValueError("Non-classical parameter for slicing")
|
331
342
|
new_slice = self._get_new_slice(key, key + 1)
|
332
343
|
new_index = new_slice[0]
|
@@ -368,10 +379,10 @@ class QArray(ArrayBase[_P], QVar):
|
|
368
379
|
else:
|
369
380
|
|
370
381
|
@property
|
371
|
-
def len(self) ->
|
382
|
+
def len(self) -> CParamScalar:
|
372
383
|
if self._length is not None:
|
373
|
-
return
|
374
|
-
return
|
384
|
+
return CParamScalar(f"{self._length}")
|
385
|
+
return CParamScalar(f"get_field({self._name}, 'len')")
|
375
386
|
|
376
387
|
@classmethod
|
377
388
|
def to_qmod_quantum_type(cls, type_hint: Any) -> QuantumType:
|
classiq/qmod/quantum_callable.py
CHANGED
@@ -12,6 +12,7 @@ from typing import ( # type: ignore[attr-defined]
|
|
12
12
|
|
13
13
|
from typing_extensions import ParamSpec
|
14
14
|
|
15
|
+
from classiq.interface.ast_node import SourceReference
|
15
16
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
16
17
|
from classiq.interface.model.quantum_function_declaration import (
|
17
18
|
QuantumFunctionDeclaration,
|
@@ -19,7 +20,8 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
19
20
|
from classiq.interface.model.quantum_statement import QuantumStatement
|
20
21
|
from classiq.interface.model.quantum_type import QuantumType
|
21
22
|
|
22
|
-
from classiq.qmod.qmod_parameter import
|
23
|
+
from classiq.qmod.qmod_parameter import CInt
|
24
|
+
from classiq.qmod.utilities import get_source_ref
|
23
25
|
|
24
26
|
if TYPE_CHECKING:
|
25
27
|
from classiq.qmod.quantum_expandable import QTerminalCallable
|
@@ -42,8 +44,9 @@ class QCallable(Generic[P], ABC):
|
|
42
44
|
|
43
45
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
44
46
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
47
|
+
source_ref = get_source_ref(sys._getframe(1))
|
45
48
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
46
|
-
self.create_quantum_function_call(*args, **kwargs)
|
49
|
+
self.create_quantum_function_call(source_ref, *args, **kwargs)
|
47
50
|
)
|
48
51
|
return
|
49
52
|
|
@@ -60,7 +63,7 @@ class QCallable(Generic[P], ABC):
|
|
60
63
|
|
61
64
|
@abstractmethod
|
62
65
|
def create_quantum_function_call(
|
63
|
-
self, *args: Any, **kwargs: Any
|
66
|
+
self, source_ref_: SourceReference, *args: Any, **kwargs: Any
|
64
67
|
) -> QuantumFunctionCall:
|
65
68
|
raise NotImplementedError()
|
66
69
|
|
@@ -71,5 +74,5 @@ class QCallableList(QCallable, Generic[P], ABC):
|
|
71
74
|
@property
|
72
75
|
def len(self) -> int: ...
|
73
76
|
|
74
|
-
def __getitem__(self, key: Union[slice, int,
|
77
|
+
def __getitem__(self, key: Union[slice, int, CInt]) -> "QTerminalCallable":
|
75
78
|
raise NotImplementedError()
|
@@ -17,6 +17,7 @@ from typing import (
|
|
17
17
|
|
18
18
|
from typing_extensions import Self
|
19
19
|
|
20
|
+
from classiq.interface.ast_node import SourceReference
|
20
21
|
from classiq.interface.generator.expressions.expression import Expression
|
21
22
|
from classiq.interface.model.classical_parameter_declaration import (
|
22
23
|
ClassicalParameterDeclaration,
|
@@ -42,12 +43,12 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
42
43
|
from classiq.exceptions import ClassiqValueError
|
43
44
|
from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
|
44
45
|
from classiq.qmod.qmod_constant import QConstant
|
45
|
-
from classiq.qmod.qmod_parameter import
|
46
|
+
from classiq.qmod.qmod_parameter import CInt, CParam, CParamScalar, create_param
|
46
47
|
from classiq.qmod.qmod_variable import QVar, create_qvar_for_port_decl
|
47
48
|
from classiq.qmod.quantum_callable import QCallable, QExpandableInterface
|
48
49
|
from classiq.qmod.utilities import mangle_keyword
|
49
50
|
|
50
|
-
ArgType = Union[
|
51
|
+
ArgType = Union[CParam, QVar, QCallable]
|
51
52
|
|
52
53
|
|
53
54
|
class QExpandable(QCallable, QExpandableInterface, ABC):
|
@@ -109,9 +110,11 @@ class QExpandable(QCallable, QExpandableInterface, ABC):
|
|
109
110
|
return result
|
110
111
|
|
111
112
|
def create_quantum_function_call(
|
112
|
-
self, *args: Any, **kwargs: Any
|
113
|
+
self, source_ref_: SourceReference, *args: Any, **kwargs: Any
|
113
114
|
) -> QuantumFunctionCall:
|
114
|
-
return _create_quantum_function_call(
|
115
|
+
return _create_quantum_function_call(
|
116
|
+
self.func_decl, None, source_ref_, *args, **kwargs
|
117
|
+
)
|
115
118
|
|
116
119
|
|
117
120
|
class QLambdaFunction(QExpandable):
|
@@ -138,7 +141,7 @@ class QTerminalCallable(QCallable):
|
|
138
141
|
def __init__(
|
139
142
|
self,
|
140
143
|
decl: QuantumFunctionDeclaration,
|
141
|
-
index_: Optional[Union[int,
|
144
|
+
index_: Optional[Union[int, CParamScalar]] = None,
|
142
145
|
) -> None:
|
143
146
|
self._decl = decl
|
144
147
|
self._index = index_
|
@@ -147,12 +150,12 @@ class QTerminalCallable(QCallable):
|
|
147
150
|
def is_list(self) -> bool:
|
148
151
|
return isinstance(self._decl, QuantumOperandDeclaration) and self._decl.is_list
|
149
152
|
|
150
|
-
def __getitem__(self, key: Union[slice, int,
|
153
|
+
def __getitem__(self, key: Union[slice, int, CInt]) -> "QTerminalCallable":
|
151
154
|
if not self.is_list:
|
152
155
|
raise ClassiqValueError("Cannot index a non-list operand")
|
153
156
|
if isinstance(key, slice):
|
154
157
|
raise NotImplementedError("Operand lists don't support slicing")
|
155
|
-
if isinstance(key,
|
158
|
+
if isinstance(key, CParam) and not isinstance(key, CParamScalar):
|
156
159
|
raise ClassiqValueError("Non-classical parameter for slicing")
|
157
160
|
return QTerminalCallable(self._decl, key)
|
158
161
|
|
@@ -169,24 +172,24 @@ class QTerminalCallable(QCallable):
|
|
169
172
|
else:
|
170
173
|
|
171
174
|
@property
|
172
|
-
def len(self) ->
|
175
|
+
def len(self) -> CParamScalar:
|
173
176
|
if not self.is_list:
|
174
177
|
raise ClassiqValueError("Cannot get length of a non-list operand")
|
175
|
-
return
|
178
|
+
return CParamScalar(f"{self.func_decl.name}.len")
|
176
179
|
|
177
180
|
@property
|
178
181
|
def func_decl(self) -> QuantumFunctionDeclaration:
|
179
182
|
return self._decl
|
180
183
|
|
181
184
|
def create_quantum_function_call(
|
182
|
-
self, *args: Any, **kwargs: Any
|
185
|
+
self, source_ref_: SourceReference, *args: Any, **kwargs: Any
|
183
186
|
) -> QuantumFunctionCall:
|
184
187
|
if self.is_list and self._index is None:
|
185
188
|
raise ClassiqValueError(
|
186
189
|
f"Quantum operand {self.func_decl.name!r} is a list and must be indexed"
|
187
190
|
)
|
188
191
|
return _create_quantum_function_call(
|
189
|
-
self.func_decl, self._index, *args, **kwargs
|
192
|
+
self.func_decl, self._index, source_ref_, *args, **kwargs
|
190
193
|
)
|
191
194
|
|
192
195
|
|
@@ -278,7 +281,8 @@ def _prepare_args(
|
|
278
281
|
|
279
282
|
def _create_quantum_function_call(
|
280
283
|
decl_: QuantumFunctionDeclaration,
|
281
|
-
index_: Optional[Union[
|
284
|
+
index_: Optional[Union[CParamScalar, int]] = None,
|
285
|
+
source_ref_: Optional[SourceReference] = None,
|
282
286
|
*args: Any,
|
283
287
|
**kwargs: Any,
|
284
288
|
) -> QuantumFunctionCall:
|
@@ -306,4 +310,6 @@ def _create_quantum_function_call(
|
|
306
310
|
index=Expression(expr=str(index_)), name=function_ident
|
307
311
|
)
|
308
312
|
|
309
|
-
return QuantumFunctionCall(
|
313
|
+
return QuantumFunctionCall(
|
314
|
+
function=function_ident, positional_args=prepared_args, source_ref=source_ref_
|
315
|
+
)
|
classiq/qmod/quantum_function.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
import ast
|
2
2
|
import functools
|
3
|
+
import warnings
|
4
|
+
from inspect import isclass
|
3
5
|
from typing import Any, Callable, Dict, List, Optional, Tuple, get_origin
|
4
6
|
|
5
7
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
8
|
+
from classiq.interface.generator.functions.classical_type import CStructBase
|
6
9
|
from classiq.interface.generator.model.constraints import Constraints
|
7
10
|
from classiq.interface.generator.model.preferences.preferences import Preferences
|
8
11
|
from classiq.interface.model.model import Model, SerializedModel
|
@@ -15,7 +18,7 @@ from classiq.exceptions import ClassiqError
|
|
15
18
|
from classiq.qmod.classical_function import CFunc
|
16
19
|
from classiq.qmod.declaration_inferrer import infer_func_decl
|
17
20
|
from classiq.qmod.qmod_constant import QConstant
|
18
|
-
from classiq.qmod.qmod_parameter import QParam
|
21
|
+
from classiq.qmod.qmod_parameter import CArray, CParam, QParam
|
19
22
|
from classiq.qmod.qmod_variable import QVar
|
20
23
|
from classiq.qmod.quantum_callable import QCallable, QCallableList
|
21
24
|
from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
|
@@ -46,6 +49,18 @@ def create_model(
|
|
46
49
|
class QFunc(QExpandable):
|
47
50
|
def __init__(self, py_callable: Callable) -> None:
|
48
51
|
_validate_no_gen_params(py_callable.__annotations__)
|
52
|
+
if any(
|
53
|
+
get_origin(annotation) == QParam
|
54
|
+
for annotation in py_callable.__annotations__.values()
|
55
|
+
):
|
56
|
+
warnings.warn(
|
57
|
+
"QParam is deprecated and will be removed in a future release. Use the "
|
58
|
+
"new classical parameter types instead:\n * QParam[int] -> CInt\n * QParam[float] "
|
59
|
+
"-> CReal\n * QParam[bool] -> CBool\n * QParam[list[int]] -> "
|
60
|
+
"CArray[CInt]",
|
61
|
+
category=DeprecationWarning,
|
62
|
+
stacklevel=4,
|
63
|
+
)
|
49
64
|
super().__init__(py_callable)
|
50
65
|
functools.update_wrapper(self, py_callable)
|
51
66
|
|
@@ -144,7 +159,10 @@ ILLEGAL_PARAM_ERROR = "Unsupported type hint '{annotation}' for argument '{name}
|
|
144
159
|
|
145
160
|
|
146
161
|
class IllegalParamsError(ClassiqError):
|
147
|
-
_HINT =
|
162
|
+
_HINT = (
|
163
|
+
"\nNote - QMOD functions can declare classical parameters using the type hints "
|
164
|
+
"'CInt', 'CReal', 'CBool', and 'CArray'."
|
165
|
+
)
|
148
166
|
|
149
167
|
def __init__(self, message: str) -> None:
|
150
168
|
super().__init__(message + self._HINT)
|
@@ -157,6 +175,11 @@ def _validate_no_gen_params(annotations: Dict[str, Any]) -> None:
|
|
157
175
|
if not (
|
158
176
|
name == "return"
|
159
177
|
or get_origin(annotation) is QParam
|
178
|
+
or isclass(annotation)
|
179
|
+
and issubclass(annotation, CParam)
|
180
|
+
or isclass(annotation)
|
181
|
+
and issubclass(annotation, CStructBase)
|
182
|
+
or get_origin(annotation) is CArray
|
160
183
|
or (get_origin(annotation) or annotation) is QCallable
|
161
184
|
or (get_origin(annotation) or annotation) is QCallableList
|
162
185
|
or QVar.from_type_hint(annotation) is not None
|