1use 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#[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#[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 pub fn new(e: E) -> Self {
102 NetworkEdge::Forward(e)
103 }
104
105 pub fn is_forward(&self) -> bool {
107 match self {
108 NetworkEdge::Forward(_) => true,
109 NetworkEdge::Backward(_) => false,
110 }
111 }
112
113 pub fn is_backward(&self) -> bool {
115 !self.is_forward()
116 }
117
118 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 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 pub fn forward(&self) -> Self {
140 NetworkEdge::Forward(self.edge())
141 }
142
143 pub fn backward(&self) -> Self {
148 NetworkEdge::Backward(self.edge())
149 }
150
151 pub fn edge(&self) -> E {
153 match self {
154 NetworkEdge::Forward(e) | NetworkEdge::Backward(e) => e.clone(),
155 }
156 }
157}
158
159#[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
182pub 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#[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 pub fn new(g: &'a G) -> Self {
258 Network(g)
259 }
260
261 pub fn as_graph(&self) -> &'a G {
263 self.0
264 }
265
266 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}