classiq 0.83.0__py3-none-any.whl → 0.85.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 (103) 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/applications/combinatorial_optimization/combinatorial_problem.py +20 -42
  11. classiq/{model_expansions/evaluators → evaluators}/arg_type_match.py +12 -4
  12. classiq/{model_expansions/evaluators → evaluators}/argument_types.py +1 -1
  13. classiq/evaluators/classical_expression.py +53 -0
  14. classiq/{model_expansions/evaluators → evaluators}/classical_type_inference.py +3 -4
  15. classiq/{model_expansions/evaluators → evaluators}/parameter_types.py +17 -15
  16. classiq/execution/__init__.py +12 -1
  17. classiq/execution/execution_session.py +238 -49
  18. classiq/execution/jobs.py +26 -1
  19. classiq/execution/qnn.py +2 -2
  20. classiq/execution/user_budgets.py +39 -0
  21. classiq/interface/_version.py +1 -1
  22. classiq/interface/constants.py +1 -0
  23. classiq/interface/debug_info/debug_info.py +0 -4
  24. classiq/interface/execution/primitives.py +29 -1
  25. classiq/interface/executor/estimate_cost.py +35 -0
  26. classiq/interface/executor/execution_result.py +13 -0
  27. classiq/interface/executor/result.py +116 -1
  28. classiq/interface/executor/user_budget.py +26 -33
  29. classiq/interface/generator/expressions/atomic_expression_functions.py +10 -1
  30. classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -6
  31. classiq/interface/generator/functions/builtins/internal_operators.py +2 -0
  32. classiq/interface/generator/functions/classical_type.py +2 -35
  33. classiq/interface/generator/functions/concrete_types.py +20 -3
  34. classiq/interface/generator/functions/type_modifier.py +0 -19
  35. classiq/interface/generator/generated_circuit_data.py +5 -18
  36. classiq/interface/generator/types/compilation_metadata.py +0 -3
  37. classiq/interface/ide/operation_registry.py +45 -0
  38. classiq/interface/ide/visual_model.py +68 -3
  39. classiq/interface/model/bounds.py +12 -2
  40. classiq/interface/model/model.py +12 -7
  41. classiq/interface/model/port_declaration.py +2 -24
  42. classiq/interface/model/quantum_expressions/arithmetic_operation.py +7 -4
  43. classiq/interface/model/variable_declaration_statement.py +33 -6
  44. classiq/interface/pretty_print/__init__.py +0 -0
  45. classiq/{qmod/native → interface/pretty_print}/expression_to_qmod.py +18 -11
  46. classiq/interface/server/routes.py +4 -0
  47. classiq/model_expansions/atomic_expression_functions_defs.py +47 -6
  48. classiq/model_expansions/function_builder.py +4 -1
  49. classiq/model_expansions/interpreters/base_interpreter.py +3 -3
  50. classiq/model_expansions/interpreters/generative_interpreter.py +16 -1
  51. classiq/model_expansions/quantum_operations/allocate.py +1 -1
  52. classiq/model_expansions/quantum_operations/assignment_result_processor.py +64 -22
  53. classiq/model_expansions/quantum_operations/bind.py +2 -2
  54. classiq/model_expansions/quantum_operations/bounds.py +7 -1
  55. classiq/model_expansions/quantum_operations/call_emitter.py +26 -20
  56. classiq/model_expansions/quantum_operations/classical_var_emitter.py +16 -0
  57. classiq/model_expansions/quantum_operations/variable_decleration.py +31 -11
  58. classiq/model_expansions/scope.py +7 -0
  59. classiq/model_expansions/scope_initialization.py +3 -3
  60. classiq/model_expansions/transformers/model_renamer.py +6 -4
  61. classiq/model_expansions/transformers/type_modifier_inference.py +81 -43
  62. classiq/model_expansions/transformers/var_splitter.py +1 -1
  63. classiq/model_expansions/visitors/symbolic_param_inference.py +2 -3
  64. classiq/open_library/functions/__init__.py +3 -2
  65. classiq/open_library/functions/amplitude_amplification.py +10 -18
  66. classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
  67. classiq/open_library/functions/grover.py +14 -6
  68. classiq/open_library/functions/modular_exponentiation.py +22 -20
  69. classiq/open_library/functions/qaoa_penalty.py +8 -1
  70. classiq/open_library/functions/state_preparation.py +18 -32
  71. classiq/qmod/__init__.py +2 -0
  72. classiq/qmod/builtins/enums.py +23 -0
  73. classiq/qmod/builtins/functions/__init__.py +2 -0
  74. classiq/qmod/builtins/functions/exponentiation.py +32 -4
  75. classiq/qmod/builtins/operations.py +65 -1
  76. classiq/qmod/builtins/structs.py +55 -3
  77. classiq/qmod/classical_variable.py +74 -0
  78. classiq/qmod/declaration_inferrer.py +3 -2
  79. classiq/qmod/native/pretty_printer.py +20 -20
  80. classiq/qmod/pretty_print/expression_to_python.py +2 -1
  81. classiq/qmod/pretty_print/pretty_printer.py +35 -21
  82. classiq/qmod/python_classical_type.py +12 -5
  83. classiq/qmod/qfunc.py +2 -19
  84. classiq/qmod/qmod_constant.py +2 -5
  85. classiq/qmod/qmod_parameter.py +2 -5
  86. classiq/qmod/qmod_variable.py +61 -23
  87. classiq/qmod/quantum_expandable.py +5 -3
  88. classiq/qmod/quantum_function.py +49 -4
  89. classiq/qmod/semantics/annotation/qstruct_annotator.py +1 -1
  90. classiq/qmod/semantics/validation/main_validation.py +1 -9
  91. classiq/qmod/symbolic_type.py +2 -1
  92. classiq/qmod/utilities.py +0 -2
  93. classiq/qmod/write_qmod.py +1 -1
  94. {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/METADATA +4 -1
  95. {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/RECORD +101 -90
  96. classiq/interface/model/quantum_variable_declaration.py +0 -7
  97. classiq/model_expansions/evaluators/classical_expression.py +0 -36
  98. /classiq/{model_expansions/evaluators → evaluators}/__init__.py +0 -0
  99. /classiq/{model_expansions/evaluators → evaluators}/control.py +0 -0
  100. /classiq/{model_expansions → evaluators}/expression_evaluator.py +0 -0
  101. /classiq/{model_expansions/evaluators → evaluators}/quantum_type_utils.py +0 -0
  102. /classiq/{model_expansions/evaluators → evaluators}/type_type_match.py +0 -0
  103. {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/WHEEL +0 -0
@@ -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]]:
@@ -218,7 +218,7 @@ class VarSplitter(ModelRenamer):
218
218
  return [
219
219
  VariableDeclarationStatement(
220
220
  name=part.target_var_name,
221
- quantum_type=part.target_var_type,
221
+ qmod_type=part.target_var_type,
222
222
  )
223
223
  for part in chain.from_iterable(symbol_parts.values())
224
224
  ]
@@ -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
@@ -51,7 +52,6 @@ OPEN_LIBRARY_FUNCTIONS = [
51
52
  qsvt_inversion,
52
53
  qsvt_lcu,
53
54
  qsvt_lcu_step,
54
- allocate_num,
55
55
  qaoa_mixer_layer,
56
56
  qaoa_cost_layer,
57
57
  qaoa_layer,
@@ -79,11 +79,11 @@ OPEN_LIBRARY_FUNCTIONS = [
79
79
  _check_msb,
80
80
  encode_in_angle,
81
81
  encode_on_bloch,
82
+ _cond_phase_flip,
82
83
  ]
83
84
 
84
85
  __all__ = [
85
86
  "_single_pauli",
86
- "allocate_num",
87
87
  "amplitude_amplification",
88
88
  "amplitude_estimation",
89
89
  "apply_to_all",
@@ -105,6 +105,7 @@ __all__ = [
105
105
  "modular_increment",
106
106
  "multiswap",
107
107
  "phase_oracle",
108
+ "prepare_basis_state",
108
109
  "prepare_bell_state",
109
110
  "prepare_complex_amplitudes",
110
111
  "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
 
@@ -1,5 +1,6 @@
1
1
  from classiq.open_library.functions.qft_functions import qft, qft_no_swap
2
2
  from classiq.qmod.builtins.classical_functions import qft_const_adder_phase
3
+ from classiq.qmod.builtins.functions.allocation import free
3
4
  from classiq.qmod.builtins.functions.standard_gates import PHASE, SWAP, X
4
5
  from classiq.qmod.builtins.operations import (
5
6
  allocate,
@@ -11,7 +12,7 @@ from classiq.qmod.builtins.operations import (
11
12
  )
12
13
  from classiq.qmod.cparam import CInt
13
14
  from classiq.qmod.qfunc import qfunc
14
- from classiq.qmod.qmod_variable import QArray, QBit
15
+ from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit
15
16
  from classiq.qmod.symbolic import min, mod_inverse
16
17
 
17
18
 
@@ -50,8 +51,10 @@ def qft_space_add_const(value: CInt, phi_b: QArray[QBit]) -> None:
50
51
  )
51
52
 
52
53
 
53
- @qfunc
54
- def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) -> None:
54
+ @qfunc(unchecked=["phi_b"])
55
+ def cc_modular_add(
56
+ n: CInt, a: CInt, phi_b: Permutable[QArray[QBit]], c1: Const[QBit], c2: Const[QBit]
57
+ ) -> None:
55
58
  """
56
59
  [Qmod Classiq-library function]
57
60
 
@@ -69,11 +72,9 @@ def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) ->
69
72
  ctrl: QArray[QBit] = QArray()
70
73
  aux = QBit()
71
74
 
75
+ allocate(aux)
72
76
  within_apply(
73
- lambda: (
74
- allocate(aux),
75
- bind([c1, c2], ctrl),
76
- ),
77
+ lambda: bind([c1, c2], ctrl),
77
78
  lambda: (
78
79
  control(ctrl, lambda: qft_space_add_const(a, phi_b)),
79
80
  invert(lambda: qft_space_add_const(n, phi_b)),
@@ -87,11 +88,16 @@ def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) ->
87
88
  ),
88
89
  ),
89
90
  )
91
+ free(aux)
90
92
 
91
93
 
92
- @qfunc
94
+ @qfunc(unchecked=["b"])
93
95
  def c_modular_multiply(
94
- n: CInt, a: CInt, b: QArray[QBit], x: QArray[QBit], ctrl: QBit
96
+ n: CInt,
97
+ a: CInt,
98
+ b: Permutable[QArray[QBit]],
99
+ x: Const[QArray[QBit]],
100
+ ctrl: Const[QBit],
95
101
  ) -> None:
96
102
  """
97
103
  [Qmod Classiq-library function]
@@ -118,7 +124,7 @@ def c_modular_multiply(
118
124
 
119
125
 
120
126
  @qfunc
121
- def multiswap(x: QArray[QBit], y: QArray[QBit]) -> None:
127
+ def multiswap(x: Permutable[QArray[QBit]], y: Permutable[QArray[QBit]]) -> None:
122
128
  """
123
129
  [Qmod Classiq-library function]
124
130
 
@@ -150,16 +156,12 @@ def inplace_c_modular_multiply(n: CInt, a: CInt, x: QArray[QBit], ctrl: QBit) ->
150
156
  x: The quantum factor.
151
157
  ctrl: The control bit.
152
158
  """
153
- b: QArray[QBit] = QArray()
154
-
155
- within_apply(
156
- lambda: allocate(x.len + 1, b),
157
- lambda: (
158
- c_modular_multiply(n, a, b, x, ctrl),
159
- control(ctrl, lambda: multiswap(x, b)),
160
- invert(lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl)),
161
- ),
162
- )
159
+ b: QArray[QBit] = QArray(length=x.len + 1)
160
+ allocate(b)
161
+ c_modular_multiply(n, a, b, x, ctrl)
162
+ control(ctrl, lambda: multiswap(x, b))
163
+ invert(lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl))
164
+ free(b)
163
165
 
164
166
 
165
167
  @qfunc
@@ -1,5 +1,8 @@
1
+ import warnings
1
2
  from typing import Literal
2
3
 
4
+ from classiq.interface.exceptions import ClassiqDeprecationWarning
5
+
3
6
  from classiq.qmod.builtins.functions import RX, H, suzuki_trotter
4
7
  from classiq.qmod.builtins.operations import repeat
5
8
  from classiq.qmod.builtins.structs import PauliTerm
@@ -42,7 +45,11 @@ def qaoa_cost_layer(
42
45
  hamiltonian: The Hamiltonian terms for the QAOA model.
43
46
  target: The target quantum array variable.
44
47
  """
45
- suzuki_trotter(hamiltonian, g, 1, 1, target)
48
+ with warnings.catch_warnings(): # FIXME: Remove (CLS-2912)
49
+ warnings.simplefilter(
50
+ "ignore", category=ClassiqDeprecationWarning
51
+ ) # FIXME: Remove (CLS-2912)
52
+ suzuki_trotter(hamiltonian, g, 1, 1, target)
46
53
 
47
54
 
48
55
  @qfunc
@@ -27,7 +27,7 @@ from classiq.qmod.builtins.operations import (
27
27
  repeat,
28
28
  within_apply,
29
29
  )
30
- from classiq.qmod.cparam import CArray, CBool, CInt, CReal
30
+ from classiq.qmod.cparam import CArray, CInt, CReal
31
31
  from classiq.qmod.qfunc import qfunc
32
32
  from classiq.qmod.qmod_variable import Output, QArray, QBit, QNum
33
33
  from classiq.qmod.symbolic import (
@@ -45,37 +45,6 @@ from classiq.qmod.symbolic import (
45
45
  )
46
46
 
47
47
 
48
- @qfunc
49
- def allocate_num(
50
- num_qubits: CInt,
51
- is_signed: CBool,
52
- fraction_digits: CInt,
53
- out: Output[
54
- QNum[Literal["num_qubits"], Literal["is_signed"], Literal["fraction_digits"]]
55
- ],
56
- ) -> None:
57
- """
58
- [Qmod Classiq-library function]
59
-
60
- This function is **deprecated** and will no longer be supported starting on
61
- 16/06/2025 at the earliest. Instead, use `allocate` which supports the same
62
- parameters.
63
-
64
- Initializes a quantum number with the given number of qubits, sign, and fractional digits.
65
-
66
- Args:
67
- num_qubits: The number of qubits to allocate.
68
- is_signed: Whether the number is signed or unsigned.
69
- fraction_digits: The number of fractional digits.
70
- """
71
- warnings.warn(
72
- "Function `allocate_num` is deprecated and will no longer be supported starting on 16/06/2025 at the earliest. Instead, use `allocate` which supports the same parameters. ",
73
- ClassiqDeprecationWarning,
74
- stacklevel=1,
75
- )
76
- allocate(num_qubits, out)
77
-
78
-
79
48
  def _prepare_uniform_trimmed_state_apply_rotation(
80
49
  size_lsb: CInt, lsbs_val: CInt, rotation_var: QBit
81
50
  ) -> None:
@@ -483,3 +452,20 @@ def prepare_dicke_state(k: int, qvar: QArray[QBit]) -> None:
483
452
  if k > 0:
484
453
  apply_to_all(X, qvar[0:k])
485
454
  prepare_dicke_state_unary_input(k, qvar)
455
+
456
+
457
+ @qfunc
458
+ def prepare_basis_state(state: list[bool], arr: Output[QArray]) -> None:
459
+ """
460
+ [Qmod Classiq-library function]
461
+
462
+ Initializes a quantum array in the specified basis state.
463
+
464
+ Args:
465
+ values: The desired basis state, given as a list of boolean values for each qubit.
466
+ arr: The quantum array to prepare.
467
+ """
468
+ allocate(len(state), arr)
469
+ for idx, value in enumerate(state):
470
+ if value:
471
+ X(arr[idx])
classiq/qmod/__init__.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from .builtins import * # noqa: F403
2
2
  from .builtins import __all__ as _builtins_all
3
3
  from .cfunc import cfunc
4
+ from .classical_variable import measure
4
5
  from .create_model_function import create_model
5
6
  from .expression_query import get_expression_numeric_attributes
6
7
  from .qfunc import qfunc
@@ -29,6 +30,7 @@ __all__ = [
29
30
  "QStruct",
30
31
  "cfunc",
31
32
  "create_model",
33
+ "measure",
32
34
  "get_expression_numeric_attributes",
33
35
  "qfunc",
34
36
  "write_qmod",