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.
- classiq/_internals/api_wrapper.py +36 -0
- classiq/analyzer/show_interactive_hack.py +58 -2
- classiq/applications/chemistry/chemistry_model_constructor.py +8 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -4
- classiq/applications/qnn/gradients/quantum_gradient.py +3 -5
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -2
- classiq/applications/qnn/qlayer.py +14 -19
- classiq/applications/qnn/types.py +1 -4
- classiq/execution/__init__.py +3 -0
- classiq/execution/execution_session.py +3 -16
- classiq/execution/qnn.py +2 -2
- classiq/execution/user_budgets.py +38 -0
- classiq/executor.py +7 -19
- classiq/interface/_version.py +1 -1
- classiq/interface/debug_info/debug_info.py +16 -2
- classiq/interface/executor/user_budget.py +56 -0
- classiq/interface/generator/application_apis/finance_declarations.py +3 -0
- classiq/interface/generator/expressions/atomic_expression_functions.py +3 -0
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +30 -124
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +45 -21
- classiq/interface/generator/expressions/proxies/classical/qmod_struct_instance.py +7 -0
- classiq/interface/generator/expressions/proxies/classical/utils.py +12 -11
- classiq/interface/generator/expressions/proxies/quantum/qmod_qscalar_proxy.py +9 -2
- classiq/interface/generator/expressions/proxies/quantum/qmod_sized_proxy.py +4 -1
- classiq/interface/generator/expressions/sympy_supported_expressions.py +1 -0
- classiq/interface/generator/functions/classical_type.py +6 -1
- classiq/interface/generator/functions/type_name.py +7 -2
- classiq/interface/generator/functions/type_qualifier.py +15 -0
- classiq/interface/generator/model/preferences/preferences.py +7 -0
- classiq/interface/generator/quantum_program.py +5 -19
- classiq/interface/helpers/backward_compatibility.py +9 -0
- classiq/interface/helpers/datastructures.py +6 -0
- classiq/interface/model/port_declaration.py +1 -2
- classiq/interface/model/quantum_lambda_function.py +2 -1
- classiq/interface/server/routes.py +6 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +62 -19
- classiq/model_expansions/capturing/captured_vars.py +2 -0
- classiq/model_expansions/closure.py +5 -0
- classiq/model_expansions/evaluators/classical_type_inference.py +17 -6
- classiq/model_expansions/evaluators/parameter_types.py +26 -13
- classiq/model_expansions/expression_evaluator.py +1 -1
- classiq/model_expansions/generative_functions.py +61 -34
- classiq/model_expansions/interpreters/base_interpreter.py +17 -6
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +5 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +13 -1
- classiq/model_expansions/quantum_operations/allocate.py +6 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +219 -20
- classiq/model_expansions/quantum_operations/bind.py +54 -30
- classiq/model_expansions/quantum_operations/block_evaluator.py +42 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +14 -7
- classiq/model_expansions/quantum_operations/composite_emitter.py +1 -1
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +23 -9
- classiq/model_expansions/quantum_operations/emitter.py +20 -3
- classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -3
- classiq/model_expansions/scope.py +10 -7
- classiq/model_expansions/sympy_conversion/arithmetics.py +18 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +2 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +10 -1
- classiq/model_expansions/transformers/model_renamer.py +45 -7
- classiq/model_expansions/utils/handles_collector.py +1 -1
- classiq/model_expansions/visitors/variable_references.py +45 -9
- classiq/qmod/builtins/functions/allocation.py +2 -2
- classiq/qmod/builtins/functions/arithmetic.py +14 -12
- classiq/qmod/builtins/functions/standard_gates.py +23 -23
- classiq/qmod/declaration_inferrer.py +19 -7
- classiq/qmod/generative.py +9 -1
- classiq/qmod/native/expression_to_qmod.py +4 -0
- classiq/qmod/native/pretty_printer.py +8 -3
- classiq/qmod/pretty_print/pretty_printer.py +1 -1
- classiq/qmod/python_classical_type.py +4 -5
- classiq/qmod/qmod_constant.py +15 -7
- classiq/qmod/qmod_variable.py +7 -1
- classiq/qmod/quantum_function.py +19 -6
- classiq/qmod/semantics/lambdas.py +6 -2
- classiq/qmod/semantics/validation/main_validation.py +17 -4
- classiq/qmod/symbolic.py +8 -19
- classiq/qmod/symbolic_expr.py +26 -0
- classiq/synthesis.py +17 -31
- classiq/visualization.py +35 -0
- {classiq-0.75.0.dist-info → classiq-0.76.0.dist-info}/METADATA +1 -1
- {classiq-0.75.0.dist-info → classiq-0.76.0.dist-info}/RECORD +83 -79
- {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
|
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) ->
|
72
|
-
|
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
|
classiq/qmod/qmod_constant.py
CHANGED
@@ -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
|
-
|
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__()
|
classiq/qmod/qmod_variable.py
CHANGED
@@ -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
|
758
|
+
raise ClassiqValueError(f"Invalid quantum type {root_type.__name__!r}")
|
753
759
|
return root_type
|
classiq/qmod/quantum_function.py
CHANGED
@@ -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
|
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
|
258
|
-
|
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.
|
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
|
18
|
-
|
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.
|
8
|
-
|
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:
|
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(
|
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__ = [
|
classiq/qmod/symbolic_expr.py
CHANGED
@@ -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,
|
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
|
16
|
-
|
17
|
-
SerializedQuantumProgram = NewType("SerializedQuantumProgram", str)
|
13
|
+
from classiq.qmod.quantum_function import BaseQFunc
|
18
14
|
|
19
|
-
|
20
|
-
"Can not parse quantum_program into GeneratedCircuit, \n"
|
21
|
-
)
|
15
|
+
SerializedQuantumProgram = QuantumProgram
|
22
16
|
|
23
17
|
|
24
|
-
def show(quantum_program:
|
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
|
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
|
-
|
38
|
-
|
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) ->
|
45
|
-
|
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) ->
|
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
|
-
|
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
|
-
) ->
|
54
|
+
) -> QuantumProgram:
|
67
55
|
model = Model.model_validate_json(serialized_model)
|
68
|
-
|
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,
|
60
|
+
model: Union[SerializedModel, BaseQFunc],
|
74
61
|
auto_show: bool = False,
|
75
62
|
constraints: Optional[Constraints] = None,
|
76
63
|
preferences: Optional[Preferences] = None,
|
77
|
-
) ->
|
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
|
-
|
76
|
+
QuantumProgram: Quantum program. (See: QuantumProgram)
|
90
77
|
"""
|
91
|
-
if isinstance(model,
|
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",
|
classiq/visualization.py
ADDED
@@ -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
|
+
]
|