sklears_decomposition/dictionary_learning/
coordinate_descent.rs1use scirs2_core::ndarray::{Array1, Array2};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6use sklears_core::{error::Result, types::Float};
7
8#[derive(Debug, Clone)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11pub struct CDConfig {
12 pub max_iter: usize,
14 pub tol: Float,
16 pub alpha: Float,
18}
19
20impl Default for CDConfig {
21 fn default() -> Self {
22 Self {
23 max_iter: 1000,
24 tol: 1e-4,
25 alpha: 1.0,
26 }
27 }
28}
29
30#[derive(Debug, Clone)]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33pub struct CDResult {
34 pub coefficients: Array1<Float>,
36 pub objective: Float,
38 pub n_iter: usize,
40}
41
42#[derive(Debug, Clone)]
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45pub struct SoftThresholding {
46 pub threshold: Float,
47}
48
49impl SoftThresholding {
50 pub fn new(threshold: Float) -> Self {
51 Self { threshold }
52 }
53
54 pub fn apply(&self, x: Float) -> Float {
55 if x > self.threshold {
56 x - self.threshold
57 } else if x < -self.threshold {
58 x + self.threshold
59 } else {
60 0.0
61 }
62 }
63}
64
65#[derive(Debug, Clone)]
67#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
68pub struct CDEncoder {
69 config: CDConfig,
70}
71
72impl CDEncoder {
73 pub fn new(config: CDConfig) -> Self {
74 Self { config }
75 }
76
77 pub fn encode(&self, dictionary: &Array2<Float>, _signal: &Array1<Float>) -> Result<CDResult> {
79 let n_atoms = dictionary.nrows();
80 let coefficients = Array1::zeros(n_atoms);
81
82 let objective = 0.0;
84
85 Ok(CDResult {
86 coefficients,
87 objective,
88 n_iter: 0,
89 })
90 }
91}