classiq 0.53.0__py3-none-any.whl → 0.54.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 (296) hide show
  1. classiq/__init__.py +1 -3
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
  3. classiq/_internals/__init__.py +0 -20
  4. classiq/_internals/api_wrapper.py +8 -8
  5. classiq/_internals/async_utils.py +1 -3
  6. classiq/_internals/authentication/auth0.py +5 -5
  7. classiq/_internals/authentication/device.py +5 -4
  8. classiq/_internals/authentication/password_manager.py +3 -3
  9. classiq/_internals/authentication/token_manager.py +3 -2
  10. classiq/_internals/client.py +10 -12
  11. classiq/_internals/config.py +2 -2
  12. classiq/_internals/jobs.py +7 -6
  13. classiq/_internals/type_validation.py +9 -9
  14. classiq/analyzer/__init__.py +1 -3
  15. classiq/analyzer/analyzer.py +8 -7
  16. classiq/analyzer/analyzer_utilities.py +8 -8
  17. classiq/analyzer/rb.py +11 -11
  18. classiq/applications/__init__.py +1 -3
  19. classiq/applications/chemistry/__init__.py +1 -3
  20. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  21. classiq/applications/chemistry/chemistry_model_constructor.py +10 -9
  22. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +26 -9
  23. classiq/applications/combinatorial_helpers/encoding_mapping.py +10 -10
  24. classiq/applications/combinatorial_helpers/encoding_utils.py +4 -4
  25. classiq/applications/combinatorial_helpers/memory.py +5 -7
  26. classiq/applications/combinatorial_helpers/optimization_model.py +43 -24
  27. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +4 -6
  28. classiq/applications/combinatorial_helpers/pyomo_utils.py +95 -24
  29. classiq/applications/combinatorial_helpers/sympy_utils.py +2 -2
  30. classiq/applications/combinatorial_helpers/transformations/encoding.py +8 -8
  31. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +5 -5
  32. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +7 -9
  33. classiq/applications/combinatorial_helpers/transformations/penalty.py +1 -2
  34. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +1 -2
  35. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +1 -2
  36. classiq/applications/combinatorial_optimization/__init__.py +1 -3
  37. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  38. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  39. classiq/applications/finance/__init__.py +1 -3
  40. classiq/applications/grover/__init__.py +1 -3
  41. classiq/applications/grover/grover_model_constructor.py +7 -9
  42. classiq/applications/hamiltonian/pauli_decomposition.py +6 -6
  43. classiq/applications/qnn/__init__.py +1 -3
  44. classiq/applications/qnn/circuit_utils.py +5 -5
  45. classiq/applications/qnn/datasets/__init__.py +1 -3
  46. classiq/applications/qnn/datasets/dataset_base_classes.py +5 -4
  47. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  48. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  49. classiq/applications/qnn/qlayer.py +3 -3
  50. classiq/applications/qnn/torch_utils.py +2 -2
  51. classiq/applications/qnn/types.py +5 -5
  52. classiq/applications/qsvm/qsvm.py +1 -3
  53. classiq/applications/qsvm/qsvm_data_generation.py +3 -3
  54. classiq/applications/qsvm/qsvm_model_constructor.py +5 -5
  55. classiq/execution/__init__.py +1 -3
  56. classiq/execution/all_hardware_devices.py +1 -3
  57. classiq/execution/execution_session.py +16 -16
  58. classiq/execution/jobs.py +4 -4
  59. classiq/execution/qaoa.py +3 -3
  60. classiq/execution/qnn.py +3 -3
  61. classiq/executor.py +3 -3
  62. classiq/interface/_version.py +1 -1
  63. classiq/interface/analyzer/analysis_params.py +9 -10
  64. classiq/interface/analyzer/cytoscape_graph.py +5 -5
  65. classiq/interface/analyzer/result.py +17 -17
  66. classiq/interface/applications/qsvm.py +6 -10
  67. classiq/interface/backend/backend_preferences.py +4 -3
  68. classiq/interface/backend/ionq/ionq_quantum_program.py +4 -5
  69. classiq/interface/backend/pydantic_backend.py +1 -2
  70. classiq/interface/chemistry/fermionic_operator.py +5 -5
  71. classiq/interface/chemistry/ground_state_problem.py +7 -8
  72. classiq/interface/chemistry/molecule.py +4 -4
  73. classiq/interface/chemistry/operator.py +11 -13
  74. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
  75. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  76. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  77. classiq/interface/combinatorial_optimization/examples/mht.py +2 -3
  78. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  79. classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
  80. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +5 -7
  81. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  82. classiq/interface/combinatorial_optimization/result.py +1 -3
  83. classiq/interface/debug_info/debug_info.py +8 -7
  84. classiq/interface/exceptions.py +8 -6
  85. classiq/interface/execution/jobs.py +2 -2
  86. classiq/interface/execution/primitives.py +3 -3
  87. classiq/interface/executor/aws_execution_cost.py +4 -4
  88. classiq/interface/executor/execution_request.py +2 -3
  89. classiq/interface/executor/execution_result.py +3 -3
  90. classiq/interface/executor/iqae_result.py +3 -5
  91. classiq/interface/executor/optimizer_preferences.py +2 -2
  92. classiq/interface/executor/quantum_code.py +6 -6
  93. classiq/interface/executor/register_initialization.py +2 -4
  94. classiq/interface/executor/result.py +23 -27
  95. classiq/interface/executor/vqe_result.py +8 -8
  96. classiq/interface/finance/function_input.py +2 -2
  97. classiq/interface/finance/gaussian_model_input.py +5 -5
  98. classiq/interface/finance/log_normal_model_input.py +2 -2
  99. classiq/interface/finance/model_input.py +1 -2
  100. classiq/interface/generator/adjacency.py +1 -3
  101. classiq/interface/generator/ansatz_library.py +4 -4
  102. classiq/interface/generator/application_apis/finance_declarations.py +1 -1
  103. classiq/interface/generator/arith/argument_utils.py +3 -3
  104. classiq/interface/generator/arith/arithmetic.py +7 -7
  105. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +5 -5
  106. classiq/interface/generator/arith/arithmetic_expression_abc.py +11 -11
  107. classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -7
  108. classiq/interface/generator/arith/arithmetic_expression_validator.py +8 -8
  109. classiq/interface/generator/arith/arithmetic_operations.py +4 -3
  110. classiq/interface/generator/arith/arithmetic_param_getters.py +6 -6
  111. classiq/interface/generator/arith/arithmetic_result_builder.py +9 -9
  112. classiq/interface/generator/arith/ast_node_rewrite.py +2 -1
  113. classiq/interface/generator/arith/binary_ops.py +10 -13
  114. classiq/interface/generator/arith/extremum_operations.py +3 -2
  115. classiq/interface/generator/arith/logical_ops.py +7 -6
  116. classiq/interface/generator/arith/number_utils.py +4 -4
  117. classiq/interface/generator/arith/register_user_input.py +4 -4
  118. classiq/interface/generator/arith/unary_ops.py +2 -1
  119. classiq/interface/generator/builtin_api_builder.py +2 -1
  120. classiq/interface/generator/circuit_code/circuit_code.py +4 -4
  121. classiq/interface/generator/circuit_code/types_and_constants.py +3 -5
  122. classiq/interface/generator/complex_type.py +1 -2
  123. classiq/interface/generator/control_state.py +2 -2
  124. classiq/interface/generator/custom_ansatz.py +1 -3
  125. classiq/interface/generator/distance.py +3 -5
  126. classiq/interface/generator/excitations.py +3 -2
  127. classiq/interface/generator/expressions/enums/finance_functions.py +1 -3
  128. classiq/interface/generator/expressions/evaluated_expression.py +4 -3
  129. classiq/interface/generator/expressions/expression.py +4 -5
  130. classiq/interface/generator/expressions/expression_constants.py +4 -4
  131. classiq/interface/generator/expressions/qmod_qarray_proxy.py +2 -1
  132. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +2 -1
  133. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +2 -1
  134. classiq/interface/generator/expressions/qmod_sized_proxy.py +2 -1
  135. classiq/interface/generator/expressions/qmod_struct_instance.py +2 -1
  136. classiq/interface/generator/expressions/sympy_supported_expressions.py +11 -13
  137. classiq/interface/generator/finance.py +2 -2
  138. classiq/interface/generator/function_param_library.py +6 -6
  139. classiq/interface/generator/function_params.py +13 -19
  140. classiq/interface/generator/functions/classical_function_declaration.py +4 -3
  141. classiq/interface/generator/functions/classical_type.py +13 -13
  142. classiq/interface/generator/functions/concrete_types.py +1 -2
  143. classiq/interface/generator/functions/function_declaration.py +1 -1
  144. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  145. classiq/interface/generator/functions/type_name.py +3 -2
  146. classiq/interface/generator/generated_circuit_data.py +34 -22
  147. classiq/interface/generator/grover_diffuser.py +7 -7
  148. classiq/interface/generator/grover_operator.py +2 -2
  149. classiq/interface/generator/hardware/hardware_data.py +7 -6
  150. classiq/interface/generator/hardware_efficient_ansatz.py +8 -8
  151. classiq/interface/generator/identity.py +5 -6
  152. classiq/interface/generator/linear_pauli_rotations.py +6 -6
  153. classiq/interface/generator/mcu.py +2 -2
  154. classiq/interface/generator/mcx.py +6 -6
  155. classiq/interface/generator/model/__init__.py +1 -3
  156. classiq/interface/generator/model/constraints.py +2 -2
  157. classiq/interface/generator/model/model.py +5 -6
  158. classiq/interface/generator/model/preferences/preferences.py +7 -6
  159. classiq/interface/generator/model/quantum_register.py +6 -11
  160. classiq/interface/generator/oracles/arithmetic_oracle.py +1 -2
  161. classiq/interface/generator/oracles/custom_oracle.py +2 -2
  162. classiq/interface/generator/oracles/oracle_abc.py +6 -5
  163. classiq/interface/generator/partitioned_register.py +6 -5
  164. classiq/interface/generator/piecewise_linear_amplitude_loading.py +8 -7
  165. classiq/interface/generator/qpe.py +4 -4
  166. classiq/interface/generator/qsvm.py +3 -3
  167. classiq/interface/generator/quantum_function_call.py +24 -29
  168. classiq/interface/generator/quantum_program.py +9 -9
  169. classiq/interface/generator/register_role.py +2 -4
  170. classiq/interface/generator/slice_parsing_utils.py +4 -3
  171. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  172. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  173. classiq/interface/generator/state_preparation/distributions.py +6 -5
  174. classiq/interface/generator/state_preparation/metrics.py +2 -4
  175. classiq/interface/generator/state_preparation/state_preparation.py +4 -4
  176. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +3 -3
  177. classiq/interface/generator/transpiler_basis_gates.py +2 -2
  178. classiq/interface/generator/types/enum_declaration.py +2 -3
  179. classiq/interface/generator/types/qstruct_declaration.py +2 -1
  180. classiq/interface/generator/types/struct_declaration.py +3 -2
  181. classiq/interface/generator/ucc.py +2 -1
  182. classiq/interface/generator/unitary_gate.py +2 -2
  183. classiq/interface/generator/user_defined_function_params.py +1 -1
  184. classiq/interface/generator/validations/flow_graph.py +6 -5
  185. classiq/interface/generator/validations/validator_functions.py +3 -2
  186. classiq/interface/generator/visitor.py +9 -14
  187. classiq/interface/hardware.py +5 -6
  188. classiq/interface/helpers/custom_encoders.py +2 -2
  189. classiq/interface/helpers/custom_pydantic_types.py +8 -9
  190. classiq/interface/helpers/hashable_mixin.py +3 -2
  191. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  192. classiq/interface/helpers/pydantic_model_helpers.py +4 -3
  193. classiq/interface/helpers/validation_helpers.py +2 -2
  194. classiq/interface/ide/ide_data.py +11 -15
  195. classiq/interface/ide/visual_model.py +20 -22
  196. classiq/interface/jobs.py +2 -2
  197. classiq/interface/model/bind_operation.py +5 -4
  198. classiq/interface/model/classical_parameter_declaration.py +2 -2
  199. classiq/interface/model/handle_binding.py +3 -2
  200. classiq/interface/model/inplace_binary_operation.py +2 -1
  201. classiq/interface/model/model.py +12 -11
  202. classiq/interface/model/port_declaration.py +2 -2
  203. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +3 -2
  204. classiq/interface/model/quantum_expressions/arithmetic_operation.py +3 -2
  205. classiq/interface/model/quantum_expressions/quantum_expression.py +8 -7
  206. classiq/interface/model/quantum_function_call.py +9 -14
  207. classiq/interface/model/quantum_function_declaration.py +10 -12
  208. classiq/interface/model/quantum_lambda_function.py +3 -16
  209. classiq/interface/model/quantum_statement.py +4 -3
  210. classiq/interface/model/quantum_type.py +5 -5
  211. classiq/interface/model/statement_block.py +2 -3
  212. classiq/interface/model/validation_handle.py +5 -4
  213. classiq/interface/server/global_versions.py +3 -3
  214. classiq/model_expansions/atomic_expression_functions_defs.py +3 -2
  215. classiq/model_expansions/call_to_model_converter.py +190 -0
  216. classiq/model_expansions/capturing/captured_var_manager.py +4 -6
  217. classiq/model_expansions/capturing/propagated_var_stack.py +7 -7
  218. classiq/model_expansions/closure.py +17 -9
  219. classiq/model_expansions/evaluators/arg_type_match.py +3 -2
  220. classiq/model_expansions/evaluators/argument_types.py +3 -3
  221. classiq/model_expansions/evaluators/control.py +3 -3
  222. classiq/model_expansions/evaluators/parameter_types.py +7 -7
  223. classiq/model_expansions/evaluators/quantum_type_utils.py +2 -1
  224. classiq/model_expansions/evaluators/type_type_match.py +1 -1
  225. classiq/model_expansions/expression_evaluator.py +10 -9
  226. classiq/model_expansions/expression_renamer.py +6 -6
  227. classiq/model_expansions/function_builder.py +19 -12
  228. classiq/model_expansions/generative_functions.py +3 -2
  229. classiq/model_expansions/interpreter.py +31 -19
  230. classiq/model_expansions/model_tables.py +14 -14
  231. classiq/model_expansions/quantum_operations/bind.py +2 -4
  232. classiq/model_expansions/quantum_operations/classicalif.py +1 -1
  233. classiq/model_expansions/quantum_operations/control.py +2 -4
  234. classiq/model_expansions/quantum_operations/emitter.py +10 -13
  235. classiq/model_expansions/quantum_operations/expression_operation.py +23 -16
  236. classiq/model_expansions/quantum_operations/inplace_binary_operation.py +160 -35
  237. classiq/model_expansions/quantum_operations/phase.py +6 -6
  238. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +25 -5
  239. classiq/model_expansions/quantum_operations/quantum_function_call.py +41 -2
  240. classiq/model_expansions/quantum_operations/repeat.py +1 -3
  241. classiq/model_expansions/scope.py +11 -10
  242. classiq/model_expansions/scope_initialization.py +6 -5
  243. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +6 -6
  244. classiq/model_expansions/sympy_conversion/sympy_to_python.py +2 -2
  245. classiq/model_expansions/visitors/variable_references.py +5 -4
  246. classiq/qmod/builtins/classical_execution_primitives.py +9 -9
  247. classiq/qmod/builtins/functions/__init__.py +72 -55
  248. classiq/qmod/builtins/functions/amplitude_estimation.py +4 -1
  249. classiq/qmod/builtins/functions/arithmetic.py +14 -1
  250. classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +86 -6
  251. classiq/qmod/builtins/functions/grover.py +41 -45
  252. classiq/qmod/builtins/functions/hea.py +60 -4
  253. classiq/qmod/builtins/functions/linear_pauli_rotation.py +26 -4
  254. classiq/qmod/builtins/functions/modular_exponentiation.py +90 -29
  255. classiq/qmod/builtins/functions/operators.py +1 -1
  256. classiq/qmod/builtins/functions/qaoa_penalty.py +14 -5
  257. classiq/qmod/builtins/functions/qft_functions.py +57 -0
  258. classiq/qmod/builtins/functions/qpe.py +20 -4
  259. classiq/qmod/builtins/functions/qsvt.py +49 -4
  260. classiq/qmod/builtins/functions/standard_gates.py +4 -4
  261. classiq/qmod/builtins/functions/state_preparation.py +92 -10
  262. classiq/qmod/builtins/functions/swap_test.py +7 -1
  263. classiq/qmod/builtins/functions/utility_functions.py +43 -0
  264. classiq/qmod/builtins/functions/variational.py +18 -2
  265. classiq/qmod/builtins/operations.py +4 -5
  266. classiq/qmod/cfunc.py +2 -2
  267. classiq/qmod/classical_function.py +3 -7
  268. classiq/qmod/create_model_function.py +7 -6
  269. classiq/qmod/declaration_inferrer.py +7 -10
  270. classiq/qmod/expression_query.py +3 -3
  271. classiq/qmod/generative.py +2 -1
  272. classiq/qmod/model_state_container.py +5 -7
  273. classiq/qmod/native/__init__.py +1 -3
  274. classiq/qmod/native/expression_to_qmod.py +9 -8
  275. classiq/qmod/native/pretty_printer.py +6 -5
  276. classiq/qmod/pretty_print/__init__.py +1 -3
  277. classiq/qmod/pretty_print/expression_to_python.py +13 -12
  278. classiq/qmod/pretty_print/pretty_printer.py +13 -12
  279. classiq/qmod/python_classical_type.py +8 -4
  280. classiq/qmod/qfunc.py +4 -4
  281. classiq/qmod/qmod_variable.py +11 -10
  282. classiq/qmod/quantum_expandable.py +12 -15
  283. classiq/qmod/quantum_function.py +10 -3
  284. classiq/qmod/semantics/annotation.py +1 -1
  285. classiq/qmod/semantics/error_manager.py +8 -7
  286. classiq/qmod/semantics/static_semantics_visitor.py +19 -24
  287. classiq/qmod/semantics/validation/constants_validation.py +1 -1
  288. classiq/qmod/semantics/validation/func_call_validation.py +2 -2
  289. classiq/qmod/semantics/validation/main_validation.py +33 -0
  290. classiq/qmod/semantics/validation/types_validation.py +2 -1
  291. classiq/qmod/symbolic.py +5 -8
  292. classiq/qmod/symbolic_type.py +2 -2
  293. {classiq-0.53.0.dist-info → classiq-0.54.0.dist-info}/METADATA +1 -1
  294. {classiq-0.53.0.dist-info → classiq-0.54.0.dist-info}/RECORD +295 -292
  295. classiq/qmod/builtins/functions/qft.py +0 -23
  296. {classiq-0.53.0.dist-info → classiq-0.54.0.dist-info}/WHEEL +0 -0
