classiq 0.38.0__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 (499) hide show
  1. classiq/__init__.py +47 -32
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
  3. classiq/_internals/api_wrapper.py +235 -97
  4. classiq/_internals/async_utils.py +1 -3
  5. classiq/_internals/authentication/auth0.py +26 -10
  6. classiq/_internals/authentication/authentication.py +11 -0
  7. classiq/_internals/authentication/device.py +10 -5
  8. classiq/_internals/authentication/password_manager.py +18 -6
  9. classiq/_internals/authentication/token_manager.py +10 -5
  10. classiq/_internals/client.py +94 -33
  11. classiq/_internals/config.py +3 -4
  12. classiq/_internals/host_checker.py +38 -15
  13. classiq/_internals/jobs.py +60 -57
  14. classiq/_internals/type_validation.py +9 -9
  15. classiq/analyzer/__init__.py +1 -3
  16. classiq/analyzer/analyzer.py +24 -19
  17. classiq/analyzer/analyzer_utilities.py +10 -10
  18. classiq/analyzer/rb.py +15 -15
  19. classiq/analyzer/show_interactive_hack.py +27 -4
  20. classiq/analyzer/url_utils.py +2 -3
  21. classiq/applications/__init__.py +3 -12
  22. classiq/applications/chemistry/__init__.py +14 -10
  23. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  24. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +165 -158
  25. classiq/applications/chemistry/ground_state_problem.py +1 -1
  26. classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +4 -1
  27. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
  28. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +1 -1
  29. classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +51 -15
  30. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +12 -12
  31. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +8 -6
  32. classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +7 -11
  33. classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +67 -40
  34. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
  35. classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
  36. classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +2 -2
  37. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +15 -20
  38. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +14 -15
  39. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +11 -15
  40. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +1 -2
  41. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
  42. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +2 -3
  43. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +5 -8
  44. classiq/applications/combinatorial_optimization/__init__.py +20 -6
  45. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  46. classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +35 -33
  47. classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
  48. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  49. classiq/applications/finance/__init__.py +4 -5
  50. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +48 -42
  51. classiq/applications/grover/__init__.py +9 -0
  52. classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +52 -51
  53. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  54. classiq/applications/libraries/qmci_library.py +22 -0
  55. classiq/applications/qnn/__init__.py +2 -4
  56. classiq/applications/qnn/circuit_utils.py +6 -6
  57. classiq/applications/qnn/datasets/__init__.py +9 -11
  58. classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
  59. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  60. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  61. classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
  62. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  63. classiq/applications/qnn/qlayer.py +30 -10
  64. classiq/applications/qnn/torch_utils.py +4 -3
  65. classiq/applications/qnn/types.py +5 -5
  66. classiq/applications/qsvm/__init__.py +6 -4
  67. classiq/applications/qsvm/qsvm.py +3 -6
  68. classiq/applications/qsvm/qsvm_data_generation.py +3 -3
  69. classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
  70. classiq/execution/__init__.py +8 -3
  71. classiq/execution/all_hardware_devices.py +11 -0
  72. classiq/execution/execution_session.py +400 -0
  73. classiq/execution/iqcc.py +63 -0
  74. classiq/execution/jobs.py +197 -25
  75. classiq/execution/qnn.py +79 -0
  76. classiq/executor.py +20 -115
  77. classiq/interface/_version.py +1 -1
  78. classiq/interface/analyzer/analysis_params.py +43 -13
  79. classiq/interface/analyzer/cytoscape_graph.py +15 -9
  80. classiq/interface/analyzer/result.py +28 -32
  81. classiq/interface/applications/qsvm.py +20 -29
  82. classiq/interface/ast_node.py +16 -0
  83. classiq/interface/backend/backend_preferences.py +390 -121
  84. classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
  85. classiq/interface/backend/pydantic_backend.py +25 -22
  86. classiq/interface/backend/quantum_backend_providers.py +69 -16
  87. classiq/interface/chemistry/fermionic_operator.py +30 -21
  88. classiq/interface/chemistry/ground_state_problem.py +28 -25
  89. classiq/interface/chemistry/molecule.py +14 -10
  90. classiq/interface/chemistry/operator.py +64 -231
  91. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  92. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
  93. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  94. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  95. classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
  96. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  97. classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
  98. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +8 -9
  99. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  100. classiq/interface/combinatorial_optimization/result.py +1 -3
  101. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  102. classiq/interface/debug_info/debug_info.py +86 -0
  103. classiq/{exceptions.py → interface/exceptions.py} +37 -9
  104. classiq/interface/execution/iqcc.py +19 -0
  105. classiq/interface/execution/jobs.py +15 -12
  106. classiq/interface/execution/primitives.py +18 -0
  107. classiq/interface/executor/constants.py +1 -0
  108. classiq/interface/executor/execution_preferences.py +26 -114
  109. classiq/interface/executor/execution_request.py +24 -46
  110. classiq/interface/executor/execution_result.py +30 -8
  111. classiq/interface/executor/iqae_result.py +4 -6
  112. classiq/interface/executor/optimizer_preferences.py +17 -14
  113. classiq/interface/executor/quantum_code.py +28 -24
  114. classiq/interface/executor/quantum_instruction_set.py +2 -2
  115. classiq/interface/executor/register_initialization.py +11 -14
  116. classiq/interface/executor/result.py +83 -56
  117. classiq/interface/executor/vqe_result.py +10 -10
  118. classiq/interface/finance/function_input.py +35 -25
  119. classiq/interface/finance/gaussian_model_input.py +5 -5
  120. classiq/interface/finance/log_normal_model_input.py +4 -4
  121. classiq/interface/finance/model_input.py +4 -4
  122. classiq/interface/generator/adjacency.py +1 -3
  123. classiq/interface/generator/amplitude_loading.py +22 -12
  124. classiq/interface/generator/ansatz_library.py +5 -5
  125. classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
  126. classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
  127. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
  128. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  129. classiq/interface/generator/application_apis/finance_declarations.py +48 -69
  130. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
  131. classiq/interface/generator/arith/argument_utils.py +46 -5
  132. classiq/interface/generator/arith/arithmetic.py +35 -16
  133. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +6 -7
  134. classiq/interface/generator/arith/arithmetic_expression_abc.py +66 -25
  135. classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -11
  136. classiq/interface/generator/arith/arithmetic_expression_validator.py +47 -43
  137. classiq/interface/generator/arith/arithmetic_operations.py +14 -6
  138. classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
  139. classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
  140. classiq/interface/generator/arith/ast_node_rewrite.py +3 -2
  141. classiq/interface/generator/arith/binary_ops.py +218 -130
  142. classiq/interface/generator/arith/endianness.py +1 -1
  143. classiq/interface/generator/arith/extremum_operations.py +96 -25
  144. classiq/interface/generator/arith/logical_ops.py +14 -12
  145. classiq/interface/generator/arith/number_utils.py +12 -6
  146. classiq/interface/generator/arith/register_user_input.py +60 -37
  147. classiq/interface/generator/arith/unary_ops.py +49 -29
  148. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  149. classiq/interface/generator/builtin_api_builder.py +2 -9
  150. classiq/interface/generator/chemistry_function_params.py +3 -3
  151. classiq/interface/generator/circuit_code/circuit_code.py +7 -7
  152. classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
  153. classiq/interface/generator/commuting_pauli_exponentiation.py +7 -7
  154. classiq/interface/generator/compiler_keywords.py +5 -1
  155. classiq/interface/generator/complex_type.py +13 -18
  156. classiq/interface/generator/constant.py +3 -4
  157. classiq/interface/generator/control_state.py +34 -29
  158. classiq/interface/generator/copy.py +47 -0
  159. classiq/interface/generator/custom_ansatz.py +2 -5
  160. classiq/interface/generator/distance.py +3 -5
  161. classiq/interface/generator/excitations.py +3 -2
  162. classiq/interface/generator/expressions/atomic_expression_functions.py +21 -5
  163. classiq/interface/generator/expressions/enums/__init__.py +0 -10
  164. classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
  165. classiq/interface/generator/expressions/evaluated_expression.py +5 -5
  166. classiq/interface/generator/expressions/expression.py +26 -14
  167. classiq/interface/generator/expressions/expression_constants.py +9 -3
  168. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  169. classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
  170. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +34 -8
  171. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
  172. classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
  173. classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
  174. classiq/interface/generator/expressions/sympy_supported_expressions.py +19 -11
  175. classiq/interface/generator/finance.py +2 -2
  176. classiq/interface/generator/function_param_library.py +6 -6
  177. classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
  178. classiq/interface/generator/function_params.py +36 -64
  179. classiq/interface/generator/functions/__init__.py +0 -22
  180. classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
  181. classiq/interface/generator/functions/classical_function_declaration.py +18 -9
  182. classiq/interface/generator/functions/classical_type.py +47 -166
  183. classiq/interface/generator/functions/concrete_types.py +55 -0
  184. classiq/interface/generator/functions/function_declaration.py +13 -14
  185. classiq/interface/generator/functions/port_declaration.py +1 -13
  186. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  187. classiq/interface/generator/functions/type_name.py +90 -0
  188. classiq/interface/generator/generated_circuit_data.py +153 -20
  189. classiq/interface/generator/grover_diffuser.py +32 -25
  190. classiq/interface/generator/grover_operator.py +34 -25
  191. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
  192. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  193. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +9 -9
  194. classiq/interface/generator/hardware/hardware_data.py +72 -34
  195. classiq/interface/generator/hardware_efficient_ansatz.py +20 -16
  196. classiq/interface/generator/hartree_fock.py +13 -5
  197. classiq/interface/generator/identity.py +10 -6
  198. classiq/interface/generator/linear_pauli_rotations.py +32 -20
  199. classiq/interface/generator/mcmt_method.py +1 -1
  200. classiq/interface/generator/mcu.py +17 -15
  201. classiq/interface/generator/mcx.py +24 -17
  202. classiq/interface/generator/model/__init__.py +2 -5
  203. classiq/interface/generator/model/constraints.py +26 -8
  204. classiq/interface/generator/model/model.py +27 -190
  205. classiq/interface/generator/model/preferences/preferences.py +115 -41
  206. classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +14 -17
  207. classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
  208. classiq/interface/generator/oracles/custom_oracle.py +15 -13
  209. classiq/interface/generator/oracles/oracle_abc.py +7 -7
  210. classiq/interface/generator/partitioned_register.py +7 -7
  211. classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
  212. classiq/interface/generator/preferences/optimization.py +1 -2
  213. classiq/interface/generator/qpe.py +41 -30
  214. classiq/interface/generator/qsvm.py +9 -10
  215. classiq/interface/generator/quantum_function_call.py +88 -73
  216. classiq/interface/generator/quantum_program.py +41 -24
  217. classiq/interface/generator/range_types.py +11 -12
  218. classiq/interface/generator/register_role.py +18 -6
  219. classiq/interface/generator/slice_parsing_utils.py +5 -5
  220. classiq/interface/generator/standard_gates/controlled_standard_gates.py +30 -39
  221. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  222. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  223. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  224. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  225. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  226. classiq/interface/generator/state_preparation/distributions.py +16 -15
  227. classiq/interface/generator/state_preparation/metrics.py +4 -7
  228. classiq/interface/generator/state_preparation/state_preparation.py +25 -20
  229. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  230. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
  231. classiq/interface/generator/transpiler_basis_gates.py +7 -3
  232. classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
  233. classiq/interface/generator/types/compilation_metadata.py +6 -0
  234. classiq/interface/generator/types/enum_declaration.py +54 -0
  235. classiq/interface/generator/types/qstruct_declaration.py +18 -0
  236. classiq/interface/generator/types/struct_declaration.py +7 -11
  237. classiq/interface/generator/ucc.py +5 -4
  238. classiq/interface/generator/unitary_gate.py +5 -5
  239. classiq/interface/generator/user_defined_function_params.py +4 -1
  240. classiq/interface/generator/validations/flow_graph.py +7 -7
  241. classiq/interface/generator/validations/validator_functions.py +4 -4
  242. classiq/interface/generator/visitor.py +23 -16
  243. classiq/interface/hardware.py +29 -8
  244. classiq/interface/helpers/classproperty.py +8 -0
  245. classiq/interface/helpers/custom_encoders.py +2 -2
  246. classiq/interface/helpers/custom_pydantic_types.py +40 -50
  247. classiq/interface/helpers/datastructures.py +26 -0
  248. classiq/interface/helpers/hashable_mixin.py +3 -2
  249. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  250. classiq/interface/helpers/pydantic_model_helpers.py +7 -5
  251. classiq/interface/helpers/validation_helpers.py +3 -20
  252. classiq/interface/helpers/versioned_model.py +1 -4
  253. classiq/interface/ide/ide_data.py +16 -20
  254. classiq/interface/ide/visual_model.py +130 -0
  255. classiq/interface/interface_version.py +1 -0
  256. classiq/interface/jobs.py +29 -69
  257. classiq/interface/model/allocate.py +16 -0
  258. classiq/interface/model/bind_operation.py +32 -9
  259. classiq/interface/model/classical_if.py +15 -0
  260. classiq/interface/model/classical_parameter_declaration.py +33 -3
  261. classiq/interface/model/control.py +45 -0
  262. classiq/interface/model/handle_binding.py +298 -20
  263. classiq/interface/model/inplace_binary_operation.py +29 -24
  264. classiq/interface/model/invert.py +12 -0
  265. classiq/interface/model/model.py +69 -61
  266. classiq/interface/model/native_function_definition.py +17 -20
  267. classiq/interface/model/parameter.py +13 -0
  268. classiq/interface/model/phase_operation.py +11 -0
  269. classiq/interface/model/port_declaration.py +27 -9
  270. classiq/interface/model/power.py +14 -0
  271. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +30 -18
  272. classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
  273. classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
  274. classiq/interface/model/quantum_function_call.py +141 -343
  275. classiq/interface/model/quantum_function_declaration.py +190 -157
  276. classiq/interface/model/quantum_lambda_function.py +33 -32
  277. classiq/interface/model/quantum_statement.py +71 -12
  278. classiq/interface/model/quantum_type.py +177 -40
  279. classiq/interface/model/quantum_variable_declaration.py +3 -25
  280. classiq/interface/model/repeat.py +15 -0
  281. classiq/interface/model/statement_block.py +40 -14
  282. classiq/interface/model/validation_handle.py +13 -6
  283. classiq/interface/model/variable_declaration_statement.py +3 -1
  284. classiq/interface/model/within_apply_operation.py +7 -5
  285. classiq/interface/server/global_versions.py +6 -7
  286. classiq/interface/server/routes.py +17 -21
  287. classiq/interface/source_reference.py +59 -0
  288. classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
  289. classiq/model_expansions/capturing/__init__.py +0 -0
  290. classiq/model_expansions/capturing/captured_vars.py +435 -0
  291. classiq/model_expansions/capturing/mangling_utils.py +56 -0
  292. classiq/model_expansions/closure.py +171 -0
  293. classiq/model_expansions/debug_flag.py +3 -0
  294. classiq/model_expansions/evaluators/__init__.py +0 -0
  295. classiq/model_expansions/evaluators/arg_type_match.py +158 -0
  296. classiq/model_expansions/evaluators/argument_types.py +42 -0
  297. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  298. classiq/model_expansions/evaluators/control.py +144 -0
  299. classiq/model_expansions/evaluators/parameter_types.py +226 -0
  300. classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
  301. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  302. classiq/model_expansions/expression_evaluator.py +135 -0
  303. classiq/model_expansions/expression_renamer.py +76 -0
  304. classiq/model_expansions/function_builder.py +247 -0
  305. classiq/model_expansions/generative_functions.py +158 -0
  306. classiq/model_expansions/interpreters/__init__.py +0 -0
  307. classiq/model_expansions/interpreters/base_interpreter.py +263 -0
  308. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
  309. classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
  310. classiq/model_expansions/model_tables.py +18 -0
  311. classiq/model_expansions/quantum_operations/__init__.py +9 -0
  312. classiq/model_expansions/quantum_operations/bind.py +60 -0
  313. classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
  314. classiq/model_expansions/quantum_operations/classicalif.py +53 -0
  315. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
  316. classiq/model_expansions/quantum_operations/emitter.py +181 -0
  317. classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
  318. classiq/model_expansions/quantum_operations/repeat.py +56 -0
  319. classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
  320. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  321. classiq/model_expansions/scope.py +240 -0
  322. classiq/model_expansions/scope_initialization.py +150 -0
  323. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  324. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  325. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
  326. classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
  327. classiq/model_expansions/transformers/__init__.py +0 -0
  328. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  329. classiq/model_expansions/transformers/var_splitter.py +299 -0
  330. classiq/model_expansions/utils/__init__.py +0 -0
  331. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  332. classiq/model_expansions/utils/handles_collector.py +33 -0
  333. classiq/model_expansions/visitors/__init__.py +0 -0
  334. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  335. classiq/model_expansions/visitors/variable_references.py +144 -0
  336. classiq/open_library/__init__.py +4 -0
  337. classiq/open_library/functions/__init__.py +130 -0
  338. classiq/open_library/functions/amplitude_estimation.py +30 -0
  339. classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
  340. classiq/open_library/functions/grover.py +157 -0
  341. classiq/open_library/functions/hea.py +115 -0
  342. classiq/open_library/functions/linear_pauli_rotation.py +82 -0
  343. classiq/open_library/functions/modular_exponentiation.py +201 -0
  344. classiq/open_library/functions/qaoa_penalty.py +117 -0
  345. classiq/open_library/functions/qft_functions.py +54 -0
  346. classiq/open_library/functions/qpe.py +46 -0
  347. classiq/open_library/functions/qsvt.py +331 -0
  348. classiq/open_library/functions/state_preparation.py +301 -0
  349. classiq/open_library/functions/swap_test.py +27 -0
  350. classiq/open_library/functions/utility_functions.py +81 -0
  351. classiq/open_library/functions/variational.py +52 -0
  352. classiq/qmod/__init__.py +10 -10
  353. classiq/qmod/builtins/__init__.py +19 -2
  354. classiq/qmod/builtins/classical_execution_primitives.py +36 -14
  355. classiq/qmod/builtins/classical_functions.py +39 -43
  356. classiq/qmod/builtins/constants.py +10 -0
  357. classiq/qmod/builtins/enums.py +208 -0
  358. classiq/qmod/builtins/functions/__init__.py +137 -0
  359. classiq/qmod/builtins/functions/allocation.py +150 -0
  360. classiq/qmod/builtins/functions/arithmetic.py +55 -0
  361. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  362. classiq/qmod/builtins/functions/chemistry.py +91 -0
  363. classiq/qmod/builtins/functions/exponentiation.py +105 -0
  364. classiq/qmod/builtins/functions/finance.py +34 -0
  365. classiq/qmod/builtins/functions/operators.py +16 -0
  366. classiq/qmod/builtins/functions/qsvm.py +24 -0
  367. classiq/qmod/builtins/functions/standard_gates.py +651 -0
  368. classiq/qmod/builtins/operations.py +373 -40
  369. classiq/qmod/builtins/structs.py +103 -80
  370. classiq/qmod/cfunc.py +2 -2
  371. classiq/qmod/classical_function.py +4 -8
  372. classiq/qmod/cparam.py +64 -0
  373. classiq/qmod/create_model_function.py +56 -0
  374. classiq/qmod/declaration_inferrer.py +143 -101
  375. classiq/qmod/expression_query.py +20 -4
  376. classiq/qmod/generative.py +42 -0
  377. classiq/qmod/model_state_container.py +18 -6
  378. classiq/qmod/native/__init__.py +7 -0
  379. classiq/qmod/native/expression_to_qmod.py +16 -11
  380. classiq/qmod/native/pretty_printer.py +187 -97
  381. classiq/qmod/pretty_print/__init__.py +7 -0
  382. classiq/qmod/pretty_print/expression_to_python.py +222 -0
  383. classiq/qmod/pretty_print/pretty_printer.py +572 -0
  384. classiq/qmod/python_classical_type.py +67 -0
  385. classiq/qmod/qfunc.py +60 -8
  386. classiq/qmod/qmod_constant.py +93 -26
  387. classiq/qmod/qmod_parameter.py +68 -59
  388. classiq/qmod/qmod_variable.py +468 -155
  389. classiq/qmod/quantum_callable.py +17 -7
  390. classiq/qmod/quantum_expandable.py +269 -96
  391. classiq/qmod/quantum_function.py +196 -41
  392. classiq/qmod/semantics/__init__.py +0 -0
  393. classiq/qmod/semantics/annotation/__init__.py +0 -0
  394. classiq/qmod/semantics/annotation/call_annotation.py +92 -0
  395. classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
  396. classiq/qmod/semantics/error_manager.py +88 -0
  397. classiq/qmod/semantics/lambdas.py +25 -0
  398. classiq/qmod/semantics/static_semantics_visitor.py +384 -0
  399. classiq/qmod/semantics/validation/__init__.py +0 -0
  400. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  401. classiq/qmod/semantics/validation/func_call_validation.py +99 -0
  402. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  403. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  404. classiq/qmod/semantics/validation/main_validation.py +33 -0
  405. classiq/qmod/semantics/validation/types_validation.py +128 -0
  406. classiq/qmod/symbolic.py +147 -123
  407. classiq/qmod/symbolic_expr.py +27 -12
  408. classiq/qmod/symbolic_type.py +2 -5
  409. classiq/qmod/type_attribute_remover.py +32 -0
  410. classiq/qmod/utilities.py +98 -4
  411. classiq/qmod/write_qmod.py +17 -3
  412. classiq/synthesis.py +210 -22
  413. {classiq-0.38.0.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -9
  414. classiq-0.65.3.dist-info/RECORD +521 -0
  415. classiq/_internals/_qfunc_ext.py +0 -6
  416. classiq/applications/benchmarking/__init__.py +0 -9
  417. classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
  418. classiq/applications/numpy_utils.py +0 -37
  419. classiq/applications_model_constructors/__init__.py +0 -25
  420. classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
  421. classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -65
  422. classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +0 -243
  423. classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
  424. classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
  425. classiq/builtin_functions/__init__.py +0 -43
  426. classiq/builtin_functions/amplitude_loading.py +0 -3
  427. classiq/builtin_functions/binary_ops.py +0 -1
  428. classiq/builtin_functions/exponentiation.py +0 -5
  429. classiq/builtin_functions/qpe.py +0 -4
  430. classiq/builtin_functions/qsvm.py +0 -7
  431. classiq/builtin_functions/range_types.py +0 -5
  432. classiq/builtin_functions/standard_gates.py +0 -1
  433. classiq/builtin_functions/state_preparation.py +0 -6
  434. classiq/builtin_functions/suzuki_trotter.py +0 -3
  435. classiq/interface/executor/aws_execution_cost.py +0 -73
  436. classiq/interface/executor/error_mitigation.py +0 -6
  437. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
  438. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
  439. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  440. classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
  441. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
  442. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  443. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  444. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  445. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  446. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
  447. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
  448. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -1229
  449. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
  450. classiq/interface/generator/functions/foreign_function_definition.py +0 -114
  451. classiq/interface/generator/functions/function_implementation.py +0 -107
  452. classiq/interface/generator/functions/native_function_definition.py +0 -155
  453. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  454. classiq/interface/generator/functions/register.py +0 -44
  455. classiq/interface/generator/functions/register_mapping_data.py +0 -106
  456. classiq/interface/generator/inequality_mixer.py +0 -51
  457. classiq/interface/generator/model/classical_main_validator.py +0 -106
  458. classiq/interface/generator/range_mixer.py +0 -56
  459. classiq/interface/generator/state_propagator.py +0 -74
  460. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  461. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
  462. classiq/interface/ide/show.py +0 -34
  463. classiq/interface/model/call_synthesis_data.py +0 -68
  464. classiq/interface/model/common_model_types.py +0 -23
  465. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  466. classiq/interface/model/quantum_if_operation.py +0 -94
  467. classiq/interface/model/resolvers/function_call_resolver.py +0 -43
  468. classiq/interface/model/validations/handle_validation_base.py +0 -55
  469. classiq/interface/model/validations/handles_validator.py +0 -156
  470. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  471. classiq/model/__init__.py +0 -14
  472. classiq/model/composite_function_generator.py +0 -33
  473. classiq/model/function_handler.py +0 -462
  474. classiq/model/logic_flow.py +0 -149
  475. classiq/model/logic_flow_change_handler.py +0 -71
  476. classiq/model/model.py +0 -229
  477. classiq/qmod/builtins/functions.py +0 -913
  478. classiq/qmod/qmod_struct.py +0 -37
  479. classiq/quantum_functions/__init__.py +0 -17
  480. classiq/quantum_functions/annotation_parser.py +0 -205
  481. classiq/quantum_functions/decorators.py +0 -22
  482. classiq/quantum_functions/function_library.py +0 -181
  483. classiq/quantum_functions/function_parser.py +0 -74
  484. classiq/quantum_functions/quantum_function.py +0 -236
  485. classiq-0.38.0.dist-info/RECORD +0 -454
  486. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
  487. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
  488. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
  489. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
  490. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
  491. /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  492. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  493. /classiq/{interface/generator/credit_risk_example → applications/hamiltonian}/__init__.py +0 -0
  494. /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
  495. /classiq/interface/{model/resolvers → debug_info}/__init__.py +0 -0
  496. /classiq/{_internals → interface}/enum_utils.py +0 -0
  497. /classiq/interface/{model/validations → generator/functions/builtins}/__init__.py +0 -0
  498. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → model_expansions/__init__.py} +0 -0
  499. {classiq-0.38.0.dist-info → classiq-0.65.3.dist-info}/WHEEL +0 -0
