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
@@ -10,16 +10,13 @@ import plotly.graph_objects as go
10
10
 
11
11
  from classiq.interface.analyzer import analysis_params
12
12
  from classiq.interface.backend.quantum_backend_providers import AnalyzerProviderVendor
13
- from classiq.interface.generator import generated_circuit as generator_result
13
+ from classiq.interface.generator import quantum_program as generator_result
14
14
 
15
- from classiq._internals import client
15
+ from classiq._internals import async_utils, client
16
16
  from classiq._internals.api_wrapper import ApiWrapper
17
- from classiq._internals.async_utils import Asyncify
18
17
  from classiq.analyzer.analyzer_utilities import (
19
18
  AnalyzerUtilities,
20
19
  DeviceName,
21
- HardwareGraphs,
22
- ProviderAvailableDevices,
23
20
  ProviderNameEnum,
24
21
  )
25
22
  from classiq.analyzer.url_utils import circuit_page_uri, client_ide_base_url
@@ -34,10 +31,10 @@ if find_ipywidgets is not None:
34
31
  from classiq._analyzer_extras.interactive_hardware import InteractiveHardware
35
32
 
36
33
 
37
- class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
34
+ class Analyzer(AnalyzerUtilities):
38
35
  """Analyzer is the wrapper object for all analysis capabilities."""
39
36
 
40
- def __init__(self, circuit: generator_result.GeneratedCircuit) -> None:
37
+ def __init__(self, circuit: generator_result.QuantumProgram) -> None:
41
38
  """Init self.
42
39
 
43
40
  Args:
@@ -47,26 +44,31 @@ class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
47
44
  raise ClassiqAnalyzerError(
48
45
  "Analysis requires a circuit with valid QASM code"
49
46
  )
50
- self._params: analysis_params.AnalysisParams = analysis_params.AnalysisParams(
47
+ params: analysis_params.AnalysisParams = analysis_params.AnalysisParams(
51
48
  qasm=circuit.qasm
52
49
  )
53
- self.circuit: generator_result.GeneratedCircuit = circuit
50
+ super().__init__(
51
+ params=params,
52
+ circuit=circuit,
53
+ available_devices=dict(),
54
+ hardware_graphs=dict(),
55
+ )
56
+
54
57
  self.hardware_comparison_table: Optional[go.Figure] = None
55
- self.available_devices: ProviderAvailableDevices = dict()
56
- self.hardware_graphs: HardwareGraphs = dict()
57
58
 
58
59
  self.transpilation_params = analysis_params.AnalysisHardwareTranspilationParams(
59
60
  hardware_data=self.circuit.hardware_data,
60
- model_preferences=self.circuit.model.preferences,
61
+ random_seed=self.circuit.model.execution_preferences.random_seed,
62
+ transpilation_option=self.circuit.model.execution_preferences.transpile_to_hardware,
61
63
  )
62
64
 
63
- async def analyzer_app_async(self) -> None:
65
+ def analyzer_app(self) -> None:
64
66
  """Opens the analyzer app with synthesis interactive results.
65
67
 
66
68
  Returns:
67
69
  None.
68
70
  """
69
- result = await ApiWrapper.call_analyzer_app(self.circuit)
71
+ result = async_utils.run(ApiWrapper.call_analyzer_app(self.circuit))
70
72
  webbrowser.open_new_tab(
71
73
  urljoin(
72
74
  client_ide_base_url(),
@@ -76,10 +78,12 @@ class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
76
78
  )
77
79
  )
78
80
 
79
- async def get_available_devices_async(
81
+ def get_available_devices(
80
82
  self, providers: Optional[List[ProviderNameEnum]] = None
81
83
  ) -> Dict[ProviderNameEnum, List[DeviceName]]:
82
- """Returns dict of the available devices by the providers. only devices
84
+ """Deprecated. Use get_all_hardware_devices instead.
85
+
86
+ Returns dict of the available devices by the providers. only devices
83
87
  with sufficient number of qubits are returns
84
88
 
85
89
  Args: providers (): List of providers (string or `AnalyzerProviderVendor`).
@@ -90,13 +94,13 @@ class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
90
94
  """
91
95
  if providers is None:
92
96
  providers = list(AnalyzerProviderVendor)
