add script for multinomial block collapse and Dicke state scaling verification

This commit is contained in:
Hans Aschauer 2026-07-17 07:57:34 +02:00
parent f195204a30
commit 6ea7900b55
2 changed files with 412 additions and 1 deletions

View file

@ -1215,7 +1215,8 @@ i.e.\ that the $2\times2$ array of blocks is circulant --- a prediction that fol
A direct check against the stabilizer group $H=\langle K_1,K_2,K_3,K_4\rangle$ of $\rho_\square$ (Lemma~\ref{lem:code-support}) confirms this: in the raw Pauli-string basis, $X_1X_3\in H$ and $X_2X_4\in H$, while $X_1X_4\notin H$ and $X_2X_3\notin H$, so
\begin{equation*}
M_{\{1\}\to\{3\}}(\rho_\square)=M_{\{2\}\to\{4\}}(\rho_\square)=1\ (\text{support on the }xx\text{ direction only}),
\qquad
\end{equation*}
\begin{equation*}
M_{\{1\}\to\{4\}}(\rho_\square)=M_{\{2\}\to\{3\}}(\rho_\square)=0,
\end{equation*}
matching Eq.~\eqref{eq:ring-circulant-prediction} exactly. This is a case where the weak, cut-factorizing symmetry and the combinatorial stabilizer mechanism of Lemma~\ref{lem:stabilizer-degeneracy} operate on the same numbers from two independent directions: the stabilizer mechanism explains \emph{why} the entries are $0$ or $\pm1$ at all, while the swap-equivariance of Proposition~\ref{prop:block-diagonal} explains, without reference to the stabilizer formalism, why the two nonzero entries must coincide and the two zero entries must coincide. Diagonalizing this $2\times2$ circulant block in the symmetric/antisymmetric basis $(\,e_x^{(1)}\pm e_x^{(2)})/\sqrt2$ gives eigenvalues $1\pm0=1$ in this instance --- here the two channels happen to be degenerate, since the off-diagonal entry vanishes, but the circulant form Eq.~\eqref{eq:ring-circulant-prediction} would hold with generically distinct symmetric/antisymmetric eigenvalues $a\pm b$ for any $\rho$ merely invariant under this same reflection, stabilizer or not.
@ -1412,6 +1413,208 @@ The $y$-parity grading occasionally useful for real-in-the-computational-basis s
Proposition~\ref{prop:block-diagonal} and Lemma~\ref{lem:stabilizer-degeneracy} are complementary, not competing, and apply under disjoint hypotheses. The representation-theoretic mechanism applies whenever $\rho$ is genuinely $G$-invariant under some compact group $G$ acting by local unitaries and preserving the cut, regardless of whether $\rho$ is Pauli-diagonal; it says nothing about states, such as a generic finite-group-symmetric state built from a permutation representation, that are not Pauli-diagonal. The stabilizer mechanism applies whenever $\rho$ is (a uniform mixture over) a stabilizer code state, regardless of whether it possesses any continuous symmetry at all --- as is the case for $\GHZ_n$, the Smolin state, and every graph state used elsewhere in this note, none of which is invariant under a nontrivial continuous collective symmetry. In the (comparatively narrow) overlap where a state is both $G$-invariant for some continuous $G$ and Pauli-diagonal, both mechanisms apply and constrain the same block structure from different directions; outside that overlap, exactly one of the two is available, and it is this Lemma, not Proposition~\ref{prop:block-diagonal}, that accounts for every numerically observed degeneracy reported so far in this note.
\end{remark}
\subsection*{A polynomial-size witness for permutation-symmetric cluster sources}
\label{sec:multinomial-collapse}
Remark~\ref{rem:computational-cost} raised the cost of evaluating $\mathcal M_S(\rho)$
as a genuine obstruction once $|S|$ or $|S^c|$ grows. We now show that this
obstruction disappears entirely for a natural and large class of states: those
invariant under permuting the parties \emph{within} $S$ and \emph{within} $S^c$
separately. This is an instance of the weak, cut-factorizing hypothesis of
Proposition~\ref{prop:block-diagonal} --- not the strong, party-local one, since a
transposition of two parties inside $S$ is not of the form $U^{(a)}\otimes U^{(b)}$
(compare Remark~\ref{rem:permutation-separating-example}) --- specialized to the
full symmetric group, whose isotypic decomposition on a Pauli-string alphabet
collapses to an elementary orbit-counting argument.
\paragraph{Setup.} Fix qubits ($d_a=2$) for concreteness (Remark~\ref{rem:qudit-collapse}
below records the general-$d$ statement). Fix a source cluster $S$ with $|S|=m$
and let $S^c$ be its complement, $|S^c|=l:=n-m$. Consider the single bigraduated
block $M_{S\to S^c}(\rho)$ of Definition~\ref{def:bigraduated} with $V=S$, $T=S^c$
--- the ``fully active'' block already singled out after
Corollary~\ref{cor:sub-block} as the witness for genuine joint $S$-cluster
correlation. In the orthonormal Pauli-string basis this is the
$3^m\times 3^l$ matrix
\begin{equation*}
c(\vec\imath,\vec\jmath):=\tr\bigl(\rho\,\sigma_{\vec\imath}\otimes\sigma_{\vec\jmath}\bigr),
\qquad
\vec\imath\in\{x,y,z\}^m,\ \vec\jmath\in\{x,y,z\}^l.
\end{equation*}
For $\vec\imath\in\{x,y,z\}^m$ let $\mathrm{type}(\vec\imath)=(a_x,a_y,a_z)\in\mathcal T_m$,
$\mathcal T_m:=\{(a_x,a_y,a_z)\in\mathbb Z_{\ge0}^3: a_x+a_y+a_z=m\}$, record how
often each label occurs; the symmetric group $S_m$ acts on $\{x,y,z\}^m$ by
permuting positions, with orbits exactly the level sets of $\mathrm{type}$, and the
orbit of type $\alpha$ has size the multinomial coefficient $\binom m\alpha:=\frac{m!}{a_x!a_y!a_z!}$.
Note $|\mathcal T_m|=\binom{m+2}{2}$, polynomial in $m$, against the ambient $3^m$.
\begin{proposition}[Multinomial block collapse]
\label{prop:multinomial-collapse}
Suppose $\rho$ is invariant under $U_\pi\otimes U_{\pi'}$ for every $\pi\in S_m$
acting by the permutation unitary on $\mathcal H^{(S)}$ and every $\pi'\in S_l$
acting by the permutation unitary on $\mathcal H^{(S^c)}$. Then $c(\vec\imath,\vec\jmath)$
depends on $(\vec\imath,\vec\jmath)$ only through $(\mathrm{type}(\vec\imath),\mathrm{type}(\vec\jmath))\in\mathcal T_m\times\mathcal T_l$;
write $\tilde c(\alpha,\beta)$ for this common value, and define the
multinomial-weighted reduced matrix $\hat C\in\mathbb C^{|\mathcal T_m|\times|\mathcal T_l|}$ by
\begin{equation}
\hat C_{\alpha,\beta}:=\sqrt{\binom m\alpha\binom l\beta}\;\tilde c(\alpha,\beta).
\label{eq:reduced-dicke-matrix}
\end{equation}
Then $M_{S\to S^c}(\rho)$ and $\hat C$ have identical nonzero singular values
(the smaller matrix effectively zero-padded), so in particular
\begin{equation*}
\norm{M_{S\to S^c}(\rho)}_*=\norm{\hat C}_*,
\qquad
\norm{M_{S\to S^c}(\rho)}_{\fro}=\norm{\hat C}_{\fro}.
\end{equation*}
\end{proposition}
\begin{proof}
$U_\pi$-invariance of $\rho$ gives $\tr(\rho\,\sigma_{\pi\vec\imath}\otimes\sigma_{\vec\jmath})
=\tr(U_\pi^\dagger\rho U_\pi\,\sigma_{\vec\imath}\otimes\sigma_{\vec\jmath})=c(\vec\imath,\vec\jmath)$
for every $\pi\in S_m$, since conjugating $\rho$ by $U_\pi$ permutes the legs of
the Pauli string in the trace exactly as $\pi$ permutes $\vec\imath$; the analogous
identity on the target side follows from $U_{\pi'}$-invariance. Hence $c$ is
constant on $S_m$-orbit $\times$ $S_l$-orbit classes, proving the first claim.
For the matrix identity, let $u_\alpha\in\mathbb R^{3^m}$ be the normalized
indicator vector of the orbit of type $\alpha$ (equal to $1/\sqrt{\binom m\alpha}$
on that orbit and $0$ elsewhere), and $v_\beta\in\mathbb R^{3^l}$ analogously.
Since distinct orbits partition the index set, $U:=(u_\alpha)_{\alpha\in\mathcal T_m}$
and $V:=(v_\beta)_{\beta\in\mathcal T_l}$ have orthonormal columns. For
$\vec\imath$ of type $\alpha$ and $\vec\jmath$ of type $\beta$,
\begin{equation*}
(U\hat C V^T)_{\vec\imath,\vec\jmath}
=\frac{1}{\sqrt{\binom m\alpha}}\,\hat C_{\alpha,\beta}\,\frac1{\sqrt{\binom l\beta}}
=\tilde c(\alpha,\beta)=c(\vec\imath,\vec\jmath),
\end{equation*}
so $M_{S\to S^c}(\rho)=U\hat C\,V^T$. Left and right multiplication by
matrices with orthonormal columns preserves singular values up to zero-padding
(e.g.\ $M^TM=V\hat C^T\hat C V^T$ has the same nonzero eigenvalues as $\hat C^T\hat C$,
since $V^TV=\id$), giving the claim.
\end{proof}
\begin{corollary}[Normalized witness]
\label{cor:dicke-normalized}
If $\rho$ is separable across $S\mid S^c$, then, in the normalization of
Corollary~\ref{cor:sub-block} applied with $\mathcal V=\{S\}$, $\mathcal T=\{S^c\}$,
\begin{equation*}
\frac{\norm{\hat C}_*}{\sqrt{(2^m-1)(2^l-1)}}
=\norm{\widehat M_{S\to S^c}(\rho)}_*
\le\norm{\mathcal M_S(\rho)}_*\le1.
\end{equation*}
\end{corollary}
The point of Proposition~\ref{prop:multinomial-collapse} is computational, not a
sharper bound: it lets one evaluate $\norm{M_{S\to S^c}(\rho)}_*$ exactly via an
SVD of size $\binom{m+2}{2}\times\binom{l+2}{2}$ rather than $3^m\times3^l$, for
\emph{any} state with the stated permutation symmetry, with no approximation.
\begin{remark}[General local dimension]
\label{rem:qudit-collapse}
For general finite $d_a\equiv d$ on $S$ (and possibly different $d$ on $S^c$),
the same argument replaces $\{x,y,z\}$ by any fixed orthonormal generator set
of size $d^2-1$; orbits of $S_m$ on $(d^2-1)$-letter strings of length $m$ are
again indexed by compositions $\mathcal T_m^{(d)}=\{\alpha\in\mathbb Z_{\ge0}^{d^2-1}:\sum\alpha_i=m\}$,
of cardinality $\binom{m+d^2-2}{d^2-2}$ --- polynomial in $m$ for fixed $d$,
exponential in $d$ but that dependence is orthogonal to the point made here.
\end{remark}
\subsection*{Worked example: Dicke states}
\label{sec:dicke-example}
\begin{lemma}[Closed-form Dicke correlator]
\label{lem:dicke-correlator}
Let $\lvert D_n^k\rangle:=\binom nk^{-1/2}\sum_{\lvert w\rvert=k}\lvert w\rangle$
be the $n$-qubit Dicke state of weight $k$, and let $P$ be a Pauli string of type
$(n_I,n_X,n_Y,n_Z)$ ($n_I+n_X+n_Y+n_Z=n$, no reference to which positions carry
which label needed, by Proposition~\ref{prop:multinomial-collapse}-type symmetry
applied to the full state). Then, if $n_X+n_Y$ is even,
\begin{equation}
\langle D_n^k\rvert P\lvert D_n^k\rangle
=\frac{i^{\,n_Y}}{\binom nk}
\sum_{\substack{a_X+a_Y=(n_X+n_Y)/2\\ a_I+a_Z=k-(n_X+n_Y)/2}}
\binom{n_X}{a_X}\binom{n_Y}{a_Y}\binom{n_I}{a_I}\binom{n_Z}{a_Z}(-1)^{a_Y+a_Z},
\label{eq:dicke-correlator}
\end{equation}
and $=0$ if $n_X+n_Y$ is odd.
\end{lemma}
\begin{proof}
Write $P\lvert w\rangle=\phi(w)\lvert w'\rangle$ where $w'$ flips the bits of $w$
at the $X$- and $Y$-labeled positions and leaves the rest unchanged, and
$\phi(w)=\prod_{Z\text{-pos}}(-1)^{w_i}\prod_{Y\text{-pos}}i(1-2w_i)$ (the $X$-
factors carry no phase). Since $\lvert D_n^k\rangle$ has support only on weight-$k$
strings, $\langle D_n^k\rvert P\lvert D_n^k\rangle=\binom nk^{-1}\sum_{\lvert w\rvert=k,\,\lvert w'\rvert=k}\phi(w)$.
The weight-preservation condition $\lvert w'\rvert=\lvert w\rvert$ forces exactly
half of the $n_X+n_Y$ flipped positions to hold a $1$ in $w$, i.e.\ $a_X+a_Y=(n_X+n_Y)/2$
if $w$ has $a_X$ ones among the $X$-positions and $a_Y$ ones among the
$Y$-positions (impossible if $n_X+n_Y$ is odd); the total-weight condition
$a_I+a_X+a_Y+a_Z=k$ then gives $a_I+a_Z=k-(n_X+n_Y)/2$. Summing $\phi(w)=(-1)^{a_Z}\cdot i^{\,n_Y-a_Y}(-i)^{a_Y}=(-1)^{a_Z+a_Y}i^{\,n_Y}$
over all $w$ with prescribed $(a_I,a_X,a_Y,a_Z)$, weighted by the number
$\binom{n_I}{a_I}\binom{n_X}{a_X}\binom{n_Y}{a_Y}\binom{n_Z}{a_Z}$ of such $w$, gives
Eq.~\eqref{eq:dicke-correlator}.
\end{proof}
Dicke states are invariant under the full party-permutation group $S_n$, hence
in particular under $S_m\times S_l$ for any cut $S\mid S^c$, so
Proposition~\ref{prop:multinomial-collapse} applies with $\tilde c(\alpha,\beta)$
given directly by Eq.~\eqref{eq:dicke-correlator} at $(n_I,n_X,n_Y,n_Z)=(n-m-l,\alpha_x+\beta_x,\alpha_y+\beta_y,\alpha_z+\beta_z)$.
\begin{example}
\label{ex:dicke-scaling}
For $n=9$, $k=4$, $S,S^c$ of size $m=4$, $l=3$, direct construction of the full
$81\times27$ matrix $M_{S\to S^c}(\rho)$ and of the reduced $15\times10$ matrix
$\hat C$ of Eq.~\eqref{eq:reduced-dicke-matrix} give identical singular-value
spectra to $10$ decimal digits, with $\norm{M_{S\to S^c}}_*=\norm{\hat C}_*=3.0972760203\ldots$,
confirming Proposition~\ref{prop:multinomial-collapse} numerically as well as
algebraically.
The practical payoff is in scaling $m,l$ far beyond what the ambient
$3^m\times3^l$ matrix could ever accommodate. Table~\ref{tab:dicke-scaling}
reports $\norm{\hat C}_*$ and wall-clock time for a fixed weight $k=3$ Dicke
state as $n,m,l$ grow; the reduced matrix and its exact SVD remain cheap
throughout, while the corresponding ambient matrix size is astronomically
out of reach already by $n\approx60$.
\begin{table}[h]
\centering
\small
\begin{tabular}{@{}rrrrrr@{}}
\toprule
$n$ & $m$ & $l$ & $\hat C$ size & ambient $3^m\times3^l$ & $\norm{\hat C}_*$ \\
\midrule
10 & 4 & 4 & $15\times15$ & $8.1\times10^{1}\times8.1\times10^{1}$ & $5.66$ \\
30 & 10 & 8 & $66\times45$ & $5.9\times10^{4}\times6.6\times10^{3}$ & $4.33$ \\
60 & 20 & 15 & $231\times136$ & $3.5\times10^{9}\times1.4\times10^{7}$ & $4.93$ \\
100 & 30 & 25 & $496\times351$ & $2.1\times10^{14}\times8.5\times10^{11}$ & $4.42$ \\
200 & 40 & 35 & $861\times666$ & $1.2\times10^{19}\times5.0\times10^{16}$ & $1.85$ \\
\bottomrule
\end{tabular}
\caption{Exact evaluation of $\norm{M_{S\to S^c}(\rho)}_*$ for the $k=3$ Dicke
state via the reduced matrix $\hat C$, Eq.~\eqref{eq:reduced-dicke-matrix}.
The rightmost ambient-matrix sizes are the dimensions an unreduced computation
would require; already at $n=200$ this is about $6\times10^{35}$ entries, versus
$861\times666\approx5.7\times10^{5}$ for $\hat C$ (computed, with full SVD, in
about $1.3$ seconds on a single core). The script
\texttt{scripts/dicke\_block\_collapse.py} reproduces this table and the exact
match with the ambient matrix at small $n$.}
\label{tab:dicke-scaling}
\end{table}
Two caveats keep this example honest. First, Table~\ref{tab:dicke-scaling}
reports the \emph{unnormalized} block $\norm{M_{S\to S^c}}_*$, not the
cut-separable witness $\norm{\widehat M_{S\to S^c}}_*$ of
Corollary~\ref{cor:dicke-normalized}; the latter divides by
$\sqrt{(2^m-1)(2^l-1)}$, which grows so quickly with $m,l$ that the normalized
witness is far below the separable threshold $1$ at the larger table entries ---
the large-$n$ rows demonstrate tractability of the computation, not entanglement
detection at that scale. Second, at half filling $k=n/2$ the unnormalized
correlator itself decays with $n$ (a genuine physical effect, not a numerical
artifact); Table~\ref{tab:dicke-scaling} therefore fixes a small $k=3$ so the
signal stays $O(1)$ throughout the range shown.
\end{example}
\section{Outlook}
The combined shadow map should be viewed as a structured refinement of the older correlation strengths $L_S$ introduced by Aschauer \emph{et al.} \cite{aschauer}. Those quantities keep one Frobenius norm per tensor block; the present construction keeps the common one-vs-rest channel structure across all orthogonal sectors on the complement. In that sense it preserves the geometric spirit of that local-invariant sector decomposition while extracting more information from the same correlation data.

View file

@ -0,0 +1,208 @@
"""
dicke_block_collapse.py
Reproduces the numerical claims of Proposition (multinomial block collapse)
and Example (Dicke-state scaling): for a Dicke state |D_n^k>, the ambient
3^m x 3^l shadow-map block M_{S->S^c}(rho) has EXACTLY the same singular
values (hence the same nuclear norm) as a much smaller multinomial-weighted
matrix C_hat of size C(m+2,2) x C(l+2,2). This lets ||M_{S->S^c}||_* be
computed exactly for cluster sizes far beyond what the ambient matrix could
ever be built at.
Two things are verified/produced:
(1) Exact-arithmetic closed-form Dicke correlator, checked against
brute-force dense simulation for small n.
(2) Exact match between the ambient matrix M and the reduced matrix C_hat
(singular values, nuclear norm), then a scaling table pushing m, l, n
far beyond brute-force reach.
Run: python3 dicke_block_collapse.py
"""
import time
from itertools import combinations, product
from math import comb, factorial
import numpy as np
# ----------------------------------------------------------------------
# Part 0: brute-force reference (only used for small-n sanity checks)
# ----------------------------------------------------------------------
_I = np.eye(2, dtype=complex)
_X = np.array([[0, 1], [1, 0]], dtype=complex)
_Y = np.array([[0, -1j], [1j, 0]], dtype=complex)
_Z = np.array([[1, 0], [0, -1]], dtype=complex)
_PAULI = {"i": _I, "x": _X, "y": _Y, "z": _Z}
def _kron_list(ops):
out = ops[0]
for o in ops[1:]:
out = np.kron(out, o)
return out
def dicke_state_vector(n, k):
"""Dense state vector of the n-qubit weight-k Dicke state (small n only)."""
dim = 2 ** n
psi = np.zeros(dim, dtype=complex)
for bits in combinations(range(n), k):
idx = 0
for b in bits:
idx |= 1 << (n - 1 - b)
psi[idx] = 1.0
psi /= np.linalg.norm(psi)
return psi
def brute_force_expectation(n, k, labels):
"""<D_n^k| P |D_n^k> by dense simulation. labels: length-n tuple in 'ixyz'."""
psi = dicke_state_vector(n, k)
op = _kron_list([_PAULI[c] for c in labels])
return psi.conj() @ op @ psi
# ----------------------------------------------------------------------
# Part 1: closed-form Dicke correlator (Lemma: closed-form Dicke correlator)
# ----------------------------------------------------------------------
def dicke_correlator(n, k, n_I, n_X, n_Y, n_Z):
"""
<D_n^k| P |D_n^k> for a Pauli-string TYPE (n_I identities, n_X X's,
n_Y Y's, n_Z Z's; n_I+n_X+n_Y+n_Z = n), via Eq. (dicke-correlator).
All intermediate sums are kept as exact Python integers to avoid
catastrophic cancellation between huge binomial coefficients; only the
final division by C(n,k) is converted to a float (Python performs a
correctly-rounded true division even for arbitrary-size integers).
"""
assert n_I + n_X + n_Y + n_Z == n
m_xy = n_X + n_Y
if m_xy % 2 != 0:
return 0.0
half = m_xy // 2
target_iz = k - half
if target_iz < 0 or target_iz > n_I + n_Z:
return 0.0
total = 0 # exact integer accumulator
for a_x in range(max(0, half - n_Y), min(n_X, half) + 1):
a_y = half - a_x
w_xy = comb(n_X, a_x) * comb(n_Y, a_y) * (-1) ** a_y
for a_i in range(max(0, target_iz - n_Z), min(n_I, target_iz) + 1):
a_z = target_iz - a_i
w_iz = comb(n_I, a_i) * comb(n_Z, a_z) * (-1) ** a_z
total += w_xy * w_iz
denom = comb(n, k)
return (1j ** n_Y) * (total / denom)
# ----------------------------------------------------------------------
# Part 2: ambient block matrix vs. multinomial-reduced matrix
# ----------------------------------------------------------------------
def multinomial(n, counts):
r = factorial(n)
for c in counts:
r //= factorial(c)
return r
def active_types(size):
"""All (a_x, a_y, a_z) with a_x+a_y+a_z == size (the 'fully active' sector)."""
return [
(ax, ay, size - ax - ay)
for ax in range(size + 1)
for ay in range(size + 1 - ax)
]
def ambient_block_matrix(n, k, m, l):
"""The full 3^m x 3^l block M_{S->S^c}(rho) in the raw Pauli-string basis."""
labels_s = list(product("xyz", repeat=m))
labels_t = list(product("xyz", repeat=l))
rest = n - m - l
M = np.zeros((len(labels_s), len(labels_t)), dtype=complex)
for i, ls in enumerate(labels_s):
cs = {c: ls.count(c) for c in "xyz"}
for j, lt in enumerate(labels_t):
ct = {c: lt.count(c) for c in "xyz"}
M[i, j] = dicke_correlator(
n, k, rest, cs["x"] + ct["x"], cs["y"] + ct["y"], cs["z"] + ct["z"]
)
return M
def reduced_block_matrix(n, k, m, l):
"""
The multinomial-weighted reduced matrix C_hat of Eq. (reduced-dicke-matrix),
size C(m+2,2) x C(l+2,2), with the SAME singular values as the ambient
3^m x 3^l block (Proposition: multinomial block collapse).
"""
src_types = active_types(m)
tgt_types = active_types(l)
rest = n - m - l
C = np.zeros((len(src_types), len(tgt_types)), dtype=complex)
for i, (sx, sy, sz) in enumerate(src_types):
w_s = multinomial(m, [sx, sy, sz])
for j, (tx, ty, tz) in enumerate(tgt_types):
w_t = multinomial(l, [tx, ty, tz])
val = dicke_correlator(n, k, rest, sx + tx, sy + ty, sz + tz)
C[i, j] = float(np.sqrt(float(w_s * w_t))) * val
return C
# ----------------------------------------------------------------------
# Part 3: checks and scaling table
# ----------------------------------------------------------------------
def check_formula_against_brute_force(n=8, k=3, trials=30, seed=0):
rng = np.random.default_rng(seed)
max_err = 0.0
for _ in range(trials):
labels = rng.choice(list("ixyz"), size=n)
counts = {c: int((labels == c).sum()) for c in "ixyz"}
ref = brute_force_expectation(n, k, tuple(labels))
val = dicke_correlator(n, k, counts["i"], counts["x"], counts["y"], counts["z"])
max_err = max(max_err, abs(ref - val))
print(f"[check 1] closed-form vs. brute force (n={n}, k={k}, {trials} random "
f"Pauli strings): max error = {max_err:.2e}")
def check_ambient_vs_reduced(n=9, k=4, m=4, l=3):
M = ambient_block_matrix(n, k, m, l)
C = reduced_block_matrix(n, k, m, l)
sv_full = np.sort(np.linalg.svd(M, compute_uv=False))[::-1]
sv_red = np.sort(np.linalg.svd(C, compute_uv=False))[::-1]
print(f"[check 2] ambient {M.shape} vs. reduced {C.shape} (n={n}, k={k}, "
f"m={m}, l={l})")
print(f" ||M||_* = {sv_full.sum().real:.10f}")
print(f" ||C||_* = {sv_red.sum().real:.10f}")
print(f" max |sv_full - sv_red| (top {min(6, len(sv_red))}) = "
f"{np.max(np.abs(sv_full[:len(sv_red)][:6] - sv_red[:6])):.2e}")
def scaling_table(k=3, cases=((10, 4, 4), (30, 10, 8), (60, 20, 15),
(100, 30, 25), (200, 40, 35))):
print(f"[scaling table] fixed weight k={k}, reduced matrix only "
f"(ambient matrix is never built)")
header = f"{'n':>5}{'m':>5}{'l':>5} {'C_hat shape':>14} {'ambient 3^m x 3^l':>26} {'||C_hat||_*':>13} {'time':>8}"
print(header)
for n, m, l in cases:
t0 = time.time()
C = reduced_block_matrix(n, k, m, l)
sv = np.linalg.svd(C, compute_uv=False)
dt = time.time() - t0
ambient = f"{3.0**m:.2e} x {3.0**l:.2e}"
print(f"{n:>5}{m:>5}{l:>5} {str(C.shape):>14} {ambient:>26} "
f"{sv.sum().real:>13.6f} {dt:>7.3f}s")
if __name__ == "__main__":
check_formula_against_brute_force()
print()
check_ambient_vs_reduced()
print()
scaling_table()