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
@@ -1,166 +1,50 @@
1
- import itertools
2
- import re
3
- from typing import Any, Dict, List, Mapping, Optional, Sequence, Set, Union
1
+ from collections.abc import Iterable, Mapping, Sequence
2
+ from typing import (
3
+ Literal,
4
+ Optional,
5
+ Union,
6
+ )
4
7
 
5
8
  import pydantic
6
- from pydantic import BaseModel
7
9
 
10
+ from classiq.interface.exceptions import ClassiqError, ClassiqValueError
8
11
  from classiq.interface.generator.expressions.expression import Expression
9
- from classiq.interface.generator.function_params import NAME_REGEX
10
- from classiq.interface.generator.functions import FunctionDeclaration
11
12
  from classiq.interface.generator.functions.port_declaration import (
12
13
  PortDeclarationDirection,
13
14
  )
14
- from classiq.interface.generator.quantum_function_call import (
15
- BAD_CALL_NAME_ERROR_MSG,
16
- SUFFIX_MARKER,
17
- randomize_suffix,
18
- )
19
- from classiq.interface.helpers.custom_pydantic_types import PydanticNonEmptyString
20
- from classiq.interface.model.bind_operation import BindOperation
21
15
  from classiq.interface.model.handle_binding import (
16
+ ConcreteHandleBinding,
22
17
  HandleBinding,
23
- SlicedHandleBinding,
24
- SubscriptHandleBinding,
25
- )
26
- from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
27
- from classiq.interface.model.numeric_reinterpretation import (
28
- NumericReinterpretationOperation,
29
- )
30
- from classiq.interface.model.operator_synthesis_data import OperatorSynthesisData
31
- from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
32
- AmplitudeLoadingOperation,
33
- )
34
- from classiq.interface.model.quantum_expressions.arithmetic_operation import (
35
- ArithmeticOperation,
36
18
  )
19
+ from classiq.interface.model.port_declaration import AnonPortDeclaration
37
20
  from classiq.interface.model.quantum_function_declaration import (
38
21
  QuantumFunctionDeclaration,
39
- QuantumOperandDeclaration,
40
22
  )