93
- await self.request_available_devices_async(providers=providers)
97
+ async_utils.run(self._request_available_devices_async(providers=providers))
94
98
  return {
95
99
  provider: self._filter_devices_by_qubits_count(provider)
96
100
  for provider in providers
97
101
  }
98
102
 
99
- async def plot_hardware_connectivity_async(
103
+ def plot_hardware_connectivity(
100
104
  self,
101
105
  provider: Optional[ProviderNameEnum] = None,
102
106
  device: Optional[DeviceName] = None,
@@ -118,7 +122,7 @@ class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
118
122
  available_devices=self.available_devices,
119
123
  hardware_graphs=self.hardware_graphs,
120
124
  )
121
- await interactive_hardware.enable_interactivity_async()
125
+ async_utils.run(interactive_hardware.enable_interactivity_async())
122
126
  if provider is not None:
123
127
  interactive_hardware.providers_combobox.value = provider
124
128
  if device is not None:
@@ -126,7 +130,7 @@ class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
126
130
 
127
131
  return interactive_hardware.show_interactive_graph()
128
132
 
129
- async def get_hardware_comparison_table_async(
133
+ def get_hardware_comparison_table(
130
134
  self,
131
135
  providers: Optional[Sequence[Union[str, AnalyzerProviderVendor]]] = None,
132
136
  devices: Optional[List[str]] = None,
@@ -148,10 +152,10 @@ class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
148
152
  devices=devices,
149
153
  transpilation_params=self.transpilation_params,
150
154
  )
151
- result = await ApiWrapper.call_table_graphs_task(params=params)
155
+ result = async_utils.run(ApiWrapper.call_table_graphs_task(params=params))
152
156
  self.hardware_comparison_table = go.Figure(json.loads(result.details))
153
157
 
154
- async def plot_hardware_comparison_table_async(
158
+ def plot_hardware_comparison_table(
155
159
  self,
156
160
  providers: Optional[List[Union[str, AnalyzerProviderVendor]]] = None,
157
161
  devices: Optional[List[str]] = None,
@@ -162,12 +166,10 @@ class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
162
166
  Returns:
163
167
  None.
164
168
  """
165
- await self._hardware_comparison_condition_async(
166
- providers=providers, devices=devices
167
- )
169
+ self._hardware_comparison_condition(providers=providers, devices=devices)
168
170
  self.hardware_comparison_table.show() # type: ignore[union-attr]
169
171
 
170
- async def _hardware_comparison_condition_async(
172
+ def _hardware_comparison_condition(
171
173
  self,
172
174
  providers: Optional[Sequence[Union[str, AnalyzerProviderVendor]]] = None,
173
175
  devices: Optional[List[str]] = None,
@@ -177,9 +179,7 @@ class Analyzer(AnalyzerUtilities, metaclass=Asyncify):
177
179
  or devices is not None
178
180
  or self.hardware_comparison_table is None
179
181
  ):
180
- await self.get_hardware_comparison_table_async(
181
- providers=providers, devices=devices
182
- )
182
+ self.get_hardware_comparison_table(providers=providers, devices=devices)
183
183
 
184
184
  @staticmethod
185
185
  def _open_route(path: str) -> None:
@@ -2,7 +2,7 @@ from typing import Dict, List, Union
2
2
 
3
3
  from classiq.interface.analyzer import analysis_params
4
4
  from classiq.interface.backend.quantum_backend_providers import AnalyzerProviderVendor
5
- from classiq.interface.generator.generated_circuit import GeneratedCircuit
5
+ from classiq.interface.generator.quantum_program import QuantumProgram
6
6
 
7
7
  from classiq._internals.api_wrapper import ApiWrapper
8
8
  from classiq.exceptions import ClassiqAnalyzerError
@@ -22,16 +22,16 @@ class AnalyzerUtilities:
22
22
  def __init__(
23
23
  self,
24
24
  params: analysis_params.AnalysisParams,
25
- circuit: GeneratedCircuit,
25
+ circuit: QuantumProgram,
26
26
  available_devices: ProviderAvailableDevices,
27
27
  hardware_graphs: HardwareGraphs,
28
28
  ) -> None:
29
29
  self._params: analysis_params.AnalysisParams = params
30
- self.circuit: GeneratedCircuit = circuit
30
+ self.circuit: QuantumProgram = circuit
31
31
  self.available_devices = available_devices
32
32
  self.hardware_graphs = hardware_graphs
33
33
 
34
- async def request_available_devices_async(
34
+ async def _request_available_devices_async(
35
35
  self, providers: List[ProviderNameEnum]
36
36
  ) -> None:
37
37
  requested_providers = self._requested_providers_filter(providers)
@@ -58,7 +58,7 @@ class AnalyzerUtilities:
58
58
  async def _device_validation_async(
59
59
  self, provider: ProviderNameEnum, device: DeviceName
60
60
  ) -> None:
61
- await self.request_available_devices_async(providers=[provider])
61
+ await self._request_available_devices_async(providers=[provider])
62
62
  provider_lower_name = _to_lower_case(provider)
63
63
  available_device_dict = self.available_devices
64
64
  if available_device_dict[provider_lower_name].get(device) is False:
classiq/analyzer/rb.py CHANGED
@@ -10,12 +10,11 @@ from classiq.interface.analyzer.analysis_params import AnalysisRBParams
10
10
  from classiq.interface.analyzer.result import RbResults
11
11
 
12
12
  from classiq._internals.api_wrapper import ApiWrapper
13
- from classiq._internals.async_utils import Asyncify
14
13
  from classiq.exceptions import ClassiqAnalyzerError
15
14
  from classiq.executor import BackendPreferencesAndResult
16
15
 
17
16
 
18
- class RBAnalysis(metaclass=Asyncify):
17
+ class RBAnalysis:
19
18
  def __init__(self, experiments_data: List[AnalysisRBParams]) -> None:
20
19
  """Init self.
21
20
 
@@ -67,9 +66,9 @@ class RBAnalysis(metaclass=Asyncify):
67
66
  df = self._total_results.loc[["mean_fidelity", "average_error"]].transpose()
68
67
  hardware = list(df.index)
69
68
  params = list(df.columns)
70
- data = []
71
- for param in params:
72
- data.append(go.Bar(name=param, x=hardware, y=df[param].values * 100))
69
+ data = [
70
+ go.Bar(name=param, x=hardware, y=df[param].values * 100) for param in params
71
+ ]
73
72
  fig = go.Figure(data).update_layout(
74
73
  title="RB hardware comparison",
75
74
  barmode="group",
@@ -1,26 +1,26 @@
1
1
  import webbrowser
2
2
  from urllib.parse import urljoin
3
3
 
4
- from classiq.interface.generator.generated_circuit import GeneratedCircuit
4
+ from classiq.interface.generator.quantum_program import QuantumProgram
5
5
 
6
6
  from classiq._internals.api_wrapper import ApiWrapper
7
7
  from classiq._internals.async_utils import syncify_function
8
8
  from classiq.analyzer.url_utils import circuit_page_uri, client_ide_base_url
9
9
 
10
10
 
11
- async def handle_remote_app(circuit: GeneratedCircuit) -> None:
11
+ async def handle_remote_app(circuit: QuantumProgram) -> None:
12
12
  circuit_dataid = await ApiWrapper.call_analyzer_app(circuit)
13
13
  app_url = urljoin(
14
14
  client_ide_base_url(),
15
15
  circuit_page_uri(circuit_id=circuit_dataid.id, circuit_version=circuit.version),
16
16
  )
17
- print(f"Opening: {app_url}")
17
+ print(f"Opening: {app_url}") # noqa: T201
18
18
  webbrowser.open_new_tab(app_url)
19
19
 
20
20
 
21
- async def _show_interactive(self: GeneratedCircuit) -> None:
21
+ async def _show_interactive(self: QuantumProgram) -> None:
22
22
  await handle_remote_app(circuit=self)
23
23
 
24
24
 
25
- GeneratedCircuit.show = syncify_function(_show_interactive) # type: ignore[attr-defined]
26
- GeneratedCircuit.show_async = _show_interactive # type: ignore[attr-defined]
25
+ QuantumProgram.show = syncify_function(_show_interactive) # type: ignore[attr-defined]
26
+ QuantumProgram.show_async = _show_interactive # type: ignore[attr-defined]
@@ -1,15 +1,8 @@
1
1
  from typing import List
2
2
 
3
- from classiq.applications import (
4
- benchmarking,
5
- chemistry,
6
- combinatorial_optimization,
7
- finance,
8
- qsvm,
9
- )
3
+ from classiq.applications import chemistry, combinatorial_optimization, finance, qsvm
10
4
 
11
5
  __all__ = [
12
- "benchmarking",
13
6
  "combinatorial_optimization",
14
7
  "chemistry",
15
8
  "finance",
@@ -15,6 +15,10 @@ from classiq.interface.chemistry.operator import PauliOperator, PauliOperators
15
15
  from . import ground_state_problem
16
16
  from .ansatz_parameters import HEAParameters, HVAParameters, UCCParameters
17
17
  from .chemistry_execution_parameters import ChemistryExecutionParameters
18
+ from .chemistry_model_constructor import (
19
+ construct_chemistry_model,
20
+ molecule_problem_to_qmod,
21
+ )
18
22
 
19
23
  __all__ = [
20
24
  "Molecule",
@@ -29,6 +33,8 @@ __all__ = [
29
33
  "HVAParameters",
30
34
  "HEAParameters",
31
35
  "ChemistryExecutionParameters",
36
+ "construct_chemistry_model",
37
+ "molecule_problem_to_qmod",
32
38
  ]
33
39
 
34
40
 
@@ -30,10 +30,8 @@ from classiq.interface.model.handle_binding import HandleBinding
30
30
  from classiq.interface.model.model import Model, SerializedModel
31
31
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
32
32
  from classiq.interface.model.port_declaration import PortDeclaration
33
- from classiq.interface.model.quantum_function_call import (
34
- QuantumFunctionCall,
35
- QuantumLambdaFunction,
36
- )
33
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
34
+ from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
37
35
 
38
36
  from classiq.applications.chemistry.ansatz_parameters import (
39
37
  AnsatzParameters,
@@ -219,7 +217,7 @@ def _atoms_to_qmod_atoms(atoms: List[Atom]) -> str:
219
217
  return ",".join(atom_struct_literals)
220
218
 
221
219
 
222
- def _molecule_problem_to_qmod_molecule_problem(
220
+ def molecule_problem_to_qmod(
223
221
  molecule_problem: MoleculeProblem,
224
222
  ) -> str:
225
223
  # fmt: off
@@ -288,7 +286,7 @@ def _hamiltonian_problem_to_qmod_fock_hamiltonian_problem(
288
286
 
289
287
  def _convert_library_problem_to_qmod_problem(problem: CHEMISTRY_PROBLEMS_TYPE) -> str:
290
288
  if isinstance(problem, MoleculeProblem):
291
- return _molecule_problem_to_qmod_molecule_problem(problem)
289
+ return molecule_problem_to_qmod(problem)
292
290
  elif isinstance(problem, HamiltonianProblem):
293
291
  return _hamiltonian_problem_to_qmod_fock_hamiltonian_problem(problem)
294
292
  else:
@@ -305,10 +303,10 @@ def _get_chemistry_function(
305
303
  return QuantumFunctionCall(
306
304
  function=f"{problem_prefix}_{chemistry_function_name}",
307
305
  params={
308
- **(ansatz_parameters_expressions or dict()),
309
306
  f"{problem_prefix}_problem": Expression(
310
307
  expr=_convert_library_problem_to_qmod_problem(chemistry_problem)
311
308
  ),
309
+ **(ansatz_parameters_expressions or dict()),
312
310
  },
313
311
  inouts=inouts,
314
312
  )
@@ -332,11 +330,11 @@ def _get_hea_function(hea_parameters: HEAParameters) -> QuantumFunctionCall:
332
330
  "is_parametrized": Expression(
333
331
  expr=f"{[int(_is_parametric_gate(_HAE_GATE_MAPPING[gate])) for gate in hea_parameters.one_qubit_gates+hea_parameters.two_qubit_gates]}"
334
332
  ),
333
+ "angle_params": Expression(expr="t"),
335
334
  "connectivity_map": Expression(
336
335
  expr=f"{[list(connectivity_pair) for connectivity_pair in hea_parameters.connectivity_map]}"
337
336
  ),
338
337
  "reps": Expression(expr=f"{hea_parameters.reps}"),
339
- "angle_params": Expression(expr="t"),
340
338
  },
341
339
  operands={
342
340
  "operands_1qubit": [
@@ -387,17 +385,11 @@ def _get_molecule_problem_execution_post_processing(
387
385
  molecule_problem: MoleculeProblem,
388
386
  ) -> str:
389
387
  return f"""
390
- {_MOLECULE_PROBLEM_RESULT} = molecule_ground_state_solution_post_process({_molecule_problem_to_qmod_molecule_problem(molecule_problem)},{_EXECUTION_RESULT})
388
+ {_MOLECULE_PROBLEM_RESULT} = molecule_ground_state_solution_post_process({molecule_problem_to_qmod(molecule_problem)},{_EXECUTION_RESULT})
391
389
  save({{{_MOLECULE_PROBLEM_RESULT!r}: {_MOLECULE_PROBLEM_RESULT}}})
392
390
  """
393
391
 
394
392
 
395
- def _get_fock_hamiltonian_problem_execution_post_processing(
396
- hamiltonian_problem: HamiltonianProblem,
397
- ) -> str:
398
- return f"save({{{_EXECUTION_RESULT!r}: {_EXECUTION_RESULT}}})"
399
-
400
-
401
393
  def _is_parametric_gate(call: QuantumFunctionCall) -> bool:
402
394
  return len(call.params) > 0
403
395
 
@@ -408,7 +400,7 @@ def _get_execution_result_post_processing_statements(
408
400
  if isinstance(problem, MoleculeProblem):
409
401
  return _get_molecule_problem_execution_post_processing(problem)
410
402
  elif isinstance(problem, HamiltonianProblem):
411
- return _get_fock_hamiltonian_problem_execution_post_processing(problem)
403
+ return ""
412
404
  else:
413
405
  raise ClassiqError(f"Invalid problem type: {problem}")
414
406
 
@@ -488,6 +480,7 @@ def _get_chemistry_classical_code(
488
480
  {_EXECUTION_RESULT} = vqe(
489
481
  hamiltonian={_get_problem_to_hamiltonian_name(chemistry_problem)}({qmod_problem}), {_get_chemistry_vqe_additional_params(execution_parameters)}
490
482
  )
483
+ save({{{_EXECUTION_RESULT!r}: {_EXECUTION_RESULT}}})
491
484
  """ + _get_execution_result_post_processing_statements(
492
485
  chemistry_problem
493
486
  )
@@ -0,0 +1,20 @@
1
+ from typing import Optional
2
+
3
+ from sympy import Add, Expr, LessThan, Symbol
4
+
5
+ from classiq.interface.combinatorial_optimization.encoding_types import EncodingType
6
+
7
+ _INEQUALITY_UPPER_LIMIT = 1
8
+
9
+
10
+ def is_constraint_sum_less_than_one(
11
+ expression: Expr, encoding_type: Optional[EncodingType] = None
12
+ ) -> bool:
13
+ # tests the case: x_1 + ... + x_n <= 1
14
+ return (
15
+ isinstance(expression, LessThan)
16
+ and isinstance(expression.args[0], Add)
17
+ and all(isinstance(arg, Symbol) for arg in expression.args[0].args)
18
+ and expression.args[1] == _INEQUALITY_UPPER_LIMIT
19
+ and encoding_type is None
20
+ )
@@ -0,0 +1,35 @@
1
+ from typing import Any
2
+
3
+ import sympy
4
+ from pyomo.core.expr.sympy_tools import PyomoSympyBimap
5
+ from scipy.optimize import differential_evolution
6
+ from sympy import Expr
7
+
8
+ from classiq.applications.combinatorial_helpers import encoding_utils
9
+
10
+
11
+ def sympy_lambdify(*args: Any, **kwargs: Any) -> Any:
12
+ new_kwargs = kwargs
13
+ new_kwargs["modules"] = ["sympy"]
14
+ return sympy.lambdify(*args, **new_kwargs)
15
+
16
+
17
+ def multivariate_extremum(
18
+ expr: Expr, symbols_map: PyomoSympyBimap, is_min: bool
19
+ ) -> float:
20
+ if expr.is_number:
21
+ return float(expr)
22
+
23
+ free_symbols = tuple(expr.free_symbols)
24
+ bounds = [
25
+ (0, encoding_utils.get_var_span(symbols_map.sympy2pyomo[sym]))
26
+ for sym in free_symbols
27
+ ]
28
+
29
+ # differential_evolution finds the global minimum, where we looking for the minimum or the maximum
30
+ extremum_type_coeff = 1 if is_min else -1
31
+
32
+ # Should be used only with sanitized imports due to use could be a potential risk to exec function https://docs.sympy.org/latest/modules/utilities/lambdify.html
33
+ func = sympy_lambdify([free_symbols], expr=extremum_type_coeff * expr)
34
+ result = differential_evolution(func, bounds)
35
+ return result.fun * extremum_type_coeff
@@ -0,0 +1,42 @@
1
+ from sympy import Eq, Expr, GreaterThan, LessThan, Rational, Symbol, solve
2
+ from sympy.core.relational import Relational
3
+
4
+ from classiq.exceptions import ClassiqCombOptNoSolutionError
5
+
6
+
7
+ def isolate(expression: Expr, var: Symbol) -> Expr:
8
+ isolated_exp = solve(expression, var)
9
+ # This converts Rationals to Floats which is needed since we don't support division in arithmetic
10
+ if isinstance(isolated_exp, Relational) and _has_rational_atom(isolated_exp):
11
+ isolated_exp = isolated_exp.evalf()
12
+
13
+ if isinstance(expression, Eq):
14
+ if len(isolated_exp) == 1:
15
+ isolated_exp = type(expression)(var, isolated_exp[0])
16
+ elif len(isolated_exp) > 1:
17
+ # sympy didn't manage to isolate an expression
18
+ isolated_exp = expression
19
+ else:
20
+ raise ClassiqCombOptNoSolutionError
21
+
22
+ else:
23
+ if _is_symbol_in_right_hand_side(isolated_exp):
24
+ isolated_exp = _reverse_ineq_exp(isolated_exp)
25
+
26
+ return isolated_exp
27
+
28
+
29
+ def _has_rational_atom(expression: Relational) -> bool:
30
+ return any(type(atom) is Rational for atom in expression.atoms())
31
+
32
+
33
+ def _is_symbol_in_right_hand_side(expression: Expr) -> bool:
34
+ return isinstance(expression.args[1], Symbol) and not isinstance(
35
+ expression.args[0], Symbol
36
+ )
37
+
38
+
39
+ def _reverse_ineq_exp(expression: Expr) -> Expr:
40
+ original_relation = type(expression)
41
+ reverse_relation = LessThan if original_relation is GreaterThan else GreaterThan
42
+ return reverse_relation(expression.args[1], expression.args[0])
@@ -0,0 +1,150 @@
1
+ import itertools
2
+ from typing import List, Union, cast
3
+
4
+ import numpy as np
5
+ import pyomo.environ as pyo
6
+
7
+ from classiq.interface.combinatorial_optimization.sense import is_maximization
8
+ from classiq.interface.combinatorial_optimization.solver_types import QSolver
9
+ from classiq.interface.executor.vqe_result import VQESolverResult
10
+ from classiq.interface.generator.functions.qmod_python_interface import QmodPyStruct
11
+
12
+ from classiq.applications.combinatorial_helpers.optimization_model import (
13
+ OptimizationModel,
14
+ )
15
+ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_sparsing import (
16
+ SparsePauliOp,
17
+ )
18
+ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import (
19
+ PauliTerm,
20
+ get_pauli_operator,
21
+ pauli_operator_to_hamiltonian,
22
+ pauli_string_to_int,
23
+ )
24
+ from classiq.applications.combinatorial_helpers.pyomo_utils import (
25
+ convert_pyomo_to_global_presentation,
26
+ )
27
+
28
+
29
+ def compute_qaoa_initial_point(
30
+ hamiltonian: List[QmodPyStruct],
31
+ repetitions: int,
32
+ ) -> List[float]:
33
+ coeffs_ising = [pauli_term["coefficient"] for pauli_term in hamiltonian[1:]]
34
+ # the first coeff is the II...I term
35
+ coeffs_abs = np.abs(coeffs_ising)
36
+ coeffs_largest = np.sort(coeffs_abs)[len(coeffs_ising) // 2 :]
37
+ operator_norm = np.mean(coeffs_largest)
38
+ time_step = 1 / (2 * operator_norm) # adapted such that for MAXCUT time_step = 1
39
+
40
+ beta_params: np.ndarray = np.linspace(1, 0, repetitions) * time_step
41
+ gamma_params: np.ndarray = np.linspace(0, 1, repetitions) * time_step
42
+ return list(itertools.chain(*zip(gamma_params, beta_params)))
43
+
44
+
45
+ def _internal_pyo_model_to_hamiltonian(
46
+ pyo_model: pyo.ConcreteModel, penalty_energy: float
47
+ ) -> List[QmodPyStruct]:
48
+ pauli_list = OptimizationModel(
49
+ pyo_model, penalty_energy=penalty_energy, qsolver=QSolver.QAOAPenalty
50
+ ).ising.pauli_list
51
+ return pauli_operator_to_hamiltonian(pauli_list)
52
+
53
+
54
+ def pyo_model_to_hamiltonian(
55
+ pyo_model: pyo.ConcreteModel, penalty_energy: float
56
+ ) -> List[PauliTerm]:
57
+ hamiltonian = _internal_pyo_model_to_hamiltonian(pyo_model, penalty_energy)
58
+ pauli_operator = get_pauli_operator(hamiltonian).pauli_list
59
+ pauli_terms = []
60
+ for item in pauli_operator:
61
+ term = PauliTerm()
62
+ term.pauli, term.coefficient = (
63
+ pauli_string_to_int(item[0]),
64
+ cast(complex, item[1]).real,
65
+ )
66
+ pauli_terms.append(term)
67
+
68
+ return pauli_terms
69
+
70
+
71
+ def _str_to_list_int(str_ints: str) -> List[int]:
72
+ return list(map(int, list(str_ints)))
73
+
74
+
75
+ def _decode_vector_str(
76
+ optimization_model: OptimizationModel, vector_str: str
77
+ ) -> List[int]:
78
+ return optimization_model.decode(
79
+ _str_to_list_int(vector_str[::-1])
80
+ ) # reverse qubit order
81
+
82
+
83
+ def _evaluate_operator(operator: SparsePauliOp, state: Union[List[int], str]) -> float:
84
+ if isinstance(state, list):
85
+ state = "".join([str(x) for x in state])
86
+
87
+ cost = 0.0
88
+ for pauli, coeff in zip(operator.paulis, operator.coeffs):
89
+ expectation = 1
90
+ for qubit, pauli_char in enumerate(pauli):
91
+ if pauli_char != "I" and state[qubit] == "1" and pauli_char in ["Z", "Y"]:
92
+ expectation *= -1
93
+ cost += expectation * coeff.real
94
+
95
+ return cost
96
+
97
+
98
+ def _eigenstate_to_solution(
99
+ optimization_model: OptimizationModel,
100
+ eigenvector: str,
101
+ probability: float,
102
+ num_shots: int,
103
+ ) -> QmodPyStruct:
104
+ pauli = optimization_model.get_operator().pauli_list
105
+
106
+ paulis = [item[0] for item in pauli]
107
+ coeffs = [item[1] for item in pauli]
108
+
109
+ operator = SparsePauliOp(paulis, coeffs)
110
+ cost = _evaluate_operator(operator, eigenvector)
111
+
112
+ if is_maximization(optimization_model._model_original):
113
+ cost *= -1
114
+
115
+ return {
116
+ "probability": probability,
117
+ "cost": cost,
118
+ "solution": _decode_vector_str(optimization_model, eigenvector),
119
+ "count": round(probability * num_shots),
120
+ }
121
+
122
+
123
+ def _get_combi_solution_histogram(
124
+ optimization_model: OptimizationModel,
125
+ vqe_result: VQESolverResult,
126
+ ) -> List[QmodPyStruct]:
127
+ if vqe_result.reduced_probabilities is None:
128
+ raise ValueError(
129
+ "reduced_probabilities is optional only for backwards compatibility, but it should always be present here"
130
+ )
131
+ return [
132
+ _eigenstate_to_solution(
133
+ optimization_model, eigenvector, probability, vqe_result.num_shots
134
+ )
135
+ for eigenvector, probability in vqe_result.reduced_probabilities.items()
136
+ ]
137
+
138
+
139
+ def get_optimization_solution_from_pyo(
140
+ pyo_model: pyo.ConcreteModel,
141
+ vqe_result: VQESolverResult,
142
+ penalty_energy: float,
143
+ ) -> List[QmodPyStruct]:
144
+ converted_pyo_model = convert_pyomo_to_global_presentation(pyo_model)
145
+ optimization_model = OptimizationModel(
146
+ converted_pyo_model, penalty_energy=penalty_energy, qsolver=QSolver.QAOAPenalty
147
+ )
148
+ histogram = _get_combi_solution_histogram(optimization_model, vqe_result)
149
+ histogram.sort(key=lambda x: x["probability"], reverse=True)
150
+ return histogram