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,28 +1,30 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from pathlib import Path
4
- from typing import Any, Dict, Optional, Tuple, Union
4
+ from typing import Any, Optional, Union
5
5
 
6
6
  import pydantic
7
- from pydantic import BaseModel
7
+ from pydantic import BaseModel, ConfigDict
8
+ from pydantic_core.core_schema import ValidationInfo
8
9
 
9
- from classiq.interface.backend.ionq import ionq_quantum_program
10
+ from classiq.interface.backend.ionq.ionq_quantum_program import IonqQuantumCircuit
10
11
  from classiq.interface.backend.pydantic_backend import PydanticArgumentNameType
12
+ from classiq.interface.exceptions import ClassiqValueError
11
13
  from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
12
14
  from classiq.interface.executor.register_initialization import RegisterInitialization
13
15
  from classiq.interface.generator.synthesis_metadata.synthesis_execution_data import (
14
16
  ExecutionData,
15
17
  )
16
18
 
17
- Arguments = Dict[PydanticArgumentNameType, Any]
18
- MultipleArguments = Tuple[Arguments, ...]
19
- CodeType = Union[str, ionq_quantum_program.IonqQuantumCircuit]
20
- RegistersInitialization = Dict[str, RegisterInitialization]
21
- Qubits = Tuple[int, ...]
22
- OutputQubitsMap = Dict[str, Qubits]
19
+ Arguments = dict[PydanticArgumentNameType, Any]
20
+ MultipleArguments = tuple[Arguments, ...]
21
+ CodeType = str
22
+ RegistersInitialization = dict[str, RegisterInitialization]
23
+ Qubits = tuple[int, ...]
24
+ OutputQubitsMap = dict[str, Qubits]
23
25
 
24
26
 
25
- class QuantumBaseProgram(BaseModel):
27
+ class QuantumBaseCode(BaseModel):
26
28
  syntax: QuantumInstructionSet = pydantic.Field(
27
29
  default=QuantumInstructionSet.QASM, description="The syntax of the program."
28
30
  )
@@ -30,18 +32,23 @@ class QuantumBaseProgram(BaseModel):
30
32
  ..., description="The textual representation of the program"
31
33
  )
32
34
 
33
- @pydantic.validator("code")
34
- def load_quantum_program(cls, code: CodeType, values: Dict[str, Any]) -> CodeType:
35
- if not isinstance(code, str):
36
- return code
35
+ @pydantic.field_validator("code")
36
+ @classmethod
37
+ def load_quantum_program(
38
+ cls, code: Union[CodeType, IonqQuantumCircuit], values: ValidationInfo
39
+ ) -> CodeType:
40
+ syntax = values.data.get("syntax")
41
+ if isinstance(code, IonqQuantumCircuit):
42
+ if syntax != QuantumInstructionSet.IONQ:
43
+ raise ClassiqValueError(
44
+ f"Invalid code type {type(code)} for syntax: {syntax}"
45
+ )
46
+ return code.model_dump_json()
37
47
 
38
- syntax = values.get("syntax")
39
- if syntax == QuantumInstructionSet.IONQ:
40
- return ionq_quantum_program.IonqQuantumCircuit.from_string(code)
41
48
  return code
42
49
 
43
50
 
44
- class QuantumProgram(QuantumBaseProgram):
51
+ class QuantumCode(QuantumBaseCode):
45
52
  arguments: MultipleArguments = pydantic.Field(
46
53
  default=(),
47
54
  description="The parameters dictionary for a parametrized quantum program.",
@@ -51,43 +58,46 @@ class QuantumProgram(QuantumBaseProgram):
51
58
  description="The map of outputs to their qubits in the circuit.",
52
59
  )
53
60
  registers_initialization: Optional[RegistersInitialization] = pydantic.Field(
54
- default_factory=None,
61
+ default=None,
55
62
  description="Initial conditions for the different registers in the circuit.",
56
63
  )
57
64
  synthesis_execution_data: Optional[ExecutionData] = pydantic.Field(default=None)
58
65
  synthesis_execution_arguments: Arguments = pydantic.Field(default_factory=dict)
66
+ model_config = ConfigDict(validate_assignment=True)
59
67
 
