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.
Files changed (98) hide show
  1. classiq/__init__.py +0 -6
  2. classiq/_internals/client.py +11 -1
  3. classiq/applications/chemistry/chemistry_model_constructor.py +18 -16
  4. classiq/applications/combinatorial_helpers/optimization_model.py +9 -2
  5. classiq/applications/combinatorial_helpers/pyomo_utils.py +6 -1
  6. classiq/applications/finance/__init__.py +0 -3
  7. classiq/applications/qsvm/__init__.py +0 -2
  8. classiq/interface/_version.py +1 -1
  9. classiq/interface/backend/backend_preferences.py +22 -0
  10. classiq/interface/backend/quantum_backend_providers.py +2 -0
  11. classiq/interface/debug_info/debug_info.py +4 -0
  12. classiq/interface/generator/expressions/expression_constants.py +0 -3
  13. classiq/interface/generator/expressions/expression_types.py +8 -3
  14. classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +135 -0
  15. classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -0
  16. classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +5 -1
  17. classiq/interface/generator/expressions/proxies/classical/utils.py +34 -0
  18. classiq/interface/generator/functions/builtins/internal_operators.py +1 -0
  19. classiq/interface/generator/functions/classical_type.py +1 -1
  20. classiq/interface/generator/functions/type_name.py +16 -0
  21. classiq/interface/generator/functions/type_qualifier.py +7 -0
  22. classiq/interface/generator/generated_circuit_data.py +14 -1
  23. classiq/interface/generator/hardware/hardware_data.py +3 -1
  24. classiq/interface/generator/quantum_function_call.py +8 -1
  25. classiq/interface/generator/synthesis_execution_parameter.py +1 -0
  26. classiq/interface/generator/transpiler_basis_gates.py +3 -1
  27. classiq/interface/generator/types/compilation_metadata.py +1 -0
  28. classiq/interface/hardware.py +1 -0
  29. classiq/interface/ide/visual_model.py +1 -0
  30. classiq/interface/interface_version.py +1 -1
  31. classiq/interface/model/allocate.py +7 -0
  32. classiq/interface/model/block.py +12 -0
  33. classiq/interface/model/classical_if.py +4 -0
  34. classiq/interface/model/handle_binding.py +21 -0
  35. classiq/interface/model/inplace_binary_operation.py +4 -0
  36. classiq/interface/model/model.py +3 -1
  37. classiq/interface/model/phase_operation.py +4 -0
  38. classiq/interface/model/port_declaration.py +3 -0
  39. classiq/interface/model/power.py +4 -0
  40. classiq/interface/model/quantum_expressions/quantum_expression.py +4 -0
  41. classiq/interface/model/quantum_function_call.py +4 -0
  42. classiq/interface/model/quantum_function_declaration.py +1 -1
  43. classiq/interface/model/quantum_statement.py +5 -0
  44. classiq/interface/model/quantum_type.py +22 -0
  45. classiq/interface/model/repeat.py +4 -0
  46. classiq/interface/model/statement_block.py +3 -0
  47. classiq/interface/model/variable_declaration_statement.py +5 -0
  48. classiq/interface/server/routes.py +0 -2
  49. classiq/model_expansions/atomic_expression_functions_defs.py +35 -13
  50. classiq/model_expansions/capturing/captured_vars.py +156 -34
  51. classiq/model_expansions/closure.py +0 -9
  52. classiq/model_expansions/evaluators/classical_type_inference.py +70 -0
  53. classiq/model_expansions/evaluators/parameter_types.py +20 -10
  54. classiq/model_expansions/expression_evaluator.py +0 -11
  55. classiq/model_expansions/function_builder.py +2 -8
  56. classiq/model_expansions/generative_functions.py +7 -30
  57. classiq/model_expansions/interpreters/base_interpreter.py +7 -8
  58. classiq/model_expansions/interpreters/generative_interpreter.py +33 -5
  59. classiq/model_expansions/quantum_operations/__init__.py +0 -2
  60. classiq/model_expansions/quantum_operations/block_evaluator.py +16 -2
  61. classiq/model_expansions/quantum_operations/call_emitter.py +49 -6
  62. classiq/model_expansions/quantum_operations/emitter.py +64 -6
  63. classiq/model_expansions/quantum_operations/expression_evaluator.py +4 -0
  64. classiq/model_expansions/quantum_operations/handle_evaluator.py +1 -1
  65. classiq/model_expansions/quantum_operations/quantum_function_call.py +49 -0
  66. classiq/model_expansions/quantum_operations/repeat_block_evaluator.py +34 -0
  67. classiq/model_expansions/scope.py +33 -21
  68. classiq/model_expansions/scope_initialization.py +28 -32
  69. classiq/model_expansions/transformers/model_renamer.py +69 -63
  70. classiq/model_expansions/utils/sympy_utils.py +24 -0
  71. classiq/model_expansions/visitors/variable_references.py +1 -0
  72. classiq/qmod/__init__.py +3 -1
  73. classiq/qmod/builtins/functions/__init__.py +8 -0
  74. classiq/qmod/builtins/functions/allocation.py +36 -0
  75. classiq/qmod/builtins/functions/arithmetic.py +10 -5
  76. classiq/qmod/builtins/functions/mid_circuit_measurement.py +3 -0
  77. classiq/qmod/builtins/operations.py +2 -2
  78. classiq/qmod/declaration_inferrer.py +52 -24
  79. classiq/qmod/model_state_container.py +9 -0
  80. classiq/qmod/native/pretty_printer.py +25 -3
  81. classiq/qmod/pretty_print/pretty_printer.py +31 -14
  82. classiq/qmod/python_classical_type.py +12 -1
  83. classiq/qmod/qfunc.py +33 -8
  84. classiq/qmod/qmod_variable.py +188 -147
  85. classiq/qmod/quantum_function.py +3 -4
  86. classiq/qmod/semantics/validation/type_hints.py +19 -10
  87. classiq/qmod/symbolic.py +16 -3
  88. {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/METADATA +1 -1
  89. {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/RECORD +90 -91
  90. classiq/applications/finance/finance_model_constructor.py +0 -137
  91. classiq/applications/grover/__init__.py +0 -9
  92. classiq/applications/grover/grover_model_constructor.py +0 -167
  93. classiq/applications/libraries/__init__.py +0 -0
  94. classiq/applications/libraries/qmci_library.py +0 -22
  95. classiq/applications/qsvm/qsvm_model_constructor.py +0 -131
  96. classiq/model_expansions/quantum_operations/classicalif.py +0 -57
  97. classiq/model_expansions/quantum_operations/repeat.py +0 -62
  98. {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.var_splitter import SymbolPart, SymbolParts
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 _CapturedHandle:
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 get_captured_ports(self) -> list[PortDeclaration]:
382
- return [captured_handle.port for captured_handle in self._captured_handles]
383
-
384
- def get_captured_args(
385
- self, current_function: "FunctionClosure"
386
- ) -> list[HandleBinding]:
387
- return [
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) -> SymbolParts:
397
- return {
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[HandleBinding]
620
+ args: Sequence[ArgValue], captured_vars: Sequence[ArgValue]
503
621
  ) -> None:
504
622
  if not captured_vars:
505
623
  return
506
- captured_handles = {demangle_handle(handle) for handle in captured_vars}
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
- copy_type_information(
264
- quantum_symbol.quantum_type,
265
- parameter_type,
266
- param_name,
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=new_parameters,
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.functions.classical_type import ClassicalArray
26
- from classiq.interface.generator.functions.type_name import Struct, TypeName
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 _create_qmod_classical_var(classical_value)
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(cast(FunctionContext, context))
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).as_type(int)
194
- end = self.evaluate(sliced_handle_binding.end).as_type(int)
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).as_type(int)
203
+ index_value = self.evaluate(subscript.index).value
205
204
  return Evaluated(value=base_value.value[index_value])
206
205
 
207
206
  @evaluate.register