use crate::error::SparseResult;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
#[derive(Default)]
pub enum SmootherType {
#[default]
Linear,
MLP,
Chebyshev,
}
#[derive(Debug, Clone)]
pub struct LearnedSmootherConfig {
pub smoother_type: SmootherType,
pub learning_rate: f64,
pub max_training_steps: usize,
pub convergence_tol: f64,
pub omega: f64,
pub pre_sweeps: usize,
pub post_sweeps: usize,
}
impl Default for LearnedSmootherConfig {
fn default() -> Self {
Self {
smoother_type: SmootherType::Linear,
learning_rate: 0.01,
max_training_steps: 1000,
convergence_tol: 1e-6,
omega: 2.0 / 3.0,
pre_sweeps: 2,
post_sweeps: 2,
}
}
}
#[derive(Debug, Clone)]
pub struct TrainingConfig {
pub learning_rate: f64,
pub max_epochs: usize,
pub batch_size: usize,
pub convergence_tol: f64,
pub momentum: f64,
}
impl Default for TrainingConfig {
fn default() -> Self {
Self {
learning_rate: 0.01,
max_epochs: 100,
batch_size: 16,
convergence_tol: 1e-8,
momentum: 0.0,
}
}
}
#[derive(Debug, Clone)]
pub struct SmootherWeights {
pub matrices: Vec<Vec<f64>>,
pub biases: Vec<Vec<f64>>,
pub layer_dims: Vec<(usize, usize)>,
}
impl SmootherWeights {
pub fn empty() -> Self {
Self {
matrices: Vec::new(),
biases: Vec::new(),
layer_dims: Vec::new(),
}
}
pub fn diagonal(diag: Vec<f64>) -> Self {
let n = diag.len();
Self {
matrices: vec![diag],
biases: vec![vec![0.0; n]],
layer_dims: vec![(n, n)],
}
}
pub fn num_parameters(&self) -> usize {
let mat_params: usize = self.matrices.iter().map(|m| m.len()).sum();
let bias_params: usize = self.biases.iter().map(|b| b.len()).sum();
mat_params + bias_params
}
}
#[derive(Debug, Clone)]
pub struct SmootherMetrics {
pub spectral_radius_reduction: f64,
pub convergence_factor: f64,
pub residual_reduction: f64,
pub training_loss_history: Vec<f64>,
}
impl SmootherMetrics {
pub fn new() -> Self {
Self {
spectral_radius_reduction: 1.0,
convergence_factor: 1.0,
residual_reduction: 1.0,
training_loss_history: Vec::new(),
}
}
}
impl Default for SmootherMetrics {
fn default() -> Self {
Self::new()
}
}
pub trait Smoother {
fn smooth(
&self,
a_values: &[f64],
a_row_ptr: &[usize],
a_col_idx: &[usize],
x: &mut [f64],
b: &[f64],
n_sweeps: usize,
) -> SparseResult<()>;
fn train_step(
&mut self,
a_values: &[f64],
a_row_ptr: &[usize],
a_col_idx: &[usize],
x: &mut [f64],
b: &[f64],
x_exact: &[f64],
lr: f64,
) -> SparseResult<f64>;
}