classiq 0.83.0__py3-none-any.whl → 0.84.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 (82) hide show
  1. classiq/_internals/api_wrapper.py +27 -0
  2. classiq/applications/chemistry/chemistry_model_constructor.py +0 -2
  3. classiq/applications/chemistry/hartree_fock.py +68 -0
  4. classiq/applications/chemistry/mapping.py +85 -0
  5. classiq/applications/chemistry/op_utils.py +79 -0
  6. classiq/applications/chemistry/problems.py +195 -0
  7. classiq/applications/chemistry/ucc.py +109 -0
  8. classiq/applications/chemistry/z2_symmetries.py +368 -0
  9. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +30 -1
  10. classiq/{model_expansions/evaluators → evaluators}/arg_type_match.py +12 -4
  11. classiq/{model_expansions/evaluators → evaluators}/argument_types.py +1 -1
  12. classiq/{model_expansions/evaluators → evaluators}/classical_expression.py +1 -1
  13. classiq/{model_expansions/evaluators → evaluators}/classical_type_inference.py +3 -4
  14. classiq/{model_expansions/evaluators → evaluators}/parameter_types.py +17 -15
  15. classiq/execution/__init__.py +12 -1
  16. classiq/execution/execution_session.py +189 -43
  17. classiq/execution/jobs.py +26 -1
  18. classiq/execution/qnn.py +2 -2
  19. classiq/execution/user_budgets.py +39 -0
  20. classiq/interface/_version.py +1 -1
  21. classiq/interface/constants.py +1 -0
  22. classiq/interface/execution/primitives.py +29 -1
  23. classiq/interface/executor/estimate_cost.py +35 -0
  24. classiq/interface/executor/execution_result.py +13 -0
  25. classiq/interface/executor/result.py +116 -1
  26. classiq/interface/executor/user_budget.py +26 -33
  27. classiq/interface/generator/expressions/atomic_expression_functions.py +5 -1
  28. classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -6
  29. classiq/interface/generator/functions/classical_type.py +2 -35
  30. classiq/interface/generator/functions/concrete_types.py +0 -3
  31. classiq/interface/generator/functions/type_modifier.py +0 -19
  32. classiq/interface/generator/generated_circuit_data.py +0 -8
  33. classiq/interface/generator/types/compilation_metadata.py +0 -3
  34. classiq/interface/ide/visual_model.py +6 -2
  35. classiq/interface/model/model.py +12 -7
  36. classiq/interface/model/port_declaration.py +2 -24
  37. classiq/interface/pretty_print/__init__.py +0 -0
  38. classiq/{qmod/native → interface/pretty_print}/expression_to_qmod.py +18 -11
  39. classiq/interface/server/routes.py +4 -0
  40. classiq/model_expansions/atomic_expression_functions_defs.py +42 -5
  41. classiq/model_expansions/interpreters/base_interpreter.py +3 -3
  42. classiq/model_expansions/quantum_operations/allocate.py +1 -1
  43. classiq/model_expansions/quantum_operations/assignment_result_processor.py +1 -1
  44. classiq/model_expansions/quantum_operations/bind.py +2 -2
  45. classiq/model_expansions/quantum_operations/call_emitter.py +26 -20
  46. classiq/model_expansions/quantum_operations/variable_decleration.py +1 -1
  47. classiq/model_expansions/scope_initialization.py +3 -3
  48. classiq/model_expansions/transformers/model_renamer.py +6 -4
  49. classiq/model_expansions/transformers/type_modifier_inference.py +81 -43
  50. classiq/model_expansions/visitors/symbolic_param_inference.py +2 -3
  51. classiq/open_library/functions/__init__.py +3 -0
  52. classiq/open_library/functions/amplitude_amplification.py +10 -18
  53. classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
  54. classiq/open_library/functions/grover.py +14 -6
  55. classiq/open_library/functions/modular_exponentiation.py +22 -20
  56. classiq/open_library/functions/state_preparation.py +17 -0
  57. classiq/qmod/builtins/enums.py +23 -0
  58. classiq/qmod/builtins/functions/__init__.py +2 -0
  59. classiq/qmod/builtins/functions/exponentiation.py +32 -4
  60. classiq/qmod/builtins/structs.py +55 -3
  61. classiq/qmod/declaration_inferrer.py +3 -2
  62. classiq/qmod/native/pretty_printer.py +2 -6
  63. classiq/qmod/pretty_print/expression_to_python.py +2 -1
  64. classiq/qmod/pretty_print/pretty_printer.py +1 -6
  65. classiq/qmod/python_classical_type.py +12 -5
  66. classiq/qmod/qmod_constant.py +2 -5
  67. classiq/qmod/qmod_parameter.py +2 -5
  68. classiq/qmod/qmod_variable.py +56 -15
  69. classiq/qmod/quantum_expandable.py +4 -2
  70. classiq/qmod/quantum_function.py +7 -2
  71. classiq/qmod/semantics/annotation/qstruct_annotator.py +1 -1
  72. classiq/qmod/semantics/validation/main_validation.py +1 -9
  73. classiq/qmod/utilities.py +0 -2
  74. classiq/qmod/write_qmod.py +1 -1
  75. {classiq-0.83.0.dist-info → classiq-0.84.0.dist-info}/METADATA +4 -1
  76. {classiq-0.83.0.dist-info → classiq-0.84.0.dist-info}/RECORD +82 -73
  77. /classiq/{model_expansions/evaluators → evaluators}/__init__.py +0 -0
  78. /classiq/{model_expansions/evaluators → evaluators}/control.py +0 -0
  79. /classiq/{model_expansions → evaluators}/expression_evaluator.py +0 -0
  80. /classiq/{model_expansions/evaluators → evaluators}/quantum_type_utils.py +0 -0
  81. /classiq/{model_expansions/evaluators → evaluators}/type_type_match.py +0 -0
  82. {classiq-0.83.0.dist-info → classiq-0.84.0.dist-info}/WHEEL +0 -0
