classiq 0.89.0__py3-none-any.whl → 0.91.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.

Potentially problematic release.


This version of classiq might be problematic. Click here for more details.

Files changed (108) hide show
  1. classiq/__init__.py +1 -0
  2. classiq/_internals/api_wrapper.py +16 -32
  3. classiq/analyzer/show_interactive_hack.py +26 -1
  4. classiq/applications/chemistry/chemistry_model_constructor.py +14 -2
  5. classiq/applications/combinatorial_helpers/pyomo_utils.py +9 -6
  6. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
  7. classiq/applications/combinatorial_optimization/combinatorial_problem.py +16 -8
  8. classiq/evaluators/classical_expression.py +63 -41
  9. classiq/evaluators/control.py +31 -52
  10. classiq/evaluators/expression_evaluator.py +31 -127
  11. classiq/evaluators/parameter_types.py +200 -104
  12. classiq/evaluators/qmod_annotated_expression.py +3 -1
  13. classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +10 -3
  14. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +12 -37
  15. classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +8 -17
  16. classiq/evaluators/qmod_node_evaluators/measurement_evaluation.py +1 -1
  17. classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +7 -1
  18. classiq/evaluators/qmod_node_evaluators/name_evaluation.py +0 -1
  19. classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +9 -1
  20. classiq/evaluators/qmod_node_evaluators/utils.py +33 -8
  21. classiq/evaluators/qmod_type_inference/classical_type_inference.py +4 -7
  22. classiq/interface/_version.py +1 -1
  23. classiq/interface/analyzer/analysis_params.py +1 -25
  24. classiq/interface/analyzer/result.py +4 -0
  25. classiq/interface/chemistry/ground_state_problem.py +16 -2
  26. classiq/interface/executor/optimizer_preferences.py +0 -112
  27. classiq/interface/executor/result.py +22 -3
  28. classiq/interface/generator/application_apis/chemistry_declarations.py +3 -1
  29. classiq/interface/generator/arith/arithmetic_expression_validator.py +2 -7
  30. classiq/interface/generator/expressions/evaluated_expression.py +3 -13
  31. classiq/interface/generator/expressions/expression_types.py +10 -22
  32. classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +3 -8
  33. classiq/interface/generator/expressions/proxies/classical/classical_proxy.py +2 -2
  34. classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +1 -2
  35. classiq/interface/generator/functions/classical_type.py +2 -5
  36. classiq/interface/generator/functions/concrete_types.py +1 -1
  37. classiq/interface/generator/functions/type_name.py +0 -12
  38. classiq/interface/generator/generated_circuit_data.py +4 -0
  39. classiq/interface/generator/preferences/qasm_to_qmod_params.py +14 -0
  40. classiq/interface/helpers/model_normalizer.py +0 -6
  41. classiq/interface/ide/visual_model.py +1 -0
  42. classiq/interface/model/handle_binding.py +1 -1
  43. classiq/interface/model/port_declaration.py +2 -1
  44. classiq/interface/model/quantum_expressions/arithmetic_operation.py +16 -12
  45. classiq/interface/model/quantum_type.py +1 -40
  46. classiq/interface/server/routes.py +2 -3
  47. classiq/model_expansions/capturing/captured_vars.py +10 -3
  48. classiq/model_expansions/closure.py +8 -0
  49. classiq/model_expansions/function_builder.py +18 -2
  50. classiq/model_expansions/interpreters/base_interpreter.py +84 -22
  51. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +1 -11
  52. classiq/model_expansions/interpreters/generative_interpreter.py +67 -20
  53. classiq/model_expansions/quantum_operations/allocate.py +92 -21
  54. classiq/model_expansions/quantum_operations/assignment_result_processor.py +28 -27
  55. classiq/model_expansions/quantum_operations/call_emitter.py +32 -26
  56. classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -2
  57. classiq/model_expansions/quantum_operations/emitter.py +50 -70
  58. classiq/model_expansions/quantum_operations/expression_evaluator.py +62 -7
  59. classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -5
  60. classiq/model_expansions/quantum_operations/variable_decleration.py +16 -11
  61. classiq/model_expansions/scope.py +39 -41
  62. classiq/model_expansions/scope_initialization.py +3 -6
  63. classiq/model_expansions/transformers/model_renamer.py +35 -64
  64. classiq/model_expansions/transformers/type_modifier_inference.py +6 -6
  65. classiq/model_expansions/utils/handles_collector.py +7 -0
  66. classiq/model_expansions/visitors/boolean_expression_transformers.py +7 -31
  67. classiq/model_expansions/visitors/symbolic_param_inference.py +9 -3
  68. classiq/open_library/functions/state_preparation.py +3 -3
  69. classiq/qmod/builtins/functions/allocation.py +8 -8
  70. classiq/qmod/builtins/functions/arithmetic.py +1 -1
  71. classiq/qmod/builtins/functions/chemistry.py +64 -0
  72. classiq/qmod/builtins/functions/exponentiation.py +7 -13
  73. classiq/qmod/builtins/functions/qsvm.py +1 -1
  74. classiq/qmod/builtins/operations.py +42 -10
  75. classiq/qmod/generative.py +2 -4
  76. classiq/qmod/native/pretty_printer.py +1 -1
  77. classiq/qmod/pretty_print/pretty_printer.py +1 -1
  78. classiq/qmod/qmod_constant.py +1 -1
  79. classiq/qmod/qmod_parameter.py +2 -2
  80. classiq/qmod/qmod_variable.py +18 -19
  81. classiq/qmod/quantum_expandable.py +1 -1
  82. classiq/qmod/semantics/error_manager.py +34 -15
  83. classiq/qmod/symbolic.py +15 -4
  84. classiq/qmod/utilities.py +4 -1
  85. classiq/synthesis.py +38 -3
  86. classiq/visualization.py +1 -1
  87. {classiq-0.89.0.dist-info → classiq-0.91.0.dist-info}/METADATA +1 -1
  88. {classiq-0.89.0.dist-info → classiq-0.91.0.dist-info}/RECORD +89 -107
  89. classiq/evaluators/arg_type_match.py +0 -168
  90. classiq/evaluators/classical_type_inference.py +0 -121
  91. classiq/interface/combinatorial_optimization/optimization_problem.py +0 -17
  92. classiq/interface/combinatorial_optimization/result.py +0 -9
  93. classiq/interface/generator/expressions/handle_identifier.py +0 -6
  94. classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -41
  95. classiq/interface/generator/expressions/proxies/quantum/__init__.py +0 -0
  96. classiq/interface/generator/expressions/proxies/quantum/qmod_qarray_proxy.py +0 -80
  97. classiq/interface/generator/expressions/proxies/quantum/qmod_qscalar_proxy.py +0 -77
  98. classiq/interface/generator/expressions/proxies/quantum/qmod_qstruct_proxy.py +0 -38
  99. classiq/interface/generator/expressions/proxies/quantum/qmod_sized_proxy.py +0 -39
  100. classiq/interface/generator/expressions/type_proxy.py +0 -10
  101. classiq/model_expansions/atomic_expression_functions_defs.py +0 -413
  102. classiq/model_expansions/model_tables.py +0 -18
  103. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  104. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +0 -181
  105. classiq/model_expansions/sympy_conversion/sympy_to_python.py +0 -132
  106. classiq/model_expansions/transformers/ast_renamer.py +0 -26
  107. classiq/model_expansions/utils/sympy_utils.py +0 -24
  108. {classiq-0.89.0.dist-info → classiq-0.91.0.dist-info}/WHEEL +0 -0
