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}