@@ -50,19 +50,19 @@ from classiq.interface.model.variable_declaration_statement import (
50
50
  VariableDeclarationStatement,
51
51
  )
52
52
 
53
+ from classiq.evaluators.argument_types import (
54
+ add_information_from_output_arguments,
55
+ handle_args_numeric_bounds,
56
+ )
57
+ from classiq.evaluators.parameter_types import (
58
+ evaluate_parameter_types_from_args,
59
+ )
53
60
  from classiq.model_expansions.capturing.captured_vars import (
54
61
  INITIALIZED_VAR_MESSAGE,
55
62
  UNINITIALIZED_VAR_MESSAGE,
56
63
  validate_args_are_not_propagated,
57
64
  )
58
65
  from classiq.model_expansions.closure import Closure, FunctionClosure
59
- from classiq.model_expansions.evaluators.argument_types import (
60
- add_information_from_output_arguments,
61
- handle_args_numeric_bounds,
62
- )
63
- from classiq.model_expansions.evaluators.parameter_types import (
64
- evaluate_parameter_types_from_args,
65
- )
66
66
  from classiq.model_expansions.function_builder import (
67
67
  FunctionContext,
68
68
  )
@@ -135,13 +135,13 @@ def _validate_gen_args(
135
135
  ):
136
136
  if (
137
137
  isinstance(param, ClassicalParameterDeclaration)
138
- and param.classical_type.is_purely_generative
138
+ and not param.classical_type.is_purely_declarative
139
139
  and _is_symbolic(arg.value)
140
140
  ):
141
+ readable_expr = transform_expression(str(arg.value), {}, {}, one_line=True)
141
142
  raise ClassiqExpansionError(
142
- f"Parameter {param.name!r} is used in a compile-time expression "
143
- f"context but is passed a runtime expression "
144
- f"{transform_expression(str(arg.value), {}, {}, one_line=True)!r}"
143
+ f"Cannot pass symbolic expression {readable_expr!r} as Python-type "
144
+ f"parameter {param.name!r}"
145
145
  )
146
146
 
147
147
 
@@ -209,17 +209,21 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
209
209
  function.name, new_declaration
210
210
  )
211
211
  else:
212
- # FIXME: enable for BE (CLS-2390)
213
- if type(self._interpreter).__name__ == "FrontendGenerativeInterpreter":
214
- _validate_gen_args(function, evaluated_args)
212
+ _validate_gen_args(function, evaluated_args)
215
213
  new_declaration = self._expand_function(
216
214
  evaluated_args, new_declaration, function
217
215
  )
218
216
  new_positional_arg_decls = new_declaration.positional_arg_declarations
