classiq 0.68.0__py3-none-any.whl → 0.70.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/_internals/api_wrapper.py +4 -8
- classiq/analyzer/analyzer.py +0 -18
- classiq/analyzer/url_utils.py +9 -4
- classiq/applications/combinatorial_helpers/pyomo_utils.py +2 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +8 -11
- classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
- classiq/applications/qnn/torch_utils.py +1 -1
- classiq/execution/jobs.py +2 -5
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +8 -3
- classiq/interface/chemistry/operator.py +12 -28
- classiq/interface/debug_info/back_ref_util.py +22 -0
- classiq/interface/debug_info/debug_info.py +11 -21
- classiq/interface/executor/optimizer_preferences.py +1 -0
- classiq/interface/executor/quantum_instruction_set.py +1 -0
- classiq/interface/generator/arith/arithmetic.py +21 -6
- classiq/interface/generator/arith/arithmetic_param_getters.py +3 -3
- classiq/interface/generator/circuit_code/circuit_code.py +4 -0
- classiq/interface/generator/circuit_code/types_and_constants.py +1 -0
- classiq/interface/generator/expressions/atomic_expression_functions.py +1 -2
- classiq/interface/generator/expressions/expression_types.py +8 -2
- classiq/interface/generator/expressions/proxies/__init__.py +0 -0
- classiq/interface/generator/expressions/proxies/classical/__init__.py +0 -0
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +75 -0
- classiq/interface/generator/expressions/proxies/classical/classical_proxy.py +26 -0
- classiq/interface/generator/expressions/proxies/classical/classical_scalar_proxy.py +32 -0
- classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +31 -0
- classiq/interface/generator/expressions/proxies/quantum/__init__.py +0 -0
- classiq/interface/generator/expressions/{qmod_qarray_proxy.py → proxies/quantum/qmod_qarray_proxy.py} +3 -1
- classiq/interface/generator/expressions/{qmod_qscalar_proxy.py → proxies/quantum/qmod_qscalar_proxy.py} +3 -1
- classiq/interface/generator/expressions/{qmod_qstruct_proxy.py → proxies/quantum/qmod_qstruct_proxy.py} +3 -1
- classiq/interface/generator/functions/classical_type.py +34 -29
- classiq/interface/generator/functions/type_name.py +26 -2
- classiq/interface/generator/generated_circuit_data.py +84 -27
- classiq/interface/generator/model/preferences/preferences.py +1 -0
- classiq/interface/generator/quantum_program.py +0 -1
- classiq/interface/generator/types/builtin_enum_declarations.py +1 -0
- classiq/interface/generator/types/enum_declaration.py +12 -1
- classiq/interface/ide/visual_model.py +0 -2
- classiq/interface/model/native_function_definition.py +0 -10
- classiq/interface/model/quantum_statement.py +1 -1
- classiq/interface/model/quantum_type.py +15 -3
- classiq/interface/server/routes.py +0 -6
- classiq/model_expansions/atomic_expression_functions_defs.py +9 -3
- classiq/model_expansions/evaluators/arg_type_match.py +4 -2
- classiq/model_expansions/evaluators/classical_expression.py +2 -2
- classiq/model_expansions/evaluators/control.py +1 -1
- classiq/model_expansions/evaluators/parameter_types.py +58 -16
- classiq/model_expansions/evaluators/quantum_type_utils.py +7 -57
- classiq/model_expansions/expression_evaluator.py +3 -1
- classiq/model_expansions/generative_functions.py +67 -7
- classiq/model_expansions/quantum_operations/arithmetic/__init__.py +0 -0
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +60 -0
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +9 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +0 -13
- classiq/model_expansions/quantum_operations/quantum_function_call.py +0 -22
- classiq/model_expansions/scope.py +7 -6
- classiq/model_expansions/scope_initialization.py +20 -33
- classiq/model_expansions/transformers/model_renamer.py +13 -4
- classiq/model_expansions/visitors/variable_references.py +8 -4
- classiq/open_library/functions/__init__.py +2 -0
- classiq/open_library/functions/amplitude_amplification.py +3 -7
- classiq/open_library/functions/discrete_sine_cosine_transform.py +4 -4
- classiq/open_library/functions/grover.py +2 -2
- classiq/open_library/functions/hea.py +3 -3
- classiq/open_library/functions/lookup_table.py +58 -0
- classiq/open_library/functions/modular_exponentiation.py +10 -20
- classiq/open_library/functions/qft_functions.py +2 -2
- classiq/open_library/functions/qsvt.py +8 -8
- classiq/open_library/functions/utility_functions.py +2 -2
- classiq/qmod/builtins/classical_functions.py +24 -7
- classiq/qmod/builtins/enums.py +1 -0
- classiq/qmod/builtins/functions/__init__.py +2 -0
- classiq/qmod/builtins/functions/exponentiation.py +24 -0
- classiq/qmod/builtins/operations.py +26 -11
- classiq/qmod/cparam.py +32 -5
- classiq/qmod/declaration_inferrer.py +3 -1
- classiq/qmod/python_classical_type.py +10 -4
- classiq/qmod/qmod_parameter.py +8 -0
- classiq/qmod/qmod_variable.py +11 -14
- classiq/qmod/quantum_callable.py +2 -1
- classiq/qmod/quantum_function.py +3 -2
- classiq/qmod/semantics/annotation/call_annotation.py +0 -28
- classiq/qmod/semantics/annotation/qstruct_annotator.py +21 -1
- classiq/qmod/semantics/error_manager.py +1 -1
- classiq/qmod/semantics/validation/main_validation.py +1 -1
- classiq/qmod/semantics/validation/type_hints.py +29 -0
- classiq/qmod/utilities.py +67 -2
- classiq/synthesis.py +9 -6
- {classiq-0.68.0.dist-info → classiq-0.70.0.dist-info}/METADATA +10 -12
- {classiq-0.68.0.dist-info → classiq-0.70.0.dist-info}/RECORD +95 -84
- {classiq-0.68.0.dist-info → classiq-0.70.0.dist-info}/WHEEL +1 -1
- classiq/interface/execution/jobs.py +0 -31
- /classiq/interface/generator/expressions/{qmod_struct_instance.py → proxies/classical/qmod_struct_instance.py} +0 -0
- /classiq/interface/generator/expressions/{qmod_sized_proxy.py → proxies/quantum/qmod_sized_proxy.py} +0 -0
@@ -1,20 +1,17 @@
|
|
1
1
|
from collections.abc import Sequence
|
2
|
-
from typing import Any
|
3
2
|
|
4
|
-
from classiq.interface.exceptions import ClassiqError
|
3
|
+
from classiq.interface.exceptions import ClassiqError, ClassiqInternalExpansionError
|
5
4
|
from classiq.interface.generator.constant import Constant
|
6
|
-
from classiq.interface.generator.
|
7
|
-
|
8
|
-
|
5
|
+
from classiq.interface.generator.functions.classical_type import (
|
6
|
+
ClassicalArray,
|
7
|
+
ClassicalList,
|
9
8
|
)
|
10
9
|
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
11
10
|
from classiq.interface.model.handle_binding import HandleBinding
|
12
11
|
from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model
|
13
12
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
14
13
|
from classiq.interface.model.port_declaration import PortDeclaration
|
15
|
-
from classiq.interface.model.quantum_function_declaration import
|
16
|
-
PositionalArg,
|
17
|
-
)
|
14
|
+
from classiq.interface.model.quantum_function_declaration import PositionalArg
|
18
15
|
|
19
16
|
from classiq.model_expansions.closure import FunctionClosure, GenerativeFunctionClosure
|
20
17
|
from classiq.model_expansions.evaluators.classical_expression import (
|
@@ -129,37 +126,27 @@ def init_builtin_types() -> None:
|
|
129
126
|
QMODULE.type_decls |= BUILTIN_STRUCT_DECLARATIONS
|
130
127
|
|
131
128
|
|
132
|
-
def _rename_exec_param(param_name: str) -> str:
|
133
|
-
if param_name in RESERVED_EXPRESSIONS:
|
134
|
-
return param_name
|
135
|
-
return param_name + CPARAM_EXECUTION_SUFFIX
|
136
|
-
|
137
|
-
|
138
|
-
def _add_exec_param_parts_to_scope(param_val: Any, scope: Scope) -> None:
|
139
|
-
if not isinstance(param_val, list):
|
140
|
-
scope[str(param_val)] = Evaluated(value=param_val)
|
141
|
-
return
|
142
|
-
for param_part in param_val:
|
143
|
-
_add_exec_param_parts_to_scope(param_part, scope)
|
144
|
-
|
145
|
-
|
146
129
|
def init_exec_params(model: Model, scope: Scope) -> dict[str, ConcreteClassicalType]:
|
147
130
|
if model.execution_parameters is not None:
|
148
|
-
exec_params =
|
149
|
-
param_name: (param_name, param_type)
|
150
|
-
for param_name, param_type in model.execution_parameters.items()
|
151
|
-
}
|
131
|
+
exec_params = model.execution_parameters
|
152
132
|
else:
|
153
133
|
exec_params = {
|
154
|
-
param.name:
|
134
|
+
param.name: param.classical_type
|
155
135
|
for param in model.function_dict.get(
|
156
136
|
"_dec_main", model.main_func
|
157
137
|
).param_decls
|
158
138
|
}
|
159
|
-
for param_name,
|
160
|
-
param_val = param_type.
|
139
|
+
for param_name, param_type in exec_params.items():
|
140
|
+
param_val = param_type.get_classical_proxy(
|
141
|
+
handle=HandleBinding(name=param_name)
|
142
|
+
)
|
161
143
|
scope[param_name] = Evaluated(value=param_val)
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
144
|
+
return exec_params
|
145
|
+
|
146
|
+
|
147
|
+
def _get_shape(classical_type: ConcreteClassicalType) -> tuple[int, ...]:
|
148
|
+
if isinstance(classical_type, ClassicalList):
|
149
|
+
raise ClassiqInternalExpansionError("Unexpected classical list")
|
150
|
+
if isinstance(classical_type, ClassicalArray):
|
151
|
+
return classical_type.size, *_get_shape(classical_type.element_type)
|
152
|
+
return ()
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import ast
|
2
|
+
import re
|
2
3
|
from collections.abc import Mapping, Sequence
|
3
4
|
from dataclasses import dataclass
|
4
5
|
from typing import TypeVar, cast
|
@@ -16,6 +17,12 @@ from classiq.model_expansions.visitors.variable_references import VarRefCollecto
|
|
16
17
|
AST_NODE = TypeVar("AST_NODE", bound=NodeType)
|
17
18
|
|
18
19
|
|
20
|
+
def _replace_full_word(pattern: str, substitution: str, target: str) -> str:
|
21
|
+
return re.sub(
|
22
|
+
rf"(^|\b|\W)({re.escape(pattern)})($|\b|\W)", rf"\1{substitution}\3", target
|
23
|
+
)
|
24
|
+
|
25
|
+
|
19
26
|
@dataclass(frozen=True)
|
20
27
|
class HandleRenaming:
|
21
28
|
source_handle: HandleBinding
|
@@ -74,7 +81,7 @@ class ModelRenamer:
|
|
74
81
|
symbol_mapping: SymbolRenaming,
|
75
82
|
expression: Expression,
|
76
83
|
) -> Expression:
|
77
|
-
vrc = VarRefCollector(ignore_duplicated_handles=True)
|
84
|
+
vrc = VarRefCollector(ignore_duplicated_handles=True, ignore_sympy_symbols=True)
|
78
85
|
vrc.visit(ast.parse(expression.expr))
|
79
86
|
|
80
87
|
handle_names = {
|
@@ -87,10 +94,12 @@ class ModelRenamer:
|
|
87
94
|
new_handle = handle.collapse()
|
88
95
|
for handle_to_replace, replacement in handle_names.items():
|
89
96
|
new_handle = new_handle.replace_prefix(handle_to_replace, replacement)
|
90
|
-
new_expr_str =
|
97
|
+
new_expr_str = _replace_full_word(
|
98
|
+
str(handle), str(new_handle), new_expr_str
|
99
|
+
)
|
91
100
|
if handle.qmod_expr != str(handle):
|
92
|
-
new_expr_str =
|
93
|
-
handle.qmod_expr, new_handle.qmod_expr
|
101
|
+
new_expr_str = _replace_full_word(
|
102
|
+
str(handle.qmod_expr), str(new_handle.qmod_expr), new_expr_str
|
94
103
|
)
|
95
104
|
|
96
105
|
new_expr = Expression(expr=new_expr_str)
|
@@ -24,10 +24,14 @@ from classiq.interface.model.handle_binding import (
|
|
24
24
|
|
25
25
|
class VarRefCollector(ast.NodeVisitor):
|
26
26
|
def __init__(
|
27
|
-
self,
|
27
|
+
self,
|
28
|
+
ignore_duplicated_handles: bool = False,
|
29
|
+
unevaluated: bool = False,
|
30
|
+
ignore_sympy_symbols: bool = False,
|
28
31
|
) -> None:
|
29
32
|
self._var_handles: dict[HandleBinding, bool] = {}
|
30
33
|
self._ignore_duplicated_handles = ignore_duplicated_handles
|
34
|
+
self._ignore_sympy_symbols = ignore_sympy_symbols
|
31
35
|
self._unevaluated = unevaluated
|
32
36
|
self._is_nested = False
|
33
37
|
|
@@ -117,9 +121,9 @@ class VarRefCollector(ast.NodeVisitor):
|
|
117
121
|
return handle
|
118
122
|
|
119
123
|
def visit_Name(self, node: ast.Name) -> Optional[HandleBinding]:
|
120
|
-
if node.id in set(
|
121
|
-
|
122
|
-
):
|
124
|
+
if not self._ignore_sympy_symbols and node.id in set(
|
125
|
+
SYMPY_SUPPORTED_EXPRESSIONS
|
126
|
+
) | set(DEFAULT_SUPPORTED_FUNC_NAMES):
|
123
127
|
return None
|
124
128
|
handle = HandleBinding(name=node.id)
|
125
129
|
if not self._is_nested:
|
@@ -9,6 +9,7 @@ from .grover import *
|
|
9
9
|
from .hea import *
|
10
10
|
from .linear_pauli_rotation import *
|
11
11
|
from .linear_pauli_rotation import _single_pauli
|
12
|
+
from .lookup_table import span_lookup_table
|
12
13
|
from .modular_exponentiation import *
|
13
14
|
from .modular_exponentiation import _check_msb
|
14
15
|
from .qaoa_penalty import *
|
@@ -131,6 +132,7 @@ __all__ = [
|
|
131
132
|
"qsvt_lcu_step",
|
132
133
|
"qsvt_step",
|
133
134
|
"reflect_about_zero",
|
135
|
+
"span_lookup_table",
|
134
136
|
"suzuki_trotter",
|
135
137
|
"swap_test",
|
136
138
|
"switch",
|
@@ -73,11 +73,9 @@ def exact_amplitude_amplification(
|
|
73
73
|
|
74
74
|
extended_qvars: QArray = QArray()
|
75
75
|
within_apply(
|
76
|
-
lambda: [
|
76
|
+
lambda: [
|
77
77
|
allocate(aux),
|
78
|
-
bind(
|
79
|
-
[aux, packed_qvars], extended_qvars
|
80
|
-
), # type:ignore[func-returns-value]
|
78
|
+
bind([aux, packed_qvars], extended_qvars),
|
81
79
|
],
|
82
80
|
lambda: amplitude_amplification(
|
83
81
|
k,
|
@@ -85,9 +83,7 @@ def exact_amplitude_amplification(
|
|
85
83
|
qvars_[0] == 0, lambda: oracle(qvars_[1 : qvars_.size])
|
86
84
|
),
|
87
85
|
lambda qvars_: [
|
88
|
-
space_transform(
|
89
|
-
qvars_[1 : qvars_.size]
|
90
|
-
),
|
86
|
+
space_transform(qvars_[1 : qvars_.size]),
|
91
87
|
RY(rot_phase, qvars_[0]),
|
92
88
|
],
|
93
89
|
extended_qvars,
|
@@ -30,9 +30,9 @@ def _qct_d_operator(x: QNum, q: QBit) -> None:
|
|
30
30
|
def _qct_pi_operator(x: QArray[QBit], q: QBit) -> None:
|
31
31
|
control(
|
32
32
|
q == 1,
|
33
|
-
lambda: [
|
33
|
+
lambda: [
|
34
34
|
apply_to_all(X, x),
|
35
|
-
inplace_add(1, x), # type:ignore[arg-type
|
35
|
+
inplace_add(1, x), # type:ignore[arg-type]
|
36
36
|
],
|
37
37
|
)
|
38
38
|
|
@@ -70,7 +70,7 @@ def _pi2_operator(x: QArray[QBit], q: QBit) -> None:
|
|
70
70
|
|
71
71
|
|
72
72
|
def _j_operator(q: QBit) -> None:
|
73
|
-
within_apply(lambda: Z(q), lambda: (S(q), H(q), S(q)))
|
73
|
+
within_apply(lambda: Z(q), lambda: (S(q), H(q), S(q)))
|
74
74
|
|
75
75
|
|
76
76
|
def _b_t_operator(q: QBit) -> None:
|
@@ -179,6 +179,6 @@ def qst_type2(x: QArray[QBit]) -> None:
|
|
179
179
|
"""
|
180
180
|
q = QBit()
|
181
181
|
within_apply(
|
182
|
-
lambda: (allocate(q), X(q)),
|
182
|
+
lambda: (allocate(q), X(q)),
|
183
183
|
lambda: qct_qst_type2(x, q),
|
184
184
|
)
|
@@ -42,7 +42,7 @@ def phase_oracle(
|
|
42
42
|
"""
|
43
43
|
aux = QBit()
|
44
44
|
within_apply(
|
45
|
-
within=lambda: (allocate(aux), X(aux), H(aux)),
|
45
|
+
within=lambda: (allocate(aux), X(aux), H(aux)),
|
46
46
|
apply=lambda: predicate(target, aux),
|
47
47
|
)
|
48
48
|
|
@@ -68,7 +68,7 @@ def reflect_about_zero(packed_vars: QArray[QBit]) -> None:
|
|
68
68
|
lsb = QBit()
|
69
69
|
bind(packed_vars, [msbs, lsb])
|
70
70
|
within_apply(
|
71
|
-
lambda: (X(lsb), H(lsb)),
|
71
|
+
lambda: (X(lsb), H(lsb)),
|
72
72
|
lambda: control(msbs == 0, lambda: X(lsb)),
|
73
73
|
)
|
74
74
|
bind([msbs, lsb], packed_vars)
|
@@ -58,8 +58,8 @@ def full_hea(
|
|
58
58
|
"""
|
59
59
|
repeat(
|
60
60
|
reps,
|
61
|
-
lambda r: [
|
62
|
-
repeat(
|
61
|
+
lambda r: [
|
62
|
+
repeat(
|
63
63
|
operands_1qubit.len,
|
64
64
|
lambda i1: repeat(
|
65
65
|
num_qubits,
|
@@ -77,7 +77,7 @@ def full_hea(
|
|
77
77
|
),
|
78
78
|
),
|
79
79
|
),
|
80
|
-
repeat(
|
80
|
+
repeat(
|
81
81
|
operands_2qubit.len,
|
82
82
|
lambda i2: repeat(
|
83
83
|
connectivity_map.len,
|
@@ -0,0 +1,58 @@
|
|
1
|
+
from itertools import product
|
2
|
+
|
3
|
+
from classiq.interface.exceptions import ClassiqValueError
|
4
|
+
|
5
|
+
from classiq.qmod.builtins.operations import assign, bind, within_apply
|
6
|
+
from classiq.qmod.qmod_variable import QNum
|
7
|
+
from classiq.qmod.symbolic import subscript
|
8
|
+
from classiq.qmod.utilities import RealFunction, get_temp_var_name, qnum_values
|
9
|
+
|
10
|
+
|
11
|
+
def _get_qnum_values(num: QNum) -> list[float]:
|
12
|
+
size = num.size
|
13
|
+
is_signed = num.is_signed
|
14
|
+
fraction_digits = num.fraction_digits
|
15
|
+
if (
|
16
|
+
not isinstance(size, int)
|
17
|
+
or not isinstance(is_signed, bool)
|
18
|
+
or not isinstance(fraction_digits, int)
|
19
|
+
):
|
20
|
+
raise ClassiqValueError(
|
21
|
+
"Must call 'span_lookup_table' inside a generative qfunc"
|
22
|
+
)
|
23
|
+
|
24
|
+
return qnum_values(size, is_signed, fraction_digits)
|
25
|
+
|
26
|
+
|
27
|
+
def span_lookup_table(func: RealFunction, *targets: QNum) -> QNum:
|
28
|
+
"""
|
29
|
+
Applies a classical function to quantum numbers.
|
30
|
+
|
31
|
+
Works by reducing the function into a lookup table over all the possible values
|
32
|
+
of the quantum numbers.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
func: A Python function
|
36
|
+
*targets: One or more initialized quantum numbers
|
37
|
+
|
38
|
+
Returns:
|
39
|
+
The quantum result of applying func to targets
|
40
|
+
|
41
|
+
Notes:
|
42
|
+
Must be called inside a generative function (`@qfunc(generative=True)`)
|
43
|
+
"""
|
44
|
+
if len(targets) == 0:
|
45
|
+
raise ClassiqValueError("No targets specified")
|
46
|
+
|
47
|
+
target_vals = [_get_qnum_values(target) for target in targets]
|
48
|
+
lookup_table = [func(*vals[::-1]) for vals in product(*target_vals[::-1])]
|
49
|
+
|
50
|
+
index_size = sum(target.size for target in targets)
|
51
|
+
index: QNum = QNum(get_temp_var_name(), size=index_size)
|
52
|
+
result: QNum = QNum(get_temp_var_name("result"))
|
53
|
+
|
54
|
+
within_apply(
|
55
|
+
lambda: bind(list(targets), index),
|
56
|
+
lambda: assign(subscript(lookup_table, index), result),
|
57
|
+
)
|
58
|
+
return result
|
@@ -70,23 +70,17 @@ def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) ->
|
|
70
70
|
aux = QBit()
|
71
71
|
|
72
72
|
within_apply(
|
73
|
-
lambda: (
|
73
|
+
lambda: (
|
74
74
|
allocate(aux),
|
75
|
-
bind([c1, c2], ctrl),
|
75
|
+
bind([c1, c2], ctrl),
|
76
76
|
),
|
77
|
-
lambda: (
|
78
|
-
control(
|
79
|
-
|
80
|
-
),
|
81
|
-
invert( # type:ignore[func-returns-value]
|
82
|
-
lambda: qft_space_add_const(n, phi_b)
|
83
|
-
),
|
77
|
+
lambda: (
|
78
|
+
control(ctrl, lambda: qft_space_add_const(a, phi_b)),
|
79
|
+
invert(lambda: qft_space_add_const(n, phi_b)),
|
84
80
|
_check_msb(1, phi_b, aux),
|
85
|
-
control(
|
86
|
-
aux, lambda: qft_space_add_const(n, phi_b)
|
87
|
-
),
|
81
|
+
control(aux, lambda: qft_space_add_const(n, phi_b)),
|
88
82
|
within_apply(
|
89
|
-
lambda: invert(
|
83
|
+
lambda: invert(
|
90
84
|
lambda: control(ctrl, lambda: qft_space_add_const(a, phi_b))
|
91
85
|
),
|
92
86
|
lambda: _check_msb(0, phi_b, aux),
|
@@ -160,14 +154,10 @@ def inplace_c_modular_multiply(n: CInt, a: CInt, x: QArray[QBit], ctrl: QBit) ->
|
|
160
154
|
|
161
155
|
within_apply(
|
162
156
|
lambda: allocate(x.len + 1, b),
|
163
|
-
lambda: (
|
157
|
+
lambda: (
|
164
158
|
c_modular_multiply(n, a, b, x, ctrl),
|
165
|
-
control(
|
166
|
-
|
167
|
-
),
|
168
|
-
invert( # type:ignore[func-returns-value]
|
169
|
-
lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl)
|
170
|
-
),
|
159
|
+
control(ctrl, lambda: multiswap(x, b)),
|
160
|
+
invert(lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl)),
|
171
161
|
),
|
172
162
|
)
|
173
163
|
|
@@ -18,9 +18,9 @@ def qft_no_swap(qbv: QArray[QBit]) -> None:
|
|
18
18
|
"""
|
19
19
|
repeat(
|
20
20
|
qbv.len,
|
21
|
-
lambda i: (
|
21
|
+
lambda i: (
|
22
22
|
H(qbv[i]),
|
23
|
-
repeat(
|
23
|
+
repeat(
|
24
24
|
qbv.len - i - 1,
|
25
25
|
lambda j: CPHASE(
|
26
26
|
theta=pi / (2 ** (j + 1)),
|
@@ -97,8 +97,8 @@ def qsvt(
|
|
97
97
|
if_(
|
98
98
|
condition=phase_seq.len % 2 == 1,
|
99
99
|
then=lambda: IDENTITY(qvar),
|
100
|
-
else_=lambda: (
|
101
|
-
u(qvar),
|
100
|
+
else_=lambda: (
|
101
|
+
u(qvar),
|
102
102
|
projector_controlled_phase(
|
103
103
|
phase_seq[phase_seq.len - 1],
|
104
104
|
proj_cnot_2,
|
@@ -297,8 +297,8 @@ def qsvt_lcu(
|
|
297
297
|
condition=phase_seq_odd.len > phase_seq_even.len,
|
298
298
|
then=lambda: control(
|
299
299
|
lcu == 0,
|
300
|
-
lambda: [
|
301
|
-
u(qvar),
|
300
|
+
lambda: [
|
301
|
+
u(qvar),
|
302
302
|
projector_controlled_phase(
|
303
303
|
phase_seq_odd[phase_seq_odd.len - 1], proj_cnot_2, qvar, aux
|
304
304
|
),
|
@@ -307,8 +307,8 @@ def qsvt_lcu(
|
|
307
307
|
)
|
308
308
|
if_(
|
309
309
|
condition=phase_seq_odd.len < phase_seq_even.len,
|
310
|
-
then=lambda: (
|
311
|
-
u(qvar),
|
310
|
+
then=lambda: (
|
311
|
+
u(qvar),
|
312
312
|
projector_controlled_double_phase(
|
313
313
|
phase_seq_even[phase_seq_even.len - 1],
|
314
314
|
phase_seq_odd[phase_seq_odd.len - 1],
|
@@ -319,8 +319,8 @@ def qsvt_lcu(
|
|
319
319
|
),
|
320
320
|
control(
|
321
321
|
lcu,
|
322
|
-
lambda: [
|
323
|
-
invert(lambda: u(qvar)),
|
322
|
+
lambda: [
|
323
|
+
invert(lambda: u(qvar)),
|
324
324
|
projector_controlled_phase(
|
325
325
|
phase_seq_even[phase_seq_even.len - 1], proj_cnot_1, qvar, aux
|
326
326
|
),
|
@@ -79,8 +79,8 @@ def modular_increment(a: CInt, x: QNum) -> None:
|
|
79
79
|
)
|
80
80
|
array_cast: QArray = QArray()
|
81
81
|
within_apply(
|
82
|
-
lambda: (
|
83
|
-
bind(x, array_cast),
|
82
|
+
lambda: (
|
83
|
+
bind(x, array_cast),
|
84
84
|
qft(array_cast),
|
85
85
|
),
|
86
86
|
lambda: repeat(
|
@@ -12,19 +12,25 @@ def qft_const_adder_phase(
|
|
12
12
|
value: CInt,
|
13
13
|
reg_len: CInt,
|
14
14
|
) -> CReal:
|
15
|
-
return symbolic_function(
|
15
|
+
return symbolic_function(
|
16
|
+
bit_index, value, reg_len, return_type=CReal # type:ignore[type-abstract]
|
17
|
+
)
|
16
18
|
|
17
19
|
|
18
20
|
def fock_hamiltonian_problem_to_hamiltonian(
|
19
21
|
problem: FockHamiltonianProblem,
|
20
22
|
) -> CArray[PauliTerm]:
|
21
|
-
return symbolic_function(
|
23
|
+
return symbolic_function(
|
24
|
+
problem, return_type=CArray[PauliTerm] # type:ignore[type-abstract]
|
25
|
+
)
|
22
26
|
|
23
27
|
|
24
28
|
def molecule_problem_to_hamiltonian(
|
25
29
|
problem: MoleculeProblem,
|
26
30
|
) -> CArray[PauliTerm]:
|
27
|
-
return symbolic_function(
|
31
|
+
return symbolic_function(
|
32
|
+
problem, return_type=CArray[PauliTerm] # type:ignore[type-abstract]
|
33
|
+
)
|
28
34
|
|
29
35
|
|
30
36
|
def grid_entangler_graph(
|
@@ -33,14 +39,19 @@ def grid_entangler_graph(
|
|
33
39
|
grid_randomization: CBool,
|
34
40
|
) -> CArray[CArray[CInt]]:
|
35
41
|
return symbolic_function(
|
36
|
-
num_qubits,
|
42
|
+
num_qubits,
|
43
|
+
schmidt_rank,
|
44
|
+
grid_randomization,
|
45
|
+
return_type=CArray[CArray[CInt]], # type:ignore[type-abstract]
|
37
46
|
)
|
38
47
|
|
39
48
|
|
40
49
|
def hypercube_entangler_graph(
|
41
50
|
num_qubits: CInt,
|
42
51
|
) -> CArray[CArray[CInt]]:
|
43
|
-
return symbolic_function(
|
52
|
+
return symbolic_function(
|
53
|
+
num_qubits, return_type=CArray[CArray[CInt]] # type:ignore[type-abstract]
|
54
|
+
)
|
44
55
|
|
45
56
|
|
46
57
|
def gaussian_finance_post_process(
|
@@ -49,7 +60,10 @@ def gaussian_finance_post_process(
|
|
49
60
|
probability: CReal,
|
50
61
|
) -> CReal:
|
51
62
|
return symbolic_function(
|
52
|
-
finance_model,
|
63
|
+
finance_model,
|
64
|
+
estimation_method,
|
65
|
+
probability,
|
66
|
+
return_type=CReal, # type:ignore[type-abstract]
|
53
67
|
)
|
54
68
|
|
55
69
|
|
@@ -59,7 +73,10 @@ def log_normal_finance_post_process(
|
|
59
73
|
probability: CReal,
|
60
74
|
) -> CReal:
|
61
75
|
return symbolic_function(
|
62
|
-
finance_model,
|
76
|
+
finance_model,
|
77
|
+
estimation_method,
|
78
|
+
probability,
|
79
|
+
return_type=CReal, # type:ignore[type-abstract]
|
63
80
|
)
|
64
81
|
|
65
82
|
|
classiq/qmod/builtins/enums.py
CHANGED
@@ -64,6 +64,7 @@ CORE_LIB_DECLS = [
|
|
64
64
|
inplace_prepare_state,
|
65
65
|
inplace_prepare_amplitudes,
|
66
66
|
single_pauli_exponent,
|
67
|
+
commuting_paulis_exponent,
|
67
68
|
suzuki_trotter,
|
68
69
|
qdrift,
|
69
70
|
exponentiation_with_depth_constraint,
|
@@ -129,6 +130,7 @@ __all__ = [ # noqa: RUF022
|
|
129
130
|
"randomized_benchmarking",
|
130
131
|
"real_xor_constant",
|
131
132
|
"single_pauli_exponent",
|
133
|
+
"commuting_paulis_exponent",
|
132
134
|
"suzuki_trotter",
|
133
135
|
"unitary",
|
134
136
|
"RESET",
|
@@ -28,6 +28,30 @@ def single_pauli_exponent(
|
|
28
28
|
pass
|
29
29
|
|
30
30
|
|
31
|
+
@qfunc(external=True)
|
32
|
+
def commuting_paulis_exponent(
|
33
|
+
pauli_operator: CArray[PauliTerm],
|
34
|
+
evolution_coefficient: CReal,
|
35
|
+
qbv: QArray[
|
36
|
+
QBit, Literal["get_field(get_field(pauli_operator[0], 'pauli'), 'len')"]
|
37
|
+
],
|
38
|
+
) -> None:
|
39
|
+
"""
|
40
|
+
[Qmod core-library function]
|
41
|
+
|
42
|
+
Exponentiates the specified commutative Pauli operator.
|
43
|
+
As all the Pauli operator's terms commute, the exponential of the whole operator
|
44
|
+
is exactly the product of exponentials of each term.
|
45
|
+
Calling this funciton with a non-commutative Pauli operator will issue an error.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
pauli_operator: The Pauli operator to be exponentiated.
|
49
|
+
evolution_coefficient: A global evolution coefficient multiplying the Pauli operator.
|
50
|
+
qbv: The target quantum variable of the exponentiation.
|
51
|
+
"""
|
52
|
+
pass
|
53
|
+
|
54
|
+
|
31
55
|
@qfunc(external=True)
|
32
56
|
def suzuki_trotter(
|
33
57
|
pauli_operator: CArray[PauliTerm],
|