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
@@ -0,0 +1,42 @@
1
+ from sympy import Eq, Expr, GreaterThan, LessThan, Rational, Symbol, solve
2
+ from sympy.core.relational import Relational
3
+
4
+ from classiq.interface.exceptions import ClassiqCombOptNoSolutionError
5
+
6
+
7
+ def isolate(expression: Expr, var: Symbol) -> Expr:
8
+ isolated_exp = solve(expression, var)
9
+ # This converts Rationals to Floats which is needed since we don't support division in arithmetic
10
+ if isinstance(isolated_exp, Relational) and _has_rational_atom(isolated_exp):
11
+ isolated_exp = isolated_exp.evalf()
12
+
13
+ if isinstance(expression, Eq):
14
+ if len(isolated_exp) == 1:
15
+ isolated_exp = type(expression)(var, isolated_exp[0])
16
+ elif len(isolated_exp) > 1:
17
+ # sympy didn't manage to isolate an expression
18
+ isolated_exp = expression
19
+ else:
20
+ raise ClassiqCombOptNoSolutionError
21
+
22
+ else:
23
+ if _is_symbol_in_right_hand_side(isolated_exp):
24
+ isolated_exp = _reverse_ineq_exp(isolated_exp)
25
+
26
+ return isolated_exp
27
+
28
+
29
+ def _has_rational_atom(expression: Relational) -> bool:
30
+ return any(type(atom) is Rational for atom in expression.atoms())
31
+
32
+
33
+ def _is_symbol_in_right_hand_side(expression: Expr) -> bool:
34
+ return isinstance(expression.args[1], Symbol) and not isinstance(
35
+ expression.args[0], Symbol
36
+ )
37
+
38
+
39
+ def _reverse_ineq_exp(expression: Expr) -> Expr:
40
+ original_relation = type(expression)
41
+ reverse_relation = LessThan if original_relation is GreaterThan else GreaterThan
42
+ return reverse_relation(expression.args[1], expression.args[0])
@@ -0,0 +1,166 @@
1
+ import itertools
2
+ from functools import partial
3
+ from typing import Callable, Union
4
+
5
+ import numpy as np
6
+ import pyomo.environ as pyo
7
+
8
+ from classiq.interface.combinatorial_optimization.sense import is_maximization
9
+ from classiq.interface.combinatorial_optimization.solver_types import QSolver
10
+ from classiq.interface.exceptions import ClassiqValueError
11
+ from classiq.interface.executor.vqe_result import VQESolverResult
12
+ from classiq.interface.generator.functions.qmod_python_interface import QmodPyStruct
13
+
14
+ from classiq.applications.combinatorial_helpers.optimization_model import (
15
+ OptimizationModel,
16
+ )
17
+ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_sparsing import (
18
+ SparsePauliOp,
19
+ )
20
+ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import (
21
+ pauli_operator_to_hamiltonian,
22
+ )
23
+ from classiq.applications.combinatorial_helpers.pyomo_utils import (
24
+ add_var_domain_constraints,
25
+ convert_pyomo_to_global_presentation,
26
+ evaluate_objective,
27
+ pyomo_to_qmod_qstruct,
28
+ )
29
+ from classiq.qmod.builtins.structs import PauliTerm
30
+ from classiq.qmod.qmod_variable import QStruct
31
+
32
+
33
+ def compute_qaoa_initial_point(
34
+ hamiltonian: list[PauliTerm],
35
+ repetitions: int,
36
+ ) -> list[float]:
37
+ coeffs_ising = [pauli_term.coefficient for pauli_term in hamiltonian[1:]]
38
+ # the first coeff is the II...I term
39
+ coeffs_abs = np.abs(coeffs_ising) # type: ignore[arg-type]
40
+ coeffs_largest = np.sort(coeffs_abs)[len(coeffs_ising) // 2 :]
41
+ operator_norm = np.mean(coeffs_largest)
42
+ time_step = 1 / (2 * operator_norm) # adapted such that for MAXCUT time_step = 1
43
+
44
+ beta_params: np.ndarray = np.linspace(1, 0, repetitions) * time_step
45
+ gamma_params: np.ndarray = np.linspace(0, 1, repetitions) * time_step
46
+ return list(itertools.chain(*zip(gamma_params, beta_params)))
47
+
48
+
49
+ def pyo_model_to_hamiltonian(
50
+ pyo_model: pyo.ConcreteModel, penalty_energy: float
51
+ ) -> list[PauliTerm]:
52
+ pauli_list = OptimizationModel(
53
+ pyo_model, penalty_energy=penalty_energy, qsolver=QSolver.QAOAPenalty
54
+ ).ising.pauli_list
55
+ return pauli_operator_to_hamiltonian(pauli_list)
56
+
57
+
58
+ def pyo_model_to_qmod_problem(
59
+ pyo_model: pyo.ConcreteModel, penalty_energy: float
60
+ ) -> tuple[type[QStruct], Callable]:
61
+ with add_var_domain_constraints(pyo_model):
62
+ optimization_model = OptimizationModel(
63
+ pyo_model, penalty_energy=penalty_energy, qsolver=QSolver.QAOAPenalty
64
+ )
65
+ _validate_var_domains(optimization_model)
66
+ qmod_struct = pyomo_to_qmod_qstruct(
67
+ "QAOAVars", optimization_model.vars_not_encoded
68
+ )
69
+ cost_func = partial(
70
+ evaluate_objective, *optimization_model.objective_not_encoded_sympy
71
+ )
72
+ return qmod_struct, cost_func
73
+
74
+
75
+ def _validate_var_domains(model: OptimizationModel) -> None:
76
+ for var in model.vars_not_encoded:
77
+ if (
78
+ isinstance(var.bounds, tuple)
79
+ and len(var.bounds) == 2
80
+ and var.bounds[0] != 0
81
+ ):
82
+ raise ClassiqValueError(
83
+ f"Bounds of variable {var.local_name} must start at 0, got {var.bounds}"
84
+ )
85
+
86
+
87
+ def _str_to_list_int(str_ints: str) -> list[int]:
88
+ return list(map(int, list(str_ints)))
89
+
90
+
91
+ def _decode_vector_str(
92
+ optimization_model: OptimizationModel, vector_str: str
93
+ ) -> list[int]:
94
+ return optimization_model.decode(
95
+ _str_to_list_int(vector_str[::-1])
96
+ ) # reverse qubit order
97
+
98
+
99
+ def _evaluate_operator(operator: SparsePauliOp, state: Union[list[int], str]) -> float:
100
+ if isinstance(state, list):
101
+ state = "".join([str(x) for x in state])
102
+
103
+ cost = 0.0
104
+ for pauli, coeff in zip(operator.paulis, operator.coeffs):
105
+ expectation = 1
106
+ for qubit, pauli_char in enumerate(pauli):
107
+ if pauli_char != "I" and state[qubit] == "1" and pauli_char in ["Z", "Y"]:
108
+ expectation *= -1
109
+ cost += expectation * coeff.real
110
+
111
+ return cost
112
+
113
+
114
+ def _eigenstate_to_solution(
115
+ optimization_model: OptimizationModel,
116
+ eigenvector: str,
117
+ probability: float,
118
+ num_shots: int,
119
+ ) -> QmodPyStruct:
120
+ pauli = optimization_model.get_operator().pauli_list
121
+
122
+ paulis = [item[0] for item in pauli]
123
+ coeffs = [item[1] for item in pauli]
124
+
125
+ operator = SparsePauliOp(paulis, coeffs)
126
+ cost = _evaluate_operator(operator, eigenvector)
127
+
128
+ if is_maximization(optimization_model._model_original):
129
+ cost *= -1
130
+
131
+ return {
132
+ "probability": probability,
133
+ "cost": cost,
134
+ "solution": _decode_vector_str(optimization_model, eigenvector),
135
+ "count": round(probability * num_shots),
136
+ }
137
+
138
+
139
+ def _get_combi_solution_histogram(
140
+ optimization_model: OptimizationModel,
141
+ vqe_result: VQESolverResult,
142
+ ) -> list[QmodPyStruct]:
143
+ if vqe_result.reduced_probabilities is None:
144
+ raise ValueError(
145
+ "reduced_probabilities is optional only for backwards compatibility, but it should always be present here"
146
+ )
147
+ return [
148
+ _eigenstate_to_solution(
149
+ optimization_model, eigenvector, probability, vqe_result.num_shots
150
+ )
151
+ for eigenvector, probability in vqe_result.reduced_probabilities.items()
152
+ ]
153
+
154
+
155
+ def get_optimization_solution_from_pyo(
156
+ pyo_model: pyo.ConcreteModel,
157
+ vqe_result: VQESolverResult,
158
+ penalty_energy: float,
159
+ ) -> list[QmodPyStruct]:
160
+ converted_pyo_model = convert_pyomo_to_global_presentation(pyo_model)
161
+ optimization_model = OptimizationModel(
162
+ converted_pyo_model, penalty_energy=penalty_energy, qsolver=QSolver.QAOAPenalty
163
+ )
164
+ histogram = _get_combi_solution_histogram(optimization_model, vqe_result)
165
+ histogram.sort(key=lambda x: x["probability"], reverse=True)
166
+ return histogram
@@ -0,0 +1,107 @@
1
+ import itertools
2
+ from dataclasses import dataclass, field
3
+ from typing import Optional, Union
4
+
5
+ import pyomo.environ as pyo
6
+ from pyomo.core.base import _GeneralVarData
7
+ from pyomo.core.expr.visitor import clone_expression, identify_variables
8
+
9
+ from classiq.interface.combinatorial_optimization.encoding_types import EncodingType
10
+ from classiq.interface.exceptions import ClassiqCombOptError
11
+
12
+ from classiq.applications.combinatorial_helpers import pyomo_utils
13
+
14
+
15
+ @dataclass
16
+ class VarExpressionMapping:
17
+ var: _GeneralVarData
18
+ expr: pyo.Expression
19
+ encodings_vars: list[_GeneralVarData] = field(default_factory=list)
20
+
21
+
22
+ class EncodingMapping:
23
+ def __init__(self, encoding_type: EncodingType) -> None:
24
+ self._data: list[VarExpressionMapping] = []
25
+ self.encoding_type = encoding_type
26
+
27
+ @property
28
+ def original_vars(self) -> list[_GeneralVarData]:
29
+ return [pair.var for pair in self._data]
30
+
31
+ @property
32
+ def encodings_vars(self) -> list[_GeneralVarData]:
33
+ return list(
34
+ itertools.chain.from_iterable(
35
+ var_mapping.encodings_vars for var_mapping in self._data
36
+ )
37
+ )
38
+
39
+ @property
40
+ def substitution_dict(self) -> dict[int, pyo.Expression]:
41
+ return {id(mapping.var): mapping.expr for mapping in self._data}
42
+
43
+ def __len__(self) -> int:
44
+ return len(self._data)
45
+
46
+ def add(
47
+ self,
48
+ original_var: _GeneralVarData,
49
+ encoding_expr: pyo.Expression,
50
+ encodings_vars: Union[list[_GeneralVarData], None] = None,
51
+ ) -> None:
52
+ if encodings_vars is None:
53
+ encodings_vars = list(identify_variables(encoding_expr))
54
+
55
+ self._check_unique_encoding_vars(encodings_vars)
56
+ self._data.append(
57
+ VarExpressionMapping(
58
+ var=original_var, expr=encoding_expr, encodings_vars=encodings_vars
59
+ )
60
+ )
61
+
62
+ def _check_unique_encoding_vars(self, variables: list[_GeneralVarData]) -> None:
63
+ assert all(
64
+ not pyomo_utils.contains(var, self.encodings_vars) for var in variables
65
+ )
66
+
67
+ def get_var_expr_mapping(
68
+ self, original_var: _GeneralVarData
69
+ ) -> VarExpressionMapping:
70
+ for var_expr_mapping in self._data:
71
+ if var_expr_mapping.var is original_var:
72
+ return var_expr_mapping
73
+ raise ClassiqCombOptError("No variable expression mapping found.")
74
+
75
+ def get_encoding_vars(self, original_var: _GeneralVarData) -> list[_GeneralVarData]:
76
+ return self.get_var_expr_mapping(original_var).encodings_vars
77
+
78
+ def get_original_var(
79
+ self, encoding_var: _GeneralVarData
80
+ ) -> Optional[_GeneralVarData]:
81
+ for original_var in self.original_vars:
82
+ if pyomo_utils.contains(encoding_var, self.get_encoding_vars(original_var)):
83
+ return original_var
84
+ return None
85
+
86
+ def decode(self, solution: list[int]) -> list[int]:
87
+ idx = 0
88
+ decoded_solution = []
89
+ for var_mapping in self._data:
90
+ num_encoding_vars = len(var_mapping.encodings_vars)
91
+ encoding_vars_solution = solution[idx : idx + num_encoding_vars]
92
+ idx += num_encoding_vars
93
+
94
+ substitution_map = {
95
+ id(var): num
96
+ for var, num in zip(var_mapping.encodings_vars, encoding_vars_solution)
97
+ }
98
+ substituted_expr = clone_expression(
99
+ var_mapping.expr, substitute=substitution_map
100
+ )
101
+
102
+ if callable(substituted_expr):
103
+ substituted_expr = substituted_expr()
104
+
105
+ decoded_solution.append(substituted_expr)
106
+
107
+ return decoded_solution
@@ -0,0 +1,124 @@
1
+ import math
2
+ from itertools import filterfalse
3
+ from typing import Any, Union, cast
4
+
5
+ import numpy as np
6
+ import pyomo.environ as pyo
7
+ from pyomo.core.base import _GeneralVarData
8
+ from pyomo.core.base.component import ComponentData, _ComponentBase
9
+ from pyomo.core.base.constraint import _GeneralConstraintData
10
+ from pyomo.core.expr.numeric_expr import (
11
+ MonomialTermExpression,
12
+ ProductExpression,
13
+ clone_expression,
14
+ )
15
+ from sympy import Expr
16
+
17
+ from classiq.interface.exceptions import ClassiqCombOptNoSolutionError
18
+
19
+ from classiq.applications.combinatorial_helpers import pyomo_utils
20
+
21
+ _INTEGER_TYPES = [pyo.NonNegativeIntegers, pyo.Integers, pyo.PositiveIntegers]
22
+
23
+
24
+ def is_model_encodable(model: pyo.ConcreteModel) -> bool:
25
+ variables = pyomo_utils.extract(model, pyo.Var)
26
+ return not all(is_var_binary(var) for var in variables)
27
+
28
+
29
+ def is_var_binary(var: _GeneralVarData) -> bool:
30
+ return var.domain == pyo.Binary or (
31
+ var.domain in _INTEGER_TYPES and var.lb == 0 and var.ub == 1
32
+ )
33
+
34
+
35
+ def is_var_span_power_of_2(var: _GeneralVarData) -> bool:
36
+ var_span = get_var_span(var)
37
+ return math.log2(var_span + 1).is_integer()
38
+
39
+
40
+ ENCODED_SUFFIX = "_encoded"
41
+ ONE_HOT_SUFFIX = "_one_hot"
42
+ CONSTRAINT_SUFFIX = "_constraint"
43
+
44
+
45
+ def is_obj_encoded(var: _ComponentBase) -> bool:
46
+ return ENCODED_SUFFIX in var.name
47
+
48
+
49
+ def get_var_span(var: _GeneralVarData) -> int:
50
+ return var.ub - var.lb
51
+
52
+
53
+ def encoded_obj_name(name: str) -> str:
54
+ return name + ENCODED_SUFFIX
55
+
56
+
57
+ def get_encoded_var_index(var: _GeneralVarData) -> int:
58
+ indexed_var = var.parent_component()
59
+ index = [
60
+ index_temp for index_temp, var_temp in indexed_var.items() if var_temp is var
61
+ ][0]
62
+ return index[1]
63
+
64
+
65
+ def recursively_remove_monomial_expr(obj: Any) -> None:
66
+ # Due to pyomo bug. see: https://github.com/Pyomo/pyomo/issues/2174
67
+ for arg in getattr(obj, "args", []):
68
+ if isinstance(arg, MonomialTermExpression):
69
+ arg.__class__ = ProductExpression
70
+ recursively_remove_monomial_expr(arg)
71
+
72
+
73
+ def encode_expr(
74
+ expr: pyo.Expression, substitution_dict: dict[int, pyo.Expression]
75
+ ) -> pyo.Expression:
76
+ encoded_expr = clone_expression(expr=expr, substitute=substitution_dict)
77
+ recursively_remove_monomial_expr(encoded_expr)
78
+ return encoded_expr
79
+
80
+
81
+ def encode_constraints(
82
+ model: pyo.ConcreteModel, substitution_dict: dict[int, pyo.Expression]
83
+ ) -> None:
84
+ all_constraints = pyomo_utils.extract(model, _GeneralConstraintData)
85
+ constraints = filterfalse(is_obj_encoded, all_constraints)
86
+
87
+ for constraint in constraints:
88
+ constraint_expression = encode_expr(constraint.expr, substitution_dict)
89
+ if not isinstance(constraint_expression, bool) and not isinstance(
90
+ constraint_expression, np.bool_
91
+ ):
92
+ constraint.set_value(expr=constraint_expression)
93
+ continue
94
+
95
+ deal_with_trivial_boolean_constraint(constraint, constraint_expression, model)
96
+
97
+
98
+ def deal_with_trivial_boolean_constraint(
99
+ constraint: _ComponentBase,
100
+ constraint_expression: Union[bool, Expr],
101
+ model: pyo.ConcreteModel,
102
+ ) -> None:
103
+ # using '==' on purpose since comparing against sympy's True
104
+ if constraint_expression == True: # noqa: E712
105
+ pyomo_utils.delete_component(model, cast(ComponentData, constraint))
106
+ if constraint_expression == False: # noqa: E712
107
+ raise ClassiqCombOptNoSolutionError
108
+
109
+
110
+ def encode_objective(
111
+ model: pyo.ConcreteModel, substitution_dict: dict[int, pyo.Expression]
112
+ ) -> None:
113
+ objective = next(model.component_objects(pyo.Objective))
114
+
115
+ encoded_objective = pyo.Objective(
116
+ expr=encode_expr(objective.expr, substitution_dict),
117
+ sense=objective.sense,
118
+ )
119
+ model.del_component(objective.name)
120
+ setattr(
121
+ model,
122
+ objective.name,
123
+ encoded_objective,
124
+ )
@@ -0,0 +1,75 @@
1
+ from __future__ import annotations
2
+
3
+ from pyomo.core.base import _GeneralVarData
4
+
5
+ from classiq.interface.generator.function_params import IOName
6
+
7
+ from classiq.applications.combinatorial_helpers import encoding_utils
8
+ from classiq.applications.combinatorial_helpers.encoding_mapping import EncodingMapping
9
+
10
+ AUXILIARY_NAME = "auxiliary"
11
+
12
+
13
+ class InternalQuantumReg:
14
+ def __init__(self, size: int, name: str) -> None:
15
+ self.name = name
16
+ self.size = size
17
+
18
+
19
+ class MemoryMapping:
20
+ def __init__(
21
+ self,
22
+ variables: list[_GeneralVarData],
23
+ vars_encoding_mapping: EncodingMapping | None = None,
24
+ ) -> None:
25
+ self.substitution_dict: dict[int, InternalQuantumReg] = dict()
26
+ self.qubit_allocation: dict[IOName, tuple[int, int]] = dict()
27
+ self.vars_encoding_mapping: EncodingMapping | None = vars_encoding_mapping
28
+ self.vars: list[_GeneralVarData] = variables
29
+ self._allocate_memory()
30
+
31
+ def __len__(self) -> int:
32
+ return len(self.substitution_dict)
33
+
34
+ def _allocate_memory(self) -> None:
35
+ for var_data in self.vars:
36
+ if (
37
+ not self.vars_encoding_mapping
38
+ or encoding_utils.get_var_span(var_data) == 1
39
+ ):
40
+ num_qubits_var = 1
41
+ else:
42
+ num_qubits_var = len(
43
+ self.vars_encoding_mapping.get_encoding_vars(var_data)
44
+ )
45
+
46
+ self.substitution_dict[id(var_data)] = InternalQuantumReg(
47
+ num_qubits_var, "q"
48
+ )
49
+ var_name = get_var_name(var_data)
50
+ self.qubit_allocation[var_name] = (
51
+ self._variable_qubits_allocated,
52
+ num_qubits_var,
53
+ )
54
+
55
+ @property
56
+ def qregs(self) -> list[InternalQuantumReg]:
57
+ return list(self.substitution_dict.values())
58
+
59
+ @property
60
+ def _variable_qubits_allocated(self) -> int:
61
+ return sum(
62
+ num_qubits
63
+ for name, (_, num_qubits) in self.qubit_allocation.items()
64
+ if name != AUXILIARY_NAME
65
+ )
66
+
67
+
68
+ def get_var_name(var: _GeneralVarData) -> str:
69
+ return (
70
+ var.name.replace("[", "")
71
+ .replace("]", "")
72
+ .replace(",", "")
73
+ .replace("'", "")
74
+ .replace('"', "")
75
+ )