classiq 0.93.0__py3-none-any.whl → 0.100.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 (318) hide show
  1. classiq/__init__.py +11 -19
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +7 -7
  3. classiq/_analyzer_extras/interactive_hardware.py +19 -12
  4. classiq/_internals/api_wrapper.py +31 -142
  5. classiq/_internals/async_utils.py +4 -7
  6. classiq/_internals/authentication/auth0.py +41 -15
  7. classiq/_internals/authentication/authorization_code.py +9 -0
  8. classiq/_internals/authentication/authorization_flow.py +41 -0
  9. classiq/_internals/authentication/device.py +33 -52
  10. classiq/_internals/authentication/hybrid_flow.py +19 -0
  11. classiq/_internals/authentication/password_manager.py +13 -13
  12. classiq/_internals/authentication/token_manager.py +9 -9
  13. classiq/_internals/client.py +17 -44
  14. classiq/_internals/config.py +19 -5
  15. classiq/_internals/help.py +1 -2
  16. classiq/_internals/host_checker.py +3 -3
  17. classiq/_internals/jobs.py +14 -14
  18. classiq/_internals/type_validation.py +3 -3
  19. classiq/analyzer/analyzer.py +18 -18
  20. classiq/analyzer/rb.py +17 -8
  21. classiq/analyzer/show_interactive_hack.py +1 -1
  22. classiq/applications/__init__.py +2 -2
  23. classiq/applications/chemistry/__init__.py +0 -30
  24. classiq/applications/chemistry/op_utils.py +4 -4
  25. classiq/applications/chemistry/problems.py +3 -3
  26. classiq/applications/chemistry/ucc.py +1 -2
  27. classiq/applications/chemistry/z2_symmetries.py +4 -4
  28. classiq/applications/combinatorial_helpers/allowed_constraints.py +1 -3
  29. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +2 -1
  30. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +2 -2
  31. classiq/applications/combinatorial_helpers/encoding_mapping.py +2 -3
  32. classiq/applications/combinatorial_helpers/encoding_utils.py +2 -2
  33. classiq/applications/combinatorial_helpers/optimization_model.py +3 -4
  34. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +2 -2
  35. classiq/applications/combinatorial_helpers/pyomo_utils.py +8 -8
  36. classiq/applications/combinatorial_helpers/sympy_utils.py +1 -3
  37. classiq/applications/combinatorial_helpers/transformations/encoding.py +3 -3
  38. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +1 -2
  39. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -3
  40. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +4 -6
  41. classiq/applications/combinatorial_optimization/combinatorial_problem.py +15 -10
  42. classiq/applications/hamiltonian/pauli_decomposition.py +6 -4
  43. classiq/applications/iqae/iqae.py +14 -11
  44. classiq/applications/qnn/datasets/dataset_base_classes.py +6 -6
  45. classiq/applications/qnn/datasets/dataset_parity.py +6 -6
  46. classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
  47. classiq/applications/qnn/qlayer.py +9 -8
  48. classiq/applications/qnn/torch_utils.py +5 -6
  49. classiq/applications/qnn/types.py +2 -1
  50. classiq/applications/qsp/__init__.py +20 -2
  51. classiq/applications/qsp/qsp.py +238 -10
  52. classiq/applications/qsvm/qsvm_data_generation.py +1 -2
  53. classiq/evaluators/classical_expression.py +0 -4
  54. classiq/evaluators/parameter_types.py +10 -8
  55. classiq/evaluators/qmod_annotated_expression.py +31 -26
  56. classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +14 -14
  57. classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +2 -1
  58. classiq/evaluators/qmod_expression_visitors/sympy_wrappers.py +8 -8
  59. classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +4 -4
  60. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +14 -4
  61. classiq/evaluators/qmod_node_evaluators/list_evaluation.py +2 -2
  62. classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +3 -3
  63. classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +9 -9
  64. classiq/evaluators/qmod_node_evaluators/utils.py +6 -6
  65. classiq/evaluators/qmod_type_inference/classical_type_inference.py +9 -10
  66. classiq/evaluators/qmod_type_inference/quantum_type_inference.py +5 -5
  67. classiq/execution/__init__.py +0 -3
  68. classiq/execution/execution_session.py +28 -21
  69. classiq/execution/jobs.py +26 -26
  70. classiq/execution/qnn.py +1 -2
  71. classiq/execution/user_budgets.py +71 -37
  72. classiq/executor.py +1 -3
  73. classiq/interface/_version.py +1 -1
  74. classiq/interface/analyzer/analysis_params.py +4 -4
  75. classiq/interface/analyzer/cytoscape_graph.py +3 -3
  76. classiq/interface/analyzer/result.py +4 -4
  77. classiq/interface/ast_node.py +3 -3
  78. classiq/interface/backend/backend_preferences.py +26 -50
  79. classiq/interface/backend/ionq/ionq_quantum_program.py +5 -5
  80. classiq/interface/backend/provider_config/__init__.py +0 -0
  81. classiq/interface/backend/provider_config/provider_config.py +8 -0
  82. classiq/interface/backend/provider_config/providers/__init__.py +0 -0
  83. classiq/interface/backend/provider_config/providers/alice_bob.py +47 -0
  84. classiq/interface/backend/provider_config/providers/aqt.py +16 -0
  85. classiq/interface/backend/provider_config/providers/azure.py +37 -0
  86. classiq/interface/backend/provider_config/providers/braket.py +39 -0
  87. classiq/interface/backend/provider_config/providers/ibm.py +26 -0
  88. classiq/interface/backend/provider_config/providers/ionq.py +22 -0
  89. classiq/interface/backend/quantum_backend_providers.py +20 -2
  90. classiq/interface/chemistry/ansatz_library.py +3 -5
  91. classiq/interface/chemistry/operator.py +3 -3
  92. classiq/interface/combinatorial_optimization/examples/knapsack.py +2 -4
  93. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +1 -2
  94. classiq/interface/compression_utils.py +2 -3
  95. classiq/interface/debug_info/debug_info.py +8 -7
  96. classiq/interface/exceptions.py +6 -7
  97. classiq/interface/execution/primitives.py +6 -6
  98. classiq/interface/executor/estimate_cost.py +1 -1
  99. classiq/interface/executor/execution_preferences.py +3 -5
  100. classiq/interface/executor/execution_request.py +10 -10
  101. classiq/interface/executor/execution_result.py +1 -2
  102. classiq/interface/executor/quantum_code.py +8 -8
  103. classiq/interface/executor/result.py +28 -18
  104. classiq/interface/executor/user_budget.py +21 -17
  105. classiq/interface/executor/vqe_result.py +5 -6
  106. classiq/interface/generator/ansatz_library.py +6 -8
  107. classiq/interface/generator/application_apis/__init__.py +0 -3
  108. classiq/interface/generator/arith/arithmetic.py +2 -2
  109. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +2 -3
  110. classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -5
  111. classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -4
  112. classiq/interface/generator/arith/arithmetic_expression_validator.py +12 -15
  113. classiq/interface/generator/arith/arithmetic_operations.py +4 -6
  114. classiq/interface/generator/arith/arithmetic_param_getters.py +70 -107
  115. classiq/interface/generator/arith/arithmetic_result_builder.py +4 -4
  116. classiq/interface/generator/arith/ast_node_rewrite.py +8 -4
  117. classiq/interface/generator/arith/binary_ops.py +15 -40
  118. classiq/interface/generator/arith/logical_ops.py +2 -3
  119. classiq/interface/generator/arith/number_utils.py +2 -2
  120. classiq/interface/generator/arith/register_user_input.py +3 -3
  121. classiq/interface/generator/arith/unary_ops.py +2 -2
  122. classiq/interface/generator/circuit_code/circuit_code.py +8 -10
  123. classiq/interface/generator/circuit_code/types_and_constants.py +1 -1
  124. classiq/interface/generator/complex_type.py +2 -2
  125. classiq/interface/generator/copy.py +1 -3
  126. classiq/interface/generator/expressions/atomic_expression_functions.py +0 -5
  127. classiq/interface/generator/expressions/evaluated_expression.py +2 -3
  128. classiq/interface/generator/expressions/expression.py +2 -2
  129. classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -7
  130. classiq/interface/generator/function_param_list.py +0 -40
  131. classiq/interface/generator/function_params.py +5 -6
  132. classiq/interface/generator/functions/classical_function_declaration.py +2 -2
  133. classiq/interface/generator/functions/classical_type.py +3 -3
  134. classiq/interface/generator/functions/type_modifier.py +0 -15
  135. classiq/interface/generator/functions/type_name.py +2 -2
  136. classiq/interface/generator/generated_circuit_data.py +14 -18
  137. classiq/interface/generator/generation_request.py +35 -0
  138. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +2 -4
  139. classiq/interface/generator/hardware/hardware_data.py +8 -8
  140. classiq/interface/generator/hardware_efficient_ansatz.py +9 -9
  141. classiq/interface/generator/mcu.py +3 -3
  142. classiq/interface/generator/mcx.py +3 -3
  143. classiq/interface/generator/model/constraints.py +34 -5
  144. classiq/interface/generator/model/preferences/preferences.py +15 -21
  145. classiq/interface/generator/model/quantum_register.py +7 -10
  146. classiq/interface/generator/noise_properties.py +3 -7
  147. classiq/interface/generator/parameters.py +1 -1
  148. classiq/interface/generator/partitioned_register.py +1 -2
  149. classiq/interface/generator/preferences/qasm_to_qmod_params.py +11 -0
  150. classiq/interface/generator/quantum_function_call.py +9 -12
  151. classiq/interface/generator/quantum_program.py +10 -23
  152. classiq/interface/generator/range_types.py +3 -3
  153. classiq/interface/generator/slice_parsing_utils.py +4 -5
  154. classiq/interface/generator/standard_gates/standard_gates.py +2 -4
  155. classiq/interface/generator/synthesis_execution_parameter.py +1 -3
  156. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +9 -0
  157. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +2 -3
  158. classiq/interface/generator/transpiler_basis_gates.py +10 -4
  159. classiq/interface/generator/types/builtin_enum_declarations.py +0 -145
  160. classiq/interface/generator/types/compilation_metadata.py +13 -2
  161. classiq/interface/generator/types/enum_declaration.py +2 -1
  162. classiq/interface/generator/validations/flow_graph.py +3 -3
  163. classiq/interface/generator/visitor.py +10 -12
  164. classiq/interface/hardware.py +2 -3
  165. classiq/interface/helpers/classproperty.py +2 -2
  166. classiq/interface/helpers/custom_encoders.py +2 -1
  167. classiq/interface/helpers/custom_pydantic_types.py +1 -1
  168. classiq/interface/helpers/text_utils.py +5 -4
  169. classiq/interface/ide/visual_model.py +6 -5
  170. classiq/interface/interface_version.py +1 -1
  171. classiq/interface/jobs.py +3 -3
  172. classiq/interface/model/allocate.py +4 -4
  173. classiq/interface/model/bind_operation.py +3 -0
  174. classiq/interface/model/block.py +6 -2
  175. classiq/interface/model/bounds.py +3 -3
  176. classiq/interface/model/classical_if.py +4 -0
  177. classiq/interface/model/control.py +8 -1
  178. classiq/interface/model/inplace_binary_operation.py +2 -2
  179. classiq/interface/model/invert.py +4 -0
  180. classiq/interface/model/model.py +4 -4
  181. classiq/interface/model/model_visitor.py +40 -1
  182. classiq/interface/model/parameter.py +1 -3
  183. classiq/interface/model/port_declaration.py +1 -1
  184. classiq/interface/model/power.py +4 -0
  185. classiq/interface/model/quantum_expressions/quantum_expression.py +1 -2
  186. classiq/interface/model/quantum_function_call.py +3 -6
  187. classiq/interface/model/quantum_function_declaration.py +1 -0
  188. classiq/interface/model/quantum_lambda_function.py +4 -4
  189. classiq/interface/model/quantum_statement.py +11 -4
  190. classiq/interface/model/quantum_type.py +14 -14
  191. classiq/interface/model/repeat.py +4 -0
  192. classiq/interface/model/skip_control.py +4 -0
  193. classiq/interface/model/validation_handle.py +2 -3
  194. classiq/interface/model/variable_declaration_statement.py +2 -2
  195. classiq/interface/model/within_apply_operation.py +4 -0
  196. classiq/interface/pretty_print/expression_to_qmod.py +3 -4
  197. classiq/interface/server/routes.py +0 -16
  198. classiq/interface/source_reference.py +3 -4
  199. classiq/model_expansions/arithmetic.py +11 -7
  200. classiq/model_expansions/arithmetic_compute_result_attrs.py +40 -28
  201. classiq/model_expansions/capturing/captured_vars.py +3 -3
  202. classiq/model_expansions/capturing/mangling_utils.py +1 -2
  203. classiq/model_expansions/closure.py +12 -11
  204. classiq/model_expansions/function_builder.py +14 -6
  205. classiq/model_expansions/generative_functions.py +7 -12
  206. classiq/model_expansions/interpreters/base_interpreter.py +3 -7
  207. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
  208. classiq/model_expansions/interpreters/generative_interpreter.py +5 -3
  209. classiq/model_expansions/quantum_operations/allocate.py +4 -4
  210. classiq/model_expansions/quantum_operations/assignment_result_processor.py +2 -4
  211. classiq/model_expansions/quantum_operations/call_emitter.py +31 -40
  212. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +2 -2
  213. classiq/model_expansions/quantum_operations/emitter.py +3 -5
  214. classiq/model_expansions/quantum_operations/expression_evaluator.py +3 -3
  215. classiq/model_expansions/quantum_operations/skip_control_verifier.py +1 -2
  216. classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
  217. classiq/model_expansions/scope.py +7 -7
  218. classiq/model_expansions/scope_initialization.py +4 -0
  219. classiq/model_expansions/visitors/symbolic_param_inference.py +6 -6
  220. classiq/model_expansions/visitors/uncomputation_signature_inference.py +328 -0
  221. classiq/model_expansions/visitors/variable_references.py +15 -14
  222. classiq/open_library/functions/__init__.py +41 -11
  223. classiq/open_library/functions/amplitude_loading.py +81 -0
  224. classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
  225. classiq/open_library/functions/encodings.py +182 -0
  226. classiq/open_library/functions/grover.py +8 -10
  227. classiq/open_library/functions/lcu.py +47 -18
  228. classiq/open_library/functions/modular_exponentiation.py +93 -8
  229. classiq/open_library/functions/qsvt.py +66 -79
  230. classiq/open_library/functions/qsvt_temp.py +536 -0
  231. classiq/open_library/functions/state_preparation.py +137 -31
  232. classiq/qmod/__init__.py +6 -4
  233. classiq/qmod/builtins/classical_execution_primitives.py +4 -23
  234. classiq/qmod/builtins/classical_functions.py +1 -42
  235. classiq/qmod/builtins/enums.py +15 -153
  236. classiq/qmod/builtins/functions/__init__.py +9 -18
  237. classiq/qmod/builtins/functions/allocation.py +25 -4
  238. classiq/qmod/builtins/functions/arithmetic.py +22 -27
  239. classiq/qmod/builtins/functions/exponentiation.py +51 -2
  240. classiq/qmod/builtins/functions/mcx_func.py +7 -0
  241. classiq/qmod/builtins/functions/standard_gates.py +46 -27
  242. classiq/qmod/builtins/operations.py +165 -79
  243. classiq/qmod/builtins/structs.py +24 -91
  244. classiq/qmod/cfunc.py +3 -2
  245. classiq/qmod/classical_function.py +2 -1
  246. classiq/qmod/cparam.py +2 -8
  247. classiq/qmod/create_model_function.py +7 -7
  248. classiq/qmod/declaration_inferrer.py +33 -30
  249. classiq/qmod/expression_query.py +7 -4
  250. classiq/qmod/model_state_container.py +2 -2
  251. classiq/qmod/native/pretty_printer.py +25 -14
  252. classiq/qmod/pretty_print/expression_to_python.py +5 -3
  253. classiq/qmod/pretty_print/pretty_printer.py +39 -17
  254. classiq/qmod/python_classical_type.py +40 -13
  255. classiq/qmod/qfunc.py +124 -19
  256. classiq/qmod/qmod_constant.py +2 -2
  257. classiq/qmod/qmod_parameter.py +5 -2
  258. classiq/qmod/qmod_variable.py +48 -47
  259. classiq/qmod/quantum_callable.py +18 -13
  260. classiq/qmod/quantum_expandable.py +31 -26
  261. classiq/qmod/quantum_function.py +84 -36
  262. classiq/qmod/semantics/annotation/call_annotation.py +5 -5
  263. classiq/qmod/semantics/error_manager.py +23 -15
  264. classiq/qmod/semantics/lambdas.py +1 -2
  265. classiq/qmod/semantics/validation/types_validation.py +1 -2
  266. classiq/qmod/symbolic.py +2 -4
  267. classiq/qmod/utilities.py +13 -20
  268. classiq/qmod/write_qmod.py +3 -4
  269. classiq/quantum_program.py +1 -3
  270. classiq/synthesis.py +11 -7
  271. {classiq-0.93.0.dist-info → classiq-0.100.0.dist-info}/METADATA +2 -3
  272. {classiq-0.93.0.dist-info → classiq-0.100.0.dist-info}/RECORD +274 -300
  273. {classiq-0.93.0.dist-info → classiq-0.100.0.dist-info}/WHEEL +1 -1
  274. classiq/applications/chemistry/ansatz_parameters.py +0 -29
  275. classiq/applications/chemistry/chemistry_execution_parameters.py +0 -16
  276. classiq/applications/chemistry/chemistry_model_constructor.py +0 -532
  277. classiq/applications/chemistry/ground_state_problem.py +0 -42
  278. classiq/applications/qsvm/__init__.py +0 -8
  279. classiq/applications/qsvm/qsvm.py +0 -11
  280. classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -129
  281. classiq/execution/iqcc.py +0 -128
  282. classiq/interface/applications/qsvm.py +0 -117
  283. classiq/interface/chemistry/elements.py +0 -120
  284. classiq/interface/chemistry/fermionic_operator.py +0 -208
  285. classiq/interface/chemistry/ground_state_problem.py +0 -132
  286. classiq/interface/chemistry/ground_state_result.py +0 -8
  287. classiq/interface/chemistry/molecule.py +0 -71
  288. classiq/interface/execution/iqcc.py +0 -44
  289. classiq/interface/generator/application_apis/chemistry_declarations.py +0 -69
  290. classiq/interface/generator/application_apis/entangler_declarations.py +0 -29
  291. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
  292. classiq/interface/generator/chemistry_function_params.py +0 -50
  293. classiq/interface/generator/entangler_params.py +0 -72
  294. classiq/interface/generator/entanglers.py +0 -14
  295. classiq/interface/generator/hamiltonian_evolution/qdrift.py +0 -27
  296. classiq/interface/generator/hartree_fock.py +0 -26
  297. classiq/interface/generator/hva.py +0 -22
  298. classiq/interface/generator/linear_pauli_rotations.py +0 -92
  299. classiq/interface/generator/qft.py +0 -37
  300. classiq/interface/generator/qsvm.py +0 -96
  301. classiq/interface/generator/state_preparation/__init__.py +0 -14
  302. classiq/interface/generator/state_preparation/bell_state_preparation.py +0 -27
  303. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +0 -28
  304. classiq/interface/generator/state_preparation/distributions.py +0 -53
  305. classiq/interface/generator/state_preparation/exponential_state_preparation.py +0 -14
  306. classiq/interface/generator/state_preparation/ghz_state_preparation.py +0 -14
  307. classiq/interface/generator/state_preparation/metrics.py +0 -41
  308. classiq/interface/generator/state_preparation/state_preparation.py +0 -113
  309. classiq/interface/generator/state_preparation/state_preparation_abc.py +0 -24
  310. classiq/interface/generator/state_preparation/uniform_distibution_state_preparation.py +0 -13
  311. classiq/interface/generator/state_preparation/w_state_preparation.py +0 -13
  312. classiq/interface/generator/ucc.py +0 -74
  313. classiq/interface/helpers/backward_compatibility.py +0 -9
  314. classiq/model_expansions/transformers/type_modifier_inference.py +0 -392
  315. classiq/open_library/functions/lookup_table.py +0 -58
  316. classiq/qmod/builtins/functions/chemistry.py +0 -123
  317. classiq/qmod/builtins/functions/qsvm.py +0 -24
  318. {classiq-0.93.0.dist-info → classiq-0.100.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -2,7 +2,7 @@ import ast
2
2
  from collections.abc import Iterator, Mapping, Sequence
3
3
  from contextlib import contextmanager
4
4
  from itertools import chain, zip_longest
5
- from typing import Optional, cast
5
+ from typing import cast
6
6
 
7
7
  from classiq.interface.generator.expressions.atomic_expression_functions import (
8
8
  CLASSICAL_ATTRIBUTES,
@@ -19,7 +19,7 @@ from classiq.interface.model.classical_parameter_declaration import (
19
19
  AnonClassicalParameterDeclaration,
20
20
  )
21
21
  from classiq.interface.model.handle_binding import FieldHandleBinding, HandleBinding
22
- from classiq.interface.model.model_visitor import ModelVisitor
22
+ from classiq.interface.model.model_visitor import ModelStatementsVisitor
23
23
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
24
24
  from classiq.interface.model.quantum_function_call import ArgValue, QuantumFunctionCall
25
25
  from classiq.interface.model.quantum_function_declaration import (
@@ -84,13 +84,13 @@ def _get_param_expressions(param: AnonPositionalArg) -> list[Expression]:
84
84
  return param.quantum_type.expressions
85
85
 
86
86
 
87
- class SymbolicParamInference(ModelVisitor):
87
+ class SymbolicParamInference(ModelStatementsVisitor):
88
88
  def __init__(
89
89
  self,
90
90
  functions: list[NativeFunctionDefinition],
91
- additional_signatures: Optional[
91
+ additional_signatures: None | (
92
92
  list[NamedParamsQuantumFunctionDeclaration]
93
- ] = None,
93
+ ) = None,
94
94
  ) -> None:
95
95
  self._functions = nameables_to_dict(functions)
96
96
  self._additional_signatures = (
@@ -166,7 +166,7 @@ class SymbolicParamInference(ModelVisitor):
166
166
  else:
167
167
  for expr in _get_expressions(arg):
168
168
  self._process_nested_compile_time_expression(expr.expr)
169
- self.generic_visit(call)
169
+ self.visit(call.positional_args)
170
170
 
171
171
  def _get_params(self, call: QuantumFunctionCall) -> Sequence[AnonPositionalArg]:
172
172
  name = call.func_name
@@ -0,0 +1,328 @@
1
+ import warnings
2
+ from collections import defaultdict
3
+ from collections.abc import Iterator
4
+ from contextlib import contextmanager
5
+ from typing import NamedTuple
6
+
7
+ from classiq.interface.ast_node import ASTNode
8
+ from classiq.interface.exceptions import (
9
+ ClassiqDeprecationWarning,
10
+ ClassiqInternalExpansionError,
11
+ )
12
+ from classiq.interface.generator.compiler_keywords import EXPANDED_KEYWORD
13
+ from classiq.interface.generator.functions.port_declaration import (
14
+ PortDeclarationDirection,
15
+ )
16
+ from classiq.interface.generator.functions.type_modifier import TypeModifier
17
+ from classiq.interface.generator.visitor import NodeType
18
+ from classiq.interface.model.allocate import Allocate
19
+ from classiq.interface.model.bind_operation import BindOperation
20
+ from classiq.interface.model.block import Block
21
+ from classiq.interface.model.classical_if import ClassicalIf
22
+ from classiq.interface.model.control import Control
23
+ from classiq.interface.model.invert import Invert
24
+ from classiq.interface.model.model_visitor import ModelStatementsVisitor
25
+ from classiq.interface.model.native_function_definition import NativeFunctionDefinition
26
+ from classiq.interface.model.power import Power
27
+ from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
28
+ AmplitudeLoadingOperation,
29
+ )
30
+ from classiq.interface.model.quantum_expressions.arithmetic_operation import (
31
+ ArithmeticOperation,
32
+ )
33
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
34
+ from classiq.interface.model.skip_control import SkipControl
35
+ from classiq.interface.model.within_apply_operation import WithinApply
36
+ from classiq.interface.source_reference import SourceReference
37
+
38
+
39
+ class _BoundVars(NamedTuple):
40
+ in_identifiers: list[str]
41
+ out_identifiers: list[str]
42
+ source_ref: SourceReference | None
43
+
44
+ def reverse(self) -> "_BoundVars":
45
+ return _BoundVars(
46
+ in_identifiers=self.out_identifiers,
47
+ out_identifiers=self.in_identifiers,
48
+ source_ref=self.source_ref,
49
+ )
50
+
51
+
52
+ class UncomputationSignatureInference(ModelStatementsVisitor):
53
+ """
54
+ Infers the uncomputation signature of a function (permutation/non-permutation for
55
+ the function, and const/non-const for each parameter).
56
+
57
+ A function is a permutation if and only if all its body operations are permutations
58
+ (note that amplitude loading operation is not a permutation).
59
+
60
+ A parameter is const if and only if it is used as a const argument in all the
61
+ body operations (including when binding it to a different variable). An exception
62
+ for this rule is that a const parameter can be used as a non-const argument to a
63
+ permutation function inside a `within` block.
64
+
65
+ This class assumes that dependent functions are already inferred, so it doesn't
66
+ recursively inferring function calls.
67
+ """
68
+
69
+ def __init__(self) -> None:
70
+ self._is_permutation: bool = True
71
+ self._non_permutation_reasons: list[SourceReference | None] = []
72
+ self._non_const_with_reasons: dict[str, list[SourceReference | None]] = (
73
+ defaultdict(list)
74
+ )
75
+
76
+ self._in_conjugation: bool = False
77
+ self._source_ref: SourceReference | None = None
78
+
79
+ # remember bound vars inside `within` to invert their effect after the `apply`
80
+ self._bound_vars_list: list[_BoundVars] = []
81
+
82
+ def run(self, func_def: NativeFunctionDefinition) -> None:
83
+ self._is_permutation = True
84
+ self._non_permutation_reasons.clear()
85
+ self._non_const_with_reasons.clear()
86
+ self.visit(func_def.body)
87
+
88
+ def is_permutation(self) -> bool:
89
+ return self._is_permutation
90
+
91
+ def non_permutation_reasons(self) -> list[SourceReference | None]:
92
+ if self._is_permutation:
93
+ raise ClassiqInternalExpansionError("Function is a permutation")
94
+ return self._non_permutation_reasons
95
+
96
+ def is_const(self, port: str) -> bool:
97
+ return port not in self._non_const_with_reasons
98
+
99
+ def non_const_reasons(self, port: str) -> list[SourceReference | None]:
100
+ if port not in self._non_const_with_reasons:
101
+ raise ClassiqInternalExpansionError("Parameter is constant")
102
+ return self._non_const_with_reasons[port]
103
+
104
+ def visit(self, node: NodeType) -> None:
105
+ if isinstance(node, ASTNode):
106
+ with self._source_reference_context(node.source_ref):
107
+ super().visit(node)
108
+ else:
109
+ super().visit(node)
110
+
111
+ def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
112
+ if not call.func_decl.permutation:
113
+ self._mark_as_non_permutation()
114
+
115
+ in_identifiers: list[str] = []
116
+ out_identifiers: list[str] = []
117
+
118
+ for handle, port in call.handles_with_params:
119
+ if port.type_modifier is not TypeModifier.Const:
120
+ self._mark_as_non_const(handle.name, call.func_decl.permutation)
121
+
122
+ if port.direction is PortDeclarationDirection.Input:
123
+ in_identifiers.append(handle.name)
124
+ elif port.direction is PortDeclarationDirection.Output:
125
+ out_identifiers.append(handle.name)
126
+
127
+ if in_identifiers or out_identifiers:
128
+ bound_vars = _BoundVars(in_identifiers, out_identifiers, call.source_ref)
129
+ self._mark_bind_outputs(bound_vars)
130
+ self._bound_vars_list.append(bound_vars)
131
+
132
+ def visit_Allocate(self, alloc: Allocate) -> None:
133
+ self._mark_as_non_const(alloc.target.name, True)
134
+
135
+ def visit_BindOperation(self, bind_op: BindOperation) -> None:
136
+ in_identifiers = [handle.name for handle in bind_op.in_handles]
137
+ out_identifiers = [handle.name for handle in bind_op.out_handles]
138
+ bound_vars = _BoundVars(in_identifiers, out_identifiers, bind_op.source_ref)
139
+ self._mark_bind_outputs(bound_vars)
140
+ self._bound_vars_list.append(bound_vars)
141
+
142
+ def visit_ArithmeticOperation(self, arith: ArithmeticOperation) -> None:
143
+ if arith.classical_assignment:
144
+ if arith.var_handles:
145
+ self._mark_as_non_permutation()
146
+ for handle in arith.var_handles:
147
+ self._mark_as_non_const(handle.name, False)
148
+ else:
149
+ self._mark_as_non_const(arith.result_var.name, True)
150
+
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
+ def visit_Control(self, control: Control) -> None:
158
+ self.visit(control.body)
159
+ if control.else_block is not None:
160
+ self.visit(control.else_block)
161
+
162
+ def visit_Invert(self, invert: Invert) -> None:
163
+ self.visit(invert.body)
164
+
165
+ def visit_Power(self, power: Power) -> None:
166
+ self.visit(power.body)
167
+
168
+ def visit_WithinApply(self, within_apply: WithinApply) -> None:
169
+ with self._conjugation_context() as bound_vars_list:
170
+ self.visit(within_apply.compute)
171
+ self.visit(within_apply.action)
172
+
173
+ for bound_vars in reversed(bound_vars_list):
174
+ self._mark_bind_outputs(bound_vars.reverse())
175
+
176
+ def visit_Block(self, block: Block) -> None:
177
+ self.visit(block.statements)
178
+
179
+ def visit_SkipControl(self, block: SkipControl) -> None:
180
+ self.visit(block.body)
181
+
182
+ def visit_ClassicalIf(self, classical_if: ClassicalIf) -> None:
183
+ self.visit(classical_if.then)
184
+ self.visit(classical_if.else_)
185
+
186
+ def _mark_as_non_permutation(self) -> None:
187
+ self._is_permutation = False
188
+ self._non_permutation_reasons.append(self._source_ref)
189
+
190
+ def _mark_as_non_const(
191
+ self,
192
+ identifier: str,
193
+ permutation_op: bool,
194
+ source_ref: SourceReference | None = None,
195
+ ) -> None:
196
+ if self._in_conjugation and permutation_op:
197
+ return
198
+ self._non_const_with_reasons[identifier].append(source_ref or self._source_ref)
199
+
200
+ def _mark_bind_outputs(self, bound_vars: _BoundVars) -> None:
201
+ if all(self.is_const(identifier) for identifier in bound_vars.in_identifiers):
202
+ return
203
+ for identifier in bound_vars.out_identifiers:
204
+ self._mark_as_non_const(identifier, False, bound_vars.source_ref)
205
+
206
+ @contextmanager
207
+ def _conjugation_context(self) -> Iterator[list[_BoundVars]]:
208
+ previous_bound_vars = self._bound_vars_list
209
+ previous_context = self._in_conjugation
210
+ self._bound_vars_list = []
211
+ self._in_conjugation = True
212
+ try:
213
+ yield self._bound_vars_list
214
+ finally:
215
+ self._in_conjugation = previous_context
216
+ self._bound_vars_list = previous_bound_vars
217
+
218
+ @contextmanager
219
+ def _source_reference_context(
220
+ self, source_ref: SourceReference | None
221
+ ) -> Iterator[None]:
222
+ previous_source_ref = self._source_ref
223
+ self._source_ref = source_ref
224
+ try:
225
+ yield
226
+ finally:
227
+ self._source_ref = previous_source_ref
228
+
229
+
230
+ def infer_and_validate_uncomputation_signature(
231
+ func_def: NativeFunctionDefinition,
232
+ disable_perm_check: bool = False,
233
+ disable_const_checks: list[str] | bool = False,
234
+ tighten_signature: bool = False,
235
+ ) -> None:
236
+ """
237
+ Runs the uncomputation signature inference in order to validate the function signature
238
+ and tighten it when requested (changing non-permutation to permutation and non-const
239
+ to const).
240
+ """
241
+ for port in func_def.port_declarations:
242
+ if port.type_modifier is TypeModifier.Const and port.direction in (
243
+ PortDeclarationDirection.Input,
244
+ PortDeclarationDirection.Output,
245
+ ):
246
+ warnings.warn(
247
+ _input_output_const(port.name, port.direction, func_def.name),
248
+ ClassiqDeprecationWarning,
249
+ stacklevel=1,
250
+ )
251
+
252
+ if disable_perm_check and (disable_const_checks is True) and not tighten_signature:
253
+ return
254
+
255
+ visitor = UncomputationSignatureInference()
256
+ visitor.run(func_def)
257
+
258
+ if not disable_perm_check and func_def.permutation and not visitor.is_permutation():
259
+ 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,
264
+ )
265
+
266
+ if tighten_signature and not func_def.permutation and visitor.is_permutation():
267
+ func_def.permutation = True
268
+
269
+ unchecked = (
270
+ set(disable_const_checks) if isinstance(disable_const_checks, list) else set()
271
+ )
272
+ for port in func_def.port_declarations:
273
+ if (
274
+ not ((disable_const_checks is True) or port.name in unchecked)
275
+ and port.type_modifier is TypeModifier.Const
276
+ and not visitor.is_const(port.name)
277
+ ):
278
+ 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,
283
+ )
284
+
285
+ if (
286
+ tighten_signature
287
+ and port.type_modifier is not TypeModifier.Const
288
+ and visitor.is_const(port.name)
289
+ ):
290
+ port.type_modifier = TypeModifier.Const
291
+
292
+
293
+ def _input_output_const(
294
+ port_name: str,
295
+ direction: PortDeclarationDirection,
296
+ function_name: str,
297
+ ) -> 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
+ )
303
+
304
+
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 ""
310
+ return (
311
+ f"Non-constant usage of a constant parameter {port_name!r}.{source_ref_str}\n"
312
+ "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."
315
+ )
316
+
317
+
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 ""
323
+ return (
324
+ f"Non-permutation operation used in a permutation function {function_name.split('_' + EXPANDED_KEYWORD)[0]!r}.{source_ref_str}\n"
325
+ "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."
328
+ )
@@ -1,7 +1,6 @@
1
1
  import ast
