use super::tests::{
TestPeriodicEvaluator, periodic_basis, small_two_atom_periodic_term, trivial_k1_euclidean_term,
};
use super::*;
use ndarray::array;
#[test]
pub(crate) fn decoder_norm_guard_reseeds_collapsed_atom_to_distinct_nonzero() {
let (term0, target, rho) = small_two_atom_periodic_term();
let mut term = term0.clone();
term.atoms[1].decoder_coefficients.fill(0.0);
let norm = |a: &SaeManifoldAtom| -> f64 {
a.decoder_coefficients
.iter()
.map(|v| v * v)
.sum::<f64>()
.sqrt()
};
assert!(norm(&term.atoms[1]) < 1e-12, "atom 1 starts collapsed");
term.enforce_decoder_norm_guard(target.view(), 0, &rho, None)
.expect("decoder-norm guard must not error on a recoverable collapse");
let reseeded = term
.collapse_events()
.iter()
.any(|e| e.atom == 1 && e.action == CollapseAction::Reseeded);
assert!(
reseeded,
"collapsed atom 1 must be recorded as Reseeded; events: {:?}",
term.collapse_events()
);
let n1 = norm(&term.atoms[1]);
let n0 = norm(&term.atoms[0]);
assert!(
n0 > 0.0 && n1 > SAE_ATOM_DECODER_NORM_COLLAPSE_RATIO * n0,
"reseeded atom 1 decoder must be non-degenerate: ‖B0‖={n0:.3e} ‖B1‖={n1:.3e}"
);
let c1 = term.assignment.coords[1].as_matrix();
let (lo, hi) = c1
.iter()
.fold((f64::INFINITY, f64::NEG_INFINITY), |(lo, hi), &v| {
(lo.min(v), hi.max(v))
});
assert!(
hi - lo > 1e-6,
"reseeded atom 1 coordinates must span a non-trivial range; got [{lo}, {hi}]"
);
let b0 = &term.atoms[0].decoder_coefficients;
let b1 = &term.atoms[1].decoder_coefficients;
let dot: f64 = b0.iter().zip(b1.iter()).map(|(x, y)| x * y).sum();
let cos = dot.abs() / (n0 * n1);
assert!(
cos < 0.999,
"reseeded atom 1 decoder must be distinct from atom 0 (|cos|={cos:.4})"
);
}
#[test]
pub(crate) fn decoder_norm_guard_reseeds_all_atoms_on_total_co_collapse_k3() {
let coords0 = array![[0.05], [0.20], [0.55], [0.80], [0.35], [0.65]];
let coords1 = array![[0.15], [0.30], [0.65], [0.90], [0.45], [0.10]];
let coords2 = array![[0.25], [0.40], [0.75], [0.05], [0.60], [0.85]];
let (phi0, jet0) = periodic_basis(&coords0);
let (phi1, jet1) = periodic_basis(&coords1);
let (phi2, jet2) = periodic_basis(&coords2);
let make_atom = |name: &str, phi: Array2<f64>, jet: Array3<f64>, scale: f64| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
Array2::<f64>::from_elem((3, 3), scale),
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let atom0 = make_atom("periodic0", phi0, jet0, 1.0e-5);
let atom1 = make_atom("periodic1", phi1, jet1, 1.2e-5);
let atom2 = make_atom("periodic2", phi2, jet2, 0.8e-5);
let logits = array![
[0.7, -0.2, 0.3],
[0.1, 0.4, -0.1],
[-0.3, 0.5, 0.2],
[0.6, -0.1, 0.4],
[0.2, 0.3, -0.2],
[0.4, 0.1, 0.5]
];
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits,
vec![coords0, coords1, coords2],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
let mut term = SaeManifoldTerm::new(vec![atom0, atom1, atom2], assignment).unwrap();
let target = array![
[0.40, -0.10, 0.05],
[-0.20, 0.35, -0.15],
[0.10, 0.05, 0.30],
[0.25, -0.30, -0.05],
[-0.15, 0.20, 0.18],
[0.30, 0.12, -0.22]
];
let rho = SaeManifoldRho::new(
(-0.3_f64).exp().ln(),
0.7_f64.ln(),
vec![
array![0.9_f64.ln()],
array![1.0_f64.ln()],
array![1.1_f64.ln()],
],
);
let ev_before = term
.dictionary_reconstruction_ev(target.view(), &rho)
.expect("EV evaluates");
assert!(
ev_before < 0.28_f64,
"test precondition: dictionary must start co-collapsed; EV={ev_before:.4}"
);
term.enforce_decoder_norm_guard(target.view(), 1, &rho, None)
.expect("co-collapse guard must recover, not error");
for atom in 0..3 {
let reseeded = term
.collapse_events()
.iter()
.any(|e| e.atom == atom && e.action == CollapseAction::Reseeded);
assert!(
reseeded,
"total co-collapse must reseed ALL atoms; atom {atom} was not reseeded. events: {:?}",
term.collapse_events()
);
}
let norm = |a: &SaeManifoldAtom| -> f64 {
a.decoder_coefficients
.iter()
.map(|v| v * v)
.sum::<f64>()
.sqrt()
};
let norms: Vec<f64> = (0..3).map(|a| norm(&term.atoms[a])).collect();
for (atom, &nrm) in norms.iter().enumerate() {
assert!(
nrm > 1e-9,
"reseeded atom {atom} decoder must be non-degenerate; ‖B‖={nrm:.3e}"
);
}
for a in 0..3 {
for b in (a + 1)..3 {
let ba = &term.atoms[a].decoder_coefficients;
let bb = &term.atoms[b].decoder_coefficients;
let dot: f64 = ba.iter().zip(bb.iter()).map(|(x, y)| x * y).sum();
let cos = dot.abs() / (norms[a] * norms[b]);
assert!(
cos < 0.999,
"reseeded atoms {a},{b} decoders must be distinct (|cos|={cos:.4})"
);
}
}
let ev_after = term
.dictionary_reconstruction_ev(target.view(), &rho)
.expect("EV evaluates post-reseed");
assert!(
ev_after > ev_before,
"co-collapse reseed must improve EV; before={ev_before:.4} after={ev_after:.4}"
);
}
#[test]
pub(crate) fn co_collapse_multistart_restores_best_basin_not_last_reseed() {
let coords0 = array![[0.05], [0.20], [0.55], [0.80], [0.35], [0.65]];
let coords1 = array![[0.15], [0.30], [0.65], [0.90], [0.45], [0.10]];
let coords2 = array![[0.25], [0.40], [0.75], [0.05], [0.60], [0.85]];
let (phi0, jet0) = periodic_basis(&coords0);
let (phi1, jet1) = periodic_basis(&coords1);
let (phi2, jet2) = periodic_basis(&coords2);
let make_atom = |name: &str, phi: Array2<f64>, jet: Array3<f64>, scale: f64| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
Array2::<f64>::from_elem((3, 3), scale),
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let atom0 = make_atom("periodic0", phi0, jet0, 1.0e-5);
let atom1 = make_atom("periodic1", phi1, jet1, 1.2e-5);
let atom2 = make_atom("periodic2", phi2, jet2, 0.8e-5);
let logits = array![
[0.7, -0.2, 0.3],
[0.1, 0.4, -0.1],
[-0.3, 0.5, 0.2],
[0.6, -0.1, 0.4],
[0.2, 0.3, -0.2],
[0.4, 0.1, 0.5]
];
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits,
vec![coords0, coords1, coords2],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
let mut term = SaeManifoldTerm::new(vec![atom0, atom1, atom2], assignment).unwrap();
let target = array![
[0.40, -0.10, 0.05],
[-0.20, 0.35, -0.15],
[0.10, 0.05, 0.30],
[0.25, -0.30, -0.05],
[-0.15, 0.20, 0.18],
[0.30, 0.12, -0.22]
];
let rho = SaeManifoldRho::new(
(-0.3_f64).exp().ln(),
0.7_f64.ln(),
vec![
array![0.9_f64.ln()],
array![1.0_f64.ln()],
array![1.1_f64.ln()],
],
);
let mut best_seen = f64::NEG_INFINITY;
for iteration in 1..=(SAE_DICTIONARY_COCOLLAPSE_RESEED_BUDGET + 1) {
let ev_at_entry = term
.dictionary_reconstruction_ev(target.view(), &rho)
.expect("EV evaluates");
if ev_at_entry < 0.28_f64 {
best_seen = best_seen.max(ev_at_entry);
}
term.enforce_decoder_norm_guard(target.view(), iteration, &rho, None)
.expect("co-collapse guard must recover, not error");
}
let ev_final = term
.dictionary_reconstruction_ev(target.view(), &rho)
.expect("EV evaluates");
assert!(
best_seen.is_finite(),
"test precondition: at least one co-collapsed attempt must be observed"
);
assert!(
ev_final >= best_seen - 1e-9,
"multi-start must return its BEST basin, not the last reseed: \
final EV={ev_final:.6} < best seen={best_seen:.6}"
);
}
#[test]
pub(crate) fn decoder_repulsion_gate_off_when_separated_on_when_collinear() {
let coords0 = array![[0.05], [0.20], [0.55], [0.80], [0.35], [0.65]];
let coords1 = array![[0.15], [0.30], [0.65], [0.90], [0.45], [0.10]];
let (phi0, jet0) = periodic_basis(&coords0);
let (phi1, jet1) = periodic_basis(&coords1);
let make_atom = |name: &str, phi: Array2<f64>, jet: Array3<f64>, decoder: Array2<f64>| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
decoder,
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let logits = array![
[0.7, -0.2],
[0.1, 0.4],
[-0.3, 0.5],
[0.6, -0.1],
[0.2, 0.3],
[0.4, 0.1]
];
let build = |dec0: Array2<f64>, dec1: Array2<f64>| {
let atom0 = make_atom("periodic0", phi0.clone(), jet0.clone(), dec0);
let atom1 = make_atom("periodic1", phi1.clone(), jet1.clone(), dec1);
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits.clone(),
vec![coords0.clone(), coords1.clone()],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
SaeManifoldTerm::new(vec![atom0, atom1], assignment).unwrap()
};
let mut dec0 = Array2::<f64>::zeros((3, 3));
dec0[[0, 0]] = 1.0;
let mut dec1 = Array2::<f64>::zeros((3, 3));
dec1[[0, 1]] = 1.0;
let mut sep = build(dec0, dec1);
sep.refresh_decoder_repulsion_gate();
assert!(
sep.decoder_repulsion_gate.is_none(),
"orthogonal decoders must leave the repulsion gate OFF (strict no-op): {:?}",
sep.decoder_repulsion_gate
);
assert_eq!(
sep.decoder_repulsion_value(1.0),
0.0,
"orthogonal decoders must contribute zero repulsion value"
);
let mut dec0c = Array2::<f64>::zeros((3, 3));
dec0c[[0, 0]] = 1.0;
let mut dec1c = Array2::<f64>::zeros((3, 3));
dec1c[[0, 0]] = 1.0;
let mut col = build(dec0c, dec1c);
col.refresh_decoder_repulsion_gate();
let gate = col
.decoder_repulsion_gate
.as_ref()
.expect("collinear decoders must ENGAGE the repulsion gate");
assert!(
gate.iter().any(|&(j, k, w)| j == 0 && k == 1 && w > 0.0),
"engaged gate must carry a positive weight on pair (0,1): {gate:?}"
);
assert!(
col.decoder_repulsion_value(1.0) > 0.0,
"collinear decoders must contribute positive repulsion value"
);
}
#[test]
pub(crate) fn separation_barrier_is_collapse_prevention_not_bandaid_1522() {
let coords0 = array![[0.05], [0.20], [0.55], [0.80], [0.35], [0.65]];
let coords1 = array![[0.15], [0.30], [0.65], [0.90], [0.45], [0.10]];
let (phi0, jet0) = periodic_basis(&coords0);
let (phi1, jet1) = periodic_basis(&coords1);
let logits = array![
[0.7, -0.2],
[0.1, 0.4],
[-0.3, 0.5],
[0.6, -0.1],
[0.2, 0.3],
[0.4, 0.1]
];
let build = |dec0: Array2<f64>, dec1: Array2<f64>| {
let make = |name: &str, phi: Array2<f64>, jet: Array3<f64>, decoder: Array2<f64>| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
decoder,
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let atom0 = make("periodic0", phi0.clone(), jet0.clone(), dec0);
let atom1 = make("periodic1", phi1.clone(), jet1.clone(), dec1);
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits.clone(),
vec![coords0.clone(), coords1.clone()],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
SaeManifoldTerm::new(vec![atom0, atom1], assignment).unwrap()
};
let row_decoder = |r: [f64; 3]| {
let mut d = Array2::<f64>::zeros((3, 3));
d[[0, 0]] = r[0];
d[[0, 1]] = r[1];
d[[0, 2]] = r[2];
d
};
let alignment_c2 = |b0: &Array2<f64>, b1: &Array2<f64>| -> f64 {
let (m0, p) = (b0.nrows(), b0.ncols());
let m1 = b1.nrows();
let mut cross = 0.0_f64;
for a in 0..m0 {
for b in 0..m1 {
let mut c = 0.0_f64;
for o in 0..p {
c += b0[[a, o]] * b1[[b, o]];
}
cross += c * c;
}
}
let n0: f64 = b0.iter().map(|v| v * v).sum();
let n1: f64 = b1.iter().map(|v| v * v).sum();
cross / (n0 * n1)
};
let dec0 = row_decoder([1.0, 0.0, 0.0]);
let dec1 = row_decoder([0.894_427_191, 0.447_213_595, 0.0]);
let c2_before = alignment_c2(&dec0, &dec1);
assert!(
(c2_before - 0.8).abs() < 1e-6,
"fixture precondition: aligned decoders must start at c² ≈ 0.8, got {c2_before}"
);
let term = build(dec0.clone(), dec1.clone());
let (value_off, grad_off) = term.separation_barrier_value_and_grad_for_test(0.0);
assert_eq!(
value_off, 0.0,
"barrier OFF must contribute zero value (the no-prevention arm)"
);
assert!(
grad_off.iter().all(|&g| g == 0.0),
"barrier OFF must leave the gradient identically zero — aligned atoms feel \
NO separating force, so without prevention they stay collapsed"
);
let (value_on, grad_on) = term.separation_barrier_value_and_grad_for_test(1.0);
assert!(
value_on > 0.0,
"barrier ON must penalize the aligned, co-firing pair (value {value_on} ≤ 0)"
);
assert!(
grad_on.iter().any(|&g| g != 0.0),
"barrier ON must produce a non-zero separating gradient on the aligned pair"
);
let eta = 1.0e-3;
let offsets = term.beta_offsets();
let p = term.output_dim();
let stepped = |atom: usize, base: &Array2<f64>| -> Array2<f64> {
let mut out = base.clone();
let off = offsets[atom];
for a in 0..out.nrows() {
for o in 0..p {
out[[a, o]] -= eta * grad_on[off + a * p + o];
}
}
out
};
let dec0_stepped = stepped(0, &dec0);
let dec1_stepped = stepped(1, &dec1);
let c2_after = alignment_c2(&dec0_stepped, &dec1_stepped);
assert!(
c2_after < c2_before - 1e-9,
"a descent step along the barrier gradient must SEPARATE the atoms \
(c² must fall): before={c2_before:.6} after={c2_after:.6}"
);
let term_less = build(dec0.clone(), row_decoder([0.6, 0.8, 0.0]));
let term_more = build(dec0.clone(), row_decoder([0.989_949_49, 0.141_421_36, 0.0]));
let value_less = term_less.separation_barrier_value(1.0);
let value_more = term_more.separation_barrier_value(1.0);
assert!(
value_more > value_on && value_on > value_less,
"barrier value must grow with alignment toward the collapse boundary: \
less(c²=.36)={value_less:.6} < base(c²=.8)={value_on:.6} < more(c²=.98)={value_more:.6}"
);
let term_ortho = build(row_decoder([1.0, 0.0, 0.0]), row_decoder([0.0, 1.0, 0.0]));
let (value_ortho, grad_ortho) = term_ortho.separation_barrier_value_and_grad_for_test(1.0);
assert!(
grad_ortho.iter().all(|&g| g == 0.0),
"orthogonal (well-separated) decoders must leave the separating gradient \
identically zero (strict no-op force) — healthy fits steer unchanged: {grad_ortho:?}"
);
assert!(
value_ortho.abs() < 1.0e-4,
"orthogonal decoders' barrier value must be negligible (only the ε-softening \
constant), got {value_ortho}"
);
}
fn aligned_two_atom_term_with_c2(c2: f64) -> SaeManifoldTerm {
let coords0 = array![[0.05], [0.20], [0.55], [0.80], [0.35], [0.65]];
let coords1 = array![[0.15], [0.30], [0.65], [0.90], [0.45], [0.10]];
let (phi0, jet0) = periodic_basis(&coords0);
let (phi1, jet1) = periodic_basis(&coords1);
let logits = array![
[0.7, -0.2],
[0.1, 0.4],
[-0.3, 0.5],
[0.6, -0.1],
[0.2, 0.3],
[0.4, 0.1]
];
let cos = c2.sqrt();
let sin = (1.0 - c2).max(0.0).sqrt();
let row_decoder = |r: [f64; 3]| {
let mut d = Array2::<f64>::zeros((3, 3));
d[[0, 0]] = r[0];
d[[0, 1]] = r[1];
d[[0, 2]] = r[2];
d
};
let make = |name: &str, phi: Array2<f64>, jet: Array3<f64>, decoder: Array2<f64>| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
decoder,
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let atom0 = make("periodic0", phi0, jet0, row_decoder([1.0, 0.0, 0.0]));
let atom1 = make("periodic1", phi1, jet1, row_decoder([cos, sin, 0.0]));
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits,
vec![coords0, coords1],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
SaeManifoldTerm::new(vec![atom0, atom1], assignment).unwrap()
}
#[test]
fn separation_barrier_force_vanishes_smoothly_as_atoms_separate() {
let grad_norm = |c2: f64| -> (f64, f64) {
let term = aligned_two_atom_term_with_c2(c2);
let (v, g) = term.separation_barrier_value_and_grad_for_test(1.0);
(v, g.iter().map(|x| x * x).sum::<f64>().sqrt())
};
let (v_lo, f_lo) = grad_norm(0.02);
let (v_mid, f_mid) = grad_norm(0.36);
let (v_hi, f_hi) = grad_norm(0.8);
assert!(
v_lo < v_mid && v_mid < v_hi,
"barrier value must grow with alignment: lo(c²=.02)={v_lo:.3e} < mid(.36)={v_mid:.3e} < hi(.8)={v_hi:.3e}"
);
assert!(
f_hi > 0.0,
"the near-collapse pair must feel a separating force, got {f_hi}"
);
assert!(
f_lo < f_mid && f_mid < f_hi,
"separating force must grow with alignment: lo={f_lo:.3e} < mid={f_mid:.3e} < hi={f_hi:.3e}"
);
assert!(
f_lo < 0.2 * f_hi,
"the separating force must become negligible as atoms separate (O(o) soft \
auto-gate): near-orthogonal force {f_lo:.3e} must be ≪ near-collapse force {f_hi:.3e}"
);
}
#[test]
fn separation_barrier_gated_gradient_matches_fd_1625() {
let c2 = 0.7_f64;
let cos = c2.sqrt();
let sin = (1.0 - c2).sqrt();
let build = |d1: [f64; 3]| -> SaeManifoldTerm {
let mut t = aligned_two_atom_term_with_c2(c2);
t.atoms[1].decoder_coefficients[[0, 0]] = d1[0];
t.atoms[1].decoder_coefficients[[0, 1]] = d1[1];
t.atoms[1].decoder_coefficients[[0, 2]] = d1[2];
t
};
let base = build([cos, sin, 0.0]);
let (_v, grad) = base.separation_barrier_value_and_grad_for_test(1.0);
let offsets = base.beta_offsets();
let p = base.output_dim();
let h = 1.0e-7;
let mut max_rel = 0.0_f64;
for o in 0..3 {
let mut plus = [cos, sin, 0.0];
let mut minus = [cos, sin, 0.0];
plus[o] += h;
minus[o] -= h;
let vp = build(plus).separation_barrier_value(1.0);
let vm = build(minus).separation_barrier_value(1.0);
let fd = (vp - vm) / (2.0 * h);
let analytic = grad[offsets[1] + 0 * p + o];
let rel = (fd - analytic).abs() / (1.0 + fd.abs().max(analytic.abs()));
max_rel = max_rel.max(rel);
}
assert!(
max_rel < 1.0e-5,
"gated barrier analytic ∂P/∂B must match FD of the value (incl. the smoothstep \
w'(c²) term) on the ramp: max rel err {max_rel:.3e}"
);
}
#[test]
fn separation_barrier_value_frozen_coactivation_invariant_to_logit_moves_1625() {
let mut term = aligned_two_atom_term_with_c2(0.8);
let target = Array2::<f64>::zeros((term.n_obs(), term.output_dim()));
let rho = SaeManifoldRho::new(
-2.0,
-2.0,
vec![Array1::from_vec(vec![-2.0]), Array1::from_vec(vec![-2.0])],
);
term.assemble_arrow_schur(target.view(), &rho, None)
.expect("assemble freezes the barrier coactivation");
let value_before = term.separation_barrier_value(1.0);
assert!(value_before > 0.0, "aligned pair must have a live barrier");
for v in term.assignment.logits.iter_mut() {
*v += 0.37;
}
let value_after = term.separation_barrier_value(1.0);
assert!(
(value_after - value_before).abs() <= 1.0e-12 * (1.0 + value_before.abs()),
"frozen coactivation must hold the barrier value across logit moves: \
before={value_before:.12e} after={value_after:.12e}"
);
}
#[test]
fn barrier_norm_floor_is_data_derived_scale_invariant_1610() {
let norm_sq = [1.0_f64, 4.0, 0.25];
let floor = SaeManifoldTerm::barrier_norm_floor_sq(&norm_sq);
let rel = SAE_BARRIER_ACTIVE_NORM_REL_FLOOR;
assert!(
(floor - rel * rel * 4.0).abs() <= 1e-30,
"floor² must be rel²·max‖B_k‖²_F = {}, got {floor}",
rel * rel * 4.0
);
let unit = SaeManifoldTerm::barrier_norm_floor_sq(&[1.0]);
assert!(
(unit - 1.0e-12).abs() <= 1e-27,
"at unit decoder scale the floor must equal the historical 1e-6² = 1e-12, got {unit}"
);
for &s2 in &[1.0e-12_f64, 1.0e6, 9.0] {
let scaled: Vec<f64> = norm_sq.iter().map(|v| v * s2).collect();
let f_scaled = SaeManifoldTerm::barrier_norm_floor_sq(&scaled);
assert!(
(f_scaled - s2 * floor).abs() <= s2 * floor * 1e-9 + 1e-30,
"floor² must scale by s² under a global ‖B‖² rescaling: s²={s2}, \
expected {}, got {f_scaled}",
s2 * floor
);
}
assert_eq!(SaeManifoldTerm::barrier_norm_floor_sq(&[0.0, 0.0]), 0.0);
}
#[test]
fn separation_barrier_collapse_prevention_is_scale_invariant_1610() {
let coords0 = array![[0.05], [0.20], [0.55], [0.80], [0.35], [0.65]];
let coords1 = array![[0.15], [0.30], [0.65], [0.90], [0.45], [0.10]];
let (phi0, jet0) = periodic_basis(&coords0);
let (phi1, jet1) = periodic_basis(&coords1);
let logits = array![
[0.7, -0.2],
[0.1, 0.4],
[-0.3, 0.5],
[0.6, -0.1],
[0.2, 0.3],
[0.4, 0.1]
];
let row_decoder = |r: [f64; 3]| {
let mut d = Array2::<f64>::zeros((3, 3));
d[[0, 0]] = r[0];
d[[0, 1]] = r[1];
d[[0, 2]] = r[2];
d
};
let dir0 = [1.0, 0.0, 0.0];
let dir1 = [0.894_427_191, 0.447_213_595, 0.0];
let build_at_scale = |s: f64| {
let scale_row = |r: [f64; 3]| [r[0] * s, r[1] * s, r[2] * s];
let make = |name: &str, phi: Array2<f64>, jet: Array3<f64>, decoder: Array2<f64>| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
decoder,
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let atom0 = make(
"p0",
phi0.clone(),
jet0.clone(),
row_decoder(scale_row(dir0)),
);
let atom1 = make(
"p1",
phi1.clone(),
jet1.clone(),
row_decoder(scale_row(dir1)),
);
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits.clone(),
vec![coords0.clone(), coords1.clone()],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
SaeManifoldTerm::new(vec![atom0, atom1], assignment).unwrap()
};
let value_unit = build_at_scale(1.0).separation_barrier_value(1.0);
assert!(
value_unit > 0.0,
"barrier must engage on the aligned, co-firing pair at unit scale, got {value_unit}"
);
let value_tiny = build_at_scale(1.0e-7).separation_barrier_value(1.0);
assert!(
value_tiny > 0.0,
"data-derived floor must keep collapse prevention ENGAGED at a tiny decoder \
scale where the old absolute 1e-6 floor disabled it, got {value_tiny}"
);
assert!(
(value_tiny - value_unit).abs() <= value_unit.abs() * 1e-9,
"the barrier value is scale-free (shape + coactivation only): unit={value_unit} \
must equal tiny-scale={value_tiny}"
);
let value_huge = build_at_scale(1.0e6).separation_barrier_value(1.0);
assert!(
(value_huge - value_unit).abs() <= value_unit.abs() * 1e-9,
"barrier value must be invariant at large decoder scale too: unit={value_unit} \
huge={value_huge}"
);
}
#[test]
pub(crate) fn decoder_repulsion_strength_is_derived_and_scale_invariant_1610() {
let coords0 = array![[0.05], [0.20], [0.55], [0.80], [0.35], [0.65]];
let coords1 = array![[0.15], [0.30], [0.65], [0.90], [0.45], [0.10]];
let (phi0, jet0) = periodic_basis(&coords0);
let (phi1, jet1) = periodic_basis(&coords1);
let logits = array![
[0.7, -0.2],
[0.1, 0.4],
[-0.3, 0.5],
[0.6, -0.1],
[0.2, 0.3],
[0.4, 0.1]
];
let build_at_scale = |s: f64| {
let mut dec0 = Array2::<f64>::zeros((3, 3));
dec0[[0, 0]] = s;
let mut dec1 = Array2::<f64>::zeros((3, 3));
dec1[[0, 0]] = 0.9 * s;
dec1[[0, 1]] = (1.0 - 0.9 * 0.9_f64).sqrt() * s; let make = |name: &str, phi: Array2<f64>, jet: Array3<f64>, decoder: Array2<f64>| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
decoder,
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let atom0 = make("rep0", phi0.clone(), jet0.clone(), dec0);
let atom1 = make("rep1", phi1.clone(), jet1.clone(), dec1);
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits.clone(),
vec![coords0.clone(), coords1.clone()],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
let mut term = SaeManifoldTerm::new(vec![atom0, atom1], assignment).unwrap();
term.refresh_decoder_repulsion_gate();
term
};
let unit_term = build_at_scale(1.0);
let expected = SAE_DECODER_REPULSION_BARRIER_RATIO * unit_term.separation_barrier_strength();
assert_eq!(
unit_term.decoder_repulsion_strength(),
expected,
"repulsion strength must be the derived fraction {SAE_DECODER_REPULSION_BARRIER_RATIO} \
of the evidence-derived separation-barrier strength {}, got {}",
unit_term.separation_barrier_strength(),
unit_term.decoder_repulsion_strength(),
);
let mu_c = unit_term.separation_barrier_strength();
assert!(
mu_c > 0.0 && mu_c.is_finite(),
"μ_C must be a positive finite evidence-derived strength for a co-active \
pair, got {mu_c}"
);
let mu_c_tiny = build_at_scale(1.0e-7).separation_barrier_strength();
let mu_c_huge = build_at_scale(1.0e6).separation_barrier_strength();
let rel_mu = |a: f64, b: f64| (a - b).abs() / b.abs().max(f64::MIN_POSITIVE);
assert!(
rel_mu(mu_c_tiny, mu_c) <= 1e-9 && rel_mu(mu_c_huge, mu_c) <= 1e-9,
"evidence-derived μ_C must be decoder-scale invariant: unit={mu_c} \
tiny={mu_c_tiny} huge={mu_c_huge}"
);
let value_unit = build_at_scale(1.0).decoder_repulsion_value(1.0);
assert!(
value_unit > 0.0 && value_unit.is_finite(),
"near-collinear gate-engaged pair must yield a positive finite repulsion \
value at unit scale, got {value_unit}"
);
let value_tiny = build_at_scale(1.0e-7).decoder_repulsion_value(1.0);
let value_huge = build_at_scale(1.0e6).decoder_repulsion_value(1.0);
let rel = |a: f64, b: f64| (a - b).abs() / b.abs().max(f64::MIN_POSITIVE);
assert!(
rel(value_tiny, value_unit) <= 1e-9,
"repulsion value must be scale-invariant: unit={value_unit} tiny={value_tiny} \
(old absolute constant scaled this by s⁴)"
);
assert!(
rel(value_huge, value_unit) <= 1e-9,
"repulsion value must be scale-invariant: unit={value_unit} huge={value_huge} \
(old absolute constant scaled this by s⁴)"
);
}
#[test]
pub(crate) fn barrier_strength_tracks_data_fit_inseparability_1610() {
let coords = array![[0.05], [0.20], [0.55], [0.80], [0.35], [0.65]];
let (phi, jet) = periodic_basis(&coords);
let make = |name: &str, decoder: Array2<f64>| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi.clone(),
jet.clone(),
decoder,
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let mut dec0 = Array2::<f64>::zeros((3, 3));
dec0[[0, 0]] = 1.0;
let mut dec1 = Array2::<f64>::zeros((3, 3));
dec1[[0, 1]] = 1.0;
let logits = array![
[0.7, -0.2],
[0.1, 0.4],
[-0.3, 0.5],
[0.6, -0.1],
[0.2, 0.3],
[0.4, 0.1]
];
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits,
vec![coords.clone(), coords.clone()],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
let term = SaeManifoldTerm::new(vec![make("a0", dec0), make("a1", dec1)], assignment).unwrap();
let gates_disjoint = array![
[1.0, 0.0],
[1.0, 0.0],
[1.0, 0.0],
[0.0, 1.0],
[0.0, 1.0],
[0.0, 1.0]
];
let gamma_sep = term.design_inseparability_with_gates(gates_disjoint.view(), 0, 1);
let mu_sep = term.barrier_pair_strength_with_gates(gates_disjoint.view(), 0, 1);
assert!(
gamma_sep <= 1e-9,
"disjoint routing on any design ⇒ data-fit separable ⇒ γ ≈ 0, got {gamma_sep}"
);
assert!(
mu_sep <= 1e-6,
"a data-fit-separable pair owes ~no separation barrier, got μ = {mu_sep}"
);
let gates_overlap = array![
[1.0, 1.0],
[1.0, 1.0],
[1.0, 1.0],
[1.0, 1.0],
[1.0, 1.0],
[1.0, 1.0]
];
let gamma_deg = term.design_inseparability_with_gates(gates_overlap.view(), 0, 1);
let mu_deg = term.barrier_pair_strength_with_gates(gates_overlap.view(), 0, 1);
assert!(
gamma_deg > 0.999,
"identical designs + identical routing ⇒ perfectly inseparable ⇒ γ → 1, got {gamma_deg}"
);
assert!(
mu_deg > mu_sep + 1.0,
"the barrier strength MUST rise as the data-fit inseparability rises: \
separable μ={mu_sep} vs degenerate μ={mu_deg}"
);
let eps = SAE_SEPARATION_BARRIER_EPS;
let expected_deg = gamma_deg / (1.0 - gamma_deg).max(eps);
assert!(
(mu_deg - expected_deg).abs() <= expected_deg.abs() * 1e-9 + 1e-12,
"μ must equal γ/max(1-γ,ε): γ={gamma_deg} expected={expected_deg} got={mu_deg}"
);
let mut big0 = Array2::<f64>::zeros((3, 3));
big0[[0, 0]] = 1.0e6;
let mut big1 = Array2::<f64>::zeros((3, 3));
big1[[0, 1]] = 1.0e6;
let assignment2 = SaeAssignment::from_blocks_with_mode_and_manifolds(
array![
[0.7, -0.2],
[0.1, 0.4],
[-0.3, 0.5],
[0.6, -0.1],
[0.2, 0.3],
[0.4, 0.1]
],
vec![coords.clone(), coords.clone()],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
let term_big =
SaeManifoldTerm::new(vec![make("a0", big0), make("a1", big1)], assignment2).unwrap();
let mu_deg_big = term_big.barrier_pair_strength_with_gates(gates_overlap.view(), 0, 1);
assert!(
(mu_deg_big - mu_deg).abs() <= mu_deg.abs() * 1e-9,
"evidence-derived μ must be decoder-scale invariant: unit={mu_deg} big={mu_deg_big}"
);
}
#[test]
pub(crate) fn co_collapse_reseed_rotation_explores_distinct_subspaces() {
let residual = array![
[3.0, 0.1, 0.0, 0.0, 0.0, 0.0],
[-3.0, -0.1, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 2.0, 0.2, 0.0, 0.0],
[0.0, 0.0, -2.0, -0.2, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 1.0, 0.3],
[0.0, 0.0, 0.0, 0.0, -1.0, -0.3],
];
let kinds = vec![
SaeAtomBasisKind::Periodic,
SaeAtomBasisKind::Periodic,
SaeAtomBasisKind::Periodic,
];
let dims = vec![1usize, 1, 1];
let seed0 = sae_pca_seed_initial_coords_with_pc_offset(residual.view(), &kinds, &dims, 0)
.expect("offset-0 seed");
let seed1 = sae_pca_seed_initial_coords_with_pc_offset(residual.view(), &kinds, &dims, 1)
.expect("offset-1 seed");
let seed2 = sae_pca_seed_initial_coords_with_pc_offset(residual.view(), &kinds, &dims, 2)
.expect("offset-2 seed");
let maxdiff = |a: &Array3<f64>, b: &Array3<f64>| -> f64 {
a.iter()
.zip(b.iter())
.map(|(x, y)| (x - y).abs())
.fold(0.0_f64, f64::max)
};
assert!(
maxdiff(&seed0, &seed1) > 1e-3,
"retry 0 vs 1 must read distinct PC pairs (max coord diff = {:.3e})",
maxdiff(&seed0, &seed1)
);
assert!(
maxdiff(&seed1, &seed2) > 1e-3,
"retry 1 vs 2 must read distinct PC pairs (max coord diff = {:.3e})",
maxdiff(&seed1, &seed2)
);
let seed_plain =
sae_pca_seed_initial_coords(residual.view(), &kinds, &dims).expect("plain seed");
assert_eq!(
seed0, seed_plain,
"offset-0 seed must equal the no-offset seed bit-for-bit"
);
}
#[test]
pub(crate) fn pca_seed_is_run_to_run_reproducible() {
let residual = array![
[3.0, 0.1, -0.2, 0.4, 0.0, 0.05],
[-3.0, -0.1, 0.2, -0.4, 0.0, -0.05],
[0.3, 0.0, 2.0, 0.2, 0.1, 0.0],
[-0.3, 0.0, -2.0, -0.2, -0.1, 0.0],
[0.0, 0.2, 0.1, 0.0, 1.0, 0.3],
[0.0, -0.2, -0.1, 0.0, -1.0, -0.3],
];
let kinds = vec![SaeAtomBasisKind::Periodic, SaeAtomBasisKind::Periodic];
let dims = vec![1usize, 1];
let seed_a = sae_pca_seed_initial_coords(residual.view(), &kinds, &dims).expect("seed #1");
let seed_b = sae_pca_seed_initial_coords(residual.view(), &kinds, &dims).expect("seed #2");
assert_eq!(
seed_a, seed_b,
"PCA seed must be bit-identical run-to-run (the issue's determinism \
requirement)"
);
}
#[test]
pub(crate) fn decoder_norm_guard_is_noop_for_k1() {
let mut term = trivial_k1_euclidean_term();
let n = term.n_obs();
let p = term.output_dim();
let target = Array2::<f64>::zeros((n, p));
let rho = SaeManifoldRho::new(0.0, 0.0, vec![array![0.0_f64]]);
let before = term.atoms[0].decoder_coefficients.clone();
term.enforce_decoder_norm_guard(target.view(), 0, &rho, None)
.expect("K=1 decoder-norm guard must be a no-op, never error");
assert!(
term.collapse_events().is_empty(),
"K=1 must record no decoder-collapse events"
);
assert_eq!(
term.atoms[0].decoder_coefficients, before,
"K=1 decoder must be untouched by the guard"
);
}
#[test]
pub(crate) fn hybrid_collapse_is_load_bearing_and_dominates() {
let (mut term, _t, rho) = small_two_atom_periodic_term();
let curved = term
.try_fitted_for_rho(&rho)
.expect("curved reconstruction assembles");
let pre = term
.hybrid_collapsed_reconstruction(&rho)
.expect("collapse with no report returns the curved fit");
assert!(
(&curved - &pre).iter().all(|d| d.abs() < 1e-15),
"with no hybrid-split report the collapse must equal the curved fit"
);
for basis_row in 1..term.atoms[0].decoder_coefficients.nrows() {
for out_col in 0..term.atoms[0].decoder_coefficients.ncols() {
term.atoms[0].decoder_coefficients[[basis_row, out_col]] = 0.0;
}
}
let full = term
.try_fitted_for_rho(&rho)
.expect("post-straighten curved reconstruction assembles");
let mut target = full.clone();
for i in 0..target.nrows() {
for j in 0..target.ncols() {
target[[i, j]] += 1.0e-3 * (0.7 * (i as f64 + 1.0) + 1.3 * (j as f64 + 1.0)).sin();
}
}
let report = term
.compute_hybrid_split_report(&rho, Some(target.view()))
.expect("hybrid split report computes")
.expect("eligible d=1 atoms present a report");
term.hybrid_split_report = Some(report);
let collapsed_any = term
.hybrid_split_report
.as_ref()
.unwrap()
.verdicts
.iter()
.any(|v| v.linear_image.is_some());
assert!(
collapsed_any,
"a straight atom must collapse at least one slot to the linear tail"
);
let ev_curved = reconstruction_explained_variance(target.view(), full.view())
.expect("curved-reconstruction EV defined");
assert!(
ev_curved > 0.99,
"the curved fit must explain essentially all of the barely-perturbed \
target; got {ev_curved}"
);
let ev_collapsed = term
.hybrid_collapsed_explained_variance(target.view(), &rho)
.expect("collapsed EV evaluates")
.expect("collapsed EV defined");
assert!(
ev_collapsed >= ev_curved - 1e-6,
"collapsing a straight atom must preserve EV (match-or-beat dominance \
floor): curved {ev_curved:.9}, collapsed {ev_collapsed:.9}"
);
let verdict = term
.hybrid_split_report
.as_ref()
.unwrap()
.verdicts
.iter()
.find(|v| v.linear_image.is_some())
.expect("a collapsed slot exists");
let collapsed_idx = verdict.linear_image.as_ref().unwrap().atom_idx;
let curved_params = term.atoms[collapsed_idx].decoder_coefficients.len();
assert!(
verdict.choice.num_parameters < curved_params,
"the linear-collapsed slot must shed curved coefficients: linear \
{} < curved {}",
verdict.choice.num_parameters,
curved_params
);
let report_with_ev = term
.compute_hybrid_split_report(&rho, Some(target.view()))
.expect("hybrid split report with target computes")
.expect("eligible d=1 atoms present a report");
assert!(
!report_with_ev.verdicts.is_empty(),
"the report must adjudicate at least one d=1 slot"
);
for v in &report_with_ev.verdicts {
let theta = v
.fitted_turning
.unwrap_or_else(|| panic!("verdict '{}' must carry a fitted turning Θ", v.atom_name));
let dev = v
.train_loao_delta_ev
.unwrap_or_else(|| panic!("verdict '{}' must carry a training LOAO ΔEV", v.atom_name));
assert!(
theta.is_finite() && theta >= 0.0,
"fitted turning Θ must be a finite non-negative arc-curvature integral; \
got {theta} for '{}'",
v.atom_name
);
assert!(
dev.is_finite(),
"training LOAO ΔEV must be finite; got {dev} for '{}'",
v.atom_name
);
if !v.kept_curved {
assert!(
theta <= 1e-3,
"a linear-tail slot must read Θ ≈ 0 (straight image); got {theta} for '{}'",
v.atom_name
);
}
}
let curved_earner = report_with_ev
.verdicts
.iter()
.find(|v| v.kept_curved && v.train_loao_delta_ev.map(|d| d > 0.0).unwrap_or(false));
assert!(
curved_earner.is_some(),
"a load-bearing curveable slot must be kept curved AND earn positive training \
LOAO ΔEV (collapsing it would drop reconstruction EV); verdicts = {:?}",
report_with_ev
.verdicts
.iter()
.map(|v| (
v.atom_name.clone(),
v.kept_curved,
v.fitted_turning,
v.train_loao_delta_ev
))
.collect::<Vec<_>>()
);
assert_eq!(
curved_earner.unwrap().atom_name,
"periodic1",
"the load-bearing (untouched) atom must be the one kept curved"
);
for v in &report_with_ev.verdicts {
if !v.kept_curved {
assert_eq!(
v.atom_name, "periodic0",
"only the straightened atom may be released to the linear tail; \
'{}' collapsed unexpectedly",
v.atom_name
);
}
}
}
#[test]
pub(crate) fn topk_reconstruction_composes_with_hybrid_collapse() {
let (mut term, _t, rho) = small_two_atom_periodic_term();
for basis_row in 1..term.atoms[0].decoder_coefficients.nrows() {
for out_col in 0..term.atoms[0].decoder_coefficients.ncols() {
term.atoms[0].decoder_coefficients[[basis_row, out_col]] = 0.0;
}
}
let full = term
.try_fitted_for_rho(&rho)
.expect("post-straighten curved reconstruction assembles");
let mut target = full.clone();
for i in 0..target.nrows() {
for j in 0..target.ncols() {
target[[i, j]] += 1.0e-3 * (0.7 * (i as f64 + 1.0) + 1.3 * (j as f64 + 1.0)).sin();
}
}
let report = term
.compute_hybrid_split_report(&rho, Some(target.view()))
.expect("hybrid split report computes")
.expect("eligible d=1 atoms present a report");
term.hybrid_split_report = Some(report);
assert!(
term.hybrid_linear_image_map().contains_key(&0),
"atom 0 must have collapsed to a linear image for this regression"
);
const WITNESS_SLOPE: f64 = 0.4;
{
let report = term.hybrid_split_report.as_mut().unwrap();
let img = report
.verdicts
.iter_mut()
.find_map(|v| v.linear_image.as_mut())
.expect("the collapsed slot must carry a linear image to install a witness into");
for slope in img.b1.iter_mut() {
*slope += WITNESS_SLOPE;
}
}
let full_assignments = term.assignment.assignments();
let projected_collapsed = term
.reconstruct_from_assignments(full_assignments.view(), true)
.expect("collapse-aware projected reconstruction assembles");
let production_collapsed = term.fitted();
let max_gap = (&projected_collapsed - &production_collapsed)
.iter()
.fold(0.0_f64, |m, d| m.max(d.abs()));
assert!(
max_gap < 1e-12,
"top_k==K collapse-aware reconstruction must equal the non-projected \
collapsed fitted() (incl. the linear-collapsed slot); max gap {max_gap:e}"
);
let projected_curved = term
.reconstruct_from_assignments(full_assignments.view(), false)
.expect("curved projected reconstruction assembles");
let curved_gap = (&projected_collapsed - &projected_curved)
.iter()
.fold(0.0_f64, |m, d| m.max(d.abs()));
assert!(
curved_gap > 1e-9,
"the collapsed slot must change the reconstruction vs the curved decoder \
(collapse engaged); max gap {curved_gap:e}"
);
}
#[test]
pub(crate) fn oos_linear_images_drive_collapsed_reconstruction() {
let (mut term, _t, rho) = small_two_atom_periodic_term();
for basis_row in 1..term.atoms[0].decoder_coefficients.nrows() {
for out_col in 0..term.atoms[0].decoder_coefficients.ncols() {
term.atoms[0].decoder_coefficients[[basis_row, out_col]] = 0.0;
}
}
let full = term
.try_fitted_for_rho(&rho)
.expect("curved reconstruction assembles");
let mut target = full.clone();
for i in 0..target.nrows() {
for j in 0..target.ncols() {
target[[i, j]] += 1.0e-3 * (0.7 * (i as f64 + 1.0) + 1.3 * (j as f64 + 1.0)).sin();
}
}
let report = term
.compute_hybrid_split_report(&rho, Some(target.view()))
.expect("hybrid split report computes")
.expect("eligible d=1 atoms present a report");
term.hybrid_split_report = Some(report);
const WITNESS_SLOPE: f64 = 0.4;
{
let report = term.hybrid_split_report.as_mut().unwrap();
let img = report
.verdicts
.iter_mut()
.find_map(|v| v.linear_image.as_mut())
.expect("the collapsed slot must carry a linear image to install a witness into");
for slope in img.b1.iter_mut() {
*slope += WITNESS_SLOPE;
}
}
let images: Vec<_> = term
.hybrid_split_report
.as_ref()
.unwrap()
.verdicts
.iter()
.filter_map(|v| v.linear_image.clone())
.collect();
assert!(
!images.is_empty(),
"the straight slot must yield at least one linear image to thread to OOS"
);
let collapsed_with_report = term.fitted();
term.hybrid_split_report = None;
let curved = term.fitted();
assert!(
(&curved - &collapsed_with_report)
.iter()
.any(|d| d.abs() > 1e-9),
"with no images attached the OOS reconstruction must be the curved one"
);
term.set_hybrid_linear_images(images)
.expect("valid linear images attach");
let collapsed_oos = term.fitted();
let gap = (&collapsed_oos - &collapsed_with_report)
.iter()
.fold(0.0_f64, |m, d| m.max(d.abs()));
assert!(
gap < 1e-12,
"attached OOS linear images must reproduce the train-side collapsed \
reconstruction; max gap {gap:e}"
);
}
fn jeffreys_two_atom_term(n: usize, dec0: [f64; 3], dec1: [f64; 3]) -> SaeManifoldTerm {
let coords0 = Array2::<f64>::from_shape_fn((n, 1), |(i, _)| (i as f64 * 0.618_034).fract());
let coords1 = Array2::<f64>::from_shape_fn((n, 1), |(i, _)| (i as f64 * 0.414_214).fract());
let (phi0, jet0) = periodic_basis(&coords0);
let (phi1, jet1) = periodic_basis(&coords1);
let logits = Array2::<f64>::from_shape_fn((n, 2), |(i, j)| {
if j == 0 {
0.4 * (i as f64 * 0.7).sin()
} else {
0.3 * (i as f64 * 1.1).cos()
}
});
let row_decoder = |r: [f64; 3]| {
let mut d = Array2::<f64>::zeros((3, 3));
d[[0, 0]] = r[0];
d[[0, 1]] = r[1];
d[[0, 2]] = r[2];
d
};
let make = |name: &str, phi: Array2<f64>, jet: Array3<f64>, decoder: Array2<f64>| {
SaeManifoldAtom::new_with_provided_function_gram(
name,
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
decoder,
Array2::<f64>::eye(3),
)
.unwrap()
.with_basis_evaluator(Arc::new(TestPeriodicEvaluator))
};
let atom0 = make("occ0", phi0, jet0, row_decoder(dec0));
let atom1 = make("occ1", phi1, jet1, row_decoder(dec1));
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
logits,
vec![coords0, coords1],
vec![
LatentManifold::Circle { period: 1.0 },
LatentManifold::Circle { period: 1.0 },
],
AssignmentMode::softmax(0.8),
)
.unwrap();
SaeManifoldTerm::new(vec![atom0, atom1], assignment).unwrap()
}
fn barrier_spectral_m_reference(lam: f64, eps: f64) -> f64 {
let x = (lam + eps) / eps;
if x >= 30.0 {
lam + eps
} else if x <= -30.0 {
eps * x.exp()
} else {
eps * x.exp().ln_1p()
}
}
fn two_atom_jeffreys_reference(term: &SaeManifoldTerm, overlap: f64) -> (f64, f64, f64) {
let gates = term.assignment.assignments();
let (mut cross, mut e0, mut e1) = (0.0_f64, 0.0_f64, 0.0_f64);
for i in 0..gates.nrows() {
let a0 = gates[[i, 0]];
let a1 = gates[[i, 1]];
cross += a0 * a1;
e0 += a0 * a0;
e1 += a1 * a1;
}
let q = cross / (e0 * e1).sqrt();
let eps = 2.0 * (2.0 / e0.min(e1)).sqrt();
let r = q * overlap;
let value = -0.5
* (barrier_spectral_m_reference(1.0 + r, eps).ln()
+ barrier_spectral_m_reference(1.0 - r, eps).ln()
- 2.0 * barrier_spectral_m_reference(1.0, eps).ln());
(value, q, eps)
}
#[test]
fn unscaled_jeffreys_value_and_gradient_match_closed_form() {
let c2 = 0.98_f64;
let cos = c2.sqrt();
let sin = (1.0 - c2).sqrt();
let n = 48_usize;
let dec0 = [1.0, 0.0, 0.0];
let dec1 = [cos, sin, 0.0];
let term = jeffreys_two_atom_term(n, dec0, dec1);
let (expected, q, eps) = two_atom_jeffreys_reference(&term, c2);
assert!(
q > 0.0 && q < 1.0,
"fixture: coactivation must be strictly interior, got q={q}"
);
let value = term.separation_barrier_value(1.0);
assert!(
value > 0.0,
"near-collapsed co-firing pair must be penalized, got {value}"
);
assert!(
(value - expected).abs() <= expected.abs() * 1e-9,
"Jeffreys value must equal the unscaled closed form \
−½·log det(F+ε_C·I): expected={expected:.12e} got={value:.12e} \
(q={q:.6}, ε_C={eps:.6})"
);
let (_v, grad) = term.separation_barrier_value_and_grad_for_test(1.0);
let offsets = term.beta_offsets();
let p = term.output_dim();
let h = 1.0e-6;
let mut max_rel = 0.0_f64;
for atom in 0..2 {
let m = term.atoms[atom].decoder_coefficients.nrows();
for a in 0..m {
for o in 0..p {
let mut plus = jeffreys_two_atom_term(n, dec0, dec1);
plus.atoms[atom].decoder_coefficients[[a, o]] += h;
let mut minus = jeffreys_two_atom_term(n, dec0, dec1);
minus.atoms[atom].decoder_coefficients[[a, o]] -= h;
let fd = (plus.separation_barrier_value(1.0) - minus.separation_barrier_value(1.0))
/ (2.0 * h);
let analytic = grad[offsets[atom] + a * p + o];
let rel = (fd - analytic).abs() / (1.0 + fd.abs().max(analytic.abs()));
max_rel = max_rel.max(rel);
}
}
}
assert!(
max_rel < 1.0e-5,
"unscaled analytic ∂P/∂B must match FD of the unscaled value at \
the near-collapsed pair: max rel err {max_rel:.3e}"
);
}
#[test]
fn jeffreys_total_information_factorization_is_sample_size_invariant() {
let overlap = 0.93_f64;
let term = jeffreys_two_atom_term(
64,
[1.0, 0.0, 0.0],
[overlap.sqrt(), (1.0 - overlap).sqrt(), 0.0],
);
let (expected, q, eps) = two_atom_jeffreys_reference(&term, overlap);
let production = term.separation_barrier_value(1.0);
assert!((production - expected).abs() <= 1.0e-12);
let r = q * overlap;
for sample_mass in [1.0_f64, 7.0, 1.0e3, 1.0e6] {
let total_information_value = -0.5
* ((sample_mass * barrier_spectral_m_reference(1.0 + r, eps)).ln()
+ (sample_mass * barrier_spectral_m_reference(1.0 - r, eps)).ln()
- 2.0 * (sample_mass * barrier_spectral_m_reference(1.0, eps)).ln());
assert!(
(total_information_value - production).abs() <= 2.0e-12,
"the common s·log(N_eff) factor must cancel: N_eff={sample_mass:e}, \
total-information value={total_information_value:.12e}, \
production={production:.12e}"
);
}
}
#[test]
fn unscaled_jeffreys_assembled_gradient_matches_penalized_objective_fd() {
let n = 32_usize;
let c2 = 0.8_f64;
let dec0 = [1.0, 0.0, 0.0];
let dec1 = [c2.sqrt(), (1.0 - c2).sqrt(), 0.0];
let term0 = jeffreys_two_atom_term(n, dec0, dec1);
let p = term0.output_dim();
let target = Array2::<f64>::from_shape_fn((n, p), |(i, j)| {
0.21 * (0.31 * (i as f64 + 1.0) + 0.47 * (j as f64 + 1.0)).sin()
- 0.13 * (0.19 * (i as f64 + 1.0) * (j as f64 + 1.0)).cos()
});
let rho = SaeManifoldRho::new(
-2.0,
-2.0,
vec![Array1::from_vec(vec![-2.0]), Array1::from_vec(vec![-2.0])],
);
let mut base = term0.clone();
base.refresh_decoder_repulsion_gate();
base.refresh_barrier_coactivation_gate();
base.refresh_amplitude_barrier_gate(); let base = base;
let reinstall_frozen_gates = |t: &mut SaeManifoldTerm| {
t.decoder_repulsion_gate = base.decoder_repulsion_gate.clone();
t.barrier_coactivation_gate = base.barrier_coactivation_gate.clone();
t.amplitude_barrier_gate = base.amplitude_barrier_gate;
};
let barrier_value = base.separation_barrier_value(1.0);
assert!(
barrier_value > 1.0e-4,
"fixture: the unscaled barrier must be live for aligned, co-firing \
atoms; got {barrier_value}"
);
let mut assembled = base.clone();
let sys = assembled
.assemble_arrow_schur(target.view(), &rho, None)
.expect("K=2 assembly succeeds");
let beta = base.flatten_beta();
assert_eq!(sys.gb.len(), beta.len());
let h = 1.0e-6;
let mut worst_rel = 0.0_f64;
let mut worst_idx = 0_usize;
for idx in 0..beta.len() {
let mut beta_plus = beta.clone();
beta_plus[idx] += h;
let mut plus = base.clone();
reinstall_frozen_gates(&mut plus);
plus.set_flat_beta(beta_plus.view()).expect("set beta plus");
let obj_plus = plus
.penalized_objective_total(target.view(), &rho, None, 1.0)
.expect("objective at plus");
let mut beta_minus = beta.clone();
beta_minus[idx] -= h;
let mut minus = base.clone();
reinstall_frozen_gates(&mut minus);
minus
.set_flat_beta(beta_minus.view())
.expect("set beta minus");
let obj_minus = minus
.penalized_objective_total(target.view(), &rho, None, 1.0)
.expect("objective at minus");
let fd = (obj_plus - obj_minus) / (2.0 * h);
let analytic = sys.gb[idx];
let rel = (fd - analytic).abs() / fd.abs().max(analytic.abs()).max(1.0e-9);
if rel > worst_rel {
worst_rel = rel;
worst_idx = idx;
}
}
assert!(
worst_rel < 5.0e-5,
"assembled gb must be the exact gradient of the line-search objective \
(unscaled Jeffreys barrier included on both sides): worst rel err \
{worst_rel:.3e} at beta index {worst_idx}"
);
}
#[test]
fn repulsion_is_radially_inert_net_radial_is_analytic_barrier_2343() {
use gam_terms::analytic_penalties::AnalyticPenalty;
let (term0, target0, _rho) = small_two_atom_periodic_term();
let mut term = term0.clone();
let p = term.output_dim();
let eps = 1.0e-7_f64;
let b0 = term.atoms[0].decoder_coefficients.clone();
term.atoms[1].decoder_coefficients = &b0 * eps;
let target = Array2::<f64>::zeros(target0.raw_dim());
let rho = SaeManifoldRho::new((1.0e-4_f64).ln(), (1.0e-4_f64).ln(), vec![array![0.0], array![0.0]]);
let sys = term
.assemble_arrow_schur(target.view(), &rho, None)
.expect("assembly must succeed at the collapse point");
let gate = term
.decoder_repulsion_gate
.clone()
.expect("#2343: the decoder repulsion gate must be ENGAGED on the collinear pair");
assert!(
gate.iter().any(|&(j, k, w)| (j, k) == (0, 1) && w > 0.0),
"#2343: pair (0,1) must carry positive repulsion weight; gate = {gate:?}"
);
let offsets = term.beta_offsets();
let off1 = offsets[1];
let b1 = term.atoms[1].decoder_coefficients.clone();
let u: f64 = b1.iter().map(|v| v * v).sum();
let s = u.sqrt();
assert!(s > 0.0, "collapsing atom must retain a radial direction");
assert_eq!(b1.ncols(), p, "decoder block must be M×p_out");
let dir: Vec<f64> = b1.iter().map(|v| v / s).collect();
let norm_sq: Vec<f64> = term
.atoms
.iter()
.map(|atom| atom.decoder_coefficients.iter().map(|v| v * v).sum::<f64>())
.collect();
let f = SaeManifoldTerm::barrier_norm_floor_sq(&norm_sq);
let mu = SAE_AMPLITUDE_BARRIER_STRENGTH;
assert!(u < f, "atom 1 must sit inside the barrier turn-on radius: u={u:e} f={f:e}");
let g_coef = -2.0 * mu * f / (u * (u + f));
let expected = g_coef * s; assert!(expected < 0.0, "barrier radial force must be outward");
let rep = term
.live_decoder_repulsion_penalty()
.expect("#2343: live repulsion penalty must exist when the gate is engaged");
let beta = term.flatten_beta();
let rep_grad = rep.grad_target(beta.view(), Array1::<f64>::zeros(0).view());
let rep_radial: f64 = (0..b1.len()).map(|i| rep_grad[off1 + i] * dir[i]).sum();
let rep_rel = rep_radial.abs() / expected.abs();
assert!(
rep_rel <= 1.0e-9,
"#2343 clause (1): the live-normalized repulsion must be radially INERT — its \
own in-situ radial β-gradient on the collapsing atom must be negligible \
against the amplitude barrier (degree-0 homogeneity, Euler). Got \
{rep_radial:.3e} vs barrier {expected:.3e} (relative {rep_rel:e}); the pre-fix \
frozen normalizer made this +2.57e7, i.e. ~5× the barrier."
);
let radial: f64 = (0..b1.len()).map(|i| sys.gb[off1 + i] * dir[i]).sum();
assert!(
radial < 0.0,
"#2343 clause (2): the net radial force must be OUTWARD (negative): \
radial={radial:e} expected={expected:e}"
);
let rel = (radial - expected).abs() / expected.abs();
assert!(
rel <= 1.0e-6,
"#2343 clause (2): with the repulsion radially inert (clause 1), the net radial \
β-gradient must equal the amplitude barrier's analytic g_coef·‖B_1‖ alone, to \
within the ~1e-8 common-mode residual of the other live terms (data-fit / \
separation): measured {radial:.12e} vs analytic {expected:.12e} (relative gap \
{rel:e}). The pre-fix frozen-normalizer repulsion flipped this to +2.07e7 \
(INWARD) — an O(1) sign change, far above this bound."
);
}
#[test]
fn zz_measure_separation_force_vs_c2_2253() {
for &c2 in &[0.5_f64, 0.9, 0.99, 0.999, 0.9999, 0.999999] {
let term = aligned_two_atom_term_with_c2(c2);
let (v, g) = term.separation_barrier_value_and_grad_for_test(1.0);
let fnorm = g.iter().map(|x| x * x).sum::<f64>().sqrt();
eprintln!("SEPFORCE c2={c2:.6} value={v:.6e} force_gradnorm={fnorm:.6e}");
}
}
#[test]
fn zz_measure_real_fixture_barrier_q_2253() {
use crate::manifold::tests::small_two_atom_periodic_term;
use crate::manifold::tests_recovery_split_780::gamma_fd_tiny_fixture;
let report = |tag: &str, term: &SaeManifoldTerm| {
let (pairs, _neff) = term.barrier_coactivation_pairs();
for (j, k, q) in &pairs {
let o = term.decoder_gram_cosine_sq(*j, *k);
eprintln!(
"REALQ {tag} pair=({j},{k}) q={q:.6e} o_c2={o:.6e} lam_min=1-q*o={:.6e}",
1.0 - q * o
);
}
if pairs.is_empty() {
eprintln!("REALQ {tag} NO co-firing pairs");
}
};
let (mut term, _t, _r) = gamma_fd_tiny_fixture();
term.assignment.mode = AssignmentMode::ordered_beta_bernoulli(0.7, 0.9, true);
term.refresh_barrier_coactivation_gate();
report("recompute_asbuilt", &term);
let b0 = term.atoms[0].decoder_coefficients.clone();
if term.atoms[1].decoder_coefficients.dim() == b0.dim() {
term.atoms[1].decoder_coefficients = b0.clone();
}
term.refresh_barrier_coactivation_gate();
report("recompute_aligned", &term);
let (mut h, _t2, _r2) = small_two_atom_periodic_term();
h.refresh_barrier_coactivation_gate();
report("hutchinson_asbuilt", &h);
let hb0 = h.atoms[0].decoder_coefficients.clone();
if h.atoms[1].decoder_coefficients.dim() == hb0.dim() {
h.atoms[1].decoder_coefficients = hb0.clone();
}
h.refresh_barrier_coactivation_gate();
report("hutchinson_aligned", &h);
}
#[test]
fn zz_measure_tiny_fixture_target_rank_2253() {
use gam_linalg::faer_ndarray::FaerSvd;
use crate::manifold::tests::small_two_atom_periodic_term;
use crate::manifold::tests_recovery_split_780::gamma_fd_tiny_fixture;
let svd_report = |tag: &str, target: &Array2<f64>| {
let (_u, sv, _vt) = target.svd(false, false).expect("svd");
let s: Vec<f64> = sv.iter().copied().collect();
let s1 = s.first().copied().unwrap_or(0.0);
let s2 = s.get(1).copied().unwrap_or(0.0);
let ratio = if s1 > 0.0 { s2 / s1 } else { 0.0 };
let sfmt: Vec<String> = s.iter().map(|x| format!("{x:.4e}")).collect();
eprintln!(
"TARGETRANK {tag} dim={:?} sigmas={:?} sigma2_over_sigma1={ratio:.6e}",
target.dim(),
sfmt
);
};
let (_t, tgt_r, _r) = gamma_fd_tiny_fixture();
svd_report("recompute_gamma_fd_tiny", &tgt_r);
let (_t2, tgt_h, _r2) = small_two_atom_periodic_term();
svd_report("hutchinson_small_two_atom", &tgt_h);
}