classiq 0.66.1__py3-none-any.whl → 0.68.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 +5 -1
- classiq/_internals/async_utils.py +1 -1
- classiq/_internals/authentication/password_manager.py +1 -1
- classiq/_internals/client.py +1 -1
- classiq/applications/finance/finance_model_constructor.py +9 -0
- classiq/applications/grover/grover_model_constructor.py +10 -0
- classiq/applications/qnn/qlayer.py +8 -2
- classiq/applications/qsvm/qsvm_model_constructor.py +9 -0
- classiq/execution/execution_session.py +7 -3
- classiq/executor.py +7 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/ast_node.py +1 -1
- classiq/interface/chemistry/operator.py +1 -1
- classiq/interface/debug_info/debug_info.py +27 -0
- classiq/interface/exceptions.py +2 -5
- classiq/interface/generator/arith/argument_utils.py +1 -1
- classiq/interface/generator/arith/arithmetic.py +99 -2
- classiq/interface/generator/arith/arithmetic_expression_parser.py +1 -1
- classiq/interface/generator/arith/binary_ops.py +3 -0
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -0
- classiq/interface/generator/functions/type_name.py +2 -2
- classiq/interface/generator/generated_circuit_data.py +38 -3
- classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
- classiq/interface/generator/hva.py +1 -1
- classiq/interface/generator/model/preferences/preferences.py +8 -1
- classiq/interface/generator/quantum_program.py +18 -1
- classiq/interface/generator/reset.py +14 -0
- classiq/interface/generator/types/enum_declaration.py +33 -2
- classiq/interface/generator/ucc.py +1 -1
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/classical_if.py +2 -2
- classiq/interface/model/control.py +2 -2
- classiq/interface/model/invert.py +2 -2
- classiq/interface/model/power.py +2 -2
- classiq/interface/model/quantum_function_call.py +4 -0
- classiq/interface/model/quantum_statement.py +13 -0
- classiq/interface/model/repeat.py +2 -2
- classiq/interface/model/statement_block.py +1 -1
- classiq/interface/model/within_apply_operation.py +2 -2
- classiq/model_expansions/atomic_expression_functions_defs.py +2 -1
- classiq/model_expansions/capturing/captured_vars.py +184 -54
- classiq/model_expansions/closure.py +6 -3
- classiq/model_expansions/evaluators/control.py +14 -38
- classiq/model_expansions/function_builder.py +19 -14
- classiq/model_expansions/generative_functions.py +7 -11
- classiq/model_expansions/interpreters/base_interpreter.py +14 -5
- classiq/model_expansions/interpreters/generative_interpreter.py +87 -26
- classiq/model_expansions/quantum_operations/allocate.py +9 -3
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +52 -0
- classiq/model_expansions/quantum_operations/bind.py +67 -14
- classiq/model_expansions/quantum_operations/block_evaluator.py +76 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +79 -10
- classiq/model_expansions/quantum_operations/classicalif.py +10 -6
- classiq/model_expansions/quantum_operations/composite_emitter.py +27 -0
- classiq/model_expansions/quantum_operations/emitter.py +24 -3
- classiq/model_expansions/quantum_operations/expression_evaluator.py +33 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +28 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +3 -2
- classiq/model_expansions/quantum_operations/repeat.py +9 -3
- classiq/model_expansions/quantum_operations/variable_decleration.py +13 -2
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +1 -1
- classiq/open_library/functions/__init__.py +1 -2
- classiq/open_library/functions/amplitude_amplification.py +12 -9
- classiq/open_library/functions/discrete_sine_cosine_transform.py +16 -13
- classiq/open_library/functions/grover.py +11 -15
- classiq/open_library/functions/modular_exponentiation.py +7 -13
- classiq/open_library/functions/state_preparation.py +16 -17
- classiq/open_library/functions/swap_test.py +1 -1
- classiq/open_library/functions/utility_functions.py +10 -2
- classiq/qmod/builtins/functions/__init__.py +3 -0
- classiq/qmod/builtins/functions/chemistry.py +6 -38
- classiq/qmod/builtins/functions/mid_circuit_measurement.py +15 -0
- classiq/qmod/quantum_expandable.py +30 -6
- classiq/qmod/quantum_function.py +4 -0
- classiq/qmod/semantics/annotation/call_annotation.py +8 -2
- classiq/qmod/semantics/annotation/model_annotation.py +9 -0
- classiq/qmod/semantics/error_manager.py +0 -6
- classiq/qmod/semantics/static_semantics_visitor.py +0 -347
- classiq/qmod/semantics/validation/types_validation.py +1 -1
- classiq/qmod/symbolic.py +2 -1
- classiq/qmod/utilities.py +2 -1
- classiq/qmod/write_qmod.py +10 -7
- classiq/synthesis.py +20 -7
- {classiq-0.66.1.dist-info → classiq-0.68.0.dist-info}/METADATA +1 -1
- {classiq-0.66.1.dist-info → classiq-0.68.0.dist-info}/RECORD +86 -81
- classiq/model_expansions/quantum_operations/shallow_emitter.py +0 -166
- classiq/qmod/semantics/validation/func_call_validation.py +0 -99
- classiq/qmod/semantics/validation/handle_validation.py +0 -85
- {classiq-0.66.1.dist-info → classiq-0.68.0.dist-info}/WHEEL +0 -0
@@ -1,13 +1,11 @@
|
|
1
1
|
from classiq.open_library.functions.qft_functions import qft
|
2
|
-
from classiq.open_library.functions.utility_functions import
|
3
|
-
apply_to_all,
|
4
|
-
modular_increment,
|
5
|
-
)
|
2
|
+
from classiq.open_library.functions.utility_functions import apply_to_all
|
6
3
|
from classiq.qmod.builtins.functions.standard_gates import PHASE, H, S, X, Z
|
7
4
|
from classiq.qmod.builtins.operations import (
|
8
5
|
allocate,
|
9
6
|
bind,
|
10
7
|
control,
|
8
|
+
inplace_add,
|
11
9
|
invert,
|
12
10
|
repeat,
|
13
11
|
within_apply,
|
@@ -30,8 +28,13 @@ def _qct_d_operator(x: QNum, q: QBit) -> None:
|
|
30
28
|
|
31
29
|
@qfunc
|
32
30
|
def _qct_pi_operator(x: QArray[QBit], q: QBit) -> None:
|
33
|
-
control(
|
34
|
-
|
31
|
+
control(
|
32
|
+
q == 1,
|
33
|
+
lambda: [ # type:ignore[arg-type]
|
34
|
+
apply_to_all(X, x),
|
35
|
+
inplace_add(1, x), # type:ignore[arg-type, func-returns-value]
|
36
|
+
],
|
37
|
+
)
|
35
38
|
|
36
39
|
|
37
40
|
def _t_operator(x: QArray) -> None:
|
@@ -63,7 +66,7 @@ def _d1_operator(x: QArray[QBit], q: QBit) -> None:
|
|
63
66
|
|
64
67
|
|
65
68
|
def _pi2_operator(x: QArray[QBit], q: QBit) -> None:
|
66
|
-
control(q == 1, lambda:
|
69
|
+
control(q == 1, lambda: inplace_add(1, x)) # type:ignore[arg-type]
|
67
70
|
|
68
71
|
|
69
72
|
def _j_operator(q: QBit) -> None:
|
@@ -76,7 +79,7 @@ def _b_t_operator(q: QBit) -> None:
|
|
76
79
|
|
77
80
|
|
78
81
|
def _d0dt_operator(x: QArray, q: QBit) -> None:
|
79
|
-
x_num: QNum = QNum(
|
82
|
+
x_num: QNum = QNum(size=x.len)
|
80
83
|
bind(x, x_num)
|
81
84
|
_b_t_operator(q)
|
82
85
|
control(x_num == 0, lambda: _j_operator(q))
|
@@ -140,7 +143,7 @@ def qct_qst_type2(x: QArray[QBit], q: QBit) -> None:
|
|
140
143
|
x: The LSB part of the qubit array to apply the transform to.
|
141
144
|
q: The MSB of the qubit array to apply the transform to.
|
142
145
|
"""
|
143
|
-
extended_state: QArray = QArray(
|
146
|
+
extended_state: QArray = QArray()
|
144
147
|
_vn_operator(x, q)
|
145
148
|
bind([x, q], extended_state)
|
146
149
|
qft(extended_state)
|
@@ -159,8 +162,8 @@ def qct_type2(x: QArray[QBit]) -> None:
|
|
159
162
|
Args:
|
160
163
|
x: The qubit array to apply the transform to.
|
161
164
|
"""
|
162
|
-
q = QBit(
|
163
|
-
within_apply(lambda: allocate(
|
165
|
+
q = QBit()
|
166
|
+
within_apply(lambda: allocate(q), lambda: qct_qst_type2(x, q))
|
164
167
|
|
165
168
|
|
166
169
|
@qfunc
|
@@ -174,8 +177,8 @@ def qst_type2(x: QArray[QBit]) -> None:
|
|
174
177
|
Args:
|
175
178
|
x: The qubit array to apply the transform to.
|
176
179
|
"""
|
177
|
-
q = QBit(
|
180
|
+
q = QBit()
|
178
181
|
within_apply(
|
179
|
-
lambda: (allocate(
|
182
|
+
lambda: (allocate(q), X(q)), # type:ignore[arg-type]
|
180
183
|
lambda: qct_qst_type2(x, q),
|
181
184
|
)
|
@@ -40,9 +40,9 @@ def phase_oracle(
|
|
40
40
|
predicate: A predicate function that takes a QArray of QBits and sets a single QBit |1> if the predicate is true, and |0> otherwise.
|
41
41
|
target: The target QArray of QBits to apply the phase oracle to.
|
42
42
|
"""
|
43
|
-
aux = QBit(
|
43
|
+
aux = QBit()
|
44
44
|
within_apply(
|
45
|
-
within=lambda: (allocate(
|
45
|
+
within=lambda: (allocate(aux), X(aux), H(aux)), # type:ignore[arg-type]
|
46
46
|
apply=lambda: predicate(target, aux),
|
47
47
|
)
|
48
48
|
|
@@ -56,16 +56,16 @@ def reflect_about_zero(packed_vars: QArray[QBit]) -> None:
|
|
56
56
|
besides the |0> state). Implements the operator $S_0$:
|
57
57
|
|
58
58
|
$$
|
59
|
-
|
60
|
-
S_0|{x}
|
59
|
+
\\begin{equation}
|
60
|
+
S_0|{x}\\rangle = (-1)^{(x\\ne0)}|{x}\\rangle= (2|{0}\\rangle\\langle{0}|-I)|{x}\\rangle
|
61
61
|
\\end{equation}
|
62
62
|
$$
|
63
63
|
|
64
64
|
Args:
|
65
65
|
packed_vars: The quantum state to reflect.
|
66
66
|
"""
|
67
|
-
msbs: QNum = QNum(
|
68
|
-
lsb = QBit(
|
67
|
+
msbs: QNum = QNum(size=packed_vars.len - 1)
|
68
|
+
lsb = QBit()
|
69
69
|
bind(packed_vars, [msbs, lsb])
|
70
70
|
within_apply(
|
71
71
|
lambda: (X(lsb), H(lsb)), # type:ignore[arg-type]
|
@@ -85,7 +85,7 @@ def grover_diffuser(
|
|
85
85
|
is the `space_transform` parameter. It is defined as:
|
86
86
|
|
87
87
|
$$
|
88
|
-
|
88
|
+
\\begin{equation}
|
89
89
|
D = A S_0 A^{\\dagger}
|
90
90
|
\\end{equation}
|
91
91
|
$$
|
@@ -118,15 +118,15 @@ def grover_operator(
|
|
118
118
|
$$
|
119
119
|
|
120
120
|
where $S_{\\psi_1}$ is a reflection about marked states, and $S_{\\psi_0}$ is a reflection
|
121
|
-
about a given state defined by $|\\psi_0
|
121
|
+
about a given state defined by $|\\psi_0\\rangle = A|0\\rangle$.
|
122
122
|
|
123
123
|
Args:
|
124
124
|
oracle: A unitary operator which adds a phase of (-1) to marked states.
|
125
|
-
space_transform: The operator which creates $|\\psi_0
|
125
|
+
space_transform: The operator which creates $|\\psi_0\\rangle$, the initial state, used by the diffuser to reflect about it.
|
126
126
|
packed_vars: The state to which to apply the grover operator.
|
127
127
|
"""
|
128
128
|
oracle(packed_vars)
|
129
|
-
grover_diffuser(
|
129
|
+
grover_diffuser(space_transform, packed_vars)
|
130
130
|
U(0, 0, 0, pi, packed_vars[0])
|
131
131
|
|
132
132
|
|
@@ -149,9 +149,5 @@ def grover_search(
|
|
149
149
|
hadamard_transform(packed_vars)
|
150
150
|
power(
|
151
151
|
reps,
|
152
|
-
lambda: grover_operator(
|
153
|
-
lambda qba: oracle(qba),
|
154
|
-
lambda qba: hadamard_transform(qba),
|
155
|
-
packed_vars,
|
156
|
-
),
|
152
|
+
lambda: grover_operator(oracle, hadamard_transform, packed_vars),
|
157
153
|
)
|
@@ -11,24 +11,18 @@ from classiq.qmod.builtins.operations import (
|
|
11
11
|
)
|
12
12
|
from classiq.qmod.cparam import CInt
|
13
13
|
from classiq.qmod.qfunc import qfunc
|
14
|
-
from classiq.qmod.qmod_variable import QArray, QBit
|
14
|
+
from classiq.qmod.qmod_variable import QArray, QBit
|
15
15
|
from classiq.qmod.symbolic import min, mod_inverse
|
16
16
|
|
17
17
|
|
18
18
|
@qfunc
|
19
19
|
def _check_msb(ref: CInt, x: QArray[QBit], aux: QBit) -> None:
|
20
20
|
within_apply(
|
21
|
-
lambda: invert(lambda: qft_no_swap(x)),
|
21
|
+
lambda: invert(lambda: qft_no_swap(x)),
|
22
|
+
lambda: control(x[0] == ref, lambda: X(aux)),
|
22
23
|
)
|
23
24
|
|
24
25
|
|
25
|
-
@qfunc
|
26
|
-
def _ctrl_x(
|
27
|
-
ref: CInt, ctrl: QNum, aux: QBit
|
28
|
-
) -> None: # TODO: remove qfunc when expressions of QBit is supported
|
29
|
-
control(ctrl == ref, lambda: X(aux))
|
30
|
-
|
31
|
-
|
32
26
|
@qfunc
|
33
27
|
def qft_space_add_const(value: CInt, phi_b: QArray[QBit]) -> None:
|
34
28
|
"""
|
@@ -72,12 +66,12 @@ def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) ->
|
|
72
66
|
c2: a control qubit.
|
73
67
|
|
74
68
|
"""
|
75
|
-
ctrl: QArray[QBit] = QArray(
|
76
|
-
aux = QBit(
|
69
|
+
ctrl: QArray[QBit] = QArray()
|
70
|
+
aux = QBit()
|
77
71
|
|
78
72
|
within_apply(
|
79
73
|
lambda: ( # type:ignore[arg-type]
|
80
|
-
allocate(
|
74
|
+
allocate(aux),
|
81
75
|
bind([c1, c2], ctrl), # type:ignore[func-returns-value]
|
82
76
|
),
|
83
77
|
lambda: ( # type:ignore[arg-type]
|
@@ -162,7 +156,7 @@ def inplace_c_modular_multiply(n: CInt, a: CInt, x: QArray[QBit], ctrl: QBit) ->
|
|
162
156
|
x: The quantum factor.
|
163
157
|
ctrl: The control bit.
|
164
158
|
"""
|
165
|
-
b: QArray[QBit] = QArray(
|
159
|
+
b: QArray[QBit] = QArray()
|
166
160
|
|
167
161
|
within_apply(
|
168
162
|
lambda: allocate(x.len + 1, b),
|
@@ -3,12 +3,9 @@ from typing import Literal
|
|
3
3
|
|
4
4
|
from classiq.interface.exceptions import ClassiqDeprecationWarning
|
5
5
|
|
6
|
-
from classiq.open_library.functions.utility_functions import
|
7
|
-
hadamard_transform,
|
8
|
-
modular_increment,
|
9
|
-
)
|
6
|
+
from classiq.open_library.functions.utility_functions import hadamard_transform
|
10
7
|
from classiq.qmod.builtins.functions.standard_gates import CX, IDENTITY, RY, H, X
|
11
|
-
from classiq.qmod.builtins.operations import allocate, control, if_, repeat
|
8
|
+
from classiq.qmod.builtins.operations import allocate, control, if_, inplace_add, repeat
|
12
9
|
from classiq.qmod.cparam import CBool, CInt
|
13
10
|
from classiq.qmod.qfunc import qfunc
|
14
11
|
from classiq.qmod.qmod_variable import Output, QArray, QBit, QNum
|
@@ -48,7 +45,7 @@ def allocate_num(
|
|
48
45
|
allocate(num_qubits, out)
|
49
46
|
|
50
47
|
|
51
|
-
def
|
48
|
+
def _prepare_uniform_trimmed_state_apply_rotation(
|
52
49
|
size_lsb: CInt, lsbs_val: CInt, rotation_var: QBit
|
53
50
|
) -> None:
|
54
51
|
# max hold for the case where the value is on the left side
|
@@ -68,7 +65,7 @@ def _prepare_uniform_trimmed_state_step(
|
|
68
65
|
lsbs_val != 0, # stop condition
|
69
66
|
lambda: control(
|
70
67
|
ctrl_var == ctrl_val,
|
71
|
-
lambda:
|
68
|
+
lambda: _prepare_uniform_trimmed_state_apply_rotation(
|
72
69
|
size_lsb, lsbs_val, rotation_var
|
73
70
|
),
|
74
71
|
),
|
@@ -102,7 +99,7 @@ def prepare_uniform_trimmed_state(m: CInt, q: QArray[QBit]) -> None:
|
|
102
99
|
if_(
|
103
100
|
m < 2**q.len,
|
104
101
|
# initial step without control
|
105
|
-
lambda:
|
102
|
+
lambda: _prepare_uniform_trimmed_state_apply_rotation(
|
106
103
|
q.len - 1, # type:ignore[arg-type]
|
107
104
|
m,
|
108
105
|
q[q.len - 1],
|
@@ -122,7 +119,7 @@ def prepare_uniform_trimmed_state(m: CInt, q: QArray[QBit]) -> None:
|
|
122
119
|
|
123
120
|
|
124
121
|
@qfunc
|
125
|
-
def prepare_uniform_interval_state(start: CInt, end: CInt, q:
|
122
|
+
def prepare_uniform_interval_state(start: CInt, end: CInt, q: QNum) -> None:
|
126
123
|
"""
|
127
124
|
[Qmod Classiq-library function]
|
128
125
|
|
@@ -144,7 +141,7 @@ def prepare_uniform_interval_state(start: CInt, end: CInt, q: QArray[QBit]) -> N
|
|
144
141
|
2. The synthesis engine automatically handles the allocation, either by drawing new qubits from the available pool or by reusing existing ones.
|
145
142
|
"""
|
146
143
|
prepare_uniform_trimmed_state(end - start, q)
|
147
|
-
|
144
|
+
inplace_add(start, q)
|
148
145
|
|
149
146
|
|
150
147
|
@qfunc
|
@@ -199,7 +196,9 @@ def prepare_exponential_state(rate: CInt, q: QArray[QBit]) -> None:
|
|
199
196
|
|
200
197
|
|
201
198
|
@qfunc
|
202
|
-
def prepare_bell_state(
|
199
|
+
def prepare_bell_state(
|
200
|
+
state_num: CInt, qpair: Output[QArray[QBit, Literal[2]]]
|
201
|
+
) -> None:
|
203
202
|
"""
|
204
203
|
[Qmod Classiq-library function]
|
205
204
|
|
@@ -207,7 +206,7 @@ def prepare_bell_state(state_num: CInt, q: Output[QArray[QBit, Literal[2]]]) ->
|
|
207
206
|
|
208
207
|
Args:
|
209
208
|
state_num: The number of the Bell state to be prepared. Must be an integer between 0 and 3.
|
210
|
-
|
209
|
+
qpair: The quantum variable that will receive the initialized state. Must be uninitialized.
|
211
210
|
|
212
211
|
Bell States:
|
213
212
|
The four Bell states are defined as follows (each state correlates to an integer between 0 and 3 as defined by the `state_num` argument):
|
@@ -241,11 +240,11 @@ def prepare_bell_state(state_num: CInt, q: Output[QArray[QBit, Literal[2]]]) ->
|
|
241
240
|
|
242
241
|
|
243
242
|
"""
|
244
|
-
allocate(
|
245
|
-
if_(logical_or(state_num == 1, state_num == 3), lambda: X(
|
246
|
-
if_(logical_or(state_num == 2, state_num == 3), lambda: X(
|
247
|
-
H(
|
248
|
-
CX(
|
243
|
+
allocate(qpair)
|
244
|
+
if_(logical_or(state_num == 1, state_num == 3), lambda: X(qpair[0]))
|
245
|
+
if_(logical_or(state_num == 2, state_num == 3), lambda: X(qpair[1]))
|
246
|
+
H(qpair[0])
|
247
|
+
CX(qpair[0], qpair[1])
|
249
248
|
|
250
249
|
|
251
250
|
@qfunc
|
@@ -21,7 +21,7 @@ def swap_test(state1: QArray[QBit], state2: QArray[QBit], test: Output[QBit]) ->
|
|
21
21
|
state2: A quantum state to check its overlap with state1.
|
22
22
|
test: A qubit for which the probability of measuring 0 is $0.5*(|\\langle state1 | state2 \\rangle |^2+1)$
|
23
23
|
"""
|
24
|
-
allocate(
|
24
|
+
allocate(test)
|
25
25
|
H(test)
|
26
26
|
control(test, lambda: repeat(state1.len, lambda i: SWAP(state1[i], state2[i])))
|
27
27
|
H(test)
|
@@ -1,5 +1,8 @@
|
|
1
|
+
import warnings
|
1
2
|
from typing import Annotated
|
2
3
|
|
4
|
+
from classiq.interface.exceptions import ClassiqDeprecationWarning
|
5
|
+
|
3
6
|
from classiq.open_library.functions.qft_functions import qft
|
4
7
|
from classiq.qmod.builtins.functions.standard_gates import PHASE, H
|
5
8
|
from classiq.qmod.builtins.operations import bind, repeat, within_apply
|
@@ -44,7 +47,7 @@ def hadamard_transform(target: QArray[QBit]) -> None:
|
|
44
47
|
target: qubits to apply to Hadamard transform to.
|
45
48
|
|
46
49
|
"""
|
47
|
-
|
50
|
+
repeat(target.len, lambda index: H(target[index]))
|
48
51
|
|
49
52
|
|
50
53
|
@qfunc
|
@@ -69,7 +72,12 @@ def modular_increment(a: CInt, x: QNum) -> None:
|
|
69
72
|
x: A quantum number that is assumed to be non-negative integer.
|
70
73
|
|
71
74
|
"""
|
72
|
-
|
75
|
+
warnings.warn(
|
76
|
+
"Function 'modular_increment' is deprecated. Use in-place-add statement in the form '<var> += <expression>' or 'inplace_add(<expression>, <var>)' instead.",
|
77
|
+
ClassiqDeprecationWarning,
|
78
|
+
stacklevel=1,
|
79
|
+
)
|
80
|
+
array_cast: QArray = QArray()
|
73
81
|
within_apply(
|
74
82
|
lambda: ( # type:ignore[arg-type]
|
75
83
|
bind(x, array_cast), # type:ignore[func-returns-value]
|
@@ -4,6 +4,7 @@ from .benchmarking import *
|
|
4
4
|
from .chemistry import *
|
5
5
|
from .exponentiation import *
|
6
6
|
from .finance import *
|
7
|
+
from .mid_circuit_measurement import *
|
7
8
|
from .operators import *
|
8
9
|
from .qsvm import *
|
9
10
|
from .standard_gates import *
|
@@ -66,6 +67,7 @@ CORE_LIB_DECLS = [
|
|
66
67
|
suzuki_trotter,
|
67
68
|
qdrift,
|
68
69
|
exponentiation_with_depth_constraint,
|
70
|
+
RESET,
|
69
71
|
)
|
70
72
|
]
|
71
73
|
|
@@ -129,6 +131,7 @@ __all__ = [ # noqa: RUF022
|
|
129
131
|
"single_pauli_exponent",
|
130
132
|
"suzuki_trotter",
|
131
133
|
"unitary",
|
134
|
+
"RESET",
|
132
135
|
]
|
133
136
|
BUILTIN_FUNCTION_DECLARATIONS = {
|
134
137
|
func_decl.name: func_decl for func_decl in STD_QMOD_OPERATORS + CORE_LIB_DECLS
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import Literal
|
2
|
-
|
3
1
|
from classiq.qmod.builtins.structs import (
|
4
2
|
FockHamiltonianProblem,
|
5
3
|
MoleculeProblem,
|
@@ -13,12 +11,7 @@ from classiq.qmod.qmod_variable import QArray, QBit
|
|
13
11
|
def molecule_ucc(
|
14
12
|
molecule_problem: MoleculeProblem,
|
15
13
|
excitations: CArray[CInt],
|
16
|
-
qbv: QArray[
|
17
|
-
QBit,
|
18
|
-
Literal[
|
19
|
-
"get_field(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'), 'len')"
|
20
|
-
],
|
21
|
-
],
|
14
|
+
qbv: QArray[QBit],
|
22
15
|
) -> None:
|
23
16
|
pass
|
24
17
|
|
@@ -27,12 +20,7 @@ def molecule_ucc(
|
|
27
20
|
def molecule_hva(
|
28
21
|
molecule_problem: MoleculeProblem,
|
29
22
|
reps: CInt,
|
30
|
-
qbv: QArray[
|
31
|
-
QBit,
|
32
|
-
Literal[
|
33
|
-
"get_field(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'), 'len')"
|
34
|
-
],
|
35
|
-
],
|
23
|
+
qbv: QArray[QBit],
|
36
24
|
) -> None:
|
37
25
|
pass
|
38
26
|
|
@@ -40,12 +28,7 @@ def molecule_hva(
|
|
40
28
|
@qfunc(external=True)
|
41
29
|
def molecule_hartree_fock(
|
42
30
|
molecule_problem: MoleculeProblem,
|
43
|
-
qbv: QArray[
|
44
|
-
QBit,
|
45
|
-
Literal[
|
46
|
-
"get_field(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'), 'len')"
|
47
|
-
],
|
48
|
-
],
|
31
|
+
qbv: QArray[QBit],
|
49
32
|
) -> None:
|
50
33
|
pass
|
51
34
|
|
@@ -54,12 +37,7 @@ def molecule_hartree_fock(
|
|
54
37
|
def fock_hamiltonian_ucc(
|
55
38
|
fock_hamiltonian_problem: FockHamiltonianProblem,
|
56
39
|
excitations: CArray[CInt],
|
57
|
-
qbv: QArray[
|
58
|
-
QBit,
|
59
|
-
Literal[
|
60
|
-
"get_field(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'), 'len')"
|
61
|
-
],
|
62
|
-
],
|
40
|
+
qbv: QArray[QBit],
|
63
41
|
) -> None:
|
64
42
|
pass
|
65
43
|
|
@@ -68,12 +46,7 @@ def fock_hamiltonian_ucc(
|
|
68
46
|
def fock_hamiltonian_hva(
|
69
47
|
fock_hamiltonian_problem: FockHamiltonianProblem,
|
70
48
|
reps: CInt,
|
71
|
-
qbv: QArray[
|
72
|
-
QBit,
|
73
|
-
Literal[
|
74
|
-
"get_field(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'), 'len')"
|
75
|
-
],
|
76
|
-
],
|
49
|
+
qbv: QArray[QBit],
|
77
50
|
) -> None:
|
78
51
|
pass
|
79
52
|
|
@@ -81,11 +54,6 @@ def fock_hamiltonian_hva(
|
|
81
54
|
@qfunc(external=True)
|
82
55
|
def fock_hamiltonian_hartree_fock(
|
83
56
|
fock_hamiltonian_problem: FockHamiltonianProblem,
|
84
|
-
qbv: QArray[
|
85
|
-
QBit,
|
86
|
-
Literal[
|
87
|
-
"get_field(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'), 'len')"
|
88
|
-
],
|
89
|
-
],
|
57
|
+
qbv: QArray[QBit],
|
90
58
|
) -> None:
|
91
59
|
pass
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from classiq.qmod.qfunc import qfunc
|
2
|
+
from classiq.qmod.qmod_variable import QBit
|
3
|
+
|
4
|
+
|
5
|
+
@qfunc(external=True)
|
6
|
+
def RESET(target: QBit) -> None:
|
7
|
+
"""
|
8
|
+
Resets the target qubit to the |0> state.
|
9
|
+
|
10
|
+
Performed by measuring the qubit and applying an X gate if necessary.
|
11
|
+
|
12
|
+
Args:
|
13
|
+
target: the qubit to reset
|
14
|
+
"""
|
15
|
+
pass
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import inspect
|
2
2
|
from abc import ABC
|
3
|
+
from collections.abc import Generator, Iterable
|
3
4
|
from dataclasses import is_dataclass
|
4
5
|
from enum import Enum as PythonEnum
|
5
6
|
from types import TracebackType
|
@@ -67,7 +68,10 @@ from classiq.qmod.qmod_variable import (
|
|
67
68
|
from classiq.qmod.quantum_callable import QCallable, QExpandableInterface
|
68
69
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
69
70
|
from classiq.qmod.type_attribute_remover import decl_without_type_attributes
|
70
|
-
from classiq.qmod.utilities import
|
71
|
+
from classiq.qmod.utilities import (
|
72
|
+
mangle_keyword,
|
73
|
+
qmod_val_to_expr_str,
|
74
|
+
)
|
71
75
|
|
72
76
|
ArgType = Union[CParam, QVar, QCallable]
|
73
77
|
|
@@ -371,11 +375,14 @@ def prepare_arg(
|
|
371
375
|
def _validate_classical_arg(
|
372
376
|
arg: Any, arg_decl: AnonClassicalParameterDeclaration, func_name: Optional[str]
|
373
377
|
) -> None:
|
374
|
-
is_native_or_compatible_type =
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
378
|
+
is_native_or_compatible_type = (
|
379
|
+
not isinstance(
|
380
|
+
arg,
|
381
|
+
(*NativePythonClassicalTypes, CParam, SymbolicExpr, Basic, PythonEnum),
|
382
|
+
)
|
383
|
+
and not _is_legal_iterable(arg)
|
384
|
+
and not is_dataclass(arg) # type: ignore[unreachable]
|
385
|
+
)
|
379
386
|
try:
|
380
387
|
is_pydantic_classical_type = isinstance(
|
381
388
|
arg, pydantic.BaseModel
|
@@ -481,3 +488,20 @@ def _create_quantum_function_call(
|
|
481
488
|
return QuantumFunctionCall(
|
482
489
|
function=function_ident, positional_args=prepared_args, source_ref=source_ref_
|
483
490
|
)
|
491
|
+
|
492
|
+
|
493
|
+
_FORBIDDEN_ITERABLES = (set, dict, str, Generator)
|
494
|
+
|
495
|
+
|
496
|
+
def _is_legal_iterable(arg: Any) -> bool:
|
497
|
+
if not isinstance(arg, Iterable) or isinstance(arg, _FORBIDDEN_ITERABLES):
|
498
|
+
return False
|
499
|
+
return all(_is_legal_iterable_element(e) for e in arg)
|
500
|
+
|
501
|
+
|
502
|
+
def _is_legal_iterable_element(arg: Any) -> bool:
|
503
|
+
if isinstance(arg, _FORBIDDEN_ITERABLES):
|
504
|
+
return False
|
505
|
+
if isinstance(arg, Iterable):
|
506
|
+
return all(_is_legal_iterable_element(e) for e in arg)
|
507
|
+
return True
|
classiq/qmod/quantum_function.py
CHANGED
@@ -31,6 +31,7 @@ from classiq.qmod.qmod_parameter import CArray, CParam
|
|
31
31
|
from classiq.qmod.qmod_variable import QVar
|
32
32
|
from classiq.qmod.quantum_callable import QCallable, QCallableList
|
33
33
|
from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
|
34
|
+
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
34
35
|
from classiq.qmod.utilities import mangle_keyword
|
35
36
|
|
36
37
|
|
@@ -161,6 +162,9 @@ class QFunc(BaseQFunc):
|
|
161
162
|
)
|
162
163
|
|
163
164
|
generative_functions = list(self._qmodule.generative_functions.values())
|
165
|
+
QStructAnnotator().visit(model_stub)
|
166
|
+
for gen_func in generative_functions:
|
167
|
+
QStructAnnotator().visit(gen_func.func_decl)
|
164
168
|
resolve_function_calls(
|
165
169
|
model_stub,
|
166
170
|
dict(model_stub.function_dict)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from collections.abc import Iterator, Mapping
|
2
2
|
from contextlib import contextmanager
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any, Optional
|
4
4
|
|
5
5
|
from classiq.interface.exceptions import ClassiqError
|
6
6
|
from classiq.interface.generator.expressions.expression import Expression
|
@@ -11,6 +11,7 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
11
11
|
from classiq.interface.model.classical_parameter_declaration import (
|
12
12
|
ClassicalParameterDeclaration,
|
13
13
|
)
|
14
|
+
from classiq.interface.model.model import Model
|
14
15
|
from classiq.interface.model.model_visitor import ModelVisitor
|
15
16
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
16
17
|
from classiq.interface.model.port_declaration import PortDeclaration
|
@@ -108,8 +109,13 @@ class _CallLambdaAnnotator(ModelVisitor):
|
|
108
109
|
|
109
110
|
def resolve_function_calls(
|
110
111
|
root: Any,
|
111
|
-
quantum_function_dict: Mapping[str, QuantumFunctionDeclaration],
|
112
|
+
quantum_function_dict: Optional[Mapping[str, QuantumFunctionDeclaration]] = None,
|
112
113
|
) -> None:
|
114
|
+
if quantum_function_dict is None:
|
115
|
+
quantum_function_dict = {}
|
116
|
+
quantum_function_dict = dict(quantum_function_dict)
|
117
|
+
if isinstance(root, Model):
|
118
|
+
quantum_function_dict |= root.function_dict
|
113
119
|
all_functions: Mapping[str, QuantumFunctionDeclaration] = {
|
114
120
|
**BUILTIN_FUNCTION_DECLARATIONS,
|
115
121
|
**quantum_function_dict,
|
@@ -0,0 +1,9 @@
|
|
1
|
+
from classiq.interface.model.model import Model
|
2
|
+
|
3
|
+
from classiq.qmod.semantics.annotation.call_annotation import resolve_function_calls
|
4
|
+
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
5
|
+
|
6
|
+
|
7
|
+
def annotate_model(model: Model) -> None:
|
8
|
+
QStructAnnotator().visit(model)
|
9
|
+
resolve_function_calls(model)
|