classiq 0.75.0__py3-none-any.whl → 0.76.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 (83) hide show
  1. classiq/_internals/api_wrapper.py +36 -0
  2. classiq/analyzer/show_interactive_hack.py +58 -2
  3. classiq/applications/chemistry/chemistry_model_constructor.py +8 -1
  4. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -0
  5. classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -4
  6. classiq/applications/qnn/gradients/quantum_gradient.py +3 -5
  7. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -2
  8. classiq/applications/qnn/qlayer.py +14 -19
  9. classiq/applications/qnn/types.py +1 -4
  10. classiq/execution/__init__.py +3 -0
  11. classiq/execution/execution_session.py +3 -16
  12. classiq/execution/qnn.py +2 -2
  13. classiq/execution/user_budgets.py +38 -0
  14. classiq/executor.py +7 -19
  15. classiq/interface/_version.py +1 -1
  16. classiq/interface/debug_info/debug_info.py +16 -2
  17. classiq/interface/executor/user_budget.py +56 -0
  18. classiq/interface/generator/application_apis/finance_declarations.py +3 -0
  19. classiq/interface/generator/expressions/atomic_expression_functions.py +3 -0
  20. classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +30 -124
  21. classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +45 -21
  22. classiq/interface/generator/expressions/proxies/classical/qmod_struct_instance.py +7 -0
  23. classiq/interface/generator/expressions/proxies/classical/utils.py +12 -11
  24. classiq/interface/generator/expressions/proxies/quantum/qmod_qscalar_proxy.py +9 -2
  25. classiq/interface/generator/expressions/proxies/quantum/qmod_sized_proxy.py +4 -1
  26. classiq/interface/generator/expressions/sympy_supported_expressions.py +1 -0
  27. classiq/interface/generator/functions/classical_type.py +6 -1
  28. classiq/interface/generator/functions/type_name.py +7 -2
  29. classiq/interface/generator/functions/type_qualifier.py +15 -0
  30. classiq/interface/generator/model/preferences/preferences.py +7 -0
  31. classiq/interface/generator/quantum_program.py +5 -19
  32. classiq/interface/helpers/backward_compatibility.py +9 -0
  33. classiq/interface/helpers/datastructures.py +6 -0
  34. classiq/interface/model/port_declaration.py +1 -2
  35. classiq/interface/model/quantum_lambda_function.py +2 -1
  36. classiq/interface/server/routes.py +6 -0
  37. classiq/model_expansions/atomic_expression_functions_defs.py +62 -19
  38. classiq/model_expansions/capturing/captured_vars.py +2 -0
  39. classiq/model_expansions/closure.py +5 -0
  40. classiq/model_expansions/evaluators/classical_type_inference.py +17 -6
  41. classiq/model_expansions/evaluators/parameter_types.py +26 -13
  42. classiq/model_expansions/expression_evaluator.py +1 -1
  43. classiq/model_expansions/generative_functions.py +61 -34
  44. classiq/model_expansions/interpreters/base_interpreter.py +17 -6
  45. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +5 -0
  46. classiq/model_expansions/interpreters/generative_interpreter.py +13 -1
  47. classiq/model_expansions/quantum_operations/allocate.py +6 -1
  48. classiq/model_expansions/quantum_operations/assignment_result_processor.py +219 -20
  49. classiq/model_expansions/quantum_operations/bind.py +54 -30
  50. classiq/model_expansions/quantum_operations/block_evaluator.py +42 -0
  51. classiq/model_expansions/quantum_operations/call_emitter.py +14 -7
  52. classiq/model_expansions/quantum_operations/composite_emitter.py +1 -1
  53. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +23 -9
  54. classiq/model_expansions/quantum_operations/emitter.py +20 -3
  55. classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -3
  56. classiq/model_expansions/scope.py +10 -7
  57. classiq/model_expansions/sympy_conversion/arithmetics.py +18 -0
  58. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +2 -0
  59. classiq/model_expansions/sympy_conversion/sympy_to_python.py +10 -1
  60. classiq/model_expansions/transformers/model_renamer.py +45 -7
  61. classiq/model_expansions/utils/handles_collector.py +1 -1
  62. classiq/model_expansions/visitors/variable_references.py +45 -9
  63. classiq/qmod/builtins/functions/allocation.py +2 -2
  64. classiq/qmod/builtins/functions/arithmetic.py +14 -12
  65. classiq/qmod/builtins/functions/standard_gates.py +23 -23
  66. classiq/qmod/declaration_inferrer.py +19 -7
  67. classiq/qmod/generative.py +9 -1
  68. classiq/qmod/native/expression_to_qmod.py +4 -0
  69. classiq/qmod/native/pretty_printer.py +8 -3
  70. classiq/qmod/pretty_print/pretty_printer.py +1 -1
  71. classiq/qmod/python_classical_type.py +4 -5
  72. classiq/qmod/qmod_constant.py +15 -7
  73. classiq/qmod/qmod_variable.py +7 -1
  74. classiq/qmod/quantum_function.py +19 -6
  75. classiq/qmod/semantics/lambdas.py +6 -2
  76. classiq/qmod/semantics/validation/main_validation.py +17 -4
  77. classiq/qmod/symbolic.py +8 -19
  78. classiq/qmod/symbolic_expr.py +26 -0
  79. classiq/synthesis.py +17 -31
  80. classiq/visualization.py +35 -0
  81. {classiq-0.75.0.dist-info → classiq-0.76.0.dist-info}/METADATA +1 -1
  82. {classiq-0.75.0.dist-info → classiq-0.76.0.dist-info}/RECORD +83 -79
  83. {classiq-0.75.0.dist-info → classiq-0.76.0.dist-info}/WHEEL +0 -0
