classiq 0.100.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/__init__.py +3 -0
- classiq/_internals/api_wrapper.py +29 -4
- classiq/applications/chemistry/op_utils.py +63 -1
- classiq/applications/chemistry/problems.py +18 -6
- classiq/applications/chemistry/ucc.py +2 -2
- classiq/evaluators/parameter_types.py +1 -4
- 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_node_evaluators/utils.py +6 -3
- classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
- classiq/execution/__init__.py +11 -1
- 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/execution/jobs.py +122 -5
- 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/exceptions.py +0 -42
- classiq/interface/executor/execution_request.py +1 -0
- classiq/interface/executor/quantum_code.py +0 -6
- 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/generation_request.py +9 -4
- classiq/interface/generator/quantum_program.py +8 -36
- classiq/interface/generator/types/compilation_metadata.py +9 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/helpers/model_normalizer.py +62 -2
- classiq/interface/helpers/text_utils.py +17 -6
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/invert.py +15 -0
- classiq/interface/model/model.py +42 -3
- classiq/interface/model/model_visitor.py +4 -2
- classiq/interface/model/quantum_function_call.py +17 -5
- 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 +12 -10
- 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 +15 -47
- classiq/open_library/functions/__init__.py +42 -27
- classiq/open_library/functions/bit_operations.py +30 -0
- classiq/open_library/functions/modular_arithmetics.py +597 -0
- classiq/open_library/functions/qft_space_arithmetics.py +81 -0
- classiq/open_library/functions/state_preparation.py +6 -3
- classiq/open_library/functions/utility_functions.py +22 -3
- classiq/qmod/builtins/functions/__init__.py +9 -0
- classiq/qmod/builtins/functions/arithmetic.py +131 -0
- classiq/qmod/builtins/functions/exponentiation.py +34 -4
- classiq/qmod/builtins/operations.py +30 -41
- classiq/qmod/native/pretty_printer.py +12 -12
- classiq/qmod/pretty_print/pretty_printer.py +11 -15
- classiq/qmod/qmod_parameter.py +4 -0
- classiq/qmod/qmod_variable.py +38 -63
- classiq/qmod/quantum_callable.py +8 -2
- classiq/qmod/quantum_expandable.py +3 -1
- classiq/qmod/quantum_function.py +45 -8
- 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/qmod/utilities.py +7 -4
- classiq/synthesis_action/__init__.py +20 -0
- classiq/synthesis_action/actions.py +106 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/METADATA +1 -1
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/RECORD +90 -84
- classiq/interface/executor/register_initialization.py +0 -36
- classiq/interface/generator/amplitude_loading.py +0 -103
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
- classiq/open_library/functions/modular_exponentiation.py +0 -272
- classiq/open_library/functions/qsvt_temp.py +0 -536
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/WHEEL +0 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING
|
|
1
|
+
from typing import TYPE_CHECKING, NoReturn, cast
|
|
2
2
|
|
|
3
|
-
from classiq.interface.exceptions import
|
|
3
|
+
from classiq.interface.exceptions import (
|
|
4
|
+
ClassiqExpansionError,
|
|
5
|
+
)
|
|
4
6
|
from classiq.interface.generator.expressions.expression import Expression
|
|
7
|
+
from classiq.interface.generator.functions.classical_type import (
|
|
8
|
+
Bool,
|
|
9
|
+
ClassicalArray,
|
|
10
|
+
ClassicalTuple,
|
|
11
|
+
Integer,
|
|
12
|
+
)
|
|
5
13
|
from classiq.interface.model.allocate import Allocate
|
|
6
14
|
from classiq.interface.model.bind_operation import BindOperation
|
|
7
15
|
from classiq.interface.model.block import Block
|
|
@@ -20,9 +28,11 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
|
20
28
|
)
|
|
21
29
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
22
30
|
from classiq.interface.model.quantum_type import (
|
|
31
|
+
QuantumBit,
|
|
23
32
|
QuantumBitvector,
|
|
24
33
|
QuantumNumeric,
|
|
25
34
|
QuantumScalar,
|
|
35
|
+
QuantumType,
|
|
26
36
|
)
|
|
27
37
|
from classiq.interface.model.statement_block import StatementBlock
|
|
28
38
|
from classiq.interface.model.variable_declaration_statement import (
|
|
@@ -31,6 +41,18 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
|
31
41
|
from classiq.interface.model.within_apply_operation import WithinApply
|
|
32
42
|
|
|
33
43
|
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
44
|
+
from classiq.evaluators.qmod_node_evaluators.utils import (
|
|
45
|
+
QmodType,
|
|
46
|
+
array_len,
|
|
47
|
+
element_types,
|
|
48
|
+
is_numeric_type,
|
|
49
|
+
)
|
|
50
|
+
from classiq.evaluators.qmod_type_inference.classical_type_inference import (
|
|
51
|
+
infer_classical_type,
|
|
52
|
+
)
|
|
53
|
+
from classiq.evaluators.qmod_type_inference.quantum_type_comparison import (
|
|
54
|
+
compare_quantum_types,
|
|
55
|
+
)
|
|
34
56
|
from classiq.evaluators.qmod_type_inference.quantum_type_inference import (
|
|
35
57
|
inject_quantum_type_attributes_inplace,
|
|
36
58
|
)
|
|
@@ -43,13 +65,22 @@ from classiq.model_expansions.quantum_operations.arithmetic.explicit_boolean_exp
|
|
|
43
65
|
validate_assignment_bool_expression,
|
|
44
66
|
)
|
|
45
67
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
|
46
|
-
from classiq.model_expansions.scope import ClassicalSymbol
|
|
68
|
+
from classiq.model_expansions.scope import ClassicalSymbol, QuantumSymbol
|
|
47
69
|
from classiq.qmod.builtins.functions.standard_gates import CX
|
|
48
70
|
|
|
49
71
|
if TYPE_CHECKING:
|
|
50
72
|
from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
|
|
51
73
|
|
|
52
74
|
|
|
75
|
+
def _get_expr_type(op: QuantumAssignmentOperation) -> QmodType:
|
|
76
|
+
expr_val = op.expression.value.value
|
|
77
|
+
if isinstance(expr_val, QmodAnnotatedExpression):
|
|
78
|
+
return expr_val.get_type(expr_val.root)
|
|
79
|
+
else:
|
|
80
|
+
expr_type = infer_classical_type(expr_val)
|
|
81
|
+
return expr_type
|
|
82
|
+
|
|
83
|
+
|
|
53
84
|
class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
54
85
|
def __init__(
|
|
55
86
|
self, interpreter: "BaseInterpreter", replace_assignment_if_needed: bool = False
|
|
@@ -60,14 +91,26 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
|
60
91
|
def emit(self, op: QuantumAssignmentOperation, /) -> bool:
|
|
61
92
|
result_symbol = self._interpreter.evaluate(op.result_var).value
|
|
62
93
|
if isinstance(result_symbol, ClassicalSymbol):
|
|
63
|
-
return
|
|
94
|
+
return self._emit_classical_assignment(op)
|
|
95
|
+
if isinstance(result_symbol.quantum_type, QuantumScalar):
|
|
96
|
+
return self._emit_scalar_assignment(op)
|
|
97
|
+
expr_val = op.expression.value.value
|
|
98
|
+
if isinstance(expr_val, QmodAnnotatedExpression) and isinstance(
|
|
99
|
+
expr_val.get_type(expr_val.root), QuantumType
|
|
100
|
+
):
|
|
101
|
+
return self._emit_quantum_var_quantum_expr_assignment(op)
|
|
102
|
+
return self._emit_quantum_var_classical_expr_assignment(op)
|
|
103
|
+
|
|
104
|
+
def _emit_classical_assignment(self, _: QuantumAssignmentOperation, /) -> bool:
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
def _emit_scalar_assignment(self, op: QuantumAssignmentOperation, /) -> bool:
|
|
108
|
+
result_symbol = self._interpreter.evaluate(op.result_var).value
|
|
64
109
|
result_type = result_symbol.quantum_type
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
f"{result_type.raw_qmod_type_name}"
|
|
70
|
-
)
|
|
110
|
+
|
|
111
|
+
expr_type = _get_expr_type(op)
|
|
112
|
+
if not is_numeric_type(expr_type) and not isinstance(expr_type, Bool):
|
|
113
|
+
self._raise_type_error(result_symbol, expr_type)
|
|
71
114
|
|
|
72
115
|
if not (
|
|
73
116
|
isinstance(op, ArithmeticOperation)
|
|
@@ -82,36 +125,73 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
|
82
125
|
)
|
|
83
126
|
convert_assignment_bool_expression(op)
|
|
84
127
|
|
|
85
|
-
|
|
86
|
-
if
|
|
128
|
+
quantum_expr_type = self._infer_scalar_expression_type(op)
|
|
129
|
+
if quantum_expr_type is None:
|
|
87
130
|
return False
|
|
88
131
|
|
|
89
132
|
if not result_type.is_instantiated:
|
|
90
|
-
if not inject_quantum_type_attributes_inplace(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
f"{str(result_symbol)!r} of type "
|
|
95
|
-
f"{result_symbol.quantum_type.qmod_type_name}"
|
|
96
|
-
)
|
|
133
|
+
if not inject_quantum_type_attributes_inplace(
|
|
134
|
+
quantum_expr_type, result_type
|
|
135
|
+
):
|
|
136
|
+
self._raise_type_error(result_symbol, expr_type)
|
|
97
137
|
return False
|
|
98
138
|
|
|
99
|
-
if isinstance(result_type,
|
|
100
|
-
|
|
139
|
+
if not isinstance(result_type, QuantumScalar) or not isinstance(
|
|
140
|
+
quantum_expr_type, QuantumScalar
|
|
101
141
|
):
|
|
102
|
-
|
|
103
|
-
if
|
|
142
|
+
return False
|
|
143
|
+
if isinstance(result_type, QuantumNumeric):
|
|
144
|
+
result_type.set_bounds(quantum_expr_type.get_bounds())
|
|
145
|
+
if self._same_numeric_attributes(result_type, quantum_expr_type):
|
|
104
146
|
return False
|
|
105
147
|
self._validate_declared_attributes(
|
|
106
|
-
result_type,
|
|
148
|
+
result_type, quantum_expr_type, str(op.result_var)
|
|
107
149
|
)
|
|
108
150
|
if not self._replace_assignment_if_needed:
|
|
109
151
|
return False
|
|
110
152
|
|
|
111
|
-
self._assign_to_inferred_var_and_bind(op, result_type,
|
|
153
|
+
self._assign_to_inferred_var_and_bind(op, result_type, quantum_expr_type)
|
|
112
154
|
return True
|
|
113
155
|
|
|
114
|
-
def
|
|
156
|
+
def _emit_quantum_var_quantum_expr_assignment(
|
|
157
|
+
self, op: QuantumAssignmentOperation, /
|
|
158
|
+
) -> bool:
|
|
159
|
+
result_symbol = self._interpreter.evaluate(op.result_var).value
|
|
160
|
+
result_type = result_symbol.quantum_type
|
|
161
|
+
expr_type = cast(QuantumType, _get_expr_type(op))
|
|
162
|
+
if not inject_quantum_type_attributes_inplace(
|
|
163
|
+
expr_type, result_type
|
|
164
|
+
) or not compare_quantum_types(result_type, expr_type):
|
|
165
|
+
self._raise_type_error(result_symbol, expr_type)
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
def _emit_quantum_var_classical_expr_assignment(
|
|
169
|
+
self, op: QuantumAssignmentOperation, /
|
|
170
|
+
) -> bool:
|
|
171
|
+
result_symbol = self._interpreter.evaluate(op.result_var).value
|
|
172
|
+
result_type = result_symbol.quantum_type
|
|
173
|
+
|
|
174
|
+
quantum_expr_type = self._infer_classical_array_expression_type(op)
|
|
175
|
+
if quantum_expr_type is None or not inject_quantum_type_attributes_inplace(
|
|
176
|
+
quantum_expr_type, result_type
|
|
177
|
+
):
|
|
178
|
+
self._raise_type_error(result_symbol, _get_expr_type(op))
|
|
179
|
+
|
|
180
|
+
return False
|
|
181
|
+
|
|
182
|
+
def _raise_type_error(
|
|
183
|
+
self, result_symbol: QuantumSymbol, expr_type: QmodType
|
|
184
|
+
) -> NoReturn:
|
|
185
|
+
raise ClassiqExpansionError(
|
|
186
|
+
f"Cannot assign expression of type "
|
|
187
|
+
f"{expr_type.qmod_type_name} to variable "
|
|
188
|
+
f"{str(result_symbol)!r} of type "
|
|
189
|
+
f"{result_symbol.quantum_type.qmod_type_name}"
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
def _infer_scalar_expression_type(
|
|
193
|
+
self, op: QuantumAssignmentOperation
|
|
194
|
+
) -> QuantumType | None:
|
|
115
195
|
expr = self._evaluate_expression(op.expression)
|
|
116
196
|
expr_val = expr.value.value
|
|
117
197
|
if isinstance(expr_val, QmodAnnotatedExpression):
|
|
@@ -129,9 +209,33 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
|
129
209
|
).to_quantum_numeric()
|
|
130
210
|
return None
|
|
131
211
|
|
|
212
|
+
def _infer_classical_array_expression_type(
|
|
213
|
+
self, op: QuantumAssignmentOperation
|
|
214
|
+
) -> QuantumType | None:
|
|
215
|
+
expr = self._evaluate_expression(op.expression)
|
|
216
|
+
expr_val = expr.value.value
|
|
217
|
+
if isinstance(expr_val, QmodAnnotatedExpression):
|
|
218
|
+
root_type = expr_val.get_type(expr_val.root)
|
|
219
|
+
if isinstance(root_type, (ClassicalArray, ClassicalTuple)) and all(
|
|
220
|
+
isinstance(element_type, Integer)
|
|
221
|
+
for element_type in element_types(root_type)
|
|
222
|
+
):
|
|
223
|
+
list_len = array_len(root_type)
|
|
224
|
+
len_expr = (
|
|
225
|
+
Expression(expr=str(list_len)) if list_len is not None else None
|
|
226
|
+
)
|
|
227
|
+
return QuantumBitvector(element_type=QuantumBit(), length=len_expr)
|
|
228
|
+
return None
|
|
229
|
+
if isinstance(expr_val, list) and all(
|
|
230
|
+
element in (0, 1) for element in expr_val
|
|
231
|
+
):
|
|
232
|
+
length_expr = Expression(expr=str(len(expr_val)))
|
|
233
|
+
return QuantumBitvector(element_type=QuantumBit(), length=length_expr)
|
|
234
|
+
return None
|
|
235
|
+
|
|
132
236
|
@staticmethod
|
|
133
237
|
def _same_numeric_attributes(
|
|
134
|
-
result_type:
|
|
238
|
+
result_type: QuantumScalar, expression_type: QuantumScalar
|
|
135
239
|
) -> bool:
|
|
136
240
|
return (
|
|
137
241
|
result_type.size_in_bits == expression_type.size_in_bits
|
|
@@ -142,7 +246,7 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
|
142
246
|
|
|
143
247
|
@classmethod
|
|
144
248
|
def _validate_declared_attributes(
|
|
145
|
-
cls, result_type:
|
|
249
|
+
cls, result_type: QuantumScalar, expression_type: QuantumScalar, var: str
|
|
146
250
|
) -> None:
|
|
147
251
|
result_size, result_sign, result_fractions = (
|
|
148
252
|
result_type.size_in_bits,
|
|
@@ -97,6 +97,8 @@ class BindEmitter(Emitter[BindOperation]):
|
|
|
97
97
|
state = self._builder.current_block.captured_vars.get_state(
|
|
98
98
|
var_name, inp.defining_function
|
|
99
99
|
)
|
|
100
|
+
if state is None:
|
|
101
|
+
continue
|
|
100
102
|
if not state:
|
|
101
103
|
raise ClassiqExpansionError(
|
|
102
104
|
f"Cannot use uninitialized quantum variable "
|
|
@@ -112,6 +114,8 @@ class BindEmitter(Emitter[BindOperation]):
|
|
|
112
114
|
state = self._builder.current_block.captured_vars.get_state(
|
|
113
115
|
var_name, out.defining_function
|
|
114
116
|
)
|
|
117
|
+
if state is None:
|
|
118
|
+
continue
|
|
115
119
|
if state:
|
|
116
120
|
raise ClassiqExpansionError(
|
|
117
121
|
f"Cannot use initialized quantum variable "
|
|
@@ -12,9 +12,6 @@ from classiq.interface.debug_info.debug_info import (
|
|
|
12
12
|
new_function_debug_info_by_node,
|
|
13
13
|
)
|
|
14
14
|
from classiq.interface.exceptions import ClassiqExpansionError
|
|
15
|
-
from classiq.interface.generator.functions.port_declaration import (
|
|
16
|
-
PortDeclarationDirection,
|
|
17
|
-
)
|
|
18
15
|
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
|
19
16
|
from classiq.interface.helpers.text_utils import are, readable_list, s
|
|
20
17
|
from classiq.interface.model.block import Block
|
|
@@ -45,8 +42,6 @@ from classiq.evaluators.parameter_types import (
|
|
|
45
42
|
)
|
|
46
43
|
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
47
44
|
from classiq.model_expansions.capturing.captured_vars import (
|
|
48
|
-
INITIALIZED_VAR_MESSAGE,
|
|
49
|
-
UNINITIALIZED_VAR_MESSAGE,
|
|
50
45
|
validate_args_are_not_propagated,
|
|
51
46
|
)
|
|
52
47
|
from classiq.model_expansions.closure import Closure, FunctionClosure
|
|
@@ -109,12 +104,14 @@ def _validate_gen_args(
|
|
|
109
104
|
if (
|
|
110
105
|
isinstance(param, ClassicalParameterDeclaration)
|
|
111
106
|
and not param.classical_type.is_purely_declarative
|
|
112
|
-
and isinstance(arg.value, QmodAnnotatedExpression)
|
|
107
|
+
and isinstance(arg_val := arg.value, QmodAnnotatedExpression)
|
|
113
108
|
):
|
|
114
109
|
readable_expr = transform_expression(str(arg.value), {}, {}, one_line=True)
|
|
110
|
+
expr_type = arg_val.get_type(arg_val.root)
|
|
115
111
|
raise ClassiqExpansionError(
|
|
116
|
-
f"Cannot pass
|
|
117
|
-
f"parameter {param.name!r}"
|
|
112
|
+
f"Cannot pass {readable_expr!r} of type {expr_type.qmod_type_name} as "
|
|
113
|
+
f"parameter {param.name!r} of Python-type "
|
|
114
|
+
f"{param.classical_type.python_type_name}"
|
|
118
115
|
)
|
|
119
116
|
|
|
120
117
|
|
|
@@ -195,7 +192,6 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], ModelR
|
|
|
195
192
|
) -> QuantumFunctionCall:
|
|
196
193
|
function = function.clone()
|
|
197
194
|
function = function.set_depth(self._builder.current_function.depth + 1)
|
|
198
|
-
self._validate_call_args(function.positional_arg_declarations, args)
|
|
199
195
|
evaluated_args = [self._interpreter.evaluate(arg) for arg in args]
|
|
200
196
|
_validate_cloning(evaluated_args)
|
|
201
197
|
_validate_runtime_args(evaluated_args, self._current_scope)
|
|
@@ -391,32 +387,6 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], ModelR
|
|
|
391
387
|
permutation=function.permutation,
|
|
392
388
|
)
|
|
393
389
|
|
|
394
|
-
def _validate_call_args(
|
|
395
|
-
self, params: Sequence[PositionalArg], args: list[ArgValue]
|
|
396
|
-
) -> None:
|
|
397
|
-
for param, arg in zip(params, args):
|
|
398
|
-
if not isinstance(param, PortDeclaration) or not isinstance(
|
|
399
|
-
arg, HandleBinding
|
|
400
|
-
):
|
|
401
|
-
continue
|
|
402
|
-
var_name = arg.name
|
|
403
|
-
symbol = self._interpreter.evaluate(var_name)
|
|
404
|
-
if (
|
|
405
|
-
not isinstance(symbol.value, QuantumSymbol)
|
|
406
|
-
or symbol.defining_function is None
|
|
407
|
-
):
|
|
408
|
-
continue
|
|
409
|
-
var_state = self._builder.current_block.captured_vars.get_state(
|
|
410
|
-
var_name, symbol.defining_function
|
|
411
|
-
)
|
|
412
|
-
if not var_state and param.direction in (
|
|
413
|
-
PortDeclarationDirection.Inout,
|
|
414
|
-
PortDeclarationDirection.Input,
|
|
415
|
-
):
|
|
416
|
-
raise ClassiqExpansionError(UNINITIALIZED_VAR_MESSAGE.format(var_name))
|
|
417
|
-
if var_state and param.direction == PortDeclarationDirection.Output:
|
|
418
|
-
raise ClassiqExpansionError(INITIALIZED_VAR_MESSAGE.format(var_name))
|
|
419
|
-
|
|
420
390
|
def _validate_type_modifiers(
|
|
421
391
|
self, func_context: FunctionContext, func_def: NativeFunctionDefinition
|
|
422
392
|
) -> None:
|
|
@@ -144,11 +144,8 @@ class Emitter(Generic[QuantumStatementT], ABC):
|
|
|
144
144
|
expression: Expression,
|
|
145
145
|
*,
|
|
146
146
|
simplify: bool = False,
|
|
147
|
-
treat_qnum_as_float: bool = False,
|
|
148
147
|
) -> Expression:
|
|
149
|
-
expr_val = self._interpreter.evaluate(
|
|
150
|
-
expression, simplify=simplify, treat_qnum_as_float=treat_qnum_as_float
|
|
151
|
-
).value
|
|
148
|
+
expr_val = self._interpreter.evaluate(expression, simplify=simplify).value
|
|
152
149
|
new_expr = Expression(expr=str(expr_val))
|
|
153
150
|
new_expr._evaluated_expr = EvaluatedExpression(value=expr_val)
|
|
154
151
|
return new_expr
|
|
@@ -26,14 +26,12 @@ class ExpressionEvaluator(Emitter[QuantumOperation]):
|
|
|
26
26
|
*,
|
|
27
27
|
readable_expression_name: str | None = None,
|
|
28
28
|
simplify: bool = False,
|
|
29
|
-
treat_qnum_as_float: bool = False,
|
|
30
29
|
allow_link_time_vars: bool = True,
|
|
31
30
|
allow_runtime_vars: bool = True,
|
|
32
31
|
) -> None:
|
|
33
32
|
super().__init__(interpreter)
|
|
34
33
|
self._expression_name = expression_name
|
|
35
34
|
self._simplify = simplify
|
|
36
|
-
self._treat_qnum_as_float = treat_qnum_as_float
|
|
37
35
|
self._allow_link_time_vars = allow_link_time_vars
|
|
38
36
|
self._allow_runtime_vars = allow_runtime_vars
|
|
39
37
|
if (
|
|
@@ -49,7 +47,6 @@ class ExpressionEvaluator(Emitter[QuantumOperation]):
|
|
|
49
47
|
evaluated_expression = self._evaluate_expression(
|
|
50
48
|
expression,
|
|
51
49
|
simplify=self._simplify,
|
|
52
|
-
treat_qnum_as_float=self._treat_qnum_as_float,
|
|
53
50
|
)
|
|
54
51
|
for symbol in self._get_symbols_in_expression(evaluated_expression):
|
|
55
52
|
self._capture_handle(symbol.handle, PortDeclarationDirection.Inout)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import warnings
|
|
2
1
|
from collections import defaultdict
|
|
3
2
|
from collections.abc import Iterator
|
|
4
3
|
from contextlib import contextmanager
|
|
@@ -6,10 +5,8 @@ from typing import NamedTuple
|
|
|
6
5
|
|
|
7
6
|
from classiq.interface.ast_node import ASTNode
|
|
8
7
|
from classiq.interface.exceptions import (
|
|
9
|
-
ClassiqDeprecationWarning,
|
|
10
8
|
ClassiqInternalExpansionError,
|
|
11
9
|
)
|
|
12
|
-
from classiq.interface.generator.compiler_keywords import EXPANDED_KEYWORD
|
|
13
10
|
from classiq.interface.generator.functions.port_declaration import (
|
|
14
11
|
PortDeclarationDirection,
|
|
15
12
|
)
|
|
@@ -24,9 +21,6 @@ from classiq.interface.model.invert import Invert
|
|
|
24
21
|
from classiq.interface.model.model_visitor import ModelStatementsVisitor
|
|
25
22
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
26
23
|
from classiq.interface.model.power import Power
|
|
27
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
28
|
-
AmplitudeLoadingOperation,
|
|
29
|
-
)
|
|
30
24
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
31
25
|
ArithmeticOperation,
|
|
32
26
|
)
|
|
@@ -35,6 +29,8 @@ from classiq.interface.model.skip_control import SkipControl
|
|
|
35
29
|
from classiq.interface.model.within_apply_operation import WithinApply
|
|
36
30
|
from classiq.interface.source_reference import SourceReference
|
|
37
31
|
|
|
32
|
+
from classiq.qmod.semantics.error_manager import ErrorManager
|
|
33
|
+
|
|
38
34
|
|
|
39
35
|
class _BoundVars(NamedTuple):
|
|
40
36
|
in_identifiers: list[str]
|
|
@@ -148,12 +144,6 @@ class UncomputationSignatureInference(ModelStatementsVisitor):
|
|
|
148
144
|
else:
|
|
149
145
|
self._mark_as_non_const(arith.result_var.name, True)
|
|
150
146
|
|
|
151
|
-
def visit_AmplitudeLoadingOperation(
|
|
152
|
-
self, amp_load: AmplitudeLoadingOperation
|
|
153
|
-
) -> None:
|
|
154
|
-
self._mark_as_non_permutation()
|
|
155
|
-
self._mark_as_non_const(amp_load.result_var.name, False)
|
|
156
|
-
|
|
157
147
|
def visit_Control(self, control: Control) -> None:
|
|
158
148
|
self.visit(control.body)
|
|
159
149
|
if control.else_block is not None:
|
|
@@ -243,11 +233,7 @@ def infer_and_validate_uncomputation_signature(
|
|
|
243
233
|
PortDeclarationDirection.Input,
|
|
244
234
|
PortDeclarationDirection.Output,
|
|
245
235
|
):
|
|
246
|
-
|
|
247
|
-
_input_output_const(port.name, port.direction, func_def.name),
|
|
248
|
-
ClassiqDeprecationWarning,
|
|
249
|
-
stacklevel=1,
|
|
250
|
-
)
|
|
236
|
+
ErrorManager().add_error(_input_output_const(port.name, port.direction))
|
|
251
237
|
|
|
252
238
|
if disable_perm_check and (disable_const_checks is True) and not tighten_signature:
|
|
253
239
|
return
|
|
@@ -257,10 +243,9 @@ def infer_and_validate_uncomputation_signature(
|
|
|
257
243
|
|
|
258
244
|
if not disable_perm_check and func_def.permutation and not visitor.is_permutation():
|
|
259
245
|
for source_ref in visitor.non_permutation_reasons():
|
|
260
|
-
|
|
261
|
-
_non_permutation_usage(
|
|
262
|
-
|
|
263
|
-
stacklevel=1,
|
|
246
|
+
ErrorManager().add_error(
|
|
247
|
+
_non_permutation_usage(),
|
|
248
|
+
source_ref=source_ref,
|
|
264
249
|
)
|
|
265
250
|
|
|
266
251
|
if tighten_signature and not func_def.permutation and visitor.is_permutation():
|
|
@@ -276,10 +261,8 @@ def infer_and_validate_uncomputation_signature(
|
|
|
276
261
|
and not visitor.is_const(port.name)
|
|
277
262
|
):
|
|
278
263
|
for source_ref in visitor.non_const_reasons(port.name):
|
|
279
|
-
|
|
280
|
-
_non_const_usage(port.name, source_ref
|
|
281
|
-
ClassiqDeprecationWarning,
|
|
282
|
-
stacklevel=1,
|
|
264
|
+
ErrorManager().add_error(
|
|
265
|
+
_non_const_usage(port.name), source_ref=source_ref
|
|
283
266
|
)
|
|
284
267
|
|
|
285
268
|
if (
|
|
@@ -293,36 +276,21 @@ def infer_and_validate_uncomputation_signature(
|
|
|
293
276
|
def _input_output_const(
|
|
294
277
|
port_name: str,
|
|
295
278
|
direction: PortDeclarationDirection,
|
|
296
|
-
function_name: str,
|
|
297
279
|
) -> str:
|
|
298
|
-
return (
|
|
299
|
-
f"{direction.capitalize()} parameters cannot be defined as constants"
|
|
300
|
-
f" (parameter {port_name!r} in function {function_name.split('_' + EXPANDED_KEYWORD)[0]!r}).\n"
|
|
301
|
-
"The deprecation warning will be elevated to an error starting 2025-12-03, at the earliest."
|
|
302
|
-
)
|
|
280
|
+
return f"{direction.capitalize()} parameter {port_name!r} cannot be defined as constant."
|
|
303
281
|
|
|
304
282
|
|
|
305
|
-
def _non_const_usage(
|
|
306
|
-
port_name: str,
|
|
307
|
-
source_ref: SourceReference | None = None,
|
|
308
|
-
) -> str:
|
|
309
|
-
source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
|
|
283
|
+
def _non_const_usage(port_name: str) -> str:
|
|
310
284
|
return (
|
|
311
|
-
f"Non-constant usage of a constant parameter {port_name!r}
|
|
285
|
+
f"Non-constant usage of a constant parameter {port_name!r}.\n"
|
|
312
286
|
"Tip: if the commulative use of the parameter in the function is constant, "
|
|
313
|
-
"use the `disable_const_checks` flag to instruct the compiler to disregard individual operations
|
|
314
|
-
"The deprecation warning will be elevated to an error starting 2025-12-03, at the earliest."
|
|
287
|
+
"use the `disable_const_checks` flag to instruct the compiler to disregard individual operations."
|
|
315
288
|
)
|
|
316
289
|
|
|
317
290
|
|
|
318
|
-
def _non_permutation_usage(
|
|
319
|
-
function_name: str,
|
|
320
|
-
source_ref: SourceReference | None = None,
|
|
321
|
-
) -> str:
|
|
322
|
-
source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
|
|
291
|
+
def _non_permutation_usage() -> str:
|
|
323
292
|
return (
|
|
324
|
-
|
|
293
|
+
"Non-permutation operation used in a permutation function.\n"
|
|
325
294
|
"Tip: if the commulative effect of the function is a permutation, "
|
|
326
|
-
"use the `disable_perm_check` flag to instruct the compiler to disregard individual operations
|
|
327
|
-
"The deprecation warning will be elevated to an error starting 2025-12-03, at the earliest."
|
|
295
|
+
"use the `disable_perm_check` flag to instruct the compiler to disregard individual operations."
|
|
328
296
|
)
|
|
@@ -15,13 +15,13 @@ from .hea import *
|
|
|
15
15
|
from .lcu import *
|
|
16
16
|
from .linear_pauli_rotation import *
|
|
17
17
|
from .linear_pauli_rotation import _single_pauli
|
|
18
|
-
from .
|
|
19
|
-
from .modular_exponentiation import _check_msb
|
|
18
|
+
from .modular_arithmetics import *
|
|
20
19
|
from .qaoa_penalty import *
|
|
21
20
|
from .qft_functions import *
|
|
21
|
+
from .qft_space_arithmetics import *
|
|
22
|
+
from .qft_space_arithmetics import _check_msb
|
|
22
23
|
from .qpe import *
|
|
23
|
-
from .qsvt import
|
|
24
|
-
from .qsvt_temp import * # change to .qsvt after deprecation
|
|
24
|
+
from .qsvt import * # change to .qsvt after deprecation
|
|
25
25
|
from .state_preparation import *
|
|
26
26
|
from .state_preparation import _prepare_uniform_trimmed_state_step
|
|
27
27
|
from .swap_test import *
|
|
@@ -31,6 +31,7 @@ from .variational import *
|
|
|
31
31
|
OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
|
|
32
32
|
qpe_flexible,
|
|
33
33
|
qpe,
|
|
34
|
+
_check_msb,
|
|
34
35
|
_single_pauli,
|
|
35
36
|
linear_pauli_rotations,
|
|
36
37
|
amplitude_estimation,
|
|
@@ -45,25 +46,14 @@ OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
|
|
|
45
46
|
apply_to_all,
|
|
46
47
|
qft_no_swap,
|
|
47
48
|
qft_space_add_const,
|
|
48
|
-
cc_modular_add,
|
|
49
|
-
c_modular_multiply,
|
|
50
49
|
multiswap,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
projector_controlled_double_phase_new,
|
|
59
|
-
projector_controlled_phase_old,
|
|
60
|
-
projector_controlled_phase_new,
|
|
61
|
-
qsvt_inversion_old,
|
|
62
|
-
qsvt_inversion_new,
|
|
63
|
-
qsvt_lcu_old,
|
|
64
|
-
qsvt_lcu_new,
|
|
65
|
-
qsvt_lcu_step_old,
|
|
66
|
-
qsvt_lcu_step_new,
|
|
50
|
+
qsvt_step,
|
|
51
|
+
qsvt,
|
|
52
|
+
projector_controlled_double_phase,
|
|
53
|
+
projector_controlled_phase,
|
|
54
|
+
qsvt_inversion,
|
|
55
|
+
qsvt_lcu,
|
|
56
|
+
qsvt_lcu_step,
|
|
67
57
|
gqsp,
|
|
68
58
|
qaoa_mixer_layer,
|
|
69
59
|
qaoa_cost_layer,
|
|
@@ -89,7 +79,6 @@ OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
|
|
|
89
79
|
_prepare_uniform_trimmed_state_step,
|
|
90
80
|
_qct_d_operator,
|
|
91
81
|
_qct_pi_operator,
|
|
92
|
-
_check_msb,
|
|
93
82
|
encode_in_angle,
|
|
94
83
|
encode_on_bloch,
|
|
95
84
|
_cond_phase_flip,
|
|
@@ -99,6 +88,22 @@ OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
|
|
|
99
88
|
one_hot_to_unary,
|
|
100
89
|
inplace_one_hot_to_unary,
|
|
101
90
|
unary_to_one_hot,
|
|
91
|
+
modular_negate_inplace,
|
|
92
|
+
modular_subtract_inplace,
|
|
93
|
+
modular_double_inplace,
|
|
94
|
+
modular_add_constant_inplace,
|
|
95
|
+
modular_add_inplace,
|
|
96
|
+
modular_multiply,
|
|
97
|
+
modular_square,
|
|
98
|
+
modular_multiply_constant,
|
|
99
|
+
modular_multiply_constant_inplace,
|
|
100
|
+
modular_to_montgomery_inplace,
|
|
101
|
+
modular_montgomery_to_standard_inplace,
|
|
102
|
+
modular_inverse_inplace,
|
|
103
|
+
kaliski_iteration,
|
|
104
|
+
modular_rsub_inplace,
|
|
105
|
+
modular_exp, # TODO: deprecate when ready
|
|
106
|
+
modular_exponentiate,
|
|
102
107
|
]
|
|
103
108
|
|
|
104
109
|
__all__ = [
|
|
@@ -109,8 +114,6 @@ __all__ = [
|
|
|
109
114
|
"assign_amplitude_table",
|
|
110
115
|
"binary_to_one_hot",
|
|
111
116
|
"binary_to_unary",
|
|
112
|
-
"c_modular_multiply",
|
|
113
|
-
"cc_modular_add",
|
|
114
117
|
"encode_in_angle",
|
|
115
118
|
"encode_on_bloch",
|
|
116
119
|
"exact_amplitude_amplification",
|
|
@@ -121,19 +124,31 @@ __all__ = [
|
|
|
121
124
|
"grover_search",
|
|
122
125
|
"hadamard_transform",
|
|
123
126
|
"inplace_binary_to_one_hot",
|
|
124
|
-
"inplace_c_modular_multiply",
|
|
125
127
|
"inplace_modular_multiply",
|
|
126
128
|
"inplace_one_hot_to_unary",
|
|
127
129
|
"inplace_prepare_complex_amplitudes",
|
|
128
130
|
"inplace_prepare_int",
|
|
129
131
|
"inplace_prepare_sparse_amplitudes",
|
|
132
|
+
"kaliski_iteration",
|
|
130
133
|
"lcu",
|
|
131
134
|
"lcu_pauli",
|
|
132
135
|
"linear_pauli_rotations",
|
|
136
|
+
"modular_add_constant_inplace",
|
|
137
|
+
"modular_add_inplace",
|
|
133
138
|
"modular_add_qft_space",
|
|
139
|
+
"modular_double_inplace",
|
|
134
140
|
"modular_exp",
|
|
135
|
-
"
|
|
141
|
+
"modular_exponentiate",
|
|
142
|
+
"modular_inverse_inplace",
|
|
143
|
+
"modular_montgomery_to_standard_inplace",
|
|
136
144
|
"modular_multiply",
|
|
145
|
+
"modular_multiply_constant",
|
|
146
|
+
"modular_multiply_constant_inplace",
|
|
147
|
+
"modular_negate_inplace",
|
|
148
|
+
"modular_rsub_inplace",
|
|
149
|
+
"modular_square",
|
|
150
|
+
"modular_subtract_inplace",
|
|
151
|
+
"modular_to_montgomery_inplace",
|
|
137
152
|
"multiswap",
|
|
138
153
|
"one_hot_to_binary",
|
|
139
154
|
"one_hot_to_unary",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from classiq.open_library.functions.utility_functions import apply_to_all
|
|
2
|
+
from classiq.qmod.builtins.functions.standard_gates import SWAP, X
|
|
3
|
+
from classiq.qmod.builtins.operations import invert, repeat
|
|
4
|
+
from classiq.qmod.qfunc import qperm
|
|
5
|
+
from classiq.qmod.qmod_variable import QArray, QBit
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@qperm
|
|
9
|
+
def cyclic_shift_left(reg: QArray[QBit]) -> None:
|
|
10
|
+
"""
|
|
11
|
+
Performs a left shift on the quantum register array `reg` using SWAP gates.
|
|
12
|
+
"""
|
|
13
|
+
n = reg.size
|
|
14
|
+
repeat(n - 1, lambda i: SWAP(reg[n - i - 1], reg[n - i - 2]))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@qperm
|
|
18
|
+
def cyclic_shift_right(reg: QArray[QBit]) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Performs a right shift on the quantum register array `reg` by inverting cyclic_shift_left.
|
|
21
|
+
"""
|
|
22
|
+
invert(lambda: cyclic_shift_left(reg))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@qperm
|
|
26
|
+
def bitwise_negate(x: QArray[QBit]) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Negates each bit of the input x.
|
|
29
|
+
"""
|
|
30
|
+
apply_to_all(X, x)
|