use crate::algebra::rings::traits::DivisionRingOperations;
use crate::algebra::vectors::operations::VectorOperations;
use crate::algebra::vectors::entries::KeyValGet;
use std::collections::HashMap;
use std::fmt::Debug;
pub fn clear_if_in< Key, Val, RingOperator > (
clearor: & Vec< (Key, Val) >,
clearee: &mut Vec< (Key, Val) >,
buffer: &mut Vec< (Key, Val) >,
pivot_entry: & (Key, Val),
ring_operator: RingOperator
)
where RingOperator: DivisionRingOperations< Element = Val > + Clone,
Key: Clone + Debug + PartialEq + PartialOrd,
Val: Clone + Debug +PartialOrd
{
let entry_to_clear_opt = clearee
.iter()
.find( |&x| x.key() == pivot_entry.key() );
if let Some(entry_to_clear) = entry_to_clear_opt
{
if ring_operator.is_0( entry_to_clear.val()) { return }
let scalar = ring_operator.divide(
ring_operator.negate( entry_to_clear.val() ),
pivot_entry.val()
);
let merged = itertools::merge( clearee.iter().cloned(),
clearor
.iter()
.cloned()
.scale_by( scalar, ring_operator.clone() )
)
.peekable() .gather( ring_operator.clone() ) .drop_zeros( ring_operator ); buffer.clear();
buffer.extend( merged );
clearee.clear();
clearee.append( buffer); }
}
pub fn clear_cols< RingOperator, Key, Val, IndexIter: IntoIterator< Item = usize > >(
clearor: & Vec< (Key, Val) >,
clearee_matrix: &mut Vec< Vec< (Key, Val) > >,
col_ind_2clear: IndexIter,
pivot_entry: & (Key, Val),
ring_operator: RingOperator,
)
where RingOperator: DivisionRingOperations< Element = Val > + Clone,
Key: Clone + Debug + PartialEq + PartialOrd,
Val: Clone + Debug +PartialOrd
{
let mut buffer = Vec::new();
for col_ind in col_ind_2clear {
clear_if_in(
clearor,
&mut clearee_matrix[ col_ind ],
&mut buffer,
pivot_entry,
ring_operator.clone()
)
}
}
type Key = usize;
pub fn right_reduce
< Val, RingOperator >
(
matrix: &mut Vec< Vec< (Key, Val) > >,
ring_operator: RingOperator
)
->
HashMap::<Key, Key>
where RingOperator: DivisionRingOperations< Element = Val > + Clone,
Key: Clone + Debug + PartialEq + PartialOrd + Eq + std::hash::Hash,
Val: Clone + Debug +PartialOrd
{
let mut pivot_hash = HashMap::< Key, Key >::new();
let mut buffer = Vec::new();
for clearee_count in 0..matrix.len() {
let mut clearee = matrix[ clearee_count ].clone();
while let Some( clearee_entry ) = clearee.last(){
if let Some( clearor_index ) = pivot_hash.get( &clearee_entry.key() ) {
let clearor = matrix[ *clearor_index ].clone();
let clearor_entry = clearor.last().unwrap();
let scalar = ring_operator.divide(
ring_operator.negate(clearee_entry.val()),
clearor_entry.val()
);
let merged = itertools::merge( clearee.iter().cloned(),
clearor
.iter()
.cloned()
.scale_by( scalar, ring_operator.clone() )
)
.peekable() .gather( ring_operator.clone() ) .drop_zeros( ring_operator.clone() );
buffer.clear();
buffer.extend( merged );
clearee.clear();
clearee.append( &mut buffer);
} else {
break;
}
}
matrix[ clearee_count ].clear(); if let Some( pivot_entry ) = clearee.last() {
pivot_hash.insert( pivot_entry.key(), clearee_count ); matrix[ clearee_count ].append( &mut clearee ); }
}
pivot_hash
}
#[cfg(test)]
mod tests {
use crate::algebra::matrices::operations::vec_of_vec_reduction::*;
use crate::algebra::rings::types::native::RingOperatorForNativeRustNumberType;
use std::iter::FromIterator;
#[test]
fn test()
{
let mut matrix = vec![
vec![ (2, 1.), (3,-1.) ],
vec![ (2,-1.), (3, 2.) ],
vec![ (1, 1.), (2, 1.) ],
vec![ (0, 1.), (1, 1.) ],
vec![ (0, 1.), ],
];
let reduced_correct = vec![
vec![ (2, 1.), (3, -1.) ],
vec![ (2, 1.), ],
vec![ (1, 1.) ],
vec![ (0, 1.), ],
vec![ ],
];
let hash = right_reduce(
&mut matrix,
RingOperatorForNativeRustNumberType::<f64>::new()
);
let mut pivot_pairs = Vec::from_iter( hash );
pivot_pairs.sort();
assert_eq!( pivot_pairs, vec![ (0,3), (1,2), (2,1), (3,0)] );
assert_eq!( reduced_correct, matrix );
}
#[test]
fn test_clear_cols()
{
let matrix = vec![
vec![ (0, 1.), (1, 1.), (2, 1.) ],
vec![ (1, 1.), (2, 1.) ],
vec![ (0, 1.), (1, 1.), ],
vec![ (0, 1.), (2, 1.) ],
vec![ (0, 1.), (1, 0.), (2, 1.) ],
vec![ (0, 1.), (1, 1.), (2, 1.) ],
vec![ (0, 1.), (1, 2.), (2, 1.) ],
vec![ ],
vec![ (0, 1.), (1, 1.), (2, 1.) ],
];
let mut clearee_matrix = matrix;
let clearor = vec![ (0, 1.), (1, 1.), ];
let pivot_entry = *clearor.last().unwrap();
let col_ind_2clear = 1..7;
clear_cols(
& clearor,
&mut clearee_matrix,
col_ind_2clear,
& pivot_entry,
RingOperatorForNativeRustNumberType::<f64>::new() ,
);
let target_matrix = vec![
vec![ (0, 1.), (1, 1.), (2, 1.) ],
vec![ (0, -1.), (2, 1.) ],
vec![ ],
vec![ (0, 1.), (2, 1.) ],
vec![ (0, 1.), (1, 0.), (2, 1.) ],
vec![ (2, 1.) ],
vec![ (0, -1.), (2, 1.) ],
vec![ ],
vec![ (0, 1.), (1, 1.), (2, 1.) ],
];
assert_eq!( clearee_matrix, target_matrix );
}
}