2
2
  from collections.abc import Iterator
3
3
  from contextlib import contextmanager
4
- from typing import Optional, Union
5
4
 
6
5
  from classiq.interface.exceptions import (
7
6
  ClassiqExpansionError,
@@ -46,13 +45,15 @@ class VarRefCollector(ast.NodeVisitor):
46
45
  handle for handle, in_subscript in self._var_handles.items() if in_subscript
47
46
  ]
48
47
 
49
- def visit(self, node: ast.AST) -> Union[
50
- SubscriptHandleBinding,
51
- SlicedHandleBinding,
52
- FieldHandleBinding,
53
- HandleBinding,
54
- None,
55
- ]:
48
+ def visit(
49
+ self, node: ast.AST
50
+ ) -> (
51
+ SubscriptHandleBinding
52
+ | SlicedHandleBinding
53
+ | FieldHandleBinding
54
+ | HandleBinding
55
+ | None
56
+ ):
56
57
  res = super().visit(node)
57
58
  if not self._ignore_duplicated_handles and len(self._var_handles) != len(
58
59
  {handle.name for handle in self._var_handles}
@@ -62,13 +63,13 @@ class VarRefCollector(ast.NodeVisitor):
62
63
  )
63
64
  return res
64
65
 
65
- def visit_Subscript(self, node: ast.Subscript) -> Union[HandleBinding, None]:
66
+ def visit_Subscript(self, node: ast.Subscript) -> HandleBinding | None:
66
67
  return self._get_subscript_handle(node.value, node.slice)
