classiq 0.64.0__py3-none-any.whl → 0.65.1__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 +30 -0
- classiq/applications/chemistry/chemistry_model_constructor.py +8 -9
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +4 -6
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +2 -5
- classiq/applications/finance/finance_model_constructor.py +7 -12
- classiq/applications/grover/grover_model_constructor.py +4 -6
- classiq/applications/qsvm/qsvm_model_constructor.py +6 -4
- classiq/execution/execution_session.py +14 -13
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +1 -9
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +11 -13
- classiq/interface/generator/functions/type_name.py +6 -0
- classiq/interface/model/allocate.py +16 -0
- classiq/interface/model/quantum_type.py +26 -0
- classiq/interface/model/statement_block.py +2 -0
- classiq/interface/server/routes.py +1 -0
- classiq/model_expansions/evaluators/quantum_type_utils.py +10 -0
- classiq/model_expansions/function_builder.py +35 -11
- classiq/model_expansions/generative_functions.py +6 -4
- classiq/model_expansions/interpreters/base_interpreter.py +37 -138
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +144 -3
- classiq/model_expansions/quantum_operations/call_emitter.py +43 -91
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
- classiq/model_expansions/quantum_operations/emitter.py +5 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +9 -0
- classiq/model_expansions/quantum_operations/shallow_emitter.py +20 -1
- classiq/model_expansions/scope.py +15 -15
- classiq/model_expansions/scope_initialization.py +3 -5
- classiq/open_library/functions/discrete_sine_cosine_transform.py +8 -2
- classiq/open_library/functions/grover.py +1 -1
- classiq/open_library/functions/modular_exponentiation.py +8 -2
- classiq/open_library/functions/state_preparation.py +23 -13
- classiq/open_library/functions/swap_test.py +1 -2
- classiq/open_library/functions/variational.py +1 -2
- classiq/qmod/builtins/__init__.py +1 -1
- classiq/qmod/builtins/operations.py +51 -0
- classiq/qmod/native/pretty_printer.py +9 -1
- classiq/qmod/pretty_print/pretty_printer.py +12 -1
- classiq/qmod/qmod_variable.py +38 -38
- classiq/qmod/quantum_function.py +4 -4
- classiq/qmod/semantics/annotation/__init__.py +0 -0
- classiq/qmod/semantics/annotation/call_annotation.py +92 -0
- classiq/qmod/semantics/lambdas.py +25 -0
- classiq/qmod/semantics/static_semantics_visitor.py +8 -46
- classiq/qmod/utilities.py +16 -0
- {classiq-0.64.0.dist-info → classiq-0.65.1.dist-info}/METADATA +1 -1
- {classiq-0.64.0.dist-info → classiq-0.65.1.dist-info}/RECORD +50 -45
- classiq/qmod/semantics/annotation.py +0 -36
- /classiq/qmod/semantics/{qstruct_annotator.py → annotation/qstruct_annotator.py} +0 -0
- {classiq-0.64.0.dist-info → classiq-0.65.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
from itertools import chain
|
2
|
+
from typing import TYPE_CHECKING, Generic
|
3
|
+
|
4
|
+
from classiq.interface.generator.functions.port_declaration import (
|
5
|
+
PortDeclarationDirection,
|
6
|
+
)
|
7
|
+
from classiq.interface.model.port_declaration import PortDeclaration
|
8
|
+
|
9
|
+
from classiq.model_expansions.closure import FunctionClosure, GenerativeClosure
|
10
|
+
from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
|
11
|
+
from classiq.model_expansions.quantum_operations.emitter import QuantumStatementT
|
12
|
+
from classiq.model_expansions.scope import Evaluated
|
13
|
+
from classiq.qmod.model_state_container import QMODULE
|
14
|
+
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
from classiq.model_expansions.interpreters.generative_interpreter import (
|
17
|
+
GenerativeInterpreter,
|
18
|
+
)
|
19
|
+
|
20
|
+
|
21
|
+
class DeclarativeCallEmitter(
|
22
|
+
Generic[QuantumStatementT], CallEmitter[QuantumStatementT]
|
23
|
+
):
|
24
|
+
_interpreter: "GenerativeInterpreter"
|
25
|
+
|
26
|
+
def __init__(self, interpreter: "GenerativeInterpreter") -> None:
|
27
|
+
super().__init__(interpreter)
|
28
|
+
|
29
|
+
def should_expand_function(
|
30
|
+
self, function: FunctionClosure, args: list[Evaluated]
|
31
|
+
) -> bool:
|
32
|
+
if not super().should_expand_function(function, args):
|
33
|
+
return False
|
34
|
+
|
35
|
+
if self._is_function_purely_declarative(
|
36
|
+
function
|
37
|
+
) and self._are_args_purely_declarative(args):
|
38
|
+
self._interpreter.add_purely_declarative_function(function)
|
39
|
+
return False
|
40
|
+
|
41
|
+
return True
|
42
|
+
|
43
|
+
def _is_function_purely_declarative(self, function: FunctionClosure) -> bool:
|
44
|
+
if function.name not in QMODULE.native_defs:
|
45
|
+
return False
|
46
|
+
|
47
|
+
if isinstance(function, GenerativeClosure):
|
48
|
+
return False
|
49
|
+
|
50
|
+
if any(
|
51
|
+
not param.quantum_type.is_instantiated
|
52
|
+
for param in function.positional_arg_declarations
|
53
|
+
if isinstance(param, PortDeclaration)
|
54
|
+
and param.direction == PortDeclarationDirection.Output
|
55
|
+
):
|
56
|
+
return False
|
57
|
+
|
58
|
+
dependencies = QMODULE.function_dependencies[function.name]
|
59
|
+
return self._are_identifiers_purely_declarative(dependencies)
|
60
|
+
|
61
|
+
def _are_args_purely_declarative(self, args: list[Evaluated]) -> bool:
|
62
|
+
values = [arg.value for arg in args]
|
63
|
+
function_inputs: list[FunctionClosure] = list(
|
64
|
+
chain.from_iterable(
|
65
|
+
(
|
66
|
+
[arg]
|
67
|
+
if isinstance(arg, FunctionClosure)
|
68
|
+
else (
|
69
|
+
arg
|
70
|
+
if isinstance(arg, list)
|
71
|
+
and any(isinstance(item, FunctionClosure) for item in arg)
|
72
|
+
else []
|
73
|
+
)
|
74
|
+
)
|
75
|
+
for arg in values
|
76
|
+
)
|
77
|
+
)
|
78
|
+
if any(func.is_lambda for func in function_inputs):
|
79
|
+
return False
|
80
|
+
dependencies = [func.name for func in function_inputs if not func.is_lambda]
|
81
|
+
return self._are_identifiers_purely_declarative(dependencies)
|
82
|
+
|
83
|
+
def _are_identifiers_purely_declarative(self, dependencies: list[str]) -> bool:
|
84
|
+
return not any(
|
85
|
+
isinstance(self._current_scope[dep].value, GenerativeClosure)
|
86
|
+
for dep in dependencies
|
87
|
+
)
|
@@ -19,6 +19,7 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
19
19
|
from classiq.interface.generator.functions.port_declaration import (
|
20
20
|
PortDeclarationDirection,
|
21
21
|
)
|
22
|
+
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
22
23
|
from classiq.interface.model.handle_binding import HandleBinding
|
23
24
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
24
25
|
from classiq.interface.model.quantum_function_declaration import (
|
@@ -80,6 +81,10 @@ class Emitter(Generic[QuantumStatementT]):
|
|
80
81
|
def _expanded_functions(self) -> dict[str, NativeFunctionDefinition]:
|
81
82
|
return self._interpreter._expanded_functions
|
82
83
|
|
84
|
+
@property
|
85
|
+
def _expanded_functions_by_name(self) -> dict[str, NativeFunctionDefinition]:
|
86
|
+
return nameables_to_dict(list(self._interpreter._expanded_functions.values()))
|
87
|
+
|
83
88
|
@property
|
84
89
|
def _counted_name_allocator(self) -> CountedNameAllocator:
|
85
90
|
return self._interpreter._counted_name_allocator
|
@@ -4,6 +4,9 @@ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
4
4
|
|
5
5
|
from classiq.model_expansions.closure import FunctionClosure
|
6
6
|
from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
|
7
|
+
from classiq.model_expansions.quantum_operations.declarative_call_emitter import (
|
8
|
+
DeclarativeCallEmitter,
|
9
|
+
)
|
7
10
|
from classiq.qmod.semantics.error_manager import ErrorManager
|
8
11
|
|
9
12
|
if TYPE_CHECKING:
|
@@ -22,3 +25,9 @@ class QuantumFunctionCallEmitter(CallEmitter[QuantumFunctionCall]):
|
|
22
25
|
self._emit_quantum_function_call(
|
23
26
|
function, args, self._debug_info.get(call.uuid)
|
24
27
|
)
|
28
|
+
|
29
|
+
|
30
|
+
class DeclarativeQuantumFunctionCallEmitter(
|
31
|
+
QuantumFunctionCallEmitter, DeclarativeCallEmitter
|
32
|
+
):
|
33
|
+
pass
|
@@ -6,6 +6,7 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
6
6
|
from classiq.interface.generator.functions.port_declaration import (
|
7
7
|
PortDeclarationDirection,
|
8
8
|
)
|
9
|
+
from classiq.interface.model.allocate import Allocate
|
9
10
|
from classiq.interface.model.handle_binding import HandleBinding
|
10
11
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
11
12
|
ArithmeticOperation,
|
@@ -17,7 +18,10 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
17
18
|
from classiq.interface.model.quantum_statement import QuantumOperation, QuantumStatement
|
18
19
|
|
19
20
|
from classiq.model_expansions.closure import Closure
|
20
|
-
from classiq.model_expansions.evaluators.quantum_type_utils import
|
21
|
+
from classiq.model_expansions.evaluators.quantum_type_utils import (
|
22
|
+
copy_type_information,
|
23
|
+
set_size,
|
24
|
+
)
|
21
25
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
22
26
|
from classiq.model_expansions.scope import QuantumSymbol, Scope
|
23
27
|
from classiq.model_expansions.transformers.ast_renamer import rename_variables
|
@@ -73,6 +77,8 @@ class ShallowEmitter(Emitter[QuantumOperation]):
|
|
73
77
|
op = op.model_copy(update=expanded_components)
|
74
78
|
if isinstance(op, QuantumAssignmentOperation):
|
75
79
|
self._post_process_assignment(op)
|
80
|
+
if isinstance(op, Allocate):
|
81
|
+
self._post_process_allocate(op)
|
76
82
|
self._builder.emit_statement(op)
|
77
83
|
|
78
84
|
def _post_process_assignment(self, op: QuantumAssignmentOperation) -> None:
|
@@ -86,6 +92,19 @@ class ShallowEmitter(Emitter[QuantumOperation]):
|
|
86
92
|
direction = PortDeclarationDirection.Inout
|
87
93
|
self._capture_handle(op.result_var, direction)
|
88
94
|
|
95
|
+
def _post_process_allocate(self, allocate: Allocate) -> None:
|
96
|
+
target_symbol = self._interpreter.evaluate(allocate.target).value
|
97
|
+
if not isinstance(target_symbol, QuantumSymbol):
|
98
|
+
return
|
99
|
+
self._capture_handle(target_symbol.handle, PortDeclarationDirection.Output)
|
100
|
+
if allocate.size is None or not allocate.size.is_evaluated():
|
101
|
+
return
|
102
|
+
set_size(
|
103
|
+
target_symbol.quantum_type,
|
104
|
+
allocate.size.to_int_value(),
|
105
|
+
str(target_symbol.handle),
|
106
|
+
)
|
107
|
+
|
89
108
|
def _split_components(
|
90
109
|
self, op: QuantumOperation
|
91
110
|
) -> tuple[list[str], list[str], list[str]]:
|
@@ -19,9 +19,6 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
19
19
|
from classiq.interface.generator.expressions.expression_constants import (
|
20
20
|
CPARAM_EXECUTION_SUFFIX_PATTERN,
|
21
21
|
)
|
22
|
-
from classiq.interface.generator.expressions.qmod_qarray_proxy import (
|
23
|
-
ILLEGAL_SLICE_BOUNDS_MSG,
|
24
|
-
)
|
25
22
|
from classiq.interface.generator.expressions.qmod_struct_instance import (
|
26
23
|
QmodStructInstance,
|
27
24
|
)
|
@@ -65,16 +62,19 @@ class QuantumSymbol:
|
|
65
62
|
def _slice(self, start: int, end: int) -> "QuantumSymbol":
|
66
63
|
if not isinstance(self.quantum_type, QuantumBitvector):
|
67
64
|
raise ClassiqExpansionError(
|
68
|
-
f"{self.quantum_type.type_name} is not subscriptable
|
65
|
+
f"{self.quantum_type.type_name} is not subscriptable"
|
69
66
|
)
|
70
67
|
if start >= end:
|
71
|
-
raise ClassiqExpansionError(ILLEGAL_SLICE_BOUNDS_MSG.format(start, end))
|
72
|
-
if (
|
73
|
-
self.quantum_type.has_length
|
74
|
-
and end - start > self.quantum_type.length_value
|
75
|
-
):
|
76
68
|
raise ClassiqExpansionError(
|
77
|
-
f"
|
69
|
+
f"{self.quantum_type.type_name} slice '{self.handle}[{start}:{end}]' "
|
70
|
+
f"has non-positive length"
|
71
|
+
)
|
72
|
+
array_length = self.quantum_type.length_value
|
73
|
+
if start < 0 or end > array_length:
|
74
|
+
raise ClassiqExpansionError(
|
75
|
+
f"Slice [{start}:{end}] is out of bounds of "
|
76
|
+
f"{self.quantum_type.type_name} {str(self.handle)!r} of length "
|
77
|
+
f"{array_length}"
|
78
78
|
)
|
79
79
|
return QuantumSymbol(
|
80
80
|
handle=SlicedHandleBinding(
|
@@ -91,13 +91,13 @@ class QuantumSymbol:
|
|
91
91
|
def _subscript(self, index: int) -> "QuantumSymbol":
|
92
92
|
if not isinstance(self.quantum_type, QuantumBitvector):
|
93
93
|
raise ClassiqExpansionError(
|
94
|
-
f"{self.quantum_type.type_name} is not subscriptable
|
94
|
+
f"{self.quantum_type.type_name} is not subscriptable"
|
95
95
|
)
|
96
|
-
|
97
|
-
|
98
|
-
):
|
96
|
+
array_length = self.quantum_type.length_value
|
97
|
+
if index < 0 or index >= array_length:
|
99
98
|
raise ClassiqExpansionError(
|
100
|
-
f"Subscript
|
99
|
+
f"Subscript {index} is out of bounds of {self.quantum_type.type_name} "
|
100
|
+
f"{str(self.handle)!r} of length {array_length}"
|
101
101
|
)
|
102
102
|
return QuantumSymbol(
|
103
103
|
handle=SubscriptHandleBinding(
|
@@ -78,7 +78,8 @@ def add_generative_functions_to_scope(
|
|
78
78
|
functions: Sequence[GenerativeQFunc], scope: Scope
|
79
79
|
) -> None:
|
80
80
|
for function in functions:
|
81
|
-
|
81
|
+
name = function.func_decl.name
|
82
|
+
if name == MAIN_FUNCTION_NAME or name not in scope:
|
82
83
|
scope[function.func_decl.name] = Evaluated(
|
83
84
|
value=GenerativeFunctionClosure.create(
|
84
85
|
name=function.func_decl.name,
|
@@ -138,10 +139,7 @@ def add_entry_point_params_to_scope(
|
|
138
139
|
)
|
139
140
|
|
140
141
|
|
141
|
-
def init_top_level_scope(
|
142
|
-
model: Model, generative_functions: list[GenerativeQFunc], scope: Scope
|
143
|
-
) -> None:
|
144
|
-
add_generative_functions_to_scope(generative_functions, scope)
|
142
|
+
def init_top_level_scope(model: Model, scope: Scope) -> None:
|
145
143
|
add_functions_to_scope(model.functions, scope)
|
146
144
|
add_constants_to_scope(model.constants, scope)
|
147
145
|
_init_builtins_scope(scope)
|
@@ -3,9 +3,15 @@ from classiq.open_library.functions.utility_functions import (
|
|
3
3
|
apply_to_all,
|
4
4
|
modular_increment,
|
5
5
|
)
|
6
|
-
from classiq.qmod.builtins.functions import allocate
|
7
6
|
from classiq.qmod.builtins.functions.standard_gates import PHASE, H, S, X, Z
|
8
|
-
from classiq.qmod.builtins.operations import
|
7
|
+
from classiq.qmod.builtins.operations import (
|
8
|
+
allocate,
|
9
|
+
bind,
|
10
|
+
control,
|
11
|
+
invert,
|
12
|
+
repeat,
|
13
|
+
within_apply,
|
14
|
+
)
|
9
15
|
from classiq.qmod.qfunc import qfunc
|
10
16
|
from classiq.qmod.qmod_variable import QArray, QBit, QNum
|
11
17
|
from classiq.qmod.symbolic import pi
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from classiq.open_library.functions.utility_functions import hadamard_transform
|
2
|
-
from classiq.qmod.builtins.functions import allocate
|
3
2
|
from classiq.qmod.builtins.functions.standard_gates import H, U, X
|
4
3
|
from classiq.qmod.builtins.operations import (
|
4
|
+
allocate,
|
5
5
|
bind,
|
6
6
|
control,
|
7
7
|
invert,
|
@@ -1,8 +1,14 @@
|
|
1
1
|
from classiq.open_library.functions.qft_functions import qft, qft_no_swap
|
2
2
|
from classiq.qmod.builtins.classical_functions import qft_const_adder_phase
|
3
|
-
from classiq.qmod.builtins.functions import allocate
|
4
3
|
from classiq.qmod.builtins.functions.standard_gates import PHASE, SWAP, X
|
5
|
-
from classiq.qmod.builtins.operations import
|
4
|
+
from classiq.qmod.builtins.operations import (
|
5
|
+
allocate,
|
6
|
+
bind,
|
7
|
+
control,
|
8
|
+
invert,
|
9
|
+
repeat,
|
10
|
+
within_apply,
|
11
|
+
)
|
6
12
|
from classiq.qmod.cparam import CInt
|
7
13
|
from classiq.qmod.qfunc import qfunc
|
8
14
|
from classiq.qmod.qmod_variable import QArray, QBit, QNum
|
@@ -1,12 +1,14 @@
|
|
1
|
+
import warnings
|
1
2
|
from typing import Literal
|
2
3
|
|
4
|
+
from classiq.interface.exceptions import ClassiqDeprecationWarning
|
5
|
+
|
3
6
|
from classiq.open_library.functions.utility_functions import (
|
4
7
|
hadamard_transform,
|
5
8
|
modular_increment,
|
6
9
|
)
|
7
|
-
from classiq.qmod.builtins.functions import allocate
|
8
10
|
from classiq.qmod.builtins.functions.standard_gates import CX, IDENTITY, RY, H, X
|
9
|
-
from classiq.qmod.builtins.operations import control, if_, repeat
|
11
|
+
from classiq.qmod.builtins.operations import allocate, control, if_, repeat
|
10
12
|
from classiq.qmod.cparam import CBool, CInt
|
11
13
|
from classiq.qmod.qfunc import qfunc
|
12
14
|
from classiq.qmod.qmod_variable import Output, QArray, QBit, QNum
|
@@ -16,6 +18,7 @@ from classiq.qmod.symbolic import (
|
|
16
18
|
exp,
|
17
19
|
floor,
|
18
20
|
log,
|
21
|
+
logical_or,
|
19
22
|
max as qmax,
|
20
23
|
min as qmin,
|
21
24
|
pi,
|
@@ -239,16 +242,19 @@ def prepare_bell_state(state_num: CInt, q: Output[QArray[QBit, Literal[2]]]) ->
|
|
239
242
|
|
240
243
|
"""
|
241
244
|
allocate(2, q)
|
242
|
-
|
245
|
+
if_(logical_or(state_num == 1, state_num == 3), lambda: X(q[0]))
|
246
|
+
if_(logical_or(state_num == 2, state_num == 3), lambda: X(q[1]))
|
243
247
|
H(q[0])
|
244
248
|
CX(q[0], q[1])
|
245
249
|
|
246
250
|
|
247
251
|
@qfunc
|
248
|
-
def inplace_prepare_int(value: CInt, target:
|
252
|
+
def inplace_prepare_int(value: CInt, target: QNum) -> None:
|
249
253
|
"""
|
250
254
|
[Qmod Classiq-library function]
|
251
255
|
|
256
|
+
This function is **deprecated**. Use in-place-xor assignment statement in the form _target-var_ **^=** _quantum-expression_ or **inplace_xor(**_quantum-expression_**,** _target-var_**)** instead.
|
257
|
+
|
252
258
|
Transitions a quantum variable in the zero state $|0\\rangle$ into the computational basis state $|\\text{value}\\rangle$.
|
253
259
|
In the general case, the function performs a bitwise-XOR, i.e. transitions the state $|\\psi\\rangle$ into $|\\psi \\oplus \\text{value}\\rangle$.
|
254
260
|
|
@@ -259,14 +265,12 @@ def inplace_prepare_int(value: CInt, target: QArray[QBit]) -> None:
|
|
259
265
|
Note:
|
260
266
|
If the value cannot fit into the quantum variable, it is truncated, i.e. treated as the value modulo $2^\\text{target.size}$.
|
261
267
|
"""
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
lambda: X(target[index]),
|
267
|
-
lambda: IDENTITY(target[index]),
|
268
|
-
),
|
268
|
+
warnings.warn(
|
269
|
+
"Function 'inplace_prepare_int' is deprecated. Use in-place-xor assignment statement in the form '<var> ^= <expression>' or 'inplace_xor(<expression>, <var>)' instead.",
|
270
|
+
ClassiqDeprecationWarning,
|
271
|
+
stacklevel=1,
|
269
272
|
)
|
273
|
+
target ^= value
|
270
274
|
|
271
275
|
|
272
276
|
@qfunc
|
@@ -277,6 +281,8 @@ def prepare_int(
|
|
277
281
|
"""
|
278
282
|
[Qmod Classiq-library function]
|
279
283
|
|
284
|
+
This function is **deprecated**. Use assignment statement in the form _target-var_ **|=** _quantum-expression_ or **assign(**_quantum-expression_**,** _target-var_**)** instead.
|
285
|
+
|
280
286
|
Initializes a quantum variable to the computational basis state $|\\text{value}\\rangle$.
|
281
287
|
The number of allocated qubits is automatically computed from the value, and is the minimal number required for representation in the computational basis.
|
282
288
|
|
@@ -287,5 +293,9 @@ def prepare_int(
|
|
287
293
|
Note:
|
288
294
|
If the output variable has been declared with a specific number of qubits, it must match the number of allocated qubits.
|
289
295
|
"""
|
290
|
-
|
291
|
-
|
296
|
+
warnings.warn(
|
297
|
+
"Function 'prepare_int' is deprecated. Use assignment statement in the form '<var> |= <expression>' or 'assign(<expression>, <var>)' instead.",
|
298
|
+
ClassiqDeprecationWarning,
|
299
|
+
stacklevel=1,
|
300
|
+
)
|
301
|
+
out |= value
|
@@ -1,6 +1,5 @@
|
|
1
|
-
from classiq.qmod.builtins.functions import allocate
|
2
1
|
from classiq.qmod.builtins.functions.standard_gates import SWAP, H
|
3
|
-
from classiq.qmod.builtins.operations import control, repeat
|
2
|
+
from classiq.qmod.builtins.operations import allocate, control, repeat
|
4
3
|
from classiq.qmod.qfunc import qfunc
|
5
4
|
from classiq.qmod.qmod_variable import Output, QArray, QBit
|
6
5
|
|
@@ -1,6 +1,5 @@
|
|
1
|
-
from classiq.qmod.builtins.functions import allocate
|
2
1
|
from classiq.qmod.builtins.functions.standard_gates import RX, RY, RZ
|
3
|
-
from classiq.qmod.builtins.operations import repeat
|
2
|
+
from classiq.qmod.builtins.operations import allocate, repeat
|
4
3
|
from classiq.qmod.cparam import CReal
|
5
4
|
from classiq.qmod.qfunc import qfunc
|
6
5
|
from classiq.qmod.qmod_parameter import CArray
|
@@ -12,7 +12,7 @@ from .enums import * # noqa: F403
|
|
12
12
|
from .enums import __all__ as _builtin_enums
|
13
13
|
from .functions import * # noqa: F403
|
14
14
|
from .functions import __all__ as _builtin_functions
|
15
|
-
from .operations import * # noqa: F403
|
15
|
+
from .operations import * # type:ignore[assignment] # noqa: F403
|
16
16
|
from .operations import __all__ as _builtin_operations
|
17
17
|
from .structs import * # noqa: F403
|
18
18
|
from .structs import __all__ as _builtin_structs
|
@@ -7,6 +7,7 @@ from typing import (
|
|
7
7
|
Callable,
|
8
8
|
Final,
|
9
9
|
Union,
|
10
|
+
overload,
|
10
11
|
)
|
11
12
|
|
12
13
|
from classiq.interface.exceptions import ClassiqValueError
|
@@ -15,6 +16,7 @@ from classiq.interface.generator.functions.builtins.internal_operators import (
|
|
15
16
|
REPEAT_OPERATOR_NAME,
|
16
17
|
)
|
17
18
|
from classiq.interface.generator.functions.classical_type import Integer
|
19
|
+
from classiq.interface.model.allocate import Allocate
|
18
20
|
from classiq.interface.model.bind_operation import BindOperation
|
19
21
|
from classiq.interface.model.classical_if import ClassicalIf
|
20
22
|
from classiq.interface.model.classical_parameter_declaration import (
|
@@ -41,6 +43,7 @@ from classiq.interface.model.statement_block import StatementBlock
|
|
41
43
|
from classiq.interface.model.within_apply_operation import WithinApply
|
42
44
|
|
43
45
|
from classiq.qmod.generative import is_generative_mode
|
46
|
+
from classiq.qmod.qmod_constant import QConstant
|
44
47
|
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QScalar, QVar
|
45
48
|
from classiq.qmod.quantum_callable import QCallable
|
46
49
|
from classiq.qmod.quantum_expandable import prepare_arg
|
@@ -50,6 +53,53 @@ from classiq.qmod.utilities import get_source_ref
|
|
50
53
|
_MISSING_VALUE: Final[int] = -1
|
51
54
|
|
52
55
|
|
56
|
+
@overload
|
57
|
+
def allocate(num_qubits: Union[int, SymbolicExpr], out: Output[QVar]) -> None:
|
58
|
+
pass
|
59
|
+
|
60
|
+
|
61
|
+
@overload
|
62
|
+
def allocate(out: Output[QVar]) -> None:
|
63
|
+
pass
|
64
|
+
|
65
|
+
|
66
|
+
def allocate(*args: Any, **kwargs: Any) -> None:
|
67
|
+
"""
|
68
|
+
Initialize a quantum variable.
|
69
|
+
|
70
|
+
If 'num_qubits' is specified, 'num_qubits' qubits will be allocated for variable
|
71
|
+
'out'. Otherwise, the number of qubits will be inferred according to the type of
|
72
|
+
'out'.
|
73
|
+
|
74
|
+
Args:
|
75
|
+
size: The number of qubits to be allocated (optional)
|
76
|
+
out: The target variable
|
77
|
+
"""
|
78
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
79
|
+
source_ref = get_source_ref(sys._getframe(1))
|
80
|
+
if len(args) == 0:
|
81
|
+
size = kwargs.get("num_qubits", None)
|
82
|
+
target = kwargs["out"]
|
83
|
+
elif len(args) == 1:
|
84
|
+
if "out" in kwargs:
|
85
|
+
size = args[0]
|
86
|
+
target = kwargs["out"]
|
87
|
+
else:
|
88
|
+
size = None
|
89
|
+
target = args[0]
|
90
|
+
else:
|
91
|
+
size, target = args
|
92
|
+
if isinstance(size, QConstant):
|
93
|
+
size.add_to_model()
|
94
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
95
|
+
Allocate(
|
96
|
+
size=None if size is None else Expression(expr=str(size)),
|
97
|
+
target=target.get_handle_binding(),
|
98
|
+
source_ref=source_ref,
|
99
|
+
)
|
100
|
+
)
|
101
|
+
|
102
|
+
|
53
103
|
def bind(
|
54
104
|
source: Union[Input[QVar], list[Input[QVar]]],
|
55
105
|
destination: Union[Output[QVar], list[Output[QVar]]],
|
@@ -369,6 +419,7 @@ def _operand_to_body(
|
|
369
419
|
|
370
420
|
|
371
421
|
__all__ = [
|
422
|
+
"allocate",
|
372
423
|
"assign",
|
373
424
|
"assign_amplitude",
|
374
425
|
"bind",
|
@@ -22,6 +22,7 @@ from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
|
22
22
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
23
23
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
24
24
|
from classiq.interface.generator.visitor import NodeType, Visitor
|
25
|
+
from classiq.interface.model.allocate import Allocate
|
25
26
|
from classiq.interface.model.bind_operation import BindOperation
|
26
27
|
from classiq.interface.model.classical_if import ClassicalIf
|
27
28
|
from classiq.interface.model.classical_parameter_declaration import (
|
@@ -80,7 +81,7 @@ from classiq.interface.model.within_apply_operation import WithinApply
|
|
80
81
|
|
81
82
|
from classiq.open_library.functions import OPEN_LIBRARY_FUNCTIONS
|
82
83
|
from classiq.qmod.native.expression_to_qmod import transform_expression
|
83
|
-
from classiq.qmod.semantics.
|
84
|
+
from classiq.qmod.semantics.annotation.call_annotation import resolve_function_calls
|
84
85
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
85
86
|
|
86
87
|
|
@@ -253,6 +254,13 @@ class DSLPrettyPrinter(Visitor):
|
|
253
254
|
self._level -= 1
|
254
255
|
return f"{self.visit_QuantumFunctionDeclaration(func_def)} {{\n{body}}}\n"
|
255
256
|
|
257
|
+
def visit_Allocate(self, allocate: Allocate) -> str:
|
258
|
+
if allocate.size is not None:
|
259
|
+
size = f"{self.visit(allocate.size)}, "
|
260
|
+
else:
|
261
|
+
size = ""
|
262
|
+
return f"{self._indent}allocate({size}{self.visit(allocate.target)});\n"
|
263
|
+
|
256
264
|
def visit_QuantumFunctionCall(self, func_call: QuantumFunctionCall) -> str:
|
257
265
|
positional_args = ", ".join(
|
258
266
|
self.visit(arg_decl) for arg_decl in func_call.positional_args
|
@@ -25,6 +25,7 @@ from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
|
25
25
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
26
26
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
27
27
|
from classiq.interface.generator.visitor import NodeType, Visitor
|
28
|
+
from classiq.interface.model.allocate import Allocate
|
28
29
|
from classiq.interface.model.bind_operation import BindOperation
|
29
30
|
from classiq.interface.model.classical_if import ClassicalIf
|
30
31
|
from classiq.interface.model.classical_parameter_declaration import (
|
@@ -376,7 +377,10 @@ class PythonPrettyPrinter(Visitor):
|
|
376
377
|
|
377
378
|
def visit_NativeFunctionDefinition(self, func_def: NativeFunctionDefinition) -> str:
|
378
379
|
self._level += 1
|
379
|
-
|
380
|
+
if len(func_def.body) == 0:
|
381
|
+
body = " pass"
|
382
|
+
else:
|
383
|
+
body = "".join(self.visit(statement) for statement in func_def.body)
|
380
384
|
self._level -= 1
|
381
385
|
return f"{self.visit_QuantumFunctionDeclaration(func_def)} \n{body}\n"
|
382
386
|
|
@@ -402,6 +406,13 @@ class PythonPrettyPrinter(Visitor):
|
|
402
406
|
)
|
403
407
|
return ", ".join(self.visit(arg) for arg in func_call.positional_args)
|
404
408
|
|
409
|
+
def visit_Allocate(self, allocate: Allocate) -> str:
|
410
|
+
if allocate.size is not None:
|
411
|
+
size = f"{self.visit(allocate.size)}, "
|
412
|
+
else:
|
413
|
+
size = ""
|
414
|
+
return f"{self._indent}allocate({size}{self.visit(allocate.target)})\n"
|
415
|
+
|
405
416
|
def visit_Control(self, op: Control) -> str:
|
406
417
|
self._imports["control"] = 1
|
407
418
|
control_else = (
|