@@ -1,35 +1,23 @@
1
- from typing import Union
1
+ from enum import IntEnum
2
+ from typing import TYPE_CHECKING, Union
2
3
 
3
- from sympy import Basic
4
- from sympy.logic.boolalg import Boolean
4
+ import sympy
5
5
 
6
- from classiq.interface.generator.expressions.handle_identifier import HandleIdentifier
7
- from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
8
- AnyClassicalValue,
9
- )
10
- from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
11
- ClassicalProxy,
12
- )
13
6
  from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
14
7
  QmodStructInstance,
15
8
  )
16
- from classiq.interface.generator.expressions.proxies.quantum.qmod_sized_proxy import (
17
- QmodSizedProxy,
18
- )
19
- from classiq.interface.generator.expressions.type_proxy import TypeProxy
9
+
10
+ if TYPE_CHECKING:
11
+ from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
20
12
 
21
13
  RuntimeConstant = Union[
22
14
  int,
23
15
  float,
24
16
  list,
25
17
  bool,
18
+ complex,
19
+ IntEnum,
26
20
  QmodStructInstance,
27
- TypeProxy,
28
- HandleIdentifier,
29
- ]
30
- Proxies = Union[
31
- QmodSizedProxy,
32
- ClassicalProxy,
21
+ sympy.Basic,
33
22
  ]
