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.
- classiq/__init__.py +23 -24
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +1 -1
- classiq/_analyzer_extras/interactive_hardware.py +3 -3
- classiq/_internals/api_wrapper.py +37 -17
- classiq/_internals/async_utils.py +1 -74
- classiq/_internals/authentication/device.py +9 -4
- classiq/_internals/authentication/password_manager.py +25 -10
- classiq/_internals/authentication/token_manager.py +2 -2
- classiq/_internals/client.py +24 -6
- classiq/_internals/jobs.py +10 -7
- classiq/analyzer/analyzer.py +29 -29
- classiq/analyzer/analyzer_utilities.py +5 -5
- classiq/analyzer/rb.py +4 -5
- classiq/analyzer/show_interactive_hack.py +6 -6
- classiq/applications/__init__.py +1 -8
- classiq/applications/chemistry/__init__.py +6 -0
- classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +9 -16
- classiq/applications/combinatorial_helpers/allowed_constraints.py +20 -0
- classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
- classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +150 -0
- classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
- classiq/applications/combinatorial_helpers/encoding_utils.py +122 -0
- classiq/applications/combinatorial_helpers/memory.py +77 -0
- classiq/applications/combinatorial_helpers/optimization_model.py +162 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +75 -0
- classiq/applications/combinatorial_helpers/py.typed +0 -0
- classiq/applications/combinatorial_helpers/pyomo_utils.py +245 -0
- classiq/applications/combinatorial_helpers/solvers/__init__.py +0 -0
- classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
- classiq/applications/combinatorial_helpers/transformations/__init__.py +0 -0
- classiq/applications/combinatorial_helpers/transformations/encoding.py +187 -0
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +142 -0
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +122 -0
- classiq/applications/combinatorial_helpers/transformations/penalty.py +32 -0
- classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
- classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +75 -0
- classiq/applications/combinatorial_helpers/transformations/slack_variables.py +88 -0
- classiq/applications/combinatorial_optimization/__init__.py +13 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +134 -0
- classiq/applications/finance/__init__.py +3 -2
- classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +27 -30
- classiq/applications/grover/__init__.py +11 -0
- classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +20 -91
- classiq/applications/libraries/__init__.py +0 -0
- classiq/applications/libraries/qmci_library.py +35 -0
- classiq/applications/qnn/circuit_utils.py +2 -2
- classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
- classiq/applications/qnn/types.py +2 -2
- classiq/applications/qsvm/__init__.py +5 -1
- classiq/applications/qsvm/qsvm.py +4 -7
- classiq/applications/qsvm/qsvm_data_generation.py +2 -5
- classiq/exceptions.py +43 -1
- classiq/execution/all_hardware_devices.py +13 -0
- classiq/executor.py +12 -10
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +6 -3
- classiq/interface/analyzer/result.py +12 -8
- classiq/interface/applications/qsvm.py +17 -3
- classiq/interface/ast_node.py +23 -0
- classiq/interface/backend/backend_preferences.py +4 -2
- classiq/interface/backend/pydantic_backend.py +3 -1
- classiq/interface/backend/quantum_backend_providers.py +1 -0
- classiq/interface/chemistry/fermionic_operator.py +15 -13
- classiq/interface/chemistry/ground_state_problem.py +18 -3
- classiq/interface/chemistry/molecule.py +8 -6
- classiq/interface/chemistry/operator.py +20 -14
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -1
- classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -2
- classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
- classiq/interface/combinatorial_optimization/examples/mht.py +8 -3
- classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
- classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
- classiq/interface/combinatorial_optimization/examples/set_cover.py +2 -1
- classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +9 -3
- classiq/interface/executor/aws_execution_cost.py +4 -3
- classiq/interface/executor/estimation.py +2 -2
- classiq/interface/executor/execution_preferences.py +5 -34
- classiq/interface/executor/execution_request.py +15 -48
- classiq/interface/executor/optimizer_preferences.py +22 -13
- classiq/interface/executor/{quantum_program.py → quantum_code.py} +21 -15
- classiq/interface/executor/quantum_instruction_set.py +2 -1
- classiq/interface/executor/register_initialization.py +1 -3
- classiq/interface/executor/result.py +41 -10
- classiq/interface/executor/vqe_result.py +2 -2
- classiq/interface/finance/function_input.py +17 -4
- classiq/interface/finance/gaussian_model_input.py +3 -1
- classiq/interface/finance/log_normal_model_input.py +3 -1
- classiq/interface/finance/model_input.py +2 -0
- classiq/interface/generator/amplitude_loading.py +6 -3
- classiq/interface/generator/application_apis/__init__.py +1 -0
- classiq/interface/generator/application_apis/arithmetic_declarations.py +14 -0
- classiq/interface/generator/arith/argument_utils.py +14 -4
- classiq/interface/generator/arith/arithmetic.py +3 -1
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +12 -13
- classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -1
- classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -2
- classiq/interface/generator/arith/arithmetic_expression_validator.py +16 -2
- classiq/interface/generator/arith/arithmetic_operations.py +5 -10
- classiq/interface/generator/arith/ast_node_rewrite.py +1 -1
- classiq/interface/generator/arith/binary_ops.py +202 -54
- classiq/interface/generator/arith/extremum_operations.py +5 -3
- classiq/interface/generator/arith/logical_ops.py +4 -2
- classiq/interface/generator/arith/machine_precision.py +3 -0
- classiq/interface/generator/arith/number_utils.py +34 -44
- classiq/interface/generator/arith/register_user_input.py +21 -1
- classiq/interface/generator/arith/unary_ops.py +16 -25
- classiq/interface/generator/builtin_api_builder.py +0 -5
- classiq/interface/generator/chemistry_function_params.py +4 -4
- classiq/interface/generator/commuting_pauli_exponentiation.py +3 -1
- classiq/interface/generator/compiler_keywords.py +4 -0
- classiq/interface/generator/complex_type.py +3 -10
- classiq/interface/generator/constant.py +2 -3
- classiq/interface/generator/control_state.py +5 -3
- classiq/interface/generator/credit_risk_example/linear_gci.py +10 -3
- classiq/interface/generator/credit_risk_example/weighted_adder.py +14 -4
- classiq/interface/generator/expressions/atomic_expression_functions.py +5 -3
- classiq/interface/generator/expressions/evaluated_expression.py +18 -4
- classiq/interface/generator/expressions/expression.py +3 -5
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +33 -0
- classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
- classiq/interface/generator/finance.py +1 -1
- classiq/interface/generator/function_params.py +7 -6
- classiq/interface/generator/functions/__init__.py +2 -2
- classiq/interface/generator/functions/builtins/__init__.py +15 -0
- classiq/interface/generator/functions/builtins/core_library/__init__.py +14 -0
- classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +62 -0
- classiq/interface/generator/functions/{core_lib_declarations/quantum_functions/std_lib_functions.py → builtins/open_lib_functions.py} +612 -219
- classiq/interface/generator/functions/builtins/quantum_operators.py +37 -0
- classiq/interface/generator/functions/classical_type.py +2 -4
- classiq/interface/generator/functions/foreign_function_definition.py +12 -4
- classiq/interface/generator/functions/function_declaration.py +2 -2
- classiq/interface/generator/functions/function_implementation.py +8 -4
- classiq/interface/generator/functions/native_function_definition.py +4 -2
- classiq/interface/generator/functions/register.py +4 -2
- classiq/interface/generator/functions/register_mapping_data.py +14 -10
- classiq/interface/generator/generated_circuit_data.py +2 -2
- classiq/interface/generator/grover_operator.py +5 -3
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +5 -1
- classiq/interface/generator/hardware/hardware_data.py +6 -4
- classiq/interface/generator/hardware_efficient_ansatz.py +25 -8
- classiq/interface/generator/hartree_fock.py +13 -3
- classiq/interface/generator/linear_pauli_rotations.py +3 -1
- classiq/interface/generator/mcu.py +5 -3
- classiq/interface/generator/mcx.py +7 -5
- classiq/interface/generator/model/classical_main_validator.py +1 -1
- classiq/interface/generator/model/constraints.py +2 -1
- classiq/interface/generator/model/model.py +12 -20
- classiq/interface/generator/model/preferences/preferences.py +4 -3
- classiq/interface/generator/oracles/custom_oracle.py +4 -2
- classiq/interface/generator/oracles/oracle_abc.py +2 -2
- classiq/interface/generator/qpe.py +6 -4
- classiq/interface/generator/qsvm.py +5 -8
- classiq/interface/generator/quantum_function_call.py +21 -16
- classiq/interface/generator/{generated_circuit.py → quantum_program.py} +10 -14
- classiq/interface/generator/range_types.py +3 -1
- classiq/interface/generator/slice_parsing_utils.py +8 -3
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +4 -2
- classiq/interface/generator/state_preparation/metrics.py +2 -1
- classiq/interface/generator/state_preparation/state_preparation.py +7 -5
- classiq/interface/generator/state_propagator.py +16 -5
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
- classiq/interface/generator/types/struct_declaration.py +10 -7
- classiq/interface/generator/ucc.py +6 -4
- classiq/interface/generator/unitary_gate.py +7 -3
- classiq/interface/generator/validations/flow_graph.py +6 -4
- classiq/interface/generator/validations/validator_functions.py +6 -4
- classiq/interface/hardware.py +2 -2
- classiq/interface/helpers/custom_encoders.py +3 -0
- classiq/interface/helpers/pydantic_model_helpers.py +0 -6
- classiq/interface/helpers/validation_helpers.py +1 -1
- classiq/interface/helpers/versioned_model.py +4 -1
- classiq/interface/ide/show.py +2 -2
- classiq/interface/jobs.py +72 -3
- classiq/interface/model/bind_operation.py +18 -11
- classiq/interface/model/call_synthesis_data.py +68 -0
- classiq/interface/model/classical_if.py +13 -0
- classiq/interface/model/classical_parameter_declaration.py +2 -3
- classiq/interface/model/control.py +16 -0
- classiq/interface/model/handle_binding.py +3 -2
- classiq/interface/model/inplace_binary_operation.py +2 -2
- classiq/interface/model/invert.py +10 -0
- classiq/interface/model/model.py +29 -22
- classiq/interface/model/native_function_definition.py +3 -5
- classiq/interface/model/power.py +12 -0
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +9 -4
- classiq/interface/model/quantum_expressions/control_state.py +2 -2
- classiq/interface/model/quantum_function_call.py +33 -142
- classiq/interface/model/quantum_function_declaration.py +8 -0
- classiq/interface/model/quantum_if_operation.py +4 -5
- classiq/interface/model/quantum_lambda_function.py +58 -0
- classiq/{quantum_register.py → interface/model/quantum_register.py} +17 -9
- classiq/interface/model/quantum_statement.py +3 -2
- classiq/interface/model/quantum_type.py +58 -59
- classiq/interface/model/quantum_variable_declaration.py +3 -3
- classiq/interface/model/repeat.py +13 -0
- classiq/interface/model/resolvers/function_call_resolver.py +26 -0
- classiq/interface/model/statement_block.py +49 -0
- classiq/interface/model/validations/handles_validator.py +16 -18
- classiq/interface/model/within_apply_operation.py +11 -0
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
- classiq/interface/server/routes.py +5 -4
- classiq/qmod/__init__.py +13 -6
- classiq/qmod/builtins/classical_execution_primitives.py +27 -36
- classiq/qmod/builtins/classical_functions.py +22 -12
- classiq/qmod/builtins/functions.py +272 -328
- classiq/qmod/builtins/operations.py +171 -35
- classiq/qmod/builtins/structs.py +15 -15
- classiq/qmod/cfunc.py +42 -0
- classiq/qmod/classical_function.py +6 -14
- classiq/qmod/declaration_inferrer.py +12 -21
- classiq/qmod/expression_query.py +23 -0
- classiq/qmod/model_state_container.py +2 -0
- classiq/qmod/native/__init__.py +0 -0
- classiq/qmod/native/expression_to_qmod.py +189 -0
- classiq/qmod/native/pretty_printer.py +340 -0
- classiq/qmod/qfunc.py +27 -0
- classiq/qmod/qmod_constant.py +100 -0
- classiq/qmod/qmod_parameter.py +36 -13
- classiq/qmod/qmod_struct.py +3 -3
- classiq/qmod/qmod_variable.py +148 -31
- classiq/qmod/quantum_callable.py +1 -0
- classiq/qmod/quantum_expandable.py +18 -19
- classiq/qmod/quantum_function.py +41 -8
- classiq/qmod/symbolic.py +48 -5
- classiq/qmod/symbolic_expr.py +9 -0
- classiq/qmod/utilities.py +13 -0
- classiq/qmod/write_qmod.py +39 -0
- {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/METADATA +2 -1
- {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/RECORD +244 -225
- {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/WHEEL +1 -1
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -17
- classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
- classiq/builtin_functions/__init__.py +0 -43
- classiq/builtin_functions/amplitude_loading.py +0 -3
- classiq/builtin_functions/binary_ops.py +0 -1
- classiq/builtin_functions/exponentiation.py +0 -5
- classiq/builtin_functions/qpe.py +0 -4
- classiq/builtin_functions/qsvm.py +0 -7
- classiq/builtin_functions/range_types.py +0 -5
- classiq/builtin_functions/standard_gates.py +0 -1
- classiq/builtin_functions/state_preparation.py +0 -6
- classiq/builtin_functions/suzuki_trotter.py +0 -3
- classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
- classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
- classiq/interface/generator/types/combinatorial_problem.py +0 -26
- classiq/interface/model/numeric_reinterpretation.py +0 -25
- classiq/interface/model/operator_synthesis_data.py +0 -48
- classiq/model/__init__.py +0 -14
- classiq/model/composite_function_generator.py +0 -33
- classiq/model/function_handler.py +0 -466
- classiq/model/function_handler.pyi +0 -152
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -246
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -207
- classiq/quantum_functions/decorators.py +0 -22
- classiq/quantum_functions/function_library.py +0 -181
- classiq/quantum_functions/function_parser.py +0 -74
- classiq/quantum_functions/quantum_function.py +0 -236
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/pauli_helpers/__init__.py} +0 -0
- /classiq/{applications_model_constructors → applications}/libraries/ampltitude_estimation_library.py +0 -0
- /classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +0 -0
- /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/atomic_quantum_functions.py +0 -0
- /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/exponentiation_functions.py +0 -0
classiq/analyzer/analyzer.py
CHANGED
@@ -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
|
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
|
34
|
+
class Analyzer(AnalyzerUtilities):
|
38
35
|
"""Analyzer is the wrapper object for all analysis capabilities."""
|
39
36
|
|
40
|
-
def __init__(self, circuit: generator_result.
|
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
|
-
|
47
|
+
params: analysis_params.AnalysisParams = analysis_params.AnalysisParams(
|
51
48
|
qasm=circuit.qasm
|
52
49
|
)
|
53
|
-
|
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
|
-
|
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
|
-
|
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 =
|
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
|
-
|
81
|
+
def get_available_devices(
|
80
82
|
self, providers: Optional[List[ProviderNameEnum]] = None
|
81
83
|
) -> Dict[ProviderNameEnum, List[DeviceName]]:
|
82
|
-
"""
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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:
|
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:
|
30
|
+
self.circuit: QuantumProgram = circuit
|
31
31
|
self.available_devices = available_devices
|
32
32
|
self.hardware_graphs = hardware_graphs
|
33
33
|
|
34
|
-
async def
|
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.
|
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
|
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
|
-
|
72
|
-
|
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.
|
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:
|
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:
|
21
|
+
async def _show_interactive(self: QuantumProgram) -> None:
|
22
22
|
await handle_remote_app(circuit=self)
|
23
23
|
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
QuantumProgram.show = syncify_function(_show_interactive) # type: ignore[attr-defined]
|
26
|
+
QuantumProgram.show_async = _show_interactive # type: ignore[attr-defined]
|
classiq/applications/__init__.py
CHANGED
@@ -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
|
|
classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py
RENAMED
@@ -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
|
-
|
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
|
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
|
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({
|
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
|
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
|