67
68
 
68
- def visit_Attribute(self, node: ast.Attribute) -> Optional[FieldHandleBinding]:
69
+ def visit_Attribute(self, node: ast.Attribute) -> FieldHandleBinding | None:
69
70
  return self._get_field_handle(node.value, node.attr)
70
71
 
71
- def visit_Call(self, node: ast.Call) -> Optional[HandleBinding]:
72
+ def visit_Call(self, node: ast.Call) -> HandleBinding | None:
72
73
  if not isinstance(node.func, ast.Name):
73
74
  return self.generic_visit(node)
74
75
  if node.func.id == "get_field":
@@ -89,7 +90,7 @@ class VarRefCollector(ast.NodeVisitor):
89
90
 
90
91
  def _get_field_handle(
91
92
  self, subject: ast.expr, field: str
92
- ) -> Optional[FieldHandleBinding]:
93
+ ) -> FieldHandleBinding | None:
93
94
  with self.set_nested():
94
95
  base_handle = self.visit(subject)
95
96
  if base_handle is None:
@@ -104,7 +105,7 @@ class VarRefCollector(ast.NodeVisitor):
104
105
 
105
106
  def _get_subscript_handle(
106
107
  self, subject: ast.expr, subscript: ast.expr
107
- ) -> Optional[HandleBinding]:
108
+ ) -> HandleBinding | None:
108
109
  with self.set_in_subscript():
