classiq 0.100.0__py3-none-any.whl → 0.104.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 +3 -0
- classiq/_internals/api_wrapper.py +29 -4
- classiq/applications/chemistry/op_utils.py +63 -1
- classiq/applications/chemistry/problems.py +18 -6
- classiq/applications/chemistry/ucc.py +2 -2
- classiq/evaluators/parameter_types.py +1 -4
- 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_node_evaluators/utils.py +6 -3
- classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
- classiq/execution/__init__.py +11 -1
- classiq/execution/execution_session.py +1 -1
- classiq/execution/functions/__init__.py +3 -0
- classiq/execution/functions/_logging.py +19 -0
- classiq/execution/functions/constants.py +9 -0
- classiq/execution/functions/parse_provider_backend.py +90 -0
- classiq/execution/functions/sample.py +257 -0
- classiq/execution/jobs.py +122 -5
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +15 -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 +3 -0
- classiq/interface/exceptions.py +0 -42
- classiq/interface/executor/execution_request.py +1 -0
- classiq/interface/executor/quantum_code.py +0 -6
- classiq/interface/executor/result.py +9 -5
- classiq/interface/generator/arith/binary_ops.py +38 -2
- classiq/interface/generator/function_param_list.py +4 -2
- classiq/interface/generator/functions/builtins/internal_operators.py +5 -9
- classiq/interface/generator/functions/classical_type.py +45 -0
- classiq/interface/generator/functions/type_name.py +23 -0
- classiq/interface/generator/generated_circuit_data.py +0 -2
- classiq/interface/generator/generation_request.py +9 -4
- classiq/interface/generator/quantum_program.py +8 -36
- classiq/interface/generator/types/compilation_metadata.py +9 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/helpers/model_normalizer.py +62 -2
- classiq/interface/helpers/text_utils.py +17 -6
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/invert.py +15 -0
- classiq/interface/model/model.py +42 -3
- classiq/interface/model/model_visitor.py +4 -2
- classiq/interface/model/quantum_function_call.py +17 -5
- classiq/interface/model/quantum_type.py +21 -0
- classiq/interface/model/statement_block.py +0 -4
- classiq/model_expansions/capturing/captured_vars.py +16 -12
- classiq/model_expansions/function_builder.py +9 -1
- classiq/model_expansions/interpreters/base_interpreter.py +12 -10
- 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 +15 -47
- classiq/open_library/functions/__init__.py +42 -27
- classiq/open_library/functions/bit_operations.py +30 -0
- classiq/open_library/functions/modular_arithmetics.py +597 -0
- classiq/open_library/functions/qft_space_arithmetics.py +81 -0
- classiq/open_library/functions/state_preparation.py +6 -3
- classiq/open_library/functions/utility_functions.py +22 -3
- classiq/qmod/builtins/functions/__init__.py +9 -0
- classiq/qmod/builtins/functions/arithmetic.py +131 -0
- classiq/qmod/builtins/functions/exponentiation.py +34 -4
- classiq/qmod/builtins/operations.py +30 -41
- classiq/qmod/native/pretty_printer.py +12 -12
- classiq/qmod/pretty_print/pretty_printer.py +11 -15
- classiq/qmod/qmod_parameter.py +4 -0
- classiq/qmod/qmod_variable.py +38 -63
- classiq/qmod/quantum_callable.py +8 -2
- classiq/qmod/quantum_expandable.py +3 -1
- classiq/qmod/quantum_function.py +45 -8
- 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/qmod/utilities.py +7 -4
- classiq/synthesis_action/__init__.py +20 -0
- classiq/synthesis_action/actions.py +106 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/METADATA +1 -1
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/RECORD +90 -84
- classiq/interface/executor/register_initialization.py +0 -36
- classiq/interface/generator/amplitude_loading.py +0 -103
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
- classiq/open_library/functions/modular_exponentiation.py +0 -272
- classiq/open_library/functions/qsvt_temp.py +0 -536
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/WHEEL +0 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -6,11 +6,32 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
|
6
6
|
from classiq.interface.generator.functions.classical_type import ClassicalType
|
|
7
7
|
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
|
8
8
|
from classiq.interface.generator.visitor import Transformer, Visitor
|
|
9
|
+
from classiq.interface.model.handle_binding import HandleBinding
|
|
9
10
|
from classiq.interface.model.model import Model
|
|
10
|
-
from classiq.interface.model.
|
|
11
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
12
|
+
from classiq.interface.model.port_declaration import (
|
|
13
|
+
PortDeclaration,
|
|
14
|
+
)
|
|
15
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
16
|
+
from classiq.interface.model.variable_declaration_statement import (
|
|
17
|
+
VariableDeclarationStatement,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
|
11
21
|
|
|
12
22
|
|
|
13
23
|
class ModelNormalizer(Visitor):
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
normalize_func_names: bool = False,
|
|
27
|
+
normalize_quantum_var_names: bool = False,
|
|
28
|
+
) -> None:
|
|
29
|
+
self._normalize_func_names = normalize_func_names
|
|
30
|
+
self._normalize_quantum_var_names = normalize_quantum_var_names
|
|
31
|
+
self._funcs_renames: dict[str, str] = {}
|
|
32
|
+
self._count_name = CountedNameAllocator()
|
|
33
|
+
self.original_names: dict[str, str] = {}
|
|
34
|
+
|
|
14
35
|
def visit(self, node: Any) -> None:
|
|
15
36
|
if isinstance(node, ASTNode):
|
|
16
37
|
node.model_config["frozen"] = False
|
|
@@ -23,10 +44,49 @@ class ModelNormalizer(Visitor):
|
|
|
23
44
|
def visit_Model(self, model: Model) -> None:
|
|
24
45
|
model.debug_info = DebugInfoCollection()
|
|
25
46
|
model.functions.sort(key=lambda x: x.name)
|
|
47
|
+
self._funcs_renames = {
|
|
48
|
+
func.name: f"___func_{index}" for index, func in enumerate(model.functions)
|
|
49
|
+
}
|
|
26
50
|
self.generic_visit(model)
|
|
27
51
|
|
|
28
|
-
def
|
|
52
|
+
def visit_NativeFunctionDefinition(self, func: NativeFunctionDefinition) -> None:
|
|
53
|
+
if self._normalize_func_names:
|
|
54
|
+
func.name = self._funcs_renames[func.name]
|
|
55
|
+
self.generic_visit(func)
|
|
56
|
+
|
|
57
|
+
def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
|
|
58
|
+
if self._normalize_func_names:
|
|
59
|
+
if isinstance(call.function, str):
|
|
60
|
+
if call.function in self._funcs_renames:
|
|
61
|
+
call.function = self._funcs_renames[call.function]
|
|
62
|
+
else:
|
|
63
|
+
if call.function.name in self._funcs_renames:
|
|
64
|
+
call.function.name = self._funcs_renames[call.function.name]
|
|
65
|
+
self.generic_visit(call)
|
|
66
|
+
|
|
67
|
+
def visit_PortDeclaration(self, decl: PortDeclaration) -> None:
|
|
29
68
|
decl.type_modifier = TypeModifier.Mutable
|
|
69
|
+
self._rename_quantum_var(decl, "_port")
|
|
70
|
+
|
|
71
|
+
def visit_VariableDeclarationStatement(
|
|
72
|
+
self, var: VariableDeclarationStatement
|
|
73
|
+
) -> None:
|
|
74
|
+
self._rename_quantum_var(var, "_var")
|
|
75
|
+
|
|
76
|
+
def _rename_quantum_var(
|
|
77
|
+
self, var: VariableDeclarationStatement | PortDeclaration, new_name_prefix: str
|
|
78
|
+
) -> None:
|
|
79
|
+
if self._normalize_quantum_var_names:
|
|
80
|
+
old_name = var.name
|
|
81
|
+
var.name = self._count_name.allocate(new_name_prefix)
|
|
82
|
+
self.original_names[old_name] = var.name
|
|
83
|
+
|
|
84
|
+
def visit_HandleBinding(self, handle: HandleBinding) -> None:
|
|
85
|
+
if self._normalize_quantum_var_names:
|
|
86
|
+
# this is a hack use just for testing, do not use in production
|
|
87
|
+
object.__setattr__(
|
|
88
|
+
handle, "name", self.original_names.get(handle.name, handle.name)
|
|
89
|
+
)
|
|
30
90
|
|
|
31
91
|
|
|
32
92
|
class ClearModelInternals(Transformer):
|
|
@@ -1,22 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
from collections.abc import Sequence, Sized
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def s(items: Sized | int) -> str:
|
|
5
|
+
if isinstance(items, Sized):
|
|
3
6
|
items = len(items)
|
|
4
7
|
return "" if items == 1 else "s"
|
|
5
8
|
|
|
6
9
|
|
|
7
|
-
def are(items:
|
|
10
|
+
def are(items: Sized) -> str:
|
|
8
11
|
return "is" if len(items) == 1 else "are"
|
|
9
12
|
|
|
10
13
|
|
|
11
|
-
def
|
|
14
|
+
def were(items: Sized) -> str:
|
|
15
|
+
return "was" if len(items) == 1 else "were"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def an(items: Sized) -> str:
|
|
19
|
+
return "an " if len(items) == 1 else ""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def they(items: Sized) -> str:
|
|
12
23
|
return "it" if len(items) == 1 else "they"
|
|
13
24
|
|
|
14
25
|
|
|
15
|
-
def conj(items:
|
|
26
|
+
def conj(items: Sized) -> str:
|
|
16
27
|
return "s" if len(items) == 1 else ""
|
|
17
28
|
|
|
18
29
|
|
|
19
|
-
def readable_list(items:
|
|
30
|
+
def readable_list(items: Sequence, quote: bool = False) -> str:
|
|
20
31
|
if quote:
|
|
21
32
|
items = [repr(str(item)) for item in items]
|
|
22
33
|
if len(items) == 1:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
INTERFACE_VERSION = "
|
|
1
|
+
INTERFACE_VERSION = "16"
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, Literal
|
|
2
2
|
|
|
3
3
|
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
|
4
|
+
from classiq.interface.enum_utils import StrEnum
|
|
5
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
|
6
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
4
7
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
|
5
8
|
|
|
6
9
|
if TYPE_CHECKING:
|
|
7
10
|
from classiq.interface.model.statement_block import StatementBlock
|
|
8
11
|
|
|
9
12
|
|
|
13
|
+
class BlockKind(StrEnum):
|
|
14
|
+
SingleCall = "single_call"
|
|
15
|
+
Compound = "compound"
|
|
16
|
+
|
|
17
|
+
|
|
10
18
|
class Invert(QuantumOperation):
|
|
11
19
|
kind: Literal["Invert"]
|
|
12
20
|
|
|
13
21
|
body: "StatementBlock"
|
|
22
|
+
block_kind: BlockKind = BlockKind.Compound
|
|
14
23
|
|
|
15
24
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
|
16
25
|
return reset_lists(self, ["body"])
|
|
@@ -18,3 +27,9 @@ class Invert(QuantumOperation):
|
|
|
18
27
|
@property
|
|
19
28
|
def blocks(self) -> dict[str, "StatementBlock"]:
|
|
20
29
|
return {"body": self.body}
|
|
30
|
+
|
|
31
|
+
def validate_node(self) -> None:
|
|
32
|
+
if self.block_kind == BlockKind.SingleCall and (
|
|
33
|
+
len(self.body) != 1 or not isinstance(self.body[0], QuantumFunctionCall)
|
|
34
|
+
):
|
|
35
|
+
raise ClassiqInternalExpansionError("Malformed single-call invert")
|
classiq/interface/model/model.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import Annotated, Any, Literal, NewType
|
|
|
5
5
|
import pydantic
|
|
6
6
|
|
|
7
7
|
from classiq.interface.ast_node import ASTNode
|
|
8
|
+
from classiq.interface.compression_utils import compress_pydantic, decompress
|
|
8
9
|
from classiq.interface.debug_info.debug_info import DebugInfoCollection
|
|
9
10
|
from classiq.interface.exceptions import ClassiqValueError
|
|
10
11
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
|
@@ -96,9 +97,9 @@ class Model(VersionedModel, ASTNode):
|
|
|
96
97
|
)
|
|
97
98
|
preferences: Preferences = pydantic.Field(default_factory=Preferences)
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
_debug_info: DebugInfoCollection | None = pydantic.PrivateAttr(default=None)
|
|
101
|
+
compressed_debug_info: bytes | None = pydantic.Field(default=None)
|
|
102
|
+
|
|
102
103
|
functions_compilation_metadata: defaultdict[
|
|
103
104
|
str,
|
|
104
105
|
Annotated[
|
|
@@ -198,3 +199,41 @@ class Model(VersionedModel, ASTNode):
|
|
|
198
199
|
return model.model_dump(
|
|
199
200
|
exclude={"constraints", "execution_preferences", "preferences"},
|
|
200
201
|
)
|
|
202
|
+
|
|
203
|
+
# TODO (CLS-4966): remove
|
|
204
|
+
@pydantic.model_validator(mode="wrap")
|
|
205
|
+
@classmethod
|
|
206
|
+
def get_deprecated_debug_info(
|
|
207
|
+
cls, data: Any, handler: pydantic.ModelWrapValidatorHandler
|
|
208
|
+
) -> "Model":
|
|
209
|
+
model = handler(data)
|
|
210
|
+
if isinstance(data, dict) and "debug_info" in data:
|
|
211
|
+
model._debug_info = DebugInfoCollection.model_validate(data["debug_info"])
|
|
212
|
+
return model
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def debug_info(self) -> DebugInfoCollection:
|
|
216
|
+
if self._debug_info is None:
|
|
217
|
+
if self.compressed_debug_info is None:
|
|
218
|
+
self._debug_info = DebugInfoCollection()
|
|
219
|
+
else:
|
|
220
|
+
self._debug_info = DebugInfoCollection.model_validate(
|
|
221
|
+
decompress(self.compressed_debug_info)
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
return self._debug_info
|
|
225
|
+
|
|
226
|
+
@debug_info.setter
|
|
227
|
+
def debug_info(self, value: DebugInfoCollection) -> None:
|
|
228
|
+
self._debug_info = value
|
|
229
|
+
self.compressed_debug_info = None
|
|
230
|
+
|
|
231
|
+
def clear_debug_info(self) -> None:
|
|
232
|
+
self._debug_info = None
|
|
233
|
+
self.compressed_debug_info = None
|
|
234
|
+
|
|
235
|
+
def compress_debug_info(self) -> None:
|
|
236
|
+
if self._debug_info is None:
|
|
237
|
+
self.compressed_debug_info = None
|
|
238
|
+
else:
|
|
239
|
+
self.compressed_debug_info = compress_pydantic(self._debug_info)
|
|
@@ -10,8 +10,10 @@ from classiq.interface.model.quantum_statement import QuantumStatement
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ModelVisitor(Visitor):
|
|
13
|
-
def visit_DebugInfoCollection(
|
|
14
|
-
|
|
13
|
+
def visit_DebugInfoCollection(
|
|
14
|
+
self, debug_info: DebugInfoCollection
|
|
15
|
+
) -> RetType | None:
|
|
16
|
+
return None
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
class ModelStatementsVisitor(ModelVisitor):
|
|
@@ -29,6 +29,13 @@ from classiq.interface.model.quantum_lambda_function import (
|
|
|
29
29
|
)
|
|
30
30
|
from classiq.interface.model.quantum_statement import HandleMetadata, QuantumOperation
|
|
31
31
|
|
|
32
|
+
|
|
33
|
+
def _split_concatenation(var: HandleBinding | HandlesList) -> list[HandleBinding]:
|
|
34
|
+
if isinstance(var, HandleBinding):
|
|
35
|
+
return [var]
|
|
36
|
+
return list(chain.from_iterable(_split_concatenation(item) for item in var.handles))
|
|
37
|
+
|
|
38
|
+
|
|
32
39
|
ArgValue = Union[
|
|
33
40
|
Expression,
|
|
34
41
|
QuantumOperand,
|
|
@@ -221,18 +228,23 @@ class QuantumFunctionCall(QuantumOperation):
|
|
|
221
228
|
def _get_handles_with_declarations(
|
|
222
229
|
self,
|
|
223
230
|
) -> Iterable[tuple[int, AnonPortDeclaration, HandleBinding]]:
|
|
231
|
+
"""
|
|
232
|
+
Get variable arguments attached to their position and parameter declaration.
|
|
233
|
+
Splits concatenations into variables.
|
|
234
|
+
"""
|
|
224
235
|
return [
|
|
225
|
-
(
|
|
226
|
-
for
|
|
236
|
+
(positional_idx, port, var)
|
|
237
|
+
for positional_idx, (port, var_or_concatenation) in enumerate(
|
|
227
238
|
zip(
|
|
228
239
|
(port_decl for port_decl in self.func_decl.port_declarations),
|
|
229
240
|
(
|
|
230
|
-
|
|
231
|
-
for
|
|
232
|
-
if isinstance(
|
|
241
|
+
arg
|
|
242
|
+
for arg in self.positional_args
|
|
243
|
+
if isinstance(arg, (HandleBinding, HandlesList))
|
|
233
244
|
),
|
|
234
245
|
)
|
|
235
246
|
)
|
|
247
|
+
for var in _split_concatenation(var_or_concatenation)
|
|
236
248
|
]
|
|
237
249
|
|
|
238
250
|
def _get_readable_location(
|
|
@@ -78,6 +78,9 @@ class QuantumType(HashableASTNode):
|
|
|
78
78
|
def without_symbolic_attributes(self) -> Self:
|
|
79
79
|
return self
|
|
80
80
|
|
|
81
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
82
|
+
return {}
|
|
83
|
+
|
|
81
84
|
|
|
82
85
|
class QuantumScalar(QuantumType):
|
|
83
86
|
@property
|
|
@@ -262,6 +265,14 @@ class QuantumBitvector(QuantumType):
|
|
|
262
265
|
length = 1
|
|
263
266
|
return length * self.element_type.minimal_size_in_bits
|
|
264
267
|
|
|
268
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
269
|
+
attrs: dict[str, Any] = {}
|
|
270
|
+
if self.has_constant_length:
|
|
271
|
+
attrs[f"{path_expr_prefix}.len"] = self.length_value
|
|
272
|
+
return attrs | self.element_type.get_compile_time_attributes(
|
|
273
|
+
f"{path_expr_prefix}[0]"
|
|
274
|
+
)
|
|
275
|
+
|
|
265
276
|
def without_symbolic_attributes(self) -> "QuantumBitvector":
|
|
266
277
|
length = (
|
|
267
278
|
None
|
|
@@ -301,6 +312,16 @@ class QuantumNumeric(QuantumScalar):
|
|
|
301
312
|
)
|
|
302
313
|
return self
|
|
303
314
|
|
|
315
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
316
|
+
attrs: dict[str, Any] = {}
|
|
317
|
+
if self.has_size_in_bits:
|
|
318
|
+
attrs[f"{path_expr_prefix}.size"] = self.size_in_bits
|
|
319
|
+
if self.has_constant_sign:
|
|
320
|
+
attrs[f"{path_expr_prefix}.is_signed"] = self.sign_value
|
|
321
|
+
if self.has_constant_fraction_digits:
|
|
322
|
+
attrs[f"{path_expr_prefix}.fraction_digits"] = self.fraction_digits_value
|
|
323
|
+
return attrs
|
|
324
|
+
|
|
304
325
|
def set_size_in_bits(self, val: int) -> None:
|
|
305
326
|
super().set_size_in_bits(val)
|
|
306
327
|
if self.size is not None:
|
|
@@ -13,9 +13,6 @@ from classiq.interface.model.invert import Invert
|
|
|
13
13
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
14
14
|
from classiq.interface.model.phase_operation import PhaseOperation
|
|
15
15
|
from classiq.interface.model.power import Power
|
|
16
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
17
|
-
AmplitudeLoadingOperation,
|
|
18
|
-
)
|
|
19
16
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
20
17
|
ArithmeticOperation,
|
|
21
18
|
)
|
|
@@ -38,7 +35,6 @@ ConcreteQuantumStatement = Annotated[
|
|
|
38
35
|
QuantumFunctionCall,
|
|
39
36
|
Allocate,
|
|
40
37
|
ArithmeticOperation,
|
|
41
|
-
AmplitudeLoadingOperation,
|
|
42
38
|
VariableDeclarationStatement,
|
|
43
39
|
BindOperation,
|
|
44
40
|
InplaceBinaryOperation,
|
|
@@ -56,8 +56,8 @@ if TYPE_CHECKING:
|
|
|
56
56
|
from classiq.model_expansions.closure import FunctionClosure
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
_INITIALIZED_VAR_MESSAGE = "Variable '{}' should be uninitialized here"
|
|
60
|
+
_UNINITIALIZED_VAR_MESSAGE = "Variable '{}' should be initialized here"
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def _get_symbol_expr(symbol: str, classical_type: ClassicalType) -> Expression:
|
|
@@ -311,7 +311,7 @@ class CapturedVars:
|
|
|
311
311
|
return PortDirection.Inout
|
|
312
312
|
if target_direction == PortDirection.Outin:
|
|
313
313
|
return PortDirection.Input
|
|
314
|
-
raise ClassiqExpansionError(
|
|
314
|
+
raise ClassiqExpansionError(_UNINITIALIZED_VAR_MESSAGE.format(var_name))
|
|
315
315
|
|
|
316
316
|
if source_direction == PortDirection.Output:
|
|
317
317
|
if target_direction == PortDirection.Input:
|
|
@@ -320,18 +320,18 @@ class CapturedVars:
|
|
|
320
320
|
PortDirection.Output,
|
|
321
321
|
PortDirection.Outin,
|
|
322
322
|
):
|
|
323
|
-
raise ClassiqExpansionError(
|
|
323
|
+
raise ClassiqExpansionError(_INITIALIZED_VAR_MESSAGE.format(var_name))
|
|
324
324
|
return PortDirection.Output
|
|
325
325
|
|
|
326
326
|
if source_direction == PortDirection.Inout:
|
|
327
327
|
if target_direction in (PortDirection.Input, PortDirection.Inout):
|
|
328
328
|
return target_direction
|
|
329
|
-
raise ClassiqExpansionError(
|
|
329
|
+
raise ClassiqExpansionError(_INITIALIZED_VAR_MESSAGE.format(var_name))
|
|
330
330
|
|
|
331
331
|
if source_direction == PortDirection.Outin:
|
|
332
332
|
if target_direction in (PortDirection.Output, PortDirection.Outin):
|
|
333
333
|
return target_direction
|
|
334
|
-
raise ClassiqExpansionError(
|
|
334
|
+
raise ClassiqExpansionError(_UNINITIALIZED_VAR_MESSAGE.format(var_name))
|
|
335
335
|
|
|
336
336
|
raise ClassiqInternalExpansionError(f"Unexpected direction {source_direction}")
|
|
337
337
|
|
|
@@ -346,7 +346,7 @@ class CapturedVars:
|
|
|
346
346
|
PortDirection.Outin,
|
|
347
347
|
):
|
|
348
348
|
raise ClassiqExpansionError(
|
|
349
|
-
|
|
349
|
+
_UNINITIALIZED_VAR_MESSAGE.format(captured_handle.handle)
|
|
350
350
|
)
|
|
351
351
|
return existing_captured_handle
|
|
352
352
|
|
|
@@ -356,7 +356,7 @@ class CapturedVars:
|
|
|
356
356
|
PortDirection.Outin,
|
|
357
357
|
):
|
|
358
358
|
raise ClassiqExpansionError(
|
|
359
|
-
|
|
359
|
+
_INITIALIZED_VAR_MESSAGE.format(captured_handle.handle)
|
|
360
360
|
)
|
|
361
361
|
return captured_handle
|
|
362
362
|
|
|
@@ -705,7 +705,9 @@ class CapturedVars:
|
|
|
705
705
|
def set_parent(self, parent: "CapturedVars") -> None:
|
|
706
706
|
self._handle_states += parent._get_handle_states()
|
|
707
707
|
|
|
708
|
-
def get_state(
|
|
708
|
+
def get_state(
|
|
709
|
+
self, var_name: str, defining_function: "FunctionClosure"
|
|
710
|
+
) -> bool | None:
|
|
709
711
|
for name, func, state in self._handle_states:
|
|
710
712
|
if name == var_name and _same_closure(func, defining_function):
|
|
711
713
|
return state
|
|
@@ -717,9 +719,7 @@ class CapturedVars:
|
|
|
717
719
|
PortDirection.Output,
|
|
718
720
|
PortDirection.Inout,
|
|
719
721
|
)
|
|
720
|
-
|
|
721
|
-
f"Cannot find {var_name!r} from {defining_function.name!r}"
|
|
722
|
-
)
|
|
722
|
+
return None
|
|
723
723
|
|
|
724
724
|
def clone(self) -> "CapturedVars":
|
|
725
725
|
return CapturedVars(
|
|
@@ -846,6 +846,10 @@ def validate_end_state(func: "FunctionClosure", captured_vars: CapturedVars) ->
|
|
|
846
846
|
for param in func.positional_arg_declarations:
|
|
847
847
|
if isinstance(param, PortDeclaration):
|
|
848
848
|
state = captured_vars.get_state(param.name, func)
|
|
849
|
+
if state is None:
|
|
850
|
+
raise ClassiqInternalExpansionError(
|
|
851
|
+
f"Cannot find {param.name!r} from {func.name!r}"
|
|
852
|
+
)
|
|
849
853
|
expected_state = param.direction in (
|
|
850
854
|
PortDeclarationDirection.Output,
|
|
851
855
|
PortDeclarationDirection.Inout,
|
|
@@ -13,6 +13,8 @@ from classiq.interface.generator.compiler_keywords import (
|
|
|
13
13
|
)
|
|
14
14
|
from classiq.interface.generator.functions.builtins.internal_operators import (
|
|
15
15
|
BLOCK_OPERATOR_NAME,
|
|
16
|
+
INVERT_OPERATOR_NAMES,
|
|
17
|
+
SINGLE_CALL_INVERT_OPERATOR_NAME,
|
|
16
18
|
SKIP_CONTROL_OPERATOR_NAME,
|
|
17
19
|
WITHIN_APPLY_NAME,
|
|
18
20
|
)
|
|
@@ -44,6 +46,7 @@ BLOCKS_ALLOWED_CAPTURING = (
|
|
|
44
46
|
WITHIN_APPLY_NAME,
|
|
45
47
|
BLOCK_OPERATOR_NAME,
|
|
46
48
|
SKIP_CONTROL_OPERATOR_NAME,
|
|
49
|
+
SINGLE_CALL_INVERT_OPERATOR_NAME,
|
|
47
50
|
)
|
|
48
51
|
|
|
49
52
|
|
|
@@ -155,6 +158,8 @@ class OperationBuilder:
|
|
|
155
158
|
self._operations[-1].blocks[block_name] = block
|
|
156
159
|
yield
|
|
157
160
|
captured_vars = self.current_block.captured_vars
|
|
161
|
+
if self.current_operation.name in INVERT_OPERATOR_NAMES:
|
|
162
|
+
captured_vars = captured_vars.negate()
|
|
158
163
|
if (
|
|
159
164
|
not isinstance(self.current_operation, FunctionClosure)
|
|
160
165
|
and self.current_operation.name not in BLOCKS_ALLOWED_CAPTURING
|
|
@@ -178,7 +183,10 @@ class OperationBuilder:
|
|
|
178
183
|
context.closure.captured_vars.init_params(original_operation)
|
|
179
184
|
else:
|
|
180
185
|
context = OperationContext(closure=original_operation)
|
|
181
|
-
context.
|
|
186
|
+
if context.name != SINGLE_CALL_INVERT_OPERATOR_NAME:
|
|
187
|
+
context.closure.captured_vars.set_parent(
|
|
188
|
+
self.current_block.captured_vars
|
|
189
|
+
)
|
|
182
190
|
self._operations.append(context)
|
|
183
191
|
yield context
|
|
184
192
|
self._finalize_within_apply()
|
|
@@ -32,6 +32,7 @@ from classiq.interface.model.handle_binding import (
|
|
|
32
32
|
from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model
|
|
33
33
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
34
34
|
from classiq.interface.model.quantum_function_declaration import (
|
|
35
|
+
NamedParamsQuantumFunctionDeclaration,
|
|
35
36
|
QuantumFunctionDeclaration,
|
|
36
37
|
)
|
|
37
38
|
from classiq.interface.model.quantum_lambda_function import (
|
|
@@ -76,6 +77,7 @@ from classiq.model_expansions.scope_initialization import (
|
|
|
76
77
|
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
|
77
78
|
from classiq.qmod.builtins.constants import __all__ as builtin_constants
|
|
78
79
|
from classiq.qmod.builtins.enums import BUILTIN_ENUM_DECLARATIONS
|
|
80
|
+
from classiq.qmod.builtins.functions import CORE_LIB_DECLS
|
|
79
81
|
from classiq.qmod.builtins.structs import BUILTIN_STRUCT_DECLARATIONS
|
|
80
82
|
from classiq.qmod.model_state_container import QMODULE
|
|
81
83
|
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
|
@@ -98,7 +100,7 @@ class BaseInterpreter:
|
|
|
98
100
|
skip_type_modifier_validation: bool = False
|
|
99
101
|
|
|
100
102
|
def __init__(self, model: Model) -> None:
|
|
101
|
-
validate_model(model)
|
|
103
|
+
validate_model(model, self.get_builtin_functions())
|
|
102
104
|
self._model = model
|
|
103
105
|
self._top_level_scope = Scope()
|
|
104
106
|
self._counted_name_allocator = CountedNameAllocator()
|
|
@@ -121,6 +123,9 @@ class BaseInterpreter:
|
|
|
121
123
|
self._counted_name_allocator = CountedNameAllocator()
|
|
122
124
|
self._error_manager: ErrorManager = ErrorManager()
|
|
123
125
|
|
|
126
|
+
def get_builtin_functions(self) -> list[NamedParamsQuantumFunctionDeclaration]:
|
|
127
|
+
return CORE_LIB_DECLS
|
|
128
|
+
|
|
124
129
|
def _expand_main_func(self) -> None:
|
|
125
130
|
main_closure = self._get_main_closure(
|
|
126
131
|
self._top_level_scope[MAIN_FUNCTION_NAME].value
|
|
@@ -159,7 +164,7 @@ class BaseInterpreter:
|
|
|
159
164
|
finally:
|
|
160
165
|
self._error_manager.report_errors(ClassiqExpansionError)
|
|
161
166
|
|
|
162
|
-
|
|
167
|
+
model = Model(
|
|
163
168
|
constraints=self._model.constraints,
|
|
164
169
|
preferences=self._model.preferences,
|
|
165
170
|
classical_execution_code=self._model.classical_execution_code,
|
|
@@ -181,9 +186,10 @@ class BaseInterpreter:
|
|
|
181
186
|
if name not in BUILTIN_STRUCT_DECLARATIONS
|
|
182
187
|
],
|
|
183
188
|
qstructs=list(QMODULE.qstruct_decls.values()),
|
|
184
|
-
debug_info=self._model.debug_info,
|
|
185
189
|
functions_compilation_metadata=self._expanded_functions_compilation_metadata,
|
|
186
190
|
)
|
|
191
|
+
model.debug_info = self._model.debug_info
|
|
192
|
+
return model
|
|
187
193
|
|
|
188
194
|
def process_exception(self, e: Exception) -> None:
|
|
189
195
|
if not isinstance(e, (ClassiqError, ValidationError)):
|
|
@@ -206,15 +212,14 @@ class BaseInterpreter:
|
|
|
206
212
|
expression: Expression,
|
|
207
213
|
*,
|
|
208
214
|
simplify: bool = False,
|
|
209
|
-
treat_qnum_as_float: bool = False,
|
|
210
215
|
) -> Evaluated:
|
|
211
216
|
if expression.is_evaluated():
|
|
212
217
|
return Evaluated(value=expression.value.value)
|
|
213
218
|
expr_ast = ast.parse(expression.expr, mode="eval").body
|
|
214
|
-
expr_val = self._eval_expr(ast.unparse(expr_ast)
|
|
219
|
+
expr_val = self._eval_expr(ast.unparse(expr_ast))
|
|
215
220
|
if simplify and not expr_val.has_value(expr_val.root):
|
|
216
221
|
simplified_expr = simplify_qmod_expression(expr_val)
|
|
217
|
-
expr_val = self._eval_expr(simplified_expr
|
|
222
|
+
expr_val = self._eval_expr(simplified_expr)
|
|
218
223
|
if expr_val.has_value(expr_val.root):
|
|
219
224
|
value = expr_val.get_value(expr_val.root)
|
|
220
225
|
else:
|
|
@@ -222,12 +227,9 @@ class BaseInterpreter:
|
|
|
222
227
|
|
|
223
228
|
return Evaluated(value=value)
|
|
224
229
|
|
|
225
|
-
def _eval_expr(
|
|
226
|
-
self, expr: str, treat_qnum_as_float: bool
|
|
227
|
-
) -> QmodAnnotatedExpression:
|
|
230
|
+
def _eval_expr(self, expr: str) -> QmodAnnotatedExpression:
|
|
228
231
|
return evaluate_qmod_expression(
|
|
229
232
|
expr,
|
|
230
|
-
treat_qnum_as_float=treat_qnum_as_float,
|
|
231
233
|
machine_precision=self._model.preferences.machine_precision,
|
|
232
234
|
classical_struct_declarations=list(QMODULE.type_decls.values()),
|
|
233
235
|
enum_declarations=list(QMODULE.enum_decls.values()),
|
|
@@ -9,10 +9,11 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
|
9
9
|
from classiq.interface.generator.functions.builtins.internal_operators import (
|
|
10
10
|
BLOCK_OPERATOR_NAME,
|
|
11
11
|
CLASSICAL_IF_OPERATOR_NAME,
|
|
12
|
+
COMPOUND_INVERT_OPERATOR_NAME,
|
|
12
13
|
CONTROL_OPERATOR_NAME,
|
|
13
|
-
INVERT_OPERATOR_NAME,
|
|
14
14
|
POWER_OPERATOR_NAME,
|
|
15
15
|
REPEAT_OPERATOR_NAME,
|
|
16
|
+
SINGLE_CALL_INVERT_OPERATOR_NAME,
|
|
16
17
|
SKIP_CONTROL_OPERATOR_NAME,
|
|
17
18
|
WITHIN_APPLY_NAME,
|
|
18
19
|
)
|
|
@@ -23,14 +24,11 @@ from classiq.interface.model.bounds import SetBoundsStatement
|
|
|
23
24
|
from classiq.interface.model.classical_if import ClassicalIf
|
|
24
25
|
from classiq.interface.model.control import Control
|
|
25
26
|
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
|
26
|
-
from classiq.interface.model.invert import Invert
|
|
27
|
+
from classiq.interface.model.invert import BlockKind, Invert
|
|
27
28
|
from classiq.interface.model.model import Model
|
|
28
29
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
29
30
|
from classiq.interface.model.phase_operation import PhaseOperation
|
|
30
31
|
from classiq.interface.model.power import Power
|
|
31
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
32
|
-
AmplitudeLoadingOperation,
|
|
33
|
-
)
|
|
34
32
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
35
33
|
ArithmeticOperation,
|
|
36
34
|
)
|
|
@@ -199,24 +197,6 @@ class GenerativeInterpreter(BaseInterpreter):
|
|
|
199
197
|
bind
|
|
200
198
|
)
|
|
201
199
|
|
|
202
|
-
@emit.register
|
|
203
|
-
def emit_amplitude_loading_operation(self, op: AmplitudeLoadingOperation) -> None:
|
|
204
|
-
CompositeEmitter[AmplitudeLoadingOperation](
|
|
205
|
-
self,
|
|
206
|
-
[
|
|
207
|
-
HandleEvaluator(self, "result_var"),
|
|
208
|
-
ExpressionEvaluator(
|
|
209
|
-
self,
|
|
210
|
-
"expression",
|
|
211
|
-
readable_expression_name="amplitude-encoding expression",
|
|
212
|
-
simplify=True,
|
|
213
|
-
treat_qnum_as_float=True,
|
|
214
|
-
allow_runtime_vars=self._symbolic_parameters_switch,
|
|
215
|
-
),
|
|
216
|
-
AssignmentResultProcessor(self),
|
|
217
|
-
],
|
|
218
|
-
).emit(op)
|
|
219
|
-
|
|
220
200
|
@emit.register
|
|
221
201
|
def _emit_arithmetic_operation(self, op: ArithmeticOperation) -> None:
|
|
222
202
|
self.emit_arithmetic_operation(op)
|
|
@@ -285,7 +265,12 @@ class GenerativeInterpreter(BaseInterpreter):
|
|
|
285
265
|
|
|
286
266
|
@emit.register
|
|
287
267
|
def emit_invert(self, invert: Invert) -> None:
|
|
288
|
-
|
|
268
|
+
match invert.block_kind:
|
|
269
|
+
case BlockKind.SingleCall:
|
|
270
|
+
op_name = SINGLE_CALL_INVERT_OPERATOR_NAME
|
|
271
|
+
case BlockKind.Compound:
|
|
272
|
+
op_name = COMPOUND_INVERT_OPERATOR_NAME
|
|
273
|
+
BlockEvaluator(self, op_name, "body").emit(invert)
|
|
289
274
|
|
|
290
275
|
@emit.register
|
|
291
276
|
def emit_skip_control(self, skip_control: SkipControl) -> None:
|