classiq 0.93.0__py3-none-any.whl → 0.99.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 (315) 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 +25 -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/hamiltonian_evolution/exponentiation.py +2 -4
  138. classiq/interface/generator/hardware/hardware_data.py +8 -8
  139. classiq/interface/generator/hardware_efficient_ansatz.py +9 -9
  140. classiq/interface/generator/mcu.py +3 -3
  141. classiq/interface/generator/mcx.py +3 -3
  142. classiq/interface/generator/model/constraints.py +34 -5
  143. classiq/interface/generator/model/preferences/preferences.py +15 -21
  144. classiq/interface/generator/model/quantum_register.py +7 -10
  145. classiq/interface/generator/noise_properties.py +3 -7
  146. classiq/interface/generator/parameters.py +1 -1
  147. classiq/interface/generator/partitioned_register.py +1 -2
  148. classiq/interface/generator/preferences/qasm_to_qmod_params.py +11 -0
  149. classiq/interface/generator/quantum_function_call.py +9 -12
  150. classiq/interface/generator/quantum_program.py +10 -23
  151. classiq/interface/generator/range_types.py +3 -3
  152. classiq/interface/generator/slice_parsing_utils.py +4 -5
  153. classiq/interface/generator/standard_gates/standard_gates.py +2 -4
  154. classiq/interface/generator/synthesis_execution_parameter.py +1 -3
  155. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +9 -0
  156. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +2 -3
  157. classiq/interface/generator/transpiler_basis_gates.py +12 -4
  158. classiq/interface/generator/types/builtin_enum_declarations.py +0 -145
  159. classiq/interface/generator/types/compilation_metadata.py +12 -1
  160. classiq/interface/generator/types/enum_declaration.py +2 -1
  161. classiq/interface/generator/validations/flow_graph.py +3 -3
  162. classiq/interface/generator/visitor.py +10 -12
  163. classiq/interface/hardware.py +2 -3
  164. classiq/interface/helpers/classproperty.py +2 -2
  165. classiq/interface/helpers/custom_encoders.py +2 -1
  166. classiq/interface/helpers/custom_pydantic_types.py +1 -1
  167. classiq/interface/helpers/text_utils.py +1 -4
  168. classiq/interface/ide/visual_model.py +6 -5
  169. classiq/interface/interface_version.py +1 -1
  170. classiq/interface/jobs.py +3 -3
  171. classiq/interface/model/allocate.py +4 -4
  172. classiq/interface/model/block.py +6 -2
  173. classiq/interface/model/bounds.py +3 -3
  174. classiq/interface/model/classical_if.py +4 -0
  175. classiq/interface/model/control.py +8 -1
  176. classiq/interface/model/inplace_binary_operation.py +2 -2
  177. classiq/interface/model/invert.py +4 -0
  178. classiq/interface/model/model.py +4 -4
  179. classiq/interface/model/model_visitor.py +40 -1
  180. classiq/interface/model/parameter.py +1 -3
  181. classiq/interface/model/port_declaration.py +1 -1
  182. classiq/interface/model/power.py +4 -0
  183. classiq/interface/model/quantum_expressions/quantum_expression.py +1 -2
  184. classiq/interface/model/quantum_function_call.py +3 -6
  185. classiq/interface/model/quantum_function_declaration.py +1 -0
  186. classiq/interface/model/quantum_lambda_function.py +4 -4
  187. classiq/interface/model/quantum_statement.py +11 -4
  188. classiq/interface/model/quantum_type.py +14 -14
  189. classiq/interface/model/repeat.py +4 -0
  190. classiq/interface/model/skip_control.py +4 -0
  191. classiq/interface/model/validation_handle.py +2 -3
  192. classiq/interface/model/variable_declaration_statement.py +2 -2
  193. classiq/interface/model/within_apply_operation.py +4 -0
  194. classiq/interface/pretty_print/expression_to_qmod.py +3 -4
  195. classiq/interface/server/routes.py +0 -16
  196. classiq/interface/source_reference.py +3 -4
  197. classiq/model_expansions/arithmetic.py +11 -7
  198. classiq/model_expansions/arithmetic_compute_result_attrs.py +30 -27
  199. classiq/model_expansions/capturing/captured_vars.py +3 -3
  200. classiq/model_expansions/capturing/mangling_utils.py +1 -2
  201. classiq/model_expansions/closure.py +12 -11
  202. classiq/model_expansions/function_builder.py +14 -6
  203. classiq/model_expansions/generative_functions.py +7 -12
  204. classiq/model_expansions/interpreters/base_interpreter.py +3 -7
  205. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
  206. classiq/model_expansions/interpreters/generative_interpreter.py +5 -3
  207. classiq/model_expansions/quantum_operations/allocate.py +4 -4
  208. classiq/model_expansions/quantum_operations/assignment_result_processor.py +2 -4
  209. classiq/model_expansions/quantum_operations/call_emitter.py +31 -37
  210. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +2 -2
  211. classiq/model_expansions/quantum_operations/emitter.py +3 -5
  212. classiq/model_expansions/quantum_operations/expression_evaluator.py +3 -3
  213. classiq/model_expansions/quantum_operations/skip_control_verifier.py +1 -2
  214. classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
  215. classiq/model_expansions/scope.py +7 -7
  216. classiq/model_expansions/scope_initialization.py +4 -0
  217. classiq/model_expansions/visitors/symbolic_param_inference.py +6 -6
  218. classiq/model_expansions/visitors/uncomputation_signature_inference.py +328 -0
  219. classiq/model_expansions/visitors/variable_references.py +15 -14
  220. classiq/open_library/functions/__init__.py +28 -11
  221. classiq/open_library/functions/amplitude_loading.py +81 -0
  222. classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
  223. classiq/open_library/functions/grover.py +8 -10
  224. classiq/open_library/functions/lcu.py +47 -18
  225. classiq/open_library/functions/modular_exponentiation.py +93 -8
  226. classiq/open_library/functions/qsvt.py +66 -79
  227. classiq/open_library/functions/qsvt_temp.py +536 -0
  228. classiq/open_library/functions/state_preparation.py +130 -27
  229. classiq/qmod/__init__.py +6 -4
  230. classiq/qmod/builtins/classical_execution_primitives.py +4 -23
  231. classiq/qmod/builtins/classical_functions.py +1 -42
  232. classiq/qmod/builtins/enums.py +15 -153
  233. classiq/qmod/builtins/functions/__init__.py +9 -18
  234. classiq/qmod/builtins/functions/allocation.py +25 -4
  235. classiq/qmod/builtins/functions/arithmetic.py +22 -27
  236. classiq/qmod/builtins/functions/exponentiation.py +51 -2
  237. classiq/qmod/builtins/functions/mcx_func.py +7 -0
  238. classiq/qmod/builtins/functions/standard_gates.py +46 -27
  239. classiq/qmod/builtins/operations.py +165 -79
  240. classiq/qmod/builtins/structs.py +24 -91
  241. classiq/qmod/cfunc.py +3 -2
  242. classiq/qmod/classical_function.py +2 -1
  243. classiq/qmod/cparam.py +2 -8
  244. classiq/qmod/create_model_function.py +7 -7
  245. classiq/qmod/declaration_inferrer.py +33 -30
  246. classiq/qmod/expression_query.py +7 -4
  247. classiq/qmod/model_state_container.py +2 -2
  248. classiq/qmod/native/pretty_printer.py +25 -14
  249. classiq/qmod/pretty_print/expression_to_python.py +5 -3
  250. classiq/qmod/pretty_print/pretty_printer.py +39 -17
  251. classiq/qmod/python_classical_type.py +40 -13
  252. classiq/qmod/qfunc.py +124 -19
  253. classiq/qmod/qmod_constant.py +2 -2
  254. classiq/qmod/qmod_parameter.py +5 -2
  255. classiq/qmod/qmod_variable.py +47 -46
  256. classiq/qmod/quantum_callable.py +18 -13
  257. classiq/qmod/quantum_expandable.py +31 -26
  258. classiq/qmod/quantum_function.py +84 -36
  259. classiq/qmod/semantics/annotation/call_annotation.py +5 -5
  260. classiq/qmod/semantics/error_manager.py +12 -14
  261. classiq/qmod/semantics/lambdas.py +1 -2
  262. classiq/qmod/semantics/validation/types_validation.py +1 -2
  263. classiq/qmod/symbolic.py +2 -4
  264. classiq/qmod/utilities.py +13 -20
  265. classiq/qmod/write_qmod.py +3 -4
  266. classiq/quantum_program.py +1 -3
  267. classiq/synthesis.py +11 -7
  268. {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/METADATA +2 -3
  269. {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/RECORD +271 -299
  270. {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/WHEEL +1 -1
  271. classiq/applications/chemistry/ansatz_parameters.py +0 -29
  272. classiq/applications/chemistry/chemistry_execution_parameters.py +0 -16
  273. classiq/applications/chemistry/chemistry_model_constructor.py +0 -532
  274. classiq/applications/chemistry/ground_state_problem.py +0 -42
  275. classiq/applications/qsvm/__init__.py +0 -8
  276. classiq/applications/qsvm/qsvm.py +0 -11
  277. classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -129
  278. classiq/execution/iqcc.py +0 -128
  279. classiq/interface/applications/qsvm.py +0 -117
  280. classiq/interface/chemistry/elements.py +0 -120
  281. classiq/interface/chemistry/fermionic_operator.py +0 -208
  282. classiq/interface/chemistry/ground_state_problem.py +0 -132
  283. classiq/interface/chemistry/ground_state_result.py +0 -8
  284. classiq/interface/chemistry/molecule.py +0 -71
  285. classiq/interface/execution/iqcc.py +0 -44
  286. classiq/interface/generator/application_apis/chemistry_declarations.py +0 -69
  287. classiq/interface/generator/application_apis/entangler_declarations.py +0 -29
  288. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
  289. classiq/interface/generator/chemistry_function_params.py +0 -50
  290. classiq/interface/generator/entangler_params.py +0 -72
  291. classiq/interface/generator/entanglers.py +0 -14
  292. classiq/interface/generator/hamiltonian_evolution/qdrift.py +0 -27
  293. classiq/interface/generator/hartree_fock.py +0 -26
  294. classiq/interface/generator/hva.py +0 -22
  295. classiq/interface/generator/linear_pauli_rotations.py +0 -92
  296. classiq/interface/generator/qft.py +0 -37
  297. classiq/interface/generator/qsvm.py +0 -96
  298. classiq/interface/generator/state_preparation/__init__.py +0 -14
  299. classiq/interface/generator/state_preparation/bell_state_preparation.py +0 -27
  300. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +0 -28
  301. classiq/interface/generator/state_preparation/distributions.py +0 -53
  302. classiq/interface/generator/state_preparation/exponential_state_preparation.py +0 -14
  303. classiq/interface/generator/state_preparation/ghz_state_preparation.py +0 -14
  304. classiq/interface/generator/state_preparation/metrics.py +0 -41
  305. classiq/interface/generator/state_preparation/state_preparation.py +0 -113
  306. classiq/interface/generator/state_preparation/state_preparation_abc.py +0 -24
  307. classiq/interface/generator/state_preparation/uniform_distibution_state_preparation.py +0 -13
  308. classiq/interface/generator/state_preparation/w_state_preparation.py +0 -13
  309. classiq/interface/generator/ucc.py +0 -74
  310. classiq/interface/helpers/backward_compatibility.py +0 -9
  311. classiq/model_expansions/transformers/type_modifier_inference.py +0 -392
  312. classiq/open_library/functions/lookup_table.py +0 -58
  313. classiq/qmod/builtins/functions/chemistry.py +0 -123
  314. classiq/qmod/builtins/functions/qsvm.py +0 -24
  315. {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -2,7 +2,6 @@ from collections.abc import Iterable, Mapping, Sequence
2
2
  from itertools import chain
3
3
  from typing import (
4
4
  Literal,
5
- Optional,
6
5
  Union,
7
6
  )
8
7
 
@@ -41,14 +40,12 @@ ArgValue = Union[
41
40
  class QuantumFunctionCall(QuantumOperation):
42
41
  kind: Literal["QuantumFunctionCall"]
43
42
 
44
- function: Union[str, OperandIdentifier] = pydantic.Field(
43
+ function: str | OperandIdentifier = pydantic.Field(
45
44
  description="The function that is called"
46
45
  )
47
46
  positional_args: list[ArgValue] = pydantic.Field(default_factory=list)
48
47
 
49
- _func_decl: Optional[QuantumFunctionDeclaration] = pydantic.PrivateAttr(
50
- default=None
51
- )
48
+ _func_decl: QuantumFunctionDeclaration | None = pydantic.PrivateAttr(default=None)
52
49
 
53
50
  def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
54
51
  return reset_lists(self, ["positional_args"])
@@ -60,7 +57,7 @@ class QuantumFunctionCall(QuantumOperation):
60
57
 
61
58
  return self._func_decl
62
59
 
63
- def set_func_decl(self, fd: Optional[QuantumFunctionDeclaration]) -> None:
60
+ def set_func_decl(self, fd: QuantumFunctionDeclaration | None) -> None:
64
61
  if fd is not None and not isinstance(fd, QuantumFunctionDeclaration):
65
62
  raise ClassiqValueError(
66
63
  "the declaration of a quantum function call cannot be set to a non-quantum function declaration."
@@ -61,6 +61,7 @@ class AnonQuantumFunctionDeclaration(FunctionDeclaration):
61
61
  positional_arg_declarations: Sequence[AnonPositionalArg] = pydantic.Field(
62
62
  default_factory=list
63
63
  )
64
+ permutation: bool = pydantic.Field(default=False)
64
65
 
65
66
  @property
66
67
  def port_declarations(self) -> Sequence[AnonPortDeclaration]:
@@ -1,11 +1,11 @@
1
- from typing import TYPE_CHECKING, Callable, Optional, Union
1
+ from collections.abc import Callable
2
+ from typing import TYPE_CHECKING, Union
2
3
 
3
4
  import pydantic
4
5
 
5
6
  from classiq.interface.ast_node import ASTNode
6
7
  from classiq.interface.exceptions import ClassiqError
7
8
  from classiq.interface.generator.expressions.expression import Expression
8
- from classiq.interface.helpers.backward_compatibility import zip_strict
9
9
  from classiq.interface.model.quantum_function_declaration import (
10
10
  AnonQuantumOperandDeclaration,
11
11
  )
@@ -28,7 +28,7 @@ class QuantumLambdaFunction(ASTNode):
28
28
  description="A list of function calls passed to the operator"
29
29
  )
30
30
 
31
- _func_decl: Optional[AnonQuantumOperandDeclaration] = pydantic.PrivateAttr(
31
+ _func_decl: AnonQuantumOperandDeclaration | None = pydantic.PrivateAttr(
32
32
  default=None
33
33
  )
34
34
 
@@ -57,7 +57,7 @@ class QuantumLambdaFunction(ASTNode):
57
57
  def named_func_decl(self) -> AnonQuantumOperandDeclaration:
58
58
  named_params = [
59
59
  param.rename(rename)
60
- for param, rename in zip_strict(
60
+ for param, rename in zip(
61
61
  self.func_decl.positional_arg_declarations,
62
62
  self.pos_rename_params,
63
63
  strict=False, # strict=False enables lambda keyword args
@@ -1,6 +1,6 @@
1
- from collections.abc import Iterable, Mapping, Sequence
1
+ from collections.abc import Callable, Iterable, Mapping, Sequence
2
2
  from dataclasses import dataclass
3
- from typing import Any, Callable, Optional
3
+ from typing import TYPE_CHECKING, Any
4
4
  from uuid import UUID, uuid4
5
5
 
6
6
  import pydantic
@@ -17,6 +17,9 @@ from classiq.interface.model.handle_binding import (
17
17
  HandleBinding,
18
18
  )
19
19
 
20
+ if TYPE_CHECKING:
21
+ from classiq.interface.model.statement_block import StatementBlock
22
+
20
23
 
21
24
  class QuantumStatement(ASTNode):
22
25
  kind: str
@@ -27,7 +30,7 @@ class QuantumStatement(ASTNode):
27
30
  def model_copy(
28
31
  self,
29
32
  *,
30
- update: Optional[Mapping[str, Any]] = None,
33
+ update: Mapping[str, Any] | None = None,
31
34
  deep: bool = False,
32
35
  keep_uuid: bool = False,
33
36
  ) -> Self:
@@ -45,11 +48,15 @@ class QuantumStatement(ASTNode):
45
48
  def expressions(self) -> list[Expression]:
46
49
  return []
47
50
 
51
+ @property
52
+ def blocks(self) -> dict[str, "StatementBlock"]:
53
+ return {}
54
+
48
55
 
49
56
  @dataclass
50
57
  class HandleMetadata:
51
58
  handle: HandleBinding
52
- readable_location: Optional[str] = None
59
+ readable_location: str | None = None
53
60
 
54
61
 
55
62
  class QuantumOperation(QuantumStatement):
@@ -1,4 +1,4 @@
1
- from typing import TYPE_CHECKING, Any, Literal, Optional
1
+ from typing import TYPE_CHECKING, Any, Literal
2
2
 
3
3
  import pydantic
4
4
  from pydantic import BaseModel, Field
@@ -23,7 +23,7 @@ if TYPE_CHECKING:
23
23
 
24
24
 
25
25
  class QuantumType(HashableASTNode):
26
- _size_in_bits: Optional[int] = pydantic.PrivateAttr(default=None)
26
+ _size_in_bits: int | None = pydantic.PrivateAttr(default=None)
27
27
 
28
28
  def _update_size_in_bits_from_declaration(self) -> None:
29
29
  pass
@@ -96,11 +96,11 @@ class QuantumScalar(QuantumType):
96
96
  def fraction_digits_value(self) -> int:
97
97
  raise NotImplementedError
98
98
 
99
- def get_bounds(self) -> Optional[tuple[float, float]]:
99
+ def get_bounds(self) -> tuple[float, float] | None:
100
100
  return None
101
101
 
102
102
  def get_effective_bounds(
103
- self, machine_precision: Optional[int] = None
103
+ self, machine_precision: int | None = None
104
104
  ) -> tuple[float, float]:
105
105
  raise NotImplementedError
106
106
 
@@ -162,7 +162,7 @@ class QuantumBit(QuantumScalar):
162
162
  return 0
163
163
 
164
164
  def get_effective_bounds(
165
- self, machine_precision: Optional[int] = None
165
+ self, machine_precision: int | None = None
166
166
  ) -> tuple[float, float]:
167
167
  return (0, 1)
168
168
 
@@ -176,7 +176,7 @@ class QuantumBitvector(QuantumType):
176
176
  discriminator="kind", default_factory=QuantumBit
177
177
  )
178
178
  kind: Literal["qvec"]
179
- length: Optional[Expression] = Field(default=None)
179
+ length: Expression | None = Field(default=None)
180
180
 
181
181
  @pydantic.model_validator(mode="before")
182
182
  @classmethod
@@ -278,11 +278,11 @@ class QuantumBitvector(QuantumType):
278
278
  class QuantumNumeric(QuantumScalar):
279
279
  kind: Literal["qnum"]
280
280
 
281
- size: Optional[Expression] = pydantic.Field(default=None)
282
- is_signed: Optional[Expression] = pydantic.Field(default=None)
283
- fraction_digits: Optional[Expression] = pydantic.Field(default=None)
281
+ size: Expression | None = pydantic.Field(default=None)
282
+ is_signed: Expression | None = pydantic.Field(default=None)
283
+ fraction_digits: Expression | None = pydantic.Field(default=None)
284
284
 
285
- _bounds: Optional[PydanticFloatTuple] = pydantic.PrivateAttr(default=None)
285
+ _bounds: PydanticFloatTuple | None = pydantic.PrivateAttr(default=None)
286
286
 
287
287
  @pydantic.model_validator(mode="before")
288
288
  @classmethod
@@ -429,10 +429,10 @@ class QuantumNumeric(QuantumScalar):
429
429
  exprs.append(self.fraction_digits)
430
430
  return exprs
431
431
 
432
- def get_bounds(self) -> Optional[tuple[float, float]]:
432
+ def get_bounds(self) -> tuple[float, float] | None:
433
433
  return self._bounds
434
434
 
435
- def set_bounds(self, bounds: Optional[tuple[float, float]]) -> None:
435
+ def set_bounds(self, bounds: tuple[float, float] | None) -> None:
436
436
  self._bounds = bounds
437
437
 
438
438
  def reset_bounds(self) -> None:
@@ -446,7 +446,7 @@ class QuantumNumeric(QuantumScalar):
446
446
  )
447
447
 
448
448
  def get_effective_bounds(
449
- self, machine_precision: Optional[int] = None
449
+ self, machine_precision: int | None = None
450
450
  ) -> tuple[float, float]:
451
451
  bounds = self.get_bounds() or self.get_maximal_bounds()
452
452
 
@@ -522,7 +522,7 @@ UNRESOLVED_SIZE = 1000
522
522
  def quantum_var_to_register(name: str, qtype: QuantumType) -> RegisterUserInput:
523
523
  signed: bool = False
524
524
  fraction_places: int = 0
525
- bounds: Optional[tuple[float, float]] = None
525
+ bounds: tuple[float, float] | None = None
526
526
  if isinstance(qtype, QuantumNumeric):
527
527
  signed = qtype.sign_value
528
528
  fraction_places = qtype.fraction_digits_value
@@ -21,3 +21,7 @@ class Repeat(QuantumOperation):
21
21
  @property
22
22
  def expressions(self) -> list[Expression]:
23
23
  return [self.count]
24
+
25
+ @property
26
+ def blocks(self) -> dict[str, "StatementBlock"]:
27
+ return {"body": self.body}
@@ -9,3 +9,7 @@ if TYPE_CHECKING:
9
9
  class SkipControl(QuantumOperation):
10
10
  kind: Literal["SkipControl"]
11
11
  body: "StatementBlock"
12
+
13
+ @property
14
+ def blocks(self) -> dict[str, "StatementBlock"]:
15
+ return {"body": self.body}
@@ -1,7 +1,6 @@
1
1
  import dataclasses
2
2
  from collections.abc import Mapping
3
3
  from enum import Enum
4
- from typing import Optional
5
4
 
6
5
  from classiq.interface.exceptions import ClassiqError
7
6
  from classiq.interface.model.handle_binding import HandleBinding
@@ -27,8 +26,8 @@ class ValidationHandle:
27
26
 
28
27
  def __init__(
29
28
  self,
30
- initial_state: Optional[HandleState] = None,
31
- errors: Optional[list[str]] = None,
29
+ initial_state: HandleState | None = None,
30
+ errors: list[str] | None = None,
32
31
  ) -> None:
33
32
  if initial_state is None and not errors:
34
33
  raise ClassiqError("Missing initial state for ValidationHandle")
@@ -1,4 +1,4 @@
1
- from typing import Any, Literal, Optional
1
+ from typing import Any, Literal
2
2
 
3
3
  import pydantic
4
4
 
@@ -15,7 +15,7 @@ class VariableDeclarationStatement(QuantumStatement):
15
15
  kind: Literal["VariableDeclarationStatement"]
16
16
 
17
17
  name: str
18
- quantum_type: Optional[ConcreteQuantumType] = None
18
+ quantum_type: ConcreteQuantumType | None = None
19
19
  qmod_type: ConcreteType
20
20
 
21
21
  @pydantic.model_validator(mode="before")
@@ -16,6 +16,10 @@ class WithinApply(QuantumOperation):
16
16
  def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
17
17
  return reset_lists(self, ["compute", "action"])
18
18
 
19
+ @property
20
+ def blocks(self) -> dict[str, "StatementBlock"]:
21
+ return {"compute": self.compute, "action": self.action}
22
+
19
23
 
20
24
  class Compute(QuantumOperation):
21
25
  kind: Literal["Compute"]
@@ -1,8 +1,7 @@
1
1
  import ast
2
2
  import re
3
- from collections.abc import Mapping
3
+ from collections.abc import Callable, Mapping
4
4
  from dataclasses import dataclass
5
- from typing import Callable, Optional
6
5
 
7
6
  import numpy as np
8
7
 
@@ -47,7 +46,7 @@ class PrettyPrinterError(AssertionError):
47
46
  @dataclass
48
47
  class ASTToQMODCode:
49
48
  level: int
50
- decimal_precision: Optional[int]
49
+ decimal_precision: int | None
51
50
  indent_seq: str = " "
52
51
 
53
52
  @property
@@ -197,7 +196,7 @@ def _remove_redundant_parentheses(expr: str) -> str:
197
196
  def transform_expression(
198
197
  expr: str,
199
198
  level: int = 0,
200
- decimal_precision: Optional[int] = DEFAULT_DECIMAL_PRECISION,
199
+ decimal_precision: int | None = DEFAULT_DECIMAL_PRECISION,
201
200
  ) -> str:
202
201
  return ASTToQMODCode(level=level, decimal_precision=decimal_precision).visit(
203
202
  ast.parse(expr)
@@ -1,11 +1,9 @@
1
1
  ANALYZER_PREFIX = "/analyzer"
2
- CHEMISTRY_PREFIX = "/chemistry"
3
2
  EXECUTION_PREFIX = "/execution"
4
3
  EXECUTION_SESSIONS_PREFIX = EXECUTION_PREFIX + "/sessions"
5
4
  CONVERSION_PREFIX = "/conversion"
6
5
  PROVIDERS_PREFIX = "/providers"
7
6
 
8
- IQCC_PREFIX = PROVIDERS_PREFIX + "/iqcc"
9
7
  USER_BUDGETS_PREFIX = "/user_budgets"
10
8
 
11
9
 
@@ -62,9 +60,6 @@ ANALYZER_RB_FULL_PATH = ANALYZER_PREFIX + TASK_RB_SUFFIX
62
60
 
63
61
  TASKS_SOLVE_EXACT_SUFFIX = "/tasks/solve_exact"
64
62
 
65
- GENERATE_HAMILTONIAN_SUFFIX = "/generate_hamiltonian"
66
- GENERATE_HAMILTONIAN_FULL_PATH = CHEMISTRY_PREFIX + GENERATE_HAMILTONIAN_SUFFIX
67
-
68
63
  CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX = "/execution_input"
69
64
  CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_FULL = (
70
65
  CONVERSION_PREFIX + CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX
@@ -74,17 +69,6 @@ QASM_TO_QMOD_FULL_PATH = CONVERSION_PREFIX + QASM_TO_QMOD_SUFFIX
74
69
 
75
70
  STATIC_SEMANTICS_VALIDATION_PATH = "/validate_static_semantics"
76
71
 
77
- IQCC_INIT_AUTH_SUFFIX = "/init_auth"
78
- IQCC_INIT_AUTH_FULL_PATH = IQCC_PREFIX + IQCC_INIT_AUTH_SUFFIX
79
- IQCC_PROBE_AUTH_SUFFIX = "/probe_auth"
80
- IQCC_PROBE_AUTH_FULL_PATH = IQCC_PREFIX + IQCC_PROBE_AUTH_SUFFIX
81
- IQCC_LIST_AUTH_SCOPES_SUFFIX = "/auth_scopes"
82
- IQCC_LIST_AUTH_SCOPES_FULL_PATH = IQCC_PREFIX + IQCC_LIST_AUTH_SCOPES_SUFFIX
83
- IQCC_LIST_AUTH_METHODS_SUFFIX = "/auth_methods"
84
- IQCC_LIST_AUTH_METHODS_FULL_PATH = IQCC_PREFIX + IQCC_LIST_AUTH_METHODS_SUFFIX
85
- IQCC_LIST_AUTH_TARGETS_SUFFIX = "/auth_targets"
86
- IQCC_LIST_AUTH_TARGETS_FULL_PATH = IQCC_PREFIX + IQCC_LIST_AUTH_TARGETS_SUFFIX
87
-
88
72
  USER_BUDGETS_SUFFIX = "/all"
89
73
  USER_BUDGETS_FULL_PATH = USER_BUDGETS_PREFIX + USER_BUDGETS_SUFFIX
90
74
  USER_BUDGET_SET_LIMIT_SUFFIX = "/set_limit"
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  import re
3
3
  from pathlib import Path
4
- from typing import Optional
5
4
 
6
5
  import pydantic
7
6
 
@@ -30,7 +29,7 @@ class SourceReference(HashablePydanticBaseModel):
30
29
  start_column: int
31
30
  end_line: int
32
31
  end_column: int
33
- file_name: Optional[str] = pydantic.Field(default=None)
32
+ file_name: str | None = pydantic.Field(default=None)
34
33
 
35
34
  def __str__(self) -> str:
36
35
  return f"{self.file_string()}{self.ref_inside_file()}"
@@ -47,8 +46,8 @@ class SourceReference(HashablePydanticBaseModel):
47
46
 
48
47
  class SourceReferencedError(pydantic.BaseModel):
49
48
  error: str
50
- source_ref: Optional[SourceReference] = None
51
- function: Optional[str] = None
49
+ source_ref: SourceReference | None = None
50
+ function: str | None = None
52
51
 
53
52
  def __str__(self) -> str:
54
53
  source_referenced_error = (
@@ -1,5 +1,4 @@
1
1
  from dataclasses import dataclass
2
- from typing import Optional, Union
3
2
 
4
3
  from classiq.interface.generator.arith import number_utils
5
4
  from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
@@ -23,7 +22,7 @@ class NumericAttributes:
23
22
  size: int,
24
23
  is_signed: bool,
25
24
  fraction_digits: int,
26
- bounds: Optional[tuple[float, float]] = None,
25
+ bounds: tuple[float, float] | None = None,
27
26
  trim_bounds: bool = False,
28
27
  ) -> None:
29
28
  self.size = size
@@ -84,6 +83,11 @@ class NumericAttributes:
84
83
  trim_bounds=True,
85
84
  )
86
85
 
86
+ def get_constant(self) -> float | None:
87
+ if self.lb == self.ub:
88
+ return self.lb
89
+ return None
90
+
87
91
  @classmethod
88
92
  def from_bounds(
89
93
  cls,
@@ -108,7 +112,7 @@ class NumericAttributes:
108
112
  def from_constant(
109
113
  cls,
110
114
  value: float,
111
- machine_precision: Optional[int] = None,
115
+ machine_precision: int | None = None,
112
116
  ) -> "NumericAttributes":
113
117
  if machine_precision is not None:
114
118
  value = number_utils.limit_fraction_places(value, machine_precision)
@@ -124,7 +128,7 @@ class NumericAttributes:
124
128
  def from_quantum_scalar(
125
129
  cls,
126
130
  quantum_type: QuantumScalar,
127
- machine_precision: Optional[int] = None,
131
+ machine_precision: int | None = None,
128
132
  ) -> "NumericAttributes":
129
133
  return cls(
130
134
  size=quantum_type.size_in_bits,
@@ -137,7 +141,7 @@ class NumericAttributes:
137
141
  def from_register_arithmetic_info(
138
142
  cls,
139
143
  register: RegisterArithmeticInfo,
140
- machine_precision: Optional[int] = None,
144
+ machine_precision: int | None = None,
141
145
  ) -> "NumericAttributes":
142
146
  return cls.from_quantum_scalar(
143
147
  quantum_type=register_info_to_quantum_type(register),
@@ -147,8 +151,8 @@ class NumericAttributes:
147
151
  @classmethod
148
152
  def from_type_or_constant(
149
153
  cls,
150
- from_: Union[float, QuantumScalar, RegisterArithmeticInfo],
151
- machine_precision: Optional[int] = None,
154
+ from_: float | QuantumScalar | RegisterArithmeticInfo,
155
+ machine_precision: int | None = None,
152
156
  ) -> "NumericAttributes":
153
157
  if isinstance(from_, QuantumScalar):
154
158
  return cls.from_quantum_scalar(from_, machine_precision)
@@ -1,6 +1,5 @@
1
1
  import math
2
2
  from collections.abc import Sequence
3
- from typing import Union
4
3
 
5
4
  from classiq.interface.exceptions import ClassiqValueError
6
5
 
@@ -153,20 +152,21 @@ def compute_result_attrs_multiply(
153
152
 
154
153
  def compute_result_attrs_power(
155
154
  left: NumericAttributes,
156
- right: Union[int, float],
155
+ right: NumericAttributes,
157
156
  machine_precision: int,
158
157
  ) -> NumericAttributes:
159
- if not float(right).is_integer() or right <= 0:
158
+ right_val = right.get_constant()
159
+ if right_val is None or not float(right_val).is_integer() or right_val <= 0:
160
160
  raise ClassiqValueError("Power must be a positive integer")
161
- right = int(right)
161
+ right_val = int(right_val)
162
162
 
163
163
  bounds: tuple[float, float]
164
- if (right % 2 == 0) and (left.lb < 0 < left.ub):
165
- bounds = (0, max(left.lb**right, left.ub**right))
164
+ if (right_val % 2 == 0) and (left.lb < 0 < left.ub):
165
+ bounds = (0, max(left.lb**right_val, left.ub**right_val))
166
166
  else:
167
- extremal_values = (left.lb**right, left.ub**right)
167
+ extremal_values = (left.lb**right_val, left.ub**right_val)
168
168
  bounds = (min(extremal_values), max(extremal_values))
169
- fraction_places = left.fraction_digits * right
169
+ fraction_places = left.fraction_digits * right_val
170
170
  return NumericAttributes.from_bounds(
171
171
  bounds[0], bounds[1], fraction_places, machine_precision, trim_bounds=True
172
172
  )
@@ -174,18 +174,19 @@ def compute_result_attrs_power(
174
174
 
175
175
  def compute_result_attrs_lshift(
176
176
  left: NumericAttributes,
177
- right: Union[int, float],
177
+ right: NumericAttributes,
178
178
  machine_precision: int,
179
179
  ) -> NumericAttributes:
180
- if not float(right).is_integer() or right < 0:
180
+ right_val = right.get_constant()
181
+ if right_val is None or not float(right_val).is_integer() or right_val < 0:
181
182
  raise ClassiqValueError("Shift must be a non-negative integer")
182
- right = int(right)
183
+ right_val = int(right_val)
183
184
 
184
185
  scale = 1 << left.fraction_digits
185
- lb = (int(left.lb * scale) << right) / scale
186
- ub = (int(left.ub * scale) << right) / scale
187
- fraction_digits = max(left.fraction_digits - right, 0)
188
- integer_digits = left.integer_digits + right
186
+ lb = (int(left.lb * scale) << right_val) / scale
187
+ ub = (int(left.ub * scale) << right_val) / scale
188
+ fraction_digits = max(left.fraction_digits - right_val, 0)
189
+ integer_digits = left.integer_digits + right_val
189
190
  return NumericAttributes(
190
191
  size=integer_digits + fraction_digits,
191
192
  is_signed=left.is_signed,
@@ -196,21 +197,22 @@ def compute_result_attrs_lshift(
196
197
 
197
198
  def compute_result_attrs_rshift(
198
199
  left: NumericAttributes,
199
- right: Union[int, float],
200
+ right: NumericAttributes,
200
201
  machine_precision: int,
201
202
  ) -> NumericAttributes:
202
- if not float(right).is_integer() or right < 0:
203
+ right_val = right.get_constant()
204
+ if right_val is None or not float(right_val).is_integer() or right_val < 0:
203
205
  raise ClassiqValueError("Shift must be a non-negative integer")
204
- right = int(right)
206
+ right_val = int(right_val)
205
207
 
206
208
  scale = 1 << left.fraction_digits
207
- lb = (int(left.lb * scale) >> right) / scale
208
- ub = (int(left.ub * scale) >> right) / scale
209
+ lb = (int(left.lb * scale) >> right_val) / scale
210
+ ub = (int(left.ub * scale) >> right_val) / scale
209
211
  fraction_digits = (
210
- 0 if (right >= left.size and not left.is_signed) else left.fraction_digits
212
+ 0 if (right_val >= left.size and not left.is_signed) else left.fraction_digits
211
213
  )
212
214
  return NumericAttributes(
213
- size=max(left.size - right, fraction_digits, 1),
215
+ size=max(left.size - right_val, fraction_digits, 1),
214
216
  is_signed=left.is_signed,
215
217
  fraction_digits=fraction_digits,
216
218
  bounds=(lb, ub),
@@ -219,19 +221,20 @@ def compute_result_attrs_rshift(
219
221
 
220
222
  def compute_result_attrs_modulo(
221
223
  left: NumericAttributes,
222
- right: Union[int, float],
224
+ right: NumericAttributes,
223
225
  machine_precision: int,
224
226
  ) -> NumericAttributes:
225
- if not float(right).is_integer() or right < 2:
227
+ right_val = right.get_constant()
228
+ if right_val is None or not float(right_val).is_integer() or right_val < 2:
226
229
  raise ClassiqValueError("Modulus must be a positive power of two")
227
- right = int(right)
228
- if right & (right - 1) != 0:
230
+ right_val = int(right_val)
231
+ if right_val & (right_val - 1) != 0:
229
232
  raise ClassiqValueError("Modulus must be a positive power of two")
230
233
 
231
234
  if left.fraction_digits > 0:
232
235
  raise ClassiqValueError("Modulo is supported for integers only")
233
236
 
234
- size = int(math.log2(right))
237
+ size = int(math.log2(right_val))
235
238
  if not left.is_signed and size >= left.size:
236
239
  return left
237
240
 
@@ -1,8 +1,8 @@
1
1
  import ast
2
2
  import dataclasses
3
- from collections.abc import Sequence
3
+ from collections.abc import Callable, Sequence
4
4
  from dataclasses import dataclass, field
5
- from typing import TYPE_CHECKING, Callable, Union, cast
5
+ from typing import TYPE_CHECKING, cast
6
6
 
7
7
  from typing_extensions import Self
8
8
 
@@ -297,7 +297,7 @@ class CapturedVars:
297
297
 
298
298
  def _conjugate_direction(
299
299
  self,
300
- source_direction: Union[PortDirection, bool],
300
+ source_direction: PortDirection | bool,
301
301
  target_direction: PortDirection,
302
302
  var_name: str,
303
303
  ) -> PortDirection:
@@ -1,5 +1,4 @@
1
1
  import re
2
- from typing import Optional
3
2
 
4
3
  from classiq.interface.generator.compiler_keywords import CAPTURE_SUFFIX
5
4
  from classiq.interface.model.handle_binding import HANDLE_ID_SEPARATOR, HandleBinding
@@ -17,7 +16,7 @@ def mangle_captured_var_name(
17
16
  return f"{var_name}{CAPTURE_SUFFIX}{function_name}__{function_depth}"
18
17
 
19
18
 
20
- def _match_capture_pattern(name: str) -> Optional[re.Match[str]]:
19
+ def _match_capture_pattern(name: str) -> re.Match[str] | None:
21
20
  return re.match(CAPTURE_PATTERN, name)
22
21
 
23
22
 
@@ -2,7 +2,7 @@ import dataclasses
2
2
  from collections.abc import Sequence
3
3
  from copy import deepcopy
4
4
  from dataclasses import dataclass, field
5
- from typing import Any, Optional
5
+ from typing import Any
6
6
 
7
7
  from typing_extensions import Self
8
8
 
@@ -47,7 +47,8 @@ class FunctionClosure(Closure):
47
47
  is_lambda: bool = False
48
48
  is_atomic: bool = False
49
49
  signature_scope: Scope = field(default_factory=Scope)
50
- _depth: Optional[int] = None
50
+ permutation: bool = False
51
+ _depth: int | None = None
51
52
 
52
53
  @property
53
54
  def depth(self) -> int:
@@ -67,9 +68,9 @@ class FunctionClosure(Closure):
67
68
  cls,
68
69
  name: str,
69
70
  scope: Scope,
70
- body: Optional[Sequence[QuantumStatement]] = None,
71
+ body: Sequence[QuantumStatement] | None = None,
71
72
  positional_arg_declarations: Sequence[PositionalArg] = tuple(),
72
- lambda_external_vars: Optional[CapturedVars] = None,
73
+ lambda_external_vars: CapturedVars | None = None,
73
74
  is_atomic: bool = False,
74
75
  **kwargs: Any,
75
76
  ) -> Self:
@@ -78,13 +79,13 @@ class FunctionClosure(Closure):
78
79
  if lambda_external_vars is not None:
79
80
  captured_vars.set_parent(lambda_external_vars)
80
81
  return cls(
81
- name,
82
- blocks,
83
- scope,
84
- positional_arg_declarations,
85
- captured_vars,
86
- lambda_external_vars is not None,
87
- is_atomic,
82
+ name=name,
83
+ blocks=blocks,
84
+ scope=scope,
85
+ positional_arg_declarations=positional_arg_declarations,
86
+ captured_vars=captured_vars,
87
+ is_lambda=lambda_external_vars is not None,
88
+ is_atomic=is_atomic,
88
89
  **kwargs,
89
90
  )
90
91