use crate::prelude::*;
use lender::*;
#[derive(Debug, Clone)]
pub struct UnionGraph<G: SequentialGraph, H: SequentialGraph>(pub G, pub H);
impl<G: SequentialGraph, H: SequentialGraph> SequentialLabeling for UnionGraph<G, H>
where
for<'a> G::Lender<'a>: SortedLender,
for<'a, 'b> LenderIntoIter<'b, G::Lender<'a>>: SortedIterator,
for<'a> H::Lender<'a>: SortedLender,
for<'a, 'b> LenderIntoIter<'b, H::Lender<'a>>: SortedIterator,
{
type Label = usize;
type Lender<'b>
= NodeLabels<G::Lender<'b>, H::Lender<'b>>
where
Self: 'b;
#[inline(always)]
fn num_nodes(&self) -> usize {
self.0.num_nodes().max(self.1.num_nodes())
}
#[inline(always)]
fn num_arcs_hint(&self) -> Option<u64> {
None
}
#[inline(always)]
fn iter_from(&self, from: usize) -> Self::Lender<'_> {
NodeLabels(
self.0.iter_from(from.min(self.0.num_nodes())),
self.1.iter_from(from.min(self.1.num_nodes())),
)
}
}
impl<G: SequentialGraph, H: SequentialGraph> SplitLabeling for UnionGraph<G, H>
where
for<'a> G::Lender<'a>: SortedLender + Clone + Send + Sync,
for<'a, 'b> LenderIntoIter<'b, G::Lender<'a>>: SortedIterator,
for<'a> H::Lender<'a>: SortedLender + Clone + Send + Sync,
for<'a, 'b> LenderIntoIter<'b, H::Lender<'a>>: SortedIterator,
{
type SplitLender<'a>
= split::seq::Lender<'a, UnionGraph<G, H>>
where
Self: 'a;
type IntoIterator<'a>
= split::seq::IntoIterator<'a, UnionGraph<G, H>>
where
Self: 'a;
fn split_iter(&self, how_many: usize) -> Self::IntoIterator<'_> {
split::seq::Iter::new(self.iter(), self.num_nodes(), how_many)
}
}
impl<G: SequentialGraph, H: SequentialGraph> SequentialGraph for UnionGraph<G, H>
where
for<'a> G::Lender<'a>: SortedLender + Clone,
for<'a, 'b> LenderIntoIter<'b, G::Lender<'a>>: SortedIterator,
for<'a> H::Lender<'a>: SortedLender + Clone,
for<'a, 'b> LenderIntoIter<'b, H::Lender<'a>>: SortedIterator,
{
}
impl<'c, G: SequentialGraph, H: SequentialGraph> IntoLender for &'c UnionGraph<G, H>
where
for<'a> G::Lender<'a>: SortedLender + Clone,
for<'a, 'b> LenderIntoIter<'b, G::Lender<'a>>: SortedIterator,
for<'a> H::Lender<'a>: SortedLender + Clone,
for<'a, 'b> LenderIntoIter<'b, H::Lender<'a>>: SortedIterator,
{
type Lender = <UnionGraph<G, H> as SequentialLabeling>::Lender<'c>;
#[inline(always)]
fn into_lender(self) -> Self::Lender {
self.iter()
}
}
#[doc(hidden)]
#[derive(Debug, Clone)]
pub struct NodeLabels<L, M>(L, M);
impl<
'succ,
L: Lender + for<'next> NodeLabelsLender<'next, Label = usize>,
M: Lender + for<'next> NodeLabelsLender<'next, Label = usize>,
> NodeLabelsLender<'succ> for NodeLabels<L, M>
{
type Label = usize;
type IntoIterator = Succ<LenderIntoIter<'succ, L>, LenderIntoIter<'succ, M>>;
}
impl<
'succ,
L: Lender + for<'next> NodeLabelsLender<'next, Label = usize>,
M: Lender + for<'next> NodeLabelsLender<'next, Label = usize>,
> Lending<'succ> for NodeLabels<L, M>
{
type Lend = (usize, <Self as NodeLabelsLender<'succ>>::IntoIterator);
}
impl<
L: Lender + for<'next> NodeLabelsLender<'next, Label = usize>,
M: Lender + for<'next> NodeLabelsLender<'next, Label = usize>,
> Lender for NodeLabels<L, M>
{
unsafe_assume_covariance!();
#[inline(always)]
fn next(&mut self) -> Option<Lend<'_, Self>> {
let (node0, iter0) = self.0.next().unzip();
let (node1, iter1) = self.1.next().unzip();
Some((
node0.or(node1)?,
Succ::new(
iter0.map(IntoIterator::into_iter),
iter1.map(IntoIterator::into_iter),
),
))
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let (min0, max0) = self.0.size_hint();
let (min1, max1) = self.1.size_hint();
(
min0.max(min1),
match (max0, max1) {
(None, None) => None,
(Some(max), None) => Some(max),
(None, Some(max)) => Some(max),
(Some(max0), Some(max1)) => Some(max0.max(max1)),
},
)
}
}
impl<
L: Lender + for<'next> NodeLabelsLender<'next, Label = usize> + ExactSizeLender,
M: Lender + for<'next> NodeLabelsLender<'next, Label = usize> + ExactSizeLender,
> ExactSizeLender for NodeLabels<L, M>
{
#[inline(always)]
fn len(&self) -> usize {
self.0.len().max(self.1.len())
}
}
unsafe impl<
L: Lender + for<'next> NodeLabelsLender<'next, Label = usize> + SortedLender,
M: Lender + for<'next> NodeLabelsLender<'next, Label = usize> + SortedLender,
> SortedLender for NodeLabels<L, M>
{
}
#[derive(Debug, Clone)]
pub struct Succ<I: Iterator<Item = usize>, J: Iterator<Item = usize>> {
iter0: Option<core::iter::Peekable<I>>,
iter1: Option<core::iter::Peekable<J>>,
}
impl<I: Iterator<Item = usize>, J: Iterator<Item = usize>> Succ<I, J> {
pub fn new(iter0: Option<I>, iter1: Option<J>) -> Self {
Self {
iter0: iter0.map(Iterator::peekable),
iter1: iter1.map(Iterator::peekable),
}
}
}
impl<I: Iterator<Item = usize>, J: Iterator<Item = usize>> Iterator for Succ<I, J> {
type Item = usize;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
let next0 = self.iter0.as_mut().and_then(|iter| iter.peek().copied());
let next1 = self.iter1.as_mut().and_then(|iter| iter.peek().copied());
match next0
.unwrap_or(usize::MAX)
.cmp(&next1.unwrap_or(usize::MAX))
{
std::cmp::Ordering::Greater => self.iter1.as_mut().and_then(Iterator::next),
std::cmp::Ordering::Less => self.iter0.as_mut().and_then(Iterator::next),
std::cmp::Ordering::Equal => {
self.iter0.as_mut().and_then(Iterator::next);
self.iter1.as_mut().and_then(Iterator::next)
}
}
}
}
unsafe impl<I: Iterator<Item = usize> + SortedIterator, J: Iterator<Item = usize> + SortedIterator>
SortedIterator for Succ<I, J>
{
}
impl<I: Iterator<Item = usize>, J: Iterator<Item = usize>> std::iter::FusedIterator for Succ<I, J> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_union_graph() -> anyhow::Result<()> {
use crate::graphs::vec_graph::VecGraph;
let g = [
VecGraph::from_arcs([
(0, 1),
(0, 3),
(1, 2),
(2, 0),
(2, 2),
(2, 4),
(3, 4),
(3, 5),
(4, 1),
]),
VecGraph::from_arcs([
(1, 2),
(1, 3),
(2, 1),
(2, 3),
(2, 4),
(4, 0),
(5, 1),
(5, 2),
(6, 6),
]),
];
for i in 0..2 {
let union = UnionGraph(g[i].clone(), g[1 - i].clone());
assert_eq!(union.num_nodes(), 7);
let mut iter = union.iter();
let Some((x, s)) = iter.next() else { panic!() };
assert_eq!(x, 0);
assert_eq!(s.collect::<Vec<_>>(), vec![1, 3]);
let Some((x, s)) = iter.next() else { panic!() };
assert_eq!(x, 1);
assert_eq!(s.collect::<Vec<_>>(), vec![2, 3]);
let Some((x, s)) = iter.next() else { panic!() };
assert_eq!(x, 2);
assert_eq!(s.collect::<Vec<_>>(), vec![0, 1, 2, 3, 4]);
let Some((x, s)) = iter.next() else { panic!() };
assert_eq!(x, 3);
assert_eq!(s.collect::<Vec<_>>(), vec![4, 5]);
let Some((x, s)) = iter.next() else { panic!() };
assert_eq!(x, 4);
assert_eq!(s.collect::<Vec<_>>(), vec![0, 1]);
let Some((x, s)) = iter.next() else { panic!() };
assert_eq!(x, 5);
assert_eq!(s.collect::<Vec<_>>(), vec![1, 2]);
let Some((x, s)) = iter.next() else { panic!() };
assert_eq!(x, 6);
assert_eq!(s.collect::<Vec<_>>(), vec![6]);
assert!(iter.next().is_none());
}
Ok(())
}
}