ultraqse 1.0.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.
qse/__init__.py ADDED
@@ -0,0 +1,74 @@
1
+ """
2
+ QSE Framework — Von Neumann Entropy via Walsh-Hadamard transforms over GF(2).
3
+
4
+ Quick start::
5
+
6
+ from qse import t14_Pb, vne_from_Pb, f2_rank
7
+
8
+ thetas = [0.8, 1.2] # Rx rotation angles for A-qubits
9
+ pairs = [(0, 0), (1, 0)] # CNOT(ctrl=0,tgt=B0), CNOT(ctrl=1,tgt=B0)
10
+ NA, NB = 2, 1
11
+
12
+ Pb, _ = t14_Pb(thetas, pairs, NA, NB)
13
+ vne = vne_from_Pb(Pb)
14
+
15
+ Submodules:
16
+ core — phi_dict, t14_Pb, t_universal, vne_from_Pb, renyi_entropy,
17
+ f2_rank, t22_moment, newton_girard, build_M
18
+ states — product_state, product_state_ry, exact_rho_B,
19
+ exact_rho_B_mixed, vne_exact
20
+ gates — apply_cnot, apply_fsim, apply_swap
21
+ gradients — vne_gradient_rx
22
+ noise — amplitude_damping_kraus, superop, noise_transfer_Pb,
23
+ build_cnot_ad_transfer
24
+ random_circuits — gaussian_binom_2, expected_gf2_rank, enumerate_vne
25
+ """
26
+
27
+ __version__ = "1.0.0"
28
+
29
+ from qse.core import (
30
+ build_M,
31
+ phi_dict,
32
+ t14_Pb,
33
+ t_universal,
34
+ vne_from_Pb,
35
+ renyi_entropy,
36
+ f2_rank,
37
+ t22_moment,
38
+ newton_girard,
39
+ )
40
+ from qse.states import (
41
+ product_state,
42
+ product_state_ry,
43
+ exact_rho_B,
44
+ exact_rho_B_mixed,
45
+ vne_exact,
46
+ )
47
+ from qse.gates import apply_cnot, apply_fsim, apply_swap
48
+ from qse.gradients import vne_gradient_rx
49
+ from qse.noise import (
50
+ amplitude_damping_kraus,
51
+ superop,
52
+ noise_transfer_Pb,
53
+ build_cnot_ad_transfer,
54
+ )
55
+ from qse.random_circuits import gaussian_binom_2, expected_gf2_rank, enumerate_vne
56
+
57
+ __all__ = [
58
+ # core
59
+ "build_M", "phi_dict", "t14_Pb", "t_universal",
60
+ "vne_from_Pb", "renyi_entropy", "f2_rank",
61
+ "t22_moment", "newton_girard",
62
+ # states
63
+ "product_state", "product_state_ry",
64
+ "exact_rho_B", "exact_rho_B_mixed", "vne_exact",
65
+ # gates
66
+ "apply_cnot", "apply_fsim", "apply_swap",
67
+ # gradients
68
+ "vne_gradient_rx",
69
+ # noise
70
+ "amplitude_damping_kraus", "superop", "noise_transfer_Pb",
71
+ "build_cnot_ad_transfer",
72
+ # random_circuits
73
+ "gaussian_binom_2", "expected_gf2_rank", "enumerate_vne",
74
+ ]
qse/core.py ADDED
@@ -0,0 +1,217 @@
1
+ """
2
+ qse/core.py — Core QSE computations: WHT formula, GF(2) algebra, entropy.
3
+
4
+ Key formulas:
5
+ T14: P_b = (1/2^NB) sum_s (-1)^{b·s} Phi_M(s)
6
+ T-UNIVERSAL: P_b = sum_{x: Mx=b} rho_A[x,x]
7
+ VNE: H(P) = -sum_b P_b log2(P_b)
8
+ """
9
+
10
+ import numpy as np
11
+ from math import cos, log2, sin
12
+
13
+ # ── Building blocks ───────────────────────────────────────────────────────────
14
+
15
+ def build_M(pairs, NA, NB):
16
+ """Build GF(2) connectivity matrix M ∈ F2^{NB×NA} from CNOT pairs.
17
+
18
+ pairs: list of (a, b) meaning CNOT(ctrl=a, tgt=b), a ∈ [0,NA), b ∈ [0,NB).
19
+ XOR for repeated pairs (mod-2 cancellation).
20
+ """
21
+ M = np.zeros((NB, NA), dtype=int)
22
+ for a, b in pairs:
23
+ M[b][a] ^= 1
24
+ return M
25
+
26
+
27
+ def phi_dict(thetas, pairs, NA, NB):
28
+ """Phi_M(s) = prod_{i: (M^T s)_i = 1} cos(theta_i) for all s ∈ {0..2^NB-1}.
29
+
30
+ Returns: (phi dict {s: float}, M matrix)
31
+ """
32
+ M = build_M(pairs, NA, NB)
33
+ cos_t = [cos(t) for t in thetas]
34
+ phi = {}
35
+ for s in range(2**NB):
36
+ sv = np.array([(s >> j) & 1 for j in range(NB)])
37
+ MTs = np.mod(M.T @ sv, 2)
38
+ phi[s] = float(np.prod([cos_t[i] for i in range(NA) if MTs[i] == 1]))
39
+ return phi, M
40
+
41
+
42
+ # ── T14: Walsh-Hadamard master theorem ───────────────────────────────────────
43
+
44
+ def t14_Pb(thetas, pairs, NA, NB):
45
+ """T14: P_b = (1/2^NB) sum_s (-1)^{b·s} Phi_M(s).
46
+
47
+ Returns: (Pb dict {b: float}, phi dict {s: float})
48
+ """
49
+ phi, _ = phi_dict(thetas, pairs, NA, NB)
50
+ Pb = {}
51
+ for b in range(2**NB):
52
+ bv = np.array([(b >> j) & 1 for j in range(NB)])
53
+ Pb[b] = sum(
54
+ (-1) ** int(np.dot(bv, np.array([(s >> j) & 1 for j in range(NB)]) % 2))
55
+ * phi[s]
56
+ for s in range(2**NB)
57
+ ) / (2**NB)
58
+ return Pb, phi
59
+
60
+
61
+ # ── T-UNIVERSAL: diagonal mixed input ────────────────────────────────────────
62
+
63
+ def t_universal(rho_A, pairs, NA, NB):
64
+ """T-UNIVERSAL: P_b = sum_{x: Mx=b} rho_A[x,x].
65
+
66
+ Works for any diagonal (or full) density matrix rho_A.
67
+ """
68
+ M = build_M(pairs, NA, NB)
69
+ Pb = {}
70
+ for b in range(2**NB):
71
+ Pb[b] = 0.0
72
+ for x in range(2**NA):
73
+ bx = 0
74
+ for i in range(NA):
75
+ if (x >> i) & 1:
76
+ for j in range(NB):
77
+ if M[j][i]:
78
+ bx ^= 1 << j
79
+ if bx == b:
80
+ Pb[b] += rho_A[x, x].real
81
+ return Pb
82
+
83
+
84
+ # ── Entropy functions ─────────────────────────────────────────────────────────
85
+
86
+ def vne_from_Pb(Pb):
87
+ """Von Neumann entropy H(P) = -sum_b P_b log2(P_b), clipped at 1e-14."""
88
+ return float(sum(-v * log2(max(v, 1e-14)) for v in Pb.values() if v > 1e-14))
89
+
90
+
91
+ def renyi_entropy(Pb, alpha):
92
+ """S_alpha = (1/(1-alpha)) * log2(sum_b P_b^alpha). Returns VNE for alpha≈1."""
93
+ if abs(alpha - 1.0) < 1e-9:
94
+ return vne_from_Pb(Pb)
95
+ tr_rho_alpha = sum(max(v, 0) ** alpha for v in Pb.values())
96
+ return log2(max(tr_rho_alpha, 1e-300)) / (1 - alpha)
97
+
98
+
99
+ # ── GF(2) rank ────────────────────────────────────────────────────────────────
100
+
101
+ def f2_rank(pairs, NA, NB):
102
+ """Compute GF(2) rank of M via Gaussian elimination over F2."""
103
+ M = build_M(pairs, NA, NB)
104
+ mat = M.copy()
105
+ rank = 0
106
+ for col in range(NA):
107
+ pivot = next((r for r in range(rank, NB) if mat[r, col]), None)
108
+ if pivot is None:
109
+ continue
110
+ mat[[rank, pivot]] = mat[[pivot, rank]]
111
+ for row in range(NB):
112
+ if row != rank and mat[row, col]:
113
+ mat[row] = (mat[row] + mat[rank]) % 2
114
+ rank += 1
115
+ return rank
116
+
117
+
118
+ # ── Moment theory ─────────────────────────────────────────────────────────────
119
+
120
+ def t22_moment(thetas, pairs, NA, NB, alpha):
121
+ """T22: Tr(rho_B^alpha) = (1/2^{(alpha-1)*NB}) sum_{s1,...,s_{alpha-1}} prod Phi_M(s_i) * Phi_M(s1^...^s_{alpha-1})."""
122
+ from itertools import product as iproduct
123
+ phi, _ = phi_dict(thetas, pairs, NA, NB)
124
+ if alpha == 1:
125
+ return 1.0
126
+ total = 0.0
127
+ for combo in iproduct(range(2**NB), repeat=alpha - 1):
128
+ xor_all = 0
129
+ for c in combo:
130
+ xor_all ^= c
131
+ total += float(np.prod([phi[c] for c in combo])) * phi[xor_all]
132
+ return total / (2 ** ((alpha - 1) * NB))
133
+
134
+
135
+ def newton_girard(moments):
136
+ """Recover eigenvalues from power-sum moments via Newton-Girard identities."""
137
+ n = len(moments)
138
+ e = [0.0] * (n + 1)
139
+ e[0] = 1.0
140
+ for k in range(1, n + 1):
141
+ total = sum(((-1) ** (i - 1)) * e[k - i] * moments[i - 1]
142
+ for i in range(1, k + 1) if k - i <= n)
143
+ e[k] = total / k
144
+ coeffs = [(-1) ** k * e[k] for k in range(n + 1)]
145
+ return sorted(np.roots(coeffs).real, reverse=True)
146
+
147
+
148
+ # ── Gradient computation (T-GRAD) ─────────────────────────────────────────────
149
+
150
+ def vne_gradient_rx(thetas, pairs, NA, NB):
151
+ """Analytic gradient d(VNE)/d(theta_i) for Rx product state input via T14.
152
+
153
+ Derivation:
154
+ Phi_M(s) = prod_{j: (M^T s)_j=1} cos(theta_j)
155
+ d Phi_M(s)/d theta_i = -tan(theta_i) * Phi_M(s) if (M^T s)_i = 1, else 0
156
+ d P_b / d theta_i = (1/2^NB) sum_s (-1)^{b.s} * d Phi_M(s)/d theta_i
157
+ d VNE / d theta_i = -sum_b (d P_b/d theta_i) * log2(P_b)
158
+ [normalization sum_b d P_b/d theta_i = 0 eliminates the -1/ln2 term]
159
+ """
160
+ phi, M = phi_dict(thetas, pairs, NA, NB)
161
+ Pb, _ = t14_Pb(thetas, pairs, NA, NB)
162
+ grad = []
163
+ for i in range(NA):
164
+ tan_i = sin(thetas[i]) / cos(thetas[i])
165
+ dPb = {}
166
+ for b in range(2**NB):
167
+ bv = np.array([(b >> j) & 1 for j in range(NB)])
168
+ val = 0.0
169
+ for s in range(2**NB):
170
+ sv = np.array([(s >> j) & 1 for j in range(NB)])
171
+ MTs = np.mod(M.T @ sv, 2)
172
+ if MTs[i] == 1:
173
+ sign = (-1) ** int(np.dot(bv, sv) % 2)
174
+ val += sign * (-tan_i * phi[s])
175
+ dPb[b] = val / (2**NB)
176
+ dvne = sum(-dPb[b] * log2(max(Pb[b], 1e-14)) for b in range(2**NB) if Pb[b] > 1e-14)
177
+ grad.append(dvne)
178
+ return grad
179
+
180
+
181
+ # ── Renyi entropy derivative (T-RENYI-DERIV) ──────────────────────────────────
182
+
183
+ def t_renyi_deriv(Pb):
184
+ """T-RENYI-DERIV: d(S_alpha)/d(alpha)|_{alpha=1} = -ln(2)/2 * Var[log2 P_b].
185
+
186
+ Measures convergence speed: positive = converging, negative = diverging.
187
+ """
188
+ import math
189
+ vne = vne_from_Pb(Pb)
190
+ second_moment = sum(v * log2(max(v, 1e-14))**2 for v in Pb.values() if v > 1e-14)
191
+ var_log = second_moment - vne**2
192
+ return -math.log(2) / 2.0 * var_log
193
+
194
+
195
+ # ── Gaussian binomial coefficients ────────────────────────────────────────────
196
+
197
+ def gaussian_binom_2(n, k):
198
+ """Gaussian binomial [n choose k]_2 over GF(2)."""
199
+ if k < 0 or k > n:
200
+ return 0
201
+ num = 1
202
+ for j in range(k):
203
+ num *= (2**n - 2**j)
204
+ den = 1
205
+ for j in range(k):
206
+ den *= (2**k - 2**j)
207
+ return num // den
208
+
209
+
210
+ def expected_gf2_rank(NA, NB):
211
+ """E[rank] for NB×NA uniform-random GF(2) matrix via Gaussian binomial formula."""
212
+ total_matrices = 2 ** (NA * NB)
213
+ total = sum(
214
+ r * gaussian_binom_2(NB, r) * int(np.prod([2**NA - 2**j for j in range(r)]))
215
+ for r in range(1, min(NA, NB) + 1)
216
+ )
217
+ return total / total_matrices
qse/gates.py ADDED
@@ -0,0 +1,52 @@
1
+ """
2
+ qse/gates.py — Quantum gate applications on statevectors.
3
+
4
+ All gates operate on flat complex numpy arrays. Qubit index k = bit k of the
5
+ integer index. A-qubits occupy bits 0..NA-1, B-qubits bits NA..NA+NB-1.
6
+ """
7
+
8
+ import numpy as np
9
+ from math import cos, sin
10
+
11
+
12
+ def apply_cnot(amps, ctrl, tgt):
13
+ """Apply CNOT(ctrl, tgt) to statevector `amps` in-place (returns new array).
14
+
15
+ Flips bit `tgt` of each basis state where bit `ctrl` is 1.
16
+ """
17
+ new = np.zeros_like(amps)
18
+ for idx in range(len(amps)):
19
+ new[idx ^ (1 << tgt) if (idx >> ctrl) & 1 else idx] += amps[idx]
20
+ return new
21
+
22
+
23
+ def apply_fsim(amps, q1, q2, alpha, phi):
24
+ """Apply fSim(alpha, phi) gate on qubits q1 and q2 of statevector.
25
+
26
+ fSim acts as:
27
+ |00⟩ → |00⟩
28
+ |01⟩ → cos(α)|01⟩ − i·sin(α)|10⟩
29
+ |10⟩ → cos(α)|10⟩ − i·sin(α)|01⟩
30
+ |11⟩ → e^{−iφ}|11⟩
31
+ """
32
+ new = amps.copy()
33
+ cos_a = cos(alpha)
34
+ sin_a = sin(alpha)
35
+ for idx in range(len(amps)):
36
+ b1 = (idx >> q1) & 1
37
+ b2 = (idx >> q2) & 1
38
+ if b1 == 1 and b2 == 1:
39
+ new[idx] = np.exp(-1j * phi) * amps[idx]
40
+ elif b1 == 0 and b2 == 1:
41
+ idx10 = idx ^ (1 << q1) ^ (1 << q2)
42
+ new[idx] = cos_a * amps[idx] - 1j * sin_a * amps[idx10]
43
+ new[idx10] = cos_a * amps[idx10] - 1j * sin_a * amps[idx]
44
+ return new
45
+
46
+
47
+ def apply_swap(amps, q1, q2):
48
+ """Apply SWAP(q1, q2) via three CNOTs: CNOT(q1→q2), CNOT(q2→q1), CNOT(q1→q2)."""
49
+ amps = apply_cnot(amps, q1, q2)
50
+ amps = apply_cnot(amps, q2, q1)
51
+ amps = apply_cnot(amps, q1, q2)
52
+ return amps
qse/gradients.py ADDED
@@ -0,0 +1,46 @@
1
+ """
2
+ qse/gradients.py — Analytic VNE gradients via T14.
3
+
4
+ T-GRAD: d(VNE)/d(θ_i) closed form for Rx product-state inputs.
5
+
6
+ Derivation:
7
+ Φ_M(s) = prod_{j: (M^T s)_j=1} cos(θ_j)
8
+ d Φ_M(s)/d θ_i = −tan(θ_i)·Φ_M(s) if (M^T s)_i = 1, else 0
9
+ d P_b / d θ_i = (1/2^NB) sum_s (−1)^{b·s} · d Φ_M(s)/d θ_i
10
+ d VNE / d θ_i = −sum_b (d P_b/d θ_i) · log2(P_b)
11
+ (normalization sum_b d P_b/d θ_i = 0 eliminates the −1/ln2 term)
12
+ """
13
+
14
+ import numpy as np
15
+ from math import sin, cos, log2
16
+
17
+ from qse.core import phi_dict, t14_Pb
18
+
19
+
20
+ def vne_gradient_rx(thetas, pairs, NA, NB):
21
+ """Analytic gradient d(VNE)/d(θ_i) for Rx product-state input.
22
+
23
+ Returns a list of length NA with the gradient for each A-qubit angle.
24
+ """
25
+ phi, M = phi_dict(thetas, pairs, NA, NB)
26
+ Pb, _ = t14_Pb(thetas, pairs, NA, NB)
27
+ grad = []
28
+ for i in range(NA):
29
+ tan_i = sin(thetas[i]) / cos(thetas[i])
30
+ dPb = {}
31
+ for b in range(2**NB):
32
+ bv = np.array([(b >> j) & 1 for j in range(NB)])
33
+ val = 0.0
34
+ for s in range(2**NB):
35
+ sv = np.array([(s >> j) & 1 for j in range(NB)])
36
+ MTs = np.mod(M.T @ sv, 2)
37
+ if MTs[i] == 1:
38
+ sign = (-1) ** int(np.dot(bv, sv) % 2)
39
+ val += sign * (-tan_i * phi[s])
40
+ dPb[b] = val / (2**NB)
41
+ dvne = sum(
42
+ -dPb[b] * log2(max(Pb[b], 1e-14))
43
+ for b in range(2**NB) if Pb[b] > 1e-14
44
+ )
45
+ grad.append(dvne)
46
+ return grad
qse/noise.py ADDED
@@ -0,0 +1,61 @@
1
+ """
2
+ qse/noise.py — Noise models for QSE circuits.
3
+
4
+ T-NOISE: Amplitude damping transfer on P_b distribution.
5
+ After CNOT(ctrl=A, tgt=B) and amplitude-damping on B with rate γ:
6
+ P_0_noisy = P_0 + γ·P_1
7
+ P_1_noisy = (1−γ)·P_1
8
+ VNE of noisy B = H(P_0_noisy, P_1_noisy)
9
+
10
+ S2 Transfer matrix: superoperator approach for iterated CNOT+AD cycles.
11
+ """
12
+
13
+ import numpy as np
14
+ from math import sqrt
15
+
16
+
17
+ def amplitude_damping_kraus(gamma):
18
+ """Return Kraus operators [K0, K1] for amplitude damping with rate γ."""
19
+ K0 = np.array([[1, 0], [0, sqrt(1 - gamma)]], dtype=complex)
20
+ K1 = np.array([[0, sqrt(gamma)], [0, 0]], dtype=complex)
21
+ return [K0, K1]
22
+
23
+
24
+ def superop(kraus_ops):
25
+ """Build superoperator S = sum_K K* ⊗ K for a set of Kraus operators.
26
+
27
+ Dimension: (d^2, d^2) where d is the operator dimension.
28
+ """
29
+ d = kraus_ops[0].shape[0]
30
+ S = np.zeros((d**2, d**2), dtype=complex)
31
+ for K in kraus_ops:
32
+ S += np.kron(K.conj(), K)
33
+ return S
34
+
35
+
36
+ def noise_transfer_Pb(Pb, gamma):
37
+ """Apply amplitude-damping T_AD(γ) directly to a 1-qubit P_b distribution.
38
+
39
+ T-NOISE formula (NA=NB=1):
40
+ P_0 → P_0 + γ·P_1
41
+ P_1 → (1−γ)·P_1
42
+ """
43
+ P0 = Pb.get(0, 0.0)
44
+ P1 = Pb.get(1, 0.0)
45
+ return {0: P0 + gamma * P1, 1: (1 - gamma) * P1}
46
+
47
+
48
+ def build_cnot_ad_transfer(gamma):
49
+ """Build the 16×16 transfer superoperator for one CNOT+AD_B+CNOT+AD_A cycle (NA=NB=1).
50
+
51
+ Returns T such that vec(ρ_k) = T^k @ vec(ρ_0).
52
+ """
53
+ K0, K1 = amplitude_damping_kraus(gamma)
54
+ CNOT = np.array([[1, 0, 0, 0],
55
+ [0, 1, 0, 0],
56
+ [0, 0, 0, 1],
57
+ [0, 0, 1, 0]], dtype=complex)
58
+ S_cnot = superop([CNOT])
59
+ S_AD_B = superop([np.kron(np.eye(2), K0), np.kron(np.eye(2), K1)])
60
+ S_AD_A = superop([np.kron(K0, np.eye(2)), np.kron(K1, np.eye(2))])
61
+ return S_AD_A @ S_cnot @ S_AD_B @ S_cnot
qse/random_circuits.py ADDED
@@ -0,0 +1,66 @@
1
+ """
2
+ qse/random_circuits.py — Random circuit statistics via GF(2) matroid theory.
3
+
4
+ T-RANDOM-VNE: E[VNE(θ=π/2)] = E[rank_GF2(M)] (Gaussian binomial formula).
5
+
6
+ At θ=π/2, VNE = rank_GF2(M) exactly (T-OPT). Averaging over all 2^{NA·NB}
7
+ binary matrices M gives the expected GF(2) rank via Gaussian binomial coefficients:
8
+
9
+ E[rank] = (1/2^{NA·NB}) sum_{r=1}^{min(NA,NB)} r · [NB choose r]_2 · prod_{j<r}(2^NA − 2^j)
10
+
11
+ where [n choose k]_2 = prod_{j=0}^{k-1}(2^n − 2^j) / prod_{j=0}^{k-1}(2^k − 2^j)
12
+ is the Gaussian binomial coefficient (count of k-dim subspaces of F2^n).
13
+ """
14
+
15
+ from math import pi
16
+ from functools import reduce
17
+ import operator
18
+
19
+
20
+ def gaussian_binom_2(n, k):
21
+ """[n choose k]_2 over GF(2): number of k-dim subspaces of F2^n.
22
+
23
+ Formula: prod_{j=0}^{k-1}(2^n − 2^j) / prod_{j=0}^{k-1}(2^k − 2^j)
24
+ Returns an exact integer.
25
+ """
26
+ if k < 0 or k > n:
27
+ return 0
28
+ num = reduce(operator.mul, (2**n - 2**j for j in range(k)), 1)
29
+ den = reduce(operator.mul, (2**k - 2**j for j in range(k)), 1)
30
+ return num // den
31
+
32
+
33
+ def expected_gf2_rank(NA, NB):
34
+ """E[rank_GF2(M)] where M is a uniformly random NB×NA binary matrix.
35
+
36
+ Uses the Gaussian binomial formula for exact integer arithmetic.
37
+ """
38
+ total_matrices = 2 ** (NA * NB)
39
+ total = sum(
40
+ r * gaussian_binom_2(NB, r) * reduce(operator.mul, (2**NA - 2**j for j in range(r)), 1)
41
+ for r in range(1, min(NA, NB) + 1)
42
+ )
43
+ return total / total_matrices
44
+
45
+
46
+ def enumerate_vne(NA, NB, thetas=None):
47
+ """Compute average VNE over all 2^{NA·NB} binary CNOT connectivity matrices.
48
+
49
+ thetas: list of NA angles; defaults to [π/2]*NA (T-OPT saturation).
50
+ Returns: (avg_vne, {matrix_index: vne} dict)
51
+ """
52
+ from qse.core import t14_Pb, vne_from_Pb
53
+ if thetas is None:
54
+ thetas = [pi / 2] * NA
55
+ vne_dict = {}
56
+ for bits in range(2 ** (NA * NB)):
57
+ pairs = [
58
+ (j, i)
59
+ for i in range(NB)
60
+ for j in range(NA)
61
+ if (bits >> (i * NA + j)) & 1
62
+ ]
63
+ Pb, _ = t14_Pb(thetas, pairs, NA, NB)
64
+ vne_dict[bits] = vne_from_Pb(Pb)
65
+ avg_vne = sum(vne_dict.values()) / len(vne_dict)
66
+ return avg_vne, vne_dict
qse/states.py ADDED
@@ -0,0 +1,94 @@
1
+ """
2
+ qse/states.py — State preparation and exact statevector simulation.
3
+
4
+ Conventions:
5
+ Rx(θ)|0⟩ = cos(θ/2)|0⟩ − i·sin(θ/2)|1⟩
6
+ Ry(θ)|0⟩ = cos(θ/2)|0⟩ − sin(θ/2)|1⟩
7
+ Qubit layout: A-qubits = bits 0..NA-1, B-qubits = bits NA..NA+NB-1
8
+ """
9
+
10
+ import numpy as np
11
+ from math import cos, sin
12
+
13
+
14
+ # ── State preparation ─────────────────────────────────────────────────────────
15
+
16
+ def product_state(thetas):
17
+ """Build |ψ_A⟩ = ⊗_i Rx(θ_i)|0⟩ as a statevector.
18
+
19
+ thetas[0] is the least-significant qubit (bit 0).
20
+ """
21
+ psi = np.array([cos(thetas[-1] / 2), -1j * sin(thetas[-1] / 2)])
22
+ for i in range(len(thetas) - 2, -1, -1):
23
+ psi = np.kron(psi, np.array([cos(thetas[i] / 2), -1j * sin(thetas[i] / 2)]))
24
+ return psi
25
+
26
+
27
+ def product_state_ry(thetas):
28
+ """Build |ψ_A⟩ = ⊗_i Ry(θ_i)|0⟩ as a statevector (no i factor vs Rx)."""
29
+ psi = np.array([cos(thetas[-1] / 2), -sin(thetas[-1] / 2)])
30
+ for i in range(len(thetas) - 2, -1, -1):
31
+ psi = np.kron(psi, np.array([cos(thetas[i] / 2), -sin(thetas[i] / 2)]))
32
+ return psi
33
+
34
+
35
+ # ── Exact simulation ──────────────────────────────────────────────────────────
36
+
37
+ def exact_rho_B(NA, NB, thetas_A, pairs, thetas_B=None):
38
+ """Compute ρ_B exactly via statevector simulation.
39
+
40
+ thetas_B=None → B initialized to |0…0⟩.
41
+ pairs: list of (a, b) meaning CNOT(ctrl=a, tgt=b).
42
+
43
+ Complexity: O(2^{NA+NB}) — scales to NA=12, NB=6 in ~8 ms.
44
+
45
+ Partial trace via reshape + matmul:
46
+ amps.reshape(2^NB, 2^NA) → ρ_B = A @ A†
47
+ Index layout: amps[a_bits | (b_bits << NA)], so the low NA bits
48
+ are A and the high NB bits are B — reshape groups B as rows, A as cols.
49
+ """
50
+ from qse.gates import apply_cnot
51
+ psi_A = product_state(thetas_A)
52
+ if thetas_B is not None:
53
+ psi_B = product_state(thetas_B)
54
+ psi = np.kron(psi_B, psi_A)
55
+ else:
56
+ psi_B0 = np.zeros(2**NB, dtype=complex)
57
+ psi_B0[0] = 1.0
58
+ psi = np.kron(psi_B0, psi_A)
59
+ amps = psi.copy()
60
+ for a_q, b_q in pairs:
61
+ amps = apply_cnot(amps, a_q, NA + b_q)
62
+ # Vectorized partial trace: reshape into (B_states, A_states), then ρ_B = A @ A†
63
+ A = amps.reshape(2**NB, 2**NA)
64
+ return A @ A.conj().T
65
+
66
+
67
+ def exact_rho_B_mixed(NA, NB, rho_A_diag, pairs):
68
+ """Compute ρ_B for a diagonal mixed input ρ_A = diag(rho_A_diag).
69
+
70
+ rho_A_diag: array of length 2^NA summing to 1.
71
+ """
72
+ from qse.gates import apply_cnot
73
+ from qse.core import build_M
74
+ M = build_M(pairs, NA, NB)
75
+ rho_B = np.zeros((2**NB, 2**NB), dtype=complex)
76
+ for x, px in enumerate(rho_A_diag):
77
+ if abs(px) < 1e-15:
78
+ continue
79
+ bx = 0
80
+ for i in range(NA):
81
+ if (x >> i) & 1:
82
+ for j in range(NB):
83
+ if M[j][i]:
84
+ bx ^= 1 << j
85
+ rho_B[bx, bx] += px
86
+ return rho_B
87
+
88
+
89
+ def vne_exact(NA, NB, thetas_A, pairs, thetas_B=None):
90
+ """Compute exact VNE of B by diagonalizing ρ_B."""
91
+ rho = exact_rho_B(NA, NB, thetas_A, pairs, thetas_B)
92
+ eigs = np.linalg.eigvalsh(rho).real
93
+ eigs = eigs[eigs > 1e-15]
94
+ return float(-np.sum(eigs * np.log2(eigs))) if len(eigs) else 0.0
@@ -0,0 +1,270 @@
1
+ Metadata-Version: 2.4
2
+ Name: ultraqse
3
+ Version: 1.0.0
4
+ Summary: Von Neumann Entropy of CNOT circuits via Walsh-Hadamard transforms over GF(2)
5
+ Author-email: Ozgurooozer <ozigoca@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/Ozgurooozer/ultraqse
8
+ Keywords: quantum,entropy,von neumann,walsh hadamard,gf2,cnot,entanglement,quantum circuits
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Scientific/Engineering :: Physics
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Operating System :: OS Independent
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: numpy>=1.21
20
+
21
+ # QSE Theorem Reference
22
+
23
+ **Convention:** `Rx(θ)|0⟩ = cos(θ/2)|0⟩ − i·sin(θ/2)|1⟩`
24
+ **Ry convention:** `Ry(θ)|0⟩ = cos(θ/2)|0⟩ − sin(θ/2)|1⟩`
25
+ **Φ_M(s)** = ∏_{i: (M^T s)_i = 1} cos(θᵢ)
26
+ **M** ∈ F₂^{NB×NA}: M[b][a] = 1 iff CNOT(ctrl=a, tgt=b) is present
27
+ **Qubit layout:** A-qubits = bits 0..NA−1, B-qubits = bits NA..NA+NB−1
28
+
29
+ ---
30
+
31
+ ## Core Theorems
32
+
33
+ | ID | Name | Formula | max_err |
34
+ |----|------|---------|---------|
35
+ | **T14** | Walsh-Hadamard Master | `P_b = (1/2^NB) Σ_s (−1)^{b·s} Φ_M(s)`, `VNE = H({P_b})` | < 7e-16 |
36
+ | **T-UNIVERSAL** | Diagonal Mixed Input | `P_b = Σ_{x: Mx=b} ρ_A[x,x]` (works for any diagonal ρ_A) | < 5e-16 |
37
+ | **T-UNIVERSAL-GEN** | Nonlinear Gates | `P_b = Σ_{x: f(x)=b} |ψ[x]|²` | < 3e-16 |
38
+ | **T16** | Phase Invariance | VNE depends only on {|cos(θᵢ/2)|²}, not on U(1) phases | < 7e-16 |
39
+
40
+ ---
41
+
42
+ ## Structural Theorems
43
+
44
+ | ID | Name | Key Result | max_err |
45
+ |----|------|-----------|---------|
46
+ | **T17** | Blindness | VNE = 0 ↔ rank_F₂(M) = 0 | exact |
47
+ | **T-RANK** | Rank Upper Bound | `VNE(B) ≤ rank_F₂(M)` | exact |
48
+ | **T-OPT** | Rank Saturation | θ = π/2 ⟹ `VNE = rank_F₂(M)` exactly | exact |
49
+ | **T-SUB** | Monotone Substructure | Adding CNOT → rank nondecreasing → VNE nondecreasing | exact |
50
+
51
+ ---
52
+
53
+ ## Gate Extensions
54
+
55
+ | ID | Name | Key Result | max_err |
56
+ |----|------|-----------|---------|
57
+ | **T-BINIT** | B-Init Independence | T14 formula unchanged for any product-state B init (full-rank M) | < 7e-16 |
58
+ | **CZ-T14** | CZ Equivalence | CZ + \|+⟩_A = CNOT + \|0⟩_A (same VNE) | < 6e-16 |
59
+ | **T-fSim** | fSim Gate (NA=1) | λ± = (1 ± √D)/2, D = 1 − sin²(2α)sin⁴(θ/2); φ-invariant | < 2e-15 |
60
+ | **T-FSIM-PRODUCT** | fSim Product Gates | NA independent fSim gates (qubit i ↔ B-qubit i): `VNE = Σᵢ H(λ±ᵢ)` | < 4e-14 |
61
+ | **iSWAP** | Full iSWAP | iSWAP + Rx(θ)\|0⟩_B → product state → VNE = 0 | < 4e-16 |
62
+ | **T-SWAP** | SWAP via 3 CNOTs | SWAP(A_a, B_b) via CNOT→CNOT→CNOT → VNE(B) = 0 | < 7e-16 |
63
+
64
+ ---
65
+
66
+ ## Symmetry & Invariance Theorems
67
+
68
+ | ID | Name | Key Result | max_err |
69
+ |----|------|-----------|---------|
70
+ | **T-RY-EQ** | Ry = Rx Symmetry | VNE(Ry(θ) circuit) = VNE(Rx(θ) circuit) for same θ and M | < 8e-16 |
71
+ | **T-MIRROR** | Schmidt Symmetry | VNE(A) = VNE(B) for any pure bipartite state \|Ψ⟩_AB | < 8e-16 |
72
+ | **T-COHERENCE-DIAG** | Off-diagonal ρ_A Blindness | Off-diagonal ρ_A elements do not affect VNE(B); ρ_B always diagonal; VNE depends only on diag(ρ_A) | 0 |
73
+
74
+ **T-COHERENCE-DIAG note:** This is a non-trivial result. Even if A is in a coherent superposition
75
+ (off-diagonal ρ_A ≠ 0), the partial trace over A produces a strictly diagonal ρ_B, so
76
+ the CNOT circuit acts as a classical channel at the level of B's entropy.
77
+
78
+ ---
79
+
80
+ ## Gradient Theorems
81
+
82
+ | ID | Name | Formula | max_err |
83
+ |----|------|---------|---------|
84
+ | **T-GRAD** | Rx VNE Gradient | `d(VNE)/dθᵢ = −Σ_b (dP_b/dθᵢ)·log₂(P_b)` where `dP_b/dθᵢ = (1/2^NB) Σ_{s: (M^T s)_i=1} (−1)^{b·s}·(−tan θᵢ)·Φ_M(s)` | < 2e-10 (FD limit) |
85
+
86
+ **T-GRAD note:** The 2e-10 error is the finite-difference floor, not an analytic error.
87
+ The closed-form formula is exact; verification uses 4th-order central differences (h=1e-5).
88
+
89
+ ---
90
+
91
+ ## Information-Theoretic Theorems
92
+
93
+ | ID | Name | Formula | max_err |
94
+ |----|------|---------|---------|
95
+ | **T-MUTUAL** | Mutual Information | `I(A;B) = 2·VNE(B)` for pure state | exact |
96
+ | **T-MI** | MI Non-Negativity | `I(B₁;B₂) ≥ 0` | analytical |
97
+ | **T-PAULI** | Pauli Representation | `Φ_M(s) = ⟨Z^{M^T s}⟩_A` (Pauli expectation value form) | exact |
98
+
99
+ ---
100
+
101
+ ## Dynamics
102
+
103
+ | ID | Name | Key Result | max_err |
104
+ |----|------|-----------|---------|
105
+ | **T15A** | k-Layer Circuits | `M_eff = M₁ ⊕ M₂ ⊕ ... ⊕ Mₖ (mod 2)` | < 8e-16 |
106
+ | **T18** | Period-2 | Even number of identical CNOT layers → M_eff = 0 → VNE = 0 | < 4e-16 |
107
+ | **T-BIDIR** | Bidirectional Circuits | Alternating A→B and B→A CNOT layers reduce to T14(M_eff) | < 2e-15 |
108
+
109
+ **T-BIDIR details:**
110
+
111
+ For circuits with interleaved A→B layers (CNOTs ctrl=a, tgt=B_b) and B→A layers
112
+ (CNOTs ctrl=B_b, tgt=a), the effective M matrix is:
113
+
114
+ ```
115
+ M_eff[b, :] = M_raw[b, :] @ T_cum (mod 2)
116
+ ```
117
+
118
+ where T_cum ∈ F₂^{NA×NA} is the cumulative A-space shear transformation accumulated
119
+ from all B→A CNOTs seen so far. Update rule after CNOT(ctrl=B_b, tgt=A_a):
120
+
121
+ ```
122
+ T_cum[a, :] ^= M_eff[b_abs, :] (row XOR, not matrix multiply)
123
+ ```
124
+
125
+ **Invertibility condition:** T_cum must have full GF(2) rank (= NA). When T_cum is
126
+ singular, multiple x-values map to the same A-state with different B-states, creating
127
+ off-diagonal ρ_B elements (quantum coherences) that break the T14 assumption. The
128
+ theorem applies only to circuits where T_cum remains invertible throughout.
129
+
130
+ ---
131
+
132
+ ## Noise Theorems
133
+
134
+ | ID | Name | Formula | max_err |
135
+ |----|------|---------|---------|
136
+ | **T-NOISE** | Amplitude Damping | After AD_γ on B: `P₀ → P₀+γP₁`, `P₁ → (1−γ)P₁`; `VNE_noisy = H(P₀+γP₁, (1−γ)P₁)` | < 3e-16 |
137
+ | **S2** | k-Round Transfer Matrix | `T = S_AD_A · S_CNOT · S_AD_B · S_CNOT` (16×16 superoperator); `vec(ρₖ) = Tᵏ·vec(ρ₀)` | < 7e-16 |
138
+
139
+ ---
140
+
141
+ ## Moment & Rényi Theory
142
+
143
+ | ID | Name | Formula | max_err |
144
+ |----|------|---------|---------|
145
+ | **T22** | Rényi Moments | `Tr(ρᵅ) = (1/2^{(α−1)NB}) Σ_{s₁..s_{α−1}} ∏Φ_M(sᵢ)·Φ_M(⊕sᵢ)` | < 2e-15 |
146
+ | **T29** | Newton-Girard Spectrum | Power-sum moments (T22) → Newton-Girard identities → all eigenvalues of ρ_B | < 7e-7 |
147
+ | **T-RENYI-DERIV** | Rényi Derivative | `dS_α/dα\|_{α=1} = −(ln2/2)·Var_P[log₂ P_b]` where `Var_P = Σ_b P_b(log₂ P_b)² − VNE²` | < 4e-10 (4th-order FD) |
148
+ | **T-RENYI-CONV** | Rényi→VNE Convergence | `S_α → VNE` as `α → 1` | 0 |
149
+
150
+ **T-RENYI-DERIV note:** Derived by Taylor-expanding `log Tr(ρᵅ)` around α=1 using T22
151
+ moments. The `(ln2/2)·Var` coefficient follows from the second cumulant of the log-probability
152
+ distribution. Verified with 4th-order central differences (h=1e-3) to avoid FD floor.
153
+
154
+ ---
155
+
156
+ ## Random Circuit Statistics
157
+
158
+ | ID | Name | Key Result | max_err |
159
+ |----|------|-----------|---------|
160
+ | **T-RANDOM-VNE** | Expected VNE = Expected GF(2) Rank | `E[VNE(θ=π/2)] = E[rank_GF₂(M)]` over uniform random M ∈ F₂^{NB×NA} | 0 |
161
+
162
+ **Gaussian binomial formula:**
163
+
164
+ ```
165
+ E[rank_GF₂(M)] = (1/2^{NA·NB}) · Σ_{r=1}^{min(NA,NB)} r · [NB choose r]₂ · ∏_{j<r}(2^NA − 2^j)
166
+
167
+ [n choose k]₂ = ∏_{j=0}^{k-1}(2^n − 2^j) / ∏_{j=0}^{k-1}(2^k − 2^j) (Gaussian binomial)
168
+ ```
169
+
170
+ The formula is exact over integers (no floating-point error).
171
+
172
+ ---
173
+
174
+ ## Inter-Theorem Connections
175
+
176
+ | ID | Connection | max_err |
177
+ |----|-----------|---------|
178
+ | **B1** | T22(α=2) = Parseval: `Σ P_b² = (1/2^NB) Σ Φ(s)²` | < 3e-16 |
179
+ | **B2** | `Φ_M(s) = E_{x~P_A}[(−1)^{(M^T s)·x}]` — Walsh-Fourier characteristic function of P_A | < 5e-16 |
180
+ | **B3** | T14 = α→1 limit of T22 Rényi hierarchy (T-RENYI-CONV) | analytical |
181
+ | **B4** | T17+T-RANK+T-OPT+T-SUB = F₂ linear matroid rank structure | analytical |
182
+ | **B5** | T22 = α-point Pauli correlation function (via T-PAULI) | analytical |
183
+ | **B6** | VNE(θ) monotone in [0, rank_F₂(M)] for uniform θ ∈ [0, π/2] | 500/500 |
184
+ | **B7** | T14 = H(f*(P_A)): VNE is Shannon entropy of the classical pushforward of P_A under M | < 4e-16 |
185
+
186
+ ---
187
+
188
+ ## Resolved Open Problems
189
+
190
+ | ID | Problem | Resolution | Theorem |
191
+ |----|---------|-----------|---------|
192
+ | **O1** | Closed-form for bidirectional circuits | M_eff = M_raw·T_cum (GF(2)), invertible T_cum required | T-BIDIR |
193
+ | **O2a** | T-fSim eigenvalue formula (NA=1) | D = 1 − sin²(2α)sin⁴(θ/2); φ-invariant | T-fSim |
194
+ | **O2b** | T-fSim for NA > 1 | VNE additivity for independent fSim gates | T-FSIM-PRODUCT |
195
+ | **O3** | Gradient d(VNE)/dθᵢ for Ry/Rz input | Ry gives same VNE as Rx (T-RY-EQ); Rx gradient in closed form (T-GRAD) | T-RY-EQ, T-GRAD |
196
+ | **O4** | Rényi approximation error bound | dS_α/dα\|₁ = −(ln2/2)·Var_P[log₂ P_b] | T-RENYI-DERIV |
197
+ | **O5** | Non-diagonal ρ_A extension | Off-diagonal ρ_A does not affect VNE; ρ_B always diagonal | T-COHERENCE-DIAG |
198
+ | **O6** | Random circuit VNE via F₂ matroid counting | E[VNE] = E[rank_GF₂] via Gaussian binomial | T-RANDOM-VNE |
199
+
200
+ ---
201
+
202
+ ## Scaling & Performance
203
+
204
+ Tested on NA=12, NB=6 (2^18 = 262,144 amplitudes):
205
+
206
+ | Operation | Complexity | Measured |
207
+ |-----------|-----------|---------|
208
+ | `t14_Pb` (WHT formula) | O(2^{2NB}) | **12 ms** |
209
+ | `vne_gradient_rx` | O(NA · 2^{2NB}) | **195 ms** |
210
+ | `exact_rho_B` (vectorized) | O(2^{NA+NB} · 2^{NB}) | **8 ms** |
211
+ | `exact_rho_B` (old O(n²) loop) | O(4^{NA+NB}) | ~hours |
212
+
213
+ **Key insight:** T14 complexity depends only on NB (the B register size), not NA.
214
+ Growing NA to 100+ costs nothing for the WHT formula — only the statevector
215
+ simulation and gradient scale with NA.
216
+
217
+ **Vectorized partial trace** (`exact_rho_B`):
218
+
219
+ ```python
220
+ # Old: O(4^{NA+NB}) double loop — infeasible for NA > 6
221
+ # New: O(2^{NA+NB}) reshape + matmul
222
+ A = amps.reshape(2**NB, 2**NA) # B-bits as rows, A-bits as cols
223
+ rho_B = A @ A.conj().T # traces out A exactly
224
+ ```
225
+
226
+ Index layout: `amps[a_bits | (b_bits << NA)]` — low NA bits are A, high NB bits are B.
227
+ Reshape naturally groups B as rows and A as columns, making the matmul correct.
228
+
229
+ ---
230
+
231
+ ## Package API (`qse/`)
232
+
233
+ ```python
234
+ from qse import (
235
+ # Core — T14 machinery
236
+ build_M, phi_dict, t14_Pb, t_universal,
237
+ vne_from_Pb, renyi_entropy, f2_rank,
238
+ t22_moment, newton_girard,
239
+
240
+ # States — simulation ground truth
241
+ product_state, product_state_ry,
242
+ exact_rho_B, exact_rho_B_mixed, vne_exact,
243
+
244
+ # Gates — statevector operations
245
+ apply_cnot, apply_fsim, apply_swap,
246
+
247
+ # Gradients
248
+ vne_gradient_rx,
249
+
250
+ # Noise
251
+ amplitude_damping_kraus, superop,
252
+ noise_transfer_Pb, build_cnot_ad_transfer,
253
+
254
+ # Random circuits
255
+ gaussian_binom_2, expected_gf2_rank, enumerate_vne,
256
+ )
257
+ ```
258
+
259
+ ---
260
+
261
+ ## Test Suite
262
+
263
+ Run `python qse_tests.py` — **34/34 tests** pass at machine precision (max_err < 1e-8).
264
+
265
+ | Phase | Tests | Notes |
266
+ |-------|-------|-------|
267
+ | Initial commit | 23/23 | Core + noise + moment theory |
268
+ | Katman 0 (bug fixes) | 23/23 | T-fSim formula fix, T-BINIT full-rank check, T18 generalization |
269
+ | Katman 1 (open problems) | 33/33 | O2b–O6 resolved; T-SWAP, T-MIRROR added |
270
+ | Katman 2 (new theorems) | 34/34 | T-BIDIR (O1) completed |
@@ -0,0 +1,11 @@
1
+ qse/__init__.py,sha256=mEmEMmkxNMPWoqR-KYRdEffBhaumxL8w0_mniY-yQzE,2115
2
+ qse/core.py,sha256=hGrC-HGNsyJ1aZToSGr7Npbc0i8vlcFWTe15qSKU7C0,8119
3
+ qse/gates.py,sha256=_8BXZI8TTQj1QdICEduU5-xBOXpvc7syQRz0NlhWAw0,1637
4
+ qse/gradients.py,sha256=0592EsjBg2upgyfyYwu2MO1Kex8C1z6Ns27LIEgSU-I,1530
5
+ qse/noise.py,sha256=tHzA0qUaERPbtN_37U4_FrPoJwqJRVffGcd6aaL524I,1905
6
+ qse/random_circuits.py,sha256=fX_idUpDXj8Lbyl8noo4gGCVAPYjCkCoxuzPHfs5VIk,2208
7
+ qse/states.py,sha256=6NSYa4F6lU-41NAqBmVPAbRNElyrcFHOeR9-YUZPf0g,3436
8
+ ultraqse-1.0.0.dist-info/METADATA,sha256=HSisgHTmL9CGIYVzm8F_ujA_A99InT1pWumEzi71EZo,11588
9
+ ultraqse-1.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
+ ultraqse-1.0.0.dist-info/top_level.txt,sha256=sOJCZwZSA9WnGrROtyLe42mcnC3sJZQj1BFwcxCk8Q4,4
11
+ ultraqse-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ qse