use irithyll::projection::{ProjectedLearner, ProjectionConfig};
use irithyll::{rls, StreamingLearner};
fn xorshift64(state: &mut u64) -> f64 {
*state ^= *state << 13;
*state ^= *state >> 7;
*state ^= *state << 17;
(*state as f64) / (u64::MAX as f64)
}
fn main() {
eprintln!("=== Irithyll: ProjectedLearner (Online Projection Learning) ===");
eprintln!("20 features, only 5 relevant. Rank-8 projection vs raw RLS.\n");
let (d_in, rank, n_samples) = (20, 8, 2000);
let config = ProjectionConfig::builder()
.rank(rank)
.warmup(100)
.supervised_lr(0.01)
.build()
.unwrap();
let mut projected = ProjectedLearner::from_learner(rls(0.99), d_in, config);
let mut raw = rls(0.99);
let mut rng: u64 = 0xDEAD_BEEF_1234_5678;
let (mut proj_sse, mut raw_sse, mut count) = (0.0, 0.0, 0u64);
eprintln!("--- Training ({} samples) ---", n_samples);
for i in 0..n_samples {
let x: Vec<f64> = (0..d_in)
.map(|_| (xorshift64(&mut rng) - 0.5) * 2.0)
.collect();
let noise = (xorshift64(&mut rng) - 0.5) * 0.1;
let y = 3.0 * x[0] + 2.0 * x[1] - 1.5 * x[2] + 0.8 * x[3] + x[4] + noise;
let proj_pred = projected.predict(&x);
let raw_pred = raw.predict(&x);
let proj_err = y - proj_pred;
let raw_err = y - raw_pred;
proj_sse += proj_err * proj_err;
raw_sse += raw_err * raw_err;
count += 1;
projected.train(&x, y);
raw.train(&x, y);
if (i + 1) % 500 == 0 {
let proj_rmse = (proj_sse / count as f64).sqrt();
let raw_rmse = (raw_sse / count as f64).sqrt();
eprintln!(
" Samples: {:>5} | Projected RMSE: {:.4} | Raw RMSE: {:.4}",
i + 1,
proj_rmse,
raw_rmse,
);
}
}
let proj_rmse = (proj_sse / count as f64).sqrt();
let raw_rmse = (raw_sse / count as f64).sqrt();
eprintln!("\n--- Results ---");
eprintln!(" Projected RMSE (rank={}): {:.4}", rank, proj_rmse);
eprintln!(" Raw RLS RMSE (dim={}): {:.4}", d_in, raw_rmse);
eprintln!(" Warmup complete: {}", projected.warmup_complete());
eprintln!(" Samples seen: {}", projected.n_samples_seen());
eprintln!("\n[DONE] ProjectedLearner example complete.");
}