fockit 0.0.2__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.
- fockit/__init__.py +53 -0
- fockit/_types.py +48 -0
- fockit/_version.py +24 -0
- fockit/algebra.py +275 -0
- fockit/constructors.py +280 -0
- fockit/converters.py +52 -0
- fockit/display.py +150 -0
- fockit/inspection.py +60 -0
- fockit/normal_order.py +142 -0
- fockit/operators.py +318 -0
- fockit/py.typed +0 -0
- fockit/simplify.py +89 -0
- fockit/solve/__init__.py +67 -0
- fockit/solve/basis.py +822 -0
- fockit/solve/diagonalize.py +96 -0
- fockit/solve/evolve.py +326 -0
- fockit/solve/matrix.py +88 -0
- fockit/solve/spaces.py +134 -0
- fockit/solve/thermal.py +196 -0
- fockit/transforms.py +151 -0
- fockit-0.0.2.dist-info/METADATA +83 -0
- fockit-0.0.2.dist-info/RECORD +24 -0
- fockit-0.0.2.dist-info/WHEEL +4 -0
- fockit-0.0.2.dist-info/licenses/LICENSE +21 -0
fockit/__init__.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Symbolic operator algebra for fermions, bosons, and beyond."""
|
|
2
|
+
|
|
3
|
+
from fockit.constructors import (
|
|
4
|
+
b,
|
|
5
|
+
bdag,
|
|
6
|
+
c,
|
|
7
|
+
cdag,
|
|
8
|
+
n,
|
|
9
|
+
nb,
|
|
10
|
+
sigma_x,
|
|
11
|
+
sigma_y,
|
|
12
|
+
sigma_z,
|
|
13
|
+
sm,
|
|
14
|
+
sp,
|
|
15
|
+
)
|
|
16
|
+
from fockit.display import to_latex, to_text
|
|
17
|
+
from fockit.inspection import degree, modes, num_terms
|
|
18
|
+
from fockit.normal_order import is_normal_ordered, normal_order
|
|
19
|
+
from fockit.operators import (
|
|
20
|
+
identity,
|
|
21
|
+
zero,
|
|
22
|
+
)
|
|
23
|
+
from fockit.simplify import drop_zeros, simplify_coeffs
|
|
24
|
+
from fockit.transforms import anticommutator, commutator, hc, substitute_modes
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"anticommutator",
|
|
28
|
+
"b",
|
|
29
|
+
"bdag",
|
|
30
|
+
"c",
|
|
31
|
+
"cdag",
|
|
32
|
+
"commutator",
|
|
33
|
+
"degree",
|
|
34
|
+
"drop_zeros",
|
|
35
|
+
"hc",
|
|
36
|
+
"identity",
|
|
37
|
+
"is_normal_ordered",
|
|
38
|
+
"modes",
|
|
39
|
+
"n",
|
|
40
|
+
"nb",
|
|
41
|
+
"normal_order",
|
|
42
|
+
"num_terms",
|
|
43
|
+
"sigma_x",
|
|
44
|
+
"sigma_y",
|
|
45
|
+
"sigma_z",
|
|
46
|
+
"simplify_coeffs",
|
|
47
|
+
"sm",
|
|
48
|
+
"sp",
|
|
49
|
+
"substitute_modes",
|
|
50
|
+
"to_latex",
|
|
51
|
+
"to_text",
|
|
52
|
+
"zero",
|
|
53
|
+
]
|
fockit/_types.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Shared typing helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Hashable
|
|
6
|
+
from typing import Protocol, SupportsComplex, SupportsFloat, SupportsIndex, cast
|
|
7
|
+
|
|
8
|
+
type Mode = Hashable
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SymbolicCoefficient(Protocol):
|
|
12
|
+
"""Protocol for symbolic coefficient objects."""
|
|
13
|
+
|
|
14
|
+
def __hash__(self) -> int: ...
|
|
15
|
+
|
|
16
|
+
def __add__(self, other: object, /) -> object: ...
|
|
17
|
+
|
|
18
|
+
def __radd__(self, other: object, /) -> object: ...
|
|
19
|
+
|
|
20
|
+
def __sub__(self, other: object, /) -> object: ...
|
|
21
|
+
|
|
22
|
+
def __rsub__(self, other: object, /) -> object: ...
|
|
23
|
+
|
|
24
|
+
def __mul__(self, other: object, /) -> object: ...
|
|
25
|
+
|
|
26
|
+
def __rmul__(self, other: object, /) -> object: ...
|
|
27
|
+
|
|
28
|
+
def __neg__(self) -> object: ...
|
|
29
|
+
|
|
30
|
+
def __abs__(self) -> object: ...
|
|
31
|
+
|
|
32
|
+
def __eq__(self, other: object, /) -> bool: ...
|
|
33
|
+
|
|
34
|
+
def conjugate(self) -> object: ...
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
type Coefficient = int | float | complex | SymbolicCoefficient
|
|
38
|
+
type ComplexConvertible = complex | SupportsComplex | SupportsFloat | SupportsIndex
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def as_coefficient(value: object) -> Coefficient:
|
|
42
|
+
"""Cast a coefficient result back to ``Coefficient``."""
|
|
43
|
+
return cast(Coefficient, value)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def as_complex(value: Coefficient) -> complex:
|
|
47
|
+
"""Convert a coefficient to ``complex``."""
|
|
48
|
+
return complex(cast(ComplexConvertible, value))
|
fockit/_version.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.0.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 0, 2)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|
fockit/algebra.py
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""Algebra rules protocol and concrete implementations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Hashable
|
|
6
|
+
from dataclasses import dataclass, replace
|
|
7
|
+
from enum import StrEnum
|
|
8
|
+
from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
|
9
|
+
|
|
10
|
+
from fockit._types import Coefficient
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from fockit.operators import Op
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Ladder(StrEnum):
|
|
17
|
+
"""Operator kinds for fermions and bosons."""
|
|
18
|
+
|
|
19
|
+
CREATE = "+"
|
|
20
|
+
ANNIHILATE = "-"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Pauli(StrEnum):
|
|
24
|
+
"""Operator kinds for Pauli matrices."""
|
|
25
|
+
|
|
26
|
+
X = "x"
|
|
27
|
+
Y = "y"
|
|
28
|
+
Z = "z"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class SwapResult:
|
|
33
|
+
"""Result of swapping two adjacent operators.
|
|
34
|
+
|
|
35
|
+
Each entry in ``terms`` is a ``(Coefficient, tuple[Op, ...])`` pair,
|
|
36
|
+
where the tuple replaces the original two-operator subsequence.
|
|
37
|
+
|
|
38
|
+
Parameters
|
|
39
|
+
----------
|
|
40
|
+
terms : tuple[tuple[Coefficient, tuple[Op, ...]], ...]
|
|
41
|
+
The replacement terms.
|
|
42
|
+
|
|
43
|
+
Notes
|
|
44
|
+
-----
|
|
45
|
+
For the normal ordering algorithm to terminate, each replacement must
|
|
46
|
+
either shorten the pair (length 0 or 1) or reduce the number of
|
|
47
|
+
inversions (length 2).
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
terms: tuple[tuple[Coefficient, tuple[Op, ...]], ...]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@runtime_checkable
|
|
55
|
+
class AlgebraRules(Protocol):
|
|
56
|
+
"""Protocol defining the (anti)commutation relations for an algebra.
|
|
57
|
+
|
|
58
|
+
Methods only ever receive operators of this algebra. Operators of
|
|
59
|
+
different algebras commute.
|
|
60
|
+
|
|
61
|
+
Notes
|
|
62
|
+
-----
|
|
63
|
+
Implementations MUST define ``__eq__`` and ``__hash__`` so that two
|
|
64
|
+
instances representing the same algebra compare equal and are usable
|
|
65
|
+
as ``lru_cache`` keys.
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def swap(self, left: Op, right: Op) -> SwapResult:
|
|
70
|
+
"""Define what happens when ``left`` and ``right`` are exchanged.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
left : Op
|
|
75
|
+
right : Op
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
SwapResult
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
...
|
|
83
|
+
|
|
84
|
+
def is_normal_ordered_pair(self, left: Op, right: Op) -> bool:
|
|
85
|
+
"""Return True if ``(left, right)`` is already in normal order.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
left : Op
|
|
90
|
+
right : Op
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
bool
|
|
95
|
+
|
|
96
|
+
"""
|
|
97
|
+
...
|
|
98
|
+
|
|
99
|
+
def dagger(self, op: Op) -> Op:
|
|
100
|
+
"""Return the Hermitian conjugate of a single operator.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
op : Op
|
|
105
|
+
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
Op
|
|
109
|
+
|
|
110
|
+
"""
|
|
111
|
+
...
|
|
112
|
+
|
|
113
|
+
def __hash__(self) -> int:
|
|
114
|
+
"""Return hash for use as ``lru_cache`` key."""
|
|
115
|
+
...
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class FermionRules:
|
|
119
|
+
"""Canonical anticommutation relations: {c_a, c†_b} = delta_{ab}."""
|
|
120
|
+
|
|
121
|
+
def swap(self, left: Op, right: Op) -> SwapResult:
|
|
122
|
+
"""Apply fermion swap rules."""
|
|
123
|
+
if left == right:
|
|
124
|
+
return SwapResult(terms=()) # c c = 0
|
|
125
|
+
swapped = ((-1, (right, left)),)
|
|
126
|
+
if (
|
|
127
|
+
left.kind is Ladder.ANNIHILATE
|
|
128
|
+
and right.kind is Ladder.CREATE
|
|
129
|
+
and left.mode == right.mode
|
|
130
|
+
):
|
|
131
|
+
return SwapResult(terms=((1, ()), *swapped))
|
|
132
|
+
return SwapResult(terms=swapped)
|
|
133
|
+
|
|
134
|
+
def is_normal_ordered_pair(self, left: Op, right: Op) -> bool:
|
|
135
|
+
"""Check if a pair is in fermionic normal order.
|
|
136
|
+
|
|
137
|
+
Creators left, canonical mode order within blocks.
|
|
138
|
+
"""
|
|
139
|
+
if left == right:
|
|
140
|
+
return False
|
|
141
|
+
if left.kind is Ladder.CREATE and right.kind is Ladder.ANNIHILATE:
|
|
142
|
+
return True
|
|
143
|
+
if left.kind is Ladder.ANNIHILATE and right.kind is Ladder.CREATE:
|
|
144
|
+
return False
|
|
145
|
+
return mode_sort_key(left.mode) <= mode_sort_key(right.mode)
|
|
146
|
+
|
|
147
|
+
def dagger(self, op: Op) -> Op:
|
|
148
|
+
"""Flip creation ↔ annihilation."""
|
|
149
|
+
flipped = Ladder.CREATE if op.kind is Ladder.ANNIHILATE else Ladder.ANNIHILATE
|
|
150
|
+
return replace(op, kind=flipped)
|
|
151
|
+
|
|
152
|
+
def __eq__(self, other: object) -> bool: # noqa: D105
|
|
153
|
+
return isinstance(other, FermionRules)
|
|
154
|
+
|
|
155
|
+
def __hash__(self) -> int: # noqa: D105
|
|
156
|
+
return hash(type(self))
|
|
157
|
+
|
|
158
|
+
def __repr__(self) -> str: # noqa: D105
|
|
159
|
+
return "FermionRules()"
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class BosonRules:
|
|
163
|
+
"""Canonical commutation relations: [b_a, b†_b] = delta_{ab}."""
|
|
164
|
+
|
|
165
|
+
def swap(self, left: Op, right: Op) -> SwapResult:
|
|
166
|
+
"""Apply boson swap rules."""
|
|
167
|
+
swapped = ((+1, (right, left)),)
|
|
168
|
+
if (
|
|
169
|
+
left.kind is Ladder.ANNIHILATE
|
|
170
|
+
and right.kind is Ladder.CREATE
|
|
171
|
+
and left.mode == right.mode
|
|
172
|
+
):
|
|
173
|
+
return SwapResult(terms=((1, ()), *swapped))
|
|
174
|
+
return SwapResult(terms=swapped)
|
|
175
|
+
|
|
176
|
+
def is_normal_ordered_pair(self, left: Op, right: Op) -> bool:
|
|
177
|
+
"""Check normal ordering for bosonic operators."""
|
|
178
|
+
if left.kind is Ladder.CREATE and right.kind is Ladder.ANNIHILATE:
|
|
179
|
+
return True
|
|
180
|
+
if left.kind is Ladder.ANNIHILATE and right.kind is Ladder.CREATE:
|
|
181
|
+
return False
|
|
182
|
+
return mode_sort_key(left.mode) <= mode_sort_key(right.mode)
|
|
183
|
+
|
|
184
|
+
def dagger(self, op: Op) -> Op:
|
|
185
|
+
"""Flip creation ↔ annihilation."""
|
|
186
|
+
flipped = Ladder.CREATE if op.kind is Ladder.ANNIHILATE else Ladder.ANNIHILATE
|
|
187
|
+
return replace(op, kind=flipped)
|
|
188
|
+
|
|
189
|
+
def __eq__(self, other: object) -> bool: # noqa: D105
|
|
190
|
+
return isinstance(other, BosonRules)
|
|
191
|
+
|
|
192
|
+
def __hash__(self) -> int: # noqa: D105
|
|
193
|
+
return hash(type(self))
|
|
194
|
+
|
|
195
|
+
def __repr__(self) -> str: # noqa: D105
|
|
196
|
+
return "BosonRules()"
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
_PAULI_PRODUCT: dict[tuple[Hashable, Hashable], tuple[complex, Hashable]] = {
|
|
200
|
+
(Pauli.X, Pauli.Y): (1j, Pauli.Z),
|
|
201
|
+
(Pauli.Y, Pauli.X): (-1j, Pauli.Z),
|
|
202
|
+
(Pauli.Y, Pauli.Z): (1j, Pauli.X),
|
|
203
|
+
(Pauli.Z, Pauli.Y): (-1j, Pauli.X),
|
|
204
|
+
(Pauli.Z, Pauli.X): (1j, Pauli.Y),
|
|
205
|
+
(Pauli.X, Pauli.Z): (-1j, Pauli.Y),
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class PauliRules:
|
|
210
|
+
"""Pauli algebra: σ_a σ_b = δ_ab + i ε_abc σ_c on a site, commute across sites."""
|
|
211
|
+
|
|
212
|
+
def swap(self, left: Op, right: Op) -> SwapResult:
|
|
213
|
+
"""Commute across sites, multiply out on the same site."""
|
|
214
|
+
if left.mode != right.mode:
|
|
215
|
+
return SwapResult(terms=((+1, (right, left)),))
|
|
216
|
+
if left.kind == right.kind:
|
|
217
|
+
return SwapResult(terms=((1, ()),))
|
|
218
|
+
phase, kind = _PAULI_PRODUCT[(left.kind, right.kind)]
|
|
219
|
+
return SwapResult(terms=((phase, (replace(left, kind=kind),)),))
|
|
220
|
+
|
|
221
|
+
def is_normal_ordered_pair(self, left: Op, right: Op) -> bool:
|
|
222
|
+
"""Sites in mode order, at most one operator per site."""
|
|
223
|
+
if left.mode == right.mode:
|
|
224
|
+
return False
|
|
225
|
+
return mode_sort_key(left.mode) <= mode_sort_key(right.mode)
|
|
226
|
+
|
|
227
|
+
def dagger(self, op: Op) -> Op:
|
|
228
|
+
"""Pauli operators are Hermitian: dagger is identity."""
|
|
229
|
+
return op
|
|
230
|
+
|
|
231
|
+
def __eq__(self, other: object) -> bool: # noqa: D105
|
|
232
|
+
return isinstance(other, PauliRules)
|
|
233
|
+
|
|
234
|
+
def __hash__(self) -> int: # noqa: D105
|
|
235
|
+
return hash(type(self))
|
|
236
|
+
|
|
237
|
+
def __repr__(self) -> str: # noqa: D105
|
|
238
|
+
return "PauliRules()"
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
FERMION = FermionRules()
|
|
242
|
+
BOSON = BosonRules()
|
|
243
|
+
PAULI = PauliRules()
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def mode_sort_key(mode: Hashable) -> tuple[object, ...]:
|
|
247
|
+
"""Canonical sort key for modes.
|
|
248
|
+
|
|
249
|
+
Stratifies by type first, then compares within type.
|
|
250
|
+
|
|
251
|
+
Parameters
|
|
252
|
+
----------
|
|
253
|
+
mode : Hashable
|
|
254
|
+
The mode label.
|
|
255
|
+
|
|
256
|
+
Returns
|
|
257
|
+
-------
|
|
258
|
+
tuple
|
|
259
|
+
A universally comparable sort key.
|
|
260
|
+
|
|
261
|
+
Notes
|
|
262
|
+
-----
|
|
263
|
+
``bool`` is a subclass of ``int``, so ``True`` and ``1`` produce
|
|
264
|
+
identical sort keys. Avoid using ``bool`` values as modes.
|
|
265
|
+
|
|
266
|
+
"""
|
|
267
|
+
match mode:
|
|
268
|
+
case int():
|
|
269
|
+
return (0, mode)
|
|
270
|
+
case str():
|
|
271
|
+
return (1, mode)
|
|
272
|
+
case tuple():
|
|
273
|
+
return (2, *(mode_sort_key(m) for m in mode))
|
|
274
|
+
case _:
|
|
275
|
+
return (3, repr(mode))
|
fockit/constructors.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"""Constructor functions for operator expressions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Hashable
|
|
6
|
+
|
|
7
|
+
from fockit.algebra import BOSON, FERMION, PAULI, AlgebraRules, Ladder, Pauli
|
|
8
|
+
from fockit.operators import Monomial, Op, OpSum
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _mode(*labels: Hashable) -> Hashable:
|
|
12
|
+
return labels if len(labels) > 1 else labels[0]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def create(*labels: Hashable, rules: AlgebraRules = FERMION) -> OpSum:
|
|
16
|
+
"""Creation operator with the given mode label(s).
|
|
17
|
+
|
|
18
|
+
If one label given: mode is that label.
|
|
19
|
+
If multiple labels given: mode is the tuple of labels.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
*labels : Hashable
|
|
24
|
+
Mode label components.
|
|
25
|
+
rules : AlgebraRules, optional
|
|
26
|
+
Algebra rules. Default: ``FERMION``.
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
OpSum
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
return OpSum({Monomial(ops=(Op(_mode(*labels), Ladder.CREATE, rules),)): 1})
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def annihilate(*labels: Hashable, rules: AlgebraRules = FERMION) -> OpSum:
|
|
37
|
+
"""Annihilation operator.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
*labels : Hashable
|
|
42
|
+
Mode label components.
|
|
43
|
+
rules : AlgebraRules, optional
|
|
44
|
+
Algebra rules. Default: ``FERMION``.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
OpSum
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
return OpSum({Monomial(ops=(Op(_mode(*labels), Ladder.ANNIHILATE, rules),)): 1})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def number(*labels: Hashable, rules: AlgebraRules = FERMION) -> OpSum:
|
|
55
|
+
"""Return the number operator create† * annihilate.
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
*labels : Hashable
|
|
60
|
+
Mode label components.
|
|
61
|
+
rules : AlgebraRules, optional
|
|
62
|
+
Algebra rules. Default: ``FERMION``.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
OpSum
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
return create(*labels, rules=rules) * annihilate(*labels, rules=rules)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def cdag(*labels: Hashable) -> OpSum:
|
|
73
|
+
"""Fermionic creation operator c†.
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
*labels : Hashable
|
|
78
|
+
Mode label components.
|
|
79
|
+
|
|
80
|
+
Returns
|
|
81
|
+
-------
|
|
82
|
+
OpSum
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
return create(*labels, rules=FERMION)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def c(*labels: Hashable) -> OpSum:
|
|
89
|
+
"""Fermionic annihilation operator c.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
*labels : Hashable
|
|
94
|
+
Mode label components.
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
OpSum
|
|
99
|
+
|
|
100
|
+
"""
|
|
101
|
+
return annihilate(*labels, rules=FERMION)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def n(*labels: Hashable) -> OpSum:
|
|
105
|
+
"""Fermionic number operator n = c† c.
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
*labels : Hashable
|
|
110
|
+
Mode label components.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
OpSum
|
|
115
|
+
|
|
116
|
+
"""
|
|
117
|
+
return number(*labels, rules=FERMION)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def bdag(*labels: Hashable) -> OpSum:
|
|
121
|
+
"""Bosonic creation operator b†.
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
*labels : Hashable
|
|
126
|
+
Mode label components.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
OpSum
|
|
131
|
+
|
|
132
|
+
"""
|
|
133
|
+
return create(*labels, rules=BOSON)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def b(*labels: Hashable) -> OpSum:
|
|
137
|
+
"""Bosonic annihilation operator b.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
*labels : Hashable
|
|
142
|
+
Mode label components.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
OpSum
|
|
147
|
+
|
|
148
|
+
"""
|
|
149
|
+
return annihilate(*labels, rules=BOSON)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def nb(*labels: Hashable) -> OpSum:
|
|
153
|
+
"""Bosonic number operator n_b = b† b.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
*labels : Hashable
|
|
158
|
+
Mode label components.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
OpSum
|
|
163
|
+
|
|
164
|
+
"""
|
|
165
|
+
return number(*labels, rules=BOSON)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def sp(*labels: Hashable) -> OpSum:
|
|
169
|
+
"""Pauli raising operator σ+ = (σx + iσy)/2.
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
*labels : Hashable
|
|
174
|
+
Mode label components.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
OpSum
|
|
179
|
+
|
|
180
|
+
"""
|
|
181
|
+
return 0.5 * sigma_x(*labels) + 0.5j * sigma_y(*labels)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def sm(*labels: Hashable) -> OpSum:
|
|
185
|
+
"""Pauli lowering operator σ- = (σx - iσy)/2.
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
*labels : Hashable
|
|
190
|
+
Mode label components.
|
|
191
|
+
|
|
192
|
+
Returns
|
|
193
|
+
-------
|
|
194
|
+
OpSum
|
|
195
|
+
|
|
196
|
+
"""
|
|
197
|
+
return 0.5 * sigma_x(*labels) - 0.5j * sigma_y(*labels)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def sigma_plus(*labels: Hashable) -> OpSum:
|
|
201
|
+
"""Pauli raising operator σ+.
|
|
202
|
+
|
|
203
|
+
Parameters
|
|
204
|
+
----------
|
|
205
|
+
*labels : Hashable
|
|
206
|
+
Mode label components.
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
OpSum
|
|
211
|
+
|
|
212
|
+
"""
|
|
213
|
+
return sp(*labels)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def sigma_minus(*labels: Hashable) -> OpSum:
|
|
217
|
+
"""Pauli lowering operator σ-.
|
|
218
|
+
|
|
219
|
+
Parameters
|
|
220
|
+
----------
|
|
221
|
+
*labels : Hashable
|
|
222
|
+
Mode label components.
|
|
223
|
+
|
|
224
|
+
Returns
|
|
225
|
+
-------
|
|
226
|
+
OpSum
|
|
227
|
+
|
|
228
|
+
"""
|
|
229
|
+
return sm(*labels)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def sigma_x(*labels: Hashable) -> OpSum:
|
|
233
|
+
"""Pauli σ_x operator.
|
|
234
|
+
|
|
235
|
+
Parameters
|
|
236
|
+
----------
|
|
237
|
+
*labels : Hashable
|
|
238
|
+
Mode label components.
|
|
239
|
+
|
|
240
|
+
Returns
|
|
241
|
+
-------
|
|
242
|
+
OpSum
|
|
243
|
+
|
|
244
|
+
"""
|
|
245
|
+
mode = _mode(*labels)
|
|
246
|
+
return OpSum({Monomial(ops=(Op(mode, Pauli.X, PAULI),)): 1})
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def sigma_y(*labels: Hashable) -> OpSum:
|
|
250
|
+
"""Pauli σ_y operator.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
*labels : Hashable
|
|
255
|
+
Mode label components.
|
|
256
|
+
|
|
257
|
+
Returns
|
|
258
|
+
-------
|
|
259
|
+
OpSum
|
|
260
|
+
|
|
261
|
+
"""
|
|
262
|
+
mode = _mode(*labels)
|
|
263
|
+
return OpSum({Monomial(ops=(Op(mode, Pauli.Y, PAULI),)): 1})
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def sigma_z(*labels: Hashable) -> OpSum:
|
|
267
|
+
"""Pauli σ_z operator.
|
|
268
|
+
|
|
269
|
+
Parameters
|
|
270
|
+
----------
|
|
271
|
+
*labels : Hashable
|
|
272
|
+
Mode label components.
|
|
273
|
+
|
|
274
|
+
Returns
|
|
275
|
+
-------
|
|
276
|
+
OpSum
|
|
277
|
+
|
|
278
|
+
"""
|
|
279
|
+
mode = _mode(*labels)
|
|
280
|
+
return OpSum({Monomial(ops=(Op(mode, Pauli.Z, PAULI),)): 1})
|