unobtanium_graph_algorithms/graph/
mod.rs1use iddqd::BiHashMap;
6
7use core::hash::Hash;
8
9mod branded;
10mod pagerank;
11pub mod ranked_nodes;
12
13use crate::node::Node;
14use crate::node::NodeId;
15
16pub use branded::BrandedNodeId;
17pub use branded::MutableGraph;
18
19pub struct Graph<T: Eq + Hash + Clone> {
21 graph: Vec<Vec<(NodeId, f32)>>,
24
25 outgoing_weight_sums: Vec<f32>,
27
28 nodes: BiHashMap<Node<T>>,
30
31 nodes_length: usize,
34}
35
36impl<T: Eq + Hash + Clone> Default for Graph<T> {
37 fn default() -> Self {
38 Self {
39 graph: Default::default(),
40 outgoing_weight_sums: Default::default(),
41 nodes: BiHashMap::new(),
42 nodes_length: 0,
43 }
44 }
45}
46
47impl<T: Eq + Hash + Clone> Graph<T> {
48 pub fn new() -> Self {
50 Default::default()
51 }
52
53 fn get_node_data_for_id(&self, id: NodeId) -> Option<&T> {
54 Some(&self.nodes.get1(&id)?.data)
55 }
56
57 fn fetch_id_for_data(&mut self, data: &T) -> NodeId {
58 if let Some(node) = self.nodes.get2(&data) {
59 return node.id;
60 }
61 let new_id = self.nodes_length;
62 self.nodes_length += 1;
63 self.outgoing_weight_sums.push(0.0);
64 self.graph.push(Vec::with_capacity(4));
65 self.nodes.insert_overwrite(Node {
66 id: NodeId(new_id),
67 data: data.clone(),
68 });
69 NodeId(new_id)
70 }
71
72 #[inline(always)]
73 fn add_edge_weighted(&mut self, from: NodeId, to: NodeId, weight: f32) {
74 let incoming_edges = self.graph
75 .get_mut(to.0)
76 .unwrap();
77 let mut found = false;
78 for (id, e) in &mut *incoming_edges {
79 if *id == from {
80 *e += weight;
81 found = true;
82 break;
83 }
84 }
85 if !found {
86 incoming_edges.push((from, weight))
87 }
88 *self.outgoing_weight_sums.get_mut(from.0).unwrap() += weight;
89 }
90
91 #[inline(always)]
95 pub fn modify<F, R>(&mut self, callback: F) -> R
96 where
97 for<'new_id> F: FnOnce(MutableGraph<'new_id, T>) -> R,
98 {
99 MutableGraph::new(self, callback)
100 }
101}