classiq 0.37.1__py3-none-any.whl → 0.65.3__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 (516) hide show
  1. classiq/__init__.py +49 -34
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +3 -2
  3. classiq/_analyzer_extras/interactive_hardware.py +3 -3
  4. classiq/_internals/api_wrapper.py +241 -95
  5. classiq/_internals/async_utils.py +2 -77
  6. classiq/_internals/authentication/auth0.py +26 -10
  7. classiq/_internals/authentication/authentication.py +11 -0
  8. classiq/_internals/authentication/device.py +18 -8
  9. classiq/_internals/authentication/password_manager.py +40 -13
  10. classiq/_internals/authentication/token_manager.py +11 -6
  11. classiq/_internals/client.py +106 -37
  12. classiq/_internals/config.py +3 -4
  13. classiq/_internals/host_checker.py +38 -15
  14. classiq/_internals/jobs.py +56 -50
  15. classiq/_internals/type_validation.py +9 -9
  16. classiq/analyzer/__init__.py +1 -3
  17. classiq/analyzer/analyzer.py +50 -47
  18. classiq/analyzer/analyzer_utilities.py +15 -15
  19. classiq/analyzer/rb.py +19 -20
  20. classiq/analyzer/show_interactive_hack.py +30 -7
  21. classiq/analyzer/url_utils.py +2 -3
  22. classiq/applications/__init__.py +3 -12
  23. classiq/applications/chemistry/__init__.py +14 -10
  24. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  25. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +170 -170
  26. classiq/applications/chemistry/ground_state_problem.py +1 -1
  27. classiq/applications/combinatorial_helpers/allowed_constraints.py +23 -0
  28. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
  29. classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
  30. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +166 -0
  31. classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
  32. classiq/applications/combinatorial_helpers/encoding_utils.py +124 -0
  33. classiq/applications/combinatorial_helpers/memory.py +75 -0
  34. classiq/applications/combinatorial_helpers/optimization_model.py +193 -0
  35. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
  36. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
  37. classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
  38. classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
  39. classiq/applications/combinatorial_helpers/transformations/encoding.py +189 -0
  40. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +143 -0
  41. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +120 -0
  42. classiq/applications/combinatorial_helpers/transformations/penalty.py +31 -0
  43. classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
  44. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +74 -0
  45. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +87 -0
  46. classiq/applications/combinatorial_optimization/__init__.py +24 -5
  47. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  48. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +137 -0
  49. classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
  50. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  51. classiq/applications/finance/__init__.py +4 -5
  52. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +50 -57
  53. classiq/applications/grover/__init__.py +9 -0
  54. classiq/applications/grover/grover_model_constructor.py +157 -0
  55. classiq/applications/hamiltonian/__init__.py +0 -0
  56. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  57. classiq/applications/libraries/__init__.py +0 -0
  58. classiq/applications/libraries/qmci_library.py +22 -0
  59. classiq/applications/qnn/__init__.py +2 -4
  60. classiq/applications/qnn/circuit_utils.py +8 -8
  61. classiq/applications/qnn/datasets/__init__.py +9 -11
  62. classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
  63. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  64. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  65. classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
  66. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  67. classiq/applications/qnn/qlayer.py +30 -10
  68. classiq/applications/qnn/torch_utils.py +4 -3
  69. classiq/applications/qnn/types.py +7 -7
  70. classiq/applications/qsvm/__init__.py +6 -4
  71. classiq/applications/qsvm/qsvm.py +4 -10
  72. classiq/applications/qsvm/qsvm_data_generation.py +5 -8
  73. classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
  74. classiq/execution/__init__.py +8 -3
  75. classiq/execution/all_hardware_devices.py +11 -0
  76. classiq/execution/execution_session.py +400 -0
  77. classiq/execution/iqcc.py +63 -0
  78. classiq/execution/jobs.py +197 -25
  79. classiq/execution/qnn.py +79 -0
  80. classiq/executor.py +23 -117
  81. classiq/interface/_version.py +1 -1
  82. classiq/interface/analyzer/analysis_params.py +49 -16
  83. classiq/interface/analyzer/cytoscape_graph.py +15 -9
  84. classiq/interface/analyzer/result.py +36 -32
  85. classiq/interface/applications/qsvm.py +28 -25
  86. classiq/interface/ast_node.py +16 -0
  87. classiq/interface/backend/backend_preferences.py +390 -119
  88. classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
  89. classiq/interface/backend/pydantic_backend.py +27 -22
  90. classiq/interface/backend/quantum_backend_providers.py +70 -16
  91. classiq/interface/chemistry/fermionic_operator.py +43 -32
  92. classiq/interface/chemistry/ground_state_problem.py +42 -24
  93. classiq/interface/chemistry/molecule.py +20 -14
  94. classiq/interface/chemistry/operator.py +75 -236
  95. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  96. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +2 -4
  97. classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
  98. classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
  99. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  100. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  101. classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
  102. classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
  103. classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
  104. classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
  105. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  106. classiq/interface/combinatorial_optimization/examples/set_cover.py +3 -3
  107. classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
  108. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
  109. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +14 -9
  110. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  111. classiq/interface/combinatorial_optimization/result.py +1 -3
  112. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  113. classiq/interface/debug_info/__init__.py +0 -0
  114. classiq/interface/debug_info/debug_info.py +86 -0
  115. classiq/interface/exceptions.py +201 -0
  116. classiq/interface/execution/iqcc.py +19 -0
  117. classiq/interface/execution/jobs.py +15 -12
  118. classiq/interface/execution/primitives.py +18 -0
  119. classiq/interface/executor/constants.py +1 -0
  120. classiq/interface/executor/estimation.py +2 -2
  121. classiq/interface/executor/execution_preferences.py +26 -143
  122. classiq/interface/executor/execution_request.py +36 -56
  123. classiq/interface/executor/execution_result.py +30 -8
  124. classiq/interface/executor/iqae_result.py +4 -6
  125. classiq/interface/executor/optimizer_preferences.py +34 -22
  126. classiq/interface/executor/{quantum_program.py → quantum_code.py} +44 -34
  127. classiq/interface/executor/quantum_instruction_set.py +3 -2
  128. classiq/interface/executor/register_initialization.py +12 -17
  129. classiq/interface/executor/result.py +122 -64
  130. classiq/interface/executor/vqe_result.py +11 -11
  131. classiq/interface/finance/function_input.py +42 -19
  132. classiq/interface/finance/gaussian_model_input.py +7 -5
  133. classiq/interface/finance/log_normal_model_input.py +6 -4
  134. classiq/interface/finance/model_input.py +6 -4
  135. classiq/interface/generator/adjacency.py +1 -3
  136. classiq/interface/generator/amplitude_loading.py +27 -14
  137. classiq/interface/generator/ansatz_library.py +5 -5
  138. classiq/interface/generator/application_apis/__init__.py +1 -0
  139. classiq/interface/generator/application_apis/arithmetic_declarations.py +17 -0
  140. classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
  141. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
  142. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  143. classiq/interface/generator/application_apis/finance_declarations.py +48 -69
  144. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
  145. classiq/interface/generator/arith/argument_utils.py +57 -6
  146. classiq/interface/generator/arith/arithmetic.py +37 -16
  147. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +15 -17
  148. classiq/interface/generator/arith/arithmetic_expression_abc.py +70 -26
  149. classiq/interface/generator/arith/arithmetic_expression_parser.py +18 -12
  150. classiq/interface/generator/arith/arithmetic_expression_validator.py +61 -43
  151. classiq/interface/generator/arith/arithmetic_operations.py +19 -16
  152. classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
  153. classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
  154. classiq/interface/generator/arith/ast_node_rewrite.py +4 -3
  155. classiq/interface/generator/arith/binary_ops.py +375 -139
  156. classiq/interface/generator/arith/endianness.py +1 -1
  157. classiq/interface/generator/arith/extremum_operations.py +96 -23
  158. classiq/interface/generator/arith/logical_ops.py +16 -12
  159. classiq/interface/generator/arith/machine_precision.py +3 -0
  160. classiq/interface/generator/arith/number_utils.py +44 -48
  161. classiq/interface/generator/arith/register_user_input.py +70 -27
  162. classiq/interface/generator/arith/unary_ops.py +57 -46
  163. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  164. classiq/interface/generator/builtin_api_builder.py +2 -9
  165. classiq/interface/generator/chemistry_function_params.py +5 -5
  166. classiq/interface/generator/circuit_code/circuit_code.py +7 -7
  167. classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
  168. classiq/interface/generator/commuting_pauli_exponentiation.py +8 -6
  169. classiq/interface/generator/compiler_keywords.py +8 -0
  170. classiq/interface/generator/complex_type.py +13 -25
  171. classiq/interface/generator/constant.py +3 -4
  172. classiq/interface/generator/control_state.py +35 -28
  173. classiq/interface/generator/copy.py +47 -0
  174. classiq/interface/generator/custom_ansatz.py +2 -5
  175. classiq/interface/generator/distance.py +3 -5
  176. classiq/interface/generator/excitations.py +3 -2
  177. classiq/interface/generator/expressions/atomic_expression_functions.py +26 -8
  178. classiq/interface/generator/expressions/enums/__init__.py +0 -10
  179. classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
  180. classiq/interface/generator/expressions/evaluated_expression.py +21 -7
  181. classiq/interface/generator/expressions/expression.py +27 -15
  182. classiq/interface/generator/expressions/expression_constants.py +9 -3
  183. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  184. classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
  185. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +59 -0
  186. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
  187. classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
  188. classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
  189. classiq/interface/generator/expressions/sympy_supported_expressions.py +20 -11
  190. classiq/interface/generator/finance.py +3 -3
  191. classiq/interface/generator/function_param_library.py +6 -6
  192. classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
  193. classiq/interface/generator/function_params.py +42 -69
  194. classiq/interface/generator/functions/__init__.py +0 -22
  195. classiq/interface/generator/functions/builtins/__init__.py +0 -0
  196. classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
  197. classiq/interface/generator/functions/classical_function_declaration.py +18 -9
  198. classiq/interface/generator/functions/classical_type.py +47 -166
  199. classiq/interface/generator/functions/concrete_types.py +55 -0
  200. classiq/interface/generator/functions/function_declaration.py +13 -14
  201. classiq/interface/generator/functions/port_declaration.py +1 -13
  202. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  203. classiq/interface/generator/functions/type_name.py +90 -0
  204. classiq/interface/generator/generated_circuit_data.py +155 -22
  205. classiq/interface/generator/grover_diffuser.py +32 -25
  206. classiq/interface/generator/grover_operator.py +34 -23
  207. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
  208. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  209. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +12 -8
  210. classiq/interface/generator/hardware/hardware_data.py +76 -36
  211. classiq/interface/generator/hardware_efficient_ansatz.py +38 -17
  212. classiq/interface/generator/hartree_fock.py +14 -4
  213. classiq/interface/generator/identity.py +10 -6
  214. classiq/interface/generator/linear_pauli_rotations.py +33 -19
  215. classiq/interface/generator/mcmt_method.py +1 -1
  216. classiq/interface/generator/mcu.py +20 -16
  217. classiq/interface/generator/mcx.py +29 -20
  218. classiq/interface/generator/model/__init__.py +2 -5
  219. classiq/interface/generator/model/constraints.py +27 -8
  220. classiq/interface/generator/model/model.py +32 -203
  221. classiq/interface/generator/model/preferences/preferences.py +118 -43
  222. classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +27 -22
  223. classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
  224. classiq/interface/generator/oracles/custom_oracle.py +17 -13
  225. classiq/interface/generator/oracles/oracle_abc.py +9 -9
  226. classiq/interface/generator/partitioned_register.py +7 -7
  227. classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
  228. classiq/interface/generator/preferences/optimization.py +1 -2
  229. classiq/interface/generator/qpe.py +47 -34
  230. classiq/interface/generator/qsvm.py +13 -17
  231. classiq/interface/generator/quantum_function_call.py +107 -87
  232. classiq/interface/generator/{generated_circuit.py → quantum_program.py} +50 -37
  233. classiq/interface/generator/range_types.py +13 -12
  234. classiq/interface/generator/register_role.py +18 -6
  235. classiq/interface/generator/slice_parsing_utils.py +11 -6
  236. classiq/interface/generator/standard_gates/controlled_standard_gates.py +32 -39
  237. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  238. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  239. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  240. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  241. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  242. classiq/interface/generator/state_preparation/distributions.py +16 -15
  243. classiq/interface/generator/state_preparation/metrics.py +5 -7
  244. classiq/interface/generator/state_preparation/state_preparation.py +30 -23
  245. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  246. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
  247. classiq/interface/generator/transpiler_basis_gates.py +7 -3
  248. classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
  249. classiq/interface/generator/types/compilation_metadata.py +6 -0
  250. classiq/interface/generator/types/enum_declaration.py +54 -0
  251. classiq/interface/generator/types/qstruct_declaration.py +18 -0
  252. classiq/interface/generator/types/struct_declaration.py +15 -14
  253. classiq/interface/generator/ucc.py +9 -6
  254. classiq/interface/generator/unitary_gate.py +10 -6
  255. classiq/interface/generator/user_defined_function_params.py +4 -1
  256. classiq/interface/generator/validations/flow_graph.py +11 -9
  257. classiq/interface/generator/validations/validator_functions.py +8 -6
  258. classiq/interface/generator/visitor.py +23 -16
  259. classiq/interface/hardware.py +31 -10
  260. classiq/interface/helpers/classproperty.py +8 -0
  261. classiq/interface/helpers/custom_encoders.py +3 -0
  262. classiq/interface/helpers/custom_pydantic_types.py +40 -50
  263. classiq/interface/helpers/datastructures.py +26 -0
  264. classiq/interface/helpers/hashable_mixin.py +3 -2
  265. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  266. classiq/interface/helpers/pydantic_model_helpers.py +7 -11
  267. classiq/interface/helpers/validation_helpers.py +4 -21
  268. classiq/interface/helpers/versioned_model.py +1 -1
  269. classiq/interface/ide/ide_data.py +16 -20
  270. classiq/interface/ide/visual_model.py +130 -0
  271. classiq/interface/interface_version.py +1 -0
  272. classiq/interface/jobs.py +35 -6
  273. classiq/interface/model/allocate.py +16 -0
  274. classiq/interface/model/bind_operation.py +44 -14
  275. classiq/interface/model/classical_if.py +15 -0
  276. classiq/interface/model/classical_parameter_declaration.py +33 -3
  277. classiq/interface/model/control.py +45 -0
  278. classiq/interface/model/handle_binding.py +298 -20
  279. classiq/interface/model/inplace_binary_operation.py +31 -26
  280. classiq/interface/model/invert.py +12 -0
  281. classiq/interface/model/model.py +87 -73
  282. classiq/interface/model/native_function_definition.py +16 -21
  283. classiq/interface/model/parameter.py +13 -0
  284. classiq/interface/model/phase_operation.py +11 -0
  285. classiq/interface/model/port_declaration.py +27 -9
  286. classiq/interface/model/power.py +14 -0
  287. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +38 -21
  288. classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
  289. classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
  290. classiq/interface/model/quantum_function_call.py +146 -462
  291. classiq/interface/model/quantum_function_declaration.py +193 -152
  292. classiq/interface/model/quantum_lambda_function.py +65 -0
  293. classiq/interface/model/quantum_statement.py +71 -12
  294. classiq/interface/model/quantum_type.py +205 -67
  295. classiq/interface/model/quantum_variable_declaration.py +4 -26
  296. classiq/interface/model/repeat.py +15 -0
  297. classiq/interface/model/statement_block.py +58 -0
  298. classiq/interface/model/validation_handle.py +13 -6
  299. classiq/interface/model/variable_declaration_statement.py +3 -1
  300. classiq/interface/model/within_apply_operation.py +13 -0
  301. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
  302. classiq/interface/server/global_versions.py +6 -7
  303. classiq/interface/server/routes.py +22 -21
  304. classiq/interface/source_reference.py +59 -0
  305. classiq/model_expansions/__init__.py +0 -0
  306. classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
  307. classiq/model_expansions/capturing/__init__.py +0 -0
  308. classiq/model_expansions/capturing/captured_vars.py +435 -0
  309. classiq/model_expansions/capturing/mangling_utils.py +56 -0
  310. classiq/model_expansions/closure.py +171 -0
  311. classiq/model_expansions/debug_flag.py +3 -0
  312. classiq/model_expansions/evaluators/__init__.py +0 -0
  313. classiq/model_expansions/evaluators/arg_type_match.py +158 -0
  314. classiq/model_expansions/evaluators/argument_types.py +42 -0
  315. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  316. classiq/model_expansions/evaluators/control.py +144 -0
  317. classiq/model_expansions/evaluators/parameter_types.py +226 -0
  318. classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
  319. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  320. classiq/model_expansions/expression_evaluator.py +135 -0
  321. classiq/model_expansions/expression_renamer.py +76 -0
  322. classiq/model_expansions/function_builder.py +247 -0
  323. classiq/model_expansions/generative_functions.py +158 -0
  324. classiq/model_expansions/interpreters/__init__.py +0 -0
  325. classiq/model_expansions/interpreters/base_interpreter.py +263 -0
  326. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
  327. classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
  328. classiq/model_expansions/model_tables.py +18 -0
  329. classiq/model_expansions/quantum_operations/__init__.py +9 -0
  330. classiq/model_expansions/quantum_operations/bind.py +60 -0
  331. classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
  332. classiq/model_expansions/quantum_operations/classicalif.py +53 -0
  333. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
  334. classiq/model_expansions/quantum_operations/emitter.py +181 -0
  335. classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
  336. classiq/model_expansions/quantum_operations/repeat.py +56 -0
  337. classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
  338. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  339. classiq/model_expansions/scope.py +240 -0
  340. classiq/model_expansions/scope_initialization.py +150 -0
  341. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  342. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  343. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
  344. classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
  345. classiq/model_expansions/transformers/__init__.py +0 -0
  346. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  347. classiq/model_expansions/transformers/var_splitter.py +299 -0
  348. classiq/model_expansions/utils/__init__.py +0 -0
  349. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  350. classiq/model_expansions/utils/handles_collector.py +33 -0
  351. classiq/model_expansions/visitors/__init__.py +0 -0
  352. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  353. classiq/model_expansions/visitors/variable_references.py +144 -0
  354. classiq/open_library/__init__.py +4 -0
  355. classiq/open_library/functions/__init__.py +130 -0
  356. classiq/open_library/functions/amplitude_estimation.py +30 -0
  357. classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
  358. classiq/open_library/functions/grover.py +157 -0
  359. classiq/open_library/functions/hea.py +115 -0
  360. classiq/open_library/functions/linear_pauli_rotation.py +82 -0
  361. classiq/open_library/functions/modular_exponentiation.py +201 -0
  362. classiq/open_library/functions/qaoa_penalty.py +117 -0
  363. classiq/open_library/functions/qft_functions.py +54 -0
  364. classiq/open_library/functions/qpe.py +46 -0
  365. classiq/open_library/functions/qsvt.py +331 -0
  366. classiq/open_library/functions/state_preparation.py +301 -0
  367. classiq/open_library/functions/swap_test.py +27 -0
  368. classiq/open_library/functions/utility_functions.py +81 -0
  369. classiq/open_library/functions/variational.py +52 -0
  370. classiq/qmod/__init__.py +17 -10
  371. classiq/qmod/builtins/__init__.py +19 -2
  372. classiq/qmod/builtins/classical_execution_primitives.py +60 -47
  373. classiq/qmod/builtins/classical_functions.py +44 -38
  374. classiq/qmod/builtins/constants.py +10 -0
  375. classiq/qmod/builtins/enums.py +208 -0
  376. classiq/qmod/builtins/functions/__init__.py +137 -0
  377. classiq/qmod/builtins/functions/allocation.py +150 -0
  378. classiq/qmod/builtins/functions/arithmetic.py +55 -0
  379. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  380. classiq/qmod/builtins/functions/chemistry.py +91 -0
  381. classiq/qmod/builtins/functions/exponentiation.py +105 -0
  382. classiq/qmod/builtins/functions/finance.py +34 -0
  383. classiq/qmod/builtins/functions/operators.py +16 -0
  384. classiq/qmod/builtins/functions/qsvm.py +24 -0
  385. classiq/qmod/builtins/functions/standard_gates.py +651 -0
  386. classiq/qmod/builtins/operations.py +379 -57
  387. classiq/qmod/builtins/structs.py +103 -80
  388. classiq/qmod/cfunc.py +42 -0
  389. classiq/qmod/classical_function.py +8 -20
  390. classiq/qmod/cparam.py +64 -0
  391. classiq/qmod/create_model_function.py +56 -0
  392. classiq/qmod/declaration_inferrer.py +145 -112
  393. classiq/qmod/expression_query.py +39 -0
  394. classiq/qmod/generative.py +42 -0
  395. classiq/qmod/model_state_container.py +19 -5
  396. classiq/qmod/native/__init__.py +7 -0
  397. classiq/qmod/native/expression_to_qmod.py +194 -0
  398. classiq/qmod/native/pretty_printer.py +401 -0
  399. classiq/qmod/pretty_print/__init__.py +7 -0
  400. classiq/qmod/pretty_print/expression_to_python.py +222 -0
  401. classiq/qmod/pretty_print/pretty_printer.py +572 -0
  402. classiq/qmod/python_classical_type.py +67 -0
  403. classiq/qmod/qfunc.py +79 -0
  404. classiq/qmod/qmod_constant.py +143 -0
  405. classiq/qmod/qmod_parameter.py +84 -53
  406. classiq/qmod/qmod_variable.py +497 -100
  407. classiq/qmod/quantum_callable.py +17 -7
  408. classiq/qmod/quantum_expandable.py +278 -105
  409. classiq/qmod/quantum_function.py +232 -48
  410. classiq/qmod/semantics/__init__.py +0 -0
  411. classiq/qmod/semantics/annotation/__init__.py +0 -0
  412. classiq/qmod/semantics/annotation/call_annotation.py +92 -0
  413. classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
  414. classiq/qmod/semantics/error_manager.py +88 -0
  415. classiq/qmod/semantics/lambdas.py +25 -0
  416. classiq/qmod/semantics/static_semantics_visitor.py +384 -0
  417. classiq/qmod/semantics/validation/__init__.py +0 -0
  418. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  419. classiq/qmod/semantics/validation/func_call_validation.py +99 -0
  420. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  421. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  422. classiq/qmod/semantics/validation/main_validation.py +33 -0
  423. classiq/qmod/semantics/validation/types_validation.py +128 -0
  424. classiq/qmod/symbolic.py +178 -111
  425. classiq/qmod/symbolic_expr.py +36 -12
  426. classiq/qmod/symbolic_type.py +2 -5
  427. classiq/qmod/type_attribute_remover.py +32 -0
  428. classiq/qmod/utilities.py +108 -1
  429. classiq/qmod/write_qmod.py +53 -0
  430. classiq/synthesis.py +210 -22
  431. {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -8
  432. classiq-0.65.3.dist-info/RECORD +521 -0
  433. {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/WHEEL +1 -1
  434. classiq/_internals/_qfunc_ext.py +0 -6
  435. classiq/applications/benchmarking/__init__.py +0 -9
  436. classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
  437. classiq/applications/numpy_utils.py +0 -37
  438. classiq/applications_model_constructors/__init__.py +0 -17
  439. classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
  440. classiq/applications_model_constructors/grover_model_constructor.py +0 -227
  441. classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
  442. classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
  443. classiq/builtin_functions/__init__.py +0 -43
  444. classiq/builtin_functions/amplitude_loading.py +0 -3
  445. classiq/builtin_functions/binary_ops.py +0 -1
  446. classiq/builtin_functions/exponentiation.py +0 -5
  447. classiq/builtin_functions/qpe.py +0 -4
  448. classiq/builtin_functions/qsvm.py +0 -7
  449. classiq/builtin_functions/range_types.py +0 -5
  450. classiq/builtin_functions/standard_gates.py +0 -1
  451. classiq/builtin_functions/state_preparation.py +0 -6
  452. classiq/builtin_functions/suzuki_trotter.py +0 -3
  453. classiq/exceptions.py +0 -131
  454. classiq/interface/executor/aws_execution_cost.py +0 -72
  455. classiq/interface/executor/error_mitigation.py +0 -6
  456. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -115
  457. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -59
  458. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  459. classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
  460. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
  461. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  462. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  463. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  464. classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
  465. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  466. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
  467. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
  468. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -862
  469. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
  470. classiq/interface/generator/functions/foreign_function_definition.py +0 -106
  471. classiq/interface/generator/functions/function_implementation.py +0 -103
  472. classiq/interface/generator/functions/native_function_definition.py +0 -153
  473. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  474. classiq/interface/generator/functions/register.py +0 -42
  475. classiq/interface/generator/functions/register_mapping_data.py +0 -102
  476. classiq/interface/generator/inequality_mixer.py +0 -51
  477. classiq/interface/generator/model/classical_main_validator.py +0 -106
  478. classiq/interface/generator/range_mixer.py +0 -56
  479. classiq/interface/generator/state_propagator.py +0 -63
  480. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -2
  481. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
  482. classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
  483. classiq/interface/generator/types/combinatorial_problem.py +0 -26
  484. classiq/interface/ide/show.py +0 -34
  485. classiq/interface/model/common_model_types.py +0 -23
  486. classiq/interface/model/numeric_reinterpretation.py +0 -25
  487. classiq/interface/model/operator_synthesis_data.py +0 -48
  488. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  489. classiq/interface/model/quantum_if_operation.py +0 -95
  490. classiq/interface/model/resolvers/function_call_resolver.py +0 -43
  491. classiq/interface/model/validations/handle_validation_base.py +0 -55
  492. classiq/interface/model/validations/handles_validator.py +0 -154
  493. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  494. classiq/model/__init__.py +0 -14
  495. classiq/model/composite_function_generator.py +0 -33
  496. classiq/model/function_handler.py +0 -466
  497. classiq/model/function_handler.pyi +0 -152
  498. classiq/model/logic_flow.py +0 -149
  499. classiq/model/logic_flow_change_handler.py +0 -71
  500. classiq/model/model.py +0 -246
  501. classiq/qmod/builtins/functions.py +0 -896
  502. classiq/qmod/qmod_struct.py +0 -37
  503. classiq/quantum_functions/__init__.py +0 -17
  504. classiq/quantum_functions/annotation_parser.py +0 -207
  505. classiq/quantum_functions/decorators.py +0 -22
  506. classiq/quantum_functions/function_library.py +0 -181
  507. classiq/quantum_functions/function_parser.py +0 -74
  508. classiq/quantum_functions/quantum_function.py +0 -236
  509. classiq-0.37.1.dist-info/RECORD +0 -418
  510. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
  511. /classiq/{interface/generator/credit_risk_example → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
  512. /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/pauli_helpers}/__init__.py +0 -0
  513. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/py.typed} +0 -0
  514. /classiq/{interface/model/resolvers → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  515. /classiq/{interface/model/validations → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  516. /classiq/{_internals → interface}/enum_utils.py +0 -0
@@ -0,0 +1,435 @@
1
+ import dataclasses
2
+ from collections.abc import Sequence
3
+ from dataclasses import dataclass, field
4
+ from typing import TYPE_CHECKING, Optional
5
+
6
+ from classiq.interface.enum_utils import StrEnum
7
+ from classiq.interface.exceptions import (
8
+ ClassiqExpansionError,
9
+ ClassiqInternalExpansionError,
10
+ )
11
+ from classiq.interface.generator.expressions.expression import Expression
12
+ from classiq.interface.generator.functions.port_declaration import (
13
+ PortDeclarationDirection,
14
+ )
15
+ from classiq.interface.model.handle_binding import (
16
+ HandleBinding,
17
+ NestedHandleBinding,
18
+ SlicedHandleBinding,
19
+ )
20
+ from classiq.interface.model.port_declaration import PortDeclaration
21
+ from classiq.interface.model.quantum_function_call import ArgValue
22
+ from classiq.interface.model.quantum_type import QuantumBitvector, QuantumType
23
+ from classiq.interface.model.variable_declaration_statement import (
24
+ VariableDeclarationStatement,
25
+ )
26
+
27
+ from classiq.model_expansions.capturing.mangling_utils import (
28
+ demangle_handle,
29
+ mangle_captured_var_name,
30
+ )
31
+ from classiq.model_expansions.transformers.var_splitter import SymbolPart, SymbolParts
32
+
33
+ if TYPE_CHECKING:
34
+ from classiq.model_expansions.closure import FunctionClosure
35
+
36
+
37
+ ALREADY_ALLOCATED_MESSAGE = "Cannot allocate variable '{}', it is already initialized"
38
+ ALREADY_FREED_MESSAGE = "Cannot free variable '{}', it is already uninitialized"
39
+
40
+
41
+ class PortDirection(StrEnum):
42
+ Input = "input"
43
+ Inout = "inout"
44
+ Output = "output"
45
+ Outin = "outin"
46
+
47
+ def negate(self) -> "PortDirection":
48
+ if self == PortDirection.Input:
49
+ return PortDirection.Output
50
+ if self == PortDirection.Output:
51
+ return PortDirection.Input
52
+ return self
53
+
54
+ @staticmethod
55
+ def load(direction: PortDeclarationDirection) -> "PortDirection":
56
+ if direction == PortDeclarationDirection.Input:
57
+ return PortDirection.Input
58
+ if direction == PortDeclarationDirection.Output:
59
+ return PortDirection.Output
60
+ if direction == PortDeclarationDirection.Inout:
61
+ return PortDirection.Inout
62
+ raise ClassiqInternalExpansionError
63
+
64
+ def dump(self) -> PortDeclarationDirection:
65
+ if self == PortDirection.Input:
66
+ return PortDeclarationDirection.Input
67
+ if self == PortDirection.Output:
68
+ return PortDeclarationDirection.Output
69
+ if self == PortDirection.Inout:
70
+ return PortDeclarationDirection.Inout
71
+ raise ClassiqInternalExpansionError
72
+
73
+
74
+ @dataclass(frozen=True)
75
+ class _CapturedHandle:
76
+ handle: HandleBinding
77
+ quantum_type: QuantumType
78
+ defining_function: "FunctionClosure"
79
+ direction: PortDirection
80
+ is_propagated: bool
81
+
82
+ @property
83
+ def mangled_name(self) -> str:
84
+ return mangle_captured_var_name(
85
+ self.handle.identifier,
86
+ self.defining_function.name,
87
+ self.defining_function.depth,
88
+ )
89
+
90
+ @property
91
+ def port(self) -> PortDeclaration:
92
+ return PortDeclaration(
93
+ name=self.mangled_name,
94
+ quantum_type=self.quantum_type,
95
+ direction=self.direction.dump(),
96
+ )
97
+
98
+ def is_same_var(self, other: "_CapturedHandle") -> bool:
99
+ return self.handle.name == other.handle.name and _same_closure(
100
+ self.defining_function, other.defining_function
101
+ )
102
+
103
+ def change_direction(self, new_direction: PortDirection) -> "_CapturedHandle":
104
+ return dataclasses.replace(self, direction=new_direction)
105
+
106
+ def set_propagated(self) -> "_CapturedHandle":
107
+ return dataclasses.replace(self, is_propagated=True)
108
+
109
+ def update_propagation(
110
+ self, other_captured_handle: "_CapturedHandle"
111
+ ) -> "_CapturedHandle":
112
+ if self.is_propagated and not other_captured_handle.is_propagated:
113
+ return dataclasses.replace(self, is_propagated=False)
114
+ return self
115
+
116
+ def set_symbol(
117
+ self, handle: HandleBinding, quantum_type: QuantumType
118
+ ) -> "_CapturedHandle":
119
+ return dataclasses.replace(self, handle=handle, quantum_type=quantum_type)
120
+
121
+
122
+ @dataclass
123
+ class CapturedVars:
124
+ _captured_handles: list[_CapturedHandle] = field(default_factory=list)
125
+
126
+ def capture_handle(
127
+ self,
128
+ handle: HandleBinding,
129
+ quantum_type: QuantumType,
130
+ defining_function: "FunctionClosure",
131
+ direction: PortDeclarationDirection,
132
+ ) -> None:
133
+ self._capture_handle(
134
+ _CapturedHandle(
135
+ handle=handle,
136
+ quantum_type=quantum_type,
137
+ defining_function=defining_function,
138
+ direction=PortDirection.load(direction),
139
+ is_propagated=False,
140
+ )
141
+ )
142
+
143
+ def _capture_handle(self, captured_handle: _CapturedHandle) -> None:
144
+ if (
145
+ isinstance(captured_handle.handle, NestedHandleBinding)
146
+ and captured_handle.direction != PortDirection.Inout
147
+ ):
148
+ verb = (
149
+ "free"
150
+ if captured_handle.direction == PortDirection.Input
151
+ else "allocate"
152
+ )
153
+ raise ClassiqExpansionError(
154
+ f"Cannot partially {verb} variable {captured_handle.handle.name}"
155
+ )
156
+
157
+ new_captured_handles = []
158
+ for existing_captured_handle in self._captured_handles:
159
+ if not existing_captured_handle.is_same_var(captured_handle):
160
+ new_captured_handles.append(existing_captured_handle)
161
+ continue
162
+ captured_handle = captured_handle.update_propagation(
163
+ existing_captured_handle
164
+ )
165
+ if existing_captured_handle.handle == captured_handle.handle:
166
+ captured_handle = self._conjugate_direction(
167
+ existing_captured_handle, captured_handle
168
+ )
169
+ elif captured_handle.handle.overlaps(existing_captured_handle.handle):
170
+ captured_handle = self._intersect_handles(
171
+ existing_captured_handle, captured_handle
172
+ )
173
+ else:
174
+ new_captured_handles.append(existing_captured_handle)
175
+ new_captured_handles.append(captured_handle)
176
+ self._captured_handles = new_captured_handles
177
+
178
+ def _conjugate_direction(
179
+ self,
180
+ existing_captured_handle: _CapturedHandle,
181
+ captured_handle: _CapturedHandle,
182
+ ) -> _CapturedHandle:
183
+ if existing_captured_handle.direction == PortDirection.Input:
184
+ if captured_handle.direction == PortDirection.Output:
185
+ return captured_handle.change_direction(PortDirection.Inout)
186
+ if captured_handle.direction == PortDirection.Outin:
187
+ return captured_handle.change_direction(PortDirection.Input)
188
+ raise ClassiqExpansionError(
189
+ ALREADY_FREED_MESSAGE.format(captured_handle.handle)
190
+ )
191
+ if existing_captured_handle.direction == PortDirection.Output:
192
+ if captured_handle.direction == PortDirection.Input:
193
+ return captured_handle.change_direction(PortDirection.Outin)
194
+ if captured_handle.direction in (
195
+ PortDirection.Output,
196
+ PortDirection.Outin,
197
+ ):
198
+ raise ClassiqExpansionError(
199
+ ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
200
+ )
201
+ return captured_handle.change_direction(PortDirection.Output)
202
+ if existing_captured_handle.direction == PortDirection.Inout:
203
+ if captured_handle.direction in (
204
+ PortDirection.Output,
205
+ PortDirection.Outin,
206
+ ):
207
+ raise ClassiqExpansionError(
208
+ ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
209
+ )
210
+ elif captured_handle.direction in (
211
+ PortDirection.Input,
212
+ PortDirection.Inout,
213
+ ):
214
+ raise ClassiqExpansionError(
215
+ ALREADY_FREED_MESSAGE.format(captured_handle.handle)
216
+ )
217
+ return captured_handle
218
+
219
+ def _intersect_handles(
220
+ self,
221
+ existing_captured_handle: _CapturedHandle,
222
+ captured_handle: _CapturedHandle,
223
+ ) -> _CapturedHandle:
224
+ if captured_handle.handle in existing_captured_handle.handle:
225
+ if existing_captured_handle.direction in (
226
+ PortDirection.Input,
227
+ PortDirection.Outin,
228
+ ):
229
+ raise ClassiqExpansionError(
230
+ ALREADY_FREED_MESSAGE.format(captured_handle.handle)
231
+ )
232
+ return existing_captured_handle
233
+
234
+ if existing_captured_handle.handle in captured_handle.handle:
235
+ if captured_handle.direction in (
236
+ PortDirection.Output,
237
+ PortDirection.Outin,
238
+ ):
239
+ raise ClassiqExpansionError(
240
+ ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
241
+ )
242
+ return captured_handle
243
+
244
+ sliced_handle, quantum_type, other_handle = self._get_sliced_handle(
245
+ existing_captured_handle, captured_handle
246
+ )
247
+ if not isinstance(other_handle, SlicedHandleBinding):
248
+ return captured_handle.set_symbol(sliced_handle, quantum_type)
249
+
250
+ merged_handle, merged_quantum_type = self._merge_sliced_handles(
251
+ sliced_handle, other_handle, quantum_type
252
+ )
253
+ return captured_handle.set_symbol(merged_handle, merged_quantum_type)
254
+
255
+ @staticmethod
256
+ def _get_sliced_handle(
257
+ existing_captured_handle: _CapturedHandle,
258
+ captured_handle: _CapturedHandle,
259
+ ) -> tuple[SlicedHandleBinding, QuantumBitvector, HandleBinding]:
260
+ handle_1 = existing_captured_handle.handle
261
+ quantum_type_1 = existing_captured_handle.quantum_type
262
+ handle_2 = captured_handle.handle
263
+ quantum_type_2 = captured_handle.quantum_type
264
+ if isinstance(handle_1, SlicedHandleBinding):
265
+ sliced_handle = handle_1
266
+ other_handle = handle_2
267
+ quantum_type = quantum_type_1
268
+ elif isinstance(handle_2, SlicedHandleBinding):
269
+ sliced_handle = handle_2
270
+ other_handle = handle_1
271
+ quantum_type = quantum_type_2
272
+ else:
273
+ raise ClassiqInternalExpansionError(
274
+ f"Unexpected overlapping handles {handle_1} and {handle_2}"
275
+ )
276
+ if not isinstance(quantum_type, QuantumBitvector):
277
+ raise ClassiqInternalExpansionError
278
+ return sliced_handle, quantum_type, other_handle
279
+
280
+ @staticmethod
281
+ def _merge_sliced_handles(
282
+ handle_1: SlicedHandleBinding,
283
+ handle_2: SlicedHandleBinding,
284
+ quantum_type: QuantumBitvector,
285
+ ) -> tuple[HandleBinding, QuantumBitvector]:
286
+ if (
287
+ not handle_1.start.is_evaluated()
288
+ or not handle_1.end.is_evaluated()
289
+ or not handle_2.start.is_evaluated()
290
+ or not handle_2.end.is_evaluated()
291
+ ):
292
+ raise ClassiqInternalExpansionError
293
+
294
+ new_start = min(handle_1.start.to_int_value(), handle_2.start.to_int_value())
295
+ new_end = max(handle_1.end.to_int_value(), handle_2.end.to_int_value())
296
+ merged_handle = SlicedHandleBinding(
297
+ base_handle=handle_1.base_handle,
298
+ start=Expression(expr=str(new_start)),
299
+ end=Expression(expr=str(new_end)),
300
+ )
301
+ merged_quantum_type = QuantumBitvector(
302
+ element_type=quantum_type.element_type,
303
+ length=Expression(expr=str(new_end - new_start)),
304
+ )
305
+ return merged_handle, merged_quantum_type
306
+
307
+ def update(self, other_captured_vars: "CapturedVars") -> None:
308
+ for captured_handle in other_captured_vars._captured_handles:
309
+ self._capture_handle(captured_handle)
310
+
311
+ def negate(self) -> "CapturedVars":
312
+ return CapturedVars(
313
+ _captured_handles=[
314
+ captured_handle.change_direction(captured_handle.direction.negate())
315
+ for captured_handle in self._captured_handles
316
+ ]
317
+ )
318
+
319
+ def filter_vars(
320
+ self,
321
+ current_function: "FunctionClosure",
322
+ current_declarations: Optional[list[VariableDeclarationStatement]] = None,
323
+ ) -> "CapturedVars":
324
+ current_declared_vars = (
325
+ None
326
+ if current_declarations is None
327
+ else {decl.name for decl in current_declarations}
328
+ )
329
+ return CapturedVars(
330
+ _captured_handles=[
331
+ captured_handle
332
+ for captured_handle in self._captured_handles
333
+ if not _same_closure(
334
+ captured_handle.defining_function, current_function
335
+ )
336
+ or (
337
+ current_declared_vars is not None
338
+ and captured_handle.handle.name not in current_declared_vars
339
+ )
340
+ ]
341
+ )
342
+
343
+ def set_propagated(self) -> "CapturedVars":
344
+ return CapturedVars(
345
+ _captured_handles=[
346
+ captured_handle.set_propagated()
347
+ for captured_handle in self._captured_handles
348
+ ]
349
+ )
350
+
351
+ def get_captured_ports(self) -> list[PortDeclaration]:
352
+ return [captured_handle.port for captured_handle in self._captured_handles]
353
+
354
+ def get_captured_args(
355
+ self, current_function: "FunctionClosure"
356
+ ) -> list[HandleBinding]:
357
+ return [
358
+ (
359
+ captured_handle.handle
360
+ if _same_closure(current_function, captured_handle.defining_function)
361
+ else HandleBinding(name=captured_handle.mangled_name)
362
+ )
363
+ for captured_handle in self._captured_handles
364
+ ]
365
+
366
+ def get_captured_mapping(self) -> SymbolParts:
367
+ return {
368
+ captured_handle.handle: [
369
+ SymbolPart(
370
+ source_handle=captured_handle.handle,
371
+ target_var_name=captured_handle.mangled_name,
372
+ target_var_type=captured_handle.quantum_type,
373
+ )
374
+ ]
375
+ for captured_handle in self._captured_handles
376
+ if not captured_handle.is_propagated
377
+ }
378
+
379
+ def clone(self) -> "CapturedVars":
380
+ return CapturedVars(_captured_handles=list(self._captured_handles))
381
+
382
+
383
+ def _same_closure(closure_1: "FunctionClosure", closure_2: "FunctionClosure") -> bool:
384
+ return closure_1.depth == closure_2.depth
385
+
386
+
387
+ def validate_args_are_not_propagated(
388
+ args: Sequence[ArgValue], captured_vars: Sequence[HandleBinding]
389
+ ) -> None:
390
+ if not captured_vars:
391
+ return
392
+ captured_handles = {demangle_handle(handle) for handle in captured_vars}
393
+ arg_handles = {
394
+ demangle_handle(arg) for arg in args if isinstance(arg, HandleBinding)
395
+ }
396
+ if any(
397
+ arg_handle.overlaps(captured_handle)
398
+ for arg_handle in arg_handles
399
+ for captured_handle in captured_handles
400
+ ):
401
+ captured_handles_str = {str(handle) for handle in captured_handles}
402
+ arg_handles_str = {str(handle) for handle in arg_handles}
403
+ vars_msg = f"Explicitly passed variables: {arg_handles_str}, captured variables: {captured_handles_str}"
404
+ raise ClassiqExpansionError(
405
+ f"Cannot capture variables that are explicitly passed as arguments. "
406
+ f"{vars_msg}"
407
+ )
408
+
409
+
410
+ def validate_captured_directions(
411
+ captured_vars: CapturedVars, report_outin: bool = True
412
+ ) -> None:
413
+ captured_inputs = [
414
+ captured_handle.handle.name
415
+ for captured_handle in captured_vars._captured_handles
416
+ if captured_handle.direction == PortDirection.Input
417
+ ]
418
+ captured_outputs = [
419
+ captured_handle.handle.name
420
+ for captured_handle in captured_vars._captured_handles
421
+ if captured_handle.direction
422
+ in (
423
+ (PortDirection.Output, PortDirection.Outin)
424
+ if report_outin
425
+ else (PortDirection.Output,)
426
+ )
427
+ ]
428
+ if len(captured_inputs) > 0:
429
+ raise ClassiqExpansionError(
430
+ f"Captured quantum variables {captured_inputs!r} cannot be used as inputs"
431
+ )
432
+ if len(captured_outputs) > 0:
433
+ raise ClassiqExpansionError(
434
+ f"Captured quantum variables {captured_outputs!r} cannot be used as outputs"
435
+ )
@@ -0,0 +1,56 @@
1
+ import re
2
+ from typing import Optional
3
+
4
+ from classiq.interface.generator.compiler_keywords import CAPTURE_SUFFIX
5
+ from classiq.interface.model.handle_binding import HANDLE_ID_SEPARATOR, HandleBinding
6
+
7
+ IDENTIFIER_PATTERN = r"[a-zA-Z_][a-zA-Z0-9_]*"
8
+ CAPTURE_PATTERN = re.compile(
9
+ rf"({IDENTIFIER_PATTERN}){CAPTURE_SUFFIX}{IDENTIFIER_PATTERN}__\d*"
10
+ )
11
+ ARRAY_CAST_SUFFIX = HANDLE_ID_SEPARATOR + "array_cast"
12
+
13
+
14
+ def mangle_captured_var_name(
15
+ var_name: str, function_name: str, function_depth: int
16
+ ) -> str:
17
+ return f"{var_name}{CAPTURE_SUFFIX}{function_name}__{function_depth}"
18
+
19
+
20
+ def _match_capture_pattern(name: str) -> Optional[re.Match[str]]:
21
+ return re.match(CAPTURE_PATTERN, name)
22
+
23
+
24
+ def is_captured_var_name(name: str) -> bool:
25
+ return _match_capture_pattern(name) is not None
26
+
27
+
28
+ def demangle_capture_name(name: str) -> str:
29
+ match = _match_capture_pattern(name)
30
+ return match.group(1) if match else name
31
+
32
+
33
+ def demangle_handle(handle: HandleBinding) -> HandleBinding:
34
+ demangled_name = demangle_name(handle.name)
35
+ return handle.rename(demangled_name)
36
+
37
+
38
+ def demangle_name(name: str) -> str:
39
+ if HANDLE_ID_SEPARATOR not in name:
40
+ return name
41
+ if ARRAY_CAST_SUFFIX in name:
42
+ return name.split(ARRAY_CAST_SUFFIX)[0]
43
+ name = re.sub(r"([^_])_\d+$", r"\1", name)
44
+ name_parts = name.split(HANDLE_ID_SEPARATOR)
45
+ new_name_parts = [name_parts[0]]
46
+ for part in name_parts[1:]:
47
+ if re.fullmatch(r"\d+", part):
48
+ new_name_parts.append(f"[{part}]")
49
+ elif re.fullmatch(r"\d+_\d+", part):
50
+ part_left, part_right = part.split("_")
51
+ new_name_parts.append(f"[{part_left}:{part_right}]")
52
+ else:
53
+ new_name_parts.append(f".{part}")
54
+ new_name_parts = list(map(demangle_capture_name, new_name_parts))
55
+ new_name = "".join(new_name_parts)
56
+ return new_name
@@ -0,0 +1,171 @@
1
+ import dataclasses
2
+ import json
3
+ from collections.abc import Collection, Sequence
4
+ from dataclasses import dataclass, field
5
+ from functools import singledispatch
6
+ from typing import Any, Optional
7
+
8
+ from typing_extensions import Self
9
+
10
+ from classiq.interface.exceptions import ClassiqInternalExpansionError
11
+ from classiq.interface.model.port_declaration import PortDeclaration
12
+ from classiq.interface.model.quantum_function_declaration import (
13
+ NamedParamsQuantumFunctionDeclaration,
14
+ PositionalArg,
15
+ )
16
+ from classiq.interface.model.quantum_lambda_function import QuantumCallable
17
+ from classiq.interface.model.quantum_statement import QuantumStatement
18
+
19
+ from classiq.model_expansions.capturing.captured_vars import CapturedVars
20
+ from classiq.model_expansions.expression_renamer import ExpressionRenamer
21
+ from classiq.model_expansions.scope import (
22
+ Evaluated,
23
+ QuantumSymbol,
24
+ Scope,
25
+ evaluated_to_str as evaluated_classical_param_to_str,
26
+ )
27
+ from classiq.qmod.builtins.functions import permute
28
+ from classiq.qmod.quantum_function import GenerativeQFunc
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ class Closure:
33
+ name: str
34
+ blocks: dict[str, Sequence[QuantumStatement]]
35
+ scope: Scope
36
+ positional_arg_declarations: Sequence[PositionalArg] = tuple()
37
+ captured_vars: CapturedVars = field(default_factory=CapturedVars)
38
+
39
+ @property
40
+ def port_declarations(self) -> dict[str, PortDeclaration]:
41
+ return {
42
+ param.name: param
43
+ for param in self.positional_arg_declarations
44
+ if isinstance(param, PortDeclaration)
45
+ }
46
+
47
+
48
+ @dataclass(frozen=True)
49
+ class GenerativeClosure(Closure):
50
+ generative_blocks: dict[str, GenerativeQFunc] = None # type:ignore[assignment]
51
+
52
+
53
+ @dataclass(frozen=True)
54
+ class FunctionClosure(Closure):
55
+ is_lambda: bool = False
56
+ is_atomic: bool = False
57
+ signature_scope: Scope = field(default_factory=Scope)
58
+ _depth: Optional[int] = None
59
+
60
+ @property
61
+ def depth(self) -> int:
62
+ if self._depth is None:
63
+ raise ClassiqInternalExpansionError
64
+ return self._depth
65
+
66
+ # creates a unique id for the function closure based on the arguments values.
67
+ # The closure is changing across the interpreter flow so it's closure_id may change
68
+ @property
69
+ def closure_id(self) -> str:
70
+ signature = _generate_closure_id(self.scope.data.values())
71
+ return f"{self.name}__{signature}"
72
+
73
+ @property
74
+ def body(self) -> Sequence[QuantumStatement]:
75
+ if self.name == permute.func_decl.name:
76
+ # permute is an old Qmod "generative" function that doesn't have a body
77
+ return []
78
+ return self.blocks["body"]
79
+
80
+ @classmethod
81
+ def create(
82
+ cls,
83
+ name: str,
84
+ scope: Scope,
85
+ body: Optional[Sequence[QuantumStatement]] = None,
86
+ positional_arg_declarations: Sequence[PositionalArg] = tuple(),
87
+ expr_renamer: Optional[ExpressionRenamer] = None,
88
+ is_lambda: bool = False,
89
+ is_atomic: bool = False,
90
+ **kwargs: Any,
91
+ ) -> Self:
92
+ if expr_renamer:
93
+ positional_arg_declarations = (
94
+ expr_renamer.rename_positional_arg_declarations(
95
+ positional_arg_declarations
96
+ )
97
+ )
98
+ if body is not None:
99
+ body = expr_renamer.visit(body)
100
+
101
+ blocks = {"body": body} if body is not None else {}
102
+ return cls(
103
+ name,
104
+ blocks,
105
+ scope,
106
+ positional_arg_declarations,
107
+ CapturedVars(),
108
+ is_lambda,
109
+ is_atomic,
110
+ **kwargs,
111
+ )
112
+
113
+ def with_new_declaration(
114
+ self, declaration: NamedParamsQuantumFunctionDeclaration
115
+ ) -> Self:
116
+ fields: dict = self.__dict__ | {
117
+ "name": declaration.name,
118
+ "positional_arg_declarations": declaration.positional_arg_declarations,
119
+ }
120
+ return type(self)(**fields)
121
+
122
+ def set_depth(self, depth: int) -> Self:
123
+ return dataclasses.replace(self, _depth=depth)
124
+
125
+ def clone(self) -> Self:
126
+ return dataclasses.replace(
127
+ self,
128
+ scope=self.scope.clone(),
129
+ signature_scope=self.signature_scope.clone(),
130
+ captured_vars=self.captured_vars.clone(),
131
+ )
132
+
133
+ def emit(self) -> QuantumCallable:
134
+ return self.name
135
+
136
+
137
+ @dataclass(frozen=True)
138
+ class GenerativeFunctionClosure(GenerativeClosure, FunctionClosure):
139
+ pass
140
+
141
+
142
+ def _generate_closure_id(evaluated_args: Collection[Evaluated]) -> str:
143
+ args_signature = [
144
+ _evaluated_arg_to_str(eval_arg.value) for eval_arg in evaluated_args
145
+ ]
146
+ return json.dumps(args_signature)
147
+
148
+
149
+ @singledispatch
150
+ def _evaluated_arg_to_str(arg: Any) -> str:
151
+ if isinstance(arg, str):
152
+ return arg
153
+ if isinstance(arg, QuantumSymbol):
154
+ return _evaluated_quantum_symbol_to_str(arg)
155
+ if isinstance(arg, FunctionClosure):
156
+ return _evaluated_one_operand_to_str(arg)
157
+ if isinstance(arg, list) and arg and isinstance(arg[0], FunctionClosure):
158
+ return _evaluated_operands_list_to_str(arg)
159
+ return evaluated_classical_param_to_str(arg)
160
+
161
+
162
+ def _evaluated_quantum_symbol_to_str(port: QuantumSymbol) -> str:
163
+ return port.quantum_type.model_dump_json(exclude_none=True, exclude={"name"})
164
+
165
+
166
+ def _evaluated_one_operand_to_str(operand: FunctionClosure) -> str:
167
+ return operand.closure_id
168
+
169
+
170
+ def _evaluated_operands_list_to_str(arg: list[FunctionClosure]) -> str:
171
+ return json.dumps([_evaluated_one_operand_to_str(ope) for ope in arg])
@@ -0,0 +1,3 @@
1
+ from contextvars import ContextVar
2
+
3
+ debug_mode: ContextVar[bool] = ContextVar("debug_mode", default=False)
File without changes