use crate::algebra::matrices::query::{ MatrixAlgebra, MatrixOracle };
use crate::algebra::matrices::operations::MatrixOracleOperations;
use crate::algebra::matrices::types::product::ProductMatrix;
use crate::algebra::rings::traits::SemiringOperations;
use crate::algebra::vectors::operations::{LinearCombinationSimplified, LinearCombinationUnsimplified, VectorOperations};
use crate::algebra::vectors::entries::{KeyValGet, KeyValSet};
use crate::utilities::iterators::merge::hit::hit_merge_by_predicate;
use crate::utilities::order::{JudgePartialOrder, ReverseOrder};
pub fn multiply_row_vector_with_matrix_unsimplified
< Matrix, RingOperator, SparseVecIter, OrderOperator>
(
sparse_vec: SparseVecIter,
matrix: Matrix,
ring_operator: RingOperator,
order_operator: OrderOperator,
)
->
LinearCombinationUnsimplified
< Matrix::Row, RingOperator, OrderOperator >
where
Matrix: MatrixOracle,
Matrix::RowEntry: KeyValSet,
RingOperator: Clone + SemiringOperations< Element = Matrix::Coefficient >, OrderOperator: Clone + JudgePartialOrder< Matrix::RowEntry >, SparseVecIter: IntoIterator,
SparseVecIter::Item: KeyValGet < Key=Matrix::RowIndex, Val=Matrix::Coefficient >,
{
hit_merge_by_predicate(
sparse_vec
.into_iter()
.map( |x|
matrix
.row( & x.key() )
.scale_by( x.val(), ring_operator.clone() )
),
order_operator
)
}
pub fn multiply_row_vector_with_matrix
< Matrix, RingOperator, SparseVecIter, OrderOperator>
(
sparse_vec: SparseVecIter,
matrix: Matrix,
ring_operator: RingOperator,
order_operator: OrderOperator,
)
->
LinearCombinationSimplified
< Matrix::Row, RingOperator, OrderOperator >
where
Matrix: MatrixOracle,
Matrix::RowEntry: KeyValSet,
RingOperator: Clone + SemiringOperations< Element = Matrix::Coefficient >, OrderOperator: Clone + JudgePartialOrder< Matrix::RowEntry >, SparseVecIter: IntoIterator,
SparseVecIter::Item: KeyValGet < Key=Matrix::RowIndex, Val=Matrix::Coefficient >,
{
multiply_row_vector_with_matrix_unsimplified(
sparse_vec,
matrix,
ring_operator.clone(),
order_operator,
)
.simplify(ring_operator)
}
pub fn multiply_column_vector_with_matrix_and_return_unsimplified_and_reversed
< Matrix, RingOperator, SparseVecIter, OrderOperatorForRowIndices>
(
sparse_vec: SparseVecIter,
matrix: Matrix,
ring_operator: RingOperator,
order_operator_for_row_indices: OrderOperatorForRowIndices,
)
->
LinearCombinationUnsimplified
< Matrix::ColumnReverse, RingOperator, ReverseOrder< OrderOperatorForRowIndices > >
where
Matrix: MatrixOracle,
Matrix::ColumnEntry: KeyValSet,
RingOperator: Clone + SemiringOperations< Element = Matrix::Coefficient >, OrderOperatorForRowIndices: Clone + JudgePartialOrder< Matrix::ColumnEntry >, SparseVecIter: IntoIterator,
SparseVecIter::Item: KeyValGet < Key = Matrix::ColumnIndex, Val = Matrix::Coefficient >,
{
hit_merge_by_predicate(
sparse_vec
.into_iter()
.map( |x|
matrix
.column_reverse(& x.key() )
.scale_by( x.val(), ring_operator.clone() )
),
ReverseOrder::new( order_operator_for_row_indices )
)
}
pub fn multiply_column_vector_with_matrix_and_return_reversed
< Matrix, RingOperator, SparseVecIter, OrderOperatorForRowIndices>
(
sparse_vec: SparseVecIter,
matrix: Matrix,
ring_operator: RingOperator,
order_operator_row_row_indices: OrderOperatorForRowIndices,
)
->
LinearCombinationSimplified
< Matrix::ColumnReverse, RingOperator, ReverseOrder< OrderOperatorForRowIndices > >
where
Matrix: MatrixOracle<
ColumnEntry: KeyValSet,
>,
RingOperator: Clone + SemiringOperations< Element = Matrix::Coefficient >, OrderOperatorForRowIndices: Clone + JudgePartialOrder< Matrix::ColumnEntry >, SparseVecIter: IntoIterator,
SparseVecIter::Item: KeyValGet < Key = Matrix::ColumnIndex, Val = Matrix::Coefficient >,
{
multiply_column_vector_with_matrix_and_return_unsimplified_and_reversed(
sparse_vec,
matrix,
ring_operator.clone(),
order_operator_row_row_indices,
)
.simplify(ring_operator)
}
#[cfg(test)]
mod doc_tests {
use crate::algebra::matrices::operations::MatrixOracleOperations;
#[test]
fn doc_test_vector_matrix_product_major_ascend_unsimplified() {
use crate::algebra::matrices::operations::multiply::multiply_row_vector_with_matrix_unsimplified;
use crate::algebra::matrices::types::vec_of_vec::sorted::VecOfVec;
use crate::algebra::rings::types::field_prime_order::PrimeOrderField;
use crate::utilities::order::OrderOperatorByKey;
let matrix = VecOfVec::new( vec![ vec![ (0isize, 1), (1isize, 6) ],
vec![ (0isize, 1), (1isize, 1) ], ] ).unwrap();
let vector = vec![ (0usize, 1), (1usize, 1) ];
let product = multiply_row_vector_with_matrix_unsimplified(
vector,
(& matrix).into_peekable_matrix(),
PrimeOrderField::new(7), OrderOperatorByKey::new(), );
itertools::assert_equal( product, vec![(0isize,1usize), (0,1), (1,1), (1,6)] )
}
#[test]
fn doc_test_vector_matrix_product_major_ascend_simplified() {
use crate::algebra::matrices::operations::multiply::multiply_row_vector_with_matrix;
use crate::algebra::matrices::types::vec_of_vec::sorted::VecOfVec;
use crate::algebra::rings::types::field_prime_order::PrimeOrderField;
use crate::utilities::order::OrderOperatorByKey;
let matrix = VecOfVec::new( vec![ vec![ (0isize, 1), (1isize, 6) ],
vec![ (0isize, 1), (1isize, 1) ], ] ).unwrap();
let vector = vec![ (0usize, 1), (1usize, 1) ];
let product = multiply_row_vector_with_matrix(
vector,
( & matrix ).into_peekable_matrix(),
PrimeOrderField::new(7), OrderOperatorByKey::new(), );
itertools::assert_equal( product, vec![(0isize, 2)] )
}
#[test]
fn doc_test_vector_matrix_product_minor_descend_unsimplified() {
use crate::algebra::matrices::operations::multiply::multiply_column_vector_with_matrix_and_return_unsimplified_and_reversed;
use crate::algebra::matrices::types::vec_of_vec::sorted::VecOfVec;
use crate::algebra::rings::types::field_prime_order::PrimeOrderField;
use crate::utilities::order::OrderOperatorAuto;
let matrix = VecOfVec::new( vec![ vec![ (0isize, 1), (1isize, 6) ],
vec![ (0isize, 1), (1isize, 1) ], ] ).unwrap();;
let vector = vec![ (0isize, 1), (1isize, 1) ];
let product = multiply_column_vector_with_matrix_and_return_unsimplified_and_reversed(
vector,
( & matrix ).into_peekable_matrix(),
PrimeOrderField::new(7), OrderOperatorAuto, );
itertools::assert_equal( product, vec![(1,1), (1,1), (0,6), (0,1)] )
}
#[test]
fn doc_test_vector_matrix_product_minor_descend_simplified() {
use crate::algebra::matrices::operations::multiply::multiply_column_vector_with_matrix_and_return_reversed;
use crate::algebra::matrices::types::vec_of_vec::sorted::VecOfVec;
use crate::algebra::rings::types::field_prime_order::PrimeOrderField;
use crate::utilities::order::OrderOperatorByKey;
let matrix = VecOfVec::new( vec![ vec![ (0isize, 1), (1isize, 6) ],
vec![ (0isize, 1), (1isize, 1) ], ] ).unwrap();;
let vector = vec![ (0isize, 1), (1isize, 1) ];
let product = multiply_column_vector_with_matrix_and_return_reversed(
vector,
( & matrix ).into_peekable_matrix(),
PrimeOrderField::new(7), OrderOperatorByKey::new(), );
itertools::assert_equal( product, vec![(1usize, 2)] )
}
#[test]
fn doc_test_matrix_product_row_unsimplified() {
use crate::algebra::rings::types::native::RingOperatorForNativeRustNumberType;
use crate::algebra::matrices::types::vec_of_vec::sorted::VecOfVec;
use crate::algebra::matrices::query::MatrixOracle;
use crate::algebra::matrices::types::product::ProductMatrix;
use crate::algebra::matrices::types::packet::MatrixAlgebraPacket;
use std::iter::FromIterator;
let ring_operator = RingOperatorForNativeRustNumberType::<f64>::new();
let matrix_1 = VecOfVec::new( vec![ vec![ (0,1.), (1,1.) ], vec![ (1,1.) ] ] ).unwrap();
let matrix_2 = VecOfVec::new( vec![ vec![ (0,1.), (1,1.) ], vec![ (1,1.) ] ] ).unwrap();
let matrix_1_packet = MatrixAlgebraPacket::with_default_order_and_f64_coefficients( &matrix_1 );
let matrix_2_packet = MatrixAlgebraPacket::with_default_order_and_f64_coefficients( &matrix_2 );
let product = ProductMatrix::new(
matrix_1_packet, matrix_2_packet, );
let output = Vec::from_iter(
(0..2)
.map( |x|
Vec::from_iter(
product
.row(&x)
)
)
);
assert_eq!(
output,
vec![ vec![(0,1.), (1,2.)], vec![(1,1.)] ]
);
let output = Vec::from_iter(
(0..2)
.map( |x|
Vec::from_iter(
product
.row(&x)
.unsimplified )
)
);
assert_eq!(
output,
vec![ vec![(0,1.), (1,1.), (1,1.)], vec![(1,1.)] ]
);
}
}
#[cfg(test)]
mod tests {
use std::iter::FromIterator;
use itertools::Itertools;
use super::*;
use crate::algebra::matrices::types::packet::MatrixAlgebraPacket;
use crate::algebra::matrices::types::vec_of_vec::sorted::VecOfVec;
use crate::algebra::rings::types::native::{RingOperatorForNativeRustNumberType};
use crate::utilities::order::OrderOperatorByLessThan;
#[test]
pub fn matrix_by_matrix_multiply_major_ascend_test_1() {
let ring_operator = RingOperatorForNativeRustNumberType::<f64>::new();
let matrix_1 = VecOfVec::new(
vec![ vec![ (0,1.), (1,1.) ], vec![ (1,1.) ] ]
).ok().unwrap();
let matrix_2 = VecOfVec::new(
vec![ vec![ (0,1.), (1,1.) ], vec![ (1,1.) ] ]
).ok().unwrap();
let matrix_1_packet = MatrixAlgebraPacket::with_default_order_and_f64_coefficients( &matrix_1 );
let matrix_2_packet = MatrixAlgebraPacket::with_default_order_and_f64_coefficients( &matrix_2 );
let product = ProductMatrix::new(
matrix_1_packet, matrix_2_packet,
);
let output = Vec::from_iter(
(0..2)
.map( |x|
Vec::from_iter(
product
.row(&x)
)
)
);
assert_eq!(
output,
vec![ vec![(0,1.), (1,2.)], vec![(1,1.)] ]
);
let output = Vec::from_iter(
(0..2)
.map( |x|
Vec::from_iter(
product
.row(&x)
.unsimplified
)
)
);
assert_eq!(
output,
vec![ vec![(0,1.), (1,1.), (1,1.)], vec![(1,1.)] ]
);
}
#[test]
pub fn matrix_by_matrix_multiply_major_ascend_test_2() {
let matrix_1 =
VecOfVec::<usize,i64>::new(
vec![
vec![ ],
vec![ (0,0) ],
vec![ (0,4), (1,-1) ],
vec![ (0,5), (1,7) ],
vec![ (0,11), (1,13) ],
]
).ok().unwrap();
let matrix_2 =
VecOfVec::<usize,i64>::new(
vec![
vec![ (0,1), (1,2), (2,3) ],
vec![ (0,4), (1,5), (2,6) ],
vec![ ],
vec![ (0,0) ],
]
).ok().unwrap();
let matrix_1_packet = MatrixAlgebraPacket::with_default_order_and_i64_coefficients( &matrix_1 );
let matrix_2_packet = MatrixAlgebraPacket::with_default_order_and_i64_coefficients( &matrix_2 );
let product_true: Vec<Vec<(usize,i64)>> =
vec![
vec![ ],
vec![ ],
vec![ (1,3), (2,6) ],
vec![ (0,33), (1,45), (2,57) ],
vec![ (0,63), (1,87), (2,111) ],
];
let product = ProductMatrix::new(
matrix_1_packet, matrix_2_packet,
);
for row_index in 0 .. 5 {
let vec_lazy = product
.row( &row_index )
.collect_vec();
let vec_true = product_true[ row_index ].clone();
assert_eq!( vec_lazy, vec_true )
}
}
#[test]
pub fn matrix_by_vector_multiply_major_ascend_test_2() {
let ring_operator = RingOperatorForNativeRustNumberType::<i32>::new();
let matrix_1 =
VecOfVec::new(
vec![
vec![ ],
vec![ (0,0) ],
vec![ (0,4), (1,-1) ],
vec![ (0,5), (1,7) ],
vec![ (0,11), (1,13) ],
]
).ok().unwrap();
let matrix_2 =
VecOfVec::new(
vec![
vec![ (0,1), (1,2), (2,3) ],
vec![ (0,4), (1,5), (2,6) ],
vec![ ],
vec![ (0,0) ],
]
).ok().unwrap();
let product_true =
vec![
vec![ ],
vec![ ],
vec![ (1,3), (2,6) ],
vec![ (0,33), (1,45), (2,57) ],
vec![ (0,63), (1,87), (2,111) ],
];
for row_index in 0 .. 5 {
let vec_lazy = multiply_row_vector_with_matrix(
(& matrix_1).row( &row_index ).clone(),
& matrix_2, ring_operator,
OrderOperatorByLessThan::new( |x:&(i32, i32), y:&(i32, i32)| x.key() < y.key() )
)
.collect_vec();
let vec_true = product_true[ row_index ].clone();
assert_eq!( vec_lazy, vec_true )
}
}
}