@@ -0,0 +1,253 @@
1
+ from collections.abc import Mapping
2
+ from enum import Enum
3
+ from typing import Any, Callable, Union
4
+
5
+ from sympy import Eq, Expr, Number, Piecewise, Symbol
6
+
7
+ from classiq.interface.exceptions import (
8
+ ClassiqExpansionError,
9
+ ClassiqInternalExpansionError,
10
+ )
11
+ from classiq.interface.generator.expressions.expression_types import (
12
+ ExpressionValue,
13
+ QmodStructInstance,
14
+ )
15
+ from classiq.interface.generator.expressions.qmod_qscalar_proxy import QmodQNumProxy
16
+ from classiq.interface.generator.expressions.qmod_qstruct_proxy import QmodQStructProxy
17
+ from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
18
+ from classiq.interface.generator.expressions.type_proxy import TypeProxy
19
+ from classiq.interface.generator.functions.classical_function_declaration import (
20
+ ClassicalFunctionDeclaration,
21
+ )
22
+ from classiq.interface.generator.functions.classical_type import (
23
+ Bool,
24
+ ClassicalList,
25
+ ClassicalType,
26
+ OpaqueHandle,
27
+ QmodPyObject,
28
+ Real,
29
+ StructMetaType,
30
+ )
31
+ from classiq.interface.generator.functions.type_name import TypeName
32
+
33
+ from classiq.model_expansions.model_tables import (
34
+ HandleIdentifier,
35
+ HandleTable,
36
+ )
37
+ from classiq.model_expansions.sympy_conversion.arithmetics import (
38
+ BitwiseAnd,
39
+ BitwiseNot,
40
+ BitwiseOr,
41
+ BitwiseXor,
42
+ LogicalXor,
43
+ )
44
+ from classiq.model_expansions.sympy_conversion.expression_to_sympy import (
45
+ MISSING_SLICE_VALUE_PLACEHOLDER,
46
+ )
47
+ from classiq.model_expansions.sympy_conversion.sympy_to_python import (
48
+ sympy_to_python,
49
+ )
50
+ from classiq.qmod.model_state_container import QMODULE
51
+
52
+
53
+ def qmod_val_to_python(val: ExpressionValue, qmod_type: ClassicalType) -> Any:
54
+ if isinstance(qmod_type, TypeName):
55
+ if (
56
+ isinstance(val, QmodStructInstance)
57
+ and val.struct_declaration == QMODULE.type_decls[qmod_type.name]
58
+ ):
59
+ return {
60
+ field_name: qmod_val_to_python(val.fields[field_name], field_type)
61
+ for field_name, field_type in val.struct_declaration.variables.items()
62
+ }
63
+
64
+ if isinstance(val, (Enum, int)):
65
+ return val
66
+
67
+ elif isinstance(qmod_type, ClassicalList):
68
+ if isinstance(val, list):
69
+ return [qmod_val_to_python(elem, qmod_type.element_type) for elem in val]
70
+
71
+ elif isinstance(qmod_type, OpaqueHandle):
72
+ if isinstance(val, HandleIdentifier):
73
+ return HandleTable.get_handle_object(val)
74
+
75
+ elif isinstance(val, Expr):
76
+ return sympy_to_python(val)
77
+
78
+ elif isinstance(qmod_type, Real):
79
+ if isinstance(val, (float, int)):
80
+ return val
81
+
82
+ elif isinstance(qmod_type, Bool):
83
+ if isinstance(val, bool):
84
+ return val
85
+
86
+ elif isinstance(qmod_type, StructMetaType):
87
+ if isinstance(val, TypeProxy):
88
+ return val.struct_declaration
89
+
90
+ elif isinstance(val, int): # other scalars are represented as int
91
+ return val
92
+
93
+ raise ClassiqInternalExpansionError(
94
+ f"Bad value {val!r} of type {type(val)!r} for {qmod_type!r}"
95
+ )
96
+
97
+
98
+ def python_val_to_qmod(val: Any, qmod_type: ClassicalType) -> ExpressionValue:
99
+ if isinstance(qmod_type, TypeName):
100
+ if qmod_type.name in QMODULE.enum_decls:
101
+ return val
102
+
103
+ struct_decl = QMODULE.type_decls[qmod_type.name]
104
+ if not isinstance(val, Mapping):
105
+ raise ClassiqInternalExpansionError(
106
+ f"Bad value for struct {struct_decl.name}"
107
+ )
108
+ qmod_dict = {
109
+ field_name: python_val_to_qmod(val[field_name], field_type)
110
+ for field_name, field_type in struct_decl.variables.items()
111
+ }
112
+ return QmodStructInstance(struct_decl, qmod_dict)
113
+
114
+ if isinstance(qmod_type, ClassicalList):
115
+ if not isinstance(val, list):
116
+ raise ClassiqInternalExpansionError("Bad value for list")
117
+ return [python_val_to_qmod(elem, qmod_type.element_type) for elem in val]
118
+
119
+ if isinstance(qmod_type, OpaqueHandle):
120
+ if not isinstance(val, QmodPyObject):
121
+ raise ClassiqInternalExpansionError("Bad value opaque handle")
122
+ return HandleTable.set_handle_object(val)
123
+
124
+ return val
125
+
126
+
127
+ def python_call_wrapper(func: Callable, *args: ExpressionValue) -> Any:
128
+ func_decl = ClassicalFunctionDeclaration.FOREIGN_FUNCTION_DECLARATIONS[
129
+ func.__name__
130
+ ]
131
+ python_args = [
132
+ qmod_val_to_python(args[idx], param_type.classical_type)
133
+ for idx, param_type in enumerate(func_decl.param_decls)
134
+ ]
135
+ assert func_decl.return_type is not None
136
+ return python_val_to_qmod(func(*python_args), func_decl.return_type)
137
+
138
+
139
+ def struct_literal(struct_type_symbol: Symbol, **kwargs: Any) -> QmodStructInstance:
140
+ return QmodStructInstance(
141
+ QMODULE.type_decls[struct_type_symbol.name],
142
+ {field: sympy_to_python(field_value) for field, field_value in kwargs.items()},
143
+ )
144
+
145
+
146
+ def get_field(
147
+ proxy: Union[QmodSizedProxy, QmodStructInstance, QmodQStructProxy, list],
148
+ field: str,
149
+ ) -> ExpressionValue:
150
+ if isinstance(proxy, type) and issubclass(proxy, Enum):
151
+ return getattr(proxy, field)
152
+ if isinstance(proxy, Symbol) and not isinstance(proxy, QmodSizedProxy):
153
+ raise ClassiqExpansionError(
154
+ f"Cannot evaluate '{proxy}.{field}': Variable {str(proxy)!r} is not "
155
+ f"initialized"
156
+ )
157
+ if isinstance(proxy, list):
158
+ if field != "len":
159
+ raise ClassiqExpansionError(
160
+ f"List {str(proxy)!r} has no attribute {field!r}. "
161
+ f"Available attributes: len"
162
+ )
163
+ return len(proxy)
164
+ if field not in proxy.fields:
165
+ if isinstance(proxy, (QmodStructInstance, QmodQStructProxy)):
166
+ property_name = "field"
167
+ else:
168
+ property_name = "attribute"
169
+ suffix = (
170
+ f". Available {property_name}s: {', '.join(proxy.fields.keys())}"
171
+ if len(proxy.fields) > 0
172
+ else ""
173
+ )
174
+ proxy_str = proxy.__name__ if isinstance(proxy, type) else f"{str(proxy)!r}"
175
+ raise ClassiqExpansionError(
176
+ f"{proxy.type_name} {proxy_str} has no {property_name} {field!r}{suffix}"
177
+ )
178
+ return proxy.fields[field]
179
+
180
+
181
+ def get_type(struct_type: Symbol) -> TypeProxy:
182
+ return TypeProxy(QMODULE.type_decls[struct_type.name])
183
+
184
+
185
+ def _unwrap_sympy_numeric(n: Any) -> Any:
186
+ if not isinstance(n, Number) or not n.is_constant():
187
+ return n
188
+ if n.is_Integer:
189
+ return int(n)
190
+ return float(n)
191
+
192
+
193
+ def do_div(lhs: Any, rhs: Any) -> Any:
194
+ lhs = _unwrap_sympy_numeric(lhs)
195
+ rhs = _unwrap_sympy_numeric(rhs)
196
+ return lhs / rhs
197
+
198
+
199
+ def do_subscript(value: Any, index: Any) -> Any:
200
+ if not isinstance(value, list) or not isinstance(index, QmodQNumProxy):
201
+ if isinstance(index, (QmodSizedProxy, QmodStructInstance)):
202
+ raise ClassiqExpansionError(
203
+ f"Subscript {value}[{index}] is not supported. Supported subscripts "
204
+ f"include:\n"
205
+ f"\t1. `qbv[idx]`, where `qbv` is a quantum array and `idx` is a "
206
+ f"classical integer.\n"
207
+ f"\t2. `l[n]`, where `l` is a list of classical real numbers and `n` "
208
+ f"is a classical or quantum integer."
209
+ )
210
+ return value[index]
211
+ if index.is_signed or index.fraction_digits > 0:
212
+ raise ClassiqExpansionError(
213
+ "Quantum numeric subscript must be an unsigned integer (is_signed=False, "
214
+ "fraction_digits=0)"
215
+ )
216
+ if len(value) != 2**index.size:
217
+ raise ClassiqExpansionError(
218
+ f"Quantum numeric subscript size mismatch: The quantum numeric has "
219
+ f"{index.size} qubits but the list size is {len(value)} != 2**{index.size}"
220
+ )
221
+ return Piecewise(
222
+ *[(item, Eq(index, idx)) for idx, item in enumerate(value[:-1])],
223
+ (value[-1], True),
224
+ )
225
+
226
+
227
+ def do_slice(value: Any, lower: Any, upper: Any) -> Any:
228
+ if isinstance(lower, Symbol) and str(lower) == MISSING_SLICE_VALUE_PLACEHOLDER:
229
+ lower = None
230
+ if isinstance(upper, Symbol) and str(upper) == MISSING_SLICE_VALUE_PLACEHOLDER:
231
+ upper = None
232
+ return do_subscript(value, slice(lower, upper))
233
+
234
+
235
+ CORE_LIB_FUNCTIONS_LIST: list[Callable] = [
236
+ print,
237
+ sum,
238
+ struct_literal,
239
+ get_field,
240
+ get_type,
241
+ do_div,
242
+ do_slice,
243
+ do_subscript,
244
+ BitwiseAnd,
245
+ BitwiseXor,
246
+ BitwiseNot,
247
+ BitwiseOr,
248
+ LogicalXor,
249
+ ]
250
+
251
+ ATOMIC_EXPRESSION_FUNCTIONS = {
252
+ **{core_func.__name__: core_func for core_func in CORE_LIB_FUNCTIONS_LIST},
253
+ }
File without changes
@@ -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
+ )