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
@@ -1,11 +1,9 @@
1
- from typing import Optional
2
-
3
1
  from classiq.interface.ast_node import ASTNode
4
2
  from classiq.interface.exceptions import ClassiqError
5
3
 
6
4
 
7
5
  class Parameter(ASTNode):
8
- name: Optional[str]
6
+ name: str | None
9
7
 
10
8
  def get_name(self) -> str:
11
9
  if self.name is None:
@@ -49,7 +49,7 @@ class AnonPortDeclaration(Parameter):
49
49
  def qmod_type_name(self) -> str:
50
50
  prefix = ""
51
51
  suffix = ""
52
- if self.type_modifier in (TypeModifier.Const, TypeModifier.Permutable):
52
+ if self.type_modifier is TypeModifier.Const:
53
53
  prefix += f"{self.type_modifier.name}["
54
54
  suffix += "]"
55
55
  if self.direction != PortDeclarationDirection.Inout:
@@ -20,3 +20,7 @@ class Power(QuantumOperation):
20
20
  @property
21
21
  def expressions(self) -> list[Expression]:
22
22
  return [self.power]
23
+
24
+ @property
25
+ def blocks(self) -> dict[str, "StatementBlock"]:
26
+ return {"body": self.body}
@@ -1,6 +1,5 @@
1
1
  import abc
2
2
  from collections.abc import Mapping
3
- from typing import Optional
4
3
 
5
4
  import pydantic
6
5
 
@@ -55,7 +54,7 @@ class QuantumAssignmentOperation(QuantumExpressionOperation):
55
54
  result_var: ConcreteHandleBinding = pydantic.Field(
56
55
  description="The variable storing the expression result"
57
56
  )
