use ndarray::{Array1, Array2};
use regression_diagnostics::multicollinearity::vif;
use regression_diagnostics::regularized::{select_lambda_gcv, RidgeFit};
use regression_diagnostics::OlsFit;
fn main() {
let rows = [
[1.0, 2.05],
[2.0, 3.98],
[3.0, 6.02],
[4.0, 8.01],
[5.0, 9.97],
[6.0, 12.03],
[7.0, 13.98],
[8.0, 16.02],
[9.0, 17.99],
[10.0, 20.05],
];
let yv = [2.1, 3.9, 6.2, 7.8, 10.1, 11.9, 14.2, 15.8, 18.1, 19.9];
let n = rows.len();
let mut x = Array2::<f64>::ones((n, 3));
for i in 0..n {
x[(i, 1)] = rows[i][0];
x[(i, 2)] = rows[i][1];
}
let y = Array1::from(yv.to_vec());
let ols = OlsFit::new(x.clone(), y.clone()).unwrap();
let ols_vif = vif(&ols);
println!("OLS (no regularization):");
println!(" coefficients: {:?}", ols.coefficients().to_vec());
println!(" VIF x1 = {:.1}, x2 = {:.1}\n", ols_vif[1], ols_vif[2]);
println!("Ridge — VIF and effective df shrink as λ grows:");
println!(" λ VIF x1 VIF x2 eff.df GCV");
for &lam in &[0.0, 0.1, 1.0, 10.0, 100.0] {
let r = RidgeFit::new(x.clone(), y.clone(), lam).unwrap();
let rv = r.ridge_vif();
println!(
" {:>7.2} {:>8.2} {:>8.2} {:>7.3} {:>8.4}",
lam,
rv[1],
rv[2],
r.effective_df(),
r.gcv()
);
}
let grid: Vec<f64> = (0..=8).map(|k| 10f64.powf(k as f64 / 2.0 - 2.0)).collect();
let best = select_lambda_gcv(x, y, &grid).unwrap();
println!(
"\nGCV-selected λ = {:.4} (effective df {:.3}, GCV {:.4})",
best.lambda(),
best.effective_df(),
best.gcv()
);
println!(
"\nRegularization trades a little bias for a large drop in coefficient\n\
variance: the VIFs collapse from the OLS values above toward ~1, which is\n\
the concrete, measurable effect of ridge on multicollinearity."
);
}