prepona/graph/subgraph/
def_mut_subgraph.rs

1use std::{collections::HashSet, marker::PhantomData};
2
3use crate::{
4    graph::{error::Error, EdgeDir},
5    prelude::{Edge, Edges, Graph, Neighbors, Vertices},
6};
7use anyhow::Result;
8
9use super::{AsFrozenSubgraph, AsMutSubgraph, AsSubgraph};
10
11/// Default implementation of [`AsMutSubgraph`](crate::graph::subgraph::AsMutSubgraph) trait.
12///
13/// ## Generic Parameters
14/// * `W`: **W**eight type associated with edges.
15/// * `E`: **E**dge type that subgraph uses.
16/// * `Dir`: **Dir**ection of edges: [`Directed`](crate::graph::DirectedEdge) or [`Undirected`](crate::graph::UndirectedEdge).
17/// * `G`: **G**raph type that subgraph is representing.
18pub struct MutSubgraph<'a, W, E: Edge<W>, Dir: EdgeDir, G: Graph<W, E, Dir>> {
19    graph: &'a mut G,
20
21    edges: Vec<(usize, usize, usize)>,
22    vertex_ids: HashSet<usize>,
23
24    phantom_w: PhantomData<W>,
25    phantom_e: PhantomData<E>,
26    phantom_dir: PhantomData<Dir>,
27}
28
29impl<'a, W, E, Dir, G> MutSubgraph<'a, W, E, Dir, G>
30where
31    E: Edge<W>,
32    Dir: EdgeDir,
33    G: Graph<W, E, Dir> + Edges<W, E> + Neighbors,
34{
35    /// Initializes a subgraph with provided `edges` and `vertex_ids`.
36    ///
37    /// # Arguments
38    /// * `graph`: Graph that this subgraph is representing.
39    /// * `edges`: Edges present in the subgraph in the format of (`src_id`, `dst_id`, `edge_id`).
40    /// * `vertex_ids`: Vertices present in the subgraph.
41    ///
42    /// # Returns
43    /// An initialized subgraph containing the provided edges and vertices.
44    pub fn init(
45        graph: &'a mut G,
46        edges: Vec<(usize, usize, usize)>,
47        vertex_ids: HashSet<usize>,
48    ) -> Self {
49        MutSubgraph {
50            graph,
51            edges,
52            vertex_ids,
53
54            phantom_w: PhantomData,
55            phantom_e: PhantomData,
56            phantom_dir: PhantomData,
57        }
58    }
59}
60
61impl<'a, W, E, Dir, G> Neighbors for MutSubgraph<'a, W, E, Dir, G>
62where
63    E: Edge<W>,
64    Dir: EdgeDir,
65    G: Graph<W, E, Dir> + Edges<W, E> + Neighbors,
66{
67    /// # Arguments:
68    /// `src_id`: Id of the source vertex.
69    ///
70    /// # Returns
71    /// * `Err`: If vertex with id: `src_id` is not present in the subgraph.
72    /// * `Ok`: Containing Id of vertices accessible from source vertex using one edge.
73    fn neighbors(&self, src_id: usize) -> Result<Vec<usize>> {
74        if !self.contains_vertex(src_id) {
75            Err(Error::new_vnf(src_id))?
76        } else {
77            Ok(self.neighbors_unchecked(src_id))
78        }
79    }
80
81    /// # Arguments:
82    /// `src_id`: Id of the source vertex.
83    ///
84    /// # Returns
85    /// Id of vertices accessible from source vertex using one edge.
86    fn neighbors_unchecked(&self, src_id: usize) -> Vec<usize> {
87        self.edges
88            .iter()
89            .filter_map(|(s_id, dst_id, _)| if *s_id == src_id { Some(*dst_id) } else { None })
90            .collect()
91    }
92}
93
94impl<'a, W, E, Dir, G> Vertices for MutSubgraph<'a, W, E, Dir, G>
95where
96    E: Edge<W>,
97    Dir: EdgeDir,
98    G: Graph<W, E, Dir>,
99{
100    /// # Returns
101    /// Id of vertices that are present in the graph.
102    fn vertices(&self) -> Vec<usize> {
103        self.vertex_ids.iter().copied().collect()
104    }
105
106    /// # Returns
107    /// * `true`: If subgraph contains the vertex with id: `vertex_id`.
108    /// * `false`: Otherwise
109    fn contains_vertex(&self, vertex_id: usize) -> bool {
110        self.vertex_ids.contains(&vertex_id)
111    }
112}
113
114impl<'a, W, E, Dir, G> Edges<W, E> for MutSubgraph<'a, W, E, Dir, G>
115where
116    E: Edge<W>,
117    Dir: EdgeDir,
118    G: Graph<W, E, Dir> + Edges<W, E> + Neighbors,
119{
120    /// # Arguments
121    /// `src_id`: Id of the source vertex.
122    ///
123    /// # Returns
124    /// * `Err`: If vertex with id: `src_id` does not exist.
125    /// * `Ok`: Containin all edges from the source vertex in the format of: (`dst_id`, `edge`)
126    fn edges_from(&self, src_id: usize) -> Result<Vec<(usize, &E)>> {
127        if !self.contains_vertex(src_id) {
128            Err(Error::new_vnf(src_id))?
129        } else {
130            Ok(self.edges_from_unchecked(src_id))
131        }
132    }
133
134    /// # Arguments
135    /// `src_id`: Id of the source vertex.
136    ///
137    /// # Returns
138    /// * All edges from the source vertex in the format of: (`dst_id`, `edge`)
139    fn edges_from_unchecked(&self, src_id: usize) -> Vec<(usize, &E)> {
140        self.graph
141            .edges_from_unchecked(src_id)
142            .into_iter()
143            .filter(|(dst_id, edge)| {
144                self.contains_vertex(*dst_id) && self.contains_edge(edge.get_id())
145            })
146            .collect()
147    }
148
149    /// # Arguments
150    /// * `src_id`: Id of source vertex.
151    /// * `dst_id`: Id of destination vertex.
152    ///
153    /// # Returns
154    /// * `Err`: If either `src_id` or `dst_id` is invalid.
155    /// * `Ok`: Containing edges from source vertex to destination vertex.
156    fn edges_between(&self, src_id: usize, dst_id: usize) -> Result<Vec<&E>> {
157        if !self.contains_vertex(src_id) {
158            Err(Error::new_vnf(src_id))?
159        } else if !self.contains_vertex(dst_id) {
160            Err(Error::new_vnf(dst_id))?
161        } else {
162            Ok(self.edges_between_unchecked(src_id, dst_id))
163        }
164    }
165
166    /// # Arguments
167    /// * `src_id`: Id of source vertex.
168    /// * `dst_id`: Id of destination vertex.
169    ///
170    /// # Returns
171    /// Edges from source vertex to destination vertex.
172    fn edges_between_unchecked(&self, src_id: usize, dst_id: usize) -> Vec<&E> {
173        self.graph
174            .edges_between_unchecked(src_id, dst_id)
175            .into_iter()
176            .filter(|edge| self.contains_edge(edge.get_id()))
177            .collect()
178    }
179
180    /// # Arguments
181    /// * `src_id`: Id of source vertex.
182    /// * `dst_id`: Id of destination vertex.
183    /// * `edge_id`: Id of the edge to retrieve.
184    ///
185    /// # Returns
186    /// * `Err`: If either vertices with `src_id` or `dst_id` does not exist.
187    /// Also when there is not edge from source to destination with id: `edge_id`.
188    /// * `Ok`: Containing reference to edge with id: `edge_id` from `src_id` to `dst_id`.
189    fn edge_between(&self, src_id: usize, dst_id: usize, edge_id: usize) -> Result<&E> {
190        if !self.contains_vertex(src_id) {
191            Err(Error::new_vnf(src_id))?
192        } else if !self.contains_vertex(dst_id) {
193            Err(Error::new_vnf(dst_id))?
194        } else if !self.contains_edge(edge_id) {
195            Err(Error::new_enf(edge_id))?
196        } else {
197            Ok(self.edge_between_unchecked(src_id, dst_id, edge_id))
198        }
199    }
200
201    /// # Arguments
202    /// * `src_id`: Id of source vertex.
203    /// * `dst_id`: Id of destination vertex.
204    /// * `edge_id`: Id of the edge to retrieve.
205    ///
206    /// # Returns
207    /// Reference to edge with id: `edge_id` from `src_id` to `dst_id`.
208    fn edge_between_unchecked(&self, src_id: usize, dst_id: usize, edge_id: usize) -> &E {
209        self.graph.edge_between_unchecked(src_id, dst_id, edge_id)
210    }
211
212    /// # Note:
213    /// Consider using `edge_between` or `edges_from` functions instead of this one.
214    /// Because default implementation of this function iterates over all edges to find the edge with specified id.
215    /// And it's likely that other storages use the same approach. So:
216    /// * if you have info about source of the edge, consider using `edges_from` function instead.
217    /// * if you have info about both source and destination of the edge, consider using `edge_between` function instead.
218    ///
219    /// # Arguments
220    /// `edge_id`: Id of the edge to be retrieved.
221    ///
222    /// # Returns
223    /// * `Err`: If there is not edge with id: `edge_id`.
224    /// * `Ok`: Containing reference to edge with id: `edge_id`.
225    fn edge(&self, edge_id: usize) -> Result<&E> {
226        if !self.contains_edge(edge_id) {
227            Err(Error::new_enf(edge_id))?
228        } else {
229            Ok(self.edge_unchecked(edge_id))
230        }
231    }
232
233    /// # Note:
234    /// Consider using `edge_between_unchecked` or `edges_from_unchecked` functions instead of this one.
235    /// Because default implementation of this function iterates over all edges to find the edge with specified id.
236    /// And it's likely that other storages use the same approach. So:
237    /// * if you have info about source of the edge, consider using `edges_from_unchecked` function instead.
238    /// * if you have info about both source and destination of the edge, consider using `edge_between_unchecked` function instead.
239    ///
240    /// # Arguments
241    /// `edge_id`: Id of the edge to be retrieved.
242    ///
243    /// # Returns
244    /// Reference to edge with id: `edge_id`.
245    fn edge_unchecked(&self, edge_id: usize) -> &E {
246        self.graph.edge_unchecked(edge_id)
247    }
248
249    /// # Arguments
250    /// * `src_id`: Id of the source vertex.
251    /// * `dst_id`: Id of the destination vertex.
252    ///
253    /// # Returns
254    /// * `Err`: If either `src_id` or `dst_id` is invalid.
255    /// * `Ok`: Containing `true` if there is at least one edge from `src_id` to `dst_id` and `false` otherwise.
256    fn has_any_edge(&self, src_id: usize, dst_id: usize) -> Result<bool> {
257        if !self.contains_vertex(src_id) {
258            Err(Error::new_vnf(src_id))?
259        } else if !self.contains_vertex(dst_id) {
260            Err(Error::new_vnf(dst_id))?
261        } else {
262            Ok(self.has_any_edge_unchecked(src_id, dst_id))
263        }
264    }
265
266    /// # Arguments
267    /// * `src_id`: Id of the source vertex.
268    /// * `dst_id`: Id of the destination vertex.
269    ///
270    /// # Returns
271    /// `true` if there is at least one edge from `src_id` to `dst_id` and `false` otherwise.
272    fn has_any_edge_unchecked(&self, src_id: usize, dst_id: usize) -> bool {
273        self.edges
274            .iter()
275            .find(|(s_id, d_id, _)| *s_id == src_id && *d_id == dst_id)
276            .is_some()
277    }
278
279    /// # Returns
280    /// All edges in the graph in the format: (`src_id`, `dst_id`, `edge`).
281    fn edges(&self) -> Vec<(usize, usize, &E)> {
282        self.graph
283            .edges()
284            .into_iter()
285            .filter(|(src_id, dst_id, edge)| {
286                self.contains_vertex(*src_id)
287                    && self.contains_vertex(*dst_id)
288                    && self.contains_edge(edge.get_id())
289            })
290            .collect()
291    }
292
293    /// Difference between this function and `edges` is that this function treats each edge as a directed edge. \
294    /// For example consider graph: a --- b \
295    /// If you call `edges` on this graph, you will get: (a, b, edge). \
296    /// But if you call `as_directed_edges`, you will get two elements: (a, b, edge) and (b, a, edge). \
297    /// It's specifically useful in algorithms that are for directed graphs but can also be applied to undirected graphs if we treat the edges as directed.
298    /// One example is [`BellmanFord`](crate::algo::BellmanFord) algorithm.
299    ///
300    /// # Returns
301    /// All edges(as directed edges) in the graph in the format of: (`src_id`, `dst_id`, `edge`).
302    fn as_directed_edges(&self) -> Vec<(usize, usize, &E)> {
303        if Dir::is_directed() {
304            self.edges()
305        } else {
306            self.edges()
307                .into_iter()
308                .filter(|(src_id, dst_id, _)| src_id <= dst_id)
309                .collect()
310        }
311    }
312
313    /// # Returns
314    /// Number of edges in the graph.
315    fn edges_count(&self) -> usize {
316        self.edges().len()
317    }
318
319    fn contains_edge(&self, edge_id: usize) -> bool {
320        self.edges
321            .iter()
322            .find(|(_, _, e_id)| *e_id == edge_id)
323            .is_some()
324    }
325}
326
327impl<'a, W, E, Dir, G> AsFrozenSubgraph<W, E> for MutSubgraph<'a, W, E, Dir, G>
328where
329    E: Edge<W>,
330    Dir: EdgeDir,
331    G: Graph<W, E, Dir> + Edges<W, E> + Neighbors,
332{
333}
334
335impl<'a, W, E, Dir, G> AsSubgraph<W, E> for MutSubgraph<'a, W, E, Dir, G>
336where
337    E: Edge<W>,
338    Dir: EdgeDir,
339    G: Graph<W, E, Dir> + Vertices + Neighbors + Edges<W, E>,
340{
341    /// Removes an edge from the subgraph.
342    ///
343    /// # Arguments
344    /// * `src_id`: Id of the source vertex.
345    /// * `dst_id`: Id of the destination vertex.
346    /// * `edge_id`: Id of the edge from source to destination to be removed.
347    ///
348    /// # Returns
349    /// * `Err`: If either vertices with `src_id` or `dst_id` does not exist.
350    /// Also when there is not edge from source to destination with id: `edge_id`.
351    /// * `Ok`:
352    fn remove_edge(&mut self, src_id: usize, dst_id: usize, edge_id: usize) -> Result<()> {
353        if !self.contains_vertex(src_id) {
354            Err(Error::new_vnf(src_id))?
355        } else if !self.contains_vertex(dst_id) {
356            Err(Error::new_vnf(dst_id))?
357        } else if !self.contains_edge(edge_id) {
358            Err(Error::new_enf(edge_id))?
359        } else {
360            Ok(self.remove_edge_unchecked(src_id, dst_id, edge_id))
361        }
362    }
363
364    /// Removes an edge from the subgraph.
365    ///
366    /// # Arguments
367    /// * `src_id`: Id of the source vertex.
368    /// * `dst_id`: Id of the destination vertex.
369    /// * `edge_id`: Id of the edge from source to destination to be removed.
370    fn remove_edge_unchecked(&mut self, _: usize, _: usize, edge_id: usize) {
371        self.edges.retain(|(_, _, e_id)| *e_id != edge_id)
372    }
373
374    /// Removes a vertex from the subgraph.
375    ///
376    /// # Arguments
377    /// `vertex_id`: Id of the vertex to be removed.
378    ///
379    /// # Returns
380    /// * `Err`: If vertex with id: `vertex_id` is not present in the subgraph.
381    /// * `Ok`:
382    fn remove_vertex(&mut self, vertex_id: usize) -> Result<()> {
383        if !self.contains_vertex(vertex_id) {
384            Err(Error::new_vnf(vertex_id))?
385        } else {
386            Ok(self.remove_vertex_unchecked(vertex_id))
387        }
388    }
389
390    /// Removes a vertex from the subgraph.
391    ///
392    /// # Arguments
393    /// `vertex_id`: Id of the vertex to be removed.
394    fn remove_vertex_unchecked(&mut self, vertex_id: usize) {
395        self.vertex_ids.retain(|v_id| *v_id != vertex_id);
396
397        self.edges
398            .retain(|(src_id, dst_id, _)| *src_id != vertex_id && *dst_id != vertex_id);
399    }
400
401    /// Adds a vertex from the graph to subgraph.
402    ///
403    /// # Arguments
404    /// `vertex_id`: Id of the vertex to be added.
405    ///
406    /// # Returns
407    /// * `Err`: If graph does not contain vertex with id: `vertex_id`.
408    /// * `Ok`:
409    fn add_vertex_from_graph(&mut self, vertex_id: usize) -> Result<()> {
410        if !self.graph.contains_vertex(vertex_id) {
411            Err(Error::new_vnf(vertex_id))?
412        } else {
413            Ok(self.add_vertex_from_graph_unchecked(vertex_id))
414        }
415    }
416
417    /// Adds a vertex from the graph to subgraph.
418    ///
419    /// # Arguments
420    /// `vertex_id`: Id of the vertex to be added.
421    fn add_vertex_from_graph_unchecked(&mut self, vertex_id: usize) {
422        self.vertex_ids.insert(vertex_id);
423    }
424
425    /// Adds an edge from the graph to subgraph.
426    ///
427    /// # Arguments
428    /// * `src_id`: Id of the source vertex.
429    /// * `dst_id`: Id of the destination vertex.
430    /// * `edge_id`: Id of the edge to be added.
431    ///
432    /// # Returns
433    /// * `Err`:
434    ///     * If vertex with id: `src_id` does not exist in graph.
435    ///     * If vertex with id: `dst_id` dost not exist in graph.
436    ///     * If edge with id: `edge_id` does not exist in graph(from src to dst).
437    ///     * If edge already exists in the subgraph.
438    /// * `Ok`:
439    fn add_edge_from_graph(&mut self, src_id: usize, dst_id: usize, edge_id: usize) -> Result<()> {
440        if !self.graph.contains_vertex(src_id) {
441            Err(Error::new_vnf(src_id))?
442        } else if !self.graph.contains_vertex(dst_id) {
443            Err(Error::new_vnf(dst_id))?
444        } else if !self.graph.contains_edge(edge_id) {
445            Err(Error::new_enf(edge_id))?
446        } else if self.contains_edge(edge_id) {
447            Err(Error::new_eae(edge_id))?
448        } else {
449            Ok(self.add_edge_from_graph_unchecked(src_id, dst_id, edge_id))
450        }
451    }
452
453    /// Adds an edge from the graph to subgraph.
454    ///
455    /// # Arguments
456    /// * `src_id`: Id of the source vertex.
457    /// * `dst_id`: Id of the destination vertex.
458    /// * `edge_id`: Id of the edge to be added.
459    fn add_edge_from_graph_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize) {
460        self.edges.push((src_id, dst_id, edge_id));
461
462        self.vertex_ids.insert(src_id);
463        self.vertex_ids.insert(dst_id);
464    }
465}
466
467impl<'a, W, E, Dir, G> AsMutSubgraph<W, E> for MutSubgraph<'a, W, E, Dir, G>
468where
469    E: Edge<W>,
470    Dir: EdgeDir,
471    G: Graph<W, E, Dir> + Vertices + Neighbors + Edges<W, E>,
472{
473    /// Removes a vertex from the graph and consequently from the subgraph as well if it contains the vertex.
474    ///
475    /// # Arguments
476    /// `vertex_id`: Id of the vertex to be removed
477    ///
478    /// # Returns
479    /// Result of calling `remove_vertex` on the graph(so it depends on the graph/storage).
480    fn remove_vertex_from_graph(&mut self, vertex_id: usize) -> Result<()> {
481        if self.contains_vertex(vertex_id) {
482            self.remove_vertex_unchecked(vertex_id);
483        }
484
485        self.graph.remove_vertex(vertex_id)
486    }
487
488    /// Removes a vertex from the graph and consequently from the subgraph as well if it contains the vertex.
489    ///
490    /// # Arguments
491    /// `vertex_id`: Id of the vertex to be removed
492    fn remove_vertex_from_graph_unchecked(&mut self, vertex_id: usize) {
493        if self.contains_vertex(vertex_id) {
494            self.remove_vertex_unchecked(vertex_id);
495        }
496
497        self.graph.remove_vertex_unchecked(vertex_id);
498    }
499
500    /// Removes an edge from the graph and consequently from the subgraph as well if it contains the edge.
501    ///
502    /// # Arguments
503    /// * `src_id`: Id of the source vertex.
504    /// * `dst_id`: Id of the destination vertex.
505    /// * `edge_id`: Id of the edge from source to destination.
506    ///
507    /// # Returns
508    /// Result of calling `remove_edge` on the graph(so it depends on the graph/storage).
509    fn remove_edge_from_graph(
510        &mut self,
511        src_id: usize,
512        dst_id: usize,
513        edge_id: usize,
514    ) -> Result<E> {
515        if self.contains_edge(edge_id) {
516            self.remove_edge_unchecked(src_id, dst_id, edge_id);
517        }
518
519        self.graph.remove_edge(src_id, dst_id, edge_id)
520    }
521
522    /// Removes an edge from the graph and consequently from the subgraph as well if it contains the edge.
523    ///
524    /// # Arguments
525    /// * `src_id`: Id of the source vertex.
526    /// * `dst_id`: Id of the destination vertex.
527    /// * `edge_id`: Id of the edge from source to destination.
528    ///
529    /// # Returns
530    /// Removed edge
531    fn remove_edge_from_graph_unchecked(
532        &mut self,
533        src_id: usize,
534        dst_id: usize,
535        edge_id: usize,
536    ) -> E {
537        if self.contains_edge(edge_id) {
538            self.remove_edge_unchecked(src_id, dst_id, edge_id);
539        }
540
541        self.graph.remove_edge_unchecked(src_id, dst_id, edge_id)
542    }
543
544    /// Adds a vertex to the subgraph and consequently to the graph.
545    ///
546    /// # Returns
547    /// Id of the newly added vertex.
548    fn add_vertex(&mut self) -> usize {
549        let vertex_id = self.graph.add_vertex();
550
551        self.vertex_ids.insert(vertex_id);
552
553        vertex_id
554    }
555
556    /// Adds an edge to the subgraph and consequently to the graph.
557    ///
558    /// # Arguments
559    /// * `src_id`: Id of the source vertex.
560    /// * `dst_id`: Id of the destination vertex.
561    /// * `edge`: Edge to be add from source to destination.
562    ///
563    /// # Returns
564    /// * `Err`: Error of calling `add_edge` on the graph(so it depends on the graph/storage).
565    /// * `Ok`: Containing id of the newly created edge.
566    fn add_edge(&mut self, src_id: usize, dst_id: usize, edge: E) -> Result<usize> {
567        let edge_id = self.graph.add_edge(src_id, dst_id, edge)?;
568
569        self.edges.push((src_id, dst_id, edge_id));
570
571        self.vertex_ids.insert(src_id);
572        self.vertex_ids.insert(dst_id);
573
574        Ok(edge_id)
575    }
576
577    /// Adds an edge to the subgraph and consequently to the graph.
578    ///
579    /// # Arguments
580    /// * `src_id`: Id of the source vertex.
581    /// * `dst_id`: Id of the destination vertex.
582    /// * `edge`: Edge to be add from source to destination.
583    ///
584    /// # Returns
585    /// Id of the newly created edge.
586    fn add_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge: E) -> usize {
587        let edge_id = self.graph.add_edge_unchecked(src_id, dst_id, edge);
588
589        self.edges.push((src_id, dst_id, edge_id));
590
591        self.vertex_ids.insert(src_id);
592        self.vertex_ids.insert(dst_id);
593
594        edge_id
595    }
596}