use noether::{
AssociativeAddition, CommutativeAddition, Field, FreeModule, InnerProductSpace, Module,
VectorSpace,
};
use num_traits::{One, Zero};
use std::fmt::{Debug, Display};
use std::marker::PhantomData;
use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};
#[derive(Debug, Clone, PartialEq)]
struct Vector<F: Field + Clone> {
elements: Vec<F>,
}
impl<F: Field + Clone> Vector<F> {
fn new(elements: &[F]) -> Self {
Self {
elements: elements.to_vec(),
}
}
fn dim(&self) -> usize {
self.elements.len()
}
}
impl<F: Field + Clone> Vector<F> {
fn basis_vector(dimension: usize, index: usize) -> Self
where
F: One,
{
assert!(index < dimension, "Index must be less than dimension");
let mut elements = vec![F::zero(); dimension];
elements[index] = F::one();
Self { elements }
}
fn standard_basis(dimension: usize) -> Vec<Self>
where
F: One,
{
(0..dimension)
.map(|i| Self::basis_vector(dimension, i))
.collect()
}
fn dot(&self, other: &Self) -> F {
assert_eq!(
self.dim(),
other.dim(),
"Vectors must have the same dimension for dot product"
);
let mut result = F::zero();
for i in 0..self.dim() {
result = result.clone() + (self.elements[i].clone() * other.elements[i].clone());
}
result
}
fn scale(&self, scalar: F) -> Self {
let mut result = Vec::with_capacity(self.dim());
for i in 0..self.dim() {
result.push(self.elements[i].clone() * scalar.clone());
}
Self { elements: result }
}
fn get(&self, i: usize) -> F {
assert!(i < self.dim(), "Index out of bounds");
self.elements[i].clone()
}
fn linear_combination<I>(vectors_and_scalars: I) -> Self
where
I: IntoIterator<Item = (Self, F)>,
{
let mut result: Option<Self> = None;
for (vector, scalar) in vectors_and_scalars {
let scaled = vector.scale(scalar);
if let Some(r) = &mut result {
*r = r.clone() + scaled;
} else {
result = Some(scaled);
}
}
result.unwrap_or_else(|| Self::new(&[]))
}
fn is_in_span(&self, vectors: &[Self]) -> bool
where
F: PartialEq + Div<Output = F>,
{
if vectors.is_empty() {
return self.is_zero();
}
let dimension = vectors[0].dim();
assert!(
vectors.iter().all(|v| v.dim() == dimension),
"All vectors must have the same dimension"
);
if dimension == 1 {
for vector in vectors {
if !vector.is_zero() {
return true;
}
}
return self.is_zero();
} else if dimension == 2 {
if vectors.len() >= 2 {
let v1 = &vectors[0];
let v2 = &vectors[1];
let determinant =
v1.get(0).clone() * v2.get(1).clone() - v1.get(1).clone() * v2.get(0).clone();
if determinant != F::zero() {
return true;
}
}
for vector in vectors {
if !vector.is_zero() {
let ratio = if vector.get(0) != F::zero() {
self.get(0).clone() / vector.get(0).clone()
} else if vector.get(1) != F::zero() {
self.get(1).clone() / vector.get(1).clone()
} else {
continue;
};
if (self.get(0) == ratio.clone() * vector.get(0).clone())
&& (self.get(1) == ratio * vector.get(1).clone())
{
return true;
}
}
}
return self.is_zero();
}
false
}
}
impl<F: Field + Clone> Add for Vector<F> {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
assert_eq!(
self.dim(),
rhs.dim(),
"Vectors must have the same dimension"
);
let mut result = Vec::with_capacity(self.dim());
for i in 0..self.dim() {
result.push(self.elements[i].clone() + rhs.elements[i].clone());
}
Self { elements: result }
}
}
impl<F: Field + Clone> AddAssign for Vector<F> {
fn add_assign(&mut self, rhs: Self) {
assert_eq!(
self.dim(),
rhs.dim(),
"Vectors must have the same dimension"
);
for i in 0..self.dim() {
self.elements[i] = self.elements[i].clone() + rhs.elements[i].clone();
}
}
}
impl<F: Field + Clone> Sub for Vector<F> {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
assert_eq!(
self.dim(),
rhs.dim(),
"Vectors must have the same dimension"
);
let mut result = Vec::with_capacity(self.dim());
for i in 0..self.dim() {
result.push(self.elements[i].clone() - rhs.elements[i].clone());
}
Self { elements: result }
}
}
impl<F: Field + Clone> SubAssign for Vector<F> {
fn sub_assign(&mut self, rhs: Self) {
assert_eq!(
self.dim(),
rhs.dim(),
"Vectors must have the same dimension"
);
for i in 0..self.dim() {
self.elements[i] = self.elements[i].clone() - rhs.elements[i].clone();
}
}
}
impl<F: Field + Clone> Neg for Vector<F> {
type Output = Self;
fn neg(self) -> Self::Output {
let mut result = Vec::with_capacity(self.dim());
for i in 0..self.dim() {
result.push(-self.elements[i].clone());
}
Self { elements: result }
}
}
impl<F: Field + Clone> Mul<F> for Vector<F> {
type Output = Self;
fn mul(self, scalar: F) -> Self::Output {
self.scale(scalar)
}
}
impl<F: Field + Clone> MulAssign<F> for Vector<F> {
fn mul_assign(&mut self, scalar: F) {
for i in 0..self.dim() {
self.elements[i] = self.elements[i].clone() * scalar.clone();
}
}
}
impl<F: Field + Clone> Zero for Vector<F> {
fn zero() -> Self {
Self { elements: vec![] }
}
fn is_zero(&self) -> bool {
self.elements.iter().all(|e| e.is_zero())
}
}
impl<F: Field + Clone> CommutativeAddition for Vector<F> {}
impl<F: Field + Clone> AssociativeAddition for Vector<F> {}
impl<F: Field + Clone + 'static> Module<F> for Vector<F> {
fn scale(&self, r: &F) -> Self {
let mut result = Vec::with_capacity(self.dim());
for i in 0..self.dim() {
result.push(self.elements[i].clone() * r.clone());
}
Self { elements: result }
}
fn zero() -> Self {
Self { elements: vec![] }
}
fn is_free() -> bool {
true }
}
impl<F: Field + Clone + 'static> FreeModule<F> for Vector<F> {
fn rank() -> usize {
3
}
fn basis_element(index: usize) -> Self {
let dim = Self::rank();
assert!(index < dim, "Index must be less than rank");
let mut elements = vec![F::zero(); dim];
elements[index] = F::one();
Self { elements }
}
fn coordinates(&self) -> Vec<F> {
self.elements.clone()
}
}
impl<F: Field + Clone + 'static> VectorSpace<F> for Vector<F> {
fn dimension() -> usize {
Self::rank()
}
fn shape(&self) -> Vec<usize> {
vec![self.dim()]
}
fn scale(&self, scalar: &F) -> Self {
let mut result = Vec::with_capacity(self.dim());
for i in 0..self.dim() {
result.push(self.elements[i].clone() * scalar.clone());
}
Self { elements: result }
}
fn zero_like(&self) -> Self {
Self {
elements: vec![F::zero(); self.dim()],
}
}
fn ones_like(&self) -> Self {
Self {
elements: vec![F::one(); self.dim()],
}
}
fn basis() -> Vec<Self> {
(0..Self::dimension())
.map(|i| Self::basis_element(i))
.collect()
}
}
impl<F: Field + Clone + PartialOrd + 'static> InnerProductSpace<F> for Vector<F> {
fn inner_product(&self, other: &Self) -> F {
self.dot(other)
}
fn norm(&self) -> F {
self.dot(self)
}
fn normalize(&self) -> Self {
let norm = self.norm();
if norm == F::zero() {
self.clone()
} else {
let scale = F::one() / norm;
self.clone() * scale
}
}
fn distance(&self, other: &Self) -> F {
let diff = self.clone() - other.clone();
diff.norm()
}
fn is_orthogonal(&self, other: &Self) -> bool {
self.dot(other) == F::zero()
}
}
impl<F: Field + Clone + Display> Display for Vector<F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[")?;
for (i, e) in self.elements.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", e)?;
}
write!(f, "]")
}
}
#[derive(Debug)]
struct FixedDimensionVectorSpace<const N: usize, F>
where
F: Field + Clone,
{
_phantom: PhantomData<F>,
}
impl<const N: usize, F> FixedDimensionVectorSpace<N, F>
where
F: Field + Clone + 'static,
{
fn vector(elements: &[F]) -> Vector<F> {
assert_eq!(elements.len(), N, "Vector must have exactly {} elements", N);
Vector::new(elements)
}
fn basis() -> Vec<Vector<F>> {
Vector::<F>::standard_basis(N)
}
}
#[derive(Debug, Clone, PartialEq)]
struct Matrix<F>
where
F: Field + Clone,
{
elements: Vec<F>,
rows: usize,
cols: usize,
}
impl<F> Matrix<F>
where
F: Field + Clone,
{
fn new(elements: &[&[F]]) -> Self {
let rows = elements.len();
let cols = if rows > 0 { elements[0].len() } else { 0 };
assert!(
elements.iter().all(|row| row.len() == cols),
"All rows must have the same number of columns"
);
let mut flat_elements = Vec::with_capacity(rows * cols);
for row in elements {
for element in *row {
flat_elements.push(element.clone());
}
}
Self {
elements: flat_elements,
rows,
cols,
}
}
fn identity(size: usize) -> Self {
let mut elements = vec![F::zero(); size * size];
for i in 0..size {
elements[i * size + i] = F::one();
}
Self {
elements,
rows: size,
cols: size,
}
}
fn zero(rows: usize, cols: usize) -> Self {
Self {
elements: vec![F::zero(); rows * cols],
rows,
cols,
}
}
fn get(&self, row: usize, col: usize) -> F {
assert!(row < self.rows && col < self.cols, "Index out of bounds");
self.elements[row * self.cols + col].clone()
}
fn set(&mut self, row: usize, col: usize, value: F) {
assert!(row < self.rows && col < self.cols, "Index out of bounds");
self.elements[row * self.cols + col] = value;
}
fn multiply_vector(&self, v: &Vector<F>) -> Vector<F> {
assert_eq!(
self.cols,
v.dim(),
"Matrix columns must match vector dimension"
);
let mut result = vec![F::zero(); self.rows];
for (i, res) in result.iter_mut().enumerate().take(self.rows) {
for j in 0..self.cols {
*res = res.clone() + self.get(i, j).clone() * v.get(j);
}
}
Vector { elements: result }
}
fn multiply(&self, other: &Self) -> Self {
assert_eq!(
self.cols, other.rows,
"Inner dimensions must match for matrix multiplication"
);
let mut result = Self::zero(self.rows, other.cols);
for i in 0..self.rows {
for j in 0..other.cols {
let mut sum = F::zero();
for k in 0..self.cols {
sum += self.get(i, k).clone() * other.get(k, j).clone();
}
result.set(i, j, sum);
}
}
result
}
fn transpose(&self) -> Self {
let mut result = Self::zero(self.cols, self.rows);
for i in 0..self.rows {
for j in 0..self.cols {
result.set(j, i, self.get(i, j));
}
}
result
}
fn is_symmetric(&self) -> bool {
if self.rows != self.cols {
return false;
}
for i in 0..self.rows {
for j in (i + 1)..self.cols {
if self.get(i, j) != self.get(j, i) {
return false;
}
}
}
true
}
}
impl<F: Field + Clone + Display> Display for Matrix<F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for i in 0..self.rows {
write!(f, "[")?;
for j in 0..self.cols {
if j > 0 {
write!(f, ", ")?;
}
write!(f, "{}", self.get(i, j))?;
}
writeln!(f, "]")?;
}
Ok(())
}
}
fn demonstrate_vector_space<F>(v1: &Vector<F>, v2: &Vector<F>, scalar: F, other_scalar: F)
where
F: Field + Clone + Display + PartialOrd + 'static,
{
println!("Vector 1: {}", v1);
println!("Vector 2: {}", v2);
let v3 = v1.clone() + v2.clone();
println!("Vector addition: v1 + v2 = {}", v3);
let v4 = v1.clone() - v2.clone();
println!("Vector subtraction: v1 - v2 = {}", v4);
let neg_v1 = -v1.clone();
println!("Additive inverse: -v1 = {}", neg_v1);
let scaled_v1 = v1.scale(scalar.clone());
println!("Scalar multiplication: {} * v1 = {}", scalar, scaled_v1);
let sum_scalar = scalar.clone() + other_scalar.clone();
let left_side = v1.scale(sum_scalar.clone());
let right_side = v1.scale(scalar.clone()) + v1.scale(other_scalar.clone());
println!("Distributivity 1: (a + b)v = av + bv:");
println!(
" Left side: ({} + {}) * v1 = {}",
scalar, other_scalar, left_side
);
println!(
" Right side: {} * v1 + {} * v1 = {}",
scalar, other_scalar, right_side
);
println!(" Equality: {}", left_side == right_side);
let sum_vector = v1.clone() + v2.clone();
let left_side = sum_vector.scale(scalar.clone());
let right_side = v1.scale(scalar.clone()) + v2.scale(scalar.clone());
println!("Distributivity 2: a(v + w) = av + aw:");
println!(" Left side: {} * (v1 + v2) = {}", scalar, left_side);
println!(
" Right side: {} * v1 + {} * v2 = {}",
scalar, scalar, right_side
);
println!(" Equality: {}", left_side == right_side);
let product_scalar = scalar.clone() * other_scalar.clone();
let left_side = v1.scale(other_scalar.clone()).scale(scalar.clone());
let right_side = v1.scale(product_scalar.clone());
println!("Scalar product: a(bv) = (ab)v:");
println!(
" Left side: {} * ({} * v1) = {}",
scalar, other_scalar, left_side
);
println!(
" Right side: ({} * {}) * v1 = {}",
scalar, other_scalar, right_side
);
println!(" Equality: {}", left_side == right_side);
let id_scaled = v1.scale(F::one());
println!("Identity scalar: 1 * v1 = {}", id_scaled);
println!(" Equality: {}", id_scaled == *v1);
let dot_product = v1.dot(v2);
println!("Inner product: v1 · v2 = {}", dot_product);
println!("\nInner Product Space Properties:");
println!("Norm of v1: ||v1|| = {}", v1.norm());
println!("Are v1 and v2 orthogonal? {}", v1.is_orthogonal(v2));
println!("\nLinear Combinations and Span:");
let basis_vectors = Vector::<F>::standard_basis(v1.dim());
println!("Standard basis vectors:");
for (i, basis) in basis_vectors.iter().enumerate() {
println!(" e_{} = {}", i + 1, basis);
}
let linear_combo = Vector::linear_combination(vec![
(v1.clone(), scalar.clone()),
(v2.clone(), other_scalar.clone()),
]);
println!(
"Linear combination {}*v1 + {}*v2 = {}",
scalar, other_scalar, linear_combo
);
let test_vector = v1.clone() + v2.clone();
println!(
"Is {} in the span of {} and {}? {}",
test_vector,
v1,
v2,
test_vector.is_in_span(&[v1.clone(), v2.clone()])
);
if v1.dim() == 2 {
println!("\nMatrix Transformations:");
let rotation_matrix = Matrix::new(&[&[F::zero(), -F::one()], &[F::one(), F::zero()]]);
println!("Rotation matrix (90 degrees):");
println!("{}", rotation_matrix);
let transformed_v1 = rotation_matrix.multiply_vector(v1);
println!("Transformed v1 = {}", transformed_v1);
}
}
fn demonstrate_specialized_field() {
println!("\n=== Specialized Field Operations ===");
println!("In a full implementation, we could demonstrate vector spaces over:");
println!("1. Finite fields (e.g., GF(5) or GF(2^8))");
println!("2. Rational function fields");
println!("3. Algebraic extensions (e.g., Q(√2))");
println!("4. Complex number fields");
println!("For example, using our finite_field.rs example's Fp<P> type");
println!("to create vector spaces over GF(p).");
}
fn main() {
println!("=== Vector Space with f64 Scalars ===");
let v1 = Vector::new(&[1.0, 2.0, 3.0]);
let v2 = Vector::new(&[4.0, 5.0, 6.0]);
demonstrate_vector_space(&v1, &v2, 2.0, 3.0);
println!("\n=== Vector Space with Fixed Dimension (R²) ===");
let u1 = FixedDimensionVectorSpace::<2, f64>::vector(&[1.0, 0.0]);
let u2 = FixedDimensionVectorSpace::<2, f64>::vector(&[0.0, 1.0]);
println!("Working in 2D vector space R²");
println!("Basis vectors:");
for (i, basis) in FixedDimensionVectorSpace::<2, f64>::basis()
.iter()
.enumerate()
{
println!(" e_{} = {}", i + 1, basis);
}
demonstrate_vector_space(&u1, &u2, 2.0, 3.0);
println!("\n=== Matrix Operations ===");
let a = Matrix::<f64>::new(&[&[1.0, 2.0], &[3.0, 4.0]]);
let b = Matrix::<f64>::new(&[&[0.0, 1.0], &[1.0, 0.0]]);
println!("Matrix A:");
println!("{}", a);
println!("Matrix B:");
println!("{}", b);
println!("A * B:");
println!("{}", a.multiply(&b));
println!("Transpose of A:");
println!("{}", a.transpose());
println!("Is B symmetric? {}", b.is_symmetric());
let id = Matrix::<f64>::identity(2);
println!("Identity matrix:");
println!("{}", id);
demonstrate_specialized_field();
println!("\n=== Vector Spaces in Abstract Algebra ===");
println!("In the noether library, vector spaces have the following structure:");
println!("- A vector space is a module over a field");
println!("- A module is an additive abelian group with scalar multiplication from a ring");
println!("- A free module has a basis of linearly independent elements");
println!(
"- Fields are commutative rings where every non-zero element has a multiplicative inverse"
);
println!("- Inner product spaces add the concept of angles and orthogonality");
println!("\nApplications of vector spaces include:");
println!("1. Linear algebra and computational mathematics");
println!("2. Quantum mechanics and quantum computing (Hilbert spaces)");
println!("3. Signal processing and Fourier analysis");
println!("4. Machine learning and data analysis");
println!("5. Computer graphics (transformations, projections)");
println!("6. Control theory and dynamical systems");
println!("\nBy implementing vector spaces over arbitrary fields, Noether");
println!("provides a framework for advanced mathematical computing across");
println!("many different domains and applications.");
}