tiny_solver/linear/
sparse_qr.rs1use super::sparse::SparseLinearSolver;
2use faer::linalg::solvers::SolveLstsqCore;
3use faer::sparse::linalg::solvers;
5
6#[derive(Debug, Clone)]
7pub struct SparseQRSolver {
8 symbolic_pattern: Option<solvers::SymbolicQr<usize>>,
9}
10
11impl SparseQRSolver {
12 pub fn new() -> Self {
13 SparseQRSolver {
14 symbolic_pattern: None,
15 }
16 }
17}
18impl Default for SparseQRSolver {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23impl SparseLinearSolver for SparseQRSolver {
24 fn solve(
25 &mut self,
26 residuals: &faer::Mat<f64>,
27 jacobians: &faer::sparse::SparseColMat<usize, f64>,
28 ) -> Option<faer::Mat<f64>> {
29 if self.symbolic_pattern.is_none() {
30 self.symbolic_pattern =
31 Some(solvers::SymbolicQr::try_new(jacobians.symbolic()).unwrap());
32 }
33
34 let sym = self.symbolic_pattern.as_ref().unwrap();
35 if let Ok(qr) = solvers::Qr::try_new_with_symbolic(sym.clone(), jacobians.as_ref()) {
36 let mut minus_residuals = -residuals;
37 qr.solve_lstsq_in_place_with_conj(faer::Conj::No, minus_residuals.as_mut());
38 Some(minus_residuals)
39 } else {
40 None
41 }
42 }
43
44 fn solve_jtj(
45 &mut self,
46 jtr: &faer::Mat<f64>,
47 jtj: &faer::sparse::SparseColMat<usize, f64>,
48 ) -> Option<faer::Mat<f64>> {
49 if self.symbolic_pattern.is_none() {
50 self.symbolic_pattern = Some(solvers::SymbolicQr::try_new(jtj.symbolic()).unwrap());
51 }
52
53 let sym = self.symbolic_pattern.as_ref().unwrap();
54 if let Ok(qr) = solvers::Qr::try_new_with_symbolic(sym.clone(), jtj.as_ref()) {
55 let mut minus_jtr = -jtr;
56 qr.solve_lstsq_in_place_with_conj(faer::Conj::No, minus_jtr.as_mut());
57 Some(minus_jtr)
58 } else {
59 None
60 }
61 }
62}