1use super::graph_core::{Graph, GraphKind, NodeId};
2use glam::Vec2;
3
4fn pseudo_random(seed: u64, i: u64) -> f64 {
5 let mut x = seed.wrapping_mul(6364136223846793005).wrapping_add(i.wrapping_mul(1442695040888963407));
6 x ^= x >> 33;
7 x = x.wrapping_mul(0xff51afd7ed558ccd);
8 x ^= x >> 33;
9 (x as f64) / (u64::MAX as f64)
10}
11
12pub fn watts_strogatz(n: usize, k: usize, beta: f64) -> Graph<(), ()> {
16 let mut g = Graph::new(GraphKind::Undirected);
17 if n == 0 { return g; }
18 let nodes: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
19
20 let half_k = k / 2;
22 let mut edges: Vec<(usize, usize)> = Vec::new();
23 for i in 0..n {
24 for j in 1..=half_k {
25 let target = (i + j) % n;
26 edges.push((i, target));
27 }
28 }
29
30 let mut seed_counter: u64 = 42;
32 for (i, target) in edges {
33 let r = pseudo_random(seed_counter, seed_counter);
34 seed_counter += 1;
35 if r < beta {
36 let mut new_target = i;
38 for attempt in 0..100 {
39 let candidate = (pseudo_random(seed_counter, attempt as u64) * n as f64) as usize % n;
40 seed_counter += 1;
41 if candidate != i && g.find_edge(nodes[i], nodes[candidate]).is_none() {
42 new_target = candidate;
43 break;
44 }
45 }
46 if new_target != i {
47 g.add_edge(nodes[i], nodes[new_target], ());
48 }
49 } else {
50 if g.find_edge(nodes[i], nodes[target]).is_none() {
51 g.add_edge(nodes[i], nodes[target], ());
52 }
53 }
54 }
55 g
56}
57
58pub fn barabasi_albert(n: usize, m: usize) -> Graph<(), ()> {
62 let mut g = Graph::new(GraphKind::Undirected);
63 if n == 0 || m == 0 { return g; }
64
65 let initial = (m + 1).min(n);
66 let nodes: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
67
68 for i in 0..initial {
70 for j in (i + 1)..initial {
71 g.add_edge(nodes[i], nodes[j], ());
72 }
73 }
74
75 let mut seed_counter: u64 = 1337;
76 let mut degree_list: Vec<usize> = Vec::new();
78 for i in 0..initial {
79 for _ in 0..(initial - 1) {
80 degree_list.push(i);
81 }
82 }
83
84 for i in initial..n {
85 let mut targets: Vec<usize> = Vec::new();
86 let mut connected = std::collections::HashSet::new();
87 for _ in 0..m {
88 if degree_list.is_empty() { break; }
89 for attempt in 0..100 {
90 let idx = (pseudo_random(seed_counter, attempt as u64) * degree_list.len() as f64) as usize % degree_list.len();
91 seed_counter += 1;
92 let target = degree_list[idx];
93 if target != i && !connected.contains(&target) {
94 connected.insert(target);
95 targets.push(target);
96 break;
97 }
98 }
99 }
100 for &t in &targets {
101 g.add_edge(nodes[i], nodes[t], ());
102 degree_list.push(i);
103 degree_list.push(t);
104 }
105 }
106 g
107}
108
109pub fn erdos_renyi(n: usize, p: f64) -> Graph<(), ()> {
112 let mut g = Graph::new(GraphKind::Undirected);
113 let nodes: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
114 let mut seed_counter: u64 = 7919;
115 for i in 0..n {
116 for j in (i + 1)..n {
117 let r = pseudo_random(seed_counter, (i * n + j) as u64);
118 seed_counter += 1;
119 if r < p {
120 g.add_edge(nodes[i], nodes[j], ());
121 }
122 }
123 }
124 g
125}
126
127pub fn complete_graph(n: usize) -> Graph<(), ()> {
129 let mut g = Graph::new(GraphKind::Undirected);
130 let nodes: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
131 for i in 0..n {
132 for j in (i + 1)..n {
133 g.add_edge(nodes[i], nodes[j], ());
134 }
135 }
136 g
137}
138
139pub fn cycle_graph(n: usize) -> Graph<(), ()> {
141 let mut g = Graph::new(GraphKind::Undirected);
142 if n == 0 { return g; }
143 let nodes: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
144 for i in 0..n {
145 g.add_edge(nodes[i], nodes[(i + 1) % n], ());
146 }
147 g
148}
149
150pub fn path_graph(n: usize) -> Graph<(), ()> {
152 let mut g = Graph::new(GraphKind::Undirected);
153 if n == 0 { return g; }
154 let nodes: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
155 for i in 0..(n - 1) {
156 g.add_edge(nodes[i], nodes[i + 1], ());
157 }
158 g
159}
160
161pub fn star_graph(n: usize) -> Graph<(), ()> {
163 let mut g = Graph::new(GraphKind::Undirected);
164 if n == 0 { return g; }
165 let nodes: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
166 for i in 1..n {
167 g.add_edge(nodes[0], nodes[i], ());
168 }
169 g
170}
171
172pub fn grid_graph(rows: usize, cols: usize) -> Graph<(), ()> {
174 let mut g = Graph::new(GraphKind::Undirected);
175 if rows == 0 || cols == 0 { return g; }
176 let mut nodes = Vec::new();
177 for r in 0..rows {
178 for c in 0..cols {
179 let pos = Vec2::new(c as f32 * 50.0, r as f32 * 50.0);
180 nodes.push(g.add_node_with_pos((), pos));
181 }
182 }
183 for r in 0..rows {
184 for c in 0..cols {
185 let idx = r * cols + c;
186 if c + 1 < cols {
187 g.add_edge(nodes[idx], nodes[idx + 1], ());
188 }
189 if r + 1 < rows {
190 g.add_edge(nodes[idx], nodes[idx + cols], ());
191 }
192 }
193 }
194 g
195}
196
197pub fn binary_tree(depth: usize) -> Graph<(), ()> {
199 let mut g = Graph::new(GraphKind::Undirected);
200 let n = (1 << (depth + 1)) - 1; let nodes: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
202 for i in 0..n {
203 let left = 2 * i + 1;
204 let right = 2 * i + 2;
205 if left < n {
206 g.add_edge(nodes[i], nodes[left], ());
207 }
208 if right < n {
209 g.add_edge(nodes[i], nodes[right], ());
210 }
211 }
212 g
213}
214
215pub fn petersen_graph() -> Graph<(), ()> {
217 let mut g = Graph::new(GraphKind::Undirected);
218 let nodes: Vec<NodeId> = (0..10).map(|_| g.add_node(())).collect();
219 for i in 0..5 {
221 g.add_edge(nodes[i], nodes[(i + 1) % 5], ());
222 }
223 g.add_edge(nodes[5], nodes[7], ());
225 g.add_edge(nodes[7], nodes[9], ());
226 g.add_edge(nodes[9], nodes[6], ());
227 g.add_edge(nodes[6], nodes[8], ());
228 g.add_edge(nodes[8], nodes[5], ());
229 for i in 0..5 {
231 g.add_edge(nodes[i], nodes[i + 5], ());
232 }
233 g
234}
235
236pub fn complete_bipartite(m: usize, n: usize) -> Graph<(), ()> {
238 let mut g = Graph::new(GraphKind::Undirected);
239 let left: Vec<NodeId> = (0..m).map(|_| g.add_node(())).collect();
240 let right: Vec<NodeId> = (0..n).map(|_| g.add_node(())).collect();
241 for &l in &left {
242 for &r in &right {
243 g.add_edge(l, r, ());
244 }
245 }
246 g
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252
253 #[test]
254 fn test_complete_graph_edges() {
255 let g = complete_graph(5);
256 assert_eq!(g.node_count(), 5);
257 assert_eq!(g.edge_count(), 10); }
259
260 #[test]
261 fn test_complete_graph_1() {
262 let g = complete_graph(1);
263 assert_eq!(g.node_count(), 1);
264 assert_eq!(g.edge_count(), 0);
265 }
266
267 #[test]
268 fn test_cycle_graph() {
269 let g = cycle_graph(6);
270 assert_eq!(g.node_count(), 6);
271 assert_eq!(g.edge_count(), 6);
272 for nid in g.node_ids() {
274 assert_eq!(g.degree(nid), 2);
275 }
276 }
277
278 #[test]
279 fn test_path_graph() {
280 let g = path_graph(5);
281 assert_eq!(g.node_count(), 5);
282 assert_eq!(g.edge_count(), 4);
283 let ids = g.node_ids();
284 assert_eq!(g.degree(ids[0]), 1);
285 assert_eq!(g.degree(ids[2]), 2);
286 assert_eq!(g.degree(ids[4]), 1);
287 }
288
289 #[test]
290 fn test_star_graph() {
291 let g = star_graph(6);
292 assert_eq!(g.node_count(), 6);
293 assert_eq!(g.edge_count(), 5);
294 let ids = g.node_ids();
295 assert_eq!(g.degree(ids[0]), 5); }
297
298 #[test]
299 fn test_grid_graph() {
300 let g = grid_graph(3, 4);
301 assert_eq!(g.node_count(), 12);
302 assert_eq!(g.edge_count(), 17);
304 }
305
306 #[test]
307 fn test_binary_tree() {
308 let g = binary_tree(3);
309 assert_eq!(g.node_count(), 15);
311 assert_eq!(g.edge_count(), 14);
312 }
313
314 #[test]
315 fn test_petersen_graph() {
316 let g = petersen_graph();
317 assert_eq!(g.node_count(), 10);
318 assert_eq!(g.edge_count(), 15);
319 for nid in g.node_ids() {
321 assert_eq!(g.degree(nid), 3);
322 }
323 }
324
325 #[test]
326 fn test_complete_bipartite() {
327 let g = complete_bipartite(3, 4);
328 assert_eq!(g.node_count(), 7);
329 assert_eq!(g.edge_count(), 12); }
331
332 #[test]
333 fn test_erdos_renyi_bounds() {
334 let g = erdos_renyi(20, 0.5);
335 assert_eq!(g.node_count(), 20);
336 assert!(g.edge_count() > 0);
338 }
339
340 #[test]
341 fn test_watts_strogatz() {
342 let g = watts_strogatz(20, 4, 0.0);
343 assert_eq!(g.node_count(), 20);
344 assert!(g.edge_count() > 0);
346 }
347
348 #[test]
349 fn test_barabasi_albert() {
350 let g = barabasi_albert(20, 2);
351 assert_eq!(g.node_count(), 20);
352 assert!(g.edge_count() > 0);
353 }
354
355 #[test]
356 fn test_empty_generators() {
357 assert_eq!(complete_graph(0).node_count(), 0);
358 assert_eq!(cycle_graph(0).node_count(), 0);
359 assert_eq!(path_graph(0).node_count(), 0);
360 assert_eq!(star_graph(0).node_count(), 0);
361 assert_eq!(grid_graph(0, 5).node_count(), 0);
362 }
363}