classiq 0.37.1__py3-none-any.whl → 0.39.0__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 (280) hide show
  1. classiq/__init__.py +23 -24
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +1 -1
  3. classiq/_analyzer_extras/interactive_hardware.py +3 -3
  4. classiq/_internals/api_wrapper.py +37 -17
  5. classiq/_internals/async_utils.py +1 -74
  6. classiq/_internals/authentication/device.py +9 -4
  7. classiq/_internals/authentication/password_manager.py +25 -10
  8. classiq/_internals/authentication/token_manager.py +2 -2
  9. classiq/_internals/client.py +24 -6
  10. classiq/_internals/jobs.py +10 -7
  11. classiq/analyzer/analyzer.py +29 -29
  12. classiq/analyzer/analyzer_utilities.py +5 -5
  13. classiq/analyzer/rb.py +4 -5
  14. classiq/analyzer/show_interactive_hack.py +6 -6
  15. classiq/applications/__init__.py +1 -8
  16. classiq/applications/chemistry/__init__.py +6 -0
  17. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +9 -16
  18. classiq/applications/combinatorial_helpers/allowed_constraints.py +20 -0
  19. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
  20. classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
  21. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +150 -0
  22. classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
  23. classiq/applications/combinatorial_helpers/encoding_utils.py +122 -0
  24. classiq/applications/combinatorial_helpers/memory.py +77 -0
  25. classiq/applications/combinatorial_helpers/optimization_model.py +162 -0
  26. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
  27. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +75 -0
  28. classiq/applications/combinatorial_helpers/py.typed +0 -0
  29. classiq/applications/combinatorial_helpers/pyomo_utils.py +245 -0
  30. classiq/applications/combinatorial_helpers/solvers/__init__.py +0 -0
  31. classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
  32. classiq/applications/combinatorial_helpers/transformations/__init__.py +0 -0
  33. classiq/applications/combinatorial_helpers/transformations/encoding.py +187 -0
  34. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +142 -0
  35. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +122 -0
  36. classiq/applications/combinatorial_helpers/transformations/penalty.py +32 -0
  37. classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
  38. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +75 -0
  39. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +88 -0
  40. classiq/applications/combinatorial_optimization/__init__.py +13 -2
  41. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +134 -0
  42. classiq/applications/finance/__init__.py +3 -2
  43. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +27 -30
  44. classiq/applications/grover/__init__.py +11 -0
  45. classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +20 -91
  46. classiq/applications/libraries/__init__.py +0 -0
  47. classiq/applications/libraries/qmci_library.py +35 -0
  48. classiq/applications/qnn/circuit_utils.py +2 -2
  49. classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
  50. classiq/applications/qnn/types.py +2 -2
  51. classiq/applications/qsvm/__init__.py +5 -1
  52. classiq/applications/qsvm/qsvm.py +4 -7
  53. classiq/applications/qsvm/qsvm_data_generation.py +2 -5
  54. classiq/exceptions.py +43 -1
  55. classiq/execution/all_hardware_devices.py +13 -0
  56. classiq/executor.py +12 -10
  57. classiq/interface/_version.py +1 -1
  58. classiq/interface/analyzer/analysis_params.py +6 -3
  59. classiq/interface/analyzer/result.py +12 -8
  60. classiq/interface/applications/qsvm.py +17 -3
  61. classiq/interface/ast_node.py +23 -0
  62. classiq/interface/backend/backend_preferences.py +4 -2
  63. classiq/interface/backend/pydantic_backend.py +3 -1
  64. classiq/interface/backend/quantum_backend_providers.py +1 -0
  65. classiq/interface/chemistry/fermionic_operator.py +15 -13
  66. classiq/interface/chemistry/ground_state_problem.py +18 -3
  67. classiq/interface/chemistry/molecule.py +8 -6
  68. classiq/interface/chemistry/operator.py +20 -14
  69. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -1
  70. classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
  71. classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
  72. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -2
  73. classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
  74. classiq/interface/combinatorial_optimization/examples/mht.py +8 -3
  75. classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
  76. classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
  77. classiq/interface/combinatorial_optimization/examples/set_cover.py +2 -1
  78. classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
  79. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
  80. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +9 -3
  81. classiq/interface/executor/aws_execution_cost.py +4 -3
  82. classiq/interface/executor/estimation.py +2 -2
  83. classiq/interface/executor/execution_preferences.py +5 -34
  84. classiq/interface/executor/execution_request.py +15 -48
  85. classiq/interface/executor/optimizer_preferences.py +22 -13
  86. classiq/interface/executor/{quantum_program.py → quantum_code.py} +21 -15
  87. classiq/interface/executor/quantum_instruction_set.py +2 -1
  88. classiq/interface/executor/register_initialization.py +1 -3
  89. classiq/interface/executor/result.py +41 -10
  90. classiq/interface/executor/vqe_result.py +2 -2
  91. classiq/interface/finance/function_input.py +17 -4
  92. classiq/interface/finance/gaussian_model_input.py +3 -1
  93. classiq/interface/finance/log_normal_model_input.py +3 -1
  94. classiq/interface/finance/model_input.py +2 -0
  95. classiq/interface/generator/amplitude_loading.py +6 -3
  96. classiq/interface/generator/application_apis/__init__.py +1 -0
  97. classiq/interface/generator/application_apis/arithmetic_declarations.py +14 -0
  98. classiq/interface/generator/arith/argument_utils.py +14 -4
  99. classiq/interface/generator/arith/arithmetic.py +3 -1
  100. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +12 -13
  101. classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -1
  102. classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -2
  103. classiq/interface/generator/arith/arithmetic_expression_validator.py +16 -2
  104. classiq/interface/generator/arith/arithmetic_operations.py +5 -10
  105. classiq/interface/generator/arith/ast_node_rewrite.py +1 -1
  106. classiq/interface/generator/arith/binary_ops.py +202 -54
  107. classiq/interface/generator/arith/extremum_operations.py +5 -3
  108. classiq/interface/generator/arith/logical_ops.py +4 -2
  109. classiq/interface/generator/arith/machine_precision.py +3 -0
  110. classiq/interface/generator/arith/number_utils.py +34 -44
  111. classiq/interface/generator/arith/register_user_input.py +21 -1
  112. classiq/interface/generator/arith/unary_ops.py +16 -25
  113. classiq/interface/generator/builtin_api_builder.py +0 -5
  114. classiq/interface/generator/chemistry_function_params.py +4 -4
  115. classiq/interface/generator/commuting_pauli_exponentiation.py +3 -1
  116. classiq/interface/generator/compiler_keywords.py +4 -0
  117. classiq/interface/generator/complex_type.py +3 -10
  118. classiq/interface/generator/constant.py +2 -3
  119. classiq/interface/generator/control_state.py +5 -3
  120. classiq/interface/generator/credit_risk_example/linear_gci.py +10 -3
  121. classiq/interface/generator/credit_risk_example/weighted_adder.py +14 -4
  122. classiq/interface/generator/expressions/atomic_expression_functions.py +5 -3
  123. classiq/interface/generator/expressions/evaluated_expression.py +18 -4
  124. classiq/interface/generator/expressions/expression.py +3 -5
  125. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +33 -0
  126. classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
  127. classiq/interface/generator/finance.py +1 -1
  128. classiq/interface/generator/function_params.py +7 -6
  129. classiq/interface/generator/functions/__init__.py +2 -2
  130. classiq/interface/generator/functions/builtins/__init__.py +15 -0
  131. classiq/interface/generator/functions/builtins/core_library/__init__.py +14 -0
  132. classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
  133. classiq/interface/generator/functions/builtins/internal_operators.py +62 -0
  134. classiq/interface/generator/functions/{core_lib_declarations/quantum_functions/std_lib_functions.py → builtins/open_lib_functions.py} +612 -219
  135. classiq/interface/generator/functions/builtins/quantum_operators.py +37 -0
  136. classiq/interface/generator/functions/classical_type.py +2 -4
  137. classiq/interface/generator/functions/foreign_function_definition.py +12 -4
  138. classiq/interface/generator/functions/function_declaration.py +2 -2
  139. classiq/interface/generator/functions/function_implementation.py +8 -4
  140. classiq/interface/generator/functions/native_function_definition.py +4 -2
  141. classiq/interface/generator/functions/register.py +4 -2
  142. classiq/interface/generator/functions/register_mapping_data.py +14 -10
  143. classiq/interface/generator/generated_circuit_data.py +2 -2
  144. classiq/interface/generator/grover_operator.py +5 -3
  145. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +5 -1
  146. classiq/interface/generator/hardware/hardware_data.py +6 -4
  147. classiq/interface/generator/hardware_efficient_ansatz.py +25 -8
  148. classiq/interface/generator/hartree_fock.py +13 -3
  149. classiq/interface/generator/linear_pauli_rotations.py +3 -1
  150. classiq/interface/generator/mcu.py +5 -3
  151. classiq/interface/generator/mcx.py +7 -5
  152. classiq/interface/generator/model/classical_main_validator.py +1 -1
  153. classiq/interface/generator/model/constraints.py +2 -1
  154. classiq/interface/generator/model/model.py +12 -20
  155. classiq/interface/generator/model/preferences/preferences.py +4 -3
  156. classiq/interface/generator/oracles/custom_oracle.py +4 -2
  157. classiq/interface/generator/oracles/oracle_abc.py +2 -2
  158. classiq/interface/generator/qpe.py +6 -4
  159. classiq/interface/generator/qsvm.py +5 -8
  160. classiq/interface/generator/quantum_function_call.py +21 -16
  161. classiq/interface/generator/{generated_circuit.py → quantum_program.py} +10 -14
  162. classiq/interface/generator/range_types.py +3 -1
  163. classiq/interface/generator/slice_parsing_utils.py +8 -3
  164. classiq/interface/generator/standard_gates/controlled_standard_gates.py +4 -2
  165. classiq/interface/generator/state_preparation/metrics.py +2 -1
  166. classiq/interface/generator/state_preparation/state_preparation.py +7 -5
  167. classiq/interface/generator/state_propagator.py +16 -5
  168. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  169. classiq/interface/generator/types/struct_declaration.py +10 -7
  170. classiq/interface/generator/ucc.py +6 -4
  171. classiq/interface/generator/unitary_gate.py +7 -3
  172. classiq/interface/generator/validations/flow_graph.py +6 -4
  173. classiq/interface/generator/validations/validator_functions.py +6 -4
  174. classiq/interface/hardware.py +2 -2
  175. classiq/interface/helpers/custom_encoders.py +3 -0
  176. classiq/interface/helpers/pydantic_model_helpers.py +0 -6
  177. classiq/interface/helpers/validation_helpers.py +1 -1
  178. classiq/interface/helpers/versioned_model.py +4 -1
  179. classiq/interface/ide/show.py +2 -2
  180. classiq/interface/jobs.py +72 -3
  181. classiq/interface/model/bind_operation.py +18 -11
  182. classiq/interface/model/call_synthesis_data.py +68 -0
  183. classiq/interface/model/classical_if.py +13 -0
  184. classiq/interface/model/classical_parameter_declaration.py +2 -3
  185. classiq/interface/model/control.py +16 -0
  186. classiq/interface/model/handle_binding.py +3 -2
  187. classiq/interface/model/inplace_binary_operation.py +2 -2
  188. classiq/interface/model/invert.py +10 -0
  189. classiq/interface/model/model.py +29 -22
  190. classiq/interface/model/native_function_definition.py +3 -5
  191. classiq/interface/model/power.py +12 -0
  192. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +9 -4
  193. classiq/interface/model/quantum_expressions/control_state.py +2 -2
  194. classiq/interface/model/quantum_function_call.py +33 -142
  195. classiq/interface/model/quantum_function_declaration.py +8 -0
  196. classiq/interface/model/quantum_if_operation.py +4 -5
  197. classiq/interface/model/quantum_lambda_function.py +58 -0
  198. classiq/{quantum_register.py → interface/model/quantum_register.py} +17 -9
  199. classiq/interface/model/quantum_statement.py +3 -2
  200. classiq/interface/model/quantum_type.py +58 -59
  201. classiq/interface/model/quantum_variable_declaration.py +3 -3
  202. classiq/interface/model/repeat.py +13 -0
  203. classiq/interface/model/resolvers/function_call_resolver.py +26 -0
  204. classiq/interface/model/statement_block.py +49 -0
  205. classiq/interface/model/validations/handles_validator.py +16 -18
  206. classiq/interface/model/within_apply_operation.py +11 -0
  207. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
  208. classiq/interface/server/routes.py +5 -4
  209. classiq/qmod/__init__.py +13 -6
  210. classiq/qmod/builtins/classical_execution_primitives.py +27 -36
  211. classiq/qmod/builtins/classical_functions.py +22 -12
  212. classiq/qmod/builtins/functions.py +272 -328
  213. classiq/qmod/builtins/operations.py +171 -35
  214. classiq/qmod/builtins/structs.py +15 -15
  215. classiq/qmod/cfunc.py +42 -0
  216. classiq/qmod/classical_function.py +6 -14
  217. classiq/qmod/declaration_inferrer.py +12 -21
  218. classiq/qmod/expression_query.py +23 -0
  219. classiq/qmod/model_state_container.py +2 -0
  220. classiq/qmod/native/__init__.py +0 -0
  221. classiq/qmod/native/expression_to_qmod.py +189 -0
  222. classiq/qmod/native/pretty_printer.py +340 -0
  223. classiq/qmod/qfunc.py +27 -0
  224. classiq/qmod/qmod_constant.py +100 -0
  225. classiq/qmod/qmod_parameter.py +36 -13
  226. classiq/qmod/qmod_struct.py +3 -3
  227. classiq/qmod/qmod_variable.py +148 -31
  228. classiq/qmod/quantum_callable.py +1 -0
  229. classiq/qmod/quantum_expandable.py +18 -19
  230. classiq/qmod/quantum_function.py +41 -8
  231. classiq/qmod/symbolic.py +48 -5
  232. classiq/qmod/symbolic_expr.py +9 -0
  233. classiq/qmod/utilities.py +13 -0
  234. classiq/qmod/write_qmod.py +39 -0
  235. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/METADATA +2 -1
  236. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/RECORD +244 -225
  237. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/WHEEL +1 -1
  238. classiq/applications/benchmarking/__init__.py +0 -9
  239. classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
  240. classiq/applications/numpy_utils.py +0 -37
  241. classiq/applications_model_constructors/__init__.py +0 -17
  242. classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
  243. classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
  244. classiq/builtin_functions/__init__.py +0 -43
  245. classiq/builtin_functions/amplitude_loading.py +0 -3
  246. classiq/builtin_functions/binary_ops.py +0 -1
  247. classiq/builtin_functions/exponentiation.py +0 -5
  248. classiq/builtin_functions/qpe.py +0 -4
  249. classiq/builtin_functions/qsvm.py +0 -7
  250. classiq/builtin_functions/range_types.py +0 -5
  251. classiq/builtin_functions/standard_gates.py +0 -1
  252. classiq/builtin_functions/state_preparation.py +0 -6
  253. classiq/builtin_functions/suzuki_trotter.py +0 -3
  254. classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
  255. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  256. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
  257. classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
  258. classiq/interface/generator/types/combinatorial_problem.py +0 -26
  259. classiq/interface/model/numeric_reinterpretation.py +0 -25
  260. classiq/interface/model/operator_synthesis_data.py +0 -48
  261. classiq/model/__init__.py +0 -14
  262. classiq/model/composite_function_generator.py +0 -33
  263. classiq/model/function_handler.py +0 -466
  264. classiq/model/function_handler.pyi +0 -152
  265. classiq/model/logic_flow.py +0 -149
  266. classiq/model/logic_flow_change_handler.py +0 -71
  267. classiq/model/model.py +0 -246
  268. classiq/quantum_functions/__init__.py +0 -17
  269. classiq/quantum_functions/annotation_parser.py +0 -207
  270. classiq/quantum_functions/decorators.py +0 -22
  271. classiq/quantum_functions/function_library.py +0 -181
  272. classiq/quantum_functions/function_parser.py +0 -74
  273. classiq/quantum_functions/quantum_function.py +0 -236
  274. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
  275. /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
  276. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/pauli_helpers/__init__.py} +0 -0
  277. /classiq/{applications_model_constructors → applications}/libraries/ampltitude_estimation_library.py +0 -0
  278. /classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +0 -0
  279. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/atomic_quantum_functions.py +0 -0
  280. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/exponentiation_functions.py +0 -0
