classiq 0.100.0__py3-none-any.whl → 0.104.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/__init__.py +3 -0
- classiq/_internals/api_wrapper.py +29 -4
- classiq/applications/chemistry/op_utils.py +63 -1
- classiq/applications/chemistry/problems.py +18 -6
- classiq/applications/chemistry/ucc.py +2 -2
- classiq/evaluators/parameter_types.py +1 -4
- classiq/evaluators/qmod_annotated_expression.py +1 -1
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +1 -8
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +1 -1
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +18 -29
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +1 -6
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -7
- classiq/evaluators/qmod_node_evaluators/utils.py +6 -3
- classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
- classiq/execution/__init__.py +11 -1
- classiq/execution/execution_session.py +1 -1
- classiq/execution/functions/__init__.py +3 -0
- classiq/execution/functions/_logging.py +19 -0
- classiq/execution/functions/constants.py +9 -0
- classiq/execution/functions/parse_provider_backend.py +90 -0
- classiq/execution/functions/sample.py +257 -0
- classiq/execution/jobs.py +122 -5
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +15 -0
- classiq/interface/backend/provider_config/providers/aqt.py +1 -1
- classiq/interface/backend/provider_config/providers/azure.py +1 -2
- classiq/interface/backend/provider_config/providers/ibm.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +3 -0
- classiq/interface/exceptions.py +0 -42
- classiq/interface/executor/execution_request.py +1 -0
- classiq/interface/executor/quantum_code.py +0 -6
- classiq/interface/executor/result.py +9 -5
- classiq/interface/generator/arith/binary_ops.py +38 -2
- classiq/interface/generator/function_param_list.py +4 -2
- classiq/interface/generator/functions/builtins/internal_operators.py +5 -9
- classiq/interface/generator/functions/classical_type.py +45 -0
- classiq/interface/generator/functions/type_name.py +23 -0
- classiq/interface/generator/generated_circuit_data.py +0 -2
- classiq/interface/generator/generation_request.py +9 -4
- classiq/interface/generator/quantum_program.py +8 -36
- classiq/interface/generator/types/compilation_metadata.py +9 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/helpers/model_normalizer.py +62 -2
- classiq/interface/helpers/text_utils.py +17 -6
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/invert.py +15 -0
- classiq/interface/model/model.py +42 -3
- classiq/interface/model/model_visitor.py +4 -2
- classiq/interface/model/quantum_function_call.py +17 -5
- classiq/interface/model/quantum_type.py +21 -0
- classiq/interface/model/statement_block.py +0 -4
- classiq/model_expansions/capturing/captured_vars.py +16 -12
- classiq/model_expansions/function_builder.py +9 -1
- classiq/model_expansions/interpreters/base_interpreter.py +12 -10
- classiq/model_expansions/interpreters/generative_interpreter.py +9 -24
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -0
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +132 -28
- classiq/model_expansions/quantum_operations/bind.py +4 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +5 -35
- classiq/model_expansions/quantum_operations/emitter.py +1 -4
- classiq/model_expansions/quantum_operations/expression_evaluator.py +0 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +15 -47
- classiq/open_library/functions/__init__.py +42 -27
- classiq/open_library/functions/bit_operations.py +30 -0
- classiq/open_library/functions/modular_arithmetics.py +597 -0
- classiq/open_library/functions/qft_space_arithmetics.py +81 -0
- classiq/open_library/functions/state_preparation.py +6 -3
- classiq/open_library/functions/utility_functions.py +22 -3
- classiq/qmod/builtins/functions/__init__.py +9 -0
- classiq/qmod/builtins/functions/arithmetic.py +131 -0
- classiq/qmod/builtins/functions/exponentiation.py +34 -4
- classiq/qmod/builtins/operations.py +30 -41
- classiq/qmod/native/pretty_printer.py +12 -12
- classiq/qmod/pretty_print/pretty_printer.py +11 -15
- classiq/qmod/qmod_parameter.py +4 -0
- classiq/qmod/qmod_variable.py +38 -63
- classiq/qmod/quantum_callable.py +8 -2
- classiq/qmod/quantum_expandable.py +3 -1
- classiq/qmod/quantum_function.py +45 -8
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +7 -4
- classiq/qmod/semantics/validation/model_validation.py +7 -2
- classiq/qmod/symbolic_type.py +4 -2
- classiq/qmod/utilities.py +7 -4
- classiq/synthesis_action/__init__.py +20 -0
- classiq/synthesis_action/actions.py +106 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/METADATA +1 -1
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/RECORD +90 -84
- classiq/interface/executor/register_initialization.py +0 -36
- classiq/interface/generator/amplitude_loading.py +0 -103
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
- classiq/open_library/functions/modular_exponentiation.py +0 -272
- classiq/open_library/functions/qsvt_temp.py +0 -536
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/WHEEL +0 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -4,13 +4,13 @@ from typing import Annotated
|
|
|
4
4
|
from classiq.interface.exceptions import ClassiqDeprecationWarning
|
|
5
5
|
|
|
6
6
|
from classiq.open_library.functions.qft_functions import qft
|
|
7
|
-
from classiq.qmod.builtins.functions.standard_gates import PHASE, H
|
|
7
|
+
from classiq.qmod.builtins.functions.standard_gates import PHASE, SWAP, H
|
|
8
8
|
from classiq.qmod.builtins.operations import bind, repeat, within_apply
|
|
9
9
|
from classiq.qmod.cparam import CInt
|
|
10
|
-
from classiq.qmod.qfunc import qfunc
|
|
10
|
+
from classiq.qmod.qfunc import qfunc, qperm
|
|
11
11
|
from classiq.qmod.qmod_variable import QArray, QBit, QCallable, QNum
|
|
12
12
|
from classiq.qmod.quantum_callable import QCallableList
|
|
13
|
-
from classiq.qmod.symbolic import pi
|
|
13
|
+
from classiq.qmod.symbolic import min, pi
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@qfunc
|
|
@@ -50,6 +50,25 @@ def hadamard_transform(target: QArray[QBit]) -> None:
|
|
|
50
50
|
repeat(target.len, lambda index: H(target[index]))
|
|
51
51
|
|
|
52
52
|
|
|
53
|
+
@qperm
|
|
54
|
+
def multiswap(x: QArray[QBit], y: QArray[QBit]) -> None:
|
|
55
|
+
"""
|
|
56
|
+
[Qmod Classiq-library function]
|
|
57
|
+
|
|
58
|
+
Swaps the qubit states between two arrays.
|
|
59
|
+
Qubits of respective indices are swapped, and additional qubits in the longer array are left unchanged.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
x: The first array
|
|
63
|
+
y: The second array
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
repeat(
|
|
67
|
+
count=min(x.len, y.len),
|
|
68
|
+
iteration=lambda index: SWAP(x[index], y[index]),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
53
72
|
@qfunc
|
|
54
73
|
def switch(selector: CInt, cases: QCallableList) -> None:
|
|
55
74
|
cases[selector]()
|
|
@@ -48,6 +48,10 @@ CORE_LIB_DECLS = [
|
|
|
48
48
|
integer_xor,
|
|
49
49
|
modular_add_constant,
|
|
50
50
|
real_xor_constant,
|
|
51
|
+
multiply,
|
|
52
|
+
multiply_constant,
|
|
53
|
+
canonical_multiply,
|
|
54
|
+
canonical_multiply_constant,
|
|
51
55
|
U,
|
|
52
56
|
CCX,
|
|
53
57
|
free,
|
|
@@ -61,6 +65,7 @@ CORE_LIB_DECLS = [
|
|
|
61
65
|
commuting_paulis_exponent,
|
|
62
66
|
suzuki_trotter,
|
|
63
67
|
unscheduled_suzuki_trotter,
|
|
68
|
+
sequential_suzuki_trotter,
|
|
64
69
|
exponentiate,
|
|
65
70
|
multi_suzuki_trotter,
|
|
66
71
|
parametric_suzuki_trotter,
|
|
@@ -111,6 +116,10 @@ __all__ = [ # noqa: RUF022
|
|
|
111
116
|
"add_inplace_right",
|
|
112
117
|
"apply",
|
|
113
118
|
"exponentiation_with_depth_constraint",
|
|
119
|
+
"multiply",
|
|
120
|
+
"multiply_constant",
|
|
121
|
+
"canonical_multiply",
|
|
122
|
+
"canonical_multiply_constant",
|
|
114
123
|
"free",
|
|
115
124
|
"drop",
|
|
116
125
|
"inplace_prepare_amplitudes",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import Literal
|
|
2
2
|
|
|
3
|
+
from classiq.qmod.cparam import CInt
|
|
3
4
|
from classiq.qmod.qfunc import qfunc, qperm
|
|
4
5
|
from classiq.qmod.qmod_parameter import CArray, CBool, CReal
|
|
5
6
|
from classiq.qmod.qmod_variable import (
|
|
@@ -83,3 +84,133 @@ def integer_xor(left: Const[QArray[QBit]], right: QArray[QBit]) -> None:
|
|
|
83
84
|
@qperm(external=True)
|
|
84
85
|
def real_xor_constant(left: CReal, right: QNum) -> None:
|
|
85
86
|
pass
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@qperm(external=True)
|
|
90
|
+
def multiply(left: Const[QNum], right: Const[QNum], result: Output[QNum]) -> None:
|
|
91
|
+
"""
|
|
92
|
+
[Qmod core-library function]
|
|
93
|
+
|
|
94
|
+
Multiplies two quantum numeric variables:
|
|
95
|
+
|
|
96
|
+
$$
|
|
97
|
+
\\left|\\text{left}\\right\\rangle \\left|\\text{right}\\right\\rangle
|
|
98
|
+
\\mapsto
|
|
99
|
+
\\left|\\text{left}\\right\\rangle \\left|\\text{right}\\right\\rangle
|
|
100
|
+
\\left|\\text{left} \\cdot \\text{right} \\right\\rangle
|
|
101
|
+
$$
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
left: The first argument for the multiplication.
|
|
105
|
+
right: The second argument for the multiplication.
|
|
106
|
+
result: The quantum variable to hold the multiplication result.
|
|
107
|
+
"""
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@qperm(external=True)
|
|
112
|
+
def multiply_constant(left: CReal, right: Const[QNum], result: Output[QNum]) -> None:
|
|
113
|
+
"""
|
|
114
|
+
[Qmod core-library function]
|
|
115
|
+
|
|
116
|
+
Multiplies a quantum numeric variable with a constant:
|
|
117
|
+
|
|
118
|
+
$$
|
|
119
|
+
\\left|\\text{right}\\right\\rangle
|
|
120
|
+
\\mapsto
|
|
121
|
+
\\left|\\text{right}\\right\\rangle
|
|
122
|
+
\\left|\\text{left} \\cdot \\text{right} \\right\\rangle
|
|
123
|
+
$$
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
left: The constant argument for the multiplication.
|
|
127
|
+
right: The variable argument for the multiplication.
|
|
128
|
+
result: The quantum variable to hold the multiplication result.
|
|
129
|
+
"""
|
|
130
|
+
pass
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@qperm(external=True)
|
|
134
|
+
def canonical_multiply(
|
|
135
|
+
left: Const[QArray],
|
|
136
|
+
extend_left: CBool,
|
|
137
|
+
right: Const[QArray],
|
|
138
|
+
extend_right: CBool,
|
|
139
|
+
result: QArray,
|
|
140
|
+
trim_result_lsb: CBool,
|
|
141
|
+
) -> None:
|
|
142
|
+
"""
|
|
143
|
+
[Qmod core-library function]
|
|
144
|
+
|
|
145
|
+
Multiplies two quantum variables representing integers (signed or unsigned) into the
|
|
146
|
+
result variable which is assumed to start in the $|0\\rangle$ state.
|
|
147
|
+
|
|
148
|
+
If `trim_result_lsb` is `False`, applies the transformation:
|
|
149
|
+
|
|
150
|
+
$$
|
|
151
|
+
\\left|\\text{left}\\right\\rangle \\left|\\text{right}\\right\\rangle
|
|
152
|
+
\\left|0\\right\\rangle \\mapsto \\left|\\text{left}\\right\\rangle
|
|
153
|
+
\\left|\\text{right}\\right\\rangle \\left|\\left( \\text{left} \\cdot
|
|
154
|
+
\\text{right} \\right) \\bmod 2^{\\text{result.size}} \\right\\rangle
|
|
155
|
+
$$
|
|
156
|
+
|
|
157
|
+
If `trim_result_lsb` is `True`, the function avoids computing the result's LSB and
|
|
158
|
+
applies the transformation:
|
|
159
|
+
|
|
160
|
+
$$
|
|
161
|
+
\\left|\\text{left}\\right\\rangle \\left|\\text{right}\\right\\rangle
|
|
162
|
+
\\left|0\\right\\rangle \\mapsto \\left|\\text{left}\\right\\rangle
|
|
163
|
+
\\left|\\text{right}\\right\\rangle \\left|\\left( \\text{left} \\cdot
|
|
164
|
+
\\text{right} \\right) \\gg 1 \\bmod 2^{\\text{result.size}} \\right\\rangle
|
|
165
|
+
$$
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
left: The first argument for the multiplication.
|
|
169
|
+
extend_left: Whether to sign-extend the left argument.
|
|
170
|
+
right: The second argument for the multiplication.
|
|
171
|
+
extend_right: Whether to sign-extend the right argument.
|
|
172
|
+
result: The quantum variable to hold the multiplication result.
|
|
173
|
+
trim_result_lsb: Whether to avoid computing the result's LSB.
|
|
174
|
+
"""
|
|
175
|
+
pass
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@qperm(external=True)
|
|
179
|
+
def canonical_multiply_constant(
|
|
180
|
+
left: CInt,
|
|
181
|
+
right: Const[QArray],
|
|
182
|
+
extend_right: CBool,
|
|
183
|
+
result: QArray,
|
|
184
|
+
trim_result_lsb: CBool,
|
|
185
|
+
) -> None:
|
|
186
|
+
"""
|
|
187
|
+
[Qmod core-library function]
|
|
188
|
+
|
|
189
|
+
Multiplies a quantum variable representing an integer (signed or unsigned) with a
|
|
190
|
+
constant, into the result variable which is assumed to start in the $|0\\rangle$ state.
|
|
191
|
+
|
|
192
|
+
If `trim_result_lsb` is `False`, applies the transformation:
|
|
193
|
+
|
|
194
|
+
$$
|
|
195
|
+
\\left|\\text{right}\\right\\rangle \\left|0\\right\\rangle \\mapsto
|
|
196
|
+
\\left|\\text{right}\\right\\rangle \\left|\\left( \\text{left} \\cdot
|
|
197
|
+
\\text{right} \\right) \\bmod 2^{\\text{result.size}} \\right\\rangle
|
|
198
|
+
$$
|
|
199
|
+
|
|
200
|
+
If `trim_result_lsb` is `True`, the function avoids computing the result's LSB and
|
|
201
|
+
applies the transformation:
|
|
202
|
+
|
|
203
|
+
$$
|
|
204
|
+
\\left|\\text{right}\\right\\rangle \\left|0\\right\\rangle \\mapsto
|
|
205
|
+
\\left|\\text{right}\\right\\rangle \\left|\\left( \\text{left} \\cdot
|
|
206
|
+
\\text{right} \\right) \\gg 1 \\bmod 2^{\\text{result.size}} \\right\\rangle
|
|
207
|
+
$$
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
left: The constant argument for the multiplication.
|
|
211
|
+
right: The variable argument for the multiplication.
|
|
212
|
+
extend_right: Whether to sign-extend the right argument.
|
|
213
|
+
result: The quantum variable to hold the multiplication result.
|
|
214
|
+
trim_result_lsb: Whether to avoid computing the result's LSB.
|
|
215
|
+
"""
|
|
216
|
+
pass
|
|
@@ -99,7 +99,7 @@ def multi_suzuki_trotter(
|
|
|
99
99
|
The error of a Suzuki-Trotter decomposition decreases as the order and number of repetitions increase.
|
|
100
100
|
|
|
101
101
|
Args:
|
|
102
|
-
hamiltonians: The
|
|
102
|
+
hamiltonians: The hamiltonians to be exponentiated, in sparse representation.
|
|
103
103
|
evolution_coefficients: The hamiltonian coefficients (can be link-time).
|
|
104
104
|
order: The order of the Suzuki-Trotter decomposition.
|
|
105
105
|
repetitions: The number of repetitions of the Suzuki-Trotter decomposition.
|
|
@@ -129,7 +129,37 @@ def unscheduled_suzuki_trotter(
|
|
|
129
129
|
The error of a Suzuki-Trotter decomposition decreases as the order and number of repetitions increase.
|
|
130
130
|
|
|
131
131
|
Args:
|
|
132
|
-
hamiltonians: The
|
|
132
|
+
hamiltonians: The hamiltonians to be exponentiated, in sparse representation.
|
|
133
|
+
evolution_coefficients: The hamiltonian coefficients (can be link-time).
|
|
134
|
+
order: The order of the Suzuki-Trotter decomposition.
|
|
135
|
+
repetitions: The number of repetitions of the Suzuki-Trotter decomposition.
|
|
136
|
+
qbv: The target quantum variable of the exponentiation.
|
|
137
|
+
"""
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@qfunc(external=True)
|
|
142
|
+
def sequential_suzuki_trotter(
|
|
143
|
+
hamiltonians: CArray[SparsePauliOp],
|
|
144
|
+
evolution_coefficients: CArray[CReal],
|
|
145
|
+
order: CInt,
|
|
146
|
+
repetitions: CInt,
|
|
147
|
+
qbv: QArray,
|
|
148
|
+
) -> None:
|
|
149
|
+
"""
|
|
150
|
+
[Qmod core-library function]
|
|
151
|
+
|
|
152
|
+
Applies the Suzuki-Trotter decomposition jointly to a sum of Hamiltonians
|
|
153
|
+
(represented as Pauli operators), each with its separate evolution coefficient,
|
|
154
|
+
approximating $\\exp{-iH_1t_1+H_2t_2+\\dots}$ with a specified order and number of
|
|
155
|
+
repetitions. Does not reorder the Pauli terms.
|
|
156
|
+
|
|
157
|
+
The Suzuki-Trotter decomposition is a method for approximating the exponential of a sum of operators by a product of exponentials of each operator.
|
|
158
|
+
The Suzuki-Trotter decomposition of a given order nullifies the error of the Taylor series expansion of the product of exponentials up to that order.
|
|
159
|
+
The error of a Suzuki-Trotter decomposition decreases as the order and number of repetitions increase.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
hamiltonians: The hamiltonians to be exponentiated, in sparse representation.
|
|
133
163
|
evolution_coefficients: The hamiltonian coefficients (can be link-time).
|
|
134
164
|
order: The order of the Suzuki-Trotter decomposition.
|
|
135
165
|
repetitions: The number of repetitions of the Suzuki-Trotter decomposition.
|
|
@@ -218,10 +248,10 @@ def sparse_suzuki_trotter(
|
|
|
218
248
|
|
|
219
249
|
@qfunc(external=True)
|
|
220
250
|
def qdrift(
|
|
221
|
-
pauli_operator: SparsePauliOp,
|
|
251
|
+
pauli_operator: SparsePauliOp,
|
|
222
252
|
evolution_coefficient: CReal,
|
|
223
253
|
num_qdrift: CInt,
|
|
224
|
-
qbv: QArray[QBit],
|
|
254
|
+
qbv: QArray[QBit, Literal["pauli_operator.num_qubits"]],
|
|
225
255
|
) -> None:
|
|
226
256
|
"""
|
|
227
257
|
[Qmod core-library function]
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
import sys
|
|
3
|
-
import warnings
|
|
4
3
|
from collections.abc import Callable, Mapping
|
|
5
4
|
from functools import wraps
|
|
6
5
|
from itertools import product
|
|
@@ -14,7 +13,7 @@ from typing import (
|
|
|
14
13
|
overload,
|
|
15
14
|
)
|
|
16
15
|
|
|
17
|
-
from classiq.interface.exceptions import
|
|
16
|
+
from classiq.interface.exceptions import ClassiqValueError
|
|
18
17
|
from classiq.interface.generator.expressions.expression import Expression
|
|
19
18
|
from classiq.interface.generator.functions.builtins.internal_operators import (
|
|
20
19
|
REPEAT_OPERATOR_NAME,
|
|
@@ -30,12 +29,9 @@ from classiq.interface.model.classical_parameter_declaration import (
|
|
|
30
29
|
ClassicalParameterDeclaration,
|
|
31
30
|
)
|
|
32
31
|
from classiq.interface.model.control import Control
|
|
33
|
-
from classiq.interface.model.invert import Invert
|
|
32
|
+
from classiq.interface.model.invert import BlockKind, Invert
|
|
34
33
|
from classiq.interface.model.phase_operation import PhaseOperation
|
|
35
34
|
from classiq.interface.model.power import Power
|
|
36
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
37
|
-
AmplitudeLoadingOperation,
|
|
38
|
-
)
|
|
39
35
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
40
36
|
ArithmeticOperation,
|
|
41
37
|
ArithmeticOperationKind,
|
|
@@ -49,6 +45,7 @@ from classiq.interface.model.repeat import Repeat
|
|
|
49
45
|
from classiq.interface.model.skip_control import SkipControl
|
|
50
46
|
from classiq.interface.model.statement_block import StatementBlock
|
|
51
47
|
from classiq.interface.model.within_apply_operation import WithinApply
|
|
48
|
+
from classiq.interface.source_reference import SourceReference
|
|
52
49
|
|
|
53
50
|
from classiq.qmod.builtins.functions import H, S
|
|
54
51
|
from classiq.qmod.generative import is_generative_mode
|
|
@@ -335,37 +332,6 @@ def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
|
335
332
|
)
|
|
336
333
|
|
|
337
334
|
|
|
338
|
-
@suppress_return_value
|
|
339
|
-
@qmod_statement
|
|
340
|
-
def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
341
|
-
"""
|
|
342
|
-
Perform an amplitude-encoding assignment operation on a quantum variable and a
|
|
343
|
-
quantum expression.
|
|
344
|
-
|
|
345
|
-
Equivalent to `<target_var> *= <expression>`.
|
|
346
|
-
|
|
347
|
-
Args:
|
|
348
|
-
expression: A quantum arithmetic expression
|
|
349
|
-
target_var: A scalar quantum variable
|
|
350
|
-
"""
|
|
351
|
-
warnings.warn(
|
|
352
|
-
"The 'assign_amplitude' function is deprecated and will no longer be "
|
|
353
|
-
"supported starting on 2025-12-03 at the earliest. Use 'assign_amplitude_table' "
|
|
354
|
-
"instead",
|
|
355
|
-
ClassiqDeprecationWarning,
|
|
356
|
-
stacklevel=3,
|
|
357
|
-
)
|
|
358
|
-
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
359
|
-
source_ref = get_source_ref(sys._getframe(2))
|
|
360
|
-
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
361
|
-
AmplitudeLoadingOperation(
|
|
362
|
-
expression=Expression(expr=str(expression)),
|
|
363
|
-
result_var=target_var.get_handle_binding(),
|
|
364
|
-
source_ref=source_ref,
|
|
365
|
-
)
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
|
|
369
335
|
@suppress_return_value
|
|
370
336
|
@qmod_statement
|
|
371
337
|
def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
|
|
@@ -552,7 +518,7 @@ def power(
|
|
|
552
518
|
|
|
553
519
|
@suppress_return_value
|
|
554
520
|
@qmod_statement
|
|
555
|
-
def invert(stmt_block: QCallable | Callable[[], Statements]) ->
|
|
521
|
+
def invert(stmt_block: QCallable | Callable[[], Statements]) -> Any:
|
|
556
522
|
"""
|
|
557
523
|
Apply the inverse of a quantum gate.
|
|
558
524
|
|
|
@@ -574,11 +540,35 @@ def invert(stmt_block: QCallable | Callable[[], Statements]) -> None:
|
|
|
574
540
|
invert(qft(x))
|
|
575
541
|
```
|
|
576
542
|
"""
|
|
577
|
-
_validate_operand(stmt_block)
|
|
578
543
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
579
544
|
source_ref = get_source_ref(sys._getframe(2))
|
|
545
|
+
|
|
546
|
+
if (
|
|
547
|
+
isinstance(stmt_block, QCallable)
|
|
548
|
+
and len(stmt_block.func_decl.positional_arg_declarations) > 0
|
|
549
|
+
):
|
|
550
|
+
return lambda *args, **kwargs: _invert(
|
|
551
|
+
lambda: stmt_block( # type:ignore[call-arg]
|
|
552
|
+
*args, **kwargs, _source_ref=source_ref
|
|
553
|
+
),
|
|
554
|
+
source_ref,
|
|
555
|
+
BlockKind.SingleCall,
|
|
556
|
+
)
|
|
557
|
+
_invert(stmt_block, source_ref, BlockKind.Compound)
|
|
558
|
+
return None
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def _invert(
|
|
562
|
+
stmt_block: Callable[[], Statements],
|
|
563
|
+
source_ref: SourceReference,
|
|
564
|
+
block_kind: BlockKind,
|
|
565
|
+
) -> None:
|
|
566
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
567
|
+
_validate_operand(stmt_block)
|
|
580
568
|
invert_stmt = Invert(
|
|
581
|
-
body=_operand_to_body(stmt_block, "stmt_block"),
|
|
569
|
+
body=_operand_to_body(stmt_block, "stmt_block"),
|
|
570
|
+
block_kind=block_kind,
|
|
571
|
+
source_ref=source_ref,
|
|
582
572
|
)
|
|
583
573
|
if is_generative_mode():
|
|
584
574
|
invert_stmt.set_generative_block("body", stmt_block)
|
|
@@ -843,7 +833,6 @@ def lookup_table(func: RealFunction, targets: QNum | list[QNum]) -> list[float]:
|
|
|
843
833
|
__all__ = [
|
|
844
834
|
"allocate",
|
|
845
835
|
"assign",
|
|
846
|
-
"assign_amplitude",
|
|
847
836
|
"assign_amplitude_poly_sin",
|
|
848
837
|
"bind",
|
|
849
838
|
"block",
|
|
@@ -42,7 +42,7 @@ from classiq.interface.model.handle_binding import (
|
|
|
42
42
|
SubscriptHandleBinding,
|
|
43
43
|
)
|
|
44
44
|
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
|
45
|
-
from classiq.interface.model.invert import Invert
|
|
45
|
+
from classiq.interface.model.invert import BlockKind, Invert
|
|
46
46
|
from classiq.interface.model.model import Model
|
|
47
47
|
from classiq.interface.model.model_visitor import ModelVisitor
|
|
48
48
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
@@ -51,9 +51,6 @@ from classiq.interface.model.port_declaration import (
|
|
|
51
51
|
AnonPortDeclaration,
|
|
52
52
|
)
|
|
53
53
|
from classiq.interface.model.power import Power
|
|
54
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
55
|
-
AmplitudeLoadingOperation,
|
|
56
|
-
)
|
|
57
54
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
58
55
|
ArithmeticOperation,
|
|
59
56
|
ArithmeticOperationKind,
|
|
@@ -367,9 +364,17 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
367
364
|
return power_code
|
|
368
365
|
|
|
369
366
|
def visit_Invert(self, invert: Invert) -> str:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
367
|
+
invert.validate_node()
|
|
368
|
+
match invert.block_kind:
|
|
369
|
+
case BlockKind.SingleCall:
|
|
370
|
+
invert_code = f"{self._indent}invert "
|
|
371
|
+
invert_code += self.visit(invert.body[0]).lstrip()
|
|
372
|
+
case BlockKind.Compound:
|
|
373
|
+
invert_code = f"{self._indent}invert {{\n"
|
|
374
|
+
invert_code += self._visit_body(invert.body)
|
|
375
|
+
invert_code += f"{self._indent}}}\n"
|
|
376
|
+
case _:
|
|
377
|
+
raise ClassiqInternalError("Unknown block type")
|
|
373
378
|
return invert_code
|
|
374
379
|
|
|
375
380
|
def visit_Block(self, block: Block) -> str:
|
|
@@ -435,11 +440,6 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
435
440
|
op = "+="
|
|
436
441
|
return f"{self._indent}{self.visit(arith_op.result_var)} {op} {self.visit(arith_op.expression)};\n"
|
|
437
442
|
|
|
438
|
-
def visit_AmplitudeLoadingOperation(
|
|
439
|
-
self, amplitude_loading_op: AmplitudeLoadingOperation
|
|
440
|
-
) -> str:
|
|
441
|
-
return f"{self._indent}{self.visit(amplitude_loading_op.result_var)} *= {self.visit(amplitude_loading_op.expression)};\n"
|
|
442
|
-
|
|
443
443
|
def _print_bind_handles(self, handles: list[HandleBinding]) -> str:
|
|
444
444
|
if len(handles) == 1:
|
|
445
445
|
return self.visit(handles[0])
|
|
@@ -45,16 +45,13 @@ from classiq.interface.model.handle_binding import (
|
|
|
45
45
|
SubscriptHandleBinding,
|
|
46
46
|
)
|
|
47
47
|
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
|
48
|
-
from classiq.interface.model.invert import Invert
|
|
48
|
+
from classiq.interface.model.invert import BlockKind, Invert
|
|
49
49
|
from classiq.interface.model.model import Model
|
|
50
50
|
from classiq.interface.model.model_visitor import ModelVisitor
|
|
51
51
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
52
52
|
from classiq.interface.model.phase_operation import PhaseOperation
|
|
53
53
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
|
54
54
|
from classiq.interface.model.power import Power
|
|
55
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
56
|
-
AmplitudeLoadingOperation,
|
|
57
|
-
)
|
|
58
55
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
59
56
|
ArithmeticOperation,
|
|
60
57
|
ArithmeticOperationKind,
|
|
@@ -508,8 +505,17 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
508
505
|
return f"{self._indent}power({self.visit(power.power)}, {self._visit_body(power.body)})\n"
|
|
509
506
|
|
|
510
507
|
def visit_Invert(self, invert: Invert) -> str:
|
|
508
|
+
invert.validate_node()
|
|
511
509
|
self._imports["invert"] = 1
|
|
512
|
-
|
|
510
|
+
match invert.block_kind:
|
|
511
|
+
case BlockKind.SingleCall:
|
|
512
|
+
call_str = self.visit(invert.body[0])
|
|
513
|
+
call_str = call_str.replace("(", ")(", 1)
|
|
514
|
+
return f"{self._indent}invert({call_str}\n"
|
|
515
|
+
case BlockKind.Compound:
|
|
516
|
+
return f"{self._indent}invert({self._visit_body(invert.body)})\n"
|
|
517
|
+
case _:
|
|
518
|
+
raise ClassiqInternalError("Unknown block type")
|
|
513
519
|
|
|
514
520
|
def visit_Block(self, block: Block) -> str:
|
|
515
521
|
self._imports["block"] = 1
|
|
@@ -528,8 +534,6 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
528
534
|
for i, statement in enumerate(body):
|
|
529
535
|
if isinstance(statement, VariableDeclarationStatement):
|
|
530
536
|
code += self.visit_VariableDeclarationStatement(statement, walrus=True)
|
|
531
|
-
elif isinstance(statement, AmplitudeLoadingOperation):
|
|
532
|
-
code += self.visit_AmplitudeLoadingOperation(statement, in_lambda=True)
|
|
533
537
|
elif isinstance(statement, ArithmeticOperation):
|
|
534
538
|
code += self.visit_ArithmeticOperation(statement, in_lambda=True)
|
|
535
539
|
else:
|
|
@@ -587,14 +591,6 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
587
591
|
return f"{func}({self.visit(arith_op.expression)}, {self._indent}{self.visit(arith_op.result_var)})\n"
|
|
588
592
|
return f"{self._indent}{self.visit(arith_op.result_var)} {op} {self.visit(arith_op.expression)}\n"
|
|
589
593
|
|
|
590
|
-
def visit_AmplitudeLoadingOperation(
|
|
591
|
-
self, amplitude_loading_op: AmplitudeLoadingOperation, in_lambda: bool = False
|
|
592
|
-
) -> str:
|
|
593
|
-
if in_lambda:
|
|
594
|
-
self._imports["assign_amplitude"] = 1
|
|
595
|
-
return f"assign_amplitude({self.visit(amplitude_loading_op.expression)}, {self._indent}{self.visit(amplitude_loading_op.result_var)})\n"
|
|
596
|
-
return f"{self._indent}{self.visit(amplitude_loading_op.result_var)} *= {self.visit(amplitude_loading_op.expression)}\n"
|
|
597
|
-
|
|
598
594
|
def _print_bind_handles(self, handles: list[HandleBinding]) -> str:
|
|
599
595
|
if len(handles) == 1:
|
|
600
596
|
return self.visit(handles[0])
|
classiq/qmod/qmod_parameter.py
CHANGED
|
@@ -63,6 +63,10 @@ class CParamList(CParam):
|
|
|
63
63
|
else:
|
|
64
64
|
param_type = self._list_type.element_type
|
|
65
65
|
else:
|
|
66
|
+
if key.start is None:
|
|
67
|
+
key = slice(0, key.stop, None)
|
|
68
|
+
if key.stop is None:
|
|
69
|
+
key = slice(key.start, self.len, None)
|
|
66
70
|
if not isinstance(self._list_type, ClassicalTuple):
|
|
67
71
|
param_type = self._list_type
|
|
68
72
|
else:
|
classiq/qmod/qmod_variable.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
import sys
|
|
3
|
-
import warnings
|
|
4
3
|
from collections.abc import Iterator, Mapping
|
|
5
4
|
from contextlib import contextmanager
|
|
6
5
|
from typing import ( # type: ignore[attr-defined]
|
|
@@ -23,7 +22,6 @@ from typing import ( # type: ignore[attr-defined]
|
|
|
23
22
|
from typing_extensions import ParamSpec, Self, _AnnotatedAlias
|
|
24
23
|
|
|
25
24
|
from classiq.interface.exceptions import (
|
|
26
|
-
ClassiqDeprecationWarning,
|
|
27
25
|
ClassiqInternalError,
|
|
28
26
|
ClassiqNotImplementedError,
|
|
29
27
|
ClassiqValueError,
|
|
@@ -45,9 +43,6 @@ from classiq.interface.model.handle_binding import (
|
|
|
45
43
|
SlicedHandleBinding,
|
|
46
44
|
SubscriptHandleBinding,
|
|
47
45
|
)
|
|
48
|
-
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
|
49
|
-
AmplitudeLoadingOperation,
|
|
50
|
-
)
|
|
51
46
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
52
47
|
ArithmeticOperation,
|
|
53
48
|
ArithmeticOperationKind,
|
|
@@ -161,37 +156,6 @@ class QVar(Symbolic):
|
|
|
161
156
|
def type_name(self) -> str:
|
|
162
157
|
return self.get_qmod_type().type_name
|
|
163
158
|
|
|
164
|
-
|
|
165
|
-
class QmodExpressionCreator(Protocol):
|
|
166
|
-
"""
|
|
167
|
-
A callable that creates a Qmod expression from the provided QVars.
|
|
168
|
-
"""
|
|
169
|
-
|
|
170
|
-
def __call__(self, **kwargs: QVar) -> SymbolicExpr: ...
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
_Q = TypeVar("_Q", bound=QVar)
|
|
174
|
-
Output = Annotated[_Q, PortDeclarationDirection.Output]
|
|
175
|
-
Input = Annotated[_Q, PortDeclarationDirection.Input]
|
|
176
|
-
Const = Annotated[
|
|
177
|
-
_Q, TypeModifier.Const
|
|
178
|
-
] # A constant variable, up to a phase dependent on the computational basis state
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
class QScalar(QVar, SymbolicExpr):
|
|
182
|
-
CONSTRUCTOR_DEPTH: int = 2
|
|
183
|
-
|
|
184
|
-
def __init__(
|
|
185
|
-
self,
|
|
186
|
-
origin: None | str | HandleBinding = None,
|
|
187
|
-
*,
|
|
188
|
-
_expr_str: str | None = None,
|
|
189
|
-
depth: int = 2,
|
|
190
|
-
) -> None:
|
|
191
|
-
origin = _infer_variable_name(origin, self.CONSTRUCTOR_DEPTH)
|
|
192
|
-
QVar.__init__(self, origin, expr_str=_expr_str, depth=depth)
|
|
193
|
-
SymbolicExpr.__init__(self, str(origin), True)
|
|
194
|
-
|
|
195
159
|
def _insert_arith_operation(
|
|
196
160
|
self,
|
|
197
161
|
expr: SymbolicTypes,
|
|
@@ -210,19 +174,6 @@ class QScalar(QVar, SymbolicExpr):
|
|
|
210
174
|
)
|
|
211
175
|
)
|
|
212
176
|
|
|
213
|
-
def _insert_amplitude_loading(
|
|
214
|
-
self, expr: SymbolicTypes, source_ref: SourceReference
|
|
215
|
-
) -> None:
|
|
216
|
-
if TYPE_CHECKING:
|
|
217
|
-
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
218
|
-
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
|
219
|
-
AmplitudeLoadingOperation(
|
|
220
|
-
expression=Expression(expr=str(expr)),
|
|
221
|
-
result_var=self.get_handle_binding(),
|
|
222
|
-
source_ref=source_ref,
|
|
223
|
-
)
|
|
224
|
-
)
|
|
225
|
-
|
|
226
177
|
def __ior__(self, other: Any) -> Self:
|
|
227
178
|
if not isinstance(other, SYMBOLIC_TYPES):
|
|
228
179
|
raise ClassiqValueError(
|
|
@@ -245,6 +196,37 @@ class QScalar(QVar, SymbolicExpr):
|
|
|
245
196
|
)
|
|
246
197
|
return self
|
|
247
198
|
|
|
199
|
+
|
|
200
|
+
class QmodExpressionCreator(Protocol):
|
|
201
|
+
"""
|
|
202
|
+
A callable that creates a Qmod expression from the provided QVars.
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
def __call__(self, **kwargs: QVar) -> SymbolicExpr: ...
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
_Q = TypeVar("_Q", bound=QVar)
|
|
209
|
+
Output = Annotated[_Q, PortDeclarationDirection.Output]
|
|
210
|
+
Input = Annotated[_Q, PortDeclarationDirection.Input]
|
|
211
|
+
Const = Annotated[
|
|
212
|
+
_Q, TypeModifier.Const
|
|
213
|
+
] # A constant variable, up to a phase dependent on the computational basis state
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class QScalar(QVar, SymbolicExpr):
|
|
217
|
+
CONSTRUCTOR_DEPTH: int = 2
|
|
218
|
+
|
|
219
|
+
def __init__(
|
|
220
|
+
self,
|
|
221
|
+
origin: None | str | HandleBinding = None,
|
|
222
|
+
*,
|
|
223
|
+
_expr_str: str | None = None,
|
|
224
|
+
depth: int = 2,
|
|
225
|
+
) -> None:
|
|
226
|
+
origin = _infer_variable_name(origin, self.CONSTRUCTOR_DEPTH)
|
|
227
|
+
QVar.__init__(self, origin, expr_str=_expr_str, depth=depth)
|
|
228
|
+
SymbolicExpr.__init__(self, str(origin), True)
|
|
229
|
+
|
|
248
230
|
def __iadd__(self, other: Any) -> Self:
|
|
249
231
|
if not isinstance(other, SYMBOLIC_TYPES):
|
|
250
232
|
raise ClassiqValueError(
|
|
@@ -256,21 +238,10 @@ class QScalar(QVar, SymbolicExpr):
|
|
|
256
238
|
)
|
|
257
239
|
return self
|
|
258
240
|
|
|
259
|
-
def __imul__(self, other: Any) ->
|
|
260
|
-
|
|
261
|
-
"
|
|
262
|
-
"starting on 2025-12-03 at the earliest. Use the 'assign_amplitude_table' "
|
|
263
|
-
"function instead",
|
|
264
|
-
ClassiqDeprecationWarning,
|
|
265
|
-
stacklevel=2,
|
|
241
|
+
def __imul__(self, other: Any) -> NoReturn:
|
|
242
|
+
raise ClassiqNotImplementedError(
|
|
243
|
+
f"{self.get_qmod_type().raw_qmod_type_name} does not support '*='"
|
|
266
244
|
)
|
|
267
|
-
if not isinstance(other, SYMBOLIC_TYPES):
|
|
268
|
-
raise ClassiqValueError(
|
|
269
|
-
f"Invalid argument {str(other)!r} for out of ampltiude encoding operation"
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
self._insert_amplitude_loading(other, get_source_ref(sys._getframe(1)))
|
|
273
|
-
return self
|
|
274
245
|
|
|
275
246
|
def __iand__(self, other: Any) -> NoReturn:
|
|
276
247
|
raise ClassiqNotImplementedError(
|
|
@@ -558,6 +529,10 @@ class QArray(ArrayBase[_P], QVar, NonSymbolicExpr):
|
|
|
558
529
|
def _get_slice(self, slice_: slice) -> Any:
|
|
559
530
|
if slice_.step is not None:
|
|
560
531
|
raise ClassiqValueError(ILLEGAL_SLICING_STEP_MSG)
|
|
532
|
+
if slice_.start is None:
|
|
533
|
+
slice_ = slice(0, slice_.stop, None)
|
|
534
|
+
if slice_.stop is None:
|
|
535
|
+
slice_ = slice(slice_.start, self.len, None)
|
|
561
536
|
if not isinstance(slice_.start, (int, SymbolicExpr)) or not isinstance(
|
|
562
537
|
slice_.stop, (int, SymbolicExpr)
|
|
563
538
|
):
|