diff --git a/src/main.rs b/src/main.rs index eb3ac1678a4af91bc0c62cf5fca22ff8f1e5002f..dfa92baac002dea5a93fec027b0f7066abd7e867 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,104 @@ mod undirected_graph; +use std::collections::HashMap; +use std::env; +use std::process; use undirected_graph::UndirectedGraph; fn main() { - let g: UndirectedGraph = UndirectedGraph::wheel_graph(5); - println!("g = {:?}", g); - println!("g.to_nauty() = {:?}", g.to_nauty()); - println!("UndirectedGraph::from_nauty(&g.to_nauty()) = {:?}", UndirectedGraph::from_nauty(&g.to_nauty())); - let (_sign, normal_g, orbits,_) = g.normal_form(false); - println!("normal_g = {:?}", normal_g); - println!("normal_g.expanding_differential(&orbits) = {:?}", normal_g.expanding_differential(&orbits)); - println!("normal_g.contractions() = {:?}", normal_g.contractions(&vec![0_usize])); - let h: UndirectedGraph = UndirectedGraph::new(7,vec![(0, 1), (0, 2), (0, 6), (1, 4), (1, 6), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6), (4, 5)]); - let edge_orbits_h: Vec<usize> = vec![0, 0, 2, 3, 4, 3, 4, 10, 7, 7, 9]; - println!("normal_h.contractions(&edge_orbits_h) = {:?}", h.contractions(&edge_orbits_h)); - let triangle: UndirectedGraph = UndirectedGraph::new(3, vec![(0,1), (1,2), (0,2)]); - println!("triangle.normal_form() = {:?}", triangle.normal_form(true)); - println!("triangle.contractions() = {:?}", triangle.contractions(&vec![0_usize])); + let args: Vec<String> = env::args().collect(); + + if args.len() != 2 { + eprintln!("Usage: {} <number-of-spokes>", args[0]); + process::exit(1); + } + + let num_spokes_maybe: Result<usize, std::num::ParseIntError> = args[1].parse::<usize>(); + if num_spokes_maybe.is_err() { + eprintln!("Error parsing the first argument as number-of-spokes."); + process::exit(1); + } + let num_spokes: usize = num_spokes_maybe.unwrap(); + + if num_spokes < 2 { + eprintln!("A wheel graph without tadpoles must have at least two spokes."); + process::exit(1); + } + + let mut cocycle_graphs: Vec<UndirectedGraph> = vec![]; + let mut cocycle_graph_index: HashMap<UndirectedGraph, usize> = HashMap::new(); + let mut cocycle_graph_vertex_orbits: Vec<HashMap<usize, usize>> = vec![]; + + let mut cocycle_differential_graphs: Vec<UndirectedGraph> = vec![]; + let mut cocycle_differential_graph_index: HashMap<UndirectedGraph, usize> = HashMap::new(); + let mut cocycle_differential_graph_edge_orbits: Vec<Vec<usize>> = vec![]; + + // NOTE: Start with the normal form of the wheel graph. + let wheel_graph: UndirectedGraph = UndirectedGraph::wheel_graph(num_spokes); + let (wheel_graph_sign, wheel_graph_normal, wheel_graph_vertex_orbits, _) = + wheel_graph.normal_form(false); + if wheel_graph_sign == 0 { + eprintln!("The {}-wheel graph has an automorphism that induces an odd permutation on edges, so it is equal to zero in the graph complex.", num_spokes); + process::exit(1); + } + cocycle_graphs.push(wheel_graph_normal.clone()); + cocycle_graph_index.insert(wheel_graph_normal.clone(), 0); + cocycle_graph_vertex_orbits.push(wheel_graph_vertex_orbits); + + println!("? ? M"); + let mut g_idx: usize = 0; + loop { + // dbg!(&g_idx); + let dg_data: HashMap<UndirectedGraph, (i64, Vec<usize>)> = + cocycle_graphs[g_idx].expanding_differential(&cocycle_graph_vertex_orbits[g_idx]); + + for (dg, (c, dg_edge_orbits)) in dg_data { + // eprintln!("{:?}", dg); + let dg_idx: usize = if let Some(&idx) = cocycle_differential_graph_index.get(&dg) { + // eprintln!("old graph in differential: {}", idx); + idx + } else { + let idx: usize = cocycle_differential_graphs.len(); + // eprintln!("new graph in differential: {}", idx); + cocycle_differential_graphs.push(dg.clone()); + cocycle_differential_graph_edge_orbits.push(dg_edge_orbits.clone()); + cocycle_differential_graph_index.insert(dg.clone(), idx); + idx + }; + // TODO: Make the output lexicographically ordered? Strictly speaking this is not the SMS format right now. + println!("{} {} {}", dg_idx + 1, g_idx + 1, c); + + let cg_data: HashMap<UndirectedGraph, HashMap<usize, usize>> = + dg.contractions(&dg_edge_orbits); + for (cg, cg_vertex_orbits) in cg_data { + // eprintln!("{:?}", cg); + if !cocycle_graph_index.contains_key(&cg) { + let idx: usize = cocycle_graphs.len(); + // eprintln!("new graph in cocycle: {}", idx); + cocycle_graphs.push(cg.clone()); + cocycle_graph_vertex_orbits.push(cg_vertex_orbits); + cocycle_graph_index.insert(cg.clone(), idx); + } + } + } + + g_idx += 1; + if g_idx >= cocycle_graphs.len() { + break; + } + } + println!("0 0 0"); + println!("# Move this line to the top:"); + println!( + "{} {} M", + cocycle_differential_graphs.len(), + cocycle_graphs.len() + ); + + eprintln!( + "Matrix size: {} x {}", + cocycle_differential_graphs.len(), + cocycle_graphs.len() + ); + + // TODO: Also output the ordered bases of graphs. }