use itertools::Itertools;
use crate::algebra::matrices::query::MatrixOracle;
use crate::algebra::rings::traits::{Semiring, Ring};
use crate::utilities::iterators::general::IntersectOrderedIteratorsUnsafe;
use std::collections::HashSet;
use std::hash::Hash;
use std::iter::FromIterator;
use std::marker::PhantomData;
use crate::topology::simplicial_complex::boundary::{SimplexBoundaryAscend, SimplexBoundaryDescend};
#[derive(Clone, Debug)]
pub struct DowkerBoundaryMatrixRowReverse< Vertex, RingOperator, RingElement >
where
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
Vertex: Ord + Clone,
{
next_cofacet_opt: Option< Vec< Vertex > >,
next_coefficient: RingElement,
vertices_to_insert: Vec< Vertex >, retrieval_locus: usize, insertion_locus: usize, ring_operator: RingOperator,
}
impl < RingOperator, RingElement >
DowkerBoundaryMatrixRowReverse
< usize, RingOperator, RingElement >
where
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
pub fn from_proximity_matrix( facet: Vec< usize >, proximity_matrix: &Vec< Vec< usize > >, ring_operator: RingOperator ) -> Self {
println!("NOTE: we assume that the proximity graph is just a sparsity pattern and DOES NOT CONTAIN the diagonal");
println!("NOTE: THIS IS INEFFICIENT; CAN REPLACE vertices-to-insert with an iterator");
println!("NOTE: consider merging the constructors for the ascending and descending ... or maybe not that; consider merging the constructor with the actual Dowker version ");
if facet.is_empty() {
return DowkerBoundaryMatrixRowReverse{
next_cofacet_opt: None,
next_coefficient: RingOperator::one(), vertices_to_insert: vec![], retrieval_locus: 0, insertion_locus: 0, ring_operator: ring_operator, }
}
let iters = facet.iter().map(|x| proximity_matrix[*x].iter().cloned() );
let vertices_to_insert = IntersectOrderedIteratorsUnsafe::new( iters ).collect_vec();
if vertices_to_insert.is_empty() {
return DowkerBoundaryMatrixRowReverse{
next_cofacet_opt: None,
next_coefficient: RingOperator::one(), vertices_to_insert: vec![], retrieval_locus: 0, insertion_locus: 0, ring_operator: ring_operator, }
}
let mut coefficient = ring_operator.minus_one_to_power( facet.len() );
let mut next_cofacet = facet.clone();
let mut insertion_locus = facet.len();
let retrieval_locus = vertices_to_insert.len() - 1;
let inserted_vertex = vertices_to_insert[retrieval_locus].clone();
while ( insertion_locus > 0 )
&&
( inserted_vertex < next_cofacet[ insertion_locus - 1 ] ) {
insertion_locus -= 1;
coefficient = ring_operator.negate( coefficient );
}
next_cofacet.insert( insertion_locus, inserted_vertex );
DowkerBoundaryMatrixRowReverse{
next_cofacet_opt: Some( next_cofacet ),
next_coefficient: coefficient,
vertices_to_insert: vertices_to_insert, retrieval_locus: retrieval_locus, insertion_locus: insertion_locus, ring_operator: ring_operator,
}
}
}
impl < Vertex, RingOperator, RingElement >
Iterator for
DowkerBoundaryMatrixRowReverse
< Vertex, RingOperator, RingElement >
where
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
Vertex: Ord + Clone,
{
type Item = (Vec<Vertex>, RingElement);
fn next( &mut self ) -> Option< Self::Item >{
match self.next_cofacet_opt {
None => { return None }
Some( ref mut next_cofacet ) => {
let return_value = ( next_cofacet.clone(), self.next_coefficient.clone() );
if self.retrieval_locus > 0 {
self.retrieval_locus -= 1;
let inserted_vertex = self.vertices_to_insert[ self.retrieval_locus ].clone();
while ( self.insertion_locus > 0 )
&&
( inserted_vertex < next_cofacet[ self.insertion_locus - 1 ] ) {
next_cofacet[ self.insertion_locus ] = next_cofacet[ self.insertion_locus - 1 ].clone();
self.insertion_locus -= 1;
self.next_coefficient = self.ring_operator.negate( self.next_coefficient.clone() );
}
next_cofacet[ self.insertion_locus ] = inserted_vertex;
}
else {
self.next_cofacet_opt = None;
}
return Some( return_value )
}
}
}
}
#[derive(Clone, Debug)]
pub struct DowkerBoundaryMatrixRow< Vertex, RingOperator, RingElement >
where
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
Vertex: Ord + Clone,
{
next_cofacet_opt: Option< Vec< Vertex > >,
next_coefficient: RingElement,
vertices_to_insert: Vec< Vertex >, retrieval_locus: usize, insertion_locus: usize, ring_operator: RingOperator,
}
impl < RingOperator, RingElement >
DowkerBoundaryMatrixRow
< usize, RingOperator, RingElement >
where
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
pub fn from_proximity_matrix( facet: Vec< usize >, proximity_matrix: &Vec< Vec< usize > >, ring_operator: RingOperator ) -> Self {
if facet.is_empty() {
return DowkerBoundaryMatrixRow{
next_cofacet_opt: None,
next_coefficient: RingOperator::one(), vertices_to_insert: vec![], retrieval_locus: 0, insertion_locus: 0, ring_operator: ring_operator, }
}
let iters = facet.iter().map(|x| proximity_matrix[*x].iter().cloned() );
let vertices_to_insert = IntersectOrderedIteratorsUnsafe::new( iters ).collect_vec();
if vertices_to_insert.is_empty() {
return DowkerBoundaryMatrixRow{
next_cofacet_opt: None,
next_coefficient: RingOperator::one(),
vertices_to_insert: vec![],
retrieval_locus: 0,
insertion_locus: 0,
ring_operator: ring_operator,
}
}
let mut coefficient = RingOperator::one();
let mut next_cofacet = facet.clone();
let mut insertion_locus = 0;
let retrieval_locus = 0;
let inserted_vertex = vertices_to_insert[retrieval_locus].clone();
while ( insertion_locus < next_cofacet.len() )
&&
( inserted_vertex > next_cofacet[ insertion_locus ] ) {
insertion_locus += 1;
coefficient = ring_operator.negate( coefficient );
}
next_cofacet.insert( insertion_locus, inserted_vertex );
DowkerBoundaryMatrixRow{
next_cofacet_opt: Some( next_cofacet ),
next_coefficient: coefficient,
vertices_to_insert: vertices_to_insert, retrieval_locus: retrieval_locus, insertion_locus: insertion_locus, ring_operator: ring_operator,
}
}
}
impl < Vertex, RingOperator, RingElement >
Iterator for
DowkerBoundaryMatrixRow
< Vertex, RingOperator, RingElement >
where
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
Vertex: Ord + Clone,
{
type Item = (Vec<Vertex>, RingElement);
fn next( &mut self ) -> Option< Self::Item >{
match self.next_cofacet_opt {
None => { return None }
Some( ref mut next_cofacet ) => {
let return_value = ( next_cofacet.clone(), self.next_coefficient.clone() );
if self.retrieval_locus + 1 < self.vertices_to_insert.len() {
self.retrieval_locus += 1;
let inserted_vertex = self.vertices_to_insert[ self.retrieval_locus ].clone();
while ( self.insertion_locus + 1 < next_cofacet.len() )
&&
( inserted_vertex > next_cofacet[ self.insertion_locus + 1 ] ) {
next_cofacet[ self.insertion_locus ] = next_cofacet[ self.insertion_locus +1 ].clone();
self.insertion_locus += 1;
self.next_coefficient = self.ring_operator.negate( self.next_coefficient.clone() );
}
next_cofacet[ self.insertion_locus ] = inserted_vertex;
}
else {
self.next_cofacet_opt = None;
}
return Some( return_value )
}
}
}
}
#[derive(Clone)]
pub struct FlagComplexBoundaryMatrixRowMajor
< Vertex, RingOperator, RingElement >
where
Vertex: Clone + Ord + Hash,
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
proximity_matrix: Vec< Vec< Vertex > >,
ring_operator: RingOperator,
phantom_ringelement: PhantomData< RingElement >,
}
impl < Vertex, RingOperator, RingElement >
FlagComplexBoundaryMatrixRowMajor
< Vertex, RingOperator, RingElement >
where
Vertex: Clone + Ord + Hash,
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
pub fn new( proximity_matrix: Vec< Vec< Vertex > >, ring_operator: RingOperator ) -> Self {
FlagComplexBoundaryMatrixRowMajor{ proximity_matrix, ring_operator, phantom_ringelement: PhantomData }
}
}
impl < Vertex, RingOperator, RingElement >
IndicesAndCoefficients for
FlagComplexBoundaryMatrixRowMajor
< Vertex, RingOperator, RingElement >
where
Vertex: Clone + Ord + Hash,
RingOperator: Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
type RowIndex = Vec< Vertex >; type ColumnIndex = Vec< Vertex >; type Coefficient = RingElement;
}
impl < RingOperator, RingElement >
MatrixOracle for
FlagComplexBoundaryMatrixRowMajor
< usize, RingOperator, RingElement >
where
RingOperator: Clone + Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
type Row = DowkerBoundaryMatrixRow< usize, RingOperator, RingElement >;
type RowIntoIter = Self::Row;
type RowEntry = ( Self::RowIndex, Self::Coefficient );
fn row( &self, row_index: Self::RowIndex ) -> Self::Row {
DowkerBoundaryMatrixRow::from_proximity_matrix( row_index, & self.proximity_matrix, self.ring_operator.clone() )
}
}
impl < RingOperator, RingElement >
ViewRowDescend for
FlagComplexBoundaryMatrixRowMajor
< usize, RingOperator, RingElement >
where
RingOperator: Clone + Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
type RowReverse = DowkerBoundaryMatrixRowReverse< usize, RingOperator, RingElement >;
type RowReverseIntoIter = Self::RowReverse;
type RowEntry = ( Self::RowIndex, Self::Coefficient );
fn row_reverse( &self, row_index: Self::RowIndex ) -> Self::RowReverse {
println!("GOT THROUGH THIS FILE ANE REMOVE THE DEBUG REQUIREMENTS");
DowkerBoundaryMatrixRowReverse::from_proximity_matrix( row_index, & self.proximity_matrix, self.ring_operator.clone() )
}
}
impl < Vertex, RingOperator, RingElement >
ViewColAscend for
FlagComplexBoundaryMatrixRowMajor
< Vertex, RingOperator, RingElement >
where
Vertex: Clone + Ord + Hash,
RingOperator: Clone + Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
type Column = SimplexBoundaryAscend< Vertex, RingOperator, RingElement >;
type ColumnIntoIter = Self::Column;
type ColumnEntry = ( Self::RowIndex, Self::Coefficient );
fn row( &self, row_index: Self::RowIndex ) -> Self::Column {
SimplexBoundaryAscend::new( row_index, self.ring_operator.clone() )
}
}
impl < Vertex, RingOperator, RingElement >
MatrixOracle for
FlagComplexBoundaryMatrixRowMajor
< Vertex, RingOperator, RingElement >
where
Vertex: Clone + Ord + Hash,
RingOperator: Clone + Semiring< RingElement > + Ring< RingElement >,
RingElement: Clone,
{
type ColumnReverse = SimplexBoundaryDescend< Vertex, RingOperator, RingElement >;
type ColumnReverseIntoIter = Self::ColumnReverse;
type ColumnEntry = ( Self::RowIndex, Self::Coefficient );
fn column_reverse( &self, row_index: Self::RowIndex ) -> Self::ColumnReverse {
SimplexBoundaryDescend::new( row_index, self.ring_operator.clone() )
}
}
#[cfg(test)]
mod tests {
}