stabtab 0.2.0__tar.gz → 0.3.0__tar.gz
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.
- {stabtab-0.2.0 → stabtab-0.3.0}/PKG-INFO +1 -1
- {stabtab-0.2.0 → stabtab-0.3.0}/pyproject.toml +1 -1
- {stabtab-0.2.0 → stabtab-0.3.0}/stabtab/tableau.py +58 -2
- {stabtab-0.2.0 → stabtab-0.3.0}/stabtab.egg-info/PKG-INFO +1 -1
- {stabtab-0.2.0 → stabtab-0.3.0}/README.md +0 -0
- {stabtab-0.2.0 → stabtab-0.3.0}/setup.cfg +0 -0
- {stabtab-0.2.0 → stabtab-0.3.0}/stabtab/__init__.py +0 -0
- {stabtab-0.2.0 → stabtab-0.3.0}/stabtab.egg-info/SOURCES.txt +0 -0
- {stabtab-0.2.0 → stabtab-0.3.0}/stabtab.egg-info/dependency_links.txt +0 -0
- {stabtab-0.2.0 → stabtab-0.3.0}/stabtab.egg-info/requires.txt +0 -0
- {stabtab-0.2.0 → stabtab-0.3.0}/stabtab.egg-info/top_level.txt +0 -0
|
@@ -112,6 +112,60 @@ class Tableau:
|
|
|
112
112
|
if not 0 <= a < self.n_qubits:
|
|
113
113
|
raise ValueError(f"Qubit idx {a} out of range [0..{self.n_qubits}]")
|
|
114
114
|
|
|
115
|
+
def to_statevector(self) -> np.ndarray:
|
|
116
|
+
n = self.n_qubits
|
|
117
|
+
if n > 16:
|
|
118
|
+
raise ValueError("Statevector display is limited to 16 qubits")
|
|
119
|
+
indices = np.arange(1 << n)
|
|
120
|
+
|
|
121
|
+
def apply_pauli(row, vector):
|
|
122
|
+
x, z = row[:n], row[n : 2 * n]
|
|
123
|
+
flips = sum(int(x[q]) << (n - q - 1) for q in range(n))
|
|
124
|
+
phases = np.full(
|
|
125
|
+
indices.size,
|
|
126
|
+
(-1 if row[-1] else 1) * 1j ** int(np.count_nonzero(x & z)),
|
|
127
|
+
dtype=complex,
|
|
128
|
+
)
|
|
129
|
+
for q in np.flatnonzero(z):
|
|
130
|
+
phases *= 1 - 2 * ((indices >> (n - int(q) - 1)) & 1)
|
|
131
|
+
result = np.empty_like(vector)
|
|
132
|
+
result[indices ^ flips] = phases * vector
|
|
133
|
+
return result
|
|
134
|
+
|
|
135
|
+
vector = np.zeros(indices.size, dtype=complex)
|
|
136
|
+
vector[0] = 1
|
|
137
|
+
for i in range(n):
|
|
138
|
+
projected = vector + apply_pauli(self.tableau[n + i], vector)
|
|
139
|
+
norm = np.linalg.norm(projected)
|
|
140
|
+
if norm < 1e-12:
|
|
141
|
+
vector = apply_pauli(self.tableau[i], vector)
|
|
142
|
+
else:
|
|
143
|
+
vector = projected / norm
|
|
144
|
+
first = vector[np.flatnonzero(np.abs(vector) > 1e-12)[0]]
|
|
145
|
+
return vector * (first.conjugate() / abs(first))
|
|
146
|
+
|
|
147
|
+
def print_state(self):
|
|
148
|
+
terms: list[str] = []
|
|
149
|
+
for basis, amplitude in enumerate(self.to_statevector()):
|
|
150
|
+
if abs(amplitude) < 1e-12:
|
|
151
|
+
continue
|
|
152
|
+
imaginary = abs(amplitude.real) < 1e-12
|
|
153
|
+
value = amplitude.imag if imaginary else amplitude.real
|
|
154
|
+
coefficient = "i" if imaginary else ""
|
|
155
|
+
sign = (
|
|
156
|
+
(" - " if value < 0 else " + ") if terms else ("-" if value < 0 else "")
|
|
157
|
+
)
|
|
158
|
+
terms.append(f"{sign}{coefficient}|{basis:0{self.n_qubits}b}⟩")
|
|
159
|
+
ket = "".join(terms)
|
|
160
|
+
exponent = len(terms).bit_length() - 1
|
|
161
|
+
factor = 1 << (exponent // 2)
|
|
162
|
+
if exponent % 2:
|
|
163
|
+
denominator = "√2" if factor == 1 else f"({factor}√2)"
|
|
164
|
+
else:
|
|
165
|
+
denominator = str(factor)
|
|
166
|
+
expression = ket if len(terms) == 1 else f"({ket}) / {denominator}"
|
|
167
|
+
print(f"|ψ⟩ = {expression}")
|
|
168
|
+
|
|
115
169
|
def __str__(self):
|
|
116
170
|
n = self.n_qubits
|
|
117
171
|
index_width = len(str(n - 1))
|
|
@@ -119,7 +173,7 @@ class Tableau:
|
|
|
119
173
|
header = " │ ".join([" " * (n + index_width + 4), *columns, "r"]) + " │"
|
|
120
174
|
separator = "".join("┼" if char == "│" else "─" for char in header)
|
|
121
175
|
lines = [header, separator]
|
|
122
|
-
for i, row in enumerate(self.tableau[:2 * n].view(np.uint8)):
|
|
176
|
+
for i, row in enumerate(self.tableau[: 2 * n].view(np.uint8)):
|
|
123
177
|
if i == n:
|
|
124
178
|
lines.append(separator)
|
|
125
179
|
row_type = "D" if i < n else "S"
|
|
@@ -135,7 +189,9 @@ class Tableau:
|
|
|
135
189
|
sign = "-" if row[-1] else "+"
|
|
136
190
|
return sign + "".join(
|
|
137
191
|
"IXZY"[int(x) + 2 * int(z)]
|
|
138
|
-
for x, z in zip(
|
|
192
|
+
for x, z in zip(
|
|
193
|
+
row[: self.n_qubits], row[self.n_qubits : 2 * self.n_qubits]
|
|
194
|
+
)
|
|
139
195
|
)
|
|
140
196
|
|
|
141
197
|
def __repr__(self):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|