1use crate::base::{DiGraph, EdgeWeight, Graph, IndexType, Node};
7use std::collections::HashSet;
8
9pub fn line_graph<N, E, Ix>(graph: &Graph<N, E, Ix>) -> Graph<(N, N), (), Ix>
21where
22 N: Node + Clone,
23 E: EdgeWeight + Clone,
24 Ix: IndexType,
25{
26 let mut line_graph = Graph::new();
27 let edges = graph.edges();
28
29 let edge_nodes: Vec<(N, N)> = edges
31 .iter()
32 .map(|e| (e.source.clone(), e.target.clone()))
33 .collect();
34
35 for edge_node in &edge_nodes {
37 line_graph.add_node(edge_node.clone());
38 }
39
40 for (i, edge1) in edge_nodes.iter().enumerate() {
42 for (_j, edge2) in edge_nodes.iter().enumerate().skip(i + 1) {
43 if edge1.0 == edge2.0 || edge1.0 == edge2.1 || edge1.1 == edge2.0 || edge1.1 == edge2.1
45 {
46 let _ = line_graph.add_edge(edge1.clone(), edge2.clone(), ());
48 }
49 }
50 }
51
52 line_graph
53}
54
55pub fn line_digraph<N, E, Ix>(digraph: &DiGraph<N, E, Ix>) -> DiGraph<(N, N), (), Ix>
60where
61 N: Node + Clone,
62 E: EdgeWeight + Clone,
63 Ix: IndexType,
64{
65 let mut line_digraph = DiGraph::new();
66 let edges = digraph.edges();
67
68 let edge_nodes: Vec<(N, N)> = edges
70 .iter()
71 .map(|e| (e.source.clone(), e.target.clone()))
72 .collect();
73
74 for edge_node in &edge_nodes {
76 line_digraph.add_node(edge_node.clone());
77 }
78
79 for edge1 in &edge_nodes {
81 for edge2 in &edge_nodes {
82 if edge1 != edge2 && edge1.1 == edge2.0 {
83 let _ = line_digraph.add_edge(edge1.clone(), edge2.clone(), ());
85 }
86 }
87 }
88
89 line_digraph
90}
91
92pub fn subgraph<N, E, Ix>(graph: &Graph<N, E, Ix>, nodes: &HashSet<N>) -> Graph<N, E, Ix>
101where
102 N: Node + Clone,
103 E: EdgeWeight + Clone,
104 Ix: IndexType,
105{
106 let mut sub = Graph::new();
107
108 for node in nodes {
110 if graph.has_node(node) {
111 sub.add_node(node.clone());
112 }
113 }
114
115 for edge in graph.edges() {
117 if nodes.contains(&edge.source) && nodes.contains(&edge.target) {
118 let _ = sub.add_edge(
119 edge.source.clone(),
120 edge.target.clone(),
121 edge.weight.clone(),
122 );
123 }
124 }
125
126 sub
127}
128
129pub fn subdigraph<N, E, Ix>(digraph: &DiGraph<N, E, Ix>, nodes: &HashSet<N>) -> DiGraph<N, E, Ix>
131where
132 N: Node + Clone,
133 E: EdgeWeight + Clone,
134 Ix: IndexType,
135{
136 let mut sub = DiGraph::new();
137
138 for node in nodes {
140 if digraph.has_node(node) {
141 sub.add_node(node.clone());
142 }
143 }
144
145 for edge in digraph.edges() {
147 if nodes.contains(&edge.source) && nodes.contains(&edge.target) {
148 let _ = sub.add_edge(
149 edge.source.clone(),
150 edge.target.clone(),
151 edge.weight.clone(),
152 );
153 }
154 }
155
156 sub
157}
158
159pub fn edge_subgraph<N, E, Ix>(graph: &Graph<N, E, Ix>, edges: &[(N, N)]) -> Graph<N, E, Ix>
170where
171 N: Node + Clone,
172 E: EdgeWeight + Clone,
173 Ix: IndexType,
174{
175 let mut sub = Graph::new();
176 let mut included_nodes = HashSet::new();
177
178 for (u, v) in edges {
180 included_nodes.insert(u.clone());
181 included_nodes.insert(v.clone());
182 }
183
184 for node in &included_nodes {
186 if graph.has_node(node) {
187 sub.add_node(node.clone());
188 }
189 }
190
191 for (u, v) in edges {
193 if graph.has_edge(u, v) {
194 if let Ok(weight) = graph.edge_weight(u, v) {
195 let _ = sub.add_edge(u.clone(), v.clone(), weight);
196 }
197 }
198 }
199
200 sub
201}
202
203pub fn cartesian_product<N1, N2, E1, E2, Ix>(
215 graph1: &Graph<N1, E1, Ix>,
216 graph2: &Graph<N2, E2, Ix>,
217) -> Graph<(N1, N2), (), Ix>
218where
219 N1: Node + Clone,
220 N2: Node + Clone,
221 E1: EdgeWeight,
222 E2: EdgeWeight,
223 Ix: IndexType,
224{
225 let mut product = Graph::new();
226
227 let nodes1: Vec<N1> = graph1.nodes().into_iter().cloned().collect();
228 let nodes2: Vec<N2> = graph2.nodes().into_iter().cloned().collect();
229
230 for n1 in &nodes1 {
232 for n2 in &nodes2 {
233 product.add_node((n1.clone(), n2.clone()));
234 }
235 }
236
237 for n1 in &nodes1 {
239 for n2 in &nodes2 {
240 if let Ok(neighbors2) = graph2.neighbors(n2) {
242 for m2 in neighbors2 {
243 if n2 != &m2 {
244 let _ = product.add_edge((n1.clone(), n2.clone()), (n1.clone(), m2), ());
246 }
247 }
248 }
249
250 if let Ok(neighbors1) = graph1.neighbors(n1) {
252 for m1 in neighbors1 {
253 if n1 != &m1 {
254 let _ = product.add_edge((n1.clone(), n2.clone()), (m1, n2.clone()), ());
256 }
257 }
258 }
259 }
260 }
261
262 product
263}
264
265pub fn tensor_product<N1, N2, E1, E2, Ix>(
270 graph1: &Graph<N1, E1, Ix>,
271 graph2: &Graph<N2, E2, Ix>,
272) -> Graph<(N1, N2), (), Ix>
273where
274 N1: Node + Clone,
275 N2: Node + Clone,
276 E1: EdgeWeight,
277 E2: EdgeWeight,
278 Ix: IndexType,
279{
280 let mut product = Graph::new();
281
282 let nodes1: Vec<N1> = graph1.nodes().into_iter().cloned().collect();
283 let nodes2: Vec<N2> = graph2.nodes().into_iter().cloned().collect();
284
285 for n1 in &nodes1 {
287 for n2 in &nodes2 {
288 product.add_node((n1.clone(), n2.clone()));
289 }
290 }
291
292 for n1 in &nodes1 {
294 for n2 in &nodes2 {
295 if let Ok(neighbors1) = graph1.neighbors(n1) {
296 if let Ok(neighbors2) = graph2.neighbors(n2) {
297 for m1 in neighbors1 {
298 for m2 in &neighbors2 {
299 if n1 != &m1 && n2 != m2 {
300 let _ = product.add_edge(
302 (n1.clone(), n2.clone()),
303 (m1.clone(), m2.clone()),
304 (),
305 );
306 }
307 }
308 }
309 }
310 }
311 }
312 }
313
314 product
315}
316
317pub fn complement<N, E, Ix>(graph: &Graph<N, E, Ix>) -> Graph<N, (), Ix>
322where
323 N: Node + Clone,
324 E: EdgeWeight,
325 Ix: IndexType,
326{
327 let mut comp = Graph::new();
328 let nodes: Vec<N> = graph.nodes().into_iter().cloned().collect();
329
330 for node in &nodes {
332 comp.add_node(node.clone());
333 }
334
335 for (i, u) in nodes.iter().enumerate() {
337 for v in nodes.iter().skip(i + 1) {
338 if !graph.has_edge(u, v) {
339 let _ = comp.add_edge(u.clone(), v.clone(), ());
340 }
341 }
342 }
343
344 comp
345}
346
347pub fn weight_filtered_subgraph<N, E, Ix>(
356 graph: &Graph<N, E, Ix>,
357 valid_weights: &HashSet<E>,
358) -> Graph<N, E, Ix>
359where
360 N: Node + Clone,
361 E: EdgeWeight + Clone + std::hash::Hash + Eq,
362 Ix: IndexType,
363{
364 let mut filtered = Graph::new();
365
366 for node in graph.nodes() {
368 filtered.add_node(node.clone());
369 }
370
371 for edge in graph.edges() {
373 if valid_weights.contains(&edge.weight) {
374 let _ = filtered.add_edge(
375 edge.source.clone(),
376 edge.target.clone(),
377 edge.weight.clone(),
378 );
379 }
380 }
381
382 filtered
383}
384
385#[cfg(test)]
386mod tests {
387 use super::*;
388 use crate::generators::create_graph;
389
390 #[test]
391 fn test_line_graph() {
392 let mut graph = create_graph::<&str, ()>();
393 graph.add_edge("A", "B", ()).unwrap();
394 graph.add_edge("B", "C", ()).unwrap();
395 graph.add_edge("C", "A", ()).unwrap();
396
397 let line = line_graph(&graph);
398
399 assert_eq!(line.node_count(), 3);
401
402 assert_eq!(line.edge_count(), 3);
404 }
405
406 #[test]
407 fn test_subgraph() {
408 let mut graph = create_graph::<i32, ()>();
409 graph.add_edge(1, 2, ()).unwrap();
410 graph.add_edge(2, 3, ()).unwrap();
411 graph.add_edge(3, 4, ()).unwrap();
412 graph.add_edge(1, 4, ()).unwrap();
413
414 let mut nodes = HashSet::new();
415 nodes.insert(1);
416 nodes.insert(2);
417 nodes.insert(3);
418
419 let sub = subgraph(&graph, &nodes);
420
421 assert_eq!(sub.node_count(), 3);
423
424 assert_eq!(sub.edge_count(), 2);
426 assert!(sub.has_edge(&1, &2));
427 assert!(sub.has_edge(&2, &3));
428 assert!(!sub.has_edge(&3, &4)); }
430
431 #[test]
432 fn test_edge_subgraph() {
433 let mut graph = create_graph::<i32, ()>();
434 graph.add_edge(1, 2, ()).unwrap();
435 graph.add_edge(2, 3, ()).unwrap();
436 graph.add_edge(3, 4, ()).unwrap();
437 graph.add_edge(1, 4, ()).unwrap();
438
439 let edges = vec![(1, 2), (3, 4)];
440 let sub = edge_subgraph(&graph, &edges);
441
442 assert_eq!(sub.node_count(), 4);
444
445 assert_eq!(sub.edge_count(), 2);
447 assert!(sub.has_edge(&1, &2));
448 assert!(sub.has_edge(&3, &4));
449 assert!(!sub.has_edge(&2, &3));
450 assert!(!sub.has_edge(&1, &4));
451 }
452
453 #[test]
454 fn test_cartesian_product() {
455 let mut k2 = create_graph::<i32, ()>();
457 k2.add_edge(1, 2, ()).unwrap();
458
459 let mut p2 = create_graph::<char, ()>();
461 p2.add_edge('A', 'B', ()).unwrap();
462
463 let product = cartesian_product(&k2, &p2);
464
465 assert_eq!(product.node_count(), 4);
467
468 assert_eq!(product.edge_count(), 8);
471 }
472
473 #[test]
474 fn test_tensor_product() {
475 let mut k2_1 = create_graph::<i32, ()>();
477 k2_1.add_edge(1, 2, ()).unwrap();
478
479 let mut k2_2 = create_graph::<char, ()>();
481 k2_2.add_edge('A', 'B', ()).unwrap();
482
483 let product = tensor_product(&k2_1, &k2_2);
484
485 assert_eq!(product.node_count(), 4);
487
488 assert_eq!(product.edge_count(), 4);
491 }
492
493 #[test]
494 fn test_complement() {
495 let mut graph = create_graph::<i32, ()>();
496 graph.add_edge(1, 2, ()).unwrap();
497 graph.add_edge(2, 3, ()).unwrap();
498
499 let comp = complement(&graph);
500
501 assert_eq!(comp.node_count(), 3);
503
504 assert_eq!(comp.edge_count(), 1);
506 assert!(comp.has_edge(&1, &3));
507 assert!(!comp.has_edge(&1, &2));
508 assert!(!comp.has_edge(&2, &3));
509 }
510
511 #[test]
512 fn test_weight_filtered_subgraph() {
513 let mut graph = create_graph::<i32, i32>();
514 graph.add_edge(1, 2, 10).unwrap();
515 graph.add_edge(2, 3, 20).unwrap();
516 graph.add_edge(3, 4, 10).unwrap();
517
518 let mut valid_weights = HashSet::new();
519 valid_weights.insert(10);
520
521 let filtered = weight_filtered_subgraph(&graph, &valid_weights);
522
523 assert_eq!(filtered.node_count(), 4);
525
526 assert_eq!(filtered.edge_count(), 2);
528 assert!(filtered.has_edge(&1, &2));
529 assert!(filtered.has_edge(&3, &4));
530 assert!(!filtered.has_edge(&2, &3)); }
532}