classiq 0.102.0__py3-none-any.whl → 1.0.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 -0
- classiq/_internals/authentication/auth0.py +29 -0
- classiq/_internals/authentication/auth_flow_factory.py +43 -0
- classiq/_internals/authentication/machine_credentials_flow.py +26 -0
- classiq/_internals/authentication/password_manager.py +84 -0
- classiq/_internals/authentication/token_manager.py +24 -8
- classiq/analyzer/show_interactive_hack.py +0 -8
- classiq/applications/chemistry/op_utils.py +32 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +1 -1
- classiq/evaluators/qmod_annotated_expression.py +1 -1
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +1 -8
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +1 -1
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +18 -29
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +1 -6
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -7
- classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
- classiq/execution/all_hardware_devices.py +59 -1
- classiq/execution/execution_session.py +1 -1
- classiq/execution/functions/__init__.py +13 -0
- classiq/execution/functions/expectation_value.py +106 -0
- classiq/execution/functions/minimize.py +90 -0
- classiq/execution/functions/sample.py +76 -0
- classiq/execution/functions/state_vector.py +113 -0
- classiq/execution/functions/util/__init__.py +0 -0
- classiq/execution/functions/util/_logging.py +19 -0
- classiq/execution/functions/util/backend_preferences.py +188 -0
- classiq/execution/functions/util/constants.py +9 -0
- classiq/execution/functions/util/parse_provider_backend.py +90 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +81 -0
- classiq/interface/backend/provider_config/providers/aqt.py +1 -1
- classiq/interface/backend/provider_config/providers/azure.py +1 -2
- classiq/interface/backend/provider_config/providers/ibm.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +14 -0
- classiq/interface/exceptions.py +0 -4
- classiq/interface/executor/result.py +9 -5
- classiq/interface/generator/arith/binary_ops.py +62 -2
- classiq/interface/generator/arith/number_utils.py +15 -6
- classiq/interface/generator/compiler_keywords.py +1 -0
- classiq/interface/generator/function_param_list.py +8 -2
- classiq/interface/generator/function_params.py +1 -1
- classiq/interface/generator/functions/builtins/internal_operators.py +5 -9
- classiq/interface/generator/functions/classical_type.py +60 -0
- classiq/interface/generator/functions/type_name.py +36 -0
- classiq/interface/generator/generated_circuit_data.py +0 -2
- classiq/interface/generator/transpiler_basis_gates.py +1 -0
- classiq/interface/generator/types/compilation_metadata.py +18 -0
- classiq/interface/hardware.py +2 -0
- classiq/interface/helpers/model_normalizer.py +42 -6
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/invert.py +8 -0
- classiq/interface/model/model.py +19 -0
- classiq/interface/model/model_visitor.py +4 -2
- classiq/interface/model/quantum_type.py +36 -0
- classiq/interface/model/statement_block.py +0 -4
- classiq/interface/qubits_mapping/__init__.py +4 -0
- classiq/interface/qubits_mapping/path_expr_range.py +69 -0
- classiq/interface/qubits_mapping/qubits_mapping.py +231 -0
- classiq/interface/qubits_mapping/slices.py +112 -0
- classiq/model_expansions/arithmetic.py +6 -0
- classiq/model_expansions/capturing/captured_vars.py +16 -12
- classiq/model_expansions/function_builder.py +9 -1
- classiq/model_expansions/interpreters/base_interpreter.py +9 -8
- classiq/model_expansions/interpreters/generative_interpreter.py +9 -24
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -0
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +132 -28
- classiq/model_expansions/quantum_operations/bind.py +4 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +5 -35
- classiq/model_expansions/quantum_operations/emitter.py +1 -4
- classiq/model_expansions/quantum_operations/expression_evaluator.py +0 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +0 -9
- classiq/qmod/builtins/functions/__init__.py +21 -9
- classiq/qmod/builtins/functions/allocation.py +0 -36
- classiq/qmod/builtins/functions/arithmetic.py +183 -0
- classiq/qmod/builtins/functions/exponentiation.py +32 -2
- classiq/qmod/builtins/functions/gray_code.py +23 -0
- classiq/qmod/builtins/functions/mcx_func.py +10 -0
- classiq/qmod/builtins/operations.py +2 -38
- classiq/qmod/builtins/structs.py +22 -3
- classiq/qmod/native/pretty_printer.py +1 -12
- classiq/qmod/pretty_print/pretty_printer.py +1 -17
- classiq/qmod/qmod_parameter.py +4 -0
- classiq/qmod/qmod_variable.py +38 -63
- classiq/qmod/quantum_function.py +43 -7
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +7 -4
- classiq/qmod/semantics/validation/model_validation.py +7 -2
- classiq/qmod/symbolic_type.py +4 -2
- classiq/qprog_to_cudaq.py +347 -0
- {classiq-0.102.0.dist-info → classiq-1.0.0.dist-info}/METADATA +4 -1
- {classiq-0.102.0.dist-info → classiq-1.0.0.dist-info}/RECORD +93 -76
- classiq/interface/generator/amplitude_loading.py +0 -103
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
- {classiq-0.102.0.dist-info → classiq-1.0.0.dist-info}/WHEEL +0 -0
- {classiq-0.102.0.dist-info → classiq-1.0.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from classiq.interface.exceptions import (
|
|
2
|
+
ClassiqInternalExpansionError,
|
|
3
|
+
)
|
|
4
|
+
from classiq.interface.generator.expressions.expression import Expression
|
|
5
|
+
from classiq.interface.generator.functions.type_name import TypeName
|
|
6
|
+
from classiq.interface.model.quantum_type import (
|
|
7
|
+
QuantumBit,
|
|
8
|
+
QuantumBitvector,
|
|
9
|
+
QuantumNumeric,
|
|
10
|
+
QuantumType,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _compare_expressions(expr1: Expression | None, expr2: Expression | None) -> bool:
|
|
15
|
+
if expr1 is None:
|
|
16
|
+
return expr2 is None
|
|
17
|
+
if expr2 is None:
|
|
18
|
+
return False
|
|
19
|
+
return expr1.expr == expr2.expr
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def compare_quantum_types(type_1: QuantumType, type_2: QuantumType) -> bool:
|
|
23
|
+
for qmod_type in (type_1, type_2):
|
|
24
|
+
if isinstance(qmod_type, TypeName) and not qmod_type.has_fields:
|
|
25
|
+
raise ClassiqInternalExpansionError("Quantum struct expected")
|
|
26
|
+
if isinstance(type_1, QuantumBit):
|
|
27
|
+
return isinstance(type_2, QuantumBit)
|
|
28
|
+
if isinstance(type_1, QuantumNumeric):
|
|
29
|
+
return (
|
|
30
|
+
isinstance(type_2, QuantumNumeric)
|
|
31
|
+
and _compare_expressions(type_1.size, type_2.size)
|
|
32
|
+
and _compare_expressions(type_1.is_signed, type_2.is_signed)
|
|
33
|
+
and _compare_expressions(type_1.fraction_digits, type_2.fraction_digits)
|
|
34
|
+
)
|
|
35
|
+
if isinstance(type_1, QuantumBitvector):
|
|
36
|
+
return (
|
|
37
|
+
isinstance(type_2, QuantumBitvector)
|
|
38
|
+
and _compare_expressions(type_1.length, type_2.length)
|
|
39
|
+
and compare_quantum_types(type_1.element_type, type_2.element_type)
|
|
40
|
+
)
|
|
41
|
+
if isinstance(type_1, TypeName):
|
|
42
|
+
return (
|
|
43
|
+
isinstance(type_2, TypeName)
|
|
44
|
+
and type_1.name == type_2.name
|
|
45
|
+
and all(
|
|
46
|
+
compare_quantum_types(field_type_1, field_type_2)
|
|
47
|
+
for field_type_1, field_type_2 in zip(
|
|
48
|
+
type_1.fields.values(), type_2.fields.values(), strict=True
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
raise ClassiqInternalExpansionError(f"Unexpected type {type(type_1).__name__}")
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
from
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from classiq.interface.hardware import HardwareInformation, Provider
|
|
2
4
|
|
|
3
5
|
from classiq._internals import async_utils
|
|
4
6
|
from classiq._internals.api_wrapper import ApiWrapper
|
|
7
|
+
from classiq.execution.functions.util.parse_provider_backend import (
|
|
8
|
+
_PROVIDER_TO_CANONICAL_NAME,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from pandas import DataFrame
|
|
5
13
|
|
|
6
14
|
|
|
7
15
|
def get_all_hardware_devices() -> list[HardwareInformation]:
|
|
@@ -9,3 +17,53 @@ def get_all_hardware_devices() -> list[HardwareInformation]:
|
|
|
9
17
|
Returns a list of all hardware devices known to Classiq.
|
|
10
18
|
"""
|
|
11
19
|
return async_utils.run(ApiWrapper.call_get_all_hardware_devices())
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _extract_relevant_hardware_fields_for_user(info: HardwareInformation) -> tuple:
|
|
23
|
+
return (
|
|
24
|
+
_PROVIDER_TO_CANONICAL_NAME[info.provider],
|
|
25
|
+
info.name,
|
|
26
|
+
info.number_of_qubits,
|
|
27
|
+
info.status.availability.is_available,
|
|
28
|
+
info.status.pending_jobs,
|
|
29
|
+
info.status.queue_time,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
_NON_DISPLAYED_DEVICES = [
|
|
34
|
+
(Provider.CLASSIQ, "simulator_statevector"),
|
|
35
|
+
(Provider.CLASSIQ, "nvidia_simulator_statevector"),
|
|
36
|
+
(Provider.GOOGLE, "cuquantum_statevector"),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_backend_details() -> "DataFrame":
|
|
41
|
+
"""
|
|
42
|
+
Returns a pandas DataFrame containing hardware devices known to Classiq.
|
|
43
|
+
"""
|
|
44
|
+
from pandas import DataFrame
|
|
45
|
+
|
|
46
|
+
devices = get_all_hardware_devices()
|
|
47
|
+
displayed_devices = [
|
|
48
|
+
device
|
|
49
|
+
for device in devices
|
|
50
|
+
if (device.provider, device.name) not in _NON_DISPLAYED_DEVICES
|
|
51
|
+
]
|
|
52
|
+
# Remove "ibm_" prefix.
|
|
53
|
+
for device in displayed_devices:
|
|
54
|
+
if device.provider == Provider.IBM_QUANTUM and device.name.startswith("ibm_"):
|
|
55
|
+
device.name = device.name[len("ibm_") :]
|
|
56
|
+
tuples = [
|
|
57
|
+
_extract_relevant_hardware_fields_for_user(info) for info in displayed_devices
|
|
58
|
+
]
|
|
59
|
+
return DataFrame(
|
|
60
|
+
tuples,
|
|
61
|
+
columns=[
|
|
62
|
+
"provider",
|
|
63
|
+
"name",
|
|
64
|
+
"number of qubits",
|
|
65
|
+
"available",
|
|
66
|
+
"pending jobs",
|
|
67
|
+
"queue time",
|
|
68
|
+
],
|
|
69
|
+
)
|
|
@@ -365,7 +365,7 @@ class ExecutionSession:
|
|
|
365
365
|
A list of tuples, each containing the estimated cost and the corresponding parameters for that iteration. `cost` is a float, and `parameters` is a dictionary matching the execution parameter format.
|
|
366
366
|
|
|
367
367
|
See Also:
|
|
368
|
-
The [
|
|
368
|
+
The [Execution Tutorial](https://docs.classiq.io/latest/getting-started/classiq_tutorial/execution_tutorial_part2/) has examples on using this method in variational quantum algorithms.
|
|
369
369
|
More information about [Hamiltonians](https://docs.classiq.io/latest/qmod-reference/language-reference/classical-types/#hamiltonians).
|
|
370
370
|
"""
|
|
371
371
|
_hamiltonian_deprecation_warning(cost_function)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from classiq.execution.functions.expectation_value import _get_expectation_value
|
|
2
|
+
from classiq.execution.functions.minimize import _minimize
|
|
3
|
+
from classiq.execution.functions.sample import _new_sample
|
|
4
|
+
from classiq.execution.functions.state_vector import _calculate_state_vector
|
|
5
|
+
from classiq.execution.functions.util.constants import Verbosity
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"Verbosity",
|
|
9
|
+
"_calculate_state_vector",
|
|
10
|
+
"_get_expectation_value",
|
|
11
|
+
"_minimize",
|
|
12
|
+
"_new_sample",
|
|
13
|
+
]
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from classiq.interface.backend.backend_preferences import (
|
|
4
|
+
BackendPreferencesTypes,
|
|
5
|
+
ClassiqBackendPreferences,
|
|
6
|
+
)
|
|
7
|
+
from classiq.interface.backend.provider_config.provider_config import ProviderConfig
|
|
8
|
+
from classiq.interface.backend.quantum_backend_providers import (
|
|
9
|
+
ClassiqSimulatorBackendNames,
|
|
10
|
+
)
|
|
11
|
+
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
|
12
|
+
from classiq.interface.generator.model.preferences import create_random_seed
|
|
13
|
+
from classiq.interface.generator.model.preferences.preferences import (
|
|
14
|
+
TranspilationOption,
|
|
15
|
+
)
|
|
16
|
+
from classiq.interface.hardware import Provider
|
|
17
|
+
|
|
18
|
+
from classiq import (
|
|
19
|
+
ExecutionParams,
|
|
20
|
+
QuantumProgram,
|
|
21
|
+
)
|
|
22
|
+
from classiq.execution.execution_session import ExecutionSession
|
|
23
|
+
from classiq.execution.functions.util._logging import _logger
|
|
24
|
+
from classiq.execution.functions.util.backend_preferences import (
|
|
25
|
+
_get_backend_preferences_from_specifier,
|
|
26
|
+
)
|
|
27
|
+
from classiq.execution.functions.util.constants import Verbosity
|
|
28
|
+
from classiq.execution.functions.util.parse_provider_backend import (
|
|
29
|
+
_parse_provider_backend,
|
|
30
|
+
)
|
|
31
|
+
from classiq.qmod.builtins.structs import SparsePauliOp
|
|
32
|
+
|
|
33
|
+
_DEFAULT_BACKEND_NAME = "simulator"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _get_backend_preferences(
|
|
37
|
+
backend: str, estimate: bool, config: dict[str, Any] | ProviderConfig | None
|
|
38
|
+
) -> BackendPreferencesTypes:
|
|
39
|
+
provider, backend_name = _parse_provider_backend(backend)
|
|
40
|
+
backend_preferences: BackendPreferencesTypes
|
|
41
|
+
if not estimate:
|
|
42
|
+
if not (
|
|
43
|
+
provider == Provider.CLASSIQ and backend_name.lower().strip() == "simulator"
|
|
44
|
+
):
|
|
45
|
+
raise ValueError(
|
|
46
|
+
"Calculating exact expectation value is supported only for the 'classiq/simulator' backend"
|
|
47
|
+
)
|
|
48
|
+
backend_preferences = ClassiqBackendPreferences(
|
|
49
|
+
# This backend name is for exact simulation
|
|
50
|
+
backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR
|
|
51
|
+
)
|
|
52
|
+
else:
|
|
53
|
+
backend_preferences = _get_backend_preferences_from_specifier(
|
|
54
|
+
backend, config or {}
|
|
55
|
+
)
|
|
56
|
+
return backend_preferences
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _get_expectation_value(
|
|
60
|
+
qprog: QuantumProgram,
|
|
61
|
+
observable: SparsePauliOp,
|
|
62
|
+
backend: str | None = None,
|
|
63
|
+
*,
|
|
64
|
+
estimate: bool = True,
|
|
65
|
+
parameters: ExecutionParams | None = None,
|
|
66
|
+
config: dict[str, Any] | ProviderConfig | None = None,
|
|
67
|
+
num_shots: int | None = None,
|
|
68
|
+
random_seed: int | None = None,
|
|
69
|
+
transpilation_option: TranspilationOption = TranspilationOption.DECOMPOSE,
|
|
70
|
+
verbosity: Verbosity = Verbosity.INFO,
|
|
71
|
+
) -> complex:
|
|
72
|
+
"""
|
|
73
|
+
Get the expectation value of the observable O with respect to the state |psi>
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
qprog: The quantum program which generates the state |psi> to be observed
|
|
77
|
+
observable: The observable O
|
|
78
|
+
backend: The device (hardware or simulator) on which to run the quantum program. Specified as "provider/device_id". Use the `get_backend_details` function to see supported devices.
|
|
79
|
+
estimate: Whether to estimate the expectation value by repeatedly measuring the circuit, or else calculate the expectation value using a simulator.
|
|
80
|
+
parameters: The classical parameters for the quantum program
|
|
81
|
+
config: Provider-specific configuration, such as api keys
|
|
82
|
+
num_shots:
|
|
83
|
+
random_seed: The random seed used for transpilation and simulation
|
|
84
|
+
transpilation_option: Advanced configuration for hardware-specific transpilation
|
|
85
|
+
verbosity: What level of information should be logged
|
|
86
|
+
|
|
87
|
+
Returns: The expectation value
|
|
88
|
+
"""
|
|
89
|
+
if backend is None:
|
|
90
|
+
backend = _DEFAULT_BACKEND_NAME
|
|
91
|
+
backend_preferences = _get_backend_preferences(backend, estimate, config)
|
|
92
|
+
ep = ExecutionPreferences(
|
|
93
|
+
backend_preferences=backend_preferences,
|
|
94
|
+
num_shots=num_shots,
|
|
95
|
+
random_seed=create_random_seed() if random_seed is None else random_seed,
|
|
96
|
+
transpile_to_hardware=transpilation_option,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
if verbosity != Verbosity.QUIET:
|
|
100
|
+
_logger.info(f"Submitting job to {backend}")
|
|
101
|
+
with ExecutionSession(qprog, execution_preferences=ep) as session:
|
|
102
|
+
job = session.submit_estimate(hamiltonian=observable, parameters=parameters)
|
|
103
|
+
if verbosity != Verbosity.QUIET:
|
|
104
|
+
_logger.info(f"Job id: {job.id}")
|
|
105
|
+
result = job.get_estimate_result()
|
|
106
|
+
return result.value
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from classiq.interface.backend.provider_config.provider_config import ProviderConfig
|
|
4
|
+
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
|
5
|
+
from classiq.interface.generator.model.preferences import create_random_seed
|
|
6
|
+
from classiq.interface.generator.model.preferences.preferences import (
|
|
7
|
+
TranspilationOption,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from classiq import (
|
|
11
|
+
ExecutionParams,
|
|
12
|
+
QuantumProgram,
|
|
13
|
+
)
|
|
14
|
+
from classiq.execution.execution_session import ExecutionSession
|
|
15
|
+
from classiq.execution.functions.util._logging import _logger
|
|
16
|
+
from classiq.execution.functions.util.backend_preferences import (
|
|
17
|
+
_get_backend_preferences_from_specifier,
|
|
18
|
+
)
|
|
19
|
+
from classiq.execution.functions.util.constants import Verbosity
|
|
20
|
+
from classiq.qmod.builtins.structs import SparsePauliOp
|
|
21
|
+
from classiq.qmod.qmod_variable import QmodExpressionCreator
|
|
22
|
+
|
|
23
|
+
_DEFAULT_BACKEND_NAME = "simulator"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _minimize(
|
|
27
|
+
qprog: QuantumProgram,
|
|
28
|
+
cost_function: SparsePauliOp | QmodExpressionCreator,
|
|
29
|
+
initial_params: ExecutionParams,
|
|
30
|
+
max_iteration: int,
|
|
31
|
+
backend: str | None = None,
|
|
32
|
+
*,
|
|
33
|
+
quantile: float = 1.0,
|
|
34
|
+
tolerance: float | None = None,
|
|
35
|
+
config: dict[str, Any] | ProviderConfig | None = None,
|
|
36
|
+
random_seed: int | None = None,
|
|
37
|
+
transpilation_option: TranspilationOption = TranspilationOption.DECOMPOSE,
|
|
38
|
+
verbosity: Verbosity = Verbosity.INFO,
|
|
39
|
+
) -> list[tuple[float, ExecutionParams]]:
|
|
40
|
+
"""
|
|
41
|
+
Minimize the given cost function using the quantum program.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
qprog: The parametric quantum program that generates the state (ansatz).
|
|
45
|
+
Only quantum programs with exactly one execution parameter are supported.
|
|
46
|
+
cost_function: The cost function to minimize. It can be one of the following:
|
|
47
|
+
- A quantum cost function defined by a Hamiltonian.
|
|
48
|
+
- A classical cost function represented as a callable that returns a Qmod expression.
|
|
49
|
+
The callable should accept `QVar`s as arguments and use names matching the Model outputs.
|
|
50
|
+
initial_params: The initial parameters for the minimization.
|
|
51
|
+
This parameter must be of type `CReal` or `CArray`. The dictionary must contain a single key-value pair, where:
|
|
52
|
+
- The key is the name of the parameter.
|
|
53
|
+
- The value is either a float or a list of floats.
|
|
54
|
+
max_iteration: The maximum number of iterations for the minimization.
|
|
55
|
+
backend: The device (hardware or simulator) on which to run the quantum programs. Specified as "provider/device_id". Use the `get_backend_details` function to see supported devices.
|
|
56
|
+
quantile: The quantile to use for cost estimation.
|
|
57
|
+
tolerance: The tolerance for the minimization.
|
|
58
|
+
config: Provider-specific configuration, such as api keys
|
|
59
|
+
random_seed: Set this to increase determinism
|
|
60
|
+
transpilation_option: Advanced configuration for hardware-specific transpilation
|
|
61
|
+
verbosity: What level of information should be logged
|
|
62
|
+
Returns:
|
|
63
|
+
A list of tuples, each containing the estimated cost and the corresponding parameters for that iteration. `cost` is a float, and `parameters` is a dictionary matching the execution parameter format.
|
|
64
|
+
|
|
65
|
+
See Also:
|
|
66
|
+
The [Execution Tutorial](https://docs.classiq.io/latest/getting-started/classiq_tutorial/execution_tutorial_part2/) has examples on using this method in variational quantum algorithms.
|
|
67
|
+
More information about [Hamiltonians](https://docs.classiq.io/latest/qmod-reference/language-reference/classical-types/#hamiltonians).
|
|
68
|
+
"""
|
|
69
|
+
if backend is None:
|
|
70
|
+
backend = _DEFAULT_BACKEND_NAME
|
|
71
|
+
backend_preferences = _get_backend_preferences_from_specifier(backend, config or {})
|
|
72
|
+
|
|
73
|
+
ep = ExecutionPreferences(
|
|
74
|
+
backend_preferences=backend_preferences,
|
|
75
|
+
random_seed=create_random_seed() if random_seed is None else random_seed,
|
|
76
|
+
transpile_to_hardware=transpilation_option,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if verbosity != Verbosity.QUIET:
|
|
80
|
+
_logger.info(f"Submitting job to {backend}")
|
|
81
|
+
with ExecutionSession(qprog, execution_preferences=ep) as session:
|
|
82
|
+
job = session.submit_minimize(
|
|
83
|
+
cost_function, initial_params, max_iteration, quantile, tolerance
|
|
84
|
+
)
|
|
85
|
+
if verbosity != Verbosity.QUIET:
|
|
86
|
+
_logger.info(f"Job id: {job.id}")
|
|
87
|
+
result = job.get_minimization_result()
|
|
88
|
+
return session._minimize_result_to_result(
|
|
89
|
+
result=result, initial_params=initial_params
|
|
90
|
+
)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any
|
|
2
|
+
|
|
3
|
+
from classiq.execution.functions.util.backend_preferences import (
|
|
4
|
+
_get_backend_preferences_from_specifier,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from pandas import DataFrame
|
|
9
|
+
|
|
10
|
+
from classiq.interface.backend.provider_config.provider_config import ProviderConfig
|
|
11
|
+
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
|
12
|
+
from classiq.interface.generator.model.preferences import create_random_seed
|
|
13
|
+
from classiq.interface.generator.model.preferences.preferences import (
|
|
14
|
+
TranspilationOption,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from classiq import (
|
|
18
|
+
ExecutionParams,
|
|
19
|
+
QuantumProgram,
|
|
20
|
+
)
|
|
21
|
+
from classiq.execution import ExecutionSession
|
|
22
|
+
from classiq.execution.functions.util._logging import _logger
|
|
23
|
+
from classiq.execution.functions.util.constants import Verbosity
|
|
24
|
+
|
|
25
|
+
_DEFAULT_BACKEND_NAME = "simulator"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _new_sample(
|
|
29
|
+
qprog: QuantumProgram,
|
|
30
|
+
backend: str | None = None,
|
|
31
|
+
*,
|
|
32
|
+
parameters: ExecutionParams | None = None,
|
|
33
|
+
config: dict[str, Any] | ProviderConfig | None = None,
|
|
34
|
+
num_shots: int | None = None,
|
|
35
|
+
random_seed: int | None = None,
|
|
36
|
+
transpilation_option: TranspilationOption = TranspilationOption.DECOMPOSE,
|
|
37
|
+
verbosity: Verbosity = Verbosity.INFO,
|
|
38
|
+
) -> "DataFrame":
|
|
39
|
+
"""
|
|
40
|
+
Sample a quantum program.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
qprog: The quantum program
|
|
44
|
+
backend: The device (hardware or simulator) on which to run the quantum program. Specified as "provider/device_id". Use the `get_backend_details` function to see supported devices.
|
|
45
|
+
parameters: The classical parameters for the quantum program
|
|
46
|
+
config: Provider-specific configuration, such as api keys
|
|
47
|
+
num_shots: The number of times to sample
|
|
48
|
+
random_seed: The random seed used for transpilation and simulation
|
|
49
|
+
transpilation_option: Advanced configuration for hardware-specific transpilation
|
|
50
|
+
verbosity: What level of information should be logged
|
|
51
|
+
|
|
52
|
+
Returns: A dataframe containing the histogram
|
|
53
|
+
"""
|
|
54
|
+
if num_shots is not None and num_shots < 1:
|
|
55
|
+
raise ValueError(f"Argument num_shots must be greater than 0, got {num_shots}")
|
|
56
|
+
if config is None:
|
|
57
|
+
config = {}
|
|
58
|
+
if backend is None:
|
|
59
|
+
backend = _DEFAULT_BACKEND_NAME
|
|
60
|
+
backend_preferences = _get_backend_preferences_from_specifier(backend, config)
|
|
61
|
+
ep = ExecutionPreferences(
|
|
62
|
+
backend_preferences=backend_preferences,
|
|
63
|
+
num_shots=num_shots,
|
|
64
|
+
random_seed=create_random_seed() if random_seed is None else random_seed,
|
|
65
|
+
transpile_to_hardware=transpilation_option,
|
|
66
|
+
)
|
|
67
|
+
if verbosity != Verbosity.QUIET:
|
|
68
|
+
_logger.info(f"Submitting job to {backend}")
|
|
69
|
+
with ExecutionSession(qprog, execution_preferences=ep) as session:
|
|
70
|
+
job = session.submit_sample(parameters)
|
|
71
|
+
if verbosity != Verbosity.QUIET:
|
|
72
|
+
_logger.info(f"Job id: {job.id}")
|
|
73
|
+
result = job.get_sample_result()
|
|
74
|
+
|
|
75
|
+
df = result.dataframe
|
|
76
|
+
return df
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from pandas import DataFrame
|
|
5
|
+
|
|
6
|
+
from classiq.interface.backend.backend_preferences import (
|
|
7
|
+
BackendPreferencesTypes,
|
|
8
|
+
ClassiqBackendPreferences,
|
|
9
|
+
GCPBackendPreferences,
|
|
10
|
+
)
|
|
11
|
+
from classiq.interface.backend.quantum_backend_providers import (
|
|
12
|
+
ClassiqNvidiaBackendNames,
|
|
13
|
+
ClassiqSimulatorBackendNames,
|
|
14
|
+
GoogleNvidiaBackendNames,
|
|
15
|
+
)
|
|
16
|
+
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
|
17
|
+
from classiq.interface.generator.model.preferences import create_random_seed
|
|
18
|
+
from classiq.interface.generator.model.preferences.preferences import (
|
|
19
|
+
TranspilationOption,
|
|
20
|
+
)
|
|
21
|
+
from classiq.interface.hardware import Provider
|
|
22
|
+
|
|
23
|
+
from classiq import (
|
|
24
|
+
ExecutionParams,
|
|
25
|
+
QuantumProgram,
|
|
26
|
+
)
|
|
27
|
+
from classiq.execution import ExecutionSession
|
|
28
|
+
from classiq.execution.functions.util._logging import _logger
|
|
29
|
+
from classiq.execution.functions.util.constants import Verbosity
|
|
30
|
+
from classiq.execution.functions.util.parse_provider_backend import (
|
|
31
|
+
_PROVIDER_TO_CANONICAL_NAME,
|
|
32
|
+
_parse_provider_backend,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
_DEFAULT_STATE_VECTOR_BACKEND_NAME = "simulator"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _calculate_state_vector(
|
|
39
|
+
qprog: QuantumProgram,
|
|
40
|
+
backend: str | None = None,
|
|
41
|
+
*,
|
|
42
|
+
parameters: ExecutionParams | None = None,
|
|
43
|
+
filters: dict[str, Any] | None = None,
|
|
44
|
+
random_seed: int | None = None,
|
|
45
|
+
transpilation_option: TranspilationOption = TranspilationOption.DECOMPOSE,
|
|
46
|
+
verbosity: Verbosity = Verbosity.INFO,
|
|
47
|
+
) -> "DataFrame":
|
|
48
|
+
"""
|
|
49
|
+
Calculate the state vector of a quantum program.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
qprog: The quantum program
|
|
53
|
+
backend: The simulator on which to simulate the quantum program. Specified as "provider/device_id"
|
|
54
|
+
parameters: The classical parameters for the quantum program
|
|
55
|
+
filters: Only states where the variables match these values will be included in the state vector.
|
|
56
|
+
random_seed: The random seed used for transpilation and simulation
|
|
57
|
+
transpilation_option: Advanced configuration for hardware-specific transpilation
|
|
58
|
+
verbosity: What level of information should be logged
|
|
59
|
+
|
|
60
|
+
Returns: A dataframe containing the state vector
|
|
61
|
+
"""
|
|
62
|
+
if backend is None:
|
|
63
|
+
backend = _DEFAULT_STATE_VECTOR_BACKEND_NAME
|
|
64
|
+
|
|
65
|
+
provider, raw_backend_name = _parse_provider_backend(backend)
|
|
66
|
+
backend_name_lower = raw_backend_name.lower()
|
|
67
|
+
backend_preferences: BackendPreferencesTypes
|
|
68
|
+
|
|
69
|
+
if provider == Provider.CLASSIQ:
|
|
70
|
+
if backend_name_lower == "simulator":
|
|
71
|
+
backend_name = str(ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR)
|
|
72
|
+
elif backend_name_lower == "nvidia_simulator":
|
|
73
|
+
backend_name = str(ClassiqNvidiaBackendNames.SIMULATOR_STATEVECTOR)
|
|
74
|
+
else:
|
|
75
|
+
raise ValueError(
|
|
76
|
+
f"Unsupported backend '{backend}'. "
|
|
77
|
+
"Under the Classiq provider, only 'classiq/simulator' and 'classiq/nvidia_simulator' are supported."
|
|
78
|
+
)
|
|
79
|
+
backend_preferences = ClassiqBackendPreferences(backend_name=backend_name)
|
|
80
|
+
elif provider == Provider.GOOGLE:
|
|
81
|
+
if backend_name_lower == "cuquantum":
|
|
82
|
+
backend_name = str(GoogleNvidiaBackendNames.CUQUANTUM_STATEVECTOR)
|
|
83
|
+
else:
|
|
84
|
+
raise ValueError(
|
|
85
|
+
f"Unsupported backend '{backend}'. "
|
|
86
|
+
"Under the Google provider, only 'google/cuquantum' is supported."
|
|
87
|
+
)
|
|
88
|
+
backend_preferences = GCPBackendPreferences(backend_name=backend_name)
|
|
89
|
+
else:
|
|
90
|
+
raise ValueError(
|
|
91
|
+
f"Provider '{_PROVIDER_TO_CANONICAL_NAME.get(provider) or provider}' does not support this operation."
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
ep = ExecutionPreferences(
|
|
95
|
+
backend_preferences=backend_preferences,
|
|
96
|
+
random_seed=create_random_seed() if random_seed is None else random_seed,
|
|
97
|
+
transpile_to_hardware=transpilation_option,
|
|
98
|
+
)
|
|
99
|
+
if verbosity != Verbosity.QUIET:
|
|
100
|
+
_logger.info(f"Submitting job to {backend}")
|
|
101
|
+
with ExecutionSession(qprog, execution_preferences=ep) as session:
|
|
102
|
+
if filters is not None:
|
|
103
|
+
for output_name, value in filters.items():
|
|
104
|
+
session.set_measured_state_filter(
|
|
105
|
+
output_name, lambda state, val=value: state == val
|
|
106
|
+
)
|
|
107
|
+
job = session.submit_sample(parameters)
|
|
108
|
+
if verbosity != Verbosity.QUIET:
|
|
109
|
+
_logger.info(f"Job id: {job.id}")
|
|
110
|
+
result = job.get_sample_result()
|
|
111
|
+
|
|
112
|
+
df = result.dataframe
|
|
113
|
+
return df
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
_logger = logging.getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _setup_logging() -> None:
|
|
7
|
+
if _logger.handlers:
|
|
8
|
+
return
|
|
9
|
+
|
|
10
|
+
handler = logging.StreamHandler()
|
|
11
|
+
formatter = logging.Formatter("%(message)s")
|
|
12
|
+
handler.setFormatter(formatter)
|
|
13
|
+
_logger.addHandler(handler)
|
|
14
|
+
_logger.setLevel(logging.INFO)
|
|
15
|
+
|
|
16
|
+
_logger.propagate = False
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
_setup_logging()
|