@@ -1,10 +1,12 @@
1
- from typing import TYPE_CHECKING, List, Tuple, Union
1
+ from typing import TYPE_CHECKING, Optional, Union
2
2
 
3
+ from classiq.interface.exceptions import ClassiqInternalExpansionError
3
4
  from classiq.interface.generator.expressions.expression import Expression
4
5
  from classiq.interface.generator.functions.port_declaration import (
5
6
  PortDeclarationDirection,
6
7
  )
7
8
  from classiq.interface.model.bind_operation import BindOperation
9
+ from classiq.interface.model.control import Control
8
10
  from classiq.interface.model.handle_binding import HandleBinding
9
11
  from classiq.interface.model.inplace_binary_operation import (
10
12
  BinaryOperation,
@@ -16,11 +18,7 @@ from classiq.interface.model.quantum_function_declaration import (
16
18
  NamedParamsQuantumFunctionDeclaration,
17
19
  )
18
20
  from classiq.interface.model.quantum_statement import QuantumStatement
19
- from classiq.interface.model.quantum_type import (
20
- QuantumBit,
21
- QuantumBitvector,
22
- QuantumNumeric,
23
- )
21
+ from classiq.interface.model.quantum_type import QuantumBitvector, QuantumNumeric
24
22
  from classiq.interface.model.variable_declaration_statement import (
25
23
  VariableDeclarationStatement,
26
24
  )
@@ -38,6 +36,7 @@ from classiq.model_expansions.scope import QuantumSymbol, Scope
38
36
  from classiq.qmod.builtins.functions import (
39
37
  CX,
40
38
  allocate,
39
+ apply_to_all,
41
40
  integer_xor,
42
41
  modular_add,
43
42
  modular_add_constant,
@@ -94,6 +93,18 @@ class InplaceBinaryOperationEmitter(Emitter[InplaceBinaryOperation]):
94
93
  handle=HandleBinding(name="target"),
95
94
  quantum_type=target_var.quantum_type,
96
95
  )
96
+ internal_func_decl = _binary_function_declaration(op.operation, constant=False)
97
+ if op.operation == BinaryOperation.Xor:
98
+ body = _build_inplace_xor_operation(
99
+ value_var=value_var,
100
+ target_var=target_var,
101
+ )
102
+ else:
103
+ body = _build_inplace_binary_operation(
104
+ value_var=value_var,
105
+ target_var=target_var,
106
+ internal_function_declaration=internal_func_decl,
107
+ )
97
108
  inplace_binary_op_function = FunctionClosure.create(
98
109
  name=op.operation.value,
99
110
  positional_arg_declarations=[
@@ -108,13 +119,7 @@ class InplaceBinaryOperationEmitter(Emitter[InplaceBinaryOperation]):
108
119
  direction=PortDeclarationDirection.Inout,
109
120
  ),
110
121
  ],
111
- body=_build_inplace_binary_operation(
112
- value_var=value_var,
113
- target_var=target_var,
114
- internal_function_declaration=_binary_function_declaration(
115
- op.operation, constant=False
116
- ),
117
- ),
122
+ body=body,
118
123
  scope=Scope(parent=self._current_scope),
119
124
  )