60
- class Config:
61
- validate_assignment = True
62
-
63
- @pydantic.validator("arguments")
68
+ @pydantic.field_validator("arguments", mode="before")
69
+ @classmethod
64
70
  def validate_arguments(
65
- cls, arguments: MultipleArguments, values: Dict[str, Any]
71
+ cls, arguments: MultipleArguments, info: ValidationInfo
66
72
  ) -> MultipleArguments:
67
- if arguments and values.get("syntax") not in (
73
+ if arguments and info.data.get("syntax") not in (
68
74
  QuantumInstructionSet.QSHARP,
69
75
  QuantumInstructionSet.QASM,
70
76
  ):
71
- raise ValueError("Only QASM or Q# programs support arguments")
77
+ raise ClassiqValueError("Only QASM or Q# programs support arguments")
72
78
 
73
- if values.get("syntax") == QuantumInstructionSet.QSHARP and len(arguments) > 1:
74
- raise ValueError(
79
+ if (
80
+ info.data.get("syntax") == QuantumInstructionSet.QSHARP
81
+ and len(arguments) > 1
82
+ ):
83
+ raise ClassiqValueError(
75
84
  f"Q# programs supports only one group of arguments. {len(arguments)} given"
76
85
  )
77
86
 
78
87
  return arguments
79
88
 
80
- @pydantic.validator("synthesis_execution_data")
89
+ @pydantic.field_validator("synthesis_execution_data")
90
+ @classmethod
81
91
  def validate_synthesis_execution_data(
82
92
  cls,
83
93
  synthesis_execution_data: Optional[ExecutionData],
84
- values: Dict[str, Any],
94
+ values: ValidationInfo,
85
95
  ) -> Optional[ExecutionData]:
86
96
  if (
87
97
  synthesis_execution_data is not None
88
- and values.get("syntax") is not QuantumInstructionSet.QASM
98
+ and values.data.get("syntax") is not QuantumInstructionSet.QASM
89
99
  ):
90
- raise ValueError("Only QASM supports the requested configuration")
100
+ raise ClassiqValueError("Only QASM supports the requested configuration")
91
101
 
92
102
  return synthesis_execution_data
93
103
 
@@ -96,9 +106,9 @@ class QuantumProgram(QuantumBaseProgram):
96
106
  file_path: Union[str, Path],
97
107
  syntax: Optional[Union[str, QuantumInstructionSet]] = None,
98
108
  arguments: MultipleArguments = (),
99
- ) -> QuantumProgram:
109
+ ) -> QuantumCode:
100
110
  path = Path(file_path)
101
111
  code = path.read_text()
102
112
  if syntax is None:
103
113
  syntax = QuantumInstructionSet.from_suffix(path.suffix.lstrip("."))
104
- return QuantumProgram(syntax=syntax, code=code, arguments=arguments)
114
+ return QuantumCode(syntax=syntax, code=code, arguments=arguments)
@@ -1,4 +1,5 @@
1
- from classiq._internals.enum_utils import StrEnum
1
+ from classiq.interface.enum_utils import StrEnum
2
+ from classiq.interface.exceptions import ClassiqValueError
2
3
 
3
4
 
4
5
  class QuantumInstructionSet(StrEnum):
@@ -14,4 +15,4 @@ class QuantumInstructionSet(StrEnum):
14
15
  return QuantumInstructionSet.QSHARP
15
16
  if suffix == "ionq":
16
17
  return QuantumInstructionSet.IONQ
17
- raise ValueError("Illegal suffix")
18
+ raise ClassiqValueError("Illegal suffix")
@@ -1,11 +1,9 @@
1
- from typing import Any, Dict, List
2
-
3
1
  import pydantic
2
+ from typing_extensions import Self
4
3
 
4
+ from classiq.interface.exceptions import ClassiqStateInitializationError
5
5
  from classiq.interface.generator.arith import number_utils
6
6
 
7
- from classiq.exceptions import ClassiqStateInitializationError
8
-
9
7
  _NON_INTEGER_INITIALIZATION_ERROR_MSG: str = (
10
8
  "Only natural numbers are supported as initial conditions"
11
9
  )
@@ -13,29 +11,26 @@ _NON_INTEGER_INITIALIZATION_ERROR_MSG: str = (
13
11
 
14
12
  class RegisterInitialization(pydantic.BaseModel):
15
13
  name: str
16
- qubits: List[int]
14
+ qubits: list[int]
17
15
  initial_condition: pydantic.NonNegativeInt
18
16
 
19
- @pydantic.validator("initial_condition", pre=True)
17
+ @pydantic.field_validator("initial_condition", mode="before")
18
+ @classmethod
20
19
  def _validate_initial_condition(cls, value: int) -> int:
21
20
  if not isinstance(value, int) or value < 0:
22
21
  raise ClassiqStateInitializationError(_NON_INTEGER_INITIALIZATION_ERROR_MSG)
23
22
  return value
24
23
 
25
- @pydantic.root_validator()
26
- def _validate_register_initialization(
27
- cls, values: Dict[str, Any]
28
- ) -> Dict[str, Any]:
29
- qubits: List[int] = values.get("qubits", list())
30
- initial_condition: int = values.get("initial_condition", 0)
31
- name: str = values.get("name", "")
24
+ @pydantic.model_validator(mode="after")
25
+ def _validate_register_initialization(self) -> Self:
26
+ qubits: list[int] = self.qubits or []
27
+ initial_condition: int = self.initial_condition or 0
28
+ name: str = self.name or ""
32
29
 
33
- initial_condition_length = number_utils.size(
34
- initial_condition, machine_precision=number_utils.MAX_FRACTION_PLACES
35
- )
30
+ initial_condition_length = number_utils.size(initial_condition)
36
31
  register_length = len(qubits)
37
32
  if initial_condition_length > register_length:
38
33
  raise ClassiqStateInitializationError(
39
34
  f"Register {name} has {register_length} qubits, which is not enough to represent the number {initial_condition}."
40
35
  )
41
- return values
36
+ return self
@@ -1,51 +1,64 @@
1
1
  import functools
2
2
  import operator
3
3
  from collections import defaultdict
4
+ from collections.abc import Iterator, Mapping
4
5
  from typing import (
6
+ TYPE_CHECKING,
5
7
  Any,
6
8
  DefaultDict,
7
- Dict,
8
- Iterator,
9
- List,
10
- Mapping,
11
9
  Optional,
12
- Tuple,
13
10
  Union,
14
11
  )
15
12
 
16
13
  import pydantic
17
14
  from pydantic import BaseModel
18
- from typing_extensions import TypeAlias
15
+ from typing_extensions import Self, TypeAlias
19
16
 
20
- from classiq.interface.executor.quantum_program import OutputQubitsMap, Qubits
17
+ from classiq.interface.exceptions import ClassiqError
18
+ from classiq.interface.executor.quantum_code import OutputQubitsMap, Qubits
21
19
  from classiq.interface.generator.arith import number_utils
22
20
  from classiq.interface.generator.complex_type import Complex
23
21
  from classiq.interface.generator.functions.classical_type import QmodPyObject
24
22
  from classiq.interface.helpers.custom_pydantic_types import PydanticNonNegIntTuple
23
+ from classiq.interface.helpers.datastructures import get_sdk_compatible_python_object
25
24
  from classiq.interface.helpers.versioned_model import VersionedModel
26
25
 
27
- from classiq.exceptions import ClassiqError
28
-
29
26
  _ILLEGAL_QUBIT_ERROR_MSG: str = "Illegal qubit index requested"
30
27
  _REPEATED_QUBIT_ERROR_MSG: str = "Requested a qubit more than once"
31
28
  _UNAVAILABLE_OUTPUT_ERROR_MSG: str = "Requested output doesn't exist in the circuit"
32
29
 
33
30
  State: TypeAlias = str
34
31
  Name: TypeAlias = str
35
- RegisterValue: TypeAlias = Union[float, int]
32
+ RegisterValue: TypeAlias = Union[float, int, list, dict]
36
33
  MeasuredShots: TypeAlias = pydantic.NonNegativeInt
37
34
  ParsedState: TypeAlias = Mapping[Name, RegisterValue]
38
35
  ParsedStates: TypeAlias = Mapping[State, ParsedState]
39
- Counts: TypeAlias = Dict[State, MeasuredShots]
40
- StateVector: TypeAlias = Optional[Dict[str, Any]]
36
+ Counts: TypeAlias = dict[State, MeasuredShots]
37
+ StateVector: TypeAlias = Optional[dict[str, Complex]]
38
+
39
+ if TYPE_CHECKING:
40
+ DotAccessParsedState = Mapping[Name, Any]
41
+ else:
42
+ DotAccessParsedState = ParsedState
41
43
 
42
44
 
43
45
  class SampledState(BaseModel):
44
- state: ParsedState
46
+ state: DotAccessParsedState
45
47
  shots: MeasuredShots
46
48
 
49
+ def __repr__(self) -> str:
50
+ return f"{self.state}: {self.shots}"
51
+
52
+ @pydantic.field_validator("state", mode="after")
53
+ @classmethod
54
+ def _make_state_sdk_compatible(cls, state: ParsedState) -> DotAccessParsedState:
55
+ return {
56
+ name: get_sdk_compatible_python_object(value)
57
+ for name, value in state.items()
58
+ }
59
+
47
60
 
48
- ParsedCounts: TypeAlias = List[SampledState]
61
+ ParsedCounts: TypeAlias = list[SampledState]
49
62
 
50
63
 
51
64
  class SimulatedState(BaseModel):
@@ -57,7 +70,8 @@ class SimulatedState(BaseModel):
57
70
  return self.state[item]
58
71
 
59
72
 
60
- ParsedStateVector: TypeAlias = List[SimulatedState]
73
+ SimulatedState.model_rebuild()
74
+ ParsedStateVector: TypeAlias = list[SimulatedState]
61
75
 
62
76
 
63
77
  class VaRResult(BaseModel):
@@ -66,10 +80,10 @@ class VaRResult(BaseModel):
66
80
 
67
81
 
68
82
  class GroverSimulationResults(VersionedModel):
69
- result: Dict[str, Any]
83
+ result: dict[str, Any]
70
84
 
71
85
 
72
- def _validate_qubit_indices(counts: Counts, indices: Tuple[int, ...]) -> None:
86
+ def _validate_qubit_indices(counts: Counts, indices: tuple[int, ...]) -> None:
73
87
  if not indices:
74
88
  raise ClassiqError(_ILLEGAL_QUBIT_ERROR_MSG)
75
89
 
@@ -80,7 +94,7 @@ def _validate_qubit_indices(counts: Counts, indices: Tuple[int, ...]) -> None:
80
94
  raise ClassiqError(_REPEATED_QUBIT_ERROR_MSG)
81
95
 
82
96
 
83
- def _slice_str(s: str, indices: Tuple[int, ...]) -> str:
97
+ def _slice_str(s: str, indices: tuple[int, ...]) -> str:
84
98
  return "".join(s[i] for i in indices)
85
99
 
86
100
 
@@ -97,8 +111,47 @@ def get_sampled_state(
97
111
  return None
98
112
 
99
113
 
114
+ def reduce_parsed_states(
115
+ parsed_states: ParsedStates, outputs: tuple[Name, ...]
116
+ ) -> ParsedStates:
117
+ return {
118
+ state: {
119
+ output: value for output, value in parsed_state.items() if output in outputs
120
+ }
121
+ for state, parsed_state in parsed_states.items()
122
+ }
123
+
124
+
125
+ def get_parsed_counts(counts: Counts, parsed_states: ParsedStates) -> ParsedCounts:
126
+ parsed_counts: ParsedCounts = []
127
+ for bitstring, count in counts.items():
128
+ parsed_state = parsed_states[bitstring]
129
+ if sampled_state := get_sampled_state(parsed_counts, parsed_state):
130
+ sampled_state.shots += count
131
+ else:
132
+ parsed_counts.append(SampledState(state=parsed_state, shots=count))
133
+ return sorted(parsed_counts, key=lambda k: k.shots, reverse=True)
134
+
135
+
136
+ def prepare_parsed_state_vector(
137
+ state_vector: StateVector, parsed_state_vector_states: ParsedStates
138
+ ) -> Optional[ParsedStateVector]:
139
+ if not state_vector:
140
+ return None
141
+
142
+ parsed_state_vector = [
143
+ SimulatedState(
144
+ state=parsed_state_vector_states[bitstring],
145
+ bitstring=bitstring,
146
+ amplitude=complex(amplitude_str),
147
+ )
148
+ for bitstring, amplitude_str in state_vector.items()
149
+ ]
150
+ return sorted(parsed_state_vector, key=lambda k: abs(k.amplitude), reverse=True)
151
+
152
+
100
153
  class ExecutionDetails(BaseModel, QmodPyObject):
101
- vendor_format_result: Dict[str, Any] = pydantic.Field(
154
+ vendor_format_result: dict[str, Any] = pydantic.Field(
102
155
  ..., description="Result in proprietary vendor format"
103
156
  )
104
157
  counts: Counts = pydantic.Field(
@@ -108,11 +161,14 @@ class ExecutionDetails(BaseModel, QmodPyObject):
108
161
  True,
109
162
  description="Is the qubit order of counts field such that the LSB is right?",
110
163
  )
164
+ probabilities: dict[State, pydantic.NonNegativeFloat] = pydantic.Field(
165
+ default_factory=dict, description="Probabilities of each state"
166
+ )
111
167
  parsed_states: ParsedStates = pydantic.Field(
112
168
  default_factory=dict,
113
169
  description="A mapping between the raw states of counts (bitstrings) to their parsed states (registers' values)",
114
170
  )
115
- histogram: Optional[Dict[State, pydantic.NonNegativeFloat]] = pydantic.Field(
171
+ histogram: Optional[dict[State, pydantic.NonNegativeFloat]] = pydantic.Field(
116
172
  None,
117
173
  description="Histogram of probability per state (an alternative to counts)",
118
174
  )
@@ -124,7 +180,7 @@ class ExecutionDetails(BaseModel, QmodPyObject):
124
180
  default=None,
125
181
  description="The state vector when executed on a simulator, with LSB right qubit order",
126
182
  )
127
- parsed_state_vector_states: ParsedStates = pydantic.Field(
183
+ parsed_state_vector_states: Optional[ParsedStates] = pydantic.Field(
128
184
  default=None,
129
185
  description="A mapping between the raw states of the state vector (bitstrings) to their parsed states (registers' values)",
130
186
  )
@@ -136,47 +192,35 @@ class ExecutionDetails(BaseModel, QmodPyObject):
136
192
  default=None, description="The total number of shots the circuit was executed"
137
193
  )
138
194
 
139
- @pydantic.validator("counts", pre=True)
195
+ @pydantic.field_validator("counts", mode="after")
196
+ @classmethod
140
197
  def _clean_spaces_from_counts_keys(cls, v: Counts) -> Counts:
141
198
  if not v or " " not in list(v.keys())[0]:
142
199
  return v
143
200
  return {state.replace(" ", ""): v[state] for state in v}
144
201
 
145
- @pydantic.validator("num_shots", always=True)
146
- def _validate_num_shots(
147
- cls, num_shots: Optional[int], values: Dict[str, Any]
148
- ) -> Optional[int]:
149
- if num_shots is not None:
150
- return num_shots
151
- counts = values.get("counts")
152
- if not counts:
153
- return None
154
- return sum(shots for _, shots in counts.items())
202
+ @pydantic.model_validator(mode="after")
203
+ def _validate_num_shots(self) -> Self:
204
+ if isinstance(self, ExecutionDetails):
205
+ if self.num_shots is not None:
206
+ return self
207
+ counts = self.counts
208
+ if not counts:
209
+ return self
210
+ self.num_shots = sum(shots for _, shots in counts.items())
211
+ return self
155
212
 
156
213
  @property
157
214
  def parsed_counts(self) -> ParsedCounts:
158
- parsed_counts: ParsedCounts = []
159
- for bitstring, count in self.counts.items():
160
- parsed_state = self.parsed_states[bitstring]
161
- if sampled_state := get_sampled_state(parsed_counts, parsed_state):
162
- sampled_state.shots += count
163
- else:
164
- parsed_counts.append(SampledState(state=parsed_state, shots=count))
165
- return sorted(parsed_counts, key=lambda k: k.shots, reverse=True)
215
+ return get_parsed_counts(self.counts, self.parsed_states)
166
216
 
167
217
  @property
168
218
  def parsed_state_vector(self) -> Optional[ParsedStateVector]:
169
- if not self.state_vector:
170
- return None
171
- parsed_state_vector = [
172
- SimulatedState(
173
- state=self.parsed_state_vector_states[bitstring],
174
- bitstring=bitstring,
175
- amplitude=complex(amplitude_str),
176
- )
177
- for bitstring, amplitude_str in self.state_vector.items()
178
- ]
179
- return sorted(parsed_state_vector, key=lambda k: abs(k.amplitude), reverse=True)
219
+ if TYPE_CHECKING:
220
+ assert self.parsed_state_vector_states is not None
221
+ return prepare_parsed_state_vector(
222
+ self.state_vector, self.parsed_state_vector_states
223
+ )
180
224
 
181
225
  def flip_execution_counts_bitstring(self) -> None:
182
226
  """Backends should return result count bitstring in right to left form"""
@@ -207,15 +251,15 @@ class ExecutionDetails(BaseModel, QmodPyObject):
207
251
  return self.counts_of_qubits(*self.output_qubits_map[output_name])
208
252
 
209
253
  def counts_of_multiple_outputs(
210
- self, output_names: Tuple[Name, ...]
211
- ) -> Dict[Tuple[State, ...], pydantic.NonNegativeInt]:
254
+ self, output_names: tuple[Name, ...]
255
+ ) -> dict[tuple[State, ...], pydantic.NonNegativeInt]:
212
256
  if any(name not in self.output_qubits_map for name in output_names):
213
257
  raise ClassiqError(_UNAVAILABLE_OUTPUT_ERROR_MSG)
214
258
 
215
- output_regs: Tuple[Qubits, ...] = tuple(
259
+ output_regs: tuple[Qubits, ...] = tuple(
216
260
  self.output_qubits_map[name] for name in output_names
217
261
  )
218
- reduced_counts: DefaultDict[Tuple[State, ...], int] = defaultdict(int)
262
+ reduced_counts: DefaultDict[tuple[State, ...], int] = defaultdict(int)
219
263
  for state_str, state_count in self.counts_by_qubit_order(
220
264
  lsb_right=False
221
265
  ).items():
@@ -223,8 +267,19 @@ class ExecutionDetails(BaseModel, QmodPyObject):
223
267
  reduced_counts[reduced_strs] += state_count
224
268
  return dict(reduced_counts)
225
269
 
226
- def register_output_from_qubits(self, qubits: Tuple[int, ...]) -> Dict[float, int]:
227
- register_output: Dict[float, int] = {}
270
+ def parsed_counts_of_outputs(
271
+ self, output_names: Union[Name, tuple[Name, ...]]
272
+ ) -> ParsedCounts:
273
+ if isinstance(output_names, Name):
274
+ output_names = (output_names,)
275
+ if any(name not in self.output_qubits_map for name in output_names):
276
+ raise ClassiqError(_UNAVAILABLE_OUTPUT_ERROR_MSG)
277
+
278
+ reduced_parsed_states = reduce_parsed_states(self.parsed_states, output_names)
279
+ return get_parsed_counts(self.counts, reduced_parsed_states)
280
+
281
+ def register_output_from_qubits(self, qubits: tuple[int, ...]) -> dict[float, int]:
282
+ register_output: dict[float, int] = {}
228
283
  value_from_str_bin = functools.partial(
229
284
  self._get_register_value_from_binary_string_results, register_qubits=qubits
230
285
  )
@@ -232,13 +287,15 @@ class ExecutionDetails(BaseModel, QmodPyObject):
232
287
  lsb_right=False
233
288
  ).items():
234
289
  value = value_from_str_bin(binary_string=results_binary_key)
290
+ if TYPE_CHECKING:
291
+ assert isinstance(value, float)
235
292
  register_output[value] = register_output.get(value, 0) + counts
236
293
 
237
294
  return register_output
238
295
 
239
296
  @staticmethod
240
297
  def _get_register_value_from_binary_string_results(
241
- binary_string: str, register_qubits: List[int]
298
+ binary_string: str, register_qubits: list[int]
242
299
  ) -> RegisterValue:
243
300
  register_binary_string = "".join(
244
301
  operator.itemgetter(*register_qubits)(binary_string)
@@ -247,33 +304,34 @@ class ExecutionDetails(BaseModel, QmodPyObject):
247
304
 
248
305
 
249
306
  class MultipleExecutionDetails(VersionedModel):
250
- details: List[ExecutionDetails]
307
+ details: list[ExecutionDetails]
251
308
 
252
309
  def __getitem__(self, index: int) -> ExecutionDetails:
253
310
  return self.details[index]
254
311
 
255
312
 
256
- class EstimationMetadata(BaseModel, extra=pydantic.Extra.allow):
313
+ class EstimationMetadata(BaseModel, extra="allow"):
257
314
  shots: Optional[pydantic.NonNegativeInt] = None
258
315
  remapped_qubits: bool = False
259
- input_qubit_map: Optional[List[PydanticNonNegIntTuple]] = None
316
+ input_qubit_map: Optional[list[PydanticNonNegIntTuple]] = None
260
317
 
261
318
 
262
319
  class EstimationResult(BaseModel, QmodPyObject):
263
320
  value: Complex = pydantic.Field(..., description="Estimation for the operator")
264
- variance: Complex = pydantic.Field(..., description="Variance of the estimation")
265
321
  metadata: EstimationMetadata = pydantic.Field(
266
322
  ..., description="Metadata for the estimation"
267
323
  )
268
324
 
269
325
 
270
326
  class EstimationResults(VersionedModel):
271
- results: List[EstimationResult]
327
+ results: list[EstimationResult]
272
328
 
273
329
  def __len__(self) -> int:
274
330
  return len(self.results)
275
331
 
276
- def __iter__(self) -> Iterator[EstimationResult]: # type: ignore
332
+ def __iter__(self) -> Iterator[EstimationResult]: # type: ignore[override]
333
+ # TODO This is a bug waiting to happen. We change the meaning of
334
+ # __iter__ in a derived class.
277
335
  return iter(self.results)
278
336
 
279
337
  def __getitem__(self, index: int) -> EstimationResult:
@@ -1,7 +1,7 @@
1
1
  import base64
2
2
  import io
3
3
  from datetime import datetime
4
- from typing import Dict, List, Optional, Tuple
4
+ from typing import Optional
5
5
 
6
6
  import pydantic
7
7
  from PIL import Image
@@ -12,14 +12,14 @@ from classiq.interface.generator.complex_type import Complex
12
12
  from classiq.interface.generator.functions.classical_type import QmodPyObject
13
13
  from classiq.interface.helpers.custom_pydantic_types import PydanticProbabilityFloat
14
14
 
15
- Solution = Tuple[int, ...]
15
+ Solution = tuple[int, ...]
16
16
 
17
17
 
18
18
  class SolverResult(BaseModel):
19
19
  energy: float
20
20
  # TODO: add time units (like seconds)
21
- time: Optional[float]
22
- solution: Optional[Solution]
21
+ time: Optional[float] = None
22
+ solution: Optional[Solution] = None
23
23
 
24
24
 
25
25
  class SolutionData(BaseModel):
@@ -34,13 +34,13 @@ class VQEIntermediateData(BaseModel):
34
34
  iteration_number: pydantic.PositiveInt = pydantic.Field(
35
35
  description="The iteration's number (evaluation count)"
36
36
  )
37
- parameters: List[float] = pydantic.Field(
37
+ parameters: list[float] = pydantic.Field(
38
38
  description="The optimizer parameters for the variational form"
39
39
  )
40
40
  mean_all_solutions: Optional[float] = pydantic.Field(
41
41
  default=None, description="The mean score of all solutions in this iteration"
42
42
  )
43
- solutions: List[SolutionData] = pydantic.Field(
43
+ solutions: list[SolutionData] = pydantic.Field(
44
44
  description="Solutions found in this iteration, their score and"
45
45
  "number of repetitions"
46
46
  )
@@ -50,11 +50,11 @@ class VQEIntermediateData(BaseModel):
50
50
 
51
51
 
52
52
  class VQESolverResult(SolverResult, QmodPyObject):
53
- eigenstate: Dict[str, Complex]
54
- reduced_probabilities: Optional[Dict[str, float]] = None
53
+ eigenstate: dict[str, Complex]
54
+ reduced_probabilities: Optional[dict[str, float]] = None
55
55
  optimized_circuit_sample_results: ExecutionDetails
56
- intermediate_results: List[VQEIntermediateData]
57
- optimal_parameters: Dict[str, float]
56
+ intermediate_results: list[VQEIntermediateData]
57
+ optimal_parameters: dict[str, float]
58
58
  convergence_graph_str: str
59
59
  num_solutions: Optional[int] = None
60
60
  num_shots: int
@@ -63,7 +63,7 @@ class VQESolverResult(SolverResult, QmodPyObject):
63
63
  self.convergence_graph.show()
64
64
 
65
65
  @property
66
- def convergence_graph(self):
66
+ def convergence_graph(self) -> Image.Image:
67
67
  return Image.open(io.BytesIO(base64.b64decode(self.convergence_graph_str)))
68
68
 
69
69
  @property