classiq 0.83.0__py3-none-any.whl → 0.85.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/_internals/api_wrapper.py +27 -0
- classiq/applications/chemistry/chemistry_model_constructor.py +0 -2
- classiq/applications/chemistry/hartree_fock.py +68 -0
- classiq/applications/chemistry/mapping.py +85 -0
- classiq/applications/chemistry/op_utils.py +79 -0
- classiq/applications/chemistry/problems.py +195 -0
- classiq/applications/chemistry/ucc.py +109 -0
- classiq/applications/chemistry/z2_symmetries.py +368 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +30 -1
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +20 -42
- classiq/{model_expansions/evaluators → evaluators}/arg_type_match.py +12 -4
- classiq/{model_expansions/evaluators → evaluators}/argument_types.py +1 -1
- classiq/evaluators/classical_expression.py +53 -0
- classiq/{model_expansions/evaluators → evaluators}/classical_type_inference.py +3 -4
- classiq/{model_expansions/evaluators → evaluators}/parameter_types.py +17 -15
- classiq/execution/__init__.py +12 -1
- classiq/execution/execution_session.py +238 -49
- classiq/execution/jobs.py +26 -1
- classiq/execution/qnn.py +2 -2
- classiq/execution/user_budgets.py +39 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/constants.py +1 -0
- classiq/interface/debug_info/debug_info.py +0 -4
- classiq/interface/execution/primitives.py +29 -1
- classiq/interface/executor/estimate_cost.py +35 -0
- classiq/interface/executor/execution_result.py +13 -0
- classiq/interface/executor/result.py +116 -1
- classiq/interface/executor/user_budget.py +26 -33
- classiq/interface/generator/expressions/atomic_expression_functions.py +10 -1
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -6
- classiq/interface/generator/functions/builtins/internal_operators.py +2 -0
- classiq/interface/generator/functions/classical_type.py +2 -35
- classiq/interface/generator/functions/concrete_types.py +20 -3
- classiq/interface/generator/functions/type_modifier.py +0 -19
- classiq/interface/generator/generated_circuit_data.py +5 -18
- classiq/interface/generator/types/compilation_metadata.py +0 -3
- classiq/interface/ide/operation_registry.py +45 -0
- classiq/interface/ide/visual_model.py +68 -3
- classiq/interface/model/bounds.py +12 -2
- classiq/interface/model/model.py +12 -7
- classiq/interface/model/port_declaration.py +2 -24
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +7 -4
- classiq/interface/model/variable_declaration_statement.py +33 -6
- classiq/interface/pretty_print/__init__.py +0 -0
- classiq/{qmod/native → interface/pretty_print}/expression_to_qmod.py +18 -11
- classiq/interface/server/routes.py +4 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +47 -6
- classiq/model_expansions/function_builder.py +4 -1
- classiq/model_expansions/interpreters/base_interpreter.py +3 -3
- classiq/model_expansions/interpreters/generative_interpreter.py +16 -1
- classiq/model_expansions/quantum_operations/allocate.py +1 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +64 -22
- classiq/model_expansions/quantum_operations/bind.py +2 -2
- classiq/model_expansions/quantum_operations/bounds.py +7 -1
- classiq/model_expansions/quantum_operations/call_emitter.py +26 -20
- classiq/model_expansions/quantum_operations/classical_var_emitter.py +16 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +31 -11
- classiq/model_expansions/scope.py +7 -0
- classiq/model_expansions/scope_initialization.py +3 -3
- classiq/model_expansions/transformers/model_renamer.py +6 -4
- classiq/model_expansions/transformers/type_modifier_inference.py +81 -43
- classiq/model_expansions/transformers/var_splitter.py +1 -1
- classiq/model_expansions/visitors/symbolic_param_inference.py +2 -3
- classiq/open_library/functions/__init__.py +3 -2
- classiq/open_library/functions/amplitude_amplification.py +10 -18
- classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
- classiq/open_library/functions/grover.py +14 -6
- classiq/open_library/functions/modular_exponentiation.py +22 -20
- classiq/open_library/functions/qaoa_penalty.py +8 -1
- classiq/open_library/functions/state_preparation.py +18 -32
- classiq/qmod/__init__.py +2 -0
- classiq/qmod/builtins/enums.py +23 -0
- classiq/qmod/builtins/functions/__init__.py +2 -0
- classiq/qmod/builtins/functions/exponentiation.py +32 -4
- classiq/qmod/builtins/operations.py +65 -1
- classiq/qmod/builtins/structs.py +55 -3
- classiq/qmod/classical_variable.py +74 -0
- classiq/qmod/declaration_inferrer.py +3 -2
- classiq/qmod/native/pretty_printer.py +20 -20
- classiq/qmod/pretty_print/expression_to_python.py +2 -1
- classiq/qmod/pretty_print/pretty_printer.py +35 -21
- classiq/qmod/python_classical_type.py +12 -5
- classiq/qmod/qfunc.py +2 -19
- classiq/qmod/qmod_constant.py +2 -5
- classiq/qmod/qmod_parameter.py +2 -5
- classiq/qmod/qmod_variable.py +61 -23
- classiq/qmod/quantum_expandable.py +5 -3
- classiq/qmod/quantum_function.py +49 -4
- classiq/qmod/semantics/annotation/qstruct_annotator.py +1 -1
- classiq/qmod/semantics/validation/main_validation.py +1 -9
- classiq/qmod/symbolic_type.py +2 -1
- classiq/qmod/utilities.py +0 -2
- classiq/qmod/write_qmod.py +1 -1
- {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/METADATA +4 -1
- {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/RECORD +101 -90
- classiq/interface/model/quantum_variable_declaration.py +0 -7
- classiq/model_expansions/evaluators/classical_expression.py +0 -36
- /classiq/{model_expansions/evaluators → evaluators}/__init__.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/control.py +0 -0
- /classiq/{model_expansions → evaluators}/expression_evaluator.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/quantum_type_utils.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/type_type_match.py +0 -0
- {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/WHEEL +0 -0
@@ -1,10 +1,12 @@
|
|
1
|
-
from typing import Optional
|
1
|
+
from typing import TYPE_CHECKING, Optional
|
2
2
|
|
3
3
|
from classiq.interface.exceptions import ClassiqExpansionError
|
4
4
|
from classiq.interface.generator.arith.arithmetic import compute_arithmetic_result_type
|
5
5
|
from classiq.interface.generator.expressions.expression import Expression
|
6
6
|
from classiq.interface.model.allocate import Allocate
|
7
7
|
from classiq.interface.model.bind_operation import BindOperation
|
8
|
+
from classiq.interface.model.block import Block
|
9
|
+
from classiq.interface.model.bounds import SetBoundsStatement
|
8
10
|
from classiq.interface.model.handle_binding import (
|
9
11
|
ConcreteHandleBinding,
|
10
12
|
HandleBinding,
|
@@ -19,25 +21,37 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
19
21
|
)
|
20
22
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
21
23
|
from classiq.interface.model.quantum_type import QuantumBitvector, QuantumNumeric
|
24
|
+
from classiq.interface.model.statement_block import StatementBlock
|
22
25
|
from classiq.interface.model.variable_declaration_statement import (
|
23
26
|
VariableDeclarationStatement,
|
24
27
|
)
|
25
28
|
from classiq.interface.model.within_apply_operation import WithinApply
|
26
29
|
|
27
|
-
from classiq.
|
30
|
+
from classiq.evaluators.quantum_type_utils import copy_type_information
|
28
31
|
from classiq.model_expansions.quantum_operations.arithmetic.explicit_boolean_expressions import (
|
29
32
|
convert_assignment_bool_expression,
|
30
33
|
validate_assignment_bool_expression,
|
31
34
|
)
|
32
35
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
33
|
-
from classiq.model_expansions.scope import
|
36
|
+
from classiq.model_expansions.scope import ClassicalSymbol
|
34
37
|
from classiq.model_expansions.transformers.ast_renamer import rename_variables
|
35
38
|
from classiq.qmod.builtins.functions.standard_gates import CX
|
36
39
|
|
40
|
+
if TYPE_CHECKING:
|
41
|
+
from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
|
42
|
+
|
37
43
|
|
38
44
|
class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
45
|
+
def __init__(
|
46
|
+
self, interpreter: "BaseInterpreter", replace_assignment_if_needed: bool = False
|
47
|
+
) -> None:
|
48
|
+
super().__init__(interpreter)
|
49
|
+
self._replace_assignment_if_needed = replace_assignment_if_needed
|
50
|
+
|
39
51
|
def emit(self, op: QuantumAssignmentOperation, /) -> bool:
|
40
|
-
result_symbol = self._interpreter.evaluate(op.result_var).
|
52
|
+
result_symbol = self._interpreter.evaluate(op.result_var).value
|
53
|
+
if isinstance(result_symbol, ClassicalSymbol):
|
54
|
+
return False
|
41
55
|
result_type = result_symbol.quantum_type
|
42
56
|
|
43
57
|
if not (
|
@@ -70,9 +84,11 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
70
84
|
self._validate_declared_attributes(
|
71
85
|
result_type, inferred_result_type, str(op.result_var)
|
72
86
|
)
|
73
|
-
self.
|
74
|
-
|
75
|
-
|
87
|
+
if self._replace_assignment_if_needed:
|
88
|
+
self._assign_to_inferred_var_and_bind(op, result_type, inferred_result_type)
|
89
|
+
return True
|
90
|
+
else:
|
91
|
+
return False
|
76
92
|
|
77
93
|
def _infer_result_type(self, op: ArithmeticOperation) -> Optional[QuantumNumeric]:
|
78
94
|
expr = self._evaluate_expression(op.expression)
|
@@ -182,6 +198,7 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
182
198
|
result_type: QuantumNumeric,
|
183
199
|
inferred_result_type: QuantumNumeric,
|
184
200
|
) -> None:
|
201
|
+
stmts: StatementBlock = []
|
185
202
|
handles: list[HandleBinding] = []
|
186
203
|
|
187
204
|
extra_fraction_digits = (
|
@@ -190,20 +207,22 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
190
207
|
)
|
191
208
|
if extra_fraction_digits > 0:
|
192
209
|
handles.append(
|
193
|
-
self._declare_qarray(
|
210
|
+
self._declare_qarray(
|
211
|
+
"extra_fraction_digits", extra_fraction_digits, stmts
|
212
|
+
)
|
194
213
|
)
|
195
214
|
|
196
215
|
inferred_result_name = self._counted_name_allocator.allocate("inferred_result")
|
197
216
|
inferred_result_handle = HandleBinding(name=inferred_result_name)
|
198
|
-
|
217
|
+
stmts.append(
|
199
218
|
VariableDeclarationStatement(
|
200
|
-
name=inferred_result_name,
|
219
|
+
name=inferred_result_name, qmod_type=inferred_result_type
|
201
220
|
)
|
202
221
|
)
|
203
222
|
handles.append(inferred_result_handle)
|
204
223
|
modified_op = op.model_copy(update={"result_var": inferred_result_handle})
|
205
224
|
self._interpreter.add_to_debug_info(modified_op)
|
206
|
-
|
225
|
+
stmts.append(modified_op)
|
207
226
|
|
208
227
|
result_integer_size = (
|
209
228
|
result_type.size_in_bits - result_type.fraction_digits_value
|
@@ -214,11 +233,11 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
214
233
|
)
|
215
234
|
extra_integers = result_integer_size - inferred_result_integer_size
|
216
235
|
if extra_integers > 0:
|
217
|
-
handles.append(
|
236
|
+
handles.append(
|
237
|
+
self._declare_qarray("extra_integers", extra_integers, stmts)
|
238
|
+
)
|
218
239
|
|
219
|
-
|
220
|
-
BindOperation(in_handles=handles, out_handles=[op.result_var])
|
221
|
-
)
|
240
|
+
stmts.append(BindOperation(in_handles=handles, out_handles=[op.result_var]))
|
222
241
|
|
223
242
|
if (
|
224
243
|
result_type.sign_value
|
@@ -226,22 +245,44 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
226
245
|
and extra_integers > 0
|
227
246
|
):
|
228
247
|
sign_idx = result_type.size_in_bits - extra_integers - 1
|
229
|
-
self._sign_extension(
|
248
|
+
self._sign_extension(
|
249
|
+
op.result_var, sign_idx, result_type.size_in_bits, stmts
|
250
|
+
)
|
251
|
+
|
252
|
+
if (inferred_bounds := inferred_result_type.get_bounds()) is not None:
|
253
|
+
lower_bound = Expression(expr=str(inferred_bounds[0]))
|
254
|
+
upper_bound = Expression(expr=str(inferred_bounds[1]))
|
255
|
+
else:
|
256
|
+
lower_bound, upper_bound = None, None
|
257
|
+
stmts.append(
|
258
|
+
SetBoundsStatement(
|
259
|
+
target=op.result_var,
|
260
|
+
lower_bound=lower_bound,
|
261
|
+
upper_bound=upper_bound,
|
262
|
+
)
|
263
|
+
)
|
264
|
+
|
265
|
+
self._interpreter.emit(
|
266
|
+
Block(
|
267
|
+
statements=stmts,
|
268
|
+
uuid=op.uuid,
|
269
|
+
back_ref=op.back_ref,
|
270
|
+
)
|
271
|
+
)
|
230
272
|
|
231
273
|
def _declare_qarray(
|
232
274
|
self,
|
233
275
|
prefix: str,
|
234
276
|
size: int,
|
277
|
+
stmts: StatementBlock,
|
235
278
|
allocate: bool = True,
|
236
279
|
) -> HandleBinding:
|
237
280
|
name = self._counted_name_allocator.allocate(prefix)
|
238
281
|
handle = HandleBinding(name=name)
|
239
282
|
quantum_type = QuantumBitvector(length=Expression(expr=str(size)))
|
240
|
-
|
241
|
-
VariableDeclarationStatement(name=name, quantum_type=quantum_type)
|
242
|
-
)
|
283
|
+
stmts.append(VariableDeclarationStatement(name=name, qmod_type=quantum_type))
|
243
284
|
if allocate:
|
244
|
-
|
285
|
+
stmts.append(Allocate(target=handle))
|
245
286
|
return handle
|
246
287
|
|
247
288
|
def _sign_extension(
|
@@ -249,9 +290,10 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
249
290
|
result_var: ConcreteHandleBinding,
|
250
291
|
sign_idx: int,
|
251
292
|
size: int,
|
293
|
+
stmts: StatementBlock,
|
252
294
|
) -> None:
|
253
|
-
aux = self._declare_qarray("inferred_result_aux", size, allocate=False)
|
254
|
-
|
295
|
+
aux = self._declare_qarray("inferred_result_aux", size, stmts, allocate=False)
|
296
|
+
stmts.append(
|
255
297
|
WithinApply(
|
256
298
|
compute=[BindOperation(in_handles=[result_var], out_handles=[aux])],
|
257
299
|
action=[
|
@@ -8,10 +8,10 @@ from classiq.interface.exceptions import (
|
|
8
8
|
from classiq.interface.model.bind_operation import BindOperation
|
9
9
|
from classiq.interface.model.quantum_type import QuantumNumeric
|
10
10
|
|
11
|
-
from classiq.
|
11
|
+
from classiq.evaluators.parameter_types import (
|
12
12
|
evaluate_types_in_quantum_symbols,
|
13
13
|
)
|
14
|
-
from classiq.
|
14
|
+
from classiq.evaluators.quantum_type_utils import (
|
15
15
|
set_size,
|
16
16
|
validate_bind_targets,
|
17
17
|
)
|
@@ -24,7 +24,13 @@ class SetBoundsEmitter(Emitter[SetBoundsStatement]):
|
|
24
24
|
raise ClassiqExpansionError(
|
25
25
|
f"Cannot set bounds of a non-numeric variable {op.target.qmod_expr!r}"
|
26
26
|
)
|
27
|
-
|
27
|
+
|
28
|
+
if op.lower_bound is not None and op.upper_bound is not None:
|
29
|
+
target.quantum_type.set_bounds(
|
30
|
+
(op.lower_bound.to_float_value(), op.upper_bound.to_float_value())
|
31
|
+
)
|
32
|
+
else:
|
33
|
+
target.quantum_type.reset_bounds()
|
28
34
|
if self._keep_statement:
|
29
35
|
self.emit_statement(op)
|
30
36
|
return True
|
@@ -50,19 +50,19 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
50
50
|
VariableDeclarationStatement,
|
51
51
|
)
|
52
52
|
|
53
|
+
from classiq.evaluators.argument_types import (
|
54
|
+
add_information_from_output_arguments,
|
55
|
+
handle_args_numeric_bounds,
|
56
|
+
)
|
57
|
+
from classiq.evaluators.parameter_types import (
|
58
|
+
evaluate_parameter_types_from_args,
|
59
|
+
)
|
53
60
|
from classiq.model_expansions.capturing.captured_vars import (
|
54
61
|
INITIALIZED_VAR_MESSAGE,
|
55
62
|
UNINITIALIZED_VAR_MESSAGE,
|
56
63
|
validate_args_are_not_propagated,
|
57
64
|
)
|
58
65
|
from classiq.model_expansions.closure import Closure, FunctionClosure
|
59
|
-
from classiq.model_expansions.evaluators.argument_types import (
|
60
|
-
add_information_from_output_arguments,
|
61
|
-
handle_args_numeric_bounds,
|
62
|
-
)
|
63
|
-
from classiq.model_expansions.evaluators.parameter_types import (
|
64
|
-
evaluate_parameter_types_from_args,
|
65
|
-
)
|
66
66
|
from classiq.model_expansions.function_builder import (
|
67
67
|
FunctionContext,
|
68
68
|
)
|
@@ -135,13 +135,13 @@ def _validate_gen_args(
|
|
135
135
|
):
|
136
136
|
if (
|
137
137
|
isinstance(param, ClassicalParameterDeclaration)
|
138
|
-
and param.classical_type.
|
138
|
+
and not param.classical_type.is_purely_declarative
|
139
139
|
and _is_symbolic(arg.value)
|
140
140
|
):
|
141
|
+
readable_expr = transform_expression(str(arg.value), {}, {}, one_line=True)
|
141
142
|
raise ClassiqExpansionError(
|
142
|
-
f"
|
143
|
-
f"
|
144
|
-
f"{transform_expression(str(arg.value), {}, {}, one_line=True)!r}"
|
143
|
+
f"Cannot pass symbolic expression {readable_expr!r} as Python-type "
|
144
|
+
f"parameter {param.name!r}"
|
145
145
|
)
|
146
146
|
|
147
147
|
|
@@ -209,17 +209,21 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
209
209
|
function.name, new_declaration
|
210
210
|
)
|
211
211
|
else:
|
212
|
-
|
213
|
-
if type(self._interpreter).__name__ == "FrontendGenerativeInterpreter":
|
214
|
-
_validate_gen_args(function, evaluated_args)
|
212
|
+
_validate_gen_args(function, evaluated_args)
|
215
213
|
new_declaration = self._expand_function(
|
216
214
|
evaluated_args, new_declaration, function
|
217
215
|
)
|
218
216
|
new_positional_arg_decls = new_declaration.positional_arg_declarations
|
219
217
|
evaluated_args = [
|
220
218
|
arg
|
221
|
-
for arg in
|
222
|
-
|
219
|
+
for param, arg in zip_strict(
|
220
|
+
function.positional_arg_declarations, evaluated_args, strict=True
|
221
|
+
)
|
222
|
+
if isinstance(arg.value, QuantumVariable)
|
223
|
+
or (
|
224
|
+
isinstance(param, ClassicalParameterDeclaration)
|
225
|
+
and param.classical_type.is_purely_declarative
|
226
|
+
)
|
223
227
|
]
|
224
228
|
|
225
229
|
add_information_from_output_arguments(new_positional_arg_decls, evaluated_args)
|
@@ -312,7 +316,7 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
312
316
|
if isinstance(param, PortDeclaration)
|
313
317
|
or (
|
314
318
|
isinstance(param, ClassicalParameterDeclaration)
|
315
|
-
and
|
319
|
+
and param.classical_type.is_purely_declarative
|
316
320
|
)
|
317
321
|
]
|
318
322
|
func_def = self._builder.create_definition(function_context, params)
|
@@ -350,8 +354,10 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
350
354
|
),
|
351
355
|
defining_function=closure,
|
352
356
|
)
|
353
|
-
elif
|
354
|
-
|
357
|
+
elif (
|
358
|
+
isinstance(parameter, ClassicalParameterDeclaration)
|
359
|
+
and parameter.classical_type.is_purely_declarative
|
360
|
+
):
|
355
361
|
inferred_arg = Evaluated(
|
356
362
|
value=parameter.classical_type.get_classical_proxy(param_handle),
|
357
363
|
defining_function=closure,
|
@@ -426,7 +432,7 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
|
|
426
432
|
).unchecked
|
427
433
|
TypeModifierValidation(
|
428
434
|
skip_validation=self._interpreter.skip_type_modifier_validation
|
429
|
-
).run(func_def
|
435
|
+
).run(func_def, unchecked)
|
430
436
|
|
431
437
|
@staticmethod
|
432
438
|
def _should_override_type_modifiers(func_context: FunctionContext) -> bool:
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
2
|
+
ArithmeticOperation,
|
3
|
+
)
|
4
|
+
|
5
|
+
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
6
|
+
from classiq.model_expansions.scope import ClassicalSymbol
|
7
|
+
|
8
|
+
|
9
|
+
class ClassicalVarEmitter(Emitter[ArithmeticOperation]):
|
10
|
+
def emit(self, op: ArithmeticOperation, /) -> bool:
|
11
|
+
result_symbol = self._interpreter.evaluate(op.result_var).value
|
12
|
+
if not isinstance(result_symbol, ClassicalSymbol):
|
13
|
+
return False
|
14
|
+
op._classical_assignment = True
|
15
|
+
self.emit_statement(op)
|
16
|
+
return True
|
@@ -1,14 +1,19 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Union
|
2
|
+
|
1
3
|
from classiq.interface.exceptions import ClassiqExpansionError
|
4
|
+
from classiq.interface.generator.functions.classical_type import ClassicalType
|
2
5
|
from classiq.interface.model.handle_binding import HandleBinding
|
6
|
+
from classiq.interface.model.quantum_type import QuantumType
|
3
7
|
from classiq.interface.model.variable_declaration_statement import (
|
4
8
|
VariableDeclarationStatement,
|
5
9
|
)
|
6
10
|
|
7
|
-
from classiq.
|
11
|
+
from classiq.evaluators.parameter_types import (
|
12
|
+
evaluate_type_in_classical_symbol,
|
8
13
|
evaluate_type_in_quantum_symbol,
|
9
14
|
)
|
10
15
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
11
|
-
from classiq.model_expansions.scope import Evaluated, QuantumSymbol
|
16
|
+
from classiq.model_expansions.scope import ClassicalSymbol, Evaluated, QuantumSymbol
|
12
17
|
|
13
18
|
|
14
19
|
class VariableDeclarationStatementEmitter(Emitter[VariableDeclarationStatement]):
|
@@ -16,24 +21,39 @@ class VariableDeclarationStatementEmitter(Emitter[VariableDeclarationStatement])
|
|
16
21
|
var_decl = variable_declaration.model_copy(
|
17
22
|
update=dict(back_ref=variable_declaration.uuid)
|
18
23
|
)
|
19
|
-
var_decl.
|
24
|
+
var_decl.qmod_type = variable_declaration.qmod_type.model_copy()
|
20
25
|
if variable_declaration.name in self._current_scope:
|
21
26
|
raise ClassiqExpansionError(
|
22
27
|
f"Variable {variable_declaration.name!r} is already defined"
|
23
28
|
)
|
24
|
-
|
25
|
-
|
29
|
+
var_value: Union[QuantumSymbol, ClassicalSymbol]
|
30
|
+
if variable_declaration.is_quantum:
|
31
|
+
if TYPE_CHECKING:
|
32
|
+
assert isinstance(var_decl.qmod_type, QuantumType)
|
33
|
+
var_value = QuantumSymbol(
|
26
34
|
handle=HandleBinding(name=var_decl.name),
|
27
35
|
quantum_type=evaluate_type_in_quantum_symbol(
|
28
|
-
var_decl.
|
36
|
+
var_decl.qmod_type,
|
29
37
|
self._current_scope,
|
30
38
|
var_decl.name,
|
31
39
|
),
|
32
|
-
)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
40
|
+
)
|
41
|
+
self._builder.current_block.captured_vars.init_var(
|
42
|
+
var_decl.name, self._builder.current_function
|
43
|
+
)
|
44
|
+
else:
|
45
|
+
if TYPE_CHECKING:
|
46
|
+
assert isinstance(var_decl.qmod_type, ClassicalType)
|
47
|
+
var_value = ClassicalSymbol(
|
48
|
+
handle=HandleBinding(name=var_decl.name),
|
49
|
+
classical_type=evaluate_type_in_classical_symbol(
|
50
|
+
var_decl.qmod_type,
|
51
|
+
self._current_scope,
|
52
|
+
var_decl.name,
|
53
|
+
),
|
54
|
+
)
|
55
|
+
self._current_scope[variable_declaration.name] = Evaluated(
|
56
|
+
value=var_value, defining_function=self._builder.current_function
|
37
57
|
)
|
38
58
|
self.emit_statement(var_decl)
|
39
59
|
return True
|
@@ -21,6 +21,7 @@ from classiq.interface.generator.expressions.proxies.classical.classical_scalar_
|
|
21
21
|
from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
|
22
22
|
QmodStructInstance,
|
23
23
|
)
|
24
|
+
from classiq.interface.generator.functions.classical_type import ClassicalType
|
24
25
|
from classiq.interface.generator.functions.type_name import TypeName
|
25
26
|
from classiq.interface.helpers.text_utils import readable_list, s
|
26
27
|
from classiq.interface.model.handle_binding import (
|
@@ -202,6 +203,12 @@ class QuantumSymbolList(QuantumVariable):
|
|
202
203
|
return str(self.handles)
|
203
204
|
|
204
205
|
|
206
|
+
@dataclass(frozen=True)
|
207
|
+
class ClassicalSymbol:
|
208
|
+
handle: HandleBinding
|
209
|
+
classical_type: ClassicalType
|
210
|
+
|
211
|
+
|
205
212
|
@singledispatch
|
206
213
|
def evaluated_to_str(value: Any) -> str:
|
207
214
|
return str(value)
|
@@ -11,13 +11,13 @@ from classiq.interface.model.native_function_definition import NativeFunctionDef
|
|
11
11
|
from classiq.interface.model.port_declaration import PortDeclaration
|
12
12
|
from classiq.interface.model.quantum_function_declaration import PositionalArg
|
13
13
|
|
14
|
-
from classiq.
|
15
|
-
from classiq.model_expansions.evaluators.classical_expression import (
|
14
|
+
from classiq.evaluators.classical_expression import (
|
16
15
|
evaluate_classical_expression,
|
17
16
|
)
|
18
|
-
from classiq.
|
17
|
+
from classiq.evaluators.parameter_types import (
|
19
18
|
evaluate_type_in_quantum_symbol,
|
20
19
|
)
|
20
|
+
from classiq.model_expansions.closure import FunctionClosure, GenerativeFunctionClosure
|
21
21
|
from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
|
22
22
|
from classiq.qmod.builtins import BUILTIN_CONSTANTS
|
23
23
|
from classiq.qmod.builtins.enums import BUILTIN_ENUM_DECLARATIONS
|
@@ -77,7 +77,7 @@ class HandleRenaming:
|
|
77
77
|
SymbolRenaming = Mapping[HandleBinding, Sequence[HandleRenaming]]
|
78
78
|
|
79
79
|
|
80
|
-
def
|
80
|
+
def rewrite_expression(
|
81
81
|
symbol_mapping: SymbolRenaming, expression: Expression
|
82
82
|
) -> Expression:
|
83
83
|
normalized_expr = ExprNormalizer().visit(ast.parse(expression.expr))
|
@@ -88,7 +88,8 @@ def _rewrite_expression(
|
|
88
88
|
|
89
89
|
handle_names = {
|
90
90
|
part.source_handle: part.target_var_handle
|
91
|
-
for parts in symbol_mapping.
|
91
|
+
for source, parts in symbol_mapping.items()
|
92
|
+
if source.name in expression.expr
|
92
93
|
for part in parts
|
93
94
|
}
|
94
95
|
new_expr_str = ast.unparse(normalized_expr)
|
@@ -101,7 +102,8 @@ def _rewrite_expression(
|
|
101
102
|
for handle in sorted_handles:
|
102
103
|
new_handle = handle.collapse()
|
103
104
|
for handle_to_replace, replacement in handle_names.items():
|
104
|
-
new_handle
|
105
|
+
if new_handle.name == handle_to_replace.name:
|
106
|
+
new_handle = new_handle.replace_prefix(handle_to_replace, replacement)
|
105
107
|
new_expr_str = _replace_full_word(str(handle), str(new_handle), new_expr_str)
|
106
108
|
|
107
109
|
new_expr = Expression(expr=new_expr_str)
|
@@ -132,7 +134,7 @@ class _ReplaceSplitVarsExpressions(ModelTransformer):
|
|
132
134
|
self._symbol_mapping = symbol_mapping
|
133
135
|
|
134
136
|
def visit_Expression(self, expr: Expression) -> Expression:
|
135
|
-
return
|
137
|
+
return rewrite_expression(self._symbol_mapping, expr)
|
136
138
|
|
137
139
|
def visit_QuantumExpressionOperation(
|
138
140
|
self, op: QuantumExpressionOperation
|