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,143 @@
1
+ import copy
2
+ from typing import Union
3
+
4
+ from pyomo.core import ConcreteModel, Var
5
+ from pyomo.core.base.constraint import _GeneralConstraintData
6
+ from pyomo.core.expr.relational_expr import EqualityExpression
7
+ from pyomo.core.expr.visitor import identify_variables
8
+ from pyomo.repn.standard_repn import _GeneralVarData
9
+
10
+ from classiq.interface.exceptions import (
11
+ ClassiqCombOptNoSolutionError,
12
+ ClassiqCombOptTrivialProblemError,
13
+ )
14
+
15
+ from classiq.applications.combinatorial_helpers import (
16
+ encoding_utils,
17
+ pyomo_utils,
18
+ sympy_utils,
19
+ )
20
+ from classiq.applications.combinatorial_helpers.arithmetic.isolation import isolate
21
+ from classiq.applications.combinatorial_helpers.encoding_utils import (
22
+ deal_with_trivial_boolean_constraint,
23
+ )
24
+ from classiq.applications.combinatorial_helpers.sympy_utils import (
25
+ sympyify_expression,
26
+ sympyify_vars,
27
+ )
28
+
29
+
30
+ def remove_fixed_variables(model: ConcreteModel) -> ConcreteModel:
31
+ _should_iterate_fixing = _should_start_fixing(model)
32
+
33
+ while _should_iterate_fixing:
34
+ _change_fixing_constraints_to_fixed_value(model)
35
+ variables = pyomo_utils.extract(model, Var)
36
+
37
+ substitution_dict = {id(var): _get_value_if_exists(var) for var in variables}
38
+
39
+ encoding_utils.encode_constraints(model, substitution_dict)
40
+ encoding_utils.encode_objective(model, substitution_dict)
41
+ _remove_empty_constraints(model)
42
+
43
+ _should_iterate_fixing = _should_continue_fixing(model)
44
+
45
+ assigned_model = copy.deepcopy(model)
46
+ _check_empty_model(assigned_model)
47
+ _remove_assigned_variables(model)
48
+
49
+ return assigned_model
50
+
51
+
52
+ def _should_continue_fixing(model: ConcreteModel) -> bool:
53
+ return bool(len(_get_fixing_constraints(model)))
54
+
55
+
56
+ def _should_start_fixing(model: ConcreteModel) -> bool:
57
+ variables = pyomo_utils.extract(model, Var)
58
+ is_some_var_fixed = any(var.value is not None for var in variables)
59
+
60
+ return is_some_var_fixed or _should_continue_fixing(model)
61
+
62
+
63
+ def _change_fixing_constraints_to_fixed_value(model: ConcreteModel) -> None:
64
+ for constraint in _get_fixing_constraints(model):
65
+ var, var_value = _get_var_and_value_from_fixing_constraint(constraint)
66
+
67
+ if var.value is not None and var.value != var_value:
68
+ raise ClassiqCombOptNoSolutionError
69
+
70
+ if int(var_value) != var_value or var_value < var.lb or var_value > var.ub:
71
+ raise ClassiqCombOptNoSolutionError
72
+
73
+ var.fix(int(var_value))
74
+ pyomo_utils.delete_component(model, constraint)
75
+
76
+
77
+ def _get_fixing_constraints(model: ConcreteModel) -> list[_GeneralConstraintData]:
78
+ constraints = pyomo_utils.extract(model, _GeneralConstraintData)
79
+ return list(filter(_is_fixing_constraint, constraints))
80
+
81
+
82
+ def _get_var_and_value_from_fixing_constraint(
83
+ constraint: _GeneralConstraintData,
84
+ ) -> tuple[_GeneralVarData, float]:
85
+ var = next(identify_variables(constraint.body))
86
+
87
+ if isinstance(constraint.body, _GeneralVarData):
88
+ return var, constraint.upper.value
89
+
90
+ symbols_map = sympyify_vars([var])
91
+ sympy_exp = sympyify_expression(constraint.expr, symbols_map)
92
+ sympy_var = symbols_map.getSympySymbol(var)
93
+
94
+ isolated_exp = isolate(sympy_exp, sympy_var)
95
+
96
+ return var, float(isolated_exp.args[1])
97
+
98
+
99
+ def _remove_assigned_variables(model: ConcreteModel) -> None:
100
+ for var in pyomo_utils.extract(model, Var):
101
+ if var.value is not None:
102
+ pyomo_utils.delete_component(model, var)
103
+
104
+
105
+ def _remove_empty_constraints(model: ConcreteModel) -> None:
106
+ # (reduces number of slack variables and potential errors)
107
+ for constraint in pyomo_utils.extract(model, _GeneralConstraintData):
108
+ sympyified_expression = sympy_utils.sympyify_expression(constraint.expr)
109
+ deal_with_trivial_boolean_constraint(constraint, sympyified_expression, model)
110
+
111
+
112
+ def add_fixed_variables_to_solution(
113
+ original_model: ConcreteModel, solution: list[int]
114
+ ) -> list[int]:
115
+ variables = pyomo_utils.extract(original_model, Var)
116
+ solution_iter = iter(solution)
117
+ # var.value might be 0 as well
118
+ solution_with_fixed = []
119
+ for var in variables:
120
+ if var.value is not None:
121
+ solution_with_fixed.append(var.value)
122
+ else:
123
+ solution_with_fixed.append(next(solution_iter, 0))
124
+ solution_with_fixed.extend(list(solution_iter))
125
+ return solution_with_fixed
126
+
127
+
128
+ def _get_value_if_exists(var: _GeneralVarData) -> Union[int, _GeneralVarData]:
129
+ return var.value if var.value is not None else var
130
+
131
+
132
+ def _is_fixing_constraint(constraint: _GeneralConstraintData) -> bool:
133
+ return (
134
+ isinstance(constraint.expr, EqualityExpression)
135
+ and len(list(identify_variables(constraint.body))) == 1
136
+ )
137
+
138
+
139
+ def _check_empty_model(model: ConcreteModel) -> None:
140
+ variables = pyomo_utils.extract(model, Var)
141
+ if all(var.value is not None for var in variables):
142
+ solution = add_fixed_variables_to_solution(original_model=model, solution=[])
143
+ raise ClassiqCombOptTrivialProblemError(solution)
@@ -0,0 +1,120 @@
1
+ import pyomo
2
+ import sympy as sp
3
+ from pyomo.core.base import _GeneralVarData
4
+
5
+ from classiq.interface.chemistry.operator import PauliOperator
6
+ from classiq.interface.exceptions import ClassiqCombOptNotSupportedProblemError
7
+ from classiq.interface.helpers import custom_pydantic_types
8
+
9
+ from classiq.applications.combinatorial_helpers import memory
10
+ from classiq.applications.combinatorial_helpers.memory import InternalQuantumReg
11
+ from classiq.applications.combinatorial_helpers.sympy_utils import (
12
+ sympyify_expression,
13
+ sympyify_vars,
14
+ )
15
+
16
+ PYOMO_PARSING_ERROR_MESAGE = "Parsing of this pyomo model is not supported."
17
+
18
+
19
+ def convert_pyomo_to_hamiltonian(
20
+ pyomo_expr: pyomo.core.Expression,
21
+ ordered_pyomo_vars: list[_GeneralVarData],
22
+ qregs: list[InternalQuantumReg],
23
+ ) -> PauliOperator:
24
+ symbols_map = sympyify_vars(ordered_pyomo_vars)
25
+ sympy_expr = sympyify_expression(pyomo_expr, symbols_map)
26
+ if not sympy_expr.is_polynomial():
27
+ raise ClassiqCombOptNotSupportedProblemError(PYOMO_PARSING_ERROR_MESAGE)
28
+
29
+ ordered_sympy_vars = [
30
+ symbols_map.pyomo2sympy[pyomo_var] for pyomo_var in ordered_pyomo_vars
31
+ ]
32
+ ising_expr = _to_ising_symbolic_objective_function(sympy_expr)
33
+ ising_expr = _refine_ising_expr(ising_expr)
34
+
35
+ operator = _convert_ising_sympy_to_operator(ising_expr, ordered_sympy_vars)
36
+ operator = _add_auxiliary_qubits_to_operator(operator, qregs)
37
+
38
+ return PauliOperator(pauli_list=operator)
39
+
40
+
41
+ def _convert_ising_sympy_to_operator(
42
+ ising_expr: sp.Expr, ordered_sympy_vars: list[sp.Symbol]
43
+ ) -> custom_pydantic_types.PydanticPauliList:
44
+ pauli_op_list: custom_pydantic_types.PydanticPauliList = []
45
+ for expr_term in ising_expr.args:
46
+ expr_vars = _get_vars(expr_term)
47
+ z_vec = _find_sub_list_items(ordered_sympy_vars, expr_vars)
48
+ pauli_string_list = ["I"] * len(z_vec)
49
+ for index, is_z_op in enumerate(z_vec):
50
+ if is_z_op:
51
+ pauli_string_list[len(z_vec) - index - 1] = (
52
+ "Z" # reminder: Pauli reverses the order!
53
+ )
54
+ pauli_string = "".join(pauli_string_list)
55
+ coeff = _get_coeff_from_expr(expr_term)
56
+ pauli_op_list.append((pauli_string, complex(coeff)))
57
+ return pauli_op_list
58
+
59
+
60
+ def _refine_ising_expr(ising_expr: sp.Expr) -> sp.Expr:
61
+ # The variables here are assumed to be either 1 or -1 (ising variables).
62
+ # Therefore x^a can replaced with 1 if a is even, and with x is a is odd.
63
+ # Change the expression recursively.
64
+ def update_expr(expr: sp.Expr) -> sp.Expr:
65
+ if isinstance(expr, sp.Pow):
66
+ if expr.args[1] % 2: # odd power: x**a -> x
67
+ expr = expr.args[0]
68
+ else: # even power: x**a -> 1
69
+ expr = sp.Float(1)
70
+ if hasattr(expr, "args") and expr.args:
71
+ new_args = [update_expr(arg) for arg in expr.args]
72
+ expr_class = type(expr)
73
+ return expr_class(*new_args)
74
+ else:
75
+ return expr
76
+
77
+ return update_expr(ising_expr)
78
+
79
+
80
+ def _to_ising_symbolic_objective_function(objective: sp.Expr) -> sp.Expr:
81
+ # cost-function to Hamiltonian conversion explanation:
82
+ # https://qiskit.org/textbook/ch-applications/qaoa.html#1.1-Diagonal-Hamiltonians
83
+ subs_vars_dict = {var: (1 - var) / 2 for var in objective.free_symbols}
84
+ objective_ising = objective.subs(subs_vars_dict)
85
+ return sp.expand(objective_ising)
86
+
87
+
88
+ def _get_vars(expr_term: sp.AtomicExpr) -> list[sp.Symbol]:
89
+ if isinstance(expr_term, sp.Symbol):
90
+ return [expr_term]
91
+ else:
92
+ return expr_term.args
93
+
94
+
95
+ def _find_sub_list_items(
96
+ long_list: list[sp.Symbol], sub_list: list[sp.Symbol]
97
+ ) -> list[bool]:
98
+ return [x in sub_list for x in long_list]
99
+
100
+
101
+ def _get_coeff_from_expr(expr: sp.Expr) -> float:
102
+ if isinstance(expr, sp.Number):
103
+ return float(expr)
104
+ if isinstance(expr, sp.Symbol):
105
+ return 1
106
+ if all(isinstance(arg, sp.Symbol) for arg in expr.args):
107
+ return 1
108
+ return float(expr.args[0])
109
+
110
+
111
+ def _add_auxiliary_qubits_to_operator(
112
+ operator: custom_pydantic_types.PydanticPauliList, qregs: list[InternalQuantumReg]
113
+ ) -> custom_pydantic_types.PydanticPauliList:
114
+ # TODO: handle the case when the auxiliary are in the middle of the circuit
115
+ for qreg in qregs:
116
+ if qreg.name == memory.AUXILIARY_NAME:
117
+ operator = [
118
+ ("I" * qreg.size + monomial[0], monomial[1]) for monomial in operator
119
+ ]
120
+ return operator
@@ -0,0 +1,31 @@
1
+ import itertools
2
+
3
+ from pyomo.core.base.constraint import _GeneralConstraintData
4
+ from pyomo.core.expr.relational_expr import EqualityExpression
5
+ from pyomo.environ import Expression
6
+
7
+
8
+ def get_penalty_expression(
9
+ flat_constraints: list[_GeneralConstraintData],
10
+ ) -> Expression:
11
+ return sum(
12
+ _convert_constraint_to_penalty_term(constraint)
13
+ for constraint in flat_constraints
14
+ )
15
+
16
+
17
+ def _convert_constraint_to_penalty_term(
18
+ constraint: _GeneralConstraintData,
19
+ ) -> Expression:
20
+ if isinstance(constraint.expr, EqualityExpression):
21
+ return (constraint.expr.args[0] - constraint.expr.args[1]) ** 2
22
+
23
+ # we can assume that isinstance(constraint.expr, InequalityExpression) and constraint.expr.args[1] == 1
24
+ # due to _is_constraint_penalty_supported method
25
+ else:
26
+ index = 0
27
+ if isinstance(constraint.expr.args[0], int):
28
+ index = 1
29
+ constraint_variables = constraint.expr.args[index].args
30
+ var_pairs = list(itertools.combinations(constraint_variables, 2))
31
+ return sum(var1 * var2 for var1, var2 in var_pairs)
@@ -0,0 +1,37 @@
1
+ from pyomo.core import ConcreteModel
2
+ from pyomo.core.base.constraint import _GeneralConstraintData
3
+ from pyomo.core.expr.relational_expr import EqualityExpression
4
+ from pyomo.repn.standard_repn import _GeneralVarData
5
+
6
+ from classiq.applications.combinatorial_helpers import (
7
+ allowed_constraints,
8
+ encoding_utils,
9
+ )
10
+ from classiq.applications.combinatorial_helpers.pyomo_utils import extract
11
+ from classiq.applications.combinatorial_helpers.sympy_utils import sympyify_expression
12
+
13
+
14
+ def is_model_penalty_supported(model: ConcreteModel) -> bool:
15
+ variables = extract(model, _GeneralVarData)
16
+ is_vars_supported = all(is_var_penalty_supported(var) for var in variables)
17
+
18
+ constraints = extract(model, _GeneralConstraintData)
19
+ is_constraints_supported = all(
20
+ is_constraint_penalty_supported(constraint) for constraint in constraints
21
+ )
22
+ return is_vars_supported and is_constraints_supported
23
+
24
+
25
+ def is_var_penalty_supported(var: _GeneralVarData) -> bool:
26
+ return encoding_utils.is_var_binary(var) or encoding_utils.is_var_span_power_of_2(
27
+ var
28
+ )
29
+
30
+
31
+ def is_constraint_penalty_supported(constraint: _GeneralConstraintData) -> bool:
32
+ if isinstance(constraint.expr, EqualityExpression):
33
+ return True
34
+
35
+ sympy_expr = sympyify_expression(constraint.expr)
36
+
37
+ return allowed_constraints.is_constraint_sum_less_than_one(sympy_expr)
@@ -0,0 +1,74 @@
1
+ from itertools import filterfalse
2
+
3
+ from sympy import (
4
+ Add,
5
+ Expr,
6
+ GreaterThan,
7
+ LessThan,
8
+ Mul,
9
+ Number,
10
+ Symbol,
11
+ expand,
12
+ simplify,
13
+ )
14
+
15
+ from classiq.interface.exceptions import ClassiqCombOptError
16
+
17
+
18
+ def sign_separation(expr: Expr) -> LessThan:
19
+ expr = simplify(expr)
20
+ expr = expand(expr)
21
+
22
+ if not isinstance(expr, (LessThan, GreaterThan)):
23
+ raise ClassiqCombOptError("sign separation didn't worked out")
24
+
25
+ if isinstance(expr, GreaterThan):
26
+ expr = LessThan(expr.args[1], expr.args[0])
27
+
28
+ expr_body = expr.args[0]
29
+ expr_bound = expr.args[1]
30
+
31
+ positive_body_args, negative_body_args = _get_positive_and_negative_args(expr_body)
32
+
33
+ positive_bound_args, negative_bound_args = _get_positive_and_negative_args(
34
+ expr_bound
35
+ )
36
+
37
+ modified_expr = LessThan(
38
+ Add(*positive_body_args) - Add(*negative_bound_args),
39
+ Add(*positive_bound_args) - Add(*negative_body_args),
40
+ )
41
+
42
+ return modified_expr
43
+
44
+
45
+ def _get_positive_and_negative_args(expr: Expr) -> tuple[list[Expr], list[Expr]]:
46
+ positive_args = []
47
+ negative_args = []
48
+
49
+ if isinstance(expr, Add):
50
+ positive_args += list(filter(_is_positive_expr, expr.args))
51
+ negative_args += list(filterfalse(_is_positive_expr, expr.args))
52
+
53
+ elif _is_positive_expr(expr):
54
+ positive_args.append(expr)
55
+ else:
56
+ negative_args.append(expr)
57
+
58
+ if not positive_args and not negative_args:
59
+ raise ClassiqCombOptError("sign separation didn't worked out")
60
+
61
+ return positive_args, negative_args
62
+
63
+
64
+ def _is_positive_expr(expr: Expr) -> bool:
65
+ return (
66
+ (isinstance(expr, Number) and expr > 0)
67
+ or isinstance(expr, Symbol)
68
+ or (
69
+ isinstance(expr, Mul)
70
+ and isinstance(expr.args[0], Number)
71
+ and expr.args[0] > 0
72
+ and isinstance(expr.args[1], Symbol)
73
+ )
74
+ )
@@ -0,0 +1,87 @@
1
+ import math
2
+ from functools import cached_property
3
+ from itertools import filterfalse
4
+
5
+ import pyomo.core as pyo
6
+ from pyomo.core.base.component import _ComponentBase
7
+ from pyomo.core.expr.sympy_tools import sympy2pyomo_expression, sympyify_expression
8
+
9
+ from classiq.applications.combinatorial_helpers import pyomo_utils
10
+ from classiq.applications.combinatorial_helpers.arithmetic.arithmetic_expression import (
11
+ multivariate_extremum,
12
+ )
13
+ from classiq.applications.combinatorial_helpers.transformations import penalty_support
14
+ from classiq.applications.combinatorial_helpers.transformations.sign_seperation import (
15
+ sign_separation,
16
+ )
17
+
18
+
19
+ def slack_vars_convert(model: pyo.ConcreteModel) -> pyo.ConcreteModel:
20
+ constraints = pyomo_utils.extract(model, pyo.Constraint)
21
+ converted_constraints = list(
22
+ filterfalse(penalty_support.is_constraint_penalty_supported, constraints)
23
+ )
24
+
25
+ for constraint in converted_constraints:
26
+ convertor = ConstraintConvertor(constraint)
27
+ setattr(model, convertor.slack_var_name, convertor.slack_var)
28
+ setattr(model, convertor.slack_constraint_name, convertor.slack_constraint)
29
+
30
+ pyomo_utils.delete_component(model, constraint)
31
+
32
+ return model
33
+
34
+
35
+ _SLACK_VAR_SUFFIX = "_slack_var"
36
+ _SLACK_SUFFIX = "_slack"
37
+
38
+
39
+ def is_obj_slacked(var: _ComponentBase) -> bool:
40
+ return _SLACK_SUFFIX in var.name
41
+
42
+
43
+ class ConstraintConvertor:
44
+ def __init__(self, constraint: pyo.Constraint) -> None:
45
+ self._symbols_map, self._expr = sympyify_expression(constraint.expr)
46
+ self._expr = sign_separation(self._expr)
47
+ self._expr_lower, self._expr_upper = self._expr.args
48
+
49
+ self._name = pyomo_utils.get_name(constraint)
50
+
51
+ self.slack_var_name = self._name + _SLACK_VAR_SUFFIX
52
+ self.slack_var_idxs = range(self._bound_int.bit_length())
53
+ self.slack_var = pyo.Var(self.slack_var_idxs, domain=pyo.Binary)
54
+ self.slack_var.construct()
55
+
56
+ self.slack_constraint_name = self._name + _SLACK_SUFFIX
57
+
58
+ @cached_property
59
+ def _bound_int(self) -> int:
60
+ max_upper = math.ceil(
61
+ multivariate_extremum(self._expr_upper, self._symbols_map, is_min=False)
62
+ )
63
+ min_lower = math.floor(
64
+ multivariate_extremum(self._expr_lower, self._symbols_map, is_min=True)
65
+ )
66
+ return max_upper - min_lower
67
+
68
+ @cached_property
69
+ def _slack_coeffs(self) -> list[int]:
70
+ coeffs = [2**idx for idx in self.slack_var_idxs[:-1]]
71
+ coeffs += [self._bound_int - sum(coeffs)]
72
+ return coeffs
73
+
74
+ @cached_property
75
+ def _slack_expr(self) -> pyo.Expression:
76
+ return sum(
77
+ coeff * self.slack_var[num] for num, coeff in enumerate(self._slack_coeffs)
78
+ )
79
+
80
+ @cached_property
81
+ def slack_constraint(self) -> pyo.Constraint:
82
+ expr_lower_pyomo = sympy2pyomo_expression(self._expr_lower, self._symbols_map)
83
+ expr_upper_pyomo = sympy2pyomo_expression(self._expr_upper, self._symbols_map)
84
+
85
+ return pyo.Constraint(
86
+ expr=expr_lower_pyomo + self._slack_expr == expr_upper_pyomo
87
+ )
@@ -1,17 +1,36 @@
1
- from typing import List
2
-
3
1
  from classiq.interface.combinatorial_optimization import examples
