classiq 0.37.1__py3-none-any.whl → 0.38.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 +2 -2
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +1 -1
- classiq/_analyzer_extras/interactive_hardware.py +3 -3
- classiq/_internals/api_wrapper.py +24 -16
- 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 +13 -5
- classiq/_internals/jobs.py +10 -7
- classiq/analyzer/analyzer.py +26 -28
- classiq/analyzer/analyzer_utilities.py +5 -5
- classiq/analyzer/rb.py +4 -5
- classiq/analyzer/show_interactive_hack.py +6 -6
- classiq/applications/benchmarking/mirror_benchmarking.py +9 -6
- classiq/applications/combinatorial_optimization/__init__.py +5 -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/qsvm.py +4 -7
- classiq/applications/qsvm/qsvm_data_generation.py +2 -5
- classiq/applications_model_constructors/__init__.py +9 -1
- classiq/applications_model_constructors/chemistry_model_constructor.py +9 -16
- classiq/applications_model_constructors/combinatorial_helpers/__init__.py +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/allowed_constraints.py +20 -0
- classiq/applications_model_constructors/combinatorial_helpers/arithmetic/__init__.py +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
- classiq/applications_model_constructors/combinatorial_helpers/arithmetic/isolation.py +42 -0
- classiq/applications_model_constructors/combinatorial_helpers/combinatorial_problem_utils.py +130 -0
- classiq/applications_model_constructors/combinatorial_helpers/encoding_mapping.py +107 -0
- classiq/applications_model_constructors/combinatorial_helpers/encoding_utils.py +122 -0
- classiq/applications_model_constructors/combinatorial_helpers/memory.py +79 -0
- classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +34 -0
- classiq/applications_model_constructors/combinatorial_helpers/optimization_model.py +166 -0
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +65 -0
- classiq/applications_model_constructors/combinatorial_helpers/py.typed +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +243 -0
- classiq/applications_model_constructors/combinatorial_helpers/sympy_utils.py +22 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/__init__.py +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/encoding.py +194 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/fixed_variables.py +144 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/ising_converter.py +124 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/penalty.py +32 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/penalty_support.py +41 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/sign_seperation.py +75 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/slack_variables.py +90 -0
- classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +48 -91
- classiq/applications_model_constructors/finance_model_constructor.py +4 -17
- classiq/applications_model_constructors/grover_model_constructor.py +20 -91
- classiq/applications_model_constructors/libraries/qmci_library.py +17 -19
- classiq/builtin_functions/standard_gates.py +1 -1
- classiq/exceptions.py +43 -1
- classiq/executor.py +10 -9
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +6 -3
- classiq/interface/analyzer/result.py +12 -4
- classiq/interface/applications/qsvm.py +13 -1
- 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 +3 -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 +19 -17
- 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 +1 -1
- 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/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/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 +1 -1
- 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 +1 -1
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +505 -138
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +25 -99
- classiq/interface/generator/functions/foreign_function_definition.py +12 -4
- 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 +3 -1
- 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/constraints.py +2 -1
- classiq/interface/generator/model/model.py +11 -19
- 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 +8 -3
- 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/inplace_binary_operation.py +2 -2
- classiq/interface/model/model.py +27 -21
- classiq/interface/model/native_function_definition.py +3 -5
- 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 +25 -139
- classiq/interface/model/quantum_function_declaration.py +8 -0
- classiq/interface/model/quantum_if_operation.py +2 -3
- classiq/interface/model/quantum_lambda_function.py +64 -0
- classiq/interface/model/quantum_type.py +57 -56
- classiq/interface/model/quantum_variable_declaration.py +1 -1
- classiq/interface/model/statement_block.py +32 -0
- classiq/interface/model/validations/handles_validator.py +14 -12
- 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 -0
- classiq/model/function_handler.py +5 -9
- classiq/model/model.py +2 -19
- classiq/qmod/__init__.py +13 -6
- classiq/qmod/builtins/classical_execution_primitives.py +27 -36
- classiq/qmod/builtins/classical_functions.py +24 -14
- classiq/qmod/builtins/functions.py +162 -145
- classiq/qmod/builtins/operations.py +24 -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 +311 -0
- classiq/qmod/qfunc.py +27 -0
- classiq/qmod/qmod_constant.py +76 -0
- classiq/qmod/qmod_parameter.py +34 -12
- classiq/qmod/qmod_struct.py +3 -3
- classiq/qmod/qmod_variable.py +102 -18
- classiq/qmod/quantum_expandable.py +16 -16
- classiq/qmod/quantum_function.py +37 -8
- classiq/qmod/symbolic.py +47 -4
- classiq/qmod/symbolic_expr.py +9 -0
- classiq/qmod/utilities.py +13 -0
- classiq/qmod/write_qmod.py +39 -0
- classiq/quantum_functions/__init__.py +2 -2
- classiq/quantum_functions/annotation_parser.py +9 -11
- classiq/quantum_functions/function_parser.py +1 -1
- classiq/quantum_functions/quantum_function.py +3 -3
- classiq/quantum_register.py +17 -9
- {classiq-0.37.1.dist-info → classiq-0.38.0.dist-info}/METADATA +2 -1
- {classiq-0.37.1.dist-info → classiq-0.38.0.dist-info}/RECORD +222 -186
- {classiq-0.37.1.dist-info → classiq-0.38.0.dist-info}/WHEEL +1 -1
- classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
- 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/function_handler.pyi +0 -152
@@ -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]
|
@@ -1,15 +1,15 @@
|
|
1
1
|
from copy import deepcopy
|
2
2
|
|
3
|
-
from classiq.interface.generator.generated_circuit import GeneratedCircuit
|
4
3
|
from classiq.interface.generator.model.preferences.preferences import (
|
5
4
|
Preferences,
|
6
5
|
QuantumFormat,
|
7
6
|
TranspilationOption,
|
8
7
|
)
|
8
|
+
from classiq.interface.generator.quantum_program import QuantumProgram
|
9
9
|
|
10
|
-
from classiq._internals
|
10
|
+
from classiq._internals import async_utils
|
11
11
|
from classiq.model.model import Model
|
12
|
-
from classiq.quantum_functions.decorators import quantum_function
|
12
|
+
from classiq.quantum_functions.decorators import quantum_function
|
13
13
|
from classiq.quantum_functions.function_library import QASM_INTRO, FunctionLibrary
|
14
14
|
from classiq.quantum_register import QReg, ZeroQReg
|
15
15
|
from classiq.synthesis import synthesize_async
|
@@ -18,7 +18,7 @@ _MB_NAME: str = "mirror_benchmarking"
|
|
18
18
|
_MB_FUNCTION_LIBRARY_NAME: str = f"{_MB_NAME}_function_library"
|
19
19
|
|
20
20
|
|
21
|
-
class MirrorBenchmarking
|
21
|
+
class MirrorBenchmarking:
|
22
22
|
def __init__(self, model: Model) -> None:
|
23
23
|
self.functional_model: Model = model
|
24
24
|
self.functional_model._model.preferences = self.get_functional_preferences(
|
@@ -26,7 +26,7 @@ class MirrorBenchmarking(metaclass=Asyncify):
|
|
26
26
|
)
|
27
27
|
|
28
28
|
async def mirror_benchmarking_model_async(self) -> Model:
|
29
|
-
functional_circuit:
|
29
|
+
functional_circuit: QuantumProgram = QuantumProgram.parse_raw(
|
30
30
|
await synthesize_async(self.functional_model.get_model())
|
31
31
|
)
|
32
32
|
|
@@ -38,7 +38,7 @@ class MirrorBenchmarking(metaclass=Asyncify):
|
|
38
38
|
)
|
39
39
|
circuit_qasm: str = circuit_qasm_list[-1]
|
40
40
|
|
41
|
-
@
|
41
|
+
@quantum_function
|
42
42
|
def functional_model_function(reg: ZeroQReg[num_qubits]) -> QReg[num_qubits]: # type: ignore[type-arg, valid-type]
|
43
43
|
return QASM_INTRO + circuit_qasm # type: ignore[return-value]
|
44
44
|
|
@@ -54,6 +54,9 @@ class MirrorBenchmarking(metaclass=Asyncify):
|
|
54
54
|
mb_model.functional_model_function(in_wires=inner_wires, is_inverse=True)
|
55
55
|
return mb_model
|
56
56
|
|
57
|
+
def mirror_benchmarking_model(self) -> Model:
|
58
|
+
return async_utils.run(self.mirror_benchmarking_model_async())
|
59
|
+
|
57
60
|
@staticmethod
|
58
61
|
def get_functional_preferences(preferences: Preferences) -> Preferences:
|
59
62
|
functional_preferences = deepcopy(preferences)
|
@@ -3,6 +3,10 @@ from typing import List
|
|
3
3
|
from classiq.interface.combinatorial_optimization import examples
|
4
4
|
from classiq.interface.combinatorial_optimization.solver_types import QSolver
|
5
5
|
|
6
|
+
from classiq.applications_model_constructors.combinatorial_helpers.combinatorial_problem_utils import (
|
7
|
+
get_optimization_solution_from_pyo,
|
8
|
+
)
|
9
|
+
|
6
10
|
from .combinatorial_optimization_config import OptimizerConfig, QAOAConfig
|
7
11
|
|
8
12
|
__all__ = [
|
@@ -10,6 +14,7 @@ __all__ = [
|
|
10
14
|
"examples",
|
11
15
|
"QAOAConfig",
|
12
16
|
"OptimizerConfig",
|
17
|
+
"get_optimization_solution_from_pyo",
|
13
18
|
]
|
14
19
|
|
15
20
|
|
@@ -5,8 +5,8 @@ from typing import Iterable, List, Tuple, Union
|
|
5
5
|
from torch import Tensor
|
6
6
|
|
7
7
|
from classiq.interface.generator.circuit_code.types_and_constants import QasmVersion
|
8
|
-
from classiq.interface.generator.generated_circuit import GeneratedCircuit
|
9
8
|
from classiq.interface.generator.model.preferences.preferences import QuantumFormat
|
9
|
+
from classiq.interface.generator.quantum_program import QuantumProgram
|
10
10
|
|
11
11
|
from classiq.applications.qnn.types import Arguments, Circuit
|
12
12
|
from classiq.exceptions import ClassiqQNNError, ClassiqValueError
|
@@ -95,7 +95,7 @@ def _get_extracted_parameters(obj: CircuitOrExtractedParameters) -> ParametersTu
|
|
95
95
|
# This `if` is for caching
|
96
96
|
if isinstance(obj, tuple):
|
97
97
|
weight_params, input_params = obj
|
98
|
-
elif isinstance(obj,
|
98
|
+
elif isinstance(obj, QuantumProgram):
|
99
99
|
weight_params, input_params = extract_parameters(obj)
|
100
100
|
else:
|
101
101
|
raise ClassiqValueError("Invalid object passed to `map_parameters`")
|
@@ -4,7 +4,7 @@ from typing import Any
|
|
4
4
|
|
5
5
|
from torch import Tensor
|
6
6
|
|
7
|
-
from classiq.interface.generator.
|
7
|
+
from classiq.interface.generator.quantum_program import QuantumProgram
|
8
8
|
|
9
9
|
from classiq.applications.qnn.circuit_utils import extract_parameters, validate_circuit
|
10
10
|
from classiq.applications.qnn.types import ExecuteFunction, PostProcessFunction
|
@@ -23,7 +23,7 @@ class QuantumGradient(abc.ABC):
|
|
23
23
|
self._execute = execute
|
24
24
|
self._post_process = post_process
|
25
25
|
|
26
|
-
circuit =
|
26
|
+
circuit = QuantumProgram.parse_raw(quantum_program)
|
27
27
|
validate_circuit(circuit)
|
28
28
|
self._quantum_program = quantum_program
|
29
29
|
self._parameters_names = extract_parameters(circuit)
|
@@ -5,13 +5,13 @@ from torch import Tensor
|
|
5
5
|
|
6
6
|
from classiq.interface.executor.execution_result import ResultsCollection, SavedResult
|
7
7
|
|
8
|
-
from classiq import
|
8
|
+
from classiq import QuantumProgram
|
9
9
|
from classiq.synthesis import SerializedQuantumProgram
|
10
10
|
|
11
11
|
Arguments = Dict[str, float]
|
12
12
|
MultipleArguments = Tuple[Arguments, ...]
|
13
13
|
|
14
|
-
Circuit =
|
14
|
+
Circuit = QuantumProgram
|
15
15
|
ExecuteFunction = Callable[
|
16
16
|
[SerializedQuantumProgram, MultipleArguments], ResultsCollection
|
17
17
|
]
|
@@ -1,15 +1,12 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import List
|
2
2
|
|
3
|
-
import
|
4
|
-
|
5
|
-
from classiq.interface.applications.qsvm import DataList, QSVMData, QSVMPreferences
|
6
|
-
|
7
|
-
Data = Union[DataList, np.ndarray]
|
8
|
-
Labels = Union[List[Any], np.ndarray]
|
3
|
+
from classiq.interface.applications.qsvm import Data, Labels, QSVMData, QSVMPreferences
|
9
4
|
|
10
5
|
__all__ = [
|
11
6
|
"QSVMData",
|
12
7
|
"QSVMPreferences",
|
8
|
+
"Data",
|
9
|
+
"Labels",
|
13
10
|
]
|
14
11
|
|
15
12
|
|
@@ -24,11 +24,8 @@ def generate_data(
|
|
24
24
|
|
25
25
|
results = {}
|
26
26
|
for index, s in enumerate(sources):
|
27
|
-
|
28
|
-
|
29
|
-
for point in s:
|
30
|
-
# draw from a gaussian distribution
|
31
|
-
temp.append(np.random.normal(point, std, amount))
|
27
|
+
# for each dimension draw from a gaussian distribution
|
28
|
+
temp = [np.random.normal(point, std, amount) for point in s]
|
32
29
|
# combine the list of np.arrays
|
33
30
|
results[index] = np.array(list(zip(*temp)))
|
34
31
|
|
@@ -1,6 +1,9 @@
|
|
1
1
|
from typing import List
|
2
2
|
|
3
|
-
from .chemistry_model_constructor import
|
3
|
+
from .chemistry_model_constructor import (
|
4
|
+
construct_chemistry_model,
|
5
|
+
molecule_problem_to_qmod,
|
6
|
+
)
|
4
7
|
from .combinatorial_optimization_model_constructor import (
|
5
8
|
construct_combinatorial_optimization_model,
|
6
9
|
)
|
@@ -14,4 +17,9 @@ __all__: List[str] = [
|
|
14
17
|
"construct_chemistry_model",
|
15
18
|
"construct_finance_model",
|
16
19
|
"construct_grover_model",
|
20
|
+
"molecule_problem_to_qmod",
|
17
21
|
]
|
22
|
+
|
23
|
+
|
24
|
+
def __dir__():
|
25
|
+
return __all__
|
@@ -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
|
)
|
File without changes
|
@@ -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
|
+
)
|
File without changes
|
classiq/applications_model_constructors/combinatorial_helpers/arithmetic/arithmetic_expression.py
ADDED
@@ -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_model_constructors.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,130 @@
|
|
1
|
+
import itertools
|
2
|
+
from typing import List, Union
|
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_model_constructors.combinatorial_helpers.optimization_model import (
|
13
|
+
OptimizationModel,
|
14
|
+
)
|
15
|
+
from classiq.applications_model_constructors.combinatorial_helpers.pauli_helpers.pauli_sparsing import (
|
16
|
+
SparsePauliOp,
|
17
|
+
)
|
18
|
+
from classiq.applications_model_constructors.combinatorial_helpers.pauli_helpers.pauli_utils import (
|
19
|
+
pauli_operator_to_hamiltonian,
|
20
|
+
)
|
21
|
+
from classiq.applications_model_constructors.combinatorial_helpers.pyomo_utils import (
|
22
|
+
convert_pyomo_to_global_presentation,
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
def compute_qaoa_initial_point(
|
27
|
+
hamiltonian: List[QmodPyStruct],
|
28
|
+
repetitions: int,
|
29
|
+
) -> List[float]:
|
30
|
+
coeffs_ising = [pauli_term["coefficient"] for pauli_term in hamiltonian[1:]]
|
31
|
+
# the first coeff is the II...I term
|
32
|
+
coeffs_abs = np.abs(coeffs_ising)
|
33
|
+
coeffs_largest = np.sort(coeffs_abs)[len(coeffs_ising) // 2 :]
|
34
|
+
operator_norm = np.mean(coeffs_largest)
|
35
|
+
time_step = 1 / (2 * operator_norm) # adapted such that for MAXCUT time_step = 1
|
36
|
+
|
37
|
+
beta_params: np.ndarray = np.linspace(1, 0, repetitions) * time_step
|
38
|
+
gamma_params: np.ndarray = np.linspace(0, 1, repetitions) * time_step
|
39
|
+
return list(itertools.chain(*zip(gamma_params, beta_params)))
|
40
|
+
|
41
|
+
|
42
|
+
def pyo_model_to_hamiltonian(
|
43
|
+
pyo_model: pyo.ConcreteModel, penalty_energy: float
|
44
|
+
) -> List[QmodPyStruct]:
|
45
|
+
pauli_list = OptimizationModel(
|
46
|
+
pyo_model, penalty_energy=penalty_energy, qsolver=QSolver.QAOAPenalty
|
47
|
+
).ising.pauli_list
|
48
|
+
return pauli_operator_to_hamiltonian(pauli_list)
|
49
|
+
|
50
|
+
|
51
|
+
def _str_to_list_int(str_ints: str) -> List[int]:
|
52
|
+
return list(map(int, list(str_ints)))
|
53
|
+
|
54
|
+
|
55
|
+
def _decode_vector_str(
|
56
|
+
optimization_model: OptimizationModel, vector_str: str
|
57
|
+
) -> List[int]:
|
58
|
+
return optimization_model.decode(
|
59
|
+
_str_to_list_int(vector_str[::-1])
|
60
|
+
) # reverse qubit order
|
61
|
+
|
62
|
+
|
63
|
+
def _evaluate_operator(operator: SparsePauliOp, state: Union[List[int], str]) -> float:
|
64
|
+
if isinstance(state, list):
|
65
|
+
state = "".join([str(x) for x in state])
|
66
|
+
|
67
|
+
cost = 0.0
|
68
|
+
for pauli, coeff in zip(operator.paulis, operator.coeffs):
|
69
|
+
expectation = 1
|
70
|
+
for qubit, pauli_char in enumerate(pauli):
|
71
|
+
if pauli_char != "I" and state[qubit] == "1" and pauli_char in ["Z", "Y"]:
|
72
|
+
expectation *= -1
|
73
|
+
cost += expectation * coeff.real
|
74
|
+
|
75
|
+
return cost
|
76
|
+
|
77
|
+
|
78
|
+
def _eigenstate_to_solution(
|
79
|
+
optimization_model: OptimizationModel,
|
80
|
+
eigenvector: str,
|
81
|
+
probability: float,
|
82
|
+
num_shots: int,
|
83
|
+
) -> QmodPyStruct:
|
84
|
+
pauli = optimization_model.get_operator().pauli_list
|
85
|
+
|
86
|
+
paulis = [item[0] for item in pauli]
|
87
|
+
coeffs = [item[1] for item in pauli]
|
88
|
+
|
89
|
+
operator = SparsePauliOp(paulis, coeffs)
|
90
|
+
cost = _evaluate_operator(operator, eigenvector)
|
91
|
+
|
92
|
+
if is_maximization(optimization_model._model_original):
|
93
|
+
cost *= -1
|
94
|
+
|
95
|
+
return {
|
96
|
+
"probability": probability,
|
97
|
+
"cost": cost,
|
98
|
+
"solution": _decode_vector_str(optimization_model, eigenvector),
|
99
|
+
"count": round(probability * num_shots),
|
100
|
+
}
|
101
|
+
|
102
|
+
|
103
|
+
def _get_combi_solution_histogram(
|
104
|
+
optimization_model: OptimizationModel,
|
105
|
+
vqe_result: VQESolverResult,
|
106
|
+
) -> List[QmodPyStruct]:
|
107
|
+
if vqe_result.reduced_probabilities is None:
|
108
|
+
raise ValueError(
|
109
|
+
"reduced_probabilities is optional only for backwards compatibility, but it should always be present here"
|
110
|
+
)
|
111
|
+
return [
|
112
|
+
_eigenstate_to_solution(
|
113
|
+
optimization_model, eigenvector, probability, vqe_result.num_shots
|
114
|
+
)
|
115
|
+
for eigenvector, probability in vqe_result.reduced_probabilities.items()
|
116
|
+
]
|
117
|
+
|
118
|
+
|
119
|
+
def get_optimization_solution_from_pyo(
|
120
|
+
pyo_model: pyo.ConcreteModel,
|
121
|
+
vqe_result: VQESolverResult,
|
122
|
+
penalty_energy: float,
|
123
|
+
) -> List[QmodPyStruct]:
|
124
|
+
converted_pyo_model = convert_pyomo_to_global_presentation(pyo_model)
|
125
|
+
optimization_model = OptimizationModel(
|
126
|
+
converted_pyo_model, penalty_energy=penalty_energy, qsolver=QSolver.QAOAPenalty
|
127
|
+
)
|
128
|
+
histogram = _get_combi_solution_histogram(optimization_model, vqe_result)
|
129
|
+
histogram.sort(key=lambda x: x["probability"], reverse=True)
|
130
|
+
return histogram
|