classiq 0.46.1__py3-none-any.whl → 0.48.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/api_wrapper.py +45 -8
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +2 -7
- classiq/applications/grover/grover_model_constructor.py +2 -1
- classiq/execution/execution_session.py +133 -45
- classiq/execution/jobs.py +120 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +0 -1
- classiq/interface/debug_info/debug_info.py +23 -1
- classiq/interface/execution/primitives.py +17 -0
- classiq/interface/executor/iqae_result.py +3 -3
- classiq/interface/executor/result.py +3 -1
- classiq/interface/generator/arith/arithmetic_operations.py +5 -2
- classiq/interface/generator/arith/binary_ops.py +21 -14
- classiq/interface/generator/arith/extremum_operations.py +9 -1
- classiq/interface/generator/arith/number_utils.py +6 -0
- classiq/interface/generator/arith/register_user_input.py +30 -21
- classiq/interface/generator/arith/unary_ops.py +13 -1
- classiq/interface/generator/expressions/expression.py +8 -0
- classiq/interface/generator/functions/type_name.py +1 -3
- classiq/interface/generator/generated_circuit_data.py +47 -2
- classiq/interface/generator/quantum_program.py +10 -2
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +17 -3
- classiq/interface/ide/visual_model.py +10 -5
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/bind_operation.py +0 -3
- classiq/interface/model/phase_operation.py +11 -0
- classiq/interface/model/port_declaration.py +1 -12
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +34 -6
- classiq/interface/model/quantum_lambda_function.py +4 -1
- classiq/interface/model/quantum_statement.py +16 -1
- classiq/interface/model/quantum_variable_declaration.py +0 -22
- classiq/interface/model/statement_block.py +3 -0
- classiq/interface/server/global_versions.py +4 -4
- classiq/interface/server/routes.py +0 -3
- classiq/model_expansions/capturing/propagated_var_stack.py +5 -2
- classiq/model_expansions/closure.py +7 -2
- classiq/model_expansions/evaluators/quantum_type_utils.py +0 -7
- classiq/model_expansions/generative_functions.py +146 -28
- classiq/model_expansions/interpreter.py +17 -5
- classiq/model_expansions/quantum_operations/classicalif.py +27 -10
- classiq/model_expansions/quantum_operations/control.py +22 -15
- classiq/model_expansions/quantum_operations/emitter.py +68 -7
- classiq/model_expansions/quantum_operations/expression_operation.py +25 -16
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +167 -95
- classiq/model_expansions/quantum_operations/invert.py +12 -6
- classiq/model_expansions/quantum_operations/phase.py +189 -0
- classiq/model_expansions/quantum_operations/power.py +9 -8
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +20 -5
- classiq/model_expansions/quantum_operations/quantum_function_call.py +1 -1
- classiq/model_expansions/quantum_operations/repeat.py +32 -13
- classiq/model_expansions/quantum_operations/within_apply.py +19 -6
- classiq/model_expansions/scope.py +16 -5
- classiq/model_expansions/scope_initialization.py +11 -1
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +23 -1
- classiq/model_expansions/visitors/variable_references.py +11 -7
- classiq/qmod/builtins/__init__.py +10 -0
- classiq/qmod/builtins/constants.py +10 -0
- classiq/qmod/builtins/functions/state_preparation.py +4 -1
- classiq/qmod/builtins/operations.py +55 -161
- classiq/qmod/create_model_function.py +1 -1
- classiq/qmod/generative.py +14 -5
- classiq/qmod/native/pretty_printer.py +14 -4
- classiq/qmod/pretty_print/pretty_printer.py +14 -4
- classiq/qmod/qmod_constant.py +28 -18
- classiq/qmod/qmod_variable.py +43 -23
- classiq/qmod/quantum_expandable.py +14 -1
- classiq/qmod/semantics/static_semantics_visitor.py +10 -0
- classiq/qmod/semantics/validation/constants_validation.py +16 -0
- {classiq-0.46.1.dist-info → classiq-0.48.0.dist-info}/METADATA +9 -4
- {classiq-0.46.1.dist-info → classiq-0.48.0.dist-info}/RECORD +71 -66
- {classiq-0.46.1.dist-info → classiq-0.48.0.dist-info}/WHEEL +0 -0
@@ -1,29 +1,7 @@
|
|
1
|
-
from typing import Any, Mapping, Optional
|
2
|
-
|
3
|
-
import pydantic
|
4
|
-
|
5
1
|
from classiq.interface.ast_node import ASTNode
|
6
|
-
from classiq.interface.generator.expressions.expression import Expression
|
7
2
|
from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
|
8
|
-
from classiq.interface.model.quantum_type import (
|
9
|
-
QuantumBitvector,
|
10
|
-
QuantumNumeric,
|
11
|
-
)
|
12
3
|
|
13
4
|
|
14
5
|
class QuantumVariableDeclaration(ASTNode):
|
15
6
|
name: str
|
16
7
|
quantum_type: ConcreteQuantumType
|
17
|
-
size: Optional[Expression] = pydantic.Field(default=None, exclude=True)
|
18
|
-
|
19
|
-
@pydantic.validator("size")
|
20
|
-
def _propagate_size_to_type(
|
21
|
-
cls, size: Optional[Expression], values: Mapping[str, Any]
|
22
|
-
) -> Optional[Expression]:
|
23
|
-
if size is not None:
|
24
|
-
quantum_type = values.get("quantum_type")
|
25
|
-
if isinstance(quantum_type, QuantumBitvector):
|
26
|
-
quantum_type.length = size
|
27
|
-
elif isinstance(quantum_type, QuantumNumeric):
|
28
|
-
quantum_type.size = size
|
29
|
-
return size
|
@@ -9,6 +9,7 @@ from classiq.interface.model.control import Control
|
|
9
9
|
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
10
10
|
from classiq.interface.model.invert import Invert
|
11
11
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
12
|
+
from classiq.interface.model.phase_operation import PhaseOperation
|
12
13
|
from classiq.interface.model.power import Power
|
13
14
|
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
14
15
|
AmplitudeLoadingOperation,
|
@@ -38,6 +39,7 @@ ConcreteQuantumStatement = Annotated[
|
|
38
39
|
ClassicalIf,
|
39
40
|
Control,
|
40
41
|
WithinApply,
|
42
|
+
PhaseOperation,
|
41
43
|
],
|
42
44
|
Field(..., discriminator="kind"),
|
43
45
|
]
|
@@ -52,3 +54,4 @@ Invert.update_forward_refs(StatementBlock=StatementBlock)
|
|
52
54
|
WithinApply.update_forward_refs(StatementBlock=StatementBlock)
|
53
55
|
ClassicalIf.update_forward_refs(StatementBlock=StatementBlock)
|
54
56
|
NativeFunctionDefinition.update_forward_refs(StatementBlock=StatementBlock)
|
57
|
+
PhaseOperation.update_forward_refs(StatementBlock=StatementBlock)
|
@@ -1,13 +1,13 @@
|
|
1
|
-
from datetime import date
|
2
|
-
from typing import Any, Dict
|
1
|
+
from datetime import date
|
2
|
+
from typing import Any, Dict
|
3
3
|
|
4
4
|
import pydantic
|
5
5
|
from pydantic import BaseModel
|
6
6
|
|
7
7
|
|
8
8
|
class DeprecationInfo(BaseModel):
|
9
|
-
deprecation_date:
|
10
|
-
removal_date:
|
9
|
+
deprecation_date: date = pydantic.Field()
|
10
|
+
removal_date: date = pydantic.Field()
|
11
11
|
|
12
12
|
|
13
13
|
class GlobalVersions(BaseModel):
|
@@ -17,9 +17,6 @@ ANALYZER_HC_TABLE_GRAPH_FULL_PATH = ANALYZER_PREFIX + ANALYZER_HC_TABLE_GRAPH
|
|
17
17
|
|
18
18
|
ANALYZER_HC_GRAPH_NEW = "/graphs/hardware_connectivity/new"
|
19
19
|
|
20
|
-
ANALYZER_OPTIONAL_DEVICES = "/graphs/available_devices"
|
21
|
-
ANALYZER_OPTIONAL_DEVICES_FULL_PATH = ANALYZER_PREFIX + ANALYZER_OPTIONAL_DEVICES
|
22
|
-
|
23
20
|
TASKS_SUFFIX = "/tasks"
|
24
21
|
RB = "/rb"
|
25
22
|
ANALYZER_DATA_TASK = f"{TASKS_SUFFIX}/data"
|
@@ -15,7 +15,7 @@ from classiq.interface.model.quantum_function_call import ArgValue
|
|
15
15
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
16
16
|
|
17
17
|
from classiq.model_expansions.capturing.mangling_utils import mangle_captured_var_name
|
18
|
-
from classiq.model_expansions.closure import FunctionClosure
|
18
|
+
from classiq.model_expansions.closure import FunctionClosure, GenerativeFunctionClosure
|
19
19
|
from classiq.model_expansions.function_builder import OperationBuilder
|
20
20
|
from classiq.model_expansions.scope import QuantumSymbol, Scope
|
21
21
|
|
@@ -144,7 +144,10 @@ class PropagatedVarStack:
|
|
144
144
|
def _get_propagated_var_name(self, var: PropagatedVariable) -> str:
|
145
145
|
if (
|
146
146
|
var.defining_function == self._builder.current_function.name
|
147
|
-
or
|
147
|
+
or not isinstance(
|
148
|
+
self._builder.current_function, GenerativeFunctionClosure
|
149
|
+
) # FIXME doesn't work for all cases (CAD-22663)
|
150
|
+
and self._no_name_conflict(var)
|
148
151
|
):
|
149
152
|
handle_name = var.name
|
150
153
|
if var in self._to_mangle:
|
@@ -40,6 +40,11 @@ class Closure:
|
|
40
40
|
}
|
41
41
|
|
42
42
|
|
43
|
+
@dataclass(frozen=True)
|
44
|
+
class GenerativeClosure(Closure):
|
45
|
+
generative_blocks: Dict[str, GenerativeQFunc] = None # type:ignore[assignment]
|
46
|
+
|
47
|
+
|
43
48
|
@dataclass(frozen=True)
|
44
49
|
class FunctionClosure(Closure):
|
45
50
|
is_lambda: bool = False
|
@@ -101,8 +106,8 @@ class FunctionClosure(Closure):
|
|
101
106
|
|
102
107
|
|
103
108
|
@dataclass(frozen=True)
|
104
|
-
class GenerativeFunctionClosure(FunctionClosure):
|
105
|
-
|
109
|
+
class GenerativeFunctionClosure(GenerativeClosure, FunctionClosure):
|
110
|
+
pass
|
106
111
|
|
107
112
|
|
108
113
|
NestedFunctionClosureT = Union[FunctionClosure, List["NestedFunctionClosureT"]]
|
@@ -10,7 +10,6 @@ from classiq.interface.generator.functions.type_name import (
|
|
10
10
|
TypeName,
|
11
11
|
)
|
12
12
|
from classiq.interface.model.bind_operation import BindOperation
|
13
|
-
from classiq.interface.model.inplace_binary_operation import BinaryOperation
|
14
13
|
from classiq.interface.model.quantum_type import (
|
15
14
|
QuantumBit,
|
16
15
|
QuantumBitvector,
|
@@ -227,9 +226,3 @@ def validate_inplace_binary_op_vars(
|
|
227
226
|
raise ClassiqExpansionError(
|
228
227
|
f"Cannot perform `{operation_name}` operation with non numeric target {target_var.handle}"
|
229
228
|
)
|
230
|
-
if operation_name != BinaryOperation.Xor.value and (
|
231
|
-
value_var.quantum_type.sign_value or target_var.quantum_type.sign_value
|
232
|
-
):
|
233
|
-
raise ClassiqExpansionError(
|
234
|
-
f"Cannot perform `{operation_name}` operation with signed variables"
|
235
|
-
)
|
@@ -1,51 +1,82 @@
|
|
1
|
-
from typing import TYPE_CHECKING, Any, List
|
1
|
+
from typing import TYPE_CHECKING, Any, List, Mapping
|
2
2
|
|
3
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
3
4
|
from classiq.interface.generator.expressions.qmod_struct_instance import (
|
4
5
|
QmodStructInstance,
|
5
6
|
)
|
6
7
|
from classiq.interface.generator.functions.type_name import Struct
|
8
|
+
from classiq.interface.generator.visitor import Visitor
|
7
9
|
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
8
10
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
9
11
|
from classiq.interface.model.port_declaration import PortDeclaration
|
12
|
+
from classiq.interface.model.quantum_function_call import ArgValue, QuantumFunctionCall
|
10
13
|
from classiq.interface.model.quantum_function_declaration import (
|
11
14
|
PositionalArg,
|
12
15
|
QuantumFunctionDeclaration,
|
13
16
|
QuantumOperandDeclaration,
|
14
17
|
)
|
18
|
+
from classiq.interface.model.quantum_lambda_function import (
|
19
|
+
QuantumCallable,
|
20
|
+
QuantumLambdaFunction,
|
21
|
+
)
|
15
22
|
from classiq.interface.model.quantum_statement import QuantumStatement
|
16
23
|
|
17
|
-
from classiq.model_expansions.closure import
|
24
|
+
from classiq.model_expansions.closure import (
|
25
|
+
FunctionClosure,
|
26
|
+
GenerativeClosure,
|
27
|
+
GenerativeFunctionClosure,
|
28
|
+
)
|
18
29
|
from classiq.model_expansions.scope import Evaluated, QuantumSymbol
|
19
30
|
from classiq.qmod.generative import generative_mode_context, set_frontend_interpreter
|
20
31
|
from classiq.qmod.model_state_container import QMODULE
|
21
32
|
from classiq.qmod.qmod_parameter import CParamStruct
|
22
|
-
from classiq.qmod.qmod_variable import
|
33
|
+
from classiq.qmod.qmod_variable import QNum, _create_qvar_for_qtype
|
23
34
|
from classiq.qmod.quantum_callable import QCallable
|
24
|
-
from classiq.qmod.quantum_expandable import
|
35
|
+
from classiq.qmod.quantum_expandable import (
|
36
|
+
QExpandable,
|
37
|
+
QLambdaFunction,
|
38
|
+
QTerminalCallable,
|
39
|
+
)
|
25
40
|
from classiq.qmod.quantum_function import QFunc
|
26
41
|
from classiq.qmod.semantics.static_semantics_visitor import resolve_function_calls
|
42
|
+
from classiq.qmod.symbolic_expr import SymbolicExpr
|
27
43
|
|
28
44
|
if TYPE_CHECKING:
|
29
45
|
from classiq.model_expansions.interpreter import Interpreter
|
30
46
|
|
31
47
|
|
48
|
+
class LenList(list):
|
49
|
+
@property
|
50
|
+
def len(self) -> int:
|
51
|
+
return len(self)
|
52
|
+
|
53
|
+
def __getitem__(self, item: Any) -> Any:
|
54
|
+
if isinstance(item, QNum):
|
55
|
+
return SymbolicExpr(f"{self}[{item}]", True)
|
56
|
+
return super().__getitem__(item)
|
57
|
+
|
58
|
+
@classmethod
|
59
|
+
def wrap(cls, obj: Any) -> Any:
|
60
|
+
if not isinstance(obj, list):
|
61
|
+
return obj
|
62
|
+
return LenList([cls.wrap(item) for item in obj])
|
63
|
+
|
64
|
+
|
32
65
|
def translate_ast_arg_to_python_qmod(param: PositionalArg, evaluated: Evaluated) -> Any:
|
33
66
|
if isinstance(param, PortDeclaration):
|
34
67
|
quantum_symbol = evaluated.as_type(QuantumSymbol)
|
35
|
-
return
|
68
|
+
return _create_qvar_for_qtype(
|
69
|
+
quantum_symbol.quantum_type, quantum_symbol.handle
|
70
|
+
)
|
36
71
|
if isinstance(param, QuantumOperandDeclaration):
|
37
72
|
if param.is_list:
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
index_=idx,
|
46
|
-
)
|
47
|
-
for idx, func in enumerate(func_list)
|
48
|
-
]
|
73
|
+
return QTerminalCallable(
|
74
|
+
QuantumOperandDeclaration(
|
75
|
+
name=param.name,
|
76
|
+
positional_arg_declarations=param.positional_arg_declarations,
|
77
|
+
is_list=True,
|
78
|
+
),
|
79
|
+
)
|
49
80
|
else:
|
50
81
|
func = evaluated.as_type(FunctionClosure)
|
51
82
|
return QTerminalCallable(
|
@@ -61,7 +92,7 @@ def translate_ast_arg_to_python_qmod(param: PositionalArg, evaluated: Evaluated)
|
|
61
92
|
struct_type=Struct(name=classical_value.struct_declaration.name),
|
62
93
|
qmodule=QMODULE,
|
63
94
|
)
|
64
|
-
return classical_value
|
95
|
+
return LenList.wrap(classical_value)
|
65
96
|
|
66
97
|
|
67
98
|
class _InterpreterExpandable(QFunc):
|
@@ -70,23 +101,32 @@ class _InterpreterExpandable(QFunc):
|
|
70
101
|
self._interpreter = interpreter
|
71
102
|
|
72
103
|
def append_statement_to_body(self, stmt: QuantumStatement) -> None:
|
73
|
-
|
104
|
+
current_operation = self._interpreter._builder._operations[-1]
|
74
105
|
dummy_function = NativeFunctionDefinition(
|
75
|
-
name=
|
76
|
-
positional_arg_declarations=
|
106
|
+
name=current_operation.name,
|
107
|
+
positional_arg_declarations=current_operation.positional_arg_declarations,
|
77
108
|
body=self._interpreter._builder._current_statements + [stmt],
|
78
109
|
)
|
79
|
-
resolve_function_calls(
|
80
|
-
dummy_function,
|
81
|
-
nameables_to_dict(self._interpreter._get_function_declarations()),
|
82
|
-
)
|
110
|
+
resolve_function_calls(dummy_function, self._get_function_declarations())
|
83
111
|
stmt = dummy_function.body[-1]
|
84
|
-
|
112
|
+
with generative_mode_context(False):
|
113
|
+
self._interpreter.emit_statement(stmt)
|
114
|
+
|
115
|
+
def _get_function_declarations(self) -> Mapping[str, QuantumFunctionDeclaration]:
|
116
|
+
return {
|
117
|
+
name: QuantumFunctionDeclaration(
|
118
|
+
name=name,
|
119
|
+
positional_arg_declarations=evaluated.value.positional_arg_declarations,
|
120
|
+
)
|
121
|
+
for name, evaluated in self._interpreter._current_scope.items()
|
122
|
+
if isinstance(evaluated, Evaluated)
|
123
|
+
and isinstance(evaluated.value, FunctionClosure)
|
124
|
+
} | nameables_to_dict(self._interpreter._get_function_declarations())
|
85
125
|
|
86
126
|
|
87
127
|
def emit_generative_statements(
|
88
128
|
interpreter: "Interpreter",
|
89
|
-
operation:
|
129
|
+
operation: GenerativeClosure,
|
90
130
|
args: List[Evaluated],
|
91
131
|
) -> None:
|
92
132
|
python_qmod_args = [
|
@@ -97,5 +137,83 @@ def emit_generative_statements(
|
|
97
137
|
QExpandable.STACK.append(interpreter_expandable)
|
98
138
|
QCallable.CURRENT_EXPANDABLE = interpreter_expandable
|
99
139
|
set_frontend_interpreter(interpreter)
|
100
|
-
|
101
|
-
|
140
|
+
for block_name, generative_function in operation.generative_blocks.items():
|
141
|
+
with interpreter._builder.block_context(block_name), generative_mode_context(
|
142
|
+
True
|
143
|
+
):
|
144
|
+
generative_function._py_callable(*python_qmod_args)
|
145
|
+
|
146
|
+
|
147
|
+
def emit_operands_as_declarative(
|
148
|
+
interpreter: "Interpreter", param: PositionalArg, arg: Evaluated
|
149
|
+
) -> ArgValue:
|
150
|
+
if not isinstance(param, QuantumOperandDeclaration):
|
151
|
+
return arg.emit()
|
152
|
+
value = arg.value
|
153
|
+
if isinstance(value, list):
|
154
|
+
return [
|
155
|
+
_expand_operand_as_declarative(interpreter, param, item) for item in value
|
156
|
+
]
|
157
|
+
if isinstance(value, GenerativeFunctionClosure):
|
158
|
+
return _expand_operand_as_declarative(interpreter, param, value)
|
159
|
+
if isinstance(value, FunctionClosure):
|
160
|
+
if value.is_lambda:
|
161
|
+
raise ClassiqInternalExpansionError
|
162
|
+
_register_declarative_function(interpreter, value.name)
|
163
|
+
return value.name
|
164
|
+
raise ClassiqInternalExpansionError
|
165
|
+
|
166
|
+
|
167
|
+
def _expand_operand_as_declarative(
|
168
|
+
interpreter: "Interpreter",
|
169
|
+
param: QuantumOperandDeclaration,
|
170
|
+
arg: GenerativeFunctionClosure,
|
171
|
+
) -> QuantumCallable:
|
172
|
+
if not arg.is_lambda:
|
173
|
+
_register_declarative_function(interpreter, arg.name)
|
174
|
+
return arg.name
|
175
|
+
val = QLambdaFunction(param, arg.generative_blocks["body"]._py_callable)
|
176
|
+
with generative_mode_context(False):
|
177
|
+
val.expand()
|
178
|
+
_DecFuncVisitor(interpreter).visit(val.body)
|
179
|
+
qlambda = QuantumLambdaFunction(
|
180
|
+
pos_rename_params=val.infer_rename_params(),
|
181
|
+
body=val.body,
|
182
|
+
)
|
183
|
+
qlambda.set_op_decl(param)
|
184
|
+
return qlambda
|
185
|
+
|
186
|
+
|
187
|
+
def _register_declarative_function(interpreter: "Interpreter", func_name: str) -> None:
|
188
|
+
if func_name in nameables_to_dict(interpreter._expanded_functions):
|
189
|
+
return
|
190
|
+
|
191
|
+
for user_gen_func in interpreter._generative_functions:
|
192
|
+
if user_gen_func.func_decl.name == func_name:
|
193
|
+
break
|
194
|
+
else:
|
195
|
+
return
|
196
|
+
|
197
|
+
with generative_mode_context(False):
|
198
|
+
dec_func = QFunc(user_gen_func._py_callable)
|
199
|
+
dec_func.expand()
|
200
|
+
dec_func_def = QMODULE.native_defs[func_name]
|
201
|
+
interpreter._expanded_functions.append(dec_func_def)
|
202
|
+
_DecFuncVisitor(interpreter).visit(dec_func_def)
|
203
|
+
|
204
|
+
|
205
|
+
class _DecFuncVisitor(Visitor):
|
206
|
+
def __init__(self, interpreter: "Interpreter"):
|
207
|
+
self._interpreter = interpreter
|
208
|
+
|
209
|
+
def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
|
210
|
+
_register_declarative_function(self._interpreter, call.func_name)
|
211
|
+
for arg in call.positional_args:
|
212
|
+
if isinstance(arg, str):
|
213
|
+
arg = [arg]
|
214
|
+
if isinstance(arg, list):
|
215
|
+
for possible_func_name in arg:
|
216
|
+
if isinstance(possible_func_name, str):
|
217
|
+
_register_declarative_function(
|
218
|
+
self._interpreter, possible_func_name
|
219
|
+
)
|
@@ -24,6 +24,7 @@ from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperat
|
|
24
24
|
from classiq.interface.model.invert import Invert
|
25
25
|
from classiq.interface.model.model import Model
|
26
26
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
27
|
+
from classiq.interface.model.phase_operation import PhaseOperation
|
27
28
|
from classiq.interface.model.power import Power
|
28
29
|
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
29
30
|
QuantumAssignmentOperation,
|
@@ -48,6 +49,7 @@ from classiq.model_expansions.capturing.propagated_var_stack import PropagatedVa
|
|
48
49
|
from classiq.model_expansions.closure import (
|
49
50
|
Closure,
|
50
51
|
FunctionClosure,
|
52
|
+
GenerativeClosure,
|
51
53
|
GenerativeFunctionClosure,
|
52
54
|
)
|
53
55
|
from classiq.model_expansions.debug_flag import debug_mode
|
@@ -74,6 +76,7 @@ from classiq.model_expansions.quantum_operations import (
|
|
74
76
|
VariableDeclarationStatementEmitter,
|
75
77
|
WithinApplyEmitter,
|
76
78
|
)
|
79
|
+
from classiq.model_expansions.quantum_operations.phase import PhaseEmitter
|
77
80
|
from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
|
78
81
|
from classiq.model_expansions.scope_initialization import (
|
79
82
|
add_entry_point_params_to_scope,
|
@@ -82,7 +85,6 @@ from classiq.model_expansions.scope_initialization import (
|
|
82
85
|
)
|
83
86
|
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
84
87
|
from classiq.qmod.builtins.functions import permute
|
85
|
-
from classiq.qmod.generative import is_generative_mode
|
86
88
|
from classiq.qmod.quantum_function import GenerativeQFunc
|
87
89
|
from classiq.qmod.semantics.error_manager import ErrorManager
|
88
90
|
|
@@ -95,8 +97,12 @@ STATEMENT_TYPES_FOR_SOURCE_REFERENCE_PROPAGATION: Tuple[Type[QuantumStatement],
|
|
95
97
|
|
96
98
|
class Interpreter:
|
97
99
|
def __init__(
|
98
|
-
self,
|
100
|
+
self,
|
101
|
+
model: Model,
|
102
|
+
generative_functions: Optional[List[GenerativeQFunc]] = None,
|
103
|
+
is_frontend: bool = False,
|
99
104
|
) -> None:
|
105
|
+
self._is_frontend = is_frontend
|
100
106
|
self._model = model
|
101
107
|
self._current_scope = Scope()
|
102
108
|
self._builder = OperationBuilder()
|
@@ -200,10 +206,12 @@ class Interpreter:
|
|
200
206
|
|
201
207
|
closure_class: Type[FunctionClosure]
|
202
208
|
extra_args: dict[str, Any]
|
203
|
-
if
|
209
|
+
if function.is_generative():
|
204
210
|
closure_class = GenerativeFunctionClosure
|
205
211
|
extra_args = {
|
206
|
-
"
|
212
|
+
"generative_blocks": {
|
213
|
+
"body": GenerativeQFunc(function.py_callable, func_decl),
|
214
|
+
}
|
207
215
|
}
|
208
216
|
else:
|
209
217
|
closure_class = FunctionClosure
|
@@ -307,6 +315,10 @@ class Interpreter:
|
|
307
315
|
def emit_power(self, power: Power) -> None:
|
308
316
|
PowerEmitter(self).emit(power)
|
309
317
|
|
318
|
+
@emit.register
|
319
|
+
def emit_phase(self, phase: PhaseOperation) -> None:
|
320
|
+
PhaseEmitter(self).emit(phase)
|
321
|
+
|
310
322
|
def _expand_block(self, block: Sequence[QuantumStatement], block_name: str) -> None:
|
311
323
|
with self._builder.block_context(block_name):
|
312
324
|
for statement in block:
|
@@ -331,7 +343,7 @@ class Interpreter:
|
|
331
343
|
# special expansion since permute is generative
|
332
344
|
with self._scope_guard(operation.scope):
|
333
345
|
self._expand_permute()
|
334
|
-
elif isinstance(operation,
|
346
|
+
elif isinstance(operation, GenerativeClosure):
|
335
347
|
with self._scope_guard(operation.scope):
|
336
348
|
args = [
|
337
349
|
self.evaluate(param.name)
|
@@ -1,15 +1,15 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import Sequence
|
2
2
|
|
3
3
|
from classiq.interface.model.classical_if import ClassicalIf
|
4
4
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
5
|
-
from classiq.interface.model.
|
5
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
6
6
|
|
7
7
|
from classiq.model_expansions.closure import FunctionClosure
|
8
8
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
9
9
|
from classiq.model_expansions.scope import Scope
|
10
10
|
|
11
11
|
|
12
|
-
def _is_all_identity_calls(body:
|
12
|
+
def _is_all_identity_calls(body: Sequence[QuantumStatement]) -> bool:
|
13
13
|
return all(
|
14
14
|
isinstance(stmt, QuantumFunctionCall) and stmt.func_name.lower() == "identity"
|
15
15
|
for stmt in body
|
@@ -18,22 +18,39 @@ def _is_all_identity_calls(body: List[ConcreteQuantumStatement]) -> bool:
|
|
18
18
|
|
19
19
|
class ClassicalIfEmitter(Emitter[ClassicalIf]):
|
20
20
|
def emit(self, classical_if: ClassicalIf, /) -> None:
|
21
|
+
with self._propagated_var_stack.capture_variables(classical_if):
|
22
|
+
self._emit_propagated(classical_if)
|
23
|
+
|
24
|
+
def _emit_propagated(self, classical_if: ClassicalIf) -> None:
|
21
25
|
condition = self._interpreter.evaluate(classical_if.condition).as_type(bool)
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
op_name = "then" if condition else "else"
|
27
|
+
is_generative = classical_if.is_generative()
|
28
|
+
|
29
|
+
body: Sequence[QuantumStatement]
|
30
|
+
if is_generative:
|
31
|
+
if not classical_if.has_generative_block(op_name):
|
32
|
+
return
|
33
|
+
context = self._register_generative_context(classical_if, op_name, op_name)
|
34
|
+
context.blocks["body"] = context.blocks[op_name]
|
35
|
+
context.blocks.pop(op_name)
|
36
|
+
body = context.statements("body")
|
37
|
+
else:
|
38
|
+
body = classical_if.then if condition else classical_if.else_
|
39
|
+
|
25
40
|
if _is_all_identity_calls(body):
|
26
41
|
return
|
27
42
|
|
28
43
|
if not self._should_wrap(body):
|
29
44
|
for stmt in body:
|
30
|
-
|
45
|
+
if is_generative:
|
46
|
+
self._interpreter._builder.emit_statement(stmt)
|
47
|
+
else:
|
48
|
+
self._interpreter.emit_statement(stmt)
|
31
49
|
return
|
32
50
|
|
33
51
|
then_else_func = FunctionClosure.create(
|
34
|
-
name=
|
52
|
+
name=op_name,
|
35
53
|
body=body,
|
36
54
|
scope=Scope(parent=self._current_scope),
|
37
55
|
)
|
38
|
-
|
39
|
-
self._emit_quantum_function_call(then_else_func, list())
|
56
|
+
self._emit_quantum_function_call(then_else_func, list())
|
@@ -21,6 +21,7 @@ from classiq.interface.model.control import Control
|
|
21
21
|
from classiq.interface.model.handle_binding import HANDLE_ID_SEPARATOR, HandleBinding
|
22
22
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
23
23
|
ArithmeticOperation,
|
24
|
+
ArithmeticOperationKind,
|
24
25
|
)
|
25
26
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
26
27
|
from classiq.interface.model.quantum_type import QuantumBit, QuantumBitvector
|
@@ -69,6 +70,14 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
69
70
|
def _emit_canonical_control(self, control: Control) -> None:
|
70
71
|
# canonical means control(q, body) where q is a single quantum variable
|
71
72
|
control = self._evaluate_types_in_expression(control, control.expression)
|
73
|
+
with self._propagated_var_stack.capture_variables(control):
|
74
|
+
self._emit_propagated(control)
|
75
|
+
|
76
|
+
def _emit_propagated(self, control: Control) -> None:
|
77
|
+
if control.is_generative():
|
78
|
+
context = self._register_generative_context(control, CONTROL_OPERATOR_NAME)
|
79
|
+
control = control.copy(update={"body": context.statements("body")})
|
80
|
+
|
72
81
|
if self._should_wrap_control(control):
|
73
82
|
self._emit_wrapped(control)
|
74
83
|
return
|
@@ -90,26 +99,24 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
90
99
|
blocks=dict(body=control.body),
|
91
100
|
scope=Scope(parent=self._current_scope),
|
92
101
|
)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
)
|
102
|
+
context = self._expand_operation(control_operation)
|
103
|
+
validate_args_are_not_propagated(
|
104
|
+
control.var_handles,
|
105
|
+
self._propagated_var_stack.get_propagated_variables(),
|
106
|
+
)
|
99
107
|
self._update_control_state(control)
|
100
108
|
self._builder.emit_statement(
|
101
109
|
control.copy(update=dict(body=context.statements("body")))
|
102
110
|
)
|
103
111
|
|
104
112
|
def _emit_wrapped(self, control: Control) -> None:
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
)
|
113
|
+
wrapping_function = self._create_expanded_wrapping_function(
|
114
|
+
CONTROL_OPERATOR_NAME, control.body
|
115
|
+
)
|
116
|
+
validate_args_are_not_propagated(
|
117
|
+
control.var_handles,
|
118
|
+
self._propagated_var_stack.get_propagated_variables(),
|
119
|
+
)
|
113
120
|
self._update_control_state(control)
|
114
121
|
self._builder.emit_statement(
|
115
122
|
control.copy(update=dict(body=[wrapping_function]))
|
@@ -208,7 +215,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
208
215
|
arith_expression = ArithmeticOperation(
|
209
216
|
result_var=HandleBinding(name=aux_var),
|
210
217
|
expression=control.expression,
|
211
|
-
|
218
|
+
operation_kind=ArithmeticOperationKind.Assignment,
|
212
219
|
)
|
213
220
|
self._interpreter.emit_statement(
|
214
221
|
WithinApply(
|