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

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