classiq 0.45.0__py3-none-any.whl → 0.46.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 (146) hide show
  1. classiq/__init__.py +0 -1
  2. classiq/_internals/__init__.py +20 -0
  3. classiq/_internals/authentication/authentication.py +11 -0
  4. classiq/analyzer/analyzer.py +12 -10
  5. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +1 -1
  6. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +1 -1
  7. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
  8. classiq/applications/libraries/qmci_library.py +4 -9
  9. classiq/execution/execution_session.py +68 -7
  10. classiq/executor.py +14 -2
  11. classiq/interface/_version.py +1 -1
  12. classiq/interface/backend/backend_preferences.py +189 -0
  13. classiq/interface/backend/quantum_backend_providers.py +38 -0
  14. classiq/interface/debug_info/debug_info.py +22 -2
  15. classiq/interface/exceptions.py +16 -1
  16. classiq/interface/executor/execution_preferences.py +18 -0
  17. classiq/interface/generator/application_apis/chemistry_declarations.py +1 -177
  18. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +0 -12
  19. classiq/interface/generator/application_apis/finance_declarations.py +8 -43
  20. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -78
  21. classiq/interface/generator/builtin_api_builder.py +0 -3
  22. classiq/interface/generator/functions/__init__.py +0 -2
  23. classiq/interface/generator/functions/builtins/__init__.py +0 -15
  24. classiq/interface/generator/generated_circuit_data.py +2 -0
  25. classiq/interface/generator/hardware/hardware_data.py +37 -0
  26. classiq/interface/generator/model/constraints.py +18 -1
  27. classiq/interface/generator/model/preferences/preferences.py +53 -1
  28. classiq/interface/generator/model/quantum_register.py +1 -1
  29. classiq/interface/generator/quantum_program.py +10 -2
  30. classiq/interface/generator/transpiler_basis_gates.py +4 -0
  31. classiq/interface/generator/types/builtin_enum_declarations.py +136 -21
  32. classiq/interface/generator/types/enum_declaration.py +1 -3
  33. classiq/interface/generator/types/struct_declaration.py +1 -3
  34. classiq/interface/hardware.py +5 -0
  35. classiq/interface/ide/visual_model.py +1 -1
  36. classiq/interface/model/classical_parameter_declaration.py +6 -0
  37. classiq/interface/model/inplace_binary_operation.py +0 -14
  38. classiq/interface/model/model.py +1 -18
  39. classiq/interface/model/port_declaration.py +4 -2
  40. classiq/interface/model/quantum_function_declaration.py +19 -6
  41. classiq/interface/model/quantum_lambda_function.py +11 -1
  42. classiq/interface/model/quantum_variable_declaration.py +1 -1
  43. classiq/model_expansions/__init__.py +0 -0
  44. classiq/model_expansions/atomic_expression_functions_defs.py +250 -0
  45. classiq/model_expansions/capturing/__init__.py +0 -0
  46. classiq/model_expansions/capturing/captured_var_manager.py +50 -0
  47. classiq/model_expansions/capturing/mangling_utils.py +17 -0
  48. classiq/model_expansions/capturing/propagated_var_stack.py +180 -0
  49. classiq/model_expansions/closure.py +160 -0
  50. classiq/model_expansions/debug_flag.py +3 -0
  51. classiq/model_expansions/evaluators/__init__.py +0 -0
  52. classiq/model_expansions/evaluators/arg_type_match.py +160 -0
  53. classiq/model_expansions/evaluators/argument_types.py +42 -0
  54. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  55. classiq/model_expansions/evaluators/control.py +144 -0
  56. classiq/model_expansions/evaluators/parameter_types.py +227 -0
  57. classiq/model_expansions/evaluators/quantum_type_utils.py +235 -0
  58. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  59. classiq/model_expansions/expression_evaluator.py +125 -0
  60. classiq/model_expansions/expression_renamer.py +76 -0
  61. classiq/model_expansions/function_builder.py +192 -0
  62. classiq/model_expansions/generative_functions.py +101 -0
  63. classiq/model_expansions/interpreter.py +365 -0
  64. classiq/model_expansions/model_tables.py +105 -0
  65. classiq/model_expansions/quantum_operations/__init__.py +19 -0
  66. classiq/model_expansions/quantum_operations/bind.py +64 -0
  67. classiq/model_expansions/quantum_operations/classicalif.py +39 -0
  68. classiq/model_expansions/quantum_operations/control.py +235 -0
  69. classiq/model_expansions/quantum_operations/emitter.py +215 -0
  70. classiq/model_expansions/quantum_operations/expression_operation.py +218 -0
  71. classiq/model_expansions/quantum_operations/inplace_binary_operation.py +250 -0
  72. classiq/model_expansions/quantum_operations/invert.py +38 -0
  73. classiq/model_expansions/quantum_operations/power.py +74 -0
  74. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +174 -0
  75. classiq/model_expansions/quantum_operations/quantum_function_call.py +15 -0
  76. classiq/model_expansions/quantum_operations/repeat.py +33 -0
  77. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  78. classiq/model_expansions/quantum_operations/within_apply.py +46 -0
  79. classiq/model_expansions/scope.py +226 -0
  80. classiq/model_expansions/scope_initialization.py +136 -0
  81. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  82. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  83. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +150 -0
  84. classiq/model_expansions/sympy_conversion/sympy_to_python.py +113 -0
  85. classiq/model_expansions/utils/__init__.py +0 -0
  86. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  87. classiq/model_expansions/visitors/__init__.py +0 -0
  88. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  89. classiq/model_expansions/visitors/variable_references.py +115 -0
  90. classiq/qmod/__init__.py +1 -3
  91. classiq/qmod/builtins/enums.py +33 -2
  92. classiq/qmod/builtins/functions/__init__.py +251 -0
  93. classiq/qmod/builtins/functions/amplitude_estimation.py +26 -0
  94. classiq/qmod/builtins/functions/arithmetic.py +68 -0
  95. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  96. classiq/qmod/builtins/functions/chemistry.py +91 -0
  97. classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +105 -0
  98. classiq/qmod/builtins/functions/exponentiation.py +110 -0
  99. classiq/qmod/builtins/functions/finance.py +34 -0
  100. classiq/qmod/builtins/functions/grover.py +179 -0
  101. classiq/qmod/builtins/functions/hea.py +59 -0
  102. classiq/qmod/builtins/functions/linear_pauli_rotation.py +65 -0
  103. classiq/qmod/builtins/functions/modular_exponentiation.py +137 -0
  104. classiq/qmod/builtins/functions/operators.py +22 -0
  105. classiq/qmod/builtins/functions/qaoa_penalty.py +116 -0
  106. classiq/qmod/builtins/functions/qft.py +23 -0
  107. classiq/qmod/builtins/functions/qpe.py +39 -0
  108. classiq/qmod/builtins/functions/qsvm.py +24 -0
  109. classiq/qmod/builtins/functions/qsvt.py +136 -0
  110. classiq/qmod/builtins/functions/standard_gates.py +739 -0
  111. classiq/qmod/builtins/functions/state_preparation.py +356 -0
  112. classiq/qmod/builtins/functions/swap_test.py +25 -0
  113. classiq/qmod/builtins/structs.py +50 -28
  114. classiq/qmod/cparam.py +64 -0
  115. classiq/qmod/create_model_function.py +190 -0
  116. classiq/qmod/declaration_inferrer.py +52 -81
  117. classiq/qmod/expression_query.py +16 -0
  118. classiq/qmod/generative.py +48 -0
  119. classiq/qmod/model_state_container.py +1 -2
  120. classiq/qmod/native/pretty_printer.py +7 -11
  121. classiq/qmod/pretty_print/pretty_printer.py +7 -11
  122. classiq/qmod/python_classical_type.py +67 -0
  123. classiq/qmod/qfunc.py +19 -4
  124. classiq/qmod/qmod_parameter.py +15 -64
  125. classiq/qmod/qmod_variable.py +28 -46
  126. classiq/qmod/quantum_callable.py +1 -1
  127. classiq/qmod/quantum_expandable.py +10 -4
  128. classiq/qmod/quantum_function.py +22 -40
  129. classiq/qmod/semantics/error_manager.py +22 -10
  130. classiq/qmod/semantics/static_semantics_visitor.py +10 -12
  131. classiq/qmod/semantics/validation/types_validation.py +6 -7
  132. classiq/qmod/utilities.py +2 -2
  133. classiq/qmod/write_qmod.py +14 -0
  134. classiq/show.py +10 -0
  135. classiq/synthesis.py +46 -2
  136. {classiq-0.45.0.dist-info → classiq-0.46.0.dist-info}/METADATA +1 -1
  137. {classiq-0.45.0.dist-info → classiq-0.46.0.dist-info}/RECORD +138 -74
  138. classiq/interface/generator/functions/builtins/core_library/__init__.py +0 -16
  139. classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +0 -710
  140. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +0 -105
  141. classiq/interface/generator/functions/builtins/open_lib_functions.py +0 -2489
  142. classiq/interface/generator/functions/builtins/quantum_operators.py +0 -24
  143. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  144. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -21
  145. classiq/qmod/builtins/functions.py +0 -1029
  146. {classiq-0.45.0.dist-info → classiq-0.46.0.dist-info}/WHEEL +0 -0
