use std::ops::{Deref, DerefMut};
use super::FilterBase;
use crate::Result;
use crate::algorithms::Rls;
use crate::filters::ProcessingMode;
use crate::types::{Float, WindowSize};
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct RlsOptions<F: Float> {
pub forgetting_factor: F,
pub p_init_scale: F,
pub window_size: usize,
}
impl<F: Float> Default for RlsOptions<F> {
fn default() -> Self {
#[allow(
clippy::unwrap_used,
clippy::missing_panics_doc,
reason = "Trivial conversions"
)]
Self {
forgetting_factor: F::from(0.999).unwrap(),
p_init_scale: F::from(0.001).unwrap(),
window_size: 8,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct RlsFilter<F: Float> {
inner: FilterBase<F, Rls<F>>,
}
impl<F: Float> RlsFilter<F> {
#[allow(clippy::needless_pass_by_value, reason = "All fields are moved")]
pub fn new(options: RlsOptions<F>, mode: ProcessingMode) -> Result<Self> {
let window_size = WindowSize::new(options.window_size)?;
let block_size = mode.block_size()?;
let rls = Rls::new(options.forgetting_factor, options.p_init_scale, window_size)?;
let filter = FilterBase::new(rls, block_size);
Ok(Self { inner: filter })
}
}
impl<F: Float> Deref for RlsFilter<F> {
type Target = FilterBase<F, Rls<F>>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<F: Float> DerefMut for RlsFilter<F> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::indexing_slicing, reason = "Tests")]
mod tests {
use super::*;
use crate::types::BlockSize;
#[test]
fn new_works() {
let forgetting_factor = 0.999;
let p_init_scale = 1e-4;
let window_size = 16;
let filter = RlsFilter::new(
RlsOptions {
forgetting_factor,
p_init_scale,
window_size,
},
ProcessingMode::Sample,
)
.unwrap();
let expected_inner = FilterBase::new(
Rls::new(
forgetting_factor,
p_init_scale,
WindowSize::new(window_size).unwrap(),
)
.unwrap(),
BlockSize::new(1).unwrap(),
);
assert_eq!(filter.inner, expected_inner);
assert_eq!(filter.window_size(), window_size);
}
#[test]
fn load_weights_works() {
let forgetting_factor = 0.999;
let p_init_scale = 1e-4;
let weights = vec![1.0, 2.0, 3.0];
let filter = {
let mut filter = RlsFilter::new(
RlsOptions {
forgetting_factor,
p_init_scale,
window_size: weights.len(),
},
ProcessingMode::Sample,
)
.unwrap();
filter.load_weights(weights.clone()).unwrap();
filter
};
let expected_inner = {
let mut expected_inner = FilterBase::new(
Rls::new(
forgetting_factor,
p_init_scale,
WindowSize::new(weights.len()).unwrap(),
)
.unwrap(),
BlockSize::new(1).unwrap(),
);
expected_inner.load_weights(weights.clone()).unwrap();
expected_inner
};
assert_eq!(filter.inner, expected_inner);
assert_eq!(filter.window_size(), weights.len());
}
}