rs_graph/
adjacencies.rs

1/*
2 * Copyright (c) 2018, 2020-2022 Frank Fischer <frank-fischer@shadow-soft.de>
3 *
4 * This program is free software: you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation, either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program.  If not, see  <http://www.gnu.org/licenses/>
16 */
17
18//! Abstraction of neighboring edges.
19//!
20//! This module implements the arguably simplest representation of a graph: for
21//! each node the list of adjacent edges and nodes. No further information like
22//! the number of nodes or edges in a graph is available.
23//!
24//! The purpose of the trait [`Adjacencies`] is therefore to abstract over the concept
25//! of adjacent edges and nodes. Standard examples are "all edges" (in the
26//! undirected sense), "incoming edges" and "outgoing edges" represented by the structs
27//! [`Neighbors`], [`InEdges`] and [`OutEdges`].
28//!
29//! Some algorithms (e.g. breadth-first search or depth-first search) can be
30//! described in terms of adjacencies only.
31//!
32//! There are three basic ways to define an adjacency:
33//!
34//! 1. From an existing graph or digraph using [`Neighbors`], [`OutEdges`] or [`InEdges`],
35//! 2. From a function returning an iterator over adjacent edges for a given node, see [`FnAdj`],
36//! 3. By implementing the [`Adjacencies`] trait on your own.
37//!
38//! # Example
39//!
40//! ```
41//! use rs_graph::classes;
42//! use rs_graph::Net;
43//! use rs_graph::traits::*;
44//! use rs_graph::adjacencies::*;
45//!
46//! let g = classes::peterson::<Net>();
47//!
48//! let neighs = Neighbors(&g);
49//! let neighs = neighs.filter(|&(e, _)| {
50//!   let (u,v) = g.enodes(e);
51//!   (g.node_id(u) < 5) == (g.node_id(v) < 5)
52//! });
53//! for u in g.nodes() {
54//!     assert_eq!(neighs.neighs(u).count(), 2);
55//! }
56//! ```
57
58use crate::traits::{Directed, GraphIter, GraphIterator, Undirected};
59use std::marker::PhantomData;
60
61//pub type AdjacenciesIter<'a, G> = GraphIter<'a, G, <G as Adjacencies<'a>>::IncidenceIt>;
62
63pub trait Adjacencies<'a> {
64    type Node: Copy + Eq + 'a;
65
66    type Edge: Copy + Eq + 'a;
67
68    type IncidenceIt: GraphIterator<Self, Item = (Self::Edge, Self::Node)>;
69
70    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt;
71
72    fn neighs<'b>(&'b self, u: Self::Node) -> GraphIter<'b, Self, Self::IncidenceIt>
73    where
74        'a: 'b,
75        Self: Sized,
76    {
77        GraphIter(self.neigh_iter(u), self)
78    }
79
80    fn filter<P>(self, predicate: P) -> FilterAdjacencies<Self, P>
81    where
82        Self: Sized,
83        P: for<'r> Fn(&'r (Self::Edge, Self::Node)) -> bool,
84    {
85        FilterAdjacencies(self, predicate)
86    }
87}
88
89pub struct FilterAdjacencies<A, P>(A, P);
90
91#[derive(Clone)]
92pub struct Filtered<I>(I);
93
94impl<A, P, I> GraphIterator<FilterAdjacencies<A, P>> for Filtered<I>
95where
96    I: GraphIterator<A>,
97    P: for<'r> Fn(&'r I::Item) -> bool,
98{
99    type Item = I::Item;
100
101    fn next(&mut self, adj: &FilterAdjacencies<A, P>) -> Option<Self::Item> {
102        while let Some(it) = self.0.next(&adj.0) {
103            if (adj.1)(&it) {
104                return Some(it);
105            }
106        }
107        None
108    }
109}
110
111impl<'a, A, P> Adjacencies<'a> for FilterAdjacencies<A, P>
112where
113    A: Adjacencies<'a>,
114    P: 'a + Clone + for<'r> Fn(&'r (A::Edge, A::Node)) -> bool,
115{
116    type Node = A::Node;
117    type Edge = A::Edge;
118    type IncidenceIt = Filtered<A::IncidenceIt>;
119
120    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
121        Filtered(self.0.neigh_iter(u))
122    }
123}
124
125#[derive(Clone)]
126pub struct AdjacenciesWrapIt<I>(I);
127
128impl<I> From<I> for AdjacenciesWrapIt<I> {
129    fn from(it: I) -> Self {
130        AdjacenciesWrapIt(it)
131    }
132}
133
134impl<'g, G, I> GraphIterator<Neighbors<'g, G>> for AdjacenciesWrapIt<I>
135where
136    I: GraphIterator<G>,
137{
138    type Item = I::Item;
139
140    fn next(&mut self, adj: &Neighbors<'g, G>) -> Option<Self::Item> {
141        self.0.next(adj.0)
142    }
143
144    fn size_hint(&self, adj: &Neighbors<'g, G>) -> (usize, Option<usize>) {
145        self.0.size_hint(adj.0)
146    }
147
148    fn count(self, adj: &Neighbors<'g, G>) -> usize {
149        self.0.count(adj.0)
150    }
151}
152
153impl<'g, G, I> GraphIterator<OutEdges<'g, G>> for AdjacenciesWrapIt<I>
154where
155    I: GraphIterator<G>,
156{
157    type Item = I::Item;
158
159    fn next(&mut self, adj: &OutEdges<'g, G>) -> Option<Self::Item> {
160        self.0.next(adj.0)
161    }
162
163    fn size_hint(&self, adj: &OutEdges<'g, G>) -> (usize, Option<usize>) {
164        self.0.size_hint(adj.0)
165    }
166
167    fn count(self, adj: &OutEdges<'g, G>) -> usize {
168        self.0.count(adj.0)
169    }
170}
171
172impl<'g, G, I> GraphIterator<InEdges<'g, G>> for AdjacenciesWrapIt<I>
173where
174    I: GraphIterator<G>,
175{
176    type Item = I::Item;
177
178    fn next(&mut self, adj: &InEdges<'g, G>) -> Option<Self::Item> {
179        self.0.next(adj.0)
180    }
181
182    fn size_hint(&self, adj: &InEdges<'g, G>) -> (usize, Option<usize>) {
183        self.0.size_hint(adj.0)
184    }
185
186    fn count(self, adj: &InEdges<'g, G>) -> usize {
187        self.0.count(adj.0)
188    }
189}
190
191/// Neighbor access over all adjacent (undirected) edges.
192pub struct Neighbors<'g, G>(pub &'g G);
193
194impl<'a, 'g: 'a, G> Adjacencies<'a> for Neighbors<'g, G>
195where
196    G: Undirected,
197{
198    type Node = G::Node<'a>;
199    type Edge = G::Edge<'a>;
200    type IncidenceIt = AdjacenciesWrapIt<G::NeighIt<'a>>;
201
202    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
203        self.0.neigh_iter(u).into()
204    }
205}
206
207/// Neighbor access over all outgoing edges of a `Digraph`.
208pub struct OutEdges<'g, G>(pub &'g G);
209
210impl<'a, 'g: 'a, G> Adjacencies<'a> for OutEdges<'g, G>
211where
212    G: Directed,
213{
214    type Node = G::Node<'a>;
215    type Edge = G::Edge<'a>;
216    type IncidenceIt = AdjacenciesWrapIt<G::OutIt<'a>>;
217
218    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
219        self.0.out_iter(u).into()
220    }
221}
222
223/// Neighbor access over all incoming edges of a `Digraph`.
224pub struct InEdges<'g, G>(pub &'g G);
225
226impl<'a, 'g: 'a, G> Adjacencies<'a> for InEdges<'g, G>
227where
228    G: Directed,
229{
230    type Node = G::Node<'a>;
231    type Edge = G::Edge<'a>;
232    type IncidenceIt = AdjacenciesWrapIt<G::InIt<'a>>;
233
234    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
235        self.0.in_iter(u).into()
236    }
237}
238
239impl<'a, A, I> GraphIterator<&'a A> for AdjacenciesWrapIt<I>
240where
241    I: GraphIterator<A>,
242{
243    type Item = I::Item;
244
245    fn next(&mut self, adj: &&'a A) -> Option<Self::Item> {
246        self.0.next(*adj)
247    }
248
249    fn size_hint(&self, adj: &&'a A) -> (usize, Option<usize>) {
250        self.0.size_hint(*adj)
251    }
252
253    fn count(self, adj: &&'a A) -> usize {
254        self.0.count(*adj)
255    }
256}
257
258/// Implement Adjacencies for references.
259impl<'a, A> Adjacencies<'a> for &'a A
260where
261    A: Adjacencies<'a>,
262{
263    type Node = A::Node;
264    type Edge = A::Edge;
265    type IncidenceIt = AdjacenciesWrapIt<A::IncidenceIt>;
266
267    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
268        (*self).neigh_iter(u).into()
269    }
270}
271
272/// An adjacency defined by a function returning iterators.
273///
274/// This struct wraps a `Fn(N) -> I` which provides for each node of
275/// type `N` an iterator over the adjacent edges. This allows to create
276/// simple graphs on the fly.
277///
278/// # Example
279///
280/// The following adjacency describes a simple grid graph.
281///
282/// ```
283/// use rs_graph::adjacencies::*;
284///
285/// // Create a 5 x 7 grid graph.
286/// // The nodes are pairs (i,j) and the edges are pairs of nodes.
287/// let n = 5;
288/// let m = 7;
289/// let g = FnAdj::from(move |u: (isize, isize)| {
290///     IntoIterator::into_iter([(-1, 0), (1, 0), (0, -1), (0, 1)])
291///         .map(move |d| (u.0 + d.0, u.1 + d.1))
292///         .filter(move |v| 0 <= v.0 && v.0 < n && 0 <= v.1 && v.1 < m)
293///         .map(move |v| ((u, v), v))
294/// });
295///
296/// // count the number of nodes with degree 2, 3 and 4
297/// let mut cnt2 = 0;
298/// let mut cnt3 = 0;
299/// let mut cnt4 = 0;
300/// for i in 0..n {
301///     for j in 0..m {
302///         match g.neighs((i, j)).count() {
303///             2 => cnt2 += 1,
304///             3 => cnt3 += 1,
305///             4 => cnt4 += 1,
306///             _ => unreachable!(),
307///         }
308///     }
309/// }
310/// assert_eq!(4, cnt2);
311/// assert_eq!(16, cnt3);
312/// assert_eq!(15, cnt4);
313/// ```
314pub struct FnAdj<N, E, Ne, NeIt> {
315    neighsfn: Ne,
316    phantom: PhantomData<(N, E, NeIt)>,
317}
318
319#[derive(Clone)]
320pub struct FnNeighIt<NeIt>
321where
322    NeIt: Clone,
323{
324    it: NeIt,
325}
326
327impl<N, E, Ne, NeIt> GraphIterator<FnAdj<N, E, Ne, NeIt>> for FnNeighIt<NeIt>
328where
329    NeIt: Iterator<Item = (E, N)> + Clone,
330{
331    type Item = (E, N);
332    fn next(&mut self, _g: &FnAdj<N, E, Ne, NeIt>) -> Option<Self::Item> {
333        self.it.next()
334    }
335}
336
337impl<'a, N, E, Ne, NeIt: Clone> Adjacencies<'a> for FnAdj<N, E, Ne, NeIt>
338where
339    N: Copy + Eq + 'a,
340    E: Copy + Eq + 'a,
341    Ne: Fn(N) -> NeIt,
342    NeIt: Iterator<Item = (E, N)> + Clone,
343{
344    type Node = N;
345    type Edge = E;
346    type IncidenceIt = FnNeighIt<NeIt>;
347
348    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
349        FnNeighIt { it: (self.neighsfn)(u) }
350    }
351}
352
353impl<'a, N, E, Ne, NeIt: Clone> From<Ne> for FnAdj<N, E, Ne, NeIt>
354where
355    N: Copy + Eq + 'a,
356    E: Copy + Eq + 'a,
357    Ne: Fn(N) -> NeIt,
358    NeIt: Iterator<Item = (E, N)> + Clone,
359{
360    fn from(neighs: Ne) -> Self {
361        FnAdj {
362            neighsfn: neighs,
363            phantom: PhantomData,
364        }
365    }
366}