rs_graph/adapters/
network.rs

1/*
2 * Copyright (c) 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//! A network graph adaptor.
19//!
20//! A network corresponds to a digraph where each of the digraph's
21//! edges is represented by a pair of edges -- the edge and its
22//! reverse edge. Hence, the network shares the node set with the
23//! underlying graph but has twice the number of edges. Each digraph
24//! can be turned into an network.
25//!
26//! # Example
27//!
28//! ```
29//! use rs_graph::classes;
30//! use rs_graph::adapters::Network;
31//! use rs_graph::LinkedListGraph;
32//! use rs_graph::traits::*;
33//!
34//! let g = classes::complete_bipartite::<LinkedListGraph>(3, 4);
35//! let n = Network::new(&g);
36//! assert_eq!(g.num_nodes(), n.num_nodes());
37//! assert_eq!(g.num_edges() * 2, n.num_edges());
38//! assert!(n.nodes().take(3).all(|u| n.inedges(u).count() == 4));
39//! assert!(n.nodes().take(3).all(|u| n.outedges(u).count() == 4));
40//! assert!(n.nodes().take(3).all(|u| n.neighs(u).count() == 8));
41//! assert!(n.nodes().skip(3).all(|u| n.inedges(u).count() == 3));
42//! assert!(n.nodes().skip(3).all(|u| n.outedges(u).count() == 3));
43//! assert!(n.nodes().skip(3).all(|u| n.neighs(u).count() == 6));
44//!
45//! for u in n.nodes().take(3) {
46//!     for v in n.nodes().skip(3) {
47//!         assert_eq!(n.edges().filter(|&e| (n.src(e), n.snk(e)) == (u, v)).count(), 1);
48//!         assert_eq!(n.edges().filter(|&e| (n.snk(e), n.src(e)) == (u, v)).count(), 1);
49//!     }
50//! }
51//!```
52
53use crate::traits::refs::{DirectedRef, FiniteDigraphRef, FiniteGraphRef, GraphTypeRef, IndexGraphRef, UndirectedRef};
54use crate::traits::{
55    Directed, DirectedEdge, FiniteDigraph, FiniteGraph, GraphIterator, GraphType, IndexGraph, Indexable, Undirected,
56};
57
58/// The network graph adaptor.
59///
60/// It is meant to be used by borrowing the underlying graph.
61/// (also see the module description [`adapters::network`](self)).
62///
63/// ```
64/// # use rs_graph::adapters::Network;
65/// # use rs_graph::LinkedListGraph;
66/// # use rs_graph::classes;
67/// let g = classes::cycle::<LinkedListGraph>(5);
68/// let n = Network::new(&g);
69/// ```
70///
71/// The network inherits all trait implementations from the underlying graph. In
72/// particular, if the underlying graph implements `IndexGraph` then nodes and
73/// edges of the network are numbered, too:
74///
75///   - The `node_id` is the same as in the underlying graph,
76///   - the edge with id `i` is mapped to the edges `2*i` (forward edge) and
77///     `2*i+1` (backward edge).
78#[derive(Copy)]
79pub struct Network<'a, G>(&'a G);
80
81impl<'a, G> Clone for Network<'a, G> {
82    fn clone(&self) -> Self {
83        Network(self.0)
84    }
85}
86
87/// A network edge.
88///
89/// This is either the forward or the backward edge of the original edge.
90#[derive(Clone, Copy, PartialEq, Eq)]
91pub enum NetworkEdge<E> {
92    Forward(E),
93    Backward(E),
94}
95
96impl<E> NetworkEdge<E>
97where
98    E: Clone + Eq,
99{
100    /// Return the *forward* edge corresponding to the given underlying edge.
101    pub fn new(e: E) -> Self {
102        NetworkEdge::Forward(e)
103    }
104
105    /// Return `true` if this is the forward edge.
106    pub fn is_forward(&self) -> bool {
107        match self {
108            NetworkEdge::Forward(_) => true,
109            NetworkEdge::Backward(_) => false,
110        }
111    }
112
113    /// Return `true` if this is the backward edge.
114    pub fn is_backward(&self) -> bool {
115        !self.is_forward()
116    }
117
118    /// Return `true` if `e` is the reverse edge of `self`.
119    pub fn is_reverse(&self, e: Self) -> bool {
120        use NetworkEdge::*;
121        match (self, &e) {
122            (Forward(a), Backward(b)) | (Backward(a), Forward(b)) => a == b,
123            _ => false,
124        }
125    }
126
127    /// Return the reverse edge of this edge.
128    pub fn reverse(&self) -> Self {
129        match self {
130            NetworkEdge::Forward(e) => NetworkEdge::Backward(e.clone()),
131            NetworkEdge::Backward(e) => NetworkEdge::Forward(e.clone()),
132        }
133    }
134
135    /// Return the forward edge of `self`.
136    ///
137    /// If this is already the forward edge then `self` is returned and
138    /// `self.reverse()` otherwise.
139    pub fn forward(&self) -> Self {
140        NetworkEdge::Forward(self.edge())
141    }
142
143    /// Return the backward edge of `self`.
144    ///
145    /// If this is already the backward edge then `self` is returned and
146    /// `self.reverse()` otherwise.
147    pub fn backward(&self) -> Self {
148        NetworkEdge::Backward(self.edge())
149    }
150
151    /// Return the edge of the underlying graph.
152    pub fn edge(&self) -> E {
153        match self {
154            NetworkEdge::Forward(e) | NetworkEdge::Backward(e) => e.clone(),
155        }
156    }
157}
158
159/// Graph iterator over all nodes of the [`Network`].
160#[derive(Clone)]
161pub struct NetworkNodeIt<I>(I);
162
163impl<'a, G, I> GraphIterator<Network<'a, G>> for NetworkNodeIt<I>
164where
165    I: GraphIterator<G>,
166{
167    type Item = I::Item;
168
169    fn next(&mut self, net: &Network<'a, G>) -> Option<Self::Item> {
170        self.0.next(net.0)
171    }
172
173    fn size_hint(&self, net: &Network<'a, G>) -> (usize, Option<usize>) {
174        self.0.size_hint(net.0)
175    }
176
177    fn count(self, net: &Network<'a, G>) -> usize {
178        self.0.count(net.0)
179    }
180}
181
182/// Graph iterator over all edges of the [`Network`].
183pub struct NetworkEdgeIt<G, I>(I, Option<I::Item>)
184where
185    I: GraphIterator<G>;
186
187impl<G, I> Clone for NetworkEdgeIt<G, I>
188where
189    I: GraphIterator<G>,
190    I::Item: Clone,
191{
192    fn clone(&self) -> Self {
193        NetworkEdgeIt(self.0.clone(), self.1.clone())
194    }
195}
196
197impl<'a, G, I> GraphIterator<Network<'a, G>> for NetworkEdgeIt<G, I>
198where
199    I: GraphIterator<G>,
200    I::Item: Clone,
201{
202    type Item = NetworkEdge<I::Item>;
203
204    fn next(&mut self, net: &Network<'a, G>) -> Option<Self::Item> {
205        if let Some(cur) = self.1.take() {
206            Some(NetworkEdge::Backward(cur))
207        } else if let Some(nxt) = self.0.next(net.0) {
208            self.1 = Some(nxt.clone());
209            Some(NetworkEdge::Forward(nxt))
210        } else {
211            None
212        }
213    }
214
215    fn size_hint(&self, net: &Network<'a, G>) -> (usize, Option<usize>) {
216        let (l, u) = self.0.size_hint(net.0);
217        (l * 2, u.map(|u| u * 2))
218    }
219
220    fn count(self, net: &Network<'a, G>) -> usize {
221        2 * self.0.count(net.0) + self.1.map(|_| 1).unwrap_or(0)
222    }
223}
224
225/// A network edge with direction information.
226///
227/// This adapter is used by [`NetworkIncidentIt`] to return whether the next edge
228/// is outgoing or incoming.
229#[derive(Clone, Copy, PartialEq, Eq)]
230pub enum NetworkDirectedEdge<E> {
231    Outgoing(E),
232    Incoming(E),
233}
234
235impl<E> DirectedEdge for NetworkDirectedEdge<E>
236where
237    E: Clone,
238{
239    type Edge = E;
240
241    fn is_incoming(&self) -> bool {
242        matches!(self, NetworkDirectedEdge::Incoming(..))
243    }
244
245    fn edge(&self) -> E {
246        match self {
247            NetworkDirectedEdge::Incoming(e) | NetworkDirectedEdge::Outgoing(e) => e.clone(),
248        }
249    }
250}
251
252impl<'a, G> Network<'a, G>
253where
254    G: GraphType,
255{
256    /// Create a new network adapter wrapping `g`.
257    pub fn new(g: &'a G) -> Self {
258        Network(g)
259    }
260
261    /// Return a reference to the underlying graph.
262    pub fn as_graph(&self) -> &'a G {
263        self.0
264    }
265
266    /// Return the forward edge corresponding the edge `e` in the underlying graph.
267    pub fn from_edge<'g>(&self, e: G::Edge<'g>) -> NetworkEdge<G::Edge<'g>> {
268        NetworkEdge::Forward(e)
269    }
270}
271
272pub struct NetworkNeighIt<G, I>(I, Option<I::Item>)
273where
274    I: GraphIterator<G>;
275
276impl<G, I> Clone for NetworkNeighIt<G, I>
277where
278    I: GraphIterator<G>,
279    I::Item: Clone,
280{
281    fn clone(&self) -> Self {
282        NetworkNeighIt(self.0.clone(), self.1.clone())
283    }
284}
285
286impl<'a, G, I, N, E> GraphIterator<Network<'a, G>> for NetworkNeighIt<G, I>
287where
288    N: Clone,
289    E: Clone,
290    I: GraphIterator<G, Item = (E, N)>,
291{
292    type Item = (NetworkEdge<E>, N);
293
294    fn next(&mut self, net: &Network<'a, G>) -> Option<Self::Item> {
295        if let Some((e, v)) = self.1.take() {
296            Some((NetworkEdge::Backward(e), v))
297        } else if let Some((e, v)) = self.0.next(net.0) {
298            self.1 = Some((e.clone(), v.clone()));
299            Some((NetworkEdge::Forward(e), v))
300        } else {
301            None
302        }
303    }
304
305    fn size_hint(&self, net: &Network<'a, G>) -> (usize, Option<usize>) {
306        let (l, u) = self.0.size_hint(net.0);
307        (l * 2, u.map(|u| u * 2))
308    }
309
310    fn count(self, net: &Network<'a, G>) -> usize {
311        2 * self.0.count(net.0) + self.1.map(|_| 1).unwrap_or(0)
312    }
313}
314
315#[derive(Clone)]
316pub struct NetworkOutIt<I>(I);
317
318impl<'a, G, I, N, D> GraphIterator<Network<'a, G>> for NetworkOutIt<I>
319where
320    I: GraphIterator<G, Item = (D, N)>,
321    D: DirectedEdge,
322{
323    type Item = (NetworkEdge<D::Edge>, N);
324
325    fn next(&mut self, net: &Network<'a, G>) -> Option<Self::Item> {
326        self.0.next(net.0).map(|(e, v)| {
327            if e.is_outgoing() {
328                (NetworkEdge::Forward(e.edge()), v)
329            } else {
330                (NetworkEdge::Backward(e.edge()), v)
331            }
332        })
333    }
334
335    fn size_hint(&self, net: &Network<'a, G>) -> (usize, Option<usize>) {
336        self.0.size_hint(net.0)
337    }
338
339    fn count(self, net: &Network<'a, G>) -> usize {
340        self.0.count(net.0)
341    }
342}
343
344#[derive(Clone)]
345pub struct NetworkInIt<I>(I);
346
347impl<'a, G, I, N, D> GraphIterator<Network<'a, G>> for NetworkInIt<I>
348where
349    I: GraphIterator<G, Item = (D, N)>,
350    D: DirectedEdge,
351{
352    type Item = (NetworkEdge<D::Edge>, N);
353
354    fn next(&mut self, net: &Network<'a, G>) -> Option<Self::Item> {
355        self.0.next(net.0).map(|(e, v)| {
356            if e.is_incoming() {
357                (NetworkEdge::Forward(e.edge()), v)
358            } else {
359                (NetworkEdge::Backward(e.edge()), v)
360            }
361        })
362    }
363
364    fn size_hint(&self, net: &Network<'a, G>) -> (usize, Option<usize>) {
365        self.0.size_hint(net.0)
366    }
367
368    fn count(self, net: &Network<'a, G>) -> usize {
369        self.0.count(net.0)
370    }
371}
372
373#[derive(Clone)]
374pub struct NetworkIncidentIt<I, T>(I, Option<T>);
375
376impl<'a, G, I, N, D> GraphIterator<Network<'a, G>> for NetworkIncidentIt<I, I::Item>
377where
378    I: GraphIterator<G, Item = (D, N)>,
379    N: Clone,
380    D: DirectedEdge + Clone,
381{
382    type Item = (NetworkDirectedEdge<NetworkEdge<D::Edge>>, N);
383
384    fn next(&mut self, net: &Network<'a, G>) -> Option<Self::Item> {
385        if let Some((e, v)) = self.1.take() {
386            if e.is_outgoing() {
387                Some((NetworkDirectedEdge::Incoming(NetworkEdge::Backward(e.edge())), v))
388            } else {
389                Some((NetworkDirectedEdge::Outgoing(NetworkEdge::Backward(e.edge())), v))
390            }
391        } else if let Some((e, v)) = self.0.next(net.0) {
392            self.1 = Some((e.clone(), v.clone()));
393            if e.is_outgoing() {
394                Some((NetworkDirectedEdge::Outgoing(NetworkEdge::Forward(e.edge())), v))
395            } else {
396                Some((NetworkDirectedEdge::Incoming(NetworkEdge::Forward(e.edge())), v))
397            }
398        } else {
399            None
400        }
401    }
402
403    fn size_hint(&self, net: &Network<'a, G>) -> (usize, Option<usize>) {
404        let (l, u) = self.0.size_hint(net.0);
405        (l * 2, u.map(|u| u * 2))
406    }
407
408    fn count(self, net: &Network<'a, G>) -> usize {
409        2 * self.0.count(net.0) + self.1.map(|_| 1).unwrap_or(0)
410    }
411}
412
413impl<E> Indexable for NetworkEdge<E>
414where
415    E: Indexable,
416{
417    fn index(&self) -> usize {
418        match self {
419            NetworkEdge::Forward(e) => e.index() << 1,
420            NetworkEdge::Backward(e) => (e.index() << 1) | 1,
421        }
422    }
423}
424
425impl<'a, G> GraphTypeRef<'a> for Network<'a, G>
426where
427    G: GraphType,
428{
429    type Node = G::Node<'a>;
430    type Edge = NetworkEdge<G::Edge<'a>>;
431}
432
433impl<'a, G> FiniteGraphRef<'a> for Network<'a, G>
434where
435    G: FiniteGraph,
436{
437    type NodeIt = NetworkNodeIt<G::NodeIt<'a>>;
438
439    type EdgeIt = NetworkEdgeIt<G, G::EdgeIt<'a>>;
440
441    fn num_nodes(&self) -> usize {
442        self.0.num_nodes()
443    }
444
445    fn num_edges(&self) -> usize {
446        self.0.num_edges() * 2
447    }
448
449    fn nodes_iter(&self) -> Self::NodeIt {
450        NetworkNodeIt(self.0.nodes_iter())
451    }
452
453    fn edges_iter(&self) -> Self::EdgeIt {
454        NetworkEdgeIt(self.0.edges_iter(), None)
455    }
456
457    fn enodes(&self, e: Self::Edge) -> (Self::Node, Self::Node) {
458        self.0.enodes(e.edge())
459    }
460}
461
462impl<'a, G> FiniteDigraphRef<'a> for Network<'a, G>
463where
464    G: FiniteDigraph,
465{
466    fn src(&self, e: Self::Edge) -> Self::Node {
467        match e {
468            NetworkEdge::Forward(e) => self.0.src(e),
469            NetworkEdge::Backward(e) => self.0.snk(e),
470        }
471    }
472
473    fn snk(&self, e: Self::Edge) -> Self::Node {
474        match e {
475            NetworkEdge::Forward(e) => self.0.snk(e),
476            NetworkEdge::Backward(e) => self.0.src(e),
477        }
478    }
479}
480
481impl<'a, G> UndirectedRef<'a> for Network<'a, G>
482where
483    G: Undirected,
484{
485    type NeighIt = NetworkNeighIt<G, G::NeighIt<'a>>;
486
487    fn neigh_iter(&self, u: Self::Node) -> Self::NeighIt {
488        NetworkNeighIt(self.0.neigh_iter(u), None)
489    }
490}
491
492impl<'a, G> DirectedRef<'a> for Network<'a, G>
493where
494    G: 'a + Directed,
495{
496    type OutIt = NetworkOutIt<G::IncidentIt<'a>>;
497
498    type InIt = NetworkInIt<G::IncidentIt<'a>>;
499
500    type IncidentIt = NetworkIncidentIt<G::IncidentIt<'a>, (G::DirectedEdge<'a>, G::Node<'a>)>;
501
502    type DirectedEdge = NetworkDirectedEdge<Self::Edge>;
503
504    fn out_iter(&self, u: Self::Node) -> Self::OutIt {
505        NetworkOutIt(self.0.incident_iter(u))
506    }
507
508    fn in_iter(&self, u: Self::Node) -> Self::InIt {
509        NetworkInIt(self.0.incident_iter(u))
510    }
511
512    fn incident_iter(&self, u: Self::Node) -> Self::IncidentIt {
513        NetworkIncidentIt(self.0.incident_iter(u), None)
514    }
515}
516
517impl<'a, G> IndexGraphRef<'a> for Network<'a, G>
518where
519    G: IndexGraph,
520{
521    fn node_id(&self, u: Self::Node) -> usize {
522        self.0.node_id(u)
523    }
524
525    fn edge_id(&self, e: Self::Edge) -> usize {
526        (self.0.edge_id(e.edge())) << 1 | (e.is_backward() as usize)
527    }
528
529    fn id2node(&self, id: usize) -> Self::Node {
530        self.0.id2node(id)
531    }
532
533    fn id2edge(&self, id: usize) -> Self::Edge {
534        match id & 1 {
535            0 => NetworkEdge::Forward(self.0.id2edge(id >> 1)),
536            _ => NetworkEdge::Backward(self.0.id2edge(id >> 1)),
537        }
538    }
539}
540
541impl<'g, G> GraphType for Network<'g, G>
542where
543    G: GraphType,
544{
545    type Node<'a> = G::Node<'a>;
546    type Edge<'a> = NetworkEdge<G::Edge<'a>>;
547}
548
549impl<'g, G> FiniteGraph for Network<'g, G>
550where
551    G: FiniteGraph,
552{
553    type NodeIt<'a> = NetworkNodeIt<G::NodeIt<'a>>
554    where
555        G: 'a,
556        'g: 'a;
557
558    type EdgeIt<'a> = NetworkEdgeIt<G, G::EdgeIt<'a>>
559    where
560        G: 'a,
561        'g: 'a;
562
563    fn num_nodes(&self) -> usize {
564        self.0.num_nodes()
565    }
566
567    fn num_edges(&self) -> usize {
568        self.0.num_edges() * 2
569    }
570
571    fn nodes_iter(&self) -> Self::NodeIt<'_> {
572        NetworkNodeIt(self.0.nodes_iter())
573    }
574
575    fn edges_iter(&self) -> Self::EdgeIt<'_> {
576        NetworkEdgeIt(self.0.edges_iter(), None)
577    }
578
579    fn enodes(&self, e: Self::Edge<'_>) -> (Self::Node<'_>, Self::Node<'_>) {
580        self.0.enodes(e.edge())
581    }
582}
583
584impl<'g, G> FiniteDigraph for Network<'g, G>
585where
586    G: FiniteDigraph,
587{
588    fn src(&self, e: Self::Edge<'_>) -> Self::Node<'_> {
589        match e {
590            NetworkEdge::Forward(e) => self.0.src(e),
591            NetworkEdge::Backward(e) => self.0.snk(e),
592        }
593    }
594
595    fn snk(&self, e: Self::Edge<'_>) -> Self::Node<'_> {
596        match e {
597            NetworkEdge::Forward(e) => self.0.snk(e),
598            NetworkEdge::Backward(e) => self.0.src(e),
599        }
600    }
601}
602
603impl<'g, G> Undirected for Network<'g, G>
604where
605    G: Undirected,
606{
607    type NeighIt<'a> = NetworkNeighIt<G, G::NeighIt<'a>>
608    where
609        G: 'a,
610        'g: 'a;
611
612    fn neigh_iter(&self, u: Self::Node<'_>) -> Self::NeighIt<'_> {
613        NetworkNeighIt(self.0.neigh_iter(u), None)
614    }
615}
616
617impl<'g, G> Directed for Network<'g, G>
618where
619    G: Directed,
620{
621    type OutIt<'a> = NetworkOutIt<G::IncidentIt<'a>>
622    where
623        G: 'a,
624        'g: 'a;
625
626    type InIt<'a> = NetworkInIt<G::IncidentIt<'a>>
627    where
628        G: 'a,
629        'g: 'a;
630
631    type IncidentIt<'a> = NetworkIncidentIt<G::IncidentIt<'a>, (G::DirectedEdge<'a>, G::Node<'a>)>
632    where
633        G: 'a,
634        'g: 'a;
635
636    type DirectedEdge<'a> = NetworkDirectedEdge<Self::Edge<'a>>
637    where
638        Self: 'a;
639
640    fn out_iter(&self, u: Self::Node<'_>) -> Self::OutIt<'_> {
641        NetworkOutIt(self.0.incident_iter(u))
642    }
643
644    fn in_iter(&self, u: Self::Node<'_>) -> Self::InIt<'_> {
645        NetworkInIt(self.0.incident_iter(u))
646    }
647
648    fn incident_iter(&self, u: Self::Node<'_>) -> Self::IncidentIt<'_> {
649        NetworkIncidentIt(self.0.incident_iter(u), None)
650    }
651}
652
653impl<'g, G> IndexGraph for Network<'g, G>
654where
655    G: IndexGraph,
656{
657    fn node_id(&self, u: Self::Node<'_>) -> usize {
658        self.0.node_id(u)
659    }
660
661    fn edge_id(&self, e: Self::Edge<'_>) -> usize {
662        (self.0.edge_id(e.edge())) << 1 | (e.is_backward() as usize)
663    }
664
665    fn id2node(&self, id: usize) -> Self::Node<'_> {
666        self.0.id2node(id)
667    }
668
669    fn id2edge(&self, id: usize) -> Self::Edge<'_> {
670        match id & 1 {
671            0 => NetworkEdge::Forward(self.0.id2edge(id >> 1)),
672            _ => NetworkEdge::Backward(self.0.id2edge(id >> 1)),
673        }
674    }
675}
676
677#[cfg(test)]
678mod tests {
679    use super::Network;
680    use crate::classes::*;
681    use crate::traits::{Directed, DirectedEdge, FiniteGraph, Undirected};
682    use crate::LinkedListGraph;
683    use std::collections::HashMap;
684
685    #[test]
686    fn test_network() {
687        for g in [cycle::<LinkedListGraph>(7), peterson(), hypercube(5)].iter() {
688            let n = Network(g);
689            assert_eq!(2 * g.num_edges(), n.num_edges());
690            for u in g.nodes() {
691                assert_eq!(g.neighs(u).count(), n.outedges(u).count());
692                assert_eq!(g.neighs(u).count(), n.inedges(u).count());
693                assert_eq!(2 * g.neighs(u).count(), n.neighs(u).count());
694                assert_eq!(2 * g.incident_edges(u).count(), n.incident_edges(u).count());
695
696                {
697                    let mut fwds = g.outedges(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
698                    let mut bwds = g.inedges(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
699                    for (e, v) in n.outedges(u) {
700                        assert!(!e.is_forward() || !fwds.insert((e.edge(), v), true).unwrap_or(true));
701                        assert!(!e.is_backward() || !bwds.insert((e.edge(), v), true).unwrap_or(true));
702                    }
703                    assert!(fwds.values().all(|x| *x));
704                    assert!(bwds.values().all(|x| *x));
705                }
706
707                {
708                    let mut fwds = g.inedges(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
709                    let mut bwds = g.outedges(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
710                    for (e, v) in n.inedges(u) {
711                        assert!(!e.is_forward() || !fwds.insert((e.edge(), v), true).unwrap_or(true));
712                        assert!(!e.is_backward() || !bwds.insert((e.edge(), v), true).unwrap_or(true));
713                    }
714                    assert!(fwds.values().all(|x| *x));
715                    assert!(bwds.values().all(|x| *x));
716                }
717
718                {
719                    let mut fwds = g.neighs(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
720                    let mut bwds = g.neighs(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
721                    for (e, v) in n.neighs(u) {
722                        assert!(!e.is_forward() || !fwds.insert((e.edge(), v), true).unwrap_or(true));
723                        assert!(!e.is_backward() || !bwds.insert((e.edge(), v), true).unwrap_or(true));
724                    }
725                    assert!(fwds.values().all(|x| *x));
726                    assert!(bwds.values().all(|x| *x));
727                }
728
729                {
730                    let mut out_fwds = g.outedges(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
731                    let mut out_bwds = g.inedges(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
732                    let mut in_fwds = g.inedges(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
733                    let mut in_bwds = g.outedges(u).map(|e| (e, false)).collect::<HashMap<_, _>>();
734                    for (e, v) in n.incident_edges(u) {
735                        if e.is_outgoing() {
736                            let e = e.edge();
737                            assert!(!e.is_forward() || !out_fwds.insert((e.edge(), v), true).unwrap_or(true));
738                            assert!(!e.is_backward() || !out_bwds.insert((e.edge(), v), true).unwrap_or(true));
739                        } else {
740                            let e = e.edge();
741                            assert!(!e.is_forward() || !in_fwds.insert((e.edge(), v), true).unwrap_or(true));
742                            assert!(!e.is_backward() || !in_bwds.insert((e.edge(), v), true).unwrap_or(true));
743                        }
744                    }
745                    assert!(out_fwds.values().all(|x| *x));
746                    assert!(out_bwds.values().all(|x| *x));
747                    assert!(in_fwds.values().all(|x| *x));
748                    assert!(in_bwds.values().all(|x| *x));
749                }
750            }
751
752            {
753                let mut fwds = g.edges().map(|e| (e, false)).collect::<HashMap<_, _>>();
754                let mut bwds = g.edges().map(|e| (e, false)).collect::<HashMap<_, _>>();
755                for e in n.edges() {
756                    assert!(!e.is_forward() || !fwds.insert(e.edge(), true).unwrap_or(true));
757                    assert!(!e.is_backward() || !bwds.insert(e.edge(), true).unwrap_or(true));
758                    assert!(e.is_reverse(e.reverse()));
759                    assert!(e.is_forward() || e.reverse().is_forward());
760                    assert!(e.is_backward() || e.reverse().is_backward());
761                    assert!(!e.is_forward() || e.forward() == e);
762                    assert!(!e.is_backward() || e.backward() == e);
763                }
764                assert!(fwds.values().all(|x| *x));
765                assert!(bwds.values().all(|x| *x));
766            }
767        }
768    }
769}