classiq 0.82.1__py3-none-any.whl → 0.84.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/_internals/api_wrapper.py +27 -0
- classiq/applications/chemistry/chemistry_model_constructor.py +2 -4
- classiq/applications/chemistry/hartree_fock.py +68 -0
- classiq/applications/chemistry/mapping.py +85 -0
- classiq/applications/chemistry/op_utils.py +79 -0
- classiq/applications/chemistry/problems.py +195 -0
- classiq/applications/chemistry/ucc.py +109 -0
- classiq/applications/chemistry/z2_symmetries.py +368 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +30 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
- classiq/{model_expansions/evaluators → evaluators}/arg_type_match.py +12 -4
- classiq/{model_expansions/evaluators → evaluators}/argument_types.py +3 -3
- classiq/{model_expansions/evaluators → evaluators}/classical_expression.py +1 -1
- classiq/{model_expansions/evaluators → evaluators}/classical_type_inference.py +3 -4
- classiq/{model_expansions/evaluators → evaluators}/parameter_types.py +17 -15
- classiq/execution/__init__.py +12 -1
- classiq/execution/execution_session.py +189 -43
- classiq/execution/jobs.py +26 -1
- classiq/execution/qnn.py +2 -2
- classiq/execution/user_budgets.py +39 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/constants.py +1 -0
- classiq/interface/execution/primitives.py +29 -1
- classiq/interface/executor/estimate_cost.py +35 -0
- classiq/interface/executor/execution_result.py +13 -0
- classiq/interface/executor/result.py +116 -1
- classiq/interface/executor/user_budget.py +26 -33
- classiq/interface/generator/application_apis/finance_declarations.py +3 -3
- classiq/interface/generator/expressions/atomic_expression_functions.py +11 -3
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -6
- classiq/interface/generator/functions/classical_type.py +2 -35
- classiq/interface/generator/functions/concrete_types.py +0 -3
- classiq/interface/generator/functions/type_modifier.py +22 -0
- classiq/interface/generator/generated_circuit_data.py +5 -16
- classiq/interface/generator/model/model.py +8 -0
- classiq/interface/generator/quantum_program.py +0 -13
- classiq/interface/generator/types/compilation_metadata.py +0 -3
- classiq/interface/helpers/model_normalizer.py +2 -2
- classiq/interface/ide/visual_model.py +6 -2
- classiq/interface/model/model.py +12 -7
- classiq/interface/model/port_declaration.py +4 -2
- classiq/interface/pretty_print/__init__.py +0 -0
- classiq/{qmod/native → interface/pretty_print}/expression_to_qmod.py +18 -11
- classiq/interface/server/routes.py +4 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +42 -5
- classiq/model_expansions/capturing/captured_vars.py +21 -8
- classiq/model_expansions/interpreters/base_interpreter.py +3 -3
- classiq/model_expansions/quantum_operations/allocate.py +1 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +1 -1
- classiq/model_expansions/quantum_operations/bind.py +2 -2
- classiq/model_expansions/quantum_operations/call_emitter.py +42 -36
- classiq/model_expansions/quantum_operations/variable_decleration.py +1 -1
- classiq/model_expansions/scope_initialization.py +3 -3
- classiq/model_expansions/transformers/model_renamer.py +16 -5
- classiq/model_expansions/transformers/{type_qualifier_inference.py → type_modifier_inference.py} +134 -100
- classiq/model_expansions/visitors/symbolic_param_inference.py +10 -7
- classiq/open_library/functions/__init__.py +3 -0
- classiq/open_library/functions/amplitude_amplification.py +10 -18
- classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
- classiq/open_library/functions/grover.py +14 -6
- classiq/open_library/functions/modular_exponentiation.py +22 -20
- classiq/open_library/functions/state_preparation.py +18 -1
- classiq/qmod/__init__.py +2 -2
- classiq/qmod/builtins/enums.py +23 -0
- classiq/qmod/builtins/functions/__init__.py +2 -0
- classiq/qmod/builtins/functions/allocation.py +2 -2
- classiq/qmod/builtins/functions/arithmetic.py +16 -8
- classiq/qmod/builtins/functions/exponentiation.py +32 -4
- classiq/qmod/builtins/functions/standard_gates.py +7 -7
- classiq/qmod/builtins/structs.py +55 -3
- classiq/qmod/declaration_inferrer.py +8 -7
- classiq/qmod/native/pretty_printer.py +7 -11
- classiq/qmod/pretty_print/expression_to_python.py +2 -1
- classiq/qmod/pretty_print/pretty_printer.py +7 -12
- classiq/qmod/python_classical_type.py +12 -5
- classiq/qmod/qfunc.py +1 -1
- classiq/qmod/qmod_constant.py +2 -5
- classiq/qmod/qmod_parameter.py +2 -5
- classiq/qmod/qmod_variable.py +66 -25
- classiq/qmod/quantum_expandable.py +4 -2
- classiq/qmod/quantum_function.py +7 -2
- classiq/qmod/semantics/annotation/qstruct_annotator.py +1 -1
- classiq/qmod/semantics/validation/main_validation.py +1 -9
- classiq/qmod/semantics/validation/type_hints.py +9 -9
- classiq/qmod/utilities.py +0 -2
- classiq/qmod/write_qmod.py +1 -1
- classiq/synthesis.py +0 -2
- {classiq-0.82.1.dist-info → classiq-0.84.0.dist-info}/METADATA +4 -1
- {classiq-0.82.1.dist-info → classiq-0.84.0.dist-info}/RECORD +95 -86
- classiq/interface/generator/functions/type_qualifier.py +0 -22
- /classiq/{model_expansions/evaluators → evaluators}/__init__.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/control.py +0 -0
- /classiq/{model_expansions → evaluators}/expression_evaluator.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/quantum_type_utils.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/type_type_match.py +0 -0
- {classiq-0.82.1.dist-info → classiq-0.84.0.dist-info}/WHEEL +0 -0
classiq/model_expansions/transformers/{type_qualifier_inference.py → type_modifier_inference.py}
RENAMED
@@ -4,6 +4,7 @@ import itertools
|
|
4
4
|
import warnings
|
5
5
|
from collections.abc import Collection, Iterator, Sequence
|
6
6
|
from contextlib import contextmanager
|
7
|
+
from typing import Optional, Union
|
7
8
|
|
8
9
|
from classiq.interface.exceptions import (
|
9
10
|
ClassiqDeprecationWarning,
|
@@ -12,12 +13,13 @@ from classiq.interface.exceptions import (
|
|
12
13
|
from classiq.interface.generator.functions.port_declaration import (
|
13
14
|
PortDeclarationDirection,
|
14
15
|
)
|
15
|
-
from classiq.interface.generator.functions.
|
16
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
16
17
|
from classiq.interface.model.allocate import Allocate
|
17
18
|
from classiq.interface.model.bind_operation import BindOperation
|
18
19
|
from classiq.interface.model.control import Control
|
19
20
|
from classiq.interface.model.invert import Invert
|
20
21
|
from classiq.interface.model.model_visitor import ModelVisitor
|
22
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
21
23
|
from classiq.interface.model.phase_operation import PhaseOperation
|
22
24
|
from classiq.interface.model.port_declaration import PortDeclaration
|
23
25
|
from classiq.interface.model.power import Power
|
@@ -31,41 +33,50 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
31
33
|
QuantumExpressionOperation,
|
32
34
|
)
|
33
35
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
34
|
-
from classiq.interface.model.quantum_statement import QuantumStatement
|
35
36
|
from classiq.interface.model.within_apply_operation import WithinApply
|
37
|
+
from classiq.interface.source_reference import SourceReference
|
36
38
|
|
37
39
|
from classiq.model_expansions.visitors.variable_references import VarRefCollector
|
38
40
|
|
39
41
|
|
40
|
-
def
|
41
|
-
port_name: str,
|
42
|
+
def _inconsistent_type_modifier_error(
|
43
|
+
port_name: str,
|
44
|
+
expected: TypeModifier,
|
45
|
+
actual: TypeModifier,
|
46
|
+
source_ref: Optional[Union[SourceReference, str]] = None,
|
42
47
|
) -> str:
|
48
|
+
source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
|
43
49
|
return (
|
44
|
-
f"The
|
50
|
+
f"The use of variable '{port_name}' does not conform to its declared modifier: "
|
45
51
|
f"expected '{expected.name}', but found '{actual.name}'.\n"
|
46
|
-
f"Tip: If the
|
47
|
-
f"
|
48
|
-
|
52
|
+
f"Tip: If the cumulative use of the variable in the function matches '{expected.name}', "
|
53
|
+
f"use the `unchecked` flag to instruct the compiler to disregard individual operations."
|
54
|
+
f"{source_ref_str}\n"
|
55
|
+
"The deprecation warning will be elevated to an error starting July 23, 2025, at the earliest."
|
49
56
|
)
|
50
57
|
|
51
58
|
|
52
|
-
def
|
53
|
-
expected:
|
59
|
+
def _inconsistent_type_modifier_in_binding_error(
|
60
|
+
expected: TypeModifier,
|
61
|
+
known_modifiers: dict[str, TypeModifier],
|
62
|
+
source_ref: Optional[Union[SourceReference, str]] = None,
|
54
63
|
) -> str:
|
55
64
|
actual = ", ".join(
|
56
|
-
f"{name}: {
|
65
|
+
f"{name}: {modifier.name}" for name, modifier in known_modifiers.items()
|
57
66
|
)
|
67
|
+
source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
|
58
68
|
return (
|
59
|
-
f"
|
69
|
+
f"Inconsistent modifiers in variable binding: "
|
60
70
|
f"Expected modifier: {expected.name}, Actual modifiers: {actual}"
|
61
|
-
|
71
|
+
f"{source_ref_str}\n"
|
72
|
+
"The deprecation warning will be elevated to an error starting July 23, 2025, at the earliest."
|
62
73
|
)
|
63
74
|
|
64
75
|
|
65
|
-
class
|
76
|
+
class TypeModifierValidation(ModelVisitor):
|
66
77
|
"""
|
67
78
|
This class assumes that function calls are topologically sorted, so it traverses
|
68
|
-
the list of function calls and infers the type
|
79
|
+
the list of function calls and infers the type modifiers for each function call
|
69
80
|
without going recursively into the function calls.
|
70
81
|
The function definition ports are modified inplace.
|
71
82
|
"""
|
@@ -77,7 +88,7 @@ class TypeQualifierValidation(ModelVisitor):
|
|
77
88
|
self._inferred_ports: dict[str, PortDeclaration] = dict()
|
78
89
|
self._unchecked: set[str] = set()
|
79
90
|
|
80
|
-
self._initialized_vars: dict[str,
|
91
|
+
self._initialized_vars: dict[str, TypeModifier] = dict()
|
81
92
|
self._bound_vars: list[set[str]] = []
|
82
93
|
|
83
94
|
self._conjugation_context: bool = False
|
@@ -85,13 +96,14 @@ class TypeQualifierValidation(ModelVisitor):
|
|
85
96
|
support_unused_ports # could be turned off for debugging
|
86
97
|
)
|
87
98
|
self._skip_validation = skip_validation
|
99
|
+
self._source_ref: Optional[Union[SourceReference, str]] = None
|
88
100
|
|
89
101
|
@contextmanager
|
90
102
|
def validate_ports(
|
91
103
|
self, ports: Collection[PortDeclaration], unchecked: Collection[str]
|
92
104
|
) -> Iterator[bool]:
|
93
105
|
for port in ports:
|
94
|
-
if port.
|
106
|
+
if port.type_modifier is TypeModifier.Inferred:
|
95
107
|
self._inferred_ports[port.name] = port
|
96
108
|
else:
|
97
109
|
self._signature_ports[port.name] = port
|
@@ -99,7 +111,7 @@ class TypeQualifierValidation(ModelVisitor):
|
|
99
111
|
|
100
112
|
yield len(self._inferred_ports) > 0 or (
|
101
113
|
any(
|
102
|
-
port.
|
114
|
+
port.type_modifier is not TypeModifier.Mutable
|
103
115
|
for port in self._signature_ports.values()
|
104
116
|
)
|
105
117
|
and not self._skip_validation
|
@@ -119,27 +131,38 @@ class TypeQualifierValidation(ModelVisitor):
|
|
119
131
|
finally:
|
120
132
|
self._conjugation_context = previous_context
|
121
133
|
|
134
|
+
@contextmanager
|
135
|
+
def source_reference_context(
|
136
|
+
self, source_ref: Optional[Union[SourceReference, str]]
|
137
|
+
) -> Iterator[None]:
|
138
|
+
previous_source_ref = self._source_ref
|
139
|
+
self._source_ref = source_ref
|
140
|
+
try:
|
141
|
+
yield
|
142
|
+
finally:
|
143
|
+
self._source_ref = previous_source_ref
|
144
|
+
|
122
145
|
def _set_unused_as_const(self) -> None:
|
123
146
|
unresolved_ports = [
|
124
147
|
port
|
125
148
|
for port in self._inferred_ports.values()
|
126
|
-
if port.
|
149
|
+
if port.type_modifier is TypeModifier.Inferred
|
127
150
|
]
|
128
151
|
if not self._support_unused_ports and len(unresolved_ports) > 0:
|
129
152
|
raise ClassiqInternalExpansionError(
|
130
153
|
f"Unresolved inferred ports detected: {', '.join(port.name for port in unresolved_ports)}. "
|
131
|
-
"All ports must have their type
|
154
|
+
"All ports must have their type modifiers resolved."
|
132
155
|
)
|
133
156
|
for port in unresolved_ports:
|
134
|
-
port.
|
157
|
+
port.type_modifier = TypeModifier.Const
|
135
158
|
|
136
|
-
def
|
137
|
-
if self._conjugation_context and
|
138
|
-
|
159
|
+
def _validate_modifier(self, candidate: str, modifier: TypeModifier) -> None:
|
160
|
+
if self._conjugation_context and modifier is TypeModifier.Permutable:
|
161
|
+
modifier = TypeModifier.Const
|
139
162
|
|
140
163
|
if candidate in self._inferred_ports:
|
141
|
-
self._inferred_ports[candidate].
|
142
|
-
self._inferred_ports[candidate].
|
164
|
+
self._inferred_ports[candidate].type_modifier = TypeModifier.and_(
|
165
|
+
self._inferred_ports[candidate].type_modifier, modifier
|
143
166
|
)
|
144
167
|
return
|
145
168
|
|
@@ -147,64 +170,68 @@ class TypeQualifierValidation(ModelVisitor):
|
|
147
170
|
return
|
148
171
|
|
149
172
|
if candidate in self._signature_ports:
|
150
|
-
self.
|
173
|
+
self._validate_signature_modifier(candidate, modifier)
|
151
174
|
|
152
175
|
elif candidate in self._initialized_vars:
|
153
|
-
self._initialized_vars[candidate] =
|
154
|
-
self._initialized_vars[candidate],
|
176
|
+
self._initialized_vars[candidate] = TypeModifier.and_(
|
177
|
+
self._initialized_vars[candidate], modifier
|
155
178
|
)
|
156
179
|
|
157
|
-
def
|
158
|
-
self, candidate: str,
|
180
|
+
def _validate_signature_modifier(
|
181
|
+
self, candidate: str, modifier: TypeModifier
|
159
182
|
) -> None:
|
160
|
-
|
161
|
-
if
|
162
|
-
signature_qualifier, qualifier
|
163
|
-
):
|
183
|
+
signature_modifier = self._signature_ports[candidate].type_modifier
|
184
|
+
if signature_modifier is not TypeModifier.and_(signature_modifier, modifier):
|
164
185
|
warnings.warn(
|
165
|
-
|
166
|
-
candidate,
|
186
|
+
_inconsistent_type_modifier_error(
|
187
|
+
candidate, signature_modifier, modifier, self._source_ref
|
167
188
|
),
|
168
189
|
ClassiqDeprecationWarning,
|
169
190
|
stacklevel=1,
|
170
191
|
)
|
171
192
|
|
172
|
-
def
|
193
|
+
def _add_initialized_modifier(self, var: str, modifier: TypeModifier) -> None:
|
173
194
|
if var in self._inferred_ports or var in self._signature_ports:
|
174
195
|
return
|
175
|
-
if self._conjugation_context and
|
176
|
-
|
177
|
-
self._initialized_vars[var] =
|
196
|
+
if self._conjugation_context and modifier is TypeModifier.Permutable:
|
197
|
+
modifier = TypeModifier.Const
|
198
|
+
self._initialized_vars[var] = modifier
|
178
199
|
|
179
200
|
def run(
|
180
201
|
self,
|
181
|
-
|
182
|
-
body: Sequence[QuantumStatement],
|
202
|
+
func_def: NativeFunctionDefinition,
|
183
203
|
unchecked: Collection[str],
|
184
204
|
) -> None:
|
185
|
-
with
|
205
|
+
with (
|
206
|
+
self.validate_ports(
|
207
|
+
func_def.port_declarations, unchecked
|
208
|
+
) as should_validate,
|
209
|
+
self.source_reference_context(f"function '{func_def.name}'"),
|
210
|
+
):
|
186
211
|
if should_validate:
|
187
|
-
self.visit(body)
|
212
|
+
self.visit(func_def.body)
|
188
213
|
self._update_bound_vars()
|
189
214
|
|
190
215
|
def _update_bound_vars(self) -> None:
|
191
216
|
merged_bound_vars = _merge_overlapping(self._bound_vars)
|
192
217
|
for bound_vars in merged_bound_vars:
|
193
|
-
|
218
|
+
reduced_modifier = self._get_reduced_modifier(bound_vars)
|
194
219
|
for var in bound_vars:
|
195
|
-
self.
|
220
|
+
self._validate_modifier(var, reduced_modifier)
|
196
221
|
|
197
222
|
def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
223
|
+
with self.source_reference_context(call.source_ref):
|
224
|
+
for handle, port in call.handles_with_params:
|
225
|
+
self._validate_modifier(handle.name, port.type_modifier)
|
226
|
+
if port.direction is PortDeclarationDirection.Output:
|
227
|
+
self._add_initialized_modifier(handle.name, port.type_modifier)
|
202
228
|
|
203
229
|
if self._has_inputs(call):
|
204
230
|
bound_vars = {
|
205
231
|
handle.name
|
206
232
|
for handle, port in call.handles_with_params
|
207
233
|
if port.direction is not PortDeclarationDirection.Inout
|
234
|
+
and handle.name not in self._unchecked
|
208
235
|
}
|
209
236
|
self._bound_vars.append(bound_vars)
|
210
237
|
|
@@ -216,61 +243,61 @@ class TypeQualifierValidation(ModelVisitor):
|
|
216
243
|
)
|
217
244
|
|
218
245
|
def visit_Allocate(self, alloc: Allocate) -> None:
|
219
|
-
self.
|
220
|
-
|
246
|
+
with self.source_reference_context(alloc.source_ref):
|
247
|
+
self._validate_modifier(alloc.target.name, TypeModifier.Permutable)
|
248
|
+
self._add_initialized_modifier(alloc.target.name, TypeModifier.Permutable)
|
221
249
|
|
222
250
|
def visit_BindOperation(self, bind_op: BindOperation) -> None:
|
223
251
|
var_names = {
|
224
252
|
handle.name
|
225
253
|
for handle in itertools.chain(bind_op.in_handles, bind_op.out_handles)
|
254
|
+
if handle.name not in self._unchecked
|
226
255
|
}
|
227
256
|
self._bound_vars.append(var_names)
|
228
257
|
for handle in bind_op.out_handles:
|
229
|
-
self.
|
258
|
+
self._add_initialized_modifier(handle.name, TypeModifier.Inferred)
|
230
259
|
|
231
|
-
def
|
232
|
-
|
233
|
-
name: self._signature_ports[name].
|
260
|
+
def _get_reduced_modifier(self, bound_vars: set[str]) -> TypeModifier:
|
261
|
+
signature_modifiers = {
|
262
|
+
name: self._signature_ports[name].type_modifier
|
234
263
|
for name in bound_vars.intersection(self._signature_ports)
|
235
264
|
}
|
236
|
-
|
237
|
-
name: self._inferred_ports[name].
|
265
|
+
known_inferred_modifiers = {
|
266
|
+
name: self._inferred_ports[name].type_modifier
|
238
267
|
for name in bound_vars.intersection(self._inferred_ports)
|
239
|
-
if self._inferred_ports[name].
|
268
|
+
if self._inferred_ports[name].type_modifier is not TypeModifier.Inferred
|
240
269
|
}
|
241
|
-
|
270
|
+
known_initialized_modifiers = {
|
242
271
|
name: self._initialized_vars[name]
|
243
272
|
for name in bound_vars.intersection(self._initialized_vars)
|
244
|
-
if self._initialized_vars[name] is not
|
273
|
+
if self._initialized_vars[name] is not TypeModifier.Inferred
|
245
274
|
}
|
246
|
-
|
247
|
-
|
248
|
-
| known_inferred_qualifiers
|
249
|
-
| known_initialized_qualifiers
|
275
|
+
known_modifiers = (
|
276
|
+
signature_modifiers | known_inferred_modifiers | known_initialized_modifiers
|
250
277
|
)
|
251
|
-
|
278
|
+
min_modifier = self._get_min_modifier(list(known_modifiers.values()))
|
252
279
|
if not all(
|
253
|
-
|
254
|
-
for
|
280
|
+
type_modifier is min_modifier
|
281
|
+
for type_modifier in signature_modifiers.values()
|
255
282
|
):
|
256
283
|
warnings.warn(
|
257
|
-
|
258
|
-
|
284
|
+
_inconsistent_type_modifier_in_binding_error(
|
285
|
+
min_modifier, known_modifiers, self._source_ref
|
259
286
|
),
|
260
287
|
ClassiqDeprecationWarning,
|
261
288
|
stacklevel=1,
|
262
289
|
)
|
263
290
|
|
264
|
-
return
|
291
|
+
return min_modifier
|
265
292
|
|
266
293
|
@staticmethod
|
267
|
-
def
|
268
|
-
if len(
|
269
|
-
return
|
270
|
-
elif len(
|
271
|
-
return
|
294
|
+
def _get_min_modifier(modifiers: list[TypeModifier]) -> TypeModifier:
|
295
|
+
if len(modifiers) == 0:
|
296
|
+
return TypeModifier.Const
|
297
|
+
elif len(modifiers) == 1:
|
298
|
+
return modifiers[0]
|
272
299
|
else:
|
273
|
-
return functools.reduce(
|
300
|
+
return functools.reduce(TypeModifier.and_, modifiers)
|
274
301
|
|
275
302
|
@staticmethod
|
276
303
|
def _extract_expr_vars(expr_op: QuantumExpressionOperation) -> list[str]:
|
@@ -281,42 +308,49 @@ class TypeQualifierValidation(ModelVisitor):
|
|
281
308
|
return [handle.name for handle in vrc.var_handles]
|
282
309
|
|
283
310
|
def visit_ArithmeticOperation(self, arith: ArithmeticOperation) -> None:
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
self.
|
288
|
-
|
289
|
-
|
311
|
+
with self.source_reference_context(arith.source_ref):
|
312
|
+
result_var = arith.result_var.name
|
313
|
+
self._validate_modifier(result_var, TypeModifier.Permutable)
|
314
|
+
for expr_var in self._extract_expr_vars(arith):
|
315
|
+
self._validate_modifier(expr_var, TypeModifier.Const)
|
316
|
+
if not arith.is_inplace:
|
317
|
+
self._add_initialized_modifier(result_var, TypeModifier.Permutable)
|
290
318
|
|
291
319
|
def visit_AmplitudeLoadingOperation(
|
292
320
|
self, amp_load: AmplitudeLoadingOperation
|
293
321
|
) -> None:
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
self.
|
322
|
+
with self.source_reference_context(amp_load.source_ref):
|
323
|
+
result_var = amp_load.result_var.name
|
324
|
+
self._validate_modifier(result_var, TypeModifier.Mutable)
|
325
|
+
for expr_var in self._extract_expr_vars(amp_load):
|
326
|
+
self._validate_modifier(expr_var, TypeModifier.Const)
|
298
327
|
|
299
328
|
def visit_PhaseOperation(self, phase_op: PhaseOperation) -> None:
|
300
|
-
|
301
|
-
self.
|
329
|
+
with self.source_reference_context(phase_op.source_ref):
|
330
|
+
for expr_var in self._extract_expr_vars(phase_op):
|
331
|
+
self._validate_modifier(expr_var, TypeModifier.Const)
|
302
332
|
|
303
333
|
def visit_Control(self, control: Control) -> None:
|
304
|
-
|
305
|
-
self.
|
306
|
-
|
307
|
-
|
308
|
-
|
334
|
+
with self.source_reference_context(control.source_ref):
|
335
|
+
for control_var in self._extract_expr_vars(control):
|
336
|
+
self._validate_modifier(control_var, TypeModifier.Const)
|
337
|
+
self.visit(control.body)
|
338
|
+
if control.else_block is not None:
|
339
|
+
self.visit(control.else_block)
|
309
340
|
|
310
341
|
def visit_Invert(self, invert: Invert) -> None:
|
311
|
-
self.
|
342
|
+
with self.source_reference_context(invert.source_ref):
|
343
|
+
self.visit(invert.body)
|
312
344
|
|
313
345
|
def visit_Power(self, power: Power) -> None:
|
314
|
-
self.
|
346
|
+
with self.source_reference_context(power.source_ref):
|
347
|
+
self.visit(power.body)
|
315
348
|
|
316
349
|
def visit_WithinApply(self, within_apply: WithinApply) -> None:
|
317
|
-
with self.
|
318
|
-
self.
|
319
|
-
|
350
|
+
with self.source_reference_context(within_apply.source_ref):
|
351
|
+
with self.conjugation_context():
|
352
|
+
self.visit(within_apply.compute)
|
353
|
+
self.visit(within_apply.action)
|
320
354
|
|
321
355
|
|
322
356
|
def _merge_overlapping(bound_vars: Sequence[Collection[str]]) -> list[set[str]]:
|
@@ -10,7 +10,6 @@ from classiq.interface.generator.expressions.atomic_expression_functions import
|
|
10
10
|
from classiq.interface.generator.expressions.expression import Expression
|
11
11
|
from classiq.interface.generator.functions.classical_type import (
|
12
12
|
ClassicalArray,
|
13
|
-
ClassicalList,
|
14
13
|
ClassicalTuple,
|
15
14
|
ClassicalType,
|
16
15
|
)
|
@@ -37,6 +36,13 @@ from classiq.interface.model.quantum_lambda_function import (
|
|
37
36
|
from classiq.model_expansions.visitors.variable_references import VarRefCollector
|
38
37
|
|
39
38
|
|
39
|
+
def handle_is_directly_used_var(handle: HandleBinding, scope_vars: set[str]) -> bool:
|
40
|
+
return handle.name in scope_vars and (
|
41
|
+
not isinstance(handle, FieldHandleBinding)
|
42
|
+
or handle.field not in CLASSICAL_ATTRIBUTES
|
43
|
+
)
|
44
|
+
|
45
|
+
|
40
46
|
def set_generative_recursively(classical_type: ClassicalType) -> None:
|
41
47
|
if (
|
42
48
|
isinstance(classical_type, TypeName)
|
@@ -46,7 +52,7 @@ def set_generative_recursively(classical_type: ClassicalType) -> None:
|
|
46
52
|
set_generative_recursively(field_type)
|
47
53
|
return
|
48
54
|
classical_type.set_generative()
|
49
|
-
if isinstance(classical_type,
|
55
|
+
if isinstance(classical_type, ClassicalArray):
|
50
56
|
set_generative_recursively(classical_type.element_type)
|
51
57
|
if isinstance(classical_type, ClassicalTuple):
|
52
58
|
for element_type in classical_type.element_types:
|
@@ -148,7 +154,7 @@ class SymbolicParamInference(ModelVisitor):
|
|
148
154
|
for param, arg in zip_longest(params, call.positional_args):
|
149
155
|
if (
|
150
156
|
not isinstance(param, AnonClassicalParameterDeclaration)
|
151
|
-
or param.classical_type.
|
157
|
+
or not param.classical_type.is_purely_declarative
|
152
158
|
):
|
153
159
|
self._process_compile_time_expressions(arg)
|
154
160
|
else:
|
@@ -178,10 +184,7 @@ class SymbolicParamInference(ModelVisitor):
|
|
178
184
|
)
|
179
185
|
vrc.visit(ast.parse(expr))
|
180
186
|
for handle in vrc.var_handles:
|
181
|
-
if handle
|
182
|
-
not isinstance(handle, FieldHandleBinding)
|
183
|
-
or handle.field not in CLASSICAL_ATTRIBUTES
|
184
|
-
):
|
187
|
+
if handle_is_directly_used_var(handle, set(self._scope)):
|
185
188
|
set_generative_recursively(self._scope[handle.name])
|
186
189
|
|
187
190
|
def _process_nested_compile_time_expression(self, expr: str) -> None:
|
@@ -6,6 +6,7 @@ from .amplitude_estimation import *
|
|
6
6
|
from .discrete_sine_cosine_transform import *
|
7
7
|
from .discrete_sine_cosine_transform import _qct_d_operator, _qct_pi_operator
|
8
8
|
from .grover import *
|
9
|
+
from .grover import _cond_phase_flip
|
9
10
|
from .hea import *
|
10
11
|
from .linear_pauli_rotation import *
|
11
12
|
from .linear_pauli_rotation import _single_pauli
|
@@ -79,6 +80,7 @@ OPEN_LIBRARY_FUNCTIONS = [
|
|
79
80
|
_check_msb,
|
80
81
|
encode_in_angle,
|
81
82
|
encode_on_bloch,
|
83
|
+
_cond_phase_flip,
|
82
84
|
]
|
83
85
|
|
84
86
|
__all__ = [
|
@@ -105,6 +107,7 @@ __all__ = [
|
|
105
107
|
"modular_increment",
|
106
108
|
"multiswap",
|
107
109
|
"phase_oracle",
|
110
|
+
"prepare_basis_state",
|
108
111
|
"prepare_bell_state",
|
109
112
|
"prepare_complex_amplitudes",
|
110
113
|
"prepare_dicke_state",
|
@@ -1,11 +1,10 @@
|
|
1
1
|
from classiq.open_library.functions.grover import grover_operator
|
2
|
+
from classiq.qmod.builtins.functions.allocation import free
|
2
3
|
from classiq.qmod.builtins.functions.standard_gates import RY
|
3
4
|
from classiq.qmod.builtins.operations import (
|
4
5
|
allocate,
|
5
|
-
bind,
|
6
6
|
control,
|
7
7
|
power,
|
8
|
-
within_apply,
|
9
8
|
)
|
10
9
|
from classiq.qmod.cparam import CInt, CReal
|
11
10
|
from classiq.qmod.qfunc import qfunc
|
@@ -71,21 +70,14 @@ def exact_amplitude_amplification(
|
|
71
70
|
theta = pi / (4 * k + 2)
|
72
71
|
rot_phase = 2 * acos(sin(theta) / amplitude)
|
73
72
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
allocate(aux)
|
74
|
+
amplitude_amplification(
|
75
|
+
k,
|
76
|
+
lambda qvars_: control(qvars_[0] == 0, lambda: oracle(qvars_[1 : qvars_.size])),
|
77
|
+
lambda qvars_: [
|
78
|
+
space_transform(qvars_[1 : qvars_.size]),
|
79
|
+
RY(rot_phase, qvars_[0]),
|
79
80
|
],
|
80
|
-
|
81
|
-
k,
|
82
|
-
lambda qvars_: control(
|
83
|
-
qvars_[0] == 0, lambda: oracle(qvars_[1 : qvars_.size])
|
84
|
-
),
|
85
|
-
lambda qvars_: [
|
86
|
-
space_transform(qvars_[1 : qvars_.size]),
|
87
|
-
RY(rot_phase, qvars_[0]),
|
88
|
-
],
|
89
|
-
extended_qvars,
|
90
|
-
),
|
81
|
+
[aux, packed_qvars],
|
91
82
|
)
|
83
|
+
free(aux)
|
@@ -11,7 +11,7 @@ from classiq.qmod.builtins.operations import (
|
|
11
11
|
within_apply,
|
12
12
|
)
|
13
13
|
from classiq.qmod.qfunc import qfunc
|
14
|
-
from classiq.qmod.qmod_variable import QArray, QBit, QNum
|
14
|
+
from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit, QNum
|
15
15
|
from classiq.qmod.symbolic import pi
|
16
16
|
|
17
17
|
|
@@ -21,13 +21,13 @@ def _b_operator(q: QBit) -> None:
|
|
21
21
|
|
22
22
|
|
23
23
|
@qfunc
|
24
|
-
def _qct_d_operator(x: QNum, q: QBit) -> None:
|
24
|
+
def _qct_d_operator(x: Const[QNum], q: QBit) -> None:
|
25
25
|
_b_operator(q)
|
26
26
|
control(x == 0, lambda: invert(lambda: _b_operator(q)))
|
27
27
|
|
28
28
|
|
29
29
|
@qfunc
|
30
|
-
def _qct_pi_operator(x: QArray[QBit], q: QBit) -> None:
|
30
|
+
def _qct_pi_operator(x: Permutable[QArray[QBit]], q: Const[QBit]) -> None:
|
31
31
|
control(
|
32
32
|
q == 1,
|
33
33
|
lambda: [
|
@@ -120,8 +120,8 @@ def qct_qst_type1(x: QArray[QBit]) -> None:
|
|
120
120
|
within_apply(lambda: _t_operator(x), lambda: qft(x))
|
121
121
|
|
122
122
|
|
123
|
-
@qfunc
|
124
|
-
def qct_qst_type2(x: QArray[QBit], q: QBit) -> None:
|
123
|
+
@qfunc(unchecked=["q"])
|
124
|
+
def qct_qst_type2(x: QArray[QBit], q: Const[QBit]) -> None:
|
125
125
|
"""
|
126
126
|
[Qmod Classiq-library function]
|
127
127
|
|
@@ -10,14 +10,22 @@ from classiq.qmod.builtins.operations import (
|
|
10
10
|
)
|
11
11
|
from classiq.qmod.qfunc import qfunc
|
12
12
|
from classiq.qmod.qmod_parameter import CInt
|
13
|
-
from classiq.qmod.qmod_variable import QArray, QBit, QNum
|
13
|
+
from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit, QNum
|
14
14
|
from classiq.qmod.quantum_callable import QCallable
|
15
15
|
from classiq.qmod.symbolic import pi
|
16
16
|
|
17
17
|
|
18
|
+
@qfunc(unchecked=["target"])
|
19
|
+
def _cond_phase_flip(
|
20
|
+
predicate: QCallable[Permutable[QBit]], target: Const[QBit]
|
21
|
+
) -> None:
|
22
|
+
within_apply(lambda: H(target), lambda: predicate(target))
|
23
|
+
|
24
|
+
|
18
25
|
@qfunc
|
19
26
|
def phase_oracle(
|
20
|
-
predicate: QCallable[QArray[QBit]
|
27
|
+
predicate: QCallable[Const[QArray[QBit]], Permutable[QBit]],
|
28
|
+
target: Const[QArray[QBit]],
|
21
29
|
) -> None:
|
22
30
|
"""
|
23
31
|
[Qmod Classiq-library function]
|
@@ -42,13 +50,13 @@ def phase_oracle(
|
|
42
50
|
"""
|
43
51
|
aux = QBit()
|
44
52
|
within_apply(
|
45
|
-
|
46
|
-
|
53
|
+
lambda: [allocate(aux), X(aux)],
|
54
|
+
lambda: _cond_phase_flip(lambda x: predicate(target, x), aux),
|
47
55
|
)
|
48
56
|
|
49
57
|
|
50
|
-
@qfunc
|
51
|
-
def reflect_about_zero(packed_vars: QArray[QBit]) -> None:
|
58
|
+
@qfunc(unchecked=["packed_vars"])
|
59
|
+
def reflect_about_zero(packed_vars: Const[QArray[QBit]]) -> None:
|
52
60
|
"""
|
53
61
|
[Qmod Classiq-library function]
|
54
62
|
|