classiq 0.70.0__py3-none-any.whl → 0.72.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 +0 -6
- classiq/_internals/client.py +11 -1
- classiq/applications/chemistry/chemistry_model_constructor.py +18 -16
- classiq/applications/combinatorial_helpers/optimization_model.py +9 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +6 -1
- classiq/applications/finance/__init__.py +0 -3
- classiq/applications/qsvm/__init__.py +0 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +22 -0
- classiq/interface/backend/quantum_backend_providers.py +2 -0
- classiq/interface/debug_info/debug_info.py +4 -0
- classiq/interface/generator/expressions/expression_constants.py +0 -3
- classiq/interface/generator/expressions/expression_types.py +8 -3
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +135 -0
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -0
- classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +5 -1
- classiq/interface/generator/expressions/proxies/classical/utils.py +34 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +1 -0
- classiq/interface/generator/functions/classical_type.py +1 -1
- classiq/interface/generator/functions/type_name.py +16 -0
- classiq/interface/generator/functions/type_qualifier.py +7 -0
- classiq/interface/generator/generated_circuit_data.py +14 -1
- classiq/interface/generator/hardware/hardware_data.py +3 -1
- classiq/interface/generator/quantum_function_call.py +8 -1
- classiq/interface/generator/synthesis_execution_parameter.py +1 -0
- classiq/interface/generator/transpiler_basis_gates.py +3 -1
- classiq/interface/generator/types/compilation_metadata.py +1 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/ide/visual_model.py +1 -0
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/allocate.py +7 -0
- classiq/interface/model/block.py +12 -0
- classiq/interface/model/classical_if.py +4 -0
- classiq/interface/model/handle_binding.py +21 -0
- classiq/interface/model/inplace_binary_operation.py +4 -0
- classiq/interface/model/model.py +3 -1
- classiq/interface/model/phase_operation.py +4 -0
- classiq/interface/model/port_declaration.py +3 -0
- classiq/interface/model/power.py +4 -0
- classiq/interface/model/quantum_expressions/quantum_expression.py +4 -0
- classiq/interface/model/quantum_function_call.py +4 -0
- classiq/interface/model/quantum_function_declaration.py +1 -1
- classiq/interface/model/quantum_statement.py +5 -0
- classiq/interface/model/quantum_type.py +22 -0
- classiq/interface/model/repeat.py +4 -0
- classiq/interface/model/statement_block.py +3 -0
- classiq/interface/model/variable_declaration_statement.py +5 -0
- classiq/interface/server/routes.py +0 -2
- classiq/model_expansions/atomic_expression_functions_defs.py +35 -13
- classiq/model_expansions/capturing/captured_vars.py +156 -34
- classiq/model_expansions/closure.py +0 -9
- classiq/model_expansions/evaluators/classical_type_inference.py +70 -0
- classiq/model_expansions/evaluators/parameter_types.py +20 -10
- classiq/model_expansions/expression_evaluator.py +0 -11
- classiq/model_expansions/function_builder.py +2 -8
- classiq/model_expansions/generative_functions.py +7 -30
- classiq/model_expansions/interpreters/base_interpreter.py +7 -8
- classiq/model_expansions/interpreters/generative_interpreter.py +33 -5
- classiq/model_expansions/quantum_operations/__init__.py +0 -2
- classiq/model_expansions/quantum_operations/block_evaluator.py +16 -2
- classiq/model_expansions/quantum_operations/call_emitter.py +49 -6
- classiq/model_expansions/quantum_operations/emitter.py +64 -6
- classiq/model_expansions/quantum_operations/expression_evaluator.py +4 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +1 -1
- classiq/model_expansions/quantum_operations/quantum_function_call.py +49 -0
- classiq/model_expansions/quantum_operations/repeat_block_evaluator.py +34 -0
- classiq/model_expansions/scope.py +33 -21
- classiq/model_expansions/scope_initialization.py +28 -32
- classiq/model_expansions/transformers/model_renamer.py +69 -63
- classiq/model_expansions/utils/sympy_utils.py +24 -0
- classiq/model_expansions/visitors/variable_references.py +1 -0
- classiq/qmod/__init__.py +3 -1
- classiq/qmod/builtins/functions/__init__.py +8 -0
- classiq/qmod/builtins/functions/allocation.py +36 -0
- classiq/qmod/builtins/functions/arithmetic.py +10 -5
- classiq/qmod/builtins/functions/mid_circuit_measurement.py +3 -0
- classiq/qmod/builtins/operations.py +2 -2
- classiq/qmod/declaration_inferrer.py +52 -24
- classiq/qmod/model_state_container.py +9 -0
- classiq/qmod/native/pretty_printer.py +25 -3
- classiq/qmod/pretty_print/pretty_printer.py +31 -14
- classiq/qmod/python_classical_type.py +12 -1
- classiq/qmod/qfunc.py +33 -8
- classiq/qmod/qmod_variable.py +188 -147
- classiq/qmod/quantum_function.py +3 -4
- classiq/qmod/semantics/validation/type_hints.py +19 -10
- classiq/qmod/symbolic.py +16 -3
- {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/METADATA +1 -1
- {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/RECORD +90 -91
- classiq/applications/finance/finance_model_constructor.py +0 -137
- classiq/applications/grover/__init__.py +0 -9
- classiq/applications/grover/grover_model_constructor.py +0 -167
- classiq/applications/libraries/__init__.py +0 -0
- classiq/applications/libraries/qmci_library.py +0 -22
- classiq/applications/qsvm/qsvm_model_constructor.py +0 -131
- classiq/model_expansions/quantum_operations/classicalif.py +0 -57
- classiq/model_expansions/quantum_operations/repeat.py +0 -62
- {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/WHEEL +0 -0
@@ -3,15 +3,21 @@ from collections.abc import Sequence
|
|
3
3
|
from dataclasses import dataclass, field
|
4
4
|
from typing import TYPE_CHECKING
|
5
5
|
|
6
|
+
from typing_extensions import Self
|
7
|
+
|
6
8
|
from classiq.interface.enum_utils import StrEnum
|
7
9
|
from classiq.interface.exceptions import (
|
8
10
|
ClassiqExpansionError,
|
9
11
|
ClassiqInternalExpansionError,
|
10
12
|
)
|
11
13
|
from classiq.interface.generator.expressions.expression import Expression
|
14
|
+
from classiq.interface.generator.functions.classical_type import ClassicalType
|
12
15
|
from classiq.interface.generator.functions.port_declaration import (
|
13
16
|
PortDeclarationDirection,
|
14
17
|
)
|
18
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
19
|
+
ClassicalParameterDeclaration,
|
20
|
+
)
|
15
21
|
from classiq.interface.model.handle_binding import (
|
16
22
|
HandleBinding,
|
17
23
|
NestedHandleBinding,
|
@@ -19,6 +25,7 @@ from classiq.interface.model.handle_binding import (
|
|
19
25
|
)
|
20
26
|
from classiq.interface.model.port_declaration import PortDeclaration
|
21
27
|
from classiq.interface.model.quantum_function_call import ArgValue
|
28
|
+
from classiq.interface.model.quantum_function_declaration import PositionalArg
|
22
29
|
from classiq.interface.model.quantum_type import QuantumBitvector, QuantumType
|
23
30
|
from classiq.interface.model.variable_declaration_statement import (
|
24
31
|
VariableDeclarationStatement,
|
@@ -28,7 +35,11 @@ from classiq.model_expansions.capturing.mangling_utils import (
|
|
28
35
|
demangle_handle,
|
29
36
|
mangle_captured_var_name,
|
30
37
|
)
|
31
|
-
from classiq.model_expansions.transformers.
|
38
|
+
from classiq.model_expansions.transformers.model_renamer import (
|
39
|
+
HandleRenaming,
|
40
|
+
SymbolRenaming,
|
41
|
+
)
|
42
|
+
from classiq.model_expansions.transformers.var_splitter import SymbolPart
|
32
43
|
|
33
44
|
if TYPE_CHECKING:
|
34
45
|
from classiq.model_expansions.closure import FunctionClosure
|
@@ -72,12 +83,29 @@ class PortDirection(StrEnum):
|
|
72
83
|
|
73
84
|
|
74
85
|
@dataclass(frozen=True)
|
75
|
-
class
|
86
|
+
class _Captured:
|
87
|
+
defining_function: "FunctionClosure"
|
88
|
+
is_propagated: bool
|
89
|
+
|
90
|
+
def change_defining_function(
|
91
|
+
self, new_defining_function: "FunctionClosure"
|
92
|
+
) -> Self:
|
93
|
+
return dataclasses.replace(self, defining_function=new_defining_function)
|
94
|
+
|
95
|
+
def set_propagated(self) -> Self:
|
96
|
+
return dataclasses.replace(self, is_propagated=True)
|
97
|
+
|
98
|
+
def update_propagation(self, other_captured_handle: Self) -> Self:
|
99
|
+
if self.is_propagated and not other_captured_handle.is_propagated:
|
100
|
+
return dataclasses.replace(self, is_propagated=False)
|
101
|
+
return self
|
102
|
+
|
103
|
+
|
104
|
+
@dataclass(frozen=True)
|
105
|
+
class _CapturedHandle(_Captured):
|
76
106
|
handle: HandleBinding
|
77
107
|
quantum_type: QuantumType
|
78
|
-
defining_function: "FunctionClosure"
|
79
108
|
direction: PortDirection
|
80
|
-
is_propagated: bool
|
81
109
|
|
82
110
|
@property
|
83
111
|
def mangled_name(self) -> str:
|
@@ -103,27 +131,33 @@ class _CapturedHandle:
|
|
103
131
|
def change_direction(self, new_direction: PortDirection) -> "_CapturedHandle":
|
104
132
|
return dataclasses.replace(self, direction=new_direction)
|
105
133
|
|
106
|
-
def change_defining_function(
|
107
|
-
self, new_defining_function: "FunctionClosure"
|
108
|
-
) -> "_CapturedHandle":
|
109
|
-
return dataclasses.replace(self, defining_function=new_defining_function)
|
110
|
-
|
111
|
-
def set_propagated(self) -> "_CapturedHandle":
|
112
|
-
return dataclasses.replace(self, is_propagated=True)
|
113
|
-
|
114
|
-
def update_propagation(
|
115
|
-
self, other_captured_handle: "_CapturedHandle"
|
116
|
-
) -> "_CapturedHandle":
|
117
|
-
if self.is_propagated and not other_captured_handle.is_propagated:
|
118
|
-
return dataclasses.replace(self, is_propagated=False)
|
119
|
-
return self
|
120
|
-
|
121
134
|
def set_symbol(
|
122
135
|
self, handle: HandleBinding, quantum_type: QuantumType
|
123
136
|
) -> "_CapturedHandle":
|
124
137
|
return dataclasses.replace(self, handle=handle, quantum_type=quantum_type)
|
125
138
|
|
126
139
|
|
140
|
+
@dataclass(frozen=True)
|
141
|
+
class _CapturedClassicalVar(_Captured):
|
142
|
+
name: str
|
143
|
+
classical_type: ClassicalType
|
144
|
+
defining_function: "FunctionClosure"
|
145
|
+
|
146
|
+
@property
|
147
|
+
def mangled_name(self) -> str:
|
148
|
+
return mangle_captured_var_name(
|
149
|
+
self.name,
|
150
|
+
self.defining_function.name,
|
151
|
+
self.defining_function.depth,
|
152
|
+
)
|
153
|
+
|
154
|
+
@property
|
155
|
+
def parameter_declaration(self) -> ClassicalParameterDeclaration:
|
156
|
+
return ClassicalParameterDeclaration(
|
157
|
+
name=self.mangled_name, classical_type=self.classical_type
|
158
|
+
)
|
159
|
+
|
160
|
+
|
127
161
|
HandleState = tuple[str, "FunctionClosure", bool]
|
128
162
|
|
129
163
|
|
@@ -131,6 +165,7 @@ HandleState = tuple[str, "FunctionClosure", bool]
|
|
131
165
|
class CapturedVars:
|
132
166
|
_captured_handles: list[_CapturedHandle] = field(default_factory=list)
|
133
167
|
_handle_states: list[HandleState] = field(default_factory=list)
|
168
|
+
_captured_classical_vars: list[_CapturedClassicalVar] = field(default_factory=list)
|
134
169
|
|
135
170
|
def capture_handle(
|
136
171
|
self,
|
@@ -332,16 +367,48 @@ class CapturedVars:
|
|
332
367
|
)
|
333
368
|
return merged_handle, merged_quantum_type
|
334
369
|
|
370
|
+
def capture_classical_var(
|
371
|
+
self,
|
372
|
+
var_name: str,
|
373
|
+
var_type: ClassicalType,
|
374
|
+
defining_function: "FunctionClosure",
|
375
|
+
) -> None:
|
376
|
+
self._capture_classical_var(
|
377
|
+
_CapturedClassicalVar(
|
378
|
+
name=var_name,
|
379
|
+
classical_type=var_type,
|
380
|
+
defining_function=defining_function,
|
381
|
+
is_propagated=False,
|
382
|
+
)
|
383
|
+
)
|
384
|
+
|
385
|
+
def _capture_classical_var(
|
386
|
+
self, captured_classical_var: _CapturedClassicalVar
|
387
|
+
) -> None:
|
388
|
+
for existing_captured_classical_var in self._captured_classical_vars:
|
389
|
+
if (
|
390
|
+
existing_captured_classical_var.name == captured_classical_var.name
|
391
|
+
and _same_closure(
|
392
|
+
existing_captured_classical_var.defining_function,
|
393
|
+
captured_classical_var.defining_function,
|
394
|
+
)
|
395
|
+
):
|
396
|
+
return
|
397
|
+
self._captured_classical_vars.append(captured_classical_var)
|
398
|
+
|
335
399
|
def update(self, other_captured_vars: "CapturedVars") -> None:
|
336
400
|
for captured_handle in other_captured_vars._captured_handles:
|
337
401
|
self._capture_handle(captured_handle)
|
402
|
+
for captured_classical_var in other_captured_vars._captured_classical_vars:
|
403
|
+
self._capture_classical_var(captured_classical_var)
|
338
404
|
|
339
405
|
def negate(self) -> "CapturedVars":
|
340
406
|
return CapturedVars(
|
341
407
|
_captured_handles=[
|
342
408
|
captured_handle.change_direction(captured_handle.direction.negate())
|
343
409
|
for captured_handle in self._captured_handles
|
344
|
-
]
|
410
|
+
],
|
411
|
+
_captured_classical_vars=self._captured_classical_vars,
|
345
412
|
)
|
346
413
|
|
347
414
|
def filter_vars(self, current_function: "FunctionClosure") -> "CapturedVars":
|
@@ -352,7 +419,14 @@ class CapturedVars:
|
|
352
419
|
if not _same_closure(
|
353
420
|
captured_handle.defining_function, current_function
|
354
421
|
)
|
355
|
-
]
|
422
|
+
],
|
423
|
+
_captured_classical_vars=[
|
424
|
+
captured_classical_var
|
425
|
+
for captured_classical_var in self._captured_classical_vars
|
426
|
+
if not _same_closure(
|
427
|
+
captured_classical_var.defining_function, current_function
|
428
|
+
)
|
429
|
+
],
|
356
430
|
)
|
357
431
|
|
358
432
|
def filter_var_decls(
|
@@ -367,7 +441,8 @@ class CapturedVars:
|
|
367
441
|
current_declared_vars is not None
|
368
442
|
and captured_handle.handle.name not in current_declared_vars
|
369
443
|
)
|
370
|
-
]
|
444
|
+
],
|
445
|
+
_captured_classical_vars=self._captured_classical_vars,
|
371
446
|
)
|
372
447
|
|
373
448
|
def set_propagated(self) -> "CapturedVars":
|
@@ -375,16 +450,37 @@ class CapturedVars:
|
|
375
450
|
_captured_handles=[
|
376
451
|
captured_handle.set_propagated()
|
377
452
|
for captured_handle in self._captured_handles
|
378
|
-
]
|
453
|
+
],
|
454
|
+
_captured_classical_vars=[
|
455
|
+
captured_classical_var.set_propagated()
|
456
|
+
for captured_classical_var in self._captured_classical_vars
|
457
|
+
],
|
379
458
|
)
|
380
459
|
|
381
|
-
def
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
460
|
+
def get_captured_parameters(self) -> list[PositionalArg]:
|
461
|
+
decls: list[PositionalArg]
|
462
|
+
decls = [
|
463
|
+
captured_classical_var.parameter_declaration
|
464
|
+
for captured_classical_var in self._captured_classical_vars
|
465
|
+
]
|
466
|
+
decls += [captured_handle.port for captured_handle in self._captured_handles]
|
467
|
+
return decls
|
468
|
+
|
469
|
+
def get_captured_args(self, current_function: "FunctionClosure") -> list[ArgValue]:
|
470
|
+
args: list[ArgValue]
|
471
|
+
args = [
|
472
|
+
Expression(
|
473
|
+
expr=(
|
474
|
+
captured_classical_var.name
|
475
|
+
if _same_closure(
|
476
|
+
current_function, captured_classical_var.defining_function
|
477
|
+
)
|
478
|
+
else captured_classical_var.mangled_name
|
479
|
+
)
|
480
|
+
)
|
481
|
+
for captured_classical_var in self._captured_classical_vars
|
482
|
+
]
|
483
|
+
args += [
|
388
484
|
(
|
389
485
|
captured_handle.handle
|
390
486
|
if _same_closure(current_function, captured_handle.defining_function)
|
@@ -392,9 +488,11 @@ class CapturedVars:
|
|
392
488
|
)
|
393
489
|
for captured_handle in self._captured_handles
|
394
490
|
]
|
491
|
+
return args
|
395
492
|
|
396
|
-
def get_captured_mapping(self) ->
|
397
|
-
|
493
|
+
def get_captured_mapping(self) -> SymbolRenaming:
|
494
|
+
mapping: SymbolRenaming
|
495
|
+
mapping = {
|
398
496
|
captured_handle.handle: [
|
399
497
|
SymbolPart(
|
400
498
|
source_handle=captured_handle.handle,
|
@@ -405,6 +503,17 @@ class CapturedVars:
|
|
405
503
|
for captured_handle in self._captured_handles
|
406
504
|
if not captured_handle.is_propagated
|
407
505
|
}
|
506
|
+
mapping |= {
|
507
|
+
(handle := HandleBinding(name=captured_classical_var.name)): [
|
508
|
+
HandleRenaming(
|
509
|
+
source_handle=handle,
|
510
|
+
target_var_name=captured_classical_var.mangled_name,
|
511
|
+
)
|
512
|
+
]
|
513
|
+
for captured_classical_var in self._captured_classical_vars
|
514
|
+
if not captured_classical_var.is_propagated
|
515
|
+
}
|
516
|
+
return mapping
|
408
517
|
|
409
518
|
def init_var(self, var_name: str, defining_function: "FunctionClosure") -> None:
|
410
519
|
self._handle_states.append((var_name, defining_function, False))
|
@@ -470,6 +579,7 @@ class CapturedVars:
|
|
470
579
|
return CapturedVars(
|
471
580
|
_captured_handles=list(self._captured_handles),
|
472
581
|
_handle_states=list(self._handle_states),
|
582
|
+
_captured_classical_vars=list(self._captured_classical_vars),
|
473
583
|
)
|
474
584
|
|
475
585
|
def set(
|
@@ -492,6 +602,14 @@ class CapturedVars:
|
|
492
602
|
self._handle_states.append((var, target_func, state))
|
493
603
|
else:
|
494
604
|
self._handle_states.append((var, defining_function, state))
|
605
|
+
self._captured_classical_vars = []
|
606
|
+
for captured_classical_var in other._captured_classical_vars:
|
607
|
+
if _same_closure(captured_classical_var.defining_function, source_func):
|
608
|
+
self._captured_classical_vars.append(
|
609
|
+
captured_classical_var.change_defining_function(target_func)
|
610
|
+
)
|
611
|
+
else:
|
612
|
+
self._captured_classical_vars.append(captured_classical_var)
|
495
613
|
|
496
614
|
|
497
615
|
def _same_closure(closure_1: "FunctionClosure", closure_2: "FunctionClosure") -> bool:
|
@@ -499,11 +617,15 @@ def _same_closure(closure_1: "FunctionClosure", closure_2: "FunctionClosure") ->
|
|
499
617
|
|
500
618
|
|
501
619
|
def validate_args_are_not_propagated(
|
502
|
-
args: Sequence[ArgValue], captured_vars: Sequence[
|
620
|
+
args: Sequence[ArgValue], captured_vars: Sequence[ArgValue]
|
503
621
|
) -> None:
|
504
622
|
if not captured_vars:
|
505
623
|
return
|
506
|
-
captured_handles = {
|
624
|
+
captured_handles = {
|
625
|
+
demangle_handle(handle)
|
626
|
+
for handle in captured_vars
|
627
|
+
if isinstance(handle, HandleBinding)
|
628
|
+
}
|
507
629
|
arg_handles = {
|
508
630
|
demangle_handle(arg) for arg in args if isinstance(arg, HandleBinding)
|
509
631
|
}
|
@@ -8,7 +8,6 @@ from typing import Any, Optional
|
|
8
8
|
from typing_extensions import Self
|
9
9
|
|
10
10
|
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
11
|
-
from classiq.interface.model.port_declaration import PortDeclaration
|
12
11
|
from classiq.interface.model.quantum_function_declaration import (
|
13
12
|
NamedParamsQuantumFunctionDeclaration,
|
14
13
|
PositionalArg,
|
@@ -35,14 +34,6 @@ class Closure:
|
|
35
34
|
positional_arg_declarations: Sequence[PositionalArg] = tuple()
|
36
35
|
captured_vars: CapturedVars = field(default_factory=CapturedVars)
|
37
36
|
|
38
|
-
@property
|
39
|
-
def port_declarations(self) -> dict[str, PortDeclaration]:
|
40
|
-
return {
|
41
|
-
param.name: param
|
42
|
-
for param in self.positional_arg_declarations
|
43
|
-
if isinstance(param, PortDeclaration)
|
44
|
-
}
|
45
|
-
|
46
37
|
|
47
38
|
@dataclass(frozen=True)
|
48
39
|
class GenerativeClosure(Closure):
|
@@ -0,0 +1,70 @@
|
|
1
|
+
from typing import Any, Union
|
2
|
+
|
3
|
+
from classiq.interface.exceptions import ClassiqExpansionError
|
4
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_array_proxy import (
|
5
|
+
ClassicalArrayProxy,
|
6
|
+
)
|
7
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_struct_proxy import (
|
8
|
+
ClassicalStructProxy,
|
9
|
+
)
|
10
|
+
from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
|
11
|
+
QmodStructInstance,
|
12
|
+
)
|
13
|
+
from classiq.interface.generator.functions.classical_type import (
|
14
|
+
ClassicalArray,
|
15
|
+
ClassicalList,
|
16
|
+
ClassicalType,
|
17
|
+
)
|
18
|
+
from classiq.interface.generator.functions.type_name import TypeName
|
19
|
+
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
20
|
+
|
21
|
+
|
22
|
+
def infer_classical_type(val: Any, classical_type: ClassicalType) -> ClassicalType:
|
23
|
+
if isinstance(classical_type, TypeName):
|
24
|
+
return _infer_classical_struct_type(val, classical_type)
|
25
|
+
if isinstance(classical_type, (ClassicalArray, ClassicalList)):
|
26
|
+
return _infer_classical_array_type(val, classical_type)
|
27
|
+
return classical_type
|
28
|
+
|
29
|
+
|
30
|
+
def _infer_classical_struct_type(val: Any, classical_type: TypeName) -> ClassicalType:
|
31
|
+
if not isinstance(val, (QmodStructInstance, ClassicalStructProxy)):
|
32
|
+
return classical_type
|
33
|
+
decl = val.struct_declaration
|
34
|
+
new_fields = {
|
35
|
+
field_name: infer_classical_type(field_val, field_type)
|
36
|
+
for (field_name, field_val), field_type in zip(
|
37
|
+
val.fields.items(),
|
38
|
+
decl.variables.values(),
|
39
|
+
strict=True,
|
40
|
+
)
|
41
|
+
}
|
42
|
+
new_classical_type = TypeName(name=decl.name)
|
43
|
+
new_classical_type.set_classical_struct_decl(
|
44
|
+
StructDeclaration(name=decl.name, variables=new_fields)
|
45
|
+
)
|
46
|
+
return new_classical_type
|
47
|
+
|
48
|
+
|
49
|
+
def _infer_classical_array_type(
|
50
|
+
val: Any, classical_type: Union[ClassicalArray, ClassicalList]
|
51
|
+
) -> ClassicalType:
|
52
|
+
if isinstance(val, list):
|
53
|
+
val_length = len(val)
|
54
|
+
elif isinstance(val, ClassicalArrayProxy):
|
55
|
+
val_length = val.length
|
56
|
+
else:
|
57
|
+
raise ClassiqExpansionError(f"Array expected, got {str(val)!r}")
|
58
|
+
if isinstance(classical_type, ClassicalArray) and val_length != classical_type.size:
|
59
|
+
raise ClassiqExpansionError(
|
60
|
+
f"Type mismatch: Argument has {val_length} items but "
|
61
|
+
f"{classical_type.size} expected"
|
62
|
+
)
|
63
|
+
return ClassicalArray(
|
64
|
+
element_type=(
|
65
|
+
infer_classical_type(val[0], classical_type.element_type)
|
66
|
+
if val_length > 0
|
67
|
+
else classical_type.element_type
|
68
|
+
),
|
69
|
+
size=val_length,
|
70
|
+
)
|
@@ -12,6 +12,9 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
12
12
|
from classiq.interface.generator.functions.type_name import (
|
13
13
|
TypeName,
|
14
14
|
)
|
15
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
16
|
+
ClassicalParameterDeclaration,
|
17
|
+
)
|
15
18
|
from classiq.interface.model.port_declaration import PortDeclaration
|
16
19
|
from classiq.interface.model.quantum_function_declaration import (
|
17
20
|
PositionalArg,
|
@@ -29,6 +32,9 @@ from classiq.model_expansions.evaluators.arg_type_match import check_type_match
|
|
29
32
|
from classiq.model_expansions.evaluators.classical_expression import (
|
30
33
|
evaluate_classical_expression,
|
31
34
|
)
|
35
|
+
from classiq.model_expansions.evaluators.classical_type_inference import (
|
36
|
+
infer_classical_type,
|
37
|
+
)
|
32
38
|
from classiq.model_expansions.evaluators.quantum_type_utils import (
|
33
39
|
copy_type_information,
|
34
40
|
set_element_type,
|
@@ -73,11 +79,6 @@ def _update_scope(
|
|
73
79
|
if parameter.direction is PortDeclarationDirection.Output:
|
74
80
|
return
|
75
81
|
quantum_symbol = argument.as_type(QuantumSymbol)
|
76
|
-
if not quantum_symbol.quantum_type.has_size_in_bits:
|
77
|
-
raise ClassiqExpansionError(
|
78
|
-
f"Argument {str(quantum_symbol.emit())!r} to function {closure.name!r} "
|
79
|
-
f"is not initialized"
|
80
|
-
)
|
81
82
|
casted_argument = _cast(
|
82
83
|
parameter.quantum_type,
|
83
84
|
quantum_symbol,
|
@@ -126,6 +127,14 @@ def _cast(
|
|
126
127
|
def _evaluate_type_from_arg(
|
127
128
|
parameter: PositionalArg, argument: Evaluated, inner_scope: Scope
|
128
129
|
) -> PositionalArg:
|
130
|
+
if isinstance(parameter, ClassicalParameterDeclaration):
|
131
|
+
return ClassicalParameterDeclaration(
|
132
|
+
name=parameter.name,
|
133
|
+
classical_type=infer_classical_type(
|
134
|
+
argument.value, parameter.classical_type
|
135
|
+
),
|
136
|
+
)
|
137
|
+
|
129
138
|
if not isinstance(parameter, PortDeclaration):
|
130
139
|
return parameter
|
131
140
|
|
@@ -260,9 +269,10 @@ def evaluate_types_in_quantum_symbols(
|
|
260
269
|
def _inject_quantum_arg_info_to_type(
|
261
270
|
parameter_type: QuantumType, quantum_symbol: QuantumSymbol, param_name: str
|
262
271
|
) -> QuantumType:
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
272
|
+
if quantum_symbol.quantum_type.has_size_in_bits:
|
273
|
+
copy_type_information(
|
274
|
+
quantum_symbol.quantum_type,
|
275
|
+
parameter_type,
|
276
|
+
param_name,
|
277
|
+
)
|
268
278
|
return parameter_type
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import ast
|
2
|
-
import re
|
3
2
|
from collections.abc import Mapping
|
4
3
|
from enum import EnumMeta
|
5
4
|
from typing import Any, Optional
|
@@ -12,9 +11,6 @@ from classiq.interface.generator.expressions.evaluated_expression import (
|
|
12
11
|
EvaluatedExpression,
|
13
12
|
)
|
14
13
|
from classiq.interface.generator.expressions.expression import Expression
|
15
|
-
from classiq.interface.generator.expressions.expression_constants import (
|
16
|
-
CPARAM_EXECUTION_SUFFIX_PATTERN,
|
17
|
-
)
|
18
14
|
from classiq.interface.generator.expressions.expression_types import ExpressionValue
|
19
15
|
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
20
16
|
from classiq.interface.generator.expressions.proxies.quantum.qmod_sized_proxy import (
|
@@ -115,13 +111,6 @@ def _validate_undefined_vars(
|
|
115
111
|
- uninitialized_locals
|
116
112
|
)
|
117
113
|
|
118
|
-
# Ignore expanded execution parameters
|
119
|
-
undefined_vars = {
|
120
|
-
var
|
121
|
-
for var in undefined_vars
|
122
|
-
if not re.search(CPARAM_EXECUTION_SUFFIX_PATTERN, var)
|
123
|
-
}
|
124
|
-
|
125
114
|
if len(undefined_vars) == 1:
|
126
115
|
undefined_var = undefined_vars.__iter__().__next__()
|
127
116
|
raise ClassiqExpansionError(f"Variable {undefined_var!r} is undefined")
|
@@ -15,7 +15,6 @@ from classiq.interface.model.model import MAIN_FUNCTION_NAME
|
|
15
15
|
from classiq.interface.model.native_function_definition import (
|
16
16
|
NativeFunctionDefinition,
|
17
17
|
)
|
18
|
-
from classiq.interface.model.port_declaration import PortDeclaration
|
19
18
|
from classiq.interface.model.quantum_function_declaration import (
|
20
19
|
PositionalArg,
|
21
20
|
)
|
@@ -210,19 +209,14 @@ class OperationBuilder:
|
|
210
209
|
self._current_source_ref = previous_source_ref
|
211
210
|
|
212
211
|
def create_definition(
|
213
|
-
self, function_context: FunctionContext
|
212
|
+
self, function_context: FunctionContext, params: Sequence[PositionalArg]
|
214
213
|
) -> NativeFunctionDefinition:
|
215
214
|
name = self._get_expanded_function_name(function_context)
|
216
|
-
new_parameters: list[PortDeclaration] = [
|
217
|
-
param
|
218
|
-
for param in function_context.positional_arg_declarations
|
219
|
-
if isinstance(param, PortDeclaration)
|
220
|
-
]
|
221
215
|
|
222
216
|
return NativeFunctionDefinition(
|
223
217
|
name=name,
|
224
218
|
body=function_context.body,
|
225
|
-
positional_arg_declarations=
|
219
|
+
positional_arg_declarations=params,
|
226
220
|
)
|
227
221
|
|
228
222
|
def _get_expanded_function_name(self, function_context: FunctionContext) -> str:
|
@@ -5,25 +5,17 @@ from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
6
6
|
from classiq.interface.exceptions import (
|
7
7
|
ClassiqExpansionError,
|
8
|
-
ClassiqInternalExpansionError,
|
9
|
-
)
|
10
|
-
from classiq.interface.generator.expressions.proxies.classical.classical_array_proxy import (
|
11
|
-
ClassicalArrayProxy,
|
12
8
|
)
|
13
9
|
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
14
10
|
ClassicalProxy,
|
15
11
|
)
|
16
|
-
from classiq.interface.generator.expressions.proxies.classical.classical_scalar_proxy import (
|
17
|
-
ClassicalScalarProxy,
|
18
|
-
)
|
19
|
-
from classiq.interface.generator.expressions.proxies.classical.classical_struct_proxy import (
|
20
|
-
ClassicalStructProxy,
|
21
|
-
)
|
22
12
|
from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
|
23
13
|
QmodStructInstance,
|
24
14
|
)
|
25
|
-
from classiq.interface.generator.
|
26
|
-
|
15
|
+
from classiq.interface.generator.expressions.proxies.classical.utils import (
|
16
|
+
get_proxy_type,
|
17
|
+
)
|
18
|
+
from classiq.interface.generator.functions.type_name import Struct
|
27
19
|
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
28
20
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
29
21
|
from classiq.interface.model.port_declaration import PortDeclaration
|
@@ -39,7 +31,6 @@ from classiq.model_expansions.closure import (
|
|
39
31
|
GenerativeClosure,
|
40
32
|
)
|
41
33
|
from classiq.model_expansions.scope import Evaluated, QuantumSymbol
|
42
|
-
from classiq.qmod.cparam import CParam
|
43
34
|
from classiq.qmod.generative import generative_mode_context, set_frontend_interpreter
|
44
35
|
from classiq.qmod.model_state_container import QMODULE
|
45
36
|
from classiq.qmod.qmod_parameter import CParamStruct, create_param
|
@@ -94,22 +85,6 @@ class LenList(list):
|
|
94
85
|
return LenList([cls.wrap(item) for item in obj])
|
95
86
|
|
96
87
|
|
97
|
-
def _create_qmod_classical_var(proxy: ClassicalProxy) -> CParam:
|
98
|
-
if isinstance(proxy, ClassicalScalarProxy):
|
99
|
-
classical_type = proxy._classical_type
|
100
|
-
elif isinstance(proxy, ClassicalArrayProxy):
|
101
|
-
classical_type = ClassicalArray(
|
102
|
-
element_type=proxy._element_type, size=proxy._length
|
103
|
-
)
|
104
|
-
elif isinstance(proxy, ClassicalStructProxy):
|
105
|
-
classical_type = TypeName(name=proxy._decl.name)
|
106
|
-
else:
|
107
|
-
raise ClassiqInternalExpansionError(
|
108
|
-
f"Unrecognized classical proxy {type(proxy).__name__}"
|
109
|
-
)
|
110
|
-
return create_param(str(proxy.handle), classical_type, QMODULE)
|
111
|
-
|
112
|
-
|
113
88
|
def translate_ast_arg_to_python_qmod(param: PositionalArg, evaluated: Evaluated) -> Any:
|
114
89
|
if isinstance(param, PortDeclaration):
|
115
90
|
quantum_symbol = evaluated.as_type(QuantumSymbol)
|
@@ -147,7 +122,9 @@ def translate_ast_arg_to_python_qmod(param: PositionalArg, evaluated: Evaluated)
|
|
147
122
|
qmodule=QMODULE,
|
148
123
|
)
|
149
124
|
if isinstance(classical_value, ClassicalProxy):
|
150
|
-
return
|
125
|
+
return create_param(
|
126
|
+
str(classical_value.handle), get_proxy_type(classical_value), QMODULE
|
127
|
+
)
|
151
128
|
|
152
129
|
return LenList.wrap(classical_value)
|
153
130
|
|
@@ -52,7 +52,6 @@ from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
|
|
52
52
|
from classiq.model_expansions.scope_initialization import (
|
53
53
|
add_entry_point_params_to_scope,
|
54
54
|
init_builtin_types,
|
55
|
-
init_exec_params,
|
56
55
|
init_top_level_scope,
|
57
56
|
)
|
58
57
|
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
@@ -77,7 +76,6 @@ class BaseInterpreter:
|
|
77
76
|
|
78
77
|
init_builtin_types()
|
79
78
|
init_top_level_scope(model, self._top_level_scope)
|
80
|
-
self._exec_params = init_exec_params(model, self._top_level_scope)
|
81
79
|
self._functions_compilation_metadata: dict[str, CompilationMetadata] = dict(
|
82
80
|
self._model.functions_compilation_metadata
|
83
81
|
)
|
@@ -96,7 +94,9 @@ class BaseInterpreter:
|
|
96
94
|
)
|
97
95
|
context = self._expand_operation(main_closure)
|
98
96
|
self._expanded_functions[main_closure.closure_id] = (
|
99
|
-
self._builder.create_definition(
|
97
|
+
self._builder.create_definition(
|
98
|
+
cast(FunctionContext, context), main_closure.positional_arg_declarations
|
99
|
+
)
|
100
100
|
)
|
101
101
|
|
102
102
|
def _get_main_closure(self, main_func: FunctionClosure) -> FunctionClosure:
|
@@ -139,7 +139,6 @@ class BaseInterpreter:
|
|
139
139
|
qstructs=list(QMODULE.qstruct_decls.values()),
|
140
140
|
debug_info=self._model.debug_info,
|
141
141
|
functions_compilation_metadata=self._expanded_functions_compilation_metadata,
|
142
|
-
execution_parameters=self._exec_params,
|
143
142
|
)
|
144
143
|
|
145
144
|
def process_exception(self, e: Exception) -> None:
|
@@ -159,7 +158,7 @@ class BaseInterpreter:
|
|
159
158
|
expr = evaluate_classical_expression(expression, self._builder.current_scope)
|
160
159
|
if not isinstance(expr.value, sympy.Basic):
|
161
160
|
return expr
|
162
|
-
vrc = VarRefCollector(ignore_duplicated_handles=True)
|
161
|
+
vrc = VarRefCollector(ignore_duplicated_handles=True, unevaluated=True)
|
163
162
|
vrc.visit(ast.parse(str(expr.value)))
|
164
163
|
for handle in vrc.var_handles:
|
165
164
|
if handle.name in self._builder.current_scope and isinstance(
|
@@ -190,8 +189,8 @@ class BaseInterpreter:
|
|
190
189
|
quantum_variable = self.evaluate(sliced_handle_binding.base_handle).as_type(
|
191
190
|
QuantumSymbol
|
192
191
|
)
|
193
|
-
start = self.evaluate(sliced_handle_binding.start).
|
194
|
-
end = self.evaluate(sliced_handle_binding.end).
|
192
|
+
start = self.evaluate(sliced_handle_binding.start).value
|
193
|
+
end = self.evaluate(sliced_handle_binding.end).value
|
195
194
|
return Evaluated(value=quantum_variable[start:end])
|
196
195
|
|
197
196
|
@evaluate.register
|
@@ -201,7 +200,7 @@ class BaseInterpreter:
|
|
201
200
|
@evaluate.register
|
202
201
|
def evaluate_subscript_handle(self, subscript: SubscriptHandleBinding) -> Evaluated:
|
203
202
|
base_value = self.evaluate(subscript.base_handle)
|
204
|
-
index_value = self.evaluate(subscript.index).
|
203
|
+
index_value = self.evaluate(subscript.index).value
|
205
204
|
return Evaluated(value=base_value.value[index_value])
|
206
205
|
|
207
206
|
@evaluate.register
|