use crate::core::Expression;
use crate::matrices::types::*;
use crate::matrices::unified::Matrix;
use crate::simplify::Simplify;
impl Matrix {
pub fn qr_decomposition(&self) -> Option<QRDecomposition> {
match self {
Matrix::Identity(data) => Some(QRDecomposition {
q: Matrix::identity(data.size),
r: Matrix::identity(data.size),
}),
Matrix::Zero(data) => Some(QRDecomposition {
q: Matrix::identity(data.rows),
r: Matrix::zero(data.rows, data.cols),
}),
_ => {
self.gram_schmidt_qr()
}
}
}
fn gram_schmidt_qr(&self) -> Option<QRDecomposition> {
let (rows, cols) = self.dimensions();
let mut q_columns: Vec<Vec<Expression>> = Vec::new();
let mut r_elements = vec![vec![Expression::integer(0); cols]; cols];
for (j, r_column) in r_elements.iter_mut().enumerate() {
let mut column: Vec<Expression> = (0..rows).map(|i| self.get_element(i, j)).collect();
for (k, q_col) in q_columns.iter().enumerate() {
let dot_product = self.vector_dot(&column, q_col);
r_column[k] = dot_product.clone();
for (col_elem, q_elem) in column.iter_mut().zip(q_col) {
let old_val = col_elem.clone();
let subtract_val = Expression::mul(vec![dot_product.clone(), q_elem.clone()]);
*col_elem = Expression::add(vec![
old_val,
Expression::mul(vec![Expression::integer(-1), subtract_val]),
])
.simplify();
}
}
let norm = self.vector_norm(&column);
if norm.is_zero() {
return None; }
r_column[j] = norm.clone();
let q_column: Vec<Expression> = column
.iter()
.map(|elem| {
Expression::mul(vec![
elem.clone(),
Expression::pow(norm.clone(), Expression::integer(-1)),
])
.simplify()
})
.collect();
q_columns.push(q_column);
}
let q_rows: Vec<Vec<Expression>> = (0..rows)
.map(|i| {
(0..cols)
.map(|j| {
if j < q_columns.len() {
q_columns[j][i].clone()
} else {
Expression::integer(0)
}
})
.collect()
})
.collect();
Some(QRDecomposition {
q: Matrix::dense(q_rows),
r: Matrix::dense(r_elements),
})
}
fn vector_dot(&self, v1: &[Expression], v2: &[Expression]) -> Expression {
if v1.len() != v2.len() {
return Expression::integer(0);
}
let products: Vec<Expression> = v1
.iter()
.zip(v2.iter())
.map(|(a, b)| Expression::mul(vec![a.clone(), b.clone()]))
.collect();
Expression::add(products).simplify()
}
fn vector_norm(&self, v: &[Expression]) -> Expression {
let sum_of_squares: Vec<Expression> = v
.iter()
.map(|x| Expression::pow(x.clone(), Expression::integer(2)))
.collect();
let sum = Expression::add(sum_of_squares).simplify();
Expression::pow(sum, Expression::rational(1, 2))
}
}