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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. classiq/__init__.py +47 -32
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
  3. classiq/_internals/api_wrapper.py +235 -97
  4. classiq/_internals/async_utils.py +1 -3
  5. classiq/_internals/authentication/auth0.py +26 -10
  6. classiq/_internals/authentication/authentication.py +11 -0
  7. classiq/_internals/authentication/device.py +10 -5
  8. classiq/_internals/authentication/password_manager.py +18 -6
  9. classiq/_internals/authentication/token_manager.py +10 -5
  10. classiq/_internals/client.py +94 -33
  11. classiq/_internals/config.py +3 -4
  12. classiq/_internals/host_checker.py +38 -15
  13. classiq/_internals/jobs.py +60 -57
  14. classiq/_internals/type_validation.py +9 -9
  15. classiq/analyzer/__init__.py +1 -3
  16. classiq/analyzer/analyzer.py +24 -19
  17. classiq/analyzer/analyzer_utilities.py +10 -10
  18. classiq/analyzer/rb.py +15 -15
  19. classiq/analyzer/show_interactive_hack.py +27 -4
  20. classiq/analyzer/url_utils.py +2 -3
  21. classiq/applications/__init__.py +3 -12
  22. classiq/applications/chemistry/__init__.py +14 -10
  23. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  24. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +165 -158
  25. classiq/applications/chemistry/ground_state_problem.py +1 -1
  26. classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +4 -1
  27. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
  28. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +1 -1
  29. classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +51 -15
  30. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +12 -12
  31. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +8 -6
  32. classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +7 -11
  33. classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +67 -40
  34. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
  35. classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
  36. classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +2 -2
  37. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +15 -20
  38. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +14 -15
  39. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +11 -15
  40. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +1 -2
  41. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
  42. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +2 -3
  43. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +5 -8
  44. classiq/applications/combinatorial_optimization/__init__.py +20 -6
  45. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  46. classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +35 -33
  47. classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
  48. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  49. classiq/applications/finance/__init__.py +4 -5
  50. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +48 -42
  51. classiq/applications/grover/__init__.py +9 -0
  52. classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +52 -51
  53. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  54. classiq/applications/libraries/qmci_library.py +22 -0
  55. classiq/applications/qnn/__init__.py +2 -4
  56. classiq/applications/qnn/circuit_utils.py +6 -6
  57. classiq/applications/qnn/datasets/__init__.py +9 -11
  58. classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
  59. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  60. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  61. classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
  62. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  63. classiq/applications/qnn/qlayer.py +30 -10
  64. classiq/applications/qnn/torch_utils.py +4 -3
  65. classiq/applications/qnn/types.py +5 -5
  66. classiq/applications/qsvm/__init__.py +6 -4
  67. classiq/applications/qsvm/qsvm.py +3 -6
  68. classiq/applications/qsvm/qsvm_data_generation.py +3 -3
  69. classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
  70. classiq/execution/__init__.py +8 -3
  71. classiq/execution/all_hardware_devices.py +11 -0
  72. classiq/execution/execution_session.py +400 -0
  73. classiq/execution/iqcc.py +63 -0
  74. classiq/execution/jobs.py +197 -25
  75. classiq/execution/qnn.py +79 -0
  76. classiq/executor.py +20 -115
  77. classiq/interface/_version.py +1 -1
  78. classiq/interface/analyzer/analysis_params.py +43 -13
  79. classiq/interface/analyzer/cytoscape_graph.py +15 -9
  80. classiq/interface/analyzer/result.py +28 -32
  81. classiq/interface/applications/qsvm.py +20 -29
  82. classiq/interface/ast_node.py +16 -0
  83. classiq/interface/backend/backend_preferences.py +390 -121
  84. classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
  85. classiq/interface/backend/pydantic_backend.py +25 -22
  86. classiq/interface/backend/quantum_backend_providers.py +69 -16
  87. classiq/interface/chemistry/fermionic_operator.py +30 -21
  88. classiq/interface/chemistry/ground_state_problem.py +28 -25
  89. classiq/interface/chemistry/molecule.py +14 -10
  90. classiq/interface/chemistry/operator.py +64 -231
  91. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  92. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
  93. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  94. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  95. classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
  96. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  97. classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
  98. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +8 -9
  99. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  100. classiq/interface/combinatorial_optimization/result.py +1 -3
  101. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  102. classiq/interface/debug_info/debug_info.py +86 -0
  103. classiq/{exceptions.py → interface/exceptions.py} +37 -9
  104. classiq/interface/execution/iqcc.py +19 -0
  105. classiq/interface/execution/jobs.py +15 -12
  106. classiq/interface/execution/primitives.py +18 -0
  107. classiq/interface/executor/constants.py +1 -0
  108. classiq/interface/executor/execution_preferences.py +26 -114
  109. classiq/interface/executor/execution_request.py +24 -46
  110. classiq/interface/executor/execution_result.py +30 -8
  111. classiq/interface/executor/iqae_result.py +4 -6
  112. classiq/interface/executor/optimizer_preferences.py +17 -14
  113. classiq/interface/executor/quantum_code.py +28 -24
  114. classiq/interface/executor/quantum_instruction_set.py +2 -2
  115. classiq/interface/executor/register_initialization.py +11 -14
  116. classiq/interface/executor/result.py +83 -56
  117. classiq/interface/executor/vqe_result.py +10 -10
  118. classiq/interface/finance/function_input.py +35 -25
  119. classiq/interface/finance/gaussian_model_input.py +5 -5
  120. classiq/interface/finance/log_normal_model_input.py +4 -4
  121. classiq/interface/finance/model_input.py +4 -4
  122. classiq/interface/generator/adjacency.py +1 -3
  123. classiq/interface/generator/amplitude_loading.py +22 -12
  124. classiq/interface/generator/ansatz_library.py +5 -5
  125. classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
  126. classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
  127. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
  128. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  129. classiq/interface/generator/application_apis/finance_declarations.py +48 -69
  130. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
  131. classiq/interface/generator/arith/argument_utils.py +46 -5
  132. classiq/interface/generator/arith/arithmetic.py +35 -16
  133. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +6 -7
  134. classiq/interface/generator/arith/arithmetic_expression_abc.py +66 -25
  135. classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -11
  136. classiq/interface/generator/arith/arithmetic_expression_validator.py +47 -43
  137. classiq/interface/generator/arith/arithmetic_operations.py +14 -6
  138. classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
  139. classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
  140. classiq/interface/generator/arith/ast_node_rewrite.py +3 -2
  141. classiq/interface/generator/arith/binary_ops.py +218 -130
  142. classiq/interface/generator/arith/endianness.py +1 -1
  143. classiq/interface/generator/arith/extremum_operations.py +96 -25
  144. classiq/interface/generator/arith/logical_ops.py +14 -12
  145. classiq/interface/generator/arith/number_utils.py +12 -6
  146. classiq/interface/generator/arith/register_user_input.py +60 -37
  147. classiq/interface/generator/arith/unary_ops.py +49 -29
  148. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  149. classiq/interface/generator/builtin_api_builder.py +2 -9
  150. classiq/interface/generator/chemistry_function_params.py +3 -3
  151. classiq/interface/generator/circuit_code/circuit_code.py +7 -7
  152. classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
  153. classiq/interface/generator/commuting_pauli_exponentiation.py +7 -7
  154. classiq/interface/generator/compiler_keywords.py +5 -1
  155. classiq/interface/generator/complex_type.py +13 -18
  156. classiq/interface/generator/constant.py +3 -4
  157. classiq/interface/generator/control_state.py +34 -29
  158. classiq/interface/generator/copy.py +47 -0
  159. classiq/interface/generator/custom_ansatz.py +2 -5
  160. classiq/interface/generator/distance.py +3 -5
  161. classiq/interface/generator/excitations.py +3 -2
  162. classiq/interface/generator/expressions/atomic_expression_functions.py +21 -5
  163. classiq/interface/generator/expressions/enums/__init__.py +0 -10
  164. classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
  165. classiq/interface/generator/expressions/evaluated_expression.py +5 -5
  166. classiq/interface/generator/expressions/expression.py +26 -14
  167. classiq/interface/generator/expressions/expression_constants.py +9 -3
  168. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  169. classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
  170. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +34 -8
  171. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
  172. classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
  173. classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
  174. classiq/interface/generator/expressions/sympy_supported_expressions.py +19 -11
  175. classiq/interface/generator/finance.py +2 -2
  176. classiq/interface/generator/function_param_library.py +6 -6
  177. classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
  178. classiq/interface/generator/function_params.py +36 -64
  179. classiq/interface/generator/functions/__init__.py +0 -22
  180. classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
  181. classiq/interface/generator/functions/classical_function_declaration.py +18 -9
  182. classiq/interface/generator/functions/classical_type.py +47 -166
  183. classiq/interface/generator/functions/concrete_types.py +55 -0
  184. classiq/interface/generator/functions/function_declaration.py +13 -14
  185. classiq/interface/generator/functions/port_declaration.py +1 -13
  186. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  187. classiq/interface/generator/functions/type_name.py +90 -0
  188. classiq/interface/generator/generated_circuit_data.py +153 -20
  189. classiq/interface/generator/grover_diffuser.py +32 -25
  190. classiq/interface/generator/grover_operator.py +34 -25
  191. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
  192. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  193. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +9 -9
  194. classiq/interface/generator/hardware/hardware_data.py +72 -34
  195. classiq/interface/generator/hardware_efficient_ansatz.py +20 -16
  196. classiq/interface/generator/hartree_fock.py +13 -5
  197. classiq/interface/generator/identity.py +10 -6
  198. classiq/interface/generator/linear_pauli_rotations.py +32 -20
  199. classiq/interface/generator/mcmt_method.py +1 -1
  200. classiq/interface/generator/mcu.py +17 -15
  201. classiq/interface/generator/mcx.py +24 -17
  202. classiq/interface/generator/model/__init__.py +2 -5
  203. classiq/interface/generator/model/constraints.py +26 -8
  204. classiq/interface/generator/model/model.py +27 -190
  205. classiq/interface/generator/model/preferences/preferences.py +115 -41
  206. classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +14 -17
  207. classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
  208. classiq/interface/generator/oracles/custom_oracle.py +15 -13
  209. classiq/interface/generator/oracles/oracle_abc.py +7 -7
  210. classiq/interface/generator/partitioned_register.py +7 -7
  211. classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
  212. classiq/interface/generator/preferences/optimization.py +1 -2
  213. classiq/interface/generator/qpe.py +41 -30
  214. classiq/interface/generator/qsvm.py +9 -10
  215. classiq/interface/generator/quantum_function_call.py +88 -73
  216. classiq/interface/generator/quantum_program.py +41 -24
  217. classiq/interface/generator/range_types.py +11 -12
  218. classiq/interface/generator/register_role.py +18 -6
  219. classiq/interface/generator/slice_parsing_utils.py +5 -5
  220. classiq/interface/generator/standard_gates/controlled_standard_gates.py +30 -39
  221. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  222. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  223. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  224. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  225. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  226. classiq/interface/generator/state_preparation/distributions.py +16 -15
  227. classiq/interface/generator/state_preparation/metrics.py +4 -7
  228. classiq/interface/generator/state_preparation/state_preparation.py +25 -20
  229. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  230. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
  231. classiq/interface/generator/transpiler_basis_gates.py +7 -3
  232. classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
  233. classiq/interface/generator/types/compilation_metadata.py +6 -0
  234. classiq/interface/generator/types/enum_declaration.py +54 -0
  235. classiq/interface/generator/types/qstruct_declaration.py +18 -0
  236. classiq/interface/generator/types/struct_declaration.py +7 -11
  237. classiq/interface/generator/ucc.py +5 -4
  238. classiq/interface/generator/unitary_gate.py +5 -5
  239. classiq/interface/generator/user_defined_function_params.py +4 -1
  240. classiq/interface/generator/validations/flow_graph.py +7 -7
  241. classiq/interface/generator/validations/validator_functions.py +4 -4
  242. classiq/interface/generator/visitor.py +23 -16
  243. classiq/interface/hardware.py +29 -8
  244. classiq/interface/helpers/classproperty.py +8 -0
  245. classiq/interface/helpers/custom_encoders.py +2 -2
  246. classiq/interface/helpers/custom_pydantic_types.py +40 -50
  247. classiq/interface/helpers/datastructures.py +26 -0
  248. classiq/interface/helpers/hashable_mixin.py +3 -2
  249. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  250. classiq/interface/helpers/pydantic_model_helpers.py +7 -5
  251. classiq/interface/helpers/validation_helpers.py +3 -20
  252. classiq/interface/helpers/versioned_model.py +1 -4
  253. classiq/interface/ide/ide_data.py +16 -20
  254. classiq/interface/ide/visual_model.py +130 -0
  255. classiq/interface/interface_version.py +1 -0
  256. classiq/interface/jobs.py +29 -69
  257. classiq/interface/model/allocate.py +16 -0
  258. classiq/interface/model/bind_operation.py +32 -9
  259. classiq/interface/model/classical_if.py +15 -0
  260. classiq/interface/model/classical_parameter_declaration.py +33 -3
  261. classiq/interface/model/control.py +45 -0
  262. classiq/interface/model/handle_binding.py +298 -20
  263. classiq/interface/model/inplace_binary_operation.py +29 -24
  264. classiq/interface/model/invert.py +12 -0
  265. classiq/interface/model/model.py +69 -61
  266. classiq/interface/model/native_function_definition.py +17 -20
  267. classiq/interface/model/parameter.py +13 -0
  268. classiq/interface/model/phase_operation.py +11 -0
  269. classiq/interface/model/port_declaration.py +27 -9
  270. classiq/interface/model/power.py +14 -0
  271. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +30 -18
  272. classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
  273. classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
  274. classiq/interface/model/quantum_function_call.py +141 -343
  275. classiq/interface/model/quantum_function_declaration.py +190 -157
  276. classiq/interface/model/quantum_lambda_function.py +33 -32
  277. classiq/interface/model/quantum_statement.py +71 -12
  278. classiq/interface/model/quantum_type.py +177 -40
  279. classiq/interface/model/quantum_variable_declaration.py +3 -25
  280. classiq/interface/model/repeat.py +15 -0
  281. classiq/interface/model/statement_block.py +40 -14
  282. classiq/interface/model/validation_handle.py +13 -6
  283. classiq/interface/model/variable_declaration_statement.py +3 -1
  284. classiq/interface/model/within_apply_operation.py +7 -5
  285. classiq/interface/server/global_versions.py +6 -7
  286. classiq/interface/server/routes.py +17 -21
  287. classiq/interface/source_reference.py +59 -0
  288. classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
  289. classiq/model_expansions/capturing/__init__.py +0 -0
  290. classiq/model_expansions/capturing/captured_vars.py +435 -0
  291. classiq/model_expansions/capturing/mangling_utils.py +56 -0
  292. classiq/model_expansions/closure.py +171 -0
  293. classiq/model_expansions/debug_flag.py +3 -0
  294. classiq/model_expansions/evaluators/__init__.py +0 -0
  295. classiq/model_expansions/evaluators/arg_type_match.py +158 -0
  296. classiq/model_expansions/evaluators/argument_types.py +42 -0
  297. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  298. classiq/model_expansions/evaluators/control.py +144 -0
  299. classiq/model_expansions/evaluators/parameter_types.py +226 -0
  300. classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
  301. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  302. classiq/model_expansions/expression_evaluator.py +135 -0
  303. classiq/model_expansions/expression_renamer.py +76 -0
  304. classiq/model_expansions/function_builder.py +247 -0
  305. classiq/model_expansions/generative_functions.py +158 -0
  306. classiq/model_expansions/interpreters/__init__.py +0 -0
  307. classiq/model_expansions/interpreters/base_interpreter.py +263 -0
  308. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
  309. classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
  310. classiq/model_expansions/model_tables.py +18 -0
  311. classiq/model_expansions/quantum_operations/__init__.py +9 -0
  312. classiq/model_expansions/quantum_operations/bind.py +60 -0
  313. classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
  314. classiq/model_expansions/quantum_operations/classicalif.py +53 -0
  315. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
  316. classiq/model_expansions/quantum_operations/emitter.py +181 -0
  317. classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
  318. classiq/model_expansions/quantum_operations/repeat.py +56 -0
  319. classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
  320. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  321. classiq/model_expansions/scope.py +240 -0
  322. classiq/model_expansions/scope_initialization.py +150 -0
  323. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  324. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  325. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
  326. classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
  327. classiq/model_expansions/transformers/__init__.py +0 -0
  328. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  329. classiq/model_expansions/transformers/var_splitter.py +299 -0
  330. classiq/model_expansions/utils/__init__.py +0 -0
  331. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  332. classiq/model_expansions/utils/handles_collector.py +33 -0
  333. classiq/model_expansions/visitors/__init__.py +0 -0
  334. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  335. classiq/model_expansions/visitors/variable_references.py +144 -0
  336. classiq/open_library/__init__.py +4 -0
  337. classiq/open_library/functions/__init__.py +130 -0
  338. classiq/open_library/functions/amplitude_estimation.py +30 -0
  339. classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
  340. classiq/open_library/functions/grover.py +157 -0
  341. classiq/open_library/functions/hea.py +115 -0
  342. classiq/open_library/functions/linear_pauli_rotation.py +82 -0
  343. classiq/open_library/functions/modular_exponentiation.py +201 -0
  344. classiq/open_library/functions/qaoa_penalty.py +117 -0
  345. classiq/open_library/functions/qft_functions.py +54 -0
  346. classiq/open_library/functions/qpe.py +46 -0
  347. classiq/open_library/functions/qsvt.py +331 -0
  348. classiq/open_library/functions/state_preparation.py +301 -0
  349. classiq/open_library/functions/swap_test.py +27 -0
  350. classiq/open_library/functions/utility_functions.py +81 -0
  351. classiq/open_library/functions/variational.py +52 -0
  352. classiq/qmod/__init__.py +10 -10
  353. classiq/qmod/builtins/__init__.py +19 -2
  354. classiq/qmod/builtins/classical_execution_primitives.py +36 -14
  355. classiq/qmod/builtins/classical_functions.py +39 -43
  356. classiq/qmod/builtins/constants.py +10 -0
  357. classiq/qmod/builtins/enums.py +208 -0
  358. classiq/qmod/builtins/functions/__init__.py +137 -0
  359. classiq/qmod/builtins/functions/allocation.py +150 -0
  360. classiq/qmod/builtins/functions/arithmetic.py +55 -0
  361. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  362. classiq/qmod/builtins/functions/chemistry.py +91 -0
  363. classiq/qmod/builtins/functions/exponentiation.py +105 -0
  364. classiq/qmod/builtins/functions/finance.py +34 -0
  365. classiq/qmod/builtins/functions/operators.py +16 -0
  366. classiq/qmod/builtins/functions/qsvm.py +24 -0
  367. classiq/qmod/builtins/functions/standard_gates.py +651 -0
  368. classiq/qmod/builtins/operations.py +373 -40
  369. classiq/qmod/builtins/structs.py +103 -80
  370. classiq/qmod/cfunc.py +2 -2
  371. classiq/qmod/classical_function.py +4 -8
  372. classiq/qmod/cparam.py +64 -0
  373. classiq/qmod/create_model_function.py +56 -0
  374. classiq/qmod/declaration_inferrer.py +143 -101
  375. classiq/qmod/expression_query.py +20 -4
  376. classiq/qmod/generative.py +42 -0
  377. classiq/qmod/model_state_container.py +18 -6
  378. classiq/qmod/native/__init__.py +7 -0
  379. classiq/qmod/native/expression_to_qmod.py +16 -11
  380. classiq/qmod/native/pretty_printer.py +187 -97
  381. classiq/qmod/pretty_print/__init__.py +7 -0
  382. classiq/qmod/pretty_print/expression_to_python.py +222 -0
  383. classiq/qmod/pretty_print/pretty_printer.py +572 -0
  384. classiq/qmod/python_classical_type.py +67 -0
  385. classiq/qmod/qfunc.py +60 -8
  386. classiq/qmod/qmod_constant.py +93 -26
  387. classiq/qmod/qmod_parameter.py +68 -59
  388. classiq/qmod/qmod_variable.py +468 -155
  389. classiq/qmod/quantum_callable.py +17 -7
  390. classiq/qmod/quantum_expandable.py +269 -96
  391. classiq/qmod/quantum_function.py +196 -41
  392. classiq/qmod/semantics/__init__.py +0 -0
  393. classiq/qmod/semantics/annotation/__init__.py +0 -0
  394. classiq/qmod/semantics/annotation/call_annotation.py +92 -0
  395. classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
  396. classiq/qmod/semantics/error_manager.py +88 -0
  397. classiq/qmod/semantics/lambdas.py +25 -0
  398. classiq/qmod/semantics/static_semantics_visitor.py +384 -0
  399. classiq/qmod/semantics/validation/__init__.py +0 -0
  400. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  401. classiq/qmod/semantics/validation/func_call_validation.py +99 -0
  402. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  403. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  404. classiq/qmod/semantics/validation/main_validation.py +33 -0
  405. classiq/qmod/semantics/validation/types_validation.py +128 -0
  406. classiq/qmod/symbolic.py +147 -123
  407. classiq/qmod/symbolic_expr.py +27 -12
  408. classiq/qmod/symbolic_type.py +2 -5
  409. classiq/qmod/type_attribute_remover.py +32 -0
  410. classiq/qmod/utilities.py +98 -4
  411. classiq/qmod/write_qmod.py +17 -3
  412. classiq/synthesis.py +210 -22
  413. {classiq-0.38.0.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -9
  414. classiq-0.65.3.dist-info/RECORD +521 -0
  415. classiq/_internals/_qfunc_ext.py +0 -6
  416. classiq/applications/benchmarking/__init__.py +0 -9
  417. classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
  418. classiq/applications/numpy_utils.py +0 -37
  419. classiq/applications_model_constructors/__init__.py +0 -25
  420. classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
  421. classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -65
  422. classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +0 -243
  423. classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
  424. classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
  425. classiq/builtin_functions/__init__.py +0 -43
  426. classiq/builtin_functions/amplitude_loading.py +0 -3
  427. classiq/builtin_functions/binary_ops.py +0 -1
  428. classiq/builtin_functions/exponentiation.py +0 -5
  429. classiq/builtin_functions/qpe.py +0 -4
  430. classiq/builtin_functions/qsvm.py +0 -7
  431. classiq/builtin_functions/range_types.py +0 -5
  432. classiq/builtin_functions/standard_gates.py +0 -1
  433. classiq/builtin_functions/state_preparation.py +0 -6
  434. classiq/builtin_functions/suzuki_trotter.py +0 -3
  435. classiq/interface/executor/aws_execution_cost.py +0 -73
  436. classiq/interface/executor/error_mitigation.py +0 -6
  437. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
  438. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
  439. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  440. classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
  441. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
  442. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  443. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  444. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  445. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  446. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
  447. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
  448. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -1229
  449. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
  450. classiq/interface/generator/functions/foreign_function_definition.py +0 -114
  451. classiq/interface/generator/functions/function_implementation.py +0 -107
  452. classiq/interface/generator/functions/native_function_definition.py +0 -155
  453. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  454. classiq/interface/generator/functions/register.py +0 -44
  455. classiq/interface/generator/functions/register_mapping_data.py +0 -106
  456. classiq/interface/generator/inequality_mixer.py +0 -51
  457. classiq/interface/generator/model/classical_main_validator.py +0 -106
  458. classiq/interface/generator/range_mixer.py +0 -56
  459. classiq/interface/generator/state_propagator.py +0 -74
  460. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  461. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
  462. classiq/interface/ide/show.py +0 -34
  463. classiq/interface/model/call_synthesis_data.py +0 -68
  464. classiq/interface/model/common_model_types.py +0 -23
  465. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  466. classiq/interface/model/quantum_if_operation.py +0 -94
  467. classiq/interface/model/resolvers/function_call_resolver.py +0 -43
  468. classiq/interface/model/validations/handle_validation_base.py +0 -55
  469. classiq/interface/model/validations/handles_validator.py +0 -156
  470. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  471. classiq/model/__init__.py +0 -14
  472. classiq/model/composite_function_generator.py +0 -33
  473. classiq/model/function_handler.py +0 -462
  474. classiq/model/logic_flow.py +0 -149
  475. classiq/model/logic_flow_change_handler.py +0 -71
  476. classiq/model/model.py +0 -229
  477. classiq/qmod/builtins/functions.py +0 -913
  478. classiq/qmod/qmod_struct.py +0 -37
  479. classiq/quantum_functions/__init__.py +0 -17
  480. classiq/quantum_functions/annotation_parser.py +0 -205
  481. classiq/quantum_functions/decorators.py +0 -22
  482. classiq/quantum_functions/function_library.py +0 -181
  483. classiq/quantum_functions/function_parser.py +0 -74
  484. classiq/quantum_functions/quantum_function.py +0 -236
  485. classiq-0.38.0.dist-info/RECORD +0 -454
  486. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
  487. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
  488. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
  489. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
  490. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
  491. /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  492. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  493. /classiq/{interface/generator/credit_risk_example → applications/hamiltonian}/__init__.py +0 -0
  494. /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
  495. /classiq/interface/{model/resolvers → debug_info}/__init__.py +0 -0
  496. /classiq/{_internals → interface}/enum_utils.py +0 -0
  497. /classiq/interface/{model/validations → generator/functions/builtins}/__init__.py +0 -0
  498. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → model_expansions/__init__.py} +0 -0
  499. {classiq-0.38.0.dist-info → classiq-0.65.3.dist-info}/WHEEL +0 -0
