use super::tests::{deterministic_circle_noise, global_ev};
use super::*;
use crate::basis::{PeriodicHarmonicEvaluator, SaeBasisSecondJet};
use gam_linalg::faer_ndarray::{FaerCholesky, fast_atb};
use gam_solve::rho_optimizer::{OuterObjective, OuterProblem};
use ndarray::{Array1, Array2, ArrayView2, array, s};
use std::sync::Arc;
#[test]
fn joint_decoder_gauge_quotients_full_rank_atom_redistribution_2080() -> Result<(), String> {
let n = 4usize;
let phi = Array2::<f64>::ones((n, 1));
let jet = ndarray::Array3::<f64>::zeros((n, 1, 1));
let make_atom = |name: &str, decoder: f64| {
SaeManifoldAtom::new(
name,
SaeAtomBasisKind::Linear,
1,
phi.clone(),
jet.clone(),
array![[decoder]],
Array2::<f64>::zeros((1, 1)),
)
};
let coords = Array2::<f64>::zeros((n, 1));
let assignment = SaeAssignment::from_blocks_with_mode(
Array2::<f64>::zeros((n, 2)),
vec![coords.clone(), coords],
AssignmentMode::softmax(1.0),
)?;
let term = SaeManifoldTerm::new(
vec![make_atom("shared-a", 1.0)?, make_atom("shared-b", -0.5)?],
assignment,
)?;
let weights = term.assignment.assignments();
for atom_idx in 0..2 {
let gram = (0..n)
.map(|row| {
let value = weights[[row, atom_idx]] * phi[[row, 0]];
value * value
})
.sum::<f64>();
assert!(
gram > 0.0,
"atom {atom_idx} must have a full-rank scalar Gram"
);
}
let gauges = term.joint_decoder_beta_null_directions(&[0.0, 0.0])?;
assert_eq!(
gauges.len(),
1,
"the two identical scalar designs have exactly one coupled decoder gauge"
);
let coord_dim = n * term.assignment.row_block_dim();
let delta_t = Array1::<f64>::zeros(coord_dim);
let delta_beta = array![1.0_f64, -1.0];
let raw = delta_beta.dot(&delta_beta);
let quotient =
term.quotient_newton_step_norm_sq(delta_t.view(), delta_beta.view(), raw, &[0.0, 0.0])?;
assert!(
quotient <= f64::EPSILON * (1.0 + raw),
"joint redistribution must vanish on the identified quotient; raw={raw:.3e}, quotient={quotient:.3e}"
);
Ok(())
}
fn two_circle_wide_target(n: usize, p: usize, sigma: f64) -> Array2<f64> {
let mut fa = Array2::<f64>::zeros((2, p));
let mut fb = Array2::<f64>::zeros((2, p));
for j in 0..p {
if j % 2 == 0 {
fa[[0, j]] = deterministic_circle_noise(j, 0);
fa[[1, j]] = deterministic_circle_noise(j, 1);
} else {
fb[[0, j]] = deterministic_circle_noise(j, 2);
fb[[1, j]] = deterministic_circle_noise(j, 3);
}
}
for f in [&mut fa, &mut fb] {
for r in 0..2 {
let nrm = (0..p).map(|j| f[[r, j]] * f[[r, j]]).sum::<f64>().sqrt();
for j in 0..p {
f[[r, j]] /= nrm.max(1.0e-300);
}
}
}
let mut z = Array2::<f64>::zeros((n, p));
for row in 0..n {
let ta = std::f64::consts::TAU * (row as f64) / (n as f64);
let tb = std::f64::consts::TAU * (2.0 * row as f64 + 0.37) / (n as f64);
let (ca, sa) = (ta.cos(), ta.sin());
let (cb, sb) = (tb.cos(), tb.sin());
for j in 0..p {
z[[row, j]] = ca * fa[[0, j]]
+ sa * fa[[1, j]]
+ cb * fb[[0, j]]
+ sb * fb[[1, j]]
+ sigma * deterministic_circle_noise(row, j + 7);
}
}
for j in 0..p {
let mut mean = 0.0_f64;
for row in 0..n {
mean += z[[row, j]];
}
mean /= n as f64;
let mut var = 0.0_f64;
for row in 0..n {
let d = z[[row, j]] - mean;
var += d * d;
}
let sd = (var / n as f64).sqrt().max(1.0e-12);
for row in 0..n {
z[[row, j]] = (z[[row, j]] - mean) / sd;
}
}
z
}
fn one_circle_wide_target(n: usize, p: usize, sigma: f64) -> Array2<f64> {
let mut frame = Array2::<f64>::zeros((2, p));
for j in 0..p {
frame[[0, j]] = deterministic_circle_noise(j, 0);
frame[[1, j]] = deterministic_circle_noise(j, 1);
}
for r in 0..2 {
let nrm = (0..p)
.map(|j| frame[[r, j]] * frame[[r, j]])
.sum::<f64>()
.sqrt();
for j in 0..p {
frame[[r, j]] /= nrm.max(1.0e-300);
}
}
let mut z = Array2::<f64>::zeros((n, p));
for row in 0..n {
let t = std::f64::consts::TAU * (row as f64) / (n as f64);
let (c, s) = (t.cos(), t.sin());
for j in 0..p {
z[[row, j]] = c * frame[[0, j]]
+ s * frame[[1, j]]
+ sigma * deterministic_circle_noise(row, j + 7);
}
}
for j in 0..p {
let mut mean = 0.0_f64;
for row in 0..n {
mean += z[[row, j]];
}
mean /= n as f64;
let mut var = 0.0_f64;
for row in 0..n {
let d = z[[row, j]] - mean;
var += d * d;
}
let sd = (var / n as f64).sqrt().max(1.0e-12);
for row in 0..n {
z[[row, j]] = (z[[row, j]] - mean) / sd;
}
}
z
}
fn two_circle_periodic_term(
z: ArrayView2<'_, f64>,
k: usize,
harmonics: usize,
) -> (SaeManifoldTerm, f64) {
let n = z.nrows();
let p = z.ncols();
let dim = 1usize;
let num_basis = 1 + 2 * harmonics;
let evaluator: Arc<dyn SaeBasisSecondJet> =
Arc::new(PeriodicHarmonicEvaluator::new(num_basis).unwrap());
let basis_kinds = vec![SaeAtomBasisKind::Periodic; k];
let atom_dims = vec![dim; k];
let seed_coords = sae_pca_seed_initial_coords(z, &basis_kinds, &atom_dims).unwrap();
let mut atoms = Vec::with_capacity(k);
let mut coords_blocks = Vec::with_capacity(k);
let mut manifolds = Vec::with_capacity(k);
let mut rss = 0.0_f64;
for atom_idx in 0..k {
let coords = seed_coords.slice(s![atom_idx, .., 0..dim]).to_owned();
let (phi, jet) = evaluator.evaluate(coords.view()).unwrap();
let mm = phi.ncols();
let mut xtx = fast_atb(&phi, &phi);
for i in 0..mm {
xtx[[i, i]] += 1.0e-8;
}
let xtz = fast_atb(&phi, &z.to_owned());
let decoder = xtx.cholesky(Side::Lower).unwrap().solve_mat(&xtz);
let fitted = phi.dot(&decoder);
for row in 0..n {
for col in 0..p {
let r = z[[row, col]] - fitted[[row, col]];
rss += r * r;
}
}
let atom = SaeManifoldAtom::new(
"circle",
SaeAtomBasisKind::Periodic,
dim,
phi,
jet,
decoder,
Array2::<f64>::eye(mm),
)
.unwrap()
.with_basis_evaluator(evaluator.clone());
atoms.push(atom);
coords_blocks.push(coords);
manifolds.push(LatentManifold::Circle { period: 1.0 });
}
let seed_dispersion = (rss / (k * n * p) as f64).max(1.0e-12);
let logits = Array2::<f64>::from_elem((n, k), 6.0);
let mode = AssignmentMode::ibp_map(1.0, 1.0, false);
let assignment =
SaeAssignment::from_blocks_with_mode_and_manifolds(logits, coords_blocks, manifolds, mode)
.unwrap();
(
SaeManifoldTerm::new(atoms, assignment).unwrap(),
seed_dispersion,
)
}
fn run_wide_outer_fit(
n: usize,
p: usize,
k: usize,
harmonics: usize,
) -> (f64, OuterProbeTelemetry) {
let z = two_circle_wide_target(n, p, 0.03);
let (term, seed_dispersion) = two_circle_periodic_term(z.view(), k, harmonics);
let mode = AssignmentMode::ibp_map(1.0, 1.0, false);
let init_rho = SaeManifoldRho::new(0.02_f64.ln(), 1.0_f64.ln(), vec![array![0.0]; k])
.seed_scaled_by_dispersion_for_assignment(seed_dispersion, mode)
.unwrap();
let seed = init_rho.to_flat();
let n_params = seed.len();
let mut objective =
SaeManifoldOuterObjective::new(term, z.clone(), None, init_rho, 8, 0.04, 1.0e-6, 1.0e-6);
let result = OuterProblem::new(n_params)
.with_initial_rho(seed)
.with_max_iter(4)
.with_seed_config(gam_problem::SeedConfig {
max_seeds: 1,
seed_budget: 1,
..Default::default()
})
.run(&mut objective, "SAE manifold")
.expect("#2080 wide-p outer REML fit must terminate, not hang / abort");
assert!(
result.converged,
"#2080 wide-p acceptance requires a CONVERGED outer REML optimum, not a \
finite max-iteration/line-search incumbent: iterations={}, final_value={:.6e}, \
final_grad_norm={:?}",
result.iterations, result.final_value, result.final_grad_norm,
);
let telemetry = objective.probe_telemetry();
objective
.certify_outer_result(&result)
.expect("#2080 wide-p outer result must certify the installed state");
let fitted = objective.into_fitted().expect("outer fit was evaluated");
let ev = global_ev(z.view(), fitted.term.fitted().view());
(ev, telemetry)
}
fn run_k1_generated_seed_outer_fit(
n: usize,
p: usize,
harmonics: usize,
) -> (f64, OuterProbeTelemetry) {
let z = one_circle_wide_target(n, p, 0.05);
let (term, seed_dispersion) = two_circle_periodic_term(z.view(), 1, harmonics);
let mode = AssignmentMode::ibp_map(1.0, 1.0, false);
let init_rho = SaeManifoldRho::new(0.02_f64.ln(), 1.0_f64.ln(), vec![array![0.0]])
.seed_scaled_by_dispersion_for_assignment(seed_dispersion, mode)
.unwrap();
let n_params = init_rho.to_flat().len();
let mut objective =
SaeManifoldOuterObjective::new(term, z.clone(), None, init_rho, 8, 0.04, 1.0e-6, 1.0e-6);
let result = OuterProblem::new(n_params)
.with_max_iter(4)
.with_seed_config(gam_problem::SeedConfig {
max_seeds: 1,
seed_budget: 1,
..Default::default()
})
.run(&mut objective, "SAE manifold K=1 generated seed")
.expect("#2153 K=1 generated-seed circle fit must terminate");
assert!(
result.converged,
"#2153 K=1 acceptance requires a converged outer optimum: iterations={}, \
final_value={:.6e}, final_grad_norm={:?}",
result.iterations, result.final_value, result.final_grad_norm,
);
let telemetry = objective.probe_telemetry();
objective
.certify_outer_result(&result)
.expect("#2153 outer result must certify the installed state");
let fitted = objective.into_fitted().expect("outer fit was evaluated");
let ev = global_ev(z.view(), fitted.term.fitted().view());
(ev, telemetry)
}
#[derive(Clone, Copy, Debug)]
struct CeilingPathologyConfig {
n: usize,
p: usize,
harmonics: usize,
sigma: f64,
inner_max_iter: usize,
outer_max_iter: usize,
initial_step_norm: f64,
materialization_ratio_floor: f64,
step_collapse_radius: f64,
huge_final_gradient_floor: f64,
pin_initial_rho: bool,
}
impl Default for CeilingPathologyConfig {
fn default() -> Self {
Self {
n: 96,
p: 96,
harmonics: 2,
sigma: 0.05,
inner_max_iter: 8,
outer_max_iter: 8,
initial_step_norm: 0.25,
materialization_ratio_floor: 0.05,
step_collapse_radius: 1.0e-3,
huge_final_gradient_floor: 10.0,
pin_initial_rho: true,
}
}
}
#[derive(Clone, Debug)]
struct CeilingPathologyReport {
initial_cost: f64,
initial_grad_norm: f64,
predicted_decrease: f64,
actual_decrease: f64,
materialization_ratio: f64,
outer_converged: bool,
outer_iterations: usize,
final_value: f64,
final_grad_norm: f64,
rho_displacement: f64,
ev: f64,
telemetry: OuterProbeTelemetry,
outer_error: Option<String>,
predicted_decrease_not_materializing: bool,
step_collapsed: bool,
huge_final_gradient: bool,
live_lock_present: bool,
}
fn l2_norm(v: &Array1<f64>) -> f64 {
v.iter().map(|x| x * x).sum::<f64>().sqrt()
}
fn seeded_k1_circle_objective(
cfg: CeilingPathologyConfig,
) -> (
Array2<f64>,
SaeManifoldRho,
Array1<f64>,
SaeManifoldOuterObjective,
) {
let z = one_circle_wide_target(cfg.n, cfg.p, cfg.sigma);
let (term, seed_dispersion) = two_circle_periodic_term(z.view(), 1, cfg.harmonics);
let mode = AssignmentMode::ibp_map(1.0, 1.0, false);
let init_rho = SaeManifoldRho::new(0.02_f64.ln(), 1.0_f64.ln(), vec![array![0.0]])
.seed_scaled_by_dispersion_for_assignment(seed_dispersion, mode)
.unwrap();
let seed = init_rho.to_flat();
let objective = SaeManifoldOuterObjective::new(
term,
z.clone(),
None,
init_rho.clone(),
cfg.inner_max_iter,
0.04,
1.0e-6,
1.0e-6,
);
(z, init_rho, seed, objective)
}
fn run_ceiling_vs_pathology_instrument(cfg: CeilingPathologyConfig) -> CeilingPathologyReport {
let probe_seeded = seeded_k1_circle_objective(cfg);
let seed_probe = probe_seeded.2;
let mut probe_objective = probe_seeded.3;
let initial = OuterObjective::eval(&mut probe_objective, &seed_probe)
.expect("#2156 instrument initial REML gradient eval must complete");
let initial_grad_norm = l2_norm(&initial.gradient);
let mut trial = seed_probe.clone();
if initial_grad_norm.is_finite() && initial_grad_norm > 0.0 {
let scale = cfg.initial_step_norm / initial_grad_norm;
for idx in 0..trial.len() {
trial[idx] -= scale * initial.gradient[idx];
}
}
let predicted_decrease = if initial_grad_norm.is_finite() {
cfg.initial_step_norm * initial_grad_norm
} else {
f64::NAN
};
let trial_cost = OuterObjective::eval_cost(&mut probe_objective, &trial)
.expect("#2156 instrument initial REML value probe must complete");
let actual_decrease = initial.cost - trial_cost;
let materialization_ratio = if predicted_decrease.is_finite()
&& predicted_decrease > f64::MIN_POSITIVE
&& actual_decrease.is_finite()
{
actual_decrease / predicted_decrease
} else {
f64::NAN
};
let predicted_decrease_not_materializing = materialization_ratio.is_finite()
&& materialization_ratio < cfg.materialization_ratio_floor;
let fit_seeded = seeded_k1_circle_objective(cfg);
let z = fit_seeded.0;
let seed = fit_seeded.2;
let mut objective = fit_seeded.3;
let n_params = seed.len();
let mut problem = OuterProblem::new(n_params)
.with_max_iter(cfg.outer_max_iter)
.with_seed_config(gam_problem::SeedConfig {
max_seeds: 1,
seed_budget: 1,
..Default::default()
});
if cfg.pin_initial_rho {
problem = problem.with_initial_rho(seed.clone());
}
let run = problem.run(&mut objective, "SAE manifold ceiling-vs-pathology #2156");
let telemetry = objective.probe_telemetry();
match run {
Ok(result) => {
let final_grad_norm = result.final_grad_norm.unwrap_or(f64::NAN);
let rho_displacement = l2_norm(&(&result.rho - &seed));
let step_collapsed =
rho_displacement.is_finite() && rho_displacement <= cfg.step_collapse_radius;
let huge_final_gradient =
final_grad_norm.is_finite() && final_grad_norm >= cfg.huge_final_gradient_floor;
objective
.certify_outer_result(&result)
.expect("ceiling-pathology outer result must certify the installed state");
let fitted = objective.into_fitted().expect("outer fit was evaluated");
let ev = global_ev(z.view(), fitted.term.fitted().view());
let live_lock_present =
predicted_decrease_not_materializing && step_collapsed && huge_final_gradient;
CeilingPathologyReport {
initial_cost: initial.cost,
initial_grad_norm,
predicted_decrease,
actual_decrease,
materialization_ratio,
outer_converged: result.converged,
outer_iterations: result.iterations,
final_value: result.final_value,
final_grad_norm,
rho_displacement,
ev,
telemetry,
outer_error: None,
predicted_decrease_not_materializing,
step_collapsed,
huge_final_gradient,
live_lock_present,
}
}
Err(err) => CeilingPathologyReport {
initial_cost: initial.cost,
initial_grad_norm,
predicted_decrease,
actual_decrease,
materialization_ratio,
outer_converged: false,
outer_iterations: 0,
final_value: f64::NAN,
final_grad_norm: f64::NAN,
rho_displacement: f64::NAN,
ev: f64::NAN,
telemetry,
outer_error: Some(err.to_string()),
predicted_decrease_not_materializing,
step_collapsed: false,
huge_final_gradient: false,
live_lock_present: true,
},
}
}
#[test]
fn wide_p_outer_reml_terminates_within_probe_budget_2080() {
let n = 96usize;
let p = 96usize;
let k = 2usize;
let harmonics = 2usize; let (ev, telemetry) = run_wide_outer_fit(n, p, k, harmonics);
eprintln!(
"[#2080] wide-p outer fit: ev={ev:.4}, criterion_calls={}, \
infeasible(non_pd_per_row={},cross_row={},schur={},inner_nc={}), \
infeasible_criterion_evals={}, reactive_scalar_installs={}, \
reactive_target_restores={}",
telemetry.criterion_calls,
telemetry.infeasible_non_pd_per_row,
telemetry.infeasible_cross_row,
telemetry.infeasible_schur,
telemetry.infeasible_inner_not_converged,
telemetry.infeasible_criterion_evals,
telemetry.reactive_scalar_installs,
telemetry.reactive_target_restores,
);
assert!(
telemetry.reactive_scalar_installs > 0,
"the initially undefined wide-K=2 seed must traverse genuine objective-installed scalar waypoints"
);
assert!(
telemetry.reactive_target_restores > 0,
"the wide-K=2 continuation must restore the objective's literal scalar target before certification"
);
assert!(
telemetry.criterion_calls <= 64,
"outer REML issued {} criterion calls; expected a bounded (<= 64) probe budget",
telemetry.criterion_calls
);
assert!(
ev.is_finite() && ev > 0.20,
"wide-p K=2 two-circle outer fit must recover a materially positive EV \
(got {ev:.4}); two disjoint circles span a rank-4 subspace an honest K=2 \
dictionary recovers"
);
}
#[test]
fn k1_generated_seed_circle_outer_reml_does_not_livelock_2153() {
let (ev, telemetry) = run_k1_generated_seed_outer_fit(32, 24, 1);
eprintln!(
"[#2153] K=1 generated-seed outer fit: ev={ev:.4}, criterion_calls={}, \
infeasible_criterion_evals={}, infeasible_total={}",
telemetry.criterion_calls,
telemetry.infeasible_criterion_evals,
telemetry.infeasible_total(),
);
assert!(
telemetry.criterion_calls <= 32,
"#2153 K=1 generated-seed fit issued {} criterion calls; expected a \
bounded first-line-search probe budget",
telemetry.criterion_calls
);
assert!(
ev.is_finite() && ev > 0.30,
"#2153 K=1 generated-seed circle fit must converge to a real positive-EV \
basin (got {ev:.4})"
);
}
#[test]
fn ceiling_vs_pathology_outer_reml_instrument_2156() {
let report = run_ceiling_vs_pathology_instrument(CeilingPathologyConfig::default());
eprintln!(
"[#2156 ceiling-vs-pathology] initial_cost={:.6e}, initial_grad_norm={:.6e}, \
predicted_decrease={:.6e}, actual_decrease={:.6e}, materialization_ratio={:.6e}, \
outer_converged={}, outer_iterations={}, final_value={:.6e}, final_grad_norm={:.6e}, \
rho_displacement={:.6e}, ev={:.4}, criterion_calls={}, \
infeasible_criterion_evals={}, infeasible_total={}, outer_error={:?}, \
predicted_not_materializing={}, step_collapsed={}, huge_final_gradient={}, \
live_lock_present={}",
report.initial_cost,
report.initial_grad_norm,
report.predicted_decrease,
report.actual_decrease,
report.materialization_ratio,
report.outer_converged,
report.outer_iterations,
report.final_value,
report.final_grad_norm,
report.rho_displacement,
report.ev,
report.telemetry.criterion_calls,
report.telemetry.infeasible_criterion_evals,
report.telemetry.infeasible_total(),
report.outer_error,
report.predicted_decrease_not_materializing,
report.step_collapsed,
report.huge_final_gradient,
report.live_lock_present,
);
assert!(
!report.live_lock_present,
"#2156 CEILING-vs-PATHOLOGY instrument detected the live-lock signature: \
predicted decrease did not materialize, accepted ρ step collapsed, and \
final gradient stayed huge; report={report:?}"
);
}
#[test]
fn wide_p_outer_reml_terminates_k3_heavy_2080() {
let (ev, telemetry) = run_wide_outer_fit(96, 96, 3, 2);
eprintln!(
"[#2080 heavy] K=3 wide-p outer fit: ev={ev:.4}, criterion_calls={}, \
infeasible_total={}",
telemetry.criterion_calls,
telemetry.infeasible_total(),
);
assert!(telemetry.criterion_calls <= 96);
assert!(ev.is_finite() && ev > 0.15);
}
fn entangled_two_circle_wide_target(n: usize, p: usize, sigma: f64) -> Array2<f64> {
let mut fa = Array2::<f64>::zeros((2, p));
let mut fb = Array2::<f64>::zeros((2, p));
for j in 0..p {
fa[[0, j]] = deterministic_circle_noise(j, 0);
fa[[1, j]] = deterministic_circle_noise(j, 1);
fb[[0, j]] = deterministic_circle_noise(j, 2);
fb[[1, j]] = deterministic_circle_noise(j, 3);
}
for f in [&mut fa, &mut fb] {
for r in 0..2 {
let nrm = (0..p).map(|j| f[[r, j]] * f[[r, j]]).sum::<f64>().sqrt();
for j in 0..p {
f[[r, j]] /= nrm.max(1.0e-300);
}
}
}
let mut n1 = 1usize;
let root = (n as f64).sqrt() as usize;
for d in 1..=root.max(1) {
if n % d == 0 {
n1 = d;
}
}
let n1 = n1.max(1);
let n2 = (n / n1).max(1);
let mut z = Array2::<f64>::zeros((n, p));
for row in 0..n {
let i = row % n1;
let j = (row / n1) % n2;
let ta = std::f64::consts::TAU * (i as f64) / (n1 as f64);
let tb = std::f64::consts::TAU * (j as f64) / (n2 as f64);
let (ca, sa) = (ta.cos(), ta.sin());
let (cb, sb) = (tb.cos(), tb.sin());
for jj in 0..p {
z[[row, jj]] = ca * fa[[0, jj]]
+ sa * fa[[1, jj]]
+ cb * fb[[0, jj]]
+ sb * fb[[1, jj]]
+ sigma * deterministic_circle_noise(row, jj + 7);
}
}
for j in 0..p {
let mut mean = 0.0_f64;
for row in 0..n {
mean += z[[row, j]];
}
mean /= n as f64;
let mut var = 0.0_f64;
for row in 0..n {
let d = z[[row, j]] - mean;
var += d * d;
}
let sd = (var / n as f64).sqrt().max(1.0e-12);
for row in 0..n {
z[[row, j]] = (z[[row, j]] - mean) / sd;
}
}
z
}
#[test]
fn entangled_two_circle_outer_reml_separates_2080() {
let n = 240usize;
let p = 96usize;
let k = 2usize;
let harmonics = 2usize;
let z = entangled_two_circle_wide_target(n, p, 0.03);
let isa_certified = match super::isa_seed::capture_signal_span(z.view(), k) {
Ok(Some(parts)) => super::isa_seed::isa_extract_certified_planes(
z.view(),
&parts,
k,
&super::isa_seed::IsaSeedConfig::default(),
)
.len(),
_ => 0,
};
let (term, seed_dispersion) = two_circle_periodic_term(z.view(), k, harmonics);
let mode = AssignmentMode::ibp_map(1.0, 1.0, false);
let init_rho = SaeManifoldRho::new(0.02_f64.ln(), 1.0_f64.ln(), vec![array![0.0]; k])
.seed_scaled_by_dispersion_for_assignment(seed_dispersion, mode)
.unwrap();
let seed = init_rho.to_flat();
let n_params = seed.len();
let mut objective =
SaeManifoldOuterObjective::new(term, z.clone(), None, init_rho, 8, 0.04, 1.0e-6, 1.0e-6);
let result = OuterProblem::new(n_params)
.with_initial_rho(seed)
.with_max_iter(4)
.with_seed_config(gam_problem::SeedConfig {
max_seeds: 1,
seed_budget: 1,
..Default::default()
})
.run(&mut objective, "SAE manifold entangled two-circle")
.expect("#2080 entangled two-circle outer REML fit must terminate, not abort");
assert!(
result.converged,
"#2080 entangled acceptance requires a converged outer REML optimum: \
iterations={}, final_value={:.6e}, final_grad_norm={:?}",
result.iterations, result.final_value, result.final_grad_norm,
);
objective
.certify_outer_result(&result)
.expect("entangled two-circle outer result must certify the installed state");
let fitted = objective.into_fitted().expect("outer fit was evaluated");
let ev = global_ev(z.view(), fitted.term.fitted().view());
let mut norms = vec![0.0_f64; k];
for (i, atom) in fitted.term.atoms.iter().enumerate() {
norms[i] = atom
.decoder_coefficients
.iter()
.map(|v| v * v)
.sum::<f64>()
.sqrt();
}
let hi = norms.iter().copied().fold(0.0_f64, f64::max);
let lo = norms.iter().copied().fold(f64::INFINITY, f64::min);
let ratio = lo / hi.max(1.0e-300);
eprintln!(
"[#2080 entangled] isa_certified_planes={isa_certified}/{k}, ev={ev:.4}, \
decoder_norms={norms:?}, ratio={ratio:.3}"
);
assert!(
ev.is_finite() && ev > 0.20,
"entangled K=2 fit must recover a materially positive EV (got {ev:.4})"
);
assert!(hi > 0.0, "at least one atom must carry decoder norm");
assert!(
ratio > 0.30,
"both entangled circles must be recovered on DISTINCT atoms (no co-collapse); \
norms={norms:?} ratio={ratio:.3} — a ratio near the ~0.13 collapse regime is the \
μ̂ = 1.0 shared-subspace collapse the joint-Jacobi ISA seed must prevent"
);
}
#[test]
fn small_fold_high_rank_circle_inner_solve_converges_2138() {
let n = 35usize;
let p = 12usize;
let harmonics = 4usize;
let m = 1 + 2 * harmonics;
let mut frames = Array2::<f64>::zeros((2 * harmonics, p));
for h in 0..2 * harmonics {
for j in 0..p {
frames[[h, j]] = deterministic_circle_noise(h, j);
}
}
let mut z = Array2::<f64>::zeros((n, p));
for row in 0..n {
let t = row as f64 / n as f64;
for hh in 0..harmonics {
let ang = std::f64::consts::TAU * (hh as f64 + 1.0) * t;
let (c, s) = (ang.cos(), ang.sin());
for j in 0..p {
z[[row, j]] += c * frames[[2 * hh, j]] + s * frames[[2 * hh + 1, j]];
}
}
}
for j in 0..p {
let mean: f64 = (0..n).map(|r| z[[r, j]]).sum::<f64>() / n as f64;
let var: f64 = (0..n).map(|r| (z[[r, j]] - mean).powi(2)).sum::<f64>() / n as f64;
let sd = var.sqrt().max(1.0e-12);
for r in 0..n {
z[[r, j]] = (z[[r, j]] - mean) / sd;
}
}
let evaluator: Arc<dyn SaeBasisSecondJet> =
Arc::new(PeriodicHarmonicEvaluator::new(m).unwrap());
let seed_coords =
sae_pca_seed_initial_coords(z.view(), &[SaeAtomBasisKind::Periodic], &[1]).unwrap();
let coords = seed_coords.slice(s![0, .., 0..1]).to_owned();
let (phi, jet) = evaluator.evaluate(coords.view()).unwrap();
let mut xtx = fast_atb(&phi, &phi);
for i in 0..m {
xtx[[i, i]] += 1.0e-8;
}
let xtz = fast_atb(&phi, &z);
let decoder = xtx.cholesky(Side::Lower).unwrap().solve_mat(&xtz);
let atom = SaeManifoldAtom::new(
"circle",
SaeAtomBasisKind::Periodic,
1,
phi,
jet,
decoder,
Array2::<f64>::eye(m),
)
.unwrap()
.with_basis_evaluator(evaluator.clone());
let assignment = SaeAssignment::from_blocks_with_mode_and_manifolds(
Array2::<f64>::from_elem((n, 1), 6.0),
vec![coords],
vec![LatentManifold::Circle { period: 1.0 }],
AssignmentMode::ibp_map(1.0, 1.0, false),
)
.unwrap();
let base = SaeManifoldTerm::new(vec![atom], assignment).unwrap();
for &smooth in &[-8.0_f64, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0] {
let mut t = base.clone();
let r = SaeManifoldRho::new(0.02_f64.ln(), smooth, vec![array![0.0]]);
let evaluated = t
.reml_criterion_with_cache(z.view(), &r, None, 60, 0.04, 1.0e-6, 1.0e-6)
.unwrap_or_else(|err| {
panic!(
"#2138: high-working-rank (m={m}) circle inner solve must converge at a \
small (n={n}) fold, smoothing={smooth}, not diverge into a \
RemlConvergenceError; got: {err}"
)
});
let cost = evaluated.0;
let ev = global_ev(z.view(), t.fitted().view());
assert_eq!(
t.atoms[0].basis_size(),
m,
"#2138: the multi-harmonic target must keep the atom at full working rank m={m}",
);
assert!(
cost.is_finite(),
"#2138: inner solve returned a non-finite REML cost at smoothing={smooth}",
);
assert!(
ev.is_finite() && ev > 0.30,
"#2138: high-working-rank small-fold circle fit must recover a materially positive \
EV at smoothing={smooth} (got {ev:.4}), proving the inner solve reached a real \
basin rather than a diverged / collapsed state",
);
}
}
#[test]
fn profile_wide_p_criterion_cost_2080() {
let harmonics = 2usize; for &p in &[16usize, 32, 48] {
let n = 96usize;
let z = one_circle_wide_target(n, p, 0.05);
let (term, seed_dispersion) = two_circle_periodic_term(z.view(), 1, harmonics);
let mode = AssignmentMode::ibp_map(1.0, 1.0, false);
let rho = SaeManifoldRho::new(0.02_f64.ln(), 1.0_f64.ln(), vec![array![0.0]])
.seed_scaled_by_dispersion_for_assignment(seed_dispersion, mode)
.unwrap();
let beta_dim = term.beta_dim();
let mut ta = term.clone();
let mut rho_a = rho.clone();
let a0 = std::time::Instant::now();
ta.run_joint_fit_arrow_schur(z.view(), &mut rho_a, None, 8, 0.04, 1.0e-6, 1.0e-6)
.expect("inner solve");
let dt_a = a0.elapsed().as_secs_f64();
let mut tb = term.clone();
let b0 = std::time::Instant::now();
let evaluated = tb
.reml_criterion_with_cache_refine_policy(
z.view(),
&rho,
None,
8,
0.04,
1.0e-6,
1.0e-6,
true,
)
.expect("full criterion");
let dt_full = b0.elapsed().as_secs_f64();
let dt_b = (dt_full - dt_a).max(0.0);
assert!(
evaluated.0.is_finite(),
"#2080/#1094: the outer REML criterion must be RANKABLE (finite) on a \
correctly-specified K=1 wide-p circle at p={p}; a non-finite value here \
is the probe-refusal failure class (got {})",
evaluated.0
);
eprintln!(
"[#2080 profile] p={p:>3} beta_dim={beta_dim:>4} | inner_solve={dt_a:8.3}s | logdet_phase={dt_b:8.3}s | full={dt_full:8.3}s | cost={:.4}",
evaluated.0
);
}
}