classiq 0.84.0__py3-none-any.whl → 0.85.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/applications/combinatorial_optimization/combinatorial_problem.py +20 -42
- classiq/evaluators/classical_expression.py +32 -15
- classiq/execution/execution_session.py +49 -6
- classiq/interface/_version.py +1 -1
- classiq/interface/debug_info/debug_info.py +0 -4
- classiq/interface/generator/expressions/atomic_expression_functions.py +5 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +2 -0
- classiq/interface/generator/functions/concrete_types.py +20 -0
- classiq/interface/generator/generated_circuit_data.py +5 -10
- classiq/interface/ide/operation_registry.py +45 -0
- classiq/interface/ide/visual_model.py +62 -1
- classiq/interface/model/bounds.py +12 -2
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +7 -4
- classiq/interface/model/variable_declaration_statement.py +33 -6
- classiq/model_expansions/atomic_expression_functions_defs.py +5 -1
- classiq/model_expansions/function_builder.py +4 -1
- classiq/model_expansions/interpreters/generative_interpreter.py +16 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +63 -21
- classiq/model_expansions/quantum_operations/bounds.py +7 -1
- classiq/model_expansions/quantum_operations/classical_var_emitter.py +16 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +30 -10
- classiq/model_expansions/scope.py +7 -0
- classiq/model_expansions/transformers/var_splitter.py +1 -1
- classiq/open_library/functions/__init__.py +0 -2
- classiq/open_library/functions/qaoa_penalty.py +8 -1
- classiq/open_library/functions/state_preparation.py +1 -32
- classiq/qmod/__init__.py +2 -0
- classiq/qmod/builtins/operations.py +65 -1
- classiq/qmod/classical_variable.py +74 -0
- classiq/qmod/native/pretty_printer.py +18 -14
- classiq/qmod/pretty_print/pretty_printer.py +34 -15
- classiq/qmod/qfunc.py +2 -19
- classiq/qmod/qmod_variable.py +5 -8
- classiq/qmod/quantum_expandable.py +1 -1
- classiq/qmod/quantum_function.py +42 -2
- classiq/qmod/symbolic_type.py +2 -1
- {classiq-0.84.0.dist-info → classiq-0.85.0.dist-info}/METADATA +1 -1
- {classiq-0.84.0.dist-info → classiq-0.85.0.dist-info}/RECORD +39 -37
- classiq/interface/model/quantum_variable_declaration.py +0 -7
- {classiq-0.84.0.dist-info → classiq-0.85.0.dist-info}/WHEEL +0 -0
@@ -1,15 +1,42 @@
|
|
1
|
-
from typing import Literal
|
1
|
+
from typing import Any, Literal, Optional
|
2
|
+
|
3
|
+
import pydantic
|
2
4
|
|
3
5
|
from classiq.interface.generator.expressions.expression import Expression
|
4
|
-
from classiq.interface.
|
5
|
-
|
6
|
-
|
6
|
+
from classiq.interface.generator.functions.concrete_types import (
|
7
|
+
ConcreteQuantumType,
|
8
|
+
ConcreteType,
|
7
9
|
)
|
10
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
11
|
+
from classiq.interface.model.quantum_type import QuantumType
|
8
12
|
|
9
13
|
|
10
|
-
class VariableDeclarationStatement(QuantumStatement
|
14
|
+
class VariableDeclarationStatement(QuantumStatement):
|
11
15
|
kind: Literal["VariableDeclarationStatement"]
|
12
16
|
|
17
|
+
name: str
|
18
|
+
quantum_type: Optional[ConcreteQuantumType] = None
|
19
|
+
qmod_type: ConcreteType
|
20
|
+
|
21
|
+
@pydantic.model_validator(mode="before")
|
22
|
+
@classmethod
|
23
|
+
def _set_qmod_type(cls, values: Any) -> dict[str, Any]:
|
24
|
+
if isinstance(values, dict):
|
25
|
+
if "quantum_type" in values and (
|
26
|
+
"qmod_type" not in values or values["qmod_type"] is None
|
27
|
+
):
|
28
|
+
values["qmod_type"] = values["quantum_type"]
|
29
|
+
values["quantum_type"] = None
|
30
|
+
return values
|
31
|
+
if values.quantum_type is not None and values.qmod_type is None:
|
32
|
+
values.qmod_type = values.quantum_type
|
33
|
+
values.quantum_type = None
|
34
|
+
return values
|
35
|
+
|
13
36
|
@property
|
14
37
|
def expressions(self) -> list[Expression]:
|
15
|
-
return self.
|
38
|
+
return self.qmod_type.expressions
|
39
|
+
|
40
|
+
@property
|
41
|
+
def is_quantum(self) -> bool:
|
42
|
+
return isinstance(self.qmod_type, QuantumType)
|
@@ -9,6 +9,9 @@ from classiq.interface.exceptions import (
|
|
9
9
|
ClassiqExpansionError,
|
10
10
|
ClassiqInternalExpansionError,
|
11
11
|
)
|
12
|
+
from classiq.interface.generator.expressions.atomic_expression_functions import (
|
13
|
+
MEASUREMENT_FUNCTIONS,
|
14
|
+
)
|
12
15
|
from classiq.interface.generator.expressions.expression_types import (
|
13
16
|
ExpressionValue,
|
14
17
|
QmodStructInstance,
|
@@ -398,7 +401,8 @@ def _symbolic_function(func: str) -> Callable:
|
|
398
401
|
|
399
402
|
|
400
403
|
QMOD_CLASSICAL_FUNCTIONS = [
|
401
|
-
_symbolic_function(func)
|
404
|
+
_symbolic_function(func)
|
405
|
+
for func in qmod_classical_functions + list(MEASUREMENT_FUNCTIONS)
|
402
406
|
]
|
403
407
|
|
404
408
|
ATOMIC_EXPRESSION_FUNCTIONS = {
|
@@ -9,6 +9,7 @@ from classiq.interface.generator.compiler_keywords import (
|
|
9
9
|
LAMBDA_KEYWORD,
|
10
10
|
)
|
11
11
|
from classiq.interface.generator.functions.builtins.internal_operators import (
|
12
|
+
BLOCK_OPERATOR_NAME,
|
12
13
|
WITHIN_APPLY_NAME,
|
13
14
|
)
|
14
15
|
from classiq.interface.model.model import MAIN_FUNCTION_NAME
|
@@ -35,6 +36,8 @@ from classiq.model_expansions.utils.counted_name_allocator import CountedNameAll
|
|
35
36
|
|
36
37
|
ClosureType = TypeVar("ClosureType", bound=Closure)
|
37
38
|
|
39
|
+
BLOCKS_ALLOWED_CAPTURING = (WITHIN_APPLY_NAME, BLOCK_OPERATOR_NAME)
|
40
|
+
|
38
41
|
|
39
42
|
@dataclass
|
40
43
|
class Block:
|
@@ -142,7 +145,7 @@ class OperationBuilder:
|
|
142
145
|
captured_vars = self.current_block.captured_vars
|
143
146
|
if (
|
144
147
|
not isinstance(self.current_operation, FunctionClosure)
|
145
|
-
and self.current_operation.name
|
148
|
+
and self.current_operation.name not in BLOCKS_ALLOWED_CAPTURING
|
146
149
|
):
|
147
150
|
validate_captured_directions(
|
148
151
|
captured_vars.filter_var_decls(
|
@@ -7,6 +7,7 @@ from numpy.random import permutation
|
|
7
7
|
from classiq.interface.generator.constant import Constant
|
8
8
|
from classiq.interface.generator.expressions.expression import Expression
|
9
9
|
from classiq.interface.generator.functions.builtins.internal_operators import (
|
10
|
+
BLOCK_OPERATOR_NAME,
|
10
11
|
CLASSICAL_IF_OPERATOR_NAME,
|
11
12
|
CONTROL_OPERATOR_NAME,
|
12
13
|
INVERT_OPERATOR_NAME,
|
@@ -15,6 +16,7 @@ from classiq.interface.generator.functions.builtins.internal_operators import (
|
|
15
16
|
)
|
16
17
|
from classiq.interface.model.allocate import Allocate
|
17
18
|
from classiq.interface.model.bind_operation import BindOperation
|
19
|
+
from classiq.interface.model.block import Block
|
18
20
|
from classiq.interface.model.bounds import SetBoundsStatement
|
19
21
|
from classiq.interface.model.classical_if import ClassicalIf
|
20
22
|
from classiq.interface.model.control import Control
|
@@ -68,6 +70,9 @@ from classiq.model_expansions.quantum_operations.block_evaluator import (
|
|
68
70
|
RepeatElimination,
|
69
71
|
)
|
70
72
|
from classiq.model_expansions.quantum_operations.bounds import SetBoundsEmitter
|
73
|
+
from classiq.model_expansions.quantum_operations.classical_var_emitter import (
|
74
|
+
ClassicalVarEmitter,
|
75
|
+
)
|
71
76
|
from classiq.model_expansions.quantum_operations.composite_emitter import (
|
72
77
|
CompositeEmitter,
|
73
78
|
)
|
@@ -192,6 +197,7 @@ class GenerativeInterpreter(BaseInterpreter):
|
|
192
197
|
[
|
193
198
|
HandleEvaluator(self, "result_var"),
|
194
199
|
ExpressionEvaluator(self, "expression"),
|
200
|
+
ClassicalVarEmitter(self),
|
195
201
|
AssignmentResultProcessor(self),
|
196
202
|
],
|
197
203
|
).emit(op)
|
@@ -303,9 +309,18 @@ class GenerativeInterpreter(BaseInterpreter):
|
|
303
309
|
def emit_set_bounds(self, op: SetBoundsStatement) -> None:
|
304
310
|
CompositeEmitter[SetBoundsStatement](
|
305
311
|
self,
|
306
|
-
[
|
312
|
+
[
|
313
|
+
ExpressionEvaluator(self, "lower_bound"),
|
314
|
+
ExpressionEvaluator(self, "upper_bound"),
|
315
|
+
HandleEvaluator(self, "target"),
|
316
|
+
SetBoundsEmitter(self),
|
317
|
+
],
|
307
318
|
).emit(op)
|
308
319
|
|
320
|
+
@emit.register
|
321
|
+
def emit_block(self, block: Block) -> None:
|
322
|
+
BlockEvaluator(self, BLOCK_OPERATOR_NAME, "statements").emit(block)
|
323
|
+
|
309
324
|
def _expand_body(self, operation: Closure) -> None:
|
310
325
|
if isinstance(operation, FunctionClosure) and operation.name == "permute":
|
311
326
|
# special expansion since permute is generative
|
@@ -1,10 +1,12 @@
|
|
1
|
-
from typing import Optional
|
1
|
+
from typing import TYPE_CHECKING, Optional
|
2
2
|
|
3
3
|
from classiq.interface.exceptions import ClassiqExpansionError
|
4
4
|
from classiq.interface.generator.arith.arithmetic import compute_arithmetic_result_type
|
5
5
|
from classiq.interface.generator.expressions.expression import Expression
|
6
6
|
from classiq.interface.model.allocate import Allocate
|
7
7
|
from classiq.interface.model.bind_operation import BindOperation
|
8
|
+
from classiq.interface.model.block import Block
|
9
|
+
from classiq.interface.model.bounds import SetBoundsStatement
|
8
10
|
from classiq.interface.model.handle_binding import (
|
9
11
|
ConcreteHandleBinding,
|
10
12
|
HandleBinding,
|
@@ -19,6 +21,7 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
19
21
|
)
|
20
22
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
21
23
|
from classiq.interface.model.quantum_type import QuantumBitvector, QuantumNumeric
|
24
|
+
from classiq.interface.model.statement_block import StatementBlock
|
22
25
|
from classiq.interface.model.variable_declaration_statement import (
|
23
26
|
VariableDeclarationStatement,
|
24
27
|
)
|
@@ -30,14 +33,25 @@ from classiq.model_expansions.quantum_operations.arithmetic.explicit_boolean_exp
|
|
30
33
|
validate_assignment_bool_expression,
|
31
34
|
)
|
32
35
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
33
|
-
from classiq.model_expansions.scope import
|
36
|
+
from classiq.model_expansions.scope import ClassicalSymbol
|
34
37
|
from classiq.model_expansions.transformers.ast_renamer import rename_variables
|
35
38
|
from classiq.qmod.builtins.functions.standard_gates import CX
|
36
39
|
|
40
|
+
if TYPE_CHECKING:
|
41
|
+
from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
|
42
|
+
|
37
43
|
|
38
44
|
class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
45
|
+
def __init__(
|
46
|
+
self, interpreter: "BaseInterpreter", replace_assignment_if_needed: bool = False
|
47
|
+
) -> None:
|
48
|
+
super().__init__(interpreter)
|
49
|
+
self._replace_assignment_if_needed = replace_assignment_if_needed
|
50
|
+
|
39
51
|
def emit(self, op: QuantumAssignmentOperation, /) -> bool:
|
40
|
-
result_symbol = self._interpreter.evaluate(op.result_var).
|
52
|
+
result_symbol = self._interpreter.evaluate(op.result_var).value
|
53
|
+
if isinstance(result_symbol, ClassicalSymbol):
|
54
|
+
return False
|
41
55
|
result_type = result_symbol.quantum_type
|
42
56
|
|
43
57
|
if not (
|
@@ -70,9 +84,11 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
70
84
|
self._validate_declared_attributes(
|
71
85
|
result_type, inferred_result_type, str(op.result_var)
|
72
86
|
)
|
73
|
-
self.
|
74
|
-
|
75
|
-
|
87
|
+
if self._replace_assignment_if_needed:
|
88
|
+
self._assign_to_inferred_var_and_bind(op, result_type, inferred_result_type)
|
89
|
+
return True
|
90
|
+
else:
|
91
|
+
return False
|
76
92
|
|
77
93
|
def _infer_result_type(self, op: ArithmeticOperation) -> Optional[QuantumNumeric]:
|
78
94
|
expr = self._evaluate_expression(op.expression)
|
@@ -182,6 +198,7 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
182
198
|
result_type: QuantumNumeric,
|
183
199
|
inferred_result_type: QuantumNumeric,
|
184
200
|
) -> None:
|
201
|
+
stmts: StatementBlock = []
|
185
202
|
handles: list[HandleBinding] = []
|
186
203
|
|
187
204
|
extra_fraction_digits = (
|
@@ -190,20 +207,22 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
190
207
|
)
|
191
208
|
if extra_fraction_digits > 0:
|
192
209
|
handles.append(
|
193
|
-
self._declare_qarray(
|
210
|
+
self._declare_qarray(
|
211
|
+
"extra_fraction_digits", extra_fraction_digits, stmts
|
212
|
+
)
|
194
213
|
)
|
195
214
|
|
196
215
|
inferred_result_name = self._counted_name_allocator.allocate("inferred_result")
|
197
216
|
inferred_result_handle = HandleBinding(name=inferred_result_name)
|
198
|
-
|
217
|
+
stmts.append(
|
199
218
|
VariableDeclarationStatement(
|
200
|
-
name=inferred_result_name,
|
219
|
+
name=inferred_result_name, qmod_type=inferred_result_type
|
201
220
|
)
|
202
221
|
)
|
203
222
|
handles.append(inferred_result_handle)
|
204
223
|
modified_op = op.model_copy(update={"result_var": inferred_result_handle})
|
205
224
|
self._interpreter.add_to_debug_info(modified_op)
|
206
|
-
|
225
|
+
stmts.append(modified_op)
|
207
226
|
|
208
227
|
result_integer_size = (
|
209
228
|
result_type.size_in_bits - result_type.fraction_digits_value
|
@@ -214,11 +233,11 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
214
233
|
)
|
215
234
|
extra_integers = result_integer_size - inferred_result_integer_size
|
216
235
|
if extra_integers > 0:
|
217
|
-
handles.append(
|
236
|
+
handles.append(
|
237
|
+
self._declare_qarray("extra_integers", extra_integers, stmts)
|
238
|
+
)
|
218
239
|
|
219
|
-
|
220
|
-
BindOperation(in_handles=handles, out_handles=[op.result_var])
|
221
|
-
)
|
240
|
+
stmts.append(BindOperation(in_handles=handles, out_handles=[op.result_var]))
|
222
241
|
|
223
242
|
if (
|
224
243
|
result_type.sign_value
|
@@ -226,22 +245,44 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
226
245
|
and extra_integers > 0
|
227
246
|
):
|
228
247
|
sign_idx = result_type.size_in_bits - extra_integers - 1
|
229
|
-
self._sign_extension(
|
248
|
+
self._sign_extension(
|
249
|
+
op.result_var, sign_idx, result_type.size_in_bits, stmts
|
250
|
+
)
|
251
|
+
|
252
|
+
if (inferred_bounds := inferred_result_type.get_bounds()) is not None:
|
253
|
+
lower_bound = Expression(expr=str(inferred_bounds[0]))
|
254
|
+
upper_bound = Expression(expr=str(inferred_bounds[1]))
|
255
|
+
else:
|
256
|
+
lower_bound, upper_bound = None, None
|
257
|
+
stmts.append(
|
258
|
+
SetBoundsStatement(
|
259
|
+
target=op.result_var,
|
260
|
+
lower_bound=lower_bound,
|
261
|
+
upper_bound=upper_bound,
|
262
|
+
)
|
263
|
+
)
|
264
|
+
|
265
|
+
self._interpreter.emit(
|
266
|
+
Block(
|
267
|
+
statements=stmts,
|
268
|
+
uuid=op.uuid,
|
269
|
+
back_ref=op.back_ref,
|
270
|
+
)
|
271
|
+
)
|
230
272
|
|
231
273
|
def _declare_qarray(
|
232
274
|
self,
|
233
275
|
prefix: str,
|
234
276
|
size: int,
|
277
|
+
stmts: StatementBlock,
|
235
278
|
allocate: bool = True,
|
236
279
|
) -> HandleBinding:
|
237
280
|
name = self._counted_name_allocator.allocate(prefix)
|
238
281
|
handle = HandleBinding(name=name)
|
239
282
|
quantum_type = QuantumBitvector(length=Expression(expr=str(size)))
|
240
|
-
|
241
|
-
VariableDeclarationStatement(name=name, quantum_type=quantum_type)
|
242
|
-
)
|
283
|
+
stmts.append(VariableDeclarationStatement(name=name, qmod_type=quantum_type))
|
243
284
|
if allocate:
|
244
|
-
|
285
|
+
stmts.append(Allocate(target=handle))
|
245
286
|
return handle
|
246
287
|
|
247
288
|
def _sign_extension(
|
@@ -249,9 +290,10 @@ class AssignmentResultProcessor(Emitter[QuantumAssignmentOperation]):
|
|
249
290
|
result_var: ConcreteHandleBinding,
|
250
291
|
sign_idx: int,
|
251
292
|
size: int,
|
293
|
+
stmts: StatementBlock,
|
252
294
|
) -> None:
|
253
|
-
aux = self._declare_qarray("inferred_result_aux", size, allocate=False)
|
254
|
-
|
295
|
+
aux = self._declare_qarray("inferred_result_aux", size, stmts, allocate=False)
|
296
|
+
stmts.append(
|
255
297
|
WithinApply(
|
256
298
|
compute=[BindOperation(in_handles=[result_var], out_handles=[aux])],
|
257
299
|
action=[
|
@@ -24,7 +24,13 @@ class SetBoundsEmitter(Emitter[SetBoundsStatement]):
|
|
24
24
|
raise ClassiqExpansionError(
|
25
25
|
f"Cannot set bounds of a non-numeric variable {op.target.qmod_expr!r}"
|
26
26
|
)
|
27
|
-
|
27
|
+
|
28
|
+
if op.lower_bound is not None and op.upper_bound is not None:
|
29
|
+
target.quantum_type.set_bounds(
|
30
|
+
(op.lower_bound.to_float_value(), op.upper_bound.to_float_value())
|
31
|
+
)
|
32
|
+
else:
|
33
|
+
target.quantum_type.reset_bounds()
|
28
34
|
if self._keep_statement:
|
29
35
|
self.emit_statement(op)
|
30
36
|
return True
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
2
|
+
ArithmeticOperation,
|
3
|
+
)
|
4
|
+
|
5
|
+
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
6
|
+
from classiq.model_expansions.scope import ClassicalSymbol
|
7
|
+
|
8
|
+
|
9
|
+
class ClassicalVarEmitter(Emitter[ArithmeticOperation]):
|
10
|
+
def emit(self, op: ArithmeticOperation, /) -> bool:
|
11
|
+
result_symbol = self._interpreter.evaluate(op.result_var).value
|
12
|
+
if not isinstance(result_symbol, ClassicalSymbol):
|
13
|
+
return False
|
14
|
+
op._classical_assignment = True
|
15
|
+
self.emit_statement(op)
|
16
|
+
return True
|
@@ -1,14 +1,19 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Union
|
2
|
+
|
1
3
|
from classiq.interface.exceptions import ClassiqExpansionError
|
4
|
+
from classiq.interface.generator.functions.classical_type import ClassicalType
|
2
5
|
from classiq.interface.model.handle_binding import HandleBinding
|
6
|
+
from classiq.interface.model.quantum_type import QuantumType
|
3
7
|
from classiq.interface.model.variable_declaration_statement import (
|
4
8
|
VariableDeclarationStatement,
|
5
9
|
)
|
6
10
|
|
7
11
|
from classiq.evaluators.parameter_types import (
|
12
|
+
evaluate_type_in_classical_symbol,
|
8
13
|
evaluate_type_in_quantum_symbol,
|
9
14
|
)
|
10
15
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
11
|
-
from classiq.model_expansions.scope import Evaluated, QuantumSymbol
|
16
|
+
from classiq.model_expansions.scope import ClassicalSymbol, Evaluated, QuantumSymbol
|
12
17
|
|
13
18
|
|
14
19
|
class VariableDeclarationStatementEmitter(Emitter[VariableDeclarationStatement]):
|
@@ -16,24 +21,39 @@ class VariableDeclarationStatementEmitter(Emitter[VariableDeclarationStatement])
|
|
16
21
|
var_decl = variable_declaration.model_copy(
|
17
22
|
update=dict(back_ref=variable_declaration.uuid)
|
18
23
|
)
|
19
|
-
var_decl.
|
24
|
+
var_decl.qmod_type = variable_declaration.qmod_type.model_copy()
|
20
25
|
if variable_declaration.name in self._current_scope:
|
21
26
|
raise ClassiqExpansionError(
|
22
27
|
f"Variable {variable_declaration.name!r} is already defined"
|
23
28
|
)
|
24
|
-
|
25
|
-
|
29
|
+
var_value: Union[QuantumSymbol, ClassicalSymbol]
|
30
|
+
if variable_declaration.is_quantum:
|
31
|
+
if TYPE_CHECKING:
|
32
|
+
assert isinstance(var_decl.qmod_type, QuantumType)
|
33
|
+
var_value = QuantumSymbol(
|
26
34
|
handle=HandleBinding(name=var_decl.name),
|
27
35
|
quantum_type=evaluate_type_in_quantum_symbol(
|
28
|
-
var_decl.
|
36
|
+
var_decl.qmod_type,
|
29
37
|
self._current_scope,
|
30
38
|
var_decl.name,
|
31
39
|
),
|
32
|
-
)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
40
|
+
)
|
41
|
+
self._builder.current_block.captured_vars.init_var(
|
42
|
+
var_decl.name, self._builder.current_function
|
43
|
+
)
|
44
|
+
else:
|
45
|
+
if TYPE_CHECKING:
|
46
|
+
assert isinstance(var_decl.qmod_type, ClassicalType)
|
47
|
+
var_value = ClassicalSymbol(
|
48
|
+
handle=HandleBinding(name=var_decl.name),
|
49
|
+
classical_type=evaluate_type_in_classical_symbol(
|
50
|
+
var_decl.qmod_type,
|
51
|
+
self._current_scope,
|
52
|
+
var_decl.name,
|
53
|
+
),
|
54
|
+
)
|
55
|
+
self._current_scope[variable_declaration.name] = Evaluated(
|
56
|
+
value=var_value, defining_function=self._builder.current_function
|
37
57
|
)
|
38
58
|
self.emit_statement(var_decl)
|
39
59
|
return True
|
@@ -21,6 +21,7 @@ from classiq.interface.generator.expressions.proxies.classical.classical_scalar_
|
|
21
21
|
from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
|
22
22
|
QmodStructInstance,
|
23
23
|
)
|
24
|
+
from classiq.interface.generator.functions.classical_type import ClassicalType
|
24
25
|
from classiq.interface.generator.functions.type_name import TypeName
|
25
26
|
from classiq.interface.helpers.text_utils import readable_list, s
|
26
27
|
from classiq.interface.model.handle_binding import (
|
@@ -202,6 +203,12 @@ class QuantumSymbolList(QuantumVariable):
|
|
202
203
|
return str(self.handles)
|
203
204
|
|
204
205
|
|
206
|
+
@dataclass(frozen=True)
|
207
|
+
class ClassicalSymbol:
|
208
|
+
handle: HandleBinding
|
209
|
+
classical_type: ClassicalType
|
210
|
+
|
211
|
+
|
205
212
|
@singledispatch
|
206
213
|
def evaluated_to_str(value: Any) -> str:
|
207
214
|
return str(value)
|
@@ -218,7 +218,7 @@ class VarSplitter(ModelRenamer):
|
|
218
218
|
return [
|
219
219
|
VariableDeclarationStatement(
|
220
220
|
name=part.target_var_name,
|
221
|
-
|
221
|
+
qmod_type=part.target_var_type,
|
222
222
|
)
|
223
223
|
for part in chain.from_iterable(symbol_parts.values())
|
224
224
|
]
|
@@ -52,7 +52,6 @@ OPEN_LIBRARY_FUNCTIONS = [
|
|
52
52
|
qsvt_inversion,
|
53
53
|
qsvt_lcu,
|
54
54
|
qsvt_lcu_step,
|
55
|
-
allocate_num,
|
56
55
|
qaoa_mixer_layer,
|
57
56
|
qaoa_cost_layer,
|
58
57
|
qaoa_layer,
|
@@ -85,7 +84,6 @@ OPEN_LIBRARY_FUNCTIONS = [
|
|
85
84
|
|
86
85
|
__all__ = [
|
87
86
|
"_single_pauli",
|
88
|
-
"allocate_num",
|
89
87
|
"amplitude_amplification",
|
90
88
|
"amplitude_estimation",
|
91
89
|
"apply_to_all",
|
@@ -1,5 +1,8 @@
|
|
1
|
+
import warnings
|
1
2
|
from typing import Literal
|
2
3
|
|
4
|
+
from classiq.interface.exceptions import ClassiqDeprecationWarning
|
5
|
+
|
3
6
|
from classiq.qmod.builtins.functions import RX, H, suzuki_trotter
|
4
7
|
from classiq.qmod.builtins.operations import repeat
|
5
8
|
from classiq.qmod.builtins.structs import PauliTerm
|
@@ -42,7 +45,11 @@ def qaoa_cost_layer(
|
|
42
45
|
hamiltonian: The Hamiltonian terms for the QAOA model.
|
43
46
|
target: The target quantum array variable.
|
44
47
|
"""
|
45
|
-
|
48
|
+
with warnings.catch_warnings(): # FIXME: Remove (CLS-2912)
|
49
|
+
warnings.simplefilter(
|
50
|
+
"ignore", category=ClassiqDeprecationWarning
|
51
|
+
) # FIXME: Remove (CLS-2912)
|
52
|
+
suzuki_trotter(hamiltonian, g, 1, 1, target)
|
46
53
|
|
47
54
|
|
48
55
|
@qfunc
|
@@ -27,7 +27,7 @@ from classiq.qmod.builtins.operations import (
|
|
27
27
|
repeat,
|
28
28
|
within_apply,
|
29
29
|
)
|
30
|
-
from classiq.qmod.cparam import CArray,
|
30
|
+
from classiq.qmod.cparam import CArray, CInt, CReal
|
31
31
|
from classiq.qmod.qfunc import qfunc
|
32
32
|
from classiq.qmod.qmod_variable import Output, QArray, QBit, QNum
|
33
33
|
from classiq.qmod.symbolic import (
|
@@ -45,37 +45,6 @@ from classiq.qmod.symbolic import (
|
|
45
45
|
)
|
46
46
|
|
47
47
|
|
48
|
-
@qfunc
|
49
|
-
def allocate_num(
|
50
|
-
num_qubits: CInt,
|
51
|
-
is_signed: CBool,
|
52
|
-
fraction_digits: CInt,
|
53
|
-
out: Output[
|
54
|
-
QNum[Literal["num_qubits"], Literal["is_signed"], Literal["fraction_digits"]]
|
55
|
-
],
|
56
|
-
) -> None:
|
57
|
-
"""
|
58
|
-
[Qmod Classiq-library function]
|
59
|
-
|
60
|
-
This function is **deprecated** and will no longer be supported starting on
|
61
|
-
16/06/2025 at the earliest. Instead, use `allocate` which supports the same
|
62
|
-
parameters.
|
63
|
-
|
64
|
-
Initializes a quantum number with the given number of qubits, sign, and fractional digits.
|
65
|
-
|
66
|
-
Args:
|
67
|
-
num_qubits: The number of qubits to allocate.
|
68
|
-
is_signed: Whether the number is signed or unsigned.
|
69
|
-
fraction_digits: The number of fractional digits.
|
70
|
-
"""
|
71
|
-
warnings.warn(
|
72
|
-
"Function `allocate_num` is deprecated and will no longer be supported starting on 16/06/2025 at the earliest. Instead, use `allocate` which supports the same parameters. ",
|
73
|
-
ClassiqDeprecationWarning,
|
74
|
-
stacklevel=1,
|
75
|
-
)
|
76
|
-
allocate(num_qubits, out)
|
77
|
-
|
78
|
-
|
79
48
|
def _prepare_uniform_trimmed_state_apply_rotation(
|
80
49
|
size_lsb: CInt, lsbs_val: CInt, rotation_var: QBit
|
81
50
|
) -> None:
|
classiq/qmod/__init__.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from .builtins import * # noqa: F403
|
2
2
|
from .builtins import __all__ as _builtins_all
|
3
3
|
from .cfunc import cfunc
|
4
|
+
from .classical_variable import measure
|
4
5
|
from .create_model_function import create_model
|
5
6
|
from .expression_query import get_expression_numeric_attributes
|
6
7
|
from .qfunc import qfunc
|
@@ -29,6 +30,7 @@ __all__ = [
|
|
29
30
|
"QStruct",
|
30
31
|
"cfunc",
|
31
32
|
"create_model",
|
33
|
+
"measure",
|
32
34
|
"get_expression_numeric_attributes",
|
33
35
|
"qfunc",
|
34
36
|
"write_qmod",
|
@@ -7,6 +7,7 @@ from typing import (
|
|
7
7
|
Callable,
|
8
8
|
Final,
|
9
9
|
NoReturn,
|
10
|
+
Optional,
|
10
11
|
Union,
|
11
12
|
overload,
|
12
13
|
)
|
@@ -20,6 +21,8 @@ from classiq.interface.generator.functions.classical_type import Integer
|
|
20
21
|
from classiq.interface.helpers.text_utils import s
|
21
22
|
from classiq.interface.model.allocate import Allocate
|
22
23
|
from classiq.interface.model.bind_operation import BindOperation
|
24
|
+
from classiq.interface.model.block import Block
|
25
|
+
from classiq.interface.model.bounds import SetBoundsStatement
|
23
26
|
from classiq.interface.model.classical_if import ClassicalIf
|
24
27
|
from classiq.interface.model.classical_parameter_declaration import (
|
25
28
|
ClassicalParameterDeclaration,
|
@@ -46,7 +49,7 @@ from classiq.interface.model.within_apply_operation import WithinApply
|
|
46
49
|
|
47
50
|
from classiq.qmod.generative import is_generative_mode
|
48
51
|
from classiq.qmod.qmod_constant import QConstant
|
49
|
-
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QScalar, QVar
|
52
|
+
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QScalar, QVar
|
50
53
|
from classiq.qmod.quantum_callable import QCallable
|
51
54
|
from classiq.qmod.quantum_expandable import prepare_arg
|
52
55
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
@@ -398,6 +401,65 @@ def phase(expr: SymbolicExpr, theta: float = 1.0) -> None:
|
|
398
401
|
)
|
399
402
|
|
400
403
|
|
404
|
+
@suppress_return_value
|
405
|
+
def block(
|
406
|
+
statements: Union[QCallable, Callable[[], Statements]],
|
407
|
+
) -> None:
|
408
|
+
_validate_operand(statements)
|
409
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
410
|
+
source_ref = get_source_ref(sys._getframe(1))
|
411
|
+
|
412
|
+
block_stmt = Block(
|
413
|
+
statements=_operand_to_body(statements, "statements"),
|
414
|
+
source_ref=source_ref,
|
415
|
+
)
|
416
|
+
if is_generative_mode():
|
417
|
+
block_stmt.set_generative_block("statements", statements)
|
418
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(block_stmt)
|
419
|
+
|
420
|
+
|
421
|
+
@overload
|
422
|
+
def reset_bounds(
|
423
|
+
target_var: QNum,
|
424
|
+
) -> None:
|
425
|
+
pass
|
426
|
+
|
427
|
+
|
428
|
+
@overload
|
429
|
+
def reset_bounds(
|
430
|
+
target_var: QNum,
|
431
|
+
lower_bound: Union[float, SymbolicExpr],
|
432
|
+
upper_bound: Union[float, SymbolicExpr],
|
433
|
+
) -> None:
|
434
|
+
pass
|
435
|
+
|
436
|
+
|
437
|
+
@suppress_return_value
|
438
|
+
def reset_bounds(
|
439
|
+
target_var: QNum,
|
440
|
+
lower_bound: Optional[Union[float, SymbolicExpr]] = None,
|
441
|
+
upper_bound: Optional[Union[float, SymbolicExpr]] = None,
|
442
|
+
) -> None:
|
443
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
444
|
+
source_ref = get_source_ref(sys._getframe(1))
|
445
|
+
|
446
|
+
lower_bound_expr = (
|
447
|
+
None if lower_bound is None else Expression(expr=str(lower_bound))
|
448
|
+
)
|
449
|
+
upper_bound_expr = (
|
450
|
+
None if upper_bound is None else Expression(expr=str(upper_bound))
|
451
|
+
)
|
452
|
+
|
453
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
454
|
+
SetBoundsStatement(
|
455
|
+
target=target_var.get_handle_binding(),
|
456
|
+
lower_bound=lower_bound_expr,
|
457
|
+
upper_bound=upper_bound_expr,
|
458
|
+
source_ref=source_ref,
|
459
|
+
)
|
460
|
+
)
|
461
|
+
|
462
|
+
|
401
463
|
def _validate_operand(stmt_block: Any, num_params: int = 0) -> None:
|
402
464
|
if stmt_block is None:
|
403
465
|
_raise_operand_error(
|
@@ -502,6 +564,7 @@ __all__ = [
|
|
502
564
|
"assign",
|
503
565
|
"assign_amplitude",
|
504
566
|
"bind",
|
567
|
+
"block",
|
505
568
|
"control",
|
506
569
|
"if_",
|
507
570
|
"inplace_add",
|
@@ -510,6 +573,7 @@ __all__ = [
|
|
510
573
|
"phase",
|
511
574
|
"power",
|
512
575
|
"repeat",
|
576
|
+
"reset_bounds",
|
513
577
|
"within_apply",
|
514
578
|
]
|
515
579
|
|