classiq 0.68.0__py3-none-any.whl → 0.69.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 +4 -8
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +8 -11
- classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
- classiq/applications/qnn/torch_utils.py +1 -1
- classiq/execution/jobs.py +2 -5
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +2 -3
- classiq/interface/chemistry/operator.py +11 -7
- classiq/interface/debug_info/back_ref_util.py +22 -0
- classiq/interface/debug_info/debug_info.py +11 -21
- classiq/interface/executor/optimizer_preferences.py +1 -0
- classiq/interface/generator/arith/arithmetic_param_getters.py +3 -3
- classiq/interface/generator/functions/classical_type.py +12 -1
- classiq/interface/generator/generated_circuit_data.py +63 -24
- classiq/interface/generator/types/builtin_enum_declarations.py +1 -0
- classiq/interface/generator/types/enum_declaration.py +12 -1
- classiq/interface/ide/visual_model.py +0 -2
- classiq/interface/model/quantum_statement.py +1 -1
- classiq/interface/server/routes.py +0 -6
- classiq/model_expansions/generative_functions.py +4 -3
- classiq/model_expansions/quantum_operations/call_emitter.py +0 -13
- classiq/model_expansions/scope_initialization.py +5 -19
- classiq/open_library/functions/amplitude_amplification.py +3 -7
- classiq/open_library/functions/discrete_sine_cosine_transform.py +4 -4
- classiq/open_library/functions/grover.py +2 -2
- classiq/open_library/functions/hea.py +3 -3
- classiq/open_library/functions/modular_exponentiation.py +10 -20
- classiq/open_library/functions/qft_functions.py +2 -2
- classiq/open_library/functions/qsvt.py +8 -8
- classiq/open_library/functions/utility_functions.py +2 -2
- classiq/qmod/builtins/classical_functions.py +24 -7
- classiq/qmod/builtins/enums.py +1 -0
- classiq/qmod/builtins/functions/__init__.py +2 -0
- classiq/qmod/builtins/functions/exponentiation.py +24 -0
- classiq/qmod/builtins/operations.py +26 -11
- classiq/qmod/cparam.py +32 -5
- classiq/qmod/python_classical_type.py +10 -4
- classiq/qmod/quantum_callable.py +2 -1
- classiq/qmod/quantum_function.py +3 -2
- classiq/qmod/semantics/error_manager.py +1 -1
- classiq/qmod/utilities.py +29 -1
- classiq/synthesis.py +9 -6
- {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/METADATA +1 -1
- {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/RECORD +46 -46
- classiq/interface/execution/jobs.py +0 -31
- {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/WHEEL +0 -0
@@ -3,10 +3,6 @@ from typing import Any
|
|
3
3
|
|
4
4
|
from classiq.interface.exceptions import ClassiqError
|
5
5
|
from classiq.interface.generator.constant import Constant
|
6
|
-
from classiq.interface.generator.expressions.expression_constants import (
|
7
|
-
CPARAM_EXECUTION_SUFFIX,
|
8
|
-
RESERVED_EXPRESSIONS,
|
9
|
-
)
|
10
6
|
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
11
7
|
from classiq.interface.model.handle_binding import HandleBinding
|
12
8
|
from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model
|
@@ -129,12 +125,6 @@ def init_builtin_types() -> None:
|
|
129
125
|
QMODULE.type_decls |= BUILTIN_STRUCT_DECLARATIONS
|
130
126
|
|
131
127
|
|
132
|
-
def _rename_exec_param(param_name: str) -> str:
|
133
|
-
if param_name in RESERVED_EXPRESSIONS:
|
134
|
-
return param_name
|
135
|
-
return param_name + CPARAM_EXECUTION_SUFFIX
|
136
|
-
|
137
|
-
|
138
128
|
def _add_exec_param_parts_to_scope(param_val: Any, scope: Scope) -> None:
|
139
129
|
if not isinstance(param_val, list):
|
140
130
|
scope[str(param_val)] = Evaluated(value=param_val)
|
@@ -145,21 +135,17 @@ def _add_exec_param_parts_to_scope(param_val: Any, scope: Scope) -> None:
|
|
145
135
|
|
146
136
|
def init_exec_params(model: Model, scope: Scope) -> dict[str, ConcreteClassicalType]:
|
147
137
|
if model.execution_parameters is not None:
|
148
|
-
exec_params =
|
149
|
-
param_name: (param_name, param_type)
|
150
|
-
for param_name, param_type in model.execution_parameters.items()
|
151
|
-
}
|
138
|
+
exec_params = model.execution_parameters
|
152
139
|
else:
|
153
140
|
exec_params = {
|
154
|
-
param.name:
|
141
|
+
param.name: param.classical_type
|
155
142
|
for param in model.function_dict.get(
|
156
143
|
"_dec_main", model.main_func
|
157
144
|
).param_decls
|
158
145
|
}
|
159
|
-
for param_name,
|
160
|
-
param_val = param_type.as_symbolic(
|
146
|
+
for param_name, param_type in exec_params.items():
|
147
|
+
param_val = param_type.as_symbolic(param_name)
|
161
148
|
scope[param_name] = Evaluated(value=param_val)
|
162
|
-
scope[param_rename] = Evaluated(value=param_val)
|
163
149
|
if isinstance(param_val, list):
|
164
150
|
_add_exec_param_parts_to_scope(param_val, scope)
|
165
|
-
return
|
151
|
+
return exec_params
|
@@ -73,11 +73,9 @@ def exact_amplitude_amplification(
|
|
73
73
|
|
74
74
|
extended_qvars: QArray = QArray()
|
75
75
|
within_apply(
|
76
|
-
lambda: [
|
76
|
+
lambda: [
|
77
77
|
allocate(aux),
|
78
|
-
bind(
|
79
|
-
[aux, packed_qvars], extended_qvars
|
80
|
-
), # type:ignore[func-returns-value]
|
78
|
+
bind([aux, packed_qvars], extended_qvars),
|
81
79
|
],
|
82
80
|
lambda: amplitude_amplification(
|
83
81
|
k,
|
@@ -85,9 +83,7 @@ def exact_amplitude_amplification(
|
|
85
83
|
qvars_[0] == 0, lambda: oracle(qvars_[1 : qvars_.size])
|
86
84
|
),
|
87
85
|
lambda qvars_: [
|
88
|
-
space_transform(
|
89
|
-
qvars_[1 : qvars_.size]
|
90
|
-
),
|
86
|
+
space_transform(qvars_[1 : qvars_.size]),
|
91
87
|
RY(rot_phase, qvars_[0]),
|
92
88
|
],
|
93
89
|
extended_qvars,
|
@@ -30,9 +30,9 @@ def _qct_d_operator(x: QNum, q: QBit) -> None:
|
|
30
30
|
def _qct_pi_operator(x: QArray[QBit], q: QBit) -> None:
|
31
31
|
control(
|
32
32
|
q == 1,
|
33
|
-
lambda: [
|
33
|
+
lambda: [
|
34
34
|
apply_to_all(X, x),
|
35
|
-
inplace_add(1, x), # type:ignore[arg-type
|
35
|
+
inplace_add(1, x), # type:ignore[arg-type]
|
36
36
|
],
|
37
37
|
)
|
38
38
|
|
@@ -70,7 +70,7 @@ def _pi2_operator(x: QArray[QBit], q: QBit) -> None:
|
|
70
70
|
|
71
71
|
|
72
72
|
def _j_operator(q: QBit) -> None:
|
73
|
-
within_apply(lambda: Z(q), lambda: (S(q), H(q), S(q)))
|
73
|
+
within_apply(lambda: Z(q), lambda: (S(q), H(q), S(q)))
|
74
74
|
|
75
75
|
|
76
76
|
def _b_t_operator(q: QBit) -> None:
|
@@ -179,6 +179,6 @@ def qst_type2(x: QArray[QBit]) -> None:
|
|
179
179
|
"""
|
180
180
|
q = QBit()
|
181
181
|
within_apply(
|
182
|
-
lambda: (allocate(q), X(q)),
|
182
|
+
lambda: (allocate(q), X(q)),
|
183
183
|
lambda: qct_qst_type2(x, q),
|
184
184
|
)
|
@@ -42,7 +42,7 @@ def phase_oracle(
|
|
42
42
|
"""
|
43
43
|
aux = QBit()
|
44
44
|
within_apply(
|
45
|
-
within=lambda: (allocate(aux), X(aux), H(aux)),
|
45
|
+
within=lambda: (allocate(aux), X(aux), H(aux)),
|
46
46
|
apply=lambda: predicate(target, aux),
|
47
47
|
)
|
48
48
|
|
@@ -68,7 +68,7 @@ def reflect_about_zero(packed_vars: QArray[QBit]) -> None:
|
|
68
68
|
lsb = QBit()
|
69
69
|
bind(packed_vars, [msbs, lsb])
|
70
70
|
within_apply(
|
71
|
-
lambda: (X(lsb), H(lsb)),
|
71
|
+
lambda: (X(lsb), H(lsb)),
|
72
72
|
lambda: control(msbs == 0, lambda: X(lsb)),
|
73
73
|
)
|
74
74
|
bind([msbs, lsb], packed_vars)
|
@@ -58,8 +58,8 @@ def full_hea(
|
|
58
58
|
"""
|
59
59
|
repeat(
|
60
60
|
reps,
|
61
|
-
lambda r: [
|
62
|
-
repeat(
|
61
|
+
lambda r: [
|
62
|
+
repeat(
|
63
63
|
operands_1qubit.len,
|
64
64
|
lambda i1: repeat(
|
65
65
|
num_qubits,
|
@@ -77,7 +77,7 @@ def full_hea(
|
|
77
77
|
),
|
78
78
|
),
|
79
79
|
),
|
80
|
-
repeat(
|
80
|
+
repeat(
|
81
81
|
operands_2qubit.len,
|
82
82
|
lambda i2: repeat(
|
83
83
|
connectivity_map.len,
|
@@ -70,23 +70,17 @@ def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) ->
|
|
70
70
|
aux = QBit()
|
71
71
|
|
72
72
|
within_apply(
|
73
|
-
lambda: (
|
73
|
+
lambda: (
|
74
74
|
allocate(aux),
|
75
|
-
bind([c1, c2], ctrl),
|
75
|
+
bind([c1, c2], ctrl),
|
76
76
|
),
|
77
|
-
lambda: (
|
78
|
-
control(
|
79
|
-
|
80
|
-
),
|
81
|
-
invert( # type:ignore[func-returns-value]
|
82
|
-
lambda: qft_space_add_const(n, phi_b)
|
83
|
-
),
|
77
|
+
lambda: (
|
78
|
+
control(ctrl, lambda: qft_space_add_const(a, phi_b)),
|
79
|
+
invert(lambda: qft_space_add_const(n, phi_b)),
|
84
80
|
_check_msb(1, phi_b, aux),
|
85
|
-
control(
|
86
|
-
aux, lambda: qft_space_add_const(n, phi_b)
|
87
|
-
),
|
81
|
+
control(aux, lambda: qft_space_add_const(n, phi_b)),
|
88
82
|
within_apply(
|
89
|
-
lambda: invert(
|
83
|
+
lambda: invert(
|
90
84
|
lambda: control(ctrl, lambda: qft_space_add_const(a, phi_b))
|
91
85
|
),
|
92
86
|
lambda: _check_msb(0, phi_b, aux),
|
@@ -160,14 +154,10 @@ def inplace_c_modular_multiply(n: CInt, a: CInt, x: QArray[QBit], ctrl: QBit) ->
|
|
160
154
|
|
161
155
|
within_apply(
|
162
156
|
lambda: allocate(x.len + 1, b),
|
163
|
-
lambda: (
|
157
|
+
lambda: (
|
164
158
|
c_modular_multiply(n, a, b, x, ctrl),
|
165
|
-
control(
|
166
|
-
|
167
|
-
),
|
168
|
-
invert( # type:ignore[func-returns-value]
|
169
|
-
lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl)
|
170
|
-
),
|
159
|
+
control(ctrl, lambda: multiswap(x, b)),
|
160
|
+
invert(lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl)),
|
171
161
|
),
|
172
162
|
)
|
173
163
|
|
@@ -18,9 +18,9 @@ def qft_no_swap(qbv: QArray[QBit]) -> None:
|
|
18
18
|
"""
|
19
19
|
repeat(
|
20
20
|
qbv.len,
|
21
|
-
lambda i: (
|
21
|
+
lambda i: (
|
22
22
|
H(qbv[i]),
|
23
|
-
repeat(
|
23
|
+
repeat(
|
24
24
|
qbv.len - i - 1,
|
25
25
|
lambda j: CPHASE(
|
26
26
|
theta=pi / (2 ** (j + 1)),
|
@@ -97,8 +97,8 @@ def qsvt(
|
|
97
97
|
if_(
|
98
98
|
condition=phase_seq.len % 2 == 1,
|
99
99
|
then=lambda: IDENTITY(qvar),
|
100
|
-
else_=lambda: (
|
101
|
-
u(qvar),
|
100
|
+
else_=lambda: (
|
101
|
+
u(qvar),
|
102
102
|
projector_controlled_phase(
|
103
103
|
phase_seq[phase_seq.len - 1],
|
104
104
|
proj_cnot_2,
|
@@ -297,8 +297,8 @@ def qsvt_lcu(
|
|
297
297
|
condition=phase_seq_odd.len > phase_seq_even.len,
|
298
298
|
then=lambda: control(
|
299
299
|
lcu == 0,
|
300
|
-
lambda: [
|
301
|
-
u(qvar),
|
300
|
+
lambda: [
|
301
|
+
u(qvar),
|
302
302
|
projector_controlled_phase(
|
303
303
|
phase_seq_odd[phase_seq_odd.len - 1], proj_cnot_2, qvar, aux
|
304
304
|
),
|
@@ -307,8 +307,8 @@ def qsvt_lcu(
|
|
307
307
|
)
|
308
308
|
if_(
|
309
309
|
condition=phase_seq_odd.len < phase_seq_even.len,
|
310
|
-
then=lambda: (
|
311
|
-
u(qvar),
|
310
|
+
then=lambda: (
|
311
|
+
u(qvar),
|
312
312
|
projector_controlled_double_phase(
|
313
313
|
phase_seq_even[phase_seq_even.len - 1],
|
314
314
|
phase_seq_odd[phase_seq_odd.len - 1],
|
@@ -319,8 +319,8 @@ def qsvt_lcu(
|
|
319
319
|
),
|
320
320
|
control(
|
321
321
|
lcu,
|
322
|
-
lambda: [
|
323
|
-
invert(lambda: u(qvar)),
|
322
|
+
lambda: [
|
323
|
+
invert(lambda: u(qvar)),
|
324
324
|
projector_controlled_phase(
|
325
325
|
phase_seq_even[phase_seq_even.len - 1], proj_cnot_1, qvar, aux
|
326
326
|
),
|
@@ -79,8 +79,8 @@ def modular_increment(a: CInt, x: QNum) -> None:
|
|
79
79
|
)
|
80
80
|
array_cast: QArray = QArray()
|
81
81
|
within_apply(
|
82
|
-
lambda: (
|
83
|
-
bind(x, array_cast),
|
82
|
+
lambda: (
|
83
|
+
bind(x, array_cast),
|
84
84
|
qft(array_cast),
|
85
85
|
),
|
86
86
|
lambda: repeat(
|
@@ -12,19 +12,25 @@ def qft_const_adder_phase(
|
|
12
12
|
value: CInt,
|
13
13
|
reg_len: CInt,
|
14
14
|
) -> CReal:
|
15
|
-
return symbolic_function(
|
15
|
+
return symbolic_function(
|
16
|
+
bit_index, value, reg_len, return_type=CReal # type:ignore[type-abstract]
|
17
|
+
)
|
16
18
|
|
17
19
|
|
18
20
|
def fock_hamiltonian_problem_to_hamiltonian(
|
19
21
|
problem: FockHamiltonianProblem,
|
20
22
|
) -> CArray[PauliTerm]:
|
21
|
-
return symbolic_function(
|
23
|
+
return symbolic_function(
|
24
|
+
problem, return_type=CArray[PauliTerm] # type:ignore[type-abstract]
|
25
|
+
)
|
22
26
|
|
23
27
|
|
24
28
|
def molecule_problem_to_hamiltonian(
|
25
29
|
problem: MoleculeProblem,
|
26
30
|
) -> CArray[PauliTerm]:
|
27
|
-
return symbolic_function(
|
31
|
+
return symbolic_function(
|
32
|
+
problem, return_type=CArray[PauliTerm] # type:ignore[type-abstract]
|
33
|
+
)
|
28
34
|
|
29
35
|
|
30
36
|
def grid_entangler_graph(
|
@@ -33,14 +39,19 @@ def grid_entangler_graph(
|
|
33
39
|
grid_randomization: CBool,
|
34
40
|
) -> CArray[CArray[CInt]]:
|
35
41
|
return symbolic_function(
|
36
|
-
num_qubits,
|
42
|
+
num_qubits,
|
43
|
+
schmidt_rank,
|
44
|
+
grid_randomization,
|
45
|
+
return_type=CArray[CArray[CInt]], # type:ignore[type-abstract]
|
37
46
|
)
|
38
47
|
|
39
48
|
|
40
49
|
def hypercube_entangler_graph(
|
41
50
|
num_qubits: CInt,
|
42
51
|
) -> CArray[CArray[CInt]]:
|
43
|
-
return symbolic_function(
|
52
|
+
return symbolic_function(
|
53
|
+
num_qubits, return_type=CArray[CArray[CInt]] # type:ignore[type-abstract]
|
54
|
+
)
|
44
55
|
|
45
56
|
|
46
57
|
def gaussian_finance_post_process(
|
@@ -49,7 +60,10 @@ def gaussian_finance_post_process(
|
|
49
60
|
probability: CReal,
|
50
61
|
) -> CReal:
|
51
62
|
return symbolic_function(
|
52
|
-
finance_model,
|
63
|
+
finance_model,
|
64
|
+
estimation_method,
|
65
|
+
probability,
|
66
|
+
return_type=CReal, # type:ignore[type-abstract]
|
53
67
|
)
|
54
68
|
|
55
69
|
|
@@ -59,7 +73,10 @@ def log_normal_finance_post_process(
|
|
59
73
|
probability: CReal,
|
60
74
|
) -> CReal:
|
61
75
|
return symbolic_function(
|
62
|
-
finance_model,
|
76
|
+
finance_model,
|
77
|
+
estimation_method,
|
78
|
+
probability,
|
79
|
+
return_type=CReal, # type:ignore[type-abstract]
|
63
80
|
)
|
64
81
|
|
65
82
|
|
classiq/qmod/builtins/enums.py
CHANGED
@@ -64,6 +64,7 @@ CORE_LIB_DECLS = [
|
|
64
64
|
inplace_prepare_state,
|
65
65
|
inplace_prepare_amplitudes,
|
66
66
|
single_pauli_exponent,
|
67
|
+
commuting_paulis_exponent,
|
67
68
|
suzuki_trotter,
|
68
69
|
qdrift,
|
69
70
|
exponentiation_with_depth_constraint,
|
@@ -129,6 +130,7 @@ __all__ = [ # noqa: RUF022
|
|
129
130
|
"randomized_benchmarking",
|
130
131
|
"real_xor_constant",
|
131
132
|
"single_pauli_exponent",
|
133
|
+
"commuting_paulis_exponent",
|
132
134
|
"suzuki_trotter",
|
133
135
|
"unitary",
|
134
136
|
"RESET",
|
@@ -28,6 +28,30 @@ def single_pauli_exponent(
|
|
28
28
|
pass
|
29
29
|
|
30
30
|
|
31
|
+
@qfunc(external=True)
|
32
|
+
def commuting_paulis_exponent(
|
33
|
+
pauli_operator: CArray[PauliTerm],
|
34
|
+
evolution_coefficient: CReal,
|
35
|
+
qbv: QArray[
|
36
|
+
QBit, Literal["get_field(get_field(pauli_operator[0], 'pauli'), 'len')"]
|
37
|
+
],
|
38
|
+
) -> None:
|
39
|
+
"""
|
40
|
+
[Qmod core-library function]
|
41
|
+
|
42
|
+
Exponentiates the specified commutative Pauli operator.
|
43
|
+
As all the Pauli operator's terms commute, the exponential of the whole operator
|
44
|
+
is exactly the product of exponentials of each term.
|
45
|
+
Calling this funciton with a non-commutative Pauli operator will issue an error.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
pauli_operator: The Pauli operator to be exponentiated.
|
49
|
+
evolution_coefficient: A global evolution coefficient multiplying the Pauli operator.
|
50
|
+
qbv: The target quantum variable of the exponentiation.
|
51
|
+
"""
|
52
|
+
pass
|
53
|
+
|
54
|
+
|
31
55
|
@qfunc(external=True)
|
32
56
|
def suzuki_trotter(
|
33
57
|
pauli_operator: CArray[PauliTerm],
|
@@ -48,7 +48,7 @@ from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QScalar, QVa
|
|
48
48
|
from classiq.qmod.quantum_callable import QCallable
|
49
49
|
from classiq.qmod.quantum_expandable import prepare_arg
|
50
50
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
51
|
-
from classiq.qmod.utilities import get_source_ref
|
51
|
+
from classiq.qmod.utilities import Statements, get_source_ref, suppress_return_value
|
52
52
|
|
53
53
|
_MISSING_VALUE: Final[int] = -1
|
54
54
|
|
@@ -63,6 +63,7 @@ def allocate(out: Output[QVar]) -> None:
|
|
63
63
|
pass
|
64
64
|
|
65
65
|
|
66
|
+
@suppress_return_value
|
66
67
|
def allocate(*args: Any, **kwargs: Any) -> None:
|
67
68
|
"""
|
68
69
|
Initialize a quantum variable to a new quantum object in the zero state:
|
@@ -106,6 +107,7 @@ def allocate(*args: Any, **kwargs: Any) -> None:
|
|
106
107
|
)
|
107
108
|
|
108
109
|
|
110
|
+
@suppress_return_value
|
109
111
|
def bind(
|
110
112
|
source: Union[Input[QVar], list[Input[QVar]]],
|
111
113
|
destination: Union[Output[QVar], list[Output[QVar]]],
|
@@ -125,10 +127,11 @@ def bind(
|
|
125
127
|
)
|
126
128
|
|
127
129
|
|
130
|
+
@suppress_return_value
|
128
131
|
def if_(
|
129
132
|
condition: Union[SymbolicExpr, bool],
|
130
|
-
then: Union[QCallable, Callable[[],
|
131
|
-
else_: Union[QCallable, Callable[[],
|
133
|
+
then: Union[QCallable, Callable[[], Statements]],
|
134
|
+
else_: Union[QCallable, Callable[[], Statements], int] = _MISSING_VALUE,
|
132
135
|
) -> None:
|
133
136
|
_validate_operand(then)
|
134
137
|
if else_ != _MISSING_VALUE:
|
@@ -149,10 +152,11 @@ def if_(
|
|
149
152
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(if_stmt)
|
150
153
|
|
151
154
|
|
155
|
+
@suppress_return_value
|
152
156
|
def control(
|
153
157
|
ctrl: Union[SymbolicExpr, QBit, QArray[QBit]],
|
154
|
-
stmt_block: Union[QCallable, Callable[[],
|
155
|
-
else_block: Union[QCallable, Callable[[],
|
158
|
+
stmt_block: Union[QCallable, Callable[[], Statements]],
|
159
|
+
else_block: Union[QCallable, Callable[[], Statements], None] = None,
|
156
160
|
) -> None:
|
157
161
|
_validate_operand(stmt_block)
|
158
162
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
@@ -170,6 +174,7 @@ def control(
|
|
170
174
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(control_stmt)
|
171
175
|
|
172
176
|
|
177
|
+
@suppress_return_value
|
173
178
|
def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
|
174
179
|
"""
|
175
180
|
Initialize a scalar quantum variable using an arithmetic expression.
|
@@ -194,6 +199,7 @@ def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
194
199
|
)
|
195
200
|
|
196
201
|
|
202
|
+
@suppress_return_value
|
197
203
|
def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
198
204
|
"""
|
199
205
|
Perform an amplitude-encoding assignment operation on a quantum variable and a
|
@@ -216,6 +222,7 @@ def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
216
222
|
)
|
217
223
|
|
218
224
|
|
225
|
+
@suppress_return_value
|
219
226
|
def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
|
220
227
|
"""
|
221
228
|
Add an arithmetic expression to a quantum variable.
|
@@ -238,6 +245,7 @@ def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
238
245
|
)
|
239
246
|
|
240
247
|
|
248
|
+
@suppress_return_value
|
241
249
|
def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
|
242
250
|
"""
|
243
251
|
Bitwise-XOR a quantum variable with an arithmetic expression.
|
@@ -260,9 +268,10 @@ def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
260
268
|
)
|
261
269
|
|
262
270
|
|
271
|
+
@suppress_return_value
|
263
272
|
def within_apply(
|
264
|
-
within: Callable[[],
|
265
|
-
apply: Callable[[],
|
273
|
+
within: Callable[[], Statements],
|
274
|
+
apply: Callable[[], Statements],
|
266
275
|
) -> None:
|
267
276
|
_validate_operand(within)
|
268
277
|
_validate_operand(apply)
|
@@ -279,7 +288,10 @@ def within_apply(
|
|
279
288
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(within_apply_stmt)
|
280
289
|
|
281
290
|
|
282
|
-
|
291
|
+
@suppress_return_value
|
292
|
+
def repeat(
|
293
|
+
count: Union[SymbolicExpr, int], iteration: Callable[[int], Statements]
|
294
|
+
) -> None:
|
283
295
|
_validate_operand(iteration)
|
284
296
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
285
297
|
source_ref = get_source_ref(sys._getframe(1))
|
@@ -310,9 +322,10 @@ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) ->
|
|
310
322
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(repeat_stmt)
|
311
323
|
|
312
324
|
|
325
|
+
@suppress_return_value
|
313
326
|
def power(
|
314
327
|
exponent: Union[SymbolicExpr, int],
|
315
|
-
stmt_block: Union[QCallable, Callable[[],
|
328
|
+
stmt_block: Union[QCallable, Callable[[], Statements]],
|
316
329
|
) -> None:
|
317
330
|
_validate_operand(stmt_block)
|
318
331
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
@@ -327,7 +340,8 @@ def power(
|
|
327
340
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(power_stmt)
|
328
341
|
|
329
342
|
|
330
|
-
|
343
|
+
@suppress_return_value
|
344
|
+
def invert(stmt_block: Union[QCallable, Callable[[], Statements]]) -> None:
|
331
345
|
_validate_operand(stmt_block)
|
332
346
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
333
347
|
source_ref = get_source_ref(sys._getframe(1))
|
@@ -339,6 +353,7 @@ def invert(stmt_block: Union[QCallable, Callable[[], None]]) -> None:
|
|
339
353
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(invert_stmt)
|
340
354
|
|
341
355
|
|
356
|
+
@suppress_return_value
|
342
357
|
def phase(expr: SymbolicExpr, theta: float = 1.0) -> None:
|
343
358
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
344
359
|
source_ref = get_source_ref(sys._getframe(1))
|
@@ -402,7 +417,7 @@ def _get_operand_hint(
|
|
402
417
|
|
403
418
|
|
404
419
|
def _operand_to_body(
|
405
|
-
callable_: Union[QCallable, Callable[[],
|
420
|
+
callable_: Union[QCallable, Callable[[], Statements]], param_name: str
|
406
421
|
) -> StatementBlock:
|
407
422
|
op_name = sys._getframe(1).f_code.co_name
|
408
423
|
if (
|
classiq/qmod/cparam.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import sys
|
2
|
+
from abc import ABC, abstractmethod
|
2
3
|
from typing import ( # type: ignore[attr-defined]
|
3
4
|
TYPE_CHECKING,
|
4
5
|
Any,
|
@@ -9,6 +10,8 @@ from typing import ( # type: ignore[attr-defined]
|
|
9
10
|
|
10
11
|
from typing_extensions import ParamSpec
|
11
12
|
|
13
|
+
from classiq.interface.exceptions import ClassiqValueError
|
14
|
+
|
12
15
|
from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
|
13
16
|
|
14
17
|
if TYPE_CHECKING:
|
@@ -21,18 +24,34 @@ else:
|
|
21
24
|
|
22
25
|
class CParam(SymbolicSuperclass):
|
23
26
|
def __init__(self, expr: str) -> None:
|
24
|
-
super().__init__(expr, False)
|
27
|
+
super().__init__(expr, is_quantum=False)
|
28
|
+
|
29
|
+
|
30
|
+
class CParamAbstract(ABC, CParam):
|
31
|
+
|
32
|
+
def __new__(cls, *args: Any, **kwargs: Any) -> "CParamAbstract":
|
33
|
+
raise ClassiqValueError(
|
34
|
+
f"{cls.__name__} is a Qmod type hint for a classical parameter and it cannot be instantiated. "
|
35
|
+
f"Use regular Pythonic values as arguments instead. "
|
36
|
+
f"Example:\n\n"
|
37
|
+
f"def foo(val: {cls.__name__}) -> None: ...\n\n"
|
38
|
+
f"foo({_EXAMPLE_VALUES[cls.__name__]}) # Correct\n"
|
39
|
+
)
|
25
40
|
|
41
|
+
@abstractmethod
|
42
|
+
def __init__(self) -> None:
|
43
|
+
pass
|
26
44
|
|
27
|
-
|
45
|
+
|
46
|
+
class CInt(CParamAbstract):
|
28
47
|
pass
|
29
48
|
|
30
49
|
|
31
|
-
class CReal(
|
50
|
+
class CReal(CParamAbstract):
|
32
51
|
pass
|
33
52
|
|
34
53
|
|
35
|
-
class CBool(
|
54
|
+
class CBool(CParamAbstract):
|
36
55
|
pass
|
37
56
|
|
38
57
|
|
@@ -47,7 +66,7 @@ class ArrayBase(Generic[_P]):
|
|
47
66
|
return _GenericAlias(cls, args)
|
48
67
|
|
49
68
|
|
50
|
-
class CArray(
|
69
|
+
class CArray(CParamAbstract, ArrayBase[_P]):
|
51
70
|
if TYPE_CHECKING:
|
52
71
|
|
53
72
|
@property
|
@@ -62,3 +81,11 @@ Array = CArray
|
|
62
81
|
class CParamScalar(CParam, SymbolicExpr):
|
63
82
|
def __hash__(self) -> int:
|
64
83
|
return hash(str(self))
|
84
|
+
|
85
|
+
|
86
|
+
_EXAMPLE_VALUES: dict[str, Any] = {
|
87
|
+
CInt.__name__: 1,
|
88
|
+
CReal.__name__: 1.0,
|
89
|
+
CBool.__name__: True,
|
90
|
+
CArray.__name__: [1, 2],
|
91
|
+
}
|
@@ -30,16 +30,22 @@ CARRAY_ERROR_MESSAGE = (
|
|
30
30
|
|
31
31
|
class PythonClassicalType:
|
32
32
|
def convert(self, py_type: type) -> Optional[ConcreteClassicalType]:
|
33
|
-
if py_type is int
|
33
|
+
if py_type is int:
|
34
|
+
return Integer().set_generative()
|
35
|
+
elif py_type is CInt:
|
34
36
|
return Integer()
|
35
|
-
elif py_type in (float, complex)
|
37
|
+
elif py_type in (float, complex):
|
38
|
+
return Real().set_generative()
|
39
|
+
elif py_type is CReal:
|
36
40
|
return Real()
|
37
|
-
elif py_type is bool
|
41
|
+
elif py_type is bool:
|
42
|
+
return Bool().set_generative()
|
43
|
+
elif py_type is CBool:
|
38
44
|
return Bool()
|
39
45
|
elif get_origin(py_type) is list:
|
40
46
|
element_type = self.convert(get_args(py_type)[0])
|
41
47
|
if element_type is not None:
|
42
|
-
return ClassicalList(element_type=element_type)
|
48
|
+
return ClassicalList(element_type=element_type).set_generative()
|
43
49
|
elif get_origin(py_type) is CArray:
|
44
50
|
array_args = version_portable_get_args(py_type)
|
45
51
|
if len(array_args) == 1:
|
classiq/qmod/quantum_callable.py
CHANGED
@@ -21,7 +21,7 @@ from classiq.interface.model.quantum_type import QuantumType
|
|
21
21
|
from classiq.interface.source_reference import SourceReference
|
22
22
|
|
23
23
|
from classiq.qmod.cparam import CInt
|
24
|
-
from classiq.qmod.utilities import get_source_ref
|
24
|
+
from classiq.qmod.utilities import get_source_ref, suppress_return_value
|
25
25
|
|
26
26
|
if TYPE_CHECKING:
|
27
27
|
from classiq.qmod.quantum_expandable import QTerminalCallable
|
@@ -48,6 +48,7 @@ class QCallable(Generic[P], ABC):
|
|
48
48
|
CURRENT_EXPANDABLE: ClassVar[Optional[QExpandableInterface]] = None
|
49
49
|
FRAME_DEPTH = 1
|
50
50
|
|
51
|
+
@suppress_return_value
|
51
52
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
52
53
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
53
54
|
source_ref = get_source_ref(sys._getframe(self.FRAME_DEPTH))
|
classiq/qmod/quantum_function.py
CHANGED
@@ -24,10 +24,11 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
24
24
|
)
|
25
25
|
|
26
26
|
from classiq.qmod.classical_function import CFunc
|
27
|
+
from classiq.qmod.cparam import CParamAbstract
|
27
28
|
from classiq.qmod.declaration_inferrer import infer_func_decl
|
28
29
|
from classiq.qmod.generative import set_frontend_interpreter
|
29
30
|
from classiq.qmod.qmod_constant import QConstant
|
30
|
-
from classiq.qmod.qmod_parameter import CArray
|
31
|
+
from classiq.qmod.qmod_parameter import CArray
|
31
32
|
from classiq.qmod.qmod_variable import QVar
|
32
33
|
from classiq.qmod.quantum_callable import QCallable, QCallableList
|
33
34
|
from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
|
@@ -308,7 +309,7 @@ def _validate_no_gen_params(annotations: dict[str, Any]) -> None:
|
|
308
309
|
for name, annotation in annotations.items()
|
309
310
|
if not (
|
310
311
|
name == "return"
|
311
|
-
or (isclass(annotation) and issubclass(annotation,
|
312
|
+
or (isclass(annotation) and issubclass(annotation, CParamAbstract))
|
312
313
|
or (isclass(annotation) and is_dataclass(annotation))
|
313
314
|
or (isclass(annotation) and isinstance(annotation, EnumMeta))
|
314
315
|
or get_origin(annotation) is CArray
|