lau_network_science/
graph.rs1use serde::{Deserialize, Serialize};
2use std::collections::{HashMap, HashSet};
3
4#[derive(Clone, Debug, Serialize, Deserialize)]
6pub struct Graph {
7 adj: HashMap<usize, HashSet<usize>>,
9 n: usize,
10 m: usize,
11 directed: bool,
12}
13
14impl Graph {
15 pub fn new() -> Self {
16 Graph {
17 adj: HashMap::new(),
18 n: 0,
19 m: 0,
20 directed: false,
21 }
22 }
23
24 pub fn with_n_nodes(n: usize) -> Self {
26 let mut adj = HashMap::new();
27 for i in 0..n {
28 adj.insert(i, HashSet::new());
29 }
30 Graph { adj, n, m: 0, directed: false }
31 }
32
33 pub fn add_node(&mut self, node: usize) {
35 if !self.adj.contains_key(&node) {
36 self.adj.insert(node, HashSet::new());
37 self.n = self.n.max(node + 1);
38 }
39 }
40
41 pub fn add_edge(&mut self, u: usize, v: usize) {
43 if u == v { return; } self.add_node(u);
45 self.add_node(v);
46 if !self.adj[&u].contains(&v) {
47 self.adj.get_mut(&u).unwrap().insert(v);
48 self.adj.get_mut(&v).unwrap().insert(u);
49 self.m += 1;
50 }
51 }
52
53 pub fn remove_edge(&mut self, u: usize, v: usize) {
55 if let Some(neighbors) = self.adj.get_mut(&u) {
56 if neighbors.remove(&v) {
57 self.m -= 1;
58 }
59 }
60 if let Some(neighbors) = self.adj.get_mut(&v) {
61 neighbors.remove(&u);
62 }
63 }
64
65 pub fn remove_node(&mut self, node: usize) {
67 if let Some(neighbors) = self.adj.remove(&node) {
68 for &nb in &neighbors {
69 if let Some(nbs) = self.adj.get_mut(&nb) {
70 nbs.remove(&node);
71 self.m -= 1;
72 }
73 }
74 }
75 }
76
77 pub fn node_count(&self) -> usize {
78 self.adj.len()
79 }
80
81 pub fn edge_count(&self) -> usize {
82 self.m
83 }
84
85 pub fn nodes(&self) -> Vec<usize> {
86 self.adj.keys().copied().collect()
87 }
88
89 pub fn has_node(&self, node: usize) -> bool {
90 self.adj.contains_key(&node)
91 }
92
93 pub fn has_edge(&self, u: usize, v: usize) -> bool {
94 self.adj.get(&u).map_or(false, |s| s.contains(&v))
95 }
96
97 pub fn neighbors(&self, node: usize) -> Vec<usize> {
98 self.adj.get(&node).map_or(vec![], |s| s.iter().copied().collect())
99 }
100
101 pub fn degree(&self, node: usize) -> usize {
102 self.adj.get(&node).map_or(0, |s| s.len())
103 }
104
105 pub fn degrees(&self) -> Vec<(usize, usize)> {
106 self.adj.keys().map(|&n| (n, self.degree(n))).collect()
107 }
108
109 pub fn edges(&self) -> Vec<(usize, usize)> {
111 let mut edges = Vec::new();
112 let mut seen = HashSet::new();
113 for (&u, nbs) in &self.adj {
114 for &v in nbs {
115 let (a, b) = if u < v { (u, v) } else { (v, u) };
116 if seen.insert((a, b)) {
117 edges.push((a, b));
118 }
119 }
120 }
121 edges
122 }
123
124 pub fn bfs_distances(&self, source: usize) -> HashMap<usize, usize> {
126 let mut dist = HashMap::new();
127 let mut queue = std::collections::VecDeque::new();
128 dist.insert(source, 0);
129 queue.push_back(source);
130 while let Some(u) = queue.pop_front() {
131 let d = dist[&u];
132 for &v in &self.adj[&u] {
133 if !dist.contains_key(&v) {
134 dist.insert(v, d + 1);
135 queue.push_back(v);
136 }
137 }
138 }
139 dist
140 }
141
142 pub fn is_connected(&self) -> bool {
144 if self.adj.is_empty() { return true; }
145 let start = *self.adj.keys().next().unwrap();
146 let dist = self.bfs_distances(start);
147 dist.len() == self.adj.len()
148 }
149
150 pub fn connected_components(&self) -> Vec<Vec<usize>> {
152 let mut visited = HashSet::new();
153 let mut components = Vec::new();
154 for &node in self.adj.keys() {
155 if visited.contains(&node) { continue; }
156 let dist = self.bfs_distances(node);
157 let comp: Vec<usize> = dist.keys().copied().collect();
158 visited.extend(comp.iter().copied());
159 components.push(comp);
160 }
161 components
162 }
163
164 pub fn adjacency(&self) -> &HashMap<usize, HashSet<usize>> {
166 &self.adj
167 }
168
169 pub fn largest_component(&self) -> Graph {
171 let components = self.connected_components();
172 let largest = components.into_iter().max_by_key(|c| c.len()).unwrap_or_default();
173 let node_set: HashSet<usize> = largest.into_iter().collect();
174 let mut g = Graph::new();
175 for &u in &node_set {
176 for &v in &self.adj[&u] {
177 if node_set.contains(&v) && u < v {
178 g.add_edge(u, v);
179 }
180 }
181 }
182 g
183 }
184}
185
186#[derive(Clone, Debug, Serialize, Deserialize)]
188pub struct DirectedGraph {
189 out_edges: HashMap<usize, HashSet<usize>>,
191 in_edges: HashMap<usize, HashSet<usize>>,
193 n: usize,
194 m: usize,
195}
196
197impl DirectedGraph {
198 pub fn new() -> Self {
199 DirectedGraph {
200 out_edges: HashMap::new(),
201 in_edges: HashMap::new(),
202 n: 0,
203 m: 0,
204 }
205 }
206
207 pub fn with_n_nodes(n: usize) -> Self {
208 let mut out_edges = HashMap::new();
209 let mut in_edges = HashMap::new();
210 for i in 0..n {
211 out_edges.insert(i, HashSet::new());
212 in_edges.insert(i, HashSet::new());
213 }
214 DirectedGraph { out_edges, in_edges, n, m: 0 }
215 }
216
217 pub fn add_node(&mut self, node: usize) {
218 if !self.out_edges.contains_key(&node) {
219 self.out_edges.insert(node, HashSet::new());
220 self.in_edges.insert(node, HashSet::new());
221 self.n = self.n.max(node + 1);
222 }
223 }
224
225 pub fn add_edge(&mut self, from: usize, to: usize) {
226 if from == to { return; }
227 self.add_node(from);
228 self.add_node(to);
229 if !self.out_edges[&from].contains(&to) {
230 self.out_edges.get_mut(&from).unwrap().insert(to);
231 self.in_edges.get_mut(&to).unwrap().insert(from);
232 self.m += 1;
233 }
234 }
235
236 pub fn node_count(&self) -> usize { self.out_edges.len() }
237 pub fn edge_count(&self) -> usize { self.m }
238 pub fn out_degree(&self, node: usize) -> usize {
239 self.out_edges.get(&node).map_or(0, |s| s.len())
240 }
241 pub fn in_degree(&self, node: usize) -> usize {
242 self.in_edges.get(&node).map_or(0, |s| s.len())
243 }
244 pub fn successors(&self, node: usize) -> Vec<usize> {
245 self.out_edges.get(&node).map_or(vec![], |s| s.iter().copied().collect())
246 }
247 pub fn predecessors(&self, node: usize) -> Vec<usize> {
248 self.in_edges.get(&node).map_or(vec![], |s| s.iter().copied().collect())
249 }
250 pub fn nodes(&self) -> Vec<usize> {
251 self.out_edges.keys().copied().collect()
252 }
253 pub fn has_edge(&self, from: usize, to: usize) -> bool {
254 self.out_edges.get(&from).map_or(false, |s| s.contains(&to))
255 }
256 pub fn out_edges_map(&self) -> &HashMap<usize, HashSet<usize>> {
257 &self.out_edges
258 }
259
260 pub fn to_undirected(&self) -> Graph {
262 let mut g = Graph::new();
263 for (&from, tos) in &self.out_edges {
264 for &to in tos {
265 g.add_edge(from, to);
266 }
267 }
268 g
269 }
270}