109
110
  self.visit(subscript)
110
111
  with self.set_nested():
@@ -138,7 +139,7 @@ class VarRefCollector(ast.NodeVisitor):
138
139
  self._add_handle(handle)
139
140
  return handle
140
141
 
141
- def visit_Name(self, node: ast.Name) -> Optional[HandleBinding]:
142
+ def visit_Name(self, node: ast.Name) -> HandleBinding | None:
142
143
  if not self._ignore_sympy_symbols and node.id in set(
143
144
  SYMPY_SUPPORTED_EXPRESSIONS
144
145
  ) | set(DEFAULT_SUPPORTED_FUNC_NAMES):
@@ -1,30 +1,34 @@
1
+ from classiq.qmod.quantum_function import BaseQFunc
2
+
1
3
  from .amplitude_amplification import (
2
4
  amplitude_amplification,
3
5
  exact_amplitude_amplification,
4
6
  )
5
7
  from .amplitude_estimation import *
8
+ from .amplitude_loading import assign_amplitude_table
6
9
  from .discrete_sine_cosine_transform import *
7
10
  from .discrete_sine_cosine_transform import _qct_d_operator, _qct_pi_operator
11
+ from .encodings import *
8
12
  from .grover import *
9
13
  from .grover import _cond_phase_flip