@@ -1,37 +1,49 @@
1
1
  import abc
2
2
  import sys
3
+ from collections.abc import Iterator, Mapping
3
4
  from contextlib import contextmanager
4
- from typing import _GenericAlias # type: ignore[attr-defined]
5
- from typing import (
5
+ from typing import ( # type: ignore[attr-defined]
6
6
  TYPE_CHECKING,
7
+ Annotated,
7
8
  Any,
8
9
  ForwardRef,
9
10
  Generic,
10
- Iterator,
11
11
  Literal,
12
12
  Optional,
13
- Tuple,
14
- Type,
15
13
  TypeVar,
16
14
  Union,
15
+ _GenericAlias,
16
+ cast,
17
17
  get_args,
18
18
  get_origin,
19
- overload,
20
19
  )
21
20
 
22
- from typing_extensions import Annotated, ParamSpec, Self, _AnnotatedAlias
21
+ from typing_extensions import ParamSpec, Self, _AnnotatedAlias
23
22
 
23
+ from classiq.interface.exceptions import ClassiqValueError
24
24
  from classiq.interface.generator.expressions.expression import Expression
25
+ from classiq.interface.generator.expressions.qmod_qarray_proxy import (
26
+ ILLEGAL_SLICE_MSG,
27
+ ILLEGAL_SLICING_STEP_MSG,
28
+ )
25
29
  from classiq.interface.generator.functions.port_declaration import (
26
30
  PortDeclarationDirection,
27
31
  )
28
- from classiq.interface.model.handle_binding import HandleBinding, SlicedHandleBinding
29
- from classiq.interface.model.port_declaration import PortDeclaration
32
+ from classiq.interface.generator.functions.type_name import TypeName
33
+ from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
34
+ from classiq.interface.model.handle_binding import (
35
+ FieldHandleBinding,
36
+ HandleBinding,
37
+ SlicedHandleBinding,
38
+ SubscriptHandleBinding,
39
+ )
40
+ from classiq.interface.model.port_declaration import AnonPortDeclaration
30
41
  from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
31
42
  AmplitudeLoadingOperation,
32
43
  )