120
125
  with self._propagated_var_stack.capture_variables(op):
@@ -139,7 +144,7 @@ def _build_inplace_binary_operation(
139
144
  value_var: QuantumSymbol,
140
145
  target_var: QuantumSymbol,
141
146
  internal_function_declaration: NamedParamsQuantumFunctionDeclaration,
142
- ) -> List[QuantumStatement]:
147
+ ) -> list[QuantumStatement]:
143
148
  if TYPE_CHECKING:
144
149
  assert isinstance(value_var.quantum_type, QuantumNumeric)
145
150
  assert isinstance(target_var.quantum_type, QuantumNumeric)
@@ -192,6 +197,54 @@ def _build_inplace_binary_operation(
192
197
  ]
193
198
 
194
199
 
200
+ def _build_inplace_xor_operation(
201
+ value_var: QuantumSymbol, target_var: QuantumSymbol
202
+ ) -> list[QuantumStatement]:
203
+ if TYPE_CHECKING:
204
+ assert isinstance(value_var.quantum_type, QuantumNumeric)
205
+ assert isinstance(target_var.quantum_type, QuantumNumeric)
206
+
207
+ frac_digits_diff = (
208
+ value_var.quantum_type.fraction_digits_value
209
+ - target_var.quantum_type.fraction_digits_value
210
+ )
211
+
212
+ target_overlap_var, target_var_decls, target_bind_ops = (
213
+ _trim_superfluous_fraction_digits("target", target_var, -frac_digits_diff)
214
+ )
215
+ value_overlap_var, value_trim_var_decls, value_bind_ops = (
216
+ _trim_superfluous_fraction_digits("value", value_var, frac_digits_diff)
217
+ )
218
+ target_left_var, value_left_var, sign_var_decls, sign_bind_ops, sign_xor = (
219
+ _split_and_xor_sign(target_overlap_var, value_overlap_var)
220
+ )
221
+
222
+ action: list[QuantumStatement] = []
223
+ if target_left_var is not None and value_left_var is not None:
224
+ action.append(
225
+ _internal_inplace_binary_operation_function_call(
226
+ integer_xor.func_decl,
227
+ value_left_var.handle,
228
+ target_left_var.handle,
229
+ )
230
+ )
231
+ action.extend(sign_xor)
232
+
233
+ return [
234
+ *target_var_decls,
235
+ *value_trim_var_decls,
236
+ *sign_var_decls,
237
+ WithinApply(
238
+ compute=[
239
+ *target_bind_ops,
240
+ *value_bind_ops,
241
+ *sign_bind_ops,
242
+ ],
243
+ action=action,
244
+ ),
245
+ ]
246
+
247
+
195
248
  def _internal_inplace_binary_operation_function_call(
196
249
  internal_function_declaration: NamedParamsQuantumFunctionDeclaration,
197
250
  value: Union[HandleBinding, Expression],
@@ -207,7 +260,7 @@ def _internal_inplace_binary_operation_function_call(
207
260
 
208
261
  def _trim_superfluous_fraction_digits(
209
262
  kind: str, var: QuantumSymbol, frac_digits_diff: int
210
- ) -> Tuple[QuantumSymbol, List[VariableDeclarationStatement], List[BindOperation]]:
263
+ ) -> tuple[QuantumSymbol, list[VariableDeclarationStatement], list[BindOperation]]:
211
264
  if frac_digits_diff <= 0:
212
265
  return var, [], []
213
266
 
@@ -246,12 +299,12 @@ def _trim_superfluous_fraction_digits(
246
299
  return overlap_var, split_var_declarations, [bind_op]
247
300
 
248
301
 
249
- def _pad_with_sign_bit(kind: str, var: QuantumSymbol, size_diff: int) -> Tuple[
302
+ def _pad_with_sign_bit(kind: str, var: QuantumSymbol, size_diff: int) -> tuple[
250
303
  QuantumSymbol,
251
- List[VariableDeclarationStatement],
252
- List[QuantumStatement],
253
- List[QuantumFunctionCall],
254
- List[BindOperation],
304
+ list[VariableDeclarationStatement],
305
+ list[QuantumStatement],
306
+ list[QuantumFunctionCall],
307
+ list[BindOperation],
255
308
  ]:
256
309
  quantum_type = var.quantum_type
257
310
  if TYPE_CHECKING:
@@ -291,7 +344,7 @@ def _pad_with_sign_bit(kind: str, var: QuantumSymbol, size_diff: int) -> Tuple[
291
344
  [padding_rebind],
292
345
  )
293
346
 
294
- significand_var, sign_var, sign_split_bind = _split_sign(kind, var)
347
+ significand_var, sign_var, sign_split_bind = _split_var(kind, var, 1)
295
348
  padding_init_ops = _init_padding(sign_var, padding_var, size_diff)
296
349
 
297
350
  padding_rebind = BindOperation(
@@ -318,7 +371,7 @@ def _pad_with_sign_bit(kind: str, var: QuantumSymbol, size_diff: int) -> Tuple[
318
371
 
319
372
  def _init_padding(
320
373
  sign_var: QuantumSymbol, padding_var: QuantumSymbol, size_diff: int
321
- ) -> List[QuantumFunctionCall]:
374
+ ) -> list[QuantumFunctionCall]:
322
375
  padding_init_ops = [
323
376
  QuantumFunctionCall(
324
377
  function=CX.func_decl.name,
@@ -333,7 +386,7 @@ def _init_padding(
333
386
 
334
387
  def _allocate_padding(
335
388
  kind: str, size_diff: int
336
- ) -> Tuple[QuantumSymbol, QuantumFunctionCall]:
389
+ ) -> tuple[QuantumSymbol, QuantumFunctionCall]:
337
390
  padding_var = QuantumSymbol(
338
391
  handle=HandleBinding(name=f"{kind}_sign_padding"),
339
392
  quantum_type=QuantumBitvector(
@@ -348,23 +401,95 @@ def _allocate_padding(
348
401
  return padding_var, padding_allocation
349
402
 
350
403
 
351
- def _split_sign(
352
- kind: str, var: QuantumSymbol
353
- ) -> Tuple[QuantumSymbol, QuantumSymbol, BindOperation]:
354
- significand_var = QuantumSymbol(
355
- handle=HandleBinding(name=f"{kind}_significand"),
404
+ def _split_var(
405
+ kind: str, var: QuantumSymbol, right_size: int
406
+ ) -> tuple[QuantumSymbol, QuantumSymbol, BindOperation]:
407
+ left_var = QuantumSymbol(
408
+ handle=HandleBinding(name=f"{kind}_left"),
356
409
  quantum_type=QuantumNumeric(
357
- size=Expression(expr=str(var.quantum_type.size_in_bits - 1)),
410
+ size=Expression(expr=str(var.quantum_type.size_in_bits - right_size)),
358
411
  is_signed=Expression(expr="False"),
359
412
  fraction_digits=Expression(expr="0"),
360
413
  ),
361
414
  )
362
- sign_var = QuantumSymbol(
363
- handle=HandleBinding(name=f"{kind}_sign_bit"),
364
- quantum_type=QuantumBit(),
415
+ right_var = QuantumSymbol(
416
+ handle=HandleBinding(name=f"{kind}_right"),
417
+ quantum_type=QuantumNumeric(
418
+ size=Expression(expr=str(right_size)),
419
+ is_signed=Expression(expr="False"),
420
+ fraction_digits=Expression(expr="0"),
421
+ ),
365
422
  )
366
- sign_split_bind = BindOperation(
423
+ split_bind = BindOperation(
367
424
  in_handles=[var.handle],
368
- out_handles=[significand_var.handle, sign_var.handle],
425
+ out_handles=[left_var.handle, right_var.handle],
426
+ )
427
+ return left_var, right_var, split_bind
428
+
429
+
430
+ def _split_and_xor_sign(target_var: QuantumSymbol, value_var: QuantumSymbol) -> tuple[
431
+ Optional[QuantumSymbol],
432
+ Optional[QuantumSymbol],
433
+ list[VariableDeclarationStatement],
434
+ list[BindOperation],
435
+ list[Control],
436
+ ]:
437
+ if TYPE_CHECKING:
438
+ assert isinstance(value_var.quantum_type, QuantumNumeric)
439
+ assert isinstance(target_var.quantum_type, QuantumNumeric)
440
+ size_diff = (
441
+ value_var.quantum_type.size_in_bits - target_var.quantum_type.size_in_bits
442
+ )
443
+ if not value_var.quantum_type.sign_value or size_diff >= 0:
444
+ return target_var, value_var, [], [], []
445
+
446
+ if value_var.quantum_type.size_in_bits == 1:
447
+ return None, None, [], [], [_xor_sign(target_var, value_var)]
448
+
449
+ value_rest_var, value_sign_var, value_split_bind = _split_var("value", value_var, 1)
450
+ target_left_var, target_right_var, target_split_bind = _split_var(
451
+ "target", target_var, -size_diff + 1
452
+ )
453
+ var_decls = [
454
+ VariableDeclarationStatement(
455
+ name=var.handle.name,
456
+ quantum_type=var.quantum_type,
457
+ )
458
+ for var in (value_rest_var, value_sign_var, target_left_var, target_right_var)
459
+ ]
460
+ bind_ops = [value_split_bind, target_split_bind]
461
+ sign_xor = _xor_sign(target_right_var, value_sign_var)
462
+ return target_left_var, value_rest_var, var_decls, bind_ops, [sign_xor]
463
+
464
+
465
+ def _xor_sign(target_var: QuantumSymbol, value_var: QuantumSymbol) -> Control:
466
+ quantum_type = value_var.quantum_type
467
+ if TYPE_CHECKING:
468
+ assert isinstance(quantum_type, QuantumNumeric)
469
+ if quantum_type.size_in_bits != 1 or quantum_type.fraction_digits_value not in (
470
+ 0,
471
+ 1,
472
+ ):
473
+ raise ClassiqInternalExpansionError
474
+
475
+ inner_xor = QuantumFunctionCall(
476
+ function=apply_to_all.func_decl.name,
477
+ positional_args=["X", target_var.handle],
478
+ )
479
+ inner_xor.set_func_decl(apply_to_all.func_decl)
480
+
481
+ if quantum_type.sign_value:
482
+ if quantum_type.fraction_digits_value == 1:
483
+ ctrl_value = -0.5
484
+ else:
485
+ ctrl_value = -1
486
+ else:
487
+ if quantum_type.fraction_digits_value == 1:
488
+ ctrl_value = 0.5
489
+ else:
490
+ ctrl_value = 1
491
+
492
+ return Control(
493
+ expression=Expression(expr=f"{value_var.handle} == {ctrl_value}"),
494
+ body=[inner_xor],
369
495
  )
370
- return significand_var, sign_var, sign_split_bind
@@ -1,4 +1,4 @@
1
- from typing import TYPE_CHECKING, Dict, List, Tuple
1
+ from typing import TYPE_CHECKING
2
2
 
3
3
  import sympy
4
4
  from sympy import sympify
@@ -108,8 +108,8 @@ class PhaseEmitter(ExpressionOperationEmitter[PhaseOperation]):
108
108
 
109
109
 
110
110
  def _get_single_bit_vars_expression(
111
- expr: sympy.Expr, vars_info: Dict[str, QuantumScalar]
112
- ) -> Tuple[sympy.Expr, List[sympy.Symbol]]:
111
+ expr: sympy.Expr, vars_info: dict[str, QuantumScalar]
112
+ ) -> tuple[sympy.Expr, list[sympy.Symbol]]:
113
113
  bit_vars = []
114
114
  for var_name, var_info in vars_info.items():
115
115
  size = var_info.size_in_bits
@@ -139,9 +139,9 @@ def _get_single_bit_vars_expression(
139
139
 
140
140
 
141
141
  def _convert_ising_sympy_to_pauli_terms(
142
- ising_expr: sympy.Expr, ordered_sympy_vars: List[sympy.Symbol]
142
+ ising_expr: sympy.Expr, ordered_sympy_vars: list[sympy.Symbol]
143
143
  ) -> str:
144
- pauli_terms: List[str] = []
144
+ pauli_terms: list[str] = []
145
145
  coefficients = ising_expr.as_coefficients_dict(*ordered_sympy_vars)
146
146
  for expr_term in ising_expr.args:
147
147
  expr_vars = _get_vars(expr_term)
@@ -171,7 +171,7 @@ def _convert_ising_sympy_to_pauli_terms(
171
171
 
172
172
  def _convert_cost_expression_to_hamiltonian(
173
173
  expr: str,
174
- vars: Dict[str, QuantumScalar],
174
+ vars: dict[str, QuantumScalar],
175
175
  ) -> Expression:
176
176
  sympy_expr = sympify(expr)
177
177
  single_bit_vars_expression, single_bit_vars = _get_single_bit_vars_expression(
@@ -1,6 +1,5 @@
1
1
  import ast
2
2
  import re
3
- from typing import Tuple
4
3
 
5
4
  from classiq.interface.exceptions import (
6
5
  ClassiqExpansionError,
@@ -23,6 +22,7 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
23
22
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
24
23
  from classiq.interface.model.quantum_type import (
25
24
  QuantumNumeric,
25
+ QuantumType,
26
26
  )
27
27
  from classiq.interface.model.variable_declaration_statement import (
28
28
  VariableDeclarationStatement,
@@ -41,6 +41,10 @@ from classiq.model_expansions.visitors.boolean_expression_transformers import (
41
41
  from classiq.qmod import builtins
42
42
  from classiq.qmod.builtins.functions import X, allocate
43
43
 
44
+ HANDLE_ERROR_MESSAGE = (
45
+ "Quantum variable '{handle_str}' cannot appear on both sides of the assignment"
46
+ )
47
+
44
48
 
45
49
  def _is_constant(expr: str) -> bool:
46
50
  try:
@@ -129,7 +133,7 @@ class QuantumAssignmentOperationEmitter(
129
133
 
130
134
  def _optimize_boolean_expression(
131
135
  self, op: ArithmeticOperation, expression: Expression
132
- ) -> Tuple[ArithmeticOperation, Expression, bool]:
136
+ ) -> tuple[ArithmeticOperation, Expression, bool]:
133
137
  if (
134
138
  self._interpreter._is_frontend
135
139
  or op.operation_kind
@@ -150,7 +154,7 @@ class QuantumAssignmentOperationEmitter(
150
154
 
151
155
  def _adapt_boolean_inplace(
152
156
  self, op: ArithmeticOperation, expression: Expression, is_bool_opt: bool
153
- ) -> Tuple[ArithmeticOperation, Expression, bool]:
157
+ ) -> tuple[ArithmeticOperation, Expression, bool]:
154
158
  adapter = BooleanExpressionFuncLibAdapter(is_bool_opt)
155
159
  adapted_expression = self._evaluate_expression(
156
160
  Expression(expr=ast.unparse(adapter.visit(ast.parse(expression.expr))))
@@ -223,12 +227,28 @@ class QuantumAssignmentOperationEmitter(
223
227
  self._interpreter.emit_statement(allocate_call)
224
228
  return True
225
229
 
230
+ @staticmethod
231
+ def _get_updated_op_split_symbols(
232
+ op: QuantumAssignmentOperation,
233
+ symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
234
+ ) -> QuantumAssignmentOperation:
235
+ if op.result_var not in symbol_mapping:
236
+ return op
237
+ handle_str, quantum_type = symbol_mapping[op.result_var]
238
+ if handle_str in op.expression.expr:
239
+ raise ClassiqExpansionError(
240
+ HANDLE_ERROR_MESSAGE.format(handle_str=str(op.result_var))
241
+ )
242
+ new_result_handle = HandleBinding(name=handle_str)
243
+ return op.model_copy(
244
+ update=dict(result_var=new_result_handle, _result_type=quantum_type)
245
+ )
246
+
226
247
 
227
248
  def _validate_naive_inplace_handles(qe: ArithmeticOperation) -> None:
228
249
  if qe.result_var in qe.var_handles:
229
250
  raise ClassiqExpansionError(
230
- f"Quantum variable {qe.result_var.name} cannot appear on both sides of "
231
- f"the ^= assignment"
251
+ HANDLE_ERROR_MESSAGE.format(handle_str=str(qe.result_var))
232
252
  )
233
253
 
234
254
 
@@ -1,15 +1,54 @@
1
+ from typing import TYPE_CHECKING
2
+
1
3
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
2
4
 
5
+ from classiq.model_expansions.call_to_model_converter import (
6
+ BlockFunctionInfo,
7
+ CallToModelConverter,
8
+ )
3
9
  from classiq.model_expansions.closure import FunctionClosure
4
10
  from classiq.model_expansions.quantum_operations.emitter import Emitter
5
11
  from classiq.qmod.semantics.error_manager import ErrorManager
6
12
 
13
+ if TYPE_CHECKING:
14
+ from classiq.model_expansions.interpreter import Interpreter
15
+
7
16
 
8
17
  class QuantumFunctionCallEmitter(Emitter[QuantumFunctionCall]):
18
+ def __init__(self, interpreter: "Interpreter") -> None:
19
+ super().__init__(interpreter)
20
+ self._model = self._interpreter._model
21
+ self._synthesized_separately_blocks = (
22
+ self._interpreter._synthesized_separately_blocks
23
+ )
24
+
9
25
  def emit(self, call: QuantumFunctionCall, /) -> None:
10
- function = self._interpreter.evaluate(call.function).as_type(FunctionClosure)
26
+ function: FunctionClosure = self._interpreter.evaluate(call.function).as_type(
27
+ FunctionClosure
28
+ )
11
29
  args = call.positional_args
12
30
  with ErrorManager().call(
13
31
  function.name
14
32
  ), function.scope.freeze(), self._propagated_var_stack.capture_variables(call):
15
- self._emit_quantum_function_call(function, args)
33
+ new_call = self._emit_quantum_function_call(function, args)
34
+ if function.synthesis_data.should_synthesize_separately:
35
+ interpreted_call_converter = CallToModelConverter(
36
+ call,
37
+ function.positional_arg_declarations,
38
+ function.scope.data,
39
+ self._model,
40
+ )
41
+ self._update_synthesized_separately_models(
42
+ interpreted_call_converter, new_call.func_name
43
+ )
44
+
45
+ def _update_synthesized_separately_models(
46
+ self, call_converter: CallToModelConverter, call_name: str
47
+ ) -> None:
48
+ synthesized_separately_blocks = self._synthesized_separately_blocks
49
+ block_id = call_converter.block_id
50
+ block_function = synthesized_separately_blocks.get(block_id)
51
+ if block_function is None:
52
+ block_function = BlockFunctionInfo.from_call_converter(call_converter)
53
+ synthesized_separately_blocks[block_id] = block_function
54
+ block_function.calls.add(call_name)
@@ -1,5 +1,3 @@
1
- from typing import Type
2
-
3
1
  from classiq.interface.generator.expressions.expression import Expression
4
2
  from classiq.interface.generator.functions.builtins.internal_operators import (
5
3
  REPEAT_OPERATOR_NAME,
@@ -24,7 +22,7 @@ class RepeatEmitter(Emitter[Repeat]):
24
22
  self._emit_propagated(repeat, i)
25
23
 
26
24
  def _emit_propagated(self, repeat: Repeat, i: int) -> None:
27
- closure_constructor: Type[FunctionClosure]
25
+ closure_constructor: type[FunctionClosure]
28
26
  extra_args: dict
29
27
  if repeat.is_generative():
30
28
  closure_constructor = GenerativeFunctionClosure
@@ -1,9 +1,10 @@
1
1
  import itertools
2
2
  from collections import UserDict
3
+ from collections.abc import Iterator
3
4
  from contextlib import contextmanager
4
5
  from dataclasses import dataclass
5
6
  from functools import singledispatch
6
- from typing import TYPE_CHECKING, Any, Dict, Iterator, Optional, Type, TypeVar, Union
7
+ from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
7
8
 
8
9
  from classiq.interface.exceptions import (
9
10
  ClassiqExpansionError,
@@ -104,7 +105,7 @@ class QuantumSymbol:
104
105
  )
105
106
 
106
107
  @property
107
- def fields(self) -> Dict[str, "QuantumSymbol"]:
108
+ def fields(self) -> dict[str, "QuantumSymbol"]:
108
109
  quantum_type = self.quantum_type
109
110
  if not isinstance(quantum_type, TypeName):
110
111
  raise ClassiqExpansionError(
@@ -120,18 +121,18 @@ class QuantumSymbol:
120
121
 
121
122
 
122
123
  @singledispatch
123
- def _evaluated_to_str(value: Any) -> str:
124
+ def evaluated_to_str(value: Any) -> str:
124
125
  return str(value)
125
126
 
126
127
 
127
- @_evaluated_to_str.register
128
+ @evaluated_to_str.register
128
129
  def _evaluated_to_str_list(value: list) -> str:
129
- return f"[{', '.join(_evaluated_to_str(x) for x in value)}]"
130
+ return f"[{', '.join(evaluated_to_str(x) for x in value)}]"
130
131
 
131
132
 
132
- @_evaluated_to_str.register
133
+ @evaluated_to_str.register
133
134
  def _evaluated_to_str_struct_literal(value: QmodStructInstance) -> str:
134
- return f"struct_literal({value.struct_declaration.name}, {', '.join(f'{k}={_evaluated_to_str(v)}' for k, v in value.fields.items())})"
135
+ return f"struct_literal({value.struct_declaration.name}, {', '.join(f'{k}={evaluated_to_str(v)}' for k, v in value.fields.items())})"
135
136
 
136
137
 
137
138
  @dataclass(frozen=True)
@@ -139,7 +140,7 @@ class Evaluated: # FIXME: Merge with EvaluatedExpression if possible
139
140
  value: Any
140
141
  defining_function: Optional["Closure"] = None
141
142
 
142
- def as_type(self, t: Type[T]) -> T:
143
+ def as_type(self, t: type[T]) -> T:
143
144
  if t is int:
144
145
  return self._as_int() # type: ignore[return-value]
145
146
 
@@ -162,7 +163,7 @@ class Evaluated: # FIXME: Merge with EvaluatedExpression if possible
162
163
  if isinstance(self.value, QuantumSymbol):
163
164
  return self.value.emit()
164
165
 
165
- ret = Expression(expr=_evaluated_to_str(self.value))
166
+ ret = Expression(expr=evaluated_to_str(self.value))
166
167
  ret._evaluated_expr = EvaluatedExpression(value=self.value)
167
168
  return ret
168
169
 
@@ -176,7 +177,7 @@ else:
176
177
  class Scope(EvaluatedUserDict):
177
178
  def __init__(
178
179
  self,
179
- data: Optional[Dict[str, Evaluated]] = None,
180
+ data: Optional[dict[str, Evaluated]] = None,
180
181
  /,
181
182
  *,
182
183
  parent: Optional["Scope"] = None,
@@ -1,4 +1,4 @@
1
- from typing import List, Sequence
1
+ from collections.abc import Sequence
2
2
 
3
3
  from classiq.interface.exceptions import ClassiqError
4
4
  from classiq.interface.generator.constant import Constant
@@ -43,7 +43,7 @@ def get_main_renamer(
43
43
  return ExpressionRenamer(var_mapping={})
44
44
 
45
45
 
46
- def _add_constants_to_scope(constants: List[Constant], scope: Scope) -> None:
46
+ def _add_constants_to_scope(constants: list[Constant], scope: Scope) -> None:
47
47
  for constant in constants:
48
48
  scope[constant.name] = Evaluated(
49
49
  value=evaluate_classical_expression(constant.value, scope).value
@@ -51,7 +51,7 @@ def _add_constants_to_scope(constants: List[Constant], scope: Scope) -> None:
51
51
 
52
52
 
53
53
  def _add_functions_to_scope(
54
- functions: List[NativeFunctionDefinition], scope: Scope
54
+ functions: list[NativeFunctionDefinition], scope: Scope
55
55
  ) -> None:
56
56
  for function in functions:
57
57
  scope[function.name] = Evaluated(
@@ -60,12 +60,13 @@ def _add_functions_to_scope(
60
60
  positional_arg_declarations=function.positional_arg_declarations,
61
61
  body=function.body,
62
62
  scope=Scope(parent=scope),
63
+ synthesis_data=function.synthesis_data,
63
64
  )
64
65
  )
65
66
 
66
67
 
67
68
  def _add_generative_functions_to_scope(
68
- functions: List[GenerativeQFunc], scope: Scope
69
+ functions: list[GenerativeQFunc], scope: Scope
69
70
  ) -> None:
70
71
  for function in functions:
71
72
  scope[function.func_decl.name] = Evaluated(
@@ -138,7 +139,7 @@ def add_entry_point_params_to_scope(
138
139
 
139
140
 
140
141
  def init_top_level_scope(
141
- model: Model, generative_functions: List[GenerativeQFunc], scope: Scope
142
+ model: Model, generative_functions: list[GenerativeQFunc], scope: Scope
142
143
  ) -> None:
143
144
  _add_functions_to_scope(model.functions, scope)
144
145
  _add_generative_functions_to_scope(generative_functions, scope)
@@ -1,5 +1,5 @@
1
1
  import ast
2
- from typing import TYPE_CHECKING, Dict, Type, cast
2
+ from typing import TYPE_CHECKING, cast
3
3
 
4
4
  from classiq.interface.exceptions import ClassiqExpansionError
5
5
 
@@ -18,29 +18,29 @@ def translate_to_sympy(expr: str) -> str:
18
18
 
19
19
 
20
20
  class ExpressionSympyTranslator(ast.NodeTransformer):
21
- BINARY_OPERATORS: Dict[Type[ast.AST], str] = {
21
+ BINARY_OPERATORS: dict[type[ast.AST], str] = {
22
22
  ast.BitOr: "BitwiseOr",
23
23
  ast.BitAnd: "BitwiseAnd",
24
24
  ast.BitXor: "BitwiseXor",
25
25
  ast.Div: "do_div",
26
26
  }
27
27
 
28
- UNARY_OPERATORS: Dict[Type[ast.AST], str] = {
28
+ UNARY_OPERATORS: dict[type[ast.AST], str] = {
29
29
  ast.Invert: "BitwiseNot",
30
30
  ast.Not: "Not",
31
31
  }
32
32
 
33
- BOOLEAN_OPERATORS: Dict[Type[ast.AST], str] = {
33
+ BOOLEAN_OPERATORS: dict[type[ast.AST], str] = {
34
34
  ast.Or: "Or",
35
35
  ast.And: "And",
36
36
  }
37
37
 
38
- COMPARE_OPERATORS: Dict[Type[ast.AST], str] = {
38
+ COMPARE_OPERATORS: dict[type[ast.AST], str] = {
39
39
  ast.Eq: "Eq",
40
40
  ast.NotEq: "Ne",
41
41
  }
42
42
 
43
- SPECIAL_FUNCTIONS: Dict[str, str] = {
43
+ SPECIAL_FUNCTIONS: dict[str, str] = {
44
44
  "max": "Max",
45
45
  "min": "Min",
46
46
  }
@@ -1,5 +1,5 @@
1
1
  import functools
2
- from typing import Any, Dict, Optional, get_args
2
+ from typing import Any, Optional, get_args
3
3
 
4
4
  from sympy import (
5
5
  Array,
@@ -22,7 +22,7 @@ from classiq.model_expansions.sympy_conversion.arithmetics import LogicalXor
22
22
 
23
23
 
24
24
  def sympy_to_python(
25
- value: Any, locals: Optional[Dict[str, ExpressionValue]] = None
25
+ value: Any, locals: Optional[dict[str, ExpressionValue]] = None
26
26
  ) -> ExpressionValue:
27
27
  if isinstance(value, Integer):
28
28
  value = int(value)
@@ -1,6 +1,7 @@
1
1
  import ast
2
+ from collections.abc import Iterator
2
3
  from contextlib import contextmanager
3
- from typing import Dict, Iterator, List, Optional, Union
4
+ from typing import Optional, Union
4
5
 
5
6
  from classiq.interface.exceptions import (
6
7
  ClassiqExpansionError,
@@ -23,12 +24,12 @@ from classiq.interface.model.handle_binding import (
23
24
 
24
25
  class VarRefCollector(ast.NodeVisitor):
25
26
  def __init__(self, ignore_duplicated_handles: bool = False) -> None:
26
- self._var_handles: Dict[HandleBinding, bool] = {}
27
+ self._var_handles: dict[HandleBinding, bool] = {}
27
28
  self._ignore_duplicated_handles = ignore_duplicated_handles
28
29
  self._is_nested = False
29
30
 
30
31
  @property
31
- def var_handles(self) -> List[HandleBinding]:
32
+ def var_handles(self) -> list[HandleBinding]:
32
33
  return list(self._var_handles)
33
34
 
34
35
  def visit(self, node: ast.AST) -> Union[
@@ -110,7 +111,7 @@ class VarRefCollector(ast.NodeVisitor):
110
111
 
111
112
 
112
113
  class VarRefTransformer(ast.NodeTransformer):
113
- def __init__(self, var_mapping: Dict[str, str]) -> None:
114
+ def __init__(self, var_mapping: dict[str, str]) -> None:
114
115
  self.var_mapping = var_mapping
115
116
 
116
117
  def visit_Name(self, node: ast.Name) -> ast.Name: