classiq 0.43.2__py3-none-any.whl → 0.44.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 +7 -1
- classiq/_internals/client.py +4 -7
- classiq/_internals/host_checker.py +34 -12
- classiq/_internals/jobs.py +2 -2
- classiq/applications/chemistry/chemistry_model_constructor.py +12 -6
- classiq/applications/combinatorial_helpers/allowed_constraints.py +4 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
- classiq/applications/finance/finance_model_constructor.py +3 -2
- classiq/applications/grover/grover_model_constructor.py +7 -5
- classiq/applications/hamiltonian/__init__.py +0 -0
- classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
- classiq/applications/qnn/qlayer.py +1 -1
- classiq/exceptions.py +4 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/ast_node.py +1 -18
- classiq/interface/backend/backend_preferences.py +15 -16
- classiq/interface/backend/ionq/ionq_quantum_program.py +1 -1
- classiq/interface/backend/pydantic_backend.py +0 -5
- classiq/interface/backend/quantum_backend_providers.py +3 -2
- classiq/interface/chemistry/operator.py +5 -1
- classiq/interface/debug_info/__init__.py +0 -0
- classiq/interface/debug_info/debug_info.py +32 -0
- classiq/interface/executor/execution_preferences.py +1 -45
- classiq/interface/executor/result.py +25 -12
- classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
- classiq/interface/generator/application_apis/chemistry_declarations.py +78 -60
- classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +19 -10
- classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
- classiq/interface/generator/application_apis/finance_declarations.py +36 -22
- classiq/interface/generator/application_apis/qsvm_declarations.py +21 -15
- classiq/interface/generator/arith/arithmetic_expression_abc.py +21 -1
- classiq/interface/generator/arith/binary_ops.py +5 -4
- classiq/interface/generator/arith/extremum_operations.py +43 -19
- classiq/interface/generator/constant.py +1 -1
- classiq/interface/generator/expressions/atomic_expression_functions.py +1 -0
- classiq/interface/generator/expressions/expression_constants.py +3 -1
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +52 -66
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +35 -0
- classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
- classiq/interface/generator/functions/builtins/core_library/__init__.py +4 -2
- classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +41 -41
- classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +52 -42
- classiq/interface/generator/functions/builtins/open_lib_functions.py +1095 -3347
- classiq/interface/generator/functions/builtins/quantum_operators.py +9 -22
- classiq/interface/generator/functions/classical_function_declaration.py +14 -6
- classiq/interface/generator/functions/classical_type.py +7 -76
- classiq/interface/generator/functions/concrete_types.py +55 -0
- classiq/interface/generator/functions/function_declaration.py +10 -10
- classiq/interface/generator/functions/type_name.py +104 -0
- classiq/interface/generator/generated_circuit_data.py +3 -3
- classiq/interface/generator/model/model.py +11 -0
- classiq/interface/generator/model/preferences/preferences.py +5 -0
- classiq/interface/generator/quantum_function_call.py +3 -0
- classiq/interface/generator/quantum_program.py +2 -2
- classiq/interface/generator/register_role.py +7 -1
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +1 -3
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +1 -2
- classiq/interface/generator/types/qstruct_declaration.py +17 -0
- classiq/interface/generator/types/struct_declaration.py +1 -1
- classiq/interface/helpers/validation_helpers.py +1 -17
- classiq/interface/ide/visual_model.py +9 -2
- classiq/interface/interface_version.py +1 -0
- classiq/interface/model/bind_operation.py +25 -5
- classiq/interface/model/classical_parameter_declaration.py +8 -5
- classiq/interface/model/control.py +5 -5
- classiq/interface/model/handle_binding.py +185 -12
- classiq/interface/model/inplace_binary_operation.py +16 -4
- classiq/interface/model/model.py +28 -5
- classiq/interface/model/native_function_definition.py +8 -4
- classiq/interface/model/parameter.py +14 -0
- classiq/interface/model/port_declaration.py +20 -2
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +21 -6
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +30 -6
- classiq/interface/model/quantum_expressions/quantum_expression.py +4 -9
- classiq/interface/model/quantum_function_call.py +135 -192
- classiq/interface/model/quantum_function_declaration.py +147 -165
- classiq/interface/model/quantum_lambda_function.py +24 -6
- classiq/interface/model/quantum_statement.py +34 -8
- classiq/interface/model/quantum_type.py +61 -10
- classiq/interface/model/quantum_variable_declaration.py +1 -1
- classiq/interface/model/statement_block.py +2 -0
- classiq/interface/model/validation_handle.py +7 -0
- classiq/interface/server/global_versions.py +4 -4
- classiq/interface/server/routes.py +2 -0
- classiq/interface/source_reference.py +59 -0
- classiq/qmod/__init__.py +2 -3
- classiq/qmod/builtins/functions.py +39 -11
- classiq/qmod/builtins/operations.py +171 -40
- classiq/qmod/declaration_inferrer.py +99 -56
- classiq/qmod/expression_query.py +1 -1
- classiq/qmod/model_state_container.py +2 -0
- classiq/qmod/native/pretty_printer.py +71 -53
- classiq/qmod/pretty_print/pretty_printer.py +98 -52
- classiq/qmod/qfunc.py +11 -5
- classiq/qmod/qmod_parameter.py +1 -2
- classiq/qmod/qmod_variable.py +364 -172
- classiq/qmod/quantum_callable.py +3 -3
- classiq/qmod/quantum_expandable.py +119 -65
- classiq/qmod/quantum_function.py +15 -3
- classiq/qmod/semantics/annotation.py +12 -13
- classiq/qmod/semantics/error_manager.py +36 -10
- classiq/qmod/semantics/static_semantics_visitor.py +163 -75
- classiq/qmod/semantics/validation/func_call_validation.py +42 -96
- classiq/qmod/semantics/validation/handle_validation.py +85 -0
- classiq/qmod/semantics/validation/types_validation.py +108 -1
- classiq/qmod/type_attribute_remover.py +32 -0
- classiq/qmod/utilities.py +26 -5
- {classiq-0.43.2.dist-info → classiq-0.44.0.dist-info}/METADATA +3 -3
- {classiq-0.43.2.dist-info → classiq-0.44.0.dist-info}/RECORD +111 -99
- classiq/qmod/qmod_struct.py +0 -13
- /classiq/{interface/ide/show.py → show.py} +0 -0
- {classiq-0.43.2.dist-info → classiq-0.44.0.dist-info}/WHEEL +0 -0
@@ -1,13 +1,13 @@
|
|
1
|
-
from datetime import datetime
|
2
|
-
from typing import Any, Dict
|
1
|
+
from datetime import date, datetime
|
2
|
+
from typing import Any, Dict, Union
|
3
3
|
|
4
4
|
import pydantic
|
5
5
|
from pydantic import BaseModel
|
6
6
|
|
7
7
|
|
8
8
|
class DeprecationInfo(BaseModel):
|
9
|
-
deprecation_date: datetime = pydantic.Field()
|
10
|
-
removal_date: datetime = pydantic.Field()
|
9
|
+
deprecation_date: Union[date, datetime] = pydantic.Field()
|
10
|
+
removal_date: Union[date, datetime] = pydantic.Field()
|
11
11
|
|
12
12
|
|
13
13
|
class GlobalVersions(BaseModel):
|
@@ -72,3 +72,5 @@ CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX = "/execution_input"
|
|
72
72
|
CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_FULL = (
|
73
73
|
CONVERSION_PREFIX + CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX
|
74
74
|
)
|
75
|
+
|
76
|
+
STATIC_SEMANTICS_VALIDATION_PATH = "/validate_static_semantics"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import os
|
2
|
+
import re
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Optional
|
5
|
+
|
6
|
+
import pydantic
|
7
|
+
|
8
|
+
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
9
|
+
HashablePydanticBaseModel,
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
def _identify_ipynb_cell(file_name: str) -> bool:
|
14
|
+
file_path = Path(file_name)
|
15
|
+
base_file = file_path.name
|
16
|
+
if re.fullmatch(r"\d*\.py", base_file) is None:
|
17
|
+
return False
|
18
|
+
parent_folder = file_path.parent
|
19
|
+
return re.fullmatch(r"ipykernel_\d*", parent_folder.name) is not None
|
20
|
+
|
21
|
+
|
22
|
+
def _prepare_file_string(file_name: str) -> str:
|
23
|
+
if _identify_ipynb_cell(file_name):
|
24
|
+
return "ipynb cell "
|
25
|
+
return f"file {os.path.basename(file_name)} "
|
26
|
+
|
27
|
+
|
28
|
+
class SourceReference(HashablePydanticBaseModel):
|
29
|
+
start_line: int
|
30
|
+
start_column: int
|
31
|
+
end_line: int
|
32
|
+
end_column: int
|
33
|
+
file_name: Optional[str] = pydantic.Field(default=None)
|
34
|
+
|
35
|
+
def __str__(self) -> str:
|
36
|
+
file_string = _prepare_file_string(self.file_name) if self.file_name else ""
|
37
|
+
start_character_string = (
|
38
|
+
f" character {self.start_column + 1}" if self.start_column > 0 else ""
|
39
|
+
)
|
40
|
+
return f"{file_string}line {self.start_line + 1}{start_character_string}"
|
41
|
+
|
42
|
+
|
43
|
+
class SourceReferencedError(pydantic.BaseModel):
|
44
|
+
error: str
|
45
|
+
source_ref: Optional[SourceReference] = None
|
46
|
+
function: Optional[str] = None
|
47
|
+
|
48
|
+
def __str__(self) -> str:
|
49
|
+
source_referenced_error = (
|
50
|
+
f"{self.error}\n\t\tat {self.source_ref}"
|
51
|
+
if self.source_ref is not None
|
52
|
+
else self.error
|
53
|
+
)
|
54
|
+
function_scoped_error = (
|
55
|
+
f"{source_referenced_error} in function {self.function}"
|
56
|
+
if self.function is not None
|
57
|
+
else source_referenced_error
|
58
|
+
)
|
59
|
+
return function_scoped_error
|
classiq/qmod/__init__.py
CHANGED
@@ -6,8 +6,7 @@ from .expression_query import get_expression_numeric_attributes
|
|
6
6
|
from .qfunc import qfunc
|
7
7
|
from .qmod_constant import QConstant
|
8
8
|
from .qmod_parameter import Array, CArray, CBool, CInt, CReal
|
9
|
-
from .
|
10
|
-
from .qmod_variable import Input, Output, QArray, QBit, QNum
|
9
|
+
from .qmod_variable import Input, Output, QArray, QBit, QNum, QStruct
|
11
10
|
from .quantum_callable import QCallable, QCallableList
|
12
11
|
from .quantum_function import create_model
|
13
12
|
from .write_qmod import write_qmod
|
@@ -26,11 +25,11 @@ __all__ = [
|
|
26
25
|
"QCallable",
|
27
26
|
"QCallableList",
|
28
27
|
"QConstant",
|
28
|
+
"QStruct",
|
29
29
|
"cfunc",
|
30
30
|
"create_model",
|
31
31
|
"get_expression_numeric_attributes",
|
32
32
|
"qfunc",
|
33
|
-
"struct",
|
34
33
|
"symbolic",
|
35
34
|
"write_qmod",
|
36
35
|
] + _builtins_all
|
@@ -473,13 +473,6 @@ def exponentiation_with_depth_constraint(
|
|
473
473
|
pass
|
474
474
|
|
475
475
|
|
476
|
-
@qfunc(external=True)
|
477
|
-
def qft(
|
478
|
-
target: QArray[QBit],
|
479
|
-
) -> None:
|
480
|
-
pass
|
481
|
-
|
482
|
-
|
483
476
|
@qfunc(external=True)
|
484
477
|
def qpe_flexible(
|
485
478
|
unitary_with_power: QCallable[CInt],
|
@@ -624,7 +617,6 @@ def cc_modular_add(
|
|
624
617
|
phi_b: QArray[QBit],
|
625
618
|
c1: QBit,
|
626
619
|
c2: QBit,
|
627
|
-
aux: QBit,
|
628
620
|
) -> None:
|
629
621
|
pass
|
630
622
|
|
@@ -636,7 +628,6 @@ def c_modular_multiply(
|
|
636
628
|
b: QArray[QBit],
|
637
629
|
x: QArray[QBit],
|
638
630
|
ctrl: QBit,
|
639
|
-
aux: QBit,
|
640
631
|
) -> None:
|
641
632
|
pass
|
642
633
|
|
@@ -655,7 +646,6 @@ def inplace_c_modular_multiply(
|
|
655
646
|
a: CInt,
|
656
647
|
x: QArray[QBit],
|
657
648
|
ctrl: QBit,
|
658
|
-
aux: QBit,
|
659
649
|
) -> None:
|
660
650
|
pass
|
661
651
|
|
@@ -793,6 +783,34 @@ def swap_test(
|
|
793
783
|
pass
|
794
784
|
|
795
785
|
|
786
|
+
@qfunc(external=True)
|
787
|
+
def _prepare_uniform_trimmed_state_step(
|
788
|
+
size_lsb: CInt,
|
789
|
+
ctrl_val: CInt,
|
790
|
+
lsbs_val: CInt,
|
791
|
+
ctrl_var: QNum,
|
792
|
+
rotation_var: QBit,
|
793
|
+
) -> None:
|
794
|
+
pass
|
795
|
+
|
796
|
+
|
797
|
+
@qfunc(external=True)
|
798
|
+
def prepare_uniform_trimmed_state(
|
799
|
+
m: CInt,
|
800
|
+
q: QArray[QBit],
|
801
|
+
) -> None:
|
802
|
+
pass
|
803
|
+
|
804
|
+
|
805
|
+
@qfunc(external=True)
|
806
|
+
def prepare_uniform_interval_state(
|
807
|
+
start: CInt,
|
808
|
+
end: CInt,
|
809
|
+
q: QArray[QBit],
|
810
|
+
) -> None:
|
811
|
+
pass
|
812
|
+
|
813
|
+
|
796
814
|
@qfunc(external=True)
|
797
815
|
def prepare_ghz_state(
|
798
816
|
size: CInt,
|
@@ -894,6 +912,13 @@ def modular_increment(
|
|
894
912
|
pass
|
895
913
|
|
896
914
|
|
915
|
+
@qfunc(external=True)
|
916
|
+
def qft(
|
917
|
+
target: QArray[QBit],
|
918
|
+
) -> None:
|
919
|
+
pass
|
920
|
+
|
921
|
+
|
897
922
|
__all__ = [
|
898
923
|
"permute",
|
899
924
|
"apply",
|
@@ -951,7 +976,6 @@ __all__ = [
|
|
951
976
|
"suzuki_trotter",
|
952
977
|
"qdrift",
|
953
978
|
"exponentiation_with_depth_constraint",
|
954
|
-
"qft",
|
955
979
|
"qpe_flexible",
|
956
980
|
"qpe",
|
957
981
|
"single_pauli",
|
@@ -985,6 +1009,9 @@ __all__ = [
|
|
985
1009
|
"qaoa_penalty",
|
986
1010
|
"full_hea",
|
987
1011
|
"swap_test",
|
1012
|
+
"_prepare_uniform_trimmed_state_step",
|
1013
|
+
"prepare_uniform_trimmed_state",
|
1014
|
+
"prepare_uniform_interval_state",
|
988
1015
|
"prepare_ghz_state",
|
989
1016
|
"prepare_exponential_state",
|
990
1017
|
"prepare_bell_state",
|
@@ -998,4 +1025,5 @@ __all__ = [
|
|
998
1025
|
"qct_type2",
|
999
1026
|
"qst_type2",
|
1000
1027
|
"modular_increment",
|
1028
|
+
"qft",
|
1001
1029
|
]
|
@@ -1,14 +1,29 @@
|
|
1
1
|
import inspect
|
2
2
|
import sys
|
3
|
+
import warnings
|
3
4
|
from types import FrameType
|
4
|
-
from typing import
|
5
|
+
from typing import (
|
6
|
+
TYPE_CHECKING,
|
7
|
+
Any,
|
8
|
+
Callable,
|
9
|
+
Final,
|
10
|
+
List,
|
11
|
+
Mapping,
|
12
|
+
Optional,
|
13
|
+
Union,
|
14
|
+
overload,
|
15
|
+
)
|
5
16
|
|
6
17
|
from classiq.interface.generator.expressions.expression import Expression
|
7
18
|
from classiq.interface.generator.functions.builtins.internal_operators import (
|
8
19
|
REPEAT_OPERATOR_NAME,
|
9
20
|
)
|
21
|
+
from classiq.interface.generator.functions.classical_type import Integer
|
10
22
|
from classiq.interface.model.bind_operation import BindOperation
|
11
23
|
from classiq.interface.model.classical_if import ClassicalIf
|
24
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
25
|
+
ClassicalParameterDeclaration,
|
26
|
+
)
|
12
27
|
from classiq.interface.model.control import Control
|
13
28
|
from classiq.interface.model.inplace_binary_operation import (
|
14
29
|
BinaryOperation,
|
@@ -25,7 +40,6 @@ from classiq.interface.model.repeat import Repeat
|
|
25
40
|
from classiq.interface.model.statement_block import StatementBlock
|
26
41
|
from classiq.interface.model.within_apply_operation import WithinApply
|
27
42
|
|
28
|
-
from classiq import Integer
|
29
43
|
from classiq.exceptions import ClassiqValueError
|
30
44
|
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QVar
|
31
45
|
from classiq.qmod.quantum_callable import QCallable
|
@@ -68,36 +82,51 @@ def if_(
|
|
68
82
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
69
83
|
ClassicalIf(
|
70
84
|
condition=Expression(expr=str(condition)),
|
71
|
-
then=_operand_to_body(then),
|
72
|
-
else_=_operand_to_body(else_) if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
|
85
|
+
then=_operand_to_body(then, "then"),
|
86
|
+
else_=_operand_to_body(else_, "else") if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
|
73
87
|
source_ref=source_ref,
|
74
88
|
)
|
75
89
|
)
|
76
90
|
|
77
91
|
|
78
|
-
@overload
|
92
|
+
@overload # FIXME: Remove overloading (CAD-21932)
|
79
93
|
def control(
|
80
|
-
ctrl: Union[QBit, QArray[QBit]],
|
94
|
+
ctrl: Union[QBit, QArray[QBit]], stmt_block: Union[QCallable, Callable[[], None]]
|
81
95
|
) -> None:
|
82
96
|
pass
|
83
97
|
|
84
98
|
|
85
99
|
@overload
|
86
|
-
def control(
|
100
|
+
def control(
|
101
|
+
ctrl: SymbolicExpr, stmt_block: Union[QCallable, Callable[[], None]]
|
102
|
+
) -> None:
|
87
103
|
pass
|
88
104
|
|
89
105
|
|
90
106
|
def control(
|
91
107
|
ctrl: Union[SymbolicExpr, QBit, QArray[QBit]],
|
92
|
-
|
108
|
+
stmt_block: Optional[Union[QCallable, Callable[[], None]]] = None,
|
109
|
+
operand: Optional[Union[QCallable, Callable[[], None]]] = None,
|
93
110
|
) -> None:
|
94
|
-
|
111
|
+
if operand is not None:
|
112
|
+
warnings.warn(
|
113
|
+
"Parameter 'operand' of function 'control' has been renamed to "
|
114
|
+
"'stmt_block'. Parameter 'operand' will be deprecated in a future "
|
115
|
+
"release.\nHint: Change `control(ctrl=..., operand=...)` to "
|
116
|
+
"`control(ctrl=..., stmt_block=...)` or `control(..., ...)`.",
|
117
|
+
category=DeprecationWarning,
|
118
|
+
stacklevel=2,
|
119
|
+
)
|
120
|
+
stmt_block = operand
|
121
|
+
if TYPE_CHECKING:
|
122
|
+
assert stmt_block is not None
|
123
|
+
_validate_operand(stmt_block)
|
95
124
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
96
125
|
source_ref = get_source_ref(sys._getframe(1))
|
97
126
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
98
127
|
Control(
|
99
128
|
expression=Expression(expr=str(ctrl)),
|
100
|
-
body=_operand_to_body(
|
129
|
+
body=_operand_to_body(stmt_block, "stmt_block"),
|
101
130
|
source_ref=source_ref,
|
102
131
|
)
|
103
132
|
)
|
@@ -135,18 +164,53 @@ def inplace_xor(
|
|
135
164
|
)
|
136
165
|
|
137
166
|
|
167
|
+
@overload # FIXME: Remove overloading (CAD-21932)
|
138
168
|
def within_apply(
|
139
|
-
|
140
|
-
|
169
|
+
within: Callable[[], None],
|
170
|
+
apply: Callable[[], None],
|
141
171
|
) -> None:
|
142
|
-
|
143
|
-
|
172
|
+
pass
|
173
|
+
|
174
|
+
|
175
|
+
@overload
|
176
|
+
def within_apply(
|
177
|
+
within: Callable[[], List[None]],
|
178
|
+
apply: Callable[[], List[None]],
|
179
|
+
) -> None:
|
180
|
+
pass
|
181
|
+
|
182
|
+
|
183
|
+
def within_apply( # type:ignore[misc]
|
184
|
+
within: Optional[Callable[[], None]] = None,
|
185
|
+
apply: Optional[Callable[[], None]] = None,
|
186
|
+
compute: Optional[Callable[[], None]] = None,
|
187
|
+
action: Optional[Callable[[], None]] = None,
|
188
|
+
) -> None:
|
189
|
+
if compute is not None or action is not None:
|
190
|
+
warnings.warn(
|
191
|
+
"Parameters 'compute' and 'action' of function 'within_apply' have "
|
192
|
+
"been renamed to 'within' and 'apply' respectively. Parameters 'compute' "
|
193
|
+
"and 'action' will be deprecated in a future release.\nHint: Change "
|
194
|
+
"`within_apply(compute=..., action=...)` to "
|
195
|
+
"`within_apply(within=..., apply=...)` or `within_apply(..., ...)`.",
|
196
|
+
category=DeprecationWarning,
|
197
|
+
stacklevel=2,
|
198
|
+
)
|
199
|
+
if compute is not None:
|
200
|
+
within = compute
|
201
|
+
if action is not None:
|
202
|
+
apply = action
|
203
|
+
if TYPE_CHECKING:
|
204
|
+
assert within is not None
|
205
|
+
assert apply is not None
|
206
|
+
_validate_operand(within)
|
207
|
+
_validate_operand(apply)
|
144
208
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
145
209
|
source_ref = get_source_ref(sys._getframe(1))
|
146
210
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
147
211
|
WithinApply(
|
148
|
-
compute=_operand_to_body(
|
149
|
-
action=_operand_to_body(
|
212
|
+
compute=_operand_to_body(within, "within"),
|
213
|
+
action=_operand_to_body(apply, "apply"),
|
150
214
|
source_ref=source_ref,
|
151
215
|
)
|
152
216
|
)
|
@@ -158,13 +222,20 @@ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) ->
|
|
158
222
|
source_ref = get_source_ref(sys._getframe(1))
|
159
223
|
iteration_operand = prepare_arg(
|
160
224
|
QuantumOperandDeclaration(
|
161
|
-
name=REPEAT_OPERATOR_NAME,
|
225
|
+
name=REPEAT_OPERATOR_NAME,
|
226
|
+
positional_arg_declarations=[
|
227
|
+
ClassicalParameterDeclaration(name="index", classical_type=Integer()),
|
228
|
+
],
|
162
229
|
),
|
163
230
|
iteration,
|
164
231
|
repeat.__name__,
|
232
|
+
"iteration",
|
165
233
|
)
|
166
234
|
if not isinstance(iteration_operand, QuantumLambdaFunction):
|
167
|
-
raise ClassiqValueError(
|
235
|
+
raise ClassiqValueError(
|
236
|
+
"Argument 'iteration' to 'repeat' should be a callable that takes one integer argument."
|
237
|
+
)
|
238
|
+
|
168
239
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
169
240
|
Repeat(
|
170
241
|
iter_var=inspect.getfullargspec(iteration).args[0],
|
@@ -175,35 +246,93 @@ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) ->
|
|
175
246
|
)
|
176
247
|
|
177
248
|
|
249
|
+
@overload # FIXME: Remove overloading (CAD-21932)
|
178
250
|
def power(
|
179
|
-
|
180
|
-
|
251
|
+
exponent: SymbolicExpr,
|
252
|
+
stmt_block: Union[QCallable, Callable[[], None]],
|
181
253
|
) -> None:
|
182
|
-
|
254
|
+
pass
|
255
|
+
|
256
|
+
|
257
|
+
@overload
|
258
|
+
def power(
|
259
|
+
exponent: int,
|
260
|
+
stmt_block: Union[QCallable, Callable[[], None]],
|
261
|
+
) -> None:
|
262
|
+
pass
|
263
|
+
|
264
|
+
|
265
|
+
def power(
|
266
|
+
exponent: Optional[Union[SymbolicExpr, int]] = None,
|
267
|
+
stmt_block: Optional[Union[QCallable, Callable[[], None]]] = None,
|
268
|
+
power: Optional[Union[SymbolicExpr, int]] = None,
|
269
|
+
operand: Optional[Union[QCallable, Callable[[], None]]] = None,
|
270
|
+
) -> None:
|
271
|
+
if power is not None or operand is not None:
|
272
|
+
warnings.warn(
|
273
|
+
"Parameters 'exponent' and 'operand' of function 'power' have been "
|
274
|
+
"renamed to 'exponent' and 'stmt_block' respectively. Parameters "
|
275
|
+
"'exponent' and 'operand' will be deprecated in a future release.\nHint: "
|
276
|
+
"Change `power(power=..., operand=...)` to "
|
277
|
+
"`power(exponent=..., stmt_block=...)` or `power(..., ...)`.",
|
278
|
+
category=DeprecationWarning,
|
279
|
+
stacklevel=2,
|
280
|
+
)
|
281
|
+
if power is not None:
|
282
|
+
exponent = power
|
283
|
+
if operand is not None:
|
284
|
+
stmt_block = operand
|
285
|
+
if TYPE_CHECKING:
|
286
|
+
assert exponent is not None
|
287
|
+
assert stmt_block is not None
|
288
|
+
_validate_operand(stmt_block)
|
183
289
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
184
290
|
source_ref = get_source_ref(sys._getframe(1))
|
185
291
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
186
292
|
Power(
|
187
|
-
power=Expression(expr=str(
|
188
|
-
body=_operand_to_body(
|
293
|
+
power=Expression(expr=str(exponent)),
|
294
|
+
body=_operand_to_body(stmt_block, "stmt_block"),
|
189
295
|
source_ref=source_ref,
|
190
296
|
)
|
191
297
|
)
|
192
298
|
|
193
299
|
|
300
|
+
@overload # FIXME: Remove overloading (CAD-21932)
|
301
|
+
def invert(stmt_block: QCallable) -> None:
|
302
|
+
pass
|
303
|
+
|
304
|
+
|
305
|
+
@overload
|
306
|
+
def invert(stmt_block: Callable[[], None]) -> None:
|
307
|
+
pass
|
308
|
+
|
309
|
+
|
194
310
|
def invert(
|
195
|
-
|
311
|
+
stmt_block: Optional[Union[QCallable, Callable[[], None]]] = None,
|
312
|
+
operand: Optional[Union[QCallable, Callable[[], None]]] = None,
|
196
313
|
) -> None:
|
197
|
-
|
314
|
+
if operand is not None:
|
315
|
+
warnings.warn(
|
316
|
+
"Parameter 'operand' of function 'invert' has been renamed to "
|
317
|
+
"'stmt_block'. Parameter 'operand' will be deprecated in a future "
|
318
|
+
"release.\nHint: Change `invert(operand=...)` to `invert(stmt_block=...)` "
|
319
|
+
"or `invert(...)`.",
|
320
|
+
category=DeprecationWarning,
|
321
|
+
stacklevel=2,
|
322
|
+
)
|
323
|
+
stmt_block = operand
|
324
|
+
if TYPE_CHECKING:
|
325
|
+
assert stmt_block is not None
|
326
|
+
_validate_operand(stmt_block)
|
198
327
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
199
328
|
source_ref = get_source_ref(sys._getframe(1))
|
200
329
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
201
|
-
Invert(body=_operand_to_body(
|
330
|
+
Invert(body=_operand_to_body(stmt_block, "stmt_block"), source_ref=source_ref)
|
202
331
|
)
|
203
332
|
|
204
333
|
|
205
|
-
def _validate_operand(
|
206
|
-
if
|
334
|
+
def _validate_operand(stmt_block: Any) -> None:
|
335
|
+
if stmt_block is not None:
|
207
336
|
return
|
208
337
|
currentframe: FrameType = inspect.currentframe() # type: ignore[assignment]
|
209
338
|
operation_frame: FrameType = currentframe.f_back # type: ignore[assignment]
|
@@ -215,7 +344,7 @@ def _validate_operand(operand: Any) -> None:
|
|
215
344
|
operand_arg_name = context[0].split("_validate_operand(")[1].split(")")[0]
|
216
345
|
|
217
346
|
error_message = (
|
218
|
-
f"{operation_name} is missing required argument for {operand_arg_name}"
|
347
|
+
f"{operation_name!r} is missing required argument for {operand_arg_name!r}."
|
219
348
|
)
|
220
349
|
error_message += _get_operand_hint(
|
221
350
|
operation_name=operation_name,
|
@@ -236,6 +365,7 @@ def _get_operand_hint_args(
|
|
236
365
|
else f"{param.name}=..."
|
237
366
|
)
|
238
367
|
for param in params.values()
|
368
|
+
if param.name != "operand" # FIXME: Remove compatibility (CAD-21932)
|
239
369
|
]
|
240
370
|
)
|
241
371
|
|
@@ -244,27 +374,28 @@ def _get_operand_hint(
|
|
244
374
|
operation_name: str, operand_arg_name: str, params: Mapping[str, inspect.Parameter]
|
245
375
|
) -> str:
|
246
376
|
return (
|
247
|
-
f"\nHint: To
|
248
|
-
f"
|
249
|
-
f"
|
250
|
-
f"
|
251
|
-
f"or a quantum function "
|
252
|
-
f"`{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'my_func')})`"
|
377
|
+
f"\nHint: To call a function under {operation_name!r} use a lambda function as in "
|
378
|
+
f"'{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'lambda: f(q)')})' "
|
379
|
+
f"or pass the quantum function directly as in "
|
380
|
+
f"'{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'f')})'."
|
253
381
|
)
|
254
382
|
|
255
383
|
|
256
|
-
def _operand_to_body(
|
384
|
+
def _operand_to_body(
|
385
|
+
callable_: Union[QCallable, Callable[[], None]], param_name: str
|
386
|
+
) -> StatementBlock:
|
257
387
|
op_name = sys._getframe(1).f_code.co_name
|
258
388
|
if (
|
259
389
|
isinstance(callable_, QCallable)
|
260
390
|
and len(callable_.func_decl.positional_arg_declarations) > 0
|
261
391
|
):
|
262
392
|
raise ClassiqValueError(
|
263
|
-
f"
|
264
|
-
f"
|
265
|
-
f"{len(callable_.func_decl.positional_arg_declarations)}"
|
393
|
+
f"Callable argument {callable_.func_decl.name!r} to {op_name!r} should "
|
394
|
+
f"not accept arguments."
|
266
395
|
)
|
267
|
-
to_operand = prepare_arg(
|
396
|
+
to_operand = prepare_arg(
|
397
|
+
QuantumOperandDeclaration(name=""), callable_, op_name, param_name
|
398
|
+
)
|
268
399
|
if isinstance(to_operand, str):
|
269
400
|
return [QuantumFunctionCall(function=to_operand)]
|
270
401
|
elif isinstance(to_operand, QuantumLambdaFunction):
|