classiq 0.82.1__py3-none-any.whl → 0.84.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 +27 -0
- classiq/applications/chemistry/chemistry_model_constructor.py +2 -4
- classiq/applications/chemistry/hartree_fock.py +68 -0
- classiq/applications/chemistry/mapping.py +85 -0
- classiq/applications/chemistry/op_utils.py +79 -0
- classiq/applications/chemistry/problems.py +195 -0
- classiq/applications/chemistry/ucc.py +109 -0
- classiq/applications/chemistry/z2_symmetries.py +368 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +30 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
- classiq/{model_expansions/evaluators → evaluators}/arg_type_match.py +12 -4
- classiq/{model_expansions/evaluators → evaluators}/argument_types.py +3 -3
- classiq/{model_expansions/evaluators → evaluators}/classical_expression.py +1 -1
- classiq/{model_expansions/evaluators → evaluators}/classical_type_inference.py +3 -4
- classiq/{model_expansions/evaluators → evaluators}/parameter_types.py +17 -15
- classiq/execution/__init__.py +12 -1
- classiq/execution/execution_session.py +189 -43
- classiq/execution/jobs.py +26 -1
- classiq/execution/qnn.py +2 -2
- classiq/execution/user_budgets.py +39 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/constants.py +1 -0
- classiq/interface/execution/primitives.py +29 -1
- classiq/interface/executor/estimate_cost.py +35 -0
- classiq/interface/executor/execution_result.py +13 -0
- classiq/interface/executor/result.py +116 -1
- classiq/interface/executor/user_budget.py +26 -33
- classiq/interface/generator/application_apis/finance_declarations.py +3 -3
- classiq/interface/generator/expressions/atomic_expression_functions.py +11 -3
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -6
- classiq/interface/generator/functions/classical_type.py +2 -35
- classiq/interface/generator/functions/concrete_types.py +0 -3
- classiq/interface/generator/functions/type_modifier.py +22 -0
- classiq/interface/generator/generated_circuit_data.py +5 -16
- classiq/interface/generator/model/model.py +8 -0
- classiq/interface/generator/quantum_program.py +0 -13
- classiq/interface/generator/types/compilation_metadata.py +0 -3
- classiq/interface/helpers/model_normalizer.py +2 -2
- classiq/interface/ide/visual_model.py +6 -2
- classiq/interface/model/model.py +12 -7
- classiq/interface/model/port_declaration.py +4 -2
- classiq/interface/pretty_print/__init__.py +0 -0
- classiq/{qmod/native → interface/pretty_print}/expression_to_qmod.py +18 -11
- classiq/interface/server/routes.py +4 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +42 -5
- classiq/model_expansions/capturing/captured_vars.py +21 -8
- classiq/model_expansions/interpreters/base_interpreter.py +3 -3
- classiq/model_expansions/quantum_operations/allocate.py +1 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +1 -1
- classiq/model_expansions/quantum_operations/bind.py +2 -2
- classiq/model_expansions/quantum_operations/call_emitter.py +42 -36
- classiq/model_expansions/quantum_operations/variable_decleration.py +1 -1
- classiq/model_expansions/scope_initialization.py +3 -3
- classiq/model_expansions/transformers/model_renamer.py +16 -5
- classiq/model_expansions/transformers/{type_qualifier_inference.py → type_modifier_inference.py} +134 -100
- classiq/model_expansions/visitors/symbolic_param_inference.py +10 -7
- classiq/open_library/functions/__init__.py +3 -0
- classiq/open_library/functions/amplitude_amplification.py +10 -18
- classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
- classiq/open_library/functions/grover.py +14 -6
- classiq/open_library/functions/modular_exponentiation.py +22 -20
- classiq/open_library/functions/state_preparation.py +18 -1
- classiq/qmod/__init__.py +2 -2
- classiq/qmod/builtins/enums.py +23 -0
- classiq/qmod/builtins/functions/__init__.py +2 -0
- classiq/qmod/builtins/functions/allocation.py +2 -2
- classiq/qmod/builtins/functions/arithmetic.py +16 -8
- classiq/qmod/builtins/functions/exponentiation.py +32 -4
- classiq/qmod/builtins/functions/standard_gates.py +7 -7
- classiq/qmod/builtins/structs.py +55 -3
- classiq/qmod/declaration_inferrer.py +8 -7
- classiq/qmod/native/pretty_printer.py +7 -11
- classiq/qmod/pretty_print/expression_to_python.py +2 -1
- classiq/qmod/pretty_print/pretty_printer.py +7 -12
- classiq/qmod/python_classical_type.py +12 -5
- classiq/qmod/qfunc.py +1 -1
- classiq/qmod/qmod_constant.py +2 -5
- classiq/qmod/qmod_parameter.py +2 -5
- classiq/qmod/qmod_variable.py +66 -25
- classiq/qmod/quantum_expandable.py +4 -2
- classiq/qmod/quantum_function.py +7 -2
- classiq/qmod/semantics/annotation/qstruct_annotator.py +1 -1
- classiq/qmod/semantics/validation/main_validation.py +1 -9
- classiq/qmod/semantics/validation/type_hints.py +9 -9
- classiq/qmod/utilities.py +0 -2
- classiq/qmod/write_qmod.py +1 -1
- classiq/synthesis.py +0 -2
- {classiq-0.82.1.dist-info → classiq-0.84.0.dist-info}/METADATA +4 -1
- {classiq-0.82.1.dist-info → classiq-0.84.0.dist-info}/RECORD +95 -86
- classiq/interface/generator/functions/type_qualifier.py +0 -22
- /classiq/{model_expansions/evaluators → evaluators}/__init__.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/control.py +0 -0
- /classiq/{model_expansions → evaluators}/expression_evaluator.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/quantum_type_utils.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/type_type_match.py +0 -0
- {classiq-0.82.1.dist-info → classiq-0.84.0.dist-info}/WHEEL +0 -0
@@ -1,5 +1,6 @@
|
|
1
1
|
from classiq.open_library.functions.qft_functions import qft, qft_no_swap
|
2
2
|
from classiq.qmod.builtins.classical_functions import qft_const_adder_phase
|
3
|
+
from classiq.qmod.builtins.functions.allocation import free
|
3
4
|
from classiq.qmod.builtins.functions.standard_gates import PHASE, SWAP, X
|
4
5
|
from classiq.qmod.builtins.operations import (
|
5
6
|
allocate,
|
@@ -11,7 +12,7 @@ from classiq.qmod.builtins.operations import (
|
|
11
12
|
)
|
12
13
|
from classiq.qmod.cparam import CInt
|
13
14
|
from classiq.qmod.qfunc import qfunc
|
14
|
-
from classiq.qmod.qmod_variable import QArray, QBit
|
15
|
+
from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit
|
15
16
|
from classiq.qmod.symbolic import min, mod_inverse
|
16
17
|
|
17
18
|
|
@@ -50,8 +51,10 @@ def qft_space_add_const(value: CInt, phi_b: QArray[QBit]) -> None:
|
|
50
51
|
)
|
51
52
|
|
52
53
|
|
53
|
-
@qfunc
|
54
|
-
def cc_modular_add(
|
54
|
+
@qfunc(unchecked=["phi_b"])
|
55
|
+
def cc_modular_add(
|
56
|
+
n: CInt, a: CInt, phi_b: Permutable[QArray[QBit]], c1: Const[QBit], c2: Const[QBit]
|
57
|
+
) -> None:
|
55
58
|
"""
|
56
59
|
[Qmod Classiq-library function]
|
57
60
|
|
@@ -69,11 +72,9 @@ def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) ->
|
|
69
72
|
ctrl: QArray[QBit] = QArray()
|
70
73
|
aux = QBit()
|
71
74
|
|
75
|
+
allocate(aux)
|
72
76
|
within_apply(
|
73
|
-
lambda: (
|
74
|
-
allocate(aux),
|
75
|
-
bind([c1, c2], ctrl),
|
76
|
-
),
|
77
|
+
lambda: bind([c1, c2], ctrl),
|
77
78
|
lambda: (
|
78
79
|
control(ctrl, lambda: qft_space_add_const(a, phi_b)),
|
79
80
|
invert(lambda: qft_space_add_const(n, phi_b)),
|
@@ -87,11 +88,16 @@ def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) ->
|
|
87
88
|
),
|
88
89
|
),
|
89
90
|
)
|
91
|
+
free(aux)
|
90
92
|
|
91
93
|
|
92
|
-
@qfunc
|
94
|
+
@qfunc(unchecked=["b"])
|
93
95
|
def c_modular_multiply(
|
94
|
-
n: CInt,
|
96
|
+
n: CInt,
|
97
|
+
a: CInt,
|
98
|
+
b: Permutable[QArray[QBit]],
|
99
|
+
x: Const[QArray[QBit]],
|
100
|
+
ctrl: Const[QBit],
|
95
101
|
) -> None:
|
96
102
|
"""
|
97
103
|
[Qmod Classiq-library function]
|
@@ -118,7 +124,7 @@ def c_modular_multiply(
|
|
118
124
|
|
119
125
|
|
120
126
|
@qfunc
|
121
|
-
def multiswap(x: QArray[QBit], y: QArray[QBit]) -> None:
|
127
|
+
def multiswap(x: Permutable[QArray[QBit]], y: Permutable[QArray[QBit]]) -> None:
|
122
128
|
"""
|
123
129
|
[Qmod Classiq-library function]
|
124
130
|
|
@@ -150,16 +156,12 @@ def inplace_c_modular_multiply(n: CInt, a: CInt, x: QArray[QBit], ctrl: QBit) ->
|
|
150
156
|
x: The quantum factor.
|
151
157
|
ctrl: The control bit.
|
152
158
|
"""
|
153
|
-
b: QArray[QBit] = QArray()
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
control(ctrl, lambda: multiswap(x, b)),
|
160
|
-
invert(lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl)),
|
161
|
-
),
|
162
|
-
)
|
159
|
+
b: QArray[QBit] = QArray(length=x.len + 1)
|
160
|
+
allocate(b)
|
161
|
+
c_modular_multiply(n, a, b, x, ctrl)
|
162
|
+
control(ctrl, lambda: multiswap(x, b))
|
163
|
+
invert(lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl))
|
164
|
+
free(b)
|
163
165
|
|
164
166
|
|
165
167
|
@qfunc
|
@@ -458,7 +458,7 @@ def prepare_dicke_state_unary_input(max_k: int, qvar: QArray[QBit]) -> None:
|
|
458
458
|
"""
|
459
459
|
if qvar.len > max(1, max_k):
|
460
460
|
_dicke_split_cycle_shift(max_k, qvar)
|
461
|
-
prepare_dicke_state_unary_input(
|
461
|
+
prepare_dicke_state_unary_input(min(max_k, qvar.len - 2), qvar[1 : qvar.len])
|
462
462
|
|
463
463
|
|
464
464
|
@qfunc
|
@@ -483,3 +483,20 @@ def prepare_dicke_state(k: int, qvar: QArray[QBit]) -> None:
|
|
483
483
|
if k > 0:
|
484
484
|
apply_to_all(X, qvar[0:k])
|
485
485
|
prepare_dicke_state_unary_input(k, qvar)
|
486
|
+
|
487
|
+
|
488
|
+
@qfunc
|
489
|
+
def prepare_basis_state(state: list[bool], arr: Output[QArray]) -> None:
|
490
|
+
"""
|
491
|
+
[Qmod Classiq-library function]
|
492
|
+
|
493
|
+
Initializes a quantum array in the specified basis state.
|
494
|
+
|
495
|
+
Args:
|
496
|
+
values: The desired basis state, given as a list of boolean values for each qubit.
|
497
|
+
arr: The quantum array to prepare.
|
498
|
+
"""
|
499
|
+
allocate(len(state), arr)
|
500
|
+
for idx, value in enumerate(state):
|
501
|
+
if value:
|
502
|
+
X(arr[idx])
|
classiq/qmod/__init__.py
CHANGED
@@ -6,7 +6,7 @@ from .expression_query import get_expression_numeric_attributes
|
|
6
6
|
from .qfunc import qfunc
|
7
7
|
from .qmod_constant import QConstant
|
8
8
|
from .qmod_parameter import Array, CArray, CBool, CInt, CReal
|
9
|
-
from .qmod_variable import Const, Input, Output, QArray, QBit,
|
9
|
+
from .qmod_variable import Const, Input, Output, Permutable, QArray, QBit, QNum, QStruct
|
10
10
|
from .quantum_callable import QCallable, QCallableList
|
11
11
|
from .write_qmod import write_qmod
|
12
12
|
|
@@ -19,7 +19,7 @@ __all__ = [
|
|
19
19
|
"Input",
|
20
20
|
"Output",
|
21
21
|
"Const",
|
22
|
-
"
|
22
|
+
"Permutable",
|
23
23
|
"QArray",
|
24
24
|
"QBit",
|
25
25
|
"QNum",
|
classiq/qmod/builtins/enums.py
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
from enum import IntEnum
|
2
|
+
from typing import TYPE_CHECKING
|
2
3
|
|
3
4
|
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
4
5
|
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from classiq.qmod.builtins.structs import SparsePauliOp
|
8
|
+
|
5
9
|
|
6
10
|
class Element(IntEnum):
|
7
11
|
H = 0
|
@@ -176,6 +180,25 @@ class Pauli(IntEnum):
|
|
176
180
|
"""Z (int): Pauli-Z matrix, represented by the integer 3. \n
|
177
181
|
$Z = \\begin{bmatrix} 1 & 0 \\\\ 0 & -1 \\end{bmatrix}$"""
|
178
182
|
|
183
|
+
def __call__(self, index: int) -> "SparsePauliOp":
|
184
|
+
from classiq.qmod.builtins.structs import (
|
185
|
+
IndexedPauli,
|
186
|
+
SparsePauliOp,
|
187
|
+
SparsePauliTerm,
|
188
|
+
)
|
189
|
+
|
190
|
+
return SparsePauliOp(
|
191
|
+
terms=[ # type:ignore[arg-type]
|
192
|
+
SparsePauliTerm(
|
193
|
+
paulis=[ # type:ignore[arg-type]
|
194
|
+
IndexedPauli(pauli=self, index=index) # type:ignore[arg-type]
|
195
|
+
],
|
196
|
+
coefficient=1.0, # type:ignore[arg-type]
|
197
|
+
)
|
198
|
+
],
|
199
|
+
num_qubits=index + 1, # type:ignore[arg-type]
|
200
|
+
)
|
201
|
+
|
179
202
|
|
180
203
|
class QSVMFeatureMapEntanglement(IntEnum):
|
181
204
|
FULL = 0
|
@@ -71,6 +71,7 @@ CORE_LIB_DECLS = [
|
|
71
71
|
single_pauli_exponent,
|
72
72
|
commuting_paulis_exponent,
|
73
73
|
suzuki_trotter,
|
74
|
+
multi_suzuki_trotter,
|
74
75
|
parametric_suzuki_trotter,
|
75
76
|
sparse_suzuki_trotter,
|
76
77
|
qdrift,
|
@@ -132,6 +133,7 @@ __all__ = [ # noqa: RUF022
|
|
132
133
|
"molecule_hartree_fock",
|
133
134
|
"molecule_hva",
|
134
135
|
"molecule_ucc",
|
136
|
+
"multi_suzuki_trotter",
|
135
137
|
"parametric_suzuki_trotter",
|
136
138
|
"pauli_feature_map",
|
137
139
|
"permute",
|
@@ -2,11 +2,11 @@ from typing import Literal
|
|
2
2
|
|
3
3
|
from classiq.qmod.qfunc import qfunc
|
4
4
|
from classiq.qmod.qmod_parameter import CArray, CReal
|
5
|
-
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit
|
5
|
+
from classiq.qmod.qmod_variable import Input, Output, Permutable, QArray, QBit
|
6
6
|
|
7
7
|
|
8
8
|
@qfunc(external=True)
|
9
|
-
def free(in_:
|
9
|
+
def free(in_: Permutable[Input[QArray[QBit]]]) -> None:
|
10
10
|
"""
|
11
11
|
[Qmod core-library function]
|
12
12
|
|
@@ -2,7 +2,15 @@ from typing import Literal
|
|
2
2
|
|
3
3
|
from classiq.qmod.qfunc import qfunc
|
4
4
|
from classiq.qmod.qmod_parameter import CArray, CBool, CReal
|
5
|
-
from classiq.qmod.qmod_variable import
|
5
|
+
from classiq.qmod.qmod_variable import (
|
6
|
+
Const,
|
7
|
+
Input,
|
8
|
+
Output,
|
9
|
+
Permutable,
|
10
|
+
QArray,
|
11
|
+
QBit,
|
12
|
+
QNum,
|
13
|
+
)
|
6
14
|
|
7
15
|
|
8
16
|
@qfunc(external=True)
|
@@ -26,7 +34,7 @@ def unitary(
|
|
26
34
|
def add(
|
27
35
|
left: Const[QNum],
|
28
36
|
right: Const[QNum],
|
29
|
-
result:
|
37
|
+
result: Permutable[
|
30
38
|
Output[
|
31
39
|
QNum[
|
32
40
|
Literal["result_size"],
|
@@ -45,8 +53,8 @@ def add(
|
|
45
53
|
@qfunc(external=True)
|
46
54
|
def add_inplace_right(
|
47
55
|
left: Const[QNum],
|
48
|
-
right:
|
49
|
-
result:
|
56
|
+
right: Permutable[Input[QNum]],
|
57
|
+
result: Permutable[
|
50
58
|
Output[
|
51
59
|
QNum[
|
52
60
|
Literal["result_size"],
|
@@ -63,20 +71,20 @@ def add_inplace_right(
|
|
63
71
|
|
64
72
|
|
65
73
|
@qfunc(external=True)
|
66
|
-
def modular_add(left: Const[QArray[QBit]], right:
|
74
|
+
def modular_add(left: Const[QArray[QBit]], right: Permutable[QArray[QBit]]) -> None:
|
67
75
|
pass
|
68
76
|
|
69
77
|
|
70
78
|
@qfunc(external=True)
|
71
|
-
def modular_add_constant(left: CReal, right:
|
79
|
+
def modular_add_constant(left: CReal, right: Permutable[QNum]) -> None:
|
72
80
|
pass
|
73
81
|
|
74
82
|
|
75
83
|
@qfunc(external=True)
|
76
|
-
def integer_xor(left: Const[QArray[QBit]], right:
|
84
|
+
def integer_xor(left: Const[QArray[QBit]], right: Permutable[QArray[QBit]]) -> None:
|
77
85
|
pass
|
78
86
|
|
79
87
|
|
80
88
|
@qfunc(external=True)
|
81
|
-
def real_xor_constant(left: CReal, right:
|
89
|
+
def real_xor_constant(left: CReal, right: Permutable[QNum]) -> None:
|
82
90
|
pass
|
@@ -55,13 +55,11 @@ def commuting_paulis_exponent(
|
|
55
55
|
|
56
56
|
@qfunc(external=True)
|
57
57
|
def suzuki_trotter(
|
58
|
-
pauli_operator:
|
58
|
+
pauli_operator: SparsePauliOp, # FIXME: Rename to hamiltonian (CLS-2912)
|
59
59
|
evolution_coefficient: CReal,
|
60
60
|
order: CInt,
|
61
61
|
repetitions: CInt,
|
62
|
-
qbv: QArray[
|
63
|
-
QBit, Literal["get_field(get_field(pauli_operator[0], 'pauli'), 'len')"]
|
64
|
-
],
|
62
|
+
qbv: QArray[QBit], # FIXME: Add length expr (CLS-2912)
|
65
63
|
) -> None:
|
66
64
|
"""
|
67
65
|
[Qmod core-library function]
|
@@ -82,6 +80,36 @@ def suzuki_trotter(
|
|
82
80
|
pass
|
83
81
|
|
84
82
|
|
83
|
+
@qfunc(external=True)
|
84
|
+
def multi_suzuki_trotter(
|
85
|
+
hamiltonians: CArray[SparsePauliOp],
|
86
|
+
evolution_coefficients: CArray[CReal],
|
87
|
+
order: CInt,
|
88
|
+
repetitions: CInt,
|
89
|
+
qbv: QArray,
|
90
|
+
) -> None:
|
91
|
+
"""
|
92
|
+
[Qmod core-library function]
|
93
|
+
|
94
|
+
Applies the Suzuki-Trotter decomposition jointly to a sum of Hamiltonians
|
95
|
+
(represented as Pauli operators), each with its separate evolution coefficient,
|
96
|
+
approximating $\\exp{-iH_1t_1+H_2t_2+\\dots}$ with a specified order and number of
|
97
|
+
repetitions.
|
98
|
+
|
99
|
+
The Suzuki-Trotter decomposition is a method for approximating the exponential of a sum of operators by a product of exponentials of each operator.
|
100
|
+
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.
|
101
|
+
The error of a Suzuki-Trotter decomposition decreases as the order and number of repetitions increase.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
hamiltonians: The hamitonians to be exponentiated, in sparse representation.
|
105
|
+
evolution_coefficients: The hamiltonian coefficients (can be link-time).
|
106
|
+
order: The order of the Suzuki-Trotter decomposition.
|
107
|
+
repetitions: The number of repetitions of the Suzuki-Trotter decomposition.
|
108
|
+
qbv: The target quantum variable of the exponentiation.
|
109
|
+
"""
|
110
|
+
pass
|
111
|
+
|
112
|
+
|
85
113
|
@qfunc(external=True)
|
86
114
|
def parametric_suzuki_trotter(
|
87
115
|
paulis: CArray[CArray[Pauli]],
|
@@ -2,7 +2,7 @@ from typing import Literal
|
|
2
2
|
|
3
3
|
from classiq.qmod.qfunc import qfunc
|
4
4
|
from classiq.qmod.qmod_parameter import CReal
|
5
|
-
from classiq.qmod.qmod_variable import Const, QArray, QBit
|
5
|
+
from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit
|
6
6
|
|
7
7
|
|
8
8
|
@qfunc(external=True)
|
@@ -25,7 +25,7 @@ def H(target: QBit) -> None:
|
|
25
25
|
|
26
26
|
|
27
27
|
@qfunc(external=True)
|
28
|
-
def X(target:
|
28
|
+
def X(target: Permutable[QBit]) -> None:
|
29
29
|
"""
|
30
30
|
[Qmod core-library function]
|
31
31
|
|
@@ -44,7 +44,7 @@ def X(target: QFree[QBit]) -> None:
|
|
44
44
|
|
45
45
|
|
46
46
|
@qfunc(external=True)
|
47
|
-
def Y(target:
|
47
|
+
def Y(target: Permutable[QBit]) -> None:
|
48
48
|
"""
|
49
49
|
[Qmod core-library function]
|
50
50
|
|
@@ -370,7 +370,7 @@ def CH(ctrl: Const[QBit], target: QBit) -> None:
|
|
370
370
|
|
371
371
|
|
372
372
|
@qfunc(external=True)
|
373
|
-
def CX(ctrl: Const[QBit], target:
|
373
|
+
def CX(ctrl: Const[QBit], target: Permutable[QBit]) -> None:
|
374
374
|
"""
|
375
375
|
[Qmod core-library function]
|
376
376
|
|
@@ -395,7 +395,7 @@ def CX(ctrl: Const[QBit], target: QFree[QBit]) -> None:
|
|
395
395
|
|
396
396
|
|
397
397
|
@qfunc(external=True)
|
398
|
-
def CY(ctrl: Const[QBit], target:
|
398
|
+
def CY(ctrl: Const[QBit], target: Permutable[QBit]) -> None:
|
399
399
|
"""
|
400
400
|
[Qmod core-library function]
|
401
401
|
|
@@ -549,7 +549,7 @@ def CPHASE(theta: CReal, ctrl: Const[QBit], target: Const[QBit]) -> None:
|
|
549
549
|
|
550
550
|
|
551
551
|
@qfunc(external=True)
|
552
|
-
def SWAP(qbit0:
|
552
|
+
def SWAP(qbit0: Permutable[QBit], qbit1: Permutable[QBit]) -> None:
|
553
553
|
"""
|
554
554
|
[Qmod core-library function]
|
555
555
|
|
@@ -623,7 +623,7 @@ def U(theta: CReal, phi: CReal, lam: CReal, gam: CReal, target: QBit) -> None:
|
|
623
623
|
|
624
624
|
|
625
625
|
@qfunc(external=True)
|
626
|
-
def CCX(ctrl: Const[QArray[QBit, Literal[2]]], target:
|
626
|
+
def CCX(ctrl: Const[QArray[QBit, Literal[2]]], target: Permutable[QBit]) -> None:
|
627
627
|
"""
|
628
628
|
[Qmod core-library function]
|
629
629
|
|
classiq/qmod/builtins/structs.py
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
from dataclasses import dataclass, fields, is_dataclass
|
2
|
+
from typing import Union
|
2
3
|
|
4
|
+
from classiq.interface.exceptions import ClassiqValueError
|
3
5
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
6
|
+
from classiq.interface.helpers.text_utils import are, readable_list, s
|
4
7
|
|
5
8
|
from classiq.qmod.builtins.enums import LadderOperator, Pauli
|
6
9
|
from classiq.qmod.cparam import CArray, CBool, CInt, CReal
|
@@ -56,13 +59,62 @@ class SparsePauliOp:
|
|
56
59
|
Represents a collection of sparse Pauli operators.
|
57
60
|
|
58
61
|
Attributes:
|
59
|
-
|
62
|
+
terms (CArray[SparsePauliTerm]): The list of chosen sparse Pauli terms, corresponds to a product of them. (See: SparsePauliTerm)
|
60
63
|
num_qubits (CInt): The number of qubits in the Hamiltonian.
|
61
64
|
"""
|
62
65
|
|
63
|
-
|
66
|
+
terms: CArray[SparsePauliTerm]
|
64
67
|
num_qubits: CInt
|
65
68
|
|
69
|
+
def __mul__(self, obj: Union[float, "SparsePauliOp"]) -> "SparsePauliOp":
|
70
|
+
if isinstance(obj, (int, float, complex)):
|
71
|
+
return SparsePauliOp(
|
72
|
+
terms=[ # type:ignore[arg-type]
|
73
|
+
SparsePauliTerm(
|
74
|
+
paulis=term.paulis,
|
75
|
+
coefficient=obj * term.coefficient,
|
76
|
+
)
|
77
|
+
for term in self.terms # type:ignore[attr-defined]
|
78
|
+
],
|
79
|
+
num_qubits=self.num_qubits,
|
80
|
+
)
|
81
|
+
if len(self.terms) != 1 or len(obj.terms) != 1: # type:ignore[arg-type]
|
82
|
+
raise ClassiqValueError("Cannot attach a pauli to multiple pauli terms")
|
83
|
+
existing_indices = {
|
84
|
+
indexed_pauli.index for indexed_pauli in self.terms[0].paulis
|
85
|
+
}
|
86
|
+
added_indices = {indexed_pauli.index for indexed_pauli in obj.terms[0].paulis}
|
87
|
+
overlapping_indices = sorted(existing_indices.intersection(added_indices))
|
88
|
+
if len(overlapping_indices):
|
89
|
+
raise ClassiqValueError(
|
90
|
+
f"Pauli{s(overlapping_indices)} at "
|
91
|
+
f"{'indices' if len(overlapping_indices) > 1 else 'index'} "
|
92
|
+
f"{readable_list(overlapping_indices)} {are(overlapping_indices)} "
|
93
|
+
f"already assigned"
|
94
|
+
)
|
95
|
+
return SparsePauliOp(
|
96
|
+
terms=[ # type:ignore[arg-type]
|
97
|
+
SparsePauliTerm(
|
98
|
+
paulis=self.terms[0].paulis + obj.terms[0].paulis,
|
99
|
+
coefficient=self.terms[0].coefficient * obj.terms[0].coefficient,
|
100
|
+
)
|
101
|
+
],
|
102
|
+
num_qubits=max(
|
103
|
+
self.num_qubits, obj.num_qubits # type:ignore[call-overload]
|
104
|
+
),
|
105
|
+
)
|
106
|
+
|
107
|
+
def __rmul__(self, obj: Union[float, "SparsePauliOp"]) -> "SparsePauliOp":
|
108
|
+
return self.__mul__(obj)
|
109
|
+
|
110
|
+
def __add__(self, other: "SparsePauliOp") -> "SparsePauliOp":
|
111
|
+
return SparsePauliOp(
|
112
|
+
terms=self.terms + other.terms, # type:ignore[arg-type]
|
113
|
+
num_qubits=max(
|
114
|
+
self.num_qubits, other.num_qubits # type:ignore[call-overload]
|
115
|
+
),
|
116
|
+
)
|
117
|
+
|
66
118
|
|
67
119
|
@dataclass
|
68
120
|
class Position:
|
@@ -167,7 +219,7 @@ BUILTIN_STRUCT_DECLARATIONS = {
|
|
167
219
|
struct_decl.__name__: StructDeclaration(
|
168
220
|
name=struct_decl.__name__,
|
169
221
|
variables={
|
170
|
-
field.name: PythonClassicalType().convert(field.type)
|
222
|
+
field.name: PythonClassicalType().convert(field.type, nested=True)
|
171
223
|
for field in fields(struct_decl)
|
172
224
|
},
|
173
225
|
)
|
@@ -19,8 +19,8 @@ from classiq.interface.generator.functions.concrete_types import ConcreteClassic
|
|
19
19
|
from classiq.interface.generator.functions.port_declaration import (
|
20
20
|
PortDeclarationDirection,
|
21
21
|
)
|
22
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
22
23
|
from classiq.interface.generator.functions.type_name import TypeName
|
23
|
-
from classiq.interface.generator.functions.type_qualifier import TypeQualifier
|
24
24
|
from classiq.interface.generator.types.enum_declaration import declaration_from_enum
|
25
25
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
26
26
|
from classiq.interface.model.classical_parameter_declaration import (
|
@@ -75,14 +75,15 @@ class _PythonClassicalType(PythonClassicalType):
|
|
75
75
|
all_decls = BUILTIN_STRUCT_DECLARATIONS | self.qmodule.type_decls
|
76
76
|
if py_type.__name__ in all_decls:
|
77
77
|
classical_type.set_classical_struct_decl(
|
78
|
-
all_decls[py_type.__name__].model_copy()
|
78
|
+
all_decls[py_type.__name__].model_copy(deep=True)
|
79
79
|
)
|
80
80
|
return classical_type
|
81
81
|
|
82
82
|
struct_decl = StructDeclaration(
|
83
83
|
name=py_type.__name__,
|
84
84
|
variables={
|
85
|
-
f.name: self.convert(f.type
|
85
|
+
f.name: self.convert(f.type, nested=True)
|
86
|
+
for f in dataclasses.fields(py_type)
|
86
87
|
},
|
87
88
|
)
|
88
89
|
check_duplicate_types([struct_decl, *self.qmodule.user_types()])
|
@@ -100,12 +101,12 @@ def python_type_to_qmod(
|
|
100
101
|
|
101
102
|
|
102
103
|
def _extract_port_decl(name: Optional[str], py_type: Any) -> AnonPortDeclaration:
|
103
|
-
quantum_type, direction,
|
104
|
+
quantum_type, direction, modifier = get_port_from_type_hint(py_type)
|
104
105
|
param = AnonPortDeclaration(
|
105
106
|
name=None,
|
106
107
|
direction=direction,
|
107
108
|
quantum_type=quantum_type,
|
108
|
-
|
109
|
+
type_modifier=modifier,
|
109
110
|
)
|
110
111
|
if name is not None:
|
111
112
|
param = param.rename(name)
|
@@ -163,7 +164,7 @@ def _unpacked_annotated(arg_0: Any, args: Any) -> _AnnotatedAlias:
|
|
163
164
|
|
164
165
|
def _get_param_name(py_type_args: Any) -> Optional[str]:
|
165
166
|
if isinstance(py_type_args[-1], str) and not isinstance(
|
166
|
-
py_type_args[-1], (PortDeclarationDirection,
|
167
|
+
py_type_args[-1], (PortDeclarationDirection, TypeModifier)
|
167
168
|
):
|
168
169
|
return py_type_args[-1]
|
169
170
|
elif py_type_args[-1] is Literal:
|
@@ -176,7 +177,7 @@ def _validate_annotations(py_type_args: Any, py_type: Any) -> None:
|
|
176
177
|
for arg in py_type_args[1:-1]:
|
177
178
|
if (
|
178
179
|
isinstance(arg, str)
|
179
|
-
and not isinstance(arg, (PortDeclarationDirection,
|
180
|
+
and not isinstance(arg, (PortDeclarationDirection, TypeModifier))
|
180
181
|
) or arg is Literal:
|
181
182
|
raise ClassiqValueError(
|
182
183
|
f"Operand parameter declaration must be of the form <param-type> or "
|
@@ -1,13 +1,13 @@
|
|
1
1
|
from collections.abc import Mapping
|
2
2
|
from typing import Optional, Union
|
3
3
|
|
4
|
+
from classiq.interface.constants import DEFAULT_DECIMAL_PRECISION
|
4
5
|
from classiq.interface.exceptions import ClassiqInternalError
|
5
6
|
from classiq.interface.generator.constant import Constant
|
6
7
|
from classiq.interface.generator.expressions.expression import Expression
|
7
8
|
from classiq.interface.generator.functions.classical_type import (
|
8
9
|
Bool,
|
9
10
|
ClassicalArray,
|
10
|
-
ClassicalList,
|
11
11
|
ClassicalTuple,
|
12
12
|
Integer,
|
13
13
|
Real,
|
@@ -19,8 +19,8 @@ from classiq.interface.generator.functions.concrete_types import (
|
|
19
19
|
from classiq.interface.generator.functions.port_declaration import (
|
20
20
|
PortDeclarationDirection,
|
21
21
|
)
|
22
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
22
23
|
from classiq.interface.generator.functions.type_name import TypeName
|
23
|
-
from classiq.interface.generator.functions.type_qualifier import TypeQualifier
|
24
24
|
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
25
25
|
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
26
26
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
@@ -85,11 +85,10 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
85
85
|
VariableDeclarationStatement,
|
86
86
|
)
|
87
87
|
from classiq.interface.model.within_apply_operation import WithinApply
|
88
|
+
from classiq.interface.pretty_print.expression_to_qmod import transform_expression
|
88
89
|
|
89
90
|
from classiq.open_library.functions import OPEN_LIBRARY_FUNCTIONS
|
90
|
-
from classiq.qmod.native.expression_to_qmod import transform_expression
|
91
91
|
from classiq.qmod.semantics.annotation.call_annotation import resolve_function_calls
|
92
|
-
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
93
92
|
|
94
93
|
|
95
94
|
class DSLPrettyPrinter(ModelVisitor):
|
@@ -196,9 +195,9 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
196
195
|
return f"{var_decl.name}: {self.visit(var_decl.quantum_type)}"
|
197
196
|
|
198
197
|
def visit_AnonPortDeclaration(self, port_decl: AnonPortDeclaration) -> str:
|
199
|
-
|
200
|
-
f"{port_decl.
|
201
|
-
if port_decl.
|
198
|
+
modifier_str = (
|
199
|
+
f"{port_decl.type_modifier} "
|
200
|
+
if port_decl.type_modifier in [TypeModifier.Const, TypeModifier.Permutable]
|
202
201
|
else ""
|
203
202
|
)
|
204
203
|
dir_str = (
|
@@ -208,7 +207,7 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
208
207
|
)
|
209
208
|
param_name = f"{port_decl.name}: " if port_decl.name is not None else ""
|
210
209
|
return (
|
211
|
-
f"{
|
210
|
+
f"{modifier_str}{dir_str}{param_name}{self.visit(port_decl.quantum_type)}"
|
212
211
|
)
|
213
212
|
|
214
213
|
def visit_QuantumBit(self, qtype: QuantumBit) -> str:
|
@@ -248,9 +247,6 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
248
247
|
def visit_Bool(self, ctbool: Bool) -> str:
|
249
248
|
return "bool"
|
250
249
|
|
251
|
-
def visit_ClassicalList(self, ctlist: ClassicalList) -> str:
|
252
|
-
return f"{self.visit(ctlist.element_type)}[]"
|
253
|
-
|
254
250
|
def visit_ClassicalArray(self, ctarray: ClassicalArray) -> str:
|
255
251
|
element_type = self.visit(ctarray.element_type)
|
256
252
|
if ctarray.length is not None:
|
@@ -6,8 +6,9 @@ from typing import Callable
|
|
6
6
|
|
7
7
|
import numpy as np
|
8
8
|
|
9
|
+
from classiq.interface.constants import DEFAULT_DECIMAL_PRECISION
|
10
|
+
|
9
11
|
import classiq
|
10
|
-
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
11
12
|
|
12
13
|
IDENTIFIER = re.compile(r"[a-zA-Z_]\w*")
|
13
14
|
BINARY_OPS: Mapping[type[ast.operator], str] = {
|
@@ -3,13 +3,13 @@ from typing import Optional, Union, cast
|
|
3
3
|
|
4
4
|
import black
|
5
5
|
|
6
|
+
from classiq.interface.constants import DEFAULT_DECIMAL_PRECISION
|
6
7
|
from classiq.interface.exceptions import ClassiqInternalError
|
7
8
|
from classiq.interface.generator.constant import Constant
|
8
9
|
from classiq.interface.generator.expressions.expression import Expression
|
9
10
|
from classiq.interface.generator.functions.classical_type import (
|
10
11
|
Bool,
|
11
12
|
ClassicalArray,
|
12
|
-
ClassicalList,
|
13
13
|
ClassicalTuple,
|
14
14
|
Integer,
|
15
15
|
Real,
|
@@ -21,8 +21,8 @@ from classiq.interface.generator.functions.concrete_types import (
|
|
21
21
|
from classiq.interface.generator.functions.port_declaration import (
|
22
22
|
PortDeclarationDirection,
|
23
23
|
)
|
24
|
+
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
24
25
|
from classiq.interface.generator.functions.type_name import TypeName
|
25
|
-
from classiq.interface.generator.functions.type_qualifier import TypeQualifier
|
26
26
|
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
27
27
|
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
28
28
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
@@ -88,7 +88,6 @@ from classiq.interface.model.within_apply_operation import WithinApply
|
|
88
88
|
import classiq
|
89
89
|
from classiq.qmod.builtins.functions import BUILTIN_FUNCTION_DECLARATIONS
|
90
90
|
from classiq.qmod.pretty_print.expression_to_python import transform_expression
|
91
|
-
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
92
91
|
|
93
92
|
|
94
93
|
class VariableDeclarationAssignment(Visitor):
|
@@ -210,8 +209,8 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
210
209
|
if len(unchecked) == 0:
|
211
210
|
return no_unchecked_decorator
|
212
211
|
|
213
|
-
|
214
|
-
unchecked_list = f"[{', '.join(
|
212
|
+
unchecked_modifiers = (f'"{modifier}"' for modifier in unchecked)
|
213
|
+
unchecked_list = f"[{', '.join(unchecked_modifiers)}]"
|
215
214
|
return no_unchecked_decorator + f" (unchecked={unchecked_list})"
|
216
215
|
|
217
216
|
def visit_QuantumFunctionDeclaration(
|
@@ -266,9 +265,9 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
266
265
|
if port_decl.direction is not PortDeclarationDirection.Inout:
|
267
266
|
self._imports[port_decl.direction.name] = 1
|
268
267
|
var_type = f"{port_decl.direction.name}[{var_type}]"
|
269
|
-
if port_decl.
|
270
|
-
self._imports[port_decl.
|
271
|
-
var_type = f"{port_decl.
|
268
|
+
if port_decl.type_modifier in [TypeModifier.Const, TypeModifier.Permutable]:
|
269
|
+
self._imports[port_decl.type_modifier.name] = 1
|
270
|
+
var_type = f"{port_decl.type_modifier.name}[{var_type}]"
|
272
271
|
return var_type
|
273
272
|
|
274
273
|
def visit_QuantumBit(self, qtype: QuantumBit) -> str:
|
@@ -338,10 +337,6 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
338
337
|
self._imports["CBool"] = 1
|
339
338
|
return "CBool"
|
340
339
|
|
341
|
-
def visit_ClassicalList(self, ctlist: ClassicalList) -> str:
|
342
|
-
self._imports["CArray"] = 1
|
343
|
-
return f"CArray[{self.visit(ctlist.element_type)}]"
|
344
|
-
|
345
340
|
def visit_ClassicalArray(self, ctarray: ClassicalArray) -> str:
|
346
341
|
self._imports["CArray"] = 1
|
347
342
|
element_type = self.visit(ctarray.element_type)
|