2
+ from classiq.interface.combinatorial_optimization.encoding_types import EncodingType
4
3
  from classiq.interface.combinatorial_optimization.solver_types import QSolver
5
4
 
5
+ from classiq.applications.combinatorial_helpers.combinatorial_problem_utils import (
6
+ compute_qaoa_initial_point,
7
+ get_optimization_solution_from_pyo,
8
+ pyo_model_to_hamiltonian,
9
+ )
10
+
6
11
  from .combinatorial_optimization_config import OptimizerConfig, QAOAConfig
12
+ from .combinatorial_optimization_model_constructor import (
13
+ construct_combinatorial_optimization_model,
14
+ )
15
+ from .combinatorial_problem import (
16
+ CombinatorialProblem,
17
+ execute_qaoa,
18
+ )
7
19
 
8
20
  __all__ = [
21
+ "CombinatorialProblem",
22
+ "EncodingType",
23
+ "OptimizerConfig",
24
+ "QAOAConfig",
9
25
  "QSolver",
26
+ "compute_qaoa_initial_point",
27
+ "construct_combinatorial_optimization_model",
10
28
  "examples",
11
- "QAOAConfig",
12
- "OptimizerConfig",
29
+ "execute_qaoa",
30
+ "get_optimization_solution_from_pyo",
31
+ "pyo_model_to_hamiltonian",
13
32
  ]