@@ -0,0 +1,122 @@
1
+ from typing import List
2
+
3
+ import pyomo
4
+ import sympy as sp
5
+ from pyomo.core.base import _GeneralVarData
6
+
7
+ from classiq.interface.chemistry.operator import PauliOperator
8
+ from classiq.interface.helpers import custom_pydantic_types
9
+
10
+ from classiq.applications.combinatorial_helpers import memory
11
+ from classiq.applications.combinatorial_helpers.memory import InternalQuantumReg
12
+ from classiq.applications.combinatorial_helpers.sympy_utils import (
13
+ sympyify_expression,
14
+ sympyify_vars,
15
+ )
16
+ from classiq.exceptions import ClassiqCombOptNotSupportedProblemError
17
+
18
+ PYOMO_PARSING_ERROR_MESAGE = "Parsing of this pyomo model is not supported."
19
+
20
+
21
+ def convert_pyomo_to_hamiltonian(
22
+ pyomo_expr: pyomo.core.Expression,
23
+ ordered_pyomo_vars: List[_GeneralVarData],
24
+ qregs: List[InternalQuantumReg],
25
+ ) -> PauliOperator:
26
+ symbols_map = sympyify_vars(ordered_pyomo_vars)
27
+ sympy_expr = sympyify_expression(pyomo_expr, symbols_map)
28
+ if not sympy_expr.is_polynomial():
29
+ raise ClassiqCombOptNotSupportedProblemError(PYOMO_PARSING_ERROR_MESAGE)
30
+
31
+ ordered_sympy_vars = [
32
+ symbols_map.pyomo2sympy[pyomo_var] for pyomo_var in ordered_pyomo_vars
33
+ ]
34
+ ising_expr = _to_ising_symbolic_objective_function(sympy_expr)
35
+ ising_expr = _refine_ising_expr(ising_expr)
36
+
37
+ operator = _convert_ising_sympy_to_operator(ising_expr, ordered_sympy_vars)
38
+ operator = _add_auxiliary_qubits_to_operator(operator, qregs)
39
+
40
+ return PauliOperator(pauli_list=operator)
41
+
42
+
43
+ def _convert_ising_sympy_to_operator(
44
+ ising_expr: sp.Expr, ordered_sympy_vars: List[sp.Symbol]
45
+ ) -> custom_pydantic_types.PydanticPauliList:
46
+ pauli_op_list: custom_pydantic_types.PydanticPauliList = []
47
+ for expr_term in ising_expr.args:
48
+ expr_vars = _get_vars(expr_term)
49
+ z_vec = _find_sub_list_items(ordered_sympy_vars, expr_vars)
50
+ pauli_string_list = ["I"] * len(z_vec)
51
+ for index, is_z_op in enumerate(z_vec):
52
+ if is_z_op:
53
+ pauli_string_list[len(z_vec) - index - 1] = (
54
+ "Z" # reminder: Pauli reverses the order!
55
+ )
56
+ pauli_string = "".join(pauli_string_list)
57
+ coeff = _get_coeff_from_expr(expr_term)
58
+ pauli_op_list.append((pauli_string, complex(coeff)))
59
+ return pauli_op_list
60
+
61
+
62
+ def _refine_ising_expr(ising_expr: sp.Expr) -> sp.Expr:
63
+ # The variables here are assumed to be either 1 or -1 (ising variables).
64
+ # Therefore x^a can replaced with 1 if a is even, and with x is a is odd.
65
+ # Change the expression recursively.
66
+ def update_expr(expr: sp.Expr) -> sp.Expr:
67
+ if isinstance(expr, sp.Pow):
68
+ if expr.args[1] % 2: # odd power: x**a -> x
69
+ expr = expr.args[0]
70
+ else: # even power: x**a -> 1
71
+ expr = sp.Float(1)
72
+ if hasattr(expr, "args") and expr.args:
73
+ new_args = [update_expr(arg) for arg in expr.args]
74
+ expr_class = type(expr)
75
+ return expr_class(*new_args)
76
+ else:
77
+ return expr
78
+
79
+ return update_expr(ising_expr)
80
+
81
+
82
+ def _to_ising_symbolic_objective_function(objective: sp.Expr) -> sp.Expr:
83
+ # cost-function to Hamiltonian conversion explanation:
84
+ # https://qiskit.org/textbook/ch-applications/qaoa.html#1.1-Diagonal-Hamiltonians
85
+ subs_vars_dict = {var: (1 - var) / 2 for var in objective.free_symbols}
86
+ objective_ising = objective.subs(subs_vars_dict)
87
+ return sp.expand(objective_ising)
88
+
89
+
90
+ def _get_vars(expr_term: sp.AtomicExpr) -> List[sp.Symbol]:
91
+ if isinstance(expr_term, sp.Symbol):
92
+ return [expr_term]
93
+ else:
94
+ return expr_term.args
95
+
96
+
97
+ def _find_sub_list_items(
98
+ long_list: List[sp.Symbol], sub_list: List[sp.Symbol]
99
+ ) -> List[bool]:
100
+ return [x in sub_list for x in long_list]
101
+
102
+
103
+ def _get_coeff_from_expr(expr: sp.Expr) -> float:
104
+ if isinstance(expr, sp.Number):
105
+ return float(expr)
106
+ if isinstance(expr, sp.Symbol):
107
+ return 1
108
+ if all(isinstance(arg, sp.Symbol) for arg in expr.args):
109
+ return 1
110
+ return float(expr.args[0])
111
+
112
+
113
+ def _add_auxiliary_qubits_to_operator(
114
+ operator: custom_pydantic_types.PydanticPauliList, qregs: List[InternalQuantumReg]
115
+ ) -> custom_pydantic_types.PydanticPauliList:
116
+ # TODO: handle the case when the auxiliary are in the middle of the circuit
117
+ for qreg in qregs:
118
+ if qreg.name == memory.AUXILIARY_NAME:
119
+ operator = [
120
+ ("I" * qreg.size + monomial[0], monomial[1]) for monomial in operator
121
+ ]
122
+ return operator
@@ -0,0 +1,32 @@
1
+ import itertools
2
+ from typing import List
3
+
4
+ from pyomo.core.base.constraint import _GeneralConstraintData
5
+ from pyomo.core.expr.relational_expr import EqualityExpression
6
+ from pyomo.environ import Expression
7
+
8
+
9
+ def get_penalty_expression(
10
+ flat_constraints: List[_GeneralConstraintData],
11
+ ) -> Expression:
12
+ return sum(
13
+ _convert_constraint_to_penalty_term(constraint)
14
+ for constraint in flat_constraints
15
+ )
16
+
17
+
18
+ def _convert_constraint_to_penalty_term(
19
+ constraint: _GeneralConstraintData,
20
+ ) -> Expression:
21
+ if isinstance(constraint.expr, EqualityExpression):
22
+ return (constraint.expr.args[0] - constraint.expr.args[1]) ** 2
23
+
24
+ # we can assume that isinstance(constraint.expr, InequalityExpression) and constraint.expr.args[1] == 1
25
+ # due to _is_constraint_penalty_supported method
26
+ else:
27
+ index = 0
28
+ if isinstance(constraint.expr.args[0], int):
29
+ index = 1
30
+ constraint_variables = constraint.expr.args[index].args
31
+ var_pairs = list(itertools.combinations(constraint_variables, 2))
32
+ 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,75 @@
1
+ from itertools import filterfalse
2
+ from typing import List, Tuple
3
+
4
+ from sympy import (
5
+ Add,
6
+ Expr,
7
+ GreaterThan,
8
+ LessThan,
9
+ Mul,
10
+ Number,
11
+ Symbol,
12
+ expand,
13
+ simplify,
14
+ )
15
+
16
+ from classiq.exceptions import ClassiqCombOptError
17
+
18
+
19
+ def sign_separation(expr: Expr) -> LessThan:
20
+ expr = simplify(expr)
21
+ expr = expand(expr)
22
+
23
+ if not isinstance(expr, (LessThan, GreaterThan)):
24
+ raise ClassiqCombOptError("sign separation didn't worked out")
25
+
26
+ if isinstance(expr, GreaterThan):
27
+ expr = LessThan(expr.args[1], expr.args[0])
28
+
29
+ expr_body = expr.args[0]
30
+ expr_bound = expr.args[1]
31
+
32
+ positive_body_args, negative_body_args = _get_positive_and_negative_args(expr_body)
33
+
34
+ positive_bound_args, negative_bound_args = _get_positive_and_negative_args(
35
+ expr_bound
36
+ )
37
+
38
+ modified_expr = LessThan(
39
+ Add(*positive_body_args) - Add(*negative_bound_args),
40
+ Add(*positive_bound_args) - Add(*negative_body_args),
41
+ )
42
+
43
+ return modified_expr
44
+
45
+
46
+ def _get_positive_and_negative_args(expr: Expr) -> Tuple[List[Expr], List[Expr]]:
47
+ positive_args = []
48
+ negative_args = []
49
+
50
+ if isinstance(expr, Add):
51
+ positive_args += list(filter(_is_positive_expr, expr.args))
52
+ negative_args += list(filterfalse(_is_positive_expr, expr.args))
53
+
54
+ elif _is_positive_expr(expr):
55
+ positive_args.append(expr)
56
+ else:
57
+ negative_args.append(expr)
58
+
59
+ if not positive_args and not negative_args:
60
+ raise ClassiqCombOptError("sign separation didn't worked out")
61
+
62
+ return positive_args, negative_args
63
+
64
+
65
+ def _is_positive_expr(expr: Expr) -> bool:
66
+ return (
67
+ (isinstance(expr, Number) and expr > 0)
68
+ or isinstance(expr, Symbol)
69
+ or (
70
+ isinstance(expr, Mul)
71
+ and isinstance(expr.args[0], Number)
72
+ and expr.args[0] > 0
73
+ and isinstance(expr.args[1], Symbol)
74
+ )
75
+ )
@@ -0,0 +1,88 @@
1
+ import math
2
+ from functools import cached_property
3
+ from itertools import filterfalse
4
+ from typing import List
5
+
6
+ import pyomo.core as pyo
7
+ from pyomo.core.base.component import _ComponentBase
8
+ from pyomo.core.expr.sympy_tools import sympy2pyomo_expression, sympyify_expression
9
+
10
+ from classiq.applications.combinatorial_helpers import pyomo_utils
11
+ from classiq.applications.combinatorial_helpers.arithmetic.arithmetic_expression import (
12
+ multivariate_extremum,
13
+ )
14
+ from classiq.applications.combinatorial_helpers.transformations import penalty_support
15
+ from classiq.applications.combinatorial_helpers.transformations.sign_seperation import (
16
+ sign_separation,
17
+ )
18
+
19
+
20
+ def slack_vars_convert(model: pyo.ConcreteModel) -> pyo.ConcreteModel:
21
+ constraints = pyomo_utils.extract(model, pyo.Constraint)
22
+ converted_constraints = list(
23
+ filterfalse(penalty_support.is_constraint_penalty_supported, constraints)
24
+ )
25
+
26
+ for constraint in converted_constraints:
27
+ convertor = ConstraintConvertor(constraint)
28
+ setattr(model, convertor.slack_var_name, convertor.slack_var)
29
+ setattr(model, convertor.slack_constraint_name, convertor.slack_constraint)
30
+
31
+ pyomo_utils.delete_component(model, constraint)
32
+
33
+ return model
34
+
35
+
36
+ _SLACK_VAR_SUFFIX = "_slack_var"
37
+ _SLACK_SUFFIX = "_slack"
38
+
39
+
40
+ def is_obj_slacked(var: _ComponentBase) -> bool:
41
+ return _SLACK_SUFFIX in var.name
42
+
43
+
44
+ class ConstraintConvertor:
45
+ def __init__(self, constraint: pyo.Constraint) -> None:
46
+ self._symbols_map, self._expr = sympyify_expression(constraint.expr)
47
+ self._expr = sign_separation(self._expr)
48
+ self._expr_lower, self._expr_upper = self._expr.args
49
+
50
+ self._name = pyomo_utils.get_name(constraint)
51
+
52
+ self.slack_var_name = self._name + _SLACK_VAR_SUFFIX
53
+ self.slack_var_idxs = range(self._bound_int.bit_length())
54
+ self.slack_var = pyo.Var(self.slack_var_idxs, domain=pyo.Binary)
55
+ self.slack_var.construct()
56
+
57
+ self.slack_constraint_name = self._name + _SLACK_SUFFIX
58
+
59
+ @cached_property
60
+ def _bound_int(self) -> int:
61
+ max_upper = math.ceil(
62
+ multivariate_extremum(self._expr_upper, self._symbols_map, is_min=False)
63
+ )
64
+ min_lower = math.floor(
65
+ multivariate_extremum(self._expr_lower, self._symbols_map, is_min=True)
66
+ )
67
+ return max_upper - min_lower
68
+
69
+ @cached_property
70
+ def _slack_coeffs(self) -> List[int]:
71
+ coeffs = [2**idx for idx in self.slack_var_idxs[:-1]]
72
+ coeffs += [self._bound_int - sum(coeffs)]
73
+ return coeffs
74
+
75
+ @cached_property
76
+ def _slack_expr(self) -> pyo.Expression:
77
+ return sum(
78
+ coeff * self.slack_var[num] for num, coeff in enumerate(self._slack_coeffs)
79
+ )
80
+
81
+ @cached_property
82
+ def slack_constraint(self) -> pyo.Constraint:
83
+ expr_lower_pyomo = sympy2pyomo_expression(self._expr_lower, self._symbols_map)
84
+ expr_upper_pyomo = sympy2pyomo_expression(self._expr_upper, self._symbols_map)
85
+
86
+ return pyo.Constraint(
87
+ expr=expr_lower_pyomo + self._slack_expr == expr_upper_pyomo
88
+ )
@@ -1,15 +1,26 @@
1
1
  from typing import List
