classiq 0.86.0__py3-none-any.whl → 0.87.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/applications/chemistry/hartree_fock.py +5 -1
- classiq/applications/chemistry/op_utils.py +2 -2
- classiq/applications/combinatorial_helpers/encoding_mapping.py +11 -15
- classiq/applications/combinatorial_helpers/encoding_utils.py +6 -6
- classiq/applications/combinatorial_helpers/memory.py +4 -4
- classiq/applications/combinatorial_helpers/optimization_model.py +5 -5
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +6 -10
- classiq/applications/combinatorial_helpers/pyomo_utils.py +27 -26
- classiq/applications/combinatorial_helpers/sympy_utils.py +2 -2
- classiq/applications/combinatorial_helpers/transformations/encoding.py +4 -6
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +4 -4
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +2 -2
- classiq/applications/combinatorial_helpers/transformations/penalty_support.py +3 -3
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -0
- classiq/applications/hamiltonian/pauli_decomposition.py +33 -1
- classiq/evaluators/argument_types.py +15 -6
- classiq/evaluators/parameter_types.py +43 -39
- classiq/evaluators/qmod_annotated_expression.py +88 -11
- classiq/evaluators/qmod_expression_visitors/out_of_place_node_transformer.py +19 -0
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +54 -11
- classiq/evaluators/qmod_expression_visitors/qmod_expression_renamer.py +40 -25
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +29 -59
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +12 -5
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +175 -28
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +21 -14
- classiq/evaluators/qmod_node_evaluators/compare_evaluation.py +9 -5
- classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +20 -1
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +97 -0
- classiq/evaluators/qmod_node_evaluators/name_evaluation.py +11 -26
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +56 -0
- classiq/evaluators/qmod_node_evaluators/piecewise_evaluation.py +40 -0
- classiq/evaluators/qmod_node_evaluators/struct_instantiation_evaluation.py +2 -3
- classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +48 -21
- classiq/evaluators/qmod_node_evaluators/unary_op_evaluation.py +53 -9
- classiq/evaluators/qmod_node_evaluators/utils.py +27 -5
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +188 -0
- classiq/evaluators/qmod_type_inference/quantum_type_inference.py +292 -0
- classiq/evaluators/quantum_type_utils.py +0 -131
- classiq/execution/execution_session.py +1 -1
- classiq/execution/qnn.py +4 -1
- classiq/execution/user_budgets.py +1 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +10 -30
- classiq/interface/backend/quantum_backend_providers.py +63 -52
- classiq/interface/generator/arith/binary_ops.py +107 -115
- classiq/interface/generator/arith/extremum_operations.py +33 -45
- classiq/interface/generator/arith/number_utils.py +4 -1
- classiq/interface/generator/circuit_code/types_and_constants.py +0 -9
- classiq/interface/generator/compiler_keywords.py +2 -0
- classiq/interface/generator/function_param_list.py +133 -5
- classiq/interface/generator/functions/classical_type.py +59 -2
- classiq/interface/generator/functions/qmod_python_interface.py +15 -0
- classiq/interface/generator/functions/type_name.py +6 -0
- classiq/interface/generator/model/preferences/preferences.py +1 -17
- classiq/interface/generator/quantum_program.py +1 -13
- classiq/interface/helpers/model_normalizer.py +2 -2
- classiq/interface/helpers/text_utils.py +7 -2
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/classical_if.py +40 -0
- classiq/interface/model/handle_binding.py +28 -16
- classiq/interface/model/quantum_type.py +61 -2
- classiq/interface/pretty_print/expression_to_qmod.py +24 -11
- classiq/interface/pyomo_extension/__init__.py +0 -4
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +2 -2
- classiq/model_expansions/arithmetic.py +43 -1
- classiq/model_expansions/arithmetic_compute_result_attrs.py +255 -0
- classiq/model_expansions/capturing/captured_vars.py +2 -5
- classiq/model_expansions/quantum_operations/allocate.py +22 -15
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -3
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +52 -71
- classiq/model_expansions/quantum_operations/bind.py +15 -7
- classiq/model_expansions/quantum_operations/call_emitter.py +2 -10
- classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -0
- classiq/open_library/functions/__init__.py +3 -0
- classiq/open_library/functions/lcu.py +117 -0
- classiq/qmod/builtins/enums.py +2 -2
- classiq/qmod/builtins/structs.py +33 -18
- classiq/qmod/pretty_print/expression_to_python.py +7 -9
- {classiq-0.86.0.dist-info → classiq-0.87.0.dist-info}/METADATA +3 -3
- {classiq-0.86.0.dist-info → classiq-0.87.0.dist-info}/RECORD +83 -89
- classiq/interface/generator/amplitude_estimation.py +0 -34
- classiq/interface/generator/function_param_list_without_self_reference.py +0 -160
- classiq/interface/generator/grover_diffuser.py +0 -93
- classiq/interface/generator/grover_operator.py +0 -106
- classiq/interface/generator/oracles/__init__.py +0 -3
- classiq/interface/generator/oracles/arithmetic_oracle.py +0 -82
- classiq/interface/generator/oracles/custom_oracle.py +0 -65
- classiq/interface/generator/oracles/oracle_abc.py +0 -76
- classiq/interface/generator/oracles/oracle_function_param_list.py +0 -6
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +0 -165
- classiq/interface/generator/qpe.py +0 -169
- classiq/interface/grover/grover_modelling_params.py +0 -13
- classiq/model_expansions/transformers/var_splitter.py +0 -224
- /classiq/{interface/grover → evaluators/qmod_type_inference}/__init__.py +0 -0
- {classiq-0.86.0.dist-info → classiq-0.87.0.dist-info}/WHEEL +0 -0
@@ -1,169 +0,0 @@
|
|
1
|
-
from typing import Any, Optional
|
2
|
-
|
3
|
-
import pydantic
|
4
|
-
from pydantic import ConfigDict
|
5
|
-
from pydantic_core.core_schema import ValidationInfo
|
6
|
-
from typing_extensions import Self
|
7
|
-
|
8
|
-
from classiq.interface.exceptions import ClassiqMismatchIOsError, ClassiqValueError
|
9
|
-
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
10
|
-
from classiq.interface.generator.function_param_list_without_self_reference import (
|
11
|
-
function_param_library_without_self_reference,
|
12
|
-
)
|
13
|
-
from classiq.interface.generator.function_params import (
|
14
|
-
DEFAULT_ZERO_NAME,
|
15
|
-
FunctionParams,
|
16
|
-
IOName,
|
17
|
-
parse_function_params_values,
|
18
|
-
)
|
19
|
-
from classiq.interface.generator.hamiltonian_evolution.exponentiation import (
|
20
|
-
Exponentiation,
|
21
|
-
)
|
22
|
-
from classiq.interface.generator.user_defined_function_params import CustomFunction
|
23
|
-
|
24
|
-
PHASE_ESTIMATION_DEFAULT_OUTPUT_NAME = "PHASE_ESTIMATION"
|
25
|
-
CUSTOM_FUNCTIONS_IO_MISMATCH_ERROR = (
|
26
|
-
"Custom function provided to the QPE has different input and output names."
|
27
|
-
)
|
28
|
-
|
29
|
-
|
30
|
-
class ExponentiationScaling(pydantic.BaseModel):
|
31
|
-
"""
|
32
|
-
Details of exponentiation scaling for phase estimation.
|
33
|
-
"""
|
34
|
-
|
35
|
-
max_depth: pydantic.PositiveInt = pydantic.Field(
|
36
|
-
description="The max_depth of the smallest exponentiation",
|
37
|
-
)
|
38
|
-
max_depth_scaling_factor: pydantic.NonNegativeFloat = pydantic.Field(
|
39
|
-
default=2.0,
|
40
|
-
description="The scaling factor of the exponentiation max_depth; defaults to 2.",
|
41
|
-
)
|
42
|
-
model_config = ConfigDict(frozen=True)
|
43
|
-
|
44
|
-
|
45
|
-
class ExponentiationSpecification(pydantic.BaseModel):
|
46
|
-
"""
|
47
|
-
Specifications of individual Exponentiation details for each qubit; only valid if Exponentiation is given as unitary_params for PhaseEstimation.
|
48
|
-
This sets the optimization to ExponentiationOptimization.MINIMIZE_ERROR and overrides the max_depth constraints.
|
49
|
-
"""
|
50
|
-
|
51
|
-
scaling: Optional[ExponentiationScaling] = pydantic.Field(
|
52
|
-
default=None,
|
53
|
-
description="The scaling of the exponentiation functions.",
|
54
|
-
)
|
55
|
-
max_depths: Optional[tuple[pydantic.NonNegativeInt, ...]] = pydantic.Field(
|
56
|
-
default=None,
|
57
|
-
description="The max_depth of each exponentiation function; overrides scaling.",
|
58
|
-
)
|
59
|
-
model_config = ConfigDict(frozen=True)
|
60
|
-
|
61
|
-
@pydantic.model_validator(mode="after")
|
62
|
-
def _validate_exponentiation_specification(self) -> Self:
|
63
|
-
if self.scaling is None and self.max_depths is None:
|
64
|
-
raise ClassiqValueError("At least one specification must be provided.")
|
65
|
-
return self
|
66
|
-
|
67
|
-
|
68
|
-
class PhaseEstimation(FunctionParams):
|
69
|
-
"""
|
70
|
-
Quantum phase estimation of a given unitary function.
|
71
|
-
"""
|
72
|
-
|
73
|
-
size: pydantic.PositiveInt = pydantic.Field(
|
74
|
-
description="The number of qubits storing the estimated phase."
|
75
|
-
)
|
76
|
-
unitary: str = pydantic.Field(
|
77
|
-
description="The unitary function for phase estimation.",
|
78
|
-
)
|
79
|
-
unitary_params: FunctionParams = pydantic.Field(
|
80
|
-
description="The unitary function parameters.",
|
81
|
-
default_factory=CustomFunction,
|
82
|
-
)
|
83
|
-
exponentiation_specification: Optional[ExponentiationSpecification] = (
|
84
|
-
pydantic.Field(
|
85
|
-
default=None,
|
86
|
-
description="The specifications for phase estimation of exponentiation functions.",
|
87
|
-
)
|
88
|
-
)
|
89
|
-
|
90
|
-
_output_name: IOName = pydantic.PrivateAttr(
|
91
|
-
default=PHASE_ESTIMATION_DEFAULT_OUTPUT_NAME
|
92
|
-
)
|
93
|
-
|
94
|
-
@property
|
95
|
-
def output_name(self) -> str:
|
96
|
-
return self._output_name
|
97
|
-
|
98
|
-
def _create_ios(self) -> None:
|
99
|
-
self._inputs = {**self.unitary_params.inputs}
|
100
|
-
self._outputs = {**self.unitary_params.outputs}
|
101
|
-
self._outputs[self._output_name] = RegisterArithmeticInfo(size=self.size)
|
102
|
-
self._create_zero_input_registers({DEFAULT_ZERO_NAME: self.size})
|
103
|
-
|
104
|
-
@pydantic.model_validator(mode="before")
|
105
|
-
@classmethod
|
106
|
-
def _validate_composite_name(cls, values: Any) -> dict[str, Any]:
|
107
|
-
if not isinstance(values, dict):
|
108
|
-
return values
|
109
|
-
unitary_params = values.get("unitary_params")
|
110
|
-
unitary = values.get("unitary")
|
111
|
-
|
112
|
-
if isinstance(unitary_params, CustomFunction) and not unitary:
|
113
|
-
raise ClassiqValueError(
|
114
|
-
"`PhaseEstimation` of a user define function (`CustomFunction`) must receive the function name from the `unitary` field"
|
115
|
-
)
|
116
|
-
return values
|
117
|
-
|
118
|
-
@pydantic.model_validator(mode="before")
|
119
|
-
@classmethod
|
120
|
-
def _parse_function_params(
|
121
|
-
cls, values: Any, info: ValidationInfo
|
122
|
-
) -> dict[str, Any]:
|
123
|
-
vals = info.data.copy() if info.data else {}
|
124
|
-
if isinstance(values, dict):
|
125
|
-
vals = values
|
126
|
-
elif isinstance(values, PhaseEstimation):
|
127
|
-
vals = values.model_dump()
|
128
|
-
|
129
|
-
parse_function_params_values(
|
130
|
-
values=vals,
|
131
|
-
params_key="unitary_params",
|
132
|
-
discriminator_key="unitary",
|
133
|
-
param_classes=function_param_library_without_self_reference.param_list,
|
134
|
-
default_parser_class=CustomFunction,
|
135
|
-
)
|
136
|
-
return vals
|
137
|
-
|
138
|
-
@pydantic.field_validator("unitary_params")
|
139
|
-
@classmethod
|
140
|
-
def _validate_unitary_params(cls, unitary_params: FunctionParams) -> FunctionParams:
|
141
|
-
if not unitary_params.is_powerable():
|
142
|
-
if isinstance(unitary_params, CustomFunction):
|
143
|
-
raise ClassiqMismatchIOsError(CUSTOM_FUNCTIONS_IO_MISMATCH_ERROR)
|
144
|
-
raise ClassiqValueError(
|
145
|
-
f"Phase estimation of {unitary_params.discriminator()} is currently not supported."
|
146
|
-
)
|
147
|
-
return unitary_params
|
148
|
-
|
149
|
-
@pydantic.field_validator("exponentiation_specification")
|
150
|
-
@classmethod
|
151
|
-
def _validate_exponentiation_specification(
|
152
|
-
cls,
|
153
|
-
exponentiation_specification: Optional[ExponentiationSpecification],
|
154
|
-
validation_info: ValidationInfo,
|
155
|
-
) -> Optional[ExponentiationSpecification]:
|
156
|
-
if exponentiation_specification is None:
|
157
|
-
return exponentiation_specification
|
158
|
-
unitary_params = validation_info.data.get("unitary_params")
|
159
|
-
if not isinstance(unitary_params, Exponentiation):
|
160
|
-
raise ClassiqValueError(
|
161
|
-
"exponentiation_specification is only valid for Exponentiation unitary_params."
|
162
|
-
)
|
163
|
-
if exponentiation_specification.max_depths is not None and len(
|
164
|
-
exponentiation_specification.max_depths
|
165
|
-
) != validation_info.data.get("size"):
|
166
|
-
raise ClassiqValueError(
|
167
|
-
"Length of max_depths must match the provided size."
|
168
|
-
)
|
169
|
-
return exponentiation_specification
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import pydantic
|
2
|
-
from pydantic import BaseModel
|
3
|
-
|
4
|
-
from classiq.interface.generator.oracles import ArithmeticOracle
|
5
|
-
|
6
|
-
|
7
|
-
class GroverParams(BaseModel):
|
8
|
-
oracle: ArithmeticOracle = pydantic.Field(
|
9
|
-
description="An arithmatic oracle for the grover search."
|
10
|
-
)
|
11
|
-
num_reps: int = pydantic.Field(
|
12
|
-
default=1, description="The number of repetitions of the " "grover block."
|
13
|
-
)
|
@@ -1,224 +0,0 @@
|
|
1
|
-
import ast
|
2
|
-
from dataclasses import dataclass
|
3
|
-
from itertools import chain
|
4
|
-
from typing import TYPE_CHECKING, Callable, Optional
|
5
|
-
|
6
|
-
from classiq.interface.exceptions import (
|
7
|
-
ClassiqExpansionError,
|
8
|
-
ClassiqInternalExpansionError,
|
9
|
-
)
|
10
|
-
from classiq.interface.generator.expressions.expression import Expression
|
11
|
-
from classiq.interface.model.bind_operation import BindOperation
|
12
|
-
from classiq.interface.model.handle_binding import (
|
13
|
-
HandleBinding,
|
14
|
-
NestedHandleBinding,
|
15
|
-
SlicedHandleBinding,
|
16
|
-
SubscriptHandleBinding,
|
17
|
-
)
|
18
|
-
from classiq.interface.model.quantum_type import (
|
19
|
-
QuantumBitvector,
|
20
|
-
QuantumScalar,
|
21
|
-
QuantumType,
|
22
|
-
)
|
23
|
-
from classiq.interface.model.variable_declaration_statement import (
|
24
|
-
VariableDeclarationStatement,
|
25
|
-
)
|
26
|
-
|
27
|
-
from classiq.model_expansions.scope import QuantumSymbol, Scope
|
28
|
-
from classiq.model_expansions.transformers.model_renamer import (
|
29
|
-
HandleRenaming,
|
30
|
-
ModelRenamer,
|
31
|
-
)
|
32
|
-
from classiq.model_expansions.visitors.variable_references import VarRefCollector
|
33
|
-
|
34
|
-
|
35
|
-
@dataclass(frozen=True)
|
36
|
-
class SymbolPart(HandleRenaming):
|
37
|
-
target_var_type: QuantumType
|
38
|
-
|
39
|
-
|
40
|
-
SymbolParts = dict[HandleBinding, list[SymbolPart]]
|
41
|
-
PartNamer = Callable[[str], str]
|
42
|
-
|
43
|
-
|
44
|
-
class VarSplitter(ModelRenamer):
|
45
|
-
def __init__(self, scope: Scope):
|
46
|
-
self._scope = scope
|
47
|
-
|
48
|
-
def split_symbols(self, expression: Expression, namer: PartNamer) -> SymbolParts:
|
49
|
-
vrc = VarRefCollector(ignore_duplicated_handles=True)
|
50
|
-
vrc.visit(ast.parse(expression.expr))
|
51
|
-
symbol_names_to_split = dict.fromkeys(
|
52
|
-
handle.name
|
53
|
-
for handle in vrc.var_handles
|
54
|
-
if isinstance(self._scope[handle.name].value, QuantumSymbol)
|
55
|
-
and isinstance(handle, NestedHandleBinding)
|
56
|
-
)
|
57
|
-
|
58
|
-
symbol_handles = {
|
59
|
-
symbol: list(
|
60
|
-
dict.fromkeys(
|
61
|
-
handle.collapse()
|
62
|
-
for handle in vrc.var_handles
|
63
|
-
if handle.name == symbol.handle.name
|
64
|
-
)
|
65
|
-
)
|
66
|
-
for symbol_name in symbol_names_to_split
|
67
|
-
if isinstance(
|
68
|
-
symbol := self._scope[symbol_name].value,
|
69
|
-
QuantumSymbol,
|
70
|
-
)
|
71
|
-
}
|
72
|
-
|
73
|
-
return {
|
74
|
-
symbol.handle: [
|
75
|
-
SymbolPart(
|
76
|
-
source_handle=part.handle,
|
77
|
-
target_var_name=namer(part.handle.identifier),
|
78
|
-
target_var_type=part.quantum_type,
|
79
|
-
)
|
80
|
-
for part in self._get_symbol_parts(symbol, handles)
|
81
|
-
]
|
82
|
-
for symbol, handles in symbol_handles.items()
|
83
|
-
}
|
84
|
-
|
85
|
-
def _get_symbol_parts(
|
86
|
-
self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
|
87
|
-
) -> list[QuantumSymbol]:
|
88
|
-
for i in range(len(target_parts)):
|
89
|
-
for j in range(i + 1, len(target_parts)):
|
90
|
-
if target_parts[i].overlaps(target_parts[j]):
|
91
|
-
raise ClassiqInternalExpansionError(
|
92
|
-
f"Handles {str(target_parts[i])!r} and "
|
93
|
-
f"{str(target_parts[j])!r} overlapping in expression"
|
94
|
-
)
|
95
|
-
return self._get_symbol_parts_unsafe(symbol, target_parts)
|
96
|
-
|
97
|
-
def _get_symbol_parts_unsafe(
|
98
|
-
self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
|
99
|
-
) -> list[QuantumSymbol]:
|
100
|
-
if all(
|
101
|
-
symbol.handle == target_part or symbol.handle not in target_part.prefixes()
|
102
|
-
for target_part in target_parts
|
103
|
-
) or isinstance(symbol.quantum_type, QuantumScalar):
|
104
|
-
return [symbol]
|
105
|
-
|
106
|
-
if isinstance(symbol.quantum_type, QuantumBitvector):
|
107
|
-
return self._get_array_parts(symbol, target_parts)
|
108
|
-
|
109
|
-
return self._get_struct_parts(symbol, target_parts)
|
110
|
-
|
111
|
-
def _get_array_parts(
|
112
|
-
self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
|
113
|
-
) -> list[QuantumSymbol]:
|
114
|
-
if TYPE_CHECKING:
|
115
|
-
assert isinstance(symbol.quantum_type, QuantumBitvector)
|
116
|
-
|
117
|
-
if not symbol.quantum_type.has_length:
|
118
|
-
raise ClassiqExpansionError(
|
119
|
-
f"Could not determine the length of quantum array " f"{symbol.handle}."
|
120
|
-
)
|
121
|
-
target_slices = self._get_target_slices(symbol, target_parts)
|
122
|
-
|
123
|
-
symbol_parts: list[QuantumSymbol] = []
|
124
|
-
idx = 0
|
125
|
-
while idx < symbol.quantum_type.length_value:
|
126
|
-
if idx in target_slices:
|
127
|
-
stop = target_slices[idx]
|
128
|
-
if stop <= idx:
|
129
|
-
raise ClassiqInternalExpansionError(
|
130
|
-
f"Illegal sliced handle {str(symbol[idx: stop].handle)!r}"
|
131
|
-
)
|
132
|
-
symbol_parts.append(symbol[idx:stop])
|
133
|
-
idx = stop
|
134
|
-
else:
|
135
|
-
symbol_parts.extend(
|
136
|
-
self._get_symbol_parts_unsafe(symbol[idx], target_parts)
|
137
|
-
)
|
138
|
-
idx += 1
|
139
|
-
|
140
|
-
return symbol_parts
|
141
|
-
|
142
|
-
def _get_target_slices(
|
143
|
-
self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
|
144
|
-
) -> dict[int, int]:
|
145
|
-
if TYPE_CHECKING:
|
146
|
-
assert isinstance(symbol.quantum_type, QuantumBitvector)
|
147
|
-
target_items = {
|
148
|
-
idx
|
149
|
-
for idx in range(symbol.quantum_type.length_value)
|
150
|
-
for target_part in target_parts
|
151
|
-
if target_part
|
152
|
-
in SubscriptHandleBinding(
|
153
|
-
base_handle=symbol.handle, index=Expression(expr=str(idx))
|
154
|
-
)
|
155
|
-
}
|
156
|
-
target_slices = {
|
157
|
-
target_part.start.to_int_value(): target_part.end.to_int_value()
|
158
|
-
for target_part in target_parts
|
159
|
-
if isinstance(target_part, SlicedHandleBinding)
|
160
|
-
and symbol.handle == target_part.base_handle
|
161
|
-
}
|
162
|
-
self._add_unused_indices_as_slices(symbol, target_items, target_slices)
|
163
|
-
return target_slices
|
164
|
-
|
165
|
-
@staticmethod
|
166
|
-
def _add_unused_indices_as_slices(
|
167
|
-
symbol: QuantumSymbol, target_items: set[int], target_slices: dict[int, int]
|
168
|
-
) -> None:
|
169
|
-
if TYPE_CHECKING:
|
170
|
-
assert isinstance(symbol.quantum_type, QuantumBitvector)
|
171
|
-
last_unused_idx: Optional[int] = None
|
172
|
-
array_length = symbol.quantum_type.length_value
|
173
|
-
idx = 0
|
174
|
-
|
175
|
-
while idx < array_length:
|
176
|
-
if (
|
177
|
-
idx in target_items or idx in target_slices
|
178
|
-
) and last_unused_idx is not None:
|
179
|
-
target_slices[last_unused_idx] = idx
|
180
|
-
last_unused_idx = None
|
181
|
-
|
182
|
-
if idx in target_slices:
|
183
|
-
if target_slices[idx] <= idx:
|
184
|
-
raise ClassiqInternalExpansionError
|
185
|
-
idx = target_slices[idx]
|
186
|
-
continue
|
187
|
-
|
188
|
-
if idx not in target_items and last_unused_idx is None:
|
189
|
-
last_unused_idx = idx
|
190
|
-
|
191
|
-
idx += 1
|
192
|
-
|
193
|
-
if last_unused_idx is not None:
|
194
|
-
target_slices[last_unused_idx] = array_length
|
195
|
-
|
196
|
-
def _get_struct_parts(
|
197
|
-
self, symbol: QuantumSymbol, target_parts: list[HandleBinding]
|
198
|
-
) -> list[QuantumSymbol]:
|
199
|
-
return list(
|
200
|
-
chain.from_iterable(
|
201
|
-
self._get_symbol_parts_unsafe(field_symbol, target_parts)
|
202
|
-
for field_symbol in symbol.fields.values()
|
203
|
-
)
|
204
|
-
)
|
205
|
-
|
206
|
-
@staticmethod
|
207
|
-
def get_bind_ops(symbol_parts: SymbolParts) -> list[BindOperation]:
|
208
|
-
return [
|
209
|
-
BindOperation(
|
210
|
-
in_handles=[handle],
|
211
|
-
out_handles=[part.target_var_handle for part in parts],
|
212
|
-
)
|
213
|
-
for handle, parts in symbol_parts.items()
|
214
|
-
]
|
215
|
-
|
216
|
-
@staticmethod
|
217
|
-
def get_var_decls(symbol_parts: SymbolParts) -> list[VariableDeclarationStatement]:
|
218
|
-
return [
|
219
|
-
VariableDeclarationStatement(
|
220
|
-
name=part.target_var_name,
|
221
|
-
qmod_type=part.target_var_type,
|
222
|
-
)
|
223
|
-
for part in chain.from_iterable(symbol_parts.values())
|
224
|
-
]
|
File without changes
|
File without changes
|