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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. classiq/__init__.py +47 -32
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
  3. classiq/_internals/api_wrapper.py +235 -97
  4. classiq/_internals/async_utils.py +1 -3
  5. classiq/_internals/authentication/auth0.py +26 -10
  6. classiq/_internals/authentication/authentication.py +11 -0
  7. classiq/_internals/authentication/device.py +10 -5
  8. classiq/_internals/authentication/password_manager.py +18 -6
  9. classiq/_internals/authentication/token_manager.py +10 -5
  10. classiq/_internals/client.py +94 -33
  11. classiq/_internals/config.py +3 -4
  12. classiq/_internals/host_checker.py +38 -15
  13. classiq/_internals/jobs.py +60 -57
  14. classiq/_internals/type_validation.py +9 -9
  15. classiq/analyzer/__init__.py +1 -3
  16. classiq/analyzer/analyzer.py +24 -19
  17. classiq/analyzer/analyzer_utilities.py +10 -10
  18. classiq/analyzer/rb.py +15 -15
  19. classiq/analyzer/show_interactive_hack.py +27 -4
  20. classiq/analyzer/url_utils.py +2 -3
  21. classiq/applications/__init__.py +3 -12
  22. classiq/applications/chemistry/__init__.py +14 -10
  23. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  24. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +165 -158
  25. classiq/applications/chemistry/ground_state_problem.py +1 -1
  26. classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +4 -1
  27. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
  28. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +1 -1
  29. classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +51 -15
  30. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +12 -12
  31. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +8 -6
  32. classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +7 -11
  33. classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +67 -40
  34. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
  35. classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
  36. classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +2 -2
  37. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +15 -20
  38. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +14 -15
  39. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +11 -15
  40. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +1 -2
  41. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
  42. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +2 -3
  43. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +5 -8
  44. classiq/applications/combinatorial_optimization/__init__.py +20 -6
  45. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  46. classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +35 -33
  47. classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
  48. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  49. classiq/applications/finance/__init__.py +4 -5
  50. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +48 -42
  51. classiq/applications/grover/__init__.py +9 -0
  52. classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +52 -51
  53. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  54. classiq/applications/libraries/qmci_library.py +22 -0
  55. classiq/applications/qnn/__init__.py +2 -4
  56. classiq/applications/qnn/circuit_utils.py +6 -6
  57. classiq/applications/qnn/datasets/__init__.py +9 -11
  58. classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
  59. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  60. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  61. classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
  62. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  63. classiq/applications/qnn/qlayer.py +30 -10
  64. classiq/applications/qnn/torch_utils.py +4 -3
  65. classiq/applications/qnn/types.py +5 -5
  66. classiq/applications/qsvm/__init__.py +6 -4
  67. classiq/applications/qsvm/qsvm.py +3 -6
  68. classiq/applications/qsvm/qsvm_data_generation.py +3 -3
  69. classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
  70. classiq/execution/__init__.py +8 -3
  71. classiq/execution/all_hardware_devices.py +11 -0
  72. classiq/execution/execution_session.py +400 -0
  73. classiq/execution/iqcc.py +63 -0
  74. classiq/execution/jobs.py +197 -25
  75. classiq/execution/qnn.py +79 -0
  76. classiq/executor.py +20 -115
  77. classiq/interface/_version.py +1 -1
  78. classiq/interface/analyzer/analysis_params.py +43 -13
  79. classiq/interface/analyzer/cytoscape_graph.py +15 -9
  80. classiq/interface/analyzer/result.py +28 -32
  81. classiq/interface/applications/qsvm.py +20 -29
  82. classiq/interface/ast_node.py +16 -0
  83. classiq/interface/backend/backend_preferences.py +390 -121
  84. classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
  85. classiq/interface/backend/pydantic_backend.py +25 -22
  86. classiq/interface/backend/quantum_backend_providers.py +69 -16
  87. classiq/interface/chemistry/fermionic_operator.py +30 -21
  88. classiq/interface/chemistry/ground_state_problem.py +28 -25
  89. classiq/interface/chemistry/molecule.py +14 -10
  90. classiq/interface/chemistry/operator.py +64 -231
  91. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  92. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
  93. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  94. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  95. classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
  96. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  97. classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
  98. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +8 -9
  99. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  100. classiq/interface/combinatorial_optimization/result.py +1 -3
  101. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  102. classiq/interface/debug_info/debug_info.py +86 -0
  103. classiq/{exceptions.py → interface/exceptions.py} +37 -9
  104. classiq/interface/execution/iqcc.py +19 -0
  105. classiq/interface/execution/jobs.py +15 -12
  106. classiq/interface/execution/primitives.py +18 -0
  107. classiq/interface/executor/constants.py +1 -0
  108. classiq/interface/executor/execution_preferences.py +26 -114
  109. classiq/interface/executor/execution_request.py +24 -46
  110. classiq/interface/executor/execution_result.py +30 -8
  111. classiq/interface/executor/iqae_result.py +4 -6
  112. classiq/interface/executor/optimizer_preferences.py +17 -14
  113. classiq/interface/executor/quantum_code.py +28 -24
  114. classiq/interface/executor/quantum_instruction_set.py +2 -2
  115. classiq/interface/executor/register_initialization.py +11 -14
  116. classiq/interface/executor/result.py +83 -56
  117. classiq/interface/executor/vqe_result.py +10 -10
  118. classiq/interface/finance/function_input.py +35 -25
  119. classiq/interface/finance/gaussian_model_input.py +5 -5
  120. classiq/interface/finance/log_normal_model_input.py +4 -4
  121. classiq/interface/finance/model_input.py +4 -4
  122. classiq/interface/generator/adjacency.py +1 -3
  123. classiq/interface/generator/amplitude_loading.py +22 -12
  124. classiq/interface/generator/ansatz_library.py +5 -5
  125. classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
  126. classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
  127. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
  128. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  129. classiq/interface/generator/application_apis/finance_declarations.py +48 -69
  130. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
  131. classiq/interface/generator/arith/argument_utils.py +46 -5
  132. classiq/interface/generator/arith/arithmetic.py +35 -16
  133. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +6 -7
  134. classiq/interface/generator/arith/arithmetic_expression_abc.py +66 -25
  135. classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -11
  136. classiq/interface/generator/arith/arithmetic_expression_validator.py +47 -43
  137. classiq/interface/generator/arith/arithmetic_operations.py +14 -6
  138. classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
  139. classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
  140. classiq/interface/generator/arith/ast_node_rewrite.py +3 -2
  141. classiq/interface/generator/arith/binary_ops.py +218 -130
  142. classiq/interface/generator/arith/endianness.py +1 -1
  143. classiq/interface/generator/arith/extremum_operations.py +96 -25
  144. classiq/interface/generator/arith/logical_ops.py +14 -12
  145. classiq/interface/generator/arith/number_utils.py +12 -6
  146. classiq/interface/generator/arith/register_user_input.py +60 -37
  147. classiq/interface/generator/arith/unary_ops.py +49 -29
  148. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  149. classiq/interface/generator/builtin_api_builder.py +2 -9
  150. classiq/interface/generator/chemistry_function_params.py +3 -3
  151. classiq/interface/generator/circuit_code/circuit_code.py +7 -7
  152. classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
  153. classiq/interface/generator/commuting_pauli_exponentiation.py +7 -7
  154. classiq/interface/generator/compiler_keywords.py +5 -1
  155. classiq/interface/generator/complex_type.py +13 -18
  156. classiq/interface/generator/constant.py +3 -4
  157. classiq/interface/generator/control_state.py +34 -29
  158. classiq/interface/generator/copy.py +47 -0
  159. classiq/interface/generator/custom_ansatz.py +2 -5
  160. classiq/interface/generator/distance.py +3 -5
  161. classiq/interface/generator/excitations.py +3 -2
  162. classiq/interface/generator/expressions/atomic_expression_functions.py +21 -5
  163. classiq/interface/generator/expressions/enums/__init__.py +0 -10
  164. classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
  165. classiq/interface/generator/expressions/evaluated_expression.py +5 -5
  166. classiq/interface/generator/expressions/expression.py +26 -14
  167. classiq/interface/generator/expressions/expression_constants.py +9 -3
  168. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  169. classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
  170. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +34 -8
  171. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
  172. classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
  173. classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
  174. classiq/interface/generator/expressions/sympy_supported_expressions.py +19 -11
  175. classiq/interface/generator/finance.py +2 -2
  176. classiq/interface/generator/function_param_library.py +6 -6
  177. classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
  178. classiq/interface/generator/function_params.py +36 -64
  179. classiq/interface/generator/functions/__init__.py +0 -22
  180. classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
  181. classiq/interface/generator/functions/classical_function_declaration.py +18 -9
  182. classiq/interface/generator/functions/classical_type.py +47 -166
  183. classiq/interface/generator/functions/concrete_types.py +55 -0
  184. classiq/interface/generator/functions/function_declaration.py +13 -14
  185. classiq/interface/generator/functions/port_declaration.py +1 -13
  186. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  187. classiq/interface/generator/functions/type_name.py +90 -0
  188. classiq/interface/generator/generated_circuit_data.py +153 -20
  189. classiq/interface/generator/grover_diffuser.py +32 -25
  190. classiq/interface/generator/grover_operator.py +34 -25
  191. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
  192. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  193. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +9 -9
  194. classiq/interface/generator/hardware/hardware_data.py +72 -34
  195. classiq/interface/generator/hardware_efficient_ansatz.py +20 -16
  196. classiq/interface/generator/hartree_fock.py +13 -5
  197. classiq/interface/generator/identity.py +10 -6
  198. classiq/interface/generator/linear_pauli_rotations.py +32 -20
  199. classiq/interface/generator/mcmt_method.py +1 -1
  200. classiq/interface/generator/mcu.py +17 -15
  201. classiq/interface/generator/mcx.py +24 -17
  202. classiq/interface/generator/model/__init__.py +2 -5
  203. classiq/interface/generator/model/constraints.py +26 -8
  204. classiq/interface/generator/model/model.py +27 -190
  205. classiq/interface/generator/model/preferences/preferences.py +115 -41
  206. classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +14 -17
  207. classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
  208. classiq/interface/generator/oracles/custom_oracle.py +15 -13
  209. classiq/interface/generator/oracles/oracle_abc.py +7 -7
  210. classiq/interface/generator/partitioned_register.py +7 -7
  211. classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
  212. classiq/interface/generator/preferences/optimization.py +1 -2
  213. classiq/interface/generator/qpe.py +41 -30
  214. classiq/interface/generator/qsvm.py +9 -10
  215. classiq/interface/generator/quantum_function_call.py +88 -73
  216. classiq/interface/generator/quantum_program.py +41 -24
  217. classiq/interface/generator/range_types.py +11 -12
  218. classiq/interface/generator/register_role.py +18 -6
  219. classiq/interface/generator/slice_parsing_utils.py +5 -5
  220. classiq/interface/generator/standard_gates/controlled_standard_gates.py +30 -39
  221. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  222. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  223. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  224. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  225. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  226. classiq/interface/generator/state_preparation/distributions.py +16 -15
  227. classiq/interface/generator/state_preparation/metrics.py +4 -7
  228. classiq/interface/generator/state_preparation/state_preparation.py +25 -20
  229. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  230. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
  231. classiq/interface/generator/transpiler_basis_gates.py +7 -3
  232. classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
  233. classiq/interface/generator/types/compilation_metadata.py +6 -0
  234. classiq/interface/generator/types/enum_declaration.py +54 -0
  235. classiq/interface/generator/types/qstruct_declaration.py +18 -0
  236. classiq/interface/generator/types/struct_declaration.py +7 -11
  237. classiq/interface/generator/ucc.py +5 -4
  238. classiq/interface/generator/unitary_gate.py +5 -5
  239. classiq/interface/generator/user_defined_function_params.py +4 -1
  240. classiq/interface/generator/validations/flow_graph.py +7 -7
  241. classiq/interface/generator/validations/validator_functions.py +4 -4
  242. classiq/interface/generator/visitor.py +23 -16
  243. classiq/interface/hardware.py +29 -8
  244. classiq/interface/helpers/classproperty.py +8 -0
  245. classiq/interface/helpers/custom_encoders.py +2 -2
  246. classiq/interface/helpers/custom_pydantic_types.py +40 -50
  247. classiq/interface/helpers/datastructures.py +26 -0
  248. classiq/interface/helpers/hashable_mixin.py +3 -2
  249. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  250. classiq/interface/helpers/pydantic_model_helpers.py +7 -5
  251. classiq/interface/helpers/validation_helpers.py +3 -20
  252. classiq/interface/helpers/versioned_model.py +1 -4
  253. classiq/interface/ide/ide_data.py +16 -20
  254. classiq/interface/ide/visual_model.py +130 -0
  255. classiq/interface/interface_version.py +1 -0
  256. classiq/interface/jobs.py +29 -69
  257. classiq/interface/model/allocate.py +16 -0
  258. classiq/interface/model/bind_operation.py +32 -9
  259. classiq/interface/model/classical_if.py +15 -0
  260. classiq/interface/model/classical_parameter_declaration.py +33 -3
  261. classiq/interface/model/control.py +45 -0
  262. classiq/interface/model/handle_binding.py +298 -20
  263. classiq/interface/model/inplace_binary_operation.py +29 -24
  264. classiq/interface/model/invert.py +12 -0
  265. classiq/interface/model/model.py +69 -61
  266. classiq/interface/model/native_function_definition.py +17 -20
  267. classiq/interface/model/parameter.py +13 -0
  268. classiq/interface/model/phase_operation.py +11 -0
  269. classiq/interface/model/port_declaration.py +27 -9
  270. classiq/interface/model/power.py +14 -0
  271. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +30 -18
  272. classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
  273. classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
  274. classiq/interface/model/quantum_function_call.py +141 -343
  275. classiq/interface/model/quantum_function_declaration.py +190 -157
  276. classiq/interface/model/quantum_lambda_function.py +33 -32
  277. classiq/interface/model/quantum_statement.py +71 -12
  278. classiq/interface/model/quantum_type.py +177 -40
  279. classiq/interface/model/quantum_variable_declaration.py +3 -25
  280. classiq/interface/model/repeat.py +15 -0
  281. classiq/interface/model/statement_block.py +40 -14
  282. classiq/interface/model/validation_handle.py +13 -6
  283. classiq/interface/model/variable_declaration_statement.py +3 -1
  284. classiq/interface/model/within_apply_operation.py +7 -5
  285. classiq/interface/server/global_versions.py +6 -7
  286. classiq/interface/server/routes.py +17 -21
  287. classiq/interface/source_reference.py +59 -0
  288. classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
  289. classiq/model_expansions/capturing/__init__.py +0 -0
  290. classiq/model_expansions/capturing/captured_vars.py +435 -0
  291. classiq/model_expansions/capturing/mangling_utils.py +56 -0
  292. classiq/model_expansions/closure.py +171 -0
  293. classiq/model_expansions/debug_flag.py +3 -0
  294. classiq/model_expansions/evaluators/__init__.py +0 -0
  295. classiq/model_expansions/evaluators/arg_type_match.py +158 -0
  296. classiq/model_expansions/evaluators/argument_types.py +42 -0
  297. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  298. classiq/model_expansions/evaluators/control.py +144 -0
  299. classiq/model_expansions/evaluators/parameter_types.py +226 -0
  300. classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
  301. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  302. classiq/model_expansions/expression_evaluator.py +135 -0
  303. classiq/model_expansions/expression_renamer.py +76 -0
  304. classiq/model_expansions/function_builder.py +247 -0
  305. classiq/model_expansions/generative_functions.py +158 -0
  306. classiq/model_expansions/interpreters/__init__.py +0 -0
  307. classiq/model_expansions/interpreters/base_interpreter.py +263 -0
  308. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
  309. classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
  310. classiq/model_expansions/model_tables.py +18 -0
  311. classiq/model_expansions/quantum_operations/__init__.py +9 -0
  312. classiq/model_expansions/quantum_operations/bind.py +60 -0
  313. classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
  314. classiq/model_expansions/quantum_operations/classicalif.py +53 -0
  315. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
  316. classiq/model_expansions/quantum_operations/emitter.py +181 -0
  317. classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
  318. classiq/model_expansions/quantum_operations/repeat.py +56 -0
  319. classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
  320. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  321. classiq/model_expansions/scope.py +240 -0
  322. classiq/model_expansions/scope_initialization.py +150 -0
  323. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  324. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  325. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
  326. classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
  327. classiq/model_expansions/transformers/__init__.py +0 -0
  328. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  329. classiq/model_expansions/transformers/var_splitter.py +299 -0
  330. classiq/model_expansions/utils/__init__.py +0 -0
  331. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  332. classiq/model_expansions/utils/handles_collector.py +33 -0
  333. classiq/model_expansions/visitors/__init__.py +0 -0
  334. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  335. classiq/model_expansions/visitors/variable_references.py +144 -0
  336. classiq/open_library/__init__.py +4 -0
  337. classiq/open_library/functions/__init__.py +130 -0
  338. classiq/open_library/functions/amplitude_estimation.py +30 -0
  339. classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
  340. classiq/open_library/functions/grover.py +157 -0
  341. classiq/open_library/functions/hea.py +115 -0
  342. classiq/open_library/functions/linear_pauli_rotation.py +82 -0
  343. classiq/open_library/functions/modular_exponentiation.py +201 -0
  344. classiq/open_library/functions/qaoa_penalty.py +117 -0
  345. classiq/open_library/functions/qft_functions.py +54 -0
  346. classiq/open_library/functions/qpe.py +46 -0
  347. classiq/open_library/functions/qsvt.py +331 -0
  348. classiq/open_library/functions/state_preparation.py +301 -0
  349. classiq/open_library/functions/swap_test.py +27 -0
  350. classiq/open_library/functions/utility_functions.py +81 -0
  351. classiq/open_library/functions/variational.py +52 -0
  352. classiq/qmod/__init__.py +10 -10
  353. classiq/qmod/builtins/__init__.py +19 -2
  354. classiq/qmod/builtins/classical_execution_primitives.py +36 -14
  355. classiq/qmod/builtins/classical_functions.py +39 -43
  356. classiq/qmod/builtins/constants.py +10 -0
  357. classiq/qmod/builtins/enums.py +208 -0
  358. classiq/qmod/builtins/functions/__init__.py +137 -0
  359. classiq/qmod/builtins/functions/allocation.py +150 -0
  360. classiq/qmod/builtins/functions/arithmetic.py +55 -0
  361. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  362. classiq/qmod/builtins/functions/chemistry.py +91 -0
  363. classiq/qmod/builtins/functions/exponentiation.py +105 -0
  364. classiq/qmod/builtins/functions/finance.py +34 -0
  365. classiq/qmod/builtins/functions/operators.py +16 -0
  366. classiq/qmod/builtins/functions/qsvm.py +24 -0
  367. classiq/qmod/builtins/functions/standard_gates.py +651 -0
  368. classiq/qmod/builtins/operations.py +373 -40
  369. classiq/qmod/builtins/structs.py +103 -80
  370. classiq/qmod/cfunc.py +2 -2
  371. classiq/qmod/classical_function.py +4 -8
  372. classiq/qmod/cparam.py +64 -0
  373. classiq/qmod/create_model_function.py +56 -0
  374. classiq/qmod/declaration_inferrer.py +143 -101
  375. classiq/qmod/expression_query.py +20 -4
  376. classiq/qmod/generative.py +42 -0
  377. classiq/qmod/model_state_container.py +18 -6
  378. classiq/qmod/native/__init__.py +7 -0
  379. classiq/qmod/native/expression_to_qmod.py +16 -11
  380. classiq/qmod/native/pretty_printer.py +187 -97
  381. classiq/qmod/pretty_print/__init__.py +7 -0
  382. classiq/qmod/pretty_print/expression_to_python.py +222 -0
  383. classiq/qmod/pretty_print/pretty_printer.py +572 -0
  384. classiq/qmod/python_classical_type.py +67 -0
  385. classiq/qmod/qfunc.py +60 -8
  386. classiq/qmod/qmod_constant.py +93 -26
  387. classiq/qmod/qmod_parameter.py +68 -59
  388. classiq/qmod/qmod_variable.py +468 -155
  389. classiq/qmod/quantum_callable.py +17 -7
  390. classiq/qmod/quantum_expandable.py +269 -96
  391. classiq/qmod/quantum_function.py +196 -41
  392. classiq/qmod/semantics/__init__.py +0 -0
  393. classiq/qmod/semantics/annotation/__init__.py +0 -0
  394. classiq/qmod/semantics/annotation/call_annotation.py +92 -0
  395. classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
  396. classiq/qmod/semantics/error_manager.py +88 -0
  397. classiq/qmod/semantics/lambdas.py +25 -0
  398. classiq/qmod/semantics/static_semantics_visitor.py +384 -0
  399. classiq/qmod/semantics/validation/__init__.py +0 -0
  400. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  401. classiq/qmod/semantics/validation/func_call_validation.py +99 -0
  402. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  403. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  404. classiq/qmod/semantics/validation/main_validation.py +33 -0
  405. classiq/qmod/semantics/validation/types_validation.py +128 -0
  406. classiq/qmod/symbolic.py +147 -123
  407. classiq/qmod/symbolic_expr.py +27 -12
  408. classiq/qmod/symbolic_type.py +2 -5
  409. classiq/qmod/type_attribute_remover.py +32 -0
  410. classiq/qmod/utilities.py +98 -4
  411. classiq/qmod/write_qmod.py +17 -3
  412. classiq/synthesis.py +210 -22
  413. {classiq-0.38.0.dist-info → classiq-0.65.4.dist-info}/METADATA +16 -9
  414. classiq-0.65.4.dist-info/RECORD +521 -0
  415. classiq/_internals/_qfunc_ext.py +0 -6
  416. classiq/applications/benchmarking/__init__.py +0 -9
  417. classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
  418. classiq/applications/numpy_utils.py +0 -37
  419. classiq/applications_model_constructors/__init__.py +0 -25
  420. classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
  421. classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -65
  422. classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +0 -243
  423. classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
  424. classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
  425. classiq/builtin_functions/__init__.py +0 -43
  426. classiq/builtin_functions/amplitude_loading.py +0 -3
  427. classiq/builtin_functions/binary_ops.py +0 -1
  428. classiq/builtin_functions/exponentiation.py +0 -5
  429. classiq/builtin_functions/qpe.py +0 -4
  430. classiq/builtin_functions/qsvm.py +0 -7
  431. classiq/builtin_functions/range_types.py +0 -5
  432. classiq/builtin_functions/standard_gates.py +0 -1
  433. classiq/builtin_functions/state_preparation.py +0 -6
  434. classiq/builtin_functions/suzuki_trotter.py +0 -3
  435. classiq/interface/executor/aws_execution_cost.py +0 -73
  436. classiq/interface/executor/error_mitigation.py +0 -6
  437. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
  438. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
  439. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  440. classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
  441. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
  442. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  443. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  444. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  445. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  446. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
  447. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
  448. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -1229
  449. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
  450. classiq/interface/generator/functions/foreign_function_definition.py +0 -114
  451. classiq/interface/generator/functions/function_implementation.py +0 -107
  452. classiq/interface/generator/functions/native_function_definition.py +0 -155
  453. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  454. classiq/interface/generator/functions/register.py +0 -44
  455. classiq/interface/generator/functions/register_mapping_data.py +0 -106
  456. classiq/interface/generator/inequality_mixer.py +0 -51
  457. classiq/interface/generator/model/classical_main_validator.py +0 -106
  458. classiq/interface/generator/range_mixer.py +0 -56
  459. classiq/interface/generator/state_propagator.py +0 -74
  460. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  461. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
  462. classiq/interface/ide/show.py +0 -34
  463. classiq/interface/model/call_synthesis_data.py +0 -68
  464. classiq/interface/model/common_model_types.py +0 -23
  465. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  466. classiq/interface/model/quantum_if_operation.py +0 -94
  467. classiq/interface/model/resolvers/function_call_resolver.py +0 -43
  468. classiq/interface/model/validations/handle_validation_base.py +0 -55
  469. classiq/interface/model/validations/handles_validator.py +0 -156
  470. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  471. classiq/model/__init__.py +0 -14
  472. classiq/model/composite_function_generator.py +0 -33
  473. classiq/model/function_handler.py +0 -462
  474. classiq/model/logic_flow.py +0 -149
  475. classiq/model/logic_flow_change_handler.py +0 -71
  476. classiq/model/model.py +0 -229
  477. classiq/qmod/builtins/functions.py +0 -913
  478. classiq/qmod/qmod_struct.py +0 -37
  479. classiq/quantum_functions/__init__.py +0 -17
  480. classiq/quantum_functions/annotation_parser.py +0 -205
  481. classiq/quantum_functions/decorators.py +0 -22
  482. classiq/quantum_functions/function_library.py +0 -181
  483. classiq/quantum_functions/function_parser.py +0 -74
  484. classiq/quantum_functions/quantum_function.py +0 -236
  485. classiq-0.38.0.dist-info/RECORD +0 -454
  486. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
  487. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
  488. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
  489. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
  490. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
  491. /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  492. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  493. /classiq/{interface/generator/credit_risk_example → applications/hamiltonian}/__init__.py +0 -0
  494. /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
  495. /classiq/interface/{model/resolvers → debug_info}/__init__.py +0 -0
  496. /classiq/{_internals → interface}/enum_utils.py +0 -0
  497. /classiq/interface/{model/validations → generator/functions/builtins}/__init__.py +0 -0
  498. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → model_expansions/__init__.py} +0 -0
  499. {classiq-0.38.0.dist-info → classiq-0.65.4.dist-info}/WHEEL +0 -0
