classiq 0.60.1__py3-none-any.whl → 0.62.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/__init__.py +2 -0
- classiq/_internals/client.py +6 -1
- classiq/applications/__init__.py +1 -1
- classiq/applications/chemistry/__init__.py +7 -7
- classiq/applications/chemistry/chemistry_model_constructor.py +17 -6
- classiq/applications/combinatorial_helpers/optimization_model.py +9 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +60 -9
- classiq/applications/combinatorial_optimization/__init__.py +7 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +230 -0
- classiq/applications/finance/finance_model_constructor.py +6 -6
- classiq/applications/grover/grover_model_constructor.py +3 -0
- classiq/applications/libraries/qmci_library.py +1 -10
- classiq/applications/qnn/__init__.py +1 -1
- classiq/applications/qnn/datasets/__init__.py +8 -8
- classiq/applications/qsvm/qsvm.py +1 -1
- classiq/execution/__init__.py +0 -2
- classiq/execution/execution_session.py +6 -0
- classiq/execution/jobs.py +9 -1
- classiq/executor.py +1 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +33 -15
- classiq/interface/backend/quantum_backend_providers.py +3 -1
- classiq/interface/executor/execution_preferences.py +1 -1
- classiq/interface/generator/application_apis/chemistry_declarations.py +1 -1
- classiq/interface/generator/application_apis/finance_declarations.py +2 -2
- classiq/interface/generator/arith/arithmetic.py +16 -1
- classiq/interface/generator/arith/arithmetic_expression_validator.py +4 -3
- classiq/interface/generator/copy.py +47 -0
- classiq/interface/generator/expressions/expression_constants.py +3 -0
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -0
- classiq/interface/generator/generated_circuit_data.py +58 -20
- classiq/interface/generator/model/__init__.py +1 -1
- classiq/interface/generator/model/preferences/preferences.py +1 -1
- classiq/interface/generator/model/quantum_register.py +3 -3
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +20 -32
- classiq/interface/generator/types/compilation_metadata.py +2 -1
- classiq/interface/ide/visual_model.py +1 -0
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/model.py +2 -3
- classiq/interface/model/quantum_function_call.py +4 -7
- classiq/interface/model/quantum_function_declaration.py +7 -0
- classiq/interface/model/quantum_lambda_function.py +10 -1
- classiq/interface/model/quantum_type.py +3 -1
- classiq/model_expansions/atomic_expression_functions_defs.py +3 -1
- classiq/model_expansions/capturing/captured_vars.py +36 -17
- classiq/model_expansions/capturing/mangling_utils.py +23 -15
- classiq/model_expansions/closure.py +6 -9
- classiq/model_expansions/evaluators/arg_type_match.py +7 -7
- classiq/model_expansions/expression_evaluator.py +5 -2
- classiq/model_expansions/function_builder.py +26 -4
- classiq/model_expansions/generative_functions.py +13 -91
- classiq/model_expansions/interpreter.py +75 -46
- classiq/model_expansions/quantum_operations/call_emitter.py +42 -29
- classiq/model_expansions/quantum_operations/classicalif.py +1 -1
- classiq/model_expansions/quantum_operations/control.py +5 -31
- classiq/model_expansions/quantum_operations/emitter.py +29 -17
- classiq/model_expansions/quantum_operations/expression_operation.py +3 -5
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +57 -15
- classiq/model_expansions/quantum_operations/invert.py +1 -6
- classiq/model_expansions/quantum_operations/phase.py +2 -5
- classiq/model_expansions/quantum_operations/power.py +0 -4
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +19 -30
- classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -2
- classiq/model_expansions/quantum_operations/shallow_emitter.py +161 -0
- classiq/model_expansions/quantum_operations/within_apply.py +0 -14
- classiq/model_expansions/scope.py +12 -16
- classiq/model_expansions/scope_initialization.py +0 -11
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +7 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +12 -2
- classiq/model_expansions/transformers/ast_renamer.py +26 -0
- classiq/model_expansions/transformers/var_splitter.py +11 -12
- classiq/model_expansions/visitors/variable_references.py +20 -12
- classiq/qmod/builtins/classical_execution_primitives.py +6 -6
- classiq/qmod/builtins/classical_functions.py +10 -10
- classiq/qmod/builtins/functions/__init__.py +89 -103
- classiq/qmod/builtins/functions/amplitude_estimation.py +1 -1
- classiq/qmod/builtins/functions/arithmetic.py +1 -1
- classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +6 -6
- classiq/qmod/builtins/functions/grover.py +5 -5
- classiq/qmod/builtins/functions/hea.py +1 -1
- classiq/qmod/builtins/functions/linear_pauli_rotation.py +2 -2
- classiq/qmod/builtins/functions/modular_exponentiation.py +8 -8
- classiq/qmod/builtins/functions/operators.py +1 -1
- classiq/qmod/builtins/functions/qaoa_penalty.py +5 -5
- classiq/qmod/builtins/functions/qft_functions.py +2 -2
- classiq/qmod/builtins/functions/qpe.py +9 -12
- classiq/qmod/builtins/functions/qsvt.py +177 -15
- classiq/qmod/builtins/functions/state_preparation.py +9 -9
- classiq/qmod/builtins/functions/swap_test.py +1 -1
- classiq/qmod/builtins/functions/utility_functions.py +2 -2
- classiq/qmod/builtins/functions/variational.py +2 -2
- classiq/qmod/builtins/operations.py +22 -83
- classiq/qmod/builtins/structs.py +9 -9
- classiq/qmod/native/pretty_printer.py +17 -19
- classiq/qmod/pretty_print/pretty_printer.py +9 -6
- classiq/qmod/python_classical_type.py +1 -5
- classiq/qmod/qmod_variable.py +2 -5
- classiq/qmod/quantum_expandable.py +20 -5
- classiq/qmod/quantum_function.py +23 -10
- classiq/qmod/semantics/static_semantics_visitor.py +34 -16
- classiq/qmod/semantics/validation/func_call_validation.py +9 -5
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
- classiq/qmod/symbolic.py +47 -47
- {classiq-0.60.1.dist-info → classiq-0.62.0.dist-info}/METADATA +2 -1
- {classiq-0.60.1.dist-info → classiq-0.62.0.dist-info}/RECORD +107 -103
- classiq/execution/qaoa.py +0 -86
- {classiq-0.60.1.dist-info → classiq-0.62.0.dist-info}/WHEEL +0 -0
@@ -1,16 +1,12 @@
|
|
1
1
|
import inspect
|
2
2
|
import sys
|
3
|
-
import warnings
|
4
3
|
from collections.abc import Mapping
|
5
4
|
from types import FrameType
|
6
5
|
from typing import (
|
7
|
-
TYPE_CHECKING,
|
8
6
|
Any,
|
9
7
|
Callable,
|
10
8
|
Final,
|
11
|
-
Optional,
|
12
9
|
Union,
|
13
|
-
overload,
|
14
10
|
)
|
15
11
|
|
16
12
|
from classiq.interface.exceptions import ClassiqValueError
|
@@ -44,7 +40,8 @@ from classiq.interface.model.repeat import Repeat
|
|
44
40
|
from classiq.interface.model.statement_block import StatementBlock
|
45
41
|
from classiq.interface.model.within_apply_operation import WithinApply
|
46
42
|
|
47
|
-
from classiq.qmod.
|
43
|
+
from classiq.qmod.generative import is_generative_mode
|
44
|
+
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QScalar, QVar
|
48
45
|
from classiq.qmod.quantum_callable import QCallable
|
49
46
|
from classiq.qmod.quantum_expandable import prepare_arg
|
50
47
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
@@ -89,9 +86,10 @@ def if_(
|
|
89
86
|
else_=_operand_to_body(else_, "else") if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
|
90
87
|
source_ref=source_ref,
|
91
88
|
)
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
if is_generative_mode():
|
90
|
+
if_stmt.set_generative_block("then", then)
|
91
|
+
if callable(else_):
|
92
|
+
if_stmt.set_generative_block("else", else_)
|
95
93
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(if_stmt)
|
96
94
|
|
97
95
|
|
@@ -109,9 +107,10 @@ def control(
|
|
109
107
|
else_block=_operand_to_body(else_block, "else_block") if else_block else None,
|
110
108
|
source_ref=source_ref,
|
111
109
|
)
|
112
|
-
|
113
|
-
|
114
|
-
|
110
|
+
if is_generative_mode():
|
111
|
+
control_stmt.set_generative_block("body", stmt_block)
|
112
|
+
if else_block is not None:
|
113
|
+
control_stmt.set_generative_block("else_block", else_block)
|
115
114
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(control_stmt)
|
116
115
|
|
117
116
|
|
@@ -161,22 +160,7 @@ def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
161
160
|
)
|
162
161
|
|
163
162
|
|
164
|
-
@overload
|
165
163
|
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
|
-
|
174
|
-
def inplace_add(
|
175
|
-
expression: Optional[SymbolicExpr] = None,
|
176
|
-
target_var: Optional[QScalar] = None,
|
177
|
-
value: Optional[QNum] = None,
|
178
|
-
target: Optional[QNum] = None,
|
179
|
-
) -> None:
|
180
164
|
"""
|
181
165
|
Add an arithmetic expression to a quantum variable.
|
182
166
|
|
@@ -187,23 +171,6 @@ def inplace_add(
|
|
187
171
|
target_var: A scalar quantum variable
|
188
172
|
"""
|
189
173
|
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
|
207
174
|
source_ref = get_source_ref(sys._getframe(1))
|
208
175
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
209
176
|
ArithmeticOperation(
|
@@ -215,22 +182,7 @@ def inplace_add(
|
|
215
182
|
)
|
216
183
|
|
217
184
|
|
218
|
-
@overload
|
219
185
|
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
|
-
|
228
|
-
def inplace_xor(
|
229
|
-
expression: Optional[SymbolicExpr] = None,
|
230
|
-
target_var: Optional[QScalar] = None,
|
231
|
-
value: Optional[QNum] = None,
|
232
|
-
target: Optional[QNum] = None,
|
233
|
-
) -> None:
|
234
186
|
"""
|
235
187
|
Bitwise-XOR a quantum variable with an arithmetic expression.
|
236
188
|
|
@@ -241,23 +193,6 @@ def inplace_xor(
|
|
241
193
|
target_var: A scalar quantum variable
|
242
194
|
"""
|
243
195
|
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
|
261
196
|
source_ref = get_source_ref(sys._getframe(1))
|
262
197
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
263
198
|
ArithmeticOperation(
|
@@ -282,8 +217,9 @@ def within_apply(
|
|
282
217
|
action=_operand_to_body(apply, "apply"),
|
283
218
|
source_ref=source_ref,
|
284
219
|
)
|
285
|
-
|
286
|
-
|
220
|
+
if is_generative_mode():
|
221
|
+
within_apply_stmt.set_generative_block("within", within)
|
222
|
+
within_apply_stmt.set_generative_block("apply", apply)
|
287
223
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(within_apply_stmt)
|
288
224
|
|
289
225
|
|
@@ -313,7 +249,8 @@ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) ->
|
|
313
249
|
body=iteration_operand.body,
|
314
250
|
source_ref=source_ref,
|
315
251
|
)
|
316
|
-
|
252
|
+
if is_generative_mode():
|
253
|
+
repeat_stmt.set_generative_block("body", iteration)
|
317
254
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(repeat_stmt)
|
318
255
|
|
319
256
|
|
@@ -329,7 +266,8 @@ def power(
|
|
329
266
|
body=_operand_to_body(stmt_block, "stmt_block"),
|
330
267
|
source_ref=source_ref,
|
331
268
|
)
|
332
|
-
|
269
|
+
if is_generative_mode():
|
270
|
+
power_stmt.set_generative_block("body", stmt_block)
|
333
271
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(power_stmt)
|
334
272
|
|
335
273
|
|
@@ -340,7 +278,8 @@ def invert(stmt_block: Union[QCallable, Callable[[], None]]) -> None:
|
|
340
278
|
invert_stmt = Invert(
|
341
279
|
body=_operand_to_body(stmt_block, "stmt_block"), source_ref=source_ref
|
342
280
|
)
|
343
|
-
|
281
|
+
if is_generative_mode():
|
282
|
+
invert_stmt.set_generative_block("body", stmt_block)
|
344
283
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(invert_stmt)
|
345
284
|
|
346
285
|
|
@@ -434,14 +373,14 @@ __all__ = [
|
|
434
373
|
"assign_amplitude",
|
435
374
|
"bind",
|
436
375
|
"control",
|
437
|
-
"invert",
|
438
376
|
"if_",
|
439
377
|
"inplace_add",
|
440
378
|
"inplace_xor",
|
379
|
+
"invert",
|
380
|
+
"phase",
|
441
381
|
"power",
|
442
|
-
"within_apply",
|
443
382
|
"repeat",
|
444
|
-
"
|
383
|
+
"within_apply",
|
445
384
|
]
|
446
385
|
|
447
386
|
|
classiq/qmod/builtins/structs.py
CHANGED
@@ -134,18 +134,18 @@ BUILTIN_STRUCT_DECLARATIONS = {
|
|
134
134
|
|
135
135
|
|
136
136
|
__all__ = [
|
137
|
-
"PauliTerm",
|
138
|
-
"MoleculeProblem",
|
139
|
-
"Molecule",
|
140
137
|
"ChemistryAtom",
|
141
|
-
"Position",
|
142
|
-
"FockHamiltonianProblem",
|
143
|
-
"LadderTerm",
|
144
|
-
"LadderOp",
|
145
138
|
"CombinatorialOptimizationSolution",
|
139
|
+
"FinanceFunction",
|
140
|
+
"FockHamiltonianProblem",
|
146
141
|
"GaussianModel",
|
142
|
+
"LadderOp",
|
143
|
+
"LadderTerm",
|
147
144
|
"LogNormalModel",
|
148
|
-
"
|
149
|
-
"
|
145
|
+
"Molecule",
|
146
|
+
"MoleculeProblem",
|
147
|
+
"PauliTerm",
|
148
|
+
"Position",
|
150
149
|
"QSVMFeatureMapPauli",
|
150
|
+
"QsvmResult",
|
151
151
|
]
|
@@ -51,7 +51,6 @@ from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
51
51
|
ArithmeticOperationKind,
|
52
52
|
)
|
53
53
|
from classiq.interface.model.quantum_function_call import (
|
54
|
-
OperandIdentifier,
|
55
54
|
QuantumFunctionCall,
|
56
55
|
)
|
57
56
|
from classiq.interface.model.quantum_function_declaration import (
|
@@ -60,7 +59,10 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
60
59
|
QuantumFunctionDeclaration,
|
61
60
|
QuantumOperandDeclaration,
|
62
61
|
)
|
63
|
-
from classiq.interface.model.quantum_lambda_function import
|
62
|
+
from classiq.interface.model.quantum_lambda_function import (
|
63
|
+
OperandIdentifier,
|
64
|
+
QuantumLambdaFunction,
|
65
|
+
)
|
64
66
|
from classiq.interface.model.quantum_type import (
|
65
67
|
QuantumBit,
|
66
68
|
QuantumBitvector,
|
@@ -76,6 +78,7 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
76
78
|
)
|
77
79
|
from classiq.interface.model.within_apply_operation import WithinApply
|
78
80
|
|
81
|
+
from classiq.qmod.builtins.functions import OPEN_LIBRARY_FUNCTIONS
|
79
82
|
from classiq.qmod.native.expression_to_qmod import transform_expression
|
80
83
|
from classiq.qmod.semantics.static_semantics_visitor import resolve_function_calls
|
81
84
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
@@ -85,11 +88,11 @@ class DSLPrettyPrinter(Visitor):
|
|
85
88
|
def __init__(
|
86
89
|
self,
|
87
90
|
decimal_precision: Optional[int] = DEFAULT_DECIMAL_PRECISION,
|
88
|
-
|
91
|
+
emit_open_lib_functions: bool = False,
|
89
92
|
) -> None:
|
90
93
|
self._level = 0
|
91
94
|
self._decimal_precision = decimal_precision
|
92
|
-
self.
|
95
|
+
self._emit_open_lib_functions = emit_open_lib_functions
|
93
96
|
|
94
97
|
def visit(self, node: NodeType) -> str:
|
95
98
|
res = super().visit(node)
|
@@ -168,10 +171,7 @@ class DSLPrettyPrinter(Visitor):
|
|
168
171
|
def visit_QuantumVariableDeclaration(
|
169
172
|
self, var_decl: QuantumVariableDeclaration
|
170
173
|
) -> str:
|
171
|
-
|
172
|
-
if self._rename_phase and var_name == "phase":
|
173
|
-
var_name = "phase_var"
|
174
|
-
return f"{var_name}: {self.visit(var_decl.quantum_type)}"
|
174
|
+
return f"{var_decl.name}: {self.visit(var_decl.quantum_type)}"
|
175
175
|
|
176
176
|
def visit_AnonPortDeclaration(self, port_decl: AnonPortDeclaration) -> str:
|
177
177
|
dir_str = (
|
@@ -179,12 +179,7 @@ class DSLPrettyPrinter(Visitor):
|
|
179
179
|
if port_decl.direction != PortDeclarationDirection.Inout
|
180
180
|
else ""
|
181
181
|
)
|
182
|
-
|
183
|
-
port_decl.name
|
184
|
-
if not (self._rename_phase and port_decl.name == "phase")
|
185
|
-
else "phase_var"
|
186
|
-
)
|
187
|
-
param_name = f"{port_name}: " if port_decl.name is not None else ""
|
182
|
+
param_name = f"{port_decl.name}: " if port_decl.name is not None else ""
|
188
183
|
return f"{dir_str}{param_name}{self.visit(port_decl.quantum_type)}"
|
189
184
|
|
190
185
|
def visit_QuantumBit(self, qtype: QuantumBit) -> str:
|
@@ -250,6 +245,10 @@ class DSLPrettyPrinter(Visitor):
|
|
250
245
|
return self.visit_AnonQuantumOperandDeclaration(op_decl)
|
251
246
|
|
252
247
|
def visit_NativeFunctionDefinition(self, func_def: NativeFunctionDefinition) -> str:
|
248
|
+
if not self._emit_open_lib_functions and func_def.name in [
|
249
|
+
qfunc_.func_decl.name for qfunc_ in OPEN_LIBRARY_FUNCTIONS
|
250
|
+
]:
|
251
|
+
return ""
|
253
252
|
self._level += 1
|
254
253
|
body = "".join(self.visit(qvar_decl) for qvar_decl in func_def.body)
|
255
254
|
self._level -= 1
|
@@ -350,11 +349,7 @@ class DSLPrettyPrinter(Visitor):
|
|
350
349
|
return f"lambda({positional_args}) {{\n{body}{self._indent}}}"
|
351
350
|
|
352
351
|
def visit_HandleBinding(self, var_ref: HandleBinding) -> str:
|
353
|
-
return
|
354
|
-
var_ref.name
|
355
|
-
if not (self._rename_phase and var_ref.name == "phase")
|
356
|
-
else "phase_var"
|
357
|
-
)
|
352
|
+
return var_ref.name
|
358
353
|
|
359
354
|
def visit_SlicedHandleBinding(self, var_ref: SlicedHandleBinding) -> str:
|
360
355
|
return f"{self.visit(var_ref.base_handle)}[{self.visit(var_ref.start)}:{self.visit(var_ref.end)}]"
|
@@ -391,6 +386,9 @@ class DSLPrettyPrinter(Visitor):
|
|
391
386
|
def visit_list(self, node: list) -> str:
|
392
387
|
return "[" + ", ".join(self.visit(elem) for elem in node) + "]"
|
393
388
|
|
389
|
+
def visit_OperandIdentifier(self, op: OperandIdentifier) -> str:
|
390
|
+
return str(op)
|
391
|
+
|
394
392
|
@property
|
395
393
|
def _indent(self) -> str:
|
396
394
|
return " " * self._level
|
@@ -52,7 +52,6 @@ from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
52
52
|
ArithmeticOperationKind,
|
53
53
|
)
|
54
54
|
from classiq.interface.model.quantum_function_call import (
|
55
|
-
OperandIdentifier,
|
56
55
|
QuantumFunctionCall,
|
57
56
|
)
|
58
57
|
from classiq.interface.model.quantum_function_declaration import (
|
@@ -61,7 +60,10 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
61
60
|
QuantumFunctionDeclaration,
|
62
61
|
QuantumOperandDeclaration,
|
63
62
|
)
|
64
|
-
from classiq.interface.model.quantum_lambda_function import
|
63
|
+
from classiq.interface.model.quantum_lambda_function import (
|
64
|
+
OperandIdentifier,
|
65
|
+
QuantumLambdaFunction,
|
66
|
+
)
|
65
67
|
from classiq.interface.model.quantum_type import (
|
66
68
|
QuantumBit,
|
67
69
|
QuantumBitvector,
|
@@ -285,10 +287,8 @@ class PythonPrettyPrinter(Visitor):
|
|
285
287
|
raise ClassiqInternalError
|
286
288
|
|
287
289
|
is_unsigned = (
|
288
|
-
is_signed_expr.is_evaluated()
|
289
|
-
|
290
|
-
or is_signed_expr.expr == "UNSIGNED"
|
291
|
-
)
|
290
|
+
is_signed_expr.is_evaluated() and not is_signed_expr.to_bool_value()
|
291
|
+
) or is_signed_expr.expr == "UNSIGNED"
|
292
292
|
is_integer = (
|
293
293
|
fraction_digits_expr.is_evaluated()
|
294
294
|
and fraction_digits_expr.to_int_value() == 0
|
@@ -526,6 +526,9 @@ class PythonPrettyPrinter(Visitor):
|
|
526
526
|
def visit_list(self, node: list) -> str:
|
527
527
|
return "[" + ", ".join(self.visit(elem) for elem in node) + "]"
|
528
528
|
|
529
|
+
def visit_OperandIdentifier(self, op: OperandIdentifier) -> str:
|
530
|
+
return str(op)
|
531
|
+
|
529
532
|
@property
|
530
533
|
def _indent(self) -> str:
|
531
534
|
return " " * self._level
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import dataclasses
|
2
2
|
import inspect
|
3
|
-
import sys
|
4
3
|
from enum import EnumMeta
|
5
4
|
from typing import (
|
6
5
|
Optional,
|
@@ -16,16 +15,13 @@ from classiq.interface.generator.functions.classical_type import (
|
|
16
15
|
Integer,
|
17
16
|
Real,
|
18
17
|
)
|
18
|
+
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
19
19
|
from classiq.interface.generator.functions.type_name import Enum, Struct
|
20
20
|
|
21
21
|
from classiq.qmod.cparam import CArray, CBool, CInt, CReal
|
22
22
|
from classiq.qmod.qmod_variable import get_type_hint_expr
|
23
23
|
from classiq.qmod.utilities import version_portable_get_args
|
24
24
|
|
25
|
-
if sys.version_info[0:2] >= (3, 9):
|
26
|
-
pass
|
27
|
-
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
28
|
-
|
29
25
|
CARRAY_ERROR_MESSAGE = (
|
30
26
|
"CArray accepts one or two generic parameters in the form "
|
31
27
|
"`CArray[<element-type>]` or `CArray[<element-type>, <size>]`"
|
classiq/qmod/qmod_variable.py
CHANGED
@@ -452,11 +452,8 @@ class QArray(ArrayBase[_P], QVar):
|
|
452
452
|
)
|
453
453
|
if self._length is not None and self._length.is_evaluated():
|
454
454
|
length = self._length.to_int_value()
|
455
|
-
if (
|
456
|
-
isinstance(slice_.
|
457
|
-
and slice_.start < 0
|
458
|
-
or isinstance(slice_.stop, int)
|
459
|
-
and slice_.stop > length
|
455
|
+
if (isinstance(slice_.start, int) and slice_.start < 0) or (
|
456
|
+
isinstance(slice_.stop, int) and slice_.stop > length
|
460
457
|
):
|
461
458
|
raise ClassiqValueError(SLICE_OUT_OF_BOUNDS_MSG)
|
462
459
|
|
@@ -18,7 +18,7 @@ import pydantic
|
|
18
18
|
from sympy import Basic
|
19
19
|
from typing_extensions import Self
|
20
20
|
|
21
|
-
from classiq.interface.exceptions import ClassiqValueError
|
21
|
+
from classiq.interface.exceptions import ClassiqInternalError, ClassiqValueError
|
22
22
|
from classiq.interface.generator.expressions.expression import Expression
|
23
23
|
from classiq.interface.generator.functions.concrete_types import (
|
24
24
|
NativePythonClassicalTypes,
|
@@ -30,7 +30,6 @@ from classiq.interface.model.classical_parameter_declaration import (
|
|
30
30
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
31
31
|
from classiq.interface.model.quantum_function_call import (
|
32
32
|
ArgValue,
|
33
|
-
OperandIdentifier,
|
34
33
|
QuantumFunctionCall,
|
35
34
|
)
|
36
35
|
from classiq.interface.model.quantum_function_declaration import (
|
@@ -39,7 +38,11 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
39
38
|
AnonQuantumOperandDeclaration,
|
40
39
|
QuantumFunctionDeclaration,
|
41
40
|
)
|
42
|
-
from classiq.interface.model.quantum_lambda_function import
|
41
|
+
from classiq.interface.model.quantum_lambda_function import (
|
42
|
+
OperandIdentifier,
|
43
|
+
QuantumCallable,
|
44
|
+
QuantumLambdaFunction,
|
45
|
+
)
|
43
46
|
from classiq.interface.model.quantum_statement import QuantumStatement
|
44
47
|
from classiq.interface.model.quantum_type import QuantumType
|
45
48
|
from classiq.interface.model.variable_declaration_statement import (
|
@@ -232,7 +235,9 @@ class QTerminalCallable(QCallable):
|
|
232
235
|
raise NotImplementedError("Operand lists don't support slicing")
|
233
236
|
if isinstance(key, CParam) and not isinstance(key, CParamScalar):
|
234
237
|
raise ClassiqValueError("Non-classical parameter for slicing")
|
235
|
-
|
238
|
+
if not isinstance(self._decl, AnonQuantumOperandDeclaration):
|
239
|
+
raise ClassiqInternalError
|
240
|
+
return QTerminalCallable(self._decl.element_declaration, index_=key)
|
236
241
|
|
237
242
|
def __len__(self) -> int:
|
238
243
|
raise ClassiqValueError(
|
@@ -267,6 +272,13 @@ class QTerminalCallable(QCallable):
|
|
267
272
|
self.func_decl, self._index, source_ref_, *args, **kwargs
|
268
273
|
)
|
269
274
|
|
275
|
+
def get_arg(self) -> QuantumCallable:
|
276
|
+
if self._index is None:
|
277
|
+
return self._decl.name
|
278
|
+
return OperandIdentifier(
|
279
|
+
name=self._decl.name, index=Expression(expr=str(self._index))
|
280
|
+
)
|
281
|
+
|
270
282
|
|
271
283
|
@overload
|
272
284
|
def prepare_arg(
|
@@ -324,11 +336,14 @@ def prepare_arg(
|
|
324
336
|
pos_rename_params=val.infer_rename_params(),
|
325
337
|
body=val.body,
|
326
338
|
)
|
327
|
-
|
339
|
+
if is_generative_mode():
|
340
|
+
qlambda.set_py_callable(val._py_callable)
|
328
341
|
return qlambda
|
329
342
|
|
330
343
|
if isinstance(val, QExpandable):
|
331
344
|
val.expand()
|
345
|
+
elif isinstance(val, QTerminalCallable):
|
346
|
+
return val.get_arg()
|
332
347
|
return val.func_decl.name
|
333
348
|
|
334
349
|
|
classiq/qmod/quantum_function.py
CHANGED
@@ -77,12 +77,24 @@ class QFunc(BaseQFunc):
|
|
77
77
|
self.compilation_metadata: Optional[CompilationMetadata] = None
|
78
78
|
|
79
79
|
@property
|
80
|
-
def
|
81
|
-
|
82
|
-
self.
|
83
|
-
|
80
|
+
def pure_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
81
|
+
if type(self.func_decl) is NamedParamsQuantumFunctionDeclaration:
|
82
|
+
return self.func_decl
|
83
|
+
return NamedParamsQuantumFunctionDeclaration(
|
84
|
+
**{
|
85
|
+
k: v
|
86
|
+
for k, v in self.func_decl.model_dump().items()
|
87
|
+
if k in NamedParamsQuantumFunctionDeclaration.model_fields
|
88
|
+
}
|
84
89
|
)
|
85
90
|
|
91
|
+
@property
|
92
|
+
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
93
|
+
name = self._py_callable.__name__
|
94
|
+
if hasattr(self._qmodule, "native_defs") and name in self._qmodule.native_defs:
|
95
|
+
return self._qmodule.native_defs[name]
|
96
|
+
return infer_func_decl(self._py_callable, qmodule=self._qmodule)
|
97
|
+
|
86
98
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
87
99
|
super().__call__(*args, **kwargs)
|
88
100
|
self.expand()
|
@@ -181,6 +193,10 @@ class ExternalQFunc(QTerminalCallable):
|
|
181
193
|
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
182
194
|
return self._decl
|
183
195
|
|
196
|
+
@property
|
197
|
+
def pure_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
198
|
+
return self.func_decl
|
199
|
+
|
184
200
|
def get_implementation(self) -> NativeFunctionDefinition:
|
185
201
|
model = QFunc(self._py_callable).create_model()
|
186
202
|
return [
|
@@ -224,12 +240,9 @@ def _validate_no_gen_params(annotations: dict[str, Any]) -> None:
|
|
224
240
|
for name, annotation in annotations.items()
|
225
241
|
if not (
|
226
242
|
name == "return"
|
227
|
-
or isclass(annotation)
|
228
|
-
and
|
229
|
-
or isclass(annotation)
|
230
|
-
and is_dataclass(annotation)
|
231
|
-
or isclass(annotation)
|
232
|
-
and isinstance(annotation, EnumMeta)
|
243
|
+
or (isclass(annotation) and issubclass(annotation, CParam))
|
244
|
+
or (isclass(annotation) and is_dataclass(annotation))
|
245
|
+
or (isclass(annotation) and isinstance(annotation, EnumMeta))
|
233
246
|
or get_origin(annotation) is CArray
|
234
247
|
or (get_origin(annotation) or annotation) is QCallable
|
235
248
|
or (get_origin(annotation) or annotation) is QCallableList
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import ast
|
1
2
|
from collections.abc import Iterator, Mapping, Sequence
|
2
3
|
from contextlib import contextmanager
|
3
4
|
from typing import (
|
@@ -6,7 +7,9 @@ from typing import (
|
|
6
7
|
)
|
7
8
|
|
8
9
|
from classiq.interface.exceptions import ClassiqSemanticError
|
10
|
+
from classiq.interface.generator.expressions.expression import Expression
|
9
11
|
from classiq.interface.generator.function_params import PortDirection
|
12
|
+
from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
|
10
13
|
from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
|
11
14
|
from classiq.interface.generator.functions.port_declaration import (
|
12
15
|
PortDeclarationDirection,
|
@@ -25,6 +28,9 @@ from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperat
|
|
25
28
|
from classiq.interface.model.model import Model
|
26
29
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
27
30
|
from classiq.interface.model.port_declaration import PortDeclaration
|
31
|
+
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
32
|
+
QuantumExpressionOperation,
|
33
|
+
)
|
28
34
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
29
35
|
from classiq.interface.model.quantum_function_declaration import (
|
30
36
|
AnonQuantumOperandDeclaration,
|
@@ -41,7 +47,10 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
41
47
|
)
|
42
48
|
from classiq.interface.model.within_apply_operation import WithinApply
|
43
49
|
|
44
|
-
from classiq.
|
50
|
+
from classiq.model_expansions.visitors.variable_references import VarRefCollector
|
51
|
+
from classiq.qmod.builtins.functions import (
|
52
|
+
BUILTIN_FUNCTION_DECLARATIONS,
|
53
|
+
)
|
45
54
|
from classiq.qmod.semantics.annotation import annotate_function_call_decl
|
46
55
|
from classiq.qmod.semantics.error_manager import ErrorManager
|
47
56
|
from classiq.qmod.semantics.qstruct_annotator import QStructAnnotator
|
@@ -52,6 +61,9 @@ from classiq.qmod.semantics.validation.func_call_validation import (
|
|
52
61
|
check_no_overlapping_quantum_args,
|
53
62
|
validate_call_arguments,
|
54
63
|
)
|
64
|
+
from classiq.qmod.semantics.validation.function_name_collisions_validation import (
|
65
|
+
_check_function_name_collisions,
|
66
|
+
)
|
55
67
|
from classiq.qmod.semantics.validation.handle_validation import resolve_handle
|
56
68
|
from classiq.qmod.semantics.validation.main_validation import validate_main_function
|
57
69
|
from classiq.qmod.semantics.validation.types_validation import (
|
@@ -266,6 +278,26 @@ class StaticSemanticsVisitor(Visitor):
|
|
266
278
|
def visit_HandleBinding(self, handle: HandleBinding) -> None:
|
267
279
|
resolve_handle(self.current_scope, handle)
|
268
280
|
|
281
|
+
def visit_Expression(self, expr: Expression) -> None:
|
282
|
+
if len(self._scope) == 0:
|
283
|
+
return
|
284
|
+
vrc = VarRefCollector(ignore_duplicated_handles=True, unevaluated=True)
|
285
|
+
vrc.visit(ast.parse(expr.expr))
|
286
|
+
handles = [
|
287
|
+
HandleMetadata(handle=handle)
|
288
|
+
for handle in vrc.var_handles
|
289
|
+
if handle.name in self.current_scope.variable_states
|
290
|
+
and (
|
291
|
+
not isinstance(handle, FieldHandleBinding)
|
292
|
+
or handle.field not in CLASSICAL_ATTRIBUTES
|
293
|
+
)
|
294
|
+
]
|
295
|
+
self._handle_inouts(handles)
|
296
|
+
|
297
|
+
def visit_QuantumExpressionOperation(self, op: QuantumExpressionOperation) -> None:
|
298
|
+
self.visit_Expression(op.expression)
|
299
|
+
self.visit_QuantumOperation(op)
|
300
|
+
|
269
301
|
def _handle_state_changing_ios(
|
270
302
|
self,
|
271
303
|
ios: Sequence[HandleMetadata],
|
@@ -314,9 +346,6 @@ class StaticSemanticsVisitor(Visitor):
|
|
314
346
|
)
|
315
347
|
|
316
348
|
def _handle_inouts(self, inouts: Sequence[HandleMetadata]) -> None:
|
317
|
-
sliced_handles = set()
|
318
|
-
whole_handles = set()
|
319
|
-
|
320
349
|
for handle_metadata in inouts:
|
321
350
|
handle_binding = handle_metadata.handle
|
322
351
|
|
@@ -345,18 +374,6 @@ class StaticSemanticsVisitor(Visitor):
|
|
345
374
|
f"{location}"
|
346
375
|
)
|
347
376
|
|
348
|
-
if isinstance(
|
349
|
-
handle_binding, (SlicedHandleBinding, SubscriptHandleBinding)
|
350
|
-
):
|
351
|
-
sliced_handles.add(handle_binding.name)
|
352
|
-
else:
|
353
|
-
whole_handles.add(handle_binding.name)
|
354
|
-
|
355
|
-
for handle in sliced_handles & whole_handles:
|
356
|
-
self._error_manager.add_error(
|
357
|
-
f"Invalid use of inout handle {handle!r}, used both in slice or subscript and whole"
|
358
|
-
)
|
359
|
-
|
360
377
|
|
361
378
|
def resolve_function_calls(
|
362
379
|
root: Any,
|
@@ -374,6 +391,7 @@ def resolve_function_calls(
|
|
374
391
|
def static_semantics_analysis_pass(
|
375
392
|
model: Model, error_type: Optional[type[Exception]] = ClassiqSemanticError
|
376
393
|
) -> None:
|
394
|
+
_check_function_name_collisions(model, error_type)
|
377
395
|
QStructAnnotator().visit(model)
|
378
396
|
StaticSemanticsVisitor(
|
379
397
|
{**BUILTIN_FUNCTION_DECLARATIONS, **model.function_dict},
|
@@ -10,6 +10,7 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
10
10
|
QuantumFunctionDeclaration,
|
11
11
|
)
|
12
12
|
from classiq.interface.model.quantum_lambda_function import (
|
13
|
+
OperandIdentifier,
|
13
14
|
QuantumLambdaFunction,
|
14
15
|
QuantumOperand,
|
15
16
|
)
|
@@ -56,16 +57,19 @@ def _check_operand_against_declaration(
|
|
56
57
|
)
|
57
58
|
return
|
58
59
|
operand_arg_decl: AnonQuantumFunctionDeclaration
|
59
|
-
|
60
|
-
|
60
|
+
operand_argument_for_decl = operand_argument
|
61
|
+
if isinstance(operand_argument_for_decl, OperandIdentifier):
|
62
|
+
operand_argument_for_decl = operand_argument_for_decl.name
|
63
|
+
if isinstance(operand_argument_for_decl, str):
|
64
|
+
if operand_argument_for_decl not in function_dict:
|
61
65
|
ErrorManager().add_error(
|
62
66
|
f"{operand_argument!r} argument to {func_name!r} is not a "
|
63
67
|
f"registered function."
|
64
68
|
)
|
65
69
|
return
|
66
|
-
operand_arg_decl = function_dict[
|
67
|
-
elif isinstance(
|
68
|
-
operand_arg_decl =
|
70
|
+
operand_arg_decl = function_dict[operand_argument_for_decl]
|
71
|
+
elif isinstance(operand_argument_for_decl, QuantumLambdaFunction):
|
72
|
+
operand_arg_decl = operand_argument_for_decl.func_decl
|
69
73
|
else:
|
70
74
|
raise ClassiqError(
|
71
75
|
f"{str(operand_argument)!r} argument to {func_name!r} is not a "
|