jc/pillar-7-3d: EWA-sandwich on 3×3 SPD covariances (Smith 1961)#403
Conversation
Sibling of the 2D EWA-sandwich probe (Pillar 6 in module numbering; line 9 of lib.rs comment). 3D analogue certifies the same Σ-push- forward claim (PSD preservation + log-norm concentration via sandwich M·Σ·Mᵀ) for the 3×3 SPD covariances consumed by ndarray::hpc::splat3d in the J·W·Σ·Wᵀ·Jᵀ EWA projection. - Spd3 self-contained in f64 (zero dep on ndarray; matches the Pillar 6 Spd2 self-containment pattern) - Smith 1961 closed-form eigendecomp; eigenvector recovery via row-pair cross product + Gram-Schmidt fallback - 1000 paths × 10 hops, σ_step=0.2, joint PASS gate: PSD rate ≥ 0.999 AND CV tightness ≤ 1.75 (3D CV formula: √(2/n)·√(1+3σ²n)) - Registered as new pillar after EWA-Sandwich (2D) in run_all_pillars https://claude.ai/code/session_017GFLBnDy23AWBqvkbHHC41
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 70866b69ec
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let vecs = [ | ||
| eigvec_for(self, lam1), | ||
| eigvec_for(self, lam2), | ||
| eigvec_for(self, lam3), | ||
| ]; |
There was a problem hiding this comment.
Handle repeated 3D eigenvalues with an orthonormal basis
When a covariance has a repeated eigenvalue but is not diagonal (for example an axisymmetric 3DGS splat with s = [2, 2, 1] and a nontrivial quaternion), A - λI is rank one and all row-pair cross products for the repeated λ are zero, so eigvec_for falls back to the same arbitrary vector for both equal eigenvalues. These duplicate, non-orthogonal vectors are then used by sqrt() and log_spd() for spectral reconstruction, producing a matrix that is not the square root/log of the input; the new 3D sandwich certification can therefore report incorrect results for common axisymmetric covariances even though the diagonal fast-path tests pass.
Useful? React with 👍 / 👎.
…isymmetric Σ User-reported bug against the merged Pillar-7 probe (PR #403): > When a covariance has a repeated eigenvalue but is not diagonal (for > example an axisymmetric 3DGS splat with s = [2, 2, 1] and a nontrivial > quaternion), A - λI is rank one and all row-pair cross products for the > repeated λ are zero, so eigvec_for falls back to the same arbitrary > vector for both equal eigenvalues. These duplicate, non-orthogonal > vectors are then used by sqrt() and log_spd() for spectral > reconstruction, producing a matrix that is not the square root/log of > the input; the new 3D sandwich certification can therefore report > incorrect results for common axisymmetric covariances even though the > diagonal fast-path tests pass. ## Root cause `Spd3::eig` called `eigvec_for` three times independently — one per eigenvalue. For repeated eigenvalues (λ₁ = λ₂), both calls hit the same matrix `A − λ·I`, picked the same largest cross-product among row pairs, and returned the SAME unit vector. V was rank-deficient and `spectral_reconstruct(sqrt λ, V)` was NOT the square root of Σ. The diagonal fast-path branch (p1 < eps_diag) bypassed eigvec_for entirely and returned the canonical basis — so axis-aligned tests passed even though the rotated-axisymmetric case was broken. The same bug existed in ndarray's `splat3d::spd3::recover_eigvecs` in the initial PR 1 commit; it was fixed there during the PP-13 audit loop (ndarray commit 08f90ff) with the same duplicate-detection pass this commit applies to the jc probe. ## Fix After the three independent `eigvec_for` recoveries: 1. Detect column pairs with |cos θ| > 0.99 (≈ 8° tolerance, well above f64 roundoff). Demote the later column. 2. For each demoted column, fill via `gram_schmidt_complement_3d` against the basis built from the remaining filled eigenvectors — any orthogonal completion spans the degenerate eigenspace equally well, so `Σ = V · diag(λ) · Vᵀ` is invariant. 3. Final modified-Gram-Schmidt pass via `orthonormalize_columns` suppresses cross-orthogonality drift to ~1e-15 at f64. ## Regression tests added (4) The diagonal fast-path tests and the random-rotation `sandwich_preserves_spd` test did not exercise this code path. Four new tests target the rotated-axisymmetric class explicitly: - `rotated_axisymmetric_sqrt_squared_equals_sigma` — the user-reported property. s = [2, 2, 1] (pancake splat) under a 30° rotation about (1,1,1)/√3. sqrt(Σ)² must equal Σ. Pre-fix: ~5% error on diagonals. Post-fix: ~1e-8 (f64 epsilon for compound computation). - `rotated_axisymmetric_eigenvalues_are_correct` — eigenvalues = (4, 4, 1) regardless of rotation. Tolerance 1e-7 (acos-based Smith-1961 accumulates ~1e-8 on quat-constructed inputs). - `rotated_axisymmetric_eigvecs_orthonormal` — every column unit length AND every pair orthogonal. Pre-fix: dot(v0, v1) ≈ 1 (same vector). Post-fix: |dot| < 1e-9. - `rotated_axisymmetric_log_spd_finite_and_correct` — log_spd uses the same spectral lift; for Σ with eigenvalues (4, 4, 1), ‖log Σ‖_F² = 2·(ln 4)² ≈ 3.844. Pre-fix: log_spd corrupted by rank-deficient V. Post-fix: matches analytical value to 1e-6. ## Test count cargo test --manifest-path crates/jc/Cargo.toml --release → 64 passed (was 60: +4 regression tests, all green) ewa_sandwich_3d::tests: → 13 passed (was 9: +4 new), pillar_passes still PASS https://claude.ai/code/session_017GFLBnDy23AWBqvkbHHC41
Sibling of the 2D EWA-sandwich probe (Pillar 6 in module numbering;
line 9 of lib.rs comment). 3D analogue certifies the same Σ-push-
forward claim (PSD preservation + log-norm concentration via
sandwich M·Σ·Mᵀ) for the 3×3 SPD covariances consumed by
ndarray::hpc::splat3d in the J·W·Σ·Wᵀ·Jᵀ EWA projection.
Pillar 6 Spd2 self-containment pattern)
row-pair cross product + Gram-Schmidt fallback
AND CV tightness ≤ 1.75 (3D CV formula: √(2/n)·√(1+3σ²n))
https://claude.ai/code/session_017GFLBnDy23AWBqvkbHHC41