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.
Files changed (95) hide show
  1. classiq/__init__.py +3 -0
  2. classiq/_internals/api_wrapper.py +29 -4
  3. classiq/applications/chemistry/op_utils.py +63 -1
  4. classiq/applications/chemistry/problems.py +18 -6
  5. classiq/applications/chemistry/ucc.py +2 -2
  6. classiq/evaluators/parameter_types.py +1 -4
  7. classiq/evaluators/qmod_annotated_expression.py +1 -1
  8. classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +1 -8
  9. classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +1 -1
  10. classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +2 -2
  11. classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +18 -29
  12. classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +1 -6
  13. classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -7
  14. classiq/evaluators/qmod_node_evaluators/utils.py +6 -3
  15. classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
  16. classiq/execution/__init__.py +11 -1
  17. classiq/execution/execution_session.py +1 -1
  18. classiq/execution/functions/__init__.py +3 -0
  19. classiq/execution/functions/_logging.py +19 -0
  20. classiq/execution/functions/constants.py +9 -0
  21. classiq/execution/functions/parse_provider_backend.py +90 -0
  22. classiq/execution/functions/sample.py +257 -0
  23. classiq/execution/jobs.py +122 -5
  24. classiq/interface/_version.py +1 -1
  25. classiq/interface/backend/backend_preferences.py +15 -0
  26. classiq/interface/backend/provider_config/providers/aqt.py +1 -1
  27. classiq/interface/backend/provider_config/providers/azure.py +1 -2
  28. classiq/interface/backend/provider_config/providers/ibm.py +1 -1
  29. classiq/interface/backend/quantum_backend_providers.py +3 -0
  30. classiq/interface/exceptions.py +0 -42
  31. classiq/interface/executor/execution_request.py +1 -0
  32. classiq/interface/executor/quantum_code.py +0 -6
  33. classiq/interface/executor/result.py +9 -5
  34. classiq/interface/generator/arith/binary_ops.py +38 -2
  35. classiq/interface/generator/function_param_list.py +4 -2
  36. classiq/interface/generator/functions/builtins/internal_operators.py +5 -9
  37. classiq/interface/generator/functions/classical_type.py +45 -0
  38. classiq/interface/generator/functions/type_name.py +23 -0
  39. classiq/interface/generator/generated_circuit_data.py +0 -2
  40. classiq/interface/generator/generation_request.py +9 -4
  41. classiq/interface/generator/quantum_program.py +8 -36
  42. classiq/interface/generator/types/compilation_metadata.py +9 -0
  43. classiq/interface/hardware.py +1 -0
  44. classiq/interface/helpers/model_normalizer.py +62 -2
  45. classiq/interface/helpers/text_utils.py +17 -6
  46. classiq/interface/interface_version.py +1 -1
  47. classiq/interface/model/invert.py +15 -0
  48. classiq/interface/model/model.py +42 -3
  49. classiq/interface/model/model_visitor.py +4 -2
  50. classiq/interface/model/quantum_function_call.py +17 -5
  51. classiq/interface/model/quantum_type.py +21 -0
  52. classiq/interface/model/statement_block.py +0 -4
  53. classiq/model_expansions/capturing/captured_vars.py +16 -12
  54. classiq/model_expansions/function_builder.py +9 -1
  55. classiq/model_expansions/interpreters/base_interpreter.py +12 -10
  56. classiq/model_expansions/interpreters/generative_interpreter.py +9 -24
  57. classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -0
  58. classiq/model_expansions/quantum_operations/assignment_result_processor.py +132 -28
  59. classiq/model_expansions/quantum_operations/bind.py +4 -0
  60. classiq/model_expansions/quantum_operations/call_emitter.py +5 -35
  61. classiq/model_expansions/quantum_operations/emitter.py +1 -4
  62. classiq/model_expansions/quantum_operations/expression_evaluator.py +0 -3
  63. classiq/model_expansions/visitors/uncomputation_signature_inference.py +15 -47
  64. classiq/open_library/functions/__init__.py +42 -27
  65. classiq/open_library/functions/bit_operations.py +30 -0
  66. classiq/open_library/functions/modular_arithmetics.py +597 -0
  67. classiq/open_library/functions/qft_space_arithmetics.py +81 -0
  68. classiq/open_library/functions/state_preparation.py +6 -3
  69. classiq/open_library/functions/utility_functions.py +22 -3
  70. classiq/qmod/builtins/functions/__init__.py +9 -0
  71. classiq/qmod/builtins/functions/arithmetic.py +131 -0
  72. classiq/qmod/builtins/functions/exponentiation.py +34 -4
  73. classiq/qmod/builtins/operations.py +30 -41
  74. classiq/qmod/native/pretty_printer.py +12 -12
  75. classiq/qmod/pretty_print/pretty_printer.py +11 -15
  76. classiq/qmod/qmod_parameter.py +4 -0
  77. classiq/qmod/qmod_variable.py +38 -63
  78. classiq/qmod/quantum_callable.py +8 -2
  79. classiq/qmod/quantum_expandable.py +3 -1
  80. classiq/qmod/quantum_function.py +45 -8
  81. classiq/qmod/semantics/validation/function_name_collisions_validation.py +7 -4
  82. classiq/qmod/semantics/validation/model_validation.py +7 -2
  83. classiq/qmod/symbolic_type.py +4 -2
  84. classiq/qmod/utilities.py +7 -4
  85. classiq/synthesis_action/__init__.py +20 -0
  86. classiq/synthesis_action/actions.py +106 -0
  87. {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/METADATA +1 -1
  88. {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/RECORD +90 -84
  89. classiq/interface/executor/register_initialization.py +0 -36
  90. classiq/interface/generator/amplitude_loading.py +0 -103
  91. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
  92. classiq/open_library/functions/modular_exponentiation.py +0 -272
  93. classiq/open_library/functions/qsvt_temp.py +0 -536
  94. {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/WHEEL +0 -0
  95. {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 ClassiqExpansionError
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 False
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
- if not isinstance(result_type, QuantumScalar):
66
- raise ClassiqExpansionError(
67
- f"Cannot assign into a non-scalar quantum variable "
68
- f"{str(result_symbol.handle)!r} of type "
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
- expression_type = self._infer_expression_type(op)
86
- if expression_type is None:
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(expression_type, result_type):
91
- raise ClassiqExpansionError(
92
- f"Cannot assign expression of type "
93
- f"{expression_type.qmod_type_name} to variable "
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, QuantumNumeric) and isinstance(
100
- expression_type, QuantumNumeric
139
+ if not isinstance(result_type, QuantumScalar) or not isinstance(
140
+ quantum_expr_type, QuantumScalar
101
141
  ):
102
- result_type.set_bounds(expression_type.get_bounds())
103
- if self._same_numeric_attributes(result_type, expression_type):
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, expression_type, str(op.result_var)
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, expression_type)
153
+ self._assign_to_inferred_var_and_bind(op, result_type, quantum_expr_type)
112
154
  return True
113
155
 
114
- def _infer_expression_type(self, op: ArithmeticOperation) -> QuantumScalar | None:
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: QuantumNumeric, expression_type: QuantumScalar
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: QuantumNumeric, expression_type: QuantumScalar, var: str
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 symbolic expression {readable_expr!r} as Python-type "
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
- warnings.warn(
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
- warnings.warn(
261
- _non_permutation_usage(func_def.name, source_ref),
262
- ClassiqDeprecationWarning,
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
- warnings.warn(
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}.{source_ref_str}\n"
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.\n"
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
- f"Non-permutation operation used in a permutation function {function_name.split('_' + EXPANDED_KEYWORD)[0]!r}.{source_ref_str}\n"
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.\n"
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 .modular_exponentiation import *
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 gqsp
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
- inplace_c_modular_multiply,
52
- modular_exp,
53
- qsvt_step_old,
54
- qsvt_step_new,
55
- qsvt_old,
56
- qsvt_new,
57
- projector_controlled_double_phase_old,
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
- "modular_increment",
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)