use std::fmt;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
use index_utils::remove_sparse_indices;
use relp_num::{Field, Negateable, One};
use relp_num::NonZero;
use relp_num::RationalBig;
use crate::algorithm::two_phase::matrix_provider::column::{Column, SparseSliceIterator};
use crate::algorithm::two_phase::matrix_provider::column::identity::Identity;
use crate::algorithm::two_phase::matrix_provider::filter::generic_wrapper::IntoFilteredColumn;
use crate::data::linear_algebra::matrix::{ColumnMajor, MatrixOrder, SparseMatrix};
use crate::data::linear_algebra::SparseTuple;
use crate::data::linear_algebra::traits::{SparseComparator, SparseElement};
use crate::data::linear_algebra::vector::{DenseVector, Vector};
#[derive(Debug, Clone, PartialEq)]
pub struct IncidenceMatrix {
data: SparseMatrix<ArcDirection, ArcDirection, ColumnMajor>,
removed: Vec<usize>,
}
impl IncidenceMatrix {
pub fn new<F: SparseElement<F> + SparseComparator>(
adjacency_matrix: SparseMatrix<F, F, ColumnMajor>,
mut removed: Vec<usize>,
) -> (Self, DenseVector<F>) {
let nr_vertices = adjacency_matrix.nr_columns();
debug_assert_eq!(adjacency_matrix.nr_columns(), adjacency_matrix.nr_rows());
debug_assert!((0..nr_vertices).all(|j| adjacency_matrix.data[j].iter().all(|&(i, _)| i != j)));
removed.sort_unstable();
let (edges, values): (Vec<_>, Vec<_>) = adjacency_matrix.data.into_iter().enumerate()
.flat_map(|(from, outgoing_arcs)| {
let removed_ref = &removed;
outgoing_arcs.into_iter().map(move |(to, values)| {
let from_deleted = removed_ref.binary_search(&from);
let to_deleted = removed_ref.binary_search(&to);
let tuples = match (from_deleted, to_deleted) {
(Ok(_), Ok(_)) => { vec![]
},
(Ok(_), Err(to_shift)) => {
vec![(to - to_shift, ArcDirection::Incoming)]
}
(Err(from_shift), Ok(_)) => {
vec![(from - from_shift, ArcDirection::Outgoing)]
}
(Err(from_shift), Err(to_shift)) => { let from_shifted = from - from_shift;
let to_shifted = to - to_shift;
if from_shifted < to_shifted {
vec![(from_shifted, ArcDirection::Outgoing), (to_shifted, ArcDirection::Incoming)]
} else {
vec![(to_shifted, ArcDirection::Incoming), (from_shifted, ArcDirection::Outgoing)]
}
},
};
(tuples, values)
})
}).unzip();
let nr_edges = edges.len();
(
Self {
data: ColumnMajor::new(edges, nr_vertices - removed.len(), nr_edges),
removed,
},
DenseVector::new(values, nr_edges),
)
}
pub fn column(&self, j: usize) -> Vec<SparseTuple<ArcDirection>> {
debug_assert!(j < self.nr_edges());
self.data.iter_column(j).cloned().collect()
}
pub fn nr_vertices(&self) -> usize {
self.data.nr_rows() + self.removed.len()
}
pub fn nr_edges(&self) -> usize {
self.data.nr_columns()
}
}
#[derive(Clone, Debug)]
pub struct ArcIncidenceColumn(pub Vec<SparseTuple<ArcDirection>>);
impl IntoIterator for ArcIncidenceColumn {
type Item = SparseTuple<ArcDirection>;
type IntoIter = impl Iterator<Item=Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Column for ArcIncidenceColumn {
type F = ArcDirection;
type Iter<'a> = SparseSliceIterator<'a, ArcDirection>;
fn iter(&self) -> Self::Iter<'_> {
SparseSliceIterator::new(&self.0)
}
fn index_to_string(&self, i: usize) -> String {
self.0.iter()
.find(|&&(index, _)| index == i)
.map_or_else(|| "0".to_string(), |(_, v)| v.to_string())
}
}
impl Identity for ArcIncidenceColumn {
fn identity(i: usize, _len: usize) -> Self {
Self(vec![(i, ArcDirection::Incoming)])
}
}
impl IntoFilteredColumn for ArcIncidenceColumn {
type Filtered = Self;
fn into_filtered(mut self, to_remove: &[usize]) -> Self::Filtered {
remove_sparse_indices(&mut self.0, to_remove);
self
}
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub enum ArcDirection {
Incoming,
Outgoing,
}
impl NonZero for ArcDirection {
fn is_not_zero(&self) -> bool {
true
}
}
impl fmt::Display for ArcDirection {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self {
ArcDirection::Incoming => "1",
ArcDirection::Outgoing => "-1",
})
}
}
impl From<ArcDirection> for RationalBig {
#[must_use]
#[inline]
fn from(direction: ArcDirection) -> Self {
From::from(&direction)
}
}
impl From<&ArcDirection> for RationalBig {
#[must_use]
#[inline]
fn from(direction: &ArcDirection) -> Self {
match direction {
ArcDirection::Incoming => RationalBig::one(),
ArcDirection::Outgoing => -RationalBig::one(),
}
}
}
impl Add<ArcDirection> for RationalBig {
type Output = Self;
#[must_use]
#[inline]
fn add(mut self, rhs: ArcDirection) -> Self::Output {
AddAssign::add_assign(&mut self, rhs);
self
}
}
impl Add<&ArcDirection> for RationalBig {
type Output = Self;
#[must_use]
#[inline]
fn add(mut self, rhs: &ArcDirection) -> Self::Output {
AddAssign::add_assign(&mut self, rhs);
self
}
}
impl AddAssign<ArcDirection> for RationalBig {
#[inline]
fn add_assign(&mut self, rhs: ArcDirection) {
AddAssign::add_assign(self, &rhs);
}
}
impl AddAssign<&ArcDirection> for RationalBig {
#[inline]
fn add_assign(&mut self, rhs: &ArcDirection) {
match rhs {
ArcDirection::Incoming => *self += One,
ArcDirection::Outgoing => *self -= One,
}
}
}
impl Sub<ArcDirection> for RationalBig {
type Output = Self;
#[must_use]
#[inline]
fn sub(mut self, rhs: ArcDirection) -> Self::Output {
SubAssign::sub_assign(&mut self, rhs);
self
}
}
impl Sub<&ArcDirection> for RationalBig {
type Output = Self;
#[must_use]
#[inline]
fn sub(mut self, rhs: &ArcDirection) -> Self::Output {
SubAssign::sub_assign(&mut self, rhs);
self
}
}
impl SubAssign<ArcDirection> for RationalBig {
#[inline]
fn sub_assign(&mut self, rhs: ArcDirection) {
SubAssign::sub_assign(self, &rhs);
}
}
impl SubAssign<&ArcDirection> for RationalBig {
#[inline]
fn sub_assign(&mut self, rhs: &ArcDirection) {
match rhs {
ArcDirection::Incoming => *self -= One,
ArcDirection::Outgoing => *self += One,
}
}
}
impl Mul<ArcDirection> for RationalBig {
type Output = Self;
#[must_use]
#[inline]
fn mul(mut self, rhs: ArcDirection) -> Self::Output {
MulAssign::mul_assign(&mut self, rhs);
self
}
}
impl Mul<&ArcDirection> for RationalBig {
type Output = Self;
#[must_use]
#[inline]
fn mul(mut self, rhs: &ArcDirection) -> Self::Output {
MulAssign::mul_assign(&mut self, rhs);
self
}
}
impl MulAssign<ArcDirection> for RationalBig {
#[inline]
fn mul_assign(&mut self, rhs: ArcDirection) {
MulAssign::mul_assign(self, &rhs);
}
}
impl MulAssign<&ArcDirection> for RationalBig {
#[inline]
fn mul_assign(&mut self, rhs: &ArcDirection) {
match rhs {
ArcDirection::Incoming => {},
ArcDirection::Outgoing => self.negate(),
}
}
}
impl Mul<&ArcDirection> for &RationalBig {
type Output = RationalBig;
#[must_use]
#[inline]
fn mul(self, rhs: &ArcDirection) -> Self::Output {
match rhs {
ArcDirection::Incoming => self.clone(),
ArcDirection::Outgoing => -self.clone(),
}
}
}
impl Div<ArcDirection> for RationalBig {
type Output = Self;
#[must_use]
#[inline]
fn div(mut self, rhs: ArcDirection) -> Self::Output {
DivAssign::div_assign(&mut self, rhs);
self
}
}
impl Div<&ArcDirection> for RationalBig {
type Output = Self;
#[must_use]
#[inline]
fn div(mut self, rhs: &ArcDirection) -> Self::Output {
DivAssign::div_assign(&mut self, rhs);
self
}
}
impl DivAssign<ArcDirection> for RationalBig {
#[inline]
fn div_assign(&mut self, rhs: ArcDirection) {
DivAssign::div_assign(self, &rhs);
}
}
impl DivAssign<&ArcDirection> for RationalBig {
#[inline]
fn div_assign(&mut self, rhs: &ArcDirection) {
match rhs {
ArcDirection::Incoming => {},
ArcDirection::Outgoing => self.negate(),
}
}
}