classiq 0.53.0__py3-none-any.whl → 0.55.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 (301) 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/builtins/internal_operators.py +9 -1
  141. classiq/interface/generator/functions/classical_function_declaration.py +4 -3
  142. classiq/interface/generator/functions/classical_type.py +13 -13
  143. classiq/interface/generator/functions/concrete_types.py +1 -2
  144. classiq/interface/generator/functions/function_declaration.py +1 -1
  145. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  146. classiq/interface/generator/functions/type_name.py +3 -2
  147. classiq/interface/generator/generated_circuit_data.py +33 -22
  148. classiq/interface/generator/grover_diffuser.py +7 -7
  149. classiq/interface/generator/grover_operator.py +2 -2
  150. classiq/interface/generator/hardware/hardware_data.py +7 -6
  151. classiq/interface/generator/hardware_efficient_ansatz.py +8 -8
  152. classiq/interface/generator/identity.py +5 -6
  153. classiq/interface/generator/linear_pauli_rotations.py +6 -6
  154. classiq/interface/generator/mcu.py +2 -2
  155. classiq/interface/generator/mcx.py +6 -6
  156. classiq/interface/generator/model/__init__.py +1 -3
  157. classiq/interface/generator/model/constraints.py +2 -2
  158. classiq/interface/generator/model/model.py +5 -6
  159. classiq/interface/generator/model/preferences/preferences.py +11 -6
  160. classiq/interface/generator/model/quantum_register.py +6 -11
  161. classiq/interface/generator/oracles/arithmetic_oracle.py +1 -2
  162. classiq/interface/generator/oracles/custom_oracle.py +2 -2
  163. classiq/interface/generator/oracles/oracle_abc.py +6 -5
  164. classiq/interface/generator/partitioned_register.py +6 -5
  165. classiq/interface/generator/piecewise_linear_amplitude_loading.py +8 -7
  166. classiq/interface/generator/qpe.py +4 -4
  167. classiq/interface/generator/qsvm.py +3 -3
  168. classiq/interface/generator/quantum_function_call.py +24 -29
  169. classiq/interface/generator/quantum_program.py +9 -9
  170. classiq/interface/generator/register_role.py +2 -4
  171. classiq/interface/generator/slice_parsing_utils.py +4 -3
  172. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  173. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  174. classiq/interface/generator/state_preparation/distributions.py +6 -5
  175. classiq/interface/generator/state_preparation/metrics.py +2 -4
  176. classiq/interface/generator/state_preparation/state_preparation.py +4 -4
  177. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +3 -3
  178. classiq/interface/generator/transpiler_basis_gates.py +2 -2
  179. classiq/interface/generator/types/compilation_metadata.py +5 -0
  180. classiq/interface/generator/types/enum_declaration.py +2 -3
  181. classiq/interface/generator/types/qstruct_declaration.py +2 -1
  182. classiq/interface/generator/types/struct_declaration.py +3 -2
  183. classiq/interface/generator/ucc.py +2 -1
  184. classiq/interface/generator/unitary_gate.py +2 -2
  185. classiq/interface/generator/user_defined_function_params.py +1 -1
  186. classiq/interface/generator/validations/flow_graph.py +6 -5
  187. classiq/interface/generator/validations/validator_functions.py +3 -2
  188. classiq/interface/generator/visitor.py +9 -14
  189. classiq/interface/hardware.py +5 -6
  190. classiq/interface/helpers/custom_encoders.py +2 -2
  191. classiq/interface/helpers/custom_pydantic_types.py +8 -9
  192. classiq/interface/helpers/hashable_mixin.py +3 -2
  193. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  194. classiq/interface/helpers/pydantic_model_helpers.py +4 -3
  195. classiq/interface/helpers/validation_helpers.py +2 -2
  196. classiq/interface/ide/ide_data.py +11 -15
  197. classiq/interface/ide/visual_model.py +22 -22
  198. classiq/interface/jobs.py +2 -2
  199. classiq/interface/model/bind_operation.py +5 -4
  200. classiq/interface/model/classical_parameter_declaration.py +2 -2
  201. classiq/interface/model/control.py +22 -1
  202. classiq/interface/model/handle_binding.py +3 -2
  203. classiq/interface/model/inplace_binary_operation.py +2 -1
  204. classiq/interface/model/model.py +16 -11
  205. classiq/interface/model/native_function_definition.py +1 -1
  206. classiq/interface/model/port_declaration.py +2 -2
  207. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +3 -2
  208. classiq/interface/model/quantum_expressions/arithmetic_operation.py +4 -27
  209. classiq/interface/model/quantum_expressions/quantum_expression.py +8 -7
  210. classiq/interface/model/quantum_function_call.py +9 -14
  211. classiq/interface/model/quantum_function_declaration.py +10 -12
  212. classiq/interface/model/quantum_lambda_function.py +3 -16
  213. classiq/interface/model/quantum_statement.py +7 -3
  214. classiq/interface/model/quantum_type.py +5 -5
  215. classiq/interface/model/statement_block.py +2 -3
  216. classiq/interface/model/validation_handle.py +5 -4
  217. classiq/interface/server/global_versions.py +3 -3
  218. classiq/model_expansions/atomic_expression_functions_defs.py +3 -2
  219. classiq/model_expansions/capturing/captured_var_manager.py +4 -6
  220. classiq/model_expansions/capturing/propagated_var_stack.py +7 -7
  221. classiq/model_expansions/closure.py +83 -12
  222. classiq/model_expansions/evaluators/arg_type_match.py +3 -2
  223. classiq/model_expansions/evaluators/argument_types.py +3 -3
  224. classiq/model_expansions/evaluators/control.py +3 -3
  225. classiq/model_expansions/evaluators/parameter_types.py +7 -7
  226. classiq/model_expansions/evaluators/quantum_type_utils.py +2 -1
  227. classiq/model_expansions/evaluators/type_type_match.py +1 -1
  228. classiq/model_expansions/expression_evaluator.py +10 -9
  229. classiq/model_expansions/expression_renamer.py +6 -6
  230. classiq/model_expansions/function_builder.py +13 -12
  231. classiq/model_expansions/generative_functions.py +5 -4
  232. classiq/model_expansions/interpreter.py +20 -11
  233. classiq/model_expansions/model_tables.py +14 -14
  234. classiq/model_expansions/quantum_operations/bind.py +2 -4
  235. classiq/model_expansions/quantum_operations/classicalif.py +1 -1
  236. classiq/model_expansions/quantum_operations/control.py +81 -24
  237. classiq/model_expansions/quantum_operations/emitter.py +33 -20
  238. classiq/model_expansions/quantum_operations/expression_operation.py +47 -16
  239. classiq/model_expansions/quantum_operations/inplace_binary_operation.py +160 -35
  240. classiq/model_expansions/quantum_operations/phase.py +6 -6
  241. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +28 -31
  242. classiq/model_expansions/quantum_operations/quantum_function_call.py +9 -0
  243. classiq/model_expansions/quantum_operations/repeat.py +1 -3
  244. classiq/model_expansions/quantum_operations/within_apply.py +0 -16
  245. classiq/model_expansions/scope.py +11 -10
  246. classiq/model_expansions/scope_initialization.py +5 -5
  247. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +6 -6
  248. classiq/model_expansions/sympy_conversion/sympy_to_python.py +2 -2
  249. classiq/model_expansions/visitors/variable_references.py +5 -4
  250. classiq/qmod/builtins/classical_execution_primitives.py +9 -9
  251. classiq/qmod/builtins/functions/__init__.py +72 -55
  252. classiq/qmod/builtins/functions/amplitude_estimation.py +4 -1
  253. classiq/qmod/builtins/functions/arithmetic.py +14 -1
  254. classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +86 -6
  255. classiq/qmod/builtins/functions/grover.py +41 -45
  256. classiq/qmod/builtins/functions/hea.py +60 -4
  257. classiq/qmod/builtins/functions/linear_pauli_rotation.py +26 -4
  258. classiq/qmod/builtins/functions/modular_exponentiation.py +90 -29
  259. classiq/qmod/builtins/functions/operators.py +1 -1
  260. classiq/qmod/builtins/functions/qaoa_penalty.py +14 -5
  261. classiq/qmod/builtins/functions/qft_functions.py +57 -0
  262. classiq/qmod/builtins/functions/qpe.py +20 -4
  263. classiq/qmod/builtins/functions/qsvt.py +49 -4
  264. classiq/qmod/builtins/functions/standard_gates.py +4 -4
  265. classiq/qmod/builtins/functions/state_preparation.py +92 -10
  266. classiq/qmod/builtins/functions/swap_test.py +7 -1
  267. classiq/qmod/builtins/functions/utility_functions.py +43 -0
  268. classiq/qmod/builtins/functions/variational.py +18 -2
  269. classiq/qmod/builtins/operations.py +117 -22
  270. classiq/qmod/cfunc.py +2 -2
  271. classiq/qmod/classical_function.py +3 -7
  272. classiq/qmod/create_model_function.py +16 -17
  273. classiq/qmod/declaration_inferrer.py +7 -10
  274. classiq/qmod/expression_query.py +3 -3
  275. classiq/qmod/generative.py +2 -1
  276. classiq/qmod/model_state_container.py +10 -8
  277. classiq/qmod/native/__init__.py +1 -3
  278. classiq/qmod/native/expression_to_qmod.py +9 -8
  279. classiq/qmod/native/pretty_printer.py +12 -6
  280. classiq/qmod/pretty_print/__init__.py +1 -3
  281. classiq/qmod/pretty_print/expression_to_python.py +13 -12
  282. classiq/qmod/pretty_print/pretty_printer.py +38 -23
  283. classiq/qmod/python_classical_type.py +8 -4
  284. classiq/qmod/qfunc.py +4 -4
  285. classiq/qmod/qmod_variable.py +11 -10
  286. classiq/qmod/quantum_expandable.py +12 -15
  287. classiq/qmod/quantum_function.py +35 -22
  288. classiq/qmod/semantics/annotation.py +1 -1
  289. classiq/qmod/semantics/error_manager.py +8 -7
  290. classiq/qmod/semantics/static_semantics_visitor.py +19 -24
  291. classiq/qmod/semantics/validation/constants_validation.py +1 -1
  292. classiq/qmod/semantics/validation/func_call_validation.py +2 -2
  293. classiq/qmod/semantics/validation/main_validation.py +33 -0
  294. classiq/qmod/semantics/validation/types_validation.py +2 -1
  295. classiq/qmod/symbolic.py +5 -8
  296. classiq/qmod/symbolic_type.py +2 -2
  297. classiq/qmod/synthesize_separately.py +1 -2
  298. {classiq-0.53.0.dist-info → classiq-0.55.0.dist-info}/METADATA +1 -1
  299. {classiq-0.53.0.dist-info → classiq-0.55.0.dist-info}/RECORD +300 -297
  300. classiq/qmod/builtins/functions/qft.py +0 -23
  301. {classiq-0.53.0.dist-info → classiq-0.55.0.dist-info}/WHEEL +0 -0