@@ -264,7 +264,7 @@ class PythonPrettyPrinter(ModelVisitor):
264
264
  if port_decl.direction is not PortDeclarationDirection.Inout:
265
265
  self._imports[port_decl.direction.name] = 1
266
266
  var_type = f"{port_decl.direction.name}[{var_type}]"
267
- if port_decl.type_qualifier is not TypeQualifier.Quantum:
267
+ if port_decl.type_qualifier in [TypeQualifier.Const, TypeQualifier.QFree]:
268
268
  self._imports[port_decl.type_qualifier.name] = 1
269
269
  var_type = f"{port_decl.type_qualifier.name}[{var_type}]"
270
270
  return var_type
@@ -19,7 +19,7 @@ from classiq.interface.generator.functions.classical_type import (
19
19
  Real,
20
20
  )
21
21
  from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
22
- from classiq.interface.generator.functions.type_name import Enum, Struct
22
+ from classiq.interface.generator.functions.type_name import Enum, Struct, TypeName
23
23
 
24
24
  from classiq.qmod.cparam import CArray, CBool, CInt, CReal
25
25
  from classiq.qmod.utilities import version_portable_get_args
@@ -59,8 +59,7 @@ class PythonClassicalType:
59
59
  )
60
60
  raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
61
61
  elif inspect.isclass(py_type) and dataclasses.is_dataclass(py_type):
62
- self.register_struct(py_type)
63
- return Struct(name=py_type.__name__)
62
+ return self.register_struct(py_type)
64
63
  elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
65
64
  self.register_enum(py_type)
66
65
  return Enum(name=py_type.__name__)
@@ -68,8 +67,8 @@ class PythonClassicalType:
68
67
  raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
69
68
  return None
70
69
 
71
- def register_struct(self, py_type: type) -> None:
72
- pass
70
+ def register_struct(self, py_type: type) -> TypeName:
71
+ return Struct(name=py_type.__name__)
73
72
 
74
73
  def register_enum(self, py_type: EnumMeta) -> None:
75
74
  pass
@@ -1,6 +1,6 @@
1
1
  import inspect
2
2
  from dataclasses import is_dataclass
3
- from typing import Any, Optional, cast, get_origin
3
+ from typing import TYPE_CHECKING, Any, Optional, cast, get_origin
4
4
 
5
5
  from classiq.interface.exceptions import ClassiqError, ClassiqValueError
6
6
  from classiq.interface.generator.constant import Constant
@@ -17,7 +17,7 @@ from classiq.qmod.generative import (
17
17
  interpret_expression,
18
18
  is_generative_mode,
19
19
  )
20
- from classiq.qmod.model_state_container import ModelStateContainer
20
+ from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
21
21
  from classiq.qmod.qmod_parameter import CParam, CParamList, CParamStruct
22
22
  from classiq.qmod.symbolic_expr import SymbolicExpr
23
23
  from classiq.qmod.utilities import qmod_val_to_expr_str
