classiq 0.92.0__py3-none-any.whl → 0.99.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 +11 -19
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +7 -7
- classiq/_analyzer_extras/interactive_hardware.py +19 -12
- classiq/_internals/api_wrapper.py +31 -142
- classiq/_internals/async_utils.py +4 -7
- classiq/_internals/authentication/auth0.py +41 -15
- classiq/_internals/authentication/authorization_code.py +9 -0
- classiq/_internals/authentication/authorization_flow.py +41 -0
- classiq/_internals/authentication/device.py +33 -52
- classiq/_internals/authentication/hybrid_flow.py +19 -0
- classiq/_internals/authentication/password_manager.py +13 -13
- classiq/_internals/authentication/token_manager.py +9 -9
- classiq/_internals/client.py +17 -44
- classiq/_internals/config.py +19 -5
- classiq/_internals/help.py +1 -2
- classiq/_internals/host_checker.py +3 -3
- classiq/_internals/jobs.py +14 -14
- classiq/_internals/type_validation.py +3 -3
- classiq/analyzer/analyzer.py +18 -18
- classiq/analyzer/rb.py +17 -8
- classiq/analyzer/show_interactive_hack.py +1 -1
- classiq/applications/__init__.py +2 -2
- classiq/applications/chemistry/__init__.py +0 -30
- classiq/applications/chemistry/op_utils.py +4 -4
- classiq/applications/chemistry/problems.py +3 -3
- classiq/applications/chemistry/ucc.py +1 -2
- classiq/applications/chemistry/z2_symmetries.py +4 -4
- classiq/applications/combinatorial_helpers/allowed_constraints.py +1 -3
- classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +2 -1
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +2 -2
- classiq/applications/combinatorial_helpers/encoding_mapping.py +2 -3
- classiq/applications/combinatorial_helpers/encoding_utils.py +2 -2
- classiq/applications/combinatorial_helpers/optimization_model.py +3 -4
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +2 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +8 -8
- classiq/applications/combinatorial_helpers/sympy_utils.py +1 -3
- classiq/applications/combinatorial_helpers/transformations/encoding.py +3 -3
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +1 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -3
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +4 -6
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +15 -10
- classiq/applications/hamiltonian/pauli_decomposition.py +6 -4
- classiq/applications/iqae/iqae.py +14 -11
- classiq/applications/qnn/datasets/dataset_base_classes.py +6 -6
- classiq/applications/qnn/datasets/dataset_parity.py +6 -6
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
- classiq/applications/qnn/qlayer.py +9 -8
- classiq/applications/qnn/torch_utils.py +5 -6
- classiq/applications/qnn/types.py +2 -1
- classiq/applications/qsp/__init__.py +20 -2
- classiq/applications/qsp/qsp.py +239 -11
- classiq/applications/qsvm/qsvm_data_generation.py +1 -2
- classiq/evaluators/classical_expression.py +0 -4
- classiq/evaluators/parameter_types.py +20 -12
- classiq/evaluators/qmod_annotated_expression.py +31 -26
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +14 -14
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +2 -1
- classiq/evaluators/qmod_expression_visitors/sympy_wrappers.py +8 -8
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +4 -4
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +14 -4
- classiq/evaluators/qmod_node_evaluators/list_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +3 -3
- classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +9 -9
- classiq/evaluators/qmod_node_evaluators/utils.py +6 -6
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +9 -10
- classiq/evaluators/qmod_type_inference/quantum_type_inference.py +5 -5
- classiq/execution/__init__.py +0 -3
- classiq/execution/execution_session.py +28 -21
- classiq/execution/jobs.py +26 -26
- classiq/execution/qnn.py +1 -2
- classiq/execution/user_budgets.py +71 -37
- classiq/executor.py +1 -3
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +4 -4
- classiq/interface/analyzer/cytoscape_graph.py +3 -3
- classiq/interface/analyzer/result.py +4 -4
- classiq/interface/ast_node.py +3 -3
- classiq/interface/backend/backend_preferences.py +26 -50
- classiq/interface/backend/ionq/ionq_quantum_program.py +5 -5
- classiq/interface/backend/provider_config/__init__.py +0 -0
- classiq/interface/backend/provider_config/provider_config.py +8 -0
- classiq/interface/backend/provider_config/providers/__init__.py +0 -0
- classiq/interface/backend/provider_config/providers/alice_bob.py +47 -0
- classiq/interface/backend/provider_config/providers/aqt.py +16 -0
- classiq/interface/backend/provider_config/providers/azure.py +37 -0
- classiq/interface/backend/provider_config/providers/braket.py +39 -0
- classiq/interface/backend/provider_config/providers/ibm.py +26 -0
- classiq/interface/backend/provider_config/providers/ionq.py +22 -0
- classiq/interface/backend/quantum_backend_providers.py +20 -2
- classiq/interface/chemistry/ansatz_library.py +3 -5
- classiq/interface/chemistry/operator.py +3 -3
- classiq/interface/combinatorial_optimization/examples/knapsack.py +2 -4
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +1 -2
- classiq/interface/compression_utils.py +2 -3
- classiq/interface/debug_info/debug_info.py +8 -7
- classiq/interface/exceptions.py +10 -7
- classiq/interface/execution/primitives.py +6 -6
- classiq/interface/executor/estimate_cost.py +1 -1
- classiq/interface/executor/execution_preferences.py +3 -5
- classiq/interface/executor/execution_request.py +10 -10
- classiq/interface/executor/execution_result.py +1 -2
- classiq/interface/executor/quantum_code.py +8 -8
- classiq/interface/executor/result.py +28 -18
- classiq/interface/executor/user_budget.py +25 -17
- classiq/interface/executor/vqe_result.py +5 -6
- classiq/interface/generator/ansatz_library.py +6 -8
- classiq/interface/generator/application_apis/__init__.py +0 -3
- classiq/interface/generator/arith/arithmetic.py +2 -2
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +2 -3
- classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -5
- classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -4
- classiq/interface/generator/arith/arithmetic_expression_validator.py +12 -15
- classiq/interface/generator/arith/arithmetic_operations.py +4 -6
- classiq/interface/generator/arith/arithmetic_param_getters.py +70 -107
- classiq/interface/generator/arith/arithmetic_result_builder.py +4 -4
- classiq/interface/generator/arith/ast_node_rewrite.py +8 -4
- classiq/interface/generator/arith/binary_ops.py +15 -40
- classiq/interface/generator/arith/logical_ops.py +2 -3
- classiq/interface/generator/arith/number_utils.py +2 -2
- classiq/interface/generator/arith/register_user_input.py +3 -3
- classiq/interface/generator/arith/unary_ops.py +2 -2
- classiq/interface/generator/circuit_code/circuit_code.py +8 -10
- classiq/interface/generator/circuit_code/types_and_constants.py +1 -1
- classiq/interface/generator/complex_type.py +2 -2
- classiq/interface/generator/copy.py +1 -3
- classiq/interface/generator/expressions/atomic_expression_functions.py +0 -5
- classiq/interface/generator/expressions/evaluated_expression.py +2 -3
- classiq/interface/generator/expressions/expression.py +2 -2
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -7
- classiq/interface/generator/function_param_list.py +0 -40
- classiq/interface/generator/function_params.py +5 -6
- classiq/interface/generator/functions/classical_function_declaration.py +2 -2
- classiq/interface/generator/functions/classical_type.py +3 -3
- classiq/interface/generator/functions/type_modifier.py +0 -15
- classiq/interface/generator/functions/type_name.py +2 -2
- classiq/interface/generator/generated_circuit_data.py +14 -18
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +2 -4
- classiq/interface/generator/hardware/hardware_data.py +8 -8
- classiq/interface/generator/hardware_efficient_ansatz.py +9 -9
- classiq/interface/generator/mcu.py +3 -3
- classiq/interface/generator/mcx.py +3 -3
- classiq/interface/generator/model/constraints.py +34 -5
- classiq/interface/generator/model/preferences/preferences.py +15 -21
- classiq/interface/generator/model/quantum_register.py +7 -10
- classiq/interface/generator/noise_properties.py +3 -7
- classiq/interface/generator/parameters.py +1 -1
- classiq/interface/generator/partitioned_register.py +1 -2
- classiq/interface/generator/preferences/qasm_to_qmod_params.py +11 -0
- classiq/interface/generator/quantum_function_call.py +9 -12
- classiq/interface/generator/quantum_program.py +10 -23
- classiq/interface/generator/range_types.py +3 -3
- classiq/interface/generator/slice_parsing_utils.py +4 -5
- classiq/interface/generator/standard_gates/standard_gates.py +2 -4
- classiq/interface/generator/synthesis_execution_parameter.py +1 -3
- classiq/interface/generator/synthesis_metadata/synthesis_duration.py +9 -0
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +2 -3
- classiq/interface/generator/transpiler_basis_gates.py +12 -4
- classiq/interface/generator/types/builtin_enum_declarations.py +0 -145
- classiq/interface/generator/types/compilation_metadata.py +12 -1
- classiq/interface/generator/types/enum_declaration.py +2 -1
- classiq/interface/generator/validations/flow_graph.py +3 -3
- classiq/interface/generator/visitor.py +10 -12
- classiq/interface/hardware.py +2 -3
- classiq/interface/helpers/classproperty.py +2 -2
- classiq/interface/helpers/custom_encoders.py +2 -1
- classiq/interface/helpers/custom_pydantic_types.py +1 -1
- classiq/interface/helpers/text_utils.py +1 -4
- classiq/interface/ide/visual_model.py +6 -5
- classiq/interface/interface_version.py +1 -1
- classiq/interface/jobs.py +3 -3
- classiq/interface/model/allocate.py +4 -4
- classiq/interface/model/block.py +6 -2
- classiq/interface/model/bounds.py +3 -3
- classiq/interface/model/classical_if.py +4 -0
- classiq/interface/model/control.py +8 -1
- classiq/interface/model/inplace_binary_operation.py +2 -2
- classiq/interface/model/invert.py +4 -0
- classiq/interface/model/model.py +4 -4
- classiq/interface/model/model_visitor.py +40 -1
- classiq/interface/model/parameter.py +1 -3
- classiq/interface/model/port_declaration.py +1 -1
- classiq/interface/model/power.py +4 -0
- classiq/interface/model/quantum_expressions/quantum_expression.py +1 -2
- classiq/interface/model/quantum_function_call.py +3 -6
- classiq/interface/model/quantum_function_declaration.py +1 -0
- classiq/interface/model/quantum_lambda_function.py +4 -4
- classiq/interface/model/quantum_statement.py +11 -4
- classiq/interface/model/quantum_type.py +14 -14
- classiq/interface/model/repeat.py +4 -0
- classiq/interface/model/skip_control.py +4 -0
- classiq/interface/model/validation_handle.py +2 -3
- classiq/interface/model/variable_declaration_statement.py +2 -2
- classiq/interface/model/within_apply_operation.py +4 -0
- classiq/interface/pretty_print/expression_to_qmod.py +3 -4
- classiq/interface/server/routes.py +0 -16
- classiq/interface/source_reference.py +3 -4
- classiq/model_expansions/arithmetic.py +11 -7
- classiq/model_expansions/arithmetic_compute_result_attrs.py +30 -27
- classiq/model_expansions/capturing/captured_vars.py +3 -3
- classiq/model_expansions/capturing/mangling_utils.py +1 -2
- classiq/model_expansions/closure.py +12 -11
- classiq/model_expansions/function_builder.py +14 -6
- classiq/model_expansions/generative_functions.py +7 -12
- classiq/model_expansions/interpreters/base_interpreter.py +3 -7
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
- classiq/model_expansions/interpreters/generative_interpreter.py +8 -4
- classiq/model_expansions/quantum_operations/allocate.py +4 -4
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +8 -4
- classiq/model_expansions/quantum_operations/call_emitter.py +31 -37
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +2 -2
- classiq/model_expansions/quantum_operations/emitter.py +3 -5
- classiq/model_expansions/quantum_operations/expression_evaluator.py +3 -3
- classiq/model_expansions/quantum_operations/skip_control_verifier.py +1 -2
- classiq/model_expansions/quantum_operations/variable_decleration.py +61 -29
- classiq/model_expansions/scope.py +7 -7
- classiq/model_expansions/scope_initialization.py +4 -0
- classiq/model_expansions/visitors/symbolic_param_inference.py +6 -6
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +328 -0
- classiq/model_expansions/visitors/variable_references.py +15 -14
- classiq/open_library/functions/__init__.py +28 -11
- classiq/open_library/functions/amplitude_loading.py +81 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +19 -14
- classiq/open_library/functions/grover.py +8 -10
- classiq/open_library/functions/lcu.py +47 -18
- classiq/open_library/functions/modular_exponentiation.py +93 -8
- classiq/open_library/functions/qsvt.py +66 -79
- classiq/open_library/functions/qsvt_temp.py +536 -0
- classiq/open_library/functions/state_preparation.py +130 -27
- classiq/qmod/__init__.py +6 -4
- classiq/qmod/builtins/classical_execution_primitives.py +4 -23
- classiq/qmod/builtins/classical_functions.py +1 -42
- classiq/qmod/builtins/enums.py +15 -153
- classiq/qmod/builtins/functions/__init__.py +9 -18
- classiq/qmod/builtins/functions/allocation.py +25 -4
- classiq/qmod/builtins/functions/arithmetic.py +22 -27
- classiq/qmod/builtins/functions/exponentiation.py +51 -2
- classiq/qmod/builtins/functions/mcx_func.py +7 -0
- classiq/qmod/builtins/functions/standard_gates.py +46 -27
- classiq/qmod/builtins/operations.py +173 -79
- classiq/qmod/builtins/structs.py +24 -91
- classiq/qmod/cfunc.py +3 -2
- classiq/qmod/classical_function.py +2 -1
- classiq/qmod/classical_variable.py +4 -2
- classiq/qmod/cparam.py +2 -8
- classiq/qmod/create_model_function.py +7 -7
- classiq/qmod/declaration_inferrer.py +33 -30
- classiq/qmod/expression_query.py +7 -4
- classiq/qmod/model_state_container.py +2 -2
- classiq/qmod/native/pretty_printer.py +25 -14
- classiq/qmod/pretty_print/expression_to_python.py +5 -3
- classiq/qmod/pretty_print/pretty_printer.py +39 -17
- classiq/qmod/python_classical_type.py +40 -13
- classiq/qmod/qfunc.py +124 -19
- classiq/qmod/qmod_constant.py +2 -2
- classiq/qmod/qmod_parameter.py +5 -2
- classiq/qmod/qmod_variable.py +47 -46
- classiq/qmod/quantum_callable.py +18 -13
- classiq/qmod/quantum_expandable.py +33 -26
- classiq/qmod/quantum_function.py +84 -36
- classiq/qmod/semantics/annotation/call_annotation.py +5 -5
- classiq/qmod/semantics/error_manager.py +12 -14
- classiq/qmod/semantics/lambdas.py +1 -2
- classiq/qmod/semantics/validation/types_validation.py +1 -2
- classiq/qmod/symbolic.py +2 -4
- classiq/qmod/symbolic_expr.py +12 -4
- classiq/qmod/utilities.py +13 -20
- classiq/qmod/write_qmod.py +3 -4
- classiq/quantum_program.py +1 -3
- classiq/synthesis.py +11 -7
- {classiq-0.92.0.dist-info → classiq-0.99.0.dist-info}/METADATA +38 -37
- {classiq-0.92.0.dist-info → classiq-0.99.0.dist-info}/RECORD +273 -300
- classiq-0.99.0.dist-info/WHEEL +4 -0
- classiq-0.99.0.dist-info/licenses/LICENSE.txt +27 -0
- classiq/applications/chemistry/ansatz_parameters.py +0 -29
- classiq/applications/chemistry/chemistry_execution_parameters.py +0 -16
- classiq/applications/chemistry/chemistry_model_constructor.py +0 -532
- classiq/applications/chemistry/ground_state_problem.py +0 -42
- classiq/applications/qsvm/__init__.py +0 -8
- classiq/applications/qsvm/qsvm.py +0 -11
- classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -129
- classiq/execution/iqcc.py +0 -128
- classiq/interface/applications/qsvm.py +0 -117
- classiq/interface/chemistry/elements.py +0 -120
- classiq/interface/chemistry/fermionic_operator.py +0 -208
- classiq/interface/chemistry/ground_state_problem.py +0 -132
- classiq/interface/chemistry/ground_state_result.py +0 -8
- classiq/interface/chemistry/molecule.py +0 -71
- classiq/interface/execution/iqcc.py +0 -44
- classiq/interface/generator/application_apis/chemistry_declarations.py +0 -69
- classiq/interface/generator/application_apis/entangler_declarations.py +0 -29
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
- classiq/interface/generator/chemistry_function_params.py +0 -50
- classiq/interface/generator/entangler_params.py +0 -72
- classiq/interface/generator/entanglers.py +0 -14
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +0 -27
- classiq/interface/generator/hartree_fock.py +0 -26
- classiq/interface/generator/hva.py +0 -22
- classiq/interface/generator/linear_pauli_rotations.py +0 -92
- classiq/interface/generator/qft.py +0 -37
- classiq/interface/generator/qsvm.py +0 -96
- classiq/interface/generator/state_preparation/__init__.py +0 -14
- classiq/interface/generator/state_preparation/bell_state_preparation.py +0 -27
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +0 -28
- classiq/interface/generator/state_preparation/distributions.py +0 -53
- classiq/interface/generator/state_preparation/exponential_state_preparation.py +0 -14
- classiq/interface/generator/state_preparation/ghz_state_preparation.py +0 -14
- classiq/interface/generator/state_preparation/metrics.py +0 -41
- classiq/interface/generator/state_preparation/state_preparation.py +0 -113
- classiq/interface/generator/state_preparation/state_preparation_abc.py +0 -24
- classiq/interface/generator/state_preparation/uniform_distibution_state_preparation.py +0 -13
- classiq/interface/generator/state_preparation/w_state_preparation.py +0 -13
- classiq/interface/generator/ucc.py +0 -74
- classiq/interface/helpers/backward_compatibility.py +0 -9
- classiq/model_expansions/transformers/type_modifier_inference.py +0 -392
- classiq/open_library/functions/lookup_table.py +0 -58
- classiq/qmod/builtins/functions/chemistry.py +0 -123
- classiq/qmod/builtins/functions/qsvm.py +0 -24
- classiq-0.92.0.dist-info/WHEEL +0 -4
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
from typing import Optional, Union
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
import pydantic
|
|
5
|
-
from pydantic_core.core_schema import ValidationInfo
|
|
6
|
-
from typing_extensions import Self
|
|
7
|
-
|
|
8
|
-
from classiq.interface.exceptions import ClassiqValueError
|
|
9
|
-
from classiq.interface.generator.range_types import NonNegativeFloatRange
|
|
10
|
-
from classiq.interface.generator.state_preparation.distributions import (
|
|
11
|
-
PMF,
|
|
12
|
-
Amplitudes,
|
|
13
|
-
FlexibleAmplitudes,
|
|
14
|
-
FlexibleProbabilities,
|
|
15
|
-
GaussianMixture,
|
|
16
|
-
Probabilities,
|
|
17
|
-
num_of_qubits,
|
|
18
|
-
)
|
|
19
|
-
from classiq.interface.generator.state_preparation.metrics import Metrics
|
|
20
|
-
from classiq.interface.generator.state_preparation.state_preparation_abc import (
|
|
21
|
-
StatePreparationABC,
|
|
22
|
-
)
|
|
23
|
-
from classiq.interface.generator.validations.validator_functions import (
|
|
24
|
-
validate_amplitudes,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class StatePreparation(StatePreparationABC):
|
|
29
|
-
amplitudes: Optional[Amplitudes] = pydantic.Field(
|
|
30
|
-
description="vector of probabilities",
|
|
31
|
-
default=None,
|
|
32
|
-
validate_default=True,
|
|
33
|
-
)
|
|
34
|
-
probabilities: Optional[Probabilities] = pydantic.Field(
|
|
35
|
-
description="vector of amplitudes",
|
|
36
|
-
default=None,
|
|
37
|
-
validate_default=True,
|
|
38
|
-
)
|
|
39
|
-
error_metric: dict[Metrics, NonNegativeFloatRange] = pydantic.Field(
|
|
40
|
-
default_factory=lambda: {
|
|
41
|
-
Metrics.L2: NonNegativeFloatRange(lower_bound=0, upper_bound=1e-4)
|
|
42
|
-
}
|
|
43
|
-
)
|
|
44
|
-
# The order of validations is important: amplitudes, probabilities, error_metric
|
|
45
|
-
|
|
46
|
-
@pydantic.field_validator("amplitudes", mode="before")
|
|
47
|
-
@classmethod
|
|
48
|
-
def _initialize_amplitudes(
|
|
49
|
-
cls, amplitudes: Optional[FlexibleAmplitudes]
|
|
50
|
-
) -> Optional[Amplitudes]:
|
|
51
|
-
if amplitudes is None:
|
|
52
|
-
return None
|
|
53
|
-
amplitudes = np.array(amplitudes).squeeze()
|
|
54
|
-
if amplitudes.ndim == 1:
|
|
55
|
-
return validate_amplitudes(tuple(amplitudes))
|
|
56
|
-
|
|
57
|
-
raise ClassiqValueError(
|
|
58
|
-
"Invalid amplitudes were given, please ensure the amplitude is a vector of float in the form of either tuple or list or numpy array"
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
@pydantic.field_validator("probabilities", mode="before")
|
|
62
|
-
@classmethod
|
|
63
|
-
def _initialize_probabilities(
|
|
64
|
-
cls, probabilities: Optional[FlexibleProbabilities]
|
|
65
|
-
) -> Optional[Union[PMF, GaussianMixture, dict]]:
|
|
66
|
-
if probabilities is None:
|
|
67
|
-
return None
|
|
68
|
-
if isinstance(probabilities, Probabilities.__args__): # type: ignore[attr-defined]
|
|
69
|
-
return probabilities
|
|
70
|
-
if isinstance(probabilities, dict): # a pydantic object
|
|
71
|
-
return probabilities
|
|
72
|
-
probabilities = np.array(probabilities).squeeze()
|
|
73
|
-
if probabilities.ndim == 1:
|
|
74
|
-
return PMF(pmf=probabilities.tolist())
|
|
75
|
-
|
|
76
|
-
raise ClassiqValueError(
|
|
77
|
-
"Invalid probabilities were given, please ensure the probabilities is a vector of float in the form of either tuple or list or numpy array"
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
@pydantic.field_validator("error_metric", mode="before")
|
|
81
|
-
@classmethod
|
|
82
|
-
def _validate_error_metric(
|
|
83
|
-
cls, error_metric: dict[Metrics, NonNegativeFloatRange], info: ValidationInfo
|
|
84
|
-
) -> dict[Metrics, NonNegativeFloatRange]:
|
|
85
|
-
if not info.data.get("amplitudes"):
|
|
86
|
-
return error_metric
|
|
87
|
-
unsupported_metrics = {
|
|
88
|
-
Metrics(metric).value
|
|
89
|
-
for metric in error_metric
|
|
90
|
-
if not Metrics(metric).supports_amplitudes
|
|
91
|
-
}
|
|
92
|
-
if unsupported_metrics:
|
|
93
|
-
raise ClassiqValueError(
|
|
94
|
-
f"{unsupported_metrics} are not supported for amplitude preparation"
|
|
95
|
-
)
|
|
96
|
-
return error_metric
|
|
97
|
-
|
|
98
|
-
@pydantic.model_validator(mode="after")
|
|
99
|
-
def _validate_either_probabilities_or_amplitudes(self) -> Self:
|
|
100
|
-
amplitudes = self.amplitudes
|
|
101
|
-
probabilities = self.probabilities
|
|
102
|
-
if amplitudes is not None and probabilities is not None:
|
|
103
|
-
raise ClassiqValueError(
|
|
104
|
-
"StatePreparation can't get both probabilities and amplitudes"
|
|
105
|
-
)
|
|
106
|
-
return self
|
|
107
|
-
|
|
108
|
-
@property
|
|
109
|
-
def num_state_qubits(self) -> int:
|
|
110
|
-
distribution = self.probabilities or self.amplitudes
|
|
111
|
-
if distribution is None:
|
|
112
|
-
raise ClassiqValueError("Must have either probabilities or amplitudes")
|
|
113
|
-
return num_of_qubits(distribution)
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
|
|
3
|
-
from classiq.interface.generator.arith.register_user_input import RegisterUserInput
|
|
4
|
-
from classiq.interface.generator.function_params import (
|
|
5
|
-
DEFAULT_INPUT_NAME,
|
|
6
|
-
DEFAULT_OUTPUT_NAME,
|
|
7
|
-
FunctionParams,
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class StatePreparationABC(FunctionParams, abc.ABC):
|
|
12
|
-
@property
|
|
13
|
-
@abc.abstractmethod
|
|
14
|
-
def num_state_qubits(self) -> int:
|
|
15
|
-
pass
|
|
16
|
-
|
|
17
|
-
def _create_ios(self) -> None:
|
|
18
|
-
self._inputs = dict()
|
|
19
|
-
self._outputs = {
|
|
20
|
-
DEFAULT_OUTPUT_NAME: RegisterUserInput(
|
|
21
|
-
name=DEFAULT_OUTPUT_NAME, size=self.num_state_qubits
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
self._create_zero_input_registers({DEFAULT_INPUT_NAME: self.num_state_qubits})
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import pydantic
|
|
2
|
-
|
|
3
|
-
from classiq.interface.generator.state_preparation.state_preparation_abc import (
|
|
4
|
-
StatePreparationABC,
|
|
5
|
-
)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class UniformDistributionStatePreparation(StatePreparationABC):
|
|
9
|
-
num_qubits: pydantic.PositiveInt = pydantic.Field(default=2)
|
|
10
|
-
|
|
11
|
-
@property
|
|
12
|
-
def num_state_qubits(self) -> int:
|
|
13
|
-
return self.num_qubits
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import pydantic
|
|
2
|
-
|
|
3
|
-
from classiq.interface.generator.state_preparation.state_preparation_abc import (
|
|
4
|
-
StatePreparationABC,
|
|
5
|
-
)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class WStatePreparation(StatePreparationABC):
|
|
9
|
-
num_qubits: pydantic.PositiveInt = pydantic.Field(default=3)
|
|
10
|
-
|
|
11
|
-
@property
|
|
12
|
-
def num_state_qubits(self) -> int:
|
|
13
|
-
return self.num_qubits
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
from collections.abc import Iterable
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
import pydantic
|
|
5
|
-
|
|
6
|
-
from classiq.interface.exceptions import ClassiqValueError
|
|
7
|
-
from classiq.interface.generator.chemistry_function_params import (
|
|
8
|
-
ChemistryFunctionParams,
|
|
9
|
-
)
|
|
10
|
-
from classiq.interface.generator.excitations import (
|
|
11
|
-
EXCITATIONS_TYPE,
|
|
12
|
-
EXCITATIONS_TYPE_EXACT,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
_EXCITATIONS_DICT = {"s": 1, "d": 2, "t": 3, "q": 4}
|
|
16
|
-
|
|
17
|
-
DEFAULT_EXCITATIONS = [1, 2]
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def default_excitation_factory() -> EXCITATIONS_TYPE_EXACT:
|
|
21
|
-
return DEFAULT_EXCITATIONS
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class UCC(ChemistryFunctionParams):
|
|
25
|
-
"""
|
|
26
|
-
Ucc ansatz
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
use_naive_evolution: bool = pydantic.Field(
|
|
30
|
-
default=False, description="Whether to evolve the operator naively"
|
|
31
|
-
)
|
|
32
|
-
excitations: EXCITATIONS_TYPE = pydantic.Field(
|
|
33
|
-
default_factory=default_excitation_factory,
|
|
34
|
-
description="type of excitation operators in the UCC ansatz",
|
|
35
|
-
)
|
|
36
|
-
max_depth: Optional[pydantic.PositiveInt] = pydantic.Field(
|
|
37
|
-
default=None,
|
|
38
|
-
description="Maximum depth of the generated quantum circuit ansatz",
|
|
39
|
-
)
|
|
40
|
-
parameter_prefix: str = pydantic.Field(
|
|
41
|
-
default="ucc_param_",
|
|
42
|
-
description="Prefix for the generated parameters",
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
@pydantic.field_validator("excitations")
|
|
46
|
-
@classmethod
|
|
47
|
-
def _validate_excitations(cls, excitations: EXCITATIONS_TYPE) -> EXCITATIONS_TYPE:
|
|
48
|
-
if isinstance(excitations, int):
|
|
49
|
-
if excitations not in _EXCITATIONS_DICT.values():
|
|
50
|
-
raise ClassiqValueError(
|
|
51
|
-
f"possible values of excitations are {list(_EXCITATIONS_DICT.values())}"
|
|
52
|
-
)
|
|
53
|
-
excitations = [excitations]
|
|
54
|
-
|
|
55
|
-
elif isinstance(excitations, Iterable):
|
|
56
|
-
excitations = list(excitations) # type: ignore[assignment]
|
|
57
|
-
if all(isinstance(idx, int) for idx in excitations):
|
|
58
|
-
if any(idx not in _EXCITATIONS_DICT.values() for idx in excitations):
|
|
59
|
-
raise ClassiqValueError(
|
|
60
|
-
f"possible values of excitations are {list(_EXCITATIONS_DICT.values())}"
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
elif all(isinstance(idx, str) for idx in excitations):
|
|
64
|
-
if any(idx not in _EXCITATIONS_DICT.keys() for idx in excitations):
|
|
65
|
-
raise ClassiqValueError(
|
|
66
|
-
f"possible values of excitations are {list(_EXCITATIONS_DICT.keys())}"
|
|
67
|
-
)
|
|
68
|
-
excitations = sorted(_EXCITATIONS_DICT[idx] for idx in excitations) # type: ignore[index]
|
|
69
|
-
|
|
70
|
-
else:
|
|
71
|
-
raise ClassiqValueError(
|
|
72
|
-
"excitations must be of the same type (all str or all int)"
|
|
73
|
-
)
|
|
74
|
-
return excitations
|
|
@@ -1,392 +0,0 @@
|
|
|
1
|
-
import functools
|
|
2
|
-
import itertools
|
|
3
|
-
import warnings
|
|
4
|
-
from collections.abc import Collection, Iterator, Sequence
|
|
5
|
-
from contextlib import contextmanager
|
|
6
|
-
from typing import Optional, Union
|
|
7
|
-
|
|
8
|
-
from classiq.interface.exceptions import (
|
|
9
|
-
ClassiqDeprecationWarning,
|
|
10
|
-
ClassiqInternalExpansionError,
|
|
11
|
-
)
|
|
12
|
-
from classiq.interface.generator.functions.port_declaration import (
|
|
13
|
-
PortDeclarationDirection,
|
|
14
|
-
)
|
|
15
|
-
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
|
16
|
-
from classiq.interface.model.allocate import Allocate
|
|
17
|
-
from classiq.interface.model.bind_operation import BindOperation
|
|
18
|
-
from classiq.interface.model.block import Block
|
|
19
|
-
from classiq.interface.model.control import Control
|
|
20
|
-
from classiq.interface.model.invert import Invert
|
|
21
|
-
from classiq.interface.model.model_visitor import ModelVisitor
|
|
22
|
-
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
23
|
-
from classiq.interface.model.phase_operation import PhaseOperation
|
|
24
|
-
from classiq.interface.model.port_declaration import PortDeclaration
|
|
25
|
-
from classiq.interface.model.power import Power
|
|
26
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
27
|
-
AmplitudeLoadingOperation,
|
|
28
|
-
)
|
|
29
|
-
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
30
|
-
ArithmeticOperation,
|
|
31
|
-
)
|
|
32
|
-
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
33
|
-
QuantumExpressionOperation,
|
|
34
|
-
)
|
|
35
|
-
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
36
|
-
from classiq.interface.model.within_apply_operation import WithinApply
|
|
37
|
-
from classiq.interface.source_reference import SourceReference
|
|
38
|
-
|
|
39
|
-
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _inconsistent_type_modifier_error(
|
|
43
|
-
port_name: str,
|
|
44
|
-
expected: TypeModifier,
|
|
45
|
-
actual: TypeModifier,
|
|
46
|
-
source_ref: Optional[Union[SourceReference, str]] = None,
|
|
47
|
-
) -> str:
|
|
48
|
-
source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
|
|
49
|
-
return (
|
|
50
|
-
f"The use of variable '{port_name}' does not conform to its declared modifier: "
|
|
51
|
-
f"expected '{expected.name}', but found '{actual.name}'.\n"
|
|
52
|
-
f"Tip: If the cumulative use of the variable in the function matches '{expected.name}', "
|
|
53
|
-
f"use the `unchecked` flag to instruct the compiler to disregard individual operations."
|
|
54
|
-
f"{source_ref_str}\n"
|
|
55
|
-
"The deprecation warning will be elevated to an error starting July 23, 2025, at the earliest."
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def _inconsistent_type_modifier_in_binding_error(
|
|
60
|
-
expected: TypeModifier,
|
|
61
|
-
known_modifiers: dict[str, TypeModifier],
|
|
62
|
-
source_ref: Optional[Union[SourceReference, str]] = None,
|
|
63
|
-
) -> str:
|
|
64
|
-
actual = ", ".join(
|
|
65
|
-
f"{name}: {modifier.name}" for name, modifier in known_modifiers.items()
|
|
66
|
-
)
|
|
67
|
-
source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
|
|
68
|
-
return (
|
|
69
|
-
f"Inconsistent modifiers in variable binding: "
|
|
70
|
-
f"Expected modifier: {expected.name}, Actual modifiers: {actual}"
|
|
71
|
-
f"{source_ref_str}\n"
|
|
72
|
-
"The deprecation warning will be elevated to an error starting July 23, 2025, at the earliest."
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
class TypeModifierValidation(ModelVisitor):
|
|
77
|
-
"""
|
|
78
|
-
This class assumes that function calls are topologically sorted, so it traverses
|
|
79
|
-
the list of function calls and infers the type modifiers for each function call
|
|
80
|
-
without going recursively into the function calls.
|
|
81
|
-
The function definition ports are modified inplace.
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
def __init__(
|
|
85
|
-
self, *, skip_validation: bool = False, support_unused_ports: bool = True
|
|
86
|
-
) -> None:
|
|
87
|
-
self._signature_ports: dict[str, PortDeclaration] = dict()
|
|
88
|
-
self._inferred_ports: dict[str, PortDeclaration] = dict()
|
|
89
|
-
self._unchecked: set[str] = set()
|
|
90
|
-
|
|
91
|
-
self._initialized_vars: dict[str, TypeModifier] = dict()
|
|
92
|
-
self._bound_vars: list[set[str]] = []
|
|
93
|
-
|
|
94
|
-
self._conjugation_context: bool = False
|
|
95
|
-
self._support_unused_ports = (
|
|
96
|
-
support_unused_ports # could be turned off for debugging
|
|
97
|
-
)
|
|
98
|
-
self._skip_validation = skip_validation
|
|
99
|
-
self._source_ref: Optional[Union[SourceReference, str]] = None
|
|
100
|
-
|
|
101
|
-
@contextmanager
|
|
102
|
-
def validate_ports(
|
|
103
|
-
self, ports: Collection[PortDeclaration], unchecked: Collection[str]
|
|
104
|
-
) -> Iterator[bool]:
|
|
105
|
-
for port in ports:
|
|
106
|
-
if port.type_modifier is TypeModifier.Inferred:
|
|
107
|
-
self._inferred_ports[port.name] = port
|
|
108
|
-
else:
|
|
109
|
-
self._signature_ports[port.name] = port
|
|
110
|
-
self._unchecked.update(unchecked)
|
|
111
|
-
|
|
112
|
-
yield len(self._inferred_ports) > 0 or (
|
|
113
|
-
any(
|
|
114
|
-
port.type_modifier is not TypeModifier.Mutable
|
|
115
|
-
for port in self._signature_ports.values()
|
|
116
|
-
)
|
|
117
|
-
and not self._skip_validation
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
self._set_unused_as_const()
|
|
121
|
-
self._signature_ports.clear()
|
|
122
|
-
self._inferred_ports.clear()
|
|
123
|
-
self._unchecked.clear()
|
|
124
|
-
|
|
125
|
-
@contextmanager
|
|
126
|
-
def conjugation_context(self) -> Iterator[None]:
|
|
127
|
-
previous_context = self._conjugation_context
|
|
128
|
-
self._conjugation_context = True
|
|
129
|
-
try:
|
|
130
|
-
yield
|
|
131
|
-
finally:
|
|
132
|
-
self._conjugation_context = previous_context
|
|
133
|
-
|
|
134
|
-
@contextmanager
|
|
135
|
-
def source_reference_context(
|
|
136
|
-
self, source_ref: Optional[Union[SourceReference, str]]
|
|
137
|
-
) -> Iterator[None]:
|
|
138
|
-
previous_source_ref = self._source_ref
|
|
139
|
-
self._source_ref = source_ref
|
|
140
|
-
try:
|
|
141
|
-
yield
|
|
142
|
-
finally:
|
|
143
|
-
self._source_ref = previous_source_ref
|
|
144
|
-
|
|
145
|
-
def _set_unused_as_const(self) -> None:
|
|
146
|
-
unresolved_ports = [
|
|
147
|
-
port
|
|
148
|
-
for port in self._inferred_ports.values()
|
|
149
|
-
if port.type_modifier is TypeModifier.Inferred
|
|
150
|
-
]
|
|
151
|
-
if not self._support_unused_ports and len(unresolved_ports) > 0:
|
|
152
|
-
raise ClassiqInternalExpansionError(
|
|
153
|
-
f"Unresolved inferred ports detected: {', '.join(port.name for port in unresolved_ports)}. "
|
|
154
|
-
"All ports must have their type modifiers resolved."
|
|
155
|
-
)
|
|
156
|
-
for port in unresolved_ports:
|
|
157
|
-
port.type_modifier = TypeModifier.Const
|
|
158
|
-
|
|
159
|
-
def _validate_modifier(self, candidate: str, modifier: TypeModifier) -> None:
|
|
160
|
-
if self._conjugation_context and modifier is TypeModifier.Permutable:
|
|
161
|
-
modifier = TypeModifier.Const
|
|
162
|
-
|
|
163
|
-
if candidate in self._inferred_ports:
|
|
164
|
-
self._inferred_ports[candidate].type_modifier = TypeModifier.and_(
|
|
165
|
-
self._inferred_ports[candidate].type_modifier, modifier
|
|
166
|
-
)
|
|
167
|
-
return
|
|
168
|
-
|
|
169
|
-
if self._skip_validation or candidate in self._unchecked:
|
|
170
|
-
return
|
|
171
|
-
|
|
172
|
-
if candidate in self._signature_ports:
|
|
173
|
-
self._validate_signature_modifier(candidate, modifier)
|
|
174
|
-
|
|
175
|
-
elif candidate in self._initialized_vars:
|
|
176
|
-
self._initialized_vars[candidate] = TypeModifier.and_(
|
|
177
|
-
self._initialized_vars[candidate], modifier
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
def _validate_signature_modifier(
|
|
181
|
-
self, candidate: str, modifier: TypeModifier
|
|
182
|
-
) -> None:
|
|
183
|
-
signature_modifier = self._signature_ports[candidate].type_modifier
|
|
184
|
-
if signature_modifier is not TypeModifier.and_(signature_modifier, modifier):
|
|
185
|
-
warnings.warn(
|
|
186
|
-
_inconsistent_type_modifier_error(
|
|
187
|
-
candidate, signature_modifier, modifier, self._source_ref
|
|
188
|
-
),
|
|
189
|
-
ClassiqDeprecationWarning,
|
|
190
|
-
stacklevel=1,
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
def _add_initialized_modifier(self, var: str, modifier: TypeModifier) -> None:
|
|
194
|
-
if var in self._inferred_ports or var in self._signature_ports:
|
|
195
|
-
return
|
|
196
|
-
if self._conjugation_context and modifier is TypeModifier.Permutable:
|
|
197
|
-
modifier = TypeModifier.Const
|
|
198
|
-
self._initialized_vars[var] = modifier
|
|
199
|
-
|
|
200
|
-
def run(
|
|
201
|
-
self,
|
|
202
|
-
func_def: NativeFunctionDefinition,
|
|
203
|
-
unchecked: Collection[str],
|
|
204
|
-
) -> None:
|
|
205
|
-
with (
|
|
206
|
-
self.validate_ports(
|
|
207
|
-
func_def.port_declarations, unchecked
|
|
208
|
-
) as should_validate,
|
|
209
|
-
self.source_reference_context(f"function '{func_def.name}'"),
|
|
210
|
-
):
|
|
211
|
-
if should_validate:
|
|
212
|
-
self.visit(func_def.body)
|
|
213
|
-
self._update_bound_vars()
|
|
214
|
-
|
|
215
|
-
def _update_bound_vars(self) -> None:
|
|
216
|
-
merged_bound_vars = _merge_overlapping(self._bound_vars)
|
|
217
|
-
for bound_vars in merged_bound_vars:
|
|
218
|
-
reduced_modifier = self._get_reduced_modifier(bound_vars)
|
|
219
|
-
for var in bound_vars:
|
|
220
|
-
self._validate_modifier(var, reduced_modifier)
|
|
221
|
-
|
|
222
|
-
def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
|
|
223
|
-
with self.source_reference_context(call.source_ref):
|
|
224
|
-
for handle, port in call.handles_with_params:
|
|
225
|
-
self._validate_modifier(handle.name, port.type_modifier)
|
|
226
|
-
if port.direction is PortDeclarationDirection.Output:
|
|
227
|
-
self._add_initialized_modifier(handle.name, port.type_modifier)
|
|
228
|
-
|
|
229
|
-
if self._has_inputs(call):
|
|
230
|
-
bound_vars = {
|
|
231
|
-
handle.name
|
|
232
|
-
for handle, port in call.handles_with_params
|
|
233
|
-
if port.direction is not PortDeclarationDirection.Inout
|
|
234
|
-
and handle.name not in self._unchecked
|
|
235
|
-
}
|
|
236
|
-
self._bound_vars.append(bound_vars)
|
|
237
|
-
|
|
238
|
-
@staticmethod
|
|
239
|
-
def _has_inputs(call: QuantumFunctionCall) -> bool:
|
|
240
|
-
return any(
|
|
241
|
-
port.direction is PortDeclarationDirection.Input
|
|
242
|
-
for _, port in call.handles_with_params
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
def visit_Allocate(self, alloc: Allocate) -> None:
|
|
246
|
-
with self.source_reference_context(alloc.source_ref):
|
|
247
|
-
self._validate_modifier(alloc.target.name, TypeModifier.Permutable)
|
|
248
|
-
self._add_initialized_modifier(alloc.target.name, TypeModifier.Permutable)
|
|
249
|
-
|
|
250
|
-
def visit_BindOperation(self, bind_op: BindOperation) -> None:
|
|
251
|
-
var_names = {
|
|
252
|
-
handle.name
|
|
253
|
-
for handle in itertools.chain(bind_op.in_handles, bind_op.out_handles)
|
|
254
|
-
if handle.name not in self._unchecked
|
|
255
|
-
}
|
|
256
|
-
self._bound_vars.append(var_names)
|
|
257
|
-
for handle in bind_op.out_handles:
|
|
258
|
-
self._add_initialized_modifier(handle.name, TypeModifier.Inferred)
|
|
259
|
-
|
|
260
|
-
def _get_reduced_modifier(self, bound_vars: set[str]) -> TypeModifier:
|
|
261
|
-
signature_modifiers = {
|
|
262
|
-
name: self._signature_ports[name].type_modifier
|
|
263
|
-
for name in bound_vars.intersection(self._signature_ports)
|
|
264
|
-
}
|
|
265
|
-
known_inferred_modifiers = {
|
|
266
|
-
name: self._inferred_ports[name].type_modifier
|
|
267
|
-
for name in bound_vars.intersection(self._inferred_ports)
|
|
268
|
-
if self._inferred_ports[name].type_modifier is not TypeModifier.Inferred
|
|
269
|
-
}
|
|
270
|
-
known_initialized_modifiers = {
|
|
271
|
-
name: self._initialized_vars[name]
|
|
272
|
-
for name in bound_vars.intersection(self._initialized_vars)
|
|
273
|
-
if self._initialized_vars[name] is not TypeModifier.Inferred
|
|
274
|
-
}
|
|
275
|
-
known_modifiers = (
|
|
276
|
-
signature_modifiers | known_inferred_modifiers | known_initialized_modifiers
|
|
277
|
-
)
|
|
278
|
-
min_modifier = self._get_min_modifier(list(known_modifiers.values()))
|
|
279
|
-
if not all(
|
|
280
|
-
type_modifier is min_modifier
|
|
281
|
-
for type_modifier in signature_modifiers.values()
|
|
282
|
-
):
|
|
283
|
-
warnings.warn(
|
|
284
|
-
_inconsistent_type_modifier_in_binding_error(
|
|
285
|
-
min_modifier, known_modifiers, self._source_ref
|
|
286
|
-
),
|
|
287
|
-
ClassiqDeprecationWarning,
|
|
288
|
-
stacklevel=1,
|
|
289
|
-
)
|
|
290
|
-
|
|
291
|
-
return min_modifier
|
|
292
|
-
|
|
293
|
-
@staticmethod
|
|
294
|
-
def _get_min_modifier(modifiers: list[TypeModifier]) -> TypeModifier:
|
|
295
|
-
if len(modifiers) == 0:
|
|
296
|
-
return TypeModifier.Const
|
|
297
|
-
elif len(modifiers) == 1:
|
|
298
|
-
return modifiers[0]
|
|
299
|
-
else:
|
|
300
|
-
return functools.reduce(TypeModifier.and_, modifiers)
|
|
301
|
-
|
|
302
|
-
@staticmethod
|
|
303
|
-
def _extract_expr_vars(expr_op: QuantumExpressionOperation) -> list[str]:
|
|
304
|
-
expr_val = expr_op.expression.value.value
|
|
305
|
-
if not isinstance(expr_val, QmodAnnotatedExpression):
|
|
306
|
-
return []
|
|
307
|
-
return list(
|
|
308
|
-
dict.fromkeys(var.name for var in expr_val.get_quantum_vars().values())
|
|
309
|
-
)
|
|
310
|
-
|
|
311
|
-
def visit_ArithmeticOperation(self, arith: ArithmeticOperation) -> None:
|
|
312
|
-
with self.source_reference_context(arith.source_ref):
|
|
313
|
-
result_var = arith.result_var.name
|
|
314
|
-
self._validate_modifier(result_var, TypeModifier.Permutable)
|
|
315
|
-
for expr_var in self._extract_expr_vars(arith):
|
|
316
|
-
self._validate_modifier(expr_var, TypeModifier.Const)
|
|
317
|
-
if not arith.is_inplace:
|
|
318
|
-
self._add_initialized_modifier(result_var, TypeModifier.Permutable)
|
|
319
|
-
|
|
320
|
-
def visit_AmplitudeLoadingOperation(
|
|
321
|
-
self, amp_load: AmplitudeLoadingOperation
|
|
322
|
-
) -> None:
|
|
323
|
-
with self.source_reference_context(amp_load.source_ref):
|
|
324
|
-
result_var = amp_load.result_var.name
|
|
325
|
-
self._validate_modifier(result_var, TypeModifier.Mutable)
|
|
326
|
-
for expr_var in self._extract_expr_vars(amp_load):
|
|
327
|
-
self._validate_modifier(expr_var, TypeModifier.Const)
|
|
328
|
-
|
|
329
|
-
def visit_PhaseOperation(self, phase_op: PhaseOperation) -> None:
|
|
330
|
-
with self.source_reference_context(phase_op.source_ref):
|
|
331
|
-
for expr_var in self._extract_expr_vars(phase_op):
|
|
332
|
-
self._validate_modifier(expr_var, TypeModifier.Const)
|
|
333
|
-
|
|
334
|
-
def visit_Control(self, control: Control) -> None:
|
|
335
|
-
with self.source_reference_context(control.source_ref):
|
|
336
|
-
for control_var in self._extract_expr_vars(control):
|
|
337
|
-
self._validate_modifier(control_var, TypeModifier.Const)
|
|
338
|
-
self.visit(control.body)
|
|
339
|
-
if control.else_block is not None:
|
|
340
|
-
self.visit(control.else_block)
|
|
341
|
-
|
|
342
|
-
def visit_Invert(self, invert: Invert) -> None:
|
|
343
|
-
with self.source_reference_context(invert.source_ref):
|
|
344
|
-
self.visit(invert.body)
|
|
345
|
-
|
|
346
|
-
def visit_Power(self, power: Power) -> None:
|
|
347
|
-
with self.source_reference_context(power.source_ref):
|
|
348
|
-
self.visit(power.body)
|
|
349
|
-
|
|
350
|
-
def visit_WithinApply(self, within_apply: WithinApply) -> None:
|
|
351
|
-
with self.source_reference_context(within_apply.source_ref):
|
|
352
|
-
with self.conjugation_context():
|
|
353
|
-
self.visit(within_apply.compute)
|
|
354
|
-
self.visit(within_apply.action)
|
|
355
|
-
|
|
356
|
-
def visit_Block(self, block: Block) -> None:
|
|
357
|
-
with self.source_reference_context(block.source_ref):
|
|
358
|
-
self.visit(block.statements)
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
def _merge_overlapping(bound_vars: Sequence[Collection[str]]) -> list[set[str]]:
|
|
362
|
-
"""
|
|
363
|
-
Merges overlapping sets of bound variables.
|
|
364
|
-
Two sets overlap if they share at least one variable.
|
|
365
|
-
"""
|
|
366
|
-
all_bound_vars = bound_vars
|
|
367
|
-
merged_bound_vars: list[set[str]] = []
|
|
368
|
-
loop_guard: int = 10
|
|
369
|
-
idx: int = 0
|
|
370
|
-
|
|
371
|
-
for _ in range(loop_guard):
|
|
372
|
-
idx += 1
|
|
373
|
-
|
|
374
|
-
merged_bound_vars = []
|
|
375
|
-
modified: bool = False
|
|
376
|
-
for current_bound_vars in all_bound_vars:
|
|
377
|
-
for existing in merged_bound_vars:
|
|
378
|
-
if existing.intersection(current_bound_vars):
|
|
379
|
-
existing.update(current_bound_vars)
|
|
380
|
-
modified = True
|
|
381
|
-
break
|
|
382
|
-
else:
|
|
383
|
-
merged_bound_vars.append(set(current_bound_vars))
|
|
384
|
-
|
|
385
|
-
if not modified:
|
|
386
|
-
break
|
|
387
|
-
all_bound_vars = merged_bound_vars
|
|
388
|
-
|
|
389
|
-
if idx == loop_guard - 1:
|
|
390
|
-
raise ClassiqInternalExpansionError
|
|
391
|
-
|
|
392
|
-
return merged_bound_vars
|