2
2
 
3
3
  from classiq.interface.combinatorial_optimization import examples
4
+ from classiq.interface.combinatorial_optimization.encoding_types import EncodingType
4
5
  from classiq.interface.combinatorial_optimization.solver_types import QSolver
5
6
 
7
+ from classiq.applications.combinatorial_helpers.combinatorial_problem_utils import (
8
+ get_optimization_solution_from_pyo,
9
+ )
10
+
6
11
  from .combinatorial_optimization_config import OptimizerConfig, QAOAConfig
12
+ from .combinatorial_optimization_model_constructor import (
13
+ construct_combinatorial_optimization_model,
14
+ )
7
15
 
8
16
  __all__ = [
17
+ "EncodingType",
18
+ "OptimizerConfig",
19
+ "QAOAConfig",
9
20
  "QSolver",
21
+ "construct_combinatorial_optimization_model",
10
22
  "examples",
11
- "QAOAConfig",
12
- "OptimizerConfig",
23
+ "get_optimization_solution_from_pyo",
13
24
  ]
14
25
 
15
26
 
@@ -0,0 +1,134 @@
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
+ Struct,
13
+ )
14
+ from classiq.interface.generator.functions.port_declaration import (
15
+ PortDeclarationDirection,
16
+ )
17
+ from classiq.interface.model.handle_binding import HandleBinding
18
+ from classiq.interface.model.model import Model, SerializedModel
19
+ from classiq.interface.model.native_function_definition import NativeFunctionDefinition
20
+ from classiq.interface.model.port_declaration import PortDeclaration
21
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
22
+
23
+ from classiq.applications.combinatorial_helpers.combinatorial_problem_utils import (
24
+ _internal_pyo_model_to_hamiltonian,
25
+ compute_qaoa_initial_point,
26
+ convert_pyomo_to_global_presentation,
27
+ )
28
+ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import (
29
+ _pauli_operator_to_qmod,
30
+ get_pauli_operator,
31
+ )
32
+ from classiq.applications.combinatorial_optimization import OptimizerConfig, QAOAConfig
33
+
34
+
35
+ def construct_combi_opt_py_model(
36
+ pyo_model: pyo.ConcreteModel,
37
+ qaoa_config: Optional[QAOAConfig] = None,
38
+ optimizer_config: Optional[OptimizerConfig] = None,
39
+ ) -> Model:
40
+ if qaoa_config is None:
41
+ qaoa_config = QAOAConfig()
42
+
43
+ if optimizer_config is None:
44
+ optimizer_config = OptimizerConfig()
45
+
46
+ max_iteration = 0
47
+ if optimizer_config.max_iteration is not None:
48
+ max_iteration = optimizer_config.max_iteration
49
+
50
+ hamiltonian = _internal_pyo_model_to_hamiltonian(
51
+ pyo_model, qaoa_config.penalty_energy
52
+ )
53
+ qaoa_initial_point = compute_qaoa_initial_point(hamiltonian, qaoa_config.num_layers)
54
+ len_hamiltonian = len(hamiltonian[0]["pauli"])
55
+ pauli_oper = get_pauli_operator(hamiltonian)
56
+ pauli_qmod = _pauli_operator_to_qmod(pauli_oper)
57
+
58
+ initial_point_expression = (
59
+ f"{optimizer_config.initial_point}"
60
+ if optimizer_config.initial_point is not None
61
+ else f"{qaoa_initial_point}"
62
+ )
63
+
64
+ return Model(
65
+ constants=[
66
+ Constant(
67
+ name="hamiltonian",
68
+ const_type=ClassicalList(element_type=Struct(name="PauliTerm")),
69
+ value=Expression(expr=f"[{pauli_qmod}]"),
70
+ )
71
+ ],
72
+ functions=[
73
+ NativeFunctionDefinition(
74
+ name="main",
75
+ param_decls={
76
+ "params_list": ClassicalArray(
77
+ element_type=Real(), size=qaoa_config.num_layers * 2
78
+ )
79
+ },
80
+ port_declarations={
81
+ "target": PortDeclaration(
82
+ name="target",
83
+ size=Expression(expr=f"{len_hamiltonian}"),
84
+ direction=PortDeclarationDirection.Output,
85
+ ),
86
+ },
87
+ body=[
88
+ QuantumFunctionCall(
89
+ function="allocate",
90
+ positional_args=[
91
+ Expression(expr="len(target)"),
92
+ HandleBinding(name="target"),
93
+ ],
94
+ ),
95
+ QuantumFunctionCall(
96
+ function="qaoa_penalty",
97
+ params={
98
+ "num_qubits": Expression(expr="len(target)"),
99
+ "params_list": Expression(expr="params_list"),
100
+ "hamiltonian": Expression(expr="hamiltonian"),
101
+ },
102
+ inouts={"target": HandleBinding(name="target")},
103
+ ),
104
+ ],
105
+ ),
106
+ ],
107
+ classical_execution_code=f"""
108
+ vqe_result = vqe(
109
+ hamiltonian=hamiltonian,
110
+ maximize={next(pyo_model.component_objects(Objective)).sense == maximize},
111
+ initial_point={initial_point_expression},
112
+ optimizer=Optimizer.{optimizer_config.opt_type},
113
+ max_iteration={max_iteration},
114
+ tolerance={optimizer_config.tolerance},
115
+ step_size={optimizer_config.step_size},
116
+ skip_compute_variance={optimizer_config.skip_compute_variance},
117
+ alpha_cvar={optimizer_config.alpha_cvar}
118
+ )
119
+
120
+ save({{"vqe_result": vqe_result, "hamiltonian": hamiltonian}})
121
+ """,
122
+ )
123
+
124
+
125
+ def construct_combinatorial_optimization_model(
126
+ pyo_model: pyo.ConcreteModel,
127
+ qaoa_config: Optional[QAOAConfig] = None,
128
+ optimizer_config: Optional[OptimizerConfig] = None,
129
+ ) -> SerializedModel:
130
+ converted_pyo_model = convert_pyomo_to_global_presentation(pyo_model)
131
+ model = construct_combi_opt_py_model(
132
+ converted_pyo_model, qaoa_config, optimizer_config
133
+ )
134
+ return model.get_model()
@@ -4,14 +4,15 @@ from classiq.interface.finance import (
4
4
  function_input,
5
5
  gaussian_model_input,
6
6
  log_normal_model_input,
7
- model_input,
8
7
  )
