1use crate::base::{DiGraph, EdgeWeight, Graph, IndexType, Node};
7use std::collections::HashSet;
8
9#[allow(dead_code)]
21pub fn line_graph<N, E, Ix>(graph: &Graph<N, E, Ix>) -> Graph<(N, N), (), Ix>
22where
23 N: Node + Clone + std::fmt::Debug,
24 E: EdgeWeight + Clone,
25 Ix: IndexType,
26{
27 let mut line_graph = Graph::new();
28 let edges = graph.edges();
29
30 let edge_nodes: Vec<(N, N)> = edges
32 .iter()
33 .map(|e| (e.source.clone(), e.target.clone()))
34 .collect();
35
36 for edge_node in &edge_nodes {
38 line_graph.add_node(edge_node.clone());
39 }
40
41 for (i, edge1) in edge_nodes.iter().enumerate() {
43 for (_j, edge2) in edge_nodes.iter().enumerate().skip(i + 1) {
44 if edge1.0 == edge2.0 || edge1.0 == edge2.1 || edge1.1 == edge2.0 || edge1.1 == edge2.1
46 {
47 let _ = line_graph.add_edge(edge1.clone(), edge2.clone(), ());
49 }
50 }
51 }
52
53 line_graph
54}
55
56#[allow(dead_code)]
61pub fn line_digraph<N, E, Ix>(digraph: &DiGraph<N, E, Ix>) -> DiGraph<(N, N), (), Ix>
62where
63 N: Node + Clone + std::fmt::Debug,
64 E: EdgeWeight + Clone,
65 Ix: IndexType,
66{
67 let mut line_digraph = DiGraph::new();
68 let edges = digraph.edges();
69
70 let edge_nodes: Vec<(N, N)> = edges
72 .iter()
73 .map(|e| (e.source.clone(), e.target.clone()))
74 .collect();
75
76 for edge_node in &edge_nodes {
78 line_digraph.add_node(edge_node.clone());
79 }
80
81 for edge1 in &edge_nodes {
83 for edge2 in &edge_nodes {
84 if edge1 != edge2 && edge1.1 == edge2.0 {
85 let _ = line_digraph.add_edge(edge1.clone(), edge2.clone(), ());
87 }
88 }
89 }
90
91 line_digraph
92}
93
94#[allow(dead_code)]
103pub fn subgraph<N, E, Ix>(graph: &Graph<N, E, Ix>, nodes: &HashSet<N>) -> Graph<N, E, Ix>
104where
105 N: Node + Clone + std::fmt::Debug,
106 E: EdgeWeight + Clone,
107 Ix: IndexType,
108{
109 let mut sub = Graph::new();
110
111 for node in nodes {
113 if graph.has_node(node) {
114 sub.add_node(node.clone());
115 }
116 }
117
118 for edge in graph.edges() {
120 if nodes.contains(&edge.source) && nodes.contains(&edge.target) {
121 let _ = sub.add_edge(
122 edge.source.clone(),
123 edge.target.clone(),
124 edge.weight.clone(),
125 );
126 }
127 }
128
129 sub
130}
131
132#[allow(dead_code)]
134pub fn subdigraph<N, E, Ix>(digraph: &DiGraph<N, E, Ix>, nodes: &HashSet<N>) -> DiGraph<N, E, Ix>
135where
136 N: Node + Clone + std::fmt::Debug,
137 E: EdgeWeight + Clone,
138 Ix: IndexType,
139{
140 let mut sub = DiGraph::new();
141
142 for node in nodes {
144 if digraph.has_node(node) {
145 sub.add_node(node.clone());
146 }
147 }
148
149 for edge in digraph.edges() {
151 if nodes.contains(&edge.source) && nodes.contains(&edge.target) {
152 let _ = sub.add_edge(
153 edge.source.clone(),
154 edge.target.clone(),
155 edge.weight.clone(),
156 );
157 }
158 }
159
160 sub
161}
162
163#[allow(dead_code)]
174pub fn edge_subgraph<N, E, Ix>(graph: &Graph<N, E, Ix>, edges: &[(N, N)]) -> Graph<N, E, Ix>
175where
176 N: Node + Clone + std::fmt::Debug,
177 E: EdgeWeight + Clone,
178 Ix: IndexType,
179{
180 let mut sub = Graph::new();
181 let mut included_nodes = HashSet::new();
182
183 for (u, v) in edges {
185 included_nodes.insert(u.clone());
186 included_nodes.insert(v.clone());
187 }
188
189 for node in &included_nodes {
191 if graph.has_node(node) {
192 sub.add_node(node.clone());
193 }
194 }
195
196 for (u, v) in edges {
198 if graph.has_edge(u, v) {
199 if let Ok(weight) = graph.edge_weight(u, v) {
200 let _ = sub.add_edge(u.clone(), v.clone(), weight);
201 }
202 }
203 }
204
205 sub
206}
207
208#[allow(dead_code)]
220pub fn cartesian_product<N1, N2, E1, E2, Ix>(
221 graph1: &Graph<N1, E1, Ix>,
222 graph2: &Graph<N2, E2, Ix>,
223) -> Graph<(N1, N2), (), Ix>
224where
225 N1: Node + Clone + std::fmt::Debug,
226 N2: Node + Clone + std::fmt::Debug,
227 E1: EdgeWeight,
228 E2: EdgeWeight,
229 Ix: IndexType,
230{
231 let mut product = Graph::new();
232
233 let nodes1: Vec<N1> = graph1.nodes().into_iter().cloned().collect();
234 let nodes2: Vec<N2> = graph2.nodes().into_iter().cloned().collect();
235
236 for n1 in &nodes1 {
238 for n2 in &nodes2 {
239 product.add_node((n1.clone(), n2.clone()));
240 }
241 }
242
243 for n1 in &nodes1 {
245 for n2 in &nodes2 {
246 if let Ok(neighbors2) = graph2.neighbors(n2) {
248 for m2 in neighbors2 {
249 if n2 != &m2 {
250 let _ = product.add_edge((n1.clone(), n2.clone()), (n1.clone(), m2), ());
252 }
253 }
254 }
255
256 if let Ok(neighbors1) = graph1.neighbors(n1) {
258 for m1 in neighbors1 {
259 if n1 != &m1 {
260 let _ = product.add_edge((n1.clone(), n2.clone()), (m1, n2.clone()), ());
262 }
263 }
264 }
265 }
266 }
267
268 product
269}
270
271#[allow(dead_code)]
276pub fn tensor_product<N1, N2, E1, E2, Ix>(
277 graph1: &Graph<N1, E1, Ix>,
278 graph2: &Graph<N2, E2, Ix>,
279) -> Graph<(N1, N2), (), Ix>
280where
281 N1: Node + Clone + std::fmt::Debug,
282 N2: Node + Clone + std::fmt::Debug,
283 E1: EdgeWeight,
284 E2: EdgeWeight,
285 Ix: IndexType,
286{
287 let mut product = Graph::new();
288
289 let nodes1: Vec<N1> = graph1.nodes().into_iter().cloned().collect();
290 let nodes2: Vec<N2> = graph2.nodes().into_iter().cloned().collect();
291
292 for n1 in &nodes1 {
294 for n2 in &nodes2 {
295 product.add_node((n1.clone(), n2.clone()));
296 }
297 }
298
299 for n1 in &nodes1 {
301 for n2 in &nodes2 {
302 if let Ok(neighbors1) = graph1.neighbors(n1) {
303 if let Ok(neighbors2) = graph2.neighbors(n2) {
304 for m1 in neighbors1 {
305 for m2 in &neighbors2 {
306 if n1 != &m1 && n2 != m2 {
307 let _ = product.add_edge(
309 (n1.clone(), n2.clone()),
310 (m1.clone(), m2.clone()),
311 (),
312 );
313 }
314 }
315 }
316 }
317 }
318 }
319 }
320
321 product
322}
323
324#[allow(dead_code)]
329pub fn complement<N, E, Ix>(graph: &Graph<N, E, Ix>) -> Graph<N, (), Ix>
330where
331 N: Node + Clone + std::fmt::Debug,
332 E: EdgeWeight,
333 Ix: IndexType,
334{
335 let mut comp = Graph::new();
336 let nodes: Vec<N> = graph.nodes().into_iter().cloned().collect();
337
338 for node in &nodes {
340 comp.add_node(node.clone());
341 }
342
343 for (i, u) in nodes.iter().enumerate() {
345 for v in nodes.iter().skip(i + 1) {
346 if !graph.has_edge(u, v) {
347 let _ = comp.add_edge(u.clone(), v.clone(), ());
348 }
349 }
350 }
351
352 comp
353}
354
355#[allow(dead_code)]
364pub fn weight_filtered_subgraph<N, E, Ix>(
365 graph: &Graph<N, E, Ix>,
366 valid_weights: &HashSet<E>,
367) -> Graph<N, E, Ix>
368where
369 N: Node + Clone + std::fmt::Debug,
370 E: EdgeWeight + Clone + std::hash::Hash + Eq,
371 Ix: IndexType,
372{
373 let mut filtered = Graph::new();
374
375 for node in graph.nodes() {
377 filtered.add_node(node.clone());
378 }
379
380 for edge in graph.edges() {
382 if valid_weights.contains(&edge.weight) {
383 let _ = filtered.add_edge(
384 edge.source.clone(),
385 edge.target.clone(),
386 edge.weight.clone(),
387 );
388 }
389 }
390
391 filtered
392}
393
394#[cfg(test)]
395mod tests {
396 use super::*;
397 use crate::generators::create_graph;
398
399 #[test]
400 fn test_line_graph() {
401 let mut graph = create_graph::<&str, ()>();
402 graph.add_edge("A", "B", ()).unwrap();
403 graph.add_edge("B", "C", ()).unwrap();
404 graph.add_edge("C", "A", ()).unwrap();
405
406 let line = line_graph(&graph);
407
408 assert_eq!(line.node_count(), 3);
410
411 assert_eq!(line.edge_count(), 3);
413 }
414
415 #[test]
416 fn test_subgraph() {
417 let mut graph = create_graph::<i32, ()>();
418 graph.add_edge(1, 2, ()).unwrap();
419 graph.add_edge(2, 3, ()).unwrap();
420 graph.add_edge(3, 4, ()).unwrap();
421 graph.add_edge(1, 4, ()).unwrap();
422
423 let mut nodes = HashSet::new();
424 nodes.insert(1);
425 nodes.insert(2);
426 nodes.insert(3);
427
428 let sub = subgraph(&graph, &nodes);
429
430 assert_eq!(sub.node_count(), 3);
432
433 assert_eq!(sub.edge_count(), 2);
435 assert!(sub.has_edge(&1, &2));
436 assert!(sub.has_edge(&2, &3));
437 assert!(!sub.has_edge(&3, &4)); }
439
440 #[test]
441 fn test_edge_subgraph() {
442 let mut graph = create_graph::<i32, ()>();
443 graph.add_edge(1, 2, ()).unwrap();
444 graph.add_edge(2, 3, ()).unwrap();
445 graph.add_edge(3, 4, ()).unwrap();
446 graph.add_edge(1, 4, ()).unwrap();
447
448 let edges = vec![(1, 2), (3, 4)];
449 let sub = edge_subgraph(&graph, &edges);
450
451 assert_eq!(sub.node_count(), 4);
453
454 assert_eq!(sub.edge_count(), 2);
456 assert!(sub.has_edge(&1, &2));
457 assert!(sub.has_edge(&3, &4));
458 assert!(!sub.has_edge(&2, &3));
459 assert!(!sub.has_edge(&1, &4));
460 }
461
462 #[test]
463 fn test_cartesian_product() {
464 let mut k2 = create_graph::<i32, ()>();
466 k2.add_edge(1, 2, ()).unwrap();
467
468 let mut p2 = create_graph::<char, ()>();
470 p2.add_edge('A', 'B', ()).unwrap();
471
472 let product = cartesian_product(&k2, &p2);
473
474 assert_eq!(product.node_count(), 4);
476
477 assert_eq!(product.edge_count(), 8);
480 }
481
482 #[test]
483 fn test_tensor_product() {
484 let mut k2_1 = create_graph::<i32, ()>();
486 k2_1.add_edge(1, 2, ()).unwrap();
487
488 let mut k2_2 = create_graph::<char, ()>();
490 k2_2.add_edge('A', 'B', ()).unwrap();
491
492 let product = tensor_product(&k2_1, &k2_2);
493
494 assert_eq!(product.node_count(), 4);
496
497 assert_eq!(product.edge_count(), 4);
500 }
501
502 #[test]
503 fn test_complement() {
504 let mut graph = create_graph::<i32, ()>();
505 graph.add_edge(1, 2, ()).unwrap();
506 graph.add_edge(2, 3, ()).unwrap();
507
508 let comp = complement(&graph);
509
510 assert_eq!(comp.node_count(), 3);
512
513 assert_eq!(comp.edge_count(), 1);
515 assert!(comp.has_edge(&1, &3));
516 assert!(!comp.has_edge(&1, &2));
517 assert!(!comp.has_edge(&2, &3));
518 }
519
520 #[test]
521 fn test_weight_filtered_subgraph() {
522 let mut graph = create_graph::<i32, i32>();
523 graph.add_edge(1, 2, 10).unwrap();
524 graph.add_edge(2, 3, 20).unwrap();
525 graph.add_edge(3, 4, 10).unwrap();
526
527 let mut valid_weights = HashSet::new();
528 valid_weights.insert(10);
529
530 let filtered = weight_filtered_subgraph(&graph, &valid_weights);
531
532 assert_eq!(filtered.node_count(), 4);
534
535 assert_eq!(filtered.edge_count(), 2);
537 assert!(filtered.has_edge(&1, &2));
538 assert!(filtered.has_edge(&3, &4));
539 assert!(!filtered.has_edge(&2, &3)); }
541}