classiq 0.86.1__py3-none-any.whl → 0.88.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/__init__.py +2 -0
- classiq/applications/__init__.py +1 -2
- classiq/applications/chemistry/hartree_fock.py +5 -1
- classiq/applications/chemistry/op_utils.py +2 -2
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +1 -1
- classiq/applications/combinatorial_helpers/encoding_mapping.py +11 -15
- classiq/applications/combinatorial_helpers/encoding_utils.py +6 -6
- classiq/applications/combinatorial_helpers/memory.py +4 -4
- classiq/applications/combinatorial_helpers/optimization_model.py +5 -5
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +6 -10
- classiq/applications/combinatorial_helpers/pyomo_utils.py +27 -26
- classiq/applications/combinatorial_helpers/sympy_utils.py +2 -2
- classiq/applications/combinatorial_helpers/transformations/encoding.py +4 -6
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +4 -4
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +2 -2
- classiq/applications/combinatorial_helpers/transformations/penalty_support.py +3 -3
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -0
- classiq/applications/hamiltonian/pauli_decomposition.py +34 -2
- classiq/evaluators/argument_types.py +15 -6
- classiq/evaluators/parameter_types.py +43 -39
- classiq/evaluators/qmod_annotated_expression.py +117 -17
- classiq/evaluators/qmod_expression_visitors/out_of_place_node_transformer.py +19 -0
- classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -5
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +66 -16
- classiq/evaluators/qmod_expression_visitors/qmod_expression_renamer.py +48 -26
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +65 -72
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +13 -6
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +175 -28
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +36 -19
- classiq/evaluators/qmod_node_evaluators/compare_evaluation.py +17 -5
- classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +24 -2
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +97 -0
- classiq/evaluators/qmod_node_evaluators/name_evaluation.py +11 -26
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +56 -0
- classiq/evaluators/qmod_node_evaluators/piecewise_evaluation.py +40 -0
- classiq/evaluators/qmod_node_evaluators/struct_instantiation_evaluation.py +3 -4
- classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +51 -24
- classiq/evaluators/qmod_node_evaluators/unary_op_evaluation.py +53 -9
- classiq/evaluators/qmod_node_evaluators/utils.py +28 -6
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +188 -0
- classiq/evaluators/qmod_type_inference/quantum_type_inference.py +330 -0
- classiq/evaluators/quantum_type_utils.py +0 -131
- classiq/evaluators/type_type_match.py +1 -1
- classiq/execution/execution_session.py +18 -3
- classiq/execution/qnn.py +4 -1
- classiq/execution/user_budgets.py +1 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +10 -30
- classiq/interface/backend/quantum_backend_providers.py +63 -52
- classiq/interface/execution/primitives.py +1 -0
- classiq/interface/generator/application_apis/__init__.py +0 -1
- classiq/interface/generator/arith/binary_ops.py +107 -115
- classiq/interface/generator/arith/extremum_operations.py +33 -45
- classiq/interface/generator/arith/number_utils.py +4 -1
- classiq/interface/generator/circuit_code/types_and_constants.py +0 -9
- classiq/interface/generator/compiler_keywords.py +2 -0
- classiq/interface/generator/expressions/atomic_expression_functions.py +0 -2
- classiq/interface/generator/function_param_list.py +129 -5
- classiq/interface/generator/functions/classical_type.py +67 -2
- classiq/interface/generator/functions/qmod_python_interface.py +15 -0
- classiq/interface/generator/functions/type_name.py +12 -0
- classiq/interface/generator/model/preferences/preferences.py +1 -17
- classiq/interface/generator/quantum_program.py +1 -13
- classiq/interface/generator/transpiler_basis_gates.py +5 -1
- classiq/interface/generator/types/builtin_enum_declarations.py +0 -8
- classiq/interface/helpers/model_normalizer.py +2 -2
- classiq/interface/helpers/text_utils.py +7 -2
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/classical_if.py +48 -0
- classiq/interface/model/classical_parameter_declaration.py +4 -0
- classiq/interface/model/handle_binding.py +28 -16
- classiq/interface/model/port_declaration.py +12 -0
- classiq/interface/model/quantum_function_declaration.py +12 -0
- classiq/interface/model/quantum_type.py +117 -2
- classiq/interface/pretty_print/expression_to_qmod.py +7 -8
- classiq/interface/pyomo_extension/__init__.py +0 -4
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +2 -2
- classiq/model_expansions/arithmetic.py +43 -1
- classiq/model_expansions/arithmetic_compute_result_attrs.py +255 -0
- classiq/model_expansions/capturing/captured_vars.py +2 -5
- classiq/model_expansions/quantum_operations/allocate.py +23 -16
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -3
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +52 -71
- classiq/model_expansions/quantum_operations/bind.py +15 -7
- classiq/model_expansions/quantum_operations/call_emitter.py +2 -10
- classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +2 -8
- classiq/open_library/functions/__init__.py +4 -0
- classiq/open_library/functions/lcu.py +117 -0
- classiq/open_library/functions/state_preparation.py +47 -5
- classiq/qmod/builtins/__init__.py +0 -3
- classiq/qmod/builtins/classical_functions.py +0 -28
- classiq/qmod/builtins/enums.py +26 -20
- classiq/qmod/builtins/functions/__init__.py +0 -5
- classiq/qmod/builtins/operations.py +142 -0
- classiq/qmod/builtins/structs.py +33 -29
- classiq/qmod/native/pretty_printer.py +1 -1
- classiq/qmod/pretty_print/expression_to_python.py +1 -6
- classiq/qmod/pretty_print/pretty_printer.py +4 -1
- classiq/qmod/qmod_variable.py +94 -2
- classiq/qmod/semantics/annotation/call_annotation.py +4 -2
- classiq/qmod/semantics/annotation/qstruct_annotator.py +20 -5
- {classiq-0.86.1.dist-info → classiq-0.88.0.dist-info}/METADATA +5 -5
- {classiq-0.86.1.dist-info → classiq-0.88.0.dist-info}/RECORD +106 -124
- classiq/applications/finance/__init__.py +0 -15
- classiq/interface/finance/finance_modelling_params.py +0 -11
- classiq/interface/finance/function_input.py +0 -102
- classiq/interface/finance/gaussian_model_input.py +0 -50
- classiq/interface/finance/log_normal_model_input.py +0 -40
- classiq/interface/finance/model_input.py +0 -22
- classiq/interface/generator/amplitude_estimation.py +0 -34
- classiq/interface/generator/application_apis/finance_declarations.py +0 -108
- classiq/interface/generator/expressions/enums/__init__.py +0 -0
- classiq/interface/generator/expressions/enums/finance_functions.py +0 -12
- classiq/interface/generator/finance.py +0 -107
- classiq/interface/generator/function_param_list_without_self_reference.py +0 -160
- classiq/interface/generator/grover_diffuser.py +0 -93
- classiq/interface/generator/grover_operator.py +0 -106
- classiq/interface/generator/oracles/__init__.py +0 -3
- classiq/interface/generator/oracles/arithmetic_oracle.py +0 -82
- classiq/interface/generator/oracles/custom_oracle.py +0 -65
- classiq/interface/generator/oracles/oracle_abc.py +0 -76
- classiq/interface/generator/oracles/oracle_function_param_list.py +0 -6
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +0 -165
- classiq/interface/generator/qpe.py +0 -169
- classiq/interface/grover/__init__.py +0 -0
- classiq/interface/grover/grover_modelling_params.py +0 -13
- classiq/model_expansions/transformers/var_splitter.py +0 -224
- classiq/qmod/builtins/functions/finance.py +0 -34
- /classiq/{interface/finance → evaluators/qmod_type_inference}/__init__.py +0 -0
- {classiq-0.86.1.dist-info → classiq-0.88.0.dist-info}/WHEEL +0 -0
|
@@ -54,38 +54,10 @@ def hypercube_entangler_graph(
|
|
|
54
54
|
)
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def gaussian_finance_post_process(
|
|
58
|
-
finance_model: GaussianModel,
|
|
59
|
-
estimation_method: FinanceFunction,
|
|
60
|
-
probability: CReal,
|
|
61
|
-
) -> CReal:
|
|
62
|
-
return symbolic_function(
|
|
63
|
-
finance_model,
|
|
64
|
-
estimation_method,
|
|
65
|
-
probability,
|
|
66
|
-
return_type=CReal, # type:ignore[type-abstract]
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def log_normal_finance_post_process(
|
|
71
|
-
finance_model: LogNormalModel,
|
|
72
|
-
estimation_method: FinanceFunction,
|
|
73
|
-
probability: CReal,
|
|
74
|
-
) -> CReal:
|
|
75
|
-
return symbolic_function(
|
|
76
|
-
finance_model,
|
|
77
|
-
estimation_method,
|
|
78
|
-
probability,
|
|
79
|
-
return_type=CReal, # type:ignore[type-abstract]
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
|
|
83
57
|
__all__ = [
|
|
84
58
|
"qft_const_adder_phase",
|
|
85
59
|
"fock_hamiltonian_problem_to_hamiltonian",
|
|
86
60
|
"molecule_problem_to_hamiltonian",
|
|
87
61
|
"grid_entangler_graph",
|
|
88
62
|
"hypercube_entangler_graph",
|
|
89
|
-
"gaussian_finance_post_process",
|
|
90
|
-
"log_normal_finance_post_process",
|
|
91
63
|
]
|
classiq/qmod/builtins/enums.py
CHANGED
|
@@ -135,13 +135,6 @@ class FermionMapping(IntEnum):
|
|
|
135
135
|
FAST_BRAVYI_KITAEV = 3
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
class FinanceFunctionType(IntEnum):
|
|
139
|
-
VAR = 0
|
|
140
|
-
SHORTFALL = 1
|
|
141
|
-
X_SQUARE = 2
|
|
142
|
-
EUROPEAN_CALL_OPTION = 3
|
|
143
|
-
|
|
144
|
-
|
|
145
138
|
class LadderOperator(IntEnum):
|
|
146
139
|
PLUS = 0
|
|
147
140
|
MINUS = 1
|
|
@@ -160,25 +153,39 @@ class Pauli(IntEnum):
|
|
|
160
153
|
"""
|
|
161
154
|
Enumeration for the Pauli matrices used in quantum computing.
|
|
162
155
|
|
|
163
|
-
|
|
164
|
-
|
|
156
|
+
Represents the four Pauli matrices used in quantum mechanics: Identity (I), X, Y, and Z operators.
|
|
157
|
+
The Pauli matrices are defined as:
|
|
158
|
+
|
|
159
|
+
$$
|
|
160
|
+
I = \\begin{pmatrix} 1 & 0 \\\\ 0 & 1 \\end{pmatrix}
|
|
161
|
+
$$
|
|
162
|
+
|
|
163
|
+
$$
|
|
164
|
+
X = \\begin{pmatrix} 0 & 1 \\\\ 1 & 0 \\end{pmatrix}
|
|
165
|
+
$$
|
|
166
|
+
|
|
167
|
+
$$
|
|
168
|
+
Y = \\begin{pmatrix} 0 & -i \\\\ i & 0 \\end{pmatrix}
|
|
169
|
+
$$
|
|
170
|
+
|
|
171
|
+
$$
|
|
172
|
+
Z = \\begin{pmatrix} 1 & 0 \\\\ 0 & -1 \\end{pmatrix}
|
|
173
|
+
$$
|
|
174
|
+
|
|
175
|
+
Attributes:
|
|
176
|
+
I (int): The identity operator (value 0).
|
|
177
|
+
X (int): The Pauli-X operator (value 1).
|
|
178
|
+
Y (int): The Pauli-Y operator (value 2).
|
|
179
|
+
Z (int): The Pauli-Z operator (value 3).
|
|
165
180
|
"""
|
|
166
181
|
|
|
167
182
|
I = 0 # noqa: E741
|
|
168
|
-
"""I (int): Identity matrix, represented by the integer 0. \n
|
|
169
|
-
$I = \\begin{bmatrix} 1 & 0 \\\\ 0 & 1 \\end{bmatrix}$"""
|
|
170
183
|
|
|
171
184
|
X = 1
|
|
172
|
-
"""X (int): Pauli-X matrix, represented by the integer 1. \n
|
|
173
|
-
$X = \\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$"""
|
|
174
185
|
|
|
175
186
|
Y = 2
|
|
176
|
-
"""Y (int): Pauli-Y matrix, represented by the integer 2. \n
|
|
177
|
-
$Y = \\begin{bmatrix} 0 & -i \\\\ i & 0 \\end{bmatrix}$"""
|
|
178
187
|
|
|
179
188
|
Z = 3
|
|
180
|
-
"""Z (int): Pauli-Z matrix, represented by the integer 3. \n
|
|
181
|
-
$Z = \\begin{bmatrix} 1 & 0 \\\\ 0 & -1 \\end{bmatrix}$"""
|
|
182
189
|
|
|
183
190
|
def __call__(self, index: int) -> "SparsePauliOp":
|
|
184
191
|
from classiq.qmod.builtins.structs import (
|
|
@@ -188,7 +195,7 @@ class Pauli(IntEnum):
|
|
|
188
195
|
)
|
|
189
196
|
|
|
190
197
|
return SparsePauliOp(
|
|
191
|
-
terms=[
|
|
198
|
+
terms=[
|
|
192
199
|
SparsePauliTerm(
|
|
193
200
|
paulis=[ # type:ignore[arg-type]
|
|
194
201
|
IndexedPauli(pauli=self, index=index) # type:ignore[arg-type]
|
|
@@ -196,7 +203,7 @@ class Pauli(IntEnum):
|
|
|
196
203
|
coefficient=1.0, # type:ignore[arg-type]
|
|
197
204
|
)
|
|
198
205
|
],
|
|
199
|
-
num_qubits=index + 1,
|
|
206
|
+
num_qubits=index + 1,
|
|
200
207
|
)
|
|
201
208
|
|
|
202
209
|
|
|
@@ -224,7 +231,6 @@ BUILTIN_ENUM_DECLARATIONS = {
|
|
|
224
231
|
__all__ = [
|
|
225
232
|
"Element",
|
|
226
233
|
"FermionMapping",
|
|
227
|
-
"FinanceFunctionType",
|
|
228
234
|
"LadderOperator",
|
|
229
235
|
"Optimizer",
|
|
230
236
|
"Pauli",
|
|
@@ -3,7 +3,6 @@ from .arithmetic import *
|
|
|
3
3
|
from .benchmarking import *
|
|
4
4
|
from .chemistry import *
|
|
5
5
|
from .exponentiation import *
|
|
6
|
-
from .finance import *
|
|
7
6
|
from .mid_circuit_measurement import *
|
|
8
7
|
from .operators import *
|
|
9
8
|
from .qsvm import *
|
|
@@ -18,8 +17,6 @@ CORE_LIB_DECLS = [
|
|
|
18
17
|
fock_hamiltonian_ucc,
|
|
19
18
|
fock_hamiltonian_hva,
|
|
20
19
|
fock_hamiltonian_hartree_fock,
|
|
21
|
-
log_normal_finance,
|
|
22
|
-
gaussian_finance,
|
|
23
20
|
pauli_feature_map,
|
|
24
21
|
bloch_sphere_feature_map,
|
|
25
22
|
H,
|
|
@@ -121,13 +118,11 @@ __all__ = [ # noqa: RUF022
|
|
|
121
118
|
"fock_hamiltonian_hva",
|
|
122
119
|
"fock_hamiltonian_ucc",
|
|
123
120
|
"free",
|
|
124
|
-
"gaussian_finance",
|
|
125
121
|
"inplace_prepare_amplitudes",
|
|
126
122
|
"inplace_prepare_amplitudes_approx",
|
|
127
123
|
"inplace_prepare_state",
|
|
128
124
|
"inplace_prepare_state_approx",
|
|
129
125
|
"integer_xor",
|
|
130
|
-
"log_normal_finance",
|
|
131
126
|
"modular_add",
|
|
132
127
|
"modular_add_constant",
|
|
133
128
|
"molecule_hartree_fock",
|
|
@@ -147,6 +147,22 @@ def bind(
|
|
|
147
147
|
source: Union[Input[QVar], list[Input[QVar]]],
|
|
148
148
|
destination: Union[Output[QVar], list[Output[QVar]]],
|
|
149
149
|
) -> None:
|
|
150
|
+
"""
|
|
151
|
+
Reassign qubit or arrays of qubits by redirecting their logical identifiers.
|
|
152
|
+
|
|
153
|
+
This operation rewires the logical identity of the `source` qubits to new objects given in `destination`.
|
|
154
|
+
For example, an array of two qubits `X` can be mapped to individual qubits `Y` and `Z`.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
source: A qubit or list of initialized qubits to reassign.
|
|
158
|
+
destination: A qubit or list of target qubits to bind to. Must match the number of qubits in `source`.
|
|
159
|
+
|
|
160
|
+
Notes:
|
|
161
|
+
- After this operation, `source` qubits are unbound and considered uninitialized.
|
|
162
|
+
- `source` and `destination` must be of the same length.
|
|
163
|
+
|
|
164
|
+
For more details, see [Qmod Reference](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/bind).
|
|
165
|
+
"""
|
|
150
166
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
151
167
|
source_ref = get_source_ref(sys._getframe(1))
|
|
152
168
|
if not isinstance(source, list):
|
|
@@ -168,6 +184,18 @@ def if_(
|
|
|
168
184
|
then: Union[QCallable, Callable[[], Statements]],
|
|
169
185
|
else_: Union[QCallable, Callable[[], Statements], int] = _MISSING_VALUE,
|
|
170
186
|
) -> None:
|
|
187
|
+
"""
|
|
188
|
+
Conditionally executes quantum operations based on a symbolic or boolean expression.
|
|
189
|
+
|
|
190
|
+
This function defines classical control flow within a quantum program. It allows quantum operations to be
|
|
191
|
+
conditionally executed based on symbolic expressions - such as parameters used in variational algorithms,
|
|
192
|
+
loop indices, or other classical variables affecting quantum control flow.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
condition: A symbolic or boolean expression evaluated at runtime to determine the execution path.
|
|
196
|
+
then: A quantum operation executed when `condition` evaluates to True.
|
|
197
|
+
else_: (Optional) A quantum operation executed when `condition` evaluates to False.
|
|
198
|
+
"""
|
|
171
199
|
_validate_operand(then)
|
|
172
200
|
if else_ != _MISSING_VALUE:
|
|
173
201
|
_validate_operand(else_)
|
|
@@ -193,6 +221,22 @@ def control(
|
|
|
193
221
|
stmt_block: Union[QCallable, Callable[[], Statements]],
|
|
194
222
|
else_block: Union[QCallable, Callable[[], Statements], None] = None,
|
|
195
223
|
) -> None:
|
|
224
|
+
"""
|
|
225
|
+
Conditionally executes quantum operations based on the value of quantum variables or expressions.
|
|
226
|
+
|
|
227
|
+
This operation enables quantum control flow similar to classical `if` statements. It evaluates a quantum condition
|
|
228
|
+
and executes one of the provided quantum code blocks accordingly.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
ctrl: A quantum control expression, which can be a logical expression, a single `QBit`, or a `QArray[QBit]`.
|
|
232
|
+
If `ctrl` is a logical expression, `stmt_block` is executed when it evaluates to `True`.
|
|
233
|
+
If `ctrl` is a `QBit` or `QArray[QBit]`, `stmt_block` is executed if all qubits are in the |1> state.
|
|
234
|
+
stmt_block: The quantum operations to execute when the condition holds. This can be a `QCallable` or a function
|
|
235
|
+
returning a `Statements` block.
|
|
236
|
+
else_block: (Optional) Quantum operations to execute when the condition does not hold.
|
|
237
|
+
|
|
238
|
+
For more details, see [Qmod Reference](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/control).
|
|
239
|
+
"""
|
|
196
240
|
_validate_operand(stmt_block)
|
|
197
241
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
198
242
|
source_ref = get_source_ref(sys._getframe(1))
|
|
@@ -308,6 +352,18 @@ def within_apply(
|
|
|
308
352
|
within: Callable[[], Statements],
|
|
309
353
|
apply: Callable[[], Statements],
|
|
310
354
|
) -> None:
|
|
355
|
+
r"""
|
|
356
|
+
Given two operations $U$ and $V$, performs the sequence of operations $U^{-1} V U$.
|
|
357
|
+
|
|
358
|
+
This operation is used to represent a sequence where the inverse gate `U^{-1}` is applied, followed by another operation `V`, and then `U` is applied to uncompute. This pattern is common in reversible
|
|
359
|
+
computation and quantum subroutines.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
within: The unitary operation `U` to be computed and then uncomputed.
|
|
363
|
+
apply: The operation `V` to be applied within the `U` block.
|
|
364
|
+
|
|
365
|
+
For more details, see [Qmod Reference](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/within-apply).
|
|
366
|
+
"""
|
|
311
367
|
_validate_operand(within)
|
|
312
368
|
_validate_operand(apply)
|
|
313
369
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
@@ -327,6 +383,29 @@ def within_apply(
|
|
|
327
383
|
def repeat(
|
|
328
384
|
count: Union[SymbolicExpr, int], iteration: Callable[[int], Statements]
|
|
329
385
|
) -> None:
|
|
386
|
+
"""
|
|
387
|
+
Executes a quantum loop a specified number of times, applying a quantum operation on each iteration.
|
|
388
|
+
|
|
389
|
+
This operation provides quantum control flow similar to a classical `for` loop, enabling repeated
|
|
390
|
+
application of quantum operations based on classical loop variables.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
count: An integer or symbolic expression specifying the number of loop iterations.
|
|
394
|
+
iteration: A callable that takes a single integer index and returns the quantum operations to
|
|
395
|
+
be performed at each iteration.
|
|
396
|
+
|
|
397
|
+
Example:
|
|
398
|
+
```python
|
|
399
|
+
from classiq import qfunc, Output, QArray, QBit, allocate, repeat, RX
|
|
400
|
+
from classiq.qmod.symbolic import pi
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@qfunc
|
|
404
|
+
def main(x: Output[QArray[QBit]]):
|
|
405
|
+
allocate(10, x)
|
|
406
|
+
repeat(x.len, lambda i: RX(2 * pi * i / x.len, x[i]))
|
|
407
|
+
```
|
|
408
|
+
"""
|
|
330
409
|
_validate_operand(iteration, num_params=1)
|
|
331
410
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
332
411
|
source_ref = get_source_ref(sys._getframe(1))
|
|
@@ -362,6 +441,34 @@ def power(
|
|
|
362
441
|
exponent: Union[SymbolicExpr, int],
|
|
363
442
|
stmt_block: Union[QCallable, Callable[[], Statements]],
|
|
364
443
|
) -> None:
|
|
444
|
+
"""
|
|
445
|
+
Apply a quantum operation raised to a symbolic or integer power.
|
|
446
|
+
|
|
447
|
+
This function enables exponentiation of a quantum gate, where the exponent can be a
|
|
448
|
+
symbolic expression or an integer. It is typically used within a quantum program
|
|
449
|
+
to repeat or scale quantum operations in a parameterized way.
|
|
450
|
+
|
|
451
|
+
Args:
|
|
452
|
+
exponent: The exponent value, either as an integer or a symbolic expression.
|
|
453
|
+
stmt_block: A callable that produces the quantum operation to be exponentiated.
|
|
454
|
+
|
|
455
|
+
Example:
|
|
456
|
+
```python
|
|
457
|
+
from classiq import qfunc, Output, QArray, QBit, allocate, repeat, RX, power
|
|
458
|
+
from classiq.qmod.symbolic import pi
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
@qfunc
|
|
462
|
+
def my_RX(x: QArray[QBit], i: CInt):
|
|
463
|
+
RX(2 * pi / x.len, x[i])
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
@qfunc
|
|
467
|
+
def main(x: Output[QArray[QBit]]):
|
|
468
|
+
allocate(10, x)
|
|
469
|
+
repeat(x.len, lambda i: power(i, lambda: my_RX(x, i)))
|
|
470
|
+
```
|
|
471
|
+
"""
|
|
365
472
|
_validate_operand(stmt_block)
|
|
366
473
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
367
474
|
source_ref = get_source_ref(sys._getframe(1))
|
|
@@ -377,6 +484,27 @@ def power(
|
|
|
377
484
|
|
|
378
485
|
@suppress_return_value
|
|
379
486
|
def invert(stmt_block: Union[QCallable, Callable[[], Statements]]) -> None:
|
|
487
|
+
"""
|
|
488
|
+
Apply the inverse of a quantum gate.
|
|
489
|
+
|
|
490
|
+
This function allows inversion of a quantum gate. It is typically used within a quantum program
|
|
491
|
+
to invert a sequence of operations.
|
|
492
|
+
|
|
493
|
+
Args:
|
|
494
|
+
stmt_block: A callable that produces the quantum operation to be inverted.
|
|
495
|
+
|
|
496
|
+
Example:
|
|
497
|
+
```python
|
|
498
|
+
from classiq import qfunc, Output, QArray, QBit, allocate, qft, invert
|
|
499
|
+
from classiq.qmod.symbolic import pi
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
@qfunc
|
|
503
|
+
def main(x: Output[QArray[QBit]]):
|
|
504
|
+
allocate(10, x)
|
|
505
|
+
invert(qft(x))
|
|
506
|
+
```
|
|
507
|
+
"""
|
|
380
508
|
_validate_operand(stmt_block)
|
|
381
509
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
382
510
|
source_ref = get_source_ref(sys._getframe(1))
|
|
@@ -390,6 +518,20 @@ def invert(stmt_block: Union[QCallable, Callable[[], Statements]]) -> None:
|
|
|
390
518
|
|
|
391
519
|
@suppress_return_value
|
|
392
520
|
def phase(expr: SymbolicExpr, theta: float = 1.0) -> None:
|
|
521
|
+
"""
|
|
522
|
+
Applies a state-dependent phase shift to the quantum state.
|
|
523
|
+
|
|
524
|
+
This operation multiplies each basis state |x> by a complex phase factor `theta * expr(x)`,
|
|
525
|
+
where `expr` is a symbolic expression dependent on the state value `x`, and `theta` is a scalar multiplier.
|
|
526
|
+
|
|
527
|
+
Args:
|
|
528
|
+
expr: A symbolic expression that evaluates to an angle (in radians) as a function of the quantum state value `x`.
|
|
529
|
+
theta: (Optional) A scalar multiplier for the evaluated expression. Defaults to 1.0.
|
|
530
|
+
|
|
531
|
+
Note:
|
|
532
|
+
The `phase` operation is equivalent to a Z-rotation up to a global phase. It is commonly used
|
|
533
|
+
to apply relative phase shifts conditioned on the quantum state.
|
|
534
|
+
"""
|
|
393
535
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
|
394
536
|
source_ref = get_source_ref(sys._getframe(1))
|
|
395
537
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
classiq/qmod/builtins/structs.py
CHANGED
|
@@ -63,27 +63,31 @@ class SparsePauliOp:
|
|
|
63
63
|
num_qubits (CInt): The number of qubits in the Hamiltonian.
|
|
64
64
|
"""
|
|
65
65
|
|
|
66
|
-
terms:
|
|
67
|
-
num_qubits:
|
|
66
|
+
terms: list[SparsePauliTerm]
|
|
67
|
+
num_qubits: int
|
|
68
68
|
|
|
69
69
|
def __mul__(self, obj: Union[float, "SparsePauliOp"]) -> "SparsePauliOp":
|
|
70
70
|
if isinstance(obj, (int, float, complex)):
|
|
71
71
|
return SparsePauliOp(
|
|
72
|
-
terms=[
|
|
72
|
+
terms=[
|
|
73
73
|
SparsePauliTerm(
|
|
74
74
|
paulis=term.paulis,
|
|
75
|
-
coefficient=obj * term.coefficient,
|
|
75
|
+
coefficient=obj * term.coefficient, # type:ignore[arg-type]
|
|
76
76
|
)
|
|
77
|
-
for term in self.terms
|
|
77
|
+
for term in self.terms
|
|
78
78
|
],
|
|
79
79
|
num_qubits=self.num_qubits,
|
|
80
80
|
)
|
|
81
|
-
if len(self.terms) != 1 or len(obj.terms) != 1:
|
|
81
|
+
if len(self.terms) != 1 or len(obj.terms) != 1:
|
|
82
82
|
raise ClassiqValueError("Cannot attach a pauli to multiple pauli terms")
|
|
83
83
|
existing_indices = {
|
|
84
|
-
indexed_pauli.index
|
|
84
|
+
indexed_pauli.index
|
|
85
|
+
for indexed_pauli in self.terms[0].paulis # type:ignore[attr-defined]
|
|
86
|
+
}
|
|
87
|
+
added_indices = {
|
|
88
|
+
indexed_pauli.index
|
|
89
|
+
for indexed_pauli in obj.terms[0].paulis # type:ignore[attr-defined]
|
|
85
90
|
}
|
|
86
|
-
added_indices = {indexed_pauli.index for indexed_pauli in obj.terms[0].paulis}
|
|
87
91
|
overlapping_indices = sorted(existing_indices.intersection(added_indices))
|
|
88
92
|
if len(overlapping_indices):
|
|
89
93
|
raise ClassiqValueError(
|
|
@@ -93,15 +97,15 @@ class SparsePauliOp:
|
|
|
93
97
|
f"already assigned"
|
|
94
98
|
)
|
|
95
99
|
return SparsePauliOp(
|
|
96
|
-
terms=[
|
|
100
|
+
terms=[
|
|
97
101
|
SparsePauliTerm(
|
|
98
|
-
paulis=self.terms[0].paulis
|
|
99
|
-
|
|
102
|
+
paulis=self.terms[0].paulis
|
|
103
|
+
+ obj.terms[0].paulis, # type:ignore[arg-type]
|
|
104
|
+
coefficient=self.terms[0].coefficient
|
|
105
|
+
* obj.terms[0].coefficient, # type:ignore[arg-type]
|
|
100
106
|
)
|
|
101
107
|
],
|
|
102
|
-
num_qubits=max(
|
|
103
|
-
self.num_qubits, obj.num_qubits # type:ignore[call-overload]
|
|
104
|
-
),
|
|
108
|
+
num_qubits=max(self.num_qubits, obj.num_qubits),
|
|
105
109
|
)
|
|
106
110
|
|
|
107
111
|
def __rmul__(self, obj: Union[float, "SparsePauliOp"]) -> "SparsePauliOp":
|
|
@@ -109,10 +113,21 @@ class SparsePauliOp:
|
|
|
109
113
|
|
|
110
114
|
def __add__(self, other: "SparsePauliOp") -> "SparsePauliOp":
|
|
111
115
|
return SparsePauliOp(
|
|
112
|
-
terms=self.terms + other.terms,
|
|
113
|
-
num_qubits=max(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
+
terms=self.terms + other.terms,
|
|
117
|
+
num_qubits=max(self.num_qubits, other.num_qubits),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def __sub__(self, other: "SparsePauliOp") -> "SparsePauliOp":
|
|
121
|
+
return self + -1.0 * other
|
|
122
|
+
|
|
123
|
+
def __str__(self) -> str:
|
|
124
|
+
return " + ".join(
|
|
125
|
+
(f"{term.coefficient}*" if term.coefficient != 1 else "")
|
|
126
|
+
+ "*".join(
|
|
127
|
+
f"Pauli.{indexed_pauli.pauli.name}({indexed_pauli.index})"
|
|
128
|
+
for indexed_pauli in term.paulis # type:ignore[attr-defined]
|
|
129
|
+
)
|
|
130
|
+
for term in self.terms
|
|
116
131
|
)
|
|
117
132
|
|
|
118
133
|
|
|
@@ -190,16 +205,6 @@ class LogNormalModel:
|
|
|
190
205
|
sigma: CReal
|
|
191
206
|
|
|
192
207
|
|
|
193
|
-
@dataclass
|
|
194
|
-
class FinanceFunction:
|
|
195
|
-
f: CInt
|
|
196
|
-
threshold: CReal
|
|
197
|
-
larger: CBool
|
|
198
|
-
polynomial_degree: CInt
|
|
199
|
-
use_chebyshev_polynomial_approximation: CBool
|
|
200
|
-
tail_probability: CReal
|
|
201
|
-
|
|
202
|
-
|
|
203
208
|
@dataclass
|
|
204
209
|
class QsvmResult:
|
|
205
210
|
test_score: CReal
|
|
@@ -231,7 +236,6 @@ BUILTIN_STRUCT_DECLARATIONS = {
|
|
|
231
236
|
__all__ = [
|
|
232
237
|
"ChemistryAtom",
|
|
233
238
|
"CombinatorialOptimizationSolution",
|
|
234
|
-
"FinanceFunction",
|
|
235
239
|
"FockHamiltonianProblem",
|
|
236
240
|
"GaussianModel",
|
|
237
241
|
"IndexedPauli",
|
|
@@ -111,7 +111,7 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
111
111
|
|
|
112
112
|
def visit_Model(self, model: Model) -> str:
|
|
113
113
|
# FIXME - CAD-20149: Remove this line once the froggies are removed, and the visit of lambdas can be done without accessing the func_decl property (with rename_params values only).
|
|
114
|
-
resolve_function_calls(model, model.function_dict)
|
|
114
|
+
resolve_function_calls(model, model.function_dict, annotate_types=False)
|
|
115
115
|
self._compilation_metadata = model.functions_compilation_metadata
|
|
116
116
|
|
|
117
117
|
enum_decls = [self.visit(enum_decl) for enum_decl in model.enums]
|
|
@@ -71,12 +71,7 @@ class ASTToQMODCode(ast.NodeVisitor):
|
|
|
71
71
|
return self.indent.join(self.visit(child) for child in node.body)
|
|
72
72
|
|
|
73
73
|
def visit_Attribute(self, node: ast.Attribute) -> str:
|
|
74
|
-
|
|
75
|
-
raise AssertionError("Error parsing enum attribute access")
|
|
76
|
-
if not (IDENTIFIER.match(node.value.id) and IDENTIFIER.match(node.attr)):
|
|
77
|
-
raise AssertionError("Error parsing enum attribute access")
|
|
78
|
-
self._handle_imports(node.value.id)
|
|
79
|
-
return f"{node.value.id!s}.{node.attr!s}"
|
|
74
|
+
return f"{self.visit(node.value)}.{node.attr}"
|
|
80
75
|
|
|
81
76
|
def visit_Name(self, node: ast.Name) -> str:
|
|
82
77
|
self._handle_imports(node.id, True)
|
|
@@ -303,10 +303,13 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
303
303
|
raise ClassiqInternalError
|
|
304
304
|
|
|
305
305
|
is_unsigned = (
|
|
306
|
-
is_signed_expr.is_evaluated()
|
|
306
|
+
is_signed_expr.is_evaluated()
|
|
307
|
+
and is_signed_expr.is_constant()
|
|
308
|
+
and not is_signed_expr.to_bool_value()
|
|
307
309
|
) or is_signed_expr.expr == "UNSIGNED"
|
|
308
310
|
is_integer = (
|
|
309
311
|
fraction_digits_expr.is_evaluated()
|
|
312
|
+
and fraction_digits_expr.is_constant()
|
|
310
313
|
and fraction_digits_expr.to_int_value() == 0
|
|
311
314
|
)
|
|
312
315
|
if is_unsigned and is_integer:
|
classiq/qmod/qmod_variable.py
CHANGED
|
@@ -63,7 +63,7 @@ from classiq.interface.model.quantum_type import (
|
|
|
63
63
|
)
|
|
64
64
|
from classiq.interface.source_reference import SourceReference
|
|
65
65
|
|
|
66
|
-
from classiq.qmod.cparam import ArrayBase, CInt, CParamScalar
|
|
66
|
+
from classiq.qmod.cparam import ArrayBase, CBool, CInt, CParamScalar
|
|
67
67
|
from classiq.qmod.generative import (
|
|
68
68
|
generative_mode_context,
|
|
69
69
|
interpret_expression,
|
|
@@ -270,6 +270,59 @@ class QScalar(QVar, SymbolicExpr):
|
|
|
270
270
|
|
|
271
271
|
|
|
272
272
|
class QBit(QScalar):
|
|
273
|
+
"""A type representing a single qubit.
|
|
274
|
+
|
|
275
|
+
`QBit` serves both as a placeholder for a temporary, non-allocated qubit
|
|
276
|
+
and as the type of an allocated physical or logical qubit.
|
|
277
|
+
Conceptually, a qubit is a two-level quantum system, described by the
|
|
278
|
+
superposition of the computational basis states:
|
|
279
|
+
|
|
280
|
+
$$
|
|
281
|
+
|0\\rangle = \\begin{pmatrix} 1 \\\\ 0 \\end{pmatrix},
|
|
282
|
+
\\quad
|
|
283
|
+
|1\\rangle = \\begin{pmatrix} 0 \\\\ 1 \\end{pmatrix}
|
|
284
|
+
$$
|
|
285
|
+
|
|
286
|
+
Therefore, a qubit state is a linear combination:
|
|
287
|
+
|
|
288
|
+
$$
|
|
289
|
+
|\\psi\\rangle = \\alpha |0\\rangle + \\beta |1\\rangle,
|
|
290
|
+
$$
|
|
291
|
+
|
|
292
|
+
where \\( \\alpha \\) and \\( \\beta \\) are complex numbers satisfying:
|
|
293
|
+
|
|
294
|
+
$$
|
|
295
|
+
|\\alpha|^2 + |\\beta|^2 = 1.
|
|
296
|
+
$$
|
|
297
|
+
|
|
298
|
+
Typical usage includes:
|
|
299
|
+
|
|
300
|
+
- Representing an unallocated qubit before its allocation.
|
|
301
|
+
- Acting as the output type for a qubit or an allocated qubit in the main function after calling an allocation function.
|
|
302
|
+
|
|
303
|
+
Examples:
|
|
304
|
+
|
|
305
|
+
Example 1: Unallocated qubit:
|
|
306
|
+
```python
|
|
307
|
+
@qfunc
|
|
308
|
+
def my_func(x1: QBit):
|
|
309
|
+
# Defining x2 as an unallocated qubit, binding it to declared qubit
|
|
310
|
+
x2 = QBit()
|
|
311
|
+
bind(x1, x2)
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Example 2, output type for a qubit:
|
|
315
|
+
```python
|
|
316
|
+
def main(q: Output[QBit]):
|
|
317
|
+
allocate(1, q)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Attributes:
|
|
321
|
+
None
|
|
322
|
+
|
|
323
|
+
For more details, see [Qmod Reference](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types/#semantics).
|
|
324
|
+
"""
|
|
325
|
+
|
|
273
326
|
@classmethod
|
|
274
327
|
def to_qvar(
|
|
275
328
|
cls,
|
|
@@ -287,13 +340,52 @@ _P = ParamSpec("_P")
|
|
|
287
340
|
|
|
288
341
|
|
|
289
342
|
class QNum(Generic[_P], QScalar):
|
|
343
|
+
"""
|
|
344
|
+
QNum is a quantum variable that represents a numeric value, which can be either integer or fixed-point,
|
|
345
|
+
encoded within a quantum register. It consists of an array of qubits for quantum representation and
|
|
346
|
+
classical metadata (number of fraction digits, sign) to define its numeric behavior.
|
|
347
|
+
|
|
348
|
+
QNum enables numerical computation in quantum circuits, supporting both signed and unsigned
|
|
349
|
+
formats, as well as configurable fixed-point precision. It is a parameterizable scalar type,
|
|
350
|
+
meaning its behavior can depend on symbolic or compile-time values. The total number of
|
|
351
|
+
qubits (`size`) determines the resolution and range of representable values.
|
|
352
|
+
|
|
353
|
+
Args:
|
|
354
|
+
name (str, optional): Identifier for this quantum number.
|
|
355
|
+
size (int, CInt, optional): Number of qubits allocated for this number.
|
|
356
|
+
Must be defined if either `is_signed` or `fraction_digits` is set.
|
|
357
|
+
is_signed (Union[bool, Expression, SymbolicExpr], optional): Whether the number is signed (i.e., can be negative).
|
|
358
|
+
Can be defined by a bool variable, or an arithmetic expression.
|
|
359
|
+
Must be set in tandem with `fraction_digits`.
|
|
360
|
+
fraction_digits (Union[int, CInt, Expression], optional): Number of fractional binary digits.
|
|
361
|
+
Defines the fixed-point precision. Must be set along with `is_signed`.
|
|
362
|
+
|
|
363
|
+
Methods:
|
|
364
|
+
fraction_digits -> Union[CParamScalar, int]:
|
|
365
|
+
Property that retrieves the number of fractional digits. Defaults to 0 if not specified.
|
|
366
|
+
|
|
367
|
+
is_signed -> Union[CParamScalar, bool]:
|
|
368
|
+
Property that retrieves whether the number is signed. Defaults to unsigned if not specified.
|
|
369
|
+
|
|
370
|
+
Example:
|
|
371
|
+
Example 1
|
|
372
|
+
```python
|
|
373
|
+
@qfunc
|
|
374
|
+
def main(x: Output[QNum], y: Output[QNum]):
|
|
375
|
+
x |= 3.5 # Allocate a quantum number
|
|
376
|
+
y |= 2 * x
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
For more details, see [Qmod Reference](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types/#semantics).
|
|
380
|
+
"""
|
|
381
|
+
|
|
290
382
|
CONSTRUCTOR_DEPTH: int = 3
|
|
291
383
|
|
|
292
384
|
def __init__(
|
|
293
385
|
self,
|
|
294
386
|
name: Union[None, str, HandleBinding] = None,
|
|
295
387
|
size: Union[int, CInt, Expression, SymbolicExpr, None] = None,
|
|
296
|
-
is_signed: Union[bool, Expression, SymbolicExpr, None] = None,
|
|
388
|
+
is_signed: Union[bool, CBool, Expression, SymbolicExpr, None] = None,
|
|
297
389
|
fraction_digits: Union[int, CInt, Expression, None] = None,
|
|
298
390
|
_expr_str: Optional[str] = None,
|
|
299
391
|
):
|
|
@@ -82,6 +82,7 @@ class _CallLambdaAnnotator(ModelVisitor):
|
|
|
82
82
|
def resolve_function_calls(
|
|
83
83
|
root: Any,
|
|
84
84
|
quantum_function_dict: Optional[Mapping[str, QuantumFunctionDeclaration]] = None,
|
|
85
|
+
annotate_types: bool = True,
|
|
85
86
|
) -> None:
|
|
86
87
|
if quantum_function_dict is None:
|
|
87
88
|
quantum_function_dict = {}
|
|
@@ -93,6 +94,7 @@ def resolve_function_calls(
|
|
|
93
94
|
**quantum_function_dict,
|
|
94
95
|
}
|
|
95
96
|
with ErrorManager().ignore_errors_context():
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
if annotate_types:
|
|
98
|
+
QStructAnnotator().visit(quantum_function_dict)
|
|
99
|
+
QStructAnnotator().visit(root)
|
|
98
100
|
_CallLambdaAnnotator(all_functions).visit(root)
|