classiq 0.94.2__py3-none-any.whl → 0.96.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.
Potentially problematic release.
This version of classiq might be problematic. Click here for more details.
- classiq/_internals/api_wrapper.py +0 -83
- classiq/_internals/authentication/auth0.py +32 -3
- classiq/_internals/authentication/authorization_code.py +9 -0
- classiq/_internals/authentication/authorization_flow.py +41 -0
- classiq/_internals/authentication/device.py +31 -50
- classiq/_internals/authentication/hybrid_flow.py +19 -0
- classiq/_internals/authentication/token_manager.py +5 -4
- classiq/applications/__init__.py +2 -2
- classiq/applications/iqae/iqae.py +6 -3
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
- classiq/applications/qnn/qlayer.py +1 -1
- classiq/applications/qnn/torch_utils.py +2 -2
- classiq/applications/qsp/qsp.py +6 -5
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +10 -0
- classiq/execution/__init__.py +0 -3
- classiq/execution/user_budgets.py +0 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +11 -35
- classiq/interface/backend/quantum_backend_providers.py +0 -2
- classiq/interface/exceptions.py +0 -4
- classiq/interface/generator/application_apis/__init__.py +0 -1
- classiq/interface/generator/arith/register_user_input.py +1 -1
- classiq/interface/generator/function_param_list.py +0 -2
- classiq/interface/generator/generated_circuit_data.py +1 -6
- classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
- classiq/interface/generator/quantum_function_call.py +1 -1
- classiq/interface/generator/quantum_program.py +0 -4
- classiq/interface/generator/transpiler_basis_gates.py +3 -0
- classiq/interface/generator/types/builtin_enum_declarations.py +0 -9
- classiq/interface/hardware.py +0 -1
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/block.py +4 -0
- classiq/interface/model/classical_if.py +4 -0
- classiq/interface/model/control.py +7 -0
- classiq/interface/model/invert.py +4 -0
- classiq/interface/model/model_visitor.py +40 -1
- classiq/interface/model/power.py +4 -0
- classiq/interface/model/quantum_statement.py +8 -1
- classiq/interface/model/repeat.py +4 -0
- classiq/interface/model/skip_control.py +4 -0
- classiq/interface/model/within_apply_operation.py +4 -0
- classiq/interface/server/routes.py +0 -12
- classiq/model_expansions/generative_functions.py +6 -8
- classiq/model_expansions/interpreters/base_interpreter.py +1 -1
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
- classiq/model_expansions/visitors/symbolic_param_inference.py +3 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +14 -3
- classiq/open_library/functions/__init__.py +3 -2
- classiq/open_library/functions/amplitude_loading.py +85 -0
- classiq/open_library/functions/lcu.py +47 -18
- classiq/open_library/functions/modular_exponentiation.py +5 -8
- classiq/open_library/functions/qsvt.py +4 -4
- classiq/open_library/functions/state_preparation.py +7 -7
- classiq/qmod/builtins/classical_execution_primitives.py +0 -12
- classiq/qmod/builtins/enums.py +15 -17
- classiq/qmod/builtins/functions/__init__.py +5 -5
- classiq/qmod/builtins/functions/allocation.py +21 -0
- classiq/qmod/builtins/functions/mcx.py +7 -0
- classiq/qmod/builtins/operations.py +125 -23
- classiq/qmod/builtins/structs.py +22 -33
- classiq/qmod/semantics/annotation/call_annotation.py +3 -3
- classiq/qmod/semantics/error_manager.py +7 -8
- classiq/qmod/utilities.py +0 -10
- {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/METADATA +1 -1
- {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/RECORD +67 -71
- {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/WHEEL +1 -1
- classiq/applications/qsvm/__init__.py +0 -8
- classiq/applications/qsvm/qsvm.py +0 -11
- classiq/execution/iqcc.py +0 -128
- classiq/interface/applications/qsvm.py +0 -114
- classiq/interface/execution/iqcc.py +0 -42
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
- classiq/interface/generator/qsvm.py +0 -96
- classiq/open_library/functions/lookup_table.py +0 -58
- classiq/qmod/builtins/functions/qsvm.py +0 -24
- {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
import sys
|
|
3
3
|
from collections.abc import Callable, Mapping
|
|
4
|
+
from functools import wraps
|
|
5
|
+
from itertools import product
|
|
4
6
|
from types import FrameType
|
|
5
7
|
from typing import (
|
|
6
8
|
Any,
|
|
7
9
|
Final,
|
|
8
10
|
NoReturn,
|
|
11
|
+
ParamSpec,
|
|
12
|
+
TypeVar,
|
|
9
13
|
overload,
|
|
10
14
|
)
|
|
11
15
|
|
|
@@ -45,16 +49,37 @@ from classiq.interface.model.skip_control import SkipControl
|
|
|
45
49
|
from classiq.interface.model.statement_block import StatementBlock
|
|
46
50
|
from classiq.interface.model.within_apply_operation import WithinApply
|
|
47
51
|
|
|
52
|
+
from classiq.qmod.builtins.functions import H, S
|
|
48
53
|
from classiq.qmod.generative import is_generative_mode
|
|
49
54
|
from classiq.qmod.qmod_constant import QConstant
|
|
50
55
|
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QScalar, QVar
|
|
51
56
|
from classiq.qmod.quantum_callable import QCallable
|
|
52
57
|
from classiq.qmod.quantum_expandable import prepare_arg
|
|
58
|
+
from classiq.qmod.semantics.error_manager import ErrorManager
|
|
53
59
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
|
54
|
-
from classiq.qmod.utilities import
|
|
60
|
+
from classiq.qmod.utilities import (
|
|
61
|
+
RealFunction,
|
|
62
|
+
Statements,
|
|
63
|
+
get_source_ref,
|
|
64
|
+
qnum_values,
|
|
65
|
+
suppress_return_value,
|
|
66
|
+
)
|
|
55
67
|
|
|
56
68
|
_MISSING_VALUE: Final[int] = -1
|
|
57
69
|
|
|
70
|
+
_Params = ParamSpec("_Params")
|
|
71
|
+
_RetType = TypeVar("_RetType")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def qmod_statement(func: Callable[_Params, _RetType]) -> Callable[_Params, _RetType]:
|
|
75
|
+
@wraps(func)
|
|
76
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
77
|
+
source_ref = get_source_ref(sys._getframe(1))
|
|
78
|
+
with ErrorManager().source_ref_context(source_ref):
|
|
79
|
+
return func(*args, **kwargs)
|
|
80
|
+
|
|
81
|
+
return wrapper
|
|
82
|
+
|
|
58
83
|
|
|
59
84
|
@overload
|
|
60
85
|
def allocate(num_qubits: int | SymbolicExpr, out: Output[QVar]) -> None:
|
|
@@ -77,6 +102,7 @@ def allocate(
|
|
|
77
102
|
|
|
78
103
|
|
|
79
104
|
@suppress_return_value
|
|
105
|
+
@qmod_statement
|
|
80
106
|
def allocate(*args: Any, **kwargs: Any) -> None:
|
|
81
107
|
"""
|
|
82
108
|
Initialize a quantum variable to a new quantum object in the zero state:
|
|
@@ -100,29 +126,34 @@ def allocate(*args: Any, **kwargs: Any) -> None:
|
|
|
100
126
|
2. The synthesis engine automatically handles the allocation, either by drawing new qubits from the available pool or by reusing existing ones.
|
|
101
127
|
"""
|
|
102
128
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
103
|
-
source_ref = get_source_ref(sys._getframe(
|
|
129
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
104
130
|
if len(args) == 0:
|
|
105
131
|
size = kwargs.get("num_qubits", None)
|
|
106
132
|
is_signed = kwargs.get("is_signed", None)
|
|
107
133
|
fraction_digits = kwargs.get("fraction_digits", None)
|
|
108
|
-
|
|
134
|
+
out = kwargs["out"]
|
|
109
135
|
elif len(args) == 1:
|
|
110
136
|
if "out" in kwargs:
|
|
111
137
|
size = args[0]
|
|
112
138
|
is_signed = kwargs.get("is_signed", None)
|
|
113
139
|
fraction_digits = kwargs.get("fraction_digits", None)
|
|
114
|
-
|
|
140
|
+
out = kwargs["out"]
|
|
115
141
|
else:
|
|
116
142
|
size = None
|
|
117
143
|
is_signed = None
|
|
118
144
|
fraction_digits = None
|
|
119
|
-
|
|
145
|
+
out = args[0]
|
|
120
146
|
elif len(args) == 2:
|
|
121
|
-
size,
|
|
147
|
+
size, out = args
|
|
122
148
|
is_signed = kwargs.get("is_signed", None)
|
|
123
149
|
fraction_digits = kwargs.get("fraction_digits", None)
|
|
124
150
|
else:
|
|
125
|
-
size, is_signed, fraction_digits,
|
|
151
|
+
size, is_signed, fraction_digits, out = args
|
|
152
|
+
if not isinstance(out, QVar):
|
|
153
|
+
raise ClassiqValueError(
|
|
154
|
+
f"Argument 'out' of operator 'allocate' must be a quantum variable, got "
|
|
155
|
+
f"{type(out).__name__}"
|
|
156
|
+
)
|
|
126
157
|
if isinstance(size, QConstant):
|
|
127
158
|
size.add_to_model()
|
|
128
159
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
@@ -134,13 +165,14 @@ def allocate(*args: Any, **kwargs: Any) -> None:
|
|
|
134
165
|
if fraction_digits is None
|
|
135
166
|
else Expression(expr=str(fraction_digits))
|
|
136
167
|
),
|
|
137
|
-
target=
|
|
168
|
+
target=out.get_handle_binding(),
|
|
138
169
|
source_ref=source_ref,
|
|
139
170
|
)
|
|
140
171
|
)
|
|
141
172
|
|
|
142
173
|
|
|
143
174
|
@suppress_return_value
|
|
175
|
+
@qmod_statement
|
|
144
176
|
def bind(
|
|
145
177
|
source: Input[QVar] | list[Input[QVar]],
|
|
146
178
|
destination: Output[QVar] | list[Output[QVar]],
|
|
@@ -162,7 +194,7 @@ def bind(
|
|
|
162
194
|
For more details, see [Qmod Reference](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/bind).
|
|
163
195
|
"""
|
|
164
196
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
165
|
-
source_ref = get_source_ref(sys._getframe(
|
|
197
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
166
198
|
if not isinstance(source, list):
|
|
167
199
|
source = [source]
|
|
168
200
|
if not isinstance(destination, list):
|
|
@@ -177,6 +209,7 @@ def bind(
|
|
|
177
209
|
|
|
178
210
|
|
|
179
211
|
@suppress_return_value
|
|
212
|
+
@qmod_statement
|
|
180
213
|
def if_(
|
|
181
214
|
condition: SymbolicExpr | bool,
|
|
182
215
|
then: QCallable | Callable[[], Statements],
|
|
@@ -198,7 +231,7 @@ def if_(
|
|
|
198
231
|
if else_ != _MISSING_VALUE:
|
|
199
232
|
_validate_operand(else_)
|
|
200
233
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
201
|
-
source_ref = get_source_ref(sys._getframe(
|
|
234
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
202
235
|
|
|
203
236
|
if_stmt = ClassicalIf(
|
|
204
237
|
condition=Expression(expr=str(condition)),
|
|
@@ -214,6 +247,7 @@ def if_(
|
|
|
214
247
|
|
|
215
248
|
|
|
216
249
|
@suppress_return_value
|
|
250
|
+
@qmod_statement
|
|
217
251
|
def control(
|
|
218
252
|
ctrl: SymbolicExpr | QBit | QArray[QBit] | list[QVar],
|
|
219
253
|
stmt_block: QCallable | Callable[[], Statements],
|
|
@@ -237,7 +271,7 @@ def control(
|
|
|
237
271
|
"""
|
|
238
272
|
_validate_operand(stmt_block)
|
|
239
273
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
240
|
-
source_ref = get_source_ref(sys._getframe(
|
|
274
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
241
275
|
control_stmt = Control(
|
|
242
276
|
expression=Expression(expr=str(ctrl)),
|
|
243
277
|
body=_operand_to_body(stmt_block, "stmt_block"),
|
|
@@ -252,6 +286,7 @@ def control(
|
|
|
252
286
|
|
|
253
287
|
|
|
254
288
|
@suppress_return_value
|
|
289
|
+
@qmod_statement
|
|
255
290
|
def skip_control(stmt_block: QCallable | Callable[[], Statements]) -> None:
|
|
256
291
|
"""
|
|
257
292
|
Applies quantum statements unconditionally.
|
|
@@ -263,7 +298,7 @@ def skip_control(stmt_block: QCallable | Callable[[], Statements]) -> None:
|
|
|
263
298
|
"""
|
|
264
299
|
_validate_operand(stmt_block)
|
|
265
300
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
266
|
-
source_ref = get_source_ref(sys._getframe(
|
|
301
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
267
302
|
sc_stmt = SkipControl(
|
|
268
303
|
body=_operand_to_body(stmt_block, "stmt_block"),
|
|
269
304
|
source_ref=source_ref,
|
|
@@ -274,6 +309,7 @@ def skip_control(stmt_block: QCallable | Callable[[], Statements]) -> None:
|
|
|
274
309
|
|
|
275
310
|
|
|
276
311
|
@suppress_return_value
|
|
312
|
+
@qmod_statement
|
|
277
313
|
def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
278
314
|
"""
|
|
279
315
|
Initialize a scalar quantum variable using an arithmetic expression.
|
|
@@ -287,7 +323,7 @@ def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
287
323
|
target_var: An uninitialized scalar quantum variable
|
|
288
324
|
"""
|
|
289
325
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
290
|
-
source_ref = get_source_ref(sys._getframe(
|
|
326
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
291
327
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
292
328
|
ArithmeticOperation(
|
|
293
329
|
expression=Expression(expr=str(expression)),
|
|
@@ -299,6 +335,7 @@ def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
299
335
|
|
|
300
336
|
|
|
301
337
|
@suppress_return_value
|
|
338
|
+
@qmod_statement
|
|
302
339
|
def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
303
340
|
"""
|
|
304
341
|
Perform an amplitude-encoding assignment operation on a quantum variable and a
|
|
@@ -311,7 +348,7 @@ def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
311
348
|
target_var: A scalar quantum variable
|
|
312
349
|
"""
|
|
313
350
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
314
|
-
source_ref = get_source_ref(sys._getframe(
|
|
351
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
315
352
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
316
353
|
AmplitudeLoadingOperation(
|
|
317
354
|
expression=Expression(expr=str(expression)),
|
|
@@ -322,6 +359,7 @@ def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
322
359
|
|
|
323
360
|
|
|
324
361
|
@suppress_return_value
|
|
362
|
+
@qmod_statement
|
|
325
363
|
def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
326
364
|
"""
|
|
327
365
|
Add an arithmetic expression to a quantum variable.
|
|
@@ -333,7 +371,7 @@ def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
333
371
|
target_var: A scalar quantum variable
|
|
334
372
|
"""
|
|
335
373
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
336
|
-
source_ref = get_source_ref(sys._getframe(
|
|
374
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
337
375
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
338
376
|
ArithmeticOperation(
|
|
339
377
|
expression=Expression(expr=str(expression)),
|
|
@@ -345,6 +383,7 @@ def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
345
383
|
|
|
346
384
|
|
|
347
385
|
@suppress_return_value
|
|
386
|
+
@qmod_statement
|
|
348
387
|
def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
349
388
|
"""
|
|
350
389
|
Bitwise-XOR a quantum variable with an arithmetic expression.
|
|
@@ -356,7 +395,7 @@ def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
356
395
|
target_var: A scalar quantum variable
|
|
357
396
|
"""
|
|
358
397
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
359
|
-
source_ref = get_source_ref(sys._getframe(
|
|
398
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
360
399
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
361
400
|
ArithmeticOperation(
|
|
362
401
|
expression=Expression(expr=str(expression)),
|
|
@@ -368,6 +407,7 @@ def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
368
407
|
|
|
369
408
|
|
|
370
409
|
@suppress_return_value
|
|
410
|
+
@qmod_statement
|
|
371
411
|
def within_apply(
|
|
372
412
|
within: Callable[[], Statements],
|
|
373
413
|
apply: Callable[[], Statements],
|
|
@@ -387,7 +427,7 @@ def within_apply(
|
|
|
387
427
|
_validate_operand(within)
|
|
388
428
|
_validate_operand(apply)
|
|
389
429
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
390
|
-
source_ref = get_source_ref(sys._getframe(
|
|
430
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
391
431
|
within_apply_stmt = WithinApply(
|
|
392
432
|
compute=_operand_to_body(within, "within"),
|
|
393
433
|
action=_operand_to_body(apply, "apply"),
|
|
@@ -400,6 +440,7 @@ def within_apply(
|
|
|
400
440
|
|
|
401
441
|
|
|
402
442
|
@suppress_return_value
|
|
443
|
+
@qmod_statement
|
|
403
444
|
def repeat(count: SymbolicExpr | int, iteration: Callable[[int], Statements]) -> None:
|
|
404
445
|
"""
|
|
405
446
|
Executes a quantum loop a specified number of times, applying a quantum operation on each iteration.
|
|
@@ -426,7 +467,7 @@ def repeat(count: SymbolicExpr | int, iteration: Callable[[int], Statements]) ->
|
|
|
426
467
|
"""
|
|
427
468
|
_validate_operand(iteration, num_params=1)
|
|
428
469
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
429
|
-
source_ref = get_source_ref(sys._getframe(
|
|
470
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
430
471
|
iteration_operand = prepare_arg(
|
|
431
472
|
QuantumOperandDeclaration(
|
|
432
473
|
name=REPEAT_OPERATOR_NAME,
|
|
@@ -455,6 +496,7 @@ def repeat(count: SymbolicExpr | int, iteration: Callable[[int], Statements]) ->
|
|
|
455
496
|
|
|
456
497
|
|
|
457
498
|
@suppress_return_value
|
|
499
|
+
@qmod_statement
|
|
458
500
|
def power(
|
|
459
501
|
exponent: SymbolicExpr | int,
|
|
460
502
|
stmt_block: QCallable | Callable[[], Statements],
|
|
@@ -489,7 +531,7 @@ def power(
|
|
|
489
531
|
"""
|
|
490
532
|
_validate_operand(stmt_block)
|
|
491
533
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
492
|
-
source_ref = get_source_ref(sys._getframe(
|
|
534
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
493
535
|
power_stmt = Power(
|
|
494
536
|
power=Expression(expr=str(exponent)),
|
|
495
537
|
body=_operand_to_body(stmt_block, "stmt_block"),
|
|
@@ -501,6 +543,7 @@ def power(
|
|
|
501
543
|
|
|
502
544
|
|
|
503
545
|
@suppress_return_value
|
|
546
|
+
@qmod_statement
|
|
504
547
|
def invert(stmt_block: QCallable | Callable[[], Statements]) -> None:
|
|
505
548
|
"""
|
|
506
549
|
Apply the inverse of a quantum gate.
|
|
@@ -525,7 +568,7 @@ def invert(stmt_block: QCallable | Callable[[], Statements]) -> None:
|
|
|
525
568
|
"""
|
|
526
569
|
_validate_operand(stmt_block)
|
|
527
570
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
528
|
-
source_ref = get_source_ref(sys._getframe(
|
|
571
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
529
572
|
invert_stmt = Invert(
|
|
530
573
|
body=_operand_to_body(stmt_block, "stmt_block"), source_ref=source_ref
|
|
531
574
|
)
|
|
@@ -535,6 +578,7 @@ def invert(stmt_block: QCallable | Callable[[], Statements]) -> None:
|
|
|
535
578
|
|
|
536
579
|
|
|
537
580
|
@suppress_return_value
|
|
581
|
+
@qmod_statement
|
|
538
582
|
def phase(
|
|
539
583
|
phase_expr: SymbolicExpr | float | None = None,
|
|
540
584
|
theta: SymbolicExpr | float = 1.0,
|
|
@@ -557,7 +601,7 @@ def phase(
|
|
|
557
601
|
they are equivalent when the phase_expr is a single-qubit variable.
|
|
558
602
|
"""
|
|
559
603
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
560
|
-
source_ref = get_source_ref(sys._getframe(
|
|
604
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
561
605
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
562
606
|
PhaseOperation(
|
|
563
607
|
expression=Expression(expr=str(phase_expr)),
|
|
@@ -568,12 +612,13 @@ def phase(
|
|
|
568
612
|
|
|
569
613
|
|
|
570
614
|
@suppress_return_value
|
|
615
|
+
@qmod_statement
|
|
571
616
|
def block(
|
|
572
617
|
statements: QCallable | Callable[[], Statements],
|
|
573
618
|
) -> None:
|
|
574
619
|
_validate_operand(statements)
|
|
575
620
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
576
|
-
source_ref = get_source_ref(sys._getframe(
|
|
621
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
577
622
|
|
|
578
623
|
block_stmt = Block(
|
|
579
624
|
statements=_operand_to_body(statements, "statements"),
|
|
@@ -601,13 +646,14 @@ def reset_bounds(
|
|
|
601
646
|
|
|
602
647
|
|
|
603
648
|
@suppress_return_value
|
|
649
|
+
@qmod_statement
|
|
604
650
|
def reset_bounds(
|
|
605
651
|
target_var: QNum,
|
|
606
652
|
lower_bound: float | SymbolicExpr | None = None,
|
|
607
653
|
upper_bound: float | SymbolicExpr | None = None,
|
|
608
654
|
) -> None:
|
|
609
655
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
610
|
-
source_ref = get_source_ref(sys._getframe(
|
|
656
|
+
source_ref = get_source_ref(sys._getframe(2))
|
|
611
657
|
|
|
612
658
|
lower_bound_expr = (
|
|
613
659
|
None if lower_bound is None else Expression(expr=str(lower_bound))
|
|
@@ -733,10 +779,65 @@ def _operand_to_body(
|
|
|
733
779
|
raise ValueError(f"Unexpected operand type: {type(to_operand)}")
|
|
734
780
|
|
|
735
781
|
|
|
782
|
+
def assign_amplitude_poly_sin(indicator: QBit, expr: Callable, *vars: QNum) -> None:
|
|
783
|
+
"""
|
|
784
|
+
Encodes the value of the sine/cosine of a polynomial into the amplitude of the
|
|
785
|
+
respective computational basis state:
|
|
786
|
+
\\( |x_1, x_2, \\ldots, x_n\\rangle|0\\rangle \\rightarrow cos(poly(x_1, x_2, \\ldots, x_n)) + sin(poly(x_1, x_2, \\ldots, x_n))|x_1, x_2, \\ldots, x_n\\rangle|1\\rangle \\)
|
|
787
|
+
|
|
788
|
+
Args:
|
|
789
|
+
indicator: The quantum indicator qubit
|
|
790
|
+
expr: A polynomial function over `len(vars)` QNums
|
|
791
|
+
*vars: Quantum numerics
|
|
792
|
+
"""
|
|
793
|
+
phase(-expr(*vars))
|
|
794
|
+
within_apply(
|
|
795
|
+
lambda: H(indicator),
|
|
796
|
+
lambda: control(indicator, lambda: phase(2 * expr(*vars))),
|
|
797
|
+
)
|
|
798
|
+
S(indicator)
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
def _get_qnum_values(num: QNum) -> list[float]:
|
|
802
|
+
size = num.size
|
|
803
|
+
is_signed = num.is_signed
|
|
804
|
+
fraction_digits = num.fraction_digits
|
|
805
|
+
if (
|
|
806
|
+
not isinstance(size, int)
|
|
807
|
+
or not isinstance(is_signed, bool)
|
|
808
|
+
or not isinstance(fraction_digits, int)
|
|
809
|
+
):
|
|
810
|
+
raise ClassiqValueError(f"QNum argument {str(num)!r} has symbolic attributes")
|
|
811
|
+
|
|
812
|
+
return qnum_values(size, is_signed, fraction_digits)
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
def lookup_table(func: RealFunction, targets: QNum | list[QNum]) -> list[float]:
|
|
816
|
+
"""
|
|
817
|
+
Reduces a classical function into a lookup table over all the possible values
|
|
818
|
+
of the quantum numbers.
|
|
819
|
+
|
|
820
|
+
Args:
|
|
821
|
+
func: A Python function
|
|
822
|
+
targets: One or more initialized quantum numbers
|
|
823
|
+
|
|
824
|
+
Returns:
|
|
825
|
+
The function's lookup table
|
|
826
|
+
|
|
827
|
+
Notes:
|
|
828
|
+
The QNum arguments must have generative attributes
|
|
829
|
+
"""
|
|
830
|
+
if not isinstance(targets, list):
|
|
831
|
+
targets = [targets]
|
|
832
|
+
target_vals = [_get_qnum_values(target) for target in targets]
|
|
833
|
+
return [func(*vals[::-1]) for vals in product(*target_vals[::-1])]
|
|
834
|
+
|
|
835
|
+
|
|
736
836
|
__all__ = [
|
|
737
837
|
"allocate",
|
|
738
838
|
"assign",
|
|
739
839
|
"assign_amplitude",
|
|
840
|
+
"assign_amplitude_poly_sin",
|
|
740
841
|
"bind",
|
|
741
842
|
"block",
|
|
742
843
|
"control",
|
|
@@ -744,6 +845,7 @@ __all__ = [
|
|
|
744
845
|
"inplace_add",
|
|
745
846
|
"inplace_xor",
|
|
746
847
|
"invert",
|
|
848
|
+
"lookup_table",
|
|
747
849
|
"phase",
|
|
748
850
|
"power",
|
|
749
851
|
"repeat",
|
classiq/qmod/builtins/structs.py
CHANGED
|
@@ -3,6 +3,7 @@ from typing import Union
|
|
|
3
3
|
|
|
4
4
|
from classiq.interface.exceptions import ClassiqValueError
|
|
5
5
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
|
6
|
+
from classiq.interface.helpers.datastructures import LenList
|
|
6
7
|
from classiq.interface.helpers.text_utils import are, readable_list, s
|
|
7
8
|
|
|
8
9
|
from classiq.qmod.builtins.enums import Pauli
|
|
@@ -69,13 +70,15 @@ class SparsePauliOp:
|
|
|
69
70
|
def __mul__(self, obj: Union[float, "SparsePauliOp"]) -> "SparsePauliOp":
|
|
70
71
|
if isinstance(obj, (int, float, complex)):
|
|
71
72
|
return SparsePauliOp(
|
|
72
|
-
terms=
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
terms=LenList(
|
|
74
|
+
[
|
|
75
|
+
SparsePauliTerm(
|
|
76
|
+
paulis=term.paulis,
|
|
77
|
+
coefficient=obj * term.coefficient, # type:ignore[arg-type]
|
|
78
|
+
)
|
|
79
|
+
for term in self.terms
|
|
80
|
+
]
|
|
81
|
+
),
|
|
79
82
|
num_qubits=self.num_qubits,
|
|
80
83
|
)
|
|
81
84
|
if len(self.terms) != 1 or len(obj.terms) != 1:
|
|
@@ -97,14 +100,17 @@ class SparsePauliOp:
|
|
|
97
100
|
f"already assigned"
|
|
98
101
|
)
|
|
99
102
|
return SparsePauliOp(
|
|
100
|
-
terms=
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
terms=LenList(
|
|
104
|
+
[
|
|
105
|
+
SparsePauliTerm(
|
|
106
|
+
paulis=LenList( # type:ignore[call-overload]
|
|
107
|
+
self.terms[0].paulis + obj.terms[0].paulis
|
|
108
|
+
),
|
|
109
|
+
coefficient=self.terms[0].coefficient
|
|
110
|
+
* obj.terms[0].coefficient, # type:ignore[arg-type]
|
|
111
|
+
)
|
|
112
|
+
]
|
|
113
|
+
),
|
|
108
114
|
num_qubits=max(self.num_qubits, obj.num_qubits),
|
|
109
115
|
)
|
|
110
116
|
|
|
@@ -113,7 +119,7 @@ class SparsePauliOp:
|
|
|
113
119
|
|
|
114
120
|
def __add__(self, other: "SparsePauliOp") -> "SparsePauliOp":
|
|
115
121
|
return SparsePauliOp(
|
|
116
|
-
terms=self.terms + other.terms,
|
|
122
|
+
terms=LenList(self.terms + other.terms),
|
|
117
123
|
num_qubits=max(self.num_qubits, other.num_qubits),
|
|
118
124
|
)
|
|
119
125
|
|
|
@@ -156,21 +162,6 @@ class LogNormalModel:
|
|
|
156
162
|
sigma: CReal
|
|
157
163
|
|
|
158
164
|
|
|
159
|
-
@dataclass
|
|
160
|
-
class QsvmResult:
|
|
161
|
-
test_score: CReal
|
|
162
|
-
predicted_labels: CArray[CReal]
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
@dataclass
|
|
166
|
-
class QSVMFeatureMapPauli:
|
|
167
|
-
feature_dimension: CInt
|
|
168
|
-
reps: CInt
|
|
169
|
-
entanglement: CInt
|
|
170
|
-
alpha: CReal
|
|
171
|
-
paulis: CArray[CArray[Pauli]]
|
|
172
|
-
|
|
173
|
-
|
|
174
165
|
BUILTIN_STRUCT_DECLARATIONS = {
|
|
175
166
|
struct_decl.__name__: StructDeclaration(
|
|
176
167
|
name=struct_decl.__name__,
|
|
@@ -190,8 +181,6 @@ __all__ = [
|
|
|
190
181
|
"IndexedPauli",
|
|
191
182
|
"LogNormalModel",
|
|
192
183
|
"PauliTerm",
|
|
193
|
-
"QSVMFeatureMapPauli",
|
|
194
|
-
"QsvmResult",
|
|
195
184
|
"SparsePauliOp",
|
|
196
185
|
"SparsePauliTerm",
|
|
197
186
|
]
|
|
@@ -4,7 +4,7 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
from classiq.interface.exceptions import ClassiqError
|
|
6
6
|
from classiq.interface.model.model import Model
|
|
7
|
-
from classiq.interface.model.model_visitor import
|
|
7
|
+
from classiq.interface.model.model_visitor import ModelStatementsVisitor
|
|
8
8
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
9
9
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
10
10
|
from classiq.interface.model.quantum_function_declaration import (
|
|
@@ -47,7 +47,7 @@ def _annotate_function_call_decl(
|
|
|
47
47
|
qlambda.set_op_decl(param)
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
class _CallLambdaAnnotator(
|
|
50
|
+
class _CallLambdaAnnotator(ModelStatementsVisitor):
|
|
51
51
|
def __init__(
|
|
52
52
|
self, quantum_functions: Mapping[str, QuantumFunctionDeclaration]
|
|
53
53
|
) -> None:
|
|
@@ -76,7 +76,7 @@ class _CallLambdaAnnotator(ModelVisitor):
|
|
|
76
76
|
_annotate_function_call_decl(
|
|
77
77
|
call, self._quantum_functions | self._current_operands
|
|
78
78
|
)
|
|
79
|
-
self.
|
|
79
|
+
self.visit(call.positional_args)
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
def resolve_function_calls(
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from collections.abc import Iterator
|
|
2
2
|
from contextlib import contextmanager
|
|
3
3
|
|
|
4
|
-
from classiq.interface.ast_node import ASTNode
|
|
5
4
|
from classiq.interface.exceptions import CLASSIQ_SLACK_COMMUNITY_LINK
|
|
6
5
|
from classiq.interface.source_reference import SourceReference, SourceReferencedError
|
|
7
6
|
|
|
@@ -18,14 +17,14 @@ class ErrorManager:
|
|
|
18
17
|
self._instantiated = True
|
|
19
18
|
self._errors: list[SourceReferencedError] = []
|
|
20
19
|
self._warnings: list[SourceReferencedError] = []
|
|
21
|
-
self.
|
|
20
|
+
self._current_refs_stack: list[SourceReference | None] = []
|
|
22
21
|
self._call_stack: list[str] = []
|
|
23
22
|
self._ignore_errors: bool = False
|
|
24
23
|
|
|
25
24
|
@property
|
|
26
25
|
def _current_source_ref(self) -> SourceReference | None:
|
|
27
|
-
if self.
|
|
28
|
-
return self.
|
|
26
|
+
if self._current_refs_stack:
|
|
27
|
+
return self._current_refs_stack[-1]
|
|
29
28
|
return None
|
|
30
29
|
|
|
31
30
|
@contextmanager
|
|
@@ -79,7 +78,7 @@ class ErrorManager:
|
|
|
79
78
|
self.clear_warnings()
|
|
80
79
|
|
|
81
80
|
def clear_errors(self) -> None:
|
|
82
|
-
self.
|
|
81
|
+
self._current_refs_stack = []
|
|
83
82
|
self._errors = []
|
|
84
83
|
|
|
85
84
|
def clear_warnings(self) -> None:
|
|
@@ -108,10 +107,10 @@ class ErrorManager:
|
|
|
108
107
|
return self._call_stack[-1] if self._call_stack else None
|
|
109
108
|
|
|
110
109
|
@contextmanager
|
|
111
|
-
def
|
|
112
|
-
self.
|
|
110
|
+
def source_ref_context(self, ref: SourceReference | None) -> Iterator[None]:
|
|
111
|
+
self._current_refs_stack.append(ref)
|
|
113
112
|
yield
|
|
114
|
-
self.
|
|
113
|
+
self._current_refs_stack.pop()
|
|
115
114
|
|
|
116
115
|
@contextmanager
|
|
117
116
|
def call(self, func_name: str) -> Iterator[None]:
|
classiq/qmod/utilities.py
CHANGED
|
@@ -3,7 +3,6 @@ import inspect
|
|
|
3
3
|
import itertools
|
|
4
4
|
import keyword
|
|
5
5
|
import sys
|
|
6
|
-
from collections import Counter
|
|
7
6
|
from collections.abc import Callable, Iterable
|
|
8
7
|
from enum import Enum as PythonEnum
|
|
9
8
|
from types import FrameType
|
|
@@ -195,13 +194,4 @@ def qnum_attributes(max_size: int) -> list[tuple[int, bool, int]]:
|
|
|
195
194
|
]
|
|
196
195
|
|
|
197
196
|
|
|
198
|
-
_VAR_NAME_COUNTER: Counter[str] = Counter()
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
def get_temp_var_name(var_name: str = "temp") -> str:
|
|
202
|
-
n = _VAR_NAME_COUNTER[var_name]
|
|
203
|
-
_VAR_NAME_COUNTER[var_name] += 1
|
|
204
|
-
return f"{var_name}_{n}"
|
|
205
|
-
|
|
206
|
-
|
|
207
197
|
RealFunction = Callable[Params, float]
|