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,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):
@@ -1,11 +1,14 @@
1
1
  import abc
2
- from typing import Any, Dict, Iterable
2
+ from collections.abc import Iterable
3
+ from typing import Any
3
4
 
4
5
  import pydantic
5
6
 
6
- from classiq.interface.generator.arith import argument_utils
7
+ from classiq.interface.exceptions import ClassiqValueError
8
+ from classiq.interface.generator.arith import argument_utils, number_utils
7
9
  from classiq.interface.generator.arith.argument_utils import RegisterOrConst
8
10
  from classiq.interface.generator.arith.arithmetic_operations import (
11
+ MODULO_WITH_FRACTION_PLACES_ERROR_MSG,
9
12
  ArithmeticOperationParams,
10
13
  )
11
14
  from classiq.interface.generator.arith.binary_ops import (
@@ -22,16 +25,18 @@ class Extremum(ArithmeticOperationParams):
22
25
  left_arg: RegisterOrConst
23
26
  right_arg: RegisterOrConst
24
27
 
25
- @pydantic.root_validator(pre=True)
26
- def _validate_one_is_register(cls, values: Dict[str, Any]) -> Dict[str, Any]:
27
- left_arg = values.get("left_arg")
28
- right_arg = values.get("right_arg")
29
- if isinstance(left_arg, Numeric) and isinstance(right_arg, Numeric):
30
- raise ValueError("One argument must be a register")
31
- if left_arg is right_arg and isinstance(left_arg, pydantic.BaseModel):
32
- # In case both arguments refer to the same object, copy it.
33
- # This prevents changes performed on one argument from affecting the other.
34
- values["right_arg"] = left_arg.copy(deep=True)
28
+ @pydantic.model_validator(mode="before")
29
+ @classmethod
30
+ def _validate_one_is_register(cls, values: Any) -> dict[str, Any]:
31
+ if isinstance(values, dict):
32
+ left_arg = values.get("left_arg")
33
+ right_arg = values.get("right_arg")
34
+ if isinstance(left_arg, Numeric) and isinstance(right_arg, Numeric):
35
+ raise ClassiqValueError("One argument must be a register")
36
+ if left_arg is right_arg and isinstance(left_arg, pydantic.BaseModel):
37
+ # In case both arguments refer to the same object, copy it.
38
+ # This prevents changes performed on one argument from affecting the other.
39
+ values["right_arg"] = left_arg.model_copy(deep=True)
35
40
  return values
36
41
 
37
42
  def _create_ios(self) -> None:
@@ -55,31 +60,77 @@ class Extremum(ArithmeticOperationParams):
55
60
  def _bound_calculator(cls, arg1: float, arg2: float) -> float:
56
61
  pass
57
62
 
63
+ @staticmethod
64
+ def _less_qubits_arg(
65
+ arg1: RegisterOrConst, arg2: RegisterOrConst
66
+ ) -> RegisterOrConst:
67
+ if not isinstance(arg1, RegisterArithmeticInfo):
68
+ return arg1
69
+ if not isinstance(arg2, RegisterArithmeticInfo):
70
+ return arg2
71
+ return arg1 if arg1.size <= arg2.size else arg2
72
+
73
+ @classmethod
74
+ @abc.abstractmethod
75
+ def preferred_arg(
76
+ cls, arg1: RegisterOrConst, arg2: RegisterOrConst
77
+ ) -> RegisterOrConst:
78
+ pass
79
+
58
80
  def _get_result_register(self) -> RegisterArithmeticInfo:
81
+ eff_left_arg = argument_utils.limit_fraction_places(
82
+ self.left_arg, self.machine_precision
83
+ )
84
+ eff_right_arg = argument_utils.limit_fraction_places(
85
+ self.right_arg, self.machine_precision
86
+ )
87
+ if argument_utils.arg_bounds_overlap((eff_left_arg, eff_right_arg)):
88
+ return self._get_general_case_result_register(eff_left_arg, eff_right_arg)
89
+ return argument_utils.as_arithmetic_info(
90
+ self.preferred_arg(eff_left_arg, eff_right_arg)
91
+ )
92
+
93
+ def _get_general_case_result_register(
94
+ self, eff_left_arg: RegisterOrConst, eff_right_arg: RegisterOrConst
95
+ ) -> RegisterArithmeticInfo:
59
96
  integer_part_size = max(
60
- argument_utils.integer_part_size(self.left_arg),
61
- argument_utils.integer_part_size(self.right_arg),
97
+ argument_utils.integer_part_size(eff_left_arg),
98
+ argument_utils.integer_part_size(eff_right_arg),
62
99
  )
63
100
  fraction_places = max(
64
- self._compute_fraction_places(self.left_arg),
65
- self._compute_fraction_places(self.right_arg),
101
+ argument_utils.fraction_places(eff_left_arg),
102
+ argument_utils.fraction_places(eff_right_arg),
66
103
  )
67
104
  required_size = integer_part_size + fraction_places
68
105
  bounds = (
69
106
  self._bound_calculator(
70
- argument_utils.lower_bound(self.left_arg),
71
- argument_utils.lower_bound(self.right_arg),
107
+ argument_utils.lower_bound(eff_left_arg),
108
+ argument_utils.lower_bound(eff_right_arg),
72
109
  ),
73
110
  self._bound_calculator(
74
- argument_utils.upper_bound(self.left_arg),
75
- argument_utils.upper_bound(self.right_arg),
111
+ argument_utils.upper_bound(eff_left_arg),
112
+ argument_utils.upper_bound(eff_right_arg),
76
113
  ),
77
114
  )
115
+ if self.output_size:
116
+ if fraction_places:
117
+ raise ValueError(MODULO_WITH_FRACTION_PLACES_ERROR_MSG)
118
+ max_bounds = RegisterArithmeticInfo.get_maximal_bounds(
119
+ size=self.output_size, is_signed=False, fraction_places=0
120
+ )
121
+ bounds = number_utils.bounds_cut(bounds, max_bounds)
122
+ size = self.output_size or required_size
123
+ is_signed = self._include_sign and min(bounds) < 0
78
124
  return RegisterArithmeticInfo(
79
- size=self.output_size or required_size,
125
+ size=size,
80
126
  fraction_places=fraction_places,
81
- is_signed=self._include_sign and min(bounds) < 0,
82
- bounds=self._legal_bounds(bounds),
127
+ is_signed=is_signed,
128
+ bounds=self._legal_bounds(
129
+ bounds,
130
+ RegisterArithmeticInfo.get_maximal_bounds(
131
+ size=size, is_signed=is_signed, fraction_places=fraction_places
132
+ ),
133
+ ),
83
134
  )
84
135
 
85
136
 
@@ -90,6 +141,17 @@ class Min(Extremum):
90
141
  def _bound_calculator(cls, arg1: float, arg2: float) -> float:
91
142
  return min(arg1, arg2)
92
143
 
144
+ @classmethod
145
+ def preferred_arg(
146
+ cls, arg1: RegisterOrConst, arg2: RegisterOrConst
147
+ ) -> RegisterOrConst:
148
+ min1, min2 = min(argument_utils.bounds(arg1)), min(argument_utils.bounds(arg2))
149
+ if min1 < min2:
150
+ return arg1
151
+ if min2 < min1:
152
+ return arg2
153
+ return cls._less_qubits_arg(arg1, arg2)
154
+
93
155
 
94
156
  class Max(Extremum):
95
157
  output_name = "max_value"
@@ -97,3 +159,14 @@ class Max(Extremum):
97
159
  @classmethod
98
160
  def _bound_calculator(cls, arg1: float, arg2: float) -> float:
99
161
  return max(arg1, arg2)
162
+
163
+ @classmethod
164
+ def preferred_arg(
165
+ cls, arg1: RegisterOrConst, arg2: RegisterOrConst
166
+ ) -> RegisterOrConst:
167
+ max1, max2 = max(argument_utils.bounds(arg1)), max(argument_utils.bounds(arg2))
168
+ if max1 > max2:
169
+ return arg1
170
+ if max2 > max1:
171
+ return arg2
172
+ return cls._less_qubits_arg(arg1, arg2)
@@ -1,7 +1,10 @@
1
- from typing import Iterable, List, Optional
1
+ from collections.abc import Iterable
2
+ from typing import Optional
2
3
 
3
4
  import pydantic
5
+ from pydantic import ConfigDict
4
6
 
7
+ from classiq.interface.exceptions import ClassiqValueError
5
8
  from classiq.interface.generator.arith.argument_utils import RegisterOrConst
6
9
  from classiq.interface.generator.arith.arithmetic_operations import (
7
10
  ArithmeticOperationParams,
@@ -15,26 +18,28 @@ def get_arg_name(idx: int) -> str:
15
18
 
16
19
 
17
20
  class LogicalOps(ArithmeticOperationParams):
18
- args: List[RegisterOrConst]
21
+ args: list[RegisterOrConst]
19
22
  target: Optional[RegisterArithmeticInfo]
20
- _should_invert_node_list: List[str] = pydantic.PrivateAttr(default_factory=list)
23
+ _should_invert_node_list: list[str] = pydantic.PrivateAttr(default_factory=list)
21
24
 
22
- def update_should_invert_node_list(self, invert_args: List[str]) -> None:
25
+ def update_should_invert_node_list(self, invert_args: list[str]) -> None:
23
26
  self._should_invert_node_list.extend(invert_args)
24
27
 
25
- @pydantic.validator("output_size")
28
+ @pydantic.field_validator("output_size")
29
+ @classmethod
26
30
  def _validate_output_size(cls, output_size: Optional[int]) -> int:
27
31
  if output_size is not None and output_size != 1:
28
- raise ValueError("logical operation output size must be 1")
32
+ raise ClassiqValueError("logical operation output size must be 1")
29
33
  return 1
30
34
 
31
- @pydantic.validator("args")
35
+ @pydantic.field_validator("args")
36
+ @classmethod
32
37
  def _validate_inputs_sizes(
33
- cls, arguments: List[RegisterOrConst]
34
- ) -> List[RegisterOrConst]:
38
+ cls, arguments: list[RegisterOrConst]
39
+ ) -> list[RegisterOrConst]:
35
40
  for arg_idx, arg in enumerate(arguments):
36
41
  if isinstance(arg, RegisterArithmeticInfo) and not arg.is_boolean_register:
37
- raise ValueError(
42
+ raise ClassiqValueError(
38
43
  f"All inputs to logical and must be of size 1 (at argument #{arg_idx})"
39
44
  )
40
45
  return arguments
@@ -63,8 +68,7 @@ class LogicalOps(ArithmeticOperationParams):
63
68
  def get_params_inplace_options(self) -> Iterable["LogicalOps"]:
64
69
  return ()
65
70
 
66
- class Config:
67
- arbitrary_types_allowed = True
71
+ model_config = ConfigDict(arbitrary_types_allowed=True)
68
72
 
69
73
 
70
74
  class LogicalAnd(LogicalOps):
@@ -0,0 +1,3 @@
1
+ from typing import Final
2
+
3
+ DEFAULT_MACHINE_PRECISION: Final[int] = 8
@@ -1,7 +1,6 @@
1
- from typing import Tuple, Union
1
+ from typing import Final, Union
2
2
 
3
- MAXIMAL_MACHINE_PRECISION: int = 20
4
- MAX_FRACTION_PLACES: int = 8
3
+ MAXIMAL_MACHINE_PRECISION: Final[int] = 20
5
4
 
6
5
 
7
6
  def signed_int_to_unsigned(number: int) -> int:
@@ -13,7 +12,7 @@ def signed_int_to_unsigned(number: int) -> int:
13
12
  return number + 2 ** (number.bit_length() + 1 * not_power2)
14
13
 
15
14
 
16
- def _binary_to_int(bin_rep: str, is_signed: bool) -> int:
15
+ def binary_to_int(bin_rep: str, is_signed: bool = False) -> int:
17
16
  negative_offset: int = -(2 ** len(bin_rep)) * (bin_rep[0] == "1") * is_signed
18
17
  return int(bin_rep, 2) + negative_offset
19
18
 
@@ -21,19 +20,19 @@ def _binary_to_int(bin_rep: str, is_signed: bool) -> int:
21
20
  def binary_to_float(
22
21
  bin_rep: str, fraction_part_size: int = 0, is_signed: bool = False
23
22
  ) -> float:
24
- return _binary_to_int(bin_rep, is_signed) / 2**fraction_part_size
23
+ return binary_to_int(bin_rep, is_signed) / 2**fraction_part_size
25
24
 
26
25
 
27
26
  def binary_to_float_or_int(
28
27
  bin_rep: str, fraction_part_size: int = 0, is_signed: bool = False
29
28
  ) -> Union[float, int]:
30
29
  if fraction_part_size == 0:
31
- return _binary_to_int(bin_rep, is_signed)
30
+ return binary_to_int(bin_rep, is_signed)
32
31
  return binary_to_float(bin_rep, fraction_part_size, is_signed)
33
32
 
34
33
 
35
- def _get_fraction_places(*, binary_value: str, machine_precision: int) -> int:
36
- fraction_places = machine_precision
34
+ def _get_fraction_places(*, binary_value: str) -> int:
35
+ fraction_places = MAXIMAL_MACHINE_PRECISION
37
36
  for bit in reversed(binary_value):
38
37
  if bit == "1" or fraction_places == 0:
39
38
  return fraction_places
@@ -41,82 +40,79 @@ def _get_fraction_places(*, binary_value: str, machine_precision: int) -> int:
41
40
  return fraction_places
42
41
 
43
42
 
44
- def get_int_representation_and_fraction_places(
45
- float_value: float, *, machine_precision: int
46
- ) -> Tuple[int, int]:
47
- int_val = signed_int_to_unsigned(int(float_value * 2**machine_precision))
43
+ def get_int_representation_and_fraction_places(float_value: float) -> tuple[int, int]:
44
+ int_val = signed_int_to_unsigned(int(float_value * 2**MAXIMAL_MACHINE_PRECISION))
48
45
  if int_val == 0:
49
46
  return 0, 0
50
- fraction_places = _get_fraction_places(
51
- binary_value=bin(int_val)[2:], machine_precision=machine_precision
52
- )
53
- int_val = int_val >> (machine_precision - fraction_places)
47
+ fraction_places = _get_fraction_places(binary_value=bin(int_val)[2:])
48
+ int_val = int_val >> (MAXIMAL_MACHINE_PRECISION - fraction_places)
54
49
  return int_val, fraction_places
55
50
 
56
51
 
57
- def fraction_places(float_value: float, *, machine_precision: int) -> int:
58
- int_val = signed_int_to_unsigned(int(float_value * 2**machine_precision))
52
+ def fraction_places(float_value: float) -> int:
53
+ int_val = signed_int_to_unsigned(int(float_value * 2**MAXIMAL_MACHINE_PRECISION))
59
54
  if int_val == 0:
60
55
  return 0
61
- return _get_fraction_places(
62
- binary_value=bin(int_val)[2:], machine_precision=machine_precision
63
- )
56
+ return _get_fraction_places(binary_value=bin(int_val)[2:])
64
57
 
65
58
 
66
59
  def _bit_length(integer_representation: int) -> int:
67
60
  return 1 if integer_representation == 0 else integer_representation.bit_length()
68
61
 
69
62
 
70
- def binary_string(
71
- float_value: float, *, machine_precision: int = MAXIMAL_MACHINE_PRECISION
72
- ) -> str:
73
- int_val, _ = get_int_representation_and_fraction_places(
74
- float_value=float_value, machine_precision=machine_precision
75
- )
63
+ def binary_string(float_value: float) -> str:
64
+ int_val, _ = get_int_representation_and_fraction_places(float_value)
76
65
  bin_rep = bin(int_val)[2:]
77
- size_diff = size(
78
- float_value=float_value, machine_precision=machine_precision
79
- ) - len(bin_rep)
66
+ size_diff = size(float_value=float_value) - len(bin_rep)
80
67
  extension_bit = "0" if float_value >= 0 else "1"
81
68
  return bin_rep[::-1] + extension_bit * size_diff
82
69
 
83
70
 
84
71
  def integer_part_size(float_value: float) -> int:
85
- int_val, fraction_places = get_int_representation_and_fraction_places(
86
- float_value=float_value, machine_precision=MAXIMAL_MACHINE_PRECISION
87
- )
72
+ int_val, fraction_places = get_int_representation_and_fraction_places(float_value)
88
73
  return max(_bit_length(int_val) - fraction_places, 0)
89
74
 
90
75
 
91
- def size(float_value: float, *, machine_precision: int) -> int:
92
- int_val, fraction_places = get_int_representation_and_fraction_places(
93
- float_value=float_value, machine_precision=machine_precision
94
- )
76
+ def size(float_value: float) -> int:
77
+ int_val, fraction_places = get_int_representation_and_fraction_places(float_value)
95
78
  return max(_bit_length(int_val), fraction_places)
96
79
 
97
80
 
81
+ def _is_extra_sign_bit_needed(*, lb: float, ub: float) -> bool:
82
+ integer_lb = lb * 2 ** fraction_places(lb)
83
+ max_represented_number = (
84
+ 2 ** (len(binary_string(integer_lb)) - 1) - 1
85
+ ) / 2 ** fraction_places(lb)
86
+ return ub > max_represented_number
87
+
88
+
98
89
  def bounds_to_integer_part_size(lb: float, ub: float) -> int:
99
90
  lb, ub = min(lb, ub), max(lb, ub)
100
91
  ub_integer_part_size: int = integer_part_size(float_value=ub)
101
92
  lb_integer_part_size: int = integer_part_size(float_value=lb)
102
- if lb == 0:
93
+ if lb >= 0:
103
94
  return ub_integer_part_size
104
- if ub == 0:
95
+ if ub <= 0:
105
96
  return lb_integer_part_size
106
- is_extra_bit_needed = lb < 0 < ub and ub_integer_part_size >= lb_integer_part_size
107
- return max(ub_integer_part_size + 1 * is_extra_bit_needed, lb_integer_part_size)
97
+ return max(
98
+ ub_integer_part_size + 1 * _is_extra_sign_bit_needed(lb=lb, ub=ub),
99
+ lb_integer_part_size,
100
+ )
108
101
 
109
102
 
110
- def limit_fraction_places(number: float, *, machine_precision: int) -> float:
111
- orig_bin_rep = binary_string(number, machine_precision=MAXIMAL_MACHINE_PRECISION)[
112
- ::-1
113
- ]
114
- orig_fractions = fraction_places(
115
- number, machine_precision=MAXIMAL_MACHINE_PRECISION
116
- )
103
+ def limit_fraction_places(number: float, machine_precision: int) -> float:
104
+ orig_bin_rep = binary_string(number)[::-1]
105
+ orig_fractions = fraction_places(number)
106
+
117
107
  removed_fractions = max(orig_fractions - machine_precision, 0)
118
108
  return binary_to_float(
119
109
  bin_rep=orig_bin_rep[: len(orig_bin_rep) - removed_fractions],
120
110
  fraction_part_size=orig_fractions - removed_fractions,
121
111
  is_signed=number < 0,
122
112
  )
113
+
114
+
115
+ def bounds_cut(
116
+ bounds1: tuple[float, float], bounds2: tuple[float, float]
117
+ ) -> tuple[float, float]:
118
+ return max(min(bounds1), min(bounds2)), min(max(bounds1), max(bounds2))
@@ -1,44 +1,87 @@
1
- from typing import Any, Dict, Optional
1
+ from typing import Any, Optional
2
2
 
3
3
  import pydantic
4
+ from pydantic import ConfigDict
5
+ from pydantic_core.core_schema import ValidationInfo
4
6
 
7
+ from classiq.interface.exceptions import ClassiqValueError
8
+ from classiq.interface.generator.arith import number_utils
5
9
  from classiq.interface.helpers.custom_pydantic_types import PydanticFloatTuple
6
10
  from classiq.interface.helpers.hashable_pydantic_base_model import (
7
11
  HashablePydanticBaseModel,
8
12
  )
9
13
 
10
- from classiq.exceptions import ClassiqValueError
11
-
12
14
 
13
15
  class RegisterArithmeticInfo(HashablePydanticBaseModel):
14
- size: pydantic.PositiveInt
16
+ size: pydantic.PositiveInt = pydantic.Field(default=1)
15
17
  is_signed: bool = pydantic.Field(default=False)
16
18
  fraction_places: pydantic.NonNegativeInt = pydantic.Field(default=0)
17
- bounds: PydanticFloatTuple = pydantic.Field(default=None)
19
+ bypass_bounds_validation: bool = pydantic.Field(default=False)
20
+ bounds: PydanticFloatTuple = pydantic.Field(
21
+ default=None,
22
+ validate_default=True,
23
+ )
18
24
 
19
- @pydantic.root_validator(pre=True)
20
- def _remove_name(cls, values: Dict[str, Any]) -> Dict[str, Any]:
21
- if "name" in values:
22
- values.pop("name")
25
+ @pydantic.model_validator(mode="before")
26
+ @classmethod
27
+ def _remove_name(cls, values: Any, info: ValidationInfo) -> dict[str, Any]:
28
+ if isinstance(values, dict):
29
+ values = values.copy()
30
+ elif hasattr(values, "__dict__"):
31
+ values = values.__dict__.copy()
32
+ elif values is None and info.data:
33
+ values = info.data.copy()
34
+ else:
35
+ raise ValueError("Unsupported type for removing 'name'.")
36
+
37
+ values.pop("name", None)
23
38
  return values
24
39
 
25
- @pydantic.validator("bounds", always=True)
26
- def _validate_bounds(
27
- cls, bounds: Optional[PydanticFloatTuple], values: Dict[str, Any]
28
- ) -> PydanticFloatTuple:
29
- if bounds is not None:
30
- if min(bounds) < 0:
31
- assert values.get("is_signed")
32
- return tuple(bounds) # type: ignore[return-value]
33
- size = values.get("size")
34
- if not isinstance(size, int):
35
- raise ClassiqValueError("RegisterUserInput must have an integer size")
36
- is_signed: bool = values.get("is_signed", False)
40
+ @staticmethod
41
+ def get_maximal_bounds(
42
+ *, size: int, is_signed: bool, fraction_places: int
43
+ ) -> tuple[float, float]:
37
44
  lb = 0 if not is_signed else -(2 ** (size - 1))
38
45
  ub = 2**size - 1 if not is_signed else 2 ** (size - 1) - 1
39
- fraction_factor = float(2 ** -values.get("fraction_places", 0))
46
+ fraction_factor = float(2**-fraction_places)
40
47
  return (lb * fraction_factor, ub * fraction_factor)
41
48
 
49
+ @pydantic.field_validator("bounds", mode="before")
50
+ @classmethod
51
+ def _validate_bounds(
52
+ cls, bounds: Optional[PydanticFloatTuple], info: ValidationInfo
53
+ ) -> PydanticFloatTuple:
54
+ size = info.data.get("size")
55
+ is_signed = info.data.get("is_signed", False)
56
+ fraction_places = info.data.get("fraction_places", 0)
57
+ if not isinstance(size, int):
58
+ raise ClassiqValueError("RegisterArithmeticInfo must have an integer size")
59
+
60
+ maximal_bounds = cls.get_maximal_bounds(
61
+ size=size, is_signed=is_signed, fraction_places=fraction_places
62
+ )
63
+ if bounds is None:
64
+ return maximal_bounds
65
+
66
+ trimmed_bounds = (
67
+ number_utils.limit_fraction_places(min(bounds), fraction_places),
68
+ number_utils.limit_fraction_places(max(bounds), fraction_places),
69
+ )
70
+ if not info.data.get("bypass_bounds_validation", False):
71
+ assert min(trimmed_bounds) >= min(maximal_bounds), "Illegal bound min"
72
+ assert max(trimmed_bounds) <= max(maximal_bounds), "Illegal bound max"
73
+ return trimmed_bounds
74
+
75
+ def limit_fraction_places(self, machine_precision: int) -> "RegisterArithmeticInfo":
76
+ truncated_bits: int = max(self.fraction_places - machine_precision, 0)
77
+ return RegisterArithmeticInfo(
78
+ size=self.size - truncated_bits,
79
+ is_signed=self.is_signed,
80
+ fraction_places=self.fraction_places - truncated_bits,
81
+ bounds=self.bounds,
82
+ bypass_bounds_validation=self.bypass_bounds_validation,
83
+ )
84
+
42
85
  @property
43
86
  def is_boolean_register(self) -> bool:
44
87
  return (not self.is_signed) and (self.size == 1) and (self.fraction_places == 0)
@@ -51,8 +94,7 @@ class RegisterArithmeticInfo(HashablePydanticBaseModel):
51
94
  def integer_part_size(self) -> pydantic.NonNegativeInt:
52
95
  return self.size - self.fraction_places
53
96
 
54
- class Config:
55
- frozen = True
97
+ model_config = ConfigDict(frozen=True)
56
98
 
57
99
 
58
100
  class RegisterUserInput(RegisterArithmeticInfo):
@@ -62,12 +104,13 @@ class RegisterUserInput(RegisterArithmeticInfo):
62
104
  super().__init__(**data)
63
105
  self._fields_to_skip_in_hash = frozenset({"name"})
64
106
 
65
- @pydantic.root_validator(pre=True)
66
- def _remove_name(cls, values: Dict[str, Any]) -> Dict[str, Any]:
107
+ @pydantic.model_validator(mode="before")
108
+ @classmethod
109
+ def _remove_name(cls, values: Any, info: ValidationInfo) -> dict[str, Any]:
67
110
  return values
68
111
 
69
112
  def revalued(self, **kwargs: Any) -> "RegisterUserInput":
70
- return self.copy(update=kwargs)
113
+ return self.model_copy(update=kwargs)
71
114
 
72
115
  @classmethod
73
116
  def from_arithmetic_info(