58
- _result_type: Optional[QuantumType] = pydantic.PrivateAttr(
57
+ _result_type: QuantumType | None = pydantic.PrivateAttr(
59
58
  default=None,
60
59
  )
61
60
 
@@ -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
 
@@ -65,11 +64,20 @@ def compute_result_attrs_bitwise_and(
65
64
  if left.fraction_digits > 0 or right.fraction_digits > 0:
66
65
  raise ClassiqValueError("Bitwise AND is only defined for integers")
67
66
 
67
+ if left.is_signed and not right.is_signed:
68
+ size = right.size
69
+ elif not left.is_signed and right.is_signed:
70
+ size = left.size
71
+ elif not left.is_signed and not right.is_signed:
72
+ size = min(left.size, right.size)
73
+ else:
74
+ size = max(left.size, right.size)
75
+
68
76
  # we comply with python, which uses arbitrary precision, so a positive number can
69
77
  # always be represented by "0..." and a negative number by "1...", thus their
70
78
  # bitwise AND is always non-negative
71
79
  return NumericAttributes(
72
- size=max(left.size, right.size),
80
+ size=size,
73
81
  is_signed=left.is_signed and right.is_signed,
74
82
  fraction_digits=0,
75
83
  )
@@ -153,20 +161,21 @@ def compute_result_attrs_multiply(
153
161
 
154
162
  def compute_result_attrs_power(
155
163
  left: NumericAttributes,
156
- right: Union[int, float],
164
+ right: NumericAttributes,
157
165
  machine_precision: int,
158
166
  ) -> NumericAttributes:
159
- if not float(right).is_integer() or right <= 0:
167
+ right_val = right.get_constant()
168
+ if right_val is None or not float(right_val).is_integer() or right_val <= 0:
160
169
  raise ClassiqValueError("Power must be a positive integer")
161
- right = int(right)
170
+ right_val = int(right_val)
162
171
 
163
172
  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))
173
+ if (right_val % 2 == 0) and (left.lb < 0 < left.ub):
174
+ bounds = (0, max(left.lb**right_val, left.ub**right_val))
166
175
  else:
167
- extremal_values = (left.lb**right, left.ub**right)
176
+ extremal_values = (left.lb**right_val, left.ub**right_val)
168
177
  bounds = (min(extremal_values), max(extremal_values))
169
- fraction_places = left.fraction_digits * right
178
+ fraction_places = left.fraction_digits * right_val
170
179
  return NumericAttributes.from_bounds(
171
180
  bounds[0], bounds[1], fraction_places, machine_precision, trim_bounds=True
172
181
  )
@@ -174,18 +183,19 @@ def compute_result_attrs_power(
174
183
 
175
184
  def compute_result_attrs_lshift(
176
185
  left: NumericAttributes,
177
- right: Union[int, float],
186
+ right: NumericAttributes,
178
187
  machine_precision: int,
179
188
  ) -> NumericAttributes:
180
- if not float(right).is_integer() or right < 0:
189
+ right_val = right.get_constant()
190
+ if right_val is None or not float(right_val).is_integer() or right_val < 0:
181
191
  raise ClassiqValueError("Shift must be a non-negative integer")
182
- right = int(right)
192
+ right_val = int(right_val)
183
193
 
184
194
  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
195
+ lb = (int(left.lb * scale) << right_val) / scale
196
+ ub = (int(left.ub * scale) << right_val) / scale
197
+ fraction_digits = max(left.fraction_digits - right_val, 0)
198
+ integer_digits = left.integer_digits + right_val
189
199
  return NumericAttributes(
190
200
  size=integer_digits + fraction_digits,
191
201
  is_signed=left.is_signed,
@@ -196,21 +206,22 @@ def compute_result_attrs_lshift(
196
206
 
197
207
  def compute_result_attrs_rshift(
198
208
  left: NumericAttributes,
199
- right: Union[int, float],
209
+ right: NumericAttributes,
200
210
  machine_precision: int,
201
211
  ) -> NumericAttributes:
202
- if not float(right).is_integer() or right < 0:
212
+ right_val = right.get_constant()
213
+ if right_val is None or not float(right_val).is_integer() or right_val < 0:
203
214
  raise ClassiqValueError("Shift must be a non-negative integer")
204
- right = int(right)
215
+ right_val = int(right_val)
205
216
 
206
217
  scale = 1 << left.fraction_digits
207
- lb = (int(left.lb * scale) >> right) / scale
208
- ub = (int(left.ub * scale) >> right) / scale
218
+ lb = (int(left.lb * scale) >> right_val) / scale
219
+ ub = (int(left.ub * scale) >> right_val) / scale
209
220
  fraction_digits = (
210
- 0 if (right >= left.size and not left.is_signed) else left.fraction_digits
221
+ 0 if (right_val >= left.size and not left.is_signed) else left.fraction_digits
211
222
  )
212
223
  return NumericAttributes(
213
- size=max(left.size - right, fraction_digits, 1),
224
+ size=max(left.size - right_val, fraction_digits, 1),
214
225
  is_signed=left.is_signed,
215
226
  fraction_digits=fraction_digits,
216
227
  bounds=(lb, ub),
@@ -219,19 +230,20 @@ def compute_result_attrs_rshift(
219
230
 
220
231
  def compute_result_attrs_modulo(
221
232
  left: NumericAttributes,
222
- right: Union[int, float],
233
+ right: NumericAttributes,
223
234
  machine_precision: int,
224
235
  ) -> NumericAttributes:
225
- if not float(right).is_integer() or right < 2:
236
+ right_val = right.get_constant()
237
+ if right_val is None or not float(right_val).is_integer() or right_val < 2:
226
238
  raise ClassiqValueError("Modulus must be a positive power of two")
227
- right = int(right)
228
- if right & (right - 1) != 0:
239
+ right_val = int(right_val)
240
+ if right_val & (right_val - 1) != 0:
229
241
  raise ClassiqValueError("Modulus must be a positive power of two")
230
242
 
231
243
  if left.fraction_digits > 0:
232
244
  raise ClassiqValueError("Modulo is supported for integers only")
233
245
 
234
- size = int(math.log2(right))
246
+ size = int(math.log2(right_val))
235
247
  if not left.is_signed and size >= left.size:
236
248
  return left
237
249
 
@@ -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