34
- RuntimeExpression = Union[AnyClassicalValue, Basic, Boolean]
35
- ExpressionValue = Union[RuntimeConstant, Proxies, RuntimeExpression]
23
+ ExpressionValue = Union[RuntimeConstant, "QmodAnnotatedExpression"]
@@ -1,5 +1,5 @@
1
1
  from collections.abc import Mapping
2
- from typing import TYPE_CHECKING, Any, Union
2
+ from typing import TYPE_CHECKING, Any, Optional, Union
3
3
 
4
4
  import sympy
5
5
  from sympy import Integer
@@ -8,9 +8,6 @@ from typing_extensions import TypeGuard
8
8
  from classiq.interface.exceptions import ClassiqIndexError
9
9
  from classiq.interface.generator.expressions.expression import Expression
10
10
  from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
11
- from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
12
- AnyClassicalValue,
13
- )
14
11
  from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
15
12
  ClassicalProxy,
16
13
  )
@@ -28,8 +25,6 @@ if TYPE_CHECKING:
28
25
 
29
26
 
30
27
  def _is_int(val: Any) -> TypeGuard[Union[int, sympy.Basic]]:
31
- if isinstance(val, AnyClassicalValue):
32
- return False
33
28
  if isinstance(val, sympy.Basic):
34
29
  return val.is_Number
35
30
  return isinstance(val, int)
@@ -99,7 +94,7 @@ class ClassicalArrayProxy(ClassicalSequenceProxy):
99
94
  self,
100
95
  handle: HandleBinding,
101
96
  element_type: "ConcreteClassicalType",
102
- length: "ExpressionValue",
97
+ length: Optional["ExpressionValue"],
103
98
  ) -> None:
104
99
  super().__init__(handle)
105
100
  self._element_type = element_type
@@ -108,7 +103,7 @@ class ClassicalArrayProxy(ClassicalSequenceProxy):
108
103
  self._length = length
109
104
 
110
105
  @property
111
- def length(self) -> "ExpressionValue":
106
+ def length(self) -> Optional["ExpressionValue"]:
112
107
  return self._length
113
108
 
114
109
  def get_slice_at(self, start: Any, stop: Any) -> ClassicalProxy:
@@ -1,5 +1,5 @@
1
1
  from collections.abc import Mapping
2
- from typing import TYPE_CHECKING
2
+ from typing import TYPE_CHECKING, Union
3
3
 
4
4
  if TYPE_CHECKING:
5
5
  from classiq.interface.generator.expressions.expression_types import ExpressionValue
@@ -18,7 +18,7 @@ class ClassicalProxy:
18
18
  return str(self.handle)
19
19
 
20
20
  @property
21
- def fields(self) -> Mapping[str, "ExpressionValue"]:
21
+ def fields(self) -> Mapping[str, Union["ExpressionValue", "ClassicalProxy"]]:
22
22
  raise NotImplementedError
23
23
 
24
24
  @property
@@ -8,7 +8,6 @@ from classiq.interface.generator.expressions.proxies.classical.classical_proxy i
8
8
  from classiq.interface.model.handle_binding import FieldHandleBinding, HandleBinding
9
9
 
10
10
  if TYPE_CHECKING:
11
- from classiq.interface.generator.expressions.expression_types import ExpressionValue
12
11
  from classiq.interface.generator.types.struct_declaration import StructDeclaration
13
12
 
14
13
 
@@ -22,7 +21,7 @@ class ClassicalStructProxy(NonSymbolicExpr, ClassicalProxy):
22
21
  return self._decl
23
22
 
24
23
  @property
