algods/graph/
directed_graph.rs

1#[cfg(test)]
2mod unit_test;
3use crate::graph::{VertexInfo, Weight};
4use crate::utils::read_lines;
5use std::collections::HashSet;
6use std::path::Path;
7
8#[derive(Eq, Hash, PartialEq, Copy, Clone)]
9pub struct DirectedEdge {
10    from: usize, // not necessarily useful but keeps the idea of an edge
11    to: usize,
12}
13
14impl DirectedEdge {
15    pub fn init(origin: usize, destination: usize) -> Self {
16        Self {
17            from: origin,
18            to: destination,
19        }
20    }
21    pub fn to(&self) -> &usize {
22        &self.to
23    }
24    pub fn from(&self) -> &usize {
25        &self.from
26    }
27}
28/// Implementation of an adjacency-list based unweighted directed graph
29/// ```
30/// use algods::graph::DirectedGraph;
31/// let mut graph = DirectedGraph::init(3);
32/// graph.add_edge(0,1);
33/// graph.add_edge(1,2);
34/// assert_eq!(graph.nb_vertices(), 3);
35/// assert_eq!(graph.nb_edges(), 2);
36/// graph.add_vertex();
37/// assert_eq!(graph.nb_vertices(), 4);
38/// ```
39pub struct DirectedGraph {
40    // implements an adjacency-list graph
41    // where vertices have indices 0, ..., nb_objects
42    // and each vertex is associated to the vertices it points to
43    data: Vec<HashSet<DirectedEdge>>,
44    nb_edges: usize,
45    nb_vertices: usize,
46    in_edges: Vec<HashSet<usize>>,
47}
48impl Default for DirectedGraph {
49    fn default() -> Self {
50        Self::new()
51    }
52}
53impl DirectedGraph {
54    /// Creates a new empty graph.
55    pub fn new() -> Self {
56        Self {
57            data: Vec::new(),
58            nb_edges: 0,
59            nb_vertices: 0,
60            in_edges: Vec::new(),
61        }
62    }
63    /// Creates a new graph with unconnected `nb_objects` objects
64    pub fn init(nb_objects: usize) -> Self {
65        let mut graph = Self::new();
66        graph.nb_vertices = nb_objects;
67        graph.data = Vec::with_capacity(nb_objects);
68        for _ in 0..nb_objects {
69            graph.data.push(HashSet::new());
70            graph.in_edges.push(HashSet::new());
71        }
72        graph
73    }
74    /// Creates a new graph which has the same vertices but edges reverted.
75    pub fn reverse(&self) -> Self {
76        // Gets the reverse graph
77        let nb_vertices = self.nb_vertices;
78        let mut rev_graph = Self::init(nb_vertices);
79        for v in 0..nb_vertices {
80            let adj_v = self.vertex_edges(&v);
81            for w in adj_v {
82                rev_graph.add_edge(*w, v);
83            }
84        }
85        rev_graph
86    }
87    /// Creates a graph from a file
88    pub fn from_file<P>(filename: P, sep: char, nb_vertices: usize) -> Self
89    where
90        P: AsRef<Path>,
91    {
92        // Builds a directed graph from a file with edges.
93        // All the elements of each row should be non
94        // negative integers separated by the value of the sep
95        // argument, each row represent one or many edges from the first vertex to
96        // the other ones. If there is only one value, it will be skipped
97        let mut nb_iter = 0;
98        println!("Initializing the graph");
99        let mut dg = DirectedGraph::init(nb_vertices);
100        match read_lines(filename) {
101            Ok(lines) => {
102                for (_, line) in lines.enumerate() {
103                    if let Ok(row) = line {
104                        let values = row.split(sep).collect::<Vec<&str>>();
105                        for i in 1..values.len() {
106                            dg.add_edge(
107                                values[0].parse::<usize>().unwrap(),
108                                values[i].parse::<usize>().unwrap(),
109                            );
110                        }
111                        // println!("{:?}", dg.vertex_edges(&values[0].parse::<usize>().unwrap()));
112                        println!("{nb_iter}");
113                        nb_iter += 1
114                    }
115                }
116            }
117            Err(error) => panic!("{error}"),
118        }
119        dg
120    }
121
122    /// Gives the number of edges
123    pub fn nb_edges(&self) -> usize {
124        // run time complexity O(1)
125        self.nb_edges
126    }
127    /// Gives the number of vertices
128    pub fn nb_vertices(&self) -> usize {
129        // run time complexity O(1)
130        self.nb_vertices
131    }
132    /// Adds a new edge o the graph
133    pub fn add_edge(&mut self, v: usize, w: usize) {
134        // adds an edge from v to w to the graph
135        // run time complexity O(1)
136        assert!(self.nb_vertices >= std::cmp::max(v, w));
137        let edge = DirectedEdge::init(v, w);
138        let w_is_in = self.data[v].insert(edge);
139        self.in_edges[w].insert(v);
140        if w_is_in {
141            // v --> w is a new directed edge
142            self.nb_edges += 1;
143        }
144    }
145    /// Adds a new vertex to the graph
146    pub fn add_vertex(&mut self) {
147        self.data.push(HashSet::<DirectedEdge>::new());
148        self.nb_vertices += 1;
149    }
150    /// Returns an immutable reference to the set of edges
151    pub fn vertex_edges(&self, v: &usize) -> Vec<&usize> {
152        // gets all the vertices linked to a given vertex v,
153        // that is the adjacent vertices of v
154        // run time complexity O(1)
155        self.data[*v]
156            .iter()
157            .map(|edge| edge.to())
158            .collect::<Vec<&usize>>()
159    }
160    ///
161    pub fn out_edges(&self, v: &usize) -> &HashSet<DirectedEdge> {
162        // gets all the vertices linked to a given vertex v,
163        // that is the adjacent vertices of v
164        // run time complexity O(1)
165        &self.data[*v]
166    }
167    ///
168    pub fn in_edges(&self, v: &usize) -> &HashSet<usize> {
169        // self.data
170        //     .iter()
171        //     .filter_map(|adj| adj.iter().find(|e| e.to() == v))
172        //     .map(|e| e.from())
173        //     .collect::<Vec<&usize>>()
174        &self.in_edges[*v]
175    }
176    /// Gives the number of vertices a vertex point to
177    pub fn out_degree(&self, v: &usize) -> usize {
178        // the number of vertices the vertex v points to
179        self.vertex_edges(v).len()
180    }
181    /// Gives the number of vertices pointing to a vertex
182    pub fn in_degree(&self, v: &usize) -> usize {
183        // gives the number of vertices pointing to vertex v
184        self.data
185            .iter()
186            .map(|adj| usize::from(adj.iter().any(|e| e.to() == v)))
187            .sum()
188    }
189    /// Gives the integer part of the average number of edges per vertex
190    pub fn average_degree(&self) -> usize {
191        // gets the average number of degree of the graph
192        if self.nb_vertices > 0 {
193            self.nb_edges / self.nb_vertices
194        } else {
195            panic!("No vertex in the graph");
196        }
197    }
198    /// Returns the number of vertices pointing to themselves
199    pub fn self_loop_number(&self) -> usize {
200        self.data
201            .iter()
202            .enumerate()
203            .map(|(v, e)| usize::from(e.contains(&DirectedEdge::init(v, v))))
204            .sum()
205    }
206}
207impl VertexInfo for DirectedGraph {
208    fn vertex_edges(&self, v: &usize) -> Vec<&usize> {
209        // gets all the vertices linked to a given vertex v,
210        // that is the adjacent vertices of v
211        // run time complexity O(1)
212        self.vertex_edges(v)
213    }
214    fn nb_vertices(&self) -> usize {
215        // run time complexity O(1)
216        self.nb_vertices
217    }
218}
219
220#[derive(Eq, Hash, PartialEq, Copy, Clone, Debug)]
221struct DirectedWeightedEdge<T>
222where
223    T: Weight,
224{
225    from: usize, // not necessarily useful but keeps the idea of an edge
226    to: usize,
227    weight: T,
228}
229impl<T: Weight> DirectedWeightedEdge<T> {
230    pub fn init(origin: usize, destination: usize, cost: T) -> Self {
231        Self {
232            from: origin,
233            to: destination,
234            weight: cost,
235        }
236    }
237    pub fn to(&self) -> &usize {
238        &self.to
239    }
240    pub fn from(&self) -> &usize {
241        &self.from
242    }
243    pub fn weight(&self) -> &T {
244        &self.weight
245    }
246}
247
248pub struct EdgeWeightedDigraph<T>
249where
250    T: Weight,
251{
252    data: Vec<HashSet<DirectedWeightedEdge<T>>>,
253    nb_edges: usize,
254    nb_vertices: usize,
255}
256
257impl<T: Weight> Default for EdgeWeightedDigraph<T> {
258    fn default() -> Self {
259        Self::new()
260    }
261}
262impl<T: Weight> EdgeWeightedDigraph<T> {
263    /// Creates a new empty graph.
264    pub fn new() -> Self {
265        Self {
266            data: Vec::new(),
267            nb_edges: 0,
268            nb_vertices: 0,
269        }
270    }
271    /// Creates a new graph with unconnected `nb_objects` objects
272    pub fn init(nb_objects: usize) -> Self {
273        let mut graph = Self::new();
274        graph.nb_vertices = nb_objects;
275        graph.data = Vec::with_capacity(nb_objects);
276        for _ in 0..nb_objects {
277            graph.data.push(HashSet::new());
278        }
279        graph
280    }
281    /// Gives the number of edges
282    pub fn nb_edges(&self) -> usize {
283        // run time complexity O(1)
284        self.nb_edges
285    }
286    /// Gives the number of vertices
287    pub fn nb_vertices(&self) -> usize {
288        // run time complexity O(1)
289        self.nb_vertices
290    }
291    /// Adds a new edge of the graph
292    pub fn add_edge(&mut self, u: usize, v: usize, w: T) {
293        // adds an edge from v to w to the graph
294        // run time complexity O(1)
295        assert!(self.nb_vertices >= std::cmp::max(u, v));
296        let edge = DirectedWeightedEdge::init(u, v, w);
297        // println!("{edge:?}");
298        let is_new = self.data[u].insert(edge);
299        if is_new {
300            // u --> v is a new directed edge
301            self.nb_edges += 1;
302        }
303    }
304    /// Adds a new vertex to the graph
305    pub fn add_vertex(&mut self) {
306        self.data.push(HashSet::new());
307        self.nb_vertices += 1;
308    }
309    /// Returns an immutable reference to the set of edges
310    pub fn vertex_edges(&self, v: &usize) -> Vec<(&usize, &T)> {
311        // gets all the vertices linked to a given vertex v,
312        // that is the adjacent vertices of v
313        // run time complexity O(1)
314        self.data[*v]
315            .iter()
316            .map(|edge| (edge.to(), edge.weight()))
317            .collect::<Vec<(&usize, &T)>>()
318    }
319    /// Gives the number of vertices a vertex point to
320    pub fn out_degree(&self, v: &usize) -> usize {
321        // the number of vertices the vertex v points to
322        self.vertex_edges(v).len()
323    }
324    /// Gives the number of vertices pointing to a vertex
325    pub fn in_degree(&self, v: &usize) -> usize {
326        // gives the number of vertices pointing to vertex v
327        self.data
328            .iter()
329            .map(|adj| usize::from(adj.iter().any(|edge| v == edge.to())))
330            .sum()
331    }
332    /// Gives the integer part of the average number of edges per vertex
333    pub fn average_degree(&self) -> usize {
334        // gets the average number of degree of the graph
335        if self.nb_vertices > 0 {
336            self.nb_edges / self.nb_vertices
337        } else {
338            panic!("No vertex in the graph");
339        }
340    }
341    /// Returns the number of vertices pointing to themselves
342    pub fn self_loop_number(&self) -> usize {
343        self.data
344            .iter()
345            .map(|adj| usize::from(adj.iter().any(|edge| edge.from() == edge.to())))
346            .sum()
347    }
348}
349impl<T: Weight> VertexInfo for EdgeWeightedDigraph<T> {
350    fn vertex_edges(&self, v: &usize) -> Vec<&usize> {
351        // gets all the vertices linked to a given vertex v,
352        // that is the adjacent vertices of v
353        self.data[*v]
354            .iter()
355            .map(|edge| edge.to())
356            .collect::<Vec<&usize>>()
357    }
358    fn nb_vertices(&self) -> usize {
359        // run time complexity O(1)
360        self.nb_vertices
361    }
362}
363
364#[derive(Debug, Eq, Hash, PartialEq, Copy, Clone)]
365pub struct FlowEdge<T>
366where
367    T: Weight,
368{
369    from: usize,
370    to: usize,
371    flow: T,
372    capacity: T,
373}
374
375impl<T: Weight> FlowEdge<T> {
376    pub fn init(origin: usize, destination: usize, f: T, c: T) -> Self {
377        Self {
378            from: origin,
379            to: destination,
380            flow: f,
381            capacity: c,
382        }
383    }
384
385    pub fn from(&self) -> &usize {
386        &self.from
387    }
388
389    pub fn to(&self) -> &usize {
390        &self.to
391    }
392
393    pub fn flow(&self) -> &T {
394        &self.flow
395    }
396    pub fn flow_mut(&mut self) -> &mut T {
397        &mut self.flow
398    }
399
400    pub fn capacity(&self) -> &T {
401        &self.capacity
402    }
403}
404
405impl<T: Weight> FlowEdge<T> {
406    pub fn residual_capacity(&self) -> T {
407        self.capacity - self.flow
408    }
409    pub fn add_residual_flow_to(&mut self, vertex: &usize, delta: T) {
410        if vertex == self.from() {
411            self.flow = self.flow - delta;
412        } else if vertex == self.to() {
413            self.flow = self.flow + delta;
414        } else {
415            panic!("Illegal endpoint {vertex}")
416        }
417    }
418}
419
420pub struct FlowNetwork<T>
421where
422    T: Weight,
423{
424    data: Vec<Vec<FlowEdge<T>>>,
425    nb_edges: usize,
426    nb_vertices: usize,
427}
428
429impl<T: Weight> FlowNetwork<T> {
430    /// Creates a new empty graph.
431    pub fn new() -> Self {
432        Self {
433            data: Vec::new(),
434            nb_edges: 0,
435            nb_vertices: 0,
436        }
437    }
438    /// Creates a new graph with unconnected `nb_objects` objects
439    pub fn init(nb_objects: usize) -> Self {
440        let mut graph = Self::new();
441        graph.nb_vertices = nb_objects;
442        graph.data = Vec::with_capacity(nb_objects);
443        for _ in 0..nb_objects {
444            graph.data.push(Vec::new());
445        }
446        graph
447    }
448    /// Gives the number of edges
449    pub fn nb_edges(&self) -> usize {
450        // run time complexity O(1)
451        self.nb_edges
452    }
453    /// Gives the number of vertices
454    pub fn nb_vertices(&self) -> usize {
455        // run time complexity O(1)
456        self.nb_vertices
457    }
458    /// Adds a new edge of the graph
459    pub fn add_edge(&mut self, from: usize, to: usize, cap: T) {
460        // adds an edge from v to w to the graph
461        // run time complexity O(1)
462        assert!(self.nb_vertices >= std::cmp::max(from, to));
463        let zero = Weight::zero();
464        let forward_edge = FlowEdge::init(from, to, zero, cap);
465        let backward_edge = FlowEdge::init(to, from, zero, zero);
466        if !self.data[from].contains(&forward_edge) {
467            self.data[from].push(forward_edge);
468            self.data[to].push(backward_edge);
469            self.nb_edges += 1;
470        }
471    }
472    /// Adds a new vertex to the graph
473    pub fn add_vertex(&mut self) {
474        self.data.push(Vec::new());
475        self.nb_vertices += 1;
476    }
477    /// Returns an immutable reference to the set of edges
478    pub fn vertex_edges(&self, v: &usize) -> Vec<&FlowEdge<T>> {
479        // gets all the vertices linked to a given vertex v,
480        // that is the adjacent vertices of v
481        // run time complexity O(1)
482        self.data[*v].iter().collect::<Vec<&FlowEdge<T>>>()
483    }
484    pub fn vertex_edges_mut(&mut self, v: &usize) -> std::slice::IterMut<'_, FlowEdge<T>> {
485        // gets all the vertices linked to a given vertex v,
486        // that is the adjacent vertices of v
487        // run time complexity O(1)
488        self.data[*v].iter_mut()
489    }
490    /// Gives the number of vertices a vertex point to
491    pub fn out_degree(&self, v: &usize) -> usize {
492        // the number of vertices the vertex v points to
493        self.vertex_edges(v).len()
494    }
495    /// Gives the number of vertices pointing to a vertex
496    pub fn in_degree(&self, v: &usize) -> usize {
497        // gives the number of vertices pointing to vertex v
498        self.data
499            .iter()
500            .map(|adj| usize::from(adj.iter().any(|edge| v == edge.to())))
501            .sum()
502    }
503    /// Gives the integer part of the average number of edges per vertex
504    pub fn average_degree(&self) -> usize {
505        // gets the average number of degree of the graph
506        if self.nb_vertices > 0 {
507            self.nb_edges / self.nb_vertices
508        } else {
509            panic!("No vertex in the graph");
510        }
511    }
512    /// Returns the number of vertices pointing to themselves
513    pub fn self_loop_number(&self) -> usize {
514        self.data
515            .iter()
516            .map(|adj| usize::from(adj.iter().any(|edge| edge.from() == edge.to())))
517            .sum()
518    }
519}