41
- from classiq.interface.model.quantum_if_operation import QuantumIfOperation
42
- from classiq.interface.model.quantum_statement import QuantumOperation
43
- from classiq.interface.model.validation_handle import get_unique_handle_names
44
- from classiq.interface.model.variable_declaration_statement import (
45
- VariableDeclarationStatement,
23
+ from classiq.interface.model.quantum_lambda_function import (
24
+ OperandIdentifier,
25
+ QuantumOperand,
46
26
  )
27
+ from classiq.interface.model.quantum_statement import HandleMetadata, QuantumOperation
47
28
 
48
- from classiq.exceptions import ClassiqError, ClassiqValueError
49
-
50
-
51
- def _validate_no_duplicated_ports(
52
- inputs: Mapping[str, HandleBinding],
53
- outputs: Mapping[str, HandleBinding],
54
- inouts: Mapping[str, HandleBinding],
55
- ) -> None:
56
- inputs_and_inouts = inputs.keys() & inouts.keys()
57
- if inputs_and_inouts:
58
- raise ClassiqValueError(
59
- f"{inputs_and_inouts} are used as ports in both inputs and inouts"
60
- )
61
-
62
- outputs_and_inouts = outputs.keys() & inouts.keys()
63
- if outputs_and_inouts:
64
- raise ClassiqValueError(
65
- f"{outputs_and_inouts} are used as ports in both outputs and inouts"
66
- )
67
-
68
-
69
- def _validate_no_duplicated_handles(
70
- inputs: Mapping[str, HandleBinding],
71
- outputs: Mapping[str, HandleBinding],
72
- inouts: Mapping[str, HandleBinding],
73
- ) -> None:
74
- inputs_and_inouts = get_unique_handle_names(inputs) & get_unique_handle_names(
75
- inouts
76
- )
77
- if inputs_and_inouts:
78
- raise ClassiqValueError(
79
- f"{inputs_and_inouts} are used as handles in both inputs and inouts"
80
- )
81
-
82
- outputs_and_inouts = get_unique_handle_names(outputs) & get_unique_handle_names(
83
- inouts
84
- )
85
- if outputs_and_inouts:
86
- raise ClassiqValueError(
87
- f"{outputs_and_inouts} are used as handles in both outputs and inouts"
88
- )
89
-
90
-
91
- def _validate_no_mixing_sliced_and_whole_handles(
92
- inouts: Mapping[str, HandleBinding],
93
- ) -> None:
94
- inout_handle_names_to_types = {
95
- handle_name: {type(handle) for handle in handles}
96
- for handle_name, handles in itertools.groupby(
97
- inouts.values(), lambda handle: handle.name
98
- )
99
- }
100
- invalid_handles = [
101
- handle
102
- for handle, types in inout_handle_names_to_types.items()
103
- if len(types) > 1
104
- ]
105
- if invalid_handles:
106
- raise ClassiqValueError(
107
- f"Inout handles {', '.join(invalid_handles)} mix sliced and whole handles"
108
- )
109
-
110
-
111
- ArgValue = Union[Expression, "QuantumOperand", SlicedHandleBinding, HandleBinding]
112
-
113
-
114
- class OperandIdentifier(BaseModel):
115
- name: str
116
- index: Expression
29
+ ArgValue = Union[
30
+ Expression,
31
+ QuantumOperand,
32
+ ConcreteHandleBinding,
33
+ ]
117
34
 
118
35
 
119
36
  class QuantumFunctionCall(QuantumOperation):
37
+ kind: Literal["QuantumFunctionCall"]
38
+
120
39
  function: Union[str, OperandIdentifier] = pydantic.Field(
121
40
  description="The function that is called"
122
41
  )
123
- params: Dict[str, Expression] = pydantic.Field(default_factory=dict)
124
- release_by_inverse: bool = pydantic.Field(
125
- default=False, description="Release zero inputs in inverse call."
126
- )
127
- should_control: bool = pydantic.Field(
128
- default=True,
129
- description="False value indicates this call shouldn't be controlled even if the flow is controlled.",
130
- )
131
- inputs: Dict[str, HandleBinding] = pydantic.Field(
132
- default_factory=dict,
133
- description="A mapping from the input name to the wire it connects to",
134
- )
135
- inouts: Dict[
136
- str, Union[SlicedHandleBinding, SubscriptHandleBinding, HandleBinding]
137
- ] = pydantic.Field(
138
- default_factory=dict,
139
- description="A mapping from in/out name to the wires that connect to it",
140
- )
141
- outputs: Dict[str, HandleBinding] = pydantic.Field(
142
- default_factory=dict,
143
- description="A mapping from the output name to the wire it connects to",
144
- )
145
- name: PydanticNonEmptyString = pydantic.Field(
146
- default=None,
147
- description="The name of the function instance. "
148
- "If not set, determined automatically.",
149
- )
150
- operands: Dict[str, "QuantumOperand"] = pydantic.Field(
151
- description="Function calls passed to the operator",
152
- default_factory=dict,
153
- )
154
- positional_args: List[ArgValue] = pydantic.Field(default_factory=list)
42
+ positional_args: list[ArgValue] = pydantic.Field(default_factory=list)
155
43
 
156
44
  _func_decl: Optional[QuantumFunctionDeclaration] = pydantic.PrivateAttr(
157
45
  default=None
158
46
  )
159
47
 
160
- _operator_synthesis_data: OperatorSynthesisData = pydantic.PrivateAttr(
161
- default_factory=OperatorSynthesisData
162
- )
163
-
164
48
  @property
165
49
  def func_decl(self) -> QuantumFunctionDeclaration:
166
50
  if self._func_decl is None:
@@ -168,7 +52,7 @@ class QuantumFunctionCall(QuantumOperation):
168
52
 
169
53
  return self._func_decl
170
54
 
171
- def set_func_decl(self, fd: Optional[FunctionDeclaration]) -> None:
55
+ def set_func_decl(self, fd: Optional[QuantumFunctionDeclaration]) -> None:
172
56
  if fd is not None and not isinstance(fd, QuantumFunctionDeclaration):
173
57
  raise ClassiqValueError(
174
58
  "the declaration of a quantum function call cannot be set to a non-quantum function declaration."
@@ -183,352 +67,152 @@ class QuantumFunctionCall(QuantumOperation):
183
67
 
184
68
  @property
185
69
  def wiring_inputs(self) -> Mapping[str, HandleBinding]:
186
- return self.inputs
70
+ return self._get_pos_port_args_by_direction(PortDeclarationDirection.Input)
187
71
 
188
72
  @property
189
- def wiring_inouts(
190
- self,
191
- ) -> Mapping[
192
- str, Union[SlicedHandleBinding, SubscriptHandleBinding, HandleBinding]
193
- ]:
194
- return self.inouts
73
+ def inputs(self) -> Sequence[HandleBinding]:
74
+ return [
75
+ handle
76
+ for _, _, handle in self._get_handles_by_direction(
77
+ PortDeclarationDirection.Input
78
+ )
79
+ ]
195
80
 
196
81
  @property
197
- def wiring_outputs(self) -> Mapping[str, HandleBinding]:
198
- return self.outputs
199
-
200
- def get_positional_args(self) -> List[ArgValue]:
201
- result: List[ArgValue] = self.positional_args
202
- if not result:
203
- result = list(self.params.values())
204
- result.extend(self.operands.values())
205
- result.extend(self.inputs.values())
206
- result.extend(self.inouts.values())
207
- result.extend(self.outputs.values())
208
- return result
209
-
210
- def __eq__(self, other: Any) -> bool:
211
- return isinstance(other, QuantumFunctionCall) and self.name == other.name
212
-
213
- def __hash__(self) -> int:
214
- return hash(self.name)
215
-
216
- @pydantic.validator("name", pre=True, always=True)
217
- def _create_name(cls, name: Optional[str], values: Dict[str, Any]) -> str:
218
- """
219
- generates a name to a user defined-functions as follows:
220
- <function_name>_<SUFFIX_MARKER>_<random_suffix>
221
- """
222
- if name is not None:
223
- match = re.fullmatch(pattern=NAME_REGEX, string=name)
224
- if match is None:
225
- raise ValueError(BAD_CALL_NAME_ERROR_MSG)
226
- return name
227
-
228
- function = values.get("function")
229
- if isinstance(function, OperandIdentifier):
230
- function = function.name
231
-
232
- suffix = f"{SUFFIX_MARKER}_{randomize_suffix()}"
233
- if not function:
234
- return name if name else suffix
235
- return f"{function}_{suffix}"
82
+ def readable_inputs(self) -> Sequence[HandleMetadata]:
83
+ return [
84
+ HandleMetadata(
85
+ handle=handle,
86
+ readable_location=self._get_readable_location(param_idx, param),
87
+ )
88
+ for param_idx, param, handle in self._get_handles_by_direction(
89
+ PortDeclarationDirection.Input
90
+ )
91
+ ]
236
92
 
237
93
  @property
238
- def pos_param_args(self) -> Dict[str, Expression]:
239
- return dict(
240
- zip(
241
- self.func_decl.param_decls.keys(),
242
- (
243
- param
244
- for param in self.positional_args
245
- if isinstance(param, Expression)
246
- ),
247
- )
248
- )
94
+ def wiring_inouts(
95
+ self,
96
+ ) -> Mapping[str, ConcreteHandleBinding]:
97
+ return self._get_pos_port_args_by_direction(PortDeclarationDirection.Inout)
249
98
 
250
99
  @property
251
- def pos_operand_args(self) -> Dict[str, "QuantumOperand"]:
252
- return dict(
253
- zip(
254
- self.func_decl.operand_declarations.keys(),
255
- (
256
- param
257
- for param in self.positional_args
258
- if not isinstance(param, (Expression, HandleBinding))
259
- ),
100
+ def inouts(self) -> Sequence[HandleBinding]:
101
+ return [
102
+ handle
103
+ for _, _, handle in self._get_handles_by_direction(
104
+ PortDeclarationDirection.Inout
260
105
  )
261
- )
106
+ ]
262
107
 
263
108
  @property
264
- def pos_port_args(self) -> Dict[str, HandleBinding]:
265
- return dict(
266
- zip(
267
- self.func_decl.port_declarations.keys(),
268
- (
269
- param
270
- for param in self.positional_args
271
- if isinstance(param, HandleBinding)
272
- ),
109
+ def readable_inouts(self) -> Sequence[HandleMetadata]:
110
+ return [
111
+ HandleMetadata(
112
+ handle=handle,
113
+ readable_location=self._get_readable_location(param_idx, param),
273
114
  )
274
- )
275
-
276
- def _update_pos_port_params(self) -> None:
277
- for name, port_decl in self.func_decl.port_declarations.items():
278
- if port_decl.direction == PortDeclarationDirection.Input:
279
- self.inputs[name] = self.pos_port_args[name]
280
- elif port_decl.direction == PortDeclarationDirection.Output:
281
- self.outputs[name] = self.pos_port_args[name]
282
- else:
283
- self.inouts[name] = self.pos_port_args[name]
284
-
285
- def _reduce_positional_args_to_keywords(self) -> None:
286
- self.params.update(self.pos_param_args)
287
- self.operands.update(self.pos_operand_args)
288
- self._update_pos_port_params()
289
-
290
- def resolve_function_decl(
291
- self,
292
- function_dict: Mapping[str, QuantumFunctionDeclaration],
293
- check_operands: bool,
294
- ) -> None:
295
- if self._func_decl is None:
296
- func_decl = function_dict.get(self.func_name)
297
- if func_decl is None:
298
- raise ClassiqValueError(
299
- f"Error resolving function {self.func_name}, the function is not found in included library."
300
- )
301
- self.set_func_decl(func_decl)
302
-
303
- if self.positional_args:
304
- self._reduce_positional_args_to_keywords()
305
-
306
- _check_params_against_declaration(
307
- set(self.params.keys()),
308
- set(self.func_decl.param_decls.keys()),
309
- self.func_decl.name,
310
- )
311
- _check_ports_against_declaration(self, self.func_decl)
312
- _check_params_against_declaration(
313
- set(self.operands.keys()),
314
- set(self.func_decl.operand_declarations.keys()),
315
- self.func_name,
316
- )
317
- if check_operands:
318
- _check_operands_against_declaration(self, self.func_decl, function_dict)
319
-
320
- for name, op in self.operands.items():
321
- op_decl = self.func_decl.operand_declarations[name]
322
- for qlambda in get_lambda_defs(op):
323
- if isinstance(qlambda, QuantumLambdaFunction):
324
- qlambda.set_op_decl(op_decl)
115
+ for param_idx, param, handle in self._get_handles_by_direction(
116
+ PortDeclarationDirection.Inout
117
+ )
118
+ ]
325
119
 
326
120
  @property
327
- def operator_synthesis_data(self) -> OperatorSynthesisData:
328
- return self._operator_synthesis_data
329
-
330
- def set_operator_synthesis_data(
331
- self, operator_synthesis_data: OperatorSynthesisData
332
- ) -> None:
333
- self._operator_synthesis_data = operator_synthesis_data
334
-
335
- @staticmethod
336
- def _has_repetitions(name_list: Sequence[str]) -> bool:
337
- return len(set(name_list)) < len(name_list)
338
-
339
- @pydantic.root_validator()
340
- def validate_handles(cls, values: Dict[str, Any]) -> Dict[str, Any]:
341
- inputs = values.get("inputs", dict())
342
- outputs = values.get("outputs", dict())
343
- inouts = values.get("inouts", dict())
344
-
345
- _validate_no_duplicated_ports(inputs, outputs, inouts)
346
- _validate_no_duplicated_handles(inputs, outputs, inouts)
347
- _validate_no_mixing_sliced_and_whole_handles(inouts)
348
-
349
- return values
350
-
351
-
352
- ConcreteQuantumStatement = Union[
353
- QuantumFunctionCall,
354
- ArithmeticOperation,
355
- AmplitudeLoadingOperation,
356
- VariableDeclarationStatement,
357
- BindOperation,
358
- NumericReinterpretationOperation,
359
- InplaceBinaryOperation,
360
- QuantumIfOperation,
361
- ]
362
-
363
-
364
- class QuantumLambdaFunction(BaseModel):
365
- """
366
- The definition of an anonymous function passed as operand to higher-level functions
367
- """
368
-
369
- rename_params: Dict[str, str] = pydantic.Field(
370
- default_factory=dict,
371
- description="Mapping of the declared param to the actual variable name used ",
372
- )
373
-
374
- body: List[ConcreteQuantumStatement] = pydantic.Field(
375
- description="A list of function calls passed to the operator"
376
- )
377
-
378
- _func_decl: Optional[QuantumOperandDeclaration] = pydantic.PrivateAttr(default=None)
121
+ def wiring_outputs(self) -> Mapping[str, HandleBinding]:
122
+ return self._get_pos_port_args_by_direction(PortDeclarationDirection.Output)
379
123
 
380
124
  @property
381
- def func_decl(self) -> Optional[QuantumOperandDeclaration]:
382
- return self._func_decl
383
-
384
- def set_op_decl(self, fd: QuantumOperandDeclaration) -> None:
385
- self._func_decl = fd
386
-
387
-
388
- class LambdaListComprehension(BaseModel):
389
- """
390
- Specification of a list of lambda functions iteratively
391
- """
392
-
393
- count: Expression = pydantic.Field(
394
- description="The number of lambda functions in the list"
395
- )
396
-
397
- index_var: str = pydantic.Field(
398
- description="The name of the integer variable holding the iteration index"
399
- )
400
-
401
- func: QuantumLambdaFunction = pydantic.Field(
402
- description="A lambda function definition replicated for index values 0 to count-1"
403
- )
404
-
405
-
406
- QuantumCallable = Union[str, QuantumLambdaFunction]
407
- QuantumOperand = Union[QuantumCallable, List[QuantumCallable], LambdaListComprehension]
408
-
409
- QuantumFunctionCall.update_forward_refs()
410
- QuantumIfOperation.update_forward_refs(QuantumOperand=QuantumOperand)
411
-
412
-
413
- def get_lambda_defs(operand: QuantumOperand) -> List[QuantumCallable]:
414
- if isinstance(operand, list):
415
- return operand
416
- elif isinstance(operand, LambdaListComprehension):
417
- return [operand.func]
418
- else:
419
- return [operand]
420
-
421
-
422
- def _check_ports_against_declaration(
423
- call: QuantumFunctionCall, decl: QuantumFunctionDeclaration
424
- ) -> None:
425
- call_input_names = set(call.inputs.keys())
426
-
427
- _check_params_against_declaration(
428
- call_input_names,
429
- decl.ports_by_declaration_direction(PortDeclarationDirection.Input),
430
- call.func_name,
431
- )
432
-
433
- call_output_names = set(call.outputs.keys())
434
-
435
- _check_params_against_declaration(
436
- call_output_names,
437
- decl.ports_by_declaration_direction(PortDeclarationDirection.Output),
438
- call.func_name,
439
- )
440
-
441
- inout_params = set(call.inouts.keys())
442
-
443
- _check_params_against_declaration(
444
- inout_params,
445
- decl.ports_by_declaration_direction(PortDeclarationDirection.Inout),
446
- call.func_name,
447
- )
448
-
449
-
450
- def _check_operand_against_declaration(
451
- call: QuantumFunctionCall,
452
- operand_decl: QuantumOperandDeclaration,
453
- operand_argument: QuantumOperand,
454
- function_dict: Mapping[str, QuantumFunctionDeclaration],
455
- in_list: bool = False,
456
- ) -> None:
457
- if isinstance(operand_argument, list):
458
- if in_list:
459
- raise ClassiqValueError(
460
- f"{str(operand_argument)!r} argument to {call.func_decl.name!r} is not "
461
- f"a valid operand. Nested operand lists are not permitted"
125
+ def outputs(self) -> Sequence[HandleBinding]:
126
+ return [
127
+ handle
128
+ for _, _, handle in self._get_handles_by_direction(
129
+ PortDeclarationDirection.Output
462
130
  )
463
- for arg in operand_argument:
464
- _check_operand_against_declaration(
465
- call, operand_decl, arg, function_dict, in_list=True
131
+ ]
132
+
133
+ @property
134
+ def readable_outputs(self) -> Sequence[HandleMetadata]:
135
+ return [
136
+ HandleMetadata(
137
+ handle=handle,
138
+ readable_location=self._get_readable_location(param_idx, param),
466
139
  )
467
- return
468
- operand_arg_decl: QuantumFunctionDeclaration
469
- if isinstance(operand_argument, str):
470
- if operand_argument not in function_dict:
471
- raise ClassiqValueError(
472
- f"{operand_argument!r} argument to {call.func_decl.name!r} is not a "
473
- f"registered function"
140
+ for param_idx, param, handle in self._get_handles_by_direction(
141
+ PortDeclarationDirection.Output
474
142
  )
475
- operand_arg_decl = function_dict[operand_argument]
476
- elif isinstance(operand_argument, QuantumLambdaFunction):
477
- if operand_argument.func_decl is None:
478
- return
479
- operand_arg_decl = operand_argument.func_decl
480
- elif isinstance(operand_argument, LambdaListComprehension):
481
- if operand_argument.func.func_decl is None:
482
- return
483
- operand_arg_decl = operand_argument.func.func_decl
484
- else:
485
- raise ClassiqValueError(
486
- f"{str(operand_argument)!r} argument to {call.func_decl.name!r} is not a "
487
- f"valid operand"
488
- )
489
- num_arg_parameters = len(operand_arg_decl.get_positional_arg_decls())
490
- num_decl_parameters = len(operand_decl.get_positional_arg_decls())
491
- if num_arg_parameters != num_decl_parameters:
492
- raise ClassiqValueError(
493
- f"Signature of argument {operand_argument!r} to {call.func_decl.name!r} "
494
- f"does not match the signature of parameter {operand_decl.name!r}. "
495
- f"{operand_decl.name!r} accepts {num_decl_parameters} parameters but "
496
- f"{operand_argument!r} accepts {num_arg_parameters} parameters"
497
- )
143
+ ]
498
144
 
145
+ @property
146
+ def params(self) -> list[Expression]:
147
+ return [
148
+ param for param in self.positional_args if isinstance(param, Expression)
149
+ ]
499
150
 
500
- def _check_operands_against_declaration(
501
- call: QuantumFunctionCall,
502
- decl: QuantumFunctionDeclaration,
503
- function_dict: Mapping[str, QuantumFunctionDeclaration],
504
- ) -> None:
505
- for operand_parameter, operand_argument in call.operands.items():
506
- _check_operand_against_declaration(
507
- call,
508
- decl.operand_declarations[operand_parameter],
509
- operand_argument,
510
- function_dict,
511
- )
151
+ @property
152
+ def params_dict(self) -> dict[str, Expression]:
153
+ return dict(zip(self.func_decl.param_names, self.params))
512
154
 
155
+ @property
156
+ def operands(self) -> list["QuantumOperand"]:
157
+ return [
158
+ param
159
+ for param in self.positional_args
160
+ if not isinstance(param, (Expression, HandleBinding))
161
+ ]
513
162
 
514
- def _check_params_against_declaration(
515
- call_params: Set[str],
516
- param_decls: Set[str],
517
- callee_name: str,
518
- ) -> None:
519
- unknown_params = call_params - param_decls
520
- if any(re.match(r"arg\d+", param) for param in unknown_params):
521
- error_msg = (
522
- f"Unsupported passing of named function {callee_name!r} as an operand."
523
- "\nSuggestion: replace the named function with lambda function."
524
- )
525
- else:
526
- error_msg = f"Unknown parameters {unknown_params} in call to {callee_name!r}."
527
- if unknown_params:
528
- raise ClassiqValueError(error_msg)
163
+ @property
164
+ def ports(self) -> list[HandleBinding]:
165
+ return [
166
+ param for param in self.positional_args if isinstance(param, HandleBinding)
167
+ ]
168
+
169
+ def _get_handles_by_direction(
170
+ self, direction: PortDeclarationDirection
171
+ ) -> list[tuple[int, AnonPortDeclaration, HandleBinding]]:
172
+ return [
173
+ (idx, port_decl, handle)
174
+ for idx, port_decl, handle in self._get_handles_with_declarations()
175
+ if direction == port_decl.direction
176
+ ]
177
+
178
+ def _get_pos_port_args_by_direction(
179
+ self, direction: PortDeclarationDirection
180
+ ) -> dict[str, HandleBinding]:
181
+ # This is a hack for handles to wires reduction tests,
182
+ # that initialize function definitions or calls not in the scope of a model,
183
+ # so there is no function resolution annotation.
184
+ if self._func_decl is None:
185
+ return dict()
186
+ return {
187
+ port_decl.get_name(): handle
188
+ for _, port_decl, handle in self._get_handles_with_declarations()
189
+ if direction == port_decl.direction
190
+ }
191
+
192
+ def _get_handles_with_declarations(
193
+ self,
194
+ ) -> Iterable[tuple[int, AnonPortDeclaration, HandleBinding]]:
195
+ return [
196
+ (idx, port, handle)
197
+ for idx, (port, handle) in enumerate(
198
+ zip(
199
+ (port_decl for port_decl in self.func_decl.port_declarations),
200
+ (
201
+ param
202
+ for param in self.positional_args
203
+ if isinstance(param, HandleBinding)
204
+ ),
205
+ )
206
+ )
207
+ ]
529
208
 
530
- missing_params = param_decls - call_params
531
- if missing_params:
532
- raise ClassiqValueError(
533
- f"Missing parameters {missing_params} in call to {callee_name!r}."
209
+ def _get_readable_location(
210
+ self, param_index: int, param_decl: AnonPortDeclaration
211
+ ) -> str:
212
+ param_name = (
213
+ repr(param_decl.name) if param_decl.name is not None else f"#{param_index}"
214
+ )
215
+ param_text = (
216
+ f" for parameter {param_name}" if len(self.positional_args) > 1 else ""
534
217
  )
218
+ return f"as an argument{param_text} of function {self.func_name!r}"