classiq 0.38.0__py3-none-any.whl → 0.65.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. classiq/__init__.py +47 -32
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
  3. classiq/_internals/api_wrapper.py +235 -97
  4. classiq/_internals/async_utils.py +1 -3
  5. classiq/_internals/authentication/auth0.py +26 -10
  6. classiq/_internals/authentication/authentication.py +11 -0
  7. classiq/_internals/authentication/device.py +10 -5
  8. classiq/_internals/authentication/password_manager.py +18 -6
  9. classiq/_internals/authentication/token_manager.py +10 -5
  10. classiq/_internals/client.py +94 -33
  11. classiq/_internals/config.py +3 -4
  12. classiq/_internals/host_checker.py +38 -15
  13. classiq/_internals/jobs.py +60 -57
  14. classiq/_internals/type_validation.py +9 -9
  15. classiq/analyzer/__init__.py +1 -3
  16. classiq/analyzer/analyzer.py +24 -19
  17. classiq/analyzer/analyzer_utilities.py +10 -10
  18. classiq/analyzer/rb.py +15 -15
  19. classiq/analyzer/show_interactive_hack.py +27 -4
  20. classiq/analyzer/url_utils.py +2 -3
  21. classiq/applications/__init__.py +3 -12
  22. classiq/applications/chemistry/__init__.py +14 -10
  23. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  24. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +165 -158
  25. classiq/applications/chemistry/ground_state_problem.py +1 -1
  26. classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +4 -1
  27. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
  28. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +1 -1
  29. classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +51 -15
  30. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +12 -12
  31. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +8 -6
  32. classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +7 -11
  33. classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +67 -40
  34. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
  35. classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
  36. classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +2 -2
  37. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +15 -20
  38. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +14 -15
  39. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +11 -15
  40. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +1 -2
  41. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
  42. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +2 -3
  43. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +5 -8
  44. classiq/applications/combinatorial_optimization/__init__.py +20 -6
  45. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  46. classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +35 -33
  47. classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
  48. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  49. classiq/applications/finance/__init__.py +4 -5
  50. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +48 -42
  51. classiq/applications/grover/__init__.py +9 -0
  52. classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +52 -51
  53. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  54. classiq/applications/libraries/qmci_library.py +22 -0
  55. classiq/applications/qnn/__init__.py +2 -4
  56. classiq/applications/qnn/circuit_utils.py +6 -6
  57. classiq/applications/qnn/datasets/__init__.py +9 -11
  58. classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
  59. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  60. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  61. classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
  62. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  63. classiq/applications/qnn/qlayer.py +30 -10
  64. classiq/applications/qnn/torch_utils.py +4 -3
  65. classiq/applications/qnn/types.py +5 -5
  66. classiq/applications/qsvm/__init__.py +6 -4
  67. classiq/applications/qsvm/qsvm.py +3 -6
  68. classiq/applications/qsvm/qsvm_data_generation.py +3 -3
  69. classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
  70. classiq/execution/__init__.py +8 -3
  71. classiq/execution/all_hardware_devices.py +11 -0
  72. classiq/execution/execution_session.py +400 -0
  73. classiq/execution/iqcc.py +63 -0
  74. classiq/execution/jobs.py +197 -25
  75. classiq/execution/qnn.py +79 -0
  76. classiq/executor.py +20 -115
  77. classiq/interface/_version.py +1 -1
  78. classiq/interface/analyzer/analysis_params.py +43 -13
  79. classiq/interface/analyzer/cytoscape_graph.py +15 -9
  80. classiq/interface/analyzer/result.py +28 -32
  81. classiq/interface/applications/qsvm.py +20 -29
  82. classiq/interface/ast_node.py +16 -0
  83. classiq/interface/backend/backend_preferences.py +390 -121
  84. classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
  85. classiq/interface/backend/pydantic_backend.py +25 -22
  86. classiq/interface/backend/quantum_backend_providers.py +69 -16
  87. classiq/interface/chemistry/fermionic_operator.py +30 -21
  88. classiq/interface/chemistry/ground_state_problem.py +28 -25
  89. classiq/interface/chemistry/molecule.py +14 -10
  90. classiq/interface/chemistry/operator.py +64 -231
  91. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  92. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
  93. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  94. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  95. classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
  96. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  97. classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
  98. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +8 -9
  99. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  100. classiq/interface/combinatorial_optimization/result.py +1 -3
  101. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  102. classiq/interface/debug_info/debug_info.py +86 -0
  103. classiq/{exceptions.py → interface/exceptions.py} +37 -9
  104. classiq/interface/execution/iqcc.py +19 -0
  105. classiq/interface/execution/jobs.py +15 -12
  106. classiq/interface/execution/primitives.py +18 -0
  107. classiq/interface/executor/constants.py +1 -0
  108. classiq/interface/executor/execution_preferences.py +26 -114
  109. classiq/interface/executor/execution_request.py +24 -46
  110. classiq/interface/executor/execution_result.py +30 -8
  111. classiq/interface/executor/iqae_result.py +4 -6
  112. classiq/interface/executor/optimizer_preferences.py +17 -14
  113. classiq/interface/executor/quantum_code.py +28 -24
  114. classiq/interface/executor/quantum_instruction_set.py +2 -2
  115. classiq/interface/executor/register_initialization.py +11 -14
  116. classiq/interface/executor/result.py +83 -56
  117. classiq/interface/executor/vqe_result.py +10 -10
  118. classiq/interface/finance/function_input.py +35 -25
  119. classiq/interface/finance/gaussian_model_input.py +5 -5
  120. classiq/interface/finance/log_normal_model_input.py +4 -4
  121. classiq/interface/finance/model_input.py +4 -4
  122. classiq/interface/generator/adjacency.py +1 -3
  123. classiq/interface/generator/amplitude_loading.py +22 -12
  124. classiq/interface/generator/ansatz_library.py +5 -5
  125. classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
  126. classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
  127. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
  128. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  129. classiq/interface/generator/application_apis/finance_declarations.py +48 -69
  130. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
  131. classiq/interface/generator/arith/argument_utils.py +46 -5
  132. classiq/interface/generator/arith/arithmetic.py +35 -16
  133. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +6 -7
  134. classiq/interface/generator/arith/arithmetic_expression_abc.py +66 -25
  135. classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -11
  136. classiq/interface/generator/arith/arithmetic_expression_validator.py +47 -43
  137. classiq/interface/generator/arith/arithmetic_operations.py +14 -6
  138. classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
  139. classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
  140. classiq/interface/generator/arith/ast_node_rewrite.py +3 -2
  141. classiq/interface/generator/arith/binary_ops.py +218 -130
  142. classiq/interface/generator/arith/endianness.py +1 -1
  143. classiq/interface/generator/arith/extremum_operations.py +96 -25
  144. classiq/interface/generator/arith/logical_ops.py +14 -12
  145. classiq/interface/generator/arith/number_utils.py +12 -6
  146. classiq/interface/generator/arith/register_user_input.py +60 -37
  147. classiq/interface/generator/arith/unary_ops.py +49 -29
  148. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  149. classiq/interface/generator/builtin_api_builder.py +2 -9
  150. classiq/interface/generator/chemistry_function_params.py +3 -3
  151. classiq/interface/generator/circuit_code/circuit_code.py +7 -7
  152. classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
  153. classiq/interface/generator/commuting_pauli_exponentiation.py +7 -7
  154. classiq/interface/generator/compiler_keywords.py +5 -1
  155. classiq/interface/generator/complex_type.py +13 -18
  156. classiq/interface/generator/constant.py +3 -4
  157. classiq/interface/generator/control_state.py +34 -29
  158. classiq/interface/generator/copy.py +47 -0
  159. classiq/interface/generator/custom_ansatz.py +2 -5
  160. classiq/interface/generator/distance.py +3 -5
  161. classiq/interface/generator/excitations.py +3 -2
  162. classiq/interface/generator/expressions/atomic_expression_functions.py +21 -5
  163. classiq/interface/generator/expressions/enums/__init__.py +0 -10
  164. classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
  165. classiq/interface/generator/expressions/evaluated_expression.py +5 -5
  166. classiq/interface/generator/expressions/expression.py +26 -14
  167. classiq/interface/generator/expressions/expression_constants.py +9 -3
  168. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  169. classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
  170. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +34 -8
  171. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
  172. classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
  173. classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
  174. classiq/interface/generator/expressions/sympy_supported_expressions.py +19 -11
  175. classiq/interface/generator/finance.py +2 -2
  176. classiq/interface/generator/function_param_library.py +6 -6
  177. classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
  178. classiq/interface/generator/function_params.py +36 -64
  179. classiq/interface/generator/functions/__init__.py +0 -22
  180. classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
  181. classiq/interface/generator/functions/classical_function_declaration.py +18 -9
  182. classiq/interface/generator/functions/classical_type.py +47 -166
  183. classiq/interface/generator/functions/concrete_types.py +55 -0
  184. classiq/interface/generator/functions/function_declaration.py +13 -14
  185. classiq/interface/generator/functions/port_declaration.py +1 -13
  186. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  187. classiq/interface/generator/functions/type_name.py +90 -0
  188. classiq/interface/generator/generated_circuit_data.py +153 -20
  189. classiq/interface/generator/grover_diffuser.py +32 -25
  190. classiq/interface/generator/grover_operator.py +34 -25
  191. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
  192. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  193. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +9 -9
  194. classiq/interface/generator/hardware/hardware_data.py +72 -34
  195. classiq/interface/generator/hardware_efficient_ansatz.py +20 -16
  196. classiq/interface/generator/hartree_fock.py +13 -5
  197. classiq/interface/generator/identity.py +10 -6
  198. classiq/interface/generator/linear_pauli_rotations.py +32 -20
  199. classiq/interface/generator/mcmt_method.py +1 -1
  200. classiq/interface/generator/mcu.py +17 -15
  201. classiq/interface/generator/mcx.py +24 -17
  202. classiq/interface/generator/model/__init__.py +2 -5
  203. classiq/interface/generator/model/constraints.py +26 -8
  204. classiq/interface/generator/model/model.py +27 -190
  205. classiq/interface/generator/model/preferences/preferences.py +115 -41
  206. classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +14 -17
  207. classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
  208. classiq/interface/generator/oracles/custom_oracle.py +15 -13
  209. classiq/interface/generator/oracles/oracle_abc.py +7 -7
  210. classiq/interface/generator/partitioned_register.py +7 -7
  211. classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
  212. classiq/interface/generator/preferences/optimization.py +1 -2
  213. classiq/interface/generator/qpe.py +41 -30
  214. classiq/interface/generator/qsvm.py +9 -10
  215. classiq/interface/generator/quantum_function_call.py +88 -73
  216. classiq/interface/generator/quantum_program.py +41 -24
  217. classiq/interface/generator/range_types.py +11 -12
  218. classiq/interface/generator/register_role.py +18 -6
  219. classiq/interface/generator/slice_parsing_utils.py +5 -5
  220. classiq/interface/generator/standard_gates/controlled_standard_gates.py +30 -39
  221. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  222. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  223. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  224. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  225. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  226. classiq/interface/generator/state_preparation/distributions.py +16 -15
  227. classiq/interface/generator/state_preparation/metrics.py +4 -7
  228. classiq/interface/generator/state_preparation/state_preparation.py +25 -20
  229. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  230. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
  231. classiq/interface/generator/transpiler_basis_gates.py +7 -3
  232. classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
  233. classiq/interface/generator/types/compilation_metadata.py +6 -0
  234. classiq/interface/generator/types/enum_declaration.py +54 -0
  235. classiq/interface/generator/types/qstruct_declaration.py +18 -0
  236. classiq/interface/generator/types/struct_declaration.py +7 -11
  237. classiq/interface/generator/ucc.py +5 -4
  238. classiq/interface/generator/unitary_gate.py +5 -5
  239. classiq/interface/generator/user_defined_function_params.py +4 -1
  240. classiq/interface/generator/validations/flow_graph.py +7 -7
  241. classiq/interface/generator/validations/validator_functions.py +4 -4
  242. classiq/interface/generator/visitor.py +23 -16
  243. classiq/interface/hardware.py +29 -8
  244. classiq/interface/helpers/classproperty.py +8 -0
  245. classiq/interface/helpers/custom_encoders.py +2 -2
  246. classiq/interface/helpers/custom_pydantic_types.py +40 -50
  247. classiq/interface/helpers/datastructures.py +26 -0
  248. classiq/interface/helpers/hashable_mixin.py +3 -2
  249. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  250. classiq/interface/helpers/pydantic_model_helpers.py +7 -5
  251. classiq/interface/helpers/validation_helpers.py +3 -20
  252. classiq/interface/helpers/versioned_model.py +1 -4
  253. classiq/interface/ide/ide_data.py +16 -20
  254. classiq/interface/ide/visual_model.py +130 -0
  255. classiq/interface/interface_version.py +1 -0
  256. classiq/interface/jobs.py +29 -69
  257. classiq/interface/model/allocate.py +16 -0
  258. classiq/interface/model/bind_operation.py +32 -9
  259. classiq/interface/model/classical_if.py +15 -0
  260. classiq/interface/model/classical_parameter_declaration.py +33 -3
  261. classiq/interface/model/control.py +45 -0
  262. classiq/interface/model/handle_binding.py +298 -20
  263. classiq/interface/model/inplace_binary_operation.py +29 -24
  264. classiq/interface/model/invert.py +12 -0
  265. classiq/interface/model/model.py +69 -61
  266. classiq/interface/model/native_function_definition.py +17 -20
  267. classiq/interface/model/parameter.py +13 -0
  268. classiq/interface/model/phase_operation.py +11 -0
  269. classiq/interface/model/port_declaration.py +27 -9
  270. classiq/interface/model/power.py +14 -0
  271. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +30 -18
  272. classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
  273. classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
  274. classiq/interface/model/quantum_function_call.py +141 -343
  275. classiq/interface/model/quantum_function_declaration.py +190 -157
  276. classiq/interface/model/quantum_lambda_function.py +33 -32
  277. classiq/interface/model/quantum_statement.py +71 -12
  278. classiq/interface/model/quantum_type.py +177 -40
  279. classiq/interface/model/quantum_variable_declaration.py +3 -25
  280. classiq/interface/model/repeat.py +15 -0
  281. classiq/interface/model/statement_block.py +40 -14
  282. classiq/interface/model/validation_handle.py +13 -6
  283. classiq/interface/model/variable_declaration_statement.py +3 -1
  284. classiq/interface/model/within_apply_operation.py +7 -5
  285. classiq/interface/server/global_versions.py +6 -7
  286. classiq/interface/server/routes.py +17 -21
  287. classiq/interface/source_reference.py +59 -0
  288. classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
  289. classiq/model_expansions/capturing/__init__.py +0 -0
  290. classiq/model_expansions/capturing/captured_vars.py +435 -0
  291. classiq/model_expansions/capturing/mangling_utils.py +56 -0
  292. classiq/model_expansions/closure.py +171 -0
  293. classiq/model_expansions/debug_flag.py +3 -0
  294. classiq/model_expansions/evaluators/__init__.py +0 -0
  295. classiq/model_expansions/evaluators/arg_type_match.py +158 -0
  296. classiq/model_expansions/evaluators/argument_types.py +42 -0
  297. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  298. classiq/model_expansions/evaluators/control.py +144 -0
  299. classiq/model_expansions/evaluators/parameter_types.py +226 -0
  300. classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
  301. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  302. classiq/model_expansions/expression_evaluator.py +135 -0
  303. classiq/model_expansions/expression_renamer.py +76 -0
  304. classiq/model_expansions/function_builder.py +247 -0
  305. classiq/model_expansions/generative_functions.py +158 -0
  306. classiq/model_expansions/interpreters/__init__.py +0 -0
  307. classiq/model_expansions/interpreters/base_interpreter.py +263 -0
  308. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
  309. classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
  310. classiq/model_expansions/model_tables.py +18 -0
  311. classiq/model_expansions/quantum_operations/__init__.py +9 -0
  312. classiq/model_expansions/quantum_operations/bind.py +60 -0
  313. classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
  314. classiq/model_expansions/quantum_operations/classicalif.py +53 -0
  315. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
  316. classiq/model_expansions/quantum_operations/emitter.py +181 -0
  317. classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
  318. classiq/model_expansions/quantum_operations/repeat.py +56 -0
  319. classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
  320. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  321. classiq/model_expansions/scope.py +240 -0
  322. classiq/model_expansions/scope_initialization.py +150 -0
  323. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  324. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  325. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
  326. classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
  327. classiq/model_expansions/transformers/__init__.py +0 -0
  328. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  329. classiq/model_expansions/transformers/var_splitter.py +299 -0
  330. classiq/model_expansions/utils/__init__.py +0 -0
  331. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  332. classiq/model_expansions/utils/handles_collector.py +33 -0
  333. classiq/model_expansions/visitors/__init__.py +0 -0
  334. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  335. classiq/model_expansions/visitors/variable_references.py +144 -0
  336. classiq/open_library/__init__.py +4 -0
  337. classiq/open_library/functions/__init__.py +130 -0
  338. classiq/open_library/functions/amplitude_estimation.py +30 -0
  339. classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
  340. classiq/open_library/functions/grover.py +157 -0
  341. classiq/open_library/functions/hea.py +115 -0
  342. classiq/open_library/functions/linear_pauli_rotation.py +82 -0
  343. classiq/open_library/functions/modular_exponentiation.py +201 -0
  344. classiq/open_library/functions/qaoa_penalty.py +117 -0
  345. classiq/open_library/functions/qft_functions.py +54 -0
  346. classiq/open_library/functions/qpe.py +46 -0
  347. classiq/open_library/functions/qsvt.py +331 -0
  348. classiq/open_library/functions/state_preparation.py +301 -0
  349. classiq/open_library/functions/swap_test.py +27 -0
  350. classiq/open_library/functions/utility_functions.py +81 -0
  351. classiq/open_library/functions/variational.py +52 -0
  352. classiq/qmod/__init__.py +10 -10
  353. classiq/qmod/builtins/__init__.py +19 -2
  354. classiq/qmod/builtins/classical_execution_primitives.py +36 -14
  355. classiq/qmod/builtins/classical_functions.py +39 -43
  356. classiq/qmod/builtins/constants.py +10 -0
  357. classiq/qmod/builtins/enums.py +208 -0
  358. classiq/qmod/builtins/functions/__init__.py +137 -0
  359. classiq/qmod/builtins/functions/allocation.py +150 -0
  360. classiq/qmod/builtins/functions/arithmetic.py +55 -0
  361. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  362. classiq/qmod/builtins/functions/chemistry.py +91 -0
  363. classiq/qmod/builtins/functions/exponentiation.py +105 -0
  364. classiq/qmod/builtins/functions/finance.py +34 -0
  365. classiq/qmod/builtins/functions/operators.py +16 -0
  366. classiq/qmod/builtins/functions/qsvm.py +24 -0
  367. classiq/qmod/builtins/functions/standard_gates.py +651 -0
  368. classiq/qmod/builtins/operations.py +373 -40
  369. classiq/qmod/builtins/structs.py +103 -80
  370. classiq/qmod/cfunc.py +2 -2
  371. classiq/qmod/classical_function.py +4 -8
  372. classiq/qmod/cparam.py +64 -0
  373. classiq/qmod/create_model_function.py +56 -0
  374. classiq/qmod/declaration_inferrer.py +143 -101
  375. classiq/qmod/expression_query.py +20 -4
  376. classiq/qmod/generative.py +42 -0
  377. classiq/qmod/model_state_container.py +18 -6
  378. classiq/qmod/native/__init__.py +7 -0
  379. classiq/qmod/native/expression_to_qmod.py +16 -11
  380. classiq/qmod/native/pretty_printer.py +187 -97
  381. classiq/qmod/pretty_print/__init__.py +7 -0
  382. classiq/qmod/pretty_print/expression_to_python.py +222 -0
  383. classiq/qmod/pretty_print/pretty_printer.py +572 -0
  384. classiq/qmod/python_classical_type.py +67 -0
  385. classiq/qmod/qfunc.py +60 -8
  386. classiq/qmod/qmod_constant.py +93 -26
  387. classiq/qmod/qmod_parameter.py +68 -59
  388. classiq/qmod/qmod_variable.py +468 -155
  389. classiq/qmod/quantum_callable.py +17 -7
  390. classiq/qmod/quantum_expandable.py +269 -96
  391. classiq/qmod/quantum_function.py +196 -41
  392. classiq/qmod/semantics/__init__.py +0 -0
  393. classiq/qmod/semantics/annotation/__init__.py +0 -0
  394. classiq/qmod/semantics/annotation/call_annotation.py +92 -0
  395. classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
  396. classiq/qmod/semantics/error_manager.py +88 -0
  397. classiq/qmod/semantics/lambdas.py +25 -0
  398. classiq/qmod/semantics/static_semantics_visitor.py +384 -0
  399. classiq/qmod/semantics/validation/__init__.py +0 -0
  400. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  401. classiq/qmod/semantics/validation/func_call_validation.py +99 -0
  402. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  403. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  404. classiq/qmod/semantics/validation/main_validation.py +33 -0
  405. classiq/qmod/semantics/validation/types_validation.py +128 -0
  406. classiq/qmod/symbolic.py +147 -123
  407. classiq/qmod/symbolic_expr.py +27 -12
  408. classiq/qmod/symbolic_type.py +2 -5
  409. classiq/qmod/type_attribute_remover.py +32 -0
  410. classiq/qmod/utilities.py +98 -4
  411. classiq/qmod/write_qmod.py +17 -3
  412. classiq/synthesis.py +210 -22
  413. {classiq-0.38.0.dist-info → classiq-0.65.4.dist-info}/METADATA +16 -9
  414. classiq-0.65.4.dist-info/RECORD +521 -0
  415. classiq/_internals/_qfunc_ext.py +0 -6
  416. classiq/applications/benchmarking/__init__.py +0 -9
  417. classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
  418. classiq/applications/numpy_utils.py +0 -37
  419. classiq/applications_model_constructors/__init__.py +0 -25
  420. classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
  421. classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -65
  422. classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +0 -243
  423. classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
  424. classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
  425. classiq/builtin_functions/__init__.py +0 -43
  426. classiq/builtin_functions/amplitude_loading.py +0 -3
  427. classiq/builtin_functions/binary_ops.py +0 -1
  428. classiq/builtin_functions/exponentiation.py +0 -5
  429. classiq/builtin_functions/qpe.py +0 -4
  430. classiq/builtin_functions/qsvm.py +0 -7
  431. classiq/builtin_functions/range_types.py +0 -5
  432. classiq/builtin_functions/standard_gates.py +0 -1
  433. classiq/builtin_functions/state_preparation.py +0 -6
  434. classiq/builtin_functions/suzuki_trotter.py +0 -3
  435. classiq/interface/executor/aws_execution_cost.py +0 -73
  436. classiq/interface/executor/error_mitigation.py +0 -6
  437. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
  438. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
  439. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  440. classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
  441. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
  442. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  443. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  444. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  445. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  446. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
  447. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
  448. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -1229
  449. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
  450. classiq/interface/generator/functions/foreign_function_definition.py +0 -114
  451. classiq/interface/generator/functions/function_implementation.py +0 -107
  452. classiq/interface/generator/functions/native_function_definition.py +0 -155
  453. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  454. classiq/interface/generator/functions/register.py +0 -44
  455. classiq/interface/generator/functions/register_mapping_data.py +0 -106
  456. classiq/interface/generator/inequality_mixer.py +0 -51
  457. classiq/interface/generator/model/classical_main_validator.py +0 -106
  458. classiq/interface/generator/range_mixer.py +0 -56
  459. classiq/interface/generator/state_propagator.py +0 -74
  460. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  461. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
  462. classiq/interface/ide/show.py +0 -34
  463. classiq/interface/model/call_synthesis_data.py +0 -68
  464. classiq/interface/model/common_model_types.py +0 -23
  465. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  466. classiq/interface/model/quantum_if_operation.py +0 -94
  467. classiq/interface/model/resolvers/function_call_resolver.py +0 -43
  468. classiq/interface/model/validations/handle_validation_base.py +0 -55
  469. classiq/interface/model/validations/handles_validator.py +0 -156
  470. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  471. classiq/model/__init__.py +0 -14
  472. classiq/model/composite_function_generator.py +0 -33
  473. classiq/model/function_handler.py +0 -462
  474. classiq/model/logic_flow.py +0 -149
  475. classiq/model/logic_flow_change_handler.py +0 -71
  476. classiq/model/model.py +0 -229
  477. classiq/qmod/builtins/functions.py +0 -913
  478. classiq/qmod/qmod_struct.py +0 -37
  479. classiq/quantum_functions/__init__.py +0 -17
  480. classiq/quantum_functions/annotation_parser.py +0 -205
  481. classiq/quantum_functions/decorators.py +0 -22
  482. classiq/quantum_functions/function_library.py +0 -181
  483. classiq/quantum_functions/function_parser.py +0 -74
  484. classiq/quantum_functions/quantum_function.py +0 -236
  485. classiq-0.38.0.dist-info/RECORD +0 -454
  486. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
  487. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
  488. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
  489. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
  490. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
  491. /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  492. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  493. /classiq/{interface/generator/credit_risk_example → applications/hamiltonian}/__init__.py +0 -0
  494. /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
  495. /classiq/interface/{model/resolvers → debug_info}/__init__.py +0 -0
  496. /classiq/{_internals → interface}/enum_utils.py +0 -0
  497. /classiq/interface/{model/validations → generator/functions/builtins}/__init__.py +0 -0
  498. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → model_expansions/__init__.py} +0 -0
  499. {classiq-0.38.0.dist-info → classiq-0.65.4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,226 @@
1
+ from typing import Union
2
+
3
+ from classiq.interface.exceptions import (
4
+ ClassiqExpansionError,
5
+ ClassiqInternalExpansionError,
6
+ )
7
+ from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
8
+ from classiq.interface.generator.functions.port_declaration import (
9
+ PortDeclarationDirection,
10
+ )
11
+ from classiq.interface.generator.functions.type_name import (
12
+ TypeName,
13
+ )
14
+ from classiq.interface.model.port_declaration import PortDeclaration
15
+ from classiq.interface.model.quantum_function_declaration import (
16
+ PositionalArg,
17
+ QuantumOperandDeclaration,
18
+ )
19
+ from classiq.interface.model.quantum_type import (
20
+ QuantumBit,
21
+ QuantumBitvector,
22
+ QuantumNumeric,
23
+ QuantumType,
24
+ )
25
+
26
+ from classiq.model_expansions.closure import FunctionClosure
27
+ from classiq.model_expansions.evaluators.arg_type_match import check_type_match
28
+ from classiq.model_expansions.evaluators.classical_expression import (
29
+ evaluate_classical_expression,
30
+ )
31
+ from classiq.model_expansions.evaluators.quantum_type_utils import (
32
+ copy_type_information,
33
+ set_element_type,
34
+ set_fraction_digits,
35
+ set_is_signed,
36
+ set_length,
37
+ set_size,
38
+ )
39
+ from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
40
+
41
+
42
+ def evaluate_parameter_types_from_args(
43
+ closure: FunctionClosure, signature_scope: Scope, arguments: list[Evaluated]
44
+ ) -> list[PositionalArg]:
45
+ parameters = closure.positional_arg_declarations
46
+ function_name = closure.name
47
+ check_type_match(parameters, arguments, function_name)
48
+
49
+ for parameter, argument in zip(parameters, arguments):
50
+ _update_scope(parameter, argument, closure)
51
+
52
+ parameter_names = {parameter.name for parameter in parameters}
53
+ for parameter in parameters:
54
+ if isinstance(parameter, QuantumOperandDeclaration):
55
+ parameter_value = closure.scope[parameter.name].value
56
+ _update_operand_signature_environment(
57
+ parameter_value, parameter_names, closure
58
+ )
59
+
60
+ return [
61
+ _evaluate_type_from_arg(
62
+ parameter, argument, Scope(parent=closure.scope | signature_scope)
63
+ )
64
+ for parameter, argument in zip(parameters, arguments)
65
+ ]
66
+
67
+
68
+ def _update_scope(
69
+ parameter: PositionalArg, argument: Evaluated, closure: FunctionClosure
70
+ ) -> None:
71
+ if not isinstance(parameter, PortDeclaration):
72
+ closure.scope[parameter.name] = argument
73
+ return
74
+ if parameter.direction is PortDeclarationDirection.Output:
75
+ return
76
+ quantum_symbol = argument.as_type(QuantumSymbol)
77
+ if not quantum_symbol.quantum_type.has_size_in_bits:
78
+ raise ClassiqExpansionError(
79
+ f"Argument {str(quantum_symbol.emit())!r} to function {closure.name!r} "
80
+ f"is not initialized"
81
+ )
82
+ casted_argument = _cast(
83
+ parameter.quantum_type,
84
+ quantum_symbol,
85
+ parameter.name,
86
+ )
87
+ closure.scope[parameter.name] = Evaluated(
88
+ value=casted_argument, defining_function=closure
89
+ )
90
+
91
+
92
+ NestedFunctionClosureT = Union[FunctionClosure, list["NestedFunctionClosureT"]]
93
+
94
+
95
+ def _update_operand_signature_environment(
96
+ operand_val: NestedFunctionClosureT,
97
+ parameter_names: set[str],
98
+ closure: FunctionClosure,
99
+ ) -> None:
100
+ # We update the environment (parent) of the operand by adding closure.scope.data,
101
+ # which includes the parameters that appear in the function's signature only.
102
+ if isinstance(operand_val, list):
103
+ for operand in operand_val:
104
+ _update_operand_signature_environment(operand, parameter_names, closure)
105
+ return
106
+ if not isinstance(operand_val, FunctionClosure):
107
+ raise ClassiqInternalExpansionError
108
+ operand_val.signature_scope.update(
109
+ {
110
+ identifier: value
111
+ for identifier, value in closure.scope.data.items()
112
+ if identifier in parameter_names
113
+ }
114
+ )
115
+
116
+
117
+ def _cast(
118
+ quantum_type: QuantumType, quantum_symbol: QuantumSymbol, param_name: str
119
+ ) -> QuantumSymbol:
120
+ updated_quantum_type = quantum_type.model_copy()
121
+ _inject_quantum_arg_info_to_type(updated_quantum_type, quantum_symbol, param_name)
122
+ return QuantumSymbol(
123
+ handle=quantum_symbol.handle, quantum_type=updated_quantum_type
124
+ )
125
+
126
+
127
+ def _evaluate_type_from_arg(
128
+ parameter: PositionalArg, argument: Evaluated, inner_scope: Scope
129
+ ) -> PositionalArg:
130
+ if not isinstance(parameter, PortDeclaration):
131
+ return parameter
132
+
133
+ updated_quantum_type: QuantumType = evaluate_type_in_quantum_symbol(
134
+ parameter.quantum_type.model_copy(), inner_scope, parameter.name
135
+ )
136
+ if parameter.direction != PortDeclarationDirection.Output:
137
+ updated_quantum_type = _inject_quantum_arg_info_to_type(
138
+ updated_quantum_type, argument.as_type(QuantumSymbol), parameter.name
139
+ )
140
+ return parameter.model_copy(update={"quantum_type": updated_quantum_type})
141
+
142
+
143
+ def evaluate_type_in_quantum_symbol(
144
+ type_to_update: QuantumType, scope: Scope, param_name: str
145
+ ) -> ConcreteQuantumType:
146
+ if isinstance(type_to_update, QuantumBitvector):
147
+ return _evaluate_qarray_in_quantum_symbol(type_to_update, scope, param_name)
148
+ elif isinstance(type_to_update, QuantumNumeric):
149
+ return _evaluate_qnum_in_quantum_symbol(type_to_update, scope, param_name)
150
+ elif isinstance(type_to_update, TypeName):
151
+ return _evaluate_qstruct_in_quantum_symbol(type_to_update, scope, param_name)
152
+ else:
153
+ assert isinstance(type_to_update, QuantumBit)
154
+ return type_to_update
155
+
156
+
157
+ def _evaluate_qarray_in_quantum_symbol(
158
+ type_to_update: QuantumBitvector, scope: Scope, param_name: str
159
+ ) -> QuantumBitvector:
160
+ new_element_type = evaluate_type_in_quantum_symbol(
161
+ type_to_update.element_type, scope, param_name
162
+ )
163
+ set_element_type(type_to_update, new_element_type)
164
+ if type_to_update.length is not None:
165
+ new_length = evaluate_classical_expression(
166
+ type_to_update.length, scope
167
+ ).as_type(int)
168
+ set_length(type_to_update, new_length)
169
+ return type_to_update
170
+
171
+
172
+ def _evaluate_qnum_in_quantum_symbol(
173
+ type_to_update: QuantumNumeric, scope: Scope, param_name: str
174
+ ) -> QuantumNumeric:
175
+ if type_to_update.is_signed is not None:
176
+ new_is_sign = evaluate_classical_expression(
177
+ type_to_update.is_signed, scope
178
+ ).as_type(bool)
179
+ set_is_signed(type_to_update, new_is_sign, param_name)
180
+ if type_to_update.fraction_digits is not None:
181
+ new_fraction_digits = evaluate_classical_expression(
182
+ type_to_update.fraction_digits, scope
183
+ ).as_type(int)
184
+ set_fraction_digits(type_to_update, new_fraction_digits, param_name)
185
+ if type_to_update.size is not None:
186
+ new_size = evaluate_classical_expression(type_to_update.size, scope).as_type(
187
+ int
188
+ )
189
+ set_size(type_to_update, new_size, param_name)
190
+ return type_to_update
191
+
192
+
193
+ def _evaluate_qstruct_in_quantum_symbol(
194
+ type_to_update: TypeName, scope: Scope, param_name: str
195
+ ) -> TypeName:
196
+ new_fields = {
197
+ field_name: evaluate_type_in_quantum_symbol(field_type, scope, param_name)
198
+ for field_name, field_type in type_to_update.fields.items()
199
+ }
200
+ type_to_update.set_fields(new_fields)
201
+ return type_to_update
202
+
203
+
204
+ def evaluate_types_in_quantum_symbols(
205
+ symbols: list[QuantumSymbol], scope: Scope
206
+ ) -> list[QuantumSymbol]:
207
+ return [
208
+ QuantumSymbol(
209
+ handle=symbol.handle,
210
+ quantum_type=evaluate_type_in_quantum_symbol(
211
+ symbol.quantum_type, scope, str(symbol.handle)
212
+ ),
213
+ )
214
+ for symbol in symbols
215
+ ]
216
+
217
+
218
+ def _inject_quantum_arg_info_to_type(
219
+ parameter_type: QuantumType, quantum_symbol: QuantumSymbol, param_name: str
220
+ ) -> QuantumType:
221
+ copy_type_information(
222
+ quantum_symbol.quantum_type,
223
+ parameter_type,
224
+ param_name,
225
+ )
226
+ return parameter_type
@@ -0,0 +1,239 @@
1
+ from collections.abc import Sequence
2
+ from typing import Optional
3
+
4
+ from classiq.interface.exceptions import (
5
+ ClassiqExpansionError,
6
+ ClassiqInternalExpansionError,
7
+ )
8
+ from classiq.interface.generator.expressions.expression import Expression
9
+ from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
10
+ from classiq.interface.generator.functions.type_name import (
11
+ TypeName,
12
+ )
13
+ from classiq.interface.model.bind_operation import BindOperation
14
+ from classiq.interface.model.inplace_binary_operation import BinaryOperation
15
+ from classiq.interface.model.port_declaration import PortDeclaration
16
+ from classiq.interface.model.quantum_function_declaration import PositionalArg
17
+ from classiq.interface.model.quantum_type import (
18
+ QuantumBit,
19
+ QuantumBitvector,
20
+ QuantumNumeric,
21
+ QuantumScalar,
22
+ QuantumType,
23
+ )
24
+
25
+ from classiq.model_expansions.scope import QuantumSymbol, Scope
26
+
27
+
28
+ def copy_type_information(
29
+ from_type: QuantumType,
30
+ to_type: QuantumType,
31
+ to_param_name: str,
32
+ ) -> None:
33
+ if isinstance(to_type, QuantumBit):
34
+ set_size(to_type, from_type.size_in_bits, to_param_name)
35
+ elif isinstance(to_type, QuantumNumeric):
36
+ set_is_signed(to_type, getattr(from_type, "sign_value", None), to_param_name)
37
+ set_fraction_digits(
38
+ to_type,
39
+ getattr(from_type, "fraction_digits_value", None),
40
+ to_param_name,
41
+ )
42
+ set_size(to_type, from_type.size_in_bits, to_param_name)
43
+ elif isinstance(to_type, QuantumBitvector):
44
+ if isinstance(from_type, QuantumBitvector) and type( # noqa: E721
45
+ from_type.element_type
46
+ ) == type(to_type.element_type):
47
+ copy_type_information(
48
+ from_type.element_type, to_type.element_type, to_param_name
49
+ )
50
+ set_size(to_type, from_type.size_in_bits, to_param_name)
51
+ elif isinstance(to_type, TypeName):
52
+ if isinstance(from_type, TypeName) and from_type.name == to_type.name:
53
+ for field in from_type.fields:
54
+ copy_type_information(
55
+ from_type.fields[field], to_type.fields[field], to_param_name
56
+ )
57
+ set_size(to_type, from_type.size_in_bits, to_param_name)
58
+ else:
59
+ raise ClassiqInternalExpansionError
60
+
61
+
62
+ def set_size(quantum_type: QuantumType, size: int, param_name: str) -> None:
63
+ if size <= 0:
64
+ raise ClassiqExpansionError(
65
+ f"Size for {param_name!r} was deduced to be non-positive: {size!r}"
66
+ )
67
+
68
+ if quantum_type.has_size_in_bits and quantum_type.size_in_bits != size:
69
+ raise ClassiqExpansionError(
70
+ f"Size mismatch for port {param_name!r} between declared size {quantum_type.size_in_bits} and assigned size {size}"
71
+ )
72
+
73
+ if isinstance(quantum_type, QuantumNumeric):
74
+ quantum_type.size = Expression(expr=str(size))
75
+ if not quantum_type.has_sign or not quantum_type.has_fraction_digits:
76
+ set_is_signed(quantum_type, False, param_name)
77
+ set_fraction_digits(quantum_type, 0, param_name)
78
+ elif isinstance(quantum_type, QuantumBitvector):
79
+ if quantum_type.has_length:
80
+ if size % quantum_type.length_value != 0:
81
+ raise ClassiqExpansionError(
82
+ f"Size mismatch for port {param_name!r}. Cannot fit {size} "
83
+ f"qubits into an array of {quantum_type.length_value} elements."
84
+ )
85
+ set_size(
86
+ quantum_type.element_type,
87
+ size // quantum_type.length_value,
88
+ param_name,
89
+ )
90
+ set_length_by_size(quantum_type, size, param_name)
91
+ elif isinstance(quantum_type, TypeName):
92
+ fields_without_size = [
93
+ field_type
94
+ for field_type in quantum_type.fields.values()
95
+ if not field_type.has_size_in_bits
96
+ ]
97
+ if len(fields_without_size) > 1:
98
+ raise ClassiqInternalExpansionError(
99
+ f"QuantumStruct should have at most one field without "
100
+ f"predetermined size. Found {fields_without_size}."
101
+ )
102
+ if len(fields_without_size) == 1:
103
+ predetermined_size_part = sum(
104
+ field_type.size_in_bits if field_type.has_size_in_bits else 0
105
+ for field_type in quantum_type.fields.values()
106
+ )
107
+ set_size(fields_without_size[0], size - predetermined_size_part, param_name)
108
+
109
+
110
+ def set_fraction_digits(
111
+ quantum_numeric: QuantumNumeric, fraction_digits: Optional[int], param_name: str
112
+ ) -> None:
113
+ if fraction_digits is not None and fraction_digits < 0:
114
+ raise ClassiqExpansionError(
115
+ f"Number of fraction digits for {param_name!r} was deduced to be negative: "
116
+ f"{fraction_digits!r}"
117
+ )
118
+
119
+ if (
120
+ fraction_digits is not None
121
+ and quantum_numeric.fraction_digits is not None
122
+ and quantum_numeric.fraction_digits.is_evaluated()
123
+ and quantum_numeric.fraction_digits_value != fraction_digits
124
+ ):
125
+ raise ClassiqExpansionError(
126
+ f"Fraction digits mismatch for port {param_name!r} between declared "
127
+ f"fraction digits {quantum_numeric.fraction_digits_value!r} and assigned fraction "
128
+ f"digits {fraction_digits!r}"
129
+ )
130
+
131
+ if not (
132
+ quantum_numeric.fraction_digits is not None
133
+ and quantum_numeric.fraction_digits.is_evaluated()
134
+ ):
135
+ quantum_numeric.fraction_digits = Expression(expr=str(fraction_digits or 0))
136
+
137
+
138
+ def set_is_signed(
139
+ quantum_numeric: QuantumNumeric, is_signed: Optional[bool], param_name: str
140
+ ) -> None:
141
+ if (
142
+ is_signed is not None
143
+ and quantum_numeric.is_signed is not None
144
+ and quantum_numeric.is_signed.is_evaluated()
145
+ and quantum_numeric.sign_value != is_signed
146
+ ):
147
+ raise ClassiqExpansionError(
148
+ f"Sign mismatch for port {param_name!r} between declared sign {quantum_numeric.sign_value!r} and assigned sign {is_signed!r}"
149
+ )
150
+
151
+ if not (
152
+ quantum_numeric.is_signed is not None
153
+ and quantum_numeric.is_signed.is_evaluated()
154
+ ):
155
+ quantum_numeric.is_signed = Expression(expr=str(is_signed or False))
156
+
157
+
158
+ def set_element_type(
159
+ quantum_array: QuantumBitvector, element_type: ConcreteQuantumType
160
+ ) -> None:
161
+ quantum_array.element_type = element_type
162
+
163
+
164
+ def set_length(quantum_array: QuantumBitvector, length: int) -> None:
165
+ quantum_array.length = Expression(expr=str(length))
166
+
167
+
168
+ def set_length_by_size(
169
+ quantum_array: QuantumBitvector, size: int, param_name: str
170
+ ) -> None:
171
+ if size <= 0:
172
+ raise ClassiqExpansionError(
173
+ f"Size for {param_name!r} was deduced to be non-positive: {size!r}"
174
+ )
175
+
176
+ if quantum_array.has_size_in_bits and quantum_array.size_in_bits != size:
177
+ raise ClassiqExpansionError(
178
+ f"Size mismatch for port {param_name!r} between declared size "
179
+ f"{quantum_array.size_in_bits} ({quantum_array.length_value} elements of "
180
+ f"size {quantum_array.element_type.size_in_bits}) and assigned size {size}."
181
+ )
182
+
183
+ if not quantum_array.element_type.has_size_in_bits:
184
+ raise ClassiqExpansionError(
185
+ f"Could not infer element size for array {param_name!r}."
186
+ )
187
+ element_size = quantum_array.element_type.size_in_bits
188
+
189
+ if size % element_size != 0:
190
+ raise ClassiqExpansionError(
191
+ f"Size mismatch for port {param_name!r}. Cannot fit elements of type "
192
+ f"{quantum_array.element_type.qmod_type_name} (size {element_size}) into "
193
+ f"{size} qubits."
194
+ )
195
+
196
+ quantum_array.length = Expression(expr=str(size // element_size))
197
+
198
+
199
+ def validate_bind_targets(bind: BindOperation, scope: Scope) -> None:
200
+ illegal_qnum_bind_targets = []
201
+ for out_handle in bind.out_handles:
202
+ out_var = scope[out_handle.name].as_type(QuantumSymbol)
203
+ out_var_type = out_var.quantum_type
204
+ if not isinstance(out_var_type, QuantumNumeric):
205
+ continue
206
+ if not out_var_type.has_size_in_bits:
207
+ illegal_qnum_bind_targets.append(str(out_var.handle))
208
+ elif not out_var_type.has_sign:
209
+ assert not out_var_type.has_fraction_digits
210
+ illegal_qnum_bind_targets.append(str(out_var.handle))
211
+ if len(illegal_qnum_bind_targets) > 0:
212
+ raise ClassiqExpansionError(
213
+ f"QNum bind targets {illegal_qnum_bind_targets!r} must be declared or initialized with size, sign, and fraction digits"
214
+ )
215
+
216
+
217
+ def get_inplace_op_scalar_as_numeric(
218
+ var: QuantumSymbol, operation: BinaryOperation, var_kind: str
219
+ ) -> QuantumNumeric:
220
+ if not isinstance(var.quantum_type, QuantumScalar):
221
+ raise ClassiqExpansionError(
222
+ f"Cannot perform inplace {operation.name.lower()} with non-scalar {var_kind} {var.handle}"
223
+ )
224
+ if isinstance(var.quantum_type, QuantumNumeric):
225
+ return var.quantum_type
226
+ if isinstance(var.quantum_type, QuantumBit):
227
+ return QuantumNumeric(
228
+ size=Expression(expr="1"),
229
+ is_signed=Expression(expr="False"),
230
+ fraction_digits=Expression(expr="0"),
231
+ )
232
+ raise ClassiqInternalExpansionError(f"Unexpected scalar type {var.quantum_type}")
233
+
234
+
235
+ def is_signature_monomorphic(params: Sequence[PositionalArg]) -> bool:
236
+ return all(
237
+ isinstance(param, PortDeclaration) and param.quantum_type.is_evaluated
238
+ for param in params
239
+ )
@@ -0,0 +1,90 @@
1
+ from collections.abc import Sequence
2
+
3
+ from classiq.interface.exceptions import (
4
+ ClassiqExpansionError,
5
+ ClassiqInternalExpansionError,
6
+ )
7
+ from classiq.interface.model.classical_parameter_declaration import (
8
+ AnonClassicalParameterDeclaration,
9
+ )
10
+ from classiq.interface.model.port_declaration import AnonPortDeclaration
11
+ from classiq.interface.model.quantum_function_declaration import (
12
+ AnonPositionalArg,
13
+ AnonQuantumOperandDeclaration,
14
+ )
15
+
16
+
17
+ def check_signature_match(
18
+ decl_params: Sequence[AnonPositionalArg],
19
+ op_params: Sequence[AnonPositionalArg],
20
+ location_str: str,
21
+ ) -> None:
22
+ if len(decl_params) != len(op_params):
23
+ raise ClassiqExpansionError(
24
+ f"{location_str} should have {len(decl_params)} parameters, "
25
+ f"not {len(op_params)}"
26
+ )
27
+ for idx, (decl_param, op_param) in enumerate(zip(decl_params, op_params)):
28
+ message_prefix = f"Argument {idx} in {location_str} has incompatible type; "
29
+ _check_type_match(op_param, decl_param, location_str, message_prefix)
30
+
31
+
32
+ def _check_type_match(
33
+ op_param: AnonPositionalArg,
34
+ decl_param: AnonPositionalArg,
35
+ location_str: str,
36
+ message_prefix: str,
37
+ ) -> None:
38
+ if isinstance(decl_param, AnonPortDeclaration):
39
+ error_message = message_prefix + "expected quantum parameter"
40
+ _check_qvar_type_match(op_param, error_message)
41
+ elif isinstance(decl_param, AnonQuantumOperandDeclaration):
42
+ if decl_param.is_list:
43
+ error_message = message_prefix + "expected operand list parameter"
44
+ else:
45
+ error_message = message_prefix + "expected operand parameter"
46
+ _check_operand_type_match(op_param, decl_param, location_str, error_message)
47
+ elif isinstance(decl_param, AnonClassicalParameterDeclaration):
48
+ error_message = (
49
+ message_prefix + f"expected classical {decl_param.classical_type} parameter"
50
+ )
51
+ _check_classical_type_match(op_param, decl_param, error_message)
52
+ else:
53
+ raise ClassiqInternalExpansionError(
54
+ f"unexpected parameter declaration type: {type(decl_param).__name__}"
55
+ )
56
+
57
+
58
+ def _check_qvar_type_match(op_param: AnonPositionalArg, error_message: str) -> None:
59
+ if not isinstance(op_param, AnonPortDeclaration):
60
+ raise ClassiqExpansionError(error_message)
61
+
62
+
63
+ def _check_operand_type_match(
64
+ op_param: AnonPositionalArg,
65
+ decl_param: AnonQuantumOperandDeclaration,
66
+ location_str: str,
67
+ error_message: str,
68
+ ) -> None:
69
+ if (
70
+ not isinstance(op_param, AnonQuantumOperandDeclaration)
71
+ or decl_param.is_list ^ op_param.is_list
72
+ ):
73
+ raise ClassiqExpansionError(error_message)
74
+ check_signature_match(
75
+ decl_param.positional_arg_declarations,
76
+ op_param.positional_arg_declarations,
77
+ f"operand {decl_param.name} in {location_str}",
78
+ )
79
+
80
+
81
+ def _check_classical_type_match(
82
+ op_param: AnonPositionalArg,
83
+ decl_param: AnonClassicalParameterDeclaration,
84
+ error_message: str,
85
+ ) -> None:
86
+ if (
87
+ not isinstance(op_param, AnonClassicalParameterDeclaration)
88
+ or decl_param.classical_type != op_param.classical_type
89
+ ):
90
+ raise ClassiqExpansionError(error_message)
@@ -0,0 +1,135 @@
1
+ import ast
2
+ import re
3
+ from collections.abc import Mapping
4
+ from enum import EnumMeta
5
+ from typing import Any, Optional
6
+
7
+ from sympy import sympify
8
+
9
+ from classiq.interface.exceptions import ClassiqExpansionError
10
+ from classiq.interface.generator.constant import Constant
11
+ from classiq.interface.generator.expressions.evaluated_expression import (
12
+ EvaluatedExpression,
13
+ )
14
+ from classiq.interface.generator.expressions.expression import Expression
15
+ from classiq.interface.generator.expressions.expression_constants import (
16
+ CPARAM_EXECUTION_SUFFIX_PATTERN,
17
+ )
18
+ from classiq.interface.generator.expressions.expression_types import ExpressionValue
19
+ from classiq.interface.generator.expressions.sympy_supported_expressions import (
20
+ SYMPY_SUPPORTED_EXPRESSIONS,
21
+ )
22
+
23
+ from classiq.model_expansions.atomic_expression_functions_defs import (
24
+ ATOMIC_EXPRESSION_FUNCTIONS,
25
+ qmod_val_to_python,
26
+ )
27
+ from classiq.model_expansions.sympy_conversion.expression_to_sympy import (
28
+ translate_to_sympy,
29
+ )
30
+ from classiq.model_expansions.sympy_conversion.sympy_to_python import sympy_to_python
31
+ from classiq.qmod import symbolic
32
+ from classiq.qmod.builtins.enums import BUILTIN_ENUM_DECLARATIONS
33
+ from classiq.qmod.model_state_container import QMODULE
34
+
35
+
36
+ def evaluate_constants(constants: list[Constant]) -> dict[str, EvaluatedExpression]:
37
+ result: dict[str, EvaluatedExpression] = {}
38
+ for constant in constants:
39
+ result[constant.name] = evaluate(constant.value, result)
40
+ return result
41
+
42
+
43
+ def evaluate_constants_as_python(constants: list[Constant]) -> dict[str, Any]:
44
+ evaluated = evaluate_constants(constants)
45
+ return {
46
+ constant.name: qmod_val_to_python(
47
+ evaluated[constant.name].value, constant.const_type
48
+ )
49
+ for constant in constants
50
+ }
51
+
52
+
53
+ def evaluate(
54
+ expr: Expression,
55
+ locals_dict: Mapping[str, EvaluatedExpression],
56
+ uninitialized_locals: Optional[set[str]] = None,
57
+ ) -> EvaluatedExpression:
58
+ model_locals: dict[str, ExpressionValue] = {}
59
+ model_locals.update(ATOMIC_EXPRESSION_FUNCTIONS)
60
+ model_locals.update(
61
+ {
62
+ enum_decl.name: enum_decl.create_enum()
63
+ for enum_decl in (QMODULE.enum_decls | BUILTIN_ENUM_DECLARATIONS).values()
64
+ }
65
+ )
66
+ # locals override builtin-functions
67
+ model_locals.update({name: expr.value for name, expr in locals_dict.items()})
68
+ uninitialized_locals = uninitialized_locals or set()
69
+
70
+ _validate_undefined_vars(expr.expr, model_locals, uninitialized_locals)
71
+
72
+ sympy_expr = translate_to_sympy(expr.expr)
73
+ try:
74
+ sympify_result = sympify(sympy_expr, locals=model_locals)
75
+ except (TypeError, IndexError) as e:
76
+ raise ClassiqExpansionError(str(e)) from None
77
+ except AttributeError as e:
78
+ if isinstance(e.obj, EnumMeta):
79
+ raise ClassiqExpansionError(
80
+ f"Enum {e.obj.__name__} has no member {e.name!r}. Available members: "
81
+ f"{', '.join(e.obj.__members__)}"
82
+ ) from e
83
+ raise
84
+
85
+ return EvaluatedExpression(
86
+ value=sympy_to_python(sympify_result, locals=model_locals)
87
+ )
88
+
89
+
90
+ def _validate_undefined_vars(
91
+ expr: str,
92
+ model_locals: dict[str, ExpressionValue],
93
+ uninitialized_locals: Optional[set[str]],
94
+ ) -> None:
95
+ uninitialized_locals = uninitialized_locals or set()
96
+ id_visitor = _VarsCollector()
97
+ id_visitor.visit(ast.parse(expr))
98
+ identifiers = id_visitor.vars
99
+ undefined_vars = (
100
+ identifiers
101
+ - model_locals.keys()
102
+ - set(SYMPY_SUPPORTED_EXPRESSIONS)
103
+ - set(symbolic.__all__)
104
+ - uninitialized_locals
105
+ )
106
+
107
+ # Ignore expanded execution parameters
108
+ undefined_vars = {
109
+ var
110
+ for var in undefined_vars
111
+ if not re.search(CPARAM_EXECUTION_SUFFIX_PATTERN, var)
112
+ }
113
+
114
+ if len(undefined_vars) == 1:
115
+ undefined_var = undefined_vars.__iter__().__next__()
116
+ raise ClassiqExpansionError(f"Variable {undefined_var!r} is undefined")
117
+ elif len(undefined_vars) > 1:
118
+ raise ClassiqExpansionError(f"Variables {list(undefined_vars)} are undefined")
119
+
120
+
121
+ class _VarsCollector(ast.NodeTransformer):
122
+ def __init__(self) -> None:
123
+ self.vars: set[str] = set()
124
+
125
+ def visit_Name(self, node: ast.Name) -> None:
126
+ self.vars.add(node.id)
127
+
128
+ def visit_Call(self, node: ast.Call) -> None:
129
+ func = node.func
130
+ self.visit(func)
131
+ if not isinstance(func, ast.Name) or func.id != "struct_literal":
132
+ for arg in node.args:
133
+ self.visit(arg)
134
+ for kw in node.keywords:
135
+ self.visit(kw)