219
217
  evaluated_args = [
220
218
  arg
221
- for arg in evaluated_args
222
- if isinstance(arg.value, QuantumVariable) or _is_symbolic(arg.value)
219
+ for param, arg in zip_strict(
220
+ function.positional_arg_declarations, evaluated_args, strict=True
221
+ )
222
+ if isinstance(arg.value, QuantumVariable)
223
+ or (
224
+ isinstance(param, ClassicalParameterDeclaration)
225
+ and param.classical_type.is_purely_declarative
226
+ )
223
227
  ]
224
228
 
225
229
  add_information_from_output_arguments(new_positional_arg_decls, evaluated_args)
@@ -312,7 +316,7 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
312
316
  if isinstance(param, PortDeclaration)
313
317
  or (
314
318
  isinstance(param, ClassicalParameterDeclaration)
315
- and _is_symbolic(arg.value)
319
+ and param.classical_type.is_purely_declarative
316
320
  )
317
321
  ]
318
322
  func_def = self._builder.create_definition(function_context, params)
@@ -350,8 +354,10 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
350
354
  ),
351
355
  defining_function=closure,
352
356
  )
353
- elif _is_symbolic(argument.value):
354
- assert isinstance(parameter, ClassicalParameterDeclaration)
357
+ elif (
358
+ isinstance(parameter, ClassicalParameterDeclaration)
359
+ and parameter.classical_type.is_purely_declarative
360
+ ):
355
361
  inferred_arg = Evaluated(
356
362
  value=parameter.classical_type.get_classical_proxy(param_handle),
357
363
  defining_function=closure,
@@ -426,7 +432,7 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
426
432
  ).unchecked
427
433
  TypeModifierValidation(
428
434
  skip_validation=self._interpreter.skip_type_modifier_validation
429
- ).run(func_def.port_declarations, func_def.body, unchecked)
435
+ ).run(func_def, unchecked)
430
436
 
431
437
  @staticmethod
432
438
  def _should_override_type_modifiers(func_context: FunctionContext) -> bool:
@@ -4,7 +4,7 @@ from classiq.interface.model.variable_declaration_statement import (
4
4
  VariableDeclarationStatement,
5
5
  )
6
6
 
