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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. classiq/__init__.py +49 -34
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +3 -2
  3. classiq/_analyzer_extras/interactive_hardware.py +3 -3
  4. classiq/_internals/api_wrapper.py +241 -95
  5. classiq/_internals/async_utils.py +2 -77
  6. classiq/_internals/authentication/auth0.py +26 -10
  7. classiq/_internals/authentication/authentication.py +11 -0
  8. classiq/_internals/authentication/device.py +18 -8
  9. classiq/_internals/authentication/password_manager.py +40 -13
  10. classiq/_internals/authentication/token_manager.py +11 -6
  11. classiq/_internals/client.py +106 -37
  12. classiq/_internals/config.py +3 -4
  13. classiq/_internals/host_checker.py +38 -15
  14. classiq/_internals/jobs.py +56 -50
  15. classiq/_internals/type_validation.py +9 -9
  16. classiq/analyzer/__init__.py +1 -3
  17. classiq/analyzer/analyzer.py +50 -47
  18. classiq/analyzer/analyzer_utilities.py +15 -15
  19. classiq/analyzer/rb.py +19 -20
  20. classiq/analyzer/show_interactive_hack.py +30 -7
  21. classiq/analyzer/url_utils.py +2 -3
  22. classiq/applications/__init__.py +3 -12
  23. classiq/applications/chemistry/__init__.py +14 -10
  24. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  25. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +170 -170
  26. classiq/applications/chemistry/ground_state_problem.py +1 -1
  27. classiq/applications/combinatorial_helpers/allowed_constraints.py +23 -0
  28. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
  29. classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
  30. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +166 -0
  31. classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
  32. classiq/applications/combinatorial_helpers/encoding_utils.py +124 -0
  33. classiq/applications/combinatorial_helpers/memory.py +75 -0
  34. classiq/applications/combinatorial_helpers/optimization_model.py +193 -0
  35. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
  36. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
  37. classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
  38. classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
  39. classiq/applications/combinatorial_helpers/transformations/encoding.py +189 -0
  40. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +143 -0
  41. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +120 -0
  42. classiq/applications/combinatorial_helpers/transformations/penalty.py +31 -0
  43. classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
  44. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +74 -0
  45. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +87 -0
  46. classiq/applications/combinatorial_optimization/__init__.py +24 -5
  47. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  48. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +137 -0
  49. classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
  50. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  51. classiq/applications/finance/__init__.py +4 -5
  52. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +50 -57
  53. classiq/applications/grover/__init__.py +9 -0
  54. classiq/applications/grover/grover_model_constructor.py +157 -0
  55. classiq/applications/hamiltonian/__init__.py +0 -0
  56. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  57. classiq/applications/libraries/__init__.py +0 -0
  58. classiq/applications/libraries/qmci_library.py +22 -0
  59. classiq/applications/qnn/__init__.py +2 -4
  60. classiq/applications/qnn/circuit_utils.py +8 -8
  61. classiq/applications/qnn/datasets/__init__.py +9 -11
  62. classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
  63. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  64. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  65. classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
  66. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  67. classiq/applications/qnn/qlayer.py +30 -10
  68. classiq/applications/qnn/torch_utils.py +4 -3
  69. classiq/applications/qnn/types.py +7 -7
  70. classiq/applications/qsvm/__init__.py +6 -4
  71. classiq/applications/qsvm/qsvm.py +4 -10
  72. classiq/applications/qsvm/qsvm_data_generation.py +5 -8
  73. classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
  74. classiq/execution/__init__.py +8 -3
  75. classiq/execution/all_hardware_devices.py +11 -0
  76. classiq/execution/execution_session.py +400 -0
  77. classiq/execution/iqcc.py +63 -0
  78. classiq/execution/jobs.py +197 -25
  79. classiq/execution/qnn.py +79 -0
  80. classiq/executor.py +23 -117
  81. classiq/interface/_version.py +1 -1
  82. classiq/interface/analyzer/analysis_params.py +49 -16
  83. classiq/interface/analyzer/cytoscape_graph.py +15 -9
  84. classiq/interface/analyzer/result.py +36 -32
  85. classiq/interface/applications/qsvm.py +28 -25
  86. classiq/interface/ast_node.py +16 -0
  87. classiq/interface/backend/backend_preferences.py +390 -119
  88. classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
  89. classiq/interface/backend/pydantic_backend.py +27 -22
  90. classiq/interface/backend/quantum_backend_providers.py +70 -16
  91. classiq/interface/chemistry/fermionic_operator.py +43 -32
  92. classiq/interface/chemistry/ground_state_problem.py +42 -24
  93. classiq/interface/chemistry/molecule.py +20 -14
  94. classiq/interface/chemistry/operator.py +75 -236
  95. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  96. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +2 -4
  97. classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
  98. classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
  99. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  100. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  101. classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
  102. classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
  103. classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
  104. classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
  105. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  106. classiq/interface/combinatorial_optimization/examples/set_cover.py +3 -3
  107. classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
  108. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
  109. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +14 -9
  110. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  111. classiq/interface/combinatorial_optimization/result.py +1 -3
  112. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  113. classiq/interface/debug_info/__init__.py +0 -0
  114. classiq/interface/debug_info/debug_info.py +86 -0
  115. classiq/interface/exceptions.py +201 -0
  116. classiq/interface/execution/iqcc.py +19 -0
  117. classiq/interface/execution/jobs.py +15 -12
  118. classiq/interface/execution/primitives.py +18 -0
  119. classiq/interface/executor/constants.py +1 -0
  120. classiq/interface/executor/estimation.py +2 -2
  121. classiq/interface/executor/execution_preferences.py +26 -143
  122. classiq/interface/executor/execution_request.py +36 -56
  123. classiq/interface/executor/execution_result.py +30 -8
  124. classiq/interface/executor/iqae_result.py +4 -6
  125. classiq/interface/executor/optimizer_preferences.py +34 -22
  126. classiq/interface/executor/{quantum_program.py → quantum_code.py} +44 -34
  127. classiq/interface/executor/quantum_instruction_set.py +3 -2
  128. classiq/interface/executor/register_initialization.py +12 -17
  129. classiq/interface/executor/result.py +122 -64
  130. classiq/interface/executor/vqe_result.py +11 -11
  131. classiq/interface/finance/function_input.py +42 -19
  132. classiq/interface/finance/gaussian_model_input.py +7 -5
  133. classiq/interface/finance/log_normal_model_input.py +6 -4
  134. classiq/interface/finance/model_input.py +6 -4
  135. classiq/interface/generator/adjacency.py +1 -3
  136. classiq/interface/generator/amplitude_loading.py +27 -14
  137. classiq/interface/generator/ansatz_library.py +5 -5
  138. classiq/interface/generator/application_apis/__init__.py +1 -0
  139. classiq/interface/generator/application_apis/arithmetic_declarations.py +17 -0
  140. classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
  141. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
  142. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  143. classiq/interface/generator/application_apis/finance_declarations.py +48 -69
  144. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
  145. classiq/interface/generator/arith/argument_utils.py +57 -6
  146. classiq/interface/generator/arith/arithmetic.py +37 -16
  147. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +15 -17
  148. classiq/interface/generator/arith/arithmetic_expression_abc.py +70 -26
  149. classiq/interface/generator/arith/arithmetic_expression_parser.py +18 -12
  150. classiq/interface/generator/arith/arithmetic_expression_validator.py +61 -43
  151. classiq/interface/generator/arith/arithmetic_operations.py +19 -16
  152. classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
  153. classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
  154. classiq/interface/generator/arith/ast_node_rewrite.py +4 -3
  155. classiq/interface/generator/arith/binary_ops.py +375 -139
  156. classiq/interface/generator/arith/endianness.py +1 -1
  157. classiq/interface/generator/arith/extremum_operations.py +96 -23
  158. classiq/interface/generator/arith/logical_ops.py +16 -12
  159. classiq/interface/generator/arith/machine_precision.py +3 -0
  160. classiq/interface/generator/arith/number_utils.py +44 -48
  161. classiq/interface/generator/arith/register_user_input.py +70 -27
  162. classiq/interface/generator/arith/unary_ops.py +57 -46
  163. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  164. classiq/interface/generator/builtin_api_builder.py +2 -9
  165. classiq/interface/generator/chemistry_function_params.py +5 -5
  166. classiq/interface/generator/circuit_code/circuit_code.py +7 -7
  167. classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
  168. classiq/interface/generator/commuting_pauli_exponentiation.py +8 -6
  169. classiq/interface/generator/compiler_keywords.py +8 -0
  170. classiq/interface/generator/complex_type.py +13 -25
  171. classiq/interface/generator/constant.py +3 -4
  172. classiq/interface/generator/control_state.py +35 -28
  173. classiq/interface/generator/copy.py +47 -0
  174. classiq/interface/generator/custom_ansatz.py +2 -5
  175. classiq/interface/generator/distance.py +3 -5
  176. classiq/interface/generator/excitations.py +3 -2
  177. classiq/interface/generator/expressions/atomic_expression_functions.py +26 -8
  178. classiq/interface/generator/expressions/enums/__init__.py +0 -10
  179. classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
  180. classiq/interface/generator/expressions/evaluated_expression.py +21 -7
  181. classiq/interface/generator/expressions/expression.py +27 -15
  182. classiq/interface/generator/expressions/expression_constants.py +9 -3
  183. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  184. classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
  185. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +59 -0
  186. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
  187. classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
  188. classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
  189. classiq/interface/generator/expressions/sympy_supported_expressions.py +20 -11
  190. classiq/interface/generator/finance.py +3 -3
  191. classiq/interface/generator/function_param_library.py +6 -6
  192. classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
  193. classiq/interface/generator/function_params.py +42 -69
  194. classiq/interface/generator/functions/__init__.py +0 -22
  195. classiq/interface/generator/functions/builtins/__init__.py +0 -0
  196. classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
  197. classiq/interface/generator/functions/classical_function_declaration.py +18 -9
  198. classiq/interface/generator/functions/classical_type.py +47 -166
  199. classiq/interface/generator/functions/concrete_types.py +55 -0
  200. classiq/interface/generator/functions/function_declaration.py +13 -14
  201. classiq/interface/generator/functions/port_declaration.py +1 -13
  202. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  203. classiq/interface/generator/functions/type_name.py +90 -0
  204. classiq/interface/generator/generated_circuit_data.py +155 -22
  205. classiq/interface/generator/grover_diffuser.py +32 -25
  206. classiq/interface/generator/grover_operator.py +34 -23
  207. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
  208. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  209. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +12 -8
  210. classiq/interface/generator/hardware/hardware_data.py +76 -36
  211. classiq/interface/generator/hardware_efficient_ansatz.py +38 -17
  212. classiq/interface/generator/hartree_fock.py +14 -4
  213. classiq/interface/generator/identity.py +10 -6
  214. classiq/interface/generator/linear_pauli_rotations.py +33 -19
  215. classiq/interface/generator/mcmt_method.py +1 -1
  216. classiq/interface/generator/mcu.py +20 -16
  217. classiq/interface/generator/mcx.py +29 -20
  218. classiq/interface/generator/model/__init__.py +2 -5
  219. classiq/interface/generator/model/constraints.py +27 -8
  220. classiq/interface/generator/model/model.py +32 -203
  221. classiq/interface/generator/model/preferences/preferences.py +118 -43
  222. classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +27 -22
  223. classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
  224. classiq/interface/generator/oracles/custom_oracle.py +17 -13
  225. classiq/interface/generator/oracles/oracle_abc.py +9 -9
  226. classiq/interface/generator/partitioned_register.py +7 -7
  227. classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
  228. classiq/interface/generator/preferences/optimization.py +1 -2
  229. classiq/interface/generator/qpe.py +47 -34
  230. classiq/interface/generator/qsvm.py +13 -17
  231. classiq/interface/generator/quantum_function_call.py +107 -87
  232. classiq/interface/generator/{generated_circuit.py → quantum_program.py} +50 -37
  233. classiq/interface/generator/range_types.py +13 -12
  234. classiq/interface/generator/register_role.py +18 -6
  235. classiq/interface/generator/slice_parsing_utils.py +11 -6
  236. classiq/interface/generator/standard_gates/controlled_standard_gates.py +32 -39
  237. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  238. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  239. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  240. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  241. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  242. classiq/interface/generator/state_preparation/distributions.py +16 -15
  243. classiq/interface/generator/state_preparation/metrics.py +5 -7
  244. classiq/interface/generator/state_preparation/state_preparation.py +30 -23
  245. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  246. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
  247. classiq/interface/generator/transpiler_basis_gates.py +7 -3
  248. classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
  249. classiq/interface/generator/types/compilation_metadata.py +6 -0
  250. classiq/interface/generator/types/enum_declaration.py +54 -0
  251. classiq/interface/generator/types/qstruct_declaration.py +18 -0
  252. classiq/interface/generator/types/struct_declaration.py +15 -14
  253. classiq/interface/generator/ucc.py +9 -6
  254. classiq/interface/generator/unitary_gate.py +10 -6
  255. classiq/interface/generator/user_defined_function_params.py +4 -1
  256. classiq/interface/generator/validations/flow_graph.py +11 -9
  257. classiq/interface/generator/validations/validator_functions.py +8 -6
  258. classiq/interface/generator/visitor.py +23 -16
  259. classiq/interface/hardware.py +31 -10
  260. classiq/interface/helpers/classproperty.py +8 -0
  261. classiq/interface/helpers/custom_encoders.py +3 -0
  262. classiq/interface/helpers/custom_pydantic_types.py +40 -50
  263. classiq/interface/helpers/datastructures.py +26 -0
  264. classiq/interface/helpers/hashable_mixin.py +3 -2
  265. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  266. classiq/interface/helpers/pydantic_model_helpers.py +7 -11
  267. classiq/interface/helpers/validation_helpers.py +4 -21
  268. classiq/interface/helpers/versioned_model.py +1 -1
  269. classiq/interface/ide/ide_data.py +16 -20
  270. classiq/interface/ide/visual_model.py +130 -0
  271. classiq/interface/interface_version.py +1 -0
  272. classiq/interface/jobs.py +35 -6
  273. classiq/interface/model/allocate.py +16 -0
  274. classiq/interface/model/bind_operation.py +44 -14
  275. classiq/interface/model/classical_if.py +15 -0
  276. classiq/interface/model/classical_parameter_declaration.py +33 -3
  277. classiq/interface/model/control.py +45 -0
  278. classiq/interface/model/handle_binding.py +298 -20
  279. classiq/interface/model/inplace_binary_operation.py +31 -26
  280. classiq/interface/model/invert.py +12 -0
  281. classiq/interface/model/model.py +87 -73
  282. classiq/interface/model/native_function_definition.py +16 -21
  283. classiq/interface/model/parameter.py +13 -0
  284. classiq/interface/model/phase_operation.py +11 -0
  285. classiq/interface/model/port_declaration.py +27 -9
  286. classiq/interface/model/power.py +14 -0
  287. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +38 -21
  288. classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
  289. classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
  290. classiq/interface/model/quantum_function_call.py +146 -462
  291. classiq/interface/model/quantum_function_declaration.py +193 -152
  292. classiq/interface/model/quantum_lambda_function.py +65 -0
  293. classiq/interface/model/quantum_statement.py +71 -12
  294. classiq/interface/model/quantum_type.py +205 -67
  295. classiq/interface/model/quantum_variable_declaration.py +4 -26
  296. classiq/interface/model/repeat.py +15 -0
  297. classiq/interface/model/statement_block.py +58 -0
  298. classiq/interface/model/validation_handle.py +13 -6
  299. classiq/interface/model/variable_declaration_statement.py +3 -1
  300. classiq/interface/model/within_apply_operation.py +13 -0
  301. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
  302. classiq/interface/server/global_versions.py +6 -7
  303. classiq/interface/server/routes.py +22 -21
  304. classiq/interface/source_reference.py +59 -0
  305. classiq/model_expansions/__init__.py +0 -0
  306. classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
  307. classiq/model_expansions/capturing/__init__.py +0 -0
  308. classiq/model_expansions/capturing/captured_vars.py +435 -0
  309. classiq/model_expansions/capturing/mangling_utils.py +56 -0
  310. classiq/model_expansions/closure.py +171 -0
  311. classiq/model_expansions/debug_flag.py +3 -0
  312. classiq/model_expansions/evaluators/__init__.py +0 -0
  313. classiq/model_expansions/evaluators/arg_type_match.py +158 -0
  314. classiq/model_expansions/evaluators/argument_types.py +42 -0
  315. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  316. classiq/model_expansions/evaluators/control.py +144 -0
  317. classiq/model_expansions/evaluators/parameter_types.py +226 -0
  318. classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
  319. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  320. classiq/model_expansions/expression_evaluator.py +135 -0
  321. classiq/model_expansions/expression_renamer.py +76 -0
  322. classiq/model_expansions/function_builder.py +247 -0
  323. classiq/model_expansions/generative_functions.py +158 -0
  324. classiq/model_expansions/interpreters/__init__.py +0 -0
  325. classiq/model_expansions/interpreters/base_interpreter.py +263 -0
  326. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
  327. classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
  328. classiq/model_expansions/model_tables.py +18 -0
  329. classiq/model_expansions/quantum_operations/__init__.py +9 -0
  330. classiq/model_expansions/quantum_operations/bind.py +60 -0
  331. classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
  332. classiq/model_expansions/quantum_operations/classicalif.py +53 -0
  333. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
  334. classiq/model_expansions/quantum_operations/emitter.py +181 -0
  335. classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
  336. classiq/model_expansions/quantum_operations/repeat.py +56 -0
  337. classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
  338. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  339. classiq/model_expansions/scope.py +240 -0
  340. classiq/model_expansions/scope_initialization.py +150 -0
  341. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  342. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  343. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
  344. classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
  345. classiq/model_expansions/transformers/__init__.py +0 -0
  346. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  347. classiq/model_expansions/transformers/var_splitter.py +299 -0
  348. classiq/model_expansions/utils/__init__.py +0 -0
  349. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  350. classiq/model_expansions/utils/handles_collector.py +33 -0
  351. classiq/model_expansions/visitors/__init__.py +0 -0
  352. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  353. classiq/model_expansions/visitors/variable_references.py +144 -0
  354. classiq/open_library/__init__.py +4 -0
  355. classiq/open_library/functions/__init__.py +130 -0
  356. classiq/open_library/functions/amplitude_estimation.py +30 -0
  357. classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
  358. classiq/open_library/functions/grover.py +157 -0
  359. classiq/open_library/functions/hea.py +115 -0
  360. classiq/open_library/functions/linear_pauli_rotation.py +82 -0
  361. classiq/open_library/functions/modular_exponentiation.py +201 -0
  362. classiq/open_library/functions/qaoa_penalty.py +117 -0
  363. classiq/open_library/functions/qft_functions.py +54 -0
  364. classiq/open_library/functions/qpe.py +46 -0
  365. classiq/open_library/functions/qsvt.py +331 -0
  366. classiq/open_library/functions/state_preparation.py +301 -0
  367. classiq/open_library/functions/swap_test.py +27 -0
  368. classiq/open_library/functions/utility_functions.py +81 -0
  369. classiq/open_library/functions/variational.py +52 -0
  370. classiq/qmod/__init__.py +17 -10
  371. classiq/qmod/builtins/__init__.py +19 -2
  372. classiq/qmod/builtins/classical_execution_primitives.py +60 -47
  373. classiq/qmod/builtins/classical_functions.py +44 -38
  374. classiq/qmod/builtins/constants.py +10 -0
  375. classiq/qmod/builtins/enums.py +208 -0
  376. classiq/qmod/builtins/functions/__init__.py +137 -0
  377. classiq/qmod/builtins/functions/allocation.py +150 -0
  378. classiq/qmod/builtins/functions/arithmetic.py +55 -0
  379. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  380. classiq/qmod/builtins/functions/chemistry.py +91 -0
  381. classiq/qmod/builtins/functions/exponentiation.py +105 -0
  382. classiq/qmod/builtins/functions/finance.py +34 -0
  383. classiq/qmod/builtins/functions/operators.py +16 -0
  384. classiq/qmod/builtins/functions/qsvm.py +24 -0
  385. classiq/qmod/builtins/functions/standard_gates.py +651 -0
  386. classiq/qmod/builtins/operations.py +379 -57
  387. classiq/qmod/builtins/structs.py +103 -80
  388. classiq/qmod/cfunc.py +42 -0
  389. classiq/qmod/classical_function.py +8 -20
  390. classiq/qmod/cparam.py +64 -0
  391. classiq/qmod/create_model_function.py +56 -0
  392. classiq/qmod/declaration_inferrer.py +145 -112
  393. classiq/qmod/expression_query.py +39 -0
  394. classiq/qmod/generative.py +42 -0
  395. classiq/qmod/model_state_container.py +19 -5
  396. classiq/qmod/native/__init__.py +7 -0
  397. classiq/qmod/native/expression_to_qmod.py +194 -0
  398. classiq/qmod/native/pretty_printer.py +401 -0
  399. classiq/qmod/pretty_print/__init__.py +7 -0
  400. classiq/qmod/pretty_print/expression_to_python.py +222 -0
  401. classiq/qmod/pretty_print/pretty_printer.py +572 -0
  402. classiq/qmod/python_classical_type.py +67 -0
  403. classiq/qmod/qfunc.py +79 -0
  404. classiq/qmod/qmod_constant.py +143 -0
  405. classiq/qmod/qmod_parameter.py +84 -53
  406. classiq/qmod/qmod_variable.py +497 -100
  407. classiq/qmod/quantum_callable.py +17 -7
  408. classiq/qmod/quantum_expandable.py +278 -105
  409. classiq/qmod/quantum_function.py +232 -48
  410. classiq/qmod/semantics/__init__.py +0 -0
  411. classiq/qmod/semantics/annotation/__init__.py +0 -0
  412. classiq/qmod/semantics/annotation/call_annotation.py +92 -0
  413. classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
  414. classiq/qmod/semantics/error_manager.py +88 -0
  415. classiq/qmod/semantics/lambdas.py +25 -0
  416. classiq/qmod/semantics/static_semantics_visitor.py +384 -0
  417. classiq/qmod/semantics/validation/__init__.py +0 -0
  418. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  419. classiq/qmod/semantics/validation/func_call_validation.py +99 -0
  420. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  421. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  422. classiq/qmod/semantics/validation/main_validation.py +33 -0
  423. classiq/qmod/semantics/validation/types_validation.py +128 -0
  424. classiq/qmod/symbolic.py +178 -111
  425. classiq/qmod/symbolic_expr.py +36 -12
  426. classiq/qmod/symbolic_type.py +2 -5
  427. classiq/qmod/type_attribute_remover.py +32 -0
  428. classiq/qmod/utilities.py +108 -1
  429. classiq/qmod/write_qmod.py +53 -0
  430. classiq/synthesis.py +210 -22
  431. {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -8
  432. classiq-0.65.3.dist-info/RECORD +521 -0
  433. {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/WHEEL +1 -1
  434. classiq/_internals/_qfunc_ext.py +0 -6
  435. classiq/applications/benchmarking/__init__.py +0 -9
  436. classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
  437. classiq/applications/numpy_utils.py +0 -37
  438. classiq/applications_model_constructors/__init__.py +0 -17
  439. classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
  440. classiq/applications_model_constructors/grover_model_constructor.py +0 -227
  441. classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
  442. classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
  443. classiq/builtin_functions/__init__.py +0 -43
  444. classiq/builtin_functions/amplitude_loading.py +0 -3
  445. classiq/builtin_functions/binary_ops.py +0 -1
  446. classiq/builtin_functions/exponentiation.py +0 -5
  447. classiq/builtin_functions/qpe.py +0 -4
  448. classiq/builtin_functions/qsvm.py +0 -7
  449. classiq/builtin_functions/range_types.py +0 -5
  450. classiq/builtin_functions/standard_gates.py +0 -1
  451. classiq/builtin_functions/state_preparation.py +0 -6
  452. classiq/builtin_functions/suzuki_trotter.py +0 -3
  453. classiq/exceptions.py +0 -131
  454. classiq/interface/executor/aws_execution_cost.py +0 -72
  455. classiq/interface/executor/error_mitigation.py +0 -6
  456. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -115
  457. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -59
  458. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  459. classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
  460. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
  461. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  462. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  463. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  464. classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
  465. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  466. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
  467. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
  468. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -862
  469. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
  470. classiq/interface/generator/functions/foreign_function_definition.py +0 -106
  471. classiq/interface/generator/functions/function_implementation.py +0 -103
  472. classiq/interface/generator/functions/native_function_definition.py +0 -153
  473. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  474. classiq/interface/generator/functions/register.py +0 -42
  475. classiq/interface/generator/functions/register_mapping_data.py +0 -102
  476. classiq/interface/generator/inequality_mixer.py +0 -51
  477. classiq/interface/generator/model/classical_main_validator.py +0 -106
  478. classiq/interface/generator/range_mixer.py +0 -56
  479. classiq/interface/generator/state_propagator.py +0 -63
  480. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -2
  481. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
  482. classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
  483. classiq/interface/generator/types/combinatorial_problem.py +0 -26
  484. classiq/interface/ide/show.py +0 -34
  485. classiq/interface/model/common_model_types.py +0 -23
  486. classiq/interface/model/numeric_reinterpretation.py +0 -25
  487. classiq/interface/model/operator_synthesis_data.py +0 -48
  488. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  489. classiq/interface/model/quantum_if_operation.py +0 -95
  490. classiq/interface/model/resolvers/function_call_resolver.py +0 -43
  491. classiq/interface/model/validations/handle_validation_base.py +0 -55
  492. classiq/interface/model/validations/handles_validator.py +0 -154
  493. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  494. classiq/model/__init__.py +0 -14
  495. classiq/model/composite_function_generator.py +0 -33
  496. classiq/model/function_handler.py +0 -466
  497. classiq/model/function_handler.pyi +0 -152
  498. classiq/model/logic_flow.py +0 -149
  499. classiq/model/logic_flow_change_handler.py +0 -71
  500. classiq/model/model.py +0 -246
  501. classiq/qmod/builtins/functions.py +0 -896
  502. classiq/qmod/qmod_struct.py +0 -37
  503. classiq/quantum_functions/__init__.py +0 -17
  504. classiq/quantum_functions/annotation_parser.py +0 -207
  505. classiq/quantum_functions/decorators.py +0 -22
  506. classiq/quantum_functions/function_library.py +0 -181
  507. classiq/quantum_functions/function_parser.py +0 -74
  508. classiq/quantum_functions/quantum_function.py +0 -236
  509. classiq-0.37.1.dist-info/RECORD +0 -418
  510. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
  511. /classiq/{interface/generator/credit_risk_example → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
  512. /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/pauli_helpers}/__init__.py +0 -0
  513. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/py.typed} +0 -0
  514. /classiq/{interface/model/resolvers → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  515. /classiq/{interface/model/validations → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  516. /classiq/{_internals → interface}/enum_utils.py +0 -0
@@ -0,0 +1,158 @@
1
+ from collections.abc import Sequence
2
+ from enum import Enum
3
+ from typing import Any
4
+
5
+ from classiq.interface.exceptions import ClassiqExpansionError
6
+ from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
7
+ from classiq.interface.generator.expressions.qmod_struct_instance import (
8
+ QmodStructInstance,
9
+ )
10
+ from classiq.interface.generator.functions.classical_type import (
11
+ StructMetaType,
12
+ )
13
+ from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
14
+ from classiq.interface.generator.functions.type_name import (
15
+ TypeName,
16
+ )
17
+ from classiq.interface.model.classical_parameter_declaration import (
18
+ AnonClassicalParameterDeclaration,
19
+ )
20
+ from classiq.interface.model.port_declaration import AnonPortDeclaration
21
+ from classiq.interface.model.quantum_function_declaration import (
22
+ AnonPositionalArg,
23
+ AnonQuantumOperandDeclaration,
24
+ )
25
+
26
+ from classiq.model_expansions.closure import FunctionClosure
27
+ from classiq.model_expansions.evaluators.type_type_match import check_signature_match
28
+ from classiq.model_expansions.scope import Evaluated, QuantumSymbol
29
+ from classiq.qmod.model_state_container import QMODULE
30
+ from classiq.qmod.qmod_parameter import CInt, get_qmod_type
31
+
32
+
33
+ def check_type_match(
34
+ parameters: Sequence[AnonPositionalArg],
35
+ arguments: list[Evaluated],
36
+ function_name: str,
37
+ ) -> None:
38
+ if len(parameters) != len(arguments):
39
+ raise ClassiqExpansionError(
40
+ f"Function {function_name!r} takes {len(parameters)} arguments but "
41
+ f"{len(arguments)} were given"
42
+ )
43
+ for parameter, evaluated_arg in zip(parameters, arguments):
44
+ check_arg_type_match(evaluated_arg.value, parameter, function_name)
45
+
46
+
47
+ def check_arg_type_match(
48
+ argument: Any, parameter: AnonPositionalArg, function_name: str
49
+ ) -> None:
50
+ message_prefix = (
51
+ f"Argument {str(argument)!r} to parameter {parameter.name!r} of function "
52
+ f"{function_name!r} has incompatible type; "
53
+ )
54
+ if isinstance(parameter, AnonPortDeclaration):
55
+ error_message = message_prefix + "expected quantum variable"
56
+ _check_qvar_type_match(argument, error_message)
57
+ elif isinstance(parameter, AnonQuantumOperandDeclaration):
58
+ if parameter.is_list:
59
+ error_message = message_prefix + "expected list of operands"
60
+ _check_operand_list_type_match(
61
+ argument, parameter, function_name, error_message
62
+ )
63
+ else:
64
+ error_message = message_prefix + "expected operand"
65
+ _check_operand_type_match(argument, parameter, function_name, error_message)
66
+ elif isinstance(parameter, AnonClassicalParameterDeclaration):
67
+ error_message = (
68
+ message_prefix + f"expected {_resolve_type_name(parameter.classical_type)}"
69
+ )
70
+ _check_classical_type_match(argument, parameter, error_message)
71
+ else:
72
+ raise ClassiqExpansionError(
73
+ f"unexpected parameter declaration type: {type(parameter).__name__}"
74
+ )
75
+
76
+
77
+ def _check_qvar_type_match(argument: Any, error_message: str) -> None:
78
+ if not isinstance(argument, QuantumSymbol):
79
+ raise ClassiqExpansionError(error_message)
80
+
81
+
82
+ def _check_operand_list_type_match(
83
+ argument: Any,
84
+ parameter: AnonQuantumOperandDeclaration,
85
+ function_name: str,
86
+ error_message: str,
87
+ ) -> None:
88
+ if not isinstance(argument, list) or any(
89
+ not isinstance(op, FunctionClosure) for op in argument
90
+ ):
91
+ raise ClassiqExpansionError(error_message)
92
+ for idx, operand in enumerate(argument):
93
+ if operand.positional_arg_declarations is not None:
94
+ check_signature_match(
95
+ parameter.positional_arg_declarations,
96
+ operand.positional_arg_declarations,
97
+ f"operand #{idx + 1} in parameter {parameter.name!r} "
98
+ f"in function {function_name!r}",
99
+ )
100
+
101
+
102
+ def _check_operand_type_match(
103
+ argument: Any,
104
+ parameter: AnonQuantumOperandDeclaration,
105
+ function_name: str,
106
+ error_message: str,
107
+ ) -> None:
108
+ if not isinstance(argument, FunctionClosure):
109
+ raise ClassiqExpansionError(error_message)
110
+ if argument.positional_arg_declarations is not None:
111
+ check_signature_match(
112
+ parameter.positional_arg_declarations,
113
+ argument.positional_arg_declarations,
114
+ f"operand {parameter.name!r} in function {function_name!r}",
115
+ )
116
+
117
+
118
+ def _check_classical_type_match(
119
+ argument: Any, parameter: AnonClassicalParameterDeclaration, error_message: str
120
+ ) -> None:
121
+ classical_type = parameter.classical_type
122
+ type_name = _resolve_type_name(classical_type)
123
+ type_is_struct = (
124
+ isinstance(classical_type, TypeName)
125
+ and classical_type.name in QMODULE.type_decls
126
+ )
127
+ type_is_enum = (
128
+ isinstance(classical_type, TypeName)
129
+ and classical_type.name in QMODULE.enum_decls
130
+ )
131
+ arg_is_qvar = isinstance(argument, QmodSizedProxy)
132
+ arg_is_builtin = argument.__class__.__module__ == "builtins"
133
+ arg_is_enum = isinstance(argument, Enum)
134
+ arg_is_struct = isinstance(argument, QmodStructInstance)
135
+ arg_struct_name = None if not arg_is_struct else argument.struct_declaration.name
136
+ if (
137
+ arg_is_qvar
138
+ or (arg_is_builtin and (type_is_struct or type_is_enum))
139
+ or (arg_is_struct and (not type_is_struct or arg_struct_name != type_name))
140
+ or (
141
+ arg_is_enum
142
+ and get_qmod_type(classical_type) != CInt
143
+ and (not type_is_enum or type(argument).__name__ != type_name)
144
+ )
145
+ ):
146
+ raise ClassiqExpansionError(error_message)
147
+
148
+
149
+ def _resolve_type_name(classical_type: ConcreteClassicalType) -> str:
150
+ if isinstance(classical_type, StructMetaType):
151
+ type_name = "Struct"
152
+ else:
153
+ type_name = get_qmod_type(classical_type).__name__
154
+ if not isinstance(classical_type, TypeName):
155
+ return type_name
156
+ if type_name not in QMODULE.type_decls and type_name not in QMODULE.enum_decls:
157
+ raise ClassiqExpansionError(f"Undefined type {type_name}")
158
+ return type_name
@@ -0,0 +1,42 @@
1
+ from collections.abc import Sequence
2
+
3
+ from classiq.interface.generator.functions.port_declaration import (
4
+ PortDeclarationDirection,
5
+ )
6
+ from classiq.interface.model.port_declaration import AnonPortDeclaration
7
+ from classiq.interface.model.quantum_function_declaration import AnonPositionalArg
8
+
9
+ from classiq.model_expansions.evaluators.quantum_type_utils import copy_type_information
10
+ from classiq.model_expansions.scope import Evaluated, QuantumSymbol
11
+
12
+
13
+ def add_information_from_output_arguments(
14
+ parameters: Sequence[AnonPositionalArg],
15
+ args: list[Evaluated],
16
+ ) -> list[Evaluated]:
17
+ """
18
+ This function propagates the quantum type information from the output arguments
19
+ to the arguments that were passed to it.
20
+ Example:
21
+ ...
22
+ p = QArray("p", QBit)
23
+ allocate(4, p)
24
+ other statements with p...
25
+
26
+ In the other statements with p, the size of 4 will be part of p's type info.
27
+ """
28
+ for parameter, argument in zip(parameters, args):
29
+ if not isinstance(parameter, AnonPortDeclaration):
30
+ continue
31
+
32
+ argument_as_quantum_symbol = argument.as_type(QuantumSymbol)
33
+
34
+ if parameter.direction != PortDeclarationDirection.Output:
35
+ continue
36
+
37
+ copy_type_information(
38
+ parameter.quantum_type,
39
+ argument_as_quantum_symbol.quantum_type,
40
+ str(argument_as_quantum_symbol.handle),
41
+ )
42
+ return args
@@ -0,0 +1,36 @@
1
+ from typing import get_args
2
+
3
+ from classiq.interface.generator.expressions.evaluated_expression import (
4
+ EvaluatedExpression,
5
+ )
6
+ from classiq.interface.generator.expressions.expression import Expression
7
+ from classiq.interface.generator.expressions.expression_types import ExpressionValue
8
+ from classiq.interface.model.handle_binding import HandleBinding
9
+
10
+ from classiq.model_expansions.expression_evaluator import evaluate
11
+ from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
12
+
13
+
14
+ def evaluate_classical_expression(expr: Expression, scope: Scope) -> Evaluated:
15
+ all_symbols = scope.items()
16
+ locals_dict = {
17
+ name: EvaluatedExpression(value=evaluated.value)
18
+ for name, evaluated in all_symbols
19
+ if isinstance(evaluated.value, get_args(ExpressionValue))
20
+ } | {
21
+ name: EvaluatedExpression(
22
+ value=evaluated.value.quantum_type.get_proxy(HandleBinding(name=name))
23
+ )
24
+ for name, evaluated in all_symbols
25
+ if isinstance(evaluated.value, QuantumSymbol)
26
+ and evaluated.value.quantum_type.has_size_in_bits
27
+ }
28
+ uninitialized_locals = {
29
+ name
30
+ for name, evaluated in all_symbols
31
+ if isinstance(evaluated.value, QuantumSymbol)
32
+ and not evaluated.value.quantum_type.has_size_in_bits
33
+ }
34
+
35
+ ret = evaluate(expr, locals_dict, uninitialized_locals)
36
+ return Evaluated(value=ret.value)
@@ -0,0 +1,144 @@
1
+ from typing import Any
2
+
3
+ from sympy import Equality
4
+ from sympy.core.numbers import Number
5
+
6
+ from classiq.interface.exceptions import ClassiqExpansionError
7
+ from classiq.interface.generator.expressions.qmod_qscalar_proxy import (
8
+ QmodQNumProxy,
9
+ QmodQScalarProxy,
10
+ QmodSizedProxy,
11
+ )
12
+
13
+ CONTROL_INOUT_NAME = "ctrl"
14
+
15
+
16
+ def type_name(obj: Any) -> str:
17
+ if isinstance(obj, QmodSizedProxy):
18
+ return obj.type_name
19
+ return type(obj).__name__
20
+
21
+
22
+ def resolve_num_condition(condition: Equality) -> tuple[QmodSizedProxy, str]:
23
+ ctrl, ctrl_val = condition.args
24
+ if isinstance(ctrl, Number) and isinstance(ctrl_val, QmodQScalarProxy):
25
+ ctrl, ctrl_val = ctrl_val, ctrl
26
+ if not isinstance(ctrl, QmodSizedProxy) or not (isinstance(ctrl_val, Number)):
27
+ _raise_numeric_condition_error(ctrl, ctrl_val)
28
+ return ctrl, _calculate_ctrl_state(ctrl, float(ctrl_val))
29
+
30
+
31
+ def _calculate_ctrl_state(ctrl: QmodSizedProxy, ctrl_val: float) -> str:
32
+ is_signed, fraction_places = _get_numeric_attributes(ctrl)
33
+
34
+ integer_ctrl_val = _get_integer_ctrl_val(ctrl, ctrl_val, fraction_places)
35
+
36
+ _validate_control_value_sign(ctrl, integer_ctrl_val, is_signed)
37
+ _validate_control_var_qubits(
38
+ ctrl, integer_ctrl_val, is_signed, fraction_places, ctrl_val
39
+ )
40
+
41
+ return _to_twos_complement(integer_ctrl_val, ctrl.size)
42
+
43
+
44
+ def _get_numeric_attributes(ctrl: QmodSizedProxy) -> tuple[bool, int]:
45
+ return (
46
+ (ctrl.is_signed, ctrl.fraction_digits)
47
+ if isinstance(ctrl, QmodQNumProxy)
48
+ else (False, 0)
49
+ )
50
+
51
+
52
+ def _get_integer_ctrl_val(
53
+ ctrl: QmodSizedProxy, ctrl_val: float, fraction_places: int
54
+ ) -> int:
55
+ unfractioned_ctrl_val = ctrl_val * 2**fraction_places
56
+ if unfractioned_ctrl_val != int(unfractioned_ctrl_val):
57
+ raise ClassiqExpansionError(
58
+ f"Variable {str(ctrl)!r} doesne't have enough fraction digits to "
59
+ f"represent control value {ctrl_val}"
60
+ )
61
+ return int(unfractioned_ctrl_val)
62
+
63
+
64
+ def _validate_control_value_sign(
65
+ ctrl: QmodSizedProxy, ctrl_val: int, is_signed: bool
66
+ ) -> None:
67
+ if not is_signed and ctrl_val < 0:
68
+ raise ClassiqExpansionError(
69
+ f"Variable {str(ctrl)!r} is not signed but control value "
70
+ f"{ctrl_val} is negative"
71
+ )
72
+
73
+
74
+ def _validate_control_var_qubits(
75
+ ctrl: QmodSizedProxy,
76
+ ctrl_val: int,
77
+ is_signed: bool,
78
+ fraction_places: int,
79
+ orig_ctrl_val: float,
80
+ ) -> None:
81
+ required_qubits = _min_bit_length(ctrl_val, is_signed)
82
+ fraction_places_message = (
83
+ f" with {fraction_places} fraction digits" if fraction_places else ""
84
+ )
85
+ if ctrl.size < required_qubits:
86
+ raise ClassiqExpansionError(
87
+ f"Variable {str(ctrl)!r} has {ctrl.size} qubits{fraction_places_message} but control value "
88
+ f"{str(orig_ctrl_val if fraction_places else ctrl_val)!r} requires at least {required_qubits} qubits{fraction_places_message}"
89
+ )
90
+
91
+
92
+ def _raise_numeric_condition_error(ctrl: Any, ctrl_val: Any) -> None:
93
+ message = (
94
+ "Control condition must be of the form '<quantum-variable> == "
95
+ "<classical-number-expression>' or vice versa. "
96
+ )
97
+ prefix = f"Neither {ctrl!r} (type {type_name(ctrl)}) or {ctrl_val!r} (type {type_name(ctrl_val)}) is a "
98
+ if not isinstance(ctrl, QmodSizedProxy) and not isinstance(
99
+ ctrl_val, QmodSizedProxy
100
+ ):
101
+ message += prefix + "quantum variable."
102
+ elif not isinstance(ctrl, Number) and not isinstance(ctrl_val, Number):
103
+ message += prefix + "classical number."
104
+ raise ClassiqExpansionError(message)
105
+
106
+
107
+ def _min_unsigned_bit_length(number: int) -> int:
108
+ if number < 0:
109
+ raise ClassiqExpansionError(
110
+ f"Quantum register is not signed but control value "
111
+ f"'{number}' is negative"
112
+ )
113
+ try:
114
+ return 1 if number == 0 else number.bit_length()
115
+ except AttributeError as e:
116
+ raise e
117
+
118
+
119
+ def _min_signed_bit_length(number: int) -> int:
120
+ pos_val = abs(number)
121
+ is_whole = pos_val & (pos_val - 1) == 0
122
+ if number <= 0 and is_whole:
123
+ return _min_unsigned_bit_length(pos_val)
124
+ return _min_unsigned_bit_length(pos_val) + 1
125
+
126
+
127
+ def _min_bit_length(number: int, is_signed: bool) -> int:
128
+ return (
129
+ _min_signed_bit_length(number)
130
+ if is_signed
131
+ else _min_unsigned_bit_length(number)
132
+ )
133
+
134
+
135
+ def _to_twos_complement(value: int, bits: int) -> str:
136
+ if value >= 0:
137
+ return bin(value)[2:].zfill(bits)[::-1]
138
+ return _to_negative_twos_complement(value, bits)
139
+
140
+
141
+ def _to_negative_twos_complement(value: int, bits: int) -> str:
142
+ mask = (1 << bits) - 1
143
+ value = (abs(value) ^ mask) + 1
144
+ return bin(value)[:1:-1].rjust(bits, "1")
@@ -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