10
14
  from .hea import *
11
15
  from .lcu import *
12
16
  from .linear_pauli_rotation import *
13
17
  from .linear_pauli_rotation import _single_pauli
14
- from .lookup_table import span_lookup_table
15
18
  from .modular_exponentiation import *
16
19
  from .modular_exponentiation import _check_msb
17
20
  from .qaoa_penalty import *
18
21
  from .qft_functions import *
19
22
  from .qpe import *
20
- from .qsvt import *
23
+ from .qsvt import gqsp
24
+ from .qsvt_temp import * # change to .qsvt after deprecation
21
25
  from .state_preparation import *
22
26
  from .state_preparation import _prepare_uniform_trimmed_state_step
23
27
  from .swap_test import *
24
28
  from .utility_functions import *
25
29
  from .variational import *
26
30
 
27
- OPEN_LIBRARY_FUNCTIONS = [
31
+ OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
28
32
  qpe_flexible,
29
33
  qpe,
30
34
  _single_pauli,
@@ -46,13 +50,20 @@ OPEN_LIBRARY_FUNCTIONS = [
46
50
  multiswap,
47
51
  inplace_c_modular_multiply,
48
52
  modular_exp,
49
- qsvt_step,
50
- qsvt,
51
- projector_controlled_double_phase,
52
- projector_controlled_phase,
53
- qsvt_inversion,
54
- qsvt_lcu,
55
- qsvt_lcu_step,
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,
56
67
  gqsp,
57
68
  qaoa_mixer_layer,
58
69
  qaoa_cost_layer,
@@ -82,6 +93,12 @@ OPEN_LIBRARY_FUNCTIONS = [
82
93
  encode_in_angle,
83
94
  encode_on_bloch,
84
95
  _cond_phase_flip,
96
+ inplace_modular_multiply,
97
+ modular_multiply,
98
+ modular_add_qft_space,
99
+ one_hot_to_unary,
100
+ inplace_one_hot_to_unary,
101
+ unary_to_one_hot,
85
102
  ]
86
103
 
87
104
  __all__ = [
@@ -89,6 +106,9 @@ __all__ = [
89
106
  "amplitude_amplification",
90
107
  "amplitude_estimation",
91
108
  "apply_to_all",
109
+ "assign_amplitude_table",
110
+ "binary_to_one_hot",
111
+ "binary_to_unary",
92
112
  "c_modular_multiply",
93
113
  "cc_modular_add",
94
114
  "encode_in_angle",
@@ -100,16 +120,24 @@ __all__ = [
100
120
  "grover_operator",
101
121
  "grover_search",
102
122
  "hadamard_transform",
123
+ "inplace_binary_to_one_hot",
103
124
  "inplace_c_modular_multiply",
125
+ "inplace_modular_multiply",
126
+ "inplace_one_hot_to_unary",
104
127
  "inplace_prepare_complex_amplitudes",
105
128
  "inplace_prepare_int",
106
129
  "inplace_prepare_sparse_amplitudes",
107
130
  "lcu",
108
131
  "lcu_pauli",
109
132
  "linear_pauli_rotations",
133
+ "modular_add_qft_space",
110
134
  "modular_exp",
111
135
  "modular_increment",
136
+ "modular_multiply",
112
137
  "multiswap",
138
+ "one_hot_to_binary",
139
+ "one_hot_to_unary",
140
+ "pad_zeros",
113
141
  "phase_oracle",
114
142
  "prepare_basis_state",
115
143
  "prepare_bell_state",
@@ -120,6 +148,7 @@ __all__ = [
120
148
  "prepare_ghz_state",
121
149
  "prepare_int",
122
150
  "prepare_linear_amplitudes",
151
+ "prepare_select",
123
152
  "prepare_sparse_amplitudes",
124
153
  "prepare_uniform_interval_state",
125
154
  "prepare_uniform_trimmed_state",
@@ -145,8 +174,9 @@ __all__ = [
145
174
  "qsvt_lcu_step",
146
175
  "qsvt_step",
147
176
  "reflect_about_zero",
148
- "span_lookup_table",
149
177
  "suzuki_trotter",
150
178
  "swap_test",
151
179
  "switch",
180
+ "unary_to_binary",
181
+ "unary_to_one_hot",
152
182
  ]
@@ -0,0 +1,81 @@
1
+ from typing import cast
2
+
3
+ import numpy as np
4
+ from sympy import fwht
5
+
6
+ from classiq.interface.exceptions import ClassiqValueError
7
+
8
+ from classiq.qmod.builtins.functions import CX, RY
9
+ from classiq.qmod.builtins.operations import skip_control
10
+ from classiq.qmod.qfunc import qfunc
11
+ from classiq.qmod.qmod_variable import Const, QArray, QBit
12
+
13
+
14
+ def _get_graycode(size: int, i: int) -> int:
15
+ if i == 2**size:
16
+ return _get_graycode(size, 0)
17
+ return i ^ (i >> 1)
18
+
19
+
20
+ def _get_graycode_angles_wh(size: int, angles: list[float]) -> list[float]:
21
+ transformed_angles = fwht(np.array(angles) / 2**size)
22
+ return [transformed_angles[_get_graycode(size, j)] for j in range(2**size)]
23
+
24
+
25
+ def _get_graycode_ctrls(size: int) -> list[int]:
26
+ return [
27
+ (_get_graycode(size, i) ^ _get_graycode(size, i + 1)).bit_length() - 1
28
+ for i in range(2**size)
29
+ ]
30
+
31
+
32
+ @qfunc
33
+ def assign_amplitude_table(
34
+ amplitudes: list[float], index: Const[QArray], indicator: QBit
35
+ ) -> None:
36
+ """
37
+ [Qmod Classiq-library function]
38
+
39
+ Load a specified list of real amplitudes into a quantum variable using an extra indicator qubit:
40
+ \\( |i\\rangle|0\\rangle \\rightarrow a(i)\\ |i\\rangle|1\\rangle + \\sqrt{1 - a(i)^2}\\ |i\\rangle|0\\rangle \\).
41
+ Here, \\(a(i)\\) is the i-th amplitude, determined by the QNum when the index is in state \\(i\\).
42
+ A list extracted from a given classical function \\(f(x)\\), with indexing according to a given QNum, can be obtained via the utility SDK function `lookup_table`.
43
+ This function expects the indicator qubit to be initialized to \\(|0\\rangle\\).
44
+
45
+ Args:
46
+ amplitudes: Real values for the amplitudes. Must be between -1 and 1
47
+ index: The quantum variable used for amplitude indexing
48
+ indicator: The quantum indicator qubit
49
+
50
+ Example:
51
+ ```python
52
+ from classiq import *
53
+
54
+
55
+ @qfunc
56
+ def main(x: Output[QNum[5, UNSIGNED, 5]], ind: Output[QBit]) -> None:
57
+ allocate(x)
58
+ hadamard_transform(x)
59
+ allocate(ind)
60
+
61
+ assign_amplitude_table(lookup_table(lambda x: x**2, x), x, ind)
62
+ ```
63
+ """
64
+ size = index.len
65
+ if len(amplitudes) != 2**size:
66
+ raise ClassiqValueError(
67
+ f"The number of amplitudes must be 2**index.size={2 ** size}, got "
68
+ f"{len(amplitudes)}"
69
+ )
70
+ if not all(-1 <= amp <= 1 for amp in amplitudes):
71
+ raise ClassiqValueError("All amplitudes must be between -1 and 1")
72
+
73
+ angles_to_load = cast(list[float], 2 * np.arcsin(amplitudes))
74
+ transformed_angles = _get_graycode_angles_wh(size, angles_to_load)
75
+ controllers = _get_graycode_ctrls(size)
76
+
77
+ for k in range(2**size):
78
+ RY(transformed_angles[k], indicator)
79
+ skip_control(
80
+ lambda k=k: CX(index[controllers[k]], indicator) # type:ignore[misc]
81
+ )
@@ -10,8 +10,8 @@ from classiq.qmod.builtins.operations import (
10
10
  repeat,
11
11
  within_apply,
12
12
  )
13
- from classiq.qmod.qfunc import qfunc
14
- from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit, QNum
13
+ from classiq.qmod.qfunc import qfunc, qperm
14
+ from classiq.qmod.qmod_variable import Const, QArray, QBit, QNum
15
15
  from classiq.qmod.symbolic import pi
16
16
  from classiq.qmod.utilities import suppress_return_value
17
17
 
@@ -27,8 +27,8 @@ def _qct_d_operator(x: Const[QNum], q: QBit) -> None:
27
27
  control(x == 0, lambda: invert(lambda: _b_operator(q)))
28
28
 
29
29
 
30
- @qfunc
31
- def _qct_pi_operator(x: Permutable[QNum], q: Const[QBit]) -> None:
30
+ @qperm
31
+ def _qct_pi_operator(x: QNum, q: Const[QBit]) -> None:
32
32
  control(
33
33
  q == 1,
34
34
  lambda: [
@@ -125,7 +125,7 @@ def qct_qst_type1(x: QArray[QBit]) -> None:
125
125
  within_apply(lambda: _t_operator(x), lambda: qft(x))
126
126
 
127
127
 
128
- @qfunc(unchecked=["q"])
128
+ @qfunc(disable_const_checks=["q"])
129
129
  def qct_qst_type2(x: QArray[QBit], q: Const[QBit]) -> None:
130
130
  """
131
131
  [Qmod Classiq-library function]