pub mod characteristic;
pub mod computation;
pub mod eigenvalues_tests;
pub mod power_methods;
use crate::core::expression::Expression;
use crate::core::symbol::Symbol;
use crate::matrices::eigenvalues::characteristic::CharacteristicPolynomial;
use crate::matrices::types::*;
use crate::matrices::unified::Matrix;
use crate::simplify::Simplify;
pub trait EigenOperations {
fn eigen_decomposition(&self) -> Option<EigenDecomposition>;
fn complex_eigen_decomposition(&self) -> Option<ComplexEigenDecomposition>;
fn eigenvalues(&self) -> Vec<Expression>;
fn characteristic_polynomial(&self) -> CharacteristicPolynomial;
fn trace(&self) -> Expression;
fn determinant_via_eigenvalues(&self) -> Expression;
fn is_diagonalizable(&self) -> bool;
fn matrix_power_eigen(&self, n: i64) -> Option<Matrix>;
fn matrix_exponential(&self) -> Option<Matrix>;
fn matrix_logarithm(&self) -> Option<Matrix>;
fn matrix_sqrt(&self) -> Option<Matrix>;
fn is_nilpotent(&self) -> bool;
}
impl EigenOperations for Matrix {
fn eigen_decomposition(&self) -> Option<EigenDecomposition> {
Matrix::eigen_decomposition(self)
}
fn complex_eigen_decomposition(&self) -> Option<ComplexEigenDecomposition> {
Matrix::complex_eigen_decomposition(self)
}
fn eigenvalues(&self) -> Vec<Expression> {
Matrix::eigenvalues(self)
}
fn characteristic_polynomial(&self) -> CharacteristicPolynomial {
let eigenvals = Matrix::eigenvalues(self);
let lambda = Symbol::scalar("lambda");
if eigenvals.is_empty() {
return CharacteristicPolynomial::new(vec![Expression::integer(0)], lambda);
}
let mut poly = CharacteristicPolynomial::new(
vec![
Expression::mul(vec![Expression::integer(-1), eigenvals[0].clone()]),
Expression::integer(1),
],
lambda.clone(),
);
for eigenval in eigenvals.iter().skip(1) {
let factor = CharacteristicPolynomial::new(
vec![
Expression::mul(vec![Expression::integer(-1), eigenval.clone()]),
Expression::integer(1),
],
lambda.clone(),
);
poly = poly.multiply(&factor);
}
poly
}
fn trace(&self) -> Expression {
Matrix::trace(self)
}
fn determinant_via_eigenvalues(&self) -> Expression {
let eigenvals = Matrix::eigenvalues(self);
if eigenvals.is_empty() {
Expression::integer(0)
} else {
Expression::mul(eigenvals).simplify()
}
}
fn is_diagonalizable(&self) -> bool {
Matrix::is_diagonalizable(self)
}
fn matrix_power_eigen(&self, n: i64) -> Option<Matrix> {
Matrix::matrix_power_eigen(self, n)
}
fn matrix_exponential(&self) -> Option<Matrix> {
Matrix::matrix_exponential_eigen(self)
}
fn matrix_logarithm(&self) -> Option<Matrix> {
Matrix::matrix_logarithm_eigen(self)
}
fn matrix_sqrt(&self) -> Option<Matrix> {
Matrix::matrix_sqrt_eigen(self)
}
fn is_nilpotent(&self) -> bool {
let eigenvals = Matrix::eigenvalues(self);
eigenvals.iter().all(|val| val.is_zero())
}
}