classiq 0.73.0__py3-none-any.whl → 0.75.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/_internals/client.py +9 -10
- classiq/analyzer/show_interactive_hack.py +1 -1
- classiq/applications/qnn/qlayer.py +9 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/ast_node.py +5 -2
- classiq/interface/compression_utils.py +31 -0
- classiq/interface/debug_info/debug_info.py +2 -11
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +5 -5
- classiq/interface/generator/expressions/proxies/classical/utils.py +2 -2
- classiq/interface/generator/functions/classical_type.py +30 -0
- classiq/interface/generator/functions/type_name.py +25 -3
- classiq/interface/generator/generated_circuit_data.py +11 -25
- classiq/interface/generator/quantum_program.py +14 -0
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +10 -13
- classiq/interface/helpers/versioned_model.py +12 -0
- classiq/interface/ide/visual_model.py +4 -2
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/handle_binding.py +12 -0
- classiq/interface/model/quantum_lambda_function.py +14 -0
- classiq/interface/model/statement_block.py +9 -1
- classiq/interface/model/within_apply_operation.py +12 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +24 -8
- classiq/model_expansions/capturing/captured_vars.py +28 -6
- classiq/model_expansions/closure.py +13 -0
- classiq/model_expansions/evaluators/argument_types.py +6 -5
- classiq/model_expansions/evaluators/type_type_match.py +2 -1
- classiq/model_expansions/generative_functions.py +14 -8
- classiq/model_expansions/interpreters/base_interpreter.py +10 -13
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +21 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +13 -5
- classiq/model_expansions/quantum_operations/allocate.py +22 -11
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +2 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +5 -10
- classiq/model_expansions/quantum_operations/emitter.py +1 -5
- classiq/model_expansions/quantum_operations/expression_evaluator.py +1 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +1 -0
- classiq/model_expansions/transformers/model_renamer.py +3 -1
- classiq/model_expansions/visitors/symbolic_param_inference.py +197 -0
- classiq/open_library/functions/__init__.py +2 -0
- classiq/open_library/functions/amplitude_amplification.py +5 -3
- classiq/open_library/functions/state_preparation.py +95 -2
- classiq/qmod/model_state_container.py +11 -8
- classiq/qmod/qmod_variable.py +23 -1
- classiq/qmod/quantum_function.py +1 -9
- classiq/qmod/symbolic_expr.py +8 -2
- classiq/qmod/write_qmod.py +5 -1
- {classiq-0.73.0.dist-info → classiq-0.75.0.dist-info}/METADATA +2 -1
- {classiq-0.73.0.dist-info → classiq-0.75.0.dist-info}/RECORD +49 -47
- {classiq-0.73.0.dist-info → classiq-0.75.0.dist-info}/WHEEL +1 -1
@@ -15,6 +15,9 @@ from classiq.interface.generator.expressions.expression_types import (
|
|
15
15
|
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
16
16
|
AnyClassicalValue,
|
17
17
|
)
|
18
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_array_proxy import (
|
19
|
+
ClassicalArrayProxy,
|
20
|
+
)
|
18
21
|
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
19
22
|
ClassicalProxy,
|
20
23
|
)
|
@@ -170,7 +173,11 @@ def get_field(
|
|
170
173
|
return AnyClassicalValue(f"({proxy}).{field}")
|
171
174
|
if isinstance(proxy, type) and issubclass(proxy, Enum):
|
172
175
|
return getattr(proxy, field)
|
173
|
-
if
|
176
|
+
if (
|
177
|
+
isinstance(proxy, Symbol)
|
178
|
+
and not isinstance(proxy, QmodSizedProxy)
|
179
|
+
and not isinstance(proxy, ClassicalProxy)
|
180
|
+
):
|
174
181
|
raise ClassiqExpansionError(
|
175
182
|
f"Cannot evaluate '{proxy}.{field}': Variable {str(proxy)!r} is not "
|
176
183
|
f"initialized"
|
@@ -229,7 +236,9 @@ def _is_qmod_value(val: Any) -> bool:
|
|
229
236
|
|
230
237
|
|
231
238
|
def do_subscript(value: Any, index: Any) -> Any:
|
232
|
-
if not isinstance(value, list) or not isinstance(
|
239
|
+
if not isinstance(value, (list, ClassicalArrayProxy)) or not isinstance(
|
240
|
+
index, QmodQNumProxy
|
241
|
+
):
|
233
242
|
if isinstance(index, (QmodSizedProxy, QmodStructInstance)):
|
234
243
|
raise ClassiqExpansionError(
|
235
244
|
f"Subscript {value}[{index}] is not supported. Supported subscripts "
|
@@ -251,15 +260,22 @@ def do_subscript(value: Any, index: Any) -> Any:
|
|
251
260
|
"Quantum numeric subscript must be an unsigned integer (is_signed=False, "
|
252
261
|
"fraction_digits=0)"
|
253
262
|
)
|
254
|
-
if
|
263
|
+
if isinstance(value, ClassicalArrayProxy):
|
264
|
+
length = value.length
|
265
|
+
else:
|
266
|
+
length = len(value)
|
267
|
+
if length != 2**index.size:
|
255
268
|
raise ClassiqExpansionError(
|
256
269
|
f"Quantum numeric subscript size mismatch: The quantum numeric has "
|
257
|
-
f"{index.size} qubits but the list size is {
|
270
|
+
f"{index.size} qubits but the list size is {length} != 2**{index.size}"
|
271
|
+
)
|
272
|
+
if isinstance(value, ClassicalArrayProxy):
|
273
|
+
return AnyClassicalValue(f"{value}[{index}]")
|
274
|
+
else:
|
275
|
+
return Piecewise(
|
276
|
+
*[(item, Eq(index, idx)) for idx, item in enumerate(value[:-1])],
|
277
|
+
(value[-1], True),
|
258
278
|
)
|
259
|
-
return Piecewise(
|
260
|
-
*[(item, Eq(index, idx)) for idx, item in enumerate(value[:-1])],
|
261
|
-
(value[-1], True),
|
262
|
-
)
|
263
279
|
|
264
280
|
|
265
281
|
def do_slice(value: Any, lower: Any, upper: Any) -> Any:
|
@@ -116,6 +116,16 @@ class _CapturedHandle(_Captured):
|
|
116
116
|
self.defining_function.depth,
|
117
117
|
)
|
118
118
|
|
119
|
+
@property
|
120
|
+
def mangled_handle(self) -> HandleBinding:
|
121
|
+
return self.handle.rename(
|
122
|
+
mangle_captured_var_name(
|
123
|
+
self.handle.name,
|
124
|
+
self.defining_function.name,
|
125
|
+
self.defining_function.depth,
|
126
|
+
)
|
127
|
+
)
|
128
|
+
|
119
129
|
@property
|
120
130
|
def port(self) -> PortDeclaration:
|
121
131
|
return PortDeclaration(
|
@@ -485,15 +495,14 @@ class CapturedVars:
|
|
485
495
|
(
|
486
496
|
captured_handle.handle
|
487
497
|
if _same_closure(current_function, captured_handle.defining_function)
|
488
|
-
else
|
498
|
+
else captured_handle.mangled_handle
|
489
499
|
)
|
490
500
|
for captured_handle in self._captured_handles
|
491
501
|
]
|
492
502
|
return args
|
493
503
|
|
494
|
-
def
|
495
|
-
|
496
|
-
mapping = {
|
504
|
+
def get_immediate_captured_mapping(self) -> SymbolRenaming:
|
505
|
+
return {
|
497
506
|
captured_handle.handle: [
|
498
507
|
SymbolPart(
|
499
508
|
source_handle=captured_handle.handle,
|
@@ -504,7 +513,21 @@ class CapturedVars:
|
|
504
513
|
for captured_handle in self._captured_handles
|
505
514
|
if not captured_handle.is_propagated
|
506
515
|
}
|
507
|
-
|
516
|
+
|
517
|
+
def get_propagated_captured_mapping(self) -> SymbolRenaming:
|
518
|
+
return {
|
519
|
+
captured_handle.mangled_handle: [
|
520
|
+
SymbolPart(
|
521
|
+
source_handle=captured_handle.mangled_handle,
|
522
|
+
target_var_name=captured_handle.mangled_name,
|
523
|
+
target_var_type=captured_handle.quantum_type,
|
524
|
+
)
|
525
|
+
]
|
526
|
+
for captured_handle in self._captured_handles
|
527
|
+
}
|
528
|
+
|
529
|
+
def get_classical_captured_mapping(self) -> SymbolRenaming:
|
530
|
+
return {
|
508
531
|
(handle := HandleBinding(name=captured_classical_var.name)): [
|
509
532
|
HandleRenaming(
|
510
533
|
source_handle=handle,
|
@@ -514,7 +537,6 @@ class CapturedVars:
|
|
514
537
|
for captured_classical_var in self._captured_classical_vars
|
515
538
|
if not captured_classical_var.is_propagated
|
516
539
|
}
|
517
|
-
return mapping
|
518
540
|
|
519
541
|
def init_var(self, var_name: str, defining_function: "FunctionClosure") -> None:
|
520
542
|
self._handle_states.append((var_name, defining_function, False))
|
@@ -8,6 +8,15 @@ from typing import Any, Optional
|
|
8
8
|
from typing_extensions import Self
|
9
9
|
|
10
10
|
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
11
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
12
|
+
ClassicalProxy,
|
13
|
+
)
|
14
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_struct_proxy import (
|
15
|
+
ClassicalStructProxy,
|
16
|
+
)
|
17
|
+
from classiq.interface.generator.expressions.proxies.classical.utils import (
|
18
|
+
get_proxy_type,
|
19
|
+
)
|
11
20
|
from classiq.interface.model.quantum_function_declaration import (
|
12
21
|
NamedParamsQuantumFunctionDeclaration,
|
13
22
|
PositionalArg,
|
@@ -139,6 +148,10 @@ def _evaluated_arg_to_str(arg: Any) -> str:
|
|
139
148
|
return _evaluated_one_operand_to_str(arg)
|
140
149
|
if isinstance(arg, list) and arg and isinstance(arg[0], FunctionClosure):
|
141
150
|
return _evaluated_operands_list_to_str(arg)
|
151
|
+
if isinstance(arg, ClassicalProxy):
|
152
|
+
if isinstance(arg, ClassicalStructProxy):
|
153
|
+
return repr(arg.struct_declaration)
|
154
|
+
return repr(get_proxy_type(arg))
|
142
155
|
return evaluated_classical_param_to_str(arg)
|
143
156
|
|
144
157
|
|
@@ -34,9 +34,10 @@ def add_information_from_output_arguments(
|
|
34
34
|
if parameter.direction != PortDeclarationDirection.Output:
|
35
35
|
continue
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
if parameter.quantum_type.is_evaluated:
|
38
|
+
copy_type_information(
|
39
|
+
parameter.quantum_type,
|
40
|
+
argument_as_quantum_symbol.quantum_type,
|
41
|
+
str(argument_as_quantum_symbol.handle),
|
42
|
+
)
|
42
43
|
return args
|
@@ -85,6 +85,7 @@ def _check_classical_type_match(
|
|
85
85
|
) -> None:
|
86
86
|
if (
|
87
87
|
not isinstance(op_param, AnonClassicalParameterDeclaration)
|
88
|
-
or decl_param.classical_type
|
88
|
+
or decl_param.classical_type.clear_flags()
|
89
|
+
!= op_param.classical_type.clear_flags()
|
89
90
|
):
|
90
91
|
raise ClassiqExpansionError(error_message)
|
@@ -81,11 +81,14 @@ def translate_ast_arg_to_python_qmod(param: PositionalArg, evaluated: Evaluated)
|
|
81
81
|
]
|
82
82
|
classical_value = evaluated.value
|
83
83
|
if isinstance(classical_value, QmodStructInstance):
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
84
|
+
if param.classical_type.is_purely_declarative:
|
85
|
+
return CParamStruct(
|
86
|
+
expr=param.name,
|
87
|
+
struct_type=Struct(name=classical_value.struct_declaration.name),
|
88
|
+
qmodule=QMODULE,
|
89
|
+
)
|
90
|
+
else:
|
91
|
+
return get_sdk_compatible_python_object(dict(classical_value.fields))
|
89
92
|
if isinstance(classical_value, ClassicalProxy):
|
90
93
|
return create_param(
|
91
94
|
str(classical_value.handle), get_proxy_type(classical_value), QMODULE
|
@@ -111,15 +114,18 @@ class _InterpreterExpandable(QFunc):
|
|
111
114
|
for name, func in self._qmodule.native_defs.items()
|
112
115
|
if name not in self._interpreter._top_level_scope
|
113
116
|
}
|
117
|
+
generative_functions = self._qmodule.generative_functions
|
114
118
|
self._interpreter.update_declarative_functions(
|
115
119
|
declarative_functions, self._qmodule
|
116
120
|
)
|
117
|
-
self._interpreter.update_generative_functions(
|
118
|
-
self._qmodule.generative_functions
|
119
|
-
)
|
121
|
+
self._interpreter.update_generative_functions(generative_functions)
|
120
122
|
func_decls = self._get_function_declarations()
|
121
123
|
for dec_func in declarative_functions.values():
|
122
124
|
resolve_function_calls(dec_func, func_decls)
|
125
|
+
self._interpreter.infer_symbolic_parameters(
|
126
|
+
list(declarative_functions.values()),
|
127
|
+
[func.func_decl for func in generative_functions.values()],
|
128
|
+
)
|
123
129
|
resolve_function_calls(dummy_function, func_decls)
|
124
130
|
stmt = dummy_function.body[-1]
|
125
131
|
with generative_mode_context(False):
|
@@ -9,14 +9,15 @@ from typing import Any, cast
|
|
9
9
|
import sympy
|
10
10
|
from pydantic import ValidationError
|
11
11
|
|
12
|
-
from classiq.interface.debug_info.debug_info import
|
12
|
+
from classiq.interface.debug_info.debug_info import (
|
13
|
+
new_function_debug_info_by_node,
|
14
|
+
)
|
13
15
|
from classiq.interface.exceptions import (
|
14
16
|
ClassiqError,
|
15
17
|
ClassiqExpansionError,
|
16
18
|
ClassiqInternalExpansionError,
|
17
19
|
)
|
18
20
|
from classiq.interface.generator.expressions.expression import Expression
|
19
|
-
from classiq.interface.generator.generated_circuit_data import OperationLevel
|
20
21
|
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
21
22
|
from classiq.interface.model.handle_binding import (
|
22
23
|
FieldHandleBinding,
|
@@ -237,20 +238,16 @@ class BaseInterpreter:
|
|
237
238
|
if source_ref is not None
|
238
239
|
else nullcontext()
|
239
240
|
)
|
240
|
-
|
241
|
-
self._model.debug_info[statement.uuid] = FunctionDebugInfo(
|
242
|
-
name="",
|
243
|
-
parameters={},
|
244
|
-
level=OperationLevel.QMOD_STATEMENT,
|
245
|
-
statement_type=None,
|
246
|
-
is_allocate_or_free=False,
|
247
|
-
is_inverse=False,
|
248
|
-
port_to_passed_variable_map={},
|
249
|
-
node=statement._as_back_ref(),
|
250
|
-
)
|
241
|
+
self.add_to_debug_info(statement)
|
251
242
|
with error_context, self._builder.source_ref_context(source_ref):
|
252
243
|
self.emit(statement)
|
253
244
|
|
245
|
+
def add_to_debug_info(self, statement: QuantumStatement) -> None:
|
246
|
+
if statement.uuid not in self._model.debug_info:
|
247
|
+
self._model.debug_info[statement.uuid] = new_function_debug_info_by_node(
|
248
|
+
statement # type: ignore[arg-type]
|
249
|
+
)
|
250
|
+
|
254
251
|
def _expand_operation(self, operation: Closure) -> OperationContext:
|
255
252
|
with self._builder.operation_context(operation) as context:
|
256
253
|
if isinstance(operation, FunctionClosure) and (
|
@@ -4,21 +4,42 @@ import os
|
|
4
4
|
from pydantic import ValidationError
|
5
5
|
|
6
6
|
from classiq.interface.exceptions import ClassiqError
|
7
|
+
from classiq.interface.model.allocate import Allocate
|
8
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
7
9
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
10
|
+
from classiq.interface.model.quantum_function_declaration import (
|
11
|
+
NamedParamsQuantumFunctionDeclaration,
|
12
|
+
)
|
8
13
|
from classiq.interface.source_reference import SourceReference
|
9
14
|
|
10
15
|
from classiq.model_expansions.closure import FunctionClosure, GenerativeFunctionClosure
|
11
16
|
from classiq.model_expansions.interpreters.generative_interpreter import (
|
12
17
|
GenerativeInterpreter,
|
13
18
|
)
|
19
|
+
from classiq.model_expansions.quantum_operations.allocate import AllocateEmitter
|
14
20
|
from classiq.model_expansions.quantum_operations.quantum_function_call import (
|
15
21
|
DeclarativeQuantumFunctionCallEmitter,
|
16
22
|
)
|
17
23
|
from classiq.model_expansions.scope import Scope
|
24
|
+
from classiq.model_expansions.visitors.symbolic_param_inference import (
|
25
|
+
SymbolicParamInference,
|
26
|
+
)
|
18
27
|
from classiq.qmod.model_state_container import QMODULE
|
19
28
|
|
20
29
|
|
21
30
|
class FrontendGenerativeInterpreter(GenerativeInterpreter):
|
31
|
+
def infer_symbolic_parameters(
|
32
|
+
self,
|
33
|
+
functions: list[NativeFunctionDefinition],
|
34
|
+
additional_signatures: (
|
35
|
+
list[NamedParamsQuantumFunctionDeclaration] | None
|
36
|
+
) = None,
|
37
|
+
) -> None:
|
38
|
+
SymbolicParamInference(functions, additional_signatures).infer()
|
39
|
+
|
40
|
+
def emit_allocate(self, allocate: Allocate) -> None:
|
41
|
+
AllocateEmitter(self, allow_symbolic_size=True).emit(allocate)
|
42
|
+
|
22
43
|
def emit_quantum_function_call(self, call: QuantumFunctionCall) -> None:
|
23
44
|
DeclarativeQuantumFunctionCallEmitter(self).emit(call)
|
24
45
|
|
@@ -93,17 +93,25 @@ class GenerativeInterpreter(BaseInterpreter):
|
|
93
93
|
add_generative_functions_to_scope(
|
94
94
|
generative_functions, self._top_level_scope, override_atomic=True
|
95
95
|
)
|
96
|
+
self.infer_symbolic_parameters(
|
97
|
+
model.functions, [gen_func.func_decl for gen_func in generative_functions]
|
98
|
+
)
|
99
|
+
|
100
|
+
def infer_symbolic_parameters(
|
101
|
+
self,
|
102
|
+
functions: list[NativeFunctionDefinition],
|
103
|
+
additional_signatures: (
|
104
|
+
list[NamedParamsQuantumFunctionDeclaration] | None
|
105
|
+
) = None,
|
106
|
+
) -> None:
|
107
|
+
pass
|
96
108
|
|
97
109
|
def evaluate_lambda(self, function: QuantumLambdaFunction) -> Evaluated:
|
98
|
-
renamed_params = [
|
99
|
-
param.rename(function.pos_rename_params[idx])
|
100
|
-
for idx, param in enumerate(function.func_decl.positional_arg_declarations)
|
101
|
-
]
|
102
110
|
func_decl = NamedParamsQuantumFunctionDeclaration(
|
103
111
|
name=self._counted_name_allocator.allocate(
|
104
112
|
function.func_decl.name or "<lambda>"
|
105
113
|
),
|
106
|
-
positional_arg_declarations=
|
114
|
+
positional_arg_declarations=function.named_func_decl.positional_arg_declarations,
|
107
115
|
)
|
108
116
|
|
109
117
|
closure_class: type[FunctionClosure]
|
@@ -1,7 +1,10 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
import sympy
|
4
|
+
|
1
5
|
from classiq.interface.debug_info.debug_info import FunctionDebugInfo
|
2
6
|
from classiq.interface.exceptions import ClassiqValueError
|
3
7
|
from classiq.interface.generator.expressions.expression import Expression
|
4
|
-
from classiq.interface.generator.generated_circuit_data import OperationLevel
|
5
8
|
from classiq.interface.model.allocate import Allocate
|
6
9
|
from classiq.interface.model.handle_binding import NestedHandleBinding
|
7
10
|
from classiq.interface.model.quantum_type import QuantumBitvector
|
@@ -10,8 +13,17 @@ from classiq.model_expansions.evaluators.quantum_type_utils import copy_type_inf
|
|
10
13
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
11
14
|
from classiq.model_expansions.scope import QuantumSymbol
|
12
15
|
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
|
18
|
+
|
13
19
|
|
14
20
|
class AllocateEmitter(Emitter[Allocate]):
|
21
|
+
def __init__(
|
22
|
+
self, interpreter: "BaseInterpreter", allow_symbolic_size: bool = False
|
23
|
+
) -> None:
|
24
|
+
super().__init__(interpreter)
|
25
|
+
self._allow_symbolic_size = allow_symbolic_size
|
26
|
+
|
15
27
|
def emit(self, allocate: Allocate, /) -> bool:
|
16
28
|
target: QuantumSymbol = self._interpreter.evaluate(allocate.target).as_type(
|
17
29
|
QuantumSymbol
|
@@ -22,10 +34,10 @@ class AllocateEmitter(Emitter[Allocate]):
|
|
22
34
|
f"Cannot allocate partial quantum variable {str(target.handle)!r}"
|
23
35
|
)
|
24
36
|
|
25
|
-
|
37
|
+
size_expr = self._get_var_size(target, allocate.size)
|
26
38
|
allocate = allocate.model_copy(
|
27
39
|
update=dict(
|
28
|
-
size=Expression(expr=
|
40
|
+
size=Expression(expr=size_expr),
|
29
41
|
target=target.handle,
|
30
42
|
back_ref=allocate.uuid,
|
31
43
|
)
|
@@ -34,27 +46,29 @@ class AllocateEmitter(Emitter[Allocate]):
|
|
34
46
|
self.emit_statement(allocate)
|
35
47
|
return True
|
36
48
|
|
37
|
-
def _get_var_size(self, target: QuantumSymbol, size: Expression | None) ->
|
49
|
+
def _get_var_size(self, target: QuantumSymbol, size: Expression | None) -> str:
|
38
50
|
if size is None:
|
39
51
|
if not target.quantum_type.is_evaluated:
|
40
52
|
raise ClassiqValueError(
|
41
53
|
f"Could not infer the size of variable {str(target.handle)!r}"
|
42
54
|
)
|
43
|
-
return target.quantum_type.size_in_bits
|
55
|
+
return str(target.quantum_type.size_in_bits)
|
44
56
|
|
45
57
|
size_value = self._interpreter.evaluate(size).value
|
58
|
+
if self._allow_symbolic_size and isinstance(size_value, sympy.Basic):
|
59
|
+
return str(size_value)
|
46
60
|
if not isinstance(size_value, (int, float)):
|
47
61
|
raise ClassiqValueError(
|
48
62
|
f"The number of allocated qubits must be an integer. Got "
|
49
63
|
f"{str(size_value)!r}"
|
50
64
|
)
|
51
|
-
|
65
|
+
size_expr = str(size_value)
|
52
66
|
copy_type_information(
|
53
|
-
QuantumBitvector(length=Expression(expr=
|
67
|
+
QuantumBitvector(length=Expression(expr=size_expr)),
|
54
68
|
target.quantum_type,
|
55
69
|
str(target.handle),
|
56
70
|
)
|
57
|
-
return
|
71
|
+
return size_expr
|
58
72
|
|
59
73
|
def _register_debug_info(self, allocate: Allocate) -> None:
|
60
74
|
if (
|
@@ -67,9 +81,6 @@ class AllocateEmitter(Emitter[Allocate]):
|
|
67
81
|
parameters["num_qubits"] = allocate.size.expr
|
68
82
|
self._debug_info[allocate.uuid] = FunctionDebugInfo(
|
69
83
|
name="allocate",
|
70
|
-
parameters=parameters,
|
71
|
-
level=OperationLevel.QMOD_STATEMENT,
|
72
|
-
is_allocate_or_free=True,
|
73
84
|
port_to_passed_variable_map={"ARG": str(allocate.target)},
|
74
85
|
node=allocate._as_back_ref(),
|
75
86
|
)
|
@@ -36,6 +36,8 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
36
36
|
|
37
37
|
def _update_result_type(self, op: ArithmeticOperation) -> None:
|
38
38
|
expr = self._evaluate_expression(op.expression)
|
39
|
+
if len(self._get_classical_vars_in_expression(expr)):
|
40
|
+
return
|
39
41
|
symbols = self._get_symbols_in_expression(expr)
|
40
42
|
expr_str = rename_variables(
|
41
43
|
expr.expr,
|
@@ -24,7 +24,6 @@ from classiq.interface.generator.expressions.proxies.classical.qmod_struct_insta
|
|
24
24
|
from classiq.interface.generator.functions.port_declaration import (
|
25
25
|
PortDeclarationDirection,
|
26
26
|
)
|
27
|
-
from classiq.interface.generator.generated_circuit_data import OperationLevel
|
28
27
|
from classiq.interface.model.classical_parameter_declaration import (
|
29
28
|
ClassicalParameterDeclaration,
|
30
29
|
)
|
@@ -63,7 +62,6 @@ from classiq.model_expansions.quantum_operations.emitter import (
|
|
63
62
|
from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
|
64
63
|
from classiq.model_expansions.transformers.var_splitter import VarSplitter
|
65
64
|
from classiq.model_expansions.utils.text_utils import are, readable_list, s
|
66
|
-
from classiq.qmod.builtins.functions import free
|
67
65
|
from classiq.qmod.semantics.validation.signature_validation import (
|
68
66
|
validate_function_signature,
|
69
67
|
)
|
@@ -188,7 +186,6 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
188
186
|
positional_args=new_positional_args,
|
189
187
|
back_ref=self._get_back_ref(propagated_debug_info),
|
190
188
|
)
|
191
|
-
is_allocate_or_free = new_call.func_name == free.func_decl.name
|
192
189
|
|
193
190
|
port_to_passed_variable_map = {
|
194
191
|
arg_decl.name: str(evaluated_arg.value.handle)
|
@@ -197,8 +194,6 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
197
194
|
}
|
198
195
|
self._debug_info[new_call.uuid] = FunctionDebugInfo(
|
199
196
|
name=new_call.func_name,
|
200
|
-
level=OperationLevel.QMOD_FUNCTION_CALL,
|
201
|
-
is_allocate_or_free=is_allocate_or_free,
|
202
197
|
port_to_passed_variable_map=port_to_passed_variable_map,
|
203
198
|
node=new_call._as_back_ref(),
|
204
199
|
)
|
@@ -263,11 +258,11 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
263
258
|
chain.from_iterable((func_def.positional_arg_declarations, captured_ports))
|
264
259
|
)
|
265
260
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
)
|
261
|
+
rewrite_mapping = dict(captured_vars.get_propagated_captured_mapping())
|
262
|
+
if function_context.is_lambda:
|
263
|
+
rewrite_mapping |= captured_vars.get_immediate_captured_mapping()
|
264
|
+
rewrite_mapping |= captured_vars.get_classical_captured_mapping()
|
265
|
+
func_def.body = self.rewrite(func_def.body, rewrite_mapping)
|
271
266
|
|
272
267
|
return func_def
|
273
268
|
|
@@ -13,7 +13,6 @@ import sympy
|
|
13
13
|
|
14
14
|
from classiq.interface.debug_info.debug_info import (
|
15
15
|
DebugInfoCollection,
|
16
|
-
new_function_debug_info_by_node,
|
17
16
|
)
|
18
17
|
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
19
18
|
from classiq.interface.generator.expressions.evaluated_expression import (
|
@@ -161,10 +160,7 @@ class Emitter(Generic[QuantumStatementT], ABC):
|
|
161
160
|
self._update_captured_classical_vars(statement)
|
162
161
|
if isinstance(statement, QuantumOperation):
|
163
162
|
self._update_captured_vars(statement)
|
164
|
-
|
165
|
-
self._interpreter._model.debug_info[statement.uuid] = (
|
166
|
-
new_function_debug_info_by_node(statement) # type:ignore[arg-type]
|
167
|
-
)
|
163
|
+
self._interpreter.add_to_debug_info(statement)
|
168
164
|
self._builder.emit_statement(statement)
|
169
165
|
|
170
166
|
def _update_captured_classical_vars(self, stmt: QuantumStatement) -> None:
|
@@ -92,7 +92,9 @@ class _ReplaceSplitVarsExpressions(ModelTransformer):
|
|
92
92
|
) -> QuantumExpressionOperation:
|
93
93
|
op = cast(QuantumExpressionOperation, self.generic_visit(op))
|
94
94
|
previous_var_handles = list(op._var_handles)
|
95
|
-
op._var_handles = self.visit(
|
95
|
+
op._var_handles = _ReplaceSplitVarsHandles(self._symbol_mapping).visit(
|
96
|
+
op._var_handles
|
97
|
+
)
|
96
98
|
op._var_types = {
|
97
99
|
new_handle.name: op._var_types.get(
|
98
100
|
new_handle.name, op._var_types[previous_handle.name]
|