classiq 0.42.2__py3-none-any.whl → 0.43.1__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 (113) hide show
  1. classiq/__init__.py +2 -6
  2. classiq/_internals/api_wrapper.py +6 -12
  3. classiq/_internals/authentication/token_manager.py +5 -2
  4. classiq/_internals/jobs.py +5 -10
  5. classiq/analyzer/rb.py +3 -3
  6. classiq/applications/chemistry/chemistry_model_constructor.py +12 -8
  7. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +2 -2
  8. classiq/applications/finance/finance_model_constructor.py +16 -13
  9. classiq/applications/qsvm/__init__.py +1 -3
  10. classiq/applications/qsvm/qsvm_model_constructor.py +7 -6
  11. classiq/exceptions.py +9 -4
  12. classiq/execution/execution_session.py +5 -2
  13. classiq/execution/qnn.py +1 -1
  14. classiq/executor.py +0 -2
  15. classiq/interface/_version.py +1 -1
  16. classiq/interface/chemistry/operator.py +19 -5
  17. classiq/interface/executor/constants.py +1 -0
  18. classiq/interface/finance/function_input.py +16 -10
  19. classiq/interface/generator/application_apis/chemistry_declarations.py +2 -2
  20. classiq/interface/generator/application_apis/qsvm_declarations.py +4 -2
  21. classiq/interface/generator/arith/argument_utils.py +20 -3
  22. classiq/interface/generator/arith/arithmetic_expression_validator.py +3 -26
  23. classiq/interface/generator/arith/binary_ops.py +8 -14
  24. classiq/interface/generator/arith/extremum_operations.py +30 -0
  25. classiq/interface/generator/arith/number_utils.py +1 -1
  26. classiq/interface/generator/arith/unary_ops.py +1 -3
  27. classiq/interface/generator/compiler_keywords.py +1 -1
  28. classiq/interface/generator/expressions/atomic_expression_functions.py +13 -3
  29. classiq/interface/generator/expressions/enums/__init__.py +0 -20
  30. classiq/interface/generator/expressions/enums/finance_functions.py +11 -18
  31. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  32. classiq/interface/generator/expressions/qmod_qarray_proxy.py +52 -37
  33. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +16 -11
  34. classiq/interface/generator/expressions/qmod_sized_proxy.py +5 -5
  35. classiq/interface/generator/function_param_list_without_self_reference.py +0 -10
  36. classiq/interface/generator/function_params.py +0 -4
  37. classiq/interface/generator/functions/__init__.py +0 -20
  38. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +2 -2
  39. classiq/interface/generator/functions/builtins/open_lib_functions.py +530 -1
  40. classiq/interface/generator/functions/classical_type.py +22 -69
  41. classiq/interface/generator/functions/port_declaration.py +0 -11
  42. classiq/interface/generator/model/__init__.py +0 -1
  43. classiq/interface/generator/model/model.py +9 -185
  44. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +3 -1
  45. classiq/interface/generator/types/builtin_enum_declarations.py +69 -0
  46. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +2 -2
  47. classiq/interface/generator/types/enum_declaration.py +57 -0
  48. classiq/interface/jobs.py +36 -65
  49. classiq/interface/model/bind_operation.py +3 -0
  50. classiq/interface/model/classical_parameter_declaration.py +3 -0
  51. classiq/interface/model/handle_binding.py +7 -0
  52. classiq/interface/model/inplace_binary_operation.py +13 -15
  53. classiq/interface/model/model.py +8 -20
  54. classiq/interface/model/native_function_definition.py +0 -17
  55. classiq/interface/model/quantum_function_call.py +63 -182
  56. classiq/interface/model/quantum_type.py +71 -10
  57. classiq/interface/server/routes.py +0 -6
  58. classiq/qmod/__init__.py +3 -3
  59. classiq/qmod/builtins/__init__.py +10 -1
  60. classiq/qmod/builtins/classical_execution_primitives.py +4 -2
  61. classiq/qmod/builtins/enums.py +177 -0
  62. classiq/qmod/builtins/functions.py +1 -2
  63. classiq/qmod/builtins/operations.py +2 -4
  64. classiq/qmod/builtins/structs.py +16 -17
  65. classiq/qmod/declaration_inferrer.py +23 -20
  66. classiq/qmod/model_state_container.py +2 -0
  67. classiq/qmod/native/pretty_printer.py +31 -13
  68. classiq/qmod/pretty_print/pretty_printer.py +52 -27
  69. classiq/qmod/qmod_constant.py +7 -3
  70. classiq/qmod/qmod_parameter.py +2 -1
  71. classiq/qmod/qmod_struct.py +9 -33
  72. classiq/qmod/qmod_variable.py +55 -22
  73. classiq/qmod/quantum_callable.py +6 -1
  74. classiq/qmod/quantum_expandable.py +29 -11
  75. classiq/qmod/quantum_function.py +8 -4
  76. classiq/qmod/semantics/annotation.py +38 -0
  77. classiq/qmod/semantics/error_manager.py +49 -0
  78. classiq/qmod/semantics/static_semantics_visitor.py +308 -0
  79. classiq/qmod/semantics/validation/func_call_validation.py +149 -0
  80. classiq/qmod/semantics/validation/types_validation.py +21 -0
  81. classiq/qmod/symbolic.py +6 -6
  82. classiq/qmod/symbolic_expr.py +26 -11
  83. classiq/qmod/utilities.py +23 -1
  84. {classiq-0.42.2.dist-info → classiq-0.43.1.dist-info}/METADATA +2 -2
  85. {classiq-0.42.2.dist-info → classiq-0.43.1.dist-info}/RECORD +88 -103
  86. classiq/_internals/_qfunc_ext.py +0 -6
  87. classiq/applications/libraries/ampltitude_estimation_library.py +0 -11
  88. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
  89. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
  90. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  91. classiq/interface/generator/expressions/enums/classical_enum.py +0 -20
  92. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -6
  93. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  94. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  95. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  96. classiq/interface/generator/functions/foreign_function_definition.py +0 -114
  97. classiq/interface/generator/functions/function_implementation.py +0 -107
  98. classiq/interface/generator/functions/native_function_definition.py +0 -155
  99. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  100. classiq/interface/generator/functions/register.py +0 -44
  101. classiq/interface/generator/functions/register_mapping_data.py +0 -106
  102. classiq/interface/generator/inequality_mixer.py +0 -51
  103. classiq/interface/generator/model/classical_main_validator.py +0 -106
  104. classiq/interface/generator/range_mixer.py +0 -56
  105. classiq/interface/generator/state_propagator.py +0 -74
  106. classiq/interface/model/resolvers/function_call_resolver.py +0 -64
  107. classiq/interface/model/validations/__init__.py +0 -0
  108. classiq/interface/model/validations/handle_validation_base.py +0 -55
  109. classiq/interface/model/validations/handles_validator.py +0 -153
  110. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  111. /classiq/{interface/generator/credit_risk_example → qmod/semantics}/__init__.py +0 -0
  112. /classiq/{interface/model/resolvers → qmod/semantics/validation}/__init__.py +0 -0
  113. {classiq-0.42.2.dist-info → classiq-0.43.1.dist-info}/WHEEL +0 -0
