classiq 0.45.1__py3-none-any.whl → 0.46.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.
- classiq/__init__.py +0 -1
- classiq/_internals/__init__.py +20 -0
- classiq/_internals/authentication/authentication.py +11 -0
- classiq/analyzer/analyzer.py +12 -10
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +1 -1
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +1 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
- classiq/applications/libraries/qmci_library.py +4 -9
- classiq/execution/execution_session.py +68 -7
- classiq/executor.py +14 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +189 -0
- classiq/interface/backend/quantum_backend_providers.py +38 -0
- classiq/interface/debug_info/debug_info.py +22 -2
- classiq/interface/exceptions.py +16 -1
- classiq/interface/executor/execution_preferences.py +18 -0
- classiq/interface/generator/application_apis/chemistry_declarations.py +1 -177
- classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +0 -12
- classiq/interface/generator/application_apis/finance_declarations.py +8 -43
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -78
- classiq/interface/generator/builtin_api_builder.py +0 -3
- classiq/interface/generator/functions/__init__.py +0 -2
- classiq/interface/generator/functions/builtins/__init__.py +0 -15
- classiq/interface/generator/generated_circuit_data.py +2 -0
- classiq/interface/generator/hardware/hardware_data.py +37 -0
- classiq/interface/generator/model/constraints.py +18 -1
- classiq/interface/generator/model/preferences/preferences.py +53 -1
- classiq/interface/generator/model/quantum_register.py +1 -1
- classiq/interface/generator/quantum_program.py +10 -2
- classiq/interface/generator/transpiler_basis_gates.py +4 -0
- classiq/interface/generator/types/builtin_enum_declarations.py +136 -21
- classiq/interface/generator/types/enum_declaration.py +1 -3
- classiq/interface/generator/types/struct_declaration.py +1 -3
- classiq/interface/hardware.py +5 -0
- classiq/interface/ide/visual_model.py +1 -1
- classiq/interface/model/classical_parameter_declaration.py +6 -0
- classiq/interface/model/inplace_binary_operation.py +0 -14
- classiq/interface/model/model.py +1 -18
- classiq/interface/model/port_declaration.py +4 -2
- classiq/interface/model/quantum_function_declaration.py +19 -6
- classiq/interface/model/quantum_lambda_function.py +11 -1
- classiq/interface/model/quantum_variable_declaration.py +1 -1
- classiq/model_expansions/__init__.py +0 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +250 -0
- classiq/model_expansions/capturing/__init__.py +0 -0
- classiq/model_expansions/capturing/captured_var_manager.py +50 -0
- classiq/model_expansions/capturing/mangling_utils.py +17 -0
- classiq/model_expansions/capturing/propagated_var_stack.py +180 -0
- classiq/model_expansions/closure.py +160 -0
- classiq/model_expansions/debug_flag.py +3 -0
- classiq/model_expansions/evaluators/__init__.py +0 -0
- classiq/model_expansions/evaluators/arg_type_match.py +160 -0
- classiq/model_expansions/evaluators/argument_types.py +42 -0
- classiq/model_expansions/evaluators/classical_expression.py +36 -0
- classiq/model_expansions/evaluators/control.py +144 -0
- classiq/model_expansions/evaluators/parameter_types.py +227 -0
- classiq/model_expansions/evaluators/quantum_type_utils.py +235 -0
- classiq/model_expansions/evaluators/type_type_match.py +90 -0
- classiq/model_expansions/expression_evaluator.py +125 -0
- classiq/model_expansions/expression_renamer.py +76 -0
- classiq/model_expansions/function_builder.py +192 -0
- classiq/model_expansions/generative_functions.py +101 -0
- classiq/model_expansions/interpreter.py +365 -0
- classiq/model_expansions/model_tables.py +105 -0
- classiq/model_expansions/quantum_operations/__init__.py +19 -0
- classiq/model_expansions/quantum_operations/bind.py +64 -0
- classiq/model_expansions/quantum_operations/classicalif.py +39 -0
- classiq/model_expansions/quantum_operations/control.py +235 -0
- classiq/model_expansions/quantum_operations/emitter.py +215 -0
- classiq/model_expansions/quantum_operations/expression_operation.py +218 -0
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +250 -0
- classiq/model_expansions/quantum_operations/invert.py +38 -0
- classiq/model_expansions/quantum_operations/power.py +74 -0
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +174 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +15 -0
- classiq/model_expansions/quantum_operations/repeat.py +33 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
- classiq/model_expansions/quantum_operations/within_apply.py +46 -0
- classiq/model_expansions/scope.py +226 -0
- classiq/model_expansions/scope_initialization.py +136 -0
- classiq/model_expansions/sympy_conversion/__init__.py +0 -0
- classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +150 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +113 -0
- classiq/model_expansions/utils/__init__.py +0 -0
- classiq/model_expansions/utils/counted_name_allocator.py +11 -0
- classiq/model_expansions/visitors/__init__.py +0 -0
- classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
- classiq/model_expansions/visitors/variable_references.py +115 -0
- classiq/qmod/__init__.py +1 -3
- classiq/qmod/builtins/enums.py +33 -2
- classiq/qmod/builtins/functions/__init__.py +251 -0
- classiq/qmod/builtins/functions/amplitude_estimation.py +27 -0
- classiq/qmod/builtins/functions/arithmetic.py +68 -0
- classiq/qmod/builtins/functions/benchmarking.py +8 -0
- classiq/qmod/builtins/functions/chemistry.py +91 -0
- classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +105 -0
- classiq/qmod/builtins/functions/exponentiation.py +111 -0
- classiq/qmod/builtins/functions/finance.py +34 -0
- classiq/qmod/builtins/functions/grover.py +178 -0
- classiq/qmod/builtins/functions/hea.py +59 -0
- classiq/qmod/builtins/functions/linear_pauli_rotation.py +65 -0
- classiq/qmod/builtins/functions/modular_exponentiation.py +137 -0
- classiq/qmod/builtins/functions/operators.py +22 -0
- classiq/qmod/builtins/functions/qaoa_penalty.py +116 -0
- classiq/qmod/builtins/functions/qft.py +23 -0
- classiq/qmod/builtins/functions/qpe.py +39 -0
- classiq/qmod/builtins/functions/qsvm.py +24 -0
- classiq/qmod/builtins/functions/qsvt.py +136 -0
- classiq/qmod/builtins/functions/standard_gates.py +739 -0
- classiq/qmod/builtins/functions/state_preparation.py +357 -0
- classiq/qmod/builtins/functions/swap_test.py +25 -0
- classiq/qmod/builtins/structs.py +50 -28
- classiq/qmod/cparam.py +64 -0
- classiq/qmod/create_model_function.py +190 -0
- classiq/qmod/declaration_inferrer.py +52 -81
- classiq/qmod/expression_query.py +16 -0
- classiq/qmod/generative.py +48 -0
- classiq/qmod/model_state_container.py +1 -2
- classiq/qmod/native/pretty_printer.py +7 -11
- classiq/qmod/pretty_print/pretty_printer.py +7 -11
- classiq/qmod/python_classical_type.py +67 -0
- classiq/qmod/qfunc.py +19 -4
- classiq/qmod/qmod_parameter.py +15 -64
- classiq/qmod/qmod_variable.py +27 -45
- classiq/qmod/quantum_callable.py +1 -1
- classiq/qmod/quantum_expandable.py +10 -4
- classiq/qmod/quantum_function.py +22 -40
- classiq/qmod/semantics/error_manager.py +22 -10
- classiq/qmod/semantics/static_semantics_visitor.py +10 -12
- classiq/qmod/semantics/validation/types_validation.py +6 -7
- classiq/qmod/utilities.py +2 -2
- classiq/qmod/write_qmod.py +14 -0
- classiq/show.py +10 -0
- classiq/synthesis.py +46 -2
- {classiq-0.45.1.dist-info → classiq-0.46.1.dist-info}/METADATA +1 -1
- {classiq-0.45.1.dist-info → classiq-0.46.1.dist-info}/RECORD +138 -74
- classiq/interface/generator/functions/builtins/core_library/__init__.py +0 -16
- classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +0 -710
- classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +0 -105
- classiq/interface/generator/functions/builtins/open_lib_functions.py +0 -2489
- classiq/interface/generator/functions/builtins/quantum_operators.py +0 -24
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -21
- classiq/qmod/builtins/functions.py +0 -1029
- {classiq-0.45.1.dist-info → classiq-0.46.1.dist-info}/WHEEL +0 -0
classiq/qmod/qmod_parameter.py
CHANGED
@@ -1,14 +1,4 @@
|
|
1
|
-
import
|
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
|
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 =
|
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
|
classiq/qmod/qmod_variable.py
CHANGED
@@ -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
|
175
|
-
|
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
|
369
|
-
|
370
|
-
|
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
|
377
|
-
|
378
|
-
|
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
|
483
|
-
|
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)
|
@@ -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
|
-
|
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
|
-
|
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:
|
classiq/qmod/quantum_callable.py
CHANGED
@@ -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.
|
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,
|
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.
|
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
|
-
|
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()
|
classiq/qmod/quantum_function.py
CHANGED
@@ -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
|
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
|
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 =
|
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
|
-
|
165
|
-
|
166
|
-
self
|
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.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
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
|
-
|
356
|
-
|
357
|
-
**
|
358
|
-
|
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
|
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
|
-
|
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
|
)
|
classiq/qmod/write_qmod.py
CHANGED
@@ -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:
|