classiq 0.102.0__py3-none-any.whl → 1.0.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 +2 -0
- classiq/_internals/authentication/auth0.py +29 -0
- classiq/_internals/authentication/auth_flow_factory.py +43 -0
- classiq/_internals/authentication/machine_credentials_flow.py +26 -0
- classiq/_internals/authentication/password_manager.py +84 -0
- classiq/_internals/authentication/token_manager.py +24 -8
- classiq/analyzer/show_interactive_hack.py +0 -8
- classiq/applications/chemistry/op_utils.py +32 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +1 -1
- classiq/evaluators/qmod_annotated_expression.py +1 -1
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +1 -8
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +1 -1
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +18 -29
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +1 -6
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -7
- classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
- classiq/execution/all_hardware_devices.py +59 -1
- classiq/execution/execution_session.py +1 -1
- classiq/execution/functions/__init__.py +13 -0
- classiq/execution/functions/expectation_value.py +106 -0
- classiq/execution/functions/minimize.py +90 -0
- classiq/execution/functions/sample.py +76 -0
- classiq/execution/functions/state_vector.py +113 -0
- classiq/execution/functions/util/__init__.py +0 -0
- classiq/execution/functions/util/_logging.py +19 -0
- classiq/execution/functions/util/backend_preferences.py +188 -0
- classiq/execution/functions/util/constants.py +9 -0
- classiq/execution/functions/util/parse_provider_backend.py +90 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +81 -0
- classiq/interface/backend/provider_config/providers/aqt.py +1 -1
- classiq/interface/backend/provider_config/providers/azure.py +1 -2
- classiq/interface/backend/provider_config/providers/ibm.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +14 -0
- classiq/interface/exceptions.py +0 -4
- classiq/interface/executor/result.py +9 -5
- classiq/interface/generator/arith/binary_ops.py +62 -2
- classiq/interface/generator/arith/number_utils.py +15 -6
- classiq/interface/generator/compiler_keywords.py +1 -0
- classiq/interface/generator/function_param_list.py +8 -2
- classiq/interface/generator/function_params.py +1 -1
- classiq/interface/generator/functions/builtins/internal_operators.py +5 -9
- classiq/interface/generator/functions/classical_type.py +60 -0
- classiq/interface/generator/functions/type_name.py +36 -0
- classiq/interface/generator/generated_circuit_data.py +0 -2
- classiq/interface/generator/transpiler_basis_gates.py +1 -0
- classiq/interface/generator/types/compilation_metadata.py +18 -0
- classiq/interface/hardware.py +2 -0
- classiq/interface/helpers/model_normalizer.py +42 -6
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/invert.py +8 -0
- classiq/interface/model/model.py +19 -0
- classiq/interface/model/model_visitor.py +4 -2
- classiq/interface/model/quantum_type.py +36 -0
- classiq/interface/model/statement_block.py +0 -4
- classiq/interface/qubits_mapping/__init__.py +4 -0
- classiq/interface/qubits_mapping/path_expr_range.py +69 -0
- classiq/interface/qubits_mapping/qubits_mapping.py +231 -0
- classiq/interface/qubits_mapping/slices.py +112 -0
- classiq/model_expansions/arithmetic.py +6 -0
- classiq/model_expansions/capturing/captured_vars.py +16 -12
- classiq/model_expansions/function_builder.py +9 -1
- classiq/model_expansions/interpreters/base_interpreter.py +9 -8
- classiq/model_expansions/interpreters/generative_interpreter.py +9 -24
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -0
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +132 -28
- classiq/model_expansions/quantum_operations/bind.py +4 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +5 -35
- classiq/model_expansions/quantum_operations/emitter.py +1 -4
- classiq/model_expansions/quantum_operations/expression_evaluator.py +0 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +0 -9
- classiq/qmod/builtins/functions/__init__.py +21 -9
- classiq/qmod/builtins/functions/allocation.py +0 -36
- classiq/qmod/builtins/functions/arithmetic.py +183 -0
- classiq/qmod/builtins/functions/exponentiation.py +32 -2
- classiq/qmod/builtins/functions/gray_code.py +23 -0
- classiq/qmod/builtins/functions/mcx_func.py +10 -0
- classiq/qmod/builtins/operations.py +2 -38
- classiq/qmod/builtins/structs.py +22 -3
- classiq/qmod/native/pretty_printer.py +1 -12
- classiq/qmod/pretty_print/pretty_printer.py +1 -17
- classiq/qmod/qmod_parameter.py +4 -0
- classiq/qmod/qmod_variable.py +38 -63
- classiq/qmod/quantum_function.py +43 -7
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +7 -4
- classiq/qmod/semantics/validation/model_validation.py +7 -2
- classiq/qmod/symbolic_type.py +4 -2
- classiq/qprog_to_cudaq.py +347 -0
- {classiq-0.102.0.dist-info → classiq-1.0.0.dist-info}/METADATA +4 -1
- {classiq-0.102.0.dist-info → classiq-1.0.0.dist-info}/RECORD +93 -76
- classiq/interface/generator/amplitude_loading.py +0 -103
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
- {classiq-0.102.0.dist-info → classiq-1.0.0.dist-info}/WHEEL +0 -0
- {classiq-0.102.0.dist-info → classiq-1.0.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
|
|
3
|
-
from classiq.interface.generator.amplitude_loading import AmplitudeLoading
|
|
4
3
|
from classiq.interface.generator.arith.arithmetic import Arithmetic
|
|
5
4
|
from classiq.interface.generator.arith.binary_ops import (
|
|
6
5
|
Adder,
|
|
7
6
|
BitwiseAnd,
|
|
8
7
|
BitwiseOr,
|
|
9
8
|
BitwiseXor,
|
|
9
|
+
CanonicalAdder,
|
|
10
|
+
CanonicalConstantAdder,
|
|
11
|
+
CanonicalConstantMultiplier,
|
|
12
|
+
CanonicalMultiplier,
|
|
10
13
|
Equal,
|
|
11
14
|
GreaterEqual,
|
|
12
15
|
GreaterThan,
|
|
@@ -58,6 +61,8 @@ function_param_library: FunctionParamLibrary = FunctionParamLibrary(
|
|
|
58
61
|
BitwiseXor,
|
|
59
62
|
BitwiseInvert,
|
|
60
63
|
Adder,
|
|
64
|
+
CanonicalAdder,
|
|
65
|
+
CanonicalConstantAdder,
|
|
61
66
|
Arithmetic,
|
|
62
67
|
Sign,
|
|
63
68
|
Equal,
|
|
@@ -79,6 +84,8 @@ function_param_library: FunctionParamLibrary = FunctionParamLibrary(
|
|
|
79
84
|
HardwareEfficientAnsatz,
|
|
80
85
|
UnitaryGate,
|
|
81
86
|
Multiplier,
|
|
87
|
+
CanonicalMultiplier,
|
|
88
|
+
CanonicalConstantMultiplier,
|
|
82
89
|
Power,
|
|
83
90
|
Min,
|
|
84
91
|
Max,
|
|
@@ -88,7 +95,6 @@ function_param_library: FunctionParamLibrary = FunctionParamLibrary(
|
|
|
88
95
|
Identity,
|
|
89
96
|
RandomizedBenchmarking,
|
|
90
97
|
UGate,
|
|
91
|
-
AmplitudeLoading,
|
|
92
98
|
HadamardTransform,
|
|
93
99
|
Copy,
|
|
94
100
|
Reset,
|
|
@@ -46,7 +46,7 @@ END_BAD_REGISTER_ERROR_MSG = (
|
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
ALPHANUM_AND_UNDERSCORE = r"[0-9a-zA-Z_]*"
|
|
49
|
-
NAME_REGEX = rf"_
|
|
49
|
+
NAME_REGEX = rf"_{{0,2}}[a-zA-Z]{ALPHANUM_AND_UNDERSCORE}"
|
|
50
50
|
|
|
51
51
|
_UNVALIDATED_FUNCTIONS = ["Arithmetic", "CustomFunction"]
|
|
52
52
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
CTRL_VAR_PREFIX = "ctrl__"
|
|
2
2
|
CONTROL_OPERATOR_NAME = "control"
|
|
3
3
|
SKIP_CONTROL_OPERATOR_NAME = "skip_control"
|
|
4
|
-
|
|
4
|
+
COMPOUND_INVERT_OPERATOR_NAME = "compound_invert"
|
|
5
|
+
SINGLE_CALL_INVERT_OPERATOR_NAME = "single_call_invert"
|
|
5
6
|
REPEAT_OPERATOR_NAME = "iteration"
|
|
6
7
|
CLASSICAL_IF_OPERATOR_NAME = "classical_if"
|
|
7
8
|
POWER_OPERATOR_NAME = "power"
|
|
@@ -9,12 +10,7 @@ UNCOMPUTE_OPERATOR_NAME = "uncompute"
|
|
|
9
10
|
WITHIN_APPLY_NAME = "within_apply"
|
|
10
11
|
BLOCK_OPERATOR_NAME = "block"
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
REPEAT_OPERATOR_NAME,
|
|
16
|
-
POWER_OPERATOR_NAME,
|
|
17
|
-
UNCOMPUTE_OPERATOR_NAME,
|
|
18
|
-
WITHIN_APPLY_NAME,
|
|
19
|
-
BLOCK_OPERATOR_NAME,
|
|
13
|
+
INVERT_OPERATOR_NAMES = {
|
|
14
|
+
COMPOUND_INVERT_OPERATOR_NAME,
|
|
15
|
+
SINGLE_CALL_INVERT_OPERATOR_NAME,
|
|
20
16
|
}
|
|
@@ -61,6 +61,10 @@ class ClassicalType(HashableASTNode):
|
|
|
61
61
|
def raw_qmod_type_name(self) -> str:
|
|
62
62
|
return self.qmod_type_name
|
|
63
63
|
|
|
64
|
+
@property
|
|
65
|
+
def python_type_name(self) -> str:
|
|
66
|
+
raise NotImplementedError
|
|
67
|
+
|
|
64
68
|
@property
|
|
65
69
|
def expressions(self) -> list[Expression]:
|
|
66
70
|
return []
|
|
@@ -76,6 +80,12 @@ class ClassicalType(HashableASTNode):
|
|
|
76
80
|
def without_symbolic_attributes(self) -> Self:
|
|
77
81
|
return self
|
|
78
82
|
|
|
83
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
84
|
+
return {}
|
|
85
|
+
|
|
86
|
+
def get_compile_time_attribute_types(self, prefix: str) -> dict[str, type]:
|
|
87
|
+
return {}
|
|
88
|
+
|
|
79
89
|
|
|
80
90
|
class Integer(ClassicalType):
|
|
81
91
|
kind: Literal["int"]
|
|
@@ -89,6 +99,10 @@ class Integer(ClassicalType):
|
|
|
89
99
|
def qmod_type_name(self) -> str:
|
|
90
100
|
return "CInt"
|
|
91
101
|
|
|
102
|
+
@property
|
|
103
|
+
def python_type_name(self) -> str:
|
|
104
|
+
return "int"
|
|
105
|
+
|
|
92
106
|
|
|
93
107
|
class Real(ClassicalType):
|
|
94
108
|
kind: Literal["real"]
|
|
@@ -102,6 +116,10 @@ class Real(ClassicalType):
|
|
|
102
116
|
def qmod_type_name(self) -> str:
|
|
103
117
|
return "CReal"
|
|
104
118
|
|
|
119
|
+
@property
|
|
120
|
+
def python_type_name(self) -> str:
|
|
121
|
+
return "float"
|
|
122
|
+
|
|
105
123
|
|
|
106
124
|
class Bool(ClassicalType):
|
|
107
125
|
kind: Literal["bool"]
|
|
@@ -115,6 +133,10 @@ class Bool(ClassicalType):
|
|
|
115
133
|
def qmod_type_name(self) -> str:
|
|
116
134
|
return "CBool"
|
|
117
135
|
|
|
136
|
+
@property
|
|
137
|
+
def python_type_name(self) -> str:
|
|
138
|
+
return "bool"
|
|
139
|
+
|
|
118
140
|
|
|
119
141
|
class StructMetaType(ClassicalType):
|
|
120
142
|
kind: Literal["type_proxy"]
|
|
@@ -201,6 +223,10 @@ class ClassicalArray(ClassicalType):
|
|
|
201
223
|
def raw_qmod_type_name(self) -> str:
|
|
202
224
|
return "CArray"
|
|
203
225
|
|
|
226
|
+
@property
|
|
227
|
+
def python_type_name(self) -> str:
|
|
228
|
+
return f"list[{self.element_type.python_type_name}]"
|
|
229
|
+
|
|
204
230
|
def without_symbolic_attributes(self) -> "ClassicalArray":
|
|
205
231
|
length = (
|
|
206
232
|
None
|
|
@@ -213,6 +239,19 @@ class ClassicalArray(ClassicalType):
|
|
|
213
239
|
element_type=self.element_type.without_symbolic_attributes(), length=length
|
|
214
240
|
)
|
|
215
241
|
|
|
242
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
243
|
+
attrs: dict[str, Any] = {}
|
|
244
|
+
if self.has_constant_length:
|
|
245
|
+
attrs[f"{path_expr_prefix}.len"] = self.length_value
|
|
246
|
+
return attrs | self.element_type.get_compile_time_attributes(
|
|
247
|
+
f"{path_expr_prefix}[0]"
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
def get_compile_time_attribute_types(self, prefix: str) -> dict[str, type]:
|
|
251
|
+
return {
|
|
252
|
+
f"{prefix}.len": int
|
|
253
|
+
} | self.element_type.get_compile_time_attribute_types(f"{prefix}[0]")
|
|
254
|
+
|
|
216
255
|
|
|
217
256
|
class ClassicalTuple(ClassicalType):
|
|
218
257
|
kind: Literal["tuple"]
|
|
@@ -283,6 +322,13 @@ class ClassicalTuple(ClassicalType):
|
|
|
283
322
|
def raw_qmod_type_name(self) -> str:
|
|
284
323
|
return "CArray"
|
|
285
324
|
|
|
325
|
+
@property
|
|
326
|
+
def python_type_name(self) -> str:
|
|
327
|
+
raw_type = self.get_raw_type(preserve_length=True)
|
|
328
|
+
if isinstance(raw_type, ClassicalTuple):
|
|
329
|
+
return "list"
|
|
330
|
+
return raw_type.python_type_name
|
|
331
|
+
|
|
286
332
|
def without_symbolic_attributes(self) -> "ClassicalTuple":
|
|
287
333
|
return ClassicalTuple(
|
|
288
334
|
element_types=[
|
|
@@ -291,6 +337,20 @@ class ClassicalTuple(ClassicalType):
|
|
|
291
337
|
]
|
|
292
338
|
)
|
|
293
339
|
|
|
340
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
341
|
+
raw_type = self.get_raw_type(preserve_length=True)
|
|
342
|
+
attrs = {f"{path_expr_prefix}.len": len(self.element_types)}
|
|
343
|
+
if isinstance(raw_type, ClassicalTuple):
|
|
344
|
+
return attrs
|
|
345
|
+
return attrs | raw_type.get_compile_time_attributes(path_expr_prefix)
|
|
346
|
+
|
|
347
|
+
def get_compile_time_attribute_types(self, prefix: str) -> dict[str, type]:
|
|
348
|
+
raw_type = self.get_raw_type(preserve_length=True)
|
|
349
|
+
attrs: dict[str, type] = {f"{prefix}.len": int}
|
|
350
|
+
if isinstance(raw_type, ClassicalTuple):
|
|
351
|
+
return attrs
|
|
352
|
+
return attrs | raw_type.get_compile_time_attribute_types(prefix)
|
|
353
|
+
|
|
294
354
|
|
|
295
355
|
class OpaqueHandle(ClassicalType):
|
|
296
356
|
pass
|
|
@@ -60,6 +60,10 @@ class TypeName(ClassicalType, QuantumType):
|
|
|
60
60
|
def qmod_type_name(self) -> str:
|
|
61
61
|
return self.name
|
|
62
62
|
|
|
63
|
+
@property
|
|
64
|
+
def python_type_name(self) -> str:
|
|
65
|
+
return self.name
|
|
66
|
+
|
|
63
67
|
@property
|
|
64
68
|
def type_name(self) -> str:
|
|
65
69
|
return self.name
|
|
@@ -202,6 +206,38 @@ class TypeName(ClassicalType, QuantumType):
|
|
|
202
206
|
return type_name
|
|
203
207
|
return self
|
|
204
208
|
|
|
209
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
210
|
+
attrs: dict[str, Any] = {}
|
|
211
|
+
if self.has_fields:
|
|
212
|
+
for field_name, field_type in self.fields.items():
|
|
213
|
+
field_prefix = f"{path_expr_prefix}.{field_name}"
|
|
214
|
+
attrs |= field_type.get_compile_time_attributes(field_prefix)
|
|
215
|
+
elif self.has_classical_struct_decl:
|
|
216
|
+
for (
|
|
217
|
+
field_name,
|
|
218
|
+
classical_field_type,
|
|
219
|
+
) in self.classical_struct_decl.variables.items():
|
|
220
|
+
field_prefix = f"{path_expr_prefix}.{field_name}"
|
|
221
|
+
attrs |= classical_field_type.get_compile_time_attributes(field_prefix)
|
|
222
|
+
return attrs
|
|
223
|
+
|
|
224
|
+
def get_compile_time_attribute_types(self, prefix: str) -> dict[str, type]:
|
|
225
|
+
attrs: dict[str, type] = {}
|
|
226
|
+
if self.has_fields:
|
|
227
|
+
for field_name, field_type in self.fields.items():
|
|
228
|
+
field_prefix = f"{prefix}.{field_name}"
|
|
229
|
+
attrs |= field_type.get_compile_time_attribute_types(field_prefix)
|
|
230
|
+
elif self.has_classical_struct_decl:
|
|
231
|
+
for (
|
|
232
|
+
field_name,
|
|
233
|
+
classical_field_type,
|
|
234
|
+
) in self.classical_struct_decl.variables.items():
|
|
235
|
+
field_prefix = f"{prefix}.{field_name}"
|
|
236
|
+
attrs |= classical_field_type.get_compile_time_attribute_types(
|
|
237
|
+
field_prefix
|
|
238
|
+
)
|
|
239
|
+
return attrs
|
|
240
|
+
|
|
205
241
|
|
|
206
242
|
class Enum(TypeName):
|
|
207
243
|
pass
|
|
@@ -140,7 +140,6 @@ class StatementType(StrEnum):
|
|
|
140
140
|
WITHIN = "within"
|
|
141
141
|
APPLY = "apply"
|
|
142
142
|
ASSIGN = "assign"
|
|
143
|
-
ASSIGN_AMPLITUDE = "assign amplitude"
|
|
144
143
|
PHASE = "phase"
|
|
145
144
|
INPLACE_XOR = "inplace xor"
|
|
146
145
|
INPLACE_ADD = "inplace add"
|
|
@@ -163,7 +162,6 @@ STATEMENTS_NAME: dict[str, StatementType] = {
|
|
|
163
162
|
"Uncompute": StatementType.WITHIN,
|
|
164
163
|
ArithmeticOperationKind.Assignment.value: StatementType.ASSIGN,
|
|
165
164
|
"InplaceBinaryOperation": StatementType.ASSIGN,
|
|
166
|
-
"AmplitudeLoadingOperation": StatementType.ASSIGN_AMPLITUDE,
|
|
167
165
|
"PhaseOperation": StatementType.PHASE,
|
|
168
166
|
ArithmeticOperationKind.InplaceXor.value: StatementType.INPLACE_XOR,
|
|
169
167
|
ArithmeticOperationKind.InplaceAdd.value: StatementType.INPLACE_ADD,
|
|
@@ -5,6 +5,8 @@ class CompilationMetadata(BaseModel):
|
|
|
5
5
|
should_synthesize_separately: bool = Field(default=False)
|
|
6
6
|
occurrences_number: NonNegativeInt = Field(default=0)
|
|
7
7
|
_occupation_number: NonNegativeInt = PrivateAttr(default=0)
|
|
8
|
+
_min_required_clean_qubit: NonNegativeInt = PrivateAttr(default=0)
|
|
9
|
+
_max_required_clean_qubit: NonNegativeInt = PrivateAttr(default=0)
|
|
8
10
|
disable_perm_check: bool = Field(default=False)
|
|
9
11
|
disable_const_checks: list[str] | bool = Field(default=False)
|
|
10
12
|
|
|
@@ -16,6 +18,22 @@ class CompilationMetadata(BaseModel):
|
|
|
16
18
|
def occupation_number(self, value: NonNegativeInt) -> None:
|
|
17
19
|
self._occupation_number = value
|
|
18
20
|
|
|
21
|
+
@property
|
|
22
|
+
def min_required_clean_qubit(self) -> NonNegativeInt:
|
|
23
|
+
return self._min_required_clean_qubit
|
|
24
|
+
|
|
25
|
+
@min_required_clean_qubit.setter
|
|
26
|
+
def min_required_clean_qubit(self, value: NonNegativeInt) -> None:
|
|
27
|
+
self._min_required_clean_qubit = value
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def max_required_clean_qubit(self) -> NonNegativeInt:
|
|
31
|
+
return self._max_required_clean_qubit
|
|
32
|
+
|
|
33
|
+
@max_required_clean_qubit.setter
|
|
34
|
+
def max_required_clean_qubit(self, value: NonNegativeInt) -> None:
|
|
35
|
+
self._max_required_clean_qubit = value
|
|
36
|
+
|
|
19
37
|
@property
|
|
20
38
|
def has_user_directives(self) -> bool:
|
|
21
39
|
return bool(self.disable_perm_check or self.disable_const_checks)
|
classiq/interface/hardware.py
CHANGED
|
@@ -6,16 +6,31 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
|
6
6
|
from classiq.interface.generator.functions.classical_type import ClassicalType
|
|
7
7
|
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
|
8
8
|
from classiq.interface.generator.visitor import Transformer, Visitor
|
|
9
|
+
from classiq.interface.model.handle_binding import HandleBinding
|
|
9
10
|
from classiq.interface.model.model import Model
|
|
10
11
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
11
|
-
from classiq.interface.model.port_declaration import
|
|
12
|
+
from classiq.interface.model.port_declaration import (
|
|
13
|
+
PortDeclaration,
|
|
14
|
+
)
|
|
12
15
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
16
|
+
from classiq.interface.model.variable_declaration_statement import (
|
|
17
|
+
VariableDeclarationStatement,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
|
13
21
|
|
|
14
22
|
|
|
15
23
|
class ModelNormalizer(Visitor):
|
|
16
|
-
def __init__(
|
|
17
|
-
self
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
normalize_func_names: bool = False,
|
|
27
|
+
normalize_quantum_var_names: bool = False,
|
|
28
|
+
) -> None:
|
|
29
|
+
self._normalize_func_names = normalize_func_names
|
|
30
|
+
self._normalize_quantum_var_names = normalize_quantum_var_names
|
|
18
31
|
self._funcs_renames: dict[str, str] = {}
|
|
32
|
+
self._count_name = CountedNameAllocator()
|
|
33
|
+
self.original_names: dict[str, str] = {}
|
|
19
34
|
|
|
20
35
|
def visit(self, node: Any) -> None:
|
|
21
36
|
if isinstance(node, ASTNode):
|
|
@@ -35,12 +50,12 @@ class ModelNormalizer(Visitor):
|
|
|
35
50
|
self.generic_visit(model)
|
|
36
51
|
|
|
37
52
|
def visit_NativeFunctionDefinition(self, func: NativeFunctionDefinition) -> None:
|
|
38
|
-
if self.
|
|
53
|
+
if self._normalize_func_names:
|
|
39
54
|
func.name = self._funcs_renames[func.name]
|
|
40
55
|
self.generic_visit(func)
|
|
41
56
|
|
|
42
57
|
def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
|
|
43
|
-
if self.
|
|
58
|
+
if self._normalize_func_names:
|
|
44
59
|
if isinstance(call.function, str):
|
|
45
60
|
if call.function in self._funcs_renames:
|
|
46
61
|
call.function = self._funcs_renames[call.function]
|
|
@@ -49,8 +64,29 @@ class ModelNormalizer(Visitor):
|
|
|
49
64
|
call.function.name = self._funcs_renames[call.function.name]
|
|
50
65
|
self.generic_visit(call)
|
|
51
66
|
|
|
52
|
-
def
|
|
67
|
+
def visit_PortDeclaration(self, decl: PortDeclaration) -> None:
|
|
53
68
|
decl.type_modifier = TypeModifier.Mutable
|
|
69
|
+
self._rename_quantum_var(decl, "_port")
|
|
70
|
+
|
|
71
|
+
def visit_VariableDeclarationStatement(
|
|
72
|
+
self, var: VariableDeclarationStatement
|
|
73
|
+
) -> None:
|
|
74
|
+
self._rename_quantum_var(var, "_var")
|
|
75
|
+
|
|
76
|
+
def _rename_quantum_var(
|
|
77
|
+
self, var: VariableDeclarationStatement | PortDeclaration, new_name_prefix: str
|
|
78
|
+
) -> None:
|
|
79
|
+
if self._normalize_quantum_var_names:
|
|
80
|
+
old_name = var.name
|
|
81
|
+
var.name = self._count_name.allocate(new_name_prefix)
|
|
82
|
+
self.original_names[old_name] = var.name
|
|
83
|
+
|
|
84
|
+
def visit_HandleBinding(self, handle: HandleBinding) -> None:
|
|
85
|
+
if self._normalize_quantum_var_names:
|
|
86
|
+
# this is a hack use just for testing, do not use in production
|
|
87
|
+
object.__setattr__(
|
|
88
|
+
handle, "name", self.original_names.get(handle.name, handle.name)
|
|
89
|
+
)
|
|
54
90
|
|
|
55
91
|
|
|
56
92
|
class ClearModelInternals(Transformer):
|
|
@@ -1 +1 @@
|
|
|
1
|
-
INTERFACE_VERSION = "
|
|
1
|
+
INTERFACE_VERSION = "17"
|
|
@@ -2,6 +2,8 @@ from typing import TYPE_CHECKING, Literal
|
|
|
2
2
|
|
|
3
3
|
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
|
4
4
|
from classiq.interface.enum_utils import StrEnum
|
|
5
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
|
6
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
5
7
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
|
6
8
|
|
|
7
9
|
if TYPE_CHECKING:
|
|
@@ -25,3 +27,9 @@ class Invert(QuantumOperation):
|
|
|
25
27
|
@property
|
|
26
28
|
def blocks(self) -> dict[str, "StatementBlock"]:
|
|
27
29
|
return {"body": self.body}
|
|
30
|
+
|
|
31
|
+
def validate_node(self) -> None:
|
|
32
|
+
if self.block_kind == BlockKind.SingleCall and (
|
|
33
|
+
len(self.body) != 1 or not isinstance(self.body[0], QuantumFunctionCall)
|
|
34
|
+
):
|
|
35
|
+
raise ClassiqInternalExpansionError("Malformed single-call invert")
|
classiq/interface/model/model.py
CHANGED
|
@@ -10,6 +10,7 @@ from classiq.interface.debug_info.debug_info import DebugInfoCollection
|
|
|
10
10
|
from classiq.interface.exceptions import ClassiqValueError
|
|
11
11
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
|
12
12
|
from classiq.interface.generator.constant import Constant
|
|
13
|
+
from classiq.interface.generator.function_params import ArithmeticIODict
|
|
13
14
|
from classiq.interface.generator.functions.port_declaration import (
|
|
14
15
|
PortDeclarationDirection,
|
|
15
16
|
)
|
|
@@ -28,6 +29,10 @@ from classiq.interface.model.native_function_definition import (
|
|
|
28
29
|
from classiq.interface.model.quantum_function_declaration import (
|
|
29
30
|
NamedParamsQuantumFunctionDeclaration,
|
|
30
31
|
)
|
|
32
|
+
from classiq.interface.model.quantum_type import (
|
|
33
|
+
RegisterQuantumTypeDict,
|
|
34
|
+
quantum_type_to_register_quantum_type,
|
|
35
|
+
)
|
|
31
36
|
from classiq.interface.model.statement_block import StatementBlock
|
|
32
37
|
|
|
33
38
|
USER_MODEL_MARKER = "user"
|
|
@@ -237,3 +242,17 @@ class Model(VersionedModel, ASTNode):
|
|
|
237
242
|
self.compressed_debug_info = None
|
|
238
243
|
else:
|
|
239
244
|
self.compressed_debug_info = compress_pydantic(self._debug_info)
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def measured_registers(self) -> ArithmeticIODict:
|
|
248
|
+
return self.main_func.outputs_dict
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def measured_registers_type(self) -> RegisterQuantumTypeDict:
|
|
252
|
+
return {
|
|
253
|
+
key: quantum_type_to_register_quantum_type(
|
|
254
|
+
self.main_func.port_declarations_dict[key].quantum_type,
|
|
255
|
+
self.main_func.port_declarations_dict[key].quantum_type.size_in_bits,
|
|
256
|
+
)
|
|
257
|
+
for key in self.measured_registers.keys()
|
|
258
|
+
}
|
|
@@ -10,8 +10,10 @@ from classiq.interface.model.quantum_statement import QuantumStatement
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ModelVisitor(Visitor):
|
|
13
|
-
def visit_DebugInfoCollection(
|
|
14
|
-
|
|
13
|
+
def visit_DebugInfoCollection(
|
|
14
|
+
self, debug_info: DebugInfoCollection
|
|
15
|
+
) -> RetType | None:
|
|
16
|
+
return None
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
class ModelStatementsVisitor(ModelVisitor):
|
|
@@ -78,6 +78,12 @@ class QuantumType(HashableASTNode):
|
|
|
78
78
|
def without_symbolic_attributes(self) -> Self:
|
|
79
79
|
return self
|
|
80
80
|
|
|
81
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
82
|
+
return {}
|
|
83
|
+
|
|
84
|
+
def get_compile_time_attribute_types(self, prefix: str) -> dict[str, type]:
|
|
85
|
+
return {}
|
|
86
|
+
|
|
81
87
|
|
|
82
88
|
class QuantumScalar(QuantumType):
|
|
83
89
|
@property
|
|
@@ -262,6 +268,19 @@ class QuantumBitvector(QuantumType):
|
|
|
262
268
|
length = 1
|
|
263
269
|
return length * self.element_type.minimal_size_in_bits
|
|
264
270
|
|
|
271
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
272
|
+
attrs: dict[str, Any] = {}
|
|
273
|
+
if self.has_constant_length:
|
|
274
|
+
attrs[f"{path_expr_prefix}.len"] = self.length_value
|
|
275
|
+
return attrs | self.element_type.get_compile_time_attributes(
|
|
276
|
+
f"{path_expr_prefix}[0]"
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
def get_compile_time_attribute_types(self, prefix: str) -> dict[str, type]:
|
|
280
|
+
return {
|
|
281
|
+
f"{prefix}.len": int
|
|
282
|
+
} | self.element_type.get_compile_time_attribute_types(f"{prefix}[0]")
|
|
283
|
+
|
|
265
284
|
def without_symbolic_attributes(self) -> "QuantumBitvector":
|
|
266
285
|
length = (
|
|
267
286
|
None
|
|
@@ -301,6 +320,23 @@ class QuantumNumeric(QuantumScalar):
|
|
|
301
320
|
)
|
|
302
321
|
return self
|
|
303
322
|
|
|
323
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
324
|
+
attrs: dict[str, Any] = {}
|
|
325
|
+
if self.has_size_in_bits:
|
|
326
|
+
attrs[f"{path_expr_prefix}.size"] = self.size_in_bits
|
|
327
|
+
if self.has_constant_sign:
|
|
328
|
+
attrs[f"{path_expr_prefix}.is_signed"] = self.sign_value
|
|
329
|
+
if self.has_constant_fraction_digits:
|
|
330
|
+
attrs[f"{path_expr_prefix}.fraction_digits"] = self.fraction_digits_value
|
|
331
|
+
return attrs
|
|
332
|
+
|
|
333
|
+
def get_compile_time_attribute_types(self, prefix: str) -> dict[str, type]:
|
|
334
|
+
return {
|
|
335
|
+
f"{prefix}.size": int,
|
|
336
|
+
f"{prefix}.is_signed": bool,
|
|
337
|
+
f"{prefix}.fraction_digits": int,
|
|
338
|
+
}
|
|
339
|
+
|
|
304
340
|
def set_size_in_bits(self, val: int) -> None:
|
|
305
341
|
super().set_size_in_bits(val)
|
|
306
342
|
if self.size is not None:
|
|
@@ -13,9 +13,6 @@ from classiq.interface.model.invert import Invert
|
|
|
13
13
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
14
14
|
from classiq.interface.model.phase_operation import PhaseOperation
|
|
15
15
|
from classiq.interface.model.power import Power
|
|
16
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
17
|
-
AmplitudeLoadingOperation,
|
|
18
|
-
)
|
|
19
16
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
20
17
|
ArithmeticOperation,
|
|
21
18
|
)
|
|
@@ -38,7 +35,6 @@ ConcreteQuantumStatement = Annotated[
|
|
|
38
35
|
QuantumFunctionCall,
|
|
39
36
|
Allocate,
|
|
40
37
|
ArithmeticOperation,
|
|
41
|
-
AmplitudeLoadingOperation,
|
|
42
38
|
VariableDeclarationStatement,
|
|
43
39
|
BindOperation,
|
|
44
40
|
InplaceBinaryOperation,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from functools import singledispatch
|
|
2
|
+
|
|
3
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
|
4
|
+
from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
|
|
5
|
+
from classiq.interface.generator.functions.type_name import TypeName
|
|
6
|
+
from classiq.interface.model.handle_binding import (
|
|
7
|
+
FieldHandleBinding,
|
|
8
|
+
HandleBinding,
|
|
9
|
+
SlicedHandleBinding,
|
|
10
|
+
SubscriptHandleBinding,
|
|
11
|
+
)
|
|
12
|
+
from classiq.interface.model.quantum_type import QuantumBitvector
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_path_expr_range(
|
|
16
|
+
var: HandleBinding, quantum_type: ConcreteQuantumType
|
|
17
|
+
) -> tuple[int, int]:
|
|
18
|
+
start = 0
|
|
19
|
+
stop = quantum_type.size_in_bits
|
|
20
|
+
for var_prefix in var.prefixes()[1:]:
|
|
21
|
+
start, stop, quantum_type = _pop_var_range(var_prefix, quantum_type, start)
|
|
22
|
+
return start, stop
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@singledispatch
|
|
26
|
+
def _pop_var_range(
|
|
27
|
+
var_prefix: HandleBinding, quantum_type: ConcreteQuantumType, start: int
|
|
28
|
+
) -> tuple[int, int, ConcreteQuantumType]:
|
|
29
|
+
raise ClassiqInternalExpansionError("Unexpected path expression")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@_pop_var_range.register
|
|
33
|
+
def _(
|
|
34
|
+
var_prefix: SubscriptHandleBinding, quantum_type: ConcreteQuantumType, start: int
|
|
35
|
+
) -> tuple[int, int, ConcreteQuantumType]:
|
|
36
|
+
if not isinstance(quantum_type, QuantumBitvector):
|
|
37
|
+
raise ClassiqInternalExpansionError("Unexpected path expression")
|
|
38
|
+
index = var_prefix.index.to_int_value()
|
|
39
|
+
element_type = quantum_type.element_type
|
|
40
|
+
start += element_type.size_in_bits * index
|
|
41
|
+
stop = start + element_type.size_in_bits
|
|
42
|
+
return start, stop, element_type
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@_pop_var_range.register
|
|
46
|
+
def _(
|
|
47
|
+
var_prefix: SlicedHandleBinding, quantum_type: ConcreteQuantumType, start: int
|
|
48
|
+
) -> tuple[int, int, ConcreteQuantumType]:
|
|
49
|
+
if not isinstance(quantum_type, QuantumBitvector):
|
|
50
|
+
raise ClassiqInternalExpansionError("Unexpected path expression")
|
|
51
|
+
slice_start = var_prefix.start.to_int_value()
|
|
52
|
+
slice_stop = var_prefix.end.to_int_value()
|
|
53
|
+
stop = start + quantum_type.element_type.size_in_bits * slice_stop
|
|
54
|
+
start += quantum_type.element_type.size_in_bits * slice_start
|
|
55
|
+
return start, stop, quantum_type
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@_pop_var_range.register
|
|
59
|
+
def _(
|
|
60
|
+
var_prefix: FieldHandleBinding, quantum_type: ConcreteQuantumType, start: int
|
|
61
|
+
) -> tuple[int, int, ConcreteQuantumType]:
|
|
62
|
+
if not isinstance(quantum_type, TypeName) or not quantum_type.has_fields:
|
|
63
|
+
raise ClassiqInternalExpansionError("Unexpected path expression")
|
|
64
|
+
for field, field_type in quantum_type.fields.items():
|
|
65
|
+
if field == var_prefix.field:
|
|
66
|
+
stop = start + field_type.size_in_bits
|
|
67
|
+
return start, stop, field_type
|
|
68
|
+
start += field_type.size_in_bits
|
|
69
|
+
raise ClassiqInternalExpansionError("Unexpected path expression")
|