@@ -1,4 +1,3 @@
1
- from abc import abstractmethod
2
1
  from typing import Any, Dict, List, Literal, Union
3
2
 
4
3
  import pydantic
@@ -7,11 +6,6 @@ from sympy import IndexedBase, Symbol
7
6
  from typing_extensions import Annotated
8
7
 
9
8
  from classiq.interface.ast_node import HashableASTNode
10
- from classiq.interface.generator.expressions.enums.classical_enum import ClassicalEnum
11
- from classiq.interface.generator.expressions.enums.ladder_operator import (
12
- LadderOperator as LadderOperatorEnum,
13
- )
14
- from classiq.interface.generator.expressions.enums.pauli import Pauli as PauliEnum
15
9
  from classiq.interface.generator.expressions.expression_types import RuntimeExpression
16
10
  from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
17
11
 
@@ -24,13 +18,6 @@ class ClassicalType(HashableASTNode):
24
18
  def as_symbolic(self, name: str) -> Union[NamedSymbol, List[NamedSymbol]]:
25
19
  return Symbol(name)
26
20
 
27
- @property
28
- @abstractmethod
29
- def default_value(self) -> Any:
30
- raise NotImplementedError(
31
- f"{self.__class__.__name__} type has no default value"
32
- )
33
-
34
21
  @property