9
8
 
9
+ from .finance_model_constructor import construct_finance_model
10
+
10
11
  __all__ = [
12
+ "construct_finance_model",
11
13
  "function_input",
12
14
  "gaussian_model_input",
13
15
  "log_normal_model_input",
14
- "model_input",
15
16
  ]
16
17
 
17
18
 
@@ -4,10 +4,6 @@ from typing import Union
4
4
  from classiq.interface.finance.function_input import FinanceFunctionInput
5
5
  from classiq.interface.finance.gaussian_model_input import GaussianModelInput
6
6
  from classiq.interface.finance.log_normal_model_input import LogNormalModelInput
7
- from classiq.interface.generator.expressions.enums.finance_functions import (
8
- FINANCE_FUNCTION_STRING,
9
- FinanceFunctionType,
10
- )
11
7
  from classiq.interface.generator.expressions.expression import Expression
12
8
  from classiq.interface.generator.functions.port_declaration import (
13
9
  PortDeclarationDirection,
@@ -16,18 +12,16 @@ from classiq.interface.model.handle_binding import HandleBinding
16
12
  from classiq.interface.model.model import Model, SerializedModel
17
13
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
18
14
  from classiq.interface.model.port_declaration import PortDeclaration
19
- from classiq.interface.model.quantum_function_call import (
20
- QuantumFunctionCall,
21
- QuantumLambdaFunction,
22
- )
15
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
16
+ from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
23
17
  from classiq.interface.model.variable_declaration_statement import (
24
18
  VariableDeclarationStatement,
25
19
  )
26
20
 
27
- from classiq.applications_model_constructors.libraries.ampltitude_estimation_library import (
21
+ from classiq.applications.libraries.ampltitude_estimation_library import (
28
22
  AE_CLASSICAL_LIBRARY,
29
23
  )
30
- from classiq.applications_model_constructors.libraries.qmci_library import QMCI_LIBRARY
24
+ from classiq.applications.libraries.qmci_library import QMCI_LIBRARY
31
25
  from classiq.exceptions import ClassiqError
32
26
 
33
27
  _OUTPUT_VARIABLE_NAME = "result"
@@ -56,13 +50,6 @@ def construct_finance_model(
56
50
  else:
57
51
  raise ClassiqError(f"Invalid model input: {finance_model_input}")
58
52
 
59
- if isinstance(finance_function_input.f, FinanceFunctionType):
60
- finance_function_f = finance_function_input.f
61
- elif isinstance(finance_function_input.f, str):
62
- finance_function_f = FINANCE_FUNCTION_STRING[finance_function_input.f]
63
- else:
64
- finance_function_f = FinanceFunctionType(finance_function_input.f)
65
-
66
53
  polynomial_degree = 0
67
54
  if finance_function_input.polynomial_degree is not None:
68
55
  polynomial_degree = finance_function_input.polynomial_degree
@@ -71,7 +58,7 @@ def construct_finance_model(
71
58
  if finance_function_input.tail_probability is not None:
72
59
  tail_probability = finance_function_input.tail_probability
73
60
 
74
- finance_function_object = f"struct_literal(FinanceFunction, f={finance_function_f}, threshold={finance_function_input.condition.threshold}, larger={finance_function_input.condition.larger}, polynomial_degree={polynomial_degree}, use_chebyshev_polynomial_approximation={finance_function_input.use_chebyshev_polynomial_approximation}, tail_probability={tail_probability})"
61
+ finance_function_object = f"struct_literal(FinanceFunction, f={finance_function_input.f}, threshold={finance_function_input.condition.threshold}, larger={finance_function_input.condition.larger}, polynomial_degree={polynomial_degree}, use_chebyshev_polynomial_approximation={finance_function_input.use_chebyshev_polynomial_approximation}, tail_probability={tail_probability})"
75
62
  num_unitary_qubits = total_num_qubits + 1
76
63
 
77
64
  model = Model(
@@ -88,16 +75,26 @@ def construct_finance_model(
88
75
  },
89
76
  body=[
90
77
  VariableDeclarationStatement(name="unitary_port"),
78
+ QuantumFunctionCall(
79
+ function="allocate",
80
+ positional_args=[
81
+ Expression(expr=f"{num_unitary_qubits}"),
82
+ HandleBinding(name="unitary_port"),
83
+ ],
84
+ ),
85
+ QuantumFunctionCall(
86
+ function="allocate_num",
87
+ positional_args=[
88
+ Expression(expr=f"{phase_port_size}"),
89
+ Expression(expr="False"),
90
+ Expression(expr=f"{phase_port_size}"),
91
+ HandleBinding(name="phase_port"),
92
+ ],
93
+ ),
91
94
  QuantumFunctionCall(
92
95
  function="qmci",
93
- params={
94
- "num_unitary_qubits": Expression(
95
- expr=f"{num_unitary_qubits}"
96
- ),
97
- "num_phase_qubits": Expression(expr=f"{phase_port_size}"),
98
- },
99
96
  operands={
100
- "sp_op": QuantumLambdaFunction(
97
+ "space_transform": QuantumLambdaFunction(
101
98
  body=[
102
99
  QuantumFunctionCall(
103
100
  function=finance_function,
@@ -110,16 +107,16 @@ def construct_finance_model(
110
107
  ),
111
108
  },
112
109
  inouts={
113
- "func_port": HandleBinding(name="reg"),
114
- "obj_port": HandleBinding(name="ind"),
110
+ "func_port": HandleBinding(name="arg0"),
111
+ "obj_port": HandleBinding(name="arg1"),
115
112
  },
116
113
  ),
117
114
  ],
118
115
  ),
119
116
  },
120
- outputs={
121
- "phase_port": HandleBinding(name="phase_port"),
122
- "unitary_port": HandleBinding(name="unitary_port"),
117
+ inouts={
118
+ "phase": HandleBinding(name="phase_port"),
119
+ "packed_vars": HandleBinding(name="unitary_port"),
123
120
  },
124
121
  ),
125
122
  ],
@@ -0,0 +1,11 @@
1
+ from typing import List
2
+
3
+ from .grover_model_constructor import construct_grover_model
4
+
5
+ __all__ = [
6
+ "construct_grover_model",
7
+ ]
8
+
9
+
10
+ def __dir__() -> List[str]:
11
+ return __all__