33
44
  from classiq.interface.model.quantum_expressions.arithmetic_operation import (
34
45
  ArithmeticOperation,
46
+ ArithmeticOperationKind,
35
47
  )
36
48
  from classiq.interface.model.quantum_type import (
37
49
  QuantumBit,
@@ -39,17 +51,24 @@ from classiq.interface.model.quantum_type import (
39
51
  QuantumNumeric,
40
52
  QuantumType,
41
53
  )
54
+ from classiq.interface.source_reference import SourceReference
42
55
 
43
- from classiq.exceptions import ClassiqValueError
44
- from classiq.qmod.qmod_parameter import ArrayBase, QParam, QParamScalar
56
+ from classiq.qmod.cparam import ArrayBase, CInt, CParamScalar
57
+ from classiq.qmod.generative import (
58
+ generative_mode_context,
59
+ interpret_expression,
60
+ is_generative_mode,
61
+ )
62
+ from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
45
63
  from classiq.qmod.quantum_callable import QCallable
46
64
  from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
47
65
  from classiq.qmod.symbolic_type import SymbolicTypes
48
- from classiq.qmod.utilities import version_portable_get_args
49
-
50
- ILLEGAL_SLICING_STEP_MSG = "Slicing with a step of a quantum variable is not supported"
51
- SLICE_OUT_OF_BOUNDS_MSG = "Slice end index out of bounds"
52
- UNSUPPORTED_ELEMENT_TYPE = "Only QBit is supported as element type for QArray"
66
+ from classiq.qmod.utilities import (
67
+ get_source_ref,
68
+ unwrap_forward_ref,
69
+ varname,
70
+ version_portable_get_args,
71
+ )
53
72
 
54
73
 
55
74
  def _is_input_output_typehint(type_hint: Any) -> bool:
@@ -77,28 +96,59 @@ def _no_current_expandable() -> Iterator[None]:
77
96
  QCallable.CURRENT_EXPANDABLE = current_expandable
78
97
 
79
98
 
80
- class QVar:
81
- def __init__(self, name: str) -> None:
82
- self._name = name
83
- if QCallable.CURRENT_EXPANDABLE is not None:
99
+ def _infer_variable_name(name: Any, depth: int) -> Any:
100
+ if name is not None:
101
+ return name
102
+ name = varname(depth + 1)
103
+ if name is None:
104
+ raise ClassiqValueError(
105
+ "Could not infer variable name. Please specify the variable name explicitly"
106
+ )
107
+ return name
108
+
109
+
110
+ class QVar(Symbolic):
111
+ CONSTRUCTOR_DEPTH: int = 1
112
+
113
+ def __init__(
114
+ self,
115
+ origin: Union[None, str, HandleBinding] = None,
116
+ *,
117
+ expr_str: Optional[str] = None,
118
+ depth: int = 2,
119
+ ) -> None:
120
+ name = _infer_variable_name(origin, self.CONSTRUCTOR_DEPTH)
121
+ super().__init__(str(name), True)
122
+ source_ref = (
123
+ get_source_ref(sys._getframe(depth))
124
+ if isinstance(name, str)
125
+ else name.source_ref
126
+ )
127
+ self._base_handle: HandleBinding = (
128
+ HandleBinding(name=name) if isinstance(name, str) else name
129
+ )
130
+ if isinstance(name, str) and QCallable.CURRENT_EXPANDABLE is not None:
84
131
  QCallable.CURRENT_EXPANDABLE.add_local_handle(
85
- self._name, self.get_qmod_type()
132
+ name, self.get_qmod_type(), source_ref
86
133
  )
134
+ self._expr_str = expr_str if expr_str is not None else str(name)
87
135
 
88
- @abc.abstractmethod
89
136
  def get_handle_binding(self) -> HandleBinding:
90
- raise NotImplementedError()
137
+ return self._base_handle
91
138
 
92
139
  @abc.abstractmethod
93
140
  def get_qmod_type(self) -> QuantumType:
94
141
  raise NotImplementedError()
95
142
 
96
143
  @staticmethod
97
- def from_type_hint(type_hint: Any) -> Optional[Type["QVar"]]:
144
+ def from_type_hint(type_hint: Any) -> Optional[type["QVar"]]:
98
145
  if _is_input_output_typehint(type_hint):
99
146
  return QVar.from_type_hint(type_hint.__args__[0])
100
147
  type_ = get_origin(type_hint) or type_hint
101
148
  if issubclass(type_, QVar):
149
+ if issubclass(type_, QStruct):
150
+ with _no_current_expandable():
151
+ type_("DUMMY")._add_qmod_qstruct(qmodule=QMODULE)
102
152
  return type_
103
153
  return None
104
154
 
@@ -107,6 +157,16 @@ class QVar:
107
157
  def to_qmod_quantum_type(cls, type_hint: Any) -> QuantumType:
108
158
  raise NotImplementedError()
109
159
 
160
+ @classmethod
161
+ @abc.abstractmethod
162
+ def to_qvar(
163
+ cls,
164
+ origin: Union[str, HandleBinding],
165
+ type_hint: Any,
166
+ expr_str: Optional[str],
167
+ ) -> Self:
168
+ raise NotImplementedError()
169
+
110
170
  @classmethod
111
171
  def port_direction(cls, type_hint: Any) -> PortDeclarationDirection:
112
172
  if _is_input_output_typehint(type_hint):
@@ -115,6 +175,16 @@ class QVar:
115
175
  assert type_hint == cls or get_origin(type_hint) == cls
116
176
  return PortDeclarationDirection.Inout
117
177
 
178
+ def __str__(self) -> str:
179
+ return self._expr_str
180
+
181
+ @property
182
+ def size(self) -> Union[CParamScalar, int]:
183
+ if is_generative_mode():
184
+ with generative_mode_context(False):
185
+ return interpret_expression(str(self.size))
186
+ return CParamScalar(f"get_field({self}, 'size')")
187
+
118
188
 
119
189
  _Q = TypeVar("_Q", bound=QVar)
120
190
  Output = Annotated[_Q, PortDeclarationDirection.Output]
@@ -122,11 +192,25 @@ Input = Annotated[_Q, PortDeclarationDirection.Input]
122
192
 
123
193
 
124
194
  class QScalar(QVar, SymbolicExpr):
125
- def __init__(self, name: str) -> None:
126
- QVar.__init__(self, name)
127
- SymbolicExpr.__init__(self, name)
195
+ CONSTRUCTOR_DEPTH: int = 2
128
196
 
129
- def _insert_arith_operation(self, expr: SymbolicTypes, inplace: bool) -> None:
197
+ def __init__(
198
+ self,
199
+ origin: Union[None, str, HandleBinding] = None,
200
+ *,
201
+ _expr_str: Optional[str] = None,
202
+ depth: int = 2,
203
+ ) -> None:
204
+ origin = _infer_variable_name(origin, self.CONSTRUCTOR_DEPTH)
205
+ QVar.__init__(self, origin, expr_str=_expr_str, depth=depth)
206
+ SymbolicExpr.__init__(self, str(origin), True)
207
+
208
+ def _insert_arith_operation(
209
+ self,
210
+ expr: SymbolicTypes,
211
+ kind: ArithmeticOperationKind,
212
+ source_ref: SourceReference,
213
+ ) -> None:
130
214
  # Fixme: Arithmetic operations are not yet supported on slices (see CAD-12670)
131
215
  if TYPE_CHECKING:
132
216
  assert QCallable.CURRENT_EXPANDABLE is not None
@@ -134,30 +218,33 @@ class QScalar(QVar, SymbolicExpr):
134
218
  ArithmeticOperation(
135
219
  expression=Expression(expr=str(expr)),
136
220
  result_var=self.get_handle_binding(),
137
- inplace_result=inplace,
221
+ operation_kind=kind,
222
+ source_ref=source_ref,
138
223
  )
139
224
  )