14
33
 
15
34
 
16
- def __dir__() -> List[str]:
35
+ def __dir__() -> list[str]:
17
36
  return __all__
@@ -1,6 +1,6 @@
1
1
  import dataclasses
2
2
  from dataclasses import dataclass
3
- from typing import List, Optional
3
+ from typing import Optional
4
4
 
5
5
  from classiq.interface.executor.optimizer_preferences import CostType, OptimizerType
6
6
 
@@ -20,4 +20,4 @@ class OptimizerConfig:
20
20
  skip_compute_variance: bool = False
21
21
  cost_type: CostType = CostType.CVAR
22
22
  alpha_cvar: float = 1.0
23
- initial_point: Optional[List[float]] = dataclasses.field(default=None)
23
+ initial_point: Optional[list[float]] = dataclasses.field(default=None)
@@ -0,0 +1,137 @@
1
+ from typing import Optional
2
+
3
+ from pyomo import environ as pyo
4
+ from pyomo.core import Objective, maximize
5
+
6
+ from classiq.interface.generator.constant import Constant
7
+ from classiq.interface.generator.expressions.expression import Expression
8
+ from classiq.interface.generator.functions.classical_type import (
9
+ ClassicalArray,
10
+ ClassicalList,
11
+ Real,
12
+ )
13
+ from classiq.interface.generator.functions.port_declaration import (
14
+ PortDeclarationDirection,
15
+ )
16
+ from classiq.interface.generator.functions.type_name import Struct
17
+ from classiq.interface.model.allocate import Allocate
18
+ from classiq.interface.model.classical_parameter_declaration import (
19
+ ClassicalParameterDeclaration,
20
+ )
21
+ from classiq.interface.model.handle_binding import HandleBinding
22
+ from classiq.interface.model.model import Model, SerializedModel
23
+ from classiq.interface.model.native_function_definition import NativeFunctionDefinition
24
+ from classiq.interface.model.port_declaration import PortDeclaration
25
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
26
+ from classiq.interface.model.quantum_type import QuantumBitvector
27
+
28
+ from classiq.applications.combinatorial_helpers.combinatorial_problem_utils import (
29
+ compute_qaoa_initial_point,
30
+ convert_pyomo_to_global_presentation,
31
+ pyo_model_to_hamiltonian,
32
+ )
33
+ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import (
34
+ _pauli_terms_to_qmod,
35
+ )
36
+ from classiq.applications.combinatorial_optimization import OptimizerConfig, QAOAConfig
37
+ from classiq.open_library.functions.qaoa_penalty import qaoa_penalty
38
+
39
+
40
+ def construct_combi_opt_py_model(
41
+ pyo_model: pyo.ConcreteModel,
42
+ qaoa_config: Optional[QAOAConfig] = None,
43
+ optimizer_config: Optional[OptimizerConfig] = None,
44
+ ) -> Model:
45
+ if qaoa_config is None:
46
+ qaoa_config = QAOAConfig()
47
+
48
+ if optimizer_config is None:
49
+ optimizer_config = OptimizerConfig()
50
+
51
+ max_iteration = 0
52
+ if optimizer_config.max_iteration is not None:
53
+ max_iteration = optimizer_config.max_iteration
54
+
55
+ hamiltonian = pyo_model_to_hamiltonian(pyo_model, qaoa_config.penalty_energy)
56
+ len_hamiltonian = len(hamiltonian[0].pauli) # type: ignore[arg-type]
57
+ qaoa_initial_point = compute_qaoa_initial_point(hamiltonian, qaoa_config.num_layers)
58
+ pauli_qmod = _pauli_terms_to_qmod(hamiltonian)
59
+
60
+ initial_point_expression = (
61
+ f"{optimizer_config.initial_point}"
62
+ if optimizer_config.initial_point is not None
63
+ else f"{qaoa_initial_point}"
64
+ )
65
+
66
+ return Model(
67
+ constants=[
68
+ Constant(
69
+ name="hamiltonian",
70
+ const_type=ClassicalList(element_type=Struct(name="PauliTerm")),
71
+ value=Expression(expr=f"[{pauli_qmod}]"),
72
+ )
73
+ ],
74
+ functions=[
75
+ NativeFunctionDefinition(
76
+ name="main",
77
+ positional_arg_declarations=[
78
+ ClassicalParameterDeclaration(
79
+ name="params_list",
80
+ classical_type=ClassicalArray(
81
+ element_type=Real(), size=qaoa_config.num_layers * 2
82
+ ),
83
+ ),
84
+ PortDeclaration(
85
+ name="target",
86
+ quantum_type=QuantumBitvector(
87
+ length=Expression(expr=f"{len_hamiltonian}"),
88
+ ),
89
+ direction=PortDeclarationDirection.Output,
90
+ ),
91
+ ],
92
+ body=[
93
+ Allocate(
94
+ size=Expression(expr="get_field(target, 'len')"),
95
+ target=HandleBinding(name="target"),
96
+ ),
97
+ QuantumFunctionCall(
98
+ function="qaoa_penalty",
99
+ positional_args=[
100
+ Expression(expr="get_field(target, 'len')"),
101
+ Expression(expr="params_list"),
102
+ Expression(expr="hamiltonian"),
103
+ HandleBinding(name="target"),
104
+ ],
105
+ ),
106
+ ],
107
+ ),
108
+ *[f for f in qaoa_penalty.create_model().functions if f.name != "main"],
109
+ ],
110
+ classical_execution_code=f"""
111
+ vqe_result = vqe(
112
+ hamiltonian=hamiltonian,
113
+ maximize={next(pyo_model.component_objects(Objective)).sense == maximize},
114
+ initial_point={initial_point_expression},
115
+ optimizer=Optimizer.{optimizer_config.opt_type},
116
+ max_iteration={max_iteration},
117
+ tolerance={optimizer_config.tolerance},
118
+ step_size={optimizer_config.step_size},
119
+ skip_compute_variance={optimizer_config.skip_compute_variance},
120
+ alpha_cvar={optimizer_config.alpha_cvar}
121
+ )
122
+
123
+ save({{"vqe_result": vqe_result, "hamiltonian": hamiltonian}})
124
+ """.strip(),
125
+ )
126
+
127
+
128
+ def construct_combinatorial_optimization_model(
129
+ pyo_model: pyo.ConcreteModel,
130
+ qaoa_config: Optional[QAOAConfig] = None,
131
+ optimizer_config: Optional[OptimizerConfig] = None,
132
+ ) -> SerializedModel:
133
+ converted_pyo_model = convert_pyomo_to_global_presentation(pyo_model)
134
+ model = construct_combi_opt_py_model(
135
+ converted_pyo_model, qaoa_config, optimizer_config
136
+ )
137
+ return model.get_model()