classiq 0.37.1__py3-none-any.whl → 0.65.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. classiq/__init__.py +49 -34
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +3 -2
  3. classiq/_analyzer_extras/interactive_hardware.py +3 -3
  4. classiq/_internals/api_wrapper.py +241 -95
  5. classiq/_internals/async_utils.py +2 -77
  6. classiq/_internals/authentication/auth0.py +26 -10
  7. classiq/_internals/authentication/authentication.py +11 -0
  8. classiq/_internals/authentication/device.py +18 -8
  9. classiq/_internals/authentication/password_manager.py +40 -13
  10. classiq/_internals/authentication/token_manager.py +11 -6
  11. classiq/_internals/client.py +106 -37
  12. classiq/_internals/config.py +3 -4
  13. classiq/_internals/host_checker.py +38 -15
  14. classiq/_internals/jobs.py +56 -50
  15. classiq/_internals/type_validation.py +9 -9
  16. classiq/analyzer/__init__.py +1 -3
  17. classiq/analyzer/analyzer.py +50 -47
  18. classiq/analyzer/analyzer_utilities.py +15 -15
  19. classiq/analyzer/rb.py +19 -20
  20. classiq/analyzer/show_interactive_hack.py +30 -7
  21. classiq/analyzer/url_utils.py +2 -3
  22. classiq/applications/__init__.py +3 -12
  23. classiq/applications/chemistry/__init__.py +14 -10
  24. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  25. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +170 -170
  26. classiq/applications/chemistry/ground_state_problem.py +1 -1
  27. classiq/applications/combinatorial_helpers/allowed_constraints.py +23 -0
  28. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
  29. classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
  30. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +166 -0
  31. classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
  32. classiq/applications/combinatorial_helpers/encoding_utils.py +124 -0
  33. classiq/applications/combinatorial_helpers/memory.py +75 -0
  34. classiq/applications/combinatorial_helpers/optimization_model.py +193 -0
  35. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
  36. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
  37. classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
  38. classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
  39. classiq/applications/combinatorial_helpers/transformations/encoding.py +189 -0
  40. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +143 -0
  41. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +120 -0
  42. classiq/applications/combinatorial_helpers/transformations/penalty.py +31 -0
  43. classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
  44. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +74 -0
  45. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +87 -0
  46. classiq/applications/combinatorial_optimization/__init__.py +24 -5
  47. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  48. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +137 -0
  49. classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
  50. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  51. classiq/applications/finance/__init__.py +4 -5
  52. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +50 -57
  53. classiq/applications/grover/__init__.py +9 -0
  54. classiq/applications/grover/grover_model_constructor.py +157 -0
  55. classiq/applications/hamiltonian/__init__.py +0 -0
  56. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  57. classiq/applications/libraries/__init__.py +0 -0
  58. classiq/applications/libraries/qmci_library.py +22 -0
  59. classiq/applications/qnn/__init__.py +2 -4
  60. classiq/applications/qnn/circuit_utils.py +8 -8
  61. classiq/applications/qnn/datasets/__init__.py +9 -11
  62. classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
  63. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  64. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  65. classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
  66. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  67. classiq/applications/qnn/qlayer.py +30 -10
  68. classiq/applications/qnn/torch_utils.py +4 -3
  69. classiq/applications/qnn/types.py +7 -7
  70. classiq/applications/qsvm/__init__.py +6 -4
  71. classiq/applications/qsvm/qsvm.py +4 -10
  72. classiq/applications/qsvm/qsvm_data_generation.py +5 -8
  73. classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
  74. classiq/execution/__init__.py +8 -3
  75. classiq/execution/all_hardware_devices.py +11 -0
  76. classiq/execution/execution_session.py +400 -0
  77. classiq/execution/iqcc.py +63 -0
  78. classiq/execution/jobs.py +197 -25
  79. classiq/execution/qnn.py +79 -0
  80. classiq/executor.py +23 -117
  81. classiq/interface/_version.py +1 -1
  82. classiq/interface/analyzer/analysis_params.py +49 -16
  83. classiq/interface/analyzer/cytoscape_graph.py +15 -9
  84. classiq/interface/analyzer/result.py +36 -32
  85. classiq/interface/applications/qsvm.py +28 -25
  86. classiq/interface/ast_node.py +16 -0
  87. classiq/interface/backend/backend_preferences.py +390 -119
  88. classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
  89. classiq/interface/backend/pydantic_backend.py +27 -22
  90. classiq/interface/backend/quantum_backend_providers.py +70 -16
  91. classiq/interface/chemistry/fermionic_operator.py +43 -32
  92. classiq/interface/chemistry/ground_state_problem.py +42 -24
  93. classiq/interface/chemistry/molecule.py +20 -14
  94. classiq/interface/chemistry/operator.py +75 -236
  95. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  96. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +2 -4
  97. classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
  98. classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
  99. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  100. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  101. classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
  102. classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
  103. classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
  104. classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
  105. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  106. classiq/interface/combinatorial_optimization/examples/set_cover.py +3 -3
  107. classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
  108. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
  109. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +14 -9
  110. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  111. classiq/interface/combinatorial_optimization/result.py +1 -3
  112. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  113. classiq/interface/debug_info/__init__.py +0 -0
  114. classiq/interface/debug_info/debug_info.py +86 -0
  115. classiq/interface/exceptions.py +201 -0
  116. classiq/interface/execution/iqcc.py +19 -0
  117. classiq/interface/execution/jobs.py +15 -12
  118. classiq/interface/execution/primitives.py +18 -0
  119. classiq/interface/executor/constants.py +1 -0
  120. classiq/interface/executor/estimation.py +2 -2
  121. classiq/interface/executor/execution_preferences.py +26 -143
  122. classiq/interface/executor/execution_request.py +36 -56
  123. classiq/interface/executor/execution_result.py +30 -8
  124. classiq/interface/executor/iqae_result.py +4 -6
  125. classiq/interface/executor/optimizer_preferences.py +34 -22
  126. classiq/interface/executor/{quantum_program.py → quantum_code.py} +44 -34
  127. classiq/interface/executor/quantum_instruction_set.py +3 -2
  128. classiq/interface/executor/register_initialization.py +12 -17
  129. classiq/interface/executor/result.py +122 -64
  130. classiq/interface/executor/vqe_result.py +11 -11
  131. classiq/interface/finance/function_input.py +42 -19
  132. classiq/interface/finance/gaussian_model_input.py +7 -5
  133. classiq/interface/finance/log_normal_model_input.py +6 -4
  134. classiq/interface/finance/model_input.py +6 -4
  135. classiq/interface/generator/adjacency.py +1 -3
  136. classiq/interface/generator/amplitude_loading.py +27 -14
  137. classiq/interface/generator/ansatz_library.py +5 -5
  138. classiq/interface/generator/application_apis/__init__.py +1 -0
  139. classiq/interface/generator/application_apis/arithmetic_declarations.py +17 -0
  140. classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
  141. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
  142. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  143. classiq/interface/generator/application_apis/finance_declarations.py +48 -69
  144. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
  145. classiq/interface/generator/arith/argument_utils.py +57 -6
  146. classiq/interface/generator/arith/arithmetic.py +37 -16
  147. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +15 -17
  148. classiq/interface/generator/arith/arithmetic_expression_abc.py +70 -26
  149. classiq/interface/generator/arith/arithmetic_expression_parser.py +18 -12
  150. classiq/interface/generator/arith/arithmetic_expression_validator.py +61 -43
  151. classiq/interface/generator/arith/arithmetic_operations.py +19 -16
  152. classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
  153. classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
  154. classiq/interface/generator/arith/ast_node_rewrite.py +4 -3
  155. classiq/interface/generator/arith/binary_ops.py +375 -139
  156. classiq/interface/generator/arith/endianness.py +1 -1
  157. classiq/interface/generator/arith/extremum_operations.py +96 -23
  158. classiq/interface/generator/arith/logical_ops.py +16 -12
  159. classiq/interface/generator/arith/machine_precision.py +3 -0
  160. classiq/interface/generator/arith/number_utils.py +44 -48
  161. classiq/interface/generator/arith/register_user_input.py +70 -27
  162. classiq/interface/generator/arith/unary_ops.py +57 -46
  163. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  164. classiq/interface/generator/builtin_api_builder.py +2 -9
  165. classiq/interface/generator/chemistry_function_params.py +5 -5
  166. classiq/interface/generator/circuit_code/circuit_code.py +7 -7
  167. classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
  168. classiq/interface/generator/commuting_pauli_exponentiation.py +8 -6
  169. classiq/interface/generator/compiler_keywords.py +8 -0
  170. classiq/interface/generator/complex_type.py +13 -25
  171. classiq/interface/generator/constant.py +3 -4
  172. classiq/interface/generator/control_state.py +35 -28
  173. classiq/interface/generator/copy.py +47 -0
  174. classiq/interface/generator/custom_ansatz.py +2 -5
  175. classiq/interface/generator/distance.py +3 -5
  176. classiq/interface/generator/excitations.py +3 -2
  177. classiq/interface/generator/expressions/atomic_expression_functions.py +26 -8
  178. classiq/interface/generator/expressions/enums/__init__.py +0 -10
  179. classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
  180. classiq/interface/generator/expressions/evaluated_expression.py +21 -7
  181. classiq/interface/generator/expressions/expression.py +27 -15
  182. classiq/interface/generator/expressions/expression_constants.py +9 -3
  183. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  184. classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
  185. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +59 -0
  186. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
  187. classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
  188. classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
  189. classiq/interface/generator/expressions/sympy_supported_expressions.py +20 -11
  190. classiq/interface/generator/finance.py +3 -3
  191. classiq/interface/generator/function_param_library.py +6 -6
  192. classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
  193. classiq/interface/generator/function_params.py +42 -69
  194. classiq/interface/generator/functions/__init__.py +0 -22
  195. classiq/interface/generator/functions/builtins/__init__.py +0 -0
  196. classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
  197. classiq/interface/generator/functions/classical_function_declaration.py +18 -9
  198. classiq/interface/generator/functions/classical_type.py +47 -166
  199. classiq/interface/generator/functions/concrete_types.py +55 -0
  200. classiq/interface/generator/functions/function_declaration.py +13 -14
  201. classiq/interface/generator/functions/port_declaration.py +1 -13
  202. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  203. classiq/interface/generator/functions/type_name.py +90 -0
  204. classiq/interface/generator/generated_circuit_data.py +155 -22
  205. classiq/interface/generator/grover_diffuser.py +32 -25
  206. classiq/interface/generator/grover_operator.py +34 -23
  207. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
  208. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  209. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +12 -8
  210. classiq/interface/generator/hardware/hardware_data.py +76 -36
  211. classiq/interface/generator/hardware_efficient_ansatz.py +38 -17
  212. classiq/interface/generator/hartree_fock.py +14 -4
  213. classiq/interface/generator/identity.py +10 -6
  214. classiq/interface/generator/linear_pauli_rotations.py +33 -19
  215. classiq/interface/generator/mcmt_method.py +1 -1
  216. classiq/interface/generator/mcu.py +20 -16
  217. classiq/interface/generator/mcx.py +29 -20
  218. classiq/interface/generator/model/__init__.py +2 -5
  219. classiq/interface/generator/model/constraints.py +27 -8
  220. classiq/interface/generator/model/model.py +32 -203
  221. classiq/interface/generator/model/preferences/preferences.py +118 -43
  222. classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +27 -22
  223. classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
  224. classiq/interface/generator/oracles/custom_oracle.py +17 -13
  225. classiq/interface/generator/oracles/oracle_abc.py +9 -9
  226. classiq/interface/generator/partitioned_register.py +7 -7
  227. classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
  228. classiq/interface/generator/preferences/optimization.py +1 -2
  229. classiq/interface/generator/qpe.py +47 -34
  230. classiq/interface/generator/qsvm.py +13 -17
  231. classiq/interface/generator/quantum_function_call.py +107 -87
  232. classiq/interface/generator/{generated_circuit.py → quantum_program.py} +50 -37
  233. classiq/interface/generator/range_types.py +13 -12
  234. classiq/interface/generator/register_role.py +18 -6
  235. classiq/interface/generator/slice_parsing_utils.py +11 -6
  236. classiq/interface/generator/standard_gates/controlled_standard_gates.py +32 -39
  237. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  238. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  239. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  240. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  241. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  242. classiq/interface/generator/state_preparation/distributions.py +16 -15
  243. classiq/interface/generator/state_preparation/metrics.py +5 -7
  244. classiq/interface/generator/state_preparation/state_preparation.py +30 -23
  245. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  246. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
  247. classiq/interface/generator/transpiler_basis_gates.py +7 -3
  248. classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
  249. classiq/interface/generator/types/compilation_metadata.py +6 -0
  250. classiq/interface/generator/types/enum_declaration.py +54 -0
  251. classiq/interface/generator/types/qstruct_declaration.py +18 -0
  252. classiq/interface/generator/types/struct_declaration.py +15 -14
  253. classiq/interface/generator/ucc.py +9 -6
  254. classiq/interface/generator/unitary_gate.py +10 -6
  255. classiq/interface/generator/user_defined_function_params.py +4 -1
  256. classiq/interface/generator/validations/flow_graph.py +11 -9
  257. classiq/interface/generator/validations/validator_functions.py +8 -6
  258. classiq/interface/generator/visitor.py +23 -16
  259. classiq/interface/hardware.py +31 -10
  260. classiq/interface/helpers/classproperty.py +8 -0
  261. classiq/interface/helpers/custom_encoders.py +3 -0
  262. classiq/interface/helpers/custom_pydantic_types.py +40 -50
  263. classiq/interface/helpers/datastructures.py +26 -0
  264. classiq/interface/helpers/hashable_mixin.py +3 -2
  265. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  266. classiq/interface/helpers/pydantic_model_helpers.py +7 -11
  267. classiq/interface/helpers/validation_helpers.py +4 -21
  268. classiq/interface/helpers/versioned_model.py +1 -1
  269. classiq/interface/ide/ide_data.py +16 -20
  270. classiq/interface/ide/visual_model.py +130 -0
  271. classiq/interface/interface_version.py +1 -0
  272. classiq/interface/jobs.py +35 -6
  273. classiq/interface/model/allocate.py +16 -0
  274. classiq/interface/model/bind_operation.py +44 -14
  275. classiq/interface/model/classical_if.py +15 -0
  276. classiq/interface/model/classical_parameter_declaration.py +33 -3
  277. classiq/interface/model/control.py +45 -0
  278. classiq/interface/model/handle_binding.py +298 -20
  279. classiq/interface/model/inplace_binary_operation.py +31 -26
  280. classiq/interface/model/invert.py +12 -0
  281. classiq/interface/model/model.py +87 -73
  282. classiq/interface/model/native_function_definition.py +16 -21
  283. classiq/interface/model/parameter.py +13 -0
  284. classiq/interface/model/phase_operation.py +11 -0
  285. classiq/interface/model/port_declaration.py +27 -9
  286. classiq/interface/model/power.py +14 -0
  287. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +38 -21
  288. classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
  289. classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
  290. classiq/interface/model/quantum_function_call.py +146 -462
  291. classiq/interface/model/quantum_function_declaration.py +193 -152
  292. classiq/interface/model/quantum_lambda_function.py +65 -0
  293. classiq/interface/model/quantum_statement.py +71 -12
  294. classiq/interface/model/quantum_type.py +205 -67
  295. classiq/interface/model/quantum_variable_declaration.py +4 -26
  296. classiq/interface/model/repeat.py +15 -0
  297. classiq/interface/model/statement_block.py +58 -0
  298. classiq/interface/model/validation_handle.py +13 -6
  299. classiq/interface/model/variable_declaration_statement.py +3 -1
  300. classiq/interface/model/within_apply_operation.py +13 -0
  301. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
  302. classiq/interface/server/global_versions.py +6 -7
  303. classiq/interface/server/routes.py +22 -21
  304. classiq/interface/source_reference.py +59 -0
  305. classiq/model_expansions/__init__.py +0 -0
  306. classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
  307. classiq/model_expansions/capturing/__init__.py +0 -0
  308. classiq/model_expansions/capturing/captured_vars.py +435 -0
  309. classiq/model_expansions/capturing/mangling_utils.py +56 -0
  310. classiq/model_expansions/closure.py +171 -0
  311. classiq/model_expansions/debug_flag.py +3 -0
  312. classiq/model_expansions/evaluators/__init__.py +0 -0
  313. classiq/model_expansions/evaluators/arg_type_match.py +158 -0
  314. classiq/model_expansions/evaluators/argument_types.py +42 -0
  315. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  316. classiq/model_expansions/evaluators/control.py +144 -0
  317. classiq/model_expansions/evaluators/parameter_types.py +226 -0
  318. classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
  319. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  320. classiq/model_expansions/expression_evaluator.py +135 -0
  321. classiq/model_expansions/expression_renamer.py +76 -0
  322. classiq/model_expansions/function_builder.py +247 -0
  323. classiq/model_expansions/generative_functions.py +158 -0
  324. classiq/model_expansions/interpreters/__init__.py +0 -0
  325. classiq/model_expansions/interpreters/base_interpreter.py +263 -0
  326. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
  327. classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
  328. classiq/model_expansions/model_tables.py +18 -0
  329. classiq/model_expansions/quantum_operations/__init__.py +9 -0
  330. classiq/model_expansions/quantum_operations/bind.py +60 -0
  331. classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
  332. classiq/model_expansions/quantum_operations/classicalif.py +53 -0
  333. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
  334. classiq/model_expansions/quantum_operations/emitter.py +181 -0
  335. classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
  336. classiq/model_expansions/quantum_operations/repeat.py +56 -0
  337. classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
  338. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  339. classiq/model_expansions/scope.py +240 -0
  340. classiq/model_expansions/scope_initialization.py +150 -0
  341. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  342. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  343. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
  344. classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
  345. classiq/model_expansions/transformers/__init__.py +0 -0
  346. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  347. classiq/model_expansions/transformers/var_splitter.py +299 -0
  348. classiq/model_expansions/utils/__init__.py +0 -0
  349. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  350. classiq/model_expansions/utils/handles_collector.py +33 -0
  351. classiq/model_expansions/visitors/__init__.py +0 -0
  352. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  353. classiq/model_expansions/visitors/variable_references.py +144 -0
  354. classiq/open_library/__init__.py +4 -0
  355. classiq/open_library/functions/__init__.py +130 -0
  356. classiq/open_library/functions/amplitude_estimation.py +30 -0
  357. classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
  358. classiq/open_library/functions/grover.py +157 -0
  359. classiq/open_library/functions/hea.py +115 -0
  360. classiq/open_library/functions/linear_pauli_rotation.py +82 -0
  361. classiq/open_library/functions/modular_exponentiation.py +201 -0
  362. classiq/open_library/functions/qaoa_penalty.py +117 -0
  363. classiq/open_library/functions/qft_functions.py +54 -0
  364. classiq/open_library/functions/qpe.py +46 -0
  365. classiq/open_library/functions/qsvt.py +331 -0
  366. classiq/open_library/functions/state_preparation.py +301 -0
  367. classiq/open_library/functions/swap_test.py +27 -0
  368. classiq/open_library/functions/utility_functions.py +81 -0
  369. classiq/open_library/functions/variational.py +52 -0
  370. classiq/qmod/__init__.py +17 -10
  371. classiq/qmod/builtins/__init__.py +19 -2
  372. classiq/qmod/builtins/classical_execution_primitives.py +60 -47
  373. classiq/qmod/builtins/classical_functions.py +44 -38
  374. classiq/qmod/builtins/constants.py +10 -0
  375. classiq/qmod/builtins/enums.py +208 -0
  376. classiq/qmod/builtins/functions/__init__.py +137 -0
  377. classiq/qmod/builtins/functions/allocation.py +150 -0
  378. classiq/qmod/builtins/functions/arithmetic.py +55 -0
  379. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  380. classiq/qmod/builtins/functions/chemistry.py +91 -0
  381. classiq/qmod/builtins/functions/exponentiation.py +105 -0
  382. classiq/qmod/builtins/functions/finance.py +34 -0
  383. classiq/qmod/builtins/functions/operators.py +16 -0
  384. classiq/qmod/builtins/functions/qsvm.py +24 -0
  385. classiq/qmod/builtins/functions/standard_gates.py +651 -0
  386. classiq/qmod/builtins/operations.py +379 -57
  387. classiq/qmod/builtins/structs.py +103 -80
  388. classiq/qmod/cfunc.py +42 -0
  389. classiq/qmod/classical_function.py +8 -20
  390. classiq/qmod/cparam.py +64 -0
  391. classiq/qmod/create_model_function.py +56 -0
  392. classiq/qmod/declaration_inferrer.py +145 -112
  393. classiq/qmod/expression_query.py +39 -0
  394. classiq/qmod/generative.py +42 -0
  395. classiq/qmod/model_state_container.py +19 -5
  396. classiq/qmod/native/__init__.py +7 -0
  397. classiq/qmod/native/expression_to_qmod.py +194 -0
  398. classiq/qmod/native/pretty_printer.py +401 -0
  399. classiq/qmod/pretty_print/__init__.py +7 -0
  400. classiq/qmod/pretty_print/expression_to_python.py +222 -0
  401. classiq/qmod/pretty_print/pretty_printer.py +572 -0
  402. classiq/qmod/python_classical_type.py +67 -0
  403. classiq/qmod/qfunc.py +79 -0
  404. classiq/qmod/qmod_constant.py +143 -0
  405. classiq/qmod/qmod_parameter.py +84 -53
  406. classiq/qmod/qmod_variable.py +497 -100
  407. classiq/qmod/quantum_callable.py +17 -7
  408. classiq/qmod/quantum_expandable.py +278 -105
  409. classiq/qmod/quantum_function.py +232 -48
  410. classiq/qmod/semantics/__init__.py +0 -0
  411. classiq/qmod/semantics/annotation/__init__.py +0 -0
  412. classiq/qmod/semantics/annotation/call_annotation.py +92 -0
  413. classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
  414. classiq/qmod/semantics/error_manager.py +88 -0
  415. classiq/qmod/semantics/lambdas.py +25 -0
  416. classiq/qmod/semantics/static_semantics_visitor.py +384 -0
  417. classiq/qmod/semantics/validation/__init__.py +0 -0
  418. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  419. classiq/qmod/semantics/validation/func_call_validation.py +99 -0
  420. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  421. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  422. classiq/qmod/semantics/validation/main_validation.py +33 -0
  423. classiq/qmod/semantics/validation/types_validation.py +128 -0
  424. classiq/qmod/symbolic.py +178 -111
  425. classiq/qmod/symbolic_expr.py +36 -12
  426. classiq/qmod/symbolic_type.py +2 -5
  427. classiq/qmod/type_attribute_remover.py +32 -0
  428. classiq/qmod/utilities.py +108 -1
  429. classiq/qmod/write_qmod.py +53 -0
  430. classiq/synthesis.py +210 -22
  431. {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -8
  432. classiq-0.65.3.dist-info/RECORD +521 -0
  433. {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/WHEEL +1 -1
  434. classiq/_internals/_qfunc_ext.py +0 -6
  435. classiq/applications/benchmarking/__init__.py +0 -9
  436. classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
  437. classiq/applications/numpy_utils.py +0 -37
  438. classiq/applications_model_constructors/__init__.py +0 -17
  439. classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
  440. classiq/applications_model_constructors/grover_model_constructor.py +0 -227
  441. classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
  442. classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
  443. classiq/builtin_functions/__init__.py +0 -43
  444. classiq/builtin_functions/amplitude_loading.py +0 -3
  445. classiq/builtin_functions/binary_ops.py +0 -1
  446. classiq/builtin_functions/exponentiation.py +0 -5
  447. classiq/builtin_functions/qpe.py +0 -4
  448. classiq/builtin_functions/qsvm.py +0 -7
  449. classiq/builtin_functions/range_types.py +0 -5
  450. classiq/builtin_functions/standard_gates.py +0 -1
  451. classiq/builtin_functions/state_preparation.py +0 -6
  452. classiq/builtin_functions/suzuki_trotter.py +0 -3
  453. classiq/exceptions.py +0 -131
  454. classiq/interface/executor/aws_execution_cost.py +0 -72
  455. classiq/interface/executor/error_mitigation.py +0 -6
  456. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -115
  457. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -59
  458. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  459. classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
  460. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
  461. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  462. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  463. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  464. classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
  465. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  466. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
  467. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
  468. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -862
  469. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
  470. classiq/interface/generator/functions/foreign_function_definition.py +0 -106
  471. classiq/interface/generator/functions/function_implementation.py +0 -103
  472. classiq/interface/generator/functions/native_function_definition.py +0 -153
  473. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  474. classiq/interface/generator/functions/register.py +0 -42
  475. classiq/interface/generator/functions/register_mapping_data.py +0 -102
  476. classiq/interface/generator/inequality_mixer.py +0 -51
  477. classiq/interface/generator/model/classical_main_validator.py +0 -106
  478. classiq/interface/generator/range_mixer.py +0 -56
  479. classiq/interface/generator/state_propagator.py +0 -63
  480. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -2
  481. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
  482. classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
  483. classiq/interface/generator/types/combinatorial_problem.py +0 -26
  484. classiq/interface/ide/show.py +0 -34
  485. classiq/interface/model/common_model_types.py +0 -23
  486. classiq/interface/model/numeric_reinterpretation.py +0 -25
  487. classiq/interface/model/operator_synthesis_data.py +0 -48
  488. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  489. classiq/interface/model/quantum_if_operation.py +0 -95
  490. classiq/interface/model/resolvers/function_call_resolver.py +0 -43
  491. classiq/interface/model/validations/handle_validation_base.py +0 -55
  492. classiq/interface/model/validations/handles_validator.py +0 -154
  493. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  494. classiq/model/__init__.py +0 -14
  495. classiq/model/composite_function_generator.py +0 -33
  496. classiq/model/function_handler.py +0 -466
  497. classiq/model/function_handler.pyi +0 -152
  498. classiq/model/logic_flow.py +0 -149
  499. classiq/model/logic_flow_change_handler.py +0 -71
  500. classiq/model/model.py +0 -246
  501. classiq/qmod/builtins/functions.py +0 -896
  502. classiq/qmod/qmod_struct.py +0 -37
  503. classiq/quantum_functions/__init__.py +0 -17
  504. classiq/quantum_functions/annotation_parser.py +0 -207
  505. classiq/quantum_functions/decorators.py +0 -22
  506. classiq/quantum_functions/function_library.py +0 -181
  507. classiq/quantum_functions/function_parser.py +0 -74
  508. classiq/quantum_functions/quantum_function.py +0 -236
  509. classiq-0.37.1.dist-info/RECORD +0 -418
  510. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
  511. /classiq/{interface/generator/credit_risk_example → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
  512. /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/pauli_helpers}/__init__.py +0 -0
  513. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/py.typed} +0 -0
  514. /classiq/{interface/model/resolvers → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  515. /classiq/{interface/model/validations → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  516. /classiq/{_internals → interface}/enum_utils.py +0 -0
@@ -0,0 +1,249 @@
1
+ from functools import singledispatchmethod
2
+ from typing import Any
3
+
4
+ import numpy as np
5
+ from numpy.random import permutation
6
+
7
+ from classiq.interface.generator.expressions.expression import Expression
8
+ from classiq.interface.generator.functions.builtins.internal_operators import (
9
+ CONTROL_OPERATOR_NAME,
10
+ INVERT_OPERATOR_NAME,
11
+ WITHIN_APPLY_NAME,
12
+ )
13
+ from classiq.interface.model.allocate import Allocate
14
+ from classiq.interface.model.bind_operation import BindOperation
15
+ from classiq.interface.model.classical_if import ClassicalIf
16
+ from classiq.interface.model.control import Control
17
+ from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
18
+ from classiq.interface.model.invert import Invert
19
+ from classiq.interface.model.model import Model
20
+ from classiq.interface.model.native_function_definition import NativeFunctionDefinition
21
+ from classiq.interface.model.phase_operation import PhaseOperation
22
+ from classiq.interface.model.power import Power
23
+ from classiq.interface.model.quantum_expressions.quantum_expression import (
24
+ QuantumAssignmentOperation,
25
+ )
26
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
27
+ from classiq.interface.model.quantum_function_declaration import (
28
+ NamedParamsQuantumFunctionDeclaration,
29
+ )
30
+ from classiq.interface.model.quantum_lambda_function import (
31
+ OperandIdentifier,
32
+ QuantumLambdaFunction,
33
+ )
34
+ from classiq.interface.model.quantum_statement import QuantumStatement
35
+ from classiq.interface.model.repeat import Repeat
36
+ from classiq.interface.model.variable_declaration_statement import (
37
+ VariableDeclarationStatement,
38
+ )
39
+ from classiq.interface.model.within_apply_operation import WithinApply
40
+
41
+ from classiq.model_expansions.closure import (
42
+ Closure,
43
+ FunctionClosure,
44
+ GenerativeClosure,
45
+ GenerativeFunctionClosure,
46
+ )
47
+ from classiq.model_expansions.generative_functions import emit_generative_statements
48
+ from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
49
+ from classiq.model_expansions.quantum_operations import (
50
+ BindEmitter,
51
+ ClassicalIfEmitter,
52
+ QuantumFunctionCallEmitter,
53
+ RepeatEmitter,
54
+ VariableDeclarationStatementEmitter,
55
+ )
56
+ from classiq.model_expansions.quantum_operations.shallow_emitter import ShallowEmitter
57
+ from classiq.model_expansions.scope import Evaluated, Scope
58
+ from classiq.model_expansions.scope_initialization import (
59
+ add_functions_to_scope,
60
+ add_generative_functions_to_scope,
61
+ )
62
+ from classiq.qmod.builtins.functions import permute
63
+ from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
64
+ from classiq.qmod.quantum_function import GenerativeQFunc
65
+
66
+
67
+ class GenerativeInterpreter(BaseInterpreter):
68
+ def __init__(
69
+ self,
70
+ model: Model,
71
+ generative_functions: list[GenerativeQFunc],
72
+ ) -> None:
73
+ super().__init__(model)
74
+ add_generative_functions_to_scope(generative_functions, self._top_level_scope)
75
+
76
+ def evaluate_lambda(self, function: QuantumLambdaFunction) -> Evaluated:
77
+ renamed_params = [
78
+ param.rename(function.pos_rename_params[idx])
79
+ for idx, param in enumerate(function.func_decl.positional_arg_declarations)
80
+ ]
81
+ func_decl = NamedParamsQuantumFunctionDeclaration(
82
+ name=self._counted_name_allocator.allocate(
83
+ function.func_decl.name or "<lambda>"
84
+ ),
85
+ positional_arg_declarations=renamed_params,
86
+ )
87
+
88
+ closure_class: type[FunctionClosure]
89
+ extra_args: dict[str, Any]
90
+ if function.is_generative():
91
+ closure_class = GenerativeFunctionClosure
92
+ extra_args = {
93
+ "generative_blocks": {
94
+ "body": GenerativeQFunc(function.py_callable, func_decl),
95
+ }
96
+ }
97
+ else:
98
+ closure_class = FunctionClosure
99
+ extra_args = {}
100
+
101
+ return Evaluated(
102
+ value=closure_class.create(
103
+ name=func_decl.name,
104
+ positional_arg_declarations=func_decl.positional_arg_declarations,
105
+ body=function.body,
106
+ scope=Scope(parent=self._builder.current_scope),
107
+ is_lambda=True,
108
+ **extra_args,
109
+ ),
110
+ defining_function=self._builder.current_function,
111
+ )
112
+
113
+ @singledispatchmethod
114
+ def emit(self, statement: QuantumStatement) -> None: # type:ignore[override]
115
+ raise NotImplementedError(f"Cannot emit {statement!r}")
116
+
117
+ @emit.register
118
+ def _emit_quantum_function_call(self, call: QuantumFunctionCall) -> None:
119
+ self.emit_quantum_function_call(call)
120
+
121
+ def emit_quantum_function_call(self, call: QuantumFunctionCall) -> None:
122
+ QuantumFunctionCallEmitter(self).emit(call)
123
+
124
+ @emit.register
125
+ def emit_allocate(self, allocate: Allocate) -> None:
126
+ ShallowEmitter(self, "allocate", components=["size", "target"]).emit(allocate)
127
+
128
+ @emit.register
129
+ def emit_bind(self, bind: BindOperation) -> None:
130
+ BindEmitter(self).emit(bind)
131
+
132
+ @emit.register
133
+ def emit_quantum_assignment_operation(self, op: QuantumAssignmentOperation) -> None:
134
+ ShallowEmitter(
135
+ self, "assignment_operation", components=["expression", "result_var"]
136
+ ).emit(op)
137
+
138
+ @emit.register
139
+ def emit_inplace_binary_operation(self, op: InplaceBinaryOperation) -> None:
140
+ ShallowEmitter(
141
+ self, "inplace_binary_operation", components=["target", "value"]
142
+ ).emit(op)
143
+
144
+ @emit.register
145
+ def emit_variable_declaration(
146
+ self, variable_declaration: VariableDeclarationStatement
147
+ ) -> None:
148
+ VariableDeclarationStatementEmitter(self).emit(variable_declaration)
149
+
150
+ @emit.register
151
+ def emit_classical_if(self, classical_if: ClassicalIf) -> None:
152
+ ClassicalIfEmitter(self).emit(classical_if)
153
+
154
+ @emit.register
155
+ def emit_within_apply(self, within_apply: WithinApply) -> None:
156
+ ShallowEmitter(
157
+ self,
158
+ WITHIN_APPLY_NAME,
159
+ components=["within", "apply", "compute", "action"],
160
+ ).emit(within_apply)
161
+
162
+ @emit.register
163
+ def emit_invert(self, invert: Invert) -> None:
164
+ ShallowEmitter(self, INVERT_OPERATOR_NAME, components=["body"]).emit(invert)
165
+
166
+ @emit.register
167
+ def emit_repeat(self, repeat: Repeat) -> None:
168
+ RepeatEmitter(self).emit(repeat)
169
+
170
+ @emit.register
171
+ def emit_control(self, control: Control) -> None:
172
+ ShallowEmitter(
173
+ self,
174
+ CONTROL_OPERATOR_NAME,
175
+ components=["expression", "body", "else_block"],
176
+ ).emit(control)
177
+
178
+ @emit.register
179
+ def emit_power(self, power: Power) -> None:
180
+ ShallowEmitter(self, CONTROL_OPERATOR_NAME, components=["power", "body"]).emit(
181
+ power
182
+ )
183
+
184
+ @emit.register
185
+ def emit_phase(self, phase: PhaseOperation) -> None:
186
+ ShallowEmitter(self, "phase", components=["expression", "theta"]).emit(phase)
187
+
188
+ def _expand_body(self, operation: Closure) -> None:
189
+ if isinstance(operation, FunctionClosure) and operation.name == "permute":
190
+ # special expansion since permute is generative
191
+ self._expand_permute()
192
+ elif isinstance(operation, GenerativeClosure):
193
+ args = [
194
+ self.evaluate(param.name)
195
+ for param in operation.positional_arg_declarations
196
+ ]
197
+ emit_generative_statements(self, operation, args)
198
+ else:
199
+ super()._expand_body(operation)
200
+
201
+ def _expand_permute(self) -> None:
202
+ functions = self.evaluate("functions").as_type(list)
203
+ functions_permutation = permutation(np.array(range(len(functions))))
204
+ calls: list[QuantumFunctionCall] = []
205
+ for function_index in functions_permutation:
206
+ permute_call = QuantumFunctionCall(
207
+ function=OperandIdentifier(
208
+ name="functions", index=Expression(expr=f"{function_index}")
209
+ )
210
+ )
211
+ permute_call.set_func_decl(permute.func_decl)
212
+ calls.append(permute_call)
213
+ self._expand_block(calls, "body")
214
+
215
+ def update_generative_functions(
216
+ self, generative_functions: dict[str, GenerativeQFunc]
217
+ ) -> None:
218
+ add_generative_functions_to_scope(
219
+ list(generative_functions.values()), self._top_level_scope
220
+ )
221
+ for name, gen_func in generative_functions.items():
222
+ if gen_func.compilation_metadata is not None:
223
+ self._functions_compilation_metadata[name] = (
224
+ gen_func.compilation_metadata
225
+ )
226
+
227
+ def update_declarative_functions(
228
+ self,
229
+ functions: dict[str, NativeFunctionDefinition],
230
+ qmodule: ModelStateContainer,
231
+ ) -> None:
232
+ add_functions_to_scope(list(functions.values()), self._top_level_scope)
233
+ for dec_func_name in functions:
234
+ if dec_func_name in qmodule.functions_compilation_metadata:
235
+ self._functions_compilation_metadata[dec_func_name] = (
236
+ qmodule.functions_compilation_metadata[dec_func_name]
237
+ )
238
+
239
+ def add_purely_declarative_function(self, function: FunctionClosure) -> None:
240
+ functions_to_add = [function.name] + QMODULE.function_dependencies[
241
+ function.name
242
+ ]
243
+ for func in functions_to_add:
244
+ if func not in self._expanded_functions and func in QMODULE.native_defs:
245
+ self._expanded_functions[func] = QMODULE.native_defs[func]
246
+ if func in QMODULE.functions_compilation_metadata:
247
+ self._expanded_functions_compilation_metadata[func] = (
248
+ QMODULE.functions_compilation_metadata[func]
249
+ )
@@ -0,0 +1,18 @@
1
+ from typing import Optional
2
+
3
+ from classiq.interface.generator.expressions.handle_identifier import HandleIdentifier
4
+ from classiq.interface.generator.functions.classical_type import QmodPyObject
5
+
6
+
7
+ class HandleTable:
8
+ _handle_map: dict[HandleIdentifier, QmodPyObject] = {}
9
+
10
+ @classmethod
11
+ def get_handle_object(cls, hid: HandleIdentifier) -> Optional[QmodPyObject]:
12
+ return cls._handle_map.get(hid)
13
+
14
+ @classmethod
15
+ def set_handle_object(cls, qmod_object: QmodPyObject) -> HandleIdentifier:
16
+ hid = HandleIdentifier(id(qmod_object))
17
+ cls._handle_map[hid] = qmod_object
18
+ return hid
@@ -0,0 +1,9 @@
1
+ from classiq.model_expansions.quantum_operations.bind import BindEmitter
2
+ from classiq.model_expansions.quantum_operations.classicalif import ClassicalIfEmitter
3
+ from classiq.model_expansions.quantum_operations.quantum_function_call import (
4
+ QuantumFunctionCallEmitter,
5
+ )
6
+ from classiq.model_expansions.quantum_operations.repeat import RepeatEmitter
7
+ from classiq.model_expansions.quantum_operations.variable_decleration import (
8
+ VariableDeclarationStatementEmitter,
9
+ )
@@ -0,0 +1,60 @@
1
+ from classiq.interface.exceptions import ClassiqExpansionError
2
+ from classiq.interface.model.bind_operation import BindOperation
3
+
4
+ from classiq.model_expansions.evaluators.parameter_types import (
5
+ evaluate_types_in_quantum_symbols,
6
+ )
7
+ from classiq.model_expansions.evaluators.quantum_type_utils import (
8
+ set_size,
9
+ validate_bind_targets,
10
+ )
11
+ from classiq.model_expansions.quantum_operations.emitter import Emitter
12
+ from classiq.model_expansions.scope import QuantumSymbol
13
+
14
+
15
+ class BindEmitter(Emitter[BindOperation]):
16
+ def emit(self, bind: BindOperation, /) -> None:
17
+ inputs: list[QuantumSymbol] = [
18
+ self._interpreter.evaluate(arg).as_type(QuantumSymbol)
19
+ for arg in bind.in_handles
20
+ ]
21
+ outputs: list[QuantumSymbol] = [
22
+ self._interpreter.evaluate(arg).as_type(QuantumSymbol)
23
+ for arg in bind.out_handles
24
+ ]
25
+ inputs = evaluate_types_in_quantum_symbols(inputs, self._current_scope)
26
+ outputs = evaluate_types_in_quantum_symbols(outputs, self._current_scope)
27
+ validate_bind_targets(bind, self._current_scope)
28
+ unsized_outputs = [
29
+ output for output in outputs if not output.quantum_type.has_size_in_bits
30
+ ]
31
+
32
+ if len(unsized_outputs) > 1:
33
+ raise ClassiqExpansionError(
34
+ f"Cannot perform the split operation {bind.in_handles[0].name} -> {{{', '.join(out_handle.name for out_handle in bind.out_handles)}}}:\n"
35
+ f"Quantum variables {', '.join(str(out_handle.handle) for out_handle in unsized_outputs)} are used as bind outputs, but their size cannot be inferred."
36
+ )
37
+
38
+ input_size = sum(input.quantum_type.size_in_bits for input in inputs)
39
+ output_size = sum(
40
+ output.quantum_type.size_in_bits
41
+ for output in outputs
42
+ if output.quantum_type.has_size_in_bits
43
+ )
44
+
45
+ if len(unsized_outputs) == 1:
46
+ set_size(
47
+ unsized_outputs[0].quantum_type,
48
+ input_size - output_size,
49
+ str(unsized_outputs[0].handle),
50
+ )
51
+
52
+ else:
53
+ if input_size != output_size:
54
+ raise ClassiqExpansionError(
55
+ f"The total size for the input and output of the bind operation must be the same. The in size is {input_size} and the out size is {output_size}"
56
+ )
57
+
58
+ self.emit_statement(
59
+ BindOperation(in_handles=bind.in_handles, out_handles=bind.out_handles)
60
+ )
@@ -0,0 +1,266 @@
1
+ from collections.abc import Sequence
2
+ from itertools import chain
3
+ from typing import (
4
+ TYPE_CHECKING,
5
+ Generic,
6
+ Optional,
7
+ cast,
8
+ )
9
+
10
+ from classiq.interface.debug_info.debug_info import FunctionDebugInfo
11
+ from classiq.interface.generator.generated_circuit_data import OperationLevel
12
+ from classiq.interface.model.classical_parameter_declaration import (
13
+ ClassicalParameterDeclaration,
14
+ )
15
+ from classiq.interface.model.handle_binding import HandleBinding
16
+ from classiq.interface.model.native_function_definition import NativeFunctionDefinition
17
+ from classiq.interface.model.port_declaration import PortDeclaration
18
+ from classiq.interface.model.quantum_function_call import ArgValue, QuantumFunctionCall
19
+ from classiq.interface.model.quantum_function_declaration import (
20
+ NamedParamsQuantumFunctionDeclaration,
21
+ PositionalArg,
22
+ )
23
+ from classiq.interface.model.quantum_statement import QuantumStatement
24
+ from classiq.interface.model.variable_declaration_statement import (
25
+ VariableDeclarationStatement,
26
+ )
27
+
28
+ from classiq.model_expansions.capturing.captured_vars import (
29
+ validate_args_are_not_propagated,
30
+ )
31
+ from classiq.model_expansions.closure import FunctionClosure
32
+ from classiq.model_expansions.evaluators.argument_types import (
33
+ add_information_from_output_arguments,
34
+ )
35
+ from classiq.model_expansions.evaluators.parameter_types import (
36
+ evaluate_parameter_types_from_args,
37
+ )
38
+ from classiq.model_expansions.function_builder import (
39
+ FunctionContext,
40
+ )
41
+ from classiq.model_expansions.quantum_operations.emitter import (
42
+ Emitter,
43
+ QuantumStatementT,
44
+ )
45
+ from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
46
+ from classiq.model_expansions.transformers.var_splitter import VarSplitter
47
+ from classiq.qmod.builtins.functions import allocate, free
48
+
49
+ if TYPE_CHECKING:
50
+ from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
51
+
52
+
53
+ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSplitter):
54
+ def __init__(self, interpreter: "BaseInterpreter") -> None:
55
+ Emitter.__init__(self, interpreter)
56
+ VarSplitter.__init__(self, interpreter._builder.current_scope)
57
+
58
+ @staticmethod
59
+ def _should_wrap(body: Sequence[QuantumStatement]) -> bool:
60
+ # This protects shadowing of captured variables (i.e, bad user code) by wrapping the body in a function
61
+ # I'm sure there are better ways to handle it, but this is the simplest way to do it for now
62
+ return any(isinstance(stmt, VariableDeclarationStatement) for stmt in body)
63
+
64
+ def _create_expanded_wrapping_function(
65
+ self, name: str, body: Sequence[QuantumStatement]
66
+ ) -> QuantumFunctionCall:
67
+ wrapping_function = FunctionClosure.create(
68
+ name=self._counted_name_allocator.allocate(name),
69
+ body=body,
70
+ scope=Scope(parent=self._current_scope),
71
+ is_lambda=True,
72
+ )
73
+ return self._create_quantum_function_call(wrapping_function, list())
74
+
75
+ def _emit_quantum_function_call(
76
+ self,
77
+ function: FunctionClosure,
78
+ args: list[ArgValue],
79
+ propagated_debug_info: Optional[FunctionDebugInfo] = None,
80
+ ) -> QuantumFunctionCall:
81
+ call = self._create_quantum_function_call(
82
+ function, args, propagated_debug_info=propagated_debug_info
83
+ )
84
+ self.emit_statement(call)
85
+ return call
86
+
87
+ def _create_quantum_function_call(
88
+ self,
89
+ function: FunctionClosure,
90
+ args: list[ArgValue],
91
+ propagated_debug_info: Optional[FunctionDebugInfo] = None,
92
+ ) -> QuantumFunctionCall:
93
+ function = function.clone()
94
+ function = function.set_depth(self._builder.current_function.depth + 1)
95
+ evaluated_args = [self._interpreter.evaluate(arg) for arg in args]
96
+ new_declaration = self._prepare_fully_typed_declaration(
97
+ function, evaluated_args
98
+ )
99
+ new_positional_arg_decls = new_declaration.positional_arg_declarations
100
+ if not self.should_expand_function(function, evaluated_args):
101
+ is_atomic = True
102
+ new_declaration = self._expanded_functions_by_name.get(
103
+ function.name, new_declaration
104
+ )
105
+ else:
106
+ is_atomic = False
107
+ new_declaration = self._expand_function(
108
+ evaluated_args, new_declaration, function
109
+ )
110
+
111
+ new_positional_args = self._get_new_positional_args(
112
+ evaluated_args, is_atomic, new_positional_arg_decls
113
+ )
114
+ captured_args = function.captured_vars.get_captured_args(
115
+ self._builder.current_function
116
+ )
117
+ validate_args_are_not_propagated(new_positional_args, captured_args)
118
+ new_positional_args.extend(captured_args)
119
+ new_call = QuantumFunctionCall(
120
+ function=new_declaration.name, positional_args=new_positional_args
121
+ )
122
+ is_allocate_or_free = (
123
+ new_call.func_name == allocate.func_decl.name
124
+ or new_call.func_name == free.func_decl.name
125
+ )
126
+ parameters = {
127
+ arg_decl.name: FunctionDebugInfo.param_controller(value=evaluated_arg.value)
128
+ for arg_decl, evaluated_arg in zip(new_positional_arg_decls, evaluated_args)
129
+ if isinstance(arg_decl, ClassicalParameterDeclaration)
130
+ }
131
+
132
+ port_to_passed_variable_map = {
133
+ arg_decl.name: str(evaluated_arg.value.handle)
134
+ for arg_decl, evaluated_arg in zip(new_positional_arg_decls, evaluated_args)
135
+ if isinstance(arg_decl, PortDeclaration)
136
+ }
137
+ self._debug_info[new_call.uuid] = FunctionDebugInfo(
138
+ name=new_call.func_name,
139
+ level=OperationLevel.QMOD_FUNCTION_CALL,
140
+ parameters=(
141
+ parameters
142
+ if propagated_debug_info is None
143
+ else propagated_debug_info.parameters
144
+ ),
145
+ is_allocate_or_free=is_allocate_or_free,
146
+ port_to_passed_variable_map=port_to_passed_variable_map,
147
+ )
148
+ new_call.set_func_decl(new_declaration)
149
+ return new_call
150
+
151
+ def should_expand_function(
152
+ self, function: FunctionClosure, args: list[Evaluated]
153
+ ) -> bool:
154
+ return not function.is_atomic
155
+
156
+ def _expand_function(
157
+ self,
158
+ args: list[Evaluated],
159
+ decl: NamedParamsQuantumFunctionDeclaration,
160
+ function: FunctionClosure,
161
+ ) -> NamedParamsQuantumFunctionDeclaration:
162
+ self._add_params_to_scope(decl.positional_arg_declarations, args, function)
163
+ context = self._expand_operation(function.with_new_declaration(decl))
164
+ function_context = cast(FunctionContext, context)
165
+ closure_id = function_context.closure.closure_id
166
+ if closure_id in self._expanded_functions:
167
+ function_def = self._expanded_functions[closure_id]
168
+ self._expanded_functions_compilation_metadata[
169
+ function_def.name
170
+ ].occurrences_number += 1
171
+ return function_def
172
+
173
+ function_def = self._create_function_definition(function_context)
174
+ self._expanded_functions[closure_id] = function_def
175
+ self._top_level_scope[function_def.name] = Evaluated(
176
+ value=function_context.closure.with_new_declaration(function_def)
177
+ )
178
+ compilation_metadata = self._functions_compilation_metadata.get(function.name)
179
+ if compilation_metadata is not None:
180
+ self._expanded_functions_compilation_metadata[function_def.name] = (
181
+ compilation_metadata
182
+ )
183
+ return function_def
184
+
185
+ def _create_function_definition(
186
+ self, function_context: FunctionContext
187
+ ) -> NativeFunctionDefinition:
188
+ func_def = self._builder.create_definition(function_context)
189
+
190
+ captured_ports = function_context.closure.captured_vars.get_captured_ports()
191
+ if len(captured_ports) == 0:
192
+ return func_def
193
+ func_def.positional_arg_declarations = list(
194
+ chain.from_iterable((func_def.positional_arg_declarations, captured_ports))
195
+ )
196
+
197
+ if not function_context.is_lambda:
198
+ return func_def
199
+ func_def.body = self.rewrite(
200
+ func_def.body, function_context.closure.captured_vars.get_captured_mapping()
201
+ )
202
+
203
+ return func_def
204
+
205
+ @staticmethod
206
+ def _add_params_to_scope(
207
+ parameters: Sequence[PositionalArg],
208
+ arguments: Sequence[Evaluated],
209
+ closure: FunctionClosure,
210
+ ) -> None:
211
+ for parameter, argument in zip(parameters, arguments):
212
+ if isinstance(argument.value, QuantumSymbol):
213
+ assert isinstance(parameter, PortDeclaration)
214
+ closure.scope[parameter.name] = Evaluated(
215
+ QuantumSymbol(
216
+ handle=HandleBinding(name=parameter.name),
217
+ quantum_type=parameter.quantum_type,
218
+ ),
219
+ defining_function=closure,
220
+ )
221
+ else:
222
+ closure.scope[parameter.name] = argument
223
+
224
+ def _get_new_positional_args(
225
+ self,
226
+ evaluated_args: list[Evaluated],
227
+ is_atomic: bool,
228
+ new_positional_arg_decls: Sequence[PositionalArg],
229
+ ) -> list[ArgValue]:
230
+ evaluated_args = add_information_from_output_arguments(
231
+ new_positional_arg_decls, evaluated_args
232
+ )
233
+ if is_atomic:
234
+ return [arg.emit() for arg in evaluated_args]
235
+
236
+ positional_args = [
237
+ arg.emit() for arg in evaluated_args if isinstance(arg.value, QuantumSymbol)
238
+ ]
239
+
240
+ return positional_args
241
+
242
+ def _prepare_fully_typed_declaration(
243
+ self, function: FunctionClosure, evaluated_args: list[Evaluated]
244
+ ) -> NamedParamsQuantumFunctionDeclaration:
245
+ """
246
+ Given, for example,
247
+ def my_func(x: int, q: QArray["x"], p: QArray[]) -> None:
248
+ ...
249
+ def main(...):
250
+ ...
251
+ allocate(5, s)
252
+ my_func(3, r, s)
253
+ The code below will evaluate x to be 3, q to be of size 3 and p to be of size 5.
254
+ Note that it requires a scope for the parameter declaration space, which is
255
+ different from the call scope. For example, the former uses r,s and the latter
256
+ uses p, q.
257
+ """
258
+ # The signature scope is passed as a separate argument to avoid contaminating the statement execution scope
259
+ return NamedParamsQuantumFunctionDeclaration(
260
+ name=function.name,
261
+ positional_arg_declarations=evaluate_parameter_types_from_args(
262
+ function,
263
+ function.signature_scope,
264
+ evaluated_args,
265
+ ),
266
+ )
@@ -0,0 +1,53 @@
1
+ from collections.abc import Sequence
2
+
3
+ from classiq.interface.model.classical_if import ClassicalIf
4
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
5
+ from classiq.interface.model.quantum_statement import QuantumStatement
6
+
7
+ from classiq.model_expansions.closure import FunctionClosure
8
+ from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
9
+ from classiq.model_expansions.scope import Scope
10
+
11
+
12
+ def _is_all_identity_calls(body: Sequence[QuantumStatement]) -> bool:
13
+ return all(
14
+ isinstance(stmt, QuantumFunctionCall) and stmt.func_name.lower() == "identity"
15
+ for stmt in body
16
+ )
17
+
18
+
19
+ class ClassicalIfEmitter(CallEmitter[ClassicalIf]):
20
+ def emit(self, classical_if: ClassicalIf, /) -> None:
21
+ condition = self._interpreter.evaluate(classical_if.condition).as_type(bool)
22
+ op_name = "then" if condition else "else"
23
+ is_generative = classical_if.is_generative()
24
+
25
+ body: Sequence[QuantumStatement]
26
+ if is_generative:
27
+ if not classical_if.has_generative_block(op_name):
28
+ return
29
+ context = self._expand_generative_context(classical_if, op_name, op_name)
30
+ context.blocks["body"] = context.blocks[op_name]
31
+ context.blocks.pop(op_name)
32
+ body = context.statements("body")
33
+ else:
34
+ body = classical_if.then if condition else classical_if.else_
35
+
36
+ if _is_all_identity_calls(body):
37
+ return
38
+
39
+ if is_generative or not self._should_wrap(body):
40
+ for stmt in body:
41
+ if is_generative:
42
+ self._interpreter._builder.emit_statement(stmt)
43
+ else:
44
+ self._interpreter.emit_statement(stmt)
45
+ return
46
+
47
+ then_else_func = FunctionClosure.create(
48
+ name=self._counted_name_allocator.allocate("then" if condition else "else"),
49
+ body=body,
50
+ scope=Scope(parent=self._current_scope),
51
+ is_lambda=True,
52
+ )
53
+ self._emit_quantum_function_call(then_else_func, list())