7
- from classiq.model_expansions.evaluators.parameter_types import (
7
+ from classiq.evaluators.parameter_types import (
8
8
  evaluate_type_in_quantum_symbol,
9
9
  )
10
10
  from classiq.model_expansions.quantum_operations.emitter import Emitter
@@ -11,13 +11,13 @@ from classiq.interface.model.native_function_definition import NativeFunctionDef
11
11
  from classiq.interface.model.port_declaration import PortDeclaration
12
12
  from classiq.interface.model.quantum_function_declaration import PositionalArg
13
13
 
14
- from classiq.model_expansions.closure import FunctionClosure, GenerativeFunctionClosure
15
- from classiq.model_expansions.evaluators.classical_expression import (
14
+ from classiq.evaluators.classical_expression import (
16
15
  evaluate_classical_expression,
17
16
  )
18
- from classiq.model_expansions.evaluators.parameter_types import (
17
+ from classiq.evaluators.parameter_types import (
19
18
  evaluate_type_in_quantum_symbol,
20
19
  )
20
+ from classiq.model_expansions.closure import FunctionClosure, GenerativeFunctionClosure
21
21
  from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
22
22
  from classiq.qmod.builtins import BUILTIN_CONSTANTS
23
23
  from classiq.qmod.builtins.enums import BUILTIN_ENUM_DECLARATIONS
@@ -77,7 +77,7 @@ class HandleRenaming:
77
77
  SymbolRenaming = Mapping[HandleBinding, Sequence[HandleRenaming]]
78
78
 
79
79
 
80
- def _rewrite_expression(
80
+ def rewrite_expression(
81
81
  symbol_mapping: SymbolRenaming, expression: Expression
82
82
  ) -> Expression:
83
83
  normalized_expr = ExprNormalizer().visit(ast.parse(expression.expr))
@@ -88,7 +88,8 @@ def _rewrite_expression(
88
88
 
89
89
  handle_names = {
90
90
  part.source_handle: part.target_var_handle
91
- for parts in symbol_mapping.values()
91
+ for source, parts in symbol_mapping.items()
92
+ if source.name in expression.expr
92
93
  for part in parts
93
94
  }
94
95
  new_expr_str = ast.unparse(normalized_expr)
@@ -101,7 +102,8 @@ def _rewrite_expression(
101
102
  for handle in sorted_handles:
102
103
  new_handle = handle.collapse()
103
104
  for handle_to_replace, replacement in handle_names.items():
104
- new_handle = new_handle.replace_prefix(handle_to_replace, replacement)
105
+ if new_handle.name == handle_to_replace.name:
106
+ new_handle = new_handle.replace_prefix(handle_to_replace, replacement)
105
107
  new_expr_str = _replace_full_word(str(handle), str(new_handle), new_expr_str)
106
108
 
107
109
  new_expr = Expression(expr=new_expr_str)
@@ -132,7 +134,7 @@ class _ReplaceSplitVarsExpressions(ModelTransformer):
132
134
  self._symbol_mapping = symbol_mapping
133
135
 
134
136
  def visit_Expression(self, expr: Expression) -> Expression:
135
- return _rewrite_expression(self._symbol_mapping, expr)
137
+ return rewrite_expression(self._symbol_mapping, expr)
136
138
 
137
139
  def visit_QuantumExpressionOperation(
138
140
  self, op: QuantumExpressionOperation
@@ -4,6 +4,7 @@ import itertools
4
4
  import warnings
5
5
  from collections.abc import Collection, Iterator, Sequence
6
6
  from contextlib import contextmanager
7
+ from typing import Optional, Union
7
8
 
8
9
  from classiq.interface.exceptions import (
9
10
  ClassiqDeprecationWarning,
@@ -18,6 +19,7 @@ from classiq.interface.model.bind_operation import BindOperation
18
19
  from classiq.interface.model.control import Control
19
20
  from classiq.interface.model.invert import Invert
20
21
  from classiq.interface.model.model_visitor import ModelVisitor
22
+ from classiq.interface.model.native_function_definition import NativeFunctionDefinition
21
23
  from classiq.interface.model.phase_operation import PhaseOperation
22
24
  from classiq.interface.model.port_declaration import PortDeclaration
23
25
  from classiq.interface.model.power import Power
@@ -31,34 +33,43 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
31
33
  QuantumExpressionOperation,
32
34
  )
33
35
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
34
- from classiq.interface.model.quantum_statement import QuantumStatement
35
36
  from classiq.interface.model.within_apply_operation import WithinApply
37
+ from classiq.interface.source_reference import SourceReference
36
38
 
37
39
  from classiq.model_expansions.visitors.variable_references import VarRefCollector
38
40
 
39
41
 
40
42
  def _inconsistent_type_modifier_error(
41
- port_name: str, expected: TypeModifier, actual: TypeModifier
43
+ port_name: str,
44
+ expected: TypeModifier,
45
+ actual: TypeModifier,
46
+ source_ref: Optional[Union[SourceReference, str]] = None,
42
47
  ) -> str:
48
+ source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
43
49
  return (
44
- f"The type modifier of variable '{port_name}' does not conform to the function signature: "
50
+ f"The use of variable '{port_name}' does not conform to its declared modifier: "
45
51
  f"expected '{expected.name}', but found '{actual.name}'.\n"
46
- f"Tip: If the final role of the variable in the function matches '{expected.name}', "
47
- f"you may use the `unchecked` flag to instruct the compiler to disregard individual operations.\n"
48
- # TODO add earliest date of enforcement. See https://classiq.atlassian.net/browse/CLS-2709.
52
+ f"Tip: If the cumulative use of the variable in the function matches '{expected.name}', "
53
+ f"use the `unchecked` flag to instruct the compiler to disregard individual operations."
54
+ f"{source_ref_str}\n"
55
+ "The deprecation warning will be elevated to an error starting July 23, 2025, at the earliest."
49
56
  )
50
57
 
51
58
 
52
59
  def _inconsistent_type_modifier_in_binding_error(
53
- expected: TypeModifier, known_modifiers: dict[str, TypeModifier]
60
+ expected: TypeModifier,
61
+ known_modifiers: dict[str, TypeModifier],
62
+ source_ref: Optional[Union[SourceReference, str]] = None,
54
63
  ) -> str:
55
64
  actual = ", ".join(
56
65
  f"{name}: {modifier.name}" for name, modifier in known_modifiers.items()
57
66
  )
67
+ source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
58
68
  return (
59
- f"The variable binding has inconsistent type modifiers: "
69
+ f"Inconsistent modifiers in variable binding: "
60
70
  f"Expected modifier: {expected.name}, Actual modifiers: {actual}"
61
- # TODO add earliest date of enforcement. See https://classiq.atlassian.net/browse/CLS-2709.
71
+ f"{source_ref_str}\n"
72
+ "The deprecation warning will be elevated to an error starting July 23, 2025, at the earliest."
62
73
  )
63
74
 
64
75
 
@@ -85,6 +96,7 @@ class TypeModifierValidation(ModelVisitor):
85
96
  support_unused_ports # could be turned off for debugging
86
97
  )
87
98
  self._skip_validation = skip_validation
99
+ self._source_ref: Optional[Union[SourceReference, str]] = None
88
100
 
89
101
  @contextmanager
90
102
  def validate_ports(
@@ -119,6 +131,17 @@ class TypeModifierValidation(ModelVisitor):
119
131
  finally:
120
132
  self._conjugation_context = previous_context
121
133
 
134
+ @contextmanager
135
+ def source_reference_context(
136
+ self, source_ref: Optional[Union[SourceReference, str]]
137
+ ) -> Iterator[None]:
138
+ previous_source_ref = self._source_ref
139
+ self._source_ref = source_ref
140
+ try:
141
+ yield
142
+ finally:
143
+ self._source_ref = previous_source_ref
144
+
122
145
  def _set_unused_as_const(self) -> None:
123
146
  unresolved_ports = [
124
147
  port
@@ -161,7 +184,7 @@ class TypeModifierValidation(ModelVisitor):
161
184
  if signature_modifier is not TypeModifier.and_(signature_modifier, modifier):
162
185
  warnings.warn(
163
186
  _inconsistent_type_modifier_error(
164
- candidate, signature_modifier, modifier
187
+ candidate, signature_modifier, modifier, self._source_ref
165
188
  ),
166
189
  ClassiqDeprecationWarning,
167
190
  stacklevel=1,
@@ -176,13 +199,17 @@ class TypeModifierValidation(ModelVisitor):
176
199
 
177
200
  def run(
178
201
  self,
179
- ports: Collection[PortDeclaration],
180
- body: Sequence[QuantumStatement],
202
+ func_def: NativeFunctionDefinition,
181
203
  unchecked: Collection[str],
182
204
  ) -> None:
183
- with self.validate_ports(ports, unchecked) as should_validate:
205
+ with (
206
+ self.validate_ports(
207
+ func_def.port_declarations, unchecked
208
+ ) as should_validate,
209
+ self.source_reference_context(f"function '{func_def.name}'"),
210
+ ):
184
211
  if should_validate:
185
- self.visit(body)
212
+ self.visit(func_def.body)
186
213
  self._update_bound_vars()
187
214
 
188
215
  def _update_bound_vars(self) -> None:
@@ -193,16 +220,18 @@ class TypeModifierValidation(ModelVisitor):
193
220
  self._validate_modifier(var, reduced_modifier)
194
221
 
195
222
  def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
196
- for handle, port in call.handles_with_params:
197
- self._validate_modifier(handle.name, port.type_modifier)
198
- if port.direction is PortDeclarationDirection.Output:
199
- self._add_initialized_modifier(handle.name, port.type_modifier)
223
+ with self.source_reference_context(call.source_ref):
224
+ for handle, port in call.handles_with_params:
225
+ self._validate_modifier(handle.name, port.type_modifier)
226
+ if port.direction is PortDeclarationDirection.Output:
227
+ self._add_initialized_modifier(handle.name, port.type_modifier)
200
228
 
201
229
  if self._has_inputs(call):
202
230
  bound_vars = {
203
231
  handle.name
204
232
  for handle, port in call.handles_with_params
205
233
  if port.direction is not PortDeclarationDirection.Inout
234
+ and handle.name not in self._unchecked
206
235
  }
207
236
  self._bound_vars.append(bound_vars)
208
237
 
@@ -214,13 +243,15 @@ class TypeModifierValidation(ModelVisitor):
214
243
  )
215
244
 
216
245
  def visit_Allocate(self, alloc: Allocate) -> None:
217
- self._validate_modifier(alloc.target.name, TypeModifier.Permutable)
218
- self._add_initialized_modifier(alloc.target.name, TypeModifier.Permutable)
246
+ with self.source_reference_context(alloc.source_ref):
247
+ self._validate_modifier(alloc.target.name, TypeModifier.Permutable)
248
+ self._add_initialized_modifier(alloc.target.name, TypeModifier.Permutable)
219
249
 
220
250
  def visit_BindOperation(self, bind_op: BindOperation) -> None:
221
251
  var_names = {
222
252
  handle.name
223
253
  for handle in itertools.chain(bind_op.in_handles, bind_op.out_handles)
254
+ if handle.name not in self._unchecked
224
255
  }
225
256
  self._bound_vars.append(var_names)
226
257
  for handle in bind_op.out_handles:
@@ -251,7 +282,7 @@ class TypeModifierValidation(ModelVisitor):
251
282
  ):
252
283
  warnings.warn(
253
284
  _inconsistent_type_modifier_in_binding_error(
254
- min_modifier, known_modifiers
285
+ min_modifier, known_modifiers, self._source_ref
255
286
  ),
256
287
  ClassiqDeprecationWarning,
257
288
  stacklevel=1,
@@ -277,42 +308,49 @@ class TypeModifierValidation(ModelVisitor):
277
308
  return [handle.name for handle in vrc.var_handles]
278
309
 
279
310
  def visit_ArithmeticOperation(self, arith: ArithmeticOperation) -> None:
280
- result_var = arith.result_var.name
281
- self._validate_modifier(result_var, TypeModifier.Permutable)
282
- for expr_var in self._extract_expr_vars(arith):
283
- self._validate_modifier(expr_var, TypeModifier.Const)
284
- if not arith.is_inplace:
285
- self._add_initialized_modifier(result_var, TypeModifier.Permutable)
311
+ with self.source_reference_context(arith.source_ref):
312
+ result_var = arith.result_var.name
313
+ self._validate_modifier(result_var, TypeModifier.Permutable)
314
+ for expr_var in self._extract_expr_vars(arith):
315
+ self._validate_modifier(expr_var, TypeModifier.Const)
316
+ if not arith.is_inplace:
317
+ self._add_initialized_modifier(result_var, TypeModifier.Permutable)
286
318
 
287
319
  def visit_AmplitudeLoadingOperation(
288
320
  self, amp_load: AmplitudeLoadingOperation
289
321
  ) -> None:
290
- result_var = amp_load.result_var.name
291
- self._validate_modifier(result_var, TypeModifier.Mutable)
292
- for expr_var in self._extract_expr_vars(amp_load):
293
- self._validate_modifier(expr_var, TypeModifier.Const)
322
+ with self.source_reference_context(amp_load.source_ref):
323
+ result_var = amp_load.result_var.name
324
+ self._validate_modifier(result_var, TypeModifier.Mutable)
325
+ for expr_var in self._extract_expr_vars(amp_load):
326
+ self._validate_modifier(expr_var, TypeModifier.Const)
294
327
 
295
328
  def visit_PhaseOperation(self, phase_op: PhaseOperation) -> None:
296
- for expr_var in self._extract_expr_vars(phase_op):
297
- self._validate_modifier(expr_var, TypeModifier.Const)
329
+ with self.source_reference_context(phase_op.source_ref):
330
+ for expr_var in self._extract_expr_vars(phase_op):
331
+ self._validate_modifier(expr_var, TypeModifier.Const)
298
332
 
299
333
  def visit_Control(self, control: Control) -> None:
300
- for control_var in self._extract_expr_vars(control):
301
- self._validate_modifier(control_var, TypeModifier.Const)
302
- self.visit(control.body)
303
- if control.else_block is not None:
304
- self.visit(control.else_block)
334
+ with self.source_reference_context(control.source_ref):
335
+ for control_var in self._extract_expr_vars(control):
336
+ self._validate_modifier(control_var, TypeModifier.Const)
337
+ self.visit(control.body)
338
+ if control.else_block is not None:
339
+ self.visit(control.else_block)
305
340
 
306
341
  def visit_Invert(self, invert: Invert) -> None:
307
- self.visit(invert.body)
342
+ with self.source_reference_context(invert.source_ref):
343
+ self.visit(invert.body)
308
344
 
309
345
  def visit_Power(self, power: Power) -> None:
310
- self.visit(power.body)
346
+ with self.source_reference_context(power.source_ref):
347
+ self.visit(power.body)
311
348
 
312
349
  def visit_WithinApply(self, within_apply: WithinApply) -> None:
313
- with self.conjugation_context():
314
- self.visit(within_apply.compute)
315
- self.visit(within_apply.action)
350
+ with self.source_reference_context(within_apply.source_ref):
351
+ with self.conjugation_context():
352
+ self.visit(within_apply.compute)
353
+ self.visit(within_apply.action)
316
354
 
317
355
 
318
356
  def _merge_overlapping(bound_vars: Sequence[Collection[str]]) -> list[set[str]]:
@@ -10,7 +10,6 @@ from classiq.interface.generator.expressions.atomic_expression_functions import
10
10
  from classiq.interface.generator.expressions.expression import Expression
11
11
  from classiq.interface.generator.functions.classical_type import (
12
12
  ClassicalArray,
13
- ClassicalList,
14
13
  ClassicalTuple,
15
14
  ClassicalType,
16
15
  )
@@ -53,7 +52,7 @@ def set_generative_recursively(classical_type: ClassicalType) -> None:
53
52
  set_generative_recursively(field_type)
54
53
  return
55
54
  classical_type.set_generative()
56
- if isinstance(classical_type, (ClassicalArray, ClassicalList)):
55
+ if isinstance(classical_type, ClassicalArray):
57
56
  set_generative_recursively(classical_type.element_type)
58
57
  if isinstance(classical_type, ClassicalTuple):
59
58
  for element_type in classical_type.element_types:
@@ -155,7 +154,7 @@ class SymbolicParamInference(ModelVisitor):
155
154
  for param, arg in zip_longest(params, call.positional_args):
156
155
  if (
157
156
  not isinstance(param, AnonClassicalParameterDeclaration)
158
- or param.classical_type.is_purely_generative
157
+ or not param.classical_type.is_purely_declarative
159
158
  ):
160
159
  self._process_compile_time_expressions(arg)
161
160
  else:
@@ -6,6 +6,7 @@ from .amplitude_estimation import *
6
6
  from .discrete_sine_cosine_transform import *
7
7
  from .discrete_sine_cosine_transform import _qct_d_operator, _qct_pi_operator
8
8
  from .grover import *
9
+ from .grover import _cond_phase_flip
9
10
  from .hea import *
10
11
  from .linear_pauli_rotation import *
11
12
  from .linear_pauli_rotation import _single_pauli
@@ -79,6 +80,7 @@ OPEN_LIBRARY_FUNCTIONS = [
79
80
  _check_msb,
80
81
  encode_in_angle,
81
82
  encode_on_bloch,
83
+ _cond_phase_flip,
82
84
  ]
83
85
 
84
86
  __all__ = [
@@ -105,6 +107,7 @@ __all__ = [
105
107
  "modular_increment",
106
108
  "multiswap",
107
109
  "phase_oracle",
110
+ "prepare_basis_state",
108
111
  "prepare_bell_state",
109
112
  "prepare_complex_amplitudes",
110
113
  "prepare_dicke_state",
@@ -1,11 +1,10 @@
1
1
  from classiq.open_library.functions.grover import grover_operator
2
+ from classiq.qmod.builtins.functions.allocation import free
2
3
  from classiq.qmod.builtins.functions.standard_gates import RY
3
4
  from classiq.qmod.builtins.operations import (
4
5
  allocate,
5
- bind,
6
6
  control,
7
7
  power,
8
- within_apply,
9
8
  )
10
9
  from classiq.qmod.cparam import CInt, CReal
11
10
  from classiq.qmod.qfunc import qfunc
@@ -71,21 +70,14 @@ def exact_amplitude_amplification(
71
70
  theta = pi / (4 * k + 2)
72
71
  rot_phase = 2 * acos(sin(theta) / amplitude)
73
72
 
74
- extended_qvars: QArray = QArray()
75
- within_apply(
76
- lambda: [
77
- allocate(aux),
78
- bind([aux, packed_qvars], extended_qvars),
73
+ allocate(aux)
74
+ amplitude_amplification(
75
+ k,
76
+ lambda qvars_: control(qvars_[0] == 0, lambda: oracle(qvars_[1 : qvars_.size])),
77
+ lambda qvars_: [
78
+ space_transform(qvars_[1 : qvars_.size]),
79
+ RY(rot_phase, qvars_[0]),
79
80
  ],
80
- lambda: amplitude_amplification(
81
- k,
82
- lambda qvars_: control(
83
- qvars_[0] == 0, lambda: oracle(qvars_[1 : qvars_.size])
84
- ),
85
- lambda qvars_: [
86
- space_transform(qvars_[1 : qvars_.size]),
87
- RY(rot_phase, qvars_[0]),
88
- ],
89
- extended_qvars,
90
- ),
81
+ [aux, packed_qvars],
91
82
  )
83
+ free(aux)
@@ -11,7 +11,7 @@ from classiq.qmod.builtins.operations import (
11
11
  within_apply,
12
12
  )
13
13
  from classiq.qmod.qfunc import qfunc
14
- from classiq.qmod.qmod_variable import QArray, QBit, QNum
14
+ from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit, QNum
15
15
  from classiq.qmod.symbolic import pi
16
16
 
17
17
 
@@ -21,13 +21,13 @@ def _b_operator(q: QBit) -> None:
21
21
 
22
22
 
23
23
  @qfunc
24
- def _qct_d_operator(x: QNum, q: QBit) -> None:
24
+ def _qct_d_operator(x: Const[QNum], q: QBit) -> None:
25
25
  _b_operator(q)
26
26
  control(x == 0, lambda: invert(lambda: _b_operator(q)))
27
27
 
28
28
 
29
29
  @qfunc
30
- def _qct_pi_operator(x: QArray[QBit], q: QBit) -> None:
30
+ def _qct_pi_operator(x: Permutable[QArray[QBit]], q: Const[QBit]) -> None:
31
31
  control(
32
32
  q == 1,
33
33
  lambda: [
@@ -120,8 +120,8 @@ def qct_qst_type1(x: QArray[QBit]) -> None:
120
120
  within_apply(lambda: _t_operator(x), lambda: qft(x))
121
121
 
122
122
 
123
- @qfunc
124
- def qct_qst_type2(x: QArray[QBit], q: QBit) -> None:
123
+ @qfunc(unchecked=["q"])
124
+ def qct_qst_type2(x: QArray[QBit], q: Const[QBit]) -> None:
125
125
  """
126
126
  [Qmod Classiq-library function]
127
127
 
@@ -10,14 +10,22 @@ from classiq.qmod.builtins.operations import (
10
10
  )
11
11
  from classiq.qmod.qfunc import qfunc
12
12
  from classiq.qmod.qmod_parameter import CInt
13
- from classiq.qmod.qmod_variable import QArray, QBit, QNum
13
+ from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit, QNum
14
14
  from classiq.qmod.quantum_callable import QCallable
15
15
  from classiq.qmod.symbolic import pi
16
16
 
17
17
 
18
+ @qfunc(unchecked=["target"])
19
+ def _cond_phase_flip(
20
+ predicate: QCallable[Permutable[QBit]], target: Const[QBit]
21
+ ) -> None:
22
+ within_apply(lambda: H(target), lambda: predicate(target))
23
+
24
+
18
25
  @qfunc
19
26
  def phase_oracle(
20
- predicate: QCallable[QArray[QBit], QBit], target: QArray[QBit]
27
+ predicate: QCallable[Const[QArray[QBit]], Permutable[QBit]],
28
+ target: Const[QArray[QBit]],
21
29
  ) -> None:
22
30
  """
23
31
  [Qmod Classiq-library function]
@@ -42,13 +50,13 @@ def phase_oracle(
42
50
  """
43
51
  aux = QBit()
44
52
  within_apply(
45
- within=lambda: (allocate(aux), X(aux), H(aux)),
46
- apply=lambda: predicate(target, aux),
53
+ lambda: [allocate(aux), X(aux)],
54
+ lambda: _cond_phase_flip(lambda x: predicate(target, x), aux),
47
55
  )
48
56
 
49
57
 
50
- @qfunc
51
- def reflect_about_zero(packed_vars: QArray[QBit]) -> None:
58
+ @qfunc(unchecked=["packed_vars"])
59
+ def reflect_about_zero(packed_vars: Const[QArray[QBit]]) -> None:
52
60
  """
53
61
  [Qmod Classiq-library function]
54
62