140
225
 
141
- def _insert_amplitude_loading(self, expr: SymbolicTypes) -> None:
226
+ def _insert_amplitude_loading(
227
+ self, expr: SymbolicTypes, source_ref: SourceReference
228
+ ) -> None:
142
229
  if TYPE_CHECKING:
143
230
  assert QCallable.CURRENT_EXPANDABLE is not None
144
231
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
145
232
  AmplitudeLoadingOperation(
146
233
  expression=Expression(expr=str(expr)),
147
234
  result_var=self.get_handle_binding(),
235
+ source_ref=source_ref,
148
236
  )
149
237
  )
150
238
 
151
- def get_handle_binding(self) -> HandleBinding:
152
- return HandleBinding(name=self._name)
153
-
154
239
  def __ior__(self, other: Any) -> Self:
155
240
  if not isinstance(other, get_args(SymbolicTypes)):
156
241
  raise TypeError(
157
242
  f"Invalid argument {other!r} for out-of-place arithmetic operation"
158
243
  )
159
244
 
160
- self._insert_arith_operation(other, False)
245
+ self._insert_arith_operation(
246
+ other, ArithmeticOperationKind.Assignment, get_source_ref(sys._getframe(1))
247
+ )
161
248
  return self
162
249
 
163
250
  def __ixor__(self, other: Any) -> Self:
