classiq 0.102.0__py3-none-any.whl → 0.104.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/applications/chemistry/op_utils.py +32 -0
- classiq/evaluators/qmod_annotated_expression.py +1 -1
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +1 -8
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +1 -1
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +18 -29
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +1 -6
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -7
- classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
- classiq/execution/execution_session.py +1 -1
- classiq/execution/functions/__init__.py +3 -0
- classiq/execution/functions/_logging.py +19 -0
- classiq/execution/functions/constants.py +9 -0
- classiq/execution/functions/parse_provider_backend.py +90 -0
- classiq/execution/functions/sample.py +257 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +15 -0
- classiq/interface/backend/provider_config/providers/aqt.py +1 -1
- classiq/interface/backend/provider_config/providers/azure.py +1 -2
- classiq/interface/backend/provider_config/providers/ibm.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +3 -0
- classiq/interface/executor/result.py +9 -5
- classiq/interface/generator/arith/binary_ops.py +38 -2
- classiq/interface/generator/function_param_list.py +4 -2
- classiq/interface/generator/functions/builtins/internal_operators.py +5 -9
- classiq/interface/generator/functions/classical_type.py +45 -0
- classiq/interface/generator/functions/type_name.py +23 -0
- classiq/interface/generator/generated_circuit_data.py +0 -2
- classiq/interface/generator/types/compilation_metadata.py +9 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/helpers/model_normalizer.py +42 -6
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/invert.py +8 -0
- classiq/interface/model/model_visitor.py +4 -2
- classiq/interface/model/quantum_type.py +21 -0
- classiq/interface/model/statement_block.py +0 -4
- classiq/model_expansions/capturing/captured_vars.py +16 -12
- classiq/model_expansions/function_builder.py +9 -1
- classiq/model_expansions/interpreters/base_interpreter.py +9 -8
- classiq/model_expansions/interpreters/generative_interpreter.py +9 -24
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -0
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +132 -28
- classiq/model_expansions/quantum_operations/bind.py +4 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +5 -35
- classiq/model_expansions/quantum_operations/emitter.py +1 -4
- classiq/model_expansions/quantum_operations/expression_evaluator.py +0 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +0 -9
- classiq/qmod/builtins/functions/__init__.py +9 -0
- classiq/qmod/builtins/functions/arithmetic.py +131 -0
- classiq/qmod/builtins/functions/exponentiation.py +32 -2
- classiq/qmod/builtins/operations.py +2 -38
- classiq/qmod/native/pretty_printer.py +1 -12
- classiq/qmod/pretty_print/pretty_printer.py +1 -17
- classiq/qmod/qmod_parameter.py +4 -0
- classiq/qmod/qmod_variable.py +38 -63
- classiq/qmod/quantum_function.py +43 -7
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +7 -4
- classiq/qmod/semantics/validation/model_validation.py +7 -2
- classiq/qmod/symbolic_type.py +4 -2
- {classiq-0.102.0.dist-info → classiq-0.104.0.dist-info}/METADATA +1 -1
- {classiq-0.102.0.dist-info → classiq-0.104.0.dist-info}/RECORD +63 -59
- classiq/interface/generator/amplitude_loading.py +0 -103
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
- {classiq-0.102.0.dist-info → classiq-0.104.0.dist-info}/WHEEL +0 -0
- {classiq-0.102.0.dist-info → classiq-0.104.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
import sys
|
|
3
|
-
import warnings
|
|
4
3
|
from collections.abc import Callable, Mapping
|
|
5
4
|
from functools import wraps
|
|
6
5
|
from itertools import product
|
|
@@ -14,7 +13,7 @@ from typing import (
|
|
|
14
13
|
overload,
|
|
15
14
|
)
|
|
16
15
|
|
|
17
|
-
from classiq.interface.exceptions import
|
|
16
|
+
from classiq.interface.exceptions import ClassiqValueError
|
|
18
17
|
from classiq.interface.generator.expressions.expression import Expression
|
|
19
18
|
from classiq.interface.generator.functions.builtins.internal_operators import (
|
|
20
19
|
REPEAT_OPERATOR_NAME,
|
|
@@ -33,9 +32,6 @@ from classiq.interface.model.control import Control
|
|
|
33
32
|
from classiq.interface.model.invert import BlockKind, Invert
|
|
34
33
|
from classiq.interface.model.phase_operation import PhaseOperation
|
|
35
34
|
from classiq.interface.model.power import Power
|
|
36
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
37
|
-
AmplitudeLoadingOperation,
|
|
38
|
-
)
|
|
39
35
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
40
36
|
ArithmeticOperation,
|
|
41
37
|
ArithmeticOperationKind,
|
|
@@ -336,37 +332,6 @@ def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
336
332
|
)
|
|
337
333
|
|
|
338
334
|
|
|
339
|
-
@suppress_return_value
|
|
340
|
-
@qmod_statement
|
|
341
|
-
def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
342
|
-
"""
|
|
343
|
-
Perform an amplitude-encoding assignment operation on a quantum variable and a
|
|
344
|
-
quantum expression.
|
|
345
|
-
|
|
346
|
-
Equivalent to `<target_var> *= <expression>`.
|
|
347
|
-
|
|
348
|
-
Args:
|
|
349
|
-
expression: A quantum arithmetic expression
|
|
350
|
-
target_var: A scalar quantum variable
|
|
351
|
-
"""
|
|
352
|
-
warnings.warn(
|
|
353
|
-
"The 'assign_amplitude' function is deprecated and will no longer be "
|
|
354
|
-
"supported starting on 2025-12-03 at the earliest. Use 'assign_amplitude_table' "
|
|
355
|
-
"instead",
|
|
356
|
-
ClassiqDeprecationWarning,
|
|
357
|
-
stacklevel=3,
|
|
358
|
-
)
|
|
359
|
-
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
360
|
-
source_ref = get_source_ref(sys._getframe(2))
|
|
361
|
-
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
362
|
-
AmplitudeLoadingOperation(
|
|
363
|
-
expression=Expression(expr=str(expression)),
|
|
364
|
-
result_var=target_var.get_handle_binding(),
|
|
365
|
-
source_ref=source_ref,
|
|
366
|
-
)
|
|
367
|
-
)
|
|
368
|
-
|
|
369
|
-
|
|
370
335
|
@suppress_return_value
|
|
371
336
|
@qmod_statement
|
|
372
337
|
def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
@@ -553,7 +518,7 @@ def power(
|
|
|
553
518
|
|
|
554
519
|
@suppress_return_value
|
|
555
520
|
@qmod_statement
|
|
556
|
-
def invert(stmt_block: QCallable | Callable[[], Statements]) ->
|
|
521
|
+
def invert(stmt_block: QCallable | Callable[[], Statements]) -> Any:
|
|
557
522
|
"""
|
|
558
523
|
Apply the inverse of a quantum gate.
|
|
559
524
|
|
|
@@ -868,7 +833,6 @@ def lookup_table(func: RealFunction, targets: QNum | list[QNum]) -> list[float]:
|
|
|
868
833
|
__all__ = [
|
|
869
834
|
"allocate",
|
|
870
835
|
"assign",
|
|
871
|
-
"assign_amplitude",
|
|
872
836
|
"assign_amplitude_poly_sin",
|
|
873
837
|
"bind",
|
|
874
838
|
"block",
|
|
@@ -51,9 +51,6 @@ from classiq.interface.model.port_declaration import (
|
|
|
51
51
|
AnonPortDeclaration,
|
|
52
52
|
)
|
|
53
53
|
from classiq.interface.model.power import Power
|
|
54
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
55
|
-
AmplitudeLoadingOperation,
|
|
56
|
-
)
|
|
57
54
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
58
55
|
ArithmeticOperation,
|
|
59
56
|
ArithmeticOperationKind,
|
|
@@ -367,12 +364,9 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
367
364
|
return power_code
|
|
368
365
|
|
|
369
366
|
def visit_Invert(self, invert: Invert) -> str:
|
|
367
|
+
invert.validate_node()
|
|
370
368
|
match invert.block_kind:
|
|
371
369
|
case BlockKind.SingleCall:
|
|
372
|
-
if len(invert.body) != 1 or not isinstance(
|
|
373
|
-
invert.body[0], QuantumFunctionCall
|
|
374
|
-
):
|
|
375
|
-
raise ClassiqInternalError("Malformed single-call invert")
|
|
376
370
|
invert_code = f"{self._indent}invert "
|
|
377
371
|
invert_code += self.visit(invert.body[0]).lstrip()
|
|
378
372
|
case BlockKind.Compound:
|
|
@@ -446,11 +440,6 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
446
440
|
op = "+="
|
|
447
441
|
return f"{self._indent}{self.visit(arith_op.result_var)} {op} {self.visit(arith_op.expression)};\n"
|
|
448
442
|
|
|
449
|
-
def visit_AmplitudeLoadingOperation(
|
|
450
|
-
self, amplitude_loading_op: AmplitudeLoadingOperation
|
|
451
|
-
) -> str:
|
|
452
|
-
return f"{self._indent}{self.visit(amplitude_loading_op.result_var)} *= {self.visit(amplitude_loading_op.expression)};\n"
|
|
453
|
-
|
|
454
443
|
def _print_bind_handles(self, handles: list[HandleBinding]) -> str:
|
|
455
444
|
if len(handles) == 1:
|
|
456
445
|
return self.visit(handles[0])
|
|
@@ -52,9 +52,6 @@ from classiq.interface.model.native_function_definition import NativeFunctionDef
|
|
|
52
52
|
from classiq.interface.model.phase_operation import PhaseOperation
|
|
53
53
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
|
54
54
|
from classiq.interface.model.power import Power
|
|
55
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
56
|
-
AmplitudeLoadingOperation,
|
|
57
|
-
)
|
|
58
55
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
59
56
|
ArithmeticOperation,
|
|
60
57
|
ArithmeticOperationKind,
|
|
@@ -508,13 +505,10 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
508
505
|
return f"{self._indent}power({self.visit(power.power)}, {self._visit_body(power.body)})\n"
|
|
509
506
|
|
|
510
507
|
def visit_Invert(self, invert: Invert) -> str:
|
|
508
|
+
invert.validate_node()
|
|
511
509
|
self._imports["invert"] = 1
|
|
512
510
|
match invert.block_kind:
|
|
513
511
|
case BlockKind.SingleCall:
|
|
514
|
-
if len(invert.body) != 1 or not isinstance(
|
|
515
|
-
invert.body[0], QuantumFunctionCall
|
|
516
|
-
):
|
|
517
|
-
raise ClassiqInternalError("Malformed single-call invert")
|
|
518
512
|
call_str = self.visit(invert.body[0])
|
|
519
513
|
call_str = call_str.replace("(", ")(", 1)
|
|
520
514
|
return f"{self._indent}invert({call_str}\n"
|
|
@@ -540,8 +534,6 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
540
534
|
for i, statement in enumerate(body):
|
|
541
535
|
if isinstance(statement, VariableDeclarationStatement):
|
|
542
536
|
code += self.visit_VariableDeclarationStatement(statement, walrus=True)
|
|
543
|
-
elif isinstance(statement, AmplitudeLoadingOperation):
|
|
544
|
-
code += self.visit_AmplitudeLoadingOperation(statement, in_lambda=True)
|
|
545
537
|
elif isinstance(statement, ArithmeticOperation):
|
|
546
538
|
code += self.visit_ArithmeticOperation(statement, in_lambda=True)
|
|
547
539
|
else:
|
|
@@ -599,14 +591,6 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
599
591
|
return f"{func}({self.visit(arith_op.expression)}, {self._indent}{self.visit(arith_op.result_var)})\n"
|
|
600
592
|
return f"{self._indent}{self.visit(arith_op.result_var)} {op} {self.visit(arith_op.expression)}\n"
|
|
601
593
|
|
|
602
|
-
def visit_AmplitudeLoadingOperation(
|
|
603
|
-
self, amplitude_loading_op: AmplitudeLoadingOperation, in_lambda: bool = False
|
|
604
|
-
) -> str:
|
|
605
|
-
if in_lambda:
|
|
606
|
-
self._imports["assign_amplitude"] = 1
|
|
607
|
-
return f"assign_amplitude({self.visit(amplitude_loading_op.expression)}, {self._indent}{self.visit(amplitude_loading_op.result_var)})\n"
|
|
608
|
-
return f"{self._indent}{self.visit(amplitude_loading_op.result_var)} *= {self.visit(amplitude_loading_op.expression)}\n"
|
|
609
|
-
|
|
610
594
|
def _print_bind_handles(self, handles: list[HandleBinding]) -> str:
|
|
611
595
|
if len(handles) == 1:
|
|
612
596
|
return self.visit(handles[0])
|
classiq/qmod/qmod_parameter.py
CHANGED
|
@@ -63,6 +63,10 @@ class CParamList(CParam):
|
|
|
63
63
|
else:
|
|
64
64
|
param_type = self._list_type.element_type
|
|
65
65
|
else:
|
|
66
|
+
if key.start is None:
|
|
67
|
+
key = slice(0, key.stop, None)
|
|
68
|
+
if key.stop is None:
|
|
69
|
+
key = slice(key.start, self.len, None)
|
|
66
70
|
if not isinstance(self._list_type, ClassicalTuple):
|
|
67
71
|
param_type = self._list_type
|
|
68
72
|
else:
|
classiq/qmod/qmod_variable.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
import sys
|
|
3
|
-
import warnings
|
|
4
3
|
from collections.abc import Iterator, Mapping
|
|
5
4
|
from contextlib import contextmanager
|
|
6
5
|
from typing import ( # type: ignore[attr-defined]
|
|
@@ -23,7 +22,6 @@ from typing import ( # type: ignore[attr-defined]
|
|
|
23
22
|
from typing_extensions import ParamSpec, Self, _AnnotatedAlias
|
|
24
23
|
|
|
25
24
|
from classiq.interface.exceptions import (
|
|
26
|
-
ClassiqDeprecationWarning,
|
|
27
25
|
ClassiqInternalError,
|
|
28
26
|
ClassiqNotImplementedError,
|
|
29
27
|
ClassiqValueError,
|
|
@@ -45,9 +43,6 @@ from classiq.interface.model.handle_binding import (
|
|
|
45
43
|
SlicedHandleBinding,
|
|
46
44
|
SubscriptHandleBinding,
|
|
47
45
|
)
|
|
48
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
49
|
-
AmplitudeLoadingOperation,
|
|
50
|
-
)
|
|
51
46
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
52
47
|
ArithmeticOperation,
|
|
53
48
|
ArithmeticOperationKind,
|
|
@@ -161,37 +156,6 @@ class QVar(Symbolic):
|
|
|
161
156
|
def type_name(self) -> str:
|
|
162
157
|
return self.get_qmod_type().type_name
|
|
163
158
|
|
|
164
|
-
|
|
165
|
-
class QmodExpressionCreator(Protocol):
|
|
166
|
-
"""
|
|
167
|
-
A callable that creates a Qmod expression from the provided QVars.
|
|
168
|
-
"""
|
|
169
|
-
|
|
170
|
-
def __call__(self, **kwargs: QVar) -> SymbolicExpr: ...
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
_Q = TypeVar("_Q", bound=QVar)
|
|
174
|
-
Output = Annotated[_Q, PortDeclarationDirection.Output]
|
|
175
|
-
Input = Annotated[_Q, PortDeclarationDirection.Input]
|
|
176
|
-
Const = Annotated[
|
|
177
|
-
_Q, TypeModifier.Const
|
|
178
|
-
] # A constant variable, up to a phase dependent on the computational basis state
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
class QScalar(QVar, SymbolicExpr):
|
|
182
|
-
CONSTRUCTOR_DEPTH: int = 2
|
|
183
|
-
|
|
184
|
-
def __init__(
|
|
185
|
-
self,
|
|
186
|
-
origin: None | str | HandleBinding = None,
|
|
187
|
-
*,
|
|
188
|
-
_expr_str: str | None = None,
|
|
189
|
-
depth: int = 2,
|
|
190
|
-
) -> None:
|
|
191
|
-
origin = _infer_variable_name(origin, self.CONSTRUCTOR_DEPTH)
|
|
192
|
-
QVar.__init__(self, origin, expr_str=_expr_str, depth=depth)
|
|
193
|
-
SymbolicExpr.__init__(self, str(origin), True)
|
|
194
|
-
|
|
195
159
|
def _insert_arith_operation(
|
|
196
160
|
self,
|
|
197
161
|
expr: SymbolicTypes,
|
|
@@ -210,19 +174,6 @@ class QScalar(QVar, SymbolicExpr):
|
|
|
210
174
|
)
|
|
211
175
|
)
|
|
212
176
|
|
|
213
|
-
def _insert_amplitude_loading(
|
|
214
|
-
self, expr: SymbolicTypes, source_ref: SourceReference
|
|
215
|
-
) -> None:
|
|
216
|
-
if TYPE_CHECKING:
|
|
217
|
-
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
218
|
-
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
219
|
-
AmplitudeLoadingOperation(
|
|
220
|
-
expression=Expression(expr=str(expr)),
|
|
221
|
-
result_var=self.get_handle_binding(),
|
|
222
|
-
source_ref=source_ref,
|
|
223
|
-
)
|
|
224
|
-
)
|
|
225
|
-
|
|
226
177
|
def __ior__(self, other: Any) -> Self:
|
|
227
178
|
if not isinstance(other, SYMBOLIC_TYPES):
|
|
228
179
|
raise ClassiqValueError(
|
|
@@ -245,6 +196,37 @@ class QScalar(QVar, SymbolicExpr):
|
|
|
245
196
|
)
|
|
246
197
|
return self
|
|
247
198
|
|
|
199
|
+
|
|
200
|
+
class QmodExpressionCreator(Protocol):
|
|
201
|
+
"""
|
|
202
|
+
A callable that creates a Qmod expression from the provided QVars.
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
def __call__(self, **kwargs: QVar) -> SymbolicExpr: ...
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
_Q = TypeVar("_Q", bound=QVar)
|
|
209
|
+
Output = Annotated[_Q, PortDeclarationDirection.Output]
|
|
210
|
+
Input = Annotated[_Q, PortDeclarationDirection.Input]
|
|
211
|
+
Const = Annotated[
|
|
212
|
+
_Q, TypeModifier.Const
|
|
213
|
+
] # A constant variable, up to a phase dependent on the computational basis state
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class QScalar(QVar, SymbolicExpr):
|
|
217
|
+
CONSTRUCTOR_DEPTH: int = 2
|
|
218
|
+
|
|
219
|
+
def __init__(
|
|
220
|
+
self,
|
|
221
|
+
origin: None | str | HandleBinding = None,
|
|
222
|
+
*,
|
|
223
|
+
_expr_str: str | None = None,
|
|
224
|
+
depth: int = 2,
|
|
225
|
+
) -> None:
|
|
226
|
+
origin = _infer_variable_name(origin, self.CONSTRUCTOR_DEPTH)
|
|
227
|
+
QVar.__init__(self, origin, expr_str=_expr_str, depth=depth)
|
|
228
|
+
SymbolicExpr.__init__(self, str(origin), True)
|
|
229
|
+
|
|
248
230
|
def __iadd__(self, other: Any) -> Self:
|
|
249
231
|
if not isinstance(other, SYMBOLIC_TYPES):
|
|
250
232
|
raise ClassiqValueError(
|
|
@@ -256,21 +238,10 @@ class QScalar(QVar, SymbolicExpr):
|
|
|
256
238
|
)
|
|
257
239
|
return self
|
|
258
240
|
|
|
259
|
-
def __imul__(self, other: Any) ->
|
|
260
|
-
|
|
261
|
-
"
|
|
262
|
-
"starting on 2025-12-03 at the earliest. Use the 'assign_amplitude_table' "
|
|
263
|
-
"function instead",
|
|
264
|
-
ClassiqDeprecationWarning,
|
|
265
|
-
stacklevel=2,
|
|
241
|
+
def __imul__(self, other: Any) -> NoReturn:
|
|
242
|
+
raise ClassiqNotImplementedError(
|
|
243
|
+
f"{self.get_qmod_type().raw_qmod_type_name} does not support '*='"
|
|
266
244
|
)
|
|
267
|
-
if not isinstance(other, SYMBOLIC_TYPES):
|
|
268
|
-
raise ClassiqValueError(
|
|
269
|
-
f"Invalid argument {str(other)!r} for out of ampltiude encoding operation"
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
self._insert_amplitude_loading(other, get_source_ref(sys._getframe(1)))
|
|
273
|
-
return self
|
|
274
245
|
|
|
275
246
|
def __iand__(self, other: Any) -> NoReturn:
|
|
276
247
|
raise ClassiqNotImplementedError(
|
|
@@ -558,6 +529,10 @@ class QArray(ArrayBase[_P], QVar, NonSymbolicExpr):
|
|
|
558
529
|
def _get_slice(self, slice_: slice) -> Any:
|
|
559
530
|
if slice_.step is not None:
|
|
560
531
|
raise ClassiqValueError(ILLEGAL_SLICING_STEP_MSG)
|
|
532
|
+
if slice_.start is None:
|
|
533
|
+
slice_ = slice(0, slice_.stop, None)
|
|
534
|
+
if slice_.stop is None:
|
|
535
|
+
slice_ = slice(slice_.start, self.len, None)
|
|
561
536
|
if not isinstance(slice_.start, (int, SymbolicExpr)) or not isinstance(
|
|
562
537
|
slice_.stop, (int, SymbolicExpr)
|
|
563
538
|
):
|
classiq/qmod/quantum_function.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ast
|
|
2
2
|
import functools
|
|
3
|
+
import inspect
|
|
3
4
|
import warnings
|
|
4
5
|
from abc import abstractmethod
|
|
5
6
|
from collections.abc import Callable
|
|
@@ -8,7 +9,11 @@ from enum import EnumMeta
|
|
|
8
9
|
from inspect import isclass
|
|
9
10
|
from typing import Any, get_origin
|
|
10
11
|
|
|
11
|
-
from classiq.interface.exceptions import
|
|
12
|
+
from classiq.interface.exceptions import (
|
|
13
|
+
ClassiqDeprecationWarning,
|
|
14
|
+
ClassiqError,
|
|
15
|
+
ClassiqExpansionError,
|
|
16
|
+
)
|
|
12
17
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
|
13
18
|
from classiq.interface.generator.functions.port_declaration import (
|
|
14
19
|
PortDeclarationDirection,
|
|
@@ -276,10 +281,16 @@ class ExternalQFunc(QTerminalCallable):
|
|
|
276
281
|
ClassiqDeprecationWarning,
|
|
277
282
|
stacklevel=2,
|
|
278
283
|
)
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
284
|
+
if self._py_callable.__name__ == "suzuki_trotter" and (
|
|
285
|
+
(
|
|
286
|
+
"pauli_operator" not in kwargs
|
|
287
|
+
and len(args) > 0
|
|
288
|
+
and isinstance(args[0], (list, CParamList))
|
|
289
|
+
)
|
|
290
|
+
or (
|
|
291
|
+
"pauli_operator" in kwargs
|
|
292
|
+
and isinstance(kwargs["pauli_operator"], (list, CParamList))
|
|
293
|
+
)
|
|
283
294
|
):
|
|
284
295
|
warnings.warn(
|
|
285
296
|
(
|
|
@@ -320,6 +331,19 @@ class ExternalQFunc(QTerminalCallable):
|
|
|
320
331
|
ClassiqDeprecationWarning,
|
|
321
332
|
stacklevel=2,
|
|
322
333
|
)
|
|
334
|
+
if (
|
|
335
|
+
self._py_callable.__name__ == "unscheduled_suzuki_trotter"
|
|
336
|
+
): # FIXME: remove (CLS-5391)
|
|
337
|
+
warnings.warn(
|
|
338
|
+
(
|
|
339
|
+
"Function 'unscheduled_suzuki_trotter' was renamed to "
|
|
340
|
+
"'sequential_suzuki_trotter'. 'unscheduled_suzuki_trotter' is "
|
|
341
|
+
"deprecated and will no longer be supported starting on 2026-02-02 "
|
|
342
|
+
"at the earliest."
|
|
343
|
+
),
|
|
344
|
+
ClassiqDeprecationWarning,
|
|
345
|
+
stacklevel=2,
|
|
346
|
+
)
|
|
323
347
|
super().__call__(*args, **kwargs)
|
|
324
348
|
|
|
325
349
|
|
|
@@ -348,14 +372,26 @@ class GenerativeQFunc(BaseQFunc):
|
|
|
348
372
|
return self._inferred_func_decl
|
|
349
373
|
|
|
350
374
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
|
375
|
+
from classiq.qmod.builtins.functions import BUILTIN_FUNCTION_DECLARATIONS
|
|
376
|
+
|
|
351
377
|
if get_global_declarative_switch():
|
|
352
378
|
return QFunc(
|
|
353
379
|
self._py_callable,
|
|
354
380
|
self.compilation_metadata,
|
|
355
381
|
permutation=self.permutation,
|
|
356
382
|
)(*args, **kwargs)
|
|
357
|
-
|
|
358
|
-
|
|
383
|
+
frame = inspect.currentframe()
|
|
384
|
+
caller_frame = frame.f_back if frame is not None else None
|
|
385
|
+
module = inspect.getmodule(caller_frame)
|
|
386
|
+
func_name = self.func_decl.name
|
|
387
|
+
if func_name in BUILTIN_FUNCTION_DECLARATIONS and (
|
|
388
|
+
module is None or not module.__name__.startswith("model.function_library")
|
|
389
|
+
):
|
|
390
|
+
raise ClassiqExpansionError(
|
|
391
|
+
f"Cannot redefine built-in function {func_name!r}"
|
|
392
|
+
)
|
|
393
|
+
if func_name not in self._qmodule.generative_functions:
|
|
394
|
+
self._qmodule.generative_functions[func_name] = self
|
|
359
395
|
if self._func_decl is None:
|
|
360
396
|
self._inferred_func_decl = infer_func_decl(
|
|
361
397
|
self._py_callable, self._qmodule, permutation=self.permutation
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
from classiq.interface.exceptions import ClassiqExpansionError
|
|
2
2
|
from classiq.interface.model.model import Model
|
|
3
|
+
from classiq.interface.model.quantum_function_declaration import (
|
|
4
|
+
NamedParamsQuantumFunctionDeclaration,
|
|
5
|
+
)
|
|
3
6
|
|
|
4
|
-
from classiq.qmod.builtins.functions import CORE_LIB_DECLS
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
def check_function_name_collisions(
|
|
9
|
+
model: Model, builtin_functions: list[NamedParamsQuantumFunctionDeclaration]
|
|
10
|
+
) -> None:
|
|
8
11
|
redefined_functions = [
|
|
9
12
|
function.name
|
|
10
|
-
for function in
|
|
13
|
+
for function in builtin_functions
|
|
11
14
|
if function.name in model.function_dict
|
|
12
15
|
]
|
|
13
16
|
if len(redefined_functions) == 1:
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
from classiq.interface.model.model import Model
|
|
2
|
+
from classiq.interface.model.quantum_function_declaration import (
|
|
3
|
+
NamedParamsQuantumFunctionDeclaration,
|
|
4
|
+
)
|
|
2
5
|
|
|
3
6
|
from classiq.qmod.semantics.validation.constants_validation import (
|
|
4
7
|
check_duplicate_constants,
|
|
@@ -14,7 +17,9 @@ from classiq.qmod.semantics.validation.types_validation import (
|
|
|
14
17
|
)
|
|
15
18
|
|
|
16
19
|
|
|
17
|
-
def validate_model(
|
|
20
|
+
def validate_model(
|
|
21
|
+
model: Model, builtin_functions: list[NamedParamsQuantumFunctionDeclaration]
|
|
22
|
+
) -> None:
|
|
18
23
|
check_duplicate_types([*model.enums, *model.types, *model.qstructs])
|
|
19
24
|
check_duplicate_constants(model.constants)
|
|
20
25
|
for qstruct in model.qstructs:
|
|
@@ -22,4 +27,4 @@ def validate_model(model: Model) -> None:
|
|
|
22
27
|
for cstruct in model.types:
|
|
23
28
|
validate_cstruct(cstruct)
|
|
24
29
|
validate_main_function(model.main_func)
|
|
25
|
-
check_function_name_collisions(model)
|
|
30
|
+
check_function_name_collisions(model, builtin_functions)
|
classiq/qmod/symbolic_type.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import Union, get_args, get_origin
|
|
2
2
|
|
|
3
|
-
from classiq.qmod.symbolic_expr import
|
|
3
|
+
from classiq.qmod.symbolic_expr import Symbolic
|
|
4
4
|
|
|
5
|
-
SymbolicTypes = Union[
|
|
5
|
+
SymbolicTypes = Union[
|
|
6
|
+
Symbolic, int, float, bool, tuple["SymbolicTypes", ...], list["SymbolicTypes"]
|
|
7
|
+
]
|
|
6
8
|
SYMBOLIC_TYPES = tuple(get_origin(t) or t for t in get_args(SymbolicTypes))
|