classiq 0.54.0__py3-none-any.whl → 0.56.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/interface/_version.py +1 -1
- classiq/interface/debug_info/debug_info.py +11 -0
- classiq/interface/executor/result.py +0 -3
- classiq/interface/generator/functions/builtins/internal_operators.py +9 -1
- classiq/interface/generator/generated_circuit_data.py +0 -1
- classiq/interface/generator/model/preferences/preferences.py +4 -0
- classiq/interface/generator/types/compilation_metadata.py +5 -0
- classiq/interface/generator/visitor.py +13 -1
- classiq/interface/ide/visual_model.py +5 -1
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/control.py +22 -1
- classiq/interface/model/handle_binding.py +28 -0
- classiq/interface/model/model.py +4 -0
- classiq/interface/model/native_function_definition.py +1 -1
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +2 -26
- classiq/interface/model/quantum_statement.py +6 -0
- classiq/model_expansions/capturing/mangling_utils.py +22 -0
- classiq/model_expansions/capturing/propagated_var_stack.py +36 -25
- classiq/model_expansions/closure.py +77 -12
- classiq/model_expansions/function_builder.py +9 -10
- classiq/model_expansions/generative_functions.py +2 -2
- classiq/model_expansions/interpreter.py +29 -26
- classiq/model_expansions/quantum_operations/control.py +114 -29
- classiq/model_expansions/quantum_operations/emitter.py +37 -11
- classiq/model_expansions/quantum_operations/expression_operation.py +80 -18
- classiq/model_expansions/quantum_operations/power.py +5 -0
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +7 -37
- classiq/model_expansions/quantum_operations/quantum_function_call.py +2 -32
- classiq/model_expansions/quantum_operations/repeat.py +5 -0
- classiq/model_expansions/quantum_operations/within_apply.py +0 -16
- classiq/model_expansions/scope_initialization.py +2 -3
- classiq/qmod/builtins/functions/arithmetic.py +0 -2
- classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +0 -12
- classiq/qmod/builtins/functions/exponentiation.py +0 -6
- classiq/qmod/builtins/functions/grover.py +0 -17
- classiq/qmod/builtins/functions/linear_pauli_rotation.py +0 -5
- classiq/qmod/builtins/functions/modular_exponentiation.py +0 -3
- classiq/qmod/builtins/functions/qaoa_penalty.py +0 -8
- classiq/qmod/builtins/functions/qft_functions.py +0 -3
- classiq/qmod/builtins/functions/qpe.py +0 -6
- classiq/qmod/builtins/functions/qsvt.py +0 -12
- classiq/qmod/builtins/functions/standard_gates.py +0 -88
- classiq/qmod/builtins/functions/state_preparation.py +7 -15
- classiq/qmod/builtins/functions/swap_test.py +0 -3
- classiq/qmod/builtins/operations.py +152 -17
- classiq/qmod/create_model_function.py +10 -12
- classiq/qmod/model_state_container.py +5 -1
- classiq/qmod/native/pretty_printer.py +6 -1
- classiq/qmod/pretty_print/pretty_printer.py +25 -11
- classiq/qmod/qmod_constant.py +31 -3
- classiq/qmod/quantum_function.py +25 -19
- classiq/qmod/synthesize_separately.py +1 -2
- {classiq-0.54.0.dist-info → classiq-0.56.0.dist-info}/METADATA +2 -3
- {classiq-0.54.0.dist-info → classiq-0.56.0.dist-info}/RECORD +55 -55
- classiq/model_expansions/call_to_model_converter.py +0 -190
- {classiq-0.54.0.dist-info → classiq-0.56.0.dist-info}/WHEEL +0 -0
@@ -1,12 +1,16 @@
|
|
1
1
|
import inspect
|
2
2
|
import sys
|
3
|
+
import warnings
|
3
4
|
from collections.abc import Mapping
|
4
5
|
from types import FrameType
|
5
6
|
from typing import (
|
7
|
+
TYPE_CHECKING,
|
6
8
|
Any,
|
7
9
|
Callable,
|
8
10
|
Final,
|
11
|
+
Optional,
|
9
12
|
Union,
|
13
|
+
overload,
|
10
14
|
)
|
11
15
|
|
12
16
|
from classiq.interface.exceptions import ClassiqValueError
|
@@ -21,13 +25,16 @@ from classiq.interface.model.classical_parameter_declaration import (
|
|
21
25
|
ClassicalParameterDeclaration,
|
22
26
|
)
|
23
27
|
from classiq.interface.model.control import Control
|
24
|
-
from classiq.interface.model.inplace_binary_operation import (
|
25
|
-
BinaryOperation,
|
26
|
-
InplaceBinaryOperation,
|
27
|
-
)
|
28
28
|
from classiq.interface.model.invert import Invert
|
29
29
|
from classiq.interface.model.phase_operation import PhaseOperation
|
30
30
|
from classiq.interface.model.power import Power
|
31
|
+
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
32
|
+
AmplitudeLoadingOperation,
|
33
|
+
)
|
34
|
+
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
35
|
+
ArithmeticOperation,
|
36
|
+
ArithmeticOperationKind,
|
37
|
+
)
|
31
38
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
32
39
|
from classiq.interface.model.quantum_function_declaration import (
|
33
40
|
QuantumOperandDeclaration,
|
@@ -37,7 +44,7 @@ from classiq.interface.model.repeat import Repeat
|
|
37
44
|
from classiq.interface.model.statement_block import StatementBlock
|
38
45
|
from classiq.interface.model.within_apply_operation import WithinApply
|
39
46
|
|
40
|
-
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QVar
|
47
|
+
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QScalar, QVar
|
41
48
|
from classiq.qmod.quantum_callable import QCallable
|
42
49
|
from classiq.qmod.quantum_expandable import prepare_arg
|
43
50
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
@@ -91,6 +98,7 @@ def if_(
|
|
91
98
|
def control(
|
92
99
|
ctrl: Union[SymbolicExpr, QBit, QArray[QBit]],
|
93
100
|
stmt_block: Union[QCallable, Callable[[], None]],
|
101
|
+
else_block: Union[QCallable, Callable[[], None], None] = None,
|
94
102
|
) -> None:
|
95
103
|
_validate_operand(stmt_block)
|
96
104
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
@@ -98,39 +106,164 @@ def control(
|
|
98
106
|
control_stmt = Control(
|
99
107
|
expression=Expression(expr=str(ctrl)),
|
100
108
|
body=_operand_to_body(stmt_block, "stmt_block"),
|
109
|
+
else_block=_operand_to_body(else_block, "else_block") if else_block else None,
|
101
110
|
source_ref=source_ref,
|
102
111
|
)
|
103
112
|
control_stmt.set_generative_block("body", stmt_block)
|
113
|
+
if else_block is not None:
|
114
|
+
control_stmt.set_generative_block("else_block", else_block)
|
104
115
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(control_stmt)
|
105
116
|
|
106
117
|
|
118
|
+
def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
|
119
|
+
"""
|
120
|
+
Initialize a scalar quantum variable using an arithmetic expression.
|
121
|
+
If specified, the variable numeric properties (size, signedness, and fraction
|
122
|
+
digits) must match the expression properties.
|
123
|
+
|
124
|
+
Equivalent to `<target_var> |= <expression>`.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
expression: A classical or quantum arithmetic expression
|
128
|
+
target_var: An uninitialized scalar quantum variable
|
129
|
+
"""
|
130
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
131
|
+
source_ref = get_source_ref(sys._getframe(1))
|
132
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
133
|
+
ArithmeticOperation(
|
134
|
+
expression=Expression(expr=str(expression)),
|
135
|
+
result_var=target_var.get_handle_binding(),
|
136
|
+
operation_kind=ArithmeticOperationKind.Assignment,
|
137
|
+
source_ref=source_ref,
|
138
|
+
)
|
139
|
+
)
|
140
|
+
|
141
|
+
|
142
|
+
def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
143
|
+
"""
|
144
|
+
Perform an amplitude-encoding assignment operation on a quantum variable and a
|
145
|
+
quantum expression.
|
146
|
+
|
147
|
+
Equivalent to `<target_var> *= <expression>`.
|
148
|
+
|
149
|
+
Args:
|
150
|
+
expression: A quantum arithmetic expression
|
151
|
+
target_var: A scalar quantum variable
|
152
|
+
"""
|
153
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
154
|
+
source_ref = get_source_ref(sys._getframe(1))
|
155
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
156
|
+
AmplitudeLoadingOperation(
|
157
|
+
expression=Expression(expr=str(expression)),
|
158
|
+
result_var=target_var.get_handle_binding(),
|
159
|
+
source_ref=source_ref,
|
160
|
+
)
|
161
|
+
)
|
162
|
+
|
163
|
+
|
164
|
+
@overload
|
165
|
+
def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
|
166
|
+
pass
|
167
|
+
|
168
|
+
|
169
|
+
@overload
|
170
|
+
def inplace_add(*, value: QNum, target: QNum) -> None:
|
171
|
+
pass
|
172
|
+
|
173
|
+
|
107
174
|
def inplace_add(
|
108
|
-
|
109
|
-
|
175
|
+
expression: Optional[SymbolicExpr] = None,
|
176
|
+
target_var: Optional[QScalar] = None,
|
177
|
+
value: Optional[QNum] = None,
|
178
|
+
target: Optional[QNum] = None,
|
110
179
|
) -> None:
|
180
|
+
"""
|
181
|
+
Add an arithmetic expression to a quantum variable.
|
182
|
+
|
183
|
+
Equivalent to `<target_var> += <expression>`.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
expression: A classical or quantum arithmetic expression
|
187
|
+
target_var: A scalar quantum variable
|
188
|
+
"""
|
111
189
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
190
|
+
if value is not None or target is not None:
|
191
|
+
warnings.warn(
|
192
|
+
"Parameters 'value' and 'target of function 'inplace_add' have "
|
193
|
+
"been renamed to 'expression' and 'target_var' respectively. Parameters "
|
194
|
+
"'value' and 'target' will no longer be supported starting on 02/12/24 at "
|
195
|
+
"the earliest.\nHint: Change `inplace_add(value=..., target=...)` to "
|
196
|
+
"`inplace_add(expression=..., target_var=...)` or `inplace_add(..., ...)`.",
|
197
|
+
category=DeprecationWarning,
|
198
|
+
stacklevel=2,
|
199
|
+
)
|
200
|
+
if value is not None:
|
201
|
+
expression = value
|
202
|
+
if target is not None:
|
203
|
+
target_var = target
|
204
|
+
if TYPE_CHECKING:
|
205
|
+
assert expression is not None
|
206
|
+
assert target_var is not None
|
112
207
|
source_ref = get_source_ref(sys._getframe(1))
|
113
208
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
209
|
+
ArithmeticOperation(
|
210
|
+
expression=Expression(expr=str(expression)),
|
211
|
+
result_var=target_var.get_handle_binding(),
|
212
|
+
operation_kind=ArithmeticOperationKind.InplaceAdd,
|
118
213
|
source_ref=source_ref,
|
119
214
|
)
|
120
215
|
)
|
121
216
|
|
122
217
|
|
218
|
+
@overload
|
219
|
+
def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
|
220
|
+
pass
|
221
|
+
|
222
|
+
|
223
|
+
@overload
|
224
|
+
def inplace_xor(*, value: QNum, target: QNum) -> None:
|
225
|
+
pass
|
226
|
+
|
227
|
+
|
123
228
|
def inplace_xor(
|
124
|
-
|
125
|
-
|
229
|
+
expression: Optional[SymbolicExpr] = None,
|
230
|
+
target_var: Optional[QScalar] = None,
|
231
|
+
value: Optional[QNum] = None,
|
232
|
+
target: Optional[QNum] = None,
|
126
233
|
) -> None:
|
234
|
+
"""
|
235
|
+
Bitwise-XOR a quantum variable with an arithmetic expression.
|
236
|
+
|
237
|
+
Equivalent to `<target_var> ^= <expression>`.
|
238
|
+
|
239
|
+
Args:
|
240
|
+
expression: A classical or quantum arithmetic expression
|
241
|
+
target_var: A scalar quantum variable
|
242
|
+
"""
|
127
243
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
244
|
+
if value is not None or target is not None:
|
245
|
+
warnings.warn(
|
246
|
+
"Parameters 'value' and 'target of function 'inplace_xor' have "
|
247
|
+
"been renamed to 'expression' and 'target_var' respectively. Parameters "
|
248
|
+
"'value' and 'target' will no longer be supported starting on 02/12/24 at "
|
249
|
+
"the earliest.\nHint: Change `inplace_xor(value=..., target=...)` to "
|
250
|
+
"`inplace_xor(expression=..., target_var=...)` or `inplace_xor(..., ...)`.",
|
251
|
+
category=DeprecationWarning,
|
252
|
+
stacklevel=2,
|
253
|
+
)
|
254
|
+
if value is not None:
|
255
|
+
expression = value
|
256
|
+
if target is not None:
|
257
|
+
target_var = target
|
258
|
+
if TYPE_CHECKING:
|
259
|
+
assert expression is not None
|
260
|
+
assert target_var is not None
|
128
261
|
source_ref = get_source_ref(sys._getframe(1))
|
129
262
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
263
|
+
ArithmeticOperation(
|
264
|
+
expression=Expression(expr=str(expression)),
|
265
|
+
result_var=target_var.get_handle_binding(),
|
266
|
+
operation_kind=ArithmeticOperationKind.InplaceXor,
|
134
267
|
source_ref=source_ref,
|
135
268
|
)
|
136
269
|
)
|
@@ -297,6 +430,8 @@ def _operand_to_body(
|
|
297
430
|
|
298
431
|
|
299
432
|
__all__ = [
|
433
|
+
"assign",
|
434
|
+
"assign_amplitude",
|
300
435
|
"bind",
|
301
436
|
"control",
|
302
437
|
"invert",
|
@@ -60,6 +60,7 @@ def create_model(
|
|
60
60
|
user_gen_functions = {
|
61
61
|
gen_func._py_callable.__name__ for gen_func in GEN_QFUNCS
|
62
62
|
} - set(BUILTIN_FUNCTION_DECLARATIONS.keys())
|
63
|
+
|
63
64
|
if len(user_gen_functions) > 0 and is_generative_expansion_enabled():
|
64
65
|
model = _expand_generative_model(
|
65
66
|
(
|
@@ -100,11 +101,17 @@ def _expand_generative_model(
|
|
100
101
|
def _dummy() -> None:
|
101
102
|
pass
|
102
103
|
|
104
|
+
functions_compilation_metadata = {
|
105
|
+
dec_func._py_callable.__name__: dec_func.compilation_metadata
|
106
|
+
for dec_func in DEC_QFUNCS
|
107
|
+
if dec_func.compilation_metadata is not None
|
108
|
+
}
|
103
109
|
model = _dummy.create_model(
|
104
110
|
constraints,
|
105
111
|
execution_preferences,
|
106
112
|
preferences,
|
107
113
|
classical_execution_function,
|
114
|
+
functions_compilation_metadata,
|
108
115
|
)
|
109
116
|
generative_functions = _get_generative_functions(gen_main, preferences)
|
110
117
|
model.functions = generative_functions
|
@@ -157,7 +164,8 @@ def _get_wrapper_main(gen_main: QFunc, preferences: Optional[Preferences]) -> Mo
|
|
157
164
|
def _get_all_model_functions_as_generative_functions() -> list[GenerativeQFunc]:
|
158
165
|
|
159
166
|
gen_functions = list(GEN_QFUNCS) + [
|
160
|
-
|
167
|
+
GenerativeQFunc(dec_func._py_callable, dec_func.func_decl)
|
168
|
+
for dec_func in DEC_QFUNCS
|
161
169
|
]
|
162
170
|
return [
|
163
171
|
(
|
@@ -173,16 +181,6 @@ def _get_all_model_functions_as_generative_functions() -> list[GenerativeQFunc]:
|
|
173
181
|
]
|
174
182
|
|
175
183
|
|
176
|
-
def _get_gen_from_dec(dec_func: QFunc) -> GenerativeQFunc:
|
177
|
-
synthesis_data = dec_func.synthesis_data
|
178
|
-
if synthesis_data is not None and synthesis_data.should_synthesize_separately:
|
179
|
-
raise ClassiqError(
|
180
|
-
"""The model contains generative functions,
|
181
|
-
which cannot coexist with functions marked for separate synthesis"""
|
182
|
-
)
|
183
|
-
return GenerativeQFunc(dec_func._py_callable, dec_func.func_decl)
|
184
|
-
|
185
|
-
|
186
184
|
def _interpret_generative_model(
|
187
185
|
gen_model: Model, gen_functions: list[GenerativeQFunc]
|
188
186
|
) -> dict[str, NativeFunctionDefinition]:
|
@@ -192,7 +190,7 @@ def _interpret_generative_model(
|
|
192
190
|
)
|
193
191
|
interpreter = Interpreter(gen_model, gen_functions, is_frontend=True)
|
194
192
|
set_frontend_interpreter(interpreter)
|
195
|
-
expand_model
|
193
|
+
expand_model = interpreter.expand()
|
196
194
|
functions_dict = nameables_to_dict(expand_model.functions)
|
197
195
|
|
198
196
|
# Inline _gen_main call in main
|
@@ -1,8 +1,11 @@
|
|
1
1
|
from classiq.interface.generator.constant import Constant
|
2
|
+
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
2
3
|
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
3
4
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
4
5
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
5
|
-
from classiq.interface.model.native_function_definition import
|
6
|
+
from classiq.interface.model.native_function_definition import (
|
7
|
+
NativeFunctionDefinition,
|
8
|
+
)
|
6
9
|
|
7
10
|
|
8
11
|
class ModelStateContainer:
|
@@ -11,6 +14,7 @@ class ModelStateContainer:
|
|
11
14
|
qstruct_decls: dict[str, QStructDeclaration]
|
12
15
|
native_defs: dict[str, NativeFunctionDefinition]
|
13
16
|
constants: dict[str, Constant]
|
17
|
+
functions_compilation_metadata: dict[str, CompilationMetadata]
|
14
18
|
|
15
19
|
|
16
20
|
QMODULE = ModelStateContainer()
|
@@ -253,7 +253,12 @@ class DSLPrettyPrinter(Visitor):
|
|
253
253
|
def visit_Control(self, op: Control) -> str:
|
254
254
|
control = f"{self._indent}control ({self.visit(op.expression)}) {{\n"
|
255
255
|
control += self._visit_body(op.body)
|
256
|
-
control += f"{self._indent}}}
|
256
|
+
control += f"{self._indent}}}"
|
257
|
+
if op.else_block is not None:
|
258
|
+
control += " else {\n"
|
259
|
+
control += self._visit_body(op.else_block)
|
260
|
+
control += f"{self._indent}}}"
|
261
|
+
control += "\n"
|
257
262
|
return control
|
258
263
|
|
259
264
|
def visit_PhaseOperation(self, op: PhaseOperation) -> str:
|
@@ -50,9 +50,6 @@ from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
50
50
|
ArithmeticOperation,
|
51
51
|
ArithmeticOperationKind,
|
52
52
|
)
|
53
|
-
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
54
|
-
QuantumAssignmentOperation,
|
55
|
-
)
|
56
53
|
from classiq.interface.model.quantum_function_call import (
|
57
54
|
OperandIdentifier,
|
58
55
|
QuantumFunctionCall,
|
@@ -391,7 +388,10 @@ class PythonPrettyPrinter(Visitor):
|
|
391
388
|
|
392
389
|
def visit_Control(self, op: Control) -> str:
|
393
390
|
self._imports["control"] = 1
|
394
|
-
|
391
|
+
control_else = (
|
392
|
+
f", {self._visit_body(op.else_block)}" if op.else_block is not None else ""
|
393
|
+
)
|
394
|
+
return f"{self._indent}control({self.visit(op.expression)}, {self._visit_body(op.body)}{control_else})\n"
|
395
395
|
|
396
396
|
def visit_PhaseOperation(self, op: PhaseOperation) -> str:
|
397
397
|
self._imports["phase"] = 1
|
@@ -429,13 +429,16 @@ class PythonPrettyPrinter(Visitor):
|
|
429
429
|
code = f"lambda{argument_string}: {'[' if len(body) > 1 else ''}\n"
|
430
430
|
self._level += 1
|
431
431
|
for i, statement in enumerate(body):
|
432
|
-
if isinstance(
|
433
|
-
statement, (QuantumAssignmentOperation, VariableDeclarationStatement)
|
434
|
-
):
|
432
|
+
if isinstance(statement, VariableDeclarationStatement):
|
435
433
|
raise AssertionError(
|
436
|
-
"pretty printing
|
434
|
+
"pretty printing variable declaration statements in quantum lambda function is unsupported."
|
437
435
|
)
|
438
|
-
|
436
|
+
if isinstance(statement, AmplitudeLoadingOperation):
|
437
|
+
code += self.visit_AmplitudeLoadingOperation(statement, in_lambda=True)
|
438
|
+
elif isinstance(statement, ArithmeticOperation):
|
439
|
+
code += self.visit_ArithmeticOperation(statement, in_lambda=True)
|
440
|
+
else:
|
441
|
+
code += self.visit(statement)
|
439
442
|
if i < len(body) - 1:
|
440
443
|
code += ","
|
441
444
|
self._level -= 1
|
@@ -469,18 +472,29 @@ class PythonPrettyPrinter(Visitor):
|
|
469
472
|
def visit_FieldHandleBinding(self, var_ref: FieldHandleBinding) -> str:
|
470
473
|
return f"{self.visit(var_ref.base_handle)}.{self.visit(var_ref.field)}"
|
471
474
|
|
472
|
-
def visit_ArithmeticOperation(
|
475
|
+
def visit_ArithmeticOperation(
|
476
|
+
self, arith_op: ArithmeticOperation, in_lambda: bool = False
|
477
|
+
) -> str:
|
473
478
|
if arith_op.operation_kind == ArithmeticOperationKind.Assignment:
|
474
479
|
op = "|="
|
480
|
+
func = "assign"
|
475
481
|
elif arith_op.operation_kind == ArithmeticOperationKind.InplaceXor:
|
476
482
|
op = "^="
|
483
|
+
func = "inplace_xor"
|
477
484
|
else:
|
478
485
|
op = "+="
|
486
|
+
func = "inplace_add"
|
487
|
+
if in_lambda:
|
488
|
+
self._imports[func] = 1
|
489
|
+
return f"{func}({self.visit(arith_op.expression)}, {self._indent}{self.visit(arith_op.result_var)})\n"
|
479
490
|
return f"{self._indent}{self.visit(arith_op.result_var)} {op} {self.visit(arith_op.expression)}\n"
|
480
491
|
|
481
492
|
def visit_AmplitudeLoadingOperation(
|
482
|
-
self, amplitude_loading_op: AmplitudeLoadingOperation
|
493
|
+
self, amplitude_loading_op: AmplitudeLoadingOperation, in_lambda: bool = False
|
483
494
|
) -> str:
|
495
|
+
if in_lambda:
|
496
|
+
self._imports["assign_amplitude"] = 1
|
497
|
+
return f"assign_amplitude({self.visit(amplitude_loading_op.expression)}, {self._indent}{self.visit(amplitude_loading_op.result_var)})\n"
|
484
498
|
return f"{self._indent}{self.visit(amplitude_loading_op.result_var)} *= {self.visit(amplitude_loading_op.expression)}\n"
|
485
499
|
|
486
500
|
def _print_bind_handles(self, handles: list[HandleBinding]) -> str:
|
classiq/qmod/qmod_constant.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import inspect
|
2
2
|
from dataclasses import is_dataclass
|
3
|
-
from typing import Any, Optional
|
3
|
+
from typing import Any, Optional, cast, get_origin
|
4
4
|
|
5
|
-
from classiq.interface.exceptions import ClassiqError
|
5
|
+
from classiq.interface.exceptions import ClassiqError, ClassiqValueError
|
6
6
|
from classiq.interface.generator.constant import Constant
|
7
7
|
from classiq.interface.generator.expressions.expression import Expression
|
8
8
|
from classiq.interface.generator.functions.classical_type import (
|
@@ -10,7 +10,13 @@ from classiq.interface.generator.functions.classical_type import (
|
|
10
10
|
ClassicalList,
|
11
11
|
)
|
12
12
|
|
13
|
+
from classiq.qmod.cparam import CArray, CParamScalar
|
13
14
|
from classiq.qmod.declaration_inferrer import python_type_to_qmod
|
15
|
+
from classiq.qmod.generative import (
|
16
|
+
get_frontend_interpreter,
|
17
|
+
interpret_expression,
|
18
|
+
is_generative_mode,
|
19
|
+
)
|
14
20
|
from classiq.qmod.model_state_container import ModelStateContainer
|
15
21
|
from classiq.qmod.qmod_parameter import CParam, CParamList, CParamStruct
|
16
22
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
@@ -49,7 +55,10 @@ class QConstant(SymbolicExpr):
|
|
49
55
|
):
|
50
56
|
raise ClassiqError(f"Constant {self.name} is already defined in the model")
|
51
57
|
|
52
|
-
|
58
|
+
constant = self._get_constant_node()
|
59
|
+
QConstant.CURRENT_QMODULE.constants[self.name] = constant
|
60
|
+
if is_generative_mode():
|
61
|
+
get_frontend_interpreter().add_constant(constant)
|
53
62
|
|
54
63
|
def _get_constant_node(self) -> Constant:
|
55
64
|
if isinstance(self._value, QConstant):
|
@@ -113,3 +122,22 @@ class QConstant(SymbolicExpr):
|
|
113
122
|
qmod_type,
|
114
123
|
QConstant.CURRENT_QMODULE,
|
115
124
|
)[item]
|
125
|
+
|
126
|
+
def __len__(self) -> int:
|
127
|
+
raise ClassiqValueError(
|
128
|
+
"len(<const>) is not supported for classical constants - use <const>.len "
|
129
|
+
"instead"
|
130
|
+
)
|
131
|
+
|
132
|
+
@property
|
133
|
+
def len(self) -> int:
|
134
|
+
self.add_to_model()
|
135
|
+
if get_origin(self._py_type) != CArray:
|
136
|
+
raise ClassiqValueError(
|
137
|
+
f"Constant {self.name!r} of type {self._py_type.__name__!r} does not "
|
138
|
+
f"have a 'len' property"
|
139
|
+
)
|
140
|
+
len_expr = f"get_field({self.name}, 'len')"
|
141
|
+
if is_generative_mode():
|
142
|
+
return interpret_expression(len_expr)
|
143
|
+
return cast(int, CParamScalar(len_expr))
|
classiq/qmod/quantum_function.py
CHANGED
@@ -9,9 +9,9 @@ from classiq.interface.exceptions import ClassiqError
|
|
9
9
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
10
10
|
from classiq.interface.generator.model.constraints import Constraints
|
11
11
|
from classiq.interface.generator.model.preferences.preferences import Preferences
|
12
|
+
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
12
13
|
from classiq.interface.model.model import Model
|
13
14
|
from classiq.interface.model.native_function_definition import (
|
14
|
-
FunctionSynthesisData,
|
15
15
|
NativeFunctionDefinition,
|
16
16
|
)
|
17
17
|
from classiq.interface.model.quantum_function_declaration import (
|
@@ -35,7 +35,7 @@ class QFunc(QExpandable):
|
|
35
35
|
_validate_no_gen_params(py_callable.__annotations__)
|
36
36
|
super().__init__(py_callable)
|
37
37
|
functools.update_wrapper(self, py_callable)
|
38
|
-
self.
|
38
|
+
self.compilation_metadata: Optional[CompilationMetadata] = None
|
39
39
|
|
40
40
|
@property
|
41
41
|
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
@@ -45,12 +45,19 @@ class QFunc(QExpandable):
|
|
45
45
|
)
|
46
46
|
|
47
47
|
@property
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
def should_synthesize_separately(self) -> bool:
|
49
|
+
if self.compilation_metadata is None:
|
50
|
+
return False
|
51
|
+
return self.compilation_metadata.should_synthesize_separately
|
52
|
+
|
53
|
+
@should_synthesize_separately.setter
|
54
|
+
def should_synthesize_separately(self, value: bool) -> None:
|
55
|
+
if self.compilation_metadata is None:
|
56
|
+
self.compilation_metadata = CompilationMetadata(
|
57
|
+
should_synthesize_separately=value
|
58
|
+
)
|
59
|
+
else:
|
60
|
+
self.compilation_metadata.should_synthesize_separately = value
|
54
61
|
|
55
62
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
56
63
|
super().__call__(*args, **kwargs)
|
@@ -62,12 +69,16 @@ class QFunc(QExpandable):
|
|
62
69
|
execution_preferences: Optional[ExecutionPreferences] = None,
|
63
70
|
preferences: Optional[Preferences] = None,
|
64
71
|
classical_execution_function: Optional[CFunc] = None,
|
72
|
+
functions_compilation_metadata: Optional[dict[str, CompilationMetadata]] = None,
|
65
73
|
) -> Model:
|
74
|
+
if functions_compilation_metadata is None:
|
75
|
+
functions_compilation_metadata = dict()
|
66
76
|
self._qmodule.enum_decls = dict()
|
67
77
|
self._qmodule.type_decls = dict()
|
68
78
|
self._qmodule.qstruct_decls = dict()
|
69
79
|
self._qmodule.native_defs = dict()
|
70
80
|
self._qmodule.constants = dict()
|
81
|
+
self._qmodule.functions_compilation_metadata = functions_compilation_metadata
|
71
82
|
QConstant.set_current_model(self._qmodule)
|
72
83
|
self.expand()
|
73
84
|
model_extra_settings: list[tuple[str, Any]] = [
|
@@ -86,6 +97,7 @@ class QFunc(QExpandable):
|
|
86
97
|
enums=list(self._qmodule.enum_decls.values()),
|
87
98
|
types=list(self._qmodule.type_decls.values()),
|
88
99
|
qstructs=list(self._qmodule.qstruct_decls.values()),
|
100
|
+
functions_compilation_metadata=self._qmodule.functions_compilation_metadata,
|
89
101
|
**{key: value for key, value in model_extra_settings if value},
|
90
102
|
)
|
91
103
|
|
@@ -94,18 +106,12 @@ class QFunc(QExpandable):
|
|
94
106
|
return
|
95
107
|
super().expand()
|
96
108
|
self._qmodule.native_defs[self.func_decl.name] = NativeFunctionDefinition(
|
97
|
-
**{
|
98
|
-
**self.func_decl.model_dump(),
|
99
|
-
**{
|
100
|
-
"body": self.body,
|
101
|
-
"synthesis_data": (
|
102
|
-
self.synthesis_data
|
103
|
-
if self.synthesis_data is not None
|
104
|
-
else FunctionSynthesisData()
|
105
|
-
),
|
106
|
-
},
|
107
|
-
},
|
109
|
+
**{**self.func_decl.model_dump(), **{"body": self.body}}
|
108
110
|
)
|
111
|
+
if self.compilation_metadata is not None:
|
112
|
+
self._qmodule.functions_compilation_metadata[self.func_decl.name] = (
|
113
|
+
self.compilation_metadata
|
114
|
+
)
|
109
115
|
|
110
116
|
def _add_constants_from_classical_code(
|
111
117
|
self, classical_execution_function: CFunc
|
@@ -1,14 +1,13 @@
|
|
1
1
|
from typing import Union
|
2
2
|
|
3
3
|
from classiq.interface.exceptions import ClassiqError
|
4
|
-
from classiq.interface.model.native_function_definition import FunctionSynthesisData
|
5
4
|
|
6
5
|
from classiq.qmod.quantum_function import ExternalQFunc, GenerativeQFunc, QFunc
|
7
6
|
|
8
7
|
|
9
8
|
def synthesize_separately(qfunc: Union[QFunc, GenerativeQFunc, ExternalQFunc]) -> QFunc:
|
10
9
|
if isinstance(qfunc, QFunc):
|
11
|
-
qfunc.
|
10
|
+
qfunc.should_synthesize_separately = True
|
12
11
|
return qfunc
|
13
12
|
if isinstance(qfunc, GenerativeQFunc):
|
14
13
|
raise ClassiqError("Generative functions can not be synthesized separately")
|
@@ -1,13 +1,13 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: classiq
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.56.0
|
4
4
|
Summary: Classiq's Python SDK for quantum computing
|
5
5
|
Home-page: https://classiq.io
|
6
6
|
License: Proprietary
|
7
7
|
Keywords: quantum computing,quantum circuits,quantum algorithms,QAD,QDL
|
8
8
|
Author: Classiq Technologies
|
9
9
|
Author-email: support@classiq.io
|
10
|
-
Requires-Python: >=3.
|
10
|
+
Requires-Python: >=3.9,<3.13
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
12
12
|
Classifier: Intended Audience :: Developers
|
13
13
|
Classifier: Intended Audience :: Education
|
@@ -16,7 +16,6 @@ Classifier: License :: Other/Proprietary License
|
|
16
16
|
Classifier: Natural Language :: English
|
17
17
|
Classifier: Operating System :: OS Independent
|
18
18
|
Classifier: Programming Language :: Python :: 3
|
19
|
-
Classifier: Programming Language :: Python :: 3.8
|
20
19
|
Classifier: Programming Language :: Python :: 3.9
|
21
20
|
Classifier: Programming Language :: Python :: 3.10
|
22
21
|
Classifier: Programming Language :: Python :: 3.11
|