@@ -1,6 +1,7 @@
1
+ from collections.abc import Iterable, Iterator, Sequence
1
2
  from contextlib import contextmanager
2
3
  from dataclasses import dataclass, field
3
- from typing import Dict, Generic, Iterable, Iterator, List, Optional, Sequence, TypeVar
4
+ from typing import Generic, Optional, TypeVar
4
5
 
5
6
  from classiq.interface.exceptions import (
6
7
  ClassiqExpansionError,
@@ -35,14 +36,14 @@ ClosureType = TypeVar("ClosureType", bound=Closure)
35
36
 
36
37
  @dataclass
37
38
  class Block:
38
- statements: List[QuantumStatement] = field(default_factory=list)
39
- captured_vars: List[PortDeclaration] = field(default_factory=list)
39
+ statements: list[QuantumStatement] = field(default_factory=list)
40
+ captured_vars: list[PortDeclaration] = field(default_factory=list)
40
41
 
41
42
 
42
43
  @dataclass
43
44
  class OperationContext(Generic[ClosureType]):
44
45
  closure: ClosureType
45
- blocks: Dict[str, Block] = field(default_factory=dict)
46
+ blocks: dict[str, Block] = field(default_factory=dict)
46
47
 
47
48
  @property
48
49
  def name(self) -> str:
@@ -52,7 +53,7 @@ class OperationContext(Generic[ClosureType]):
52
53
  def positional_arg_declarations(self) -> Sequence[PositionalArg]:
53
54
  return self.closure.positional_arg_declarations
54
55
 
55
- def statements(self, block_name: str) -> List[QuantumStatement]:
56
+ def statements(self, block_name: str) -> list[QuantumStatement]:
56
57
  return self.blocks[block_name].statements
57
58
 
58
59
 
@@ -63,11 +64,11 @@ class FunctionContext(OperationContext[FunctionClosure]):
63
64
  return cls(original_function, {"body": Block()})
64
65
 
65
66
  @property
66
- def body(self) -> List[QuantumStatement]:
67
+ def body(self) -> list[QuantumStatement]:
67
68
  return self.statements("body")
68
69
 
69
70
  @property
70
- def captured_vars(self) -> List[PortDeclaration]:
71
+ def captured_vars(self) -> list[PortDeclaration]:
71
72
  return self.blocks["body"].captured_vars
72
73
 
73
74
  @property
@@ -77,8 +78,8 @@ class FunctionContext(OperationContext[FunctionClosure]):
77
78
 
78
79
  class OperationBuilder:
79
80
  def __init__(self) -> None:
80
- self._operations: List[OperationContext] = []
81
- self._blocks: List[str] = []
81
+ self._operations: list[OperationContext] = []
82
+ self._blocks: list[str] = []
82
83
  self._counter = 0
83
84
 
84
85
  @property
@@ -93,7 +94,7 @@ class OperationBuilder:
93
94
  raise ClassiqInternalExpansionError("No function found")
94
95
 
95
96
  @property
96
- def _current_statements(self) -> List[QuantumStatement]:
97
+ def _current_statements(self) -> list[QuantumStatement]:
97
98
  return self._operations[-1].blocks[self._blocks[-1]].statements
98
99
 
99
100
  def emit_statement(self, statement: QuantumStatement) -> None:
@@ -160,7 +161,7 @@ class OperationBuilder:
160
161
  name = f"{name}_{LAMBDA_KEYWORD + '_0_0_' if function_context.is_lambda else ''}{EXPANDED_KEYWORD}_{self._counter}"
161
162
  self._counter += 1
162
163
 
163
- new_parameters: List[PortDeclaration] = [
164
+ new_parameters: list[PortDeclaration] = [
164
165
  param
165
166
  for param in function_context.positional_arg_declarations
166
167
  if isinstance(param, PortDeclaration)
@@ -173,7 +174,7 @@ class OperationBuilder:
173
174
  )
174
175
 
175
176
 
176
- def validate_captured_vars(captured_vars: List[PortDeclaration]) -> None:
177
+ def validate_captured_vars(captured_vars: list[PortDeclaration]) -> None:
177
178
  if input_captured := [
178
179
  demangle_name(var.name)
179
180
  for var in captured_vars
@@ -1,4 +1,5 @@
1
- from typing import TYPE_CHECKING, Any, List, Mapping
1
+ from collections.abc import Mapping
2
+ from typing import TYPE_CHECKING, Any
2
3
 
3
4
  from classiq.interface.exceptions import ClassiqInternalExpansionError
4
5
  from classiq.interface.generator.expressions.qmod_struct_instance import (
@@ -127,7 +128,7 @@ class _InterpreterExpandable(QFunc):
127
128
  def emit_generative_statements(
128
129
  interpreter: "Interpreter",
129
130
  operation: GenerativeClosure,
130
- args: List[Evaluated],
131
+ args: list[Evaluated],
131
132
  ) -> None:
132
133
  python_qmod_args = [
133
134
  translate_ast_arg_to_python_qmod(param, arg)
@@ -185,7 +186,7 @@ def _expand_operand_as_declarative(
185
186
 
186
187
 
187
188
  def _register_declarative_function(interpreter: "Interpreter", func_name: str) -> None:
188
- if func_name in nameables_to_dict(interpreter._expanded_functions):
189
+ if func_name in nameables_to_dict(list(interpreter._expanded_functions.values())):
189
190
  return
190
191
 
191
192
  for user_gen_func in interpreter._generative_functions:
@@ -198,7 +199,7 @@ def _register_declarative_function(interpreter: "Interpreter", func_name: str) -
198
199
  dec_func = QFunc(user_gen_func._py_callable)
199
200
  dec_func.expand()
200
201
  dec_func_def = QMODULE.native_defs[func_name]
201
- interpreter._expanded_functions.append(dec_func_def)
202
+ interpreter._expanded_functions[func_name] = dec_func_def
202
203
  _DecFuncVisitor(interpreter).visit(dec_func_def)
203
204
 
204
205
 
@@ -1,7 +1,8 @@
1
1
  import copy
2
+ from collections.abc import Iterator, Sequence
2
3
  from contextlib import contextmanager, nullcontext
3
4
  from functools import singledispatchmethod
4
- from typing import Any, Iterator, List, Optional, Sequence, Tuple, Type, cast
5
+ from typing import Any, Optional, cast
5
6
 
6
7
  import numpy as np
7
8
  from numpy.random import permutation
@@ -11,6 +12,7 @@ from classiq.interface.exceptions import (
11
12
  ClassiqInternalExpansionError,
12
13
  )
13
14
  from classiq.interface.generator.expressions.expression import Expression
15
+ from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
14
16
  from classiq.interface.model.bind_operation import BindOperation
15
17
  from classiq.interface.model.classical_if import ClassicalIf
16
18
  from classiq.interface.model.control import Control
@@ -88,7 +90,7 @@ from classiq.qmod.builtins.functions import permute
88
90
  from classiq.qmod.quantum_function import GenerativeQFunc
89
91
  from classiq.qmod.semantics.error_manager import ErrorManager
90
92
 
91
- STATEMENT_TYPES_FOR_SOURCE_REFERENCE_PROPAGATION: Tuple[Type[QuantumStatement], ...] = (
93
+ STATEMENT_TYPES_FOR_SOURCE_REFERENCE_PROPAGATION: tuple[type[QuantumStatement], ...] = (
92
94
  QuantumFunctionCall,
93
95
  VariableDeclarationStatement,
94
96
  QuantumAssignmentOperation,
@@ -99,14 +101,14 @@ class Interpreter:
99
101
  def __init__(
100
102
  self,
101
103
  model: Model,
102
- generative_functions: Optional[List[GenerativeQFunc]] = None,
104
+ generative_functions: Optional[list[GenerativeQFunc]] = None,
103
105
  is_frontend: bool = False,
104
106
  ) -> None:
105
107
  self._is_frontend = is_frontend
106
108
  self._model = model
107
109
  self._current_scope = Scope()
108
110
  self._builder = OperationBuilder()
109
- self._expanded_functions: List[NativeFunctionDefinition] = []
111
+ self._expanded_functions: dict[str, NativeFunctionDefinition] = {}
110
112
  self._propagated_var_stack = PropagatedVarStack(
111
113
  self._current_scope, self._builder
112
114
  )
@@ -117,7 +119,9 @@ class Interpreter:
117
119
  generative_functions = []
118
120
  self._generative_functions = generative_functions
119
121
  init_top_level_scope(model, generative_functions, self._current_scope)
120
-
122
+ self._expanded_functions_compilation_metadata: dict[
123
+ str, CompilationMetadata
124
+ ] = dict()
121
125
  self._counted_name_allocator = CountedNameAllocator()
122
126
  self._error_manager: ErrorManager = ErrorManager()
123
127
 
@@ -150,7 +154,7 @@ class Interpreter:
150
154
  main_closure.positional_arg_declarations, main_closure
151
155
  )
152
156
  context = self._expand_operation(main_closure)
153
- self._expanded_functions.append(
157
+ self._expanded_functions[main_closure.closure_id] = (
154
158
  self._builder.create_definition(cast(FunctionContext, context))
155
159
  )
156
160
 
@@ -173,12 +177,13 @@ class Interpreter:
173
177
  preferences=self._model.preferences,
174
178
  classical_execution_code=self._model.classical_execution_code,
175
179
  execution_preferences=self._model.execution_preferences,
176
- functions=self._expanded_functions,
180
+ functions=list(self._expanded_functions.values()),
177
181
  constants=self._model.constants,
178
182
  enums=self._model.enums,
179
183
  types=self._model.types,
180
184
  qstructs=self._model.qstructs,
181
185
  debug_info=self._model.debug_info,
186
+ functions_compilation_metadata=self._expanded_functions_compilation_metadata,
182
187
  )
183
188
 
184
189
  @singledispatchmethod
@@ -196,7 +201,7 @@ class Interpreter:
196
201
  @evaluate.register
197
202
  def evaluate_lambda(self, function: QuantumLambdaFunction) -> Evaluated:
198
203
  renamed_params = [
199
- param.rename(function.get_rename_params()[idx])
204
+ param.rename(function.pos_rename_params[idx])
200
205
  for idx, param in enumerate(function.func_decl.positional_arg_declarations)
201
206
  ]
202
207
  func_decl = NamedParamsQuantumFunctionDeclaration(
@@ -204,7 +209,7 @@ class Interpreter:
204
209
  positional_arg_declarations=renamed_params,
205
210
  )
206
211
 
207
- closure_class: Type[FunctionClosure]
212
+ closure_class: type[FunctionClosure]
208
213
  extra_args: dict[str, Any]
209
214
  if function.is_generative():
210
215
  closure_class = GenerativeFunctionClosure
@@ -339,7 +344,11 @@ class Interpreter:
339
344
 
340
345
  def _expand_operation(self, operation: Closure) -> OperationContext:
341
346
  with self._builder.operation_context(operation) as context:
342
- if isinstance(operation, FunctionClosure) and operation.name == "permute":
347
+ if isinstance(operation, FunctionClosure) and (
348
+ self._expanded_functions.get(operation.closure_id) is not None
349
+ ):
350
+ pass
351
+ elif isinstance(operation, FunctionClosure) and operation.name == "permute":
343
352
  # special expansion since permute is generative
344
353
  with self._scope_guard(operation.scope):
345
354
  self._expand_permute()
@@ -373,5 +382,5 @@ class Interpreter:
373
382
  return (
374
383
  self._model.functions
375
384
  + [gen_func.func_decl for gen_func in self._generative_functions]
376
- + self._expanded_functions # type:ignore[operator]
385
+ + list(self._expanded_functions.values())
377
386
  )
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from enum import IntEnum
3
- from typing import ClassVar, Dict, Generic, List, Optional, TypeVar
3
+ from typing import ClassVar, Generic, Optional, TypeVar
4
4
 
5
5
  from classiq.interface.generator.expressions.handle_identifier import HandleIdentifier
6
6
  from classiq.interface.generator.functions.classical_type import QmodPyObject
@@ -18,15 +18,15 @@ DeclarationType = TypeVar(
18
18
 
19
19
 
20
20
  class TypeTable(Generic[DeclarationType], ABC):
21
- def __init__(self, user_types: List[DeclarationType]) -> None:
22
- self._all_types: Dict[str, DeclarationType] = self.builtins.copy()
21
+ def __init__(self, user_types: list[DeclarationType]) -> None:
22
+ self._all_types: dict[str, DeclarationType] = self.builtins.copy()
23
23
  for t in user_types:
24
24
  assert t.name not in self._all_types # FIXME: issue user error (CAD-7856)
25
25
  self._all_types[t.name] = t
26
26
 
27
27
  @property
28
28
  @abstractmethod
29
- def builtins(self) -> Dict[str, DeclarationType]:
29
+ def builtins(self) -> dict[str, DeclarationType]:
30
30
  pass
31
31
 
32
32
  def __getitem__(self, key: str) -> DeclarationType:
@@ -38,20 +38,20 @@ class TypeTable(Generic[DeclarationType], ABC):
38
38
  def __contains__(self, key: str) -> bool:
39
39
  return key in self._all_types
40
40
 
41
- def all_types(self) -> Dict[str, DeclarationType]:
41
+ def all_types(self) -> dict[str, DeclarationType]:
42
42
  return self._all_types
43
43
 
44
44
 
45
45
  class EnumTable(TypeTable[EnumDeclaration]):
46
- def __init__(self, user_types: List[EnumDeclaration]) -> None:
46
+ def __init__(self, user_types: list[EnumDeclaration]) -> None:
47
47
  super().__init__(user_types)
48
48
 
49
49
  @property
50
- def builtins(self) -> Dict[str, EnumDeclaration]:
50
+ def builtins(self) -> dict[str, EnumDeclaration]:
51
51
  return BUILTIN_ENUM_DECLARATIONS
52
52
 
53
53
  @property
54
- def enums(self) -> Dict[str, IntEnum]:
54
+ def enums(self) -> dict[str, IntEnum]:
55
55
  return {
56
56
  enum_decl.name: enum_decl.create_enum()
57
57
  for enum_decl in self.all_types().values()
@@ -60,13 +60,13 @@ class EnumTable(TypeTable[EnumDeclaration]):
60
60
 
61
61
  class StructTable(TypeTable[StructDeclaration]):
62
62
  @property
63
- def builtins(self) -> Dict[str, StructDeclaration]:
63
+ def builtins(self) -> dict[str, StructDeclaration]:
64
64
  return BUILTIN_STRUCT_DECLARATIONS
65
65
 
66
66
 
67
67
  class QStructTable(TypeTable[QStructDeclaration]):
68
68
  @property
69
- def builtins(self) -> Dict[str, QStructDeclaration]:
69
+ def builtins(self) -> dict[str, QStructDeclaration]:
70
70
  return {}
71
71
 
72
72
 
@@ -76,15 +76,15 @@ class SymbolTable:
76
76
  qstruct_table: ClassVar[QStructTable] = QStructTable([])
77
77
 
78
78
  @classmethod
79
- def init_user_enums(cls, user_enums: List[EnumDeclaration]) -> None:
79
+ def init_user_enums(cls, user_enums: list[EnumDeclaration]) -> None:
80
80
  cls.enum_table = EnumTable(user_enums)
81
81
 
82
82
  @classmethod
83
- def init_user_types(cls, user_types: List[StructDeclaration]) -> None:
83
+ def init_user_types(cls, user_types: list[StructDeclaration]) -> None:
84
84
  cls.type_table = StructTable(user_types)
85
85
 
86
86
  @classmethod
87
- def init_user_qstructs(cls, user_qstructs: List[QStructDeclaration]) -> None:
87
+ def init_user_qstructs(cls, user_qstructs: list[QStructDeclaration]) -> None:
88
88
  cls.qstruct_table = QStructTable(user_qstructs)
89
89
  QMODULE.qstruct_decls = {
90
90
  qstruct_decl.name: qstruct_decl for qstruct_decl in user_qstructs
@@ -92,7 +92,7 @@ class SymbolTable:
92
92
 
93
93
 
94
94
  class HandleTable:
95
- _handle_map: Dict[HandleIdentifier, QmodPyObject] = {}
95
+ _handle_map: dict[HandleIdentifier, QmodPyObject] = {}
96
96
 
97
97
  @classmethod
98
98
  def get_handle_object(cls, hid: HandleIdentifier) -> Optional[QmodPyObject]:
@@ -1,5 +1,3 @@
1
- from typing import List
2
-
3
1
  from classiq.interface.exceptions import ClassiqExpansionError
4
2
  from classiq.interface.model.bind_operation import BindOperation
5
3
 
@@ -18,11 +16,11 @@ class BindEmitter(Emitter[BindOperation]):
18
16
  def emit(self, bind: BindOperation, /) -> None:
19
17
  with self._propagated_var_stack.capture_variables(bind):
20
18
  pass
21
- inputs: List[QuantumSymbol] = [
19
+ inputs: list[QuantumSymbol] = [
22
20
  self._interpreter.evaluate(arg).as_type(QuantumSymbol)
23
21
  for arg in bind.in_handles
24
22
  ]
25
- outputs: List[QuantumSymbol] = [
23
+ outputs: list[QuantumSymbol] = [
26
24
  self._interpreter.evaluate(arg).as_type(QuantumSymbol)
27
25
  for arg in bind.out_handles
28
26
  ]
@@ -1,4 +1,4 @@
1
- from typing import Sequence
1
+ from collections.abc import Sequence
2
2
 
3
3
  from classiq.interface.model.classical_if import ClassicalIf
4
4
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
@@ -1,5 +1,3 @@
1
- from typing import List, Tuple
2
-
3
1
  from sympy import Equality
4
2
  from sympy.logic.boolalg import Boolean
5
3
  from typing_extensions import TypeGuard
@@ -11,6 +9,7 @@ from classiq.interface.exceptions import (
11
9
  from classiq.interface.generator.compiler_keywords import INPLACE_ARITH_AUX_VAR_PREFIX
12
10
  from classiq.interface.generator.expressions.expression import Expression
13
11
  from classiq.interface.generator.expressions.expression_types import ExpressionValue
12
+ from classiq.interface.generator.expressions.qmod_qarray_proxy import QmodQArrayProxy
14
13
  from classiq.interface.generator.expressions.qmod_qscalar_proxy import QmodQNumProxy
15
14
  from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
16
15
  from classiq.interface.generator.functions.builtins.internal_operators import (
@@ -23,6 +22,7 @@ from classiq.interface.model.quantum_expressions.arithmetic_operation import (
23
22
  ArithmeticOperation,
24
23
  ArithmeticOperationKind,
25
24
  )
25
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
26
26
  from classiq.interface.model.quantum_type import QuantumBit, QuantumBitvector
27
27
  from classiq.interface.model.statement_block import ConcreteQuantumStatement
28
28
  from classiq.interface.model.variable_declaration_statement import (
@@ -42,6 +42,7 @@ from classiq.model_expansions.quantum_operations.expression_operation import (
42
42
  ExpressionOperationEmitter,
43
43
  )
44
44
  from classiq.model_expansions.scope import Scope
45
+ from classiq.qmod.builtins.functions.standard_gates import X
45
46
 
46
47
  ARRAY_CAST_SUFFIX = HANDLE_ID_SEPARATOR + "array_cast"
47
48
 
@@ -49,22 +50,42 @@ ARRAY_CAST_SUFFIX = HANDLE_ID_SEPARATOR + "array_cast"
49
50
  class ControlEmitter(ExpressionOperationEmitter[Control]):
50
51
  def emit(self, control: Control, /) -> None:
51
52
  condition = self._evaluate_op_expression(control)
52
- control = control.model_copy(update=dict(expression=condition))
53
53
 
54
54
  arrays_with_subscript = self._get_symbols_to_split(condition)
55
55
  if len(arrays_with_subscript) > 0:
56
56
  self._emit_with_split(control, condition, arrays_with_subscript)
57
57
  return
58
58
 
59
+ control = self._evaluate_types_in_expression(control, condition)
59
60
  condition_val = condition.value.value
60
61
  if isinstance(condition_val, QmodSizedProxy):
61
- self._validate_canonical_condition(condition_val)
62
- self._emit_canonical_control(control)
63
- return
62
+ if control.else_block is None:
63
+ self._validate_canonical_condition(condition_val)
64
+ self._emit_canonical_control(control)
65
+ return
66
+ else:
67
+ self._interpreter.emit_statement(
68
+ control.model_copy(
69
+ update=dict(
70
+ expression=self._uncanonize_condition(condition_val)
71
+ )
72
+ )
73
+ )
74
+ return
64
75
 
65
- self._validate_condition(condition_val)
76
+ self._validate_condition(control)
66
77
  self._emit_with_boolean(control)
67
78
 
79
+ def _uncanonize_condition(self, condition_val: QmodSizedProxy) -> Expression:
80
+ lhs = (
81
+ " & ".join(
82
+ f"{condition_val.handle}[{idx}]" for idx in range(condition_val.size)
83
+ )
84
+ if isinstance(condition_val, QmodQArrayProxy)
85
+ else condition_val.handle
86
+ )
87
+ return Expression(expr=f"{lhs} == 1")
88
+
68
89
  def _emit_canonical_control(self, control: Control) -> None:
69
90
  # canonical means control(q, body) where q is a single quantum variable
70
91
  control = self._evaluate_types_in_expression(control, control.expression)
@@ -131,9 +152,10 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
131
152
  condition_val = control.expression.value.value
132
153
  if self._is_simple_equality(condition_val):
133
154
  ctrl, ctrl_state = resolve_num_condition(condition_val)
134
- self._emit_with_x_gates(control, ctrl, ctrl_state)
135
- else:
136
- self._emit_with_arithmetic(control)
155
+ if control.else_block is None or ctrl.size == 1:
156
+ self._emit_with_x_gates(control, ctrl, ctrl_state)
157
+ return
158
+ self._emit_with_arithmetic(control)
137
159
 
138
160
  @staticmethod
139
161
  def _is_simple_equality(condition_val: ExpressionValue) -> TypeGuard[Equality]:
@@ -153,14 +175,38 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
153
175
 
154
176
  def _create_canonical_control_op(
155
177
  self, control: Control, handle_name: str
156
- ) -> Control:
178
+ ) -> list[ConcreteQuantumStatement]:
157
179
  handle_expr = self._interpreter.evaluate(Expression(expr=handle_name)).emit()
158
- return control.model_copy(update=dict(expression=handle_expr))
180
+ control_then = control.model_copy(
181
+ update=dict(expression=handle_expr, else_block=None)
182
+ )
183
+ if control.else_block is None:
184
+ return [control_then]
185
+ else_compute_call = QuantumFunctionCall(
186
+ function="X", positional_args=[HandleBinding(name=handle_name)]
187
+ )
188
+ else_compute_call.set_func_decl(X.func_decl)
189
+ control_else_inner = control.model_copy(
190
+ update=dict(
191
+ expression=handle_expr, body=control.else_block, else_block=None
192
+ ),
193
+ deep=True,
194
+ )
195
+ control_else = WithinApply(
196
+ compute=[else_compute_call],
197
+ action=[control_else_inner],
198
+ )
199
+ if control_else_inner.is_generative():
200
+ control_else_inner.set_generative_block(
201
+ "body", control_else_inner.get_generative_block("else_block")
202
+ )
203
+ control_else_inner.remove_generative_block("else_block")
204
+ return [control_then, control_else]
159
205
 
160
- def _emit_with_x_gates(
206
+ def _control_with_x_gates(
161
207
  self, control: Control, ctrl: QmodSizedProxy, ctrl_state: str
162
- ) -> None:
163
- compute_op: List[ConcreteQuantumStatement] = []
208
+ ) -> ConcreteQuantumStatement:
209
+ compute_op: list[ConcreteQuantumStatement] = []
164
210
 
165
211
  x_gate_value = self._get_x_gate_value(ctrl_state)
166
212
  if x_gate_value != 0:
@@ -177,12 +223,19 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
177
223
  cast_decl, bind_op = self._get_array_cast_ops(ctrl)
178
224
  self._interpreter.emit_statement(cast_decl)
179
225
  compute_op.append(bind_op)
180
- control_op = self._create_canonical_control_op(control, str(cast_decl.name))
226
+ control_ops = self._create_canonical_control_op(
227
+ control, str(cast_decl.name)
228
+ )
181
229
  else:
182
- control_op = self._create_canonical_control_op(control, str(ctrl.handle))
230
+ control_ops = self._create_canonical_control_op(control, str(ctrl.handle))
231
+
232
+ return WithinApply(compute=compute_op, action=control_ops)
183
233
 
234
+ def _emit_with_x_gates(
235
+ self, control: Control, ctrl: QmodSizedProxy, ctrl_state: str
236
+ ) -> None:
184
237
  self._interpreter.emit_statement(
185
- WithinApply(compute=compute_op, action=[control_op])
238
+ self._control_with_x_gates(control, ctrl, ctrl_state)
186
239
  )
187
240
 
188
241
  @staticmethod
@@ -194,7 +247,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
194
247
 
195
248
  def _get_array_cast_ops(
196
249
  self, ctrl: QmodQNumProxy
197
- ) -> Tuple[VariableDeclarationStatement, BindOperation]:
250
+ ) -> tuple[VariableDeclarationStatement, BindOperation]:
198
251
  array_cast = self._counted_name_allocator.allocate(
199
252
  f"{ctrl.handle}{ARRAY_CAST_SUFFIX}"
200
253
  )
@@ -219,14 +272,18 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
219
272
  self._interpreter.emit_statement(
220
273
  WithinApply(
221
274
  compute=[arith_expression],
222
- action=[self._create_canonical_control_op(control, aux_var)],
275
+ action=self._create_canonical_control_op(control, aux_var),
223
276
  )
224
277
  )
225
278
 
226
- @staticmethod
227
- def _validate_condition(condition_val: ExpressionValue) -> None:
228
- if not isinstance(condition_val, Boolean):
229
- raise ClassiqExpansionError(_condition_err_msg(condition_val))
279
+ def _validate_condition(self, control: Control) -> None:
280
+ condition_value = control.expression.value.value
281
+ if not (
282
+ isinstance(condition_value, Boolean)
283
+ or self._all_vars_boolean(control)
284
+ and self._is_res_boolean(control)
285
+ ):
286
+ raise ClassiqExpansionError(_condition_err_msg(condition_value))
230
287
 
231
288
  @staticmethod
232
289
  def _validate_canonical_condition(condition_val: ExpressionValue) -> None: