1use std::collections::{HashMap, HashSet, VecDeque};
21use std::fmt::{Debug, Display};
22use std::hash::Hash;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum GraphType {
27 Undirected,
29 Directed,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35pub struct NodeId(pub(crate) usize);
36
37impl Display for NodeId {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 write!(f, "Node({})", self.0)
40 }
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub struct EdgeId(pub(crate) usize);
46
47impl Display for EdgeId {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 write!(f, "Edge({})", self.0)
50 }
51}
52
53#[derive(Debug, Clone)]
55pub struct Node<N> {
56 pub id: NodeId,
58 pub data: N,
60 pub(crate) outgoing: Vec<EdgeId>,
62 pub(crate) incoming: Vec<EdgeId>,
64}
65
66impl<N> Node<N> {
67 pub fn new(id: NodeId, data: N) -> Self {
69 Node {
70 id,
71 data,
72 outgoing: Vec::new(),
73 incoming: Vec::new(),
74 }
75 }
76
77 pub fn degree(&self) -> usize {
79 self.outgoing.len() + self.incoming.len()
80 }
81
82 pub fn out_degree(&self) -> usize {
84 self.outgoing.len()
85 }
86
87 pub fn in_degree(&self) -> usize {
89 self.incoming.len()
90 }
91}
92
93#[derive(Debug, Clone)]
95pub struct Edge<W> {
96 pub id: EdgeId,
98 pub source: NodeId,
100 pub target: NodeId,
102 pub weight: Option<W>,
104}
105
106impl<W> Edge<W> {
107 pub fn new(id: EdgeId, source: NodeId, target: NodeId, weight: Option<W>) -> Self {
109 Edge {
110 id,
111 source,
112 target,
113 weight,
114 }
115 }
116}
117
118#[derive(Debug, Clone)]
120pub enum GraphError {
121 NodeNotFound(NodeId),
123 EdgeNotFound(EdgeId),
125 InvalidOperation(String),
127 CycleDetected,
129 NotConnected,
131 NegativeWeightCycle,
133}
134
135impl std::fmt::Display for GraphError {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 match self {
138 GraphError::NodeNotFound(id) => write!(f, "Node not found: {}", id),
139 GraphError::EdgeNotFound(id) => write!(f, "Edge not found: {}", id),
140 GraphError::InvalidOperation(msg) => write!(f, "Invalid operation: {}", msg),
141 GraphError::CycleDetected => write!(f, "Cycle detected in graph"),
142 GraphError::NotConnected => write!(f, "Graph is not connected"),
143 GraphError::NegativeWeightCycle => write!(f, "Negative weight cycle detected"),
144 }
145 }
146}
147
148impl std::error::Error for GraphError {}
149
150#[derive(Debug, Clone)]
156pub struct Graph<N, W> {
157 graph_type: GraphType,
159 nodes: HashMap<NodeId, Node<N>>,
161 edges: HashMap<EdgeId, Edge<W>>,
163 next_node_id: usize,
165 next_edge_id: usize,
167 adjacency: HashMap<NodeId, Vec<(NodeId, EdgeId)>>,
169 reverse_adjacency: HashMap<NodeId, Vec<(NodeId, EdgeId)>>,
171}
172
173impl<N, W> Graph<N, W>
174where
175 N: Clone + Debug,
176 W: Clone + Debug,
177{
178 pub fn new(graph_type: GraphType) -> Self {
180 Graph {
181 graph_type,
182 nodes: HashMap::new(),
183 edges: HashMap::new(),
184 next_node_id: 0,
185 next_edge_id: 0,
186 adjacency: HashMap::new(),
187 reverse_adjacency: HashMap::new(),
188 }
189 }
190
191 pub fn graph_type(&self) -> GraphType {
193 self.graph_type
194 }
195
196 pub fn node_count(&self) -> usize {
198 self.nodes.len()
199 }
200
201 pub fn edge_count(&self) -> usize {
203 self.edges.len()
204 }
205
206 pub fn is_empty(&self) -> bool {
208 self.nodes.is_empty()
209 }
210
211 pub fn add_node(&mut self, data: N) -> NodeId {
213 let id = NodeId(self.next_node_id);
214 self.next_node_id += 1;
215
216 let node = Node::new(id, data);
217 self.nodes.insert(id, node);
218 self.adjacency.insert(id, Vec::new());
219 self.reverse_adjacency.insert(id, Vec::new());
220
221 id
222 }
223
224 pub fn remove_node(&mut self, node_id: NodeId) -> Result<N, GraphError> {
226 let edges_to_remove: Vec<EdgeId> = self
228 .edges
229 .iter()
230 .filter(|(_, edge)| edge.source == node_id || edge.target == node_id)
231 .map(|(id, _)| *id)
232 .collect();
233
234 for edge_id in edges_to_remove {
236 self.remove_edge(edge_id)?;
237 }
238
239 let node = self
241 .nodes
242 .remove(&node_id)
243 .ok_or(GraphError::NodeNotFound(node_id))?;
244
245 self.adjacency.remove(&node_id);
246 self.reverse_adjacency.remove(&node_id);
247
248 Ok(node.data)
249 }
250
251 pub fn get_node(&self, node_id: NodeId) -> Option<&Node<N>> {
253 self.nodes.get(&node_id)
254 }
255
256 pub fn get_node_mut(&mut self, node_id: NodeId) -> Option<&mut Node<N>> {
258 self.nodes.get_mut(&node_id)
259 }
260
261 pub fn add_edge(
263 &mut self,
264 source: NodeId,
265 target: NodeId,
266 weight: Option<W>,
267 ) -> Result<EdgeId, GraphError> {
268 if !self.nodes.contains_key(&source) {
270 return Err(GraphError::NodeNotFound(source));
271 }
272 if !self.nodes.contains_key(&target) {
273 return Err(GraphError::NodeNotFound(target));
274 }
275
276 let edge_id = EdgeId(self.next_edge_id);
277 self.next_edge_id += 1;
278
279 let edge = Edge::new(edge_id, source, target, weight);
280 self.edges.insert(edge_id, edge);
281
282 self.adjacency
284 .get_mut(&source)
285 .unwrap()
286 .push((target, edge_id));
287
288 if self.graph_type == GraphType::Directed {
289 self.reverse_adjacency
290 .get_mut(&target)
291 .unwrap()
292 .push((source, edge_id));
293
294 self.nodes.get_mut(&source).unwrap().outgoing.push(edge_id);
296 self.nodes.get_mut(&target).unwrap().incoming.push(edge_id);
297 } else {
298 self.adjacency
300 .get_mut(&target)
301 .unwrap()
302 .push((source, edge_id));
303
304 self.nodes.get_mut(&source).unwrap().outgoing.push(edge_id);
306 self.nodes.get_mut(&target).unwrap().outgoing.push(edge_id);
307 }
308
309 Ok(edge_id)
310 }
311
312 pub fn remove_edge(&mut self, edge_id: EdgeId) -> Result<Edge<W>, GraphError> {
314 let edge = self
315 .edges
316 .remove(&edge_id)
317 .ok_or(GraphError::EdgeNotFound(edge_id))?;
318
319 if let Some(neighbors) = self.adjacency.get_mut(&edge.source) {
321 neighbors.retain(|(_, eid)| *eid != edge_id);
322 }
323
324 if self.graph_type == GraphType::Directed {
325 if let Some(neighbors) = self.reverse_adjacency.get_mut(&edge.target) {
326 neighbors.retain(|(_, eid)| *eid != edge_id);
327 }
328
329 if let Some(node) = self.nodes.get_mut(&edge.source) {
331 node.outgoing.retain(|eid| *eid != edge_id);
332 }
333 if let Some(node) = self.nodes.get_mut(&edge.target) {
334 node.incoming.retain(|eid| *eid != edge_id);
335 }
336 } else {
337 if let Some(neighbors) = self.adjacency.get_mut(&edge.target) {
339 neighbors.retain(|(_, eid)| *eid != edge_id);
340 }
341
342 if let Some(node) = self.nodes.get_mut(&edge.source) {
344 node.outgoing.retain(|eid| *eid != edge_id);
345 }
346 if let Some(node) = self.nodes.get_mut(&edge.target) {
347 node.outgoing.retain(|eid| *eid != edge_id);
348 }
349 }
350
351 Ok(edge)
352 }
353
354 pub fn get_edge(&self, edge_id: EdgeId) -> Option<&Edge<W>> {
356 self.edges.get(&edge_id)
357 }
358
359 pub fn get_edge_mut(&mut self, edge_id: EdgeId) -> Option<&mut Edge<W>> {
361 self.edges.get_mut(&edge_id)
362 }
363
364 pub fn nodes(&self) -> impl Iterator<Item = (&NodeId, &Node<N>)> {
366 self.nodes.iter()
367 }
368
369 pub fn edges(&self) -> impl Iterator<Item = (&EdgeId, &Edge<W>)> {
371 self.edges.iter()
372 }
373
374 pub fn node_ids(&self) -> impl Iterator<Item = NodeId> + '_ {
376 self.nodes.keys().copied()
377 }
378
379 pub fn edge_ids(&self) -> impl Iterator<Item = EdgeId> + '_ {
381 self.edges.keys().copied()
382 }
383
384 pub fn neighbors(&self, node_id: NodeId) -> Option<Vec<NodeId>> {
386 self.adjacency
387 .get(&node_id)
388 .map(|neighbors| neighbors.iter().map(|(n, _)| *n).collect())
389 }
390
391 pub fn predecessors(&self, node_id: NodeId) -> Option<Vec<NodeId>> {
393 if self.graph_type == GraphType::Directed {
394 self.reverse_adjacency
395 .get(&node_id)
396 .map(|neighbors| neighbors.iter().map(|(n, _)| *n).collect())
397 } else {
398 self.neighbors(node_id)
400 }
401 }
402
403 pub fn edges_of(&self, node_id: NodeId) -> Option<Vec<EdgeId>> {
405 let node = self.nodes.get(&node_id)?;
406
407 if self.graph_type == GraphType::Directed {
408 let mut edges: Vec<EdgeId> = node.outgoing.clone();
409 edges.extend(node.incoming.iter().cloned());
410 Some(edges)
411 } else {
412 Some(node.outgoing.clone())
413 }
414 }
415
416 pub fn has_edge(&self, source: NodeId, target: NodeId) -> bool {
418 if let Some(neighbors) = self.adjacency.get(&source) {
419 neighbors.iter().any(|(n, _)| *n == target)
420 } else {
421 false
422 }
423 }
424
425 pub fn get_edge_between(&self, source: NodeId, target: NodeId) -> Option<&Edge<W>> {
427 let neighbors = self.adjacency.get(&source)?;
428 let (_, edge_id) = neighbors.iter().find(|(n, _)| *n == target)?;
429 self.edges.get(edge_id)
430 }
431
432 pub fn degree(&self, node_id: NodeId) -> Option<usize> {
434 self.nodes.get(&node_id).map(|n| {
435 if self.graph_type == GraphType::Directed {
436 n.outgoing.len() + n.incoming.len()
437 } else {
438 n.outgoing.len()
439 }
440 })
441 }
442
443 pub fn in_degree(&self, node_id: NodeId) -> Option<usize> {
445 if self.graph_type == GraphType::Directed {
446 self.nodes.get(&node_id).map(|n| n.incoming.len())
447 } else {
448 self.degree(node_id)
449 }
450 }
451
452 pub fn out_degree(&self, node_id: NodeId) -> Option<usize> {
454 self.nodes.get(&node_id).map(|n| n.outgoing.len())
455 }
456
457 pub fn subgraph(&self, node_ids: &[NodeId]) -> Graph<N, W> {
459 let node_set: HashSet<NodeId> = node_ids.iter().copied().collect();
460 let mut subgraph = Graph::new(self.graph_type);
461
462 let mut id_map: HashMap<NodeId, NodeId> = HashMap::new();
464
465 for &node_id in node_ids {
467 if let Some(node) = self.nodes.get(&node_id) {
468 let new_id = subgraph.add_node(node.data.clone());
469 id_map.insert(node_id, new_id);
470 }
471 }
472
473 for edge in self.edges.values() {
475 if node_set.contains(&edge.source) && node_set.contains(&edge.target) {
476 let new_source = id_map[&edge.source];
477 let new_target = id_map[&edge.target];
478 let _ = subgraph.add_edge(new_source, new_target, edge.weight.clone());
479 }
480 }
481
482 subgraph
483 }
484
485 pub fn reverse(&self) -> Graph<N, W> {
487 let mut reversed = Graph::new(self.graph_type);
488
489 let mut id_map: HashMap<NodeId, NodeId> = HashMap::new();
491
492 for (node_id, node) in &self.nodes {
494 let new_id = reversed.add_node(node.data.clone());
495 id_map.insert(*node_id, new_id);
496 }
497
498 for edge in self.edges.values() {
500 let new_source = id_map[&edge.target];
501 let new_target = id_map[&edge.source];
502 let _ = reversed.add_edge(new_source, new_target, edge.weight.clone());
503 }
504
505 reversed
506 }
507
508 pub fn to_undirected(&self) -> Graph<N, W> {
510 let mut undirected = Graph::new(GraphType::Undirected);
511
512 let mut id_map: HashMap<NodeId, NodeId> = HashMap::new();
514
515 for (node_id, node) in &self.nodes {
517 let new_id = undirected.add_node(node.data.clone());
518 id_map.insert(*node_id, new_id);
519 }
520
521 let mut added_edges: HashSet<(NodeId, NodeId)> = HashSet::new();
523 for edge in self.edges.values() {
524 let new_source = id_map[&edge.source];
525 let new_target = id_map[&edge.target];
526
527 let normalized = if new_source.0 < new_target.0 {
529 (new_source, new_target)
530 } else {
531 (new_target, new_source)
532 };
533
534 if !added_edges.contains(&normalized) {
535 let _ = undirected.add_edge(new_source, new_target, edge.weight.clone());
536 added_edges.insert(normalized);
537 }
538 }
539
540 undirected
541 }
542
543 pub fn clear(&mut self) {
545 self.nodes.clear();
546 self.edges.clear();
547 self.adjacency.clear();
548 self.reverse_adjacency.clear();
549 self.next_node_id = 0;
550 self.next_edge_id = 0;
551 }
552}
553
554impl<N, W> Default for Graph<N, W>
555where
556 N: Clone + Debug,
557 W: Clone + Debug,
558{
559 fn default() -> Self {
560 Graph::new(GraphType::Undirected)
561 }
562}
563
564pub struct GraphBuilder<N, W> {
566 graph: Graph<N, W>,
567 node_map: HashMap<String, NodeId>,
568}
569
570impl<N, W> GraphBuilder<N, W>
571where
572 N: Clone + Debug,
573 W: Clone + Debug,
574{
575 pub fn new(graph_type: GraphType) -> Self {
577 GraphBuilder {
578 graph: Graph::new(graph_type),
579 node_map: HashMap::new(),
580 }
581 }
582
583 pub fn undirected() -> Self {
585 Self::new(GraphType::Undirected)
586 }
587
588 pub fn directed() -> Self {
590 Self::new(GraphType::Directed)
591 }
592
593 pub fn add_node(mut self, name: &str, data: N) -> Self {
595 let id = self.graph.add_node(data);
596 self.node_map.insert(name.to_string(), id);
597 self
598 }
599
600 pub fn add_edge(mut self, source: &str, target: &str, weight: Option<W>) -> Self {
602 if let (Some(&src), Some(&tgt)) = (self.node_map.get(source), self.node_map.get(target)) {
603 let _ = self.graph.add_edge(src, tgt, weight);
604 }
605 self
606 }
607
608 pub fn build(self) -> Graph<N, W> {
610 self.graph
611 }
612
613 pub fn get_node_id(&self, name: &str) -> Option<NodeId> {
615 self.node_map.get(name).copied()
616 }
617}
618
619#[cfg(test)]
620mod tests {
621 use super::*;
622
623 #[test]
624 fn test_create_graph() {
625 let graph: Graph<&str, f64> = Graph::new(GraphType::Undirected);
626 assert_eq!(graph.node_count(), 0);
627 assert_eq!(graph.edge_count(), 0);
628 assert!(graph.is_empty());
629 }
630
631 #[test]
632 fn test_add_nodes() {
633 let mut graph: Graph<&str, f64> = Graph::new(GraphType::Undirected);
634 let a = graph.add_node("A");
635 let b = graph.add_node("B");
636
637 assert_eq!(graph.node_count(), 2);
638 assert_eq!(graph.get_node(a).unwrap().data, "A");
639 assert_eq!(graph.get_node(b).unwrap().data, "B");
640 }
641
642 #[test]
643 fn test_add_edges() {
644 let mut graph: Graph<&str, f64> = Graph::new(GraphType::Undirected);
645 let a = graph.add_node("A");
646 let b = graph.add_node("B");
647 let c = graph.add_node("C");
648
649 graph.add_edge(a, b, Some(1.0)).unwrap();
650 graph.add_edge(b, c, Some(2.0)).unwrap();
651
652 assert_eq!(graph.edge_count(), 2);
653 assert!(graph.has_edge(a, b));
654 assert!(graph.has_edge(b, a)); assert!(graph.has_edge(b, c));
656 assert!(!graph.has_edge(a, c));
657 }
658
659 #[test]
660 fn test_directed_graph() {
661 let mut graph: Graph<&str, f64> = Graph::new(GraphType::Directed);
662 let a = graph.add_node("A");
663 let b = graph.add_node("B");
664
665 graph.add_edge(a, b, Some(1.0)).unwrap();
666
667 assert!(graph.has_edge(a, b));
668 assert!(!graph.has_edge(b, a)); }
670
671 #[test]
672 fn test_neighbors() {
673 let mut graph: Graph<&str, f64> = Graph::new(GraphType::Undirected);
674 let a = graph.add_node("A");
675 let b = graph.add_node("B");
676 let c = graph.add_node("C");
677
678 graph.add_edge(a, b, None).unwrap();
679 graph.add_edge(a, c, None).unwrap();
680
681 let neighbors = graph.neighbors(a).unwrap();
682 assert_eq!(neighbors.len(), 2);
683 assert!(neighbors.contains(&b));
684 assert!(neighbors.contains(&c));
685 }
686
687 #[test]
688 fn test_graph_builder() {
689 let graph: Graph<&str, f64> = GraphBuilder::undirected()
690 .add_node("a", "A")
691 .add_node("b", "B")
692 .add_node("c", "C")
693 .add_edge("a", "b", Some(1.0))
694 .add_edge("b", "c", Some(2.0))
695 .build();
696
697 assert_eq!(graph.node_count(), 3);
698 assert_eq!(graph.edge_count(), 2);
699 }
700
701 #[test]
702 fn test_remove_node() {
703 let mut graph: Graph<&str, f64> = Graph::new(GraphType::Undirected);
704 let a = graph.add_node("A");
705 let b = graph.add_node("B");
706 let c = graph.add_node("C");
707
708 graph.add_edge(a, b, None).unwrap();
709 graph.add_edge(b, c, None).unwrap();
710
711 assert_eq!(graph.edge_count(), 2);
712
713 graph.remove_node(b).unwrap();
714
715 assert_eq!(graph.node_count(), 2);
716 assert_eq!(graph.edge_count(), 0); }
718
719 #[test]
720 fn test_subgraph() {
721 let mut graph: Graph<&str, f64> = Graph::new(GraphType::Undirected);
722 let a = graph.add_node("A");
723 let b = graph.add_node("B");
724 let c = graph.add_node("C");
725 let d = graph.add_node("D");
726
727 graph.add_edge(a, b, None).unwrap();
728 graph.add_edge(b, c, None).unwrap();
729 graph.add_edge(c, d, None).unwrap();
730
731 let subgraph = graph.subgraph(&[a, b, c]);
732 assert_eq!(subgraph.node_count(), 3);
733 assert_eq!(subgraph.edge_count(), 2); }
735}