25
- def fields(self) -> Mapping[str, "ExpressionValue"]:
24
+ def fields(self) -> Mapping[str, ClassicalProxy]:
26
25
  return {
27
26
  field_name: field_type.get_classical_proxy(
28
27
  FieldHandleBinding(base_handle=self.handle, field=field_name)
@@ -9,9 +9,6 @@ from classiq.interface.ast_node import HashableASTNode
9
9
  from classiq.interface.exceptions import ClassiqInternalExpansionError
10
10
  from classiq.interface.generator.expressions.expression import Expression
11
11
  from classiq.interface.generator.expressions.expression_types import ExpressionValue
12
- from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
13
- AnyClassicalValue,
14
- )
15
12
  from classiq.interface.generator.expressions.proxies.classical.classical_array_proxy import (
16
13
  ClassicalArrayProxy,
17
14
  ClassicalTupleProxy,
@@ -163,9 +160,9 @@ class ClassicalArray(ClassicalType):
163
160
  return self.length.to_int_value()
164
161
 
165
162
  def get_classical_proxy(self, handle: HandleBinding) -> ClassicalProxy:
166
- length: ExpressionValue
163
+ length: Optional[ExpressionValue]
167
164
  if self.length is None:
168
- length = AnyClassicalValue(f"get_field({handle}, 'len')")
165
+ length = None
169
166
  elif not self.length.is_evaluated():
170
167
  raise ClassiqInternalExpansionError(
171
168
  "Classical list length is not evaluated"
@@ -47,7 +47,7 @@ PythonClassicalPydanticTypes = (Enum,)
47
47
 
48
48
  ConcreteQuantumType = Annotated[
49
49
  Union[QuantumBit, QuantumBitvector, QuantumNumeric, TypeName],
50
- Field(discriminator="kind", default_factory=QuantumBitvector),
50
+ Field(discriminator="kind"),
51
51
  ]
52
52
  QuantumBitvector.model_rebuild()
53
53
  TypeName.model_rebuild()
@@ -15,9 +15,6 @@ from classiq.interface.generator.expressions.proxies.classical.classical_scalar_
15
15
  from classiq.interface.generator.expressions.proxies.classical.classical_struct_proxy import (
16
16
  ClassicalStructProxy,
17
17
  )
18
- from classiq.interface.generator.expressions.proxies.quantum.qmod_qstruct_proxy import (
19
- QmodQStructProxy,
20
- )
21
18
  from classiq.interface.generator.functions.classical_type import (
22
19
  ClassicalType,
23
20
  )
@@ -59,15 +56,6 @@ class TypeName(ClassicalType, QuantumType):
59
56
  field_type.size_in_bits for field_type in fields_types
60
57
  )
61
58
 
62
- def get_proxy(self, handle: "HandleBinding") -> "QmodQStructProxy":
63
- from classiq.interface.generator.expressions.proxies.quantum.qmod_qstruct_proxy import (
64
- QmodQStructProxy,
65
- )
66
-
67
- return QmodQStructProxy(
68
- handle=handle, struct_name=self.name, fields=self.fields
69
- )
70
-
71
59
  @property
72
60
  def qmod_type_name(self) -> str:
73
61
  return self.name
@@ -17,6 +17,7 @@ from classiq.interface.generator.register_role import RegisterRole
17
17
  from classiq.interface.generator.synthesis_metadata.synthesis_execution_data import (
18
18
  ExecutionData,
19
19
  )
20
+ from classiq.interface.model.block import Block
20
21
  from classiq.interface.model.quantum_expressions.arithmetic_operation import (
21
22
  ArithmeticOperationKind,
22
23
  )
@@ -210,10 +211,13 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
210
211
  )
211
212
  name_with_suffix = self.add_suffix_from_generated_name(generated_name, name)
212
213
  return name_with_suffix
214
+ if isinstance(back_ref, Block) and back_ref.label is not None:
215
+ return back_ref.label
213
216
 
214
217
  statement_kind: str = back_ref.kind
215
218
  if isinstance(back_ref, ArithmeticOperation):
216
219
  statement_kind = back_ref.operation_kind.value
220
+
217
221
  return self.add_suffix_from_generated_name(
218
222
  generated_name, STATEMENTS_NAME[statement_kind]
219
223
  )
@@ -0,0 +1,14 @@
1
+ from pydantic import BaseModel
2
+
3
+ from classiq.interface.analyzer.result import QasmCode
4
+ from classiq.interface.enum_utils import StrEnum
5
+
6
+
7
+ class QmodFormat(StrEnum):
8
+ NATIVE = "native"
9
+ PYTHON = "python"
10
+
11
+
12
+ class QasmToQmodParams(BaseModel):
13
+ qasm: QasmCode
14
+ qmod_format: QmodFormat
@@ -1,4 +1,3 @@
1
- import ast
2
1
  from typing import Any
3
2
 
4
3
  from classiq.interface.ast_node import ASTNode
@@ -10,8 +9,6 @@ from classiq.interface.generator.visitor import Transformer, Visitor
10
9
  from classiq.interface.model.model import Model
11
10
  from classiq.interface.model.port_declaration import AnonPortDeclaration
12
11
 
13
- from classiq.model_expansions.transformers.model_renamer import ExprNormalizer
14
-
15
12
 
16
13
  class ModelNormalizer(Visitor):
17
14
  def visit(self, node: Any) -> None:
@@ -28,9 +25,6 @@ class ModelNormalizer(Visitor):
28
25
  model.functions.sort(key=lambda x: x.name)
29
26
  self.generic_visit(model)
30
27
 
31
- def visit_Expression(self, expr: Expression) -> None:
32
- expr.expr = ast.unparse(ExprNormalizer().visit(ast.parse(expr.expr)))
33
-
34
28
  def visit_AnonPortDeclaration(self, decl: AnonPortDeclaration) -> None:
35
29
  decl.type_modifier = TypeModifier.Mutable
36
30
 
@@ -171,6 +171,7 @@ class Operation(pydantic.BaseModel):
171
171
  expanded: bool = pydantic.Field(default=False)
172
172
  show_expanded_label: bool = pydantic.Field(default=False)
173
173
  is_low_level_fallback: bool = pydantic.Field(default=False)
174
+ is_measurement: bool = pydantic.Field(default=False)
174
175
 
175
176
  model_config = ConfigDict(frozen=True)
176
177
 
@@ -349,7 +349,7 @@ class FieldHandleBinding(NestedHandleBinding):
349
349
 
350
350
  @property
351
351
  def qmod_expr(self) -> str:
352
- return f"get_field({self.base_handle.qmod_expr}, '{self.field}')"
352
+ return f"{self.base_handle.qmod_expr}.{self.field}"
353
353
 
354
354
  @property
355
355
  def identifier(self) -> str:
@@ -13,10 +13,11 @@ from classiq.interface.generator.functions.type_modifier import (
13
13
  )
14
14
  from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
15
15
  from classiq.interface.model.parameter import Parameter
16
+ from classiq.interface.model.quantum_type import QuantumBitvector
16
17
 
17
18
 
18
19
  class AnonPortDeclaration(Parameter):
19
- quantum_type: ConcreteQuantumType
20
+ quantum_type: ConcreteQuantumType = pydantic.Field(default_factory=QuantumBitvector)
20
21
  direction: PortDeclarationDirection
21
22
  kind: Literal["PortDeclaration"]
22
23
  type_modifier: TypeModifier
@@ -1,12 +1,9 @@
1
1
  from collections.abc import Mapping, Sequence
2
- from typing import Literal
3
-
4
- from pydantic import PrivateAttr
2
+ from typing import Literal, cast
5
3
 
6
4
  from classiq.interface.enum_utils import StrEnum
7
5
  from classiq.interface.generator.arith.arithmetic import (
8
6
  ARITHMETIC_EXPRESSION_RESULT_NAME,
9
- compute_arithmetic_result_type,
10
7
  )
11
8
  from classiq.interface.model.handle_binding import (
12
9
  ConcreteHandleBinding,
@@ -18,6 +15,9 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
18
15
  from classiq.interface.model.quantum_statement import HandleMetadata
19
16
  from classiq.interface.model.quantum_type import QuantumType
20
17
 
18
+ from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
19
+ from classiq.model_expansions.arithmetic import NumericAttributes
20
+
21
21
 
22
22
  class ArithmeticOperationKind(StrEnum):
23
23
  InplaceAdd = "inplace_add"
@@ -29,7 +29,7 @@ class ArithmeticOperation(QuantumAssignmentOperation):
29
29
  kind: Literal["ArithmeticOperation"]
30
30
 
31
31
  operation_kind: ArithmeticOperationKind
32
- _classical_assignment: bool = PrivateAttr(default=False)
32
+ classical_assignment: bool = False
33
33
 
34
34
  @property
35
35
  def is_inplace(self) -> bool:
@@ -44,16 +44,20 @@ class ArithmeticOperation(QuantumAssignmentOperation):
44
44
  machine_precision: int,
45
45
  ) -> None:
46
46
  super().initialize_var_types(var_types, machine_precision)
47
- self._result_type = compute_arithmetic_result_type(
48
- self.expression.expr, var_types, machine_precision
49
- )
47
+ expr_val = self.expression.value.value
48
+ if isinstance(expr_val, QmodAnnotatedExpression):
49
+ self._result_type = expr_val.get_quantum_type(expr_val.root)
50
+ else:
51
+ self._result_type = NumericAttributes.from_constant(
52
+ cast(float, expr_val), machine_precision
53
+ ).to_quantum_numeric()
50
54
 
51
55
  @property
52
56
  def wiring_inouts(
53
57
  self,
54
58
  ) -> Mapping[str, ConcreteHandleBinding]:
55
59
  inouts = dict(super().wiring_inouts)
56
- if self.is_inplace and not self._classical_assignment:
60
+ if self.is_inplace and not self.classical_assignment:
57
61
  inouts[self.result_name()] = self.result_var
58
62
  return inouts
59
63
 
@@ -63,7 +67,7 @@ class ArithmeticOperation(QuantumAssignmentOperation):
63
67
  HandleMetadata(handle=handle, readable_location="in an expression")
64
68
  for handle in self.var_handles
65
69
  ]