@@ -1,14 +1,4 @@
1
- import sys
2
- from typing import ( # type: ignore[attr-defined]
3
- TYPE_CHECKING,
4
- Any,
5
- Generic,
6
- TypeVar,
7
- Union,
8
- _GenericAlias,
9
- )
10
-
11
- from typing_extensions import ParamSpec
1
+ from typing import TYPE_CHECKING, Any, Union
12
2
 
13
3
  from classiq.interface.exceptions import ClassiqValueError
14
4
  from classiq.interface.generator.functions.classical_type import (
@@ -19,65 +9,29 @@ from classiq.interface.generator.functions.classical_type import (
19
9
  Integer,
20
10
  Real,
21
11
  )
22
- from classiq.interface.generator.functions.type_name import TypeName
23
-
24
- from classiq import Struct, StructDeclaration
12
+ from classiq.interface.generator.functions.type_name import Struct, TypeName
13
+
14
+ from classiq.qmod.builtins.structs import BUILTIN_STRUCT_DECLARATIONS
15
+ from classiq.qmod.cparam import ( # noqa: F401
16
+ Array,
17
+ ArrayBase,
18
+ CArray,
19
+ CBool,
20
+ CInt,
21
+ CParam,
22
+ CParamScalar,
23
+ CReal,
24
+ )
25
25
  from classiq.qmod.model_state_container import ModelStateContainer
26
26
  from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
27
27
 
28
- _T = TypeVar("_T")
29
-
30
28
  if TYPE_CHECKING:
31
- from classiq.qmod.qmod_variable import QNum
32
29
 
33
30
  SymbolicSuperclass = SymbolicExpr
34
31
  else:
35
32
  SymbolicSuperclass = Symbolic
36
33
 
37
34
 
38
- class CParam(SymbolicSuperclass):
39
- def __init__(self, expr: str) -> None:
40
- super().__init__(expr, False)
41
-
42
-
43
- class CInt(CParam):
44
- pass
45
-
46
-
47
- class CReal(CParam):
48
- pass
49
-
50
-
51
- class CBool(CParam):
52
- pass
53
-
54
-
55
- _P = ParamSpec("_P")
56
-
57
-
58
- class ArrayBase(Generic[_P]):
59
- # Support comma-separated generic args in older Python versions
60
- if sys.version_info[0:2] < (3, 10):
61
-
62
- def __class_getitem__(cls, args) -> _GenericAlias:
63
- return _GenericAlias(cls, args)
64
-
65
-
66
- class CArray(CParam, ArrayBase[_P]):
67
- if TYPE_CHECKING:
68
-
69
- @property
70
- def len(self) -> int: ...
71
-
72
- def __getitem__(self, idx: Union[int, CInt, slice, "QNum"]) -> Any: ...
73
-
74
-
75
- class CParamScalar(CParam, SymbolicExpr):
76
-
77
- def __hash__(self) -> int:
78
- return hash(str(self))
79
-
80
-
81
35
  class CParamList(CParam):
82
36
  def __init__(
83
37
  self,
@@ -133,7 +87,7 @@ class CParamStruct(CParam):
133
87
  struct_name: str,
134
88
  field_name: str,
135
89
  ) -> CParam:
136
- struct_decl = StructDeclaration.BUILTIN_STRUCT_DECLARATIONS.get(
90
+ struct_decl = BUILTIN_STRUCT_DECLARATIONS.get(
137
91
  struct_name, qmodule.type_decls.get(struct_name)
138
92
  )
139
93
  assert struct_decl is not None
@@ -162,9 +116,6 @@ def create_param(
162
116
  return CParamScalar(expr_str)
163
117
 
164
118
 
165
- Array = CArray
166
-
167
-
168
119
  def get_qmod_type(ctype: ClassicalType) -> type:
169
120
  if isinstance(ctype, Integer):
170
121
  return CInt
@@ -57,24 +57,18 @@ from classiq.interface.model.quantum_type import (
57
57
  )
58
58
  from classiq.interface.source_reference import SourceReference
59
59
 
60
+ from classiq.qmod.cparam import ArrayBase, CBool, CInt, CParamScalar
61
+ from classiq.qmod.generative import (
62
+ generative_mode_context,
63
+ get_frontend_interpreter,
64
+ is_generative_mode,
65
+ )
60
66
  from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
61
- from classiq.qmod.qmod_parameter import ArrayBase, CBool, CInt, CParamScalar
62
67
  from classiq.qmod.quantum_callable import QCallable
63
68
  from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
64
69
  from classiq.qmod.symbolic_type import SymbolicTypes
65
70
  from classiq.qmod.utilities import get_source_ref, version_portable_get_args
66
71
 
67
- QVAR_PROPERTIES_ARE_SYMBOLIC = True
68
-
69
-
70
- @contextmanager
71
- def set_symbolic_qvar_properties(symbolic: bool) -> Iterator[None]:
72
- global QVAR_PROPERTIES_ARE_SYMBOLIC
73
- previous_symbolic = QVAR_PROPERTIES_ARE_SYMBOLIC
74
- QVAR_PROPERTIES_ARE_SYMBOLIC = symbolic
75
- yield
76
- QVAR_PROPERTIES_ARE_SYMBOLIC = previous_symbolic
77
-
78
72
 
79
73
  def _is_input_output_typehint(type_hint: Any) -> bool:
80
74
  return isinstance(type_hint, _AnnotatedAlias) and isinstance(
@@ -101,6 +95,10 @@ def _no_current_expandable() -> Iterator[None]:
101
95
  QCallable.CURRENT_EXPANDABLE = current_expandable
102
96
 
103
97
 
98
+ def _evaluate_expression(expr: str) -> Any:
99
+ return get_frontend_interpreter().evaluate(Expression(expr=expr)).value
100
+
101
+
104
102
  class QVar(Symbolic):
105
103
  def __init__(
106
104
  self,
@@ -171,14 +169,11 @@ class QVar(Symbolic):
171
169
 
172
170
  @property
173
171
  def size(self) -> Union[CParamScalar, int]:
174
- if not QVAR_PROPERTIES_ARE_SYMBOLIC:
175
- return self._evaluate_size()
172
+ if is_generative_mode():
173
+ with generative_mode_context(False):
174
+ return _evaluate_expression(str(self.size))
176
175
  return CParamScalar(f"get_field({self}, 'size')")
177
176
 
178
- @abc.abstractmethod
179
- def _evaluate_size(self) -> int:
180
- raise NotImplementedError
181
-
182
177
 
183
178
  _Q = TypeVar("_Q", bound=QVar)
184
179
  Output = Annotated[_Q, PortDeclarationDirection.Output]
@@ -269,9 +264,6 @@ class QBit(QScalar):
269
264
  def get_qmod_type(self) -> QuantumType:
270
265
  return QuantumBit()
271
266
 
272
- def _evaluate_size(self) -> int:
273
- return 1
274
-
275
267
 
276
268
  _P = ParamSpec("_P")
277
269
 
@@ -358,25 +350,18 @@ class QNum(Generic[_P], QScalar):
358
350
  fraction_digits=self._fraction_digits,
359
351
  )
360
352
 
361
- def _evaluate_size(self) -> int:
362
- if TYPE_CHECKING:
363
- assert self._size is not None
364
- return self._size.to_int_value()
365
-
366
353
  @property
367
354
  def fraction_digits(self) -> Union[CParamScalar, int]:
368
- if not QVAR_PROPERTIES_ARE_SYMBOLIC:
369
- if TYPE_CHECKING:
370
- assert self._fraction_digits is not None
371
- return self._fraction_digits.to_int_value()
355
+ if is_generative_mode():
356
+ with generative_mode_context(False):
357
+ return _evaluate_expression(str(self.fraction_digits))
372
358
  return CParamScalar(f"get_field({self}, 'fraction_digits')")
373
359
 
374
360
  @property
375
361
  def is_signed(self) -> Union[CParamScalar, bool]:
376
- if not QVAR_PROPERTIES_ARE_SYMBOLIC:
377
- if TYPE_CHECKING:
378
- assert self._is_signed is not None
379
- return self._is_signed.to_bool_value()
362
+ if is_generative_mode():
363
+ with generative_mode_context(False):
364
+ return _evaluate_expression(str(self.is_signed))
380
365
  return CParamScalar(f"get_field({self}, 'is_signed')")
381
366
 
382
367
  # Support comma-separated generic args in older Python versions
@@ -479,17 +464,13 @@ class QArray(ArrayBase[_P], QVar):
479
464
 
480
465
  @property
481
466
  def len(self) -> Union[CParamScalar, int]:
482
- if not QVAR_PROPERTIES_ARE_SYMBOLIC:
483
- return self._length.to_int_value()
467
+ if is_generative_mode():
468
+ with generative_mode_context(False):
469
+ return _evaluate_expression(str(self.len))
484
470
  if self._length is not None:
485
471
  return CParamScalar(f"{self._length}")
486
472
  return CParamScalar(f"get_field({self}, 'len')")
487
473
 
488
- def _evaluate_size(self) -> int:
489
- if TYPE_CHECKING:
490
- assert self._length is not None
491
- return self._element_type.size_in_bits * self._length.to_int_value()
492
-
493
474
  @classmethod
494
475
  def _get_attributes(cls, type_hint: Any) -> Tuple[Type[QVar], Any]:
495
476
  type_args = version_portable_get_args(type_hint)
@@ -559,7 +540,7 @@ class QStruct(QVar):
559
540
  self._fields = _fields
560
541
  for field_name, var in _fields.items():
561
542
  setattr(self, field_name, var)
562
- super().__init__(name)
543
+ super().__init__(name, expr_str=_expr_str)
563
544
  self._add_qmod_qstruct(qmodule=QMODULE)
564
545
 
565
546
  def get_qmod_type(self) -> QuantumType:
@@ -611,16 +592,17 @@ class QStruct(QVar):
611
592
  )
612
593
 
613
594
  def _add_qmod_qstruct(self, *, qmodule: ModelStateContainer) -> None:
595
+ from classiq.model_expansions.model_tables import SymbolTable
596
+
614
597
  if self._struct_name in qmodule.qstruct_decls:
615
598
  return
616
599
 
617
- qmodule.qstruct_decls[self._struct_name] = QStructDeclaration(
600
+ struct_decl = QStructDeclaration(
618
601
  name=self._struct_name,
619
602
  fields={name: qvar.get_qmod_type() for name, qvar in self._fields.items()},
620
603
  )
621
-
622
- def _evaluate_size(self) -> int:
623
- return sum(var._evaluate_size() for var in self._fields.values())
604
+ qmodule.qstruct_decls[self._struct_name] = struct_decl
605
+ SymbolTable.qstruct_table[self._struct_name] = struct_decl
624
606
 
625
607
 
626
608
  def create_qvar_for_port_decl(port: AnonPortDeclaration, name: str) -> QVar:
@@ -20,7 +20,7 @@ from classiq.interface.model.quantum_statement import QuantumStatement
20
20
  from classiq.interface.model.quantum_type import QuantumType
21
21
  from classiq.interface.source_reference import SourceReference
22
22
 
23
- from classiq.qmod.qmod_parameter import CInt
23
+ from classiq.qmod.cparam import CInt
24
24
  from classiq.qmod.utilities import get_source_ref
25
25
 
26
26
  if TYPE_CHECKING:
@@ -46,6 +46,7 @@ from classiq.interface.model.variable_declaration_statement import (
46
46
  )
47
47
  from classiq.interface.source_reference import SourceReference
48
48
 
49
+ from classiq.qmod.generative import generative_mode_context, is_generative_mode
49
50
  from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
50
51
  from classiq.qmod.qmod_constant import QConstant
51
52
  from classiq.qmod.qmod_parameter import (
@@ -58,7 +59,6 @@ from classiq.qmod.qmod_parameter import (
58
59
  from classiq.qmod.qmod_variable import (
59
60
  QVar,
60
61
  create_qvar_for_port_decl,
61
- set_symbolic_qvar_properties,
62
62
  )
63
63
  from classiq.qmod.quantum_callable import QCallable, QExpandableInterface
64
64
  from classiq.qmod.symbolic_expr import SymbolicExpr
@@ -99,7 +99,7 @@ class QExpandable(QCallable, QExpandableInterface, ABC):
99
99
 
100
100
  def expand(self) -> None:
101
101
  if self not in QExpandable.STACK:
102
- with self, set_symbolic_qvar_properties(True):
102
+ with self, generative_mode_context(False):
103
103
  self._py_callable(*self._get_positional_args())
104
104
 
105
105
  def infer_rename_params(self) -> Optional[List[str]]:
@@ -111,7 +111,7 @@ class QExpandable(QCallable, QExpandableInterface, ABC):
111
111
  qtype: QuantumType,
112
112
  source_ref: Optional[SourceReference] = None,
113
113
  ) -> None:
114
- self._body.append(
114
+ self.append_statement_to_body(
115
115
  VariableDeclarationStatement(
116
116
  name=name, quantum_type=qtype, source_ref=source_ref
117
117
  )
@@ -161,6 +161,10 @@ class QLambdaFunction(QExpandable):
161
161
  def func_decl(self) -> AnonQuantumFunctionDeclaration:
162
162
  return self._decl
163
163
 
164
+ def expand(self) -> None:
165
+ if not is_generative_mode():
166
+ super().expand()
167
+
164
168
  def infer_rename_params(self) -> List[str]:
165
169
  return inspect.getfullargspec(self._py_callable).args
166
170
 
@@ -302,10 +306,12 @@ def prepare_arg(
302
306
  new_arg_decl = decl_without_type_attributes(arg_decl)
303
307
  val = QLambdaFunction(new_arg_decl, val)
304
308
  val.expand()
305
- return QuantumLambdaFunction(
309
+ qlambda = QuantumLambdaFunction(
306
310
  pos_rename_params=val.infer_rename_params(),
307
311
  body=val.body,
308
312
  )
313
+ qlambda.set_py_callable(val._py_callable)
314
+ return qlambda
309
315
 
310
316
  if isinstance(val, QExpandable):
311
317
  val.expand()
@@ -9,50 +9,20 @@ from classiq.interface.exceptions import ClassiqError
9
9
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
10
10
  from classiq.interface.generator.model.constraints import Constraints
11
11
  from classiq.interface.generator.model.preferences.preferences import Preferences
12
- from classiq.interface.model.model import Model, SerializedModel
12
+ from classiq.interface.model.model import Model
13
13
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
14
14
  from classiq.interface.model.quantum_function_declaration import (
15
15
  NamedParamsQuantumFunctionDeclaration,
16
- QuantumFunctionDeclaration,
17
16
  )
18
17
 
19
18
  from classiq.qmod.classical_function import CFunc
20
19
  from classiq.qmod.declaration_inferrer import infer_func_decl
21
- from classiq.qmod.model_state_container import QMODULE
22
20
  from classiq.qmod.qmod_constant import QConstant
23
21
  from classiq.qmod.qmod_parameter import CArray, CParam
24
22
  from classiq.qmod.qmod_variable import QVar
25
23
  from classiq.qmod.quantum_callable import QCallable, QCallableList
26
24
  from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
27
- from classiq.qmod.utilities import mangle_keyword, unmangle_keyword
28
- from classiq.qmod.write_qmod import write_qmod
29
-
30
-
31
- def _lookup_qfunc(name: str) -> Optional[NamedParamsQuantumFunctionDeclaration]:
32
- # FIXME: to be generalized to existing user-defined functions
33
- return QuantumFunctionDeclaration.BUILTIN_FUNCTION_DECLARATIONS.get(name)
34
-
35
-
36
- def create_model(
37
- entry_point: "QFunc",
38
- constraints: Optional[Constraints] = None,
39
- execution_preferences: Optional[ExecutionPreferences] = None,
40
- preferences: Optional[Preferences] = None,
41
- classical_execution_function: Optional[CFunc] = None,
42
- out_file: Optional[str] = None,
43
- ) -> SerializedModel:
44
- if entry_point.func_decl.name != "main":
45
- raise ClassiqError(
46
- f"The entry point function must be named 'main', got '{entry_point.func_decl.name}'"
47
- )
48
- result = entry_point.create_model(
49
- constraints, execution_preferences, preferences, classical_execution_function
50
- ).get_model()
51
-
52
- if out_file is not None:
53
- write_qmod(result, out_file)
54
-
55
- return result
25
+ from classiq.qmod.utilities import mangle_keyword
56
26
 
57
27
 
58
28
  class QFunc(QExpandable):
@@ -142,10 +112,10 @@ class QFunc(QExpandable):
142
112
 
143
113
 
144
114
  class ExternalQFunc(QTerminalCallable):
115
+ _decl: NamedParamsQuantumFunctionDeclaration
116
+
145
117
  def __init__(self, py_callable: Callable) -> None:
146
- decl = _lookup_qfunc(unmangle_keyword(py_callable.__name__))
147
- if decl is None:
148
- raise ClassiqError(f"Definition of {py_callable.__name__!r} not found")
118
+ decl = infer_func_decl(py_callable)
149
119
 
150
120
  py_callable.__annotations__.pop("return", None)
151
121
  if py_callable.__annotations__.keys() != {
@@ -157,13 +127,25 @@ class ExternalQFunc(QTerminalCallable):
157
127
  super().__init__(decl)
158
128
  functools.update_wrapper(self, py_callable)
159
129
 
130
+ @property
131
+ def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
132
+ return self._decl
160
133
 
161
- class GenerativeQFunc(QTerminalCallable):
162
- func_decl: NamedParamsQuantumFunctionDeclaration
163
134
 
164
- def __init__(self, py_callable: Callable) -> None:
165
- super().__init__(infer_func_decl(py_callable, QMODULE))
166
- self.py_callable = py_callable
135
+ class GenerativeQFunc(QExpandable):
136
+ def __init__(
137
+ self,
138
+ py_callable: Callable,
139
+ func_decl: Optional[NamedParamsQuantumFunctionDeclaration] = None,
140
+ ) -> None:
141
+ super().__init__(py_callable)
142
+ self._func_decl = func_decl
143
+
144
+ @property
145
+ def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
146
+ if self._func_decl is None:
147
+ self._func_decl = infer_func_decl(self._py_callable, self._qmodule)
148
+ return self._func_decl
167
149
 
168
150
 
169
151
  ILLEGAL_PARAM_ERROR = "Unsupported type hint '{annotation}' for argument '{name}'."
@@ -2,6 +2,7 @@ from contextlib import contextmanager
2
2
  from typing import Iterator, List, Optional, Type
3
3
 
4
4
  from classiq.interface.ast_node import ASTNode
5
+ from classiq.interface.exceptions import CLASSIQ_SLACK_COMMUNITY_LINK
5
6
  from classiq.interface.source_reference import SourceReferencedError
6
7
 
7
8
 
@@ -18,23 +19,34 @@ class ErrorManager:
18
19
  self._errors: List[SourceReferencedError] = []
19
20
  self._current_nodes_stack: List[ASTNode] = []
20
21
  self._call_stack: List[str] = []
22
+ self._ignore_errors: bool = False
23
+
24
+ @contextmanager
25
+ def ignore_errors_context(self) -> Iterator[None]:
26
+ previous = self._ignore_errors
27
+ self._ignore_errors = True
28
+ try:
29
+ yield
30
+ finally:
31
+ self._ignore_errors = previous
21
32
 
22
33
  @property
23
34
  def annotated_errors(self) -> List[str]:
24
35
  return [str(error) for error in self._errors]
25
36
 
26
37
  def add_error(self, error: str) -> None:
27
- self._errors.append(
28
- SourceReferencedError(
29
- error=error,
30
- source_ref=(
31
- self._current_nodes_stack[-1].source_ref
32
- if self._current_nodes_stack
33
- else None
34
- ),
35
- function=self.current_function,
38
+ if not self._ignore_errors:
39
+ self._errors.append(
40
+ SourceReferencedError(
41
+ error=error.replace(CLASSIQ_SLACK_COMMUNITY_LINK, ""),
42
+ source_ref=(
43
+ self._current_nodes_stack[-1].source_ref
44
+ if self._current_nodes_stack
45
+ else None
46
+ ),
47
+ function=self.current_function,
48
+ )
36
49
  )
37
- )
38
50
 
39
51
  def get_errors(self) -> List[SourceReferencedError]:
40
52
  return self._errors
@@ -19,6 +19,9 @@ from classiq.interface.generator.functions.port_declaration import (
19
19
  PortDeclarationDirection,
20
20
  )
21
21
  from classiq.interface.generator.visitor import Visitor
22
+ from classiq.interface.model.classical_parameter_declaration import (
23
+ AnonClassicalParameterDeclaration,
24
+ )
22
25
  from classiq.interface.model.handle_binding import (
23
26
  FieldHandleBinding,
24
27
  HandleBinding,
@@ -45,7 +48,7 @@ from classiq.interface.model.variable_declaration_statement import (
45
48
  )
46
49
  from classiq.interface.model.within_apply_operation import WithinApply
47
50
 
48
- from classiq import AnonClassicalParameterDeclaration
51
+ from classiq.qmod.builtins.functions import BUILTIN_FUNCTION_DECLARATIONS
49
52
  from classiq.qmod.semantics.annotation import annotate_function_call_decl
50
53
  from classiq.qmod.semantics.error_manager import ErrorManager
51
54
  from classiq.qmod.semantics.validation.func_call_validation import (
@@ -352,23 +355,18 @@ def resolve_function_calls(
352
355
  root: Any,
353
356
  quantum_function_dict: Mapping[str, QuantumFunctionDeclaration],
354
357
  ) -> None:
355
- StaticSemanticsVisitor(
356
- {
357
- **QuantumFunctionDeclaration.BUILTIN_FUNCTION_DECLARATIONS,
358
- **quantum_function_dict,
359
- },
360
- [],
361
- ).visit(root)
358
+ with ErrorManager().ignore_errors_context():
359
+ StaticSemanticsVisitor(
360
+ {**BUILTIN_FUNCTION_DECLARATIONS, **quantum_function_dict},
361
+ [],
362
+ ).visit(root)
362
363
 
363
364
 
364
365
  def static_semantics_analysis_pass(
365
366
  model: Model, error_type: Optional[Type[Exception]] = ClassiqSemanticError
366
367
  ) -> None:
367
368
  StaticSemanticsVisitor(
368
- {
369
- **QuantumFunctionDeclaration.BUILTIN_FUNCTION_DECLARATIONS,
370
- **model.function_dict,
371
- },
369
+ {**BUILTIN_FUNCTION_DECLARATIONS, **model.function_dict},
372
370
  [const.name for const in model.constants],
373
371
  ).visit(model)
374
372
  if error_type is not None:
@@ -1,10 +1,13 @@
1
1
  from typing import Sequence, Union
2
2
 
3
3
  from classiq.interface.generator.functions.type_name import TypeName
4
+ from classiq.interface.generator.types.enum_declaration import EnumDeclaration
4
5
  from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
6
+ from classiq.interface.generator.types.struct_declaration import StructDeclaration
5
7
  from classiq.interface.model.quantum_type import QuantumBitvector
6
8
 
7
- from classiq import EnumDeclaration, StructDeclaration
9
+ from classiq.qmod.builtins.enums import BUILTIN_ENUM_DECLARATIONS
10
+ from classiq.qmod.builtins.structs import BUILTIN_STRUCT_DECLARATIONS
8
11
  from classiq.qmod.model_state_container import QMODULE
9
12
  from classiq.qmod.semantics.error_manager import ErrorManager
10
13
 
@@ -12,12 +15,8 @@ from classiq.qmod.semantics.error_manager import ErrorManager
12
15
  def check_duplicate_types(
13
16
  types: Sequence[Union[EnumDeclaration, StructDeclaration, QStructDeclaration]]
14
17
  ) -> None:
15
- known_types = {
16
- type_.name for type_ in EnumDeclaration.BUILTIN_ENUM_DECLARATIONS.values()
17
- }
18
- known_types |= {
19
- type_.name for type_ in StructDeclaration.BUILTIN_STRUCT_DECLARATIONS.values()
20
- }
18
+ known_types = {type_.name for type_ in BUILTIN_ENUM_DECLARATIONS.values()}
19
+ known_types |= {type_.name for type_ in BUILTIN_STRUCT_DECLARATIONS.values()}
21
20
  for type_ in types:
22
21
  if type_.name in known_types:
23
22
  with ErrorManager().node_context(type_):
classiq/qmod/utilities.py CHANGED
@@ -44,10 +44,10 @@ def version_portable_get_args(py_type: type) -> tuple:
44
44
  else:
45
45
  type_args = get_args(py_type)[0]
46
46
  if not isinstance(type_args, tuple):
47
- return type_args
47
+ return (type_args,)
48
48
  return tuple(
49
49
  (
50
- version_portable_get_args(type_arg)
50
+ version_portable_get_args(type_arg)[0]
51
51
  if get_origin(type_arg) == Literal
52
52
  else type_arg
53
53
  )
@@ -17,6 +17,20 @@ def write_qmod(
17
17
  directory: Optional[Path] = None,
18
18
  decimal_precision: int = DEFAULT_DECIMAL_PRECISION,
19
19
  ) -> None:
20
+ """
21
+ Creates a native Qmod file from a serialized model and outputs the synthesis options (Preferences and Constraints) to a file.
22
+ The native Qmod file may be uploaded to the Classiq IDE.
23
+
24
+ Args:
25
+ serialized_model: The serialized model to write as a native Qmod file and synthesis options file.
26
+ name: The name to save the file by.
27
+ directory: The directory to save the files in. If None, the current working directory is used.
28
+ decimal_precision: The number of decimal places to use for numbers, set to 4 by default.
29
+
30
+ Returns:
31
+ None
32
+ """
33
+
20
34
  model = Model.parse_raw(serialized_model)
21
35
  pretty_printed_model = DSLPrettyPrinter(decimal_precision=decimal_precision).visit(
22
36
  model
classiq/show.py CHANGED
@@ -27,6 +27,16 @@ CANT_PARSE_QUANTUM_PROGRAM_MSG = (
27
27
 
28
28
 
29
29
  def show(quantum_program: SerializedQuantumProgram) -> None:
30
+ """
31
+ Displays the interactive representation of the quantum program in the Classiq IDE.
32
+
33
+ Args:
34
+ quantum_program:
35
+ The serialized quantum program to be displayed.
36
+
37
+ Links:
38
+ [Visualization tool](https://docs.classiq.io/latest/reference-manual/analyzer/quantum-program-visualization-tool/)
39
+ """
30
40
  try:
31
41
  circuit = QuantumProgram.parse_raw(quantum_program)
32
42
  except pydantic.error_wrappers.ValidationError as exc: