diff --git a/.gitignore b/.gitignore index c340f2b..2936858 100644 --- a/.gitignore +++ b/.gitignore @@ -332,228 +332,3 @@ TSWLatexianTemp* paper/*.pdf -.docs_mcp/ -julia/ - -#### Python - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[codz] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py.cover -*.lcov -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -# Pipfile.lock - -# UV -# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# uv.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -# poetry.lock -# poetry.toml - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. -# https://pdm-project.org/en/latest/usage/project/#working-with-version-control -# pdm.lock -# pdm.toml -.pdm-python -.pdm-build/ - -# pixi -# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. -# pixi.lock -# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one -# in the .venv directory. It is recommended not to include this directory in version control. -.pixi/* -!.pixi/config.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule* -celerybeat.pid - -# Redis -*.rdb -*.aof -*.pid - -# RabbitMQ -mnesia/ -rabbitmq/ -rabbitmq-data/ - -# ActiveMQ -activemq-data/ - -# SageMath parsed files -*.sage.py - -# Environments -.env -.envrc -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -# .idea/ - -# Abstra -# Abstra is an AI-powered process automation framework. -# Ignore directories containing user credentials, local state, and settings. -# Learn more at https://abstra.io/docs -.abstra/ - -# Visual Studio Code -# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore -# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore -# and can be added to the global gitignore or merged into this file. However, if you prefer, -# you could uncomment the following to ignore the entire vscode folder -# .vscode/ -# Temporary file for partial code execution -tempCodeRunnerFile.py - -# Ruff stuff: -.ruff_cache/ - -# PyPI configuration file -.pypirc - -# Marimo -marimo/_static/ -marimo/_lsp/ -__marimo__/ - -# Streamlit -.streamlit/secrets.toml \ No newline at end of file diff --git a/paper/shadow_maps_symmetric_states.tex b/paper/shadow_maps_symmetric_states.tex index 6fcb251..c75c772 100644 --- a/paper/shadow_maps_symmetric_states.tex +++ b/paper/shadow_maps_symmetric_states.tex @@ -731,132 +731,46 @@ independent of which cut's matricization is subsequently taken. $T(\rho)(\vec\imath)=\tr(\rho\,\sigma_{\vec\imath})$ is linear in $\rho$; substituting $\rho=\sum_{a,b}c_{ab}\ketbra{\phi_a}{\phi_b}$ and using $\tr(\ketbra{\phi_a}{\phi_b}\sigma_{\vec\imath})=\bra{\phi_b}\sigma_{\vec\imath}\ket{\phi_a}=T_{ba}(\vec\imath)$ gives Eq.~\eqref{eq:general-coherence-decomposition} termwise; the cut dependence enters only afterward, through the reshape of the index set $\vec\imath$, and does not affect the coefficients $c_{ab}$ or the tensors $T_{ab}$. \end{proof} -\begin{corollary}[Real-tensor count, corrected] -\label{cor:real-tensor-count} -Since $\sigma_{\vec\imath}$ is Hermitian, $T_{ba}=\overline{T_{ab}}$; in particular each $T_{aa}$ is real. Writing $T_{ab}=P_{ab}+iQ_{ab}$ for $ab symmetry) -- this is mechanical but has not been written out or +% numerically tested here for r>2. Do this before submission if the general +% statement is kept; otherwise restate the Proposition for r=2 only and move +% the general case to a remark. \begin{remark}[What this does and does not establish] \label{rem:recoupling-scope} Proposition~\ref{prop:coherence-templates} is a bookkeeping consequence of the linearity already used throughout this note (cf.\ the unfolding proposition and the "one rank-one fact, inherited everywhere" theorem of \cite{aschauer2026a}); its content is operational rather than a new inequality: once the $r^2$ template tensors are computed -- from simulation, or in principle extracted from permutationally/collectively-adapted state tomography -- every cut, every mixing angle, and every isotypic block $\|A_j\|_*$ of Corollary~\ref{cor:projector-norm-formula} for the resulting state family is available without revisiting the full $\bigl(\mathbb R^3\bigr)^{\otimes n}$-sized contraction again. +% TODO (deferred to future work, see session notes): the stronger, +% state-independent question of whether the reduced blocks A_j themselves +% (not just the raw tensor) transform between two different cuts of the +% SAME invariant tensor via an explicit, computable recoupling map -- i.e. +% a Racah/6j-symbol type formula relating A_j at cut S|S^c directly to the +% A_{j'} at a different cut S'|S'^c, without reshaping the full raw tensor +% -- is NOT established here. An exact branching-dimension check (m_p^{(4)} +% = sum over compatible y of m_y^{(3)} for every p=0,...,4) is consistent +% with such a relation existing, but the explicit coefficients (presumably +% governed by an SU(2) recoupling/6j-symbol calculation for the six spin-1 +% legs, or by the Brauer-algebra structure of Inv((R^3)^{\otimes 6}) since +% the example states here are literally perfect-matching invariants) have +% not been derived or numerically verified. Left for later. \end{remark} -\subsubsection{Recoupling the reduced blocks between two cuts} -\label{sec:six-j-recoupling} - -% ============================================================ -% NEW SUBSUBSECTION -- draft. Resolves the open point left in -% rem:recoupling-scope of an earlier draft: the reduced blocks A_j -% themselves (not just the raw tensor) DO transform between two cuts of -% the same invariant tensor via an explicit, closed-form, state-independent -% map. Derived and verified exactly (sympy, symbolic CG sums; brute-force -% simulation cross-check at machine precision) in -% scripts/six_j_recoupling_proof.py. The derivation below is condensed; -% the script carries every intermediate identity with its own numerical -% check, in case a step needs to be revisited. -% ============================================================ - -Remark~\ref{rem:recoupling-scope} left open whether the reduced blocks $A_j$ of two different cuts of the \emph{same} invariant tensor -- not merely the raw correlation tensor -- are related by an explicit, state-independent map. For the six-qubit example of Section~\ref{sec:singlet-network-example} they are, exactly, and the relating coefficients are elementary. - -\begin{theorem}[Cut recoupling for six spin-1 legs] -\label{thm:six-j-recoupling} -Fix $S_1=ABC\mid DEF$ with source tree $(AB)C\!\to\! j$, target tree $(DE)F\!\to\! j$, giving the reduced blocks $A_j^{(1)}[p,y]$ of Example~\ref{ex:singlet-superposition}, and $S_2=AB\mid CDEF$ with source $AB\!\to\! p$ directly and target tree $C,(DE)F\!\to\! p$, giving $A_p^{(2)}[y,j]$. For every $G$-invariant $\rho$ on the six qubits (collective hypothesis~\eqref{eq:collective-hypothesis}) and every valid $(p,y,j)$, -\begin{equation} -A_p^{(2)}[y,j] \;=\; -\sqrt{\frac{2j+1}{2p+1}}\;A_j^{(1)}[p,y], -\label{eq:six-j-recoupling} -\end{equation} -independent of $y$. -\end{theorem} - -\begin{proof}[Proof sketch] -Write $\widehat T$ for $T(\rho)$ regarded as a genuinely multilinear (not sesquilinear) functional of one real vector per leg, complexified $\mathbb C$-multilinearly; this is the natural extension of the real bilinear pairing underlying $M_{S\to S^c}(\rho)$ (the response-map construction of \cite{aschauer2026a}), and $G$-invariance of $\rho$ makes $\widehat T$ invariant under simultaneous rotation of all six legs. - -\emph{Step 1 (the correct Schur reduction).} For coupled multiplets $u_{p,j,m}$ (tree $(AB)C$) and $v_{y,j,m'}$ (tree $(DE)F$), invariance forces $X_{mm'}:=\widehat T(u_{p,j,m},v_{y,j,m'})$ to satisfy $X=D^j(g)^{\mathsf T}XD^j(g)$ for every $g$ (transpose, not the Hermitian adjoint, since $\widehat T$ is bilinear). Using $D^j(g)^{\mathsf T}=C_jD^j(g^{-1})C_j^{-1}$ with the metric $(C_j)_{mm'}=(-1)^{j-m}\delta_{m,-m'}$ turns this into an ordinary intertwiner condition $D^j(g)(C_j^{-1}X)=(C_j^{-1}X)D^j(g)$, so by Schur's lemma $C_j^{-1}X\propto\id$, i.e. -\begin{equation} -\widehat T(u_{p,j,m},v_{y,j,m'}) = c(p,y,j)\,(-1)^{j-m}\,\delta_{m,-m'} -\label{eq:schur-metric-form} -\end{equation} -for a single scalar $c(p,y,j)$. The identical argument, applied with the $C$-leg left unpaired, gives the reduced three-index object $R(m_p,m_C,m_j):=\widehat T(u^{AB}_{p,m_p}\otimes e_{m_C},\,v_{y,j,m_j})$ in terms of the \emph{same} scalar $c(p,y,j)$: since $R$, viewed as pairing the $j$-isotype of $V_p\otimes V_1$ against $V_j$, is subject to the same metric-form constraint, -\begin{equation} -R(m_p,m_C,m_j) = c(p,y,j)\,(-1)^{j+m_j}\,\langle p,m_p;1,m_C\,|\,j,-m_j\rangle. -\label{eq:R-metric-form} -\end{equation} -(Naively assuming $R\propto\langle p,m_p;1,m_C|j,m_j\rangle$ without the metric/sign flip -- i.e.\ skipping the $C_j$ correction in Step 1 -- reproduces neither the correct selection rule $m_p+m_C+m_j=0$ forced by $\widehat T$'s own weight conservation, nor a $y$-independent final answer; this was the error in an earlier attempt.) - -\emph{Step 2 (conjugation of a real-representation-derived multiplet).} For an $n_\ell$-leg multiplet of total spin $J$ built from the single-leg basis, complex conjugation acts by -\begin{equation} -\overline{v_{J,m}} = (-1)^{J+n_\ell}\,(-1)^m\,v_{J,-m}, -\label{eq:conjugation-phase} -\end{equation} -verified directly for the $3$-leg tree $(DE)F$ ($n_\ell=3$) and the $4$-leg tree $C,(DE)F$ ($n_\ell=4$) in \texttt{scripts/six\_j\_recoupling\_proof.py}, exactly and for every multiplet label. (Eq.~\eqref{eq:conjugation-phase} follows from the standard conjugation identity for Wigner $D$-matrices, $\overline{D^j_{m'm}(g)}=(-1)^{m'-m}D^j_{-m',-m}(g)$, applied inductively through the coupling tree together with Schur's lemma at each step; we verify the closed form directly rather than re-deriving the induction here.) - -\emph{Step 3 (assembly).} Combining Eqs.~\eqref{eq:schur-metric-form} and \eqref{eq:conjugation-phase} (with $n_\ell=3$) gives $A_j^{(1)}[p,y]=(-1)^{j+1}(-1)^jc(p,y,j)=-c(p,y,j)$, since $(-1)^{2j+1}=-1$ for integer $j$. For $A_p^{(2)}[y,j]$, expand the target multiplet $w_{y,j,p,m'}=\sum_{m_C,m_j}\langle1,m_C;j,m_j|p,m'\rangle\,e_{m_C}\otimes v_{y,j,m_j}$, apply Eq.~\eqref{eq:conjugation-phase} with $n_\ell=4$, and use Eq.~\eqref{eq:R-metric-form} for the resulting contraction with $R$. This leaves the finite sum -\begin{equation} -\Xi(p,j,m') := \sum_{m_C,m_j}\langle1,m_C;j,m_j\,|\,p,-m'\rangle\,(-1)^{j+m_j}\,\langle p,m';1,m_C\,|\,j,-m_j\rangle, -\label{eq:xi-sum} -\end{equation} -verified exactly (sympy, symbolic Clebsch--Gordan coefficients) to satisfy $(-1)^p(-1)^{m'}\Xi(p,j,m')=\sqrt{(2j+1)/(2p+1)}$ for every valid $(p,j,m')$ with $p,j\le3$ -- in particular independent of $m'$, as it must be, since $A_p^{(2)}$ is $m'$-independent by Corollary~\ref{cor:projector-norm-formula}. Assembling: $A_p^{(2)}[y,j]=\sqrt{(2j+1)/(2p+1)}\,c(p,y,j)=-\sqrt{(2j+1)/(2p+1)}\,A_j^{(1)}[p,y]$, proving Eq.~\eqref{eq:six-j-recoupling}. -\end{proof} - -\begin{remark}[Scope and what remains open] -\label{rem:six-j-scope} -Eq.~\eqref{eq:xi-sum} is a special value of a Racah recoupling coefficient with one of the six angular momenta equal to $1$, a case with classically known closed forms (see e.g.\ Varshalovich, \emph{Quantum Theory of Angular Momentum}, tables of $6j$ symbols with a unit argument); we verify the needed closed form directly by exhaustive exact symbolic evaluation for $p,j\le3$ rather than by matching a specific textbook formula, since two attempts at identifying the exact literature convention (transcribed as comments in \texttt{scripts/search\_6j.py}) did not reproduce it and the discrepancy was not tracked down. The proof above is therefore complete and independently checked (symbolically for the $\Xi$-sum, and end-to-end against brute-force simulation of both example states to $10^{-15}$), but does not give a citation-ready closed form for general $(p,j)$ beyond $p,j\le3$; extending the exact symbolic check to arbitrary $p,j$, or locating the precise textbook identity, is left for later. The conjugation phase of Eq.~\eqref{eq:conjugation-phase} is likewise verified rather than derived from first principles for general $n_\ell$; Step 2 sketches the expected inductive argument. -\end{remark} - -\subsubsection{Combining with permutation symmetry: multiplicity-free channels} -\label{sec:sm-so3-combination} - -% ============================================================ -% NEW SUBSUBSECTION -- draft. Resolves the second open point from an -% earlier draft's outlook TODO: combining the S_m-permutation collapse of -% Proposition~\ref{prop:multinomial-collapse} with the SO(3) branching of -% this subsection. Verified computationally on a concrete 6-qubit example -% (two coupled 3-qubit Dicke/symmetric multiplets) in -% scripts/combined_sm_so3_collapse.py. -% ============================================================ - -The two reduction mechanisms developed in this note -- the $S_m$-permutation collapse of Proposition~\ref{prop:multinomial-collapse} and the $SO(3)$ branching of this subsection -- combine multiplicatively rather than merely coexisting, and the combination is worth making explicit because it is genuinely stronger than either alone. - -\begin{proposition}[Harmonic decomposition of symmetric tensors; classical] -\label{prop:harmonic-decomposition} -As an $SO(3)$-representation, $\mathrm{Sym}^m(\mathbb R^3)$ decomposes multiplicity-free, -\begin{equation} -\mathrm{Sym}^m(\mathbb R^3) \;\cong\; \bigoplus_{k=0}^{\lfloor m/2\rfloor} \mathcal H_{m-2k}, -\qquad \dim\mathcal H_j = 2j+1, -\label{eq:harmonic-decomposition} -\end{equation} -where $\mathcal H_j$ denotes the space of degree-$j$ solid harmonics (equivalently, the traceless part of $\mathrm{Sym}^j(\mathbb R^3)$). This is the standard trace-decomposition of symmetric tensors underlying the multipole expansion; see e.g.\ Fulton--Harris. -\end{proposition} - -Consequently, for a source cluster $S$ of size $m$ that is invariant under \emph{both} $S_m$ (permutations of its own $m$ parties) \emph{and} the collective hypothesis~\eqref{eq:collective-hypothesis}, the source sector $\mathcal V_S^{(S)}$ collapses in two independent, compatible steps rather than one: first from $3^m$ to $\binom{m+2}{2}$ via Proposition~\ref{prop:multinomial-collapse} (a polynomial, but quadratic, reduction), and then, \emph{within} that $\binom{m+2}2$-dimensional space, the isotypic multiplicities collapse to exactly $1$ for each of the $O(m)$ surviving values $j=m,m-2,\dots$ -- dramatically finer than the generic branching multiplicities $m_j^{(m)}$ of Proposition~\ref{prop:branching-su2}, which grow with $m$ (e.g.\ $m_1^{(3)}=3$ unrestricted, versus multiplicity exactly $1$ within $\mathrm{Sym}^3$). Computationally, this second step costs one further Hermitian eigendecomposition of the $J^2$ Casimir restricted to the already-small $\binom{m+2}2$-dimensional space -- i.e.\ diagonalizing a matrix of side length $\binom{m+2}2$, not $3^m$ -- after which every surviving channel carries a genuine \emph{scalar} reduced matrix element $A_j$ (no residual multiplicity, hence no Clebsch--Gordan bookkeeping of the kind needed in Section~\ref{sec:six-j-recoupling}). - -\begin{example}[A doubly-symmetric six-qubit state] -\label{ex:dicke-network} -Let $S=\{A,B,C\}$, $S^c=\{D,E,F\}$, and let $\ket{D_3^k}$ denote the $3$-qubit Dicke state of weight $k$ (Section~\ref{sec:dicke-example}). The state -\begin{equation} -\ket{Q} \;\propto\; \sum_{k=0}^3 (-1)^k\, \ket{D_3^k}_{ABC}\otimes\ket{D_3^{3-k}}_{DEF} -\label{eq:dicke-network-state} -\end{equation} -is the canonical invariant ("singlet") combination of the two spin-$3/2$ multiplets spanned by the Dicke states on $ABC$ and on $DEF$ respectively (directly analogous to the two-spin-$1$ singlet construction of Example~\ref{ex:aligned-singlets}, now for the \emph{physical} qubit spin instead of the Bloch-vector generator spin). By construction $\ket Q$ is $S_3$-symmetric separately on $ABC$ and on $DEF$ (each factor is built from Dicke states), and, being the canonical invariant combination of two matching total-spin multiplets, satisfies the full collective hypothesis~\eqref{eq:collective-hypothesis} (verified directly: $\lvert\bra{Q}U_g^{\otimes6}\ket{Q}\rvert=1$ to machine precision for random $g\in SU(2)$). - -Restricting the $27\times27$ block $M_{S\to S^c}(\ketbra QQ)$ to the $10$-dimensional symmetric subspace $\mathrm{Sym}^3(\mathbb C^3)\subset\mathcal V_S^{(S)}$ on both sides (via the orthonormal "type" basis $\{u_\alpha\}_{\alpha\in\mathcal T_3}$ of Proposition~\ref{prop:multinomial-collapse}) and diagonalizing the restricted Casimir $U^\dagger J^2_{\mathrm{tot}}U$ gives eigenvalues $2$ (three-fold, $j=1$) and $12$ (seven-fold, $j=3$) \emph{exactly}, with $j=0,2$ entirely absent -- confirming Proposition~\ref{prop:harmonic-decomposition} concretely for $m=3$ ($\dim\mathcal H_3+\dim\mathcal H_1=7+3=10$). The two surviving channels carry the scalar reduced matrix elements -\begin{equation} -A_1 = \tfrac13, \qquad A_3 = 2, -\label{eq:dicke-network-values} -\end{equation} -satisfying $3A_1+7A_3=1+14=15=\norm{M_{S\to S^c}(\ketbra QQ)}_*$ exactly, matching the nuclear norm of the full, unrestricted $27\times27$ block computed directly -- so for this state \emph{every} unit of correlation captured by the cut already lives inside the doubly-symmetric sector (verified: the nuclear norm of $M_{S\to S^c}$ orthogonally projected \emph{away} from $\mathrm{Sym}^3\otimes\mathrm{Sym}^3$ is zero to $10^{-14}$). -\end{example} +% TODO (outlook, not attempted): combining the S_m-permutation collapse of +% Section~\ref{sec:polynomial-witness} (Proposition~\ref{prop:multinomial-collapse}) +% with the SO(3) branching of this subsection. For a cluster invariant under +% BOTH S_m and collective SO(3) simultaneously, Sym^m(R^3) is known classically +% to decompose multiplicity-free into spherical harmonics, m_j=1 for +% j=m,m-2,...; combined with Proposition~\ref{prop:multinomial-collapse} this +% should collapse a full sector to O(m) one-dimensional channels rather than +% the polynomial-but-not-linear \binom{m+2}{2} of that Proposition alone. +% Not worked out or tested here. \subsection{Exact degeneracy from stabilizer structure} diff --git a/scripts/symmetric_states/1_recoupling_check.py b/scripts/symmetric_states/1_recoupling_check.py deleted file mode 100644 index 2044588..0000000 --- a/scripts/symmetric_states/1_recoupling_check.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -Numerical check of the 'one invariant tensor, many cuts' claim -for the 6-qubit singlet-network example states. - -Qubits ordered A,B,C,D,E,F -> tensor axes 0..5. -S1 = ABC | DEF (3|3 cut) -S2 = AB | CDEF (2|4 cut) - -We build the two 'basis' states - |psi1> = singlets (A,D)(B,E)(C,F) - |psi2> = singlets (A,E)(B,F)(C,D) -and the family - |Xi(alpha)> = (cos(a) psi1 + sin(a) psi2) / norm - -For rho_Xi = |Xi>, T2 = , C12 = + , -N2 = . - -Key point: T1, T2, C12 do NOT depend on alpha or on the cut. -Once computed ONCE (full 6-leg tensors), every cut's shadow-map block -for every alpha is obtained by (i) taking this fixed linear combination -of THREE fixed numbers times three fixed tensors, and (ii) a plain -numpy .reshape() -- no further contraction over the 64-dim Hilbert space. - -This script verifies that against two independent brute-force -quantum simulations (cut S1 and cut S2, both done from scratch). -""" - -import numpy as np - -# ---------- Pauli matrices ---------- -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) -paulis = [X, Y, Z] - -# ---------- build the two basis states (6-qubit amplitude tensors) ---------- -def s(a,b): - if (a,b) == (0,1): return 1/np.sqrt(2) - if (a,b) == (1,0): return -1/np.sqrt(2) - return 0.0 - -def build_pairing(pairs): - psi = np.zeros((2,)*6, dtype=complex) - for idx in np.ndindex(2,2,2,2,2,2): - val = 1.0 - for (p,q) in pairs: - val *= s(idx[p], idx[q]) - if val == 0: break - psi[idx] = val - return psi - -psi1 = build_pairing([(0,3),(1,4),(2,5)]) # (A,D)(B,E)(C,F) -psi2 = build_pairing([(0,4),(1,5),(2,3)]) # (A,E)(B,F)(C,D) -overlap = np.vdot(psi1, psi2) -print("overlap =", overlap) - -def apply_pauli_leg(psi, axis, P): - psi2 = np.moveaxis(psi, axis, 0) - out = np.tensordot(P, psi2, axes=([1],[0])) - return np.moveaxis(out, 0, axis) - -def corr_tensor(bra, ket): - """, all six legs active (i in {0,1,2}=x,y,z).""" - c = np.zeros((3,3,3,3,3,3), dtype=complex) - for iA in range(3): - for iB in range(3): - for iC in range(3): - for iD in range(3): - for iE in range(3): - for iF in range(3): - ket_ = ket - for axis,ii in zip(range(6),(iA,iB,iC,iD,iE,iF)): - ket_ = apply_pauli_leg(ket_, axis, paulis[ii]) - c[iA,iB,iC,iD,iE,iF] = np.vdot(bra, ket_) - return c - -print("computing T1 = ...") -T1 = corr_tensor(psi1, psi1) -print("computing T2 = ...") -T2 = corr_tensor(psi2, psi2) -print("computing cross term ...") -X12 = corr_tensor(psi1, psi2) -X21 = corr_tensor(psi2, psi1) -C12 = X12 + X21 - -print("max imag part T1,T2,C12:", - np.abs(T1.imag).max(), np.abs(T2.imag).max(), np.abs(C12.imag).max()) -T1, T2, C12 = T1.real, T2.real, C12.real - -np.save("T1.npy", T1); np.save("T2.npy", T2); np.save("C12.npy", C12) - -# ---------- ground truth: brute-force Xi(alpha) for a couple of alphas, both cuts ---------- -alpha_list = [np.pi/5, 0.9, -0.3] - -def build_Xi(alpha): - raw = np.cos(alpha)*psi1 + np.sin(alpha)*psi2 - n = np.linalg.norm(raw) - return raw/n, n**2 - -def predict_from_basis(alpha): - N2 = 1 + np.sin(2*alpha)*overlap.real - return (np.cos(alpha)**2*T1 + np.sin(alpha)**2*T2 + np.cos(alpha)*np.sin(alpha)*C12) / N2 - -max_err_cut1 = 0.0 -max_err_cut2 = 0.0 -for a in alpha_list: - Xi, N2_check = build_Xi(a) - Tgt = corr_tensor(Xi, Xi).real # brute-force ground truth, full simulation - Tpred = predict_from_basis(a) # from the 3 fixed tensors, no new simulation - - err = np.abs(Tgt - Tpred).max() - print(f"alpha={a:+.4f}: max|T_bruteforce - T_predicted| = {err:.3e} (N2 check: {N2_check:.6f})") - - # cut 1: ABC|DEF (27x27) - M1_true = Tgt.reshape(27,27) - M1_pred = Tpred.reshape(27,27) - e1 = np.abs(M1_true - M1_pred).max() - max_err_cut1 = max(max_err_cut1, e1) - - # cut 2: AB|CDEF (9x81) - M2_true = Tgt.reshape(9,81) - M2_pred = Tpred.reshape(9,81) - e2 = np.abs(M2_true - M2_pred).max() - max_err_cut2 = max(max_err_cut2, e2) - - print(f" cut ABC|DEF : max matrix error = {e1:.3e}, ||M||_* true={np.linalg.svd(M1_true,compute_uv=False).sum():.4f} " - f"pred={np.linalg.svd(M1_pred,compute_uv=False).sum():.4f}") - print(f" cut AB|CDEF : max matrix error = {e2:.3e}, ||M||_* true={np.linalg.svd(M2_true,compute_uv=False).sum():.4f} " - f"pred={np.linalg.svd(M2_pred,compute_uv=False).sum():.4f}") - -print() -print(f"WORST CASE over all tested alpha, both cuts: {max(max_err_cut1, max_err_cut2):.3e}") diff --git a/scripts/symmetric_states/2_exact_casimir_projectors.py b/scripts/symmetric_states/2_exact_casimir_projectors.py deleted file mode 100644 index 35773af..0000000 --- a/scripts/symmetric_states/2_exact_casimir_projectors.py +++ /dev/null @@ -1,88 +0,0 @@ -""" -Exact SO(3) isotypic projectors on (R^3)^{\otimes k} via the Casimir -operator J^2, instead of Monte-Carlo character averaging. - -The spin-1 (vector) generators in the real Cartesian basis are - (J_a)_{bc} = -i * epsilon_{abc} (standard so(3) generators) -Built exactly with sympy, then verified to satisfy [J_a,J_b] = i eps_abc J_c -and J^2 = J_x^2+J_y^2+J_z^2 = 2*I_3 (i.e. j=1, j(j+1)=2) -- symbolically exact. - -For k copies, total J_a = sum_{l=1}^k I x ... x J_a^{(l)} x ... x I, -J^2_total is Hermitian on (C^3)^{\otimes k}; its eigenspaces are EXACTLY -the isotypic components (eigenvalue j(j+1)). No integration needed. -""" -import numpy as np -import sympy as sp - -i = sp.I -eps = lambda a,b,c: sp.LeviCivita(a,b,c) - -def J_component(a): - # a in {0,1,2} = x,y,z ; (J_a)_{bc} = -i * eps(a,b,c) - M = sp.zeros(3,3) - for b in range(3): - for c in range(3): - M[b,c] = -i*eps(a,b,c) - return M - -Jx, Jy, Jz = J_component(0), J_component(1), J_component(2) - -# --- symbolic sanity checks --- -comm = Jx*Jy - Jy*Jx -print("[Jx,Jy] - i*Jz == 0 ?", sp.simplify(comm - i*Jz) == sp.zeros(3,3)) -J2_single = sp.simplify(Jx*Jx + Jy*Jy + Jz*Jz) -print("J^2 (single spin-1 leg), should be 2*I_3:") -sp.pprint(J2_single) - -# convert to numpy (complex) for fast Kronecker-sum construction at larger k -Jx_np = np.array(Jx.tolist(), dtype=complex) -Jy_np = np.array(Jy.tolist(), dtype=complex) -Jz_np = np.array(Jz.tolist(), dtype=complex) - -def total_J2(k): - dim = 3**k - Jtot = {a: np.zeros((dim,dim), dtype=complex) for a in range(3)} - comps = [Jx_np, Jy_np, Jz_np] - for leg in range(k): - for a in range(3): - mats = [np.eye(3, dtype=complex)]*k - mats[leg] = comps[a] - M = mats[0] - for m in mats[1:]: - M = np.kron(M, m) - Jtot[a] += M - return Jtot[0]@Jtot[0] + Jtot[1]@Jtot[1] + Jtot[2]@Jtot[2] - -def exact_projectors(k, jmax): - J2 = total_J2(k) - assert np.abs(J2 - J2.conj().T).max() < 1e-10, "J^2 not Hermitian!" - evals, evecs = np.linalg.eigh(J2) - Ps = {} - for j in range(jmax+1): - target = j*(j+1) - mask = np.abs(evals - target) < 1e-6 - if not np.any(mask): - Ps[j] = np.zeros((3**k,3**k)) - continue - V = evecs[:, mask] - P = (V @ V.conj().T).real - Ps[j] = P - # sanity: eigenvalues actually cluster near integers j(j+1) - return Ps, evals - -print("\nBuilding exact projectors for k=2,3,4 via Casimir diagonalization...") -Ps2, ev2 = exact_projectors(2, 2) -Ps3, ev3 = exact_projectors(3, 3) -Ps4, ev4 = exact_projectors(4, 4) - -for k,Ps,jmax in [(2,Ps2,2),(3,Ps3,3),(4,Ps4,4)]: - print(f"\nk={k}:") - for j in range(jmax+1): - tr = np.trace(Ps[j]).real - print(f" j={j}: trace(P_j) = {tr:.10f} (expect (2j+1)*m_j)") - -np.savez("projectors_exact.npz", - P2_0=Ps2[0],P2_1=Ps2[1],P2_2=Ps2[2], - P3_0=Ps3[0],P3_1=Ps3[1],P3_2=Ps3[2],P3_3=Ps3[3], - P4_0=Ps4[0],P4_1=Ps4[1],P4_2=Ps4[2],P4_3=Ps4[3],P4_4=Ps4[4]) -print("\nsaved projectors_exact.npz") diff --git a/scripts/symmetric_states/3_apply_exact_projectors.py b/scripts/symmetric_states/3_apply_exact_projectors.py deleted file mode 100644 index f50405b..0000000 --- a/scripts/symmetric_states/3_apply_exact_projectors.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Apply the EXACT Casimir-based isotypic projectors (projectors_exact.npz) -to the two example states, at both cuts, replacing the earlier -Monte-Carlo-based ||A_j||_* estimates with machine-precision values. - -Uses T1, T2, C12 (saved by recoupling_check.py) so that "Example 1" -(pure psi1) and "Example 2" (Xi at alpha) are both obtained from the -SAME three fixed tensors, no new quantum simulation. -""" -import numpy as np - -T1 = np.load("T1.npy") -T2 = np.load("T2.npy") -C12 = np.load("C12.npy") -overlap = 0.25 # , real (checked earlier) - -P = np.load("projectors_exact.npz") - -def state_tensor(alpha): - N2 = 1 + np.sin(2*alpha)*overlap - return (np.cos(alpha)**2*T1 + np.sin(alpha)**2*T2 - + np.cos(alpha)*np.sin(alpha)*C12) / N2 - -def report(label, alpha): - T = state_tensor(alpha) - M_c1 = T.reshape(27,27) # cut ABC|DEF - M_c2 = T.reshape(9,81) # cut AB|CDEF - - print(f"\n=== {label} (alpha={alpha}) ===") - print("-- cut ABC|DEF --") - tot = 0.0 - for j in range(4): - Pj = P[f"P3_{j}"] - block = Pj @ M_c1 @ Pj - nn = np.linalg.svd(block, compute_uv=False).sum() - Aj = nn/(2*j+1) - tot += (2*j+1)*Aj - print(f" j={j}: ||A_j||_* = {Aj:.6f}") - raw_nn = np.linalg.svd(M_c1, compute_uv=False).sum() - print(f" sum_j (2j+1)||A_j||_* = {tot:.6f} vs. ||M||_* direct = {raw_nn:.6f}") - - print("-- cut AB|CDEF --") - tot = 0.0 - for j in range(3): - Pj_src = P[f"P2_{j}"] - Pj_tgt = P[f"P4_{j}"] - block = Pj_src @ M_c2 @ Pj_tgt - nn = np.linalg.svd(block, compute_uv=False).sum() - Aj = nn/(2*j+1) - tot += (2*j+1)*Aj - print(f" j={j}: ||A_j||_* = {Aj:.6f}") - raw_nn = np.linalg.svd(M_c2, compute_uv=False).sum() - print(f" sum_j (2j+1)||A_j||_* = {tot:.6f} vs. ||M||_* direct = {raw_nn:.6f}") - -report("Example 1 (pure psi1, three aligned singlets)", 0.0) -report("Example 2 (superposition)", np.pi/5) diff --git a/scripts/symmetric_states/4_spherical_basis.py b/scripts/symmetric_states/4_spherical_basis.py deleted file mode 100644 index 86ea99b..0000000 --- a/scripts/symmetric_states/4_spherical_basis.py +++ /dev/null @@ -1,65 +0,0 @@ -""" -Step 1: build a Condon-Shortley-consistent spherical basis {|1,-1>,|1,0>,|1,+1>} -for a single spin-1 leg, starting from the EXACT Cartesian generators -(J_a)_{bc} = -i eps_{abc} (already verified symbolically in -exact_casimir_projectors.py), and using the ladder-operator construction -so we do not have to trust a memorized phase convention. -""" -import numpy as np - -def J_component(a): - eps = np.zeros((3,3,3)) - eps[0,1,2]=eps[1,2,0]=eps[2,0,1]=1 - eps[0,2,1]=eps[2,1,0]=eps[1,0,2]=-1 - M = np.zeros((3,3), dtype=complex) - for b in range(3): - for c in range(3): - M[b,c] = -1j*eps[a,b,c] - return M - -Jx, Jy, Jz = J_component(0), J_component(1), J_component(2) -Jp = Jx + 1j*Jy # raising -Jm = Jx - 1j*Jy # lowering - -# sanity -print("[Jx,Jy]-i Jz max err:", np.abs(Jx@Jy-Jy@Jx - 1j*Jz).max()) -print("J^2 (single leg), should be 2*I:") -print(np.round(Jx@Jx+Jy@Jy+Jz@Jz,6)) - -# eigenvectors of Jz -evals, evecs = np.linalg.eigh(Jz) # Jz Hermitian? check -print("Jz Hermitian check:", np.abs(Jz - Jz.conj().T).max()) -print("Jz eigenvalues:", np.round(evals,6)) - -# pick |1,-1> = eigenvector with eigenvalue closest to -1, fix phase: first -# nonzero component real positive -idx_m1 = np.argmin(np.abs(evals - (-1))) -v_m1 = evecs[:, idx_m1] -# fix global phase -k = np.argmax(np.abs(v_m1)) -v_m1 = v_m1 * np.exp(-1j*np.angle(v_m1[k])) -if v_m1[k].real < 0: v_m1 = -v_m1 -print("\n|1,-1> (Cartesian components x,y,z):", np.round(v_m1,4)) - -# ladder up: |1,0> = Jp|1,-1> / ||...|| (standard CS convention: J+|j,m>=sqrt((j-m)(j+m+1))|j,m+1>, positive real coefficient) -v0_raw = Jp @ v_m1 -n0 = np.linalg.norm(v0_raw) -v_0 = v0_raw / n0 -print("|1,0> raw ladder norm (expect sqrt((1-(-1))*(1+(-1)+1))=sqrt(2)):", n0) - -v_p1_raw = Jp @ v_0 -n_p1 = np.linalg.norm(v_p1_raw) -v_p1 = v_p1_raw / n_p1 -print("|1,+1> raw ladder norm (expect sqrt((1-0)*(1+0+1))=sqrt(2)):", n_p1) - -# check orthonormality and Jz eigenvalues -basis = np.stack([v_m1, v_0, v_p1], axis=1) # columns -print("\northonormality check (should be I_3):") -print(np.round(basis.conj().T @ basis, 6)) - -for name, v, m in [("|1,-1>", v_m1, -1), ("|1,0>", v_0, 0), ("|1,+1>", v_p1, 1)]: - Jzv = Jz @ v - print(f"{name}: Jz|.> - {m}|.> max err = {np.abs(Jzv - m*v).max():.2e}") - -np.save("spherical_basis_single_leg.npy", basis) # columns m=-1,0,+1 -print("\nsaved spherical_basis_single_leg.npy (columns ordered m=-1,0,+1)") diff --git a/scripts/symmetric_states/6_six_j_recoupling_proof(1).py b/scripts/symmetric_states/6_six_j_recoupling_proof(1).py deleted file mode 100644 index f0fc5f8..0000000 --- a/scripts/symmetric_states/6_six_j_recoupling_proof(1).py +++ /dev/null @@ -1,189 +0,0 @@ -""" -COMPLETE, VERIFIED PROOF of the cut-recoupling formula for full collective -SU(2) symmetry (six qubits A,B,C,D,E,F), relating the reduced blocks A_j^(1) -(cut ABC|DEF, source tree (AB)C, target tree (DE)F) to A_p^(2) (cut AB|CDEF, -source AB directly, target tree C,(DE)F). - -CLAIM: A_p^(2)[y,j] = -sqrt((2j+1)/(2p+1)) * A_j^(1)[p,y] (indep. of y) - -Proof outline (each step verified below): - (1) Schur's lemma, applied CORRECTLY to the bilinear (not sesquilinear) - invariant pairing of T -- accounting for the fact that the transpose - of a Wigner D-matrix relates to D^{-1} via the metric C_j, - (C_j)_{mm'} = (-1)^{j-m} delta_{m,-m'}, NOT via D itself -- gives - That(u_{p,j,m}, v_{y,j,m'}) = c(p,y,j) * (-1)^(j-m) * delta(m,-m') - for a single scalar c(p,y,j), and the analogous statement with the - C-leg left free (R^bilin), reduced matrix element proportional to the - SAME c(p,y,j). - (2) Complex conjugation of a real-representation-derived CG-coupled - n_leg-particle multiplet of total spin J satisfies EXACTLY - conj(v_{J,m}) = (-1)^(J+n_leg) * (-1)^m * v_{J,-m} - verified here for n_leg=3 (DEF tree) and n_leg=4 (CDEF tree). - (3) Combining (1),(2): A_j^(1)[p,y] = -c(p,y,j). - (4) The analogous combination for A_p^(2) requires evaluating the CG sum - Xi(p,j,m') = sum_{mC,mj} <1,mC;j,mj|p,-m'> (-1)^(j+mj) - which is verified EXACTLY (sympy, symbolic) to equal, for every - (p,j) with p,j <= 3 and every valid m': - (-1)^p * (-1)^m' * Xi(p,j,m') = sqrt((2j+1)/(2p+1)) - (5) Assembling (3)+(4) gives the claim. - -This script re-derives (1)-(5) and, as an end-to-end sanity check, verifies -the final formula directly against brute-force quantum simulation of the -two example states of the companion note (three aligned singlets; a -coherent superposition of two singlet networks). -""" -import numpy as np -from sympy import Rational as Rat, sqrt, simplify -from sympy.physics.quantum.cg import CG - -# ---------- single-leg spherical basis (Condon-Shortley, via ladder ops) ---------- -def J_component(a): - eps = np.zeros((3,3,3)) - eps[0,1,2]=eps[1,2,0]=eps[2,0,1]=1 - eps[0,2,1]=eps[2,1,0]=eps[1,0,2]=-1 - M = np.zeros((3,3), dtype=complex) - for b in range(3): - for c in range(3): - M[b,c] = -1j*eps[a,b,c] - return M -Jx,Jy,Jz = J_component(0),J_component(1),J_component(2) -Jp = Jx+1j*Jy -evals,evecs = np.linalg.eigh(Jz) -idx_m1 = np.argmin(np.abs(evals+1)) -v_m1 = evecs[:,idx_m1] -k = np.argmax(np.abs(v_m1)); v_m1 = v_m1*np.exp(-1j*np.angle(v_m1[k])) -if v_m1[k].real<0: v_m1=-v_m1 -v_0 = Jp@v_m1; v_0/=np.linalg.norm(v_0) -v_p1 = Jp@v_0; v_p1/=np.linalg.norm(v_p1) -leg = {-1:v_m1, 0:v_0, 1:v_p1} - -def cg(j1,m1,j2,m2,j3,m3): - if abs(m1)>j1 or abs(m2)>j2 or abs(m3)>j3 or m1+m2!=m3: return 0.0 - return complex(CG(Rat(j1),Rat(m1),Rat(j2),Rat(m2),Rat(j3),Rat(m3)).doit()) -def couple(vecs1,j1,vecs2,j2,j3): - out={} - d = len(vecs1[list(vecs1.keys())[0]])*len(vecs2[list(vecs2.keys())[0]]) - for m3 in range(-j3,j3+1): - v = np.zeros(d,dtype=complex) - for m1 in range(-j1,j1+1): - m2 = m3-m1 - if abs(m2)>j2: continue - c = cg(j1,m1,j2,m2,j3,m3) - if c==0: continue - v = v + c*np.kron(vecs1[m1],vecs2[m2]) - out[m3]=v - return out -def valid_j(j1,j2): return range(abs(j1-j2), j1+j2+1) - -mult_AB = {p: couple(leg,1,leg,1,p) for p in range(3)} -mult_DE = {y: couple(leg,1,leg,1,y) for y in range(3)} -mult_ABC = {(p,j): couple(mult_AB[p],p,leg,1,j) for p in range(3) for j in valid_j(p,1)} -mult_DEF = {(y,j): couple(mult_DE[y],y,leg,1,j) for y in range(3) for j in valid_j(y,1)} -mult_CDEF = {} -for (y,j),vdef in mult_DEF.items(): - for p in valid_j(1,j): - if p<=2: mult_CDEF[(y,j,p)] = couple(leg,1,vdef,j,p) - -print("=== Step (2): verify conj(v) = (-1)^(J+n_leg) * (-1)^m * v(-m) ===") -ok = True -for (y,j),v in mult_DEF.items(): - for m in range(-j,j+1): - pred = ((-1)**(j+3)) * ((-1)**m) * v[-m] - err = np.abs(np.conj(v[m]) - pred).max() - if err > 1e-8: ok = False -print("DEF (n_leg=3) multiplets: conj identity holds for all y,j,m:", ok) - -ok=True -for (y,j,p),w in mult_CDEF.items(): - for m in range(-p,p+1): - pred = ((-1)**(p+4)) * ((-1)**m) * w[-m] - err = np.abs(np.conj(w[m]) - pred).max() - if err > 1e-8: ok=False -print("CDEF (n_leg=4) multiplets: conj identity holds for all y,j,p,m:", ok) - -print("\n=== Step (4): verify Xi identity symbolically for all p,j<=3 ===") -def cgS(j1,m1,j2,m2,j3,m3): - if abs(m1)>j1 or abs(m2)>j2 or abs(m3)>j3 or m1+m2!=m3: return 0 - return CG(Rat(j1),Rat(m1),Rat(j2),Rat(m2),Rat(j3),Rat(m3)).doit() -all_ok = True -for p in range(3): - for j in valid_j(p,1): - for mp in range(-p,p+1): - Xi = 0 - for mC in (-1,0,1): - for mj in range(-j,j+1): - a = cgS(1,mC,j,mj,p,-mp) - if a==0: continue - b = cgS(p,mp,1,mC,j,-mj) - if b==0: continue - Xi += a*(-1)**(j+mj)*b - lhs = simplify((-1)**p * (-1)**mp * Xi) - rhs = simplify(sqrt(Rat(2*j+1,2*p+1))) - if simplify(lhs-rhs)!=0: all_ok=False -print("Xi identity holds exactly for every (p,j,m'), p,j<=3:", all_ok) - -print("\n=== End-to-end: verify final formula against brute-force simulation ===") -def s(a,b): - if (a,b)==(0,1): return 1/np.sqrt(2) - if (a,b)==(1,0): return -1/np.sqrt(2) - return 0.0 -def build_pairing(pairs): - psi = np.zeros((2,)*6, dtype=complex) - for idx in np.ndindex(2,2,2,2,2,2): - val=1.0 - for (p_,q_) in pairs: - val *= s(idx[p_], idx[q_]) - if val==0: break - psi[idx]=val - return psi -psi1 = build_pairing([(0,3),(1,4),(2,5)]) -psi2 = build_pairing([(0,4),(1,5),(2,3)]) -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) -paulis=[X,Y,Z] -def apply_leg(psi,axis,P): - p2=np.moveaxis(psi,axis,0); out=np.tensordot(P,p2,axes=([1],[0])); return np.moveaxis(out,0,axis) -def corr_tensor(bra,ket): - c=np.zeros((3,3,3,3,3,3),dtype=complex) - for iA in range(3): - for iB in range(3): - for iC in range(3): - for iD in range(3): - for iE in range(3): - for iF in range(3): - k=ket - for ax,ii in zip(range(6),(iA,iB,iC,iD,iE,iF)): - k=apply_leg(k,ax,paulis[ii]) - c[iA,iB,iC,iD,iE,iF]=np.vdot(bra,k) - return c - -def A1_table(T): - M = T.reshape(27,27) - out = {} - for (p,j),vp in mult_ABC.items(): - for y in range(3): - if (y,j) not in mult_DEF: continue - vy = mult_DEF[(y,j)] - out[(p,y,j)] = (vp[0] @ M @ np.conj(vy[0])).real if j>=0 else None - return out -def A2_table(T): - M2 = T.reshape(9,81) - out = {} - for p, vab in mult_AB.items(): - for (y,j,p2), vcdef in mult_CDEF.items(): - if p2 != p: continue - out[(p,y,j)] = (vab[0] @ M2 @ np.conj(vcdef[0])).real - return out - -alpha = np.pi/5 -raw = np.cos(alpha)*psi1 + np.sin(alpha)*psi2 -Xi_state = raw/np.linalg.norm(raw) -Tstate = corr_tensor(Xi_state,Xi_state).real -A1 = A1_table(Tstate); A2 = A2_table(Tstate) -maxerr = 0 -for key in set(A1)&set(A2): - p,y,j = key - pred = -np.sqrt((2*j+1)/(2*p+1))*A1[key] - err = abs(pred - A2[key]) - maxerr = max(maxerr, err) -print(f"max |A2 - (-sqrt((2j+1)/(2p+1)))*A1| over all (p,y,j), superposition state: {maxerr:.2e}") -print("\n==> PROOF COMPLETE AND VERIFIED END-TO-END.") diff --git a/scripts/symmetric_states/6_six_j_recoupling_proof.py b/scripts/symmetric_states/6_six_j_recoupling_proof.py deleted file mode 100644 index f0fc5f8..0000000 --- a/scripts/symmetric_states/6_six_j_recoupling_proof.py +++ /dev/null @@ -1,189 +0,0 @@ -""" -COMPLETE, VERIFIED PROOF of the cut-recoupling formula for full collective -SU(2) symmetry (six qubits A,B,C,D,E,F), relating the reduced blocks A_j^(1) -(cut ABC|DEF, source tree (AB)C, target tree (DE)F) to A_p^(2) (cut AB|CDEF, -source AB directly, target tree C,(DE)F). - -CLAIM: A_p^(2)[y,j] = -sqrt((2j+1)/(2p+1)) * A_j^(1)[p,y] (indep. of y) - -Proof outline (each step verified below): - (1) Schur's lemma, applied CORRECTLY to the bilinear (not sesquilinear) - invariant pairing of T -- accounting for the fact that the transpose - of a Wigner D-matrix relates to D^{-1} via the metric C_j, - (C_j)_{mm'} = (-1)^{j-m} delta_{m,-m'}, NOT via D itself -- gives - That(u_{p,j,m}, v_{y,j,m'}) = c(p,y,j) * (-1)^(j-m) * delta(m,-m') - for a single scalar c(p,y,j), and the analogous statement with the - C-leg left free (R^bilin), reduced matrix element proportional to the - SAME c(p,y,j). - (2) Complex conjugation of a real-representation-derived CG-coupled - n_leg-particle multiplet of total spin J satisfies EXACTLY - conj(v_{J,m}) = (-1)^(J+n_leg) * (-1)^m * v_{J,-m} - verified here for n_leg=3 (DEF tree) and n_leg=4 (CDEF tree). - (3) Combining (1),(2): A_j^(1)[p,y] = -c(p,y,j). - (4) The analogous combination for A_p^(2) requires evaluating the CG sum - Xi(p,j,m') = sum_{mC,mj} <1,mC;j,mj|p,-m'> (-1)^(j+mj) - which is verified EXACTLY (sympy, symbolic) to equal, for every - (p,j) with p,j <= 3 and every valid m': - (-1)^p * (-1)^m' * Xi(p,j,m') = sqrt((2j+1)/(2p+1)) - (5) Assembling (3)+(4) gives the claim. - -This script re-derives (1)-(5) and, as an end-to-end sanity check, verifies -the final formula directly against brute-force quantum simulation of the -two example states of the companion note (three aligned singlets; a -coherent superposition of two singlet networks). -""" -import numpy as np -from sympy import Rational as Rat, sqrt, simplify -from sympy.physics.quantum.cg import CG - -# ---------- single-leg spherical basis (Condon-Shortley, via ladder ops) ---------- -def J_component(a): - eps = np.zeros((3,3,3)) - eps[0,1,2]=eps[1,2,0]=eps[2,0,1]=1 - eps[0,2,1]=eps[2,1,0]=eps[1,0,2]=-1 - M = np.zeros((3,3), dtype=complex) - for b in range(3): - for c in range(3): - M[b,c] = -1j*eps[a,b,c] - return M -Jx,Jy,Jz = J_component(0),J_component(1),J_component(2) -Jp = Jx+1j*Jy -evals,evecs = np.linalg.eigh(Jz) -idx_m1 = np.argmin(np.abs(evals+1)) -v_m1 = evecs[:,idx_m1] -k = np.argmax(np.abs(v_m1)); v_m1 = v_m1*np.exp(-1j*np.angle(v_m1[k])) -if v_m1[k].real<0: v_m1=-v_m1 -v_0 = Jp@v_m1; v_0/=np.linalg.norm(v_0) -v_p1 = Jp@v_0; v_p1/=np.linalg.norm(v_p1) -leg = {-1:v_m1, 0:v_0, 1:v_p1} - -def cg(j1,m1,j2,m2,j3,m3): - if abs(m1)>j1 or abs(m2)>j2 or abs(m3)>j3 or m1+m2!=m3: return 0.0 - return complex(CG(Rat(j1),Rat(m1),Rat(j2),Rat(m2),Rat(j3),Rat(m3)).doit()) -def couple(vecs1,j1,vecs2,j2,j3): - out={} - d = len(vecs1[list(vecs1.keys())[0]])*len(vecs2[list(vecs2.keys())[0]]) - for m3 in range(-j3,j3+1): - v = np.zeros(d,dtype=complex) - for m1 in range(-j1,j1+1): - m2 = m3-m1 - if abs(m2)>j2: continue - c = cg(j1,m1,j2,m2,j3,m3) - if c==0: continue - v = v + c*np.kron(vecs1[m1],vecs2[m2]) - out[m3]=v - return out -def valid_j(j1,j2): return range(abs(j1-j2), j1+j2+1) - -mult_AB = {p: couple(leg,1,leg,1,p) for p in range(3)} -mult_DE = {y: couple(leg,1,leg,1,y) for y in range(3)} -mult_ABC = {(p,j): couple(mult_AB[p],p,leg,1,j) for p in range(3) for j in valid_j(p,1)} -mult_DEF = {(y,j): couple(mult_DE[y],y,leg,1,j) for y in range(3) for j in valid_j(y,1)} -mult_CDEF = {} -for (y,j),vdef in mult_DEF.items(): - for p in valid_j(1,j): - if p<=2: mult_CDEF[(y,j,p)] = couple(leg,1,vdef,j,p) - -print("=== Step (2): verify conj(v) = (-1)^(J+n_leg) * (-1)^m * v(-m) ===") -ok = True -for (y,j),v in mult_DEF.items(): - for m in range(-j,j+1): - pred = ((-1)**(j+3)) * ((-1)**m) * v[-m] - err = np.abs(np.conj(v[m]) - pred).max() - if err > 1e-8: ok = False -print("DEF (n_leg=3) multiplets: conj identity holds for all y,j,m:", ok) - -ok=True -for (y,j,p),w in mult_CDEF.items(): - for m in range(-p,p+1): - pred = ((-1)**(p+4)) * ((-1)**m) * w[-m] - err = np.abs(np.conj(w[m]) - pred).max() - if err > 1e-8: ok=False -print("CDEF (n_leg=4) multiplets: conj identity holds for all y,j,p,m:", ok) - -print("\n=== Step (4): verify Xi identity symbolically for all p,j<=3 ===") -def cgS(j1,m1,j2,m2,j3,m3): - if abs(m1)>j1 or abs(m2)>j2 or abs(m3)>j3 or m1+m2!=m3: return 0 - return CG(Rat(j1),Rat(m1),Rat(j2),Rat(m2),Rat(j3),Rat(m3)).doit() -all_ok = True -for p in range(3): - for j in valid_j(p,1): - for mp in range(-p,p+1): - Xi = 0 - for mC in (-1,0,1): - for mj in range(-j,j+1): - a = cgS(1,mC,j,mj,p,-mp) - if a==0: continue - b = cgS(p,mp,1,mC,j,-mj) - if b==0: continue - Xi += a*(-1)**(j+mj)*b - lhs = simplify((-1)**p * (-1)**mp * Xi) - rhs = simplify(sqrt(Rat(2*j+1,2*p+1))) - if simplify(lhs-rhs)!=0: all_ok=False -print("Xi identity holds exactly for every (p,j,m'), p,j<=3:", all_ok) - -print("\n=== End-to-end: verify final formula against brute-force simulation ===") -def s(a,b): - if (a,b)==(0,1): return 1/np.sqrt(2) - if (a,b)==(1,0): return -1/np.sqrt(2) - return 0.0 -def build_pairing(pairs): - psi = np.zeros((2,)*6, dtype=complex) - for idx in np.ndindex(2,2,2,2,2,2): - val=1.0 - for (p_,q_) in pairs: - val *= s(idx[p_], idx[q_]) - if val==0: break - psi[idx]=val - return psi -psi1 = build_pairing([(0,3),(1,4),(2,5)]) -psi2 = build_pairing([(0,4),(1,5),(2,3)]) -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) -paulis=[X,Y,Z] -def apply_leg(psi,axis,P): - p2=np.moveaxis(psi,axis,0); out=np.tensordot(P,p2,axes=([1],[0])); return np.moveaxis(out,0,axis) -def corr_tensor(bra,ket): - c=np.zeros((3,3,3,3,3,3),dtype=complex) - for iA in range(3): - for iB in range(3): - for iC in range(3): - for iD in range(3): - for iE in range(3): - for iF in range(3): - k=ket - for ax,ii in zip(range(6),(iA,iB,iC,iD,iE,iF)): - k=apply_leg(k,ax,paulis[ii]) - c[iA,iB,iC,iD,iE,iF]=np.vdot(bra,k) - return c - -def A1_table(T): - M = T.reshape(27,27) - out = {} - for (p,j),vp in mult_ABC.items(): - for y in range(3): - if (y,j) not in mult_DEF: continue - vy = mult_DEF[(y,j)] - out[(p,y,j)] = (vp[0] @ M @ np.conj(vy[0])).real if j>=0 else None - return out -def A2_table(T): - M2 = T.reshape(9,81) - out = {} - for p, vab in mult_AB.items(): - for (y,j,p2), vcdef in mult_CDEF.items(): - if p2 != p: continue - out[(p,y,j)] = (vab[0] @ M2 @ np.conj(vcdef[0])).real - return out - -alpha = np.pi/5 -raw = np.cos(alpha)*psi1 + np.sin(alpha)*psi2 -Xi_state = raw/np.linalg.norm(raw) -Tstate = corr_tensor(Xi_state,Xi_state).real -A1 = A1_table(Tstate); A2 = A2_table(Tstate) -maxerr = 0 -for key in set(A1)&set(A2): - p,y,j = key - pred = -np.sqrt((2*j+1)/(2*p+1))*A1[key] - err = abs(pred - A2[key]) - maxerr = max(maxerr, err) -print(f"max |A2 - (-sqrt((2j+1)/(2p+1)))*A1| over all (p,y,j), superposition state: {maxerr:.2e}") -print("\n==> PROOF COMPLETE AND VERIFIED END-TO-END.") diff --git a/scripts/symmetric_states/7_combined_sm_so3_collapse.py b/scripts/symmetric_states/7_combined_sm_so3_collapse.py deleted file mode 100644 index ed4343a..0000000 --- a/scripts/symmetric_states/7_combined_sm_so3_collapse.py +++ /dev/null @@ -1,128 +0,0 @@ -import numpy as np -from itertools import permutations, product -from math import comb - -def dicke3(k): - psi = np.zeros(8, dtype=complex); n=0 - for bits in range(8): - if bin(bits).count("1")==k: psi[bits]=1.0; n+=1 - return psi/np.sqrt(n) -D3 = {k: dicke3(k) for k in range(4)} -Q = np.zeros(64, dtype=complex) -for k in range(4): - Q += ((-1)**k) * np.kron(D3[k], D3[3-k]) -Q /= np.linalg.norm(Q) - -# --- correlation tensor (Cartesian, all six legs, A,B,C,D,E,F) --- -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) -paulis=[X,Y,Z] -Qt = Q.reshape((2,)*6) -def apply_leg(psi,axis,P): - p2=np.moveaxis(psi,axis,0); out=np.tensordot(P,p2,axes=([1],[0])); return np.moveaxis(out,0,axis) -def corr_tensor(bra,ket): - c=np.zeros((3,3,3,3,3,3),dtype=complex) - for iA in range(3): - for iB in range(3): - for iC in range(3): - for iD in range(3): - for iE in range(3): - for iF in range(3): - k=ket - for ax,ii in zip(range(6),(iA,iB,iC,iD,iE,iF)): - k=apply_leg(k,ax,paulis[ii]) - c[iA,iB,iC,iD,iE,iF]=np.vdot(bra,k) - return c -T = corr_tensor(Qt,Qt).real -M = T.reshape(27,27) # cut ABC|DEF -print("nuclear norm of raw M (cut ABC|DEF):", np.linalg.svd(M,compute_uv=False).sum()) - -# --- exact Casimir (from before) for k=3 legs --- -def J_component(a): - eps = np.zeros((3,3,3)) - eps[0,1,2]=eps[1,2,0]=eps[2,0,1]=1 - eps[0,2,1]=eps[2,1,0]=eps[1,0,2]=-1 - Mm = np.zeros((3,3), dtype=complex) - for b in range(3): - for c in range(3): - Mm[b,c] = -1j*eps[a,b,c] - return Mm -Jx,Jy,Jz = J_component(0),J_component(1),J_component(2) -def total_J2(k): - dim=3**k - comps=[Jx,Jy,Jz] - Jtot=[np.zeros((dim,dim),dtype=complex) for _ in range(3)] - for leg in range(k): - for a in range(3): - mats=[np.eye(3,dtype=complex)]*k - mats[leg]=comps[a] - Mm=mats[0] - for mm in mats[1:]: Mm=np.kron(Mm,mm) - Jtot[a]+=Mm - return Jtot[0]@Jtot[0]+Jtot[1]@Jtot[1]+Jtot[2]@Jtot[2] -J2_3 = total_J2(3) - -# --- multinomial "type" basis u_alpha for Sym^3(C^3): dimension binom(3+2,2)=10 --- -types = [(a,b,c) for a in range(4) for b in range(4) for c in range(4) if a+b+c==3] -print("\ntypes (a_x,a_y,a_z):", types, " count:", len(types)) - -def type_vector(alpha): - ax,ay,az = alpha - letters = ['x']*ax+['y']*ay+['z']*az # length 3 - idxmap = {'x':0,'y':1,'z':2} - seen = set() - vec = np.zeros(27, dtype=complex) - count = 0 - for perm in set(permutations(letters)): - idx = tuple(idxmap[l] for l in perm) - flat = idx[0]*9+idx[1]*3+idx[2] - vec[flat] = 1.0 - count += 1 - vec /= np.linalg.norm(vec) - return vec - -U = np.zeros((27,10), dtype=complex) -for i,alpha in enumerate(types): - U[:,i] = type_vector(alpha) - -print("orthonormality check (U^T U should be I_10), max dev:", np.abs(U.conj().T@U - np.eye(10)).max()) - -# --- restrict Casimir to the 10-dim symmetric subspace --- -J2_sym = U.conj().T @ J2_3 @ U -evals_sym = np.linalg.eigvalsh(J2_sym) -print("\nEigenvalues of J^2 restricted to Sym^3(C^3) (10-dim):") -print(np.round(np.sort(evals_sym),6)) -print("expected: j=1 (val=2, x3) and j=3 (val=12, x7) -- j=0,2 should be ABSENT") - -# --- restrict shadow-map block M to the symmetric subspace on BOTH sides --- -M_sym = U.conj().T @ M @ U # 10x10 (reduced, S_3-symmetric on both ABC and DEF) -print("\nnuclear norm of M restricted to Sym^3 x Sym^3 (10x10):", np.linalg.svd(M_sym,compute_uv=False).sum()) - -# isotypic projectors within the 10-dim space, from J2_sym eigenvectors -evals, evecs = np.linalg.eigh(J2_sym) -for jtarget, label in [(1,'j=1 (val=2)'), (3,'j=3 (val=12)')]: - target = jtarget*(jtarget+1) - mask = np.abs(evals-target)<1e-6 - print(f"{label}: multiplicity found = {mask.sum()} (expect {2*jtarget+1})") - -for j0 in (0,2): - target=j0*(j0+1) - mask=np.abs(evals-target)<1e-6 - print(f"j={j0}: multiplicity found = {mask.sum()} (expect 0)") - -# --- verify ALL signal lives in the symmetric x symmetric block --- -Proj_sym_27 = U @ U.conj().T # 27x27 projector onto Sym^3 within full space -M_outside = M - Proj_sym_27 @ M @ Proj_sym_27 -print("\nnuclear norm of M OUTSIDE the Sym^3 x Sym^3 block:", - np.linalg.svd(M_outside, compute_uv=False).sum(), " (should be ~0)") - -# --- extract the actual scalar A_1, A_3 values within the multiplicity-free channels --- -for jtarget in (1,3): - target = jtarget*(jtarget+1) - mask = np.abs(evals-target)<1e-6 - P = evecs[:,mask] @ evecs[:,mask].conj().T # 10x10 projector - block = P @ M_sym @ P - nn = np.linalg.svd(block, compute_uv=False).sum() - A_j = nn/(2*jtarget+1) - print(f"j={jtarget}: ||A_j||_* (now a genuine SCALAR, multiplicity 1) = {A_j:.6f}") - -print(f"\ncheck: 3*A_1 + 7*A_3 = {3*2.5+7*(15-3*2.5)/7 if False else ''}") diff --git a/scripts/symmetric_states/8_general_r_check.py b/scripts/symmetric_states/8_general_r_check.py deleted file mode 100644 index dab3336..0000000 --- a/scripts/symmetric_states/8_general_r_check.py +++ /dev/null @@ -1,132 +0,0 @@ -""" -General-r check of Proposition coherence-templates: for r G-fixed states -phi_1,...,phi_r and ANY density matrix rho = sum_{a,b} c_{ab} |phi_a>=0, sum=1):", np.round(evals_rho[np.abs(evals_rho)>1e-9],6)) - -# --- brute-force TRUE correlation tensor of rho --- -def corr_tensor_rho(rho): - rho6 = rho.reshape((2,)*12) # not directly useful; do it via trace instead - c=np.zeros((3,3,3,3,3,3),dtype=complex) - for iA in range(3): - for iB in range(3): - for iC in range(3): - for iD in range(3): - for iE in range(3): - for iF in range(3): - O = paulis[iA] - for ii in (iB,iC,iD,iE,iF): - O = np.kron(O, paulis[ii]) - c[iA,iB,iC,iD,iE,iF] = np.trace(rho @ O) - return c -T_true = corr_tensor_rho(rho).real - -# --- predicted via T(rho) = sum_ab c_ab T_ab --- -T_pred = np.zeros((3,3,3,3,3,3), dtype=complex) -for a in range(3): - for b in range(3): - T_pred += c[a,b] * T[(a,b)] -T_pred = T_pred.real - -err = np.abs(T_true - T_pred).max() -print(f"\nmax|T_true - T_pred| (full 6-index tensor, r=3, genuinely mixed rho): {err:.2e}") - -# --- verify at BOTH cuts via simple reshape, no new contraction --- -M1_true, M1_pred = T_true.reshape(27,27), T_pred.reshape(27,27) -M2_true, M2_pred = T_true.reshape(9,81), T_pred.reshape(9,81) -print(f"cut ABC|DEF: max matrix error = {np.abs(M1_true-M1_pred).max():.2e}, " - f"||M||_* true={np.linalg.svd(M1_true,compute_uv=False).sum():.4f} " - f"pred={np.linalg.svd(M1_pred,compute_uv=False).sum():.4f}") -print(f"cut AB|CDEF: max matrix error = {np.abs(M2_true-M2_pred).max():.2e}, " - f"||M||_* true={np.linalg.svd(M2_true,compute_uv=False).sum():.4f} " - f"pred={np.linalg.svd(M2_pred,compute_uv=False).sum():.4f}") diff --git a/scripts/symmetric_states/README.md b/scripts/symmetric_states/README.md deleted file mode 100644 index 475c6a7..0000000 --- a/scripts/symmetric_states/README.md +++ /dev/null @@ -1,118 +0,0 @@ -# Shadow maps / symmetric states — numerical scripts - -Ausführungsreihenfolge (jedes Skript liest die .npy/.npz-Dateien des vorigen): - -## 1. `1_recoupling_check.py` -Baut die zwei Basiszustände (6 Qubits, Singulett-Netzwerke mit den -Paarungen (A,D)(B,E)(C,F) bzw. (A,E)(B,F)(C,D)) und deren volle -Korrelationstensoren T1, T2 sowie den Kohärenz-Kreuzterm C12. -Verifiziert per Brute-Force-Quantensimulation (unabhängig, für mehrere -Werte von alpha), dass für JEDE kohärente Überlagerung - |Xi(alpha)> = (cos(alpha) psi1 + sin(alpha) psi2)/norm -der volle Korrelationstensor exakt - T(Xi) = [cos^2(a) T1 + sin^2(a) T2 + cos(a)sin(a) C12] / N2 -ist -- UND dass diese drei festen Tensoren (unabhängig von alpha UND -unabhängig vom gewählten Schnitt!) per einfachem .reshape() sowohl den -Schnitt ABC|DEF (27x27) als auch AB|CDEF (9x81) liefern, exakt -übereinstimmend mit unabhängiger Brute-Force-Simulation für jeden Schnitt. -Output: T1.npy, T2.npy, C12.npy - -## 2. `2_exact_casimir_projectors.py` -Baut die exakten SO(3)-Spin-1-Generatoren J_x,J_y,J_z symbolisch mit -sympy (Levi-Civita-Definition), verifiziert die so(3)-Kommutatorrelation -und J^2=2*I_3 symbolisch exakt. Konstruiert dann den totalen -Casimir-Operator J^2_total auf (R^3)^{⊗k} für k=2,3,4 und diagonalisiert -ihn (numpy, Hermitesch, maschinengenau). Die Eigenräume zu Eigenwert -j(j+1) SIND per Definition die Isotypen-Projektoren -- exakt, ohne -Monte-Carlo-Integration über SO(3) wie in einer früheren Version. -Output: projectors_exact.npz - -## 3. `3_apply_exact_projectors.py` -Wendet die exakten Projektoren auf T1, T2, C12 an (für beliebiges alpha, -beliebigen Schnitt) und berechnet ||A_j||_* pro Drehimpulssektor j, -für zwei Beispielzustände und beide Schnitte (ABC|DEF und AB|CDEF). -Bestätigt exakte Additivität sum_j (2j+1)||A_j||_* = ||M||_*. - -## Kontext -Diese Skripte gehören zur Diskussion der Frage, wie die bigraduierte -Shadow Map M_S(rho) sich unter globaler kollektiver SO(3)-Symmetrie in -Drehimpuls-Isotypen zerlegt (Erweiterung von symmetric_shadow_maps_formal.tex -/ shadow_maps_symmetric_states.tex um die Rotationssymmetrie-Seite neben -der bereits behandelten S_m-Permutationssymmetrie), und wie sich diese -Zerlegung zwischen verschiedenen Schnitten desselben global-invarianten -Zustands umrechnen lässt (siehe Skript 1: EIN Tripel (T1,T2,C12) liefert -JEDEN Schnitt per reshape, ohne erneute Kontraktion über den vollen -Hilbertraum). - -## 4. `4_spherical_basis.py` -Baut eine Condon-Shortley-konsistente sphärische Basis {|1,-1>,|1,0>,|1,+1>} -für ein einzelnes Spin-1-Bein über Leiteroperatoren (nicht aus einer -memorierten Formel zitiert), ausgehend von den exakten Cartesischen -Generatoren. Validiert Kommutatoren, Normierung, Jz-Eigenwerte. - -## 5. `5_six_j_recoupling.py` -Baut die gekoppelten Basen |p,j,m>_ABC (Baum (AB)C), |y,j,m>_DEF (Baum -(DE)F) und |y,j,p,m>_CDEF (Baum (C,(DE)F)) via sympy-Clebsch-Gordan- -Koeffizienten. Extrahiert die reduzierten Matrixelemente A_j^(1)[p,y] -(Schnitt ABC|DEF) und A_p^(2)[y,j] (Schnitt AB|CDEF) für zwei Zustände -und findet empirisch (numerisch bis auf 1e-6, an 15 unabhaengigen -Datenpunkten): - A_p^(2)[y,j] = -sqrt((2j+1)/(2p+1)) * A_j^(1)[p,y] (unabhaengig von y!) -Das ist die 6j-Rekopplungsformel zwischen den A_j-Bloecken zweier -verschiedener Schnitte desselben invarianten Tensors -- numerisch -bewiesen, aber NICHT sauber gegen eine Standard-Lehrbuch-6j-Formel -identifiziert (siehe verify_6j.py / search_6j.py Versuche, beide mit -Konventions-Mismatch). Das ist die offene Baustelle. - -## 6. `6_six_j_recoupling_proof.py` (SUPERSEDES the earlier `5_six_j_recoupling.py`) -Vollstaendiger, verifizierter Beweis der Rekopplungsformel zwischen den -reduzierten Bloecken A_j^(1) (Schnitt ABC|DEF) und A_p^(2) (Schnitt -AB|CDEF) desselben invarianten Tensors: - A_p^(2)[y,j] = -sqrt((2j+1)/(2p+1)) * A_j^(1)[p,y] (y-unabhaengig!) -Kernschritte (jeder einzeln verifiziert): - (1) Schur-Lemma KORREKT auf die bilineare (nicht sesquilineare) Paarung - angewandt -- die Transponierte einer Wigner-D-Matrix haengt ueber die - Metrik C_j (nicht D selbst) mit der Inversen zusammen; das war der - Fehler im ersten Versuch. - (2) Exakte Konjugationsphase fuer CG-gekoppelte Multipletts: - conj(v_{J,m}) = (-1)^(J+n_leg) * (-1)^m * v_{J,-m} - (n_leg = Anzahl der elementaren Spin-1-Beine im Baum), verifiziert - fuer n_leg=3 und n_leg=4. - (3) Eine endliche CG-Summe Xi(p,j,m'), exakt symbolisch (sympy) zu - sqrt((2j+1)/(2p+1)) ausgewertet, m'-unabhaengig, fuer alle p,j<=3. - (4) End-to-End-Kreuzcheck gegen Brute-Force-Quantensimulation: Fehler - 2.2e-16 (Maschinengenauigkeit). -Offen (siehe Kommentare im Skript und rem:six-j-scope im .tex): die -allgemeine (nicht nur p,j<=3) geschlossene Form von Xi als zitierfaehiges -Standard-6j-Symbol wurde nicht identifiziert (zwei Versuche dazu blieben -erfolglos, siehe search_6j.py-Fragmente); ebenso ist Gl. (2) nur verifiziert, -nicht fuer allgemeines n_leg induktiv hergeleitet. - -## 7. `7_combined_sm_so3_collapse.py` -Kombiniert S_m-Permutationssymmetrie mit voller kollektiver SO(3)-Symmetrie -an einem konkreten 6-Qubit-Beispiel: |Q> = kanonische Invariante zweier -gekoppelter Spin-3/2-Dicke-Multipletts auf ABC und DEF (Gl. -eq:dicke-network-state im .tex). Verifiziert: - - |Q> ist exakt kollektiv-rotationsinvariant (||=1 exakt). - - Innerhalb des 10-dim S_3-symmetrischen Unterraums (Typ-Basis u_alpha, - Sym^3(C^3)) zeigt der Casimir NUR j=1 (x3) und j=3 (x7) -- j=0,2 - komplett abwesend, multiplizitätsfrei wie klassisch vorhergesagt. - - Die gesamte Kernnorm (15.0) lebt exakt im doppelt-symmetrischen - Sektor (Norm ausserhalb: 7e-15). - - Konkrete Skalarwerte: A_1=1/3, A_3=2, mit 3*A_1+7*A_3=15 exakt. -Ist jetzt Proposition harmonic-decomposition + Example dicke-network im -.tex (Abschnitt sec:sm-so3-combination). - -## 8. `8_general_r_check.py` -Schliesst die letzte offene TODO im Abschnitt: verallgemeinert die -Cut-unabhaengige Template-Aussage (Proposition coherence-templates) von -r=2 auf r=3, mit einem ECHT GEMISCHTEN (volle Rang-3, nicht reine -Ueberlagerung) Zustand. Korrigiert nebenbei einen Zaehlfehler im -urspruenglichen TODO-Kommentar: die Anzahl unabhaengiger reeller Tensoren -ist r^2 (= reelle Dimension hermitescher r x r Matrizen), nicht r(r+1)/2. -Drei verschiedene Perfect-Matchings von 6 Qubits als Basis-Zustaende, -Gram-Matrix-Konditionszahl 2 (linear unabhaengig), Haar-zufaellige -hermitesche PSD-Koeffizientenmatrix voller Rang. Ergebnis: Fehler 1.1e-16 -zwischen Brute-Force- und Template-basierter Korrelationstensor-Berechnung, -an BEIDEN Schnitten gleichzeitig, ohne erneute Simulation. -Ist jetzt Corollary real-tensor-count + Example general-r-three im .tex. \ No newline at end of file