classiq 0.61.0__py3-none-any.whl → 0.63.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 +6 -26
- classiq/_internals/client.py +1 -9
- classiq/applications/chemistry/chemistry_model_constructor.py +1 -1
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +26 -8
- classiq/applications/combinatorial_helpers/optimization_model.py +13 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +143 -13
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +58 -23
- classiq/applications/grover/grover_model_constructor.py +1 -1
- classiq/applications/libraries/qmci_library.py +2 -1
- classiq/execution/execution_session.py +66 -96
- classiq/execution/jobs.py +12 -10
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +26 -5
- classiq/interface/backend/pydantic_backend.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +3 -1
- classiq/interface/chemistry/operator.py +0 -204
- classiq/interface/execution/primitives.py +1 -0
- classiq/interface/generator/compiler_keywords.py +4 -0
- classiq/interface/generator/copy.py +47 -0
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -0
- classiq/interface/generator/functions/type_name.py +6 -0
- classiq/interface/generator/generated_circuit_data.py +22 -7
- classiq/interface/generator/model/model.py +3 -0
- classiq/interface/generator/model/preferences/preferences.py +14 -1
- classiq/interface/generator/quantum_function_call.py +4 -2
- classiq/interface/generator/types/compilation_metadata.py +2 -1
- classiq/interface/model/handle_binding.py +50 -5
- classiq/interface/model/quantum_type.py +16 -0
- classiq/interface/server/routes.py +1 -3
- classiq/model_expansions/capturing/captured_vars.py +114 -28
- classiq/model_expansions/closure.py +25 -65
- classiq/model_expansions/function_builder.py +19 -9
- classiq/model_expansions/generative_functions.py +16 -2
- classiq/model_expansions/interpreter.py +110 -66
- classiq/model_expansions/model_tables.py +4 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +83 -20
- classiq/model_expansions/quantum_operations/classicalif.py +1 -1
- classiq/model_expansions/quantum_operations/control.py +3 -10
- classiq/model_expansions/quantum_operations/emitter.py +3 -4
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +1 -2
- classiq/model_expansions/quantum_operations/quantum_function_call.py +1 -1
- classiq/model_expansions/quantum_operations/repeat.py +4 -3
- classiq/model_expansions/quantum_operations/shallow_emitter.py +9 -3
- classiq/model_expansions/scope.py +9 -13
- classiq/model_expansions/scope_initialization.py +34 -25
- classiq/model_expansions/transformers/var_splitter.py +57 -7
- classiq/open_library/__init__.py +4 -0
- classiq/open_library/functions/__init__.py +130 -0
- classiq/{qmod/builtins → open_library}/functions/amplitude_estimation.py +2 -2
- classiq/{qmod/builtins → open_library}/functions/discrete_sine_cosine_transform.py +6 -4
- classiq/{qmod/builtins → open_library}/functions/grover.py +2 -2
- classiq/{qmod/builtins → open_library}/functions/linear_pauli_rotation.py +1 -1
- classiq/{qmod/builtins → open_library}/functions/modular_exponentiation.py +2 -2
- classiq/{qmod/builtins → open_library}/functions/qpe.py +2 -2
- classiq/{qmod/builtins → open_library}/functions/state_preparation.py +6 -149
- classiq/{qmod/builtins → open_library}/functions/swap_test.py +1 -1
- classiq/open_library/functions/utility_functions.py +81 -0
- classiq/{qmod/builtins → open_library}/functions/variational.py +1 -1
- classiq/qmod/builtins/functions/__init__.py +4 -130
- classiq/qmod/builtins/functions/allocation.py +150 -0
- classiq/qmod/builtins/functions/arithmetic.py +0 -34
- classiq/qmod/builtins/functions/operators.py +0 -6
- classiq/qmod/builtins/operations.py +19 -80
- classiq/qmod/create_model_function.py +8 -162
- classiq/qmod/generative.py +0 -16
- classiq/qmod/model_state_container.py +7 -0
- classiq/qmod/native/pretty_printer.py +10 -11
- classiq/qmod/pretty_print/pretty_printer.py +1 -1
- classiq/qmod/python_classical_type.py +1 -5
- classiq/qmod/qfunc.py +11 -12
- classiq/qmod/qmod_variable.py +1 -3
- classiq/qmod/quantum_expandable.py +23 -1
- classiq/qmod/quantum_function.py +69 -7
- {classiq-0.61.0.dist-info → classiq-0.63.0.dist-info}/METADATA +2 -1
- {classiq-0.61.0.dist-info → classiq-0.63.0.dist-info}/RECORD +82 -78
- classiq/qmod/builtins/functions/utility_functions.py +0 -43
- /classiq/{qmod/builtins → open_library}/functions/hea.py +0 -0
- /classiq/{qmod/builtins → open_library}/functions/qaoa_penalty.py +0 -0
- /classiq/{qmod/builtins → open_library}/functions/qft_functions.py +0 -0
- /classiq/{qmod/builtins → open_library}/functions/qsvt.py +0 -0
- {classiq-0.61.0.dist-info → classiq-0.63.0.dist-info}/WHEEL +0 -0
@@ -1,28 +1,21 @@
|
|
1
1
|
import dataclasses
|
2
2
|
import json
|
3
|
-
import
|
4
|
-
from collections.abc import Collection, Iterator, Sequence
|
5
|
-
from contextlib import contextmanager
|
3
|
+
from collections.abc import Collection, Sequence
|
6
4
|
from dataclasses import dataclass, field
|
7
5
|
from functools import singledispatch
|
8
|
-
from symtable import Symbol
|
9
6
|
from typing import Any, Optional
|
10
7
|
|
11
8
|
from typing_extensions import Self
|
12
9
|
|
13
10
|
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
14
|
-
from classiq.interface.generator.functions.builtins.internal_operators import (
|
15
|
-
All_BUILTINS_OPERATORS,
|
16
|
-
)
|
17
11
|
from classiq.interface.model.port_declaration import PortDeclaration
|
18
12
|
from classiq.interface.model.quantum_function_declaration import (
|
19
13
|
NamedParamsQuantumFunctionDeclaration,
|
20
14
|
PositionalArg,
|
21
|
-
QuantumOperandDeclaration,
|
22
15
|
)
|
16
|
+
from classiq.interface.model.quantum_lambda_function import QuantumCallable
|
23
17
|
from classiq.interface.model.quantum_statement import QuantumStatement
|
24
18
|
|
25
|
-
from classiq import ClassicalParameterDeclaration
|
26
19
|
from classiq.model_expansions.capturing.captured_vars import CapturedVars
|
27
20
|
from classiq.model_expansions.expression_renamer import ExpressionRenamer
|
28
21
|
from classiq.model_expansions.scope import (
|
@@ -51,11 +44,6 @@ class Closure:
|
|
51
44
|
if isinstance(param, PortDeclaration)
|
52
45
|
}
|
53
46
|
|
54
|
-
@contextmanager
|
55
|
-
def freeze(self) -> Iterator[None]:
|
56
|
-
with self.scope.freeze(), self.captured_vars.freeze():
|
57
|
-
yield
|
58
|
-
|
59
47
|
|
60
48
|
@dataclass(frozen=True)
|
61
49
|
class GenerativeClosure(Closure):
|
@@ -79,15 +67,7 @@ class FunctionClosure(Closure):
|
|
79
67
|
# The closure is changing across the interpreter flow so it's closure_id may change
|
80
68
|
@property
|
81
69
|
def closure_id(self) -> str:
|
82
|
-
|
83
|
-
# may create a bugs. Therefore, with each call to closure_id a new id is
|
84
|
-
# created
|
85
|
-
if self.is_lambda or self.name in All_BUILTINS_OPERATORS:
|
86
|
-
signature = str(uuid.uuid4())
|
87
|
-
else:
|
88
|
-
signature = _generate_closure_id(
|
89
|
-
self.positional_arg_declarations, self.scope.data.values()
|
90
|
-
)
|
70
|
+
signature = _generate_closure_id(self.scope.data.values())
|
91
71
|
return f"{self.name}__{signature}"
|
92
72
|
|
93
73
|
@property
|
@@ -142,70 +122,50 @@ class FunctionClosure(Closure):
|
|
142
122
|
def set_depth(self, depth: int) -> Self:
|
143
123
|
return dataclasses.replace(self, _depth=depth)
|
144
124
|
|
145
|
-
def
|
125
|
+
def clone(self) -> Self:
|
146
126
|
return dataclasses.replace(
|
147
|
-
self,
|
127
|
+
self,
|
128
|
+
scope=self.scope.clone(),
|
129
|
+
signature_scope=self.signature_scope.clone(),
|
130
|
+
captured_vars=self.captured_vars.clone(),
|
148
131
|
)
|
149
132
|
|
133
|
+
def emit(self) -> QuantumCallable:
|
134
|
+
return self.name
|
135
|
+
|
150
136
|
|
151
137
|
@dataclass(frozen=True)
|
152
138
|
class GenerativeFunctionClosure(GenerativeClosure, FunctionClosure):
|
153
139
|
pass
|
154
140
|
|
155
141
|
|
156
|
-
def _generate_closure_id(
|
157
|
-
|
158
|
-
)
|
159
|
-
|
160
|
-
for arg_declara, eval_arg in zip(args_declaration, evaluated_args):
|
161
|
-
args_signature |= _generate_arg_id(arg_declara, eval_arg)
|
142
|
+
def _generate_closure_id(evaluated_args: Collection[Evaluated]) -> str:
|
143
|
+
args_signature = [
|
144
|
+
_evaluated_arg_to_str(eval_arg.value) for eval_arg in evaluated_args
|
145
|
+
]
|
162
146
|
return json.dumps(args_signature)
|
163
147
|
|
164
148
|
|
165
|
-
|
166
|
-
arg_declaration: PositionalArg, evaluated_arg: Evaluated
|
167
|
-
) -> dict[str, str]:
|
168
|
-
arg_value = evaluated_arg.value
|
169
|
-
arg_name = arg_declaration.name
|
170
|
-
if isinstance(arg_declaration, ClassicalParameterDeclaration):
|
171
|
-
return {arg_name: evaluated_classical_param_to_str(arg_value)}
|
172
|
-
if isinstance(arg_declaration, PortDeclaration):
|
173
|
-
return {arg_name: _evaluated_port_to_str(arg_value)}
|
174
|
-
if isinstance(arg_declaration, QuantumOperandDeclaration):
|
175
|
-
return {arg_name: _evaluated_operand_to_str(arg_value)}
|
176
|
-
|
177
|
-
|
149
|
+
@singledispatch
|
178
150
|
def _evaluated_arg_to_str(arg: Any) -> str:
|
179
151
|
if isinstance(arg, str):
|
180
152
|
return arg
|
181
|
-
|
153
|
+
if isinstance(arg, QuantumSymbol):
|
154
|
+
return _evaluated_quantum_symbol_to_str(arg)
|
155
|
+
if isinstance(arg, FunctionClosure):
|
156
|
+
return _evaluated_one_operand_to_str(arg)
|
157
|
+
if isinstance(arg, list) and arg and isinstance(arg[0], FunctionClosure):
|
158
|
+
return _evaluated_operands_list_to_str(arg)
|
159
|
+
return evaluated_classical_param_to_str(arg)
|
182
160
|
|
183
161
|
|
184
|
-
@singledispatch
|
185
|
-
def _evaluated_port_to_str(arg: Any) -> str:
|
186
|
-
return _evaluated_arg_to_str(arg)
|
187
|
-
|
188
|
-
|
189
|
-
@_evaluated_port_to_str.register
|
190
162
|
def _evaluated_quantum_symbol_to_str(port: QuantumSymbol) -> str:
|
191
163
|
return port.quantum_type.model_dump_json(exclude_none=True, exclude={"name"})
|
192
164
|
|
193
165
|
|
194
|
-
@_evaluated_port_to_str.register
|
195
|
-
def _evaluated_symbol_to_str(port: Symbol) -> str:
|
196
|
-
return repr(port)
|
197
|
-
|
198
|
-
|
199
|
-
@singledispatch
|
200
|
-
def _evaluated_operand_to_str(arg: Any) -> str:
|
201
|
-
return _evaluated_arg_to_str(arg)
|
202
|
-
|
203
|
-
|
204
|
-
@_evaluated_operand_to_str.register
|
205
166
|
def _evaluated_one_operand_to_str(operand: FunctionClosure) -> str:
|
206
167
|
return operand.closure_id
|
207
168
|
|
208
169
|
|
209
|
-
|
210
|
-
|
211
|
-
return json.dumps([_evaluated_operand_to_str(ope) for ope in operands])
|
170
|
+
def _evaluated_operands_list_to_str(arg: list[FunctionClosure]) -> str:
|
171
|
+
return json.dumps([_evaluated_one_operand_to_str(ope) for ope in arg])
|
@@ -31,6 +31,7 @@ from classiq.model_expansions.capturing.captured_vars import (
|
|
31
31
|
)
|
32
32
|
from classiq.model_expansions.closure import Closure, FunctionClosure
|
33
33
|
from classiq.model_expansions.scope import Scope
|
34
|
+
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
34
35
|
|
35
36
|
ClosureType = TypeVar("ClosureType", bound=Closure)
|
36
37
|
|
@@ -82,16 +83,23 @@ class FunctionContext(OperationContext[FunctionClosure]):
|
|
82
83
|
|
83
84
|
|
84
85
|
class OperationBuilder:
|
85
|
-
def __init__(
|
86
|
+
def __init__(
|
87
|
+
self, functions_scope: Scope, counted_name_allocator: CountedNameAllocator
|
88
|
+
) -> None:
|
86
89
|
self._operations: list[OperationContext] = []
|
87
90
|
self._blocks: list[str] = []
|
88
91
|
self._functions_scope = functions_scope
|
89
92
|
self._current_source_ref: Optional[SourceReference] = None
|
93
|
+
self._counted_name_allocator = counted_name_allocator
|
90
94
|
|
91
95
|
@property
|
92
96
|
def current_operation(self) -> Closure:
|
93
97
|
return self._operations[-1].closure
|
94
98
|
|
99
|
+
@property
|
100
|
+
def current_scope(self) -> Scope:
|
101
|
+
return self.current_operation.scope
|
102
|
+
|
95
103
|
@property
|
96
104
|
def current_function(self) -> FunctionClosure:
|
97
105
|
return self._get_last_function(self._operations)
|
@@ -137,7 +145,8 @@ class OperationBuilder:
|
|
137
145
|
validate_captured_directions(
|
138
146
|
captured_vars.filter_vars(
|
139
147
|
self.current_function, self.current_block.variable_declarations
|
140
|
-
)
|
148
|
+
),
|
149
|
+
report_outin=False,
|
141
150
|
)
|
142
151
|
self.current_operation.captured_vars.update(
|
143
152
|
captured_vars.filter_vars(self.current_function)
|
@@ -193,13 +202,14 @@ class OperationBuilder:
|
|
193
202
|
) -> NativeFunctionDefinition:
|
194
203
|
name = function_context.name
|
195
204
|
if name != MAIN_FUNCTION_NAME:
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
205
|
+
for _ in self.current_scope:
|
206
|
+
name = self._counted_name_allocator.allocate(
|
207
|
+
f"{name}_{LAMBDA_KEYWORD + '_0_0_' if function_context.is_lambda else ''}{EXPANDED_KEYWORD}"
|
208
|
+
)
|
209
|
+
if name not in self.current_scope:
|
210
|
+
break
|
211
|
+
else:
|
212
|
+
raise ClassiqInternalExpansionError("Could not allocate function name")
|
203
213
|
new_parameters: list[PortDeclaration] = [
|
204
214
|
param
|
205
215
|
for param in function_context.positional_arg_declarations
|
@@ -105,7 +105,21 @@ class _InterpreterExpandable(QFunc):
|
|
105
105
|
positional_arg_declarations=current_operation.positional_arg_declarations,
|
106
106
|
body=self._interpreter._builder._current_statements + [stmt],
|
107
107
|
)
|
108
|
-
|
108
|
+
declarative_functions = {
|
109
|
+
name: func
|
110
|
+
for name, func in self._qmodule.native_defs.items()
|
111
|
+
if name not in self._interpreter._top_level_scope
|
112
|
+
}
|
113
|
+
self._interpreter.update_declarative_functions(
|
114
|
+
declarative_functions, self._qmodule
|
115
|
+
)
|
116
|
+
self._interpreter.update_generative_functions(
|
117
|
+
self._qmodule.generative_functions
|
118
|
+
)
|
119
|
+
func_decls = self._get_function_declarations()
|
120
|
+
for dec_func in declarative_functions.values():
|
121
|
+
resolve_function_calls(dec_func, func_decls)
|
122
|
+
resolve_function_calls(dummy_function, func_decls)
|
109
123
|
stmt = dummy_function.body[-1]
|
110
124
|
with generative_mode_context(False):
|
111
125
|
self._interpreter.emit_statement(stmt)
|
@@ -116,7 +130,7 @@ class _InterpreterExpandable(QFunc):
|
|
116
130
|
name=name,
|
117
131
|
positional_arg_declarations=evaluated.value.positional_arg_declarations,
|
118
132
|
)
|
119
|
-
for name, evaluated in self._interpreter.
|
133
|
+
for name, evaluated in self._interpreter._builder.current_scope.items()
|
120
134
|
if isinstance(evaluated, Evaluated)
|
121
135
|
and isinstance(evaluated.value, FunctionClosure)
|
122
136
|
} | nameables_to_dict(self._interpreter._get_function_declarations())
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import
|
2
|
-
from collections.abc import
|
3
|
-
from contextlib import
|
1
|
+
from collections import defaultdict
|
2
|
+
from collections.abc import Sequence
|
3
|
+
from contextlib import nullcontext
|
4
4
|
from functools import singledispatchmethod
|
5
5
|
from typing import Any, Optional, cast
|
6
6
|
|
@@ -32,7 +32,7 @@ from classiq.interface.model.handle_binding import (
|
|
32
32
|
)
|
33
33
|
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
34
34
|
from classiq.interface.model.invert import Invert
|
35
|
-
from classiq.interface.model.model import Model
|
35
|
+
from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model
|
36
36
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
37
37
|
from classiq.interface.model.phase_operation import PhaseOperation
|
38
38
|
from classiq.interface.model.power import Power
|
@@ -93,11 +93,14 @@ from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
|
|
93
93
|
from classiq.model_expansions.scope_initialization import (
|
94
94
|
add_constants_to_scope,
|
95
95
|
add_entry_point_params_to_scope,
|
96
|
+
add_functions_to_scope,
|
97
|
+
add_generative_functions_to_scope,
|
96
98
|
get_main_renamer,
|
97
99
|
init_top_level_scope,
|
98
100
|
)
|
99
101
|
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
100
102
|
from classiq.qmod.builtins.functions import permute
|
103
|
+
from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
|
101
104
|
from classiq.qmod.quantum_function import GenerativeQFunc
|
102
105
|
from classiq.qmod.semantics.error_manager import ErrorManager
|
103
106
|
|
@@ -107,51 +110,52 @@ class Interpreter:
|
|
107
110
|
self,
|
108
111
|
model: Model,
|
109
112
|
generative_functions: Optional[list[GenerativeQFunc]] = None,
|
110
|
-
|
113
|
+
is_normalizer: bool = False,
|
114
|
+
is_shallow: bool = False,
|
111
115
|
) -> None:
|
112
|
-
self.
|
116
|
+
self._is_normalizer = is_normalizer
|
117
|
+
self._is_shallow = is_shallow
|
113
118
|
self._model = model
|
114
|
-
self.
|
115
|
-
self.
|
116
|
-
self._builder = OperationBuilder(
|
119
|
+
self._top_level_scope = Scope()
|
120
|
+
self._counted_name_allocator = CountedNameAllocator()
|
121
|
+
self._builder = OperationBuilder(
|
122
|
+
self._top_level_scope, self._counted_name_allocator
|
123
|
+
)
|
117
124
|
self._expanded_functions: dict[str, NativeFunctionDefinition] = {}
|
118
125
|
|
126
|
+
init_top_level_scope(model, generative_functions or [], self._top_level_scope)
|
119
127
|
self._main_renamer: Optional[ExpressionRenamer] = (
|
120
|
-
get_main_renamer(self.
|
128
|
+
get_main_renamer(self._get_function_declarations())
|
129
|
+
if self._is_normalizer
|
130
|
+
else None
|
131
|
+
)
|
132
|
+
self._functions_compilation_metadata: dict[str, CompilationMetadata] = dict(
|
133
|
+
self._model.functions_compilation_metadata
|
121
134
|
)
|
122
|
-
|
123
|
-
if generative_functions is None:
|
124
|
-
generative_functions = []
|
125
|
-
self._generative_functions = generative_functions
|
126
|
-
init_top_level_scope(model, generative_functions, self._current_scope)
|
127
135
|
self._expanded_functions_compilation_metadata: dict[
|
128
136
|
str, CompilationMetadata
|
129
|
-
] =
|
137
|
+
] = defaultdict(CompilationMetadata)
|
130
138
|
self._counted_name_allocator = CountedNameAllocator()
|
131
139
|
self._error_manager: ErrorManager = ErrorManager()
|
132
140
|
|
133
|
-
@contextmanager
|
134
|
-
def _scope_guard(self, scope: Scope) -> Iterator[None]:
|
135
|
-
"""This manager restores both `scope` and `self._current_scope` to their previous values."""
|
136
|
-
scope_data = copy.copy(scope.data)
|
137
|
-
prev_context_scope_data = copy.copy(self._current_scope.data)
|
138
|
-
|
139
|
-
prev_context_scope = self._current_scope
|
140
|
-
self._current_scope = scope
|
141
|
-
yield
|
142
|
-
prev_context_scope.data = prev_context_scope_data
|
143
|
-
self._current_scope = prev_context_scope
|
144
|
-
|
145
|
-
scope.data = scope_data
|
146
|
-
|
147
141
|
def _expand_main_func(self) -> None:
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
142
|
+
main_func = self._top_level_scope[MAIN_FUNCTION_NAME].value
|
143
|
+
closure_constructor: Any
|
144
|
+
if isinstance(main_func, GenerativeFunctionClosure):
|
145
|
+
closure_constructor = GenerativeFunctionClosure
|
146
|
+
extra_args = {
|
147
|
+
"generative_blocks": {"body": main_func.generative_blocks["body"]}
|
148
|
+
}
|
149
|
+
else:
|
150
|
+
closure_constructor = FunctionClosure
|
151
|
+
extra_args = {"body": main_func.body}
|
152
|
+
main_closure = closure_constructor.create(
|
153
|
+
name=main_func.name,
|
154
|
+
positional_arg_declarations=main_func.positional_arg_declarations,
|
155
|
+
scope=Scope(parent=self._top_level_scope),
|
153
156
|
expr_renamer=self._main_renamer,
|
154
157
|
_depth=0,
|
158
|
+
**extra_args,
|
155
159
|
)
|
156
160
|
|
157
161
|
add_entry_point_params_to_scope(
|
@@ -185,9 +189,9 @@ class Interpreter:
|
|
185
189
|
execution_preferences=self._model.execution_preferences,
|
186
190
|
functions=list(self._expanded_functions.values()),
|
187
191
|
constants=self._model.constants,
|
188
|
-
enums=
|
189
|
-
types=
|
190
|
-
qstructs=
|
192
|
+
enums=list(QMODULE.enum_decls.values()),
|
193
|
+
types=list(QMODULE.type_decls.values()),
|
194
|
+
qstructs=list(QMODULE.qstruct_decls.values()),
|
191
195
|
debug_info=self._model.debug_info,
|
192
196
|
functions_compilation_metadata=self._expanded_functions_compilation_metadata,
|
193
197
|
)
|
@@ -198,11 +202,11 @@ class Interpreter:
|
|
198
202
|
|
199
203
|
@evaluate.register
|
200
204
|
def evaluate_classical_expression(self, expression: Expression) -> Evaluated:
|
201
|
-
return evaluate_classical_expression(expression, self.
|
205
|
+
return evaluate_classical_expression(expression, self._builder.current_scope)
|
202
206
|
|
203
207
|
@evaluate.register
|
204
208
|
def evaluate_identifier(self, identifier: str) -> Evaluated:
|
205
|
-
return self.
|
209
|
+
return self._builder.current_scope[identifier]
|
206
210
|
|
207
211
|
@evaluate.register
|
208
212
|
def evaluate_lambda(self, function: QuantumLambdaFunction) -> Evaluated:
|
@@ -211,7 +215,9 @@ class Interpreter:
|
|
211
215
|
for idx, param in enumerate(function.func_decl.positional_arg_declarations)
|
212
216
|
]
|
213
217
|
func_decl = NamedParamsQuantumFunctionDeclaration(
|
214
|
-
name=
|
218
|
+
name=self._counted_name_allocator.allocate(
|
219
|
+
function.func_decl.name or "<lambda>"
|
220
|
+
),
|
215
221
|
positional_arg_declarations=renamed_params,
|
216
222
|
)
|
217
223
|
|
@@ -233,7 +239,7 @@ class Interpreter:
|
|
233
239
|
name=func_decl.name,
|
234
240
|
positional_arg_declarations=func_decl.positional_arg_declarations,
|
235
241
|
body=function.body,
|
236
|
-
scope=Scope(parent=self.
|
242
|
+
scope=Scope(parent=self._builder.current_scope),
|
237
243
|
is_lambda=True,
|
238
244
|
**extra_args,
|
239
245
|
),
|
@@ -290,7 +296,7 @@ class Interpreter:
|
|
290
296
|
|
291
297
|
@emit.register
|
292
298
|
def emit_quantum_assignment_operation(self, op: QuantumAssignmentOperation) -> None:
|
293
|
-
if self.
|
299
|
+
if self._is_normalizer:
|
294
300
|
ShallowEmitter(
|
295
301
|
self, "assignment_operation", components=["expression", "result_var"]
|
296
302
|
).emit(op)
|
@@ -299,7 +305,7 @@ class Interpreter:
|
|
299
305
|
|
300
306
|
@emit.register
|
301
307
|
def emit_inplace_binary_operation(self, op: InplaceBinaryOperation) -> None:
|
302
|
-
if self.
|
308
|
+
if self._is_normalizer:
|
303
309
|
ShallowEmitter(
|
304
310
|
self, "inplace_binary_operation", components=["target", "value"]
|
305
311
|
).emit(op)
|
@@ -318,7 +324,7 @@ class Interpreter:
|
|
318
324
|
|
319
325
|
@emit.register
|
320
326
|
def emit_within_apply(self, within_apply: WithinApply) -> None:
|
321
|
-
if self.
|
327
|
+
if self._is_normalizer:
|
322
328
|
ShallowEmitter(
|
323
329
|
self,
|
324
330
|
WITHIN_APPLY_NAME,
|
@@ -329,7 +335,7 @@ class Interpreter:
|
|
329
335
|
|
330
336
|
@emit.register
|
331
337
|
def emit_invert(self, invert: Invert) -> None:
|
332
|
-
if self.
|
338
|
+
if self._is_normalizer:
|
333
339
|
ShallowEmitter(self, INVERT_OPERATOR_NAME, components=["body"]).emit(invert)
|
334
340
|
else:
|
335
341
|
InvertEmitter(self).emit(invert)
|
@@ -340,7 +346,7 @@ class Interpreter:
|
|
340
346
|
|
341
347
|
@emit.register
|
342
348
|
def emit_control(self, control: Control) -> None:
|
343
|
-
if self.
|
349
|
+
if self._is_normalizer:
|
344
350
|
ShallowEmitter(
|
345
351
|
self,
|
346
352
|
CONTROL_OPERATOR_NAME,
|
@@ -351,7 +357,7 @@ class Interpreter:
|
|
351
357
|
|
352
358
|
@emit.register
|
353
359
|
def emit_power(self, power: Power) -> None:
|
354
|
-
if self.
|
360
|
+
if self._is_normalizer:
|
355
361
|
ShallowEmitter(
|
356
362
|
self, CONTROL_OPERATOR_NAME, components=["power", "body"]
|
357
363
|
).emit(power)
|
@@ -360,7 +366,7 @@ class Interpreter:
|
|
360
366
|
|
361
367
|
@emit.register
|
362
368
|
def emit_phase(self, phase: PhaseOperation) -> None:
|
363
|
-
if self.
|
369
|
+
if self._is_normalizer:
|
364
370
|
ShallowEmitter(self, "phase", components=["expression", "theta"]).emit(
|
365
371
|
phase
|
366
372
|
)
|
@@ -385,24 +391,23 @@ class Interpreter:
|
|
385
391
|
def _expand_operation(self, operation: Closure) -> OperationContext:
|
386
392
|
with self._builder.operation_context(operation) as context:
|
387
393
|
if isinstance(operation, FunctionClosure) and (
|
388
|
-
self._expanded_functions.get(operation.closure_id)
|
394
|
+
(func_def := self._expanded_functions.get(operation.closure_id))
|
395
|
+
is not None
|
389
396
|
):
|
390
|
-
|
397
|
+
captured_vars = self._top_level_scope[func_def.name].value.captured_vars
|
398
|
+
operation.captured_vars.update(captured_vars)
|
391
399
|
elif isinstance(operation, FunctionClosure) and operation.name == "permute":
|
392
400
|
# special expansion since permute is generative
|
393
|
-
|
394
|
-
self._expand_permute()
|
401
|
+
self._expand_permute()
|
395
402
|
elif isinstance(operation, GenerativeClosure):
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
emit_generative_statements(self, operation, args)
|
403
|
+
args = [
|
404
|
+
self.evaluate(param.name)
|
405
|
+
for param in operation.positional_arg_declarations
|
406
|
+
]
|
407
|
+
emit_generative_statements(self, operation, args)
|
402
408
|
else:
|
403
409
|
for block, block_body in operation.blocks.items():
|
404
|
-
|
405
|
-
self._expand_block(block_body, block)
|
410
|
+
self._expand_block(block_body, block)
|
406
411
|
|
407
412
|
return context
|
408
413
|
|
@@ -421,11 +426,50 @@ class Interpreter:
|
|
421
426
|
self._expand_block(calls, "body")
|
422
427
|
|
423
428
|
def _get_function_declarations(self) -> Sequence[QuantumFunctionDeclaration]:
|
424
|
-
return
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
+
return [
|
430
|
+
QuantumFunctionDeclaration(
|
431
|
+
name=func_closure.name,
|
432
|
+
positional_arg_declarations=func_closure.positional_arg_declarations,
|
433
|
+
)
|
434
|
+
for func in self._top_level_scope.values()
|
435
|
+
if isinstance(func_closure := func.value, FunctionClosure)
|
436
|
+
]
|
429
437
|
|
430
438
|
def add_constant(self, constant: Constant) -> None:
|
431
439
|
add_constants_to_scope([constant], self._top_level_scope)
|
440
|
+
|
441
|
+
def update_declarative_functions(
|
442
|
+
self,
|
443
|
+
functions: dict[str, NativeFunctionDefinition],
|
444
|
+
qmodule: ModelStateContainer,
|
445
|
+
) -> None:
|
446
|
+
add_functions_to_scope(list(functions.values()), self._top_level_scope)
|
447
|
+
for dec_func_name in functions:
|
448
|
+
if dec_func_name in qmodule.functions_compilation_metadata:
|
449
|
+
self._functions_compilation_metadata[dec_func_name] = (
|
450
|
+
qmodule.functions_compilation_metadata[dec_func_name]
|
451
|
+
)
|
452
|
+
|
453
|
+
def update_generative_functions(
|
454
|
+
self, generative_functions: dict[str, GenerativeQFunc]
|
455
|
+
) -> None:
|
456
|
+
add_generative_functions_to_scope(
|
457
|
+
list(generative_functions.values()), self._top_level_scope
|
458
|
+
)
|
459
|
+
for name, gen_func in generative_functions.items():
|
460
|
+
if gen_func.compilation_metadata is not None:
|
461
|
+
self._functions_compilation_metadata[name] = (
|
462
|
+
gen_func.compilation_metadata
|
463
|
+
)
|
464
|
+
|
465
|
+
def add_purely_declarative_function(self, function: FunctionClosure) -> None:
|
466
|
+
functions_to_add = [function.name] + QMODULE.function_dependencies[
|
467
|
+
function.name
|
468
|
+
]
|
469
|
+
for func in functions_to_add:
|
470
|
+
if func not in self._expanded_functions and func in QMODULE.native_defs:
|
471
|
+
self._expanded_functions[func] = QMODULE.native_defs[func]
|
472
|
+
if func in QMODULE.functions_compilation_metadata:
|
473
|
+
self._expanded_functions_compilation_metadata[func] = (
|
474
|
+
QMODULE.functions_compilation_metadata[func]
|
475
|
+
)
|
@@ -78,10 +78,14 @@ class SymbolTable:
|
|
78
78
|
@classmethod
|
79
79
|
def init_user_enums(cls, user_enums: list[EnumDeclaration]) -> None:
|
80
80
|
cls.enum_table = EnumTable(user_enums)
|
81
|
+
QMODULE.enum_decls = {enum_decl.name: enum_decl for enum_decl in user_enums}
|
81
82
|
|
82
83
|
@classmethod
|
83
84
|
def init_user_types(cls, user_types: list[StructDeclaration]) -> None:
|
84
85
|
cls.type_table = StructTable(user_types)
|
86
|
+
QMODULE.type_decls = {
|
87
|
+
struct_decl.name: struct_decl for struct_decl in user_types
|
88
|
+
}
|
85
89
|
|
86
90
|
@classmethod
|
87
91
|
def init_user_qstructs(cls, user_qstructs: list[QStructDeclaration]) -> None:
|