classiq 0.45.1__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.
- 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 +26 -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 +110 -0
- classiq/qmod/builtins/functions/finance.py +34 -0
- classiq/qmod/builtins/functions/grover.py +179 -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 +356 -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.0.dist-info}/METADATA +1 -1
- {classiq-0.45.1.dist-info → classiq-0.46.0.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.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,190 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Union, cast
|
2
|
+
|
3
|
+
from classiq.interface.exceptions import ClassiqError
|
4
|
+
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
5
|
+
from classiq.interface.generator.model.constraints import Constraints
|
6
|
+
from classiq.interface.generator.model.preferences.preferences import Preferences
|
7
|
+
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
8
|
+
from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model, SerializedModel
|
9
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
10
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
11
|
+
|
12
|
+
from classiq.model_expansions.interpreter import Interpreter
|
13
|
+
from classiq.qmod.builtins.functions import BUILTIN_FUNCTION_DECLARATIONS
|
14
|
+
from classiq.qmod.classical_function import CFunc
|
15
|
+
from classiq.qmod.generative import (
|
16
|
+
is_generative_expansion_enabled,
|
17
|
+
set_frontend_interpreter,
|
18
|
+
)
|
19
|
+
from classiq.qmod.model_state_container import QMODULE
|
20
|
+
from classiq.qmod.qfunc import DEC_QFUNCS, GEN_QFUNCS
|
21
|
+
from classiq.qmod.quantum_expandable import _prepare_args
|
22
|
+
from classiq.qmod.quantum_function import GenerativeQFunc, QFunc
|
23
|
+
from classiq.qmod.semantics.static_semantics_visitor import resolve_function_calls
|
24
|
+
from classiq.qmod.write_qmod import write_qmod
|
25
|
+
|
26
|
+
GEN_MAIN_NAME = "_gen_main"
|
27
|
+
|
28
|
+
|
29
|
+
def create_model(
|
30
|
+
entry_point: Union[QFunc, GenerativeQFunc],
|
31
|
+
constraints: Optional[Constraints] = None,
|
32
|
+
execution_preferences: Optional[ExecutionPreferences] = None,
|
33
|
+
preferences: Optional[Preferences] = None,
|
34
|
+
classical_execution_function: Optional[CFunc] = None,
|
35
|
+
out_file: Optional[str] = None,
|
36
|
+
) -> SerializedModel:
|
37
|
+
"""
|
38
|
+
Create a serialized model from a given Qmod entry function and additional parameters.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
entry_point: The entry point function for the model, which must be a QFunc named 'main'.
|
42
|
+
constraints: Constraints for the synthesis of the model. See Constraints (Optional).
|
43
|
+
execution_preferences: Preferences for the execution of the model. See ExecutionPreferences (Optional).
|
44
|
+
preferences: Preferences for the synthesis of the model. See Preferences (Optional).
|
45
|
+
classical_execution_function: A function for the classical execution logic, which must be a CFunc (Optional).
|
46
|
+
out_file: File path to write the Qmod model in native Qmod representation to (Optional).
|
47
|
+
|
48
|
+
Returns:
|
49
|
+
SerializedModel: A serialized model.
|
50
|
+
|
51
|
+
Raises:
|
52
|
+
ClassiqError: If the entry point function is not named 'main'.
|
53
|
+
"""
|
54
|
+
|
55
|
+
if entry_point.func_decl.name != MAIN_FUNCTION_NAME:
|
56
|
+
raise ClassiqError(
|
57
|
+
f"The entry point function must be named 'main', got '{entry_point.func_decl.name}'"
|
58
|
+
)
|
59
|
+
|
60
|
+
user_gen_functions = {
|
61
|
+
gen_func._py_callable.__name__ for gen_func in GEN_QFUNCS
|
62
|
+
} - set(BUILTIN_FUNCTION_DECLARATIONS.keys())
|
63
|
+
if len(user_gen_functions) > 0 and is_generative_expansion_enabled():
|
64
|
+
model = _expand_generative_model(
|
65
|
+
(
|
66
|
+
entry_point
|
67
|
+
if isinstance(entry_point, QFunc)
|
68
|
+
else QFunc(entry_point._py_callable)
|
69
|
+
),
|
70
|
+
constraints,
|
71
|
+
execution_preferences,
|
72
|
+
preferences,
|
73
|
+
classical_execution_function,
|
74
|
+
)
|
75
|
+
else:
|
76
|
+
if TYPE_CHECKING:
|
77
|
+
assert isinstance(entry_point, QFunc)
|
78
|
+
model = entry_point.create_model(
|
79
|
+
constraints,
|
80
|
+
execution_preferences,
|
81
|
+
preferences,
|
82
|
+
classical_execution_function,
|
83
|
+
)
|
84
|
+
result = model.get_model()
|
85
|
+
|
86
|
+
if out_file is not None:
|
87
|
+
write_qmod(result, out_file)
|
88
|
+
|
89
|
+
return result
|
90
|
+
|
91
|
+
|
92
|
+
def _expand_generative_model(
|
93
|
+
gen_main: QFunc,
|
94
|
+
constraints: Optional[Constraints] = None,
|
95
|
+
execution_preferences: Optional[ExecutionPreferences] = None,
|
96
|
+
preferences: Optional[Preferences] = None,
|
97
|
+
classical_execution_function: Optional[CFunc] = None,
|
98
|
+
) -> Model:
|
99
|
+
@QFunc
|
100
|
+
def _dummy() -> None:
|
101
|
+
pass
|
102
|
+
|
103
|
+
model = _dummy.create_model(
|
104
|
+
constraints,
|
105
|
+
execution_preferences,
|
106
|
+
preferences,
|
107
|
+
classical_execution_function,
|
108
|
+
)
|
109
|
+
generative_functions = _get_generative_functions(gen_main)
|
110
|
+
model.functions = generative_functions
|
111
|
+
model.types = list(QMODULE.type_decls.values())
|
112
|
+
model.enums = list(QMODULE.enum_decls.values())
|
113
|
+
model.qstructs = list(QMODULE.qstruct_decls.values())
|
114
|
+
return model
|
115
|
+
|
116
|
+
|
117
|
+
def _get_generative_functions(gen_main: QFunc) -> List[NativeFunctionDefinition]:
|
118
|
+
# The Interpreter accepts a model and a list of generative functions.
|
119
|
+
# Since the main function is generative, it can only be expanded using the
|
120
|
+
# Interpreter.
|
121
|
+
# To solve this deadlock, we create a wrapper model
|
122
|
+
# `qfunc main(...) { _gen_main(...); }` and rename `main` to `_gen_main` before
|
123
|
+
# passing them to the Interpreter.
|
124
|
+
gen_model = _get_wrapper_main(gen_main)
|
125
|
+
gen_functions = _get_all_model_functions_as_generative_functions()
|
126
|
+
functions_dict = _interpret_generative_model(gen_model, gen_functions)
|
127
|
+
return list(functions_dict.values())
|
128
|
+
|
129
|
+
|
130
|
+
def _get_wrapper_main(gen_main: QFunc) -> Model:
|
131
|
+
return Model(
|
132
|
+
functions=[
|
133
|
+
NativeFunctionDefinition(
|
134
|
+
name=MAIN_FUNCTION_NAME,
|
135
|
+
positional_arg_declarations=gen_main.func_decl.positional_arg_declarations,
|
136
|
+
body=[
|
137
|
+
QuantumFunctionCall(
|
138
|
+
function=GEN_MAIN_NAME,
|
139
|
+
positional_args=_prepare_args(
|
140
|
+
gen_main.func_decl,
|
141
|
+
gen_main._get_positional_args(),
|
142
|
+
{},
|
143
|
+
),
|
144
|
+
),
|
145
|
+
],
|
146
|
+
),
|
147
|
+
],
|
148
|
+
)
|
149
|
+
|
150
|
+
|
151
|
+
def _get_all_model_functions_as_generative_functions() -> List[GenerativeQFunc]:
|
152
|
+
gen_functions = list(GEN_QFUNCS) + [
|
153
|
+
GenerativeQFunc(dec_func._py_callable, dec_func.func_decl)
|
154
|
+
for dec_func in DEC_QFUNCS
|
155
|
+
]
|
156
|
+
return [
|
157
|
+
(
|
158
|
+
gen_func
|
159
|
+
if gen_func.func_decl.name != MAIN_FUNCTION_NAME
|
160
|
+
else GenerativeQFunc(
|
161
|
+
gen_func._py_callable,
|
162
|
+
gen_func.func_decl.copy(update={"name": GEN_MAIN_NAME}),
|
163
|
+
)
|
164
|
+
)
|
165
|
+
for gen_func in gen_functions
|
166
|
+
if gen_func.func_decl.name not in BUILTIN_FUNCTION_DECLARATIONS
|
167
|
+
]
|
168
|
+
|
169
|
+
|
170
|
+
def _interpret_generative_model(
|
171
|
+
gen_model: Model, gen_functions: List[GenerativeQFunc]
|
172
|
+
) -> Dict[str, NativeFunctionDefinition]:
|
173
|
+
resolve_function_calls(
|
174
|
+
gen_model,
|
175
|
+
{gen_func.func_decl.name: gen_func.func_decl for gen_func in gen_functions},
|
176
|
+
)
|
177
|
+
interpreter = Interpreter(gen_model, gen_functions)
|
178
|
+
set_frontend_interpreter(interpreter)
|
179
|
+
functions_dict = nameables_to_dict(interpreter.expand().functions)
|
180
|
+
|
181
|
+
# Inline _gen_main call in main
|
182
|
+
expanded_gen_main_name = cast(
|
183
|
+
QuantumFunctionCall, functions_dict[MAIN_FUNCTION_NAME].body[0]
|
184
|
+
).func_name
|
185
|
+
functions_dict[MAIN_FUNCTION_NAME] = functions_dict[expanded_gen_main_name].copy(
|
186
|
+
update={"name": MAIN_FUNCTION_NAME}
|
187
|
+
)
|
188
|
+
functions_dict.pop(expanded_gen_main_name)
|
189
|
+
|
190
|
+
return functions_dict
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import dataclasses
|
2
|
-
import inspect
|
3
2
|
import sys
|
4
3
|
from enum import EnumMeta
|
5
4
|
from typing import (
|
@@ -19,22 +18,12 @@ from typing import (
|
|
19
18
|
from typing_extensions import _AnnotatedAlias
|
20
19
|
|
21
20
|
from classiq.interface.exceptions import ClassiqValueError
|
22
|
-
from classiq.interface.generator.functions.classical_type import (
|
23
|
-
Bool,
|
24
|
-
ClassicalArray,
|
25
|
-
ClassicalList,
|
26
|
-
Integer,
|
27
|
-
Real,
|
28
|
-
)
|
29
21
|
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
30
22
|
from classiq.interface.generator.functions.port_declaration import (
|
31
23
|
PortDeclarationDirection,
|
32
24
|
)
|
33
|
-
from classiq.interface.generator.
|
34
|
-
from classiq.interface.generator.types.
|
35
|
-
EnumDeclaration,
|
36
|
-
declaration_from_enum,
|
37
|
-
)
|
25
|
+
from classiq.interface.generator.types.enum_declaration import declaration_from_enum
|
26
|
+
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
38
27
|
from classiq.interface.model.classical_parameter_declaration import (
|
39
28
|
AnonClassicalParameterDeclaration,
|
40
29
|
)
|
@@ -46,10 +35,12 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
46
35
|
PositionalArg,
|
47
36
|
)
|
48
37
|
|
49
|
-
from classiq import
|
38
|
+
from classiq.model_expansions.model_tables import SymbolTable
|
39
|
+
from classiq.qmod.builtins.enums import BUILTIN_ENUM_DECLARATIONS
|
40
|
+
from classiq.qmod.builtins.structs import BUILTIN_STRUCT_DECLARATIONS
|
50
41
|
from classiq.qmod.model_state_container import ModelStateContainer
|
51
|
-
from classiq.qmod.
|
52
|
-
from classiq.qmod.qmod_variable import QVar
|
42
|
+
from classiq.qmod.python_classical_type import PythonClassicalType
|
43
|
+
from classiq.qmod.qmod_variable import QVar
|
53
44
|
from classiq.qmod.quantum_callable import QCallableList
|
54
45
|
from classiq.qmod.utilities import unmangle_keyword, version_portable_get_args
|
55
46
|
|
@@ -57,67 +48,45 @@ if sys.version_info[0:2] >= (3, 9):
|
|
57
48
|
from typing import Annotated
|
58
49
|
|
59
50
|
|
51
|
+
class _PythonClassicalType(PythonClassicalType):
|
52
|
+
def __init__(self, qmodule: Optional[ModelStateContainer]):
|
53
|
+
super().__init__()
|
54
|
+
self.qmodule = qmodule
|
55
|
+
|
56
|
+
def register_enum(self, py_type: EnumMeta) -> None:
|
57
|
+
if (
|
58
|
+
self.qmodule is None
|
59
|
+
or py_type.__name__ in BUILTIN_ENUM_DECLARATIONS
|
60
|
+
or py_type.__name__ in self.qmodule.enum_decls
|
61
|
+
):
|
62
|
+
return
|
63
|
+
|
64
|
+
enum_decl = declaration_from_enum(py_type)
|
65
|
+
self.qmodule.enum_decls[py_type.__name__] = enum_decl
|
66
|
+
SymbolTable.enum_table[py_type.__name__] = enum_decl
|
67
|
+
|
68
|
+
def register_struct(self, py_type: type) -> None:
|
69
|
+
if (
|
70
|
+
self.qmodule is None
|
71
|
+
or py_type.__name__ in BUILTIN_STRUCT_DECLARATIONS
|
72
|
+
or py_type.__name__ in self.qmodule.type_decls
|
73
|
+
):
|
74
|
+
return
|
75
|
+
|
76
|
+
struct_decl = StructDeclaration(
|
77
|
+
name=py_type.__name__,
|
78
|
+
variables={
|
79
|
+
f.name: self.convert(f.type) for f in dataclasses.fields(py_type)
|
80
|
+
},
|
81
|
+
)
|
82
|
+
self.qmodule.type_decls[py_type.__name__] = struct_decl
|
83
|
+
SymbolTable.type_table[py_type.__name__] = struct_decl
|
84
|
+
|
85
|
+
|
60
86
|
def python_type_to_qmod(
|
61
|
-
py_type: type, *, qmodule: ModelStateContainer
|
87
|
+
py_type: type, *, qmodule: Optional[ModelStateContainer]
|
62
88
|
) -> Optional[ConcreteClassicalType]:
|
63
|
-
|
64
|
-
return Integer()
|
65
|
-
elif py_type in (float, complex) or py_type is CReal:
|
66
|
-
return Real()
|
67
|
-
elif py_type is bool or py_type is CBool:
|
68
|
-
return Bool()
|
69
|
-
elif get_origin(py_type) is list:
|
70
|
-
element_type = python_type_to_qmod(get_args(py_type)[0], qmodule=qmodule)
|
71
|
-
if element_type is not None:
|
72
|
-
return ClassicalList(element_type=element_type)
|
73
|
-
elif get_origin(py_type) is CArray:
|
74
|
-
array_args = version_portable_get_args(py_type)
|
75
|
-
if len(array_args) == 1:
|
76
|
-
return ClassicalList(
|
77
|
-
element_type=python_type_to_qmod(array_args[0], qmodule=qmodule)
|
78
|
-
)
|
79
|
-
elif len(array_args) == 2:
|
80
|
-
return ClassicalArray(
|
81
|
-
element_type=python_type_to_qmod(array_args[0], qmodule=qmodule),
|
82
|
-
size=get_type_hint_expr(array_args[1]),
|
83
|
-
)
|
84
|
-
raise ClassiqValueError(
|
85
|
-
"CArray accepts one or two generic parameters in the form "
|
86
|
-
"`CArray[<element-type>]` or `CArray[<element-type>, <size>]`"
|
87
|
-
)
|
88
|
-
elif inspect.isclass(py_type) and dataclasses.is_dataclass(py_type):
|
89
|
-
_add_qmod_struct(py_type, qmodule=qmodule)
|
90
|
-
return Struct(name=py_type.__name__)
|
91
|
-
elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
|
92
|
-
_add_qmod_enum(py_type, qmodule=qmodule)
|
93
|
-
return Enum(name=py_type.__name__)
|
94
|
-
return None
|
95
|
-
|
96
|
-
|
97
|
-
def _add_qmod_enum(py_type: EnumMeta, *, qmodule: ModelStateContainer) -> None:
|
98
|
-
if (
|
99
|
-
py_type.__name__ in EnumDeclaration.BUILTIN_ENUM_DECLARATIONS
|
100
|
-
or py_type.__name__ in qmodule.enum_decls
|
101
|
-
):
|
102
|
-
return
|
103
|
-
|
104
|
-
qmodule.enum_decls[py_type.__name__] = declaration_from_enum(py_type)
|
105
|
-
|
106
|
-
|
107
|
-
def _add_qmod_struct(py_type: Type, *, qmodule: ModelStateContainer) -> None:
|
108
|
-
if (
|
109
|
-
py_type.__name__ in StructDeclaration.BUILTIN_STRUCT_DECLARATIONS
|
110
|
-
or py_type.__name__ in qmodule.type_decls
|
111
|
-
):
|
112
|
-
return
|
113
|
-
|
114
|
-
qmodule.type_decls[py_type.__name__] = StructDeclaration(
|
115
|
-
name=py_type.__name__,
|
116
|
-
variables={
|
117
|
-
f.name: python_type_to_qmod(f.type, qmodule=qmodule)
|
118
|
-
for f in dataclasses.fields(py_type)
|
119
|
-
},
|
120
|
-
)
|
89
|
+
return _PythonClassicalType(qmodule).convert(py_type)
|
121
90
|
|
122
91
|
|
123
92
|
def _extract_port_decl(name: Optional[str], py_type: Any) -> AnonPortDeclaration:
|
@@ -137,13 +106,15 @@ def _extract_port_decl(name: Optional[str], py_type: Any) -> AnonPortDeclaration
|
|
137
106
|
|
138
107
|
|
139
108
|
def _extract_operand_decl(
|
140
|
-
name: Optional[str], py_type: Any, qmodule: ModelStateContainer
|
109
|
+
name: Optional[str], py_type: Any, qmodule: Optional[ModelStateContainer]
|
141
110
|
) -> AnonQuantumOperandDeclaration:
|
142
111
|
is_list = (get_origin(py_type) or py_type) is QCallableList
|
143
112
|
if get_origin(py_type) is list:
|
144
113
|
is_list = True
|
145
|
-
py_type = version_portable_get_args(py_type)
|
114
|
+
py_type = version_portable_get_args(py_type)[0]
|
146
115
|
type_args = version_portable_get_args(py_type)
|
116
|
+
if len(type_args) > 0 and isinstance(type_args[0], list): # Callable support
|
117
|
+
type_args = tuple(type_args[0])
|
147
118
|
param_decls = [_extract_operand_param(arg_type) for arg_type in type_args]
|
148
119
|
param = AnonQuantumOperandDeclaration(
|
149
120
|
name=name,
|
@@ -181,20 +152,20 @@ def _extract_operand_param(py_type: Any) -> Tuple[Optional[str], Any]:
|
|
181
152
|
|
182
153
|
@overload
|
183
154
|
def _extract_positional_args(
|
184
|
-
args: Sequence[Tuple[str, Any]], qmodule: ModelStateContainer
|
155
|
+
args: Sequence[Tuple[str, Any]], qmodule: Optional[ModelStateContainer]
|
185
156
|
) -> Sequence[PositionalArg]:
|
186
157
|
pass
|
187
158
|
|
188
159
|
|
189
160
|
@overload
|
190
161
|
def _extract_positional_args(
|
191
|
-
args: Sequence[Tuple[Optional[str], Any]], qmodule: ModelStateContainer
|
162
|
+
args: Sequence[Tuple[Optional[str], Any]], qmodule: Optional[ModelStateContainer]
|
192
163
|
) -> Sequence[AnonPositionalArg]:
|
193
164
|
pass
|
194
165
|
|
195
166
|
|
196
167
|
def _extract_positional_args(
|
197
|
-
args: Sequence[Tuple[Optional[str], Any]], qmodule: ModelStateContainer
|
168
|
+
args: Sequence[Tuple[Optional[str], Any]], qmodule: Optional[ModelStateContainer]
|
198
169
|
) -> Sequence[AnonPositionalArg]:
|
199
170
|
result: List[AnonPositionalArg] = []
|
200
171
|
for name, py_type in args:
|
@@ -218,7 +189,7 @@ def _extract_positional_args(
|
|
218
189
|
|
219
190
|
|
220
191
|
def infer_func_decl(
|
221
|
-
py_func: Callable, qmodule: ModelStateContainer
|
192
|
+
py_func: Callable, qmodule: Optional[ModelStateContainer] = None
|
222
193
|
) -> NamedParamsQuantumFunctionDeclaration:
|
223
194
|
return NamedParamsQuantumFunctionDeclaration(
|
224
195
|
name=unmangle_keyword(py_func.__name__),
|
classiq/qmod/expression_query.py
CHANGED
@@ -13,6 +13,22 @@ def get_expression_numeric_attributes(
|
|
13
13
|
expr: SymbolicTypes,
|
14
14
|
machine_precision: int = MAXIMAL_MACHINE_PRECISION,
|
15
15
|
) -> Tuple[int, bool, int]:
|
16
|
+
"""
|
17
|
+
Computes and returns the numeric attributes of a given symbolic expression.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
vars: A list of `QNum` variables used in the symbolic expression.
|
21
|
+
expr: The symbolic expression for which numeric attributes are to be computed.
|
22
|
+
machine_precision: The precision level of the machine for the computation. Defaults to MAXIMAL_MACHINE_PRECISION = 20.
|
23
|
+
|
24
|
+
Returns:
|
25
|
+
Tuple[int, bool, int]:
|
26
|
+
A tuple containing the following numeric attributes:
|
27
|
+
- The size in bits (int) required to represent the result.
|
28
|
+
- A boolean indicating whether the result is signed (bool).
|
29
|
+
- The number of fraction digits (int) in the result.
|
30
|
+
|
31
|
+
"""
|
16
32
|
res_type = compute_arithmetic_result_type(
|
17
33
|
expr_str=str(expr),
|
18
34
|
var_types={str(var.get_handle_binding()): var.get_qmod_type() for var in vars},
|
@@ -0,0 +1,48 @@
|
|
1
|
+
from contextlib import contextmanager
|
2
|
+
from typing import TYPE_CHECKING, Iterator, Optional
|
3
|
+
|
4
|
+
from classiq.interface.exceptions import ClassiqError
|
5
|
+
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from classiq.model_expansions.interpreter import Interpreter
|
8
|
+
|
9
|
+
_GENERATIVE_ENABLED_SWITCH: bool = True
|
10
|
+
_GENERATIVE_MODE: bool = False
|
11
|
+
_FRONTEND_INTERPRETER: Optional["Interpreter"] = None
|
12
|
+
|
13
|
+
|
14
|
+
def is_generative_mode() -> bool:
|
15
|
+
return _GENERATIVE_MODE
|
16
|
+
|
17
|
+
|
18
|
+
@contextmanager
|
19
|
+
def generative_mode_context(generative: bool) -> Iterator[None]:
|
20
|
+
global _GENERATIVE_MODE
|
21
|
+
previous = _GENERATIVE_MODE
|
22
|
+
_GENERATIVE_MODE = generative
|
23
|
+
yield
|
24
|
+
_GENERATIVE_MODE = previous
|
25
|
+
|
26
|
+
|
27
|
+
@contextmanager
|
28
|
+
def enable_generative_expansion(enabled: bool) -> Iterator[None]:
|
29
|
+
global _GENERATIVE_ENABLED_SWITCH
|
30
|
+
previous = _GENERATIVE_ENABLED_SWITCH
|
31
|
+
_GENERATIVE_ENABLED_SWITCH = enabled
|
32
|
+
yield
|
33
|
+
_GENERATIVE_ENABLED_SWITCH = previous
|
34
|
+
|
35
|
+
|
36
|
+
def is_generative_expansion_enabled() -> bool:
|
37
|
+
return _GENERATIVE_ENABLED_SWITCH
|
38
|
+
|
39
|
+
|
40
|
+
def set_frontend_interpreter(interpreter: "Interpreter") -> None:
|
41
|
+
global _FRONTEND_INTERPRETER
|
42
|
+
_FRONTEND_INTERPRETER = interpreter
|
43
|
+
|
44
|
+
|
45
|
+
def get_frontend_interpreter() -> "Interpreter":
|
46
|
+
if _FRONTEND_INTERPRETER is None:
|
47
|
+
raise ClassiqError("Interpreter was not set")
|
48
|
+
return _FRONTEND_INTERPRETER
|
@@ -3,10 +3,9 @@ from typing import Dict
|
|
3
3
|
from classiq.interface.generator.constant import Constant
|
4
4
|
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
5
5
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
6
|
+
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
6
7
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
7
8
|
|
8
|
-
from classiq import StructDeclaration
|
9
|
-
|
10
9
|
|
11
10
|
class ModelStateContainer:
|
12
11
|
enum_decls: Dict[str, EnumDeclaration]
|
@@ -3,7 +3,11 @@ from typing import Dict, List, Mapping, Optional, Union
|
|
3
3
|
from classiq.interface.generator.constant import Constant
|
4
4
|
from classiq.interface.generator.expressions.expression import Expression
|
5
5
|
from classiq.interface.generator.functions.classical_type import (
|
6
|
+
Bool,
|
6
7
|
ClassicalArray,
|
8
|
+
ClassicalList,
|
9
|
+
Integer,
|
10
|
+
Real,
|
7
11
|
)
|
8
12
|
from classiq.interface.generator.functions.concrete_types import (
|
9
13
|
ConcreteClassicalType,
|
@@ -15,6 +19,7 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
15
19
|
from classiq.interface.generator.functions.type_name import TypeName
|
16
20
|
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
17
21
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
22
|
+
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
18
23
|
from classiq.interface.generator.visitor import NodeType, Visitor
|
19
24
|
from classiq.interface.model.bind_operation import BindOperation
|
20
25
|
from classiq.interface.model.classical_if import ClassicalIf
|
@@ -68,17 +73,8 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
68
73
|
)
|
69
74
|
from classiq.interface.model.within_apply_operation import WithinApply
|
70
75
|
|
71
|
-
from classiq import (
|
72
|
-
Bool,
|
73
|
-
ClassicalList,
|
74
|
-
Integer,
|
75
|
-
Real,
|
76
|
-
StructDeclaration,
|
77
|
-
)
|
78
76
|
from classiq.qmod.native.expression_to_qmod import transform_expression
|
79
|
-
from classiq.qmod.semantics.static_semantics_visitor import
|
80
|
-
static_semantics_analysis_pass,
|
81
|
-
)
|
77
|
+
from classiq.qmod.semantics.static_semantics_visitor import resolve_function_calls
|
82
78
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
83
79
|
|
84
80
|
|
@@ -97,7 +93,7 @@ class DSLPrettyPrinter(Visitor):
|
|
97
93
|
|
98
94
|
def visit_Model(self, model: Model) -> str:
|
99
95
|
# FIXME - CAD-20149: Remove this line once the froggies are removed, and the visit of lambdas can be done without accessing the func_decl property (with rename_params values only).
|
100
|
-
|
96
|
+
resolve_function_calls(model, model.function_dict)
|
101
97
|
enum_decls = [self.visit(enum_decl) for enum_decl in model.enums]
|
102
98
|
struct_decls = [self.visit(struct_decl) for struct_decl in model.types]
|
103
99
|
qstruct_decls = [self.visit(qstruct_decl) for qstruct_decl in model.qstructs]
|
@@ -5,7 +5,11 @@ import black
|
|
5
5
|
from classiq.interface.generator.constant import Constant
|
6
6
|
from classiq.interface.generator.expressions.expression import Expression
|
7
7
|
from classiq.interface.generator.functions.classical_type import (
|
8
|
+
Bool,
|
8
9
|
ClassicalArray,
|
10
|
+
ClassicalList,
|
11
|
+
Integer,
|
12
|
+
Real,
|
9
13
|
)
|
10
14
|
from classiq.interface.generator.functions.concrete_types import (
|
11
15
|
ConcreteClassicalType,
|
@@ -17,6 +21,7 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
17
21
|
from classiq.interface.generator.functions.type_name import TypeName
|
18
22
|
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
19
23
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
24
|
+
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
20
25
|
from classiq.interface.generator.visitor import NodeType, Visitor
|
21
26
|
from classiq.interface.model.bind_operation import BindOperation
|
22
27
|
from classiq.interface.model.classical_if import ClassicalIf
|
@@ -72,13 +77,7 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
72
77
|
from classiq.interface.model.within_apply_operation import WithinApply
|
73
78
|
|
74
79
|
import classiq
|
75
|
-
from classiq import
|
76
|
-
Bool,
|
77
|
-
ClassicalList,
|
78
|
-
Integer,
|
79
|
-
Real,
|
80
|
-
StructDeclaration,
|
81
|
-
)
|
80
|
+
from classiq.qmod.builtins.functions import BUILTIN_FUNCTION_DECLARATIONS
|
82
81
|
from classiq.qmod.pretty_print.expression_to_python import transform_expression
|
83
82
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
84
83
|
|
@@ -147,10 +146,7 @@ class PythonPrettyPrinter(Visitor):
|
|
147
146
|
return res
|
148
147
|
|
149
148
|
def visit_Model(self, model: Model) -> str:
|
150
|
-
self._functions = {
|
151
|
-
**model.function_dict,
|
152
|
-
**QuantumFunctionDeclaration.BUILTIN_FUNCTION_DECLARATIONS,
|
153
|
-
}
|
149
|
+
self._functions = {**model.function_dict, **BUILTIN_FUNCTION_DECLARATIONS}
|
154
150
|
enum_decls = [self.visit(decl) for decl in model.enums]
|
155
151
|
struct_decls = [self.visit(decl) for decl in model.types]
|
156
152
|
qstruct_decls = [self.visit(qstruct_decl) for qstruct_decl in model.qstructs]
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import dataclasses
|
2
|
+
import inspect
|
3
|
+
import sys
|
4
|
+
from enum import EnumMeta
|
5
|
+
from typing import (
|
6
|
+
Optional,
|
7
|
+
get_args,
|
8
|
+
get_origin,
|
9
|
+
)
|
10
|
+
|
11
|
+
from classiq.interface.exceptions import ClassiqValueError
|
12
|
+
from classiq.interface.generator.functions.classical_type import (
|
13
|
+
Bool,
|
14
|
+
ClassicalArray,
|
15
|
+
ClassicalList,
|
16
|
+
Integer,
|
17
|
+
Real,
|
18
|
+
)
|
19
|
+
from classiq.interface.generator.functions.type_name import Enum, Struct
|
20
|
+
|
21
|
+
from classiq.qmod.cparam import CArray, CBool, CInt, CReal
|
22
|
+
from classiq.qmod.qmod_variable import get_type_hint_expr
|
23
|
+
from classiq.qmod.utilities import version_portable_get_args
|
24
|
+
|
25
|
+
if sys.version_info[0:2] >= (3, 9):
|
26
|
+
pass
|
27
|
+
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
28
|
+
|
29
|
+
|
30
|
+
class PythonClassicalType:
|
31
|
+
def convert(self, py_type: type) -> Optional[ConcreteClassicalType]:
|
32
|
+
if py_type is int or py_type is CInt:
|
33
|
+
return Integer()
|
34
|
+
elif py_type in (float, complex) or py_type is CReal:
|
35
|
+
return Real()
|
36
|
+
elif py_type is bool or py_type is CBool:
|
37
|
+
return Bool()
|
38
|
+
elif get_origin(py_type) is list:
|
39
|
+
element_type = self.convert(get_args(py_type)[0])
|
40
|
+
if element_type is not None:
|
41
|
+
return ClassicalList(element_type=element_type)
|
42
|
+
elif get_origin(py_type) is CArray:
|
43
|
+
array_args = version_portable_get_args(py_type)
|
44
|
+
if len(array_args) == 1:
|
45
|
+
return ClassicalList(element_type=self.convert(array_args[0]))
|
46
|
+
elif len(array_args) == 2:
|
47
|
+
return ClassicalArray(
|
48
|
+
element_type=self.convert(array_args[0]),
|
49
|
+
size=get_type_hint_expr(array_args[1]),
|
50
|
+
)
|
51
|
+
raise ClassiqValueError(
|
52
|
+
"CArray accepts one or two generic parameters in the form "
|
53
|
+
"`CArray[<element-type>]` or `CArray[<element-type>, <size>]`"
|
54
|
+
)
|
55
|
+
elif inspect.isclass(py_type) and dataclasses.is_dataclass(py_type):
|
56
|
+
self.register_struct(py_type)
|
57
|
+
return Struct(name=py_type.__name__)
|
58
|
+
elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
|
59
|
+
self.register_enum(py_type)
|
60
|
+
return Enum(name=py_type.__name__)
|
61
|
+
return None
|
62
|
+
|
63
|
+
def register_struct(self, py_type: type) -> None:
|
64
|
+
pass
|
65
|
+
|
66
|
+
def register_enum(self, py_type: EnumMeta) -> None:
|
67
|
+
pass
|
classiq/qmod/qfunc.py
CHANGED
@@ -1,8 +1,20 @@
|
|
1
|
-
from typing import Callable, Literal, Optional, Union, overload
|
1
|
+
from typing import Callable, List, Literal, Optional, Union, overload
|
2
2
|
|
3
3
|
from classiq.qmod.quantum_callable import QCallable
|
4
4
|
from classiq.qmod.quantum_function import ExternalQFunc, GenerativeQFunc, QFunc
|
5
5
|
|
6
|
+
GEN_QFUNCS: List[GenerativeQFunc] = []
|
7
|
+
DEC_QFUNCS: List[QFunc] = []
|
8
|
+
|
9
|
+
|
10
|
+
def set_discovered_functions(
|
11
|
+
dec_funcs: List[QFunc], gen_funcs: List[GenerativeQFunc]
|
12
|
+
) -> None:
|
13
|
+
DEC_QFUNCS.clear()
|
14
|
+
DEC_QFUNCS.extend(dec_funcs)
|
15
|
+
GEN_QFUNCS.clear()
|
16
|
+
GEN_QFUNCS.extend(gen_funcs)
|
17
|
+
|
6
18
|
|
7
19
|
@overload
|
8
20
|
def qfunc(func: Callable) -> QFunc: ...
|
@@ -21,11 +33,14 @@ def qfunc(
|
|
21
33
|
) -> Union[Callable[[Callable], QCallable], QCallable]:
|
22
34
|
def wrapper(func: Callable) -> QCallable:
|
23
35
|
if generative:
|
24
|
-
|
36
|
+
gen_qfunc = GenerativeQFunc(func)
|
37
|
+
GEN_QFUNCS.append(gen_qfunc)
|
38
|
+
return gen_qfunc
|
25
39
|
if external:
|
26
40
|
return ExternalQFunc(func)
|
27
|
-
|
28
|
-
|
41
|
+
dec_qfunc = QFunc(func)
|
42
|
+
DEC_QFUNCS.append(dec_qfunc)
|
43
|
+
return dec_qfunc
|
29
44
|
|
30
45
|
if func is not None:
|
31
46
|
return wrapper(func)
|