66
- if self.is_inplace and not self._classical_assignment:
70
+ if self.is_inplace and not self.classical_assignment:
67
71
  inouts.append(
68
72
  HandleMetadata(
69
73
  handle=self.result_var,
@@ -74,13 +78,13 @@ class ArithmeticOperation(QuantumAssignmentOperation):
74
78
 
75
79
  @property
76
80
  def wiring_outputs(self) -> Mapping[str, HandleBinding]:
77
- if self.is_inplace or self._classical_assignment:
81
+ if self.is_inplace or self.classical_assignment:
78
82
  return {}
79
83
  return super().wiring_outputs
80
84
 
81
85
  @property
82
86
  def readable_outputs(self) -> Sequence[HandleMetadata]:
83
- if self.is_inplace or self._classical_assignment:
87
+ if self.is_inplace or self.classical_assignment:
84
88
  return []
85
89
  return [
86
90
  HandleMetadata(
@@ -15,20 +15,8 @@ from classiq.interface.generator.arith.register_user_input import (
15
15
  RegisterUserInput,
16
16
  )
17
17
  from classiq.interface.generator.expressions.expression import Expression
18
- from classiq.interface.generator.expressions.proxies.quantum.qmod_qarray_proxy import (
19
- QmodQArrayProxy,
20
- )
21
- from classiq.interface.generator.expressions.proxies.quantum.qmod_qscalar_proxy import (
22
- QmodQBitProxy,
23
- QmodQNumProxy,
24
- QmodQScalarProxy,
25
- )
26
- from classiq.interface.generator.expressions.proxies.quantum.qmod_sized_proxy import (
27
- QmodSizedProxy,
28
- )
29
18
  from classiq.interface.helpers.custom_pydantic_types import PydanticFloatTuple
30
19
  from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
31
- from classiq.interface.model.handle_binding import HandleBinding
32
20
 
33
21
  if TYPE_CHECKING:
34
22
  from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
@@ -59,9 +47,6 @@ class QuantumType(HashableASTNode):
59
47
  def minimal_size_in_bits(self) -> int:
60
48
  raise NotImplementedError
61
49
 
62
- def get_proxy(self, handle: "HandleBinding") -> QmodSizedProxy:
63
- return QmodSizedProxy(handle=handle, size=self.size_in_bits)
64
-
65
50
  @property
66
51
  def qmod_type_name(self) -> str:
67
52
  raise NotImplementedError
@@ -95,9 +80,6 @@ class QuantumType(HashableASTNode):
95
80
 
96
81
 
97
82
  class QuantumScalar(QuantumType):
98
- def get_proxy(self, handle: "HandleBinding") -> QmodQScalarProxy:
99
- return QmodQScalarProxy(handle, size=self.size_in_bits)
100
-
101
83
  @property
102
84
  def has_sign(self) -> bool:
103
85
  raise NotImplementedError
@@ -147,9 +129,6 @@ class QuantumBit(QuantumScalar):
147
129
  def qmod_type_name(self) -> str:
148
130
  return "QBit"
149
131
 
150
- def get_proxy(self, handle: "HandleBinding") -> QmodQBitProxy:
151
- return QmodQBitProxy(handle)
152
-
153
132
  @property
154
133
  def type_name(self) -> str:
155
134
  return "Quantum bit"
@@ -233,16 +212,6 @@ class QuantumBitvector(QuantumType):
233
212
  assert self.length is not None
234
213
  return self.length.to_int_value()
235
214
 
236
- def get_proxy(self, handle: "HandleBinding") -> QmodQArrayProxy:
237
- element_size = self.element_type.size_in_bits
238
- assert self.size_in_bits % element_size == 0
239
- return QmodQArrayProxy(
240
- handle,
241
- self.element_type,
242
- element_size,
243
- self.size_in_bits // element_size,
244
- )
245
-
246
215
  @property
247
216
  def qmod_type_name(self) -> str:
248
217
  element_type = [self.element_type.qmod_type_name]
@@ -382,14 +351,6 @@ class QuantumNumeric(QuantumScalar):
382
351
  ):
383
352
  self._size_in_bits = self.size.to_int_value()
384
353
 
385
- def get_proxy(self, handle: "HandleBinding") -> QmodQNumProxy:
386
- return QmodQNumProxy(
387
- handle,
388
- size=self.size_in_bits,
389
- fraction_digits=self.fraction_digits_value,
390
- is_signed=self.sign_value,
391
- )
392
-
393
354
  @property
394
355
  def qmod_type_name(self) -> str:
395
356
  if (
@@ -532,7 +493,7 @@ class QuantumNumeric(QuantumScalar):
532
493
 
533
494
 
534
495
  class RegisterQuantumType(BaseModel):
535
- quantum_types: "ConcreteQuantumType"
496
+ quantum_types: "ConcreteQuantumType" = Field(default_factory=QuantumBitvector)
536
497
  size: int = Field(default=1)
537
498
 
538
499
  @property
@@ -44,9 +44,6 @@ TASKS_VISUALIZE_SUFFIX = TASKS_SUFFIX + "/visualize"
44
44
  TASKS_VISUAL_MODEL_SUFFIX = TASKS_SUFFIX + "/visual_model"
45
45
  TASKS_SOLVE_SUFFIX = "/tasks/solve"
46
46
 
47
- CHEMISTRY_QMOD_PATH = "/generate_model/chemistry/qmod"
48
-
49
-
50
47
  TASK_TRAIN_SUFFIX = TASKS_SUFFIX + "/train"
51
48
  TASK_TEST_SUFFIX = TASKS_SUFFIX + "/test"
52
49
  TASK_PREDICT_SUFFIX = TASKS_SUFFIX + "/predict"
@@ -75,6 +72,8 @@ CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX = "/execution_input"
75
72
  CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_FULL = (
76
73
  CONVERSION_PREFIX + CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX
77
74
  )
75
+ QASM_TO_QMOD_SUFFIX = "/qasm_to_qmod"
76
+ QASM_TO_QMOD_FULL_PATH = CONVERSION_PREFIX + QASM_TO_QMOD_SUFFIX
78
77
 
79
78
  STATIC_SEMANTICS_VALIDATION_PATH = "/validate_static_semantics"
80
79
 
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  import dataclasses
2
3
  from collections.abc import Sequence
3
4
  from dataclasses import dataclass, field
@@ -41,6 +42,7 @@ from classiq.interface.model.variable_declaration_statement import (
41
42
  VariableDeclarationStatement,
42
43
  )
43
44
 
45
+ from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
44
46
  from classiq.model_expansions.capturing.mangling_utils import (
45
47
  demangle_handle,
46
48
  mangle_captured_var_name,
@@ -60,9 +62,11 @@ UNINITIALIZED_VAR_MESSAGE = "Variable '{}' should be initialized here"
60
62
 
61
63
  def _get_symbol_expr(symbol: str, classical_type: ClassicalType) -> Expression:
62
64
  expr = Expression(expr=symbol)
63
- expr._evaluated_expr = EvaluatedExpression(
64
- value=classical_type.get_classical_proxy(handle=HandleBinding(name=symbol))
65
- )
65
+ expr_val = QmodAnnotatedExpression(ast.Name(id=symbol))
66
+ expr_val.set_type(expr_val.root, classical_type)
67
+ expr_val.set_var(expr_val.root, HandleBinding(name=symbol))
68
+ expr_val.lock()
69
+ expr._evaluated_expr = EvaluatedExpression(value=expr_val)
66
70
  return expr
67
71
 
68
72
 
@@ -550,6 +554,9 @@ class CapturedVars:
550
554
  ],
551
555
  )
552
556
 
557
+ def get_captured_classical_vars(self) -> list[str]:
558
+ return [var.name for var in self._captured_classical_vars]
559
+
553
560
  def get_captured_parameters(self) -> list[PositionalArg]:
554
561
  decls: list[PositionalArg]
555
562
  decls = [
@@ -11,6 +11,7 @@ from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
11
11
  from classiq.interface.model.quantum_function_declaration import (
12
12
  NamedParamsQuantumFunctionDeclaration,
13
13
  PositionalArg,
14
+ QuantumOperandDeclaration,
14
15
  )
15
16
  from classiq.interface.model.quantum_lambda_function import QuantumCallable
16
17
  from classiq.interface.model.quantum_statement import QuantumStatement
@@ -111,6 +112,13 @@ class FunctionClosure(Closure):
111
112
  def emit(self) -> QuantumCallable:
112
113
  return self.name
113
114
 
115
+ def as_operand_declaration(self, is_list: bool) -> QuantumOperandDeclaration:
116
+ return QuantumOperandDeclaration(
117
+ name=self.name,
118
+ positional_arg_declarations=self.positional_arg_declarations,
119
+ is_list=is_list,
120
+ )
121
+
114
122
 
115
123
  @dataclass(frozen=True)
116
124
  class GenerativeFunctionClosure(GenerativeClosure, FunctionClosure):
@@ -3,7 +3,10 @@ from contextlib import contextmanager
3
3
  from dataclasses import dataclass, field
4
4
  from typing import Generic, Optional, TypeVar
5
5
 
6
- from classiq.interface.exceptions import ClassiqInternalExpansionError
6
+ from classiq.interface.exceptions import (
7
+ ClassiqExpansionError,
8
+ ClassiqInternalExpansionError,
9
+ )
7
10
  from classiq.interface.generator.compiler_keywords import (
8
11
  EXPANDED_KEYWORD,
9
12
  LAMBDA_KEYWORD,
@@ -31,7 +34,7 @@ from classiq.model_expansions.capturing.captured_vars import (
31
34
  validate_end_state,
32
35
  )
33
36
  from classiq.model_expansions.closure import Closure, FunctionClosure
34
- from classiq.model_expansions.scope import Scope
37
+ from classiq.model_expansions.scope import ClassicalSymbol, Scope
35
38
  from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
36
39
 
37
40
  ClosureType = TypeVar("ClosureType", bound=Closure)
@@ -190,6 +193,8 @@ class OperationBuilder:
190
193
  self.current_function
191
194
  ).set_propagated()
192
195
  validate_captured_directions(captured_vars)
196
+ else:
197
+ self._validate_no_captured_runtime_params(captured_vars)
193
198
  if len(self._operations) < 2:
194
199
  return
195
200
  parent_block = self._operations[-2].blocks[self._blocks[-1]]
@@ -231,3 +236,14 @@ class OperationBuilder:
231
236
  raise ClassiqInternalExpansionError("Could not allocate function name")
232
237
 
233
238
  return name
239
+
240
+ def _validate_no_captured_runtime_params(self, captured_vars: CapturedVars) -> None:
241
+ if any(
242
+ var in self.current_scope
243
+ and isinstance(self.current_scope[var].value, ClassicalSymbol)
244
+ for var in captured_vars.get_captured_classical_vars()
245
+ ):
246
+ raise ClassiqExpansionError(
247
+ "Runtime classical variables can only be declared and used at the "
248
+ "function's top scope"
249
+ )