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,179 @@
1
+ import ast
2
+ from typing import TYPE_CHECKING, cast
3
+
4
+ from classiq.interface.exceptions import ClassiqExpansionError
5
+
6
+ MISSING_SLICE_VALUE_PLACEHOLDER = "MISSING_SLICE_VALUE"
7
+
8
+
9
+ def translate_to_sympy(expr: str) -> str:
10
+ node = ast.parse(expr)
11
+ node = ExpressionSympyTranslator().visit(node)
12
+ # node is a Module, we want an Expression
13
+ if TYPE_CHECKING:
14
+ assert isinstance(node.body[0], ast.Expr)
15
+ expression = ast.Expression(node.body[0].value)
16
+
17
+ return ast.unparse(ast.fix_missing_locations(expression))
18
+
19
+
20
+ class ExpressionSympyTranslator(ast.NodeTransformer):
21
+ BINARY_OPERATORS: dict[type[ast.AST], str] = {
22
+ ast.BitOr: "BitwiseOr",
23
+ ast.BitAnd: "BitwiseAnd",
24
+ ast.BitXor: "BitwiseXor",
25
+ ast.Div: "do_div",
26
+ }
27
+
28
+ UNARY_OPERATORS: dict[type[ast.AST], str] = {
29
+ ast.Invert: "BitwiseNot",
30
+ ast.Not: "Not",
31
+ }
32
+
33
+ BOOLEAN_OPERATORS: dict[type[ast.AST], str] = {
34
+ ast.Or: "Or",
35
+ ast.And: "And",
36
+ }
37
+
38
+ COMPARE_OPERATORS: dict[type[ast.AST], str] = {
39
+ ast.Eq: "Eq",
40
+ ast.NotEq: "Ne",
41
+ }
42
+
43
+ SPECIAL_FUNCTIONS: dict[str, str] = {
44
+ "max": "Max",
45
+ "min": "Min",
46
+ }
47
+
48
+ def visit_BinOp(self, node: ast.BinOp) -> ast.AST:
49
+ sympy_class = self.BINARY_OPERATORS.get(node.op.__class__)
50
+ if sympy_class is not None:
51
+ left = self.visit(node.left)
52
+ right = self.visit(node.right)
53
+
54
+ new_node = ast.Call(
55
+ func=ast.Name(id=sympy_class, ctx=ast.Load()),
56
+ args=[left, right],
57
+ starargs=None,
58
+ keywords=[],
59
+ kwargs=None,
60
+ )
61
+
62
+ return new_node
63
+ return self.generic_visit(node)
64
+
65
+ def visit_Compare(self, node: ast.Compare) -> ast.AST:
66
+ if len(node.ops) > 1:
67
+ raise ClassiqExpansionError(
68
+ f"Qmod expressions do not support chained comparison, as done in {ast.unparse(node)}"
69
+ )
70
+ sympy_class = self.COMPARE_OPERATORS.get(node.ops[0].__class__)
71
+ if sympy_class is not None:
72
+ left = self.visit(node.left)
73
+ right = self.visit(node.comparators[0])
74
+
75
+ new_node = ast.Call(
76
+ func=ast.Name(id=sympy_class, ctx=ast.Load()),
77
+ args=[left, right],
78
+ starargs=None,
79
+ keywords=[],
80
+ kwargs=None,
81
+ )
82
+
83
+ return new_node
84
+ return self.generic_visit(node)
85
+
86
+ def visit_BoolOp(self, node: ast.BoolOp) -> ast.AST:
87
+ sympy_class = self.BOOLEAN_OPERATORS.get(node.op.__class__)
88
+ if sympy_class is not None:
89
+ values = [self.visit(value) for value in node.values]
90
+
91
+ new_node = ast.Call(
92
+ func=ast.Name(id=sympy_class, ctx=ast.Load()),
93
+ args=values,
94
+ starargs=None,
95
+ keywords=[],
96
+ kwargs=None,
97
+ )
98
+
99
+ return new_node
100
+ return self.generic_visit(node)
101
+
102
+ def visit_UnaryOp(self, node: ast.UnaryOp) -> ast.AST:
103
+ sympy_class = self.UNARY_OPERATORS.get(node.op.__class__)
104
+ if sympy_class is not None:
105
+ operand = self.visit(node.operand)
106
+
107
+ new_node = ast.Call(
108
+ func=ast.Name(id=sympy_class, ctx=ast.Load()),
109
+ args=[operand],
110
+ starargs=None,
111
+ keywords=[],
112
+ kwargs=None,
113
+ )
114
+
115
+ return new_node
116
+ return self.generic_visit(node)
117
+
118
+ def visit_Call(self, node: ast.Call) -> ast.AST:
119
+ if isinstance(node.func, ast.Name) and node.func.id == "Piecewise":
120
+ return self._visit_piecewise(node)
121
+
122
+ if (
123
+ not isinstance(node.func, ast.Name)
124
+ or node.func.id not in self.SPECIAL_FUNCTIONS
125
+ ):
126
+ return self.generic_visit(node)
127
+
128
+ return ast.Call(
129
+ func=ast.Name(self.SPECIAL_FUNCTIONS[node.func.id]),
130
+ args=[self.visit(arg) for arg in (node.args)],
131
+ keywords=[self.visit(arg) for arg in node.keywords],
132
+ )
133
+
134
+ def _visit_piecewise(self, node: ast.Call) -> ast.AST:
135
+ # sympy Piecewise expression may include bitwise operations:
136
+ # Piecewise((0, Eq(x, 0)), (0.5, Eq(x, 1) | Eq(x, 2)), (1, True))
137
+ # ^
138
+ # We should avoid converting these to 'BitwiseOr' and such.
139
+ return ast.Call(
140
+ func=node.func,
141
+ args=[
142
+ ast.Tuple(
143
+ elts=(
144
+ self.generic_visit(cast(ast.Tuple, arg).elts[0]),
145
+ cast(ast.Tuple, arg).elts[1],
146
+ )
147
+ )
148
+ for arg in node.args
149
+ ],
150
+ keywords=node.keywords,
151
+ )
152
+
153
+ def visit_Subscript(self, node: ast.Subscript) -> ast.AST:
154
+ if isinstance(node.slice, ast.Slice):
155
+ if node.slice.lower is not None:
156
+ lower = self.visit(node.slice.lower)
157
+ else:
158
+ lower = ast.Name(MISSING_SLICE_VALUE_PLACEHOLDER)
159
+ if node.slice.upper is not None:
160
+ upper = self.visit(node.slice.upper)
161
+ else:
162
+ upper = ast.Name(MISSING_SLICE_VALUE_PLACEHOLDER)
163
+ return ast.Call(
164
+ func=ast.Name("do_slice"),
165
+ args=[self.visit(node.value), lower, upper],
166
+ keywords=[],
167
+ )
168
+ return ast.Call(
169
+ func=ast.Name("do_subscript"),
170
+ args=[self.visit(node.value), self.visit(node.slice)],
171
+ keywords=[],
172
+ )
173
+
174
+ def visit_Attribute(self, node: ast.Attribute) -> ast.Call:
175
+ return ast.Call(
176
+ func=ast.Name("get_field"),
177
+ args=[node.value, ast.Constant(value=node.attr)],
178
+ keywords=[],
179
+ )
@@ -0,0 +1,123 @@
1
+ import functools
2
+ from typing import Any, Optional, get_args
3
+
4
+ from sympy import (
5
+ Array,
6
+ Basic,
7
+ Expr,
8
+ Float,
9
+ Integer,
10
+ Matrix,
11
+ Piecewise,
12
+ Rational,
13
+ Symbol,
14
+ )
15
+ from sympy.logic.boolalg import BooleanAtom
16
+ from sympy.printing.pycode import PythonCodePrinter
17
+
18
+ from classiq.interface.exceptions import ClassiqInternalExpansionError
19
+ from classiq.interface.generator.expressions.expression_types import ExpressionValue
20
+
21
+ from classiq.model_expansions.sympy_conversion.arithmetics import LogicalXor
22
+
23
+
24
+ def sympy_to_python(
25
+ value: Any, locals: Optional[dict[str, ExpressionValue]] = None
26
+ ) -> ExpressionValue:
27
+ if isinstance(value, Integer):
28
+ value = int(value)
29
+ elif isinstance(value, Float):
30
+ value = float(value)
31
+ elif isinstance(value, BooleanAtom):
32
+ value = bool(value)
33
+ elif isinstance(value, Array):
34
+ value = sympy_to_python(value.tolist(), locals)
35
+ elif isinstance(value, Rational):
36
+ value = float(value.evalf())
37
+ elif isinstance(value, list):
38
+ value = [sympy_to_python(element, locals) for element in value]
39
+ elif isinstance(value, Matrix):
40
+ value = [sympy_to_python(element, locals) for element in value.tolist()]
41
+ elif isinstance(value, Symbol) and locals is not None and value.name in locals:
42
+ return locals[value.name]
43
+ if value is None:
44
+ value = False
45
+
46
+ if not isinstance(value, get_args(ExpressionValue)):
47
+ raise ClassiqInternalExpansionError(
48
+ f"Invalid evaluated expression {value} of type {type(value)}"
49
+ )
50
+
51
+ return value
52
+
53
+
54
+ def _conditional_true(*args: Any, **kwargs: Any) -> bool:
55
+ return True
56
+
57
+
58
+ class SympyToQuantumExpressionTranslator(PythonCodePrinter):
59
+ _operators = {**PythonCodePrinter._operators, **{"not": "~", "xor": "^"}}
60
+ _kf = {
61
+ **PythonCodePrinter._kf,
62
+ **{"max": "max", "min": "min", "Max": "max", "Min": "min"},
63
+ }
64
+ BINARY_BITWISE_OPERATORS_MAPPING = {
65
+ "BitwiseAnd": "&",
66
+ "BitwiseOr": "|",
67
+ "BitwiseXor": "^",
68
+ "LogicalXor": "^",
69
+ }
70
+ UNARY_BITWISE_OPERATORS_MAPPING = {"BitwiseNot": "~"}
71
+
72
+ @staticmethod
73
+ def _print_bitwise_binary_operator(
74
+ left_arg: Expr, right_arg: Expr, operator: str
75
+ ) -> str:
76
+ return f"(({left_arg}) {operator} ({right_arg}))"
77
+
78
+ @staticmethod
79
+ def _print_bitwise_unary_operator(arg: Expr, operator: str) -> str:
80
+ return f"({operator} ({arg}))"
81
+
82
+ def __init__(self) -> None:
83
+ super().__init__(settings={"fully_qualified_modules": False})
84
+ for binary_operator in self.BINARY_BITWISE_OPERATORS_MAPPING:
85
+ self.known_functions[binary_operator] = [
86
+ (
87
+ _conditional_true,
88
+ functools.partial(
89
+ self._print_bitwise_binary_operator,
90
+ operator=self.BINARY_BITWISE_OPERATORS_MAPPING[binary_operator],
91
+ ),
92
+ )
93
+ ]
94
+ for unary_operator in self.UNARY_BITWISE_OPERATORS_MAPPING:
95
+ self.known_functions[unary_operator] = [
96
+ (
97
+ _conditional_true,
98
+ functools.partial(
99
+ self._print_bitwise_unary_operator,
100
+ operator=self.UNARY_BITWISE_OPERATORS_MAPPING[unary_operator],
101
+ ),
102
+ )
103
+ ]
104
+
105
+ def _print_Piecewise(self, expr: Piecewise) -> str: # noqa: N802
106
+ return str(expr)
107
+
108
+ def _print_LogicalXor(self, expr: LogicalXor) -> str: # noqa: N802
109
+ return f"(({self._print(expr.args[0])}) ^ ({self._print(expr.args[1])}))"
110
+
111
+
112
+ class SympyToBoolExpressionTranslator(SympyToQuantumExpressionTranslator):
113
+ _operators = {
114
+ **SympyToQuantumExpressionTranslator._operators,
115
+ **{"not": "not ", "xor": "xor"},
116
+ }
117
+
118
+
119
+ def translate_sympy_quantum_expression(expr: Basic, preserve_bool_ops: bool) -> str:
120
+ if preserve_bool_ops:
121
+ return SympyToBoolExpressionTranslator().doprint(expr)
122
+ else:
123
+ return SympyToQuantumExpressionTranslator().doprint(expr)
File without changes
@@ -0,0 +1,26 @@
1
+ import ast
2
+
3
+ _POSSIBLE_HANDLE_AST_TYPES = (ast.Subscript, ast.Attribute, ast.Name)
4
+
5
+
6
+ class _ASTRenamer(ast.NodeTransformer):
7
+ def __init__(self, sub: dict[str, str]) -> None:
8
+ self._sub = sub
9
+
10
+ def visit(self, node: ast.AST) -> ast.AST:
11
+ if isinstance(node, _POSSIBLE_HANDLE_AST_TYPES):
12
+ node_expr = ast.unparse(node)
13
+ if node_expr in self._sub:
14
+ return ast.Name(id=self._sub[node_expr])
15
+ return super().visit(node)
16
+
17
+ def visit_Call(self, node: ast.Call) -> ast.Call:
18
+ return ast.Call(
19
+ func=node.func,
20
+ args=[self.visit(arg) for arg in node.args],
21
+ keywords=[],
22
+ )
23
+
24
+
25
+ def rename_variables(expr: str, sub: dict[str, str]) -> str:
26
+ return ast.unparse(_ASTRenamer(sub).visit(ast.parse(expr)))
@@ -0,0 +1,299 @@
1
+ import ast
2
+ from dataclasses import dataclass
3
+ from itertools import chain
4
+ from typing import TYPE_CHECKING, Callable, Optional, TypeVar, cast
5
+
6
+ from classiq.interface.exceptions import (
7
+ ClassiqExpansionError,
8
+ ClassiqInternalExpansionError,
9
+ )
10
+ from classiq.interface.generator.expressions.expression import Expression
11
+ from classiq.interface.generator.visitor import NodeType, Transformer
12
+ from classiq.interface.model.bind_operation import BindOperation
13
+ from classiq.interface.model.handle_binding import (
14
+ HandleBinding,
15
+ NestedHandleBinding,
16
+ SlicedHandleBinding,
17
+ SubscriptHandleBinding,
18
+ )
19
+ from classiq.interface.model.quantum_expressions.quantum_expression import (
20
+ QuantumExpressionOperation,
21
+ )
22
+ from classiq.interface.model.quantum_type import (
23
+ QuantumBitvector,
24
+ QuantumScalar,
25
+ QuantumType,
26
+ )
27
+ from classiq.interface.model.variable_declaration_statement import (
28
+ VariableDeclarationStatement,
29
+ )
30
+
31
+ from classiq.model_expansions.scope import QuantumSymbol, Scope
32
+ from classiq.model_expansions.visitors.variable_references import VarRefCollector
33
+
34
+ AST_NODE = TypeVar("AST_NODE", bound=NodeType)
35
+
36
+
37
+ @dataclass(frozen=True)
38
+ class SymbolPart:
39
+ source_handle: HandleBinding
40
+ target_var_name: str
41
+ target_var_type: QuantumType
42
+
43
+ @property
44
+ def target_var_handle(self) -> HandleBinding:
45
+ return HandleBinding(name=self.target_var_name)
46
+
47
+
48
+ SymbolParts = dict[HandleBinding, list[SymbolPart]]
49
+ PartNamer = Callable[[str], str]
50
+
51
+
52
+ class VarSplitter:
53
+ def __init__(self, scope: Scope):
54
+ self._scope = scope
55
+
56
+ def split_symbols(self, expression: Expression, namer: PartNamer) -> SymbolParts:
57
+ vrc = VarRefCollector(ignore_duplicated_handles=True)
58
+ vrc.visit(ast.parse(expression.expr))
59
+ symbol_names_to_split = dict.fromkeys(
60
+ handle.name
61
+ for handle in vrc.var_handles
62
+ if isinstance(self._scope[handle.name].value, QuantumSymbol)
63
+ and isinstance(handle, NestedHandleBinding)
64
+ )
65
+
66
+ symbol_handles = {
67
+ symbol: list(
68
+ dict.fromkeys(
69
+ handle.collapse()
70
+ for handle in vrc.var_handles
71
+ if handle.name == symbol.handle.name
72
+ )
73
+ )
74
+ for symbol_name in symbol_names_to_split
75
+ if isinstance(
76
+ symbol := self._scope[symbol_name].value,
77
+ QuantumSymbol,
78
+ )
79
+ }
80
+
81
+ return {
82
+ symbol.handle: [
83
+ SymbolPart(
84
+ source_handle=part.handle,
85
+ target_var_name=namer(part.handle.identifier),
86
+ target_var_type=part.quantum_type,
87
+ )
88
+ for part in self._get_symbol_parts(symbol, handles)
89
+ ]
90
+ for symbol, handles in symbol_handles.items()
91
+ }
92
+
93
+ def _get_symbol_parts(
94
+ self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
95
+ ) -> list[QuantumSymbol]:
96
+ for i in range(len(target_parts)):
97
+ for j in range(i + 1, len(target_parts)):
98
+ if target_parts[i].overlaps(target_parts[j]):
99
+ raise ClassiqInternalExpansionError(
100
+ f"Handles {str(target_parts[i])!r} and "
101
+ f"{str(target_parts[j])!r} overlapping in expression"
102
+ )
103
+ return self._get_symbol_parts_unsafe(symbol, target_parts)
104
+
105
+ def _get_symbol_parts_unsafe(
106
+ self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
107
+ ) -> list[QuantumSymbol]:
108
+ if all(
109
+ symbol.handle == target_part or symbol.handle not in target_part.prefixes()
110
+ for target_part in target_parts
111
+ ) or isinstance(symbol.quantum_type, QuantumScalar):
112
+ return [symbol]
113
+
114
+ if isinstance(symbol.quantum_type, QuantumBitvector):
115
+ return self._get_array_parts(symbol, target_parts)
116
+
117
+ return self._get_struct_parts(symbol, target_parts)
118
+
119
+ def _get_array_parts(
120
+ self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
121
+ ) -> list[QuantumSymbol]:
122
+ if TYPE_CHECKING:
123
+ assert isinstance(symbol.quantum_type, QuantumBitvector)
124
+
125
+ if not symbol.quantum_type.has_length:
126
+ raise ClassiqExpansionError(
127
+ f"Could not determine the length of quantum array " f"{symbol.handle}."
128
+ )
129
+ target_slices = self._get_target_slices(symbol, target_parts)
130
+
131
+ symbol_parts: list[QuantumSymbol] = []
132
+ idx = 0
133
+ while idx < symbol.quantum_type.length_value:
134
+ if idx in target_slices:
135
+ stop = target_slices[idx]
136
+ if stop <= idx:
137
+ raise ClassiqInternalExpansionError(
138
+ f"Illegal sliced handle {str(symbol[idx: stop].handle)!r}"
139
+ )
140
+ symbol_parts.append(symbol[idx:stop])
141
+ idx = stop
142
+ else:
143
+ symbol_parts.extend(
144
+ self._get_symbol_parts_unsafe(symbol[idx], target_parts)
145
+ )
146
+ idx += 1
147
+
148
+ return symbol_parts
149
+
150
+ def _get_target_slices(
151
+ self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
152
+ ) -> dict[int, int]:
153
+ if TYPE_CHECKING:
154
+ assert isinstance(symbol.quantum_type, QuantumBitvector)
155
+ target_items = {
156
+ idx
157
+ for idx in range(symbol.quantum_type.length_value)
158
+ for target_part in target_parts
159
+ if target_part
160
+ in SubscriptHandleBinding(
161
+ base_handle=symbol.handle, index=Expression(expr=str(idx))
162
+ )
163
+ }
164
+ target_slices = {
165
+ target_part.start.to_int_value(): target_part.end.to_int_value()
166
+ for target_part in target_parts
167
+ if isinstance(target_part, SlicedHandleBinding)
168
+ and symbol.handle == target_part.base_handle
169
+ }
170
+ self._add_unused_indices_as_slices(symbol, target_items, target_slices)
171
+ return target_slices
172
+
173
+ @staticmethod
174
+ def _add_unused_indices_as_slices(
175
+ symbol: QuantumSymbol, target_items: set[int], target_slices: dict[int, int]
176
+ ) -> None:
177
+ if TYPE_CHECKING:
178
+ assert isinstance(symbol.quantum_type, QuantumBitvector)
179
+ last_unused_idx: Optional[int] = None
180
+ array_length = symbol.quantum_type.length_value
181
+ idx = 0
182
+
183
+ while idx < array_length:
184
+ if (
185
+ idx in target_items or idx in target_slices
186
+ ) and last_unused_idx is not None:
187
+ target_slices[last_unused_idx] = idx
188
+ last_unused_idx = None
189
+
190
+ if idx in target_slices:
191
+ if target_slices[idx] <= idx:
192
+ raise ClassiqInternalExpansionError
193
+ idx = target_slices[idx]
194
+ continue
195
+
196
+ if idx not in target_items and last_unused_idx is None:
197
+ last_unused_idx = idx
198
+
199
+ idx += 1
200
+
201
+ if last_unused_idx is not None:
202
+ target_slices[last_unused_idx] = array_length
203
+
204
+ def _get_struct_parts(
205
+ self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
206
+ ) -> list[QuantumSymbol]:
207
+ return list(
208
+ chain.from_iterable(
209
+ self._get_symbol_parts_unsafe(field_symbol, target_parts)
210
+ for field_symbol in symbol.fields.values()
211
+ )
212
+ )
213
+
214
+ @staticmethod
215
+ def get_bind_ops(symbol_parts: SymbolParts) -> list[BindOperation]:
216
+ return [
217
+ BindOperation(
218
+ in_handles=[handle],
219
+ out_handles=[part.target_var_handle for part in parts],
220
+ )
221
+ for handle, parts in symbol_parts.items()
222
+ ]
223
+
224
+ @staticmethod
225
+ def get_var_decls(symbol_parts: SymbolParts) -> list[VariableDeclarationStatement]:
226
+ return [
227
+ VariableDeclarationStatement(
228
+ name=part.target_var_name,
229
+ quantum_type=part.target_var_type,
230
+ )
231
+ for part in chain.from_iterable(symbol_parts.values())
232
+ ]
233
+
234
+ def rewrite(self, subject: AST_NODE, symbol_mapping: SymbolParts) -> AST_NODE:
235
+ if len(symbol_mapping) == 0:
236
+ return subject
237
+ handle_replacements = {
238
+ part.source_handle: part.target_var_handle
239
+ for parts in symbol_mapping.values()
240
+ for part in parts
241
+ }
242
+
243
+ class ReplaceSplitVars(Transformer):
244
+ @staticmethod
245
+ def visit_HandleBinding(handle: HandleBinding) -> HandleBinding:
246
+ handle = handle.collapse()
247
+ for handle_to_replace, replacement in handle_replacements.items():
248
+ handle = handle.replace_prefix(handle_to_replace, replacement)
249
+ return handle
250
+
251
+ @staticmethod
252
+ def visit_Expression(expr: Expression) -> Expression:
253
+ return self._rewrite_expression(symbol_mapping, expr)
254
+
255
+ def visit_QuantumExpressionOperation(
256
+ self, op: QuantumExpressionOperation
257
+ ) -> QuantumExpressionOperation:
258
+ op = cast(QuantumExpressionOperation, self.generic_visit(op))
259
+ previous_var_handles = list(op._var_handles)
260
+ op._var_handles = self.visit(op._var_handles)
261
+ op._var_types = {
262
+ new_handle.name: op._var_types.get(
263
+ new_handle.name, op._var_types[previous_handle.name]
264
+ )
265
+ for previous_handle, new_handle in zip(
266
+ previous_var_handles, op._var_handles
267
+ )
268
+ }
269
+ return op
270
+
271
+ return ReplaceSplitVars().visit(subject)
272
+
273
+ def _rewrite_expression(
274
+ self,
275
+ symbol_mapping: SymbolParts,
276
+ expression: Expression,
277
+ ) -> Expression:
278
+ vrc = VarRefCollector(ignore_duplicated_handles=True)
279
+ vrc.visit(ast.parse(expression.expr))
280
+
281
+ handle_names = {
282
+ part.source_handle: part.target_var_handle
283
+ for parts in symbol_mapping.values()
284
+ for part in parts
285
+ }
286
+ new_expr_str = expression.expr
287
+ for handle in vrc.var_handles:
288
+ new_handle = handle.collapse()
289
+ for handle_to_replace, replacement in handle_names.items():
290
+ new_handle = new_handle.replace_prefix(handle_to_replace, replacement)
291
+ new_expr_str = new_expr_str.replace(str(handle), str(new_handle))
292
+ if handle.qmod_expr != str(handle):
293
+ new_expr_str = new_expr_str.replace(
294
+ handle.qmod_expr, new_handle.qmod_expr
295
+ )
296
+
297
+ new_expr = Expression(expr=new_expr_str)
298
+ new_expr._evaluated_expr = expression._evaluated_expr
299
+ return new_expr
File without changes
@@ -0,0 +1,11 @@
1
+ from collections import Counter
2
+
3
+
4
+ class CountedNameAllocator:
5
+ def __init__(self) -> None:
6
+ self._count: Counter[str] = Counter()
7
+
8
+ def allocate(self, prefix: str) -> str:
9
+ allocated = f"{prefix}_{self._count[prefix]}"
10
+ self._count[prefix] += 1
11
+ return allocated
@@ -0,0 +1,33 @@
1
+ import ast
2
+
3
+ from classiq.interface.generator.expressions.expression import Expression
4
+ from classiq.interface.generator.visitor import NodeType, Visitor
5
+ from classiq.interface.model.handle_binding import HandleBinding
6
+ from classiq.interface.model.quantum_expressions.quantum_expression import (
7
+ QuantumExpressionOperation,
8
+ )
9
+
10
+ from classiq.model_expansions.visitors.variable_references import VarRefCollector
11
+
12
+
13
+ class _HandlesCollector(Visitor):
14
+ def __init__(self) -> None:
15
+ self.handles: list[HandleBinding] = []
16
+
17
+ def visit_HandleBinding(self, handle: HandleBinding) -> None:
18
+ self.handles.append(handle)
19
+
20
+ def visit_Expression(self, expression: Expression) -> None:
21
+ vrc = VarRefCollector(ignore_duplicated_handles=True)
22
+ vrc.visit(ast.parse(expression.expr))
23
+ self.handles.extend(vrc.var_handles)
24
+
25
+ def visit_QuantumExpressionOperation(self, op: QuantumExpressionOperation) -> None:
26
+ self.handles.extend(op.var_handles)
27
+ self.generic_visit(op)
28
+
29
+
30
+ def extract_handles(node: NodeType) -> list[HandleBinding]:
31
+ collector = _HandlesCollector()
32
+ collector.visit(node)
33
+ return collector.handles
File without changes