@@ -166,7 +253,20 @@ class QScalar(QVar, SymbolicExpr):
166
253
  f"Invalid argument {other!r} for in-place arithmetic operation"
167
254
  )
168
255
 
169
- self._insert_arith_operation(other, True)
256
+ self._insert_arith_operation(
257
+ other, ArithmeticOperationKind.InplaceXor, get_source_ref(sys._getframe(1))
258
+ )
259
+ return self
260
+
261
+ def __iadd__(self, other: Any) -> Self:
262
+ if not isinstance(other, get_args(SymbolicTypes)):
263
+ raise TypeError(
264
+ f"Invalid argument {other!r} for in-place arithmetic operation"
265
+ )
266
+
267
+ self._insert_arith_operation(
268
+ other, ArithmeticOperationKind.InplaceAdd, get_source_ref(sys._getframe(1))
269
+ )
170
270
  return self
171
271
 
172
272
  def __imul__(self, other: Any) -> Self:
@@ -175,7 +275,7 @@ class QScalar(QVar, SymbolicExpr):
175
275
  f"Invalid argument {other!r} for out of ampltiude encoding operation"
176
276
  )
177
277
 
178
- self._insert_amplitude_loading(other)
278
+ self._insert_amplitude_loading(other, get_source_ref(sys._getframe(1)))
179
279
  return self