@@ -1,24 +1,29 @@
1
1
  import math
2
+ from collections.abc import Iterable
2
3
  from typing import (
3
4
  Any,
4
5
  ClassVar,
5
- Dict,
6
6
  Generic,
7
- Iterable,
8
7
  Literal,
9
8
  Optional,
10
- Tuple,
11
- Type,
12
9
  TypeVar,
13
10
  Union,
14
11
  )
15
12
 
16
13
  import pydantic
17
- from pydantic.generics import GenericModel
14
+ from pydantic import BaseModel
15
+ from pydantic_core.core_schema import ValidationInfo
16
+ from typing_extensions import Self
18
17
 
18
+ from classiq.interface.enum_utils import StrEnum
19
+ from classiq.interface.exceptions import ClassiqValueError
19
20
  from classiq.interface.generator.arith import argument_utils, number_utils
20
- from classiq.interface.generator.arith.argument_utils import RegisterOrConst
21
+ from classiq.interface.generator.arith.argument_utils import (
22
+ RegisterOrConst,
23
+ as_arithmetic_info,
24
+ )
21
25
  from classiq.interface.generator.arith.arithmetic_operations import (
26
+ MODULO_WITH_FRACTION_PLACES_ERROR_MSG,
22
27
  ArithmeticOperationParams,
23
28
  )