35
22
  def qmod_type(self) -> type:
36
23
  raise NotImplementedError(
@@ -44,20 +31,12 @@ class ClassicalType(HashableASTNode):
44
31
  return str(type(self).__name__)
45
32
 
46
33
 
47
- class EnumType(ClassicalType):
48
- pass
49
-
50
-
51
34
  class Integer(ClassicalType):
52
35
  kind: Literal["int"]
53
36
 
54
37
  def as_symbolic(self, name: str) -> Symbol:
55
38
  return Symbol(name, integer=True)
56
39
 
57
- @property
58
- def default_value(self) -> int:
59
- return 0
60
-
61
40
  @pydantic.root_validator(pre=True)
62
41
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
63
42
  return values_with_discriminator(values, "kind", "int")
@@ -75,10 +54,6 @@ class Real(ClassicalType):
75
54
  def as_symbolic(self, name: str) -> Symbol:
76
55
  return Symbol(name, real=True)
77
56
 
78
- @property
79
- def default_value(self) -> float:
80
- return 0.0
81
-
82
57
  @pydantic.root_validator(pre=True)
83
58
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
84
59
  return values_with_discriminator(values, "kind", "real")
@@ -93,10 +68,6 @@ class Real(ClassicalType):
93
68
  class Bool(ClassicalType):
94
69
  kind: Literal["bool"]
95
70
 
96
- @property
97
- def default_value(self) -> bool:
98
- return False
99
-
100
71
  @pydantic.root_validator(pre=True)
101
72
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
102
73
  return values_with_discriminator(values, "kind", "bool")
@@ -115,10 +86,6 @@ class ClassicalList(ClassicalType):
115
86
  def as_symbolic(self, name: str) -> Symbol:
116
87
  return IndexedBase(name)
117
88
 
118
- @property
119
- def default_value(self) -> List:
120
- return []
121
-
122
89
  @pydantic.root_validator(pre=True)
123
90
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
124
91
  return values_with_discriminator(values, "kind", "list")
@@ -130,45 +97,31 @@ class ClassicalList(ClassicalType):
130
97
  return CArray[self.element_type.qmod_type] # type:ignore[name-defined]
131
98
 
132
99
 
133
- class Pauli(EnumType):
100
+ class Pauli(ClassicalType):
134
101
  kind: Literal["pauli"]
135
102
 
136
- @property
137
- def default_value(self) -> PauliEnum:
138
- return PauliEnum.I
139
-
140
103
  @pydantic.root_validator(pre=True)
141
104
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
142
105
  return values_with_discriminator(values, "kind", "pauli")
143
106
 
144
107
  @property
145
108
  def qmod_type(self) -> type:
146
- return PauliEnum
109
+ from classiq.qmod.builtins.enums import Pauli
110
+
111
+ return Pauli
147
112
 
148
113
 
149
114
  class StructMetaType(ClassicalType):
150
115
  kind: Literal["type_proxy"]
151
116
 
152
- @property
153
- def default_value(self) -> Any:
154
- return super().default_value
155
-
156
117
  @pydantic.root_validator(pre=True)
157
118
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
158
119
  return values_with_discriminator(values, "kind", "type_proxy")
159
120
 
160
121
 
161
- class CStructBase: # marker for Qmod structs in the Python SDK
162
- pass
163
-
164
-
165
- class Struct(ClassicalType):
122
+ class TypeName(ClassicalType):
166
123
  kind: Literal["struct_instance"]
167
- name: str = pydantic.Field(description="The struct type of the instance")
168
-
169
- @property
170
- def default_value(self) -> Any:
171
- return super().default_value
124
+ name: str = pydantic.Field(description="The type name of the instance")
172
125
 
173
126
  @pydantic.root_validator(pre=True)
174
127
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@@ -176,7 +129,15 @@ class Struct(ClassicalType):
176
129
 
177
130
  @property
178
131
  def qmod_type(self) -> type:
179
- return type(self.name, (CStructBase,), dict())
132
+ return type(self.name, (TypeName,), dict())
133
+
134
+
135
+ class Enum(TypeName):
136
+ pass
137
+
138
+
139
+ class Struct(TypeName):
140
+ pass
180
141
 
181
142
 
182
143
  class ClassicalArray(ClassicalType):
@@ -187,10 +148,6 @@ class ClassicalArray(ClassicalType):
187
148
  def as_symbolic(self, name: str) -> list:
188
149
  return [self.element_type.as_symbolic(f"{name}_{i}") for i in range(self.size)]
189
150
 
190
- @property
191
- def default_value(self) -> Any:
192
- return super().default_value
193
-
194
151
  @pydantic.root_validator(pre=True)
195
152
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
196
153
  return values_with_discriminator(values, "kind", "array")
@@ -205,9 +162,7 @@ class ClassicalArray(ClassicalType):
205
162
 
206
163
 
207
164
  class OpaqueHandle(ClassicalType):
208
- @property
209
- def default_value(self) -> int:
210
- return 0
165
+ pass
211
166
 
212
167
 
213
168
  class VQEResult(OpaqueHandle):
@@ -242,20 +197,18 @@ class IQAERes(OpaqueHandle):
242
197
  return values_with_discriminator(values, "kind", "iqae_result")
243
198
 
244
199
 
245
- class LadderOperator(EnumType):
200
+ class LadderOperator(ClassicalType):
246
201
  kind: Literal["ladder_operator"]
247
202
 
248
- @property
249
- def default_value(self) -> LadderOperatorEnum:
250
- return LadderOperatorEnum.PLUS
251
-
252
203
  @pydantic.root_validator(pre=True)
253
204
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
254
205
  return values_with_discriminator(values, "kind", "ladder_operator")
255
206
 
256
207
  @property
257
208
  def qmod_type(self) -> type:
258
- return LadderOperatorEnum
209
+ from classiq.qmod.builtins.enums import LadderOperator
210
+
211
+ return LadderOperator
259
212
 
260
213
 
261
214
  ConcreteClassicalType = Annotated[
@@ -266,7 +219,7 @@ ConcreteClassicalType = Annotated[
266
219
  ClassicalList,
267
220
  Pauli,
268
221
  StructMetaType,
269
- Struct,
222
+ TypeName,
270
223
  ClassicalArray,
271
224
  VQEResult,
272
225
  Histogram,
@@ -279,7 +232,7 @@ ConcreteClassicalType = Annotated[
279
232
  ClassicalList.update_forward_refs()
280
233
  ClassicalArray.update_forward_refs()
281
234
 
282
- PythonClassicalTypes = (int, float, bool, list, CStructBase, ClassicalEnum)
235
+ PythonClassicalTypes = (int, float, bool, list, Enum)
283
236
 
284
237
 
285
238
  def as_symbolic(symbols: Dict[str, ClassicalType]) -> Dict[str, RuntimeExpression]:
@@ -1,8 +1,5 @@
1
1
  from typing import Any
2
2
 
3
- import pydantic
4
- from pydantic import BaseModel
5
-
6
3
  from classiq.interface.generator.function_params import PortDirection
7
4
 
8
5
  from classiq._internals.enum_utils import StrEnum
@@ -39,11 +36,3 @@ class PortDeclarationDirection(StrEnum):
39
36
  cls, port_direction: PortDirection
40
37
  ) -> "PortDeclarationDirection":
41
38
  return cls(port_direction.value)
42
-
43
-
44
- class SynthesisPortDeclaration(BaseModel):
45
- name: str
46
- size: int
47
- direction: PortDeclarationDirection
48
- is_signed: bool = pydantic.Field(default=False)
49
- fraction_places: int = pydantic.Field(default=0)
@@ -5,7 +5,6 @@ from classiq.interface.generator.model.constraints import (
5
5
  OptimizationParameter,
6
6
  TranspilerBasisGates,
7
7
  )
8
- from classiq.interface.generator.model.model import SynthesisModel
9
8
  from classiq.interface.generator.model.preferences import (
10
9
  CustomHardwareSettings,
11
10
  Preferences,
@@ -1,68 +1,36 @@
1
1
  from abc import ABC
2
- from typing import Any, Dict, List, Literal, Mapping, NewType, Optional, Union
2
+ from typing import List
3
3
 
4
4
  import pydantic
5
5
 
6
6
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
7
7
  from classiq.interface.generator.constant import Constant
8
- from classiq.interface.generator.function_params import ArithmeticIODict, IOName
9
- from classiq.interface.generator.functions import (
10
- SynthesisNativeFunctionDefinition,
11
- SynthesisPortDeclaration,
12
- SynthesisQuantumFunctionDeclaration,
13
- )
14
- from classiq.interface.generator.functions.port_declaration import (
15
- PortDeclarationDirection,
16
- )
17
- from classiq.interface.generator.model.constraints import Constraints
18
- from classiq.interface.generator.model.preferences.preferences import Preferences
19
- from classiq.interface.generator.model.quantum_register import QReg, QRegGenericAlias
20
- from classiq.interface.generator.quantum_function_call import (
21
- SUFFIX_RANDOMIZER,
22
- SynthesisQuantumFunctionCall,
23
- WireDict,
24
- WireName,
25
- )
8
+ from classiq.interface.generator.function_params import ArithmeticIODict
9
+ from classiq.interface.generator.types.enum_declaration import EnumDeclaration
26
10
  from classiq.interface.generator.types.struct_declaration import StructDeclaration
27
- from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
28
11
  from classiq.interface.helpers.validation_helpers import is_list_unique
29
12
  from classiq.interface.helpers.versioned_model import VersionedModel
30
13
 
31
- from classiq import ForeignFunctionDefinition as SynthesisForeignFunctionDefinition
32
14
  from classiq.exceptions import ClassiqValueError
33
15
 
34
- MAIN_FUNCTION_NAME = "main"
35
- CLASSICAL_ENTRY_FUNCTION_NAME = "cmain"
36
-
37
- DEFAULT_PORT_SIZE = 1
38
-
39
-
40
- SerializedModel = NewType("SerializedModel", str)
41
-
42
- # We need to define ConcreteFunctionData so pydantic will know
43
- # what class to use when deserializing from object (pydantic attempts to
44
- # parse as each of the classes in the Union, in order).
45
- ConcreteFunctionDefinition = Union[
46
- SynthesisForeignFunctionDefinition, SynthesisNativeFunctionDefinition
47
- ]
48
-
49
16
  TYPE_LIBRARY_DUPLICATED_TYPE_NAMES = (
50
17
  "Cannot have multiple struct types with the same name"
51
18
  )
52
19
 
53
20
 
54
- def _create_default_functions() -> List[ConcreteFunctionDefinition]:
55
- return [SynthesisNativeFunctionDefinition(name=MAIN_FUNCTION_NAME)]
56
-
57
-
58
21
  class ClassiqBaseModel(VersionedModel, ABC):
59
22
  """
60
23
  All the relevant data for evaluating execution in one place.
61
24
  """
62
25
 
26
+ enums: List[EnumDeclaration] = pydantic.Field(
27
+ default_factory=list,
28
+ description="user-defined enums",
29
+ )
30
+
63
31
  types: List[StructDeclaration] = pydantic.Field(
64
32
  default_factory=list,
65
- description="The user-defined custom function library.",
33
+ description="user-defined structs",
66
34
  )
67
35
 
68
36
  constants: List[Constant] = pydantic.Field(
@@ -90,147 +58,3 @@ class ExecutionModel(ClassiqBaseModel):
90
58
  description="Mapping between a measured register name and its arithmetic type",
91
59
  default_factory=dict,
92
60
  )
93
-
94
-
95
- class SynthesisModel(ClassiqBaseModel):
96
- """
97
- All the relevant data for generating quantum circuit in one place.
98
- """
99
-
100
- kind: Literal["synthesis"] = pydantic.Field(default="synthesis")
101
-
102
- # Must be validated before logic_flow
103
- functions: List[ConcreteFunctionDefinition] = pydantic.Field(
104
- default_factory=_create_default_functions,
105
- description="The quantum functions of the model.",
106
- )
107
-
108
- constraints: Constraints = pydantic.Field(default_factory=Constraints)
109
- preferences: Preferences = pydantic.Field(default_factory=Preferences)
110
-
111
- def __init__(
112
- self,
113
- *,
114
- body: Optional[List[SynthesisQuantumFunctionCall]] = None,
115
- inputs: Optional[WireDict] = None,
116
- outputs: Optional[WireDict] = None,
117
- **kwargs: Any,
118
- ) -> None:
119
- super().__init__(**kwargs)
120
- if body:
121
- self.main_func.body.extend(body)
122
- if inputs:
123
- self.set_inputs(
124
- {
125
- name: QRegGenericAlias(
126
- QReg(DEFAULT_PORT_SIZE), (DEFAULT_PORT_SIZE, 0)
127
- )
128
- for name in inputs.keys()
129
- },
130
- inputs,
131
- )
132
- if outputs:
133
- self.set_outputs(
134
- {name: QReg(DEFAULT_PORT_SIZE) for name in outputs.keys()}, outputs
135
- )
136
-
137
- @property
138
- def main_func(self) -> SynthesisNativeFunctionDefinition:
139
- return self.function_dict[MAIN_FUNCTION_NAME] # type:ignore[return-value]
140
-
141
- @property
142
- def body(self) -> List[SynthesisQuantumFunctionCall]:
143
- return self.main_func.body
144
-
145
- @property
146
- def inputs(self) -> WireDict:
147
- return self.main_func.input_ports_wiring
148
-
149
- def set_inputs(
150
- self,
151
- inputs: Mapping[IOName, QRegGenericAlias],
152
- input_wiring: Mapping[IOName, WireName],
153
- ) -> None:
154
- self._update_main_declarations(inputs, PortDeclarationDirection.Input)
155
- self.main_func.input_ports_wiring.update(input_wiring)
156
-
157
- @property
158
- def outputs(self) -> WireDict:
159
- return self.main_func.output_ports_wiring
160
-
161
- def set_outputs(
162
- self, outputs: Mapping[IOName, QReg], output_wiring: Mapping[IOName, WireName]
163
- ) -> None:
164
- self._update_main_declarations(outputs, PortDeclarationDirection.Output)
165
- self.main_func.output_ports_wiring.update(output_wiring)
166
-
167
- @pydantic.validator("preferences", always=True)
168
- def _seed_suffix_randomizer(cls, preferences: Preferences) -> Preferences:
169
- SUFFIX_RANDOMIZER.seed(preferences.random_seed)
170
- return preferences
171
-
172
- def _get_qualified_direction(
173
- self, port_name: str, direction: PortDeclarationDirection
174
- ) -> PortDeclarationDirection:
175
- if port_name in self.main_func.port_declarations:
176
- return PortDeclarationDirection.Inout
177
- return direction
178
-
179
- def _update_main_declarations(
180
- self,
181
- value: Union[Mapping[IOName, QReg], Mapping[IOName, QRegGenericAlias]],
182
- direction: PortDeclarationDirection,
183
- ) -> None:
184
- for port_name, register in value.items():
185
- if isinstance(register, QReg):
186
- size = len(register)
187
- is_signed = getattr(register, "is_signed", False) or False
188
- fraction_places = getattr(register, "fraction_places", 0) or 0
189
- else:
190
- size = register.size if register.size is not None else DEFAULT_PORT_SIZE
191
- is_signed = False
192
- fraction_places = (
193
- register.fraction_places
194
- if register.fraction_places is not None
195
- else 0
196
- )
197
-
198
- self.main_func.port_declarations[port_name] = SynthesisPortDeclaration(
199
- name=port_name,
200
- size=size,
201
- direction=self._get_qualified_direction(port_name, direction),
202
- is_signed=is_signed,
203
- fraction_places=fraction_places,
204
- )
205
-
206
- @property
207
- def function_dict(self) -> Dict[str, SynthesisQuantumFunctionDeclaration]:
208
- return nameables_to_dict(self.functions)
209
-
210
- @pydantic.validator("functions", each_item=True)
211
- def validate_static_correctness(
212
- cls, func_def: ConcreteFunctionDefinition
213
- ) -> ConcreteFunctionDefinition:
214
- if isinstance(func_def, SynthesisNativeFunctionDefinition):
215
- func_def.validate_body()
216
- return func_def
217
-
218
- @pydantic.validator("functions")
219
- def validate_main_function_exists(
220
- cls, func_defs: List[ConcreteFunctionDefinition]
221
- ) -> List[ConcreteFunctionDefinition]:
222
- if MAIN_FUNCTION_NAME not in {func.name for func in func_defs}:
223
- raise ClassiqValueError("The model must contain a `main` function")
224
- return func_defs
225
-
226
- def get_model(self) -> SerializedModel:
227
- return SerializedModel(self.json(exclude_defaults=True, indent=2))
228
-
229
- def classical_model(self) -> ExecutionModel:
230
- return ExecutionModel(
231
- types=self.types,
232
- constants=self.constants,
233
- classical_execution_code=self.classical_execution_code,
234
- execution_preferences=self.execution_preferences,
235
- circuit_outputs=self.main_func.outputs,
236
- )
@@ -1,9 +1,11 @@
1
- from typing import Dict, Optional, Set
1
+ from typing import Dict, Final, Optional, Set
2
2
 
3
3
  import pydantic
4
4
 
5
5
  from classiq.interface.backend.pydantic_backend import PydanticExecutionParameter
6
6
 
7
+ CPARAM_EXECUTION_SUFFIX: Final[str] = "_param"
8
+
7
9
 
8
10
  class FunctionExecutionData(pydantic.BaseModel):
9
11
  power_parameter: Optional[PydanticExecutionParameter] = pydantic.Field(default=None)
@@ -0,0 +1,69 @@
1
+ from classiq.interface.chemistry.elements import ELEMENTS
2
+ from classiq.interface.chemistry.ground_state_problem import FermionMapping
3
+ from classiq.interface.generator.types.enum_declaration import EnumDeclaration
4
+
5
+ ELEMENT = EnumDeclaration(
6
+ name="Element", members={element: idx for idx, element in enumerate(ELEMENTS)}
7
+ )
8
+
9
+ FERMION_MAPPING = EnumDeclaration(
10
+ name="FermionMapping",
11
+ members={
12
+ mapping.name: idx # type:ignore[attr-defined]
13
+ for idx, mapping in enumerate(FermionMapping)
14
+ },
15
+ )
16
+
17
+ FINANCE_FUNCTION_TYPE = EnumDeclaration(
18
+ name="FinanceFunctionType",
19
+ members={
20
+ "VAR": 0,
21
+ "SHORTFALL": 1,
22
+ "X_SQUARE": 2,
23
+ "EUROPEAN_CALL_OPTION": 3,
24
+ },
25
+ )
26
+
27
+ LADDER_OPERATOR = EnumDeclaration(
28
+ name="LadderOperator",
29
+ members={
30
+ "PLUS": 0,
31
+ "MINUS": 1,
32
+ },
33
+ )
34
+
35
+ OPTIMIZER = EnumDeclaration(
36
+ name="Optimizer",
37
+ members={
38
+ "COBYLA": 1,
39
+ "SPSA": 2,
40
+ "L_BFGS_B": 3,
41
+ "NELDER_MEAD": 4,
42
+ "ADAM": 5,
43
+ },
44
+ )
45
+
46
+ PAULI = EnumDeclaration(
47
+ name="Pauli",
48
+ members={
49
+ "I": 0,
50
+ "X": 1,
51
+ "Y": 2,
52
+ "Z": 3,
53
+ },
54
+ )
55
+
56
+ QSVM_FEATURE_MAP_ENTANGLEMENT = EnumDeclaration(
57
+ name="QSVMFeatureMapEntanglement",
58
+ members={
59
+ "FULL": 0,
60
+ "LINEAR": 1,
61
+ "CIRCULAR": 2,
62
+ "SCA": 3,
63
+ "PAIRWISE": 4,
64
+ },
65
+ )
66
+
67
+ for enum_decl in list(vars().values()):
68
+ if isinstance(enum_decl, EnumDeclaration):
69
+ EnumDeclaration.BUILTIN_ENUM_DECLARATIONS[enum_decl.name] = enum_decl
@@ -2,7 +2,7 @@ import functools
2
2
 
3
3
  from classiq.interface.generator.functions.classical_type import (
4
4
  ClassicalList,
5
- Pauli,
5
+ Enum,
6
6
  Real,
7
7
  Struct,
8
8
  )
@@ -12,7 +12,7 @@ from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
12
12
  PAULI_TERM = StructDeclaration(
13
13
  name="PauliTerm",
14
14
  variables={
15
- "pauli": ClassicalList(element_type=Pauli()),
15
+ "pauli": ClassicalList(element_type=Enum(name="Pauli")),
16
16
  "coefficient": Real(),
17
17
  },
18
18
  )
@@ -0,0 +1,57 @@
1
+ from collections import Counter
2
+ from enum import Enum, EnumMeta, IntEnum
3
+ from typing import ClassVar, Dict
4
+
5
+ import pydantic
6
+
7
+ from classiq.interface.ast_node import HashableASTNode
8
+
9
+ from classiq.exceptions import ClassiqValueError
10
+
11
+
12
+ class EnumDeclaration(HashableASTNode):
13
+ name: str
14
+
15
+ members: Dict[str, int] = pydantic.Field(
16
+ default_factory=dict,
17
+ description="Dictionary of member names and their values",
18
+ )
19
+
20
+ BUILTIN_ENUM_DECLARATIONS: ClassVar[Dict[str, "EnumDeclaration"]] = {}
21
+
22
+ @pydantic.validator("members")
23
+ def _validate_members(cls, members: Dict[str, int]) -> Dict[str, int]:
24
+ underscore_members = [
25
+ member for member in members.keys() if member.startswith("_")
26
+ ]
27
+ if len(underscore_members) > 0:
28
+ raise ClassiqValueError(
29
+ f"Enum member names must not start with an underscore. The offending "
30
+ f"members: {underscore_members}"
31
+ )
32
+
33
+ counter = Counter(members.values())
34
+ repeating_members = [
35
+ member for member, value in members.items() if counter[value] > 1
36
+ ]
37
+ if len(repeating_members) > 0:
38
+ raise ClassiqValueError(
39
+ f"Cannot assign the same value to more than one enum member. The "
40
+ f"offending members: {repeating_members}"
41
+ )
42
+
43
+ return members
44
+
45
+ def create_enum(self) -> IntEnum:
46
+ return IntEnum(self.name, self.members)
47
+
48
+
49
+ def declaration_from_enum(enum_type: EnumMeta) -> EnumDeclaration:
50
+ members: list[Enum] = list(enum_type)
51
+ return EnumDeclaration(
52
+ name=enum_type.__name__,
53
+ members={
54
+ member.name: member.value
55
+ for member in sorted(members, key=lambda member: member.value)
56
+ },
57
+ )