use std::rc::Rc;
use crate::prelude::{Pair, RandomAccessLabeling, SequentialLabeling};
use impl_tools::autoimpl;
use lender::*;
use super::{
SortedIterator, SortedLender,
labels::EqError,
lenders::{LenderIntoIter, NodeLabelsLender},
split::SplitLabeling,
};
#[allow(non_camel_case_types)]
struct this_method_cannot_be_called_use_successors_instead;
#[autoimpl(for<S: trait + ?Sized> &S, &mut S, Rc<S>)]
pub trait SequentialGraph: SequentialLabeling<Label = usize> {}
pub fn eq<G0: SequentialGraph, G1: SequentialGraph>(g0: &G0, g1: &G1) -> Result<(), EqError>
where
for<'a> G0::Lender<'a>: SortedLender,
for<'a> G1::Lender<'a>: SortedLender,
{
if g0.num_nodes() != g1.num_nodes() {
return Err(EqError::NumNodes {
first: g0.num_nodes(),
second: g1.num_nodes(),
});
}
for_!((index, ((node0, succ0), (node1, succ1))) in g0.iter().zip(g1.iter()).enumerate() {
if node0 != node1 {
return Err(EqError::Node {
index,
first: node0,
second: node1,
});
}
let mut succ0 = succ0.into_iter().collect::<Vec<_>>();
let mut succ1 = succ1.into_iter().collect::<Vec<_>>();
succ0.sort();
succ1.sort();
super::labels::eq_succs(node0, succ0, succ1)?;
});
Ok(())
}
pub type Succ<'succ, 'node, S> =
<<S as SequentialLabeling>::Lender<'node> as NodeLabelsLender<'succ>>::IntoIterator;
#[autoimpl(for<S: trait + ?Sized> &S, &mut S, Rc<S>)]
pub trait RandomAccessGraph: RandomAccessLabeling<Label = usize> + SequentialGraph {
#[inline(always)]
fn successors(&self, node_id: usize) -> <Self as RandomAccessLabeling>::Labels<'_> {
<Self as RandomAccessLabeling>::labels(self, node_id)
}
#[allow(private_bounds)]
fn labels(&self, _node_id: usize) -> <Self as RandomAccessLabeling>::Labels<'_>
where
for<'a> this_method_cannot_be_called_use_successors_instead: Clone,
{
unimplemented!("use the `successors` method instead");
}
fn has_arc(&self, src_node_id: usize, dst_node_id: usize) -> bool {
for succ in self.successors(src_node_id) {
if succ == dst_node_id {
return true;
}
}
false
}
}
#[autoimpl(for<S: trait + ?Sized> &S, &mut S, Rc<S>)]
pub trait LabeledSequentialGraph<L>: SequentialLabeling<Label = (usize, L)> {}
pub fn eq_labeled<M, G0: LabeledSequentialGraph<M>, G1: LabeledSequentialGraph<M>>(
g0: &G0,
g1: &G1,
) -> Result<(), EqError>
where
for<'a> G0::Lender<'a>: SortedLender,
for<'a> G1::Lender<'a>: SortedLender,
M: PartialEq + std::fmt::Debug,
{
if g0.num_nodes() != g1.num_nodes() {
return Err(EqError::NumNodes {
first: g0.num_nodes(),
second: g1.num_nodes(),
});
}
for_!(((node0, succ0), (node1, succ1)) in g0.iter().zip(g1.iter()) {
debug_assert_eq!(node0, node1);
super::labels::eq_succs(node0, succ0, succ1)?;
});
Ok(())
}
#[derive(Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct UnitLabelGraph<G: SequentialGraph>(pub G);
#[doc(hidden)]
#[repr(transparent)]
pub struct UnitLender<L>(pub L);
impl<'succ, L> NodeLabelsLender<'succ> for UnitLender<L>
where
L: for<'next> NodeLabelsLender<'next, Label = usize>,
{
type Label = (usize, ());
type IntoIterator = UnitSucc<LenderIntoIter<'succ, L>>;
}
impl<'succ, L> Lending<'succ> for UnitLender<L>
where
L: for<'next> NodeLabelsLender<'next, Label = usize>,
{
type Lend = (usize, <Self as NodeLabelsLender<'succ>>::IntoIterator);
}
impl<L> Lender for UnitLender<L>
where
L: for<'next> NodeLabelsLender<'next, Label = usize>,
{
unsafe_assume_covariance!();
#[inline(always)]
fn next(&mut self) -> Option<Lend<'_, Self>> {
self.0.next().map(|x| {
let t = x.into_pair();
(t.0, UnitSucc(t.1.into_iter()))
})
}
}
unsafe impl<L: SortedLender> SortedLender for UnitLender<L> where
L: for<'next> NodeLabelsLender<'next, Label = usize>
{
}
#[doc(hidden)]
#[repr(transparent)]
pub struct UnitSucc<I>(pub I);
impl<I: Iterator<Item = usize>> Iterator for UnitSucc<I> {
type Item = (usize, ());
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
Some((self.0.next()?, ()))
}
}
unsafe impl<I: Iterator<Item = usize> + SortedIterator> SortedIterator for UnitSucc<I> {}
impl<G: SequentialGraph> SequentialLabeling for UnitLabelGraph<G> {
type Label = (usize, ());
type Lender<'node>
= UnitLender<G::Lender<'node>>
where
Self: 'node;
#[inline(always)]
fn num_nodes(&self) -> usize {
self.0.num_nodes()
}
#[inline(always)]
fn iter_from(&self, from: usize) -> Self::Lender<'_> {
UnitLender(self.0.iter_from(from))
}
}
impl<G: SequentialGraph> LabeledSequentialGraph<()> for UnitLabelGraph<G> {}
impl<G: SequentialGraph + SplitLabeling> SplitLabeling for UnitLabelGraph<G>
where
for<'a> <G::IntoIterator<'a> as IntoIterator>::IntoIter: Send + Sync,
{
type SplitLender<'a>
= UnitLender<G::SplitLender<'a>>
where
Self: 'a;
type IntoIterator<'a>
= core::iter::Map<
<G::IntoIterator<'a> as IntoIterator>::IntoIter,
fn(G::SplitLender<'a>) -> Self::SplitLender<'a>,
>
where
Self: 'a;
fn split_iter(&self, how_many: usize) -> Self::IntoIterator<'_> {
self.0.split_iter(how_many).into_iter().map(UnitLender)
}
}
#[autoimpl(for<S: trait + ?Sized> &S, &mut S, Rc<S>)]
pub trait LabeledRandomAccessGraph<L>: RandomAccessLabeling<Label = (usize, L)> {
#[inline(always)]
fn successors(&self, node_id: usize) -> <Self as RandomAccessLabeling>::Labels<'_> {
<Self as RandomAccessLabeling>::labels(self, node_id)
}
#[allow(private_bounds)]
fn labels(&self, _node_id: usize) -> <Self as RandomAccessLabeling>::Labels<'_>
where
for<'a> this_method_cannot_be_called_use_successors_instead: Clone,
{
unimplemented!("use the `successors` method instead");
}
fn has_arc(&self, src: usize, dst: usize) -> bool {
for (succ, _) in self.successors(src) {
if succ == dst {
return true;
}
}
false
}
}
impl<G: RandomAccessGraph> RandomAccessLabeling for UnitLabelGraph<G> {
type Labels<'succ>
= UnitSucc<<<G as RandomAccessLabeling>::Labels<'succ> as IntoIterator>::IntoIter>
where
Self: 'succ;
#[inline(always)]
fn num_arcs(&self) -> u64 {
self.0.num_arcs()
}
#[inline(always)]
fn labels(&self, node_id: usize) -> <Self as RandomAccessLabeling>::Labels<'_> {
UnitSucc(self.0.successors(node_id).into_iter())
}
#[inline(always)]
fn outdegree(&self, node_id: usize) -> usize {
self.0.outdegree(node_id)
}
}
impl<G: RandomAccessGraph> LabeledRandomAccessGraph<()> for UnitLabelGraph<G> {}