classiq 0.43.3__py3-none-any.whl → 0.44.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 +7 -1
- classiq/_internals/client.py +4 -7
- classiq/_internals/host_checker.py +34 -12
- classiq/_internals/jobs.py +2 -2
- classiq/applications/chemistry/chemistry_model_constructor.py +12 -6
- classiq/applications/combinatorial_helpers/allowed_constraints.py +4 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
- classiq/applications/finance/finance_model_constructor.py +3 -2
- classiq/applications/grover/grover_model_constructor.py +7 -5
- classiq/applications/hamiltonian/__init__.py +0 -0
- classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
- classiq/applications/qnn/qlayer.py +1 -1
- classiq/exceptions.py +4 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/ast_node.py +1 -18
- classiq/interface/backend/backend_preferences.py +10 -16
- classiq/interface/backend/ionq/ionq_quantum_program.py +1 -1
- classiq/interface/backend/pydantic_backend.py +0 -5
- classiq/interface/backend/quantum_backend_providers.py +3 -2
- classiq/interface/chemistry/operator.py +5 -1
- classiq/interface/debug_info/__init__.py +0 -0
- classiq/interface/debug_info/debug_info.py +32 -0
- classiq/interface/executor/execution_preferences.py +1 -45
- classiq/interface/executor/result.py +25 -12
- classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
- classiq/interface/generator/application_apis/chemistry_declarations.py +78 -60
- classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +19 -10
- classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
- classiq/interface/generator/application_apis/finance_declarations.py +36 -22
- classiq/interface/generator/application_apis/qsvm_declarations.py +21 -15
- classiq/interface/generator/arith/arithmetic_expression_abc.py +21 -1
- classiq/interface/generator/arith/binary_ops.py +5 -4
- classiq/interface/generator/arith/extremum_operations.py +43 -19
- classiq/interface/generator/constant.py +1 -1
- classiq/interface/generator/expressions/atomic_expression_functions.py +1 -0
- classiq/interface/generator/expressions/expression_constants.py +3 -1
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +52 -66
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +35 -0
- classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
- classiq/interface/generator/functions/builtins/core_library/__init__.py +4 -2
- classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +41 -41
- classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +52 -42
- classiq/interface/generator/functions/builtins/open_lib_functions.py +1095 -3347
- classiq/interface/generator/functions/builtins/quantum_operators.py +9 -22
- classiq/interface/generator/functions/classical_function_declaration.py +14 -6
- classiq/interface/generator/functions/classical_type.py +7 -76
- classiq/interface/generator/functions/concrete_types.py +55 -0
- classiq/interface/generator/functions/function_declaration.py +10 -10
- classiq/interface/generator/functions/type_name.py +104 -0
- classiq/interface/generator/generated_circuit_data.py +3 -3
- classiq/interface/generator/model/model.py +11 -0
- classiq/interface/generator/model/preferences/preferences.py +5 -0
- classiq/interface/generator/quantum_function_call.py +3 -0
- classiq/interface/generator/quantum_program.py +2 -2
- classiq/interface/generator/register_role.py +7 -1
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +1 -3
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +1 -2
- classiq/interface/generator/types/qstruct_declaration.py +17 -0
- classiq/interface/generator/types/struct_declaration.py +1 -1
- classiq/interface/helpers/validation_helpers.py +1 -17
- classiq/interface/ide/visual_model.py +9 -2
- classiq/interface/interface_version.py +1 -0
- classiq/interface/model/bind_operation.py +25 -5
- classiq/interface/model/classical_parameter_declaration.py +8 -5
- classiq/interface/model/control.py +5 -5
- classiq/interface/model/handle_binding.py +185 -12
- classiq/interface/model/inplace_binary_operation.py +16 -4
- classiq/interface/model/model.py +28 -5
- classiq/interface/model/native_function_definition.py +8 -4
- classiq/interface/model/parameter.py +14 -0
- classiq/interface/model/port_declaration.py +20 -2
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +21 -6
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +30 -6
- classiq/interface/model/quantum_expressions/quantum_expression.py +4 -9
- classiq/interface/model/quantum_function_call.py +135 -192
- classiq/interface/model/quantum_function_declaration.py +147 -165
- classiq/interface/model/quantum_lambda_function.py +24 -6
- classiq/interface/model/quantum_statement.py +34 -8
- classiq/interface/model/quantum_type.py +61 -10
- classiq/interface/model/quantum_variable_declaration.py +1 -1
- classiq/interface/model/statement_block.py +2 -0
- classiq/interface/model/validation_handle.py +7 -0
- classiq/interface/server/global_versions.py +4 -4
- classiq/interface/server/routes.py +2 -0
- classiq/interface/source_reference.py +59 -0
- classiq/qmod/__init__.py +2 -3
- classiq/qmod/builtins/functions.py +39 -11
- classiq/qmod/builtins/operations.py +171 -40
- classiq/qmod/declaration_inferrer.py +99 -56
- classiq/qmod/expression_query.py +1 -1
- classiq/qmod/model_state_container.py +2 -0
- classiq/qmod/native/pretty_printer.py +71 -53
- classiq/qmod/pretty_print/pretty_printer.py +98 -52
- classiq/qmod/qfunc.py +11 -5
- classiq/qmod/qmod_parameter.py +1 -2
- classiq/qmod/qmod_variable.py +364 -172
- classiq/qmod/quantum_callable.py +3 -3
- classiq/qmod/quantum_expandable.py +119 -65
- classiq/qmod/quantum_function.py +15 -3
- classiq/qmod/semantics/annotation.py +12 -13
- classiq/qmod/semantics/error_manager.py +36 -10
- classiq/qmod/semantics/static_semantics_visitor.py +163 -75
- classiq/qmod/semantics/validation/func_call_validation.py +42 -96
- classiq/qmod/semantics/validation/handle_validation.py +85 -0
- classiq/qmod/semantics/validation/types_validation.py +108 -1
- classiq/qmod/type_attribute_remover.py +32 -0
- classiq/qmod/utilities.py +26 -5
- {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/METADATA +3 -3
- {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/RECORD +111 -99
- classiq/qmod/qmod_struct.py +0 -13
- /classiq/{interface/ide/show.py → show.py} +0 -0
- {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/WHEEL +0 -0
@@ -2,18 +2,16 @@ from typing import (
|
|
2
2
|
Any,
|
3
3
|
ClassVar,
|
4
4
|
Dict,
|
5
|
-
List,
|
6
5
|
Literal,
|
7
|
-
Mapping,
|
8
6
|
Sequence,
|
9
7
|
Set,
|
10
|
-
Type,
|
11
8
|
Union,
|
12
9
|
)
|
13
10
|
|
14
11
|
import pydantic
|
15
12
|
from typing_extensions import Annotated
|
16
13
|
|
14
|
+
from classiq.interface.generator.arith.register_user_input import RegisterUserInput
|
17
15
|
from classiq.interface.generator.function_params import ArithmeticIODict, PortDirection
|
18
16
|
from classiq.interface.generator.functions.function_declaration import (
|
19
17
|
FunctionDeclaration,
|
@@ -22,218 +20,122 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
22
20
|
PortDeclarationDirection,
|
23
21
|
)
|
24
22
|
from classiq.interface.helpers.pydantic_model_helpers import (
|
25
|
-
Nameable,
|
26
23
|
values_with_discriminator,
|
27
24
|
)
|
28
|
-
from classiq.interface.helpers.validation_helpers import (
|
29
|
-
validate_nameables_mapping,
|
30
|
-
validate_nameables_no_overlap,
|
31
|
-
)
|
32
25
|
from classiq.interface.model.classical_parameter_declaration import (
|
26
|
+
AnonClassicalParameterDeclaration,
|
33
27
|
ClassicalParameterDeclaration,
|
34
28
|
)
|
35
|
-
from classiq.interface.model.port_declaration import
|
29
|
+
from classiq.interface.model.port_declaration import (
|
30
|
+
AnonPortDeclaration,
|
31
|
+
PortDeclaration,
|
32
|
+
)
|
36
33
|
from classiq.interface.model.quantum_type import quantum_var_to_register
|
37
34
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
return pos_decl == kw_decl
|
45
|
-
|
46
|
-
|
47
|
-
def _populate_declaration_dicts_with_positional_lists(
|
48
|
-
pos_decls: Sequence[Nameable],
|
49
|
-
kw_decls: Dict[str, Nameable],
|
50
|
-
param_type: Type[Nameable],
|
51
|
-
) -> None:
|
52
|
-
for pos_decl in pos_decls:
|
53
|
-
if not isinstance(pos_decl, param_type):
|
54
|
-
continue
|
55
|
-
kw_decl = kw_decls.get(pos_decl.name)
|
56
|
-
if kw_decl is not None and not _is_equiv_kw_and_pos_decl(kw_decl, pos_decl):
|
57
|
-
raise ClassiqValueError(
|
58
|
-
f"{param_type.__name__} parameter with name {pos_decl.name} already declared"
|
59
|
-
)
|
60
|
-
kw_decls[pos_decl.name] = (
|
61
|
-
pos_decl.classical_type # type:ignore[assignment]
|
62
|
-
if isinstance(pos_decl, ClassicalParameterDeclaration)
|
63
|
-
else pos_decl
|
64
|
-
)
|
65
|
-
|
66
|
-
|
67
|
-
PositionalArg = Annotated[
|
68
|
-
Union[ClassicalParameterDeclaration, "QuantumOperandDeclaration", PortDeclaration],
|
35
|
+
AnonPositionalArg = Annotated[
|
36
|
+
Union[
|
37
|
+
AnonClassicalParameterDeclaration,
|
38
|
+
"AnonQuantumOperandDeclaration",
|
39
|
+
AnonPortDeclaration,
|
40
|
+
],
|
69
41
|
pydantic.Field(..., discriminator="kind"),
|
70
42
|
]
|
71
43
|
|
72
44
|
|
73
45
|
def _ports_to_registers(
|
74
|
-
port_declarations:
|
75
|
-
) ->
|
76
|
-
return
|
77
|
-
|
78
|
-
for
|
46
|
+
port_declarations: Sequence[AnonPortDeclaration], direction: PortDirection
|
47
|
+
) -> Sequence[RegisterUserInput]:
|
48
|
+
return [
|
49
|
+
quantum_var_to_register(port_decl.get_name(), port_decl.quantum_type)
|
50
|
+
for port_decl in port_declarations
|
79
51
|
if port_decl.direction.includes_port_direction(direction)
|
80
|
-
|
52
|
+
]
|
81
53
|
|
82
54
|
|
83
|
-
class
|
55
|
+
class AnonQuantumFunctionDeclaration(FunctionDeclaration):
|
84
56
|
"""
|
85
57
|
Facilitates the creation of a common quantum function interface object.
|
86
58
|
"""
|
87
59
|
|
88
|
-
|
89
|
-
|
90
|
-
default_factory=dict,
|
60
|
+
positional_arg_declarations: Sequence[AnonPositionalArg] = pydantic.Field(
|
61
|
+
default_factory=list
|
91
62
|
)
|
92
63
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
64
|
+
@property
|
65
|
+
def port_declarations(self) -> Sequence[AnonPortDeclaration]:
|
66
|
+
return [
|
67
|
+
arg
|
68
|
+
for arg in self.positional_arg_declarations
|
69
|
+
if isinstance(arg, AnonPortDeclaration)
|
70
|
+
]
|
97
71
|
|
98
|
-
|
99
|
-
|
100
|
-
|
72
|
+
@property
|
73
|
+
def operand_declarations(self) -> Sequence["AnonQuantumOperandDeclaration"]:
|
74
|
+
return [
|
75
|
+
arg
|
76
|
+
for arg in self.positional_arg_declarations
|
77
|
+
if isinstance(arg, AnonQuantumOperandDeclaration)
|
78
|
+
]
|
101
79
|
|
102
|
-
|
103
|
-
|
104
|
-
|
80
|
+
@property
|
81
|
+
def param_decls(self) -> Sequence[AnonClassicalParameterDeclaration]:
|
82
|
+
return [
|
83
|
+
arg
|
84
|
+
for arg in self.positional_arg_declarations
|
85
|
+
if isinstance(arg, AnonClassicalParameterDeclaration)
|
86
|
+
]
|
87
|
+
|
88
|
+
@property
|
89
|
+
def param_names(self) -> Sequence[str]:
|
90
|
+
return [param.get_name() for param in self.param_decls]
|
105
91
|
|
106
92
|
@property
|
107
93
|
def input_set(self) -> Set[str]:
|
108
|
-
return
|
94
|
+
return {inp.name for inp in self.inputs}
|
109
95
|
|
110
96
|
@property
|
111
97
|
def output_set(self) -> Set[str]:
|
112
|
-
return
|
98
|
+
return {output.name for output in self.outputs}
|
113
99
|
|
114
100
|
@property
|
115
|
-
def inputs(self) ->
|
101
|
+
def inputs(self) -> Sequence[RegisterUserInput]:
|
116
102
|
return _ports_to_registers(self.port_declarations, PortDirection.Input)
|
117
103
|
|
118
104
|
@property
|
119
|
-
def outputs(self) ->
|
105
|
+
def outputs(self) -> Sequence[RegisterUserInput]:
|
120
106
|
return _ports_to_registers(self.port_declarations, PortDirection.Output)
|
121
107
|
|
122
|
-
def update_logic_flow(
|
123
|
-
self, function_dict: Mapping[str, "QuantumFunctionDeclaration"]
|
124
|
-
) -> None:
|
125
|
-
pass
|
126
|
-
|
127
108
|
@property
|
128
|
-
def port_names(self) ->
|
129
|
-
return
|
109
|
+
def port_names(self) -> Sequence[str]:
|
110
|
+
return [port.get_name() for port in self.port_declarations]
|
130
111
|
|
131
112
|
@property
|
132
|
-
def operand_names(self) ->
|
133
|
-
return
|
113
|
+
def operand_names(self) -> Sequence[str]:
|
114
|
+
return [operand.get_name() for operand in self.operand_declarations]
|
134
115
|
|
135
116
|
def ports_by_direction(
|
136
117
|
self, direction: PortDirection
|
137
|
-
) ->
|
138
|
-
return
|
139
|
-
|
140
|
-
for
|
118
|
+
) -> Sequence[AnonPortDeclaration]:
|
119
|
+
return [
|
120
|
+
port
|
121
|
+
for port in self.port_declarations
|
141
122
|
if port.direction.includes_port_direction(direction)
|
142
|
-
|
123
|
+
]
|
143
124
|
|
144
125
|
def ports_by_declaration_direction(
|
145
126
|
self, direction: PortDeclarationDirection
|
146
127
|
) -> Set[str]:
|
147
128
|
return {
|
148
|
-
|
149
|
-
for
|
129
|
+
port.get_name()
|
130
|
+
for port in self.port_declarations
|
150
131
|
if port.direction == direction
|
151
132
|
}
|
152
133
|
|
153
|
-
def
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
for name, ctype in self.param_decls.items()
|
159
|
-
]
|
160
|
-
result.extend(self.operand_declarations.values())
|
161
|
-
result.extend(self.port_declarations.values())
|
162
|
-
return result
|
163
|
-
|
164
|
-
@pydantic.validator("operand_declarations")
|
165
|
-
def _validate_operand_declarations_names(
|
166
|
-
cls, operand_declarations: Dict[str, "QuantumOperandDeclaration"]
|
167
|
-
) -> Dict[str, "QuantumOperandDeclaration"]:
|
168
|
-
validate_nameables_mapping(operand_declarations, "Operand")
|
169
|
-
return operand_declarations
|
170
|
-
|
171
|
-
@pydantic.validator("port_declarations")
|
172
|
-
def _validate_port_declarations_names(
|
173
|
-
cls, port_declarations: Dict[str, PortDeclaration]
|
174
|
-
) -> Dict[str, PortDeclaration]:
|
175
|
-
validate_nameables_mapping(port_declarations, "Port")
|
176
|
-
return port_declarations
|
177
|
-
|
178
|
-
@pydantic.root_validator()
|
179
|
-
def _validate_params_and_operands_uniqueness(
|
180
|
-
cls, values: Dict[str, Any]
|
181
|
-
) -> Dict[str, Any]:
|
182
|
-
operand_declarations = values.get("operand_declarations")
|
183
|
-
parameter_declarations = values.get("param_decls")
|
184
|
-
port_declarations = values.get("port_declarations")
|
185
|
-
operand_parameter = validate_nameables_no_overlap(
|
186
|
-
operand_declarations, parameter_declarations, "operand", "parameter"
|
187
|
-
)
|
188
|
-
operand_port = validate_nameables_no_overlap(
|
189
|
-
operand_declarations, port_declarations, "operand", "port"
|
190
|
-
)
|
191
|
-
parameter_port = validate_nameables_no_overlap(
|
192
|
-
parameter_declarations, port_declarations, "parameter", "port"
|
193
|
-
)
|
194
|
-
error_message = ",".join(
|
195
|
-
msg
|
196
|
-
for msg in [operand_parameter, operand_port, parameter_port]
|
197
|
-
if msg is not None
|
198
|
-
)
|
199
|
-
|
200
|
-
if error_message:
|
201
|
-
raise ClassiqValueError(error_message)
|
202
|
-
|
203
|
-
return values
|
204
|
-
|
205
|
-
@pydantic.root_validator()
|
206
|
-
def _reduce_positional_declarations_to_keyword(
|
207
|
-
cls, values: Dict[str, Any]
|
208
|
-
) -> Dict[str, Any]:
|
209
|
-
operand_declarations = values.get("operand_declarations", dict())
|
210
|
-
parameter_declarations = values.get("param_decls", dict())
|
211
|
-
port_declarations = values.get("port_declarations", dict())
|
212
|
-
|
213
|
-
positional_arg_declarations = values.get("positional_arg_declarations", list())
|
214
|
-
|
215
|
-
_populate_declaration_dicts_with_positional_lists(
|
216
|
-
positional_arg_declarations,
|
217
|
-
parameter_declarations,
|
218
|
-
ClassicalParameterDeclaration,
|
219
|
-
)
|
220
|
-
_populate_declaration_dicts_with_positional_lists(
|
221
|
-
positional_arg_declarations,
|
222
|
-
operand_declarations,
|
223
|
-
QuantumOperandDeclaration,
|
224
|
-
)
|
225
|
-
_populate_declaration_dicts_with_positional_lists(
|
226
|
-
positional_arg_declarations, port_declarations, PortDeclaration
|
227
|
-
)
|
228
|
-
|
229
|
-
values["operand_declarations"] = operand_declarations
|
230
|
-
values["param_decls"] = parameter_declarations
|
231
|
-
values["port_declarations"] = port_declarations
|
232
|
-
|
233
|
-
return values
|
234
|
-
|
235
|
-
|
236
|
-
class QuantumOperandDeclaration(QuantumFunctionDeclaration):
|
134
|
+
def rename(self, new_name: str) -> "QuantumFunctionDeclaration":
|
135
|
+
return QuantumFunctionDeclaration(**{**self.__dict__, "name": new_name})
|
136
|
+
|
137
|
+
|
138
|
+
class AnonQuantumOperandDeclaration(AnonQuantumFunctionDeclaration):
|
237
139
|
kind: Literal["QuantumOperandDeclaration"]
|
238
140
|
|
239
141
|
is_list: bool = pydantic.Field(
|
@@ -245,5 +147,85 @@ class QuantumOperandDeclaration(QuantumFunctionDeclaration):
|
|
245
147
|
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
246
148
|
return values_with_discriminator(values, "kind", "QuantumOperandDeclaration")
|
247
149
|
|
150
|
+
def rename(self, new_name: str) -> "QuantumOperandDeclaration":
|
151
|
+
return QuantumOperandDeclaration(**{**self.__dict__, "name": new_name})
|
152
|
+
|
153
|
+
|
154
|
+
AnonQuantumFunctionDeclaration.update_forward_refs()
|
155
|
+
|
156
|
+
|
157
|
+
class QuantumFunctionDeclaration(AnonQuantumFunctionDeclaration):
|
158
|
+
name: str
|
159
|
+
|
160
|
+
BUILTIN_FUNCTION_DECLARATIONS: ClassVar[
|
161
|
+
Dict[str, "NamedParamsQuantumFunctionDeclaration"]
|
162
|
+
] = {}
|
163
|
+
|
164
|
+
|
165
|
+
class QuantumOperandDeclaration(
|
166
|
+
QuantumFunctionDeclaration, AnonQuantumOperandDeclaration
|
167
|
+
):
|
168
|
+
pass
|
248
169
|
|
249
|
-
|
170
|
+
|
171
|
+
PositionalArg = Annotated[
|
172
|
+
Union[
|
173
|
+
ClassicalParameterDeclaration,
|
174
|
+
QuantumOperandDeclaration,
|
175
|
+
PortDeclaration,
|
176
|
+
],
|
177
|
+
pydantic.Field(..., discriminator="kind"),
|
178
|
+
]
|
179
|
+
|
180
|
+
|
181
|
+
class NamedParamsQuantumFunctionDeclaration(QuantumFunctionDeclaration):
|
182
|
+
|
183
|
+
positional_arg_declarations: Sequence[PositionalArg] = pydantic.Field(
|
184
|
+
default_factory=list
|
185
|
+
)
|
186
|
+
|
187
|
+
@property
|
188
|
+
def port_declarations_dict(self) -> Dict[str, PortDeclaration]:
|
189
|
+
return {port.name: port for port in self.port_declarations}
|
190
|
+
|
191
|
+
@property
|
192
|
+
def operand_declarations_dict(self) -> Dict[str, QuantumOperandDeclaration]:
|
193
|
+
return {op.name: op for op in self.operand_declarations}
|
194
|
+
|
195
|
+
@property
|
196
|
+
def param_decls_dict(self) -> Dict[str, ClassicalParameterDeclaration]:
|
197
|
+
return {param.name: param for param in self.param_decls}
|
198
|
+
|
199
|
+
@property
|
200
|
+
def inputs_dict(self) -> ArithmeticIODict:
|
201
|
+
return _ports_to_registers_dict(self.port_declarations, PortDirection.Input)
|
202
|
+
|
203
|
+
@property
|
204
|
+
def inouts_dict(self) -> ArithmeticIODict:
|
205
|
+
return _ports_to_registers_dict(self.port_declarations, PortDirection.Inout)
|
206
|
+
|
207
|
+
@property
|
208
|
+
def outputs_dict(self) -> ArithmeticIODict:
|
209
|
+
return _ports_to_registers_dict(self.port_declarations, PortDirection.Output)
|
210
|
+
|
211
|
+
@property
|
212
|
+
def port_declarations(self) -> Sequence[PortDeclaration]:
|
213
|
+
return super().port_declarations # type:ignore[return-value]
|
214
|
+
|
215
|
+
@property
|
216
|
+
def operand_declarations(self) -> Sequence[QuantumOperandDeclaration]:
|
217
|
+
return super().operand_declarations # type:ignore[return-value]
|
218
|
+
|
219
|
+
@property
|
220
|
+
def param_decls(self) -> Sequence[ClassicalParameterDeclaration]:
|
221
|
+
return super().param_decls # type:ignore[return-value]
|
222
|
+
|
223
|
+
|
224
|
+
def _ports_to_registers_dict(
|
225
|
+
port_declarations: Sequence[PortDeclaration], direction: PortDirection
|
226
|
+
) -> ArithmeticIODict:
|
227
|
+
return {
|
228
|
+
port_decl.name: quantum_var_to_register(port_decl.name, port_decl.quantum_type)
|
229
|
+
for port_decl in port_declarations
|
230
|
+
if port_decl.direction.includes_port_direction(direction)
|
231
|
+
}
|
@@ -1,12 +1,14 @@
|
|
1
|
-
from typing import TYPE_CHECKING, Dict, List, Optional, Union
|
1
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Union, cast
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
5
5
|
from classiq.interface.ast_node import ASTNode
|
6
6
|
from classiq.interface.model.quantum_function_declaration import (
|
7
|
-
|
7
|
+
AnonQuantumOperandDeclaration,
|
8
8
|
)
|
9
9
|
|
10
|
+
from classiq.exceptions import ClassiqError
|
11
|
+
|
10
12
|
if TYPE_CHECKING:
|
11
13
|
from classiq.interface.model.statement_block import StatementBlock
|
12
14
|
|
@@ -18,22 +20,38 @@ class QuantumLambdaFunction(ASTNode):
|
|
18
20
|
|
19
21
|
rename_params: Dict[str, str] = pydantic.Field(
|
20
22
|
default_factory=dict,
|
21
|
-
|
23
|
+
)
|
24
|
+
|
25
|
+
pos_rename_params: List[str] = pydantic.Field(
|
26
|
+
default_factory=list,
|
27
|
+
description="Mapping of the declared param to the actual variable name used",
|
22
28
|
)
|
23
29
|
|
24
30
|
body: "StatementBlock" = pydantic.Field(
|
25
31
|
description="A list of function calls passed to the operator"
|
26
32
|
)
|
27
33
|
|
28
|
-
_func_decl: Optional[
|
34
|
+
_func_decl: Optional[AnonQuantumOperandDeclaration] = pydantic.PrivateAttr(
|
35
|
+
default=None
|
36
|
+
)
|
29
37
|
|
30
38
|
@property
|
31
|
-
def func_decl(self) ->
|
39
|
+
def func_decl(self) -> AnonQuantumOperandDeclaration:
|
40
|
+
if self._func_decl is None:
|
41
|
+
raise ClassiqError("Could not resolve lambda signature.")
|
32
42
|
return self._func_decl
|
33
43
|
|
34
|
-
def set_op_decl(self, fd:
|
44
|
+
def set_op_decl(self, fd: AnonQuantumOperandDeclaration) -> None:
|
35
45
|
self._func_decl = fd
|
36
46
|
|
47
|
+
def get_rename_params(self) -> List[str]:
|
48
|
+
if self.pos_rename_params:
|
49
|
+
return self.pos_rename_params
|
50
|
+
return [
|
51
|
+
self.rename_params.get(cast(str, param.name), cast(str, param.name))
|
52
|
+
for param in self.func_decl.positional_arg_declarations
|
53
|
+
]
|
54
|
+
|
37
55
|
|
38
56
|
QuantumCallable = Union[str, QuantumLambdaFunction]
|
39
57
|
QuantumOperand = Union[QuantumCallable, List[QuantumCallable]]
|
@@ -1,13 +1,13 @@
|
|
1
|
-
from
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from typing import Any, Dict, Mapping, Optional, Sequence
|
2
3
|
|
3
4
|
from pydantic import Extra, root_validator
|
4
5
|
|
5
6
|
from classiq.interface.ast_node import ASTNode
|
6
7
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
7
8
|
from classiq.interface.model.handle_binding import (
|
9
|
+
ConcreteHandleBinding,
|
8
10
|
HandleBinding,
|
9
|
-
SlicedHandleBinding,
|
10
|
-
SubscriptHandleBinding,
|
11
11
|
)
|
12
12
|
|
13
13
|
|
@@ -22,19 +22,45 @@ class QuantumStatement(ASTNode):
|
|
22
22
|
return values_with_discriminator(values, "kind", cls.__name__) # type: ignore[attr-defined]
|
23
23
|
|
24
24
|
|
25
|
+
@dataclass
|
26
|
+
class HandleMetadata:
|
27
|
+
handle: HandleBinding
|
28
|
+
readable_location: Optional[str] = None
|
29
|
+
|
30
|
+
|
25
31
|
class QuantumOperation(QuantumStatement):
|
26
32
|
@property
|
27
33
|
def wiring_inputs(self) -> Mapping[str, HandleBinding]:
|
28
34
|
return dict()
|
29
35
|
|
30
36
|
@property
|
31
|
-
def
|
32
|
-
self
|
33
|
-
|
34
|
-
|
35
|
-
]:
|
37
|
+
def inputs(self) -> Sequence[HandleBinding]:
|
38
|
+
return list(self.wiring_inputs.values())
|
39
|
+
|
40
|
+
@property
|
41
|
+
def wiring_inouts(self) -> Mapping[str, ConcreteHandleBinding]:
|
36
42
|
return dict()
|
37
43
|
|
44
|
+
@property
|
45
|
+
def inouts(self) -> Sequence[HandleBinding]:
|
46
|
+
return list(self.wiring_inouts.values())
|
47
|
+
|
38
48
|
@property
|
39
49
|
def wiring_outputs(self) -> Mapping[str, HandleBinding]:
|
40
50
|
return dict()
|
51
|
+
|
52
|
+
@property
|
53
|
+
def outputs(self) -> Sequence[HandleBinding]:
|
54
|
+
return list(self.wiring_outputs.values())
|
55
|
+
|
56
|
+
@property
|
57
|
+
def readable_inputs(self) -> Sequence[HandleMetadata]:
|
58
|
+
return [HandleMetadata(handle=handle) for handle in self.inputs]
|
59
|
+
|
60
|
+
@property
|
61
|
+
def readable_inouts(self) -> Sequence[HandleMetadata]:
|
62
|
+
return [HandleMetadata(handle=handle) for handle in self.inouts]
|
63
|
+
|
64
|
+
@property
|
65
|
+
def readable_outputs(self) -> Sequence[HandleMetadata]:
|
66
|
+
return [HandleMetadata(handle=handle) for handle in self.outputs]
|
@@ -1,8 +1,7 @@
|
|
1
|
-
from typing import Any, Dict, Literal, Optional
|
1
|
+
from typing import TYPE_CHECKING, Any, Dict, Literal, Optional
|
2
2
|
|
3
3
|
import pydantic
|
4
|
-
from pydantic import Extra, Field
|
5
|
-
from typing_extensions import Annotated
|
4
|
+
from pydantic import BaseModel, Extra, Field
|
6
5
|
|
7
6
|
from classiq.interface.ast_node import HashableASTNode
|
8
7
|
from classiq.interface.generator.arith.register_user_input import (
|
@@ -22,6 +21,11 @@ from classiq.interface.model.handle_binding import HandleBinding
|
|
22
21
|
|
23
22
|
from classiq.exceptions import ClassiqValueError
|
24
23
|
|
24
|
+
if TYPE_CHECKING:
|
25
|
+
from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
|
26
|
+
|
27
|
+
from classiq.qmod.qmod_variable import QArray, QBit, QNum, QVar
|
28
|
+
|
25
29
|
|
26
30
|
class QuantumType(HashableASTNode):
|
27
31
|
class Config:
|
@@ -56,7 +60,10 @@ class QuantumType(HashableASTNode):
|
|
56
60
|
|
57
61
|
@property
|
58
62
|
def type_name(self) -> str:
|
59
|
-
|
63
|
+
raise NotImplementedError
|
64
|
+
|
65
|
+
def to_qvar(self, origin: HandleBinding) -> "QVar":
|
66
|
+
raise NotImplementedError
|
60
67
|
|
61
68
|
|
62
69
|
class QuantumScalar(QuantumType):
|
@@ -82,6 +89,15 @@ class QuantumBit(QuantumScalar):
|
|
82
89
|
def get_proxy(self, handle: "HandleBinding") -> QmodQBitProxy:
|
83
90
|
return QmodQBitProxy(handle)
|
84
91
|
|
92
|
+
@property
|
93
|
+
def type_name(self) -> str:
|
94
|
+
return "Quantum bit"
|
95
|
+
|
96
|
+
def to_qvar(self, origin: HandleBinding) -> "QBit":
|
97
|
+
from classiq.qmod.qmod_variable import QBit
|
98
|
+
|
99
|
+
return QBit(origin)
|
100
|
+
|
85
101
|
|
86
102
|
class QuantumBitvector(QuantumType):
|
87
103
|
kind: Literal["qvec"]
|
@@ -120,7 +136,7 @@ class QuantumBitvector(QuantumType):
|
|
120
136
|
assert self.size_in_bits % element_size == 0
|
121
137
|
return QmodQArrayProxy(
|
122
138
|
handle,
|
123
|
-
self.element_type
|
139
|
+
self.element_type,
|
124
140
|
element_size,
|
125
141
|
self.size_in_bits // element_size,
|
126
142
|
)
|
@@ -131,6 +147,15 @@ class QuantumBitvector(QuantumType):
|
|
131
147
|
length = [self.length.expr] if self.length is not None else []
|
132
148
|
return f"QArray[{', '.join(element_type + length)}]"
|
133
149
|
|
150
|
+
@property
|
151
|
+
def type_name(self) -> str:
|
152
|
+
return "Quantum array"
|
153
|
+
|
154
|
+
def to_qvar(self, origin: HandleBinding) -> "QArray":
|
155
|
+
from classiq.qmod.qmod_variable import QArray
|
156
|
+
|
157
|
+
return QArray(origin, element_type=self.element_type, length=self.length)
|
158
|
+
|
134
159
|
|
135
160
|
class QuantumNumeric(QuantumScalar):
|
136
161
|
kind: Literal["qnum"]
|
@@ -193,12 +218,29 @@ class QuantumNumeric(QuantumScalar):
|
|
193
218
|
return f"QNum[{self.size.expr}, {self.is_signed.expr}, {self.fraction_digits.expr}]"
|
194
219
|
return "QNum"
|
195
220
|
|
221
|
+
@property
|
222
|
+
def type_name(self) -> str:
|
223
|
+
return "Quantum numeric"
|
224
|
+
|
225
|
+
def to_qvar(self, origin: HandleBinding) -> "QNum":
|
226
|
+
from classiq.qmod.qmod_variable import QNum
|
227
|
+
|
228
|
+
return QNum(origin, self.size, self.is_signed, self.fraction_digits)
|
229
|
+
|
230
|
+
|
231
|
+
class RegisterQuantumType(BaseModel):
|
232
|
+
quantum_types: "ConcreteQuantumType"
|
233
|
+
size: int = Field(default=1)
|
196
234
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
]
|
201
|
-
|
235
|
+
@property
|
236
|
+
def qmod_type_name(self) -> str:
|
237
|
+
try:
|
238
|
+
return self.quantum_types.qmod_type_name.split("[")[0]
|
239
|
+
except AttributeError:
|
240
|
+
return "default"
|
241
|
+
|
242
|
+
|
243
|
+
RegisterQuantumTypeDict = Dict[str, RegisterQuantumType]
|
202
244
|
|
203
245
|
|
204
246
|
def register_info_to_quantum_type(reg_info: RegisterArithmeticInfo) -> QuantumNumeric:
|
@@ -225,3 +267,12 @@ def quantum_var_to_register(name: str, qtype: QuantumType) -> RegisterUserInput:
|
|
225
267
|
is_signed=signed,
|
226
268
|
fraction_places=fraction_places,
|
227
269
|
)
|
270
|
+
|
271
|
+
|
272
|
+
def quantum_type_to_register_quantum_type(
|
273
|
+
qtype: QuantumType, size: int
|
274
|
+
) -> RegisterQuantumType:
|
275
|
+
return RegisterQuantumType(
|
276
|
+
quantum_types=qtype,
|
277
|
+
size=size,
|
278
|
+
)
|
@@ -4,8 +4,8 @@ import pydantic
|
|
4
4
|
|
5
5
|
from classiq.interface.ast_node import ASTNode
|
6
6
|
from classiq.interface.generator.expressions.expression import Expression
|
7
|
+
from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
|
7
8
|
from classiq.interface.model.quantum_type import (
|
8
|
-
ConcreteQuantumType,
|
9
9
|
QuantumBitvector,
|
10
10
|
QuantumNumeric,
|
11
11
|
)
|
@@ -8,6 +8,7 @@ from classiq.interface.model.classical_if import ClassicalIf
|
|
8
8
|
from classiq.interface.model.control import Control
|
9
9
|
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
10
10
|
from classiq.interface.model.invert import Invert
|
11
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
11
12
|
from classiq.interface.model.power import Power
|
12
13
|
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
13
14
|
AmplitudeLoadingOperation,
|
@@ -50,3 +51,4 @@ Power.update_forward_refs(StatementBlock=StatementBlock)
|
|
50
51
|
Invert.update_forward_refs(StatementBlock=StatementBlock)
|
51
52
|
WithinApply.update_forward_refs(StatementBlock=StatementBlock)
|
52
53
|
ClassicalIf.update_forward_refs(StatementBlock=StatementBlock)
|
54
|
+
NativeFunctionDefinition.update_forward_refs(StatementBlock=StatementBlock)
|
@@ -12,6 +12,13 @@ class HandleState(Enum):
|
|
12
12
|
UNINITIALIZED = 1
|
13
13
|
ERRORED = 2
|
14
14
|
|
15
|
+
def __invert__(self) -> "HandleState":
|
16
|
+
if self == HandleState.INITIALIZED:
|
17
|
+
return HandleState.UNINITIALIZED
|
18
|
+
if self == HandleState.UNINITIALIZED:
|
19
|
+
return HandleState.INITIALIZED
|
20
|
+
return self
|
21
|
+
|
15
22
|
|
16
23
|
@dataclasses.dataclass
|
17
24
|
class ValidationHandle:
|