1use super::{Edge, EdgeId, EdgeList, NetworkError, Vertex, VertexId};
2use crate::algorithm::search::Direction;
3use crate::model::network::EdgeListId;
4use crate::model::network::GraphConfig;
5use crate::util::fs::read_utils;
6use indexmap::IndexMap;
7use itertools::Itertools;
8use kdam::tqdm;
9use kdam::Bar;
10
11#[derive(Debug)]
30pub struct Graph {
31 pub vertices: Box<[Vertex]>,
32 pub edge_lists: Vec<EdgeList>,
33 pub adj: DenseAdjacencyList,
34 pub rev: DenseAdjacencyList,
35}
36
37pub type DenseAdjacencyList = Box<[IndexMap<(EdgeListId, EdgeId), VertexId>]>;
39
40impl TryFrom<&GraphConfig> for Graph {
41 type Error = NetworkError;
42
43 fn try_from(config: &GraphConfig) -> Result<Self, Self::Error> {
46 let vertices: Box<[Vertex]> = read_utils::from_csv(
47 &config.vertex_list_input_file,
48 true,
49 Some(Bar::builder().desc(format!("graph vertices: {}", config.vertex_list_input_file))),
50 None,
51 )
52 .map_err(|e| NetworkError::CsvError { source: e })?;
53
54 let mut adj: Vec<IndexMap<(EdgeListId, EdgeId), VertexId>> =
55 vec![IndexMap::new(); vertices.len()];
56 let mut rev: Vec<IndexMap<(EdgeListId, EdgeId), VertexId>> =
57 vec![IndexMap::new(); vertices.len()];
58
59 let edge_lists = config
63 .edge_list
64 .iter()
65 .enumerate()
66 .map(|(idx, c)| EdgeList::new(&c.input_file, EdgeListId(idx)))
67 .collect::<Result<Vec<_>, _>>()?;
68
69 let total_edges = edge_lists.iter().map(|el| el.len()).sum::<usize>();
70 log::info!(
71 "loaded {} edge lists with a total of {} edges",
72 edge_lists.len(),
73 total_edges
74 );
75
76 let build_adjacencies_iter = tqdm!(
77 edge_lists.iter().flat_map(|el| el.edges()),
78 desc = "building adjacencies",
79 total = total_edges
80 );
81 let mut bad_refs: Vec<String> = vec![];
82 for edge in build_adjacencies_iter {
83 if let Err(e) = append_to_adjacency(edge, &mut adj, true) {
84 bad_refs.push(e);
85 }
86 if let Err(e) = append_to_adjacency(edge, &mut rev, false) {
87 bad_refs.push(e);
88 }
89 }
90
91 if !bad_refs.is_empty() {
92 let msg = format!("[{}]", bad_refs.iter().take(5).join("\n "));
93 return Err(NetworkError::DatasetError(format!(
94 "invalid edge lists for vertex set. (up to) first five errors:\n {msg}"
95 )));
96 }
97
98 let graph = Graph {
99 edge_lists,
100 vertices,
101 adj: adj.into_boxed_slice(),
102 rev: rev.into_boxed_slice(),
103 };
104
105 Ok(graph)
106 }
107}
108
109impl Graph {
110 pub fn get_edge_list(&self, edge_list_id: &EdgeListId) -> Result<&EdgeList, NetworkError> {
112 self.edge_lists
113 .get(edge_list_id.0)
114 .ok_or(NetworkError::EdgeListNotFound(*edge_list_id))
115 }
116
117 pub fn n_edge_lists(&self) -> usize {
118 self.edge_lists.len()
119 }
120
121 pub fn n_edges(&self) -> usize {
123 self.edge_lists.iter().map(|el| el.len()).sum::<usize>()
124 }
125
126 pub fn n_vertices(&self) -> usize {
128 self.vertices.len()
129 }
130
131 pub fn edge_ids(
135 &self,
136 edge_list_id: &EdgeListId,
137 ) -> Result<Box<dyn Iterator<Item = EdgeId>>, NetworkError> {
138 self.get_edge_list(edge_list_id).map(|e| {
139 let iter: Box<dyn Iterator<Item = EdgeId>> = Box::new((0..e.len()).map(EdgeId));
140 iter
141 })
142 }
143
144 pub fn vertex_ids(&self) -> Box<dyn Iterator<Item = VertexId>> {
148 let range = (0..self.n_vertices()).map(VertexId);
149 Box::new(range)
150 }
151
152 pub fn edges<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Edge> + 'a> {
154 Box::new(self.edge_lists.iter().flat_map(|el| el.edges()))
155 }
156
157 pub fn get_edge(
167 &self,
168 edge_list_id: &EdgeListId,
169 edge_id: &EdgeId,
170 ) -> Result<&Edge, NetworkError> {
171 match self.edge_lists.get(edge_list_id.0) {
172 None => Err(NetworkError::InternalError(format!(
173 "EdgeListId not found: {edge_list_id}"
174 ))),
175 Some(edge_list) => match edge_list.get(edge_id) {
176 None => Err(NetworkError::EdgeNotFound(*edge_id)),
177 Some(edge) => Ok(edge),
178 },
179 }
180 }
181
182 pub fn get_vertex(&self, vertex_id: &VertexId) -> Result<&Vertex, NetworkError> {
192 match self.vertices.get(vertex_id.0) {
193 None => Err(NetworkError::VertexNotFound(*vertex_id)),
194 Some(vertex) => Ok(vertex),
195 }
196 }
197
198 pub fn out_edges(&self, src: &VertexId) -> Vec<(EdgeListId, EdgeId)> {
209 self.out_edges_iter(src).cloned().collect_vec()
210 }
211
212 pub fn out_edges_iter<'a>(
214 &'a self,
215 src: &'a VertexId,
216 ) -> Box<dyn Iterator<Item = &'a (EdgeListId, EdgeId)> + 'a> {
217 match self.adj.get(src.0) {
218 Some(out_map) => Box::new(out_map.keys()),
219 None => Box::new(std::iter::empty()),
220 }
221 }
222
223 pub fn in_edges(&self, dst: &VertexId) -> Vec<(EdgeListId, EdgeId)> {
234 self.in_edges_iter(dst).cloned().collect_vec()
235 }
236
237 pub fn in_edges_iter<'a>(
238 &'a self,
239 src: &'a VertexId,
240 ) -> Box<dyn Iterator<Item = &'a (EdgeListId, EdgeId)> + 'a> {
241 match self.rev.get(src.0) {
242 Some(in_map) => Box::new(in_map.keys()),
243 None => Box::new(std::iter::empty()),
244 }
245 }
246
247 pub fn src_vertex_id(
257 &self,
258 edge_list_id: &EdgeListId,
259 edge_id: &EdgeId,
260 ) -> Result<VertexId, NetworkError> {
261 self.get_edge(edge_list_id, edge_id)
262 .map(|e| e.src_vertex_id)
263 }
264
265 pub fn dst_vertex_id(
275 &self,
276 edge_list_id: &EdgeListId,
277 edge_id: &EdgeId,
278 ) -> Result<VertexId, NetworkError> {
279 self.get_edge(edge_list_id, edge_id)
280 .map(|e| e.dst_vertex_id)
281 }
282
283 pub fn incident_edges(
295 &self,
296 vertex_id: &VertexId,
297 direction: &Direction,
298 ) -> Vec<(EdgeListId, EdgeId)> {
299 match direction {
300 Direction::Forward => self.out_edges(vertex_id),
301 Direction::Reverse => self.in_edges(vertex_id),
302 }
303 }
304
305 pub fn incident_edges_iter<'a>(
317 &'a self,
318 vertex_id: &'a VertexId,
319 direction: &Direction,
320 ) -> Box<dyn Iterator<Item = &'a (EdgeListId, EdgeId)> + 'a> {
321 match direction {
322 Direction::Forward => self.out_edges_iter(vertex_id),
323 Direction::Reverse => self.in_edges_iter(vertex_id),
324 }
325 }
326
327 pub fn incident_vertex(
339 &self,
340 edge_list_id: &EdgeListId,
341 edge_id: &EdgeId,
342 direction: &Direction,
343 ) -> Result<VertexId, NetworkError> {
344 match direction {
345 Direction::Forward => self.dst_vertex_id(edge_list_id, edge_id),
346 Direction::Reverse => self.src_vertex_id(edge_list_id, edge_id),
347 }
348 }
349
350 pub fn edge_triplet(
361 &self,
362 edge_list_id: &EdgeListId,
363 edge_id: &EdgeId,
364 ) -> Result<(&Vertex, &Edge, &Vertex), NetworkError> {
365 let edge = self.get_edge(edge_list_id, edge_id)?;
366 let src = self.get_vertex(&edge.src_vertex_id)?;
367 let dst = self.get_vertex(&edge.dst_vertex_id)?;
368
369 Ok((src, edge, dst))
370 }
371
372 pub fn incident_triplet_ids(
388 &self,
389 vertex_id: &VertexId,
390 direction: &Direction,
391 ) -> Result<Vec<(VertexId, EdgeListId, EdgeId, VertexId)>, NetworkError> {
392 self.incident_edges_iter(vertex_id, direction)
393 .map(|(edge_list_id, edge_id)| {
394 let terminal_vid = self.incident_vertex(edge_list_id, edge_id, direction)?;
395 Ok((*vertex_id, *edge_list_id, *edge_id, terminal_vid))
396 })
397 .collect()
398 }
399
400 pub fn incident_triplet_attributes(
416 &self,
417 vertex_id: &VertexId,
418 direction: &Direction,
419 ) -> Result<Vec<(&Vertex, &Edge, &Vertex)>, NetworkError> {
420 self.incident_triplet_ids(vertex_id, direction)?
421 .iter()
422 .map(|(src_id, edge_list_id, edge_id, dst_id)| {
423 let src = self.get_vertex(src_id)?;
424 let edge = self.get_edge(edge_list_id, edge_id)?;
425 let dst = self.get_vertex(dst_id)?;
426 Ok((src, edge, dst))
427 })
428 .collect()
429 }
430}
431
432fn append_to_adjacency(
445 edge: &Edge,
446 adj: &mut [IndexMap<(EdgeListId, EdgeId), VertexId>],
447 forward: bool,
448) -> Result<(), String> {
449 let vertex_idx = if forward {
450 edge.src_vertex_id.0
451 } else {
452 edge.dst_vertex_id.0
453 };
454 match adj.get_mut(vertex_idx) {
455 None => {
456 let direction = if forward { "forward" } else { "reverse" };
457 Err(format!(
458 "vertex {} not found in {} adjacencies for edge list, edge: {}, {}",
459 vertex_idx, direction, edge.edge_list_id.0, edge.edge_id.0
460 ))
461 }
462 Some(out_links) => {
463 let target_vertex = if forward {
464 edge.dst_vertex_id
465 } else {
466 edge.src_vertex_id
467 };
468 out_links.insert((edge.edge_list_id, edge.edge_id), target_vertex);
469 Ok(())
470 }
471 }
472}
473
474#[cfg(test)]
475mod tests {
476 use super::*;
477 use uom::si::{f64::Length, length::meter};
478
479 fn create_test_edge(
480 edge_list_id: usize,
481 edge_id: usize,
482 src_vertex_id: usize,
483 dst_vertex_id: usize,
484 ) -> Edge {
485 Edge::new(
486 edge_list_id,
487 edge_id,
488 src_vertex_id,
489 dst_vertex_id,
490 Length::new::<meter>(1.0),
491 )
492 }
493
494 #[test]
495 fn test_append_to_adjacency_forward_success() {
496 let mut adj: Vec<IndexMap<(EdgeListId, EdgeId), VertexId>> =
498 vec![IndexMap::new(), IndexMap::new(), IndexMap::new()];
499
500 let edge = create_test_edge(0, 0, 0, 2);
502
503 let result = append_to_adjacency(&edge, &mut adj, true);
505
506 assert!(result.is_ok());
507
508 let expected_key = (EdgeListId(0), EdgeId(0));
510 assert!(adj[0].contains_key(&expected_key));
511 assert_eq!(adj[0][&expected_key], VertexId(2)); assert!(adj[1].is_empty());
515 assert!(adj[2].is_empty());
516 }
517
518 #[test]
519 fn test_append_to_adjacency_reverse_success() {
520 let mut adj: Vec<IndexMap<(EdgeListId, EdgeId), VertexId>> =
522 vec![IndexMap::new(), IndexMap::new(), IndexMap::new()];
523
524 let edge = create_test_edge(0, 0, 0, 2);
526
527 let result = append_to_adjacency(&edge, &mut adj, false);
529
530 assert!(result.is_ok());
531
532 let expected_key = (EdgeListId(0), EdgeId(0));
534 assert!(adj[2].contains_key(&expected_key));
535 assert_eq!(adj[2][&expected_key], VertexId(0)); assert!(adj[0].is_empty());
539 assert!(adj[1].is_empty());
540 }
541
542 #[test]
543 fn test_append_to_adjacency_forward_invalid_vertex() {
544 let mut adj: Vec<IndexMap<(EdgeListId, EdgeId), VertexId>> =
546 vec![IndexMap::new(), IndexMap::new()];
547
548 let edge = create_test_edge(0, 5, 3, 1);
550
551 let result = append_to_adjacency(&edge, &mut adj, true);
553
554 assert!(result.is_err());
555 let error_msg = result.unwrap_err();
556 assert!(error_msg.contains("vertex 3 not found in forward adjacencies"));
557 assert!(error_msg.contains("edge list, edge: 0, 5"));
558 }
559
560 #[test]
561 fn test_append_to_adjacency_reverse_invalid_vertex() {
562 let mut adj: Vec<IndexMap<(EdgeListId, EdgeId), VertexId>> =
564 vec![IndexMap::new(), IndexMap::new()];
565
566 let edge = create_test_edge(1, 10, 0, 5);
568
569 let result = append_to_adjacency(&edge, &mut adj, false);
571
572 assert!(result.is_err());
573 let error_msg = result.unwrap_err();
574 assert!(error_msg.contains("vertex 5 not found in reverse adjacencies"));
575 assert!(error_msg.contains("edge list, edge: 1, 10"));
576 }
577
578 #[test]
579 fn test_append_to_adjacency_multiple_edges_same_vertex() {
580 let mut adj: Vec<IndexMap<(EdgeListId, EdgeId), VertexId>> =
582 vec![IndexMap::new(), IndexMap::new(), IndexMap::new()];
583
584 let edge1 = create_test_edge(0, 0, 0, 1);
586 let edge2 = create_test_edge(0, 1, 0, 2);
587 let edge3 = create_test_edge(1, 0, 0, 2); assert!(append_to_adjacency(&edge1, &mut adj, true).is_ok());
591 assert!(append_to_adjacency(&edge2, &mut adj, true).is_ok());
592 assert!(append_to_adjacency(&edge3, &mut adj, true).is_ok());
593
594 assert_eq!(adj[0].len(), 3);
596
597 assert_eq!(adj[0][&(EdgeListId(0), EdgeId(0))], VertexId(1));
599 assert_eq!(adj[0][&(EdgeListId(0), EdgeId(1))], VertexId(2));
600 assert_eq!(adj[0][&(EdgeListId(1), EdgeId(0))], VertexId(2));
601 }
602
603 #[test]
604 fn test_append_to_adjacency_edge_overwrite() {
605 let mut adj: Vec<IndexMap<(EdgeListId, EdgeId), VertexId>> =
607 vec![IndexMap::new(), IndexMap::new(), IndexMap::new()];
608
609 let edge1 = create_test_edge(0, 0, 0, 1);
611 let edge2 = create_test_edge(0, 0, 0, 2); assert!(append_to_adjacency(&edge1, &mut adj, true).is_ok());
615 assert_eq!(adj[0][&(EdgeListId(0), EdgeId(0))], VertexId(1));
616
617 assert!(append_to_adjacency(&edge2, &mut adj, true).is_ok());
619 assert_eq!(adj[0].len(), 1); assert_eq!(adj[0][&(EdgeListId(0), EdgeId(0))], VertexId(2)); }
622}