@@ -42,11 +42,12 @@ class QConstant(SymbolicExpr):
42
42
 
43
43
  def add_to_model(self) -> None:
44
44
  from classiq.qmod.builtins.constants import __all__ as builtin_constants
45
+ from classiq.qmod.semantics.validation.constants_validation import (
46
+ check_duplicate_constants,
47
+ )
45
48
 
46
- if self.name in builtin_constants:
49
+ if self.name in builtin_constants or QConstant.CURRENT_QMODULE is None:
47
50
  return
48
- if QConstant.CURRENT_QMODULE is None:
49
- raise ClassiqError(QMODULE_ERROR_MESSAGE)
50
51
 
51
52
  expr = qmod_val_to_expr_str(self._value)
52
53
  if (
@@ -57,6 +58,7 @@ class QConstant(SymbolicExpr):
57
58
 
58
59
  constant = self._get_constant_node()
59
60
  QConstant.CURRENT_QMODULE.constants[self.name] = constant
61
+ check_duplicate_constants([constant])
60
62
  if is_generative_mode():
61
63
  get_frontend_interpreter().add_constant(constant)
62
64
 
@@ -106,8 +108,10 @@ class QConstant(SymbolicExpr):
106
108
  def __getitem__(self, item: Any) -> CParam:
107
109
  self.add_to_model()
108
110
 
109
- assert QConstant.CURRENT_QMODULE is not None
110
-
111
+ if QConstant.CURRENT_QMODULE is None:
112
+ QConstant.set_current_model(QMODULE)
113
+ if TYPE_CHECKING:
114
+ assert QConstant.CURRENT_QMODULE is not None
111
115
  qmod_type = python_type_to_qmod(
112
116
  self._py_type, qmodule=QConstant.CURRENT_QMODULE
113
117
  )
@@ -141,3 +145,7 @@ class QConstant(SymbolicExpr):
141
145
  if is_generative_mode():
142
146
  return interpret_expression(len_expr)
143
147
  return cast(int, CParamScalar(len_expr))
148
+
149
+ def __str__(self) -> str:
150
+ self.add_to_model()
151
+ return super().__str__()
@@ -70,6 +70,8 @@ from classiq.qmod.generative import (
70
70
  )
71
71
  from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
72
72
  from classiq.qmod.quantum_callable import QCallable
73
+ from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
74
+ from classiq.qmod.semantics.validation.types_validation import validate_qstruct
73
75
  from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
74
76
  from classiq.qmod.symbolic_type import SymbolicTypes
75
77
  from classiq.qmod.utilities import (
@@ -696,6 +698,8 @@ def _register_qstruct(
696
698
  if type_hint is QStruct or struct_name in qmodule.qstruct_decls:
697
699
  return
698
700
 
701
+ # temp assignment for recursive qstruct definitions
702
+ qmodule.qstruct_decls[struct_name] = QStructDeclaration(name=struct_name)
699
703
  _validate_fields(type_hint)
700
704
  struct_decl = QStructDeclaration(
701
705
  name=struct_name,
@@ -705,6 +709,8 @@ def _register_qstruct(
705
709
  },
706
710
  )
707
711
  qmodule.qstruct_decls[struct_name] = struct_decl
712
+ QStructAnnotator().visit(struct_decl)
713
+ validate_qstruct(struct_decl)
708
714
 
709
715
 
710
716
  def _validate_fields(type_hint: type[QStruct]) -> None:
@@ -749,5 +755,5 @@ def _get_root_type(py_type: Any) -> type[QVar]:
749
755
  )
750
756
  root_type = get_origin(non_annotated_type) or non_annotated_type
751
757
  if not issubclass(root_type, QVar):
752
- raise ClassiqInternalError(f"Invalid quantum type {root_type}")
758
+ raise ClassiqValueError(f"Invalid quantum type {root_type.__name__!r}")
753
759
  return root_type
@@ -14,7 +14,7 @@ from classiq.interface.generator.functions.port_declaration import (
14
14
  from classiq.interface.generator.model.constraints import Constraints
15
15
  from classiq.interface.generator.model.preferences.preferences import Preferences
16
16
  from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
17
- from classiq.interface.model.model import Model
17
+ from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model
18
18
  from classiq.interface.model.native_function_definition import (
19
19
  NativeFunctionDefinition,
20
20
  )
@@ -31,6 +31,7 @@ from classiq.qmod.qmod_parameter import CArray
31
31
  from classiq.qmod.quantum_callable import QCallable, QCallableList
32
32
  from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
33
33
  from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
34
+ from classiq.qmod.semantics.validation.main_validation import validate_main_function
34
35
  from classiq.qmod.utilities import mangle_keyword
35
36
 
36
37
 
@@ -104,7 +105,7 @@ class QFunc(BaseQFunc):
104
105
  @property
105
106
  def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
106
107
  name = self._py_callable.__name__
107
- if hasattr(self._qmodule, "native_defs") and name in self._qmodule.native_defs:
108
+ if name in self._qmodule.native_defs:
108
109
  return self._qmodule.native_defs[name]
109
110
  return infer_func_decl(self._py_callable, qmodule=self._qmodule)
110
111
 
@@ -250,15 +251,23 @@ class GenerativeQFunc(BaseQFunc):
250
251
  ) -> None:
251
252
  super().__init__(py_callable, compilation_metadata)
252
253
  self._func_decl = func_decl
254
+ self._inferred_func_decl: Optional[NamedParamsQuantumFunctionDeclaration] = None
253
255
 
254
256
  @property
255
257
  def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
256
- if self._func_decl is None:
257
- self._func_decl = infer_func_decl(self._py_callable, self._qmodule)
258
- return self._func_decl
258
+ if self._func_decl is not None:
259
+ return self._func_decl
260
+ if self._inferred_func_decl is None:
261
+ self._inferred_func_decl = infer_func_decl(self._py_callable, self._qmodule)
262
+ return self._inferred_func_decl
259
263
 
260
264
  def __call__(self, *args: Any, **kwargs: Any) -> None:
261
- self._qmodule.generative_functions[self.func_decl.name] = self
265
+ if self.func_decl.name not in self._qmodule.generative_functions:
266
+ self._qmodule.generative_functions[self.func_decl.name] = self
267
+ if self._func_decl is None:
268
+ self._inferred_func_decl = infer_func_decl(
269
+ self._py_callable, self._qmodule
270
+ )
262
271
  super().__call__(*args, **kwargs)
263
272
 
264
273
  def create_model(
@@ -268,6 +277,10 @@ class GenerativeQFunc(BaseQFunc):
268
277
  preferences: Optional[Preferences] = None,
269
278
  classical_execution_function: Optional[CFunc] = None,
270
279
  ) -> Model:
280
+ self._qmodule.reset()
281
+ if self.func_decl.name == MAIN_FUNCTION_NAME:
282
+ validate_main_function(self.func_decl)
283
+
271
284
  def _dec_main(*args: Any, **kwargs: Any) -> None:
272
285
  self(*args, **kwargs)
273
286
 
@@ -1,3 +1,4 @@
1
+ from classiq.interface.helpers.backward_compatibility import zip_strict
1
2
  from classiq.interface.model.port_declaration import PortDeclaration
2
3
  from classiq.interface.model.quantum_function_declaration import (
3
4
  AnonQuantumOperandDeclaration,
@@ -14,8 +15,11 @@ def get_renamed_parameters(
14
15
  renamed_parameters: list[str] = []
15
16
  renamed_operands: dict[str, QuantumOperandDeclaration] = {}
16
17
  renamed_ports: list[PortDeclaration] = []
17
- for idx, param in enumerate(lambda_func.func_decl.positional_arg_declarations):
18
- param_name = lambda_func.pos_rename_params[idx]
18
+ for param, param_name in zip_strict(
19
+ lambda_func.func_decl.positional_arg_declarations,
20
+ lambda_func.pos_rename_params,
21
+ strict=False,
22
+ ):
19
23
  if isinstance(param, AnonClassicalParameterDeclaration):
20
24
  renamed_parameters.append(param_name)
21
25
  elif isinstance(param, AnonQuantumOperandDeclaration):
@@ -1,16 +1,22 @@
1
- from classiq.interface.exceptions import ClassiqExpansionError
1
+ from classiq.interface.exceptions import ClassiqExpansionError, ClassiqValueError
2
2
  from classiq.interface.generator.functions.classical_type import (
3
3
  ClassicalArray,
4
4
  ClassicalList,
5
5
  )
6
6
  from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
7
- from classiq.interface.model.native_function_definition import NativeFunctionDefinition
8
- from classiq.interface.model.quantum_function_declaration import PositionalArg
7
+ from classiq.interface.generator.functions.port_declaration import (
8
+ PortDeclarationDirection,
9
+ )
10
+ from classiq.interface.model.port_declaration import PortDeclaration
11
+ from classiq.interface.model.quantum_function_declaration import (
12
+ NamedParamsQuantumFunctionDeclaration,
13
+ PositionalArg,
14
+ )
9
15
 
10
16
  from classiq import ClassicalParameterDeclaration
11
17
 
12
18
 
13
- def validate_main_function(func: NativeFunctionDefinition) -> None:
19
+ def validate_main_function(func: NamedParamsQuantumFunctionDeclaration) -> None:
14
20
  for param in func.positional_arg_declarations:
15
21
  _validate_main_param(param)
16
22
 
@@ -18,6 +24,8 @@ def validate_main_function(func: NativeFunctionDefinition) -> None:
18
24
  def _validate_main_param(param: PositionalArg) -> None:
19
25
  if isinstance(param, ClassicalParameterDeclaration):
20
26
  _validate_main_classical_param_type(param.classical_type, param.name)
27
+ if isinstance(param, PortDeclaration):
28
+ _validate_main_quantum_param_type(param)
21
29
 
22
30
 
23
31
  def _validate_main_classical_param_type(
@@ -30,3 +38,8 @@ def _validate_main_classical_param_type(
30
38
  )
31
39
  if isinstance(param, ClassicalArray):
32
40
  _validate_main_classical_param_type(param.element_type, param_name)
41
+
42
+
43
+ def _validate_main_quantum_param_type(param: PortDeclaration) -> None:
44
+ if param.direction != PortDeclarationDirection.Output:
45
+ raise ClassiqValueError("Function 'main' cannot declare quantum inputs")
classiq/qmod/symbolic.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import sys
2
- from collections.abc import Sequence
3
2
  from typing import (
4
3
  TYPE_CHECKING,
5
4
  Any,
@@ -12,6 +11,9 @@ from typing import (
12
11
  import numpy as np
13
12
 
14
13
  from classiq.interface.exceptions import ClassiqValueError
14
+ from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
15
+ subscript_to_str,
16
+ )
15
17
 
16
18
  from classiq.qmod import model_state_container
17
19
  from classiq.qmod.declaration_inferrer import python_type_to_qmod
@@ -24,6 +26,7 @@ from classiq.qmod.qmod_parameter import (
24
26
  )
25
27
  from classiq.qmod.symbolic_expr import SymbolicExpr
26
28
  from classiq.qmod.symbolic_type import SymbolicTypes
29
+ from classiq.qmod.utilities import qmod_val_to_expr_str
27
30
 
28
31
  pi = SymbolicExpr("pi", False)
29
32
  E = SymbolicExpr("E", False)
@@ -306,27 +309,13 @@ def sum(arr: SymbolicTypes) -> CParamScalar:
306
309
  return symbolic_function(arr)
307
310
 
308
311
 
309
- def _subscript_to_str(index: Any) -> str:
310
- if not isinstance(index, slice):
311
- return str(index)
312
- expr = ""
313
- if index.start is not None:
314
- expr += str(index.start)
315
- expr += ":"
316
- if index.stop is not None:
317
- expr += str(index.stop)
318
- if index.step is not None:
319
- expr += f":{index.step}"
320
- return expr
321
-
322
-
323
312
  def subscript(
324
- array: Union[
325
- Sequence[Union[float, CReal, CParamScalar]], CArray[CReal], np.ndarray
326
- ],
313
+ array: Union[list, CArray[CReal], np.ndarray],
327
314
  index: Any,
328
315
  ) -> CParamScalar:
329
- return CParamScalar(expr=f"{_unwrap_numpy(array)}[{_subscript_to_str(index)}]")
316
+ return CParamScalar(
317
+ expr=f"{qmod_val_to_expr_str(_unwrap_numpy(array))}[{subscript_to_str(index)}]"
318
+ )
330
319
 
331
320
 
332
321
  __all__ = [
@@ -177,3 +177,29 @@ class SymbolicEquality(SymbolicExpr):
177
177
  super().__init__(sym_expr._expr, sym_expr.is_quantum)
178
178
  self.lhs = lhs
179
179
  self.rhs = rhs
180
+
181
+
182
+ class SymbolicSubscriptAndField(SymbolicExpr):
183
+ def __getattr__(self, item: str) -> SymbolicSubscriptAndField:
184
+ return SymbolicSubscriptAndField(f"{self}.{item}", is_quantum=self.is_quantum)
185
+
186
+ def __getitem__(self, item: Any) -> SymbolicExpr:
187
+ if isinstance(item, slice):
188
+ start = item.start
189
+ stop = item.stop
190
+ step = item.step
191
+ item_is_quantum = (
192
+ (isinstance(start, SymbolicExpr) and start.is_quantum)
193
+ or (isinstance(stop, SymbolicExpr) and stop.is_quantum)
194
+ or (isinstance(step, SymbolicExpr) and step.is_quantum)
195
+ )
196
+ start_str = "" if start is None else qmod_val_to_expr_str(start)
197
+ stop_str = "" if stop is None else qmod_val_to_expr_str(stop)
198
+ step_str = "" if step is None else qmod_val_to_expr_str(step)
199
+ item_str = f"{start_str}:{stop_str}:{step_str}"
200
+ else:
201
+ item_is_quantum = isinstance(item, SymbolicExpr) and item.is_quantum
202
+ item_str = qmod_val_to_expr_str(item)
203
+ return SymbolicSubscriptAndField(
204
+ f"{self}[{item_str}]", is_quantum=self.is_quantum or item_is_quantum
205
+ )
classiq/synthesis.py CHANGED
@@ -1,6 +1,4 @@
1
- from typing import Any, NewType, Optional, Union
2
-
3
- import pydantic
1
+ from typing import Any, Optional, Union
4
2
 
5
3
  from classiq.interface.analyzer.result import QasmCode
6
4
  from classiq.interface.exceptions import ClassiqError, ClassiqValueError
@@ -12,43 +10,33 @@ from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model, SerializedM
12
10
  from classiq import QuantumProgram
13
11
  from classiq._internals import async_utils
14
12
  from classiq._internals.api_wrapper import ApiWrapper
15
- from classiq.qmod.quantum_function import GenerativeQFunc, QFunc
16
-
17
- SerializedQuantumProgram = NewType("SerializedQuantumProgram", str)
13
+ from classiq.qmod.quantum_function import BaseQFunc
18
14
 
19
- CANT_PARSE_QUANTUM_PROGRAM_MSG = (
20
- "Can not parse quantum_program into GeneratedCircuit, \n"
21
- )
15
+ SerializedQuantumProgram = QuantumProgram
22
16
 
23
17
 
24
- def show(quantum_program: SerializedQuantumProgram, display_url: bool = True) -> None:
18
+ def show(quantum_program: QuantumProgram, display_url: bool = True) -> None:
25
19
  """
26
20
  Displays the interactive representation of the quantum program in the Classiq IDE.
27
21
 
28
22
  Args:
29
23
  quantum_program:
30
- The serialized quantum program to be displayed.
24
+ The quantum program to be displayed.
31
25
  display_url:
32
26
  Whether to print the url
33
27
 
34
28
  Links:
35
29
  [Visualization tool](https://docs.classiq.io/latest/reference-manual/analyzer/quantum-program-visualization-tool/)
36
30
  """
37
- try:
38
- circuit = QuantumProgram.model_validate_json(quantum_program)
39
- except pydantic.ValidationError as exc:
40
- raise ClassiqValueError(CANT_PARSE_QUANTUM_PROGRAM_MSG) from exc
41
- circuit.show() # type: ignore[attr-defined]
31
+ QuantumProgram.model_validate(quantum_program)
32
+ quantum_program.show() # type: ignore[attr-defined]
42
33
 
43
34
 
44
- async def quantum_program_from_qasm_async(qasm: str) -> SerializedQuantumProgram:
45
- quantum_program = await ApiWrapper.get_generated_circuit_from_qasm(
46
- QasmCode(code=qasm)
47
- )
48
- return SerializedQuantumProgram(quantum_program.model_dump_json())
35
+ async def quantum_program_from_qasm_async(qasm: str) -> QuantumProgram:
36
+ return await ApiWrapper.get_generated_circuit_from_qasm(QasmCode(code=qasm))
49
37
 
50
38
 
51
- def quantum_program_from_qasm(qasm: str) -> SerializedQuantumProgram:
39
+ def quantum_program_from_qasm(qasm: str) -> QuantumProgram:
52
40
  """
53
41
  generate a quantum program from a QASM file.
54
42
 
@@ -56,25 +44,24 @@ def quantum_program_from_qasm(qasm: str) -> SerializedQuantumProgram:
56
44
  qasm: A QASM2/3 string.
57
45
 
58
46
  Returns:
59
- SerializedQuantumProgram: Quantum program serialized as a string. (See: QuantumProgram)
47
+ QuantumProgram: Quantum program. (See: QuantumProgram)
60
48
  """
61
49
  return async_utils.run(quantum_program_from_qasm_async(qasm))
62
50
 
63
51
 
64
52
  async def synthesize_async(
65
53
  serialized_model: SerializedModel,
66
- ) -> SerializedQuantumProgram:
54
+ ) -> QuantumProgram:
67
55
  model = Model.model_validate_json(serialized_model)
68
- quantum_program = await ApiWrapper.call_generation_task(model)
69
- return SerializedQuantumProgram(quantum_program.model_dump_json(indent=2))
56
+ return await ApiWrapper.call_generation_task(model)
70
57
 
71
58
 
72
59
  def synthesize(
73
- model: Union[SerializedModel, QFunc, GenerativeQFunc],
60
+ model: Union[SerializedModel, BaseQFunc],
74
61
  auto_show: bool = False,
75
62
  constraints: Optional[Constraints] = None,
76
63
  preferences: Optional[Preferences] = None,
77
- ) -> SerializedQuantumProgram:
64
+ ) -> QuantumProgram:
78
65
  """
79
66
  Synthesize a model with the Classiq engine to receive a quantum program.
80
67
  [More details](https://docs.classiq.io/latest/reference-manual/synthesis/)
@@ -86,9 +73,9 @@ def synthesize(
86
73
  preferences: Preferences for the synthesis of the model. See Preferences (Optional).
87
74
 
88
75
  Returns:
89
- SerializedQuantumProgram: Quantum program serialized as a string. (See: QuantumProgram)
76
+ QuantumProgram: Quantum program. (See: QuantumProgram)
90
77
  """
91
- if isinstance(model, (QFunc, GenerativeQFunc)):
78
+ if isinstance(model, BaseQFunc):
92
79
  func_name = model._py_callable.__name__
93
80
  if func_name != MAIN_FUNCTION_NAME:
94
81
  raise ClassiqError(
@@ -252,7 +239,6 @@ def update_execution_preferences(
252
239
 
253
240
  __all__ = [
254
241
  "SerializedModel",
255
- "SerializedQuantumProgram",
256
242
  "set_constraints",
257
243
  "set_execution_preferences",
258
244
  "set_preferences",
@@ -0,0 +1,35 @@
1
+ from typing import NewType
2
+
3
+ from classiq.interface.analyzer.result import DataID
4
+ from classiq.interface.exceptions import ClassiqAPIError
5
+
6
+ from classiq._internals import async_utils
7
+ from classiq._internals.api_wrapper import ApiWrapper
8
+
9
+ SerializedVisualModel = NewType("SerializedVisualModel", str)
10
+
11
+
12
+ async def visualize_async(
13
+ data_id: DataID,
14
+ ) -> SerializedVisualModel:
15
+ try:
16
+ visual_model = await ApiWrapper.call_get_visual_model(data_id.id)
17
+ except ClassiqAPIError as error:
18
+ if error.status_code != 404:
19
+ raise error
20
+ analyzer_data = await ApiWrapper.get_analyzer_app_data(data_id)
21
+ visual_model = await ApiWrapper.call_visualization_task(analyzer_data)
22
+ return SerializedVisualModel(visual_model.model_dump_json(indent=2))
23
+
24
+
25
+ def visualize(
26
+ data_id: DataID,
27
+ ) -> SerializedVisualModel:
28
+ result = async_utils.run(visualize_async(data_id))
29
+ return result
30
+
31
+
32
+ __all__ = [
33
+ "SerializedVisualModel",
34
+ "visualize",
35
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: classiq
3
- Version: 0.75.0
3
+ Version: 0.76.0
4
4
  Summary: Classiq's Python SDK for quantum computing
5
5
  License: Proprietary
6
6
  Keywords: quantum computing,quantum circuits,quantum algorithms,QAD,QDL