24
29
  from classiq.interface.generator.arith.ast_node_rewrite import (
@@ -28,9 +33,6 @@ from classiq.interface.generator.arith.register_user_input import RegisterArithm
28
33
  from classiq.interface.generator.arith.unary_ops import Negation
29
34
  from classiq.interface.generator.function_params import get_zero_input_name
30
35
 
31
- from classiq._internals.enum_utils import StrEnum
32
- from classiq.exceptions import ClassiqValueError
33
-
34
36
  LeftDataT = TypeVar("LeftDataT")
35
37
  RightDataT = TypeVar("RightDataT")
36
38
  _NumericArgumentInplaceErrorMessage: str = "Cannot inplace the numeric argument {}"
@@ -51,23 +53,24 @@ class ArgToInplace(StrEnum):
51
53
 
52
54
 
53
55
  class BinaryOpParams(
54
- ArithmeticOperationParams, GenericModel, Generic[LeftDataT, RightDataT]
56
+ ArithmeticOperationParams, BaseModel, Generic[LeftDataT, RightDataT]
55
57
  ):
56
58
  left_arg: LeftDataT
57
59
  right_arg: RightDataT
58
60
  left_arg_name: ClassVar[str] = DEFAULT_LEFT_ARG_NAME
59
61
  right_arg_name: ClassVar[str] = DEFAULT_RIGHT_ARG_NAME
60
62
 
61
- @pydantic.root_validator(pre=True)
62
- def _validate_one_is_register(cls, values: Dict[str, Any]) -> Dict[str, Any]:
63
- left_arg = values.get("left_arg")
64
- right_arg = values.get("right_arg")
65
- if isinstance(left_arg, Numeric) and isinstance(right_arg, Numeric):
66
- raise ClassiqValueError("One argument must be a register")
67
- if left_arg is right_arg and isinstance(left_arg, pydantic.BaseModel):
68
- # In case both arguments refer to the same object, copy it.
69
- # This prevents changes performed on one argument to affect the other.
70
- values["right_arg"] = left_arg.copy(deep=True)
63
+ @pydantic.model_validator(mode="before")
64
+ @classmethod
65
+ def _clone_repeated_arg(cls, values: Any) -> dict[str, Any]:
66
+ if isinstance(values, dict):
67
+ left_arg = values.get("left_arg")
68
+ right_arg = values.get("right_arg")
69
+
70
+ if left_arg is right_arg and isinstance(left_arg, pydantic.BaseModel):
71
+ # In case both arguments refer to the same object, copy it.
72
+ # This prevents changes performed on one argument to affect the other.
73
+ values["right_arg"] = left_arg.model_copy(deep=True)
71
74
  return values
72
75
 
73
76
  def garbage_output_size(self) -> pydantic.NonNegativeInt:
@@ -105,19 +108,21 @@ class InplacableBinaryOpParams(
105
108
  ):
106
109
  inplace_arg: Optional[ArgToInplace] = None
107
110
 
108
- @pydantic.root_validator(pre=True)
109
- def _validate_inplace_arg(cls, values: Dict[str, Any]) -> Dict[str, Any]:
110
- left_arg = values.get("left_arg")
111
- right_arg = values.get("right_arg")
112
- inplace_arg: Optional[ArgToInplace] = values.get("inplace_arg")
113
- if inplace_arg == ArgToInplace.RIGHT and isinstance(right_arg, Numeric):
114
- raise ClassiqValueError(
115
- _NumericArgumentInplaceErrorMessage.format(right_arg)
116
- )
117
- elif inplace_arg == ArgToInplace.LEFT and isinstance(left_arg, Numeric):
118
- raise ClassiqValueError(
119
- _NumericArgumentInplaceErrorMessage.format(left_arg)
120
- )
111
+ @pydantic.model_validator(mode="before")
112
+ @classmethod
113
+ def _validate_inplace_arg(cls, values: Any) -> dict[str, Any]:
114
+ if isinstance(values, dict):
115
+ left_arg = values.get("left_arg")
116
+ right_arg = values.get("right_arg")
117
+ inplace_arg: Optional[ArgToInplace] = values.get("inplace_arg")
118
+ if inplace_arg == ArgToInplace.RIGHT and isinstance(right_arg, Numeric):
119
+ raise ClassiqValueError(
120
+ _NumericArgumentInplaceErrorMessage.format(right_arg)
121
+ )
122
+ elif inplace_arg == ArgToInplace.LEFT and isinstance(left_arg, Numeric):
123
+ raise ClassiqValueError(
124
+ _NumericArgumentInplaceErrorMessage.format(left_arg)
125
+ )
121
126
  return values
122
127
 
123
128
  def _create_ios(self) -> None:
@@ -154,9 +159,13 @@ class InplacableBinaryOpParams(
154
159
  if self.inplace_arg is None:
155
160
  return 0
156
161
  arg = self.left_arg if self.inplace_arg == ArgToInplace.LEFT else self.right_arg
157
- return max(0, arg.integer_part_size - self.result_register.integer_part_size) # type: ignore[attr-defined]
162
+ return max(
163
+ 0, arg.integer_part_size - self.result_register.integer_part_size # type: ignore[attr-defined]
164
+ ) + max(
165
+ 0, arg.fraction_places - self.result_register.fraction_places # type: ignore[attr-defined]
166
+ )
158
167
 
159
- def _carried_arguments(self) -> Tuple[Optional[LeftDataT], Optional[RightDataT]]:
168
+ def _carried_arguments(self) -> tuple[Optional[LeftDataT], Optional[RightDataT]]:
160
169
  if self.inplace_arg == ArgToInplace.RIGHT and isinstance(
161
170
  self.left_arg, RegisterArithmeticInfo
162
171
  ):
@@ -187,28 +196,28 @@ class InplacableBinaryOpParams(
187
196
  yield ArgToInplace.LEFT
188
197
 
189
198
  def get_params_inplace_options(self) -> Iterable["InplacableBinaryOpParams"]:
190
- params_kwargs = self.copy().__dict__
199
+ params_kwargs = self.model_copy().__dict__
191
200
  for inplace_arg in self._get_binary_op_inplace_options():
192
201
  params_kwargs["inplace_arg"] = inplace_arg
193
202
  yield self.__class__(**params_kwargs)
194
203
 
195
204
 
196
205
  class BinaryOpWithIntInputs(BinaryOpParams[RegisterOrInt, RegisterOrInt]):
197
- @pydantic.root_validator()
198
- def validate_int_registers(cls, values: Dict[str, Any]) -> Dict[str, Any]:
199
- left_arg = values.get("left_arg")
206
+ @pydantic.model_validator(mode="after")
207
+ def validate_int_registers(self) -> Self:
208
+ left_arg = self.left_arg
200
209
  is_left_arg_float_register = (
201
210
  isinstance(left_arg, RegisterArithmeticInfo)
202
211
  and left_arg.fraction_places > 0
203
212
  )
204
- right_arg = values.get("right_arg")
213
+ right_arg = self.right_arg
205
214
  is_right_arg_float_register = (
206
215
  isinstance(right_arg, RegisterArithmeticInfo)
207
216
  and right_arg.fraction_places > 0
208
217
  )
209
218
  if is_left_arg_float_register or is_right_arg_float_register:
210
219
  raise ClassiqValueError(BOOLEAN_OP_WITH_FRACTIONS_ERROR)
211
- return values
220
+ return self
212
221
 
213
222
  @staticmethod
214
223
  def _is_signed(arg: Union[int, RegisterArithmeticInfo]) -> bool:
@@ -259,15 +268,21 @@ class Adder(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
259
268
  output_name = "sum"
260
269
 
261
270
  def _get_result_register(self) -> RegisterArithmeticInfo:
262
- lb = argument_utils.lower_bound(self.left_arg) + argument_utils.lower_bound(
263
- self.right_arg
271
+ left_arg = argument_utils.limit_fraction_places(
272
+ self.left_arg, self.machine_precision
273
+ )
274
+ right_arg = argument_utils.limit_fraction_places(
275
+ self.right_arg, self.machine_precision
276
+ )
277
+ lb = argument_utils.lower_bound(left_arg) + argument_utils.lower_bound(
278
+ right_arg
264
279
  )
265
- ub = argument_utils.upper_bound(self.left_arg) + argument_utils.upper_bound(
266
- self.right_arg
280
+ ub = argument_utils.upper_bound(left_arg) + argument_utils.upper_bound(
281
+ right_arg
267
282
  )
268
283
  fraction_places = max(
269
- argument_utils.fraction_places(self.left_arg),
270
- argument_utils.fraction_places(self.right_arg),
284
+ argument_utils.fraction_places(left_arg),
285
+ argument_utils.fraction_places(right_arg),
271
286
  )
272
287
  return RegisterArithmeticInfo(
273
288
  size=self.output_size or self._get_output_size(ub, lb, fraction_places),
@@ -278,8 +293,9 @@ class Adder(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
278
293
 
279
294
  def _get_output_size(self, ub: float, lb: float, fraction_places: int) -> int:
280
295
  if isinstance(self.left_arg, float) and self.left_arg == 0.0:
281
- assert isinstance(self.right_arg, RegisterArithmeticInfo)
282
- return self.right_arg.size
296
+ if isinstance(self.right_arg, RegisterArithmeticInfo):
297
+ return self.right_arg.size
298
+ return as_arithmetic_info(self.right_arg).size
283
299
  elif isinstance(self.right_arg, float) and self.right_arg == 0.0:
284
300
  assert isinstance(self.left_arg, RegisterArithmeticInfo)
285
301
  return self.left_arg.size
@@ -291,60 +307,121 @@ class Adder(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
291
307
  class Subtractor(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
292
308
  output_name = "difference"
293
309
 
310
+ @staticmethod
311
+ def _get_effective_arg(
312
+ arg: RegisterOrConst, machine_precision: int
313
+ ) -> RegisterOrConst:
314
+ return argument_utils.limit_fraction_places(arg, machine_precision)
315
+
316
+ @property
317
+ def effective_left_arg(self) -> RegisterOrConst:
318
+ return self._get_effective_arg(self.left_arg, self.machine_precision)
319
+
320
+ @property
321
+ def effective_right_arg(self) -> RegisterOrConst:
322
+ return self._get_effective_arg(self.right_arg, self.machine_precision)
323
+
324
+ @staticmethod
325
+ def _is_arg_trimmed_register(arg: RegisterOrConst, machine_precision: int) -> bool:
326
+ return (
327
+ isinstance(arg, RegisterArithmeticInfo)
328
+ and arg.fraction_places > machine_precision
329
+ )
330
+
331
+ @property
332
+ def left_arg_is_trimmed_register(self) -> bool:
333
+ return self._is_arg_trimmed_register(self.left_arg, self.machine_precision)
334
+
335
+ @property
336
+ def right_arg_is_trimmed_register(self) -> bool:
337
+ return self._is_arg_trimmed_register(self.right_arg, self.machine_precision)
338
+
294
339
  def _get_result_register(self) -> RegisterArithmeticInfo:
295
340
  bounds = (
296
- argument_utils.lower_bound(self.left_arg)
297
- - argument_utils.upper_bound(self.right_arg),
298
- argument_utils.upper_bound(self.left_arg)
299
- - argument_utils.lower_bound(self.right_arg),
341
+ argument_utils.lower_bound(self.effective_left_arg)
342
+ - argument_utils.upper_bound(self.effective_right_arg),
343
+ argument_utils.upper_bound(self.effective_left_arg)
344
+ - argument_utils.lower_bound(self.effective_right_arg),
300
345
  )
301
346
  fraction_places = max(
302
- argument_utils.fraction_places(self.left_arg),
303
- argument_utils.fraction_places(self.right_arg),
347
+ argument_utils.fraction_places(self.effective_left_arg),
348
+ argument_utils.fraction_places(self.effective_right_arg),
304
349
  )
305
350
 
351
+ size = self.output_size or self._get_output_size(bounds, fraction_places)
352
+ is_signed = self._include_sign and min(bounds) < 0
306
353
  return RegisterArithmeticInfo(
307
- size=self.output_size or self._get_output_size(bounds, fraction_places),
354
+ size=size,
308
355
  fraction_places=fraction_places,
309
- is_signed=self._include_sign and min(bounds) < 0,
310
- bounds=self._legal_bounds(bounds),
356
+ is_signed=is_signed,
357
+ bounds=self._legal_bounds(
358
+ bounds,
359
+ RegisterArithmeticInfo.get_maximal_bounds(
360
+ size=size, is_signed=is_signed, fraction_places=fraction_places
361
+ ),
362
+ ),
311
363
  )
312
364
 
313
365
  def _get_output_size(
314
- self, bounds: Tuple[float, float], fraction_places: int
366
+ self, bounds: tuple[float, float], fraction_places: int
315
367
  ) -> int:
316
- if isinstance(self.right_arg, float) and self.right_arg == 0:
317
- assert isinstance(self.left_arg, RegisterArithmeticInfo)
318
- return self.left_arg.size
368
+ if isinstance(self.right_arg, float) and self.effective_right_arg == 0:
369
+ assert isinstance(self.effective_left_arg, RegisterArithmeticInfo)
370
+ return self.effective_left_arg.size
319
371
  integer_part_size = number_utils.bounds_to_integer_part_size(*bounds)
320
372
  size_needed = integer_part_size + fraction_places
321
373
  return size_needed
322
374
 
323
375
  def garbage_output_size(self) -> pydantic.NonNegativeInt:
324
- if not isinstance(self.right_arg, RegisterArithmeticInfo):
376
+ if (
377
+ not self.left_arg_is_trimmed_register
378
+ and not self.right_arg_is_trimmed_register
379
+ ):
380
+ return self._untrimmed_garbage_output_size()
381
+ if not self.is_inplaced():
382
+ return 0
383
+ inplace_arg_name = (
384
+ self.left_arg_name
385
+ if self.inplace_arg == ArgToInplace.LEFT
386
+ else self.right_arg_name
387
+ )
388
+ return max(
389
+ 0,
390
+ self._inputs[inplace_arg_name].fraction_places
391
+ - self.result_register.fraction_places,
392
+ )
393
+
394
+ def _untrimmed_garbage_output_size(self) -> pydantic.NonNegativeInt:
395
+ if not isinstance(self.effective_right_arg, RegisterArithmeticInfo):
325
396
  adder_params = Adder(
326
- left_arg=self.left_arg,
327
- right_arg=-self.right_arg,
397
+ left_arg=self.effective_left_arg,
398
+ right_arg=-self.effective_right_arg,
328
399
  output_size=self.output_size,
329
400
  inplace_arg=self.inplace_arg,
330
401
  )
331
402
  return adder_params.garbage_output_size()
332
403
 
333
404
  negation_params = Negation(
334
- arg=self.right_arg,
405
+ arg=self.effective_right_arg,
335
406
  output_size=self.negation_output_size,
336
407
  inplace=self.should_inplace_negation,
408
+ bypass_bounds_validation=True,
337
409
  )
338
410
  negation_result = negation_params.result_register
339
- if self.output_size is None and max(self.right_arg.bounds) > 0:
340
- negation_result = negation_result.copy(
341
- update=dict(
342
- is_signed=True,
343
- bounds=(-max(self.right_arg.bounds), -min(self.right_arg.bounds)),
344
- )
411
+ if self.output_size is None and max(self.effective_right_arg.bounds) > 0:
412
+ bounds = (
413
+ -max(self.effective_right_arg.bounds),
414
+ -min(self.effective_right_arg.bounds),
415
+ )
416
+ negation_result = RegisterArithmeticInfo(
417
+ size=negation_result.size,
418
+ fraction_places=negation_result.fraction_places,
419
+ is_signed=True,
420
+ bounds=bounds,
421
+ bypass_bounds_validation=True,
345
422
  )
346
423
  adder_params = Adder(
347
- left_arg=self.left_arg,
424
+ left_arg=self.effective_left_arg,
348
425
  right_arg=negation_result,
349
426
  output_size=self.output_size,
350
427
  inplace_arg=self.arg_to_inplace_adder,
@@ -359,10 +436,10 @@ class Subtractor(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
359
436
  return self.inplace_arg == ArgToInplace.LEFT
360
437
 
361
438
  def _expected_negation_output_size(self) -> int:
362
- return argument_utils.fraction_places(self.right_arg) + min(
439
+ return argument_utils.fraction_places(self.effective_right_arg) + min(
363
440
  self.result_register.integer_part_size,
364
441
  number_utils.bounds_to_integer_part_size(
365
- *(-bound for bound in argument_utils.bounds(self.right_arg))
442
+ *(-bound for bound in argument_utils.bounds(self.effective_right_arg))
366
443
  ),
367
444
  )
368
445
 
@@ -390,54 +467,61 @@ class Multiplier(BinaryOpWithFloatInputs):
390
467
 
391
468
  def expected_fraction_places(self) -> int:
392
469
  return argument_utils.fraction_places(
393
- argument_utils.limit_fraction_places(
394
- self.left_arg, machine_precision=self.machine_precision
395
- )
470
+ argument_utils.limit_fraction_places(self.left_arg, self.machine_precision)
396
471
  ) + argument_utils.fraction_places(
397
- argument_utils.limit_fraction_places(
398
- self.right_arg, machine_precision=self.machine_precision
399
- )
472
+ argument_utils.limit_fraction_places(self.right_arg, self.machine_precision)
400
473
  )
401
474
 
402
475
  @staticmethod
403
476
  def _get_bounds(
404
- args: Tuple[RegisterOrConst, RegisterOrConst], machine_precision: int
405
- ) -> Tuple[float, float]:
477
+ args: tuple[RegisterOrConst, RegisterOrConst], machine_precision: int
478
+ ) -> tuple[float, float]:
406
479
  extremal_values = [
407
480
  left * right
408
481
  for left in argument_utils.bounds(args[0])
409
482
  for right in argument_utils.bounds(args[1])
410
483
  ]
411
484
  return (
412
- number_utils.limit_fraction_places(
413
- min(extremal_values), machine_precision=machine_precision
414
- ),
415
- number_utils.limit_fraction_places(
416
- max(extremal_values), machine_precision=machine_precision
417
- ),
485
+ number_utils.limit_fraction_places(min(extremal_values), machine_precision),
486
+ number_utils.limit_fraction_places(max(extremal_values), machine_precision),
418
487
  )
419
488
 
420
489
  def _get_result_register(self) -> RegisterArithmeticInfo:
421
490
  fraction_places = min(self.machine_precision, self.expected_fraction_places())
422
491
  left_arg = argument_utils.limit_fraction_places(
423
- self.left_arg, machine_precision=self.machine_precision
492
+ self.left_arg, self.machine_precision
424
493
  )
425
494
  right_arg = argument_utils.limit_fraction_places(
426
- self.right_arg, machine_precision=self.machine_precision
495
+ self.right_arg, self.machine_precision
427
496
  )
428
497
  bounds = self._get_bounds((left_arg, right_arg), self.machine_precision)
498
+ if self.output_size:
499
+ if fraction_places:
500
+ raise ValueError(MODULO_WITH_FRACTION_PLACES_ERROR_MSG)
501
+ max_bounds = RegisterArithmeticInfo.get_maximal_bounds(
502
+ size=self.output_size, is_signed=False, fraction_places=0
503
+ )
504
+ bounds = number_utils.bounds_cut(bounds, max_bounds)
429
505
 
506
+ size = self.output_size or self._get_output_size(
507
+ bounds, fraction_places, left_arg, right_arg
508
+ )
509
+ is_signed = self._include_sign and min(bounds) < 0
430
510
  return RegisterArithmeticInfo(
431
- size=self.output_size
432
- or self._get_output_size(bounds, fraction_places, left_arg, right_arg),
511
+ size=size,
433
512
  fraction_places=fraction_places,
434
- is_signed=self._include_sign and min(bounds) < 0,
435
- bounds=self._legal_bounds(bounds),
513
+ is_signed=is_signed,
514
+ bounds=self._legal_bounds(
515
+ bounds,
516
+ RegisterArithmeticInfo.get_maximal_bounds(
517
+ size=size, is_signed=is_signed, fraction_places=fraction_places
518
+ ),
519
+ ),
436
520
  )
437
521
 
438
522
  @staticmethod
439
523
  def _get_output_size(
440
- bounds: Tuple[float, float],
524
+ bounds: tuple[float, float],
441
525
  fraction_places: int,
442
526
  left_arg: Union[RegisterArithmeticInfo, float],
443
527
  right_arg: Union[RegisterArithmeticInfo, float],
@@ -497,7 +581,8 @@ class LessEqual(Comparator):
497
581
  class Power(BinaryOpParams[RegisterArithmeticInfo, pydantic.PositiveInt]):
498
582
  output_name = "powered"
499
583
 
500
- @pydantic.validator("right_arg", pre=True)
584
+ @pydantic.field_validator("right_arg", mode="before")
585
+ @classmethod
501
586
  def _validate_legal_power(cls, right_arg: Any) -> pydantic.PositiveInt:
502
587
  if not float(right_arg).is_integer():
503
588
  raise ClassiqValueError("Power must be an integer")
@@ -509,13 +594,13 @@ class Power(BinaryOpParams[RegisterArithmeticInfo, pydantic.PositiveInt]):
509
594
  return (
510
595
  argument_utils.fraction_places(
511
596
  argument_utils.limit_fraction_places(
512
- self.left_arg, machine_precision=self.machine_precision
597
+ self.left_arg, self.machine_precision
513
598
  )
514
599
  )
515
600
  * self.right_arg
516
601
  )
517
602
 
518
- def _get_result_bounds(self) -> Tuple[float, float]:
603
+ def _get_result_bounds(self) -> tuple[float, float]:
519
604
  bounds = [
520
605
  number_utils.limit_fraction_places(
521
606
  bound, machine_precision=self.machine_precision
@@ -556,11 +641,11 @@ class Power(BinaryOpParams[RegisterArithmeticInfo, pydantic.PositiveInt]):
556
641
 
557
642
  def _get_inner_action_garbage_size(
558
643
  self,
559
- action_type: Union[Type["Power"], Type[Multiplier]],
644
+ action_type: Union[type["Power"], type[Multiplier]],
560
645
  *,
561
646
  arg: RegisterArithmeticInfo,
562
647
  action_right_arg: RegisterOrConst,
563
- compute_power: int
648
+ compute_power: int,
564
649
  ) -> pydantic.NonNegativeInt:
565
650
  inner_compute_power_params = Power(
566
651
  left_arg=arg,
@@ -609,19 +694,19 @@ class LShift(EffectiveUnaryOpParams[pydantic.NonNegativeInt]):
609
694
  output_name = "left_shifted"
610
695
  inplace_arg: Optional[ArgToInplace] = ArgToInplace.LEFT
611
696
 
612
- @pydantic.root_validator()
613
- def _validate_legal_modulo(cls, values: Dict[str, Any]) -> Dict[str, Any]:
614
- output_size = values.get("output_size")
697
+ @pydantic.model_validator(mode="after")
698
+ def _validate_legal_modulo(self) -> Self:
699
+ output_size = self.output_size
615
700
  if output_size is None:
616
- return values
617
- arg = values.get("left_arg")
618
- shift = values.get("right_arg")
701
+ return self
702
+ arg = self.left_arg
703
+ shift = self.right_arg
619
704
  if not isinstance(arg, RegisterArithmeticInfo):
620
705
  raise ClassiqValueError("left arg must be a RegisterArithmeticInfo")
621
706
  if not isinstance(shift, int):
622
707
  raise ClassiqValueError("Shift must be an integer")
623
708
  assert arg.fraction_places - shift <= 0, _FLOATING_POINT_MODULO_ERROR_MESSAGE
624
- return values
709
+ return self
625
710
 
626
711
  def garbage_output_size(self) -> pydantic.NonNegativeInt:
627
712
  if self.inplace_arg is None or self.output_size is None:
@@ -650,21 +735,21 @@ class RShift(EffectiveUnaryOpParams[pydantic.NonNegativeInt]):
650
735
  def _shifted_fraction_places(*, arg: RegisterArithmeticInfo, shift: int) -> int:
651
736
  return arg.fraction_places * int(arg.is_signed or shift < arg.size)
652
737
 
653
- @pydantic.root_validator()
654
- def _validate_legal_modulo(cls, values: Dict[str, Any]) -> Dict[str, Any]:
655
- output_size = values.get("output_size")
738
+ @pydantic.model_validator(mode="after")
739
+ def _validate_legal_modulo(self) -> Self:
740
+ output_size = self.output_size
656
741
  if output_size is None:
657
- return values
658
- arg = values.get("left_arg")
659
- shift = values.get("right_arg")
742
+ return self
743
+ arg = self.left_arg
744
+ shift = self.right_arg
660
745
  if not isinstance(arg, RegisterArithmeticInfo):
661
746
  raise ClassiqValueError("left arg must be a RegisterArithmeticInfo")
662
747
  if not isinstance(shift, int):
663
748
  raise ClassiqValueError("Shift must be an integer")
664
749
  assert (
665
- cls._shifted_fraction_places(arg=arg, shift=shift) == 0
750
+ self._shifted_fraction_places(arg=arg, shift=shift) == 0
666
751
  ), _FLOATING_POINT_MODULO_ERROR_MESSAGE
667
- return values
752
+ return self
668
753
 
669
754
  def garbage_output_size(self) -> pydantic.NonNegativeInt:
670
755
  if self.inplace_arg is None:
@@ -694,16 +779,16 @@ class CyclicShift(EffectiveUnaryOpParams[int]):
694
779
  output_name = "cyclic_shifted"
695
780
  inplace_arg: Optional[ArgToInplace] = ArgToInplace.LEFT
696
781
 
697
- @pydantic.root_validator()
698
- def _validate_legal_modulo(cls, values: Dict[str, Any]) -> Dict[str, Any]:
699
- output_size = values.get("output_size")
782
+ @pydantic.model_validator(mode="after")
783
+ def _validate_legal_modulo(self) -> Self:
784
+ output_size = self.output_size
700
785
  if output_size is None:
701
- return values
702
- arg = values.get("left_arg")
786
+ return self
787
+ arg = self.left_arg
703
788
  if not isinstance(arg, RegisterArithmeticInfo):
704
789
  raise ClassiqValueError("left arg must be a RegisterArithmeticInfo")
705
790
  assert arg.fraction_places == 0, _FLOATING_POINT_MODULO_ERROR_MESSAGE
706
- return values
791
+ return self
707
792
 
708
793
  def garbage_output_size(self) -> pydantic.NonNegativeInt:
709
794
  if self.inplace_arg is None:
@@ -722,27 +807,30 @@ class Modulo(EffectiveUnaryOpParams[int]):
722
807
  output_name = "modulus"
723
808
  inplace_arg: Optional[ArgToInplace] = ArgToInplace.LEFT
724
809
 
725
- @pydantic.validator("left_arg")
810
+ @pydantic.field_validator("left_arg", mode="before")
811
+ @classmethod
726
812
  def _validate_left_arg_is_integer(
727
813
  cls, left_arg: RegisterArithmeticInfo
728
814
  ) -> RegisterArithmeticInfo:
729
815
  assert left_arg.fraction_places == 0, _FLOATING_POINT_MODULO_ERROR_MESSAGE
730
816
  return left_arg
731
817
 
732
- @pydantic.validator("right_arg")
818
+ @pydantic.field_validator("right_arg", mode="before")
819
+ @classmethod
733
820
  def _validate_right_arg_is_a_power_of_two(
734
- cls, right_arg: int, values: Dict[str, Any]
821
+ cls, right_arg: int, info: ValidationInfo
735
822
  ) -> int:
736
823
  repr_qubits_float = math.log2(right_arg)
737
824
  repr_qubits = round(repr_qubits_float)
738
825
  assert abs(repr_qubits - repr_qubits_float) < 10**-8, NOT_POWER_OF_TWO_ERROR_MSG
739
- output_size = values.get("output_size")
826
+ output_size = info.data.get("output_size")
740
827
  if output_size is not None:
741
828
  repr_qubits = min(repr_qubits, output_size)
742
- values["output_size"] = None
829
+ info.data["output_size"] = None
743
830
  return 2 ** (repr_qubits)
744
831
 
745
832
  def _get_result_register(self) -> RegisterArithmeticInfo:
746
- return RegisterArithmeticInfo(
747
- size=round(math.log2(self.right_arg)), is_signed=False, fraction_places=0
748
- )
833
+ size = round(math.log2(self.right_arg))
834
+ if size <= 0:
835
+ raise ClassiqValueError("Cannot use a quantum expression with zero size")
836
+ return RegisterArithmeticInfo(size=size, is_signed=False, fraction_places=0)
@@ -1,4 +1,4 @@
1
- from classiq._internals.enum_utils import StrEnum
1
+ from classiq.interface.enum_utils import StrEnum
2
2
 
3
3
 
4
4
  class Endianness(StrEnum):