180
280
 
181
281
 
@@ -184,6 +284,15 @@ class QBit(QScalar):
184
284
  def to_qmod_quantum_type(cls, type_hint: Any) -> QuantumType:
185
285
  return QuantumBit()
186
286
 
287
+ @classmethod
288
+ def to_qvar(
289
+ cls,
290
+ origin: Union[str, HandleBinding],
291
+ type_hint: Any,
292
+ expr_str: Optional[str],
293
+ ) -> "QBit":
294
+ return QBit(origin, _expr_str=expr_str)
295
+
187
296
  def get_qmod_type(self) -> QuantumType:
188
297
  return QuantumBit()
189
298
 
@@ -192,80 +301,111 @@ _P = ParamSpec("_P")
192
301
 
193
302
 
194
303
  class QNum(Generic[_P], QScalar):
195
- QMOD_TYPE = QuantumNumeric
196
-
197
- @overload
198
- def __init__(self, name: str):
199
- pass
200
-
201
- @overload
202
- def __init__(
203
- self,
204
- name: str,
205
- size: Union[int, QParam[int]],
206
- is_signed: Union[bool, QParam[bool]],
207
- fraction_digits: Union[int, QParam[int]],
208
- ):
209
- pass
304
+ CONSTRUCTOR_DEPTH: int = 3
210
305
 
211
306
  def __init__(
212
307
  self,
213
- name: str,
214
- size: Union[int, QParam[int], None] = None,
215
- is_signed: Union[bool, QParam[bool], None] = None,
216
- fraction_digits: Union[int, QParam[int], None] = None,
308
+ name: Union[None, str, HandleBinding] = None,
309
+ size: Union[int, CInt, Expression, SymbolicExpr, None] = None,
310
+ is_signed: Union[bool, Expression, SymbolicExpr, None] = None,
311
+ fraction_digits: Union[int, CInt, Expression, None] = None,
312
+ _expr_str: Optional[str] = None,
217
313
  ):
218
- if (
219
- size is None
220
- and (is_signed is not None or fraction_digits is not None)
221
- or size is not None
222
- and (is_signed is None or fraction_digits is None)
223
- ):
314
+ if size is None and (is_signed is not None or fraction_digits is not None):
315
+ raise ClassiqValueError(
316
+ "Cannot assign 'is_signed' and 'fraction_digits' without 'size'"
317
+ )
318
+ if is_signed is not None and fraction_digits is None:
224
319
  raise ClassiqValueError(
225
- "Assign none or all of size, is_signed, and fraction_digits"
320
+ "Cannot assign 'is_signed' without 'fraction_digits'"
226
321
  )
227
- self._size = None if size is None else Expression(expr=str(size))
228
- self._is_signed = None if is_signed is None else Expression(expr=str(is_signed))
322
+ if is_signed is None and fraction_digits is not None:
323
+ raise ClassiqValueError(
324
+ "Cannot assign 'fraction_digits' without 'is_signed'"
325
+ )
326
+ self._size = (
327
+ size
328
+ if size is None or isinstance(size, Expression)
329
+ else Expression(expr=str(size))
330
+ )
331
+ self._is_signed = (
332
+ is_signed
333
+ if is_signed is None or isinstance(is_signed, Expression)
334
+ else Expression(expr=str(is_signed))
335
+ )
229
336
  self._fraction_digits = (
230
- None if fraction_digits is None else Expression(expr=str(fraction_digits))
337
+ fraction_digits
338
+ if fraction_digits is None or isinstance(fraction_digits, Expression)
339
+ else Expression(expr=str(fraction_digits))
231
340
  )
232
- super().__init__(name)
341
+ super().__init__(name, _expr_str=_expr_str, depth=3)
233
342
 
234
343
  @classmethod
235
- def to_qmod_quantum_type(cls, type_hint: Any) -> QuantumType:
236
- type_args = get_args(type_hint)
344
+ def _get_attributes(cls, type_hint: Any) -> tuple[Any, Any, Any]:
345
+ type_args = version_portable_get_args(type_hint)
237
346
  if len(type_args) == 0:
238
- return cls.QMOD_TYPE()
239
- type_args = type_args[0]
240
- if len(type_args) != 3:
347
+ return None, None, None
348
+ if len(type_args) not in (1, 3):
241
349
  raise ClassiqValueError(
242
- "QNum receives three type arguments: QNum[size: int | QParam[int], "
243
- "is_signed: bool | QParam[bool], fraction_digits: int | QParam[int]]"
350
+ "QNum receives three type arguments: QNum[size: int | CInt, "
351
+ "is_signed: bool | CBool, fraction_digits: int | CInt]"
244
352
  )
245
- return cls.QMOD_TYPE(
246
- size=Expression(expr=get_type_hint_expr(type_args[0])),
247
- is_signed=Expression(expr=get_type_hint_expr(type_args[1])),
248
- fraction_digits=Expression(expr=get_type_hint_expr(type_args[2])),
353
+ if len(type_args) == 1:
354
+ return unwrap_forward_ref(type_args[0]), None, None
355
+ return (
356
+ unwrap_forward_ref(type_args[0]),
357
+ unwrap_forward_ref(type_args[1]),
358
+ unwrap_forward_ref(type_args[2]),
359
+ )
360
+
361
+ @classmethod
362
+ def to_qmod_quantum_type(cls, type_hint: Any) -> QuantumType:
363
+ size, is_signed, fraction_digits = cls._get_attributes(type_hint)
364
+ return QuantumNumeric(
365
+ size=(
366
+ Expression(expr=get_type_hint_expr(size)) if size is not None else None
367
+ ),
368
+ is_signed=(
369
+ Expression(expr=get_type_hint_expr(is_signed))
370
+ if is_signed is not None
371
+ else None
372
+ ),
373
+ fraction_digits=(
374
+ Expression(expr=get_type_hint_expr(fraction_digits))
375
+ if fraction_digits is not None
376
+ else None
377
+ ),
249
378
  )
250
379
 
380
+ @classmethod
381
+ def to_qvar(
382
+ cls,
383
+ origin: Union[str, HandleBinding],
384
+ type_hint: Any,
385
+ expr_str: Optional[str],
386
+ ) -> "QNum":
387
+ return QNum(origin, *cls._get_attributes(type_hint), _expr_str=expr_str)
388
+
251
389
  def get_qmod_type(self) -> QuantumType:
252
- return self.QMOD_TYPE(
390
+ return QuantumNumeric(
253
391
  size=self._size,
254
392
  is_signed=self._is_signed,
255
393
  fraction_digits=self._fraction_digits,
256
394
  )
257
395
 
258
396
  @property
259
- def size(self) -> QParamScalar:
260
- return QParamScalar(f"len({self._name})")
397
+ def fraction_digits(self) -> Union[CParamScalar, int]:
398
+ if is_generative_mode():
399
+ with generative_mode_context(False):
400
+ return interpret_expression(str(self.fraction_digits))
401
+ return CParamScalar(f"get_field({self}, 'fraction_digits')")
261
402
 
262
403
  @property
263
- def fraction_digits(self) -> QParamScalar:
264
- return QParamScalar(f"fraction_digits({self._name})")
265
-
266
- @property
267
- def is_signed(self) -> QParamScalar:
268
- return QParamScalar(f"is_signed({self._name})")
404
+ def is_signed(self) -> Union[CParamScalar, bool]:
405
+ if is_generative_mode():
406
+ with generative_mode_context(False):
407
+ return interpret_expression(str(self.is_signed))
408
+ return CParamScalar(f"get_field({self}, 'is_signed')")
269
409
 
270
410
  # Support comma-separated generic args in older Python versions
271
411
  if sys.version_info[0:2] < (3, 10):
@@ -275,101 +415,274 @@ class QNum(Generic[_P], QScalar):
275
415
 
276
416
 
277
417
  class QArray(ArrayBase[_P], QVar):
418
+ CONSTRUCTOR_DEPTH: int = 3
419
+
420
+ # TODO [CAD-18620]: improve type hints
278
421
  def __init__(
279
422
  self,
280
- name: str,
281
- element_type: _GenericAlias = QBit,
282
- length: Optional[Union[int, QParam[int]]] = None,
283
- slice_: Optional[Tuple[int, int]] = None,
423
+ name: Union[None, str, HandleBinding] = None,
424
+ element_type: Union[_GenericAlias, QuantumType] = QBit,
425
+ length: Optional[Union[int, SymbolicExpr, Expression]] = None,
426
+ _expr_str: Optional[str] = None,
284
427
  ) -> None:
285
- if element_type is not QBit:
286
- raise ClassiqValueError(UNSUPPORTED_ELEMENT_TYPE)
287
428
  self._element_type = element_type
288
- self._length = length
289
- self._slice = slice_
290
- super().__init__(name)
429
+ self._length = (
430
+ length
431
+ if length is None or isinstance(length, Expression)
432
+ else Expression(expr=str(length))
433
+ )
434
+ super().__init__(name, expr_str=_expr_str)
291
435
 
292
- def get_handle_binding(self) -> HandleBinding:
293
- if self._slice is None:
294
- return HandleBinding(name=self._name)
295
- return SlicedHandleBinding(
296
- name=self._name,
297
- start=Expression(expr=str(self._slice[0])),
298
- end=Expression(expr=str(self._slice[1])),
436
+ def __getitem__(self, key: Union[slice, int, SymbolicExpr]) -> Any:
437
+ return (
438
+ self._get_slice(key) if isinstance(key, slice) else self._get_subscript(key)
299
439
  )
300
440
 
301
- def __getitem__(self, key: Union[slice, int, QParam]) -> "QArray":
302
- offset = self._slice[0] if self._slice is not None else 0
303
- if isinstance(key, slice):
304
- if key.step is not None:
305
- raise ClassiqValueError(ILLEGAL_SLICING_STEP_MSG)
306
- new_slice = (offset + key.start, offset + key.stop)
307
- else:
308
- if isinstance(key, QParam) and not isinstance(key, QParamScalar):
309
- raise ClassiqValueError("Non-classical parameter for slicing")
310
- new_slice = (offset + key, offset + key + 1)
311
- if (
312
- self._slice is not None
313
- and not isinstance(new_slice[1], Symbolic)
314
- and not isinstance(self._slice[1], Symbolic)
315
- and new_slice[1] > self._slice[1]
316
- ) or (
317
- self._length is not None
318
- and not isinstance(new_slice[1], Symbolic)
319
- and not isinstance(self._length, Symbolic)
320
- and new_slice[1] > self._length
441
+ def __setitem__(self, *args: Any) -> None:
442
+ pass
443
+
444
+ def _get_subscript(self, index: Union[slice, int, SymbolicExpr]) -> Any:
445
+ if isinstance(index, SymbolicExpr) and index.is_quantum:
446
+ raise ClassiqValueError("Non-classical parameter for slicing")
447
+
448
+ return _create_qvar_for_qtype(
449
+ self.get_qmod_type().element_type,
450
+ SubscriptHandleBinding(
451
+ base_handle=self._base_handle,
452
+ index=Expression(expr=str(index)),
453
+ ),
454
+ expr_str=f"{self}[{index}]",
455
+ )
456
+
457
+ def _get_slice(self, slice_: slice) -> Any:
458
+ if slice_.step is not None:
459
+ raise ClassiqValueError(ILLEGAL_SLICING_STEP_MSG)
460
+ if not isinstance(slice_.start, (int, SymbolicExpr)) or not isinstance(
461
+ slice_.stop, (int, SymbolicExpr)
321
462
  ):
322
- raise ClassiqValueError(SLICE_OUT_OF_BOUNDS_MSG)
323
- # prevent addition to local handles, since this is used for slicing existing local handles
324
- with _no_current_expandable():
325
- return QArray(self._name, length=self._length, slice_=new_slice)
463
+ raise ClassiqValueError(ILLEGAL_SLICE_MSG)
464
+
465
+ return QArray(
466
+ name=SlicedHandleBinding(
467
+ base_handle=self._base_handle,
468
+ start=Expression(expr=str(slice_.start)),
469
+ end=Expression(expr=str(slice_.stop)),
470
+ ),
471
+ element_type=self._element_type,
472
+ length=slice_.stop - slice_.start,
473
+ _expr_str=f"{self}[{slice_.start}:{slice_.stop}]",
474
+ )
326
475
 
327
476
  def __len__(self) -> int:
328
477
  raise ClassiqValueError(
329
- "len(<var>) is not supported for quantum variables - use <var>.len() instead"
478
+ "len(<var>) is not supported for quantum variables - use <var>.len instead"
330
479
  )
331
480
 
332
481
  if TYPE_CHECKING:
333
482
 
483
+ @property
334
484
  def len(self) -> int: ...
335
485
 
336
486
  else:
337
487
 
338
- def len(self) -> QParamScalar:
339
- if self._length is not None:
340
- return QParamScalar(f"{self._length}")
341
- return QParamScalar(f"len({self._name})")
488
+ @property
489
+ def len(self) -> Union[CParamScalar, int]:
490
+ if is_generative_mode():
491
+ with generative_mode_context(False):
492
+ return interpret_expression(str(self.len))
493
+ return CParamScalar(f"get_field({self}, 'len')")
494
+
495
+ @classmethod
496
+ def _get_attributes(cls, type_hint: Any) -> tuple[type[QVar], Any]:
497
+ type_args = version_portable_get_args(type_hint)
498
+ if len(type_args) == 0:
499
+ return QBit, None
500
+ first_arg = unwrap_forward_ref(type_args[0])
501
+ if len(type_args) == 1:
502
+ if isinstance(first_arg, (str, int)):
503
+ return QBit, first_arg
504
+ return first_arg, None
505
+ if len(type_args) != 2:
506
+ raise ClassiqValueError(
507
+ "QArray receives two type arguments: QArray[element_type: QVar, "
508
+ "length: int | CInt]"
509
+ )
510
+ second_arg = unwrap_forward_ref(type_args[1])
511
+ return cast(tuple[type[QVar], Any], (first_arg, second_arg))
342
512
 
343
513
  @classmethod
344
514
  def to_qmod_quantum_type(cls, type_hint: Any) -> QuantumType:
515
+ api_element_type, length = cls._get_attributes(type_hint)
516
+ api_element_class = get_origin(api_element_type) or api_element_type
517
+ element_type = api_element_class.to_qmod_quantum_type(api_element_type)
518
+
345
519
  length_expr: Optional[Expression] = None
346
- if len(version_portable_get_args(type_hint)) == 2:
347
- length_expr = Expression(
348
- expr=get_type_hint_expr(version_portable_get_args(type_hint)[1])
349
- )
350
- return QuantumBitvector(length=length_expr)
520
+ if length is not None:
521
+ length_expr = Expression(expr=get_type_hint_expr(length))
522
+
523
+ return QuantumBitvector(element_type=element_type, length=length_expr)
524
+
525
+ @classmethod
526
+ def to_qvar(
527
+ cls,
528
+ origin: Union[str, HandleBinding],
529
+ type_hint: Any,
530
+ expr_str: Optional[str],
531
+ ) -> "QArray":
532
+ return QArray(origin, *cls._get_attributes(type_hint), _expr_str=expr_str)
533
+
534
+ def get_qmod_type(self) -> QuantumBitvector:
535
+ if isinstance(self._element_type, QuantumType):
536
+ element_type = self._element_type
537
+ else:
538
+ element_class = get_origin(self._element_type) or self._element_type
539
+ element_type = element_class.to_qmod_quantum_type(self._element_type)
540
+ return QuantumBitvector(
541
+ element_type=element_type,
542
+ length=self._length,
543
+ )
544
+
545
+
546
+ class QStruct(QVar):
547
+ CONSTRUCTOR_DEPTH: int = 2
548
+
549
+ _struct_name: str
550
+ _fields: Mapping[str, QVar]
551
+
552
+ def __init__(
553
+ self,
554
+ origin: Union[None, str, HandleBinding] = None,
555
+ _struct_name: Optional[str] = None,
556
+ _fields: Optional[Mapping[str, QVar]] = None,
557
+ _expr_str: Optional[str] = None,
558
+ ) -> None:
559
+ name = _infer_variable_name(origin, self.CONSTRUCTOR_DEPTH)
560
+ if _struct_name is None or _fields is None:
561
+ with _no_current_expandable():
562
+ temp_var = QStruct.to_qvar(name, type(self), _expr_str)
563
+ _struct_name = temp_var._struct_name
564
+ _fields = temp_var._fields
565
+ self._struct_name = _struct_name
566
+ self._fields = _fields
567
+ for field_name, var in _fields.items():
568
+ setattr(self, field_name, var)
569
+ super().__init__(name, expr_str=_expr_str)
570
+ self._add_qmod_qstruct(qmodule=QMODULE)
351
571
 
352
572
  def get_qmod_type(self) -> QuantumType:
353
- if self._length is not None:
354
- return QuantumBitvector(length=Expression(expr=str(self._length)))
355
- return QuantumBitvector()
573
+ return TypeName(name=self._struct_name)
356
574
 
575
+ @classmethod
576
+ def to_qmod_quantum_type(cls, type_hint: Any) -> QuantumType:
577
+ with _no_current_expandable():
578
+ type_hint("DUMMY")
579
+ return TypeName(name=type_hint.__name__)
357
580
 
358
- def create_qvar_for_port_decl(port: PortDeclaration) -> QVar:
581
+ @classmethod
582
+ def to_qvar(
583
+ cls,
584
+ origin: Union[str, HandleBinding],
585
+ type_hint: Any,
586
+ expr_str: Optional[str],
587
+ ) -> "QStruct":
588
+ field_types = {
589
+ field_name: (QVar.from_type_hint(field_type), field_type)
590
+ for field_name, field_type in type_hint.__annotations__.items()
591
+ }
592
+ illegal_fields = [
593
+ (field_name, field_type)
594
+ for field_name, (field_class, field_type) in field_types.items()
595
+ if field_class is None
596
+ ]
597
+ if len(illegal_fields) > 0:
598
+ raise ClassiqValueError(
599
+ f"Field {illegal_fields[0][0]!r} of quantum struct "
600
+ f"{type_hint.__name__} has a non-quantum type "
601
+ f"{illegal_fields[0][1].__name__}."
602
+ )
603
+ base_handle = HandleBinding(name=origin) if isinstance(origin, str) else origin
604
+ with _no_current_expandable():
605
+ field_vars = {
606
+ field_name: cast(type[QVar], field_class).to_qvar(
607
+ FieldHandleBinding(base_handle=base_handle, field=field_name),
608
+ field_type,
609
+ f"get_field({expr_str if expr_str is not None else str(origin)}, '{field_name}')",
610
+ )
611
+ for field_name, (field_class, field_type) in field_types.items()
612
+ }
613
+ return QStruct(
614
+ origin,
615
+ _struct_name=type_hint.__name__,
616
+ _fields=field_vars,
617
+ _expr_str=expr_str,
618
+ )
619
+
620
+ def _add_qmod_qstruct(self, *, qmodule: ModelStateContainer) -> None:
621
+ if self._struct_name in qmodule.qstruct_decls:
622
+ return
623
+
624
+ struct_decl = QStructDeclaration(
625
+ name=self._struct_name,
626
+ fields={name: qvar.get_qmod_type() for name, qvar in self._fields.items()},
627
+ )
628
+ qmodule.qstruct_decls[self._struct_name] = struct_decl
629
+
630
+
631
+ def create_qvar_for_port_decl(port: AnonPortDeclaration, name: str) -> QVar:
632
+ return _create_qvar_for_qtype(port.quantum_type, HandleBinding(name=name))
633
+
634
+
635
+ def _create_qvar_for_qtype(
636
+ qtype: QuantumType, origin: HandleBinding, expr_str: Optional[str] = None
637
+ ) -> QVar:
359
638
  # prevent addition to local handles, since this is used for ports
360
639
  with _no_current_expandable():
361
- if _is_single_qbit_vector(port):
362
- return QBit(port.name)
363
- elif isinstance(port.quantum_type, QuantumNumeric):
364
- return QNum(port.name)
365
- return QArray(port.name)
366
-
367
-
368
- def _is_single_qbit_vector(port: PortDeclaration) -> bool:
369
- return (
370
- isinstance(port.quantum_type, QuantumBit)
371
- or isinstance(port.quantum_type, QuantumBitvector)
372
- and port.size is not None
373
- and port.size.is_evaluated()
374
- and port.size.to_int_value() == 1
375
- )
640
+ if isinstance(qtype, QuantumBit):
641
+ return QBit(origin, _expr_str=expr_str)
642
+ elif isinstance(qtype, QuantumNumeric):
643
+ return QNum(
644
+ origin,
645
+ qtype.size,
646
+ qtype.is_signed,
647
+ qtype.fraction_digits,
648
+ _expr_str=expr_str,
649
+ )
650
+ elif isinstance(qtype, TypeName):
651
+ struct_decl = QMODULE.qstruct_decls[qtype.name]
652
+ return QStruct(
653
+ origin,
654
+ struct_decl.name,
655
+ {
656
+ field_name: _create_qvar_for_qtype(
657
+ field_type,
658
+ FieldHandleBinding(base_handle=origin, field=field_name),
659
+ f"get_field({expr_str if expr_str is not None else str(origin)}, '{field_name}')",
660
+ )
661
+ for field_name, field_type in struct_decl.fields.items()
662
+ },
663
+ _expr_str=expr_str,
664
+ )
665
+ if TYPE_CHECKING:
666
+ assert isinstance(qtype, QuantumBitvector)
667
+ return QArray(origin, qtype.element_type, qtype.length, _expr_str=expr_str)
668
+
669
+
670
+ def get_qvar(qtype: QuantumType, origin: HandleBinding) -> "QVar":
671
+ if isinstance(qtype, QuantumBit):
672
+ return QBit(origin)
673
+ elif isinstance(qtype, QuantumBitvector):
674
+ return QArray(origin, qtype.element_type, qtype.length)
675
+ elif isinstance(qtype, QuantumNumeric):
676
+ return QNum(origin, qtype.size, qtype.is_signed, qtype.fraction_digits)
677
+ elif isinstance(qtype, TypeName):
678
+ return QStruct(
679
+ origin,
680
+ qtype.name,
681
+ {
682
+ field_name: get_qvar(
683
+ field_type, FieldHandleBinding(base_handle=origin, field=field_name)
684
+ )
685
+ for field_name, field_type in qtype.fields.items()
686
+ },
687
+ )
688
+ raise NotImplementedError