arr_rs/linalg/operations/
eigen.rs1use crate::{
2 core::prelude::*,
3 errors::prelude::*,
4 linalg::prelude::*,
5 numeric::prelude::*,
6 validators::prelude::*,
7};
8
9pub trait ArrayLinalgEigen<N: NumericOps> where Self: Sized + Clone {
11
12 fn eigvals(&self) -> Result<Vec<Array<N>>, ArrayError>;
28
29 fn eig(&self) -> LinalgResult<N>;
46}
47
48impl <N: NumericOps> ArrayLinalgEigen<N> for Array<N> {
49
50 fn eigvals(&self) -> Result<Vec<Self>, ArrayError> {
51 self.is_square()?;
52 if self.ndim()? == 2 {
53 let mut h = self.hessenberg_reduction()?;
54
55 let mut max_iter = 10000;
56 while max_iter > 0 {
58 let (q, r) = h.qr()?[0].clone();
59 h = r.dot(&q)?.hessenberg_reduction()?;
60 if h.is_convergent()? { break }
61 max_iter -= 1;
62 }
63
64 let mut eigenvalues = vec![];
65 for i in 0..self.get_shape()?[0] {
66 eigenvalues.push(h.at(&[i, i])?);
67 }
68
69 Ok(vec![Self::flat(eigenvalues)?])
70 } else {
71 let shape = self.get_shape()?;
72 let sub_shape = shape[self.ndim()? - 2 ..].to_vec();
73 let vals = self
74 .ravel()?
75 .split(self.len()? / sub_shape.iter().product::<usize>(), None)?
76 .iter()
77 .map(|arr| arr.reshape(&sub_shape).eigvals())
78 .collect::<Vec<Result<Vec<Self>, _>>>()
79 .has_error()?.into_iter()
80 .flat_map(Result::unwrap)
81 .collect::<Vec<Self>>();
82 Ok(vals)
83 }
84 }
85
86 fn eig(&self) -> LinalgResult<N> {
87 let mut results = vec![];
88 for eigenvalues in self.eigvals()? {
89 let mut vectors = vec![];
90 for value in eigenvalues.get_elements()? {
91 let mut vector = (self.clone() - (Self::eye(self.get_shape()?[0], None, None)? * value)?)
92 .solve(&Self::ones(vec![self.get_shape()?[0]])?)?;
93 vector /= vector
94 .norm(None::<NormOrd>, None, None)
95 .broadcast_to(vector.get_shape()?)?;
96 vectors.push(vector);
97 }
98 let eigenvectors = vectors.iter()
99 .flatten()
100 .copied()
101 .collect::<Self>()
102 .reshape(&[eigenvalues.len()?; 2])
103 .transpose(None)?;
104 results.push((eigenvalues, eigenvectors));
105 }
106
107 Ok(results)
108 }
109}
110
111impl <N: NumericOps> ArrayLinalgEigen<N> for Result<Array<N>, ArrayError> {
112
113 fn eigvals(&self) -> Result<Vec<Array<N>>, ArrayError> {
114 self.clone()?.eigvals()
115 }
116
117 fn eig(&self) -> LinalgResult<N> {
118 self.clone()?.eig()
119 }
120}