diff --git a/src/expand_n_contract.rs b/src/expand_n_contract.rs index 7241a11edead3cf49c15d257c07302a3fe744d80..02b18ed59354c0ff114f0745ac917fb21827bfde 100644 --- a/src/expand_n_contract.rs +++ b/src/expand_n_contract.rs @@ -1,8 +1,11 @@ +//! Implementation of expansion-contraction using three text files. + use crate::undirected_graph::UndirectedGraph; use std::collections::HashMap; use std::fs::File; use std::io::{Seek, Write}; +/// Performs expansion-contraction starting from the wheel with the given number of spokes. pub fn expand_n_contract( num_spokes: usize, cocycle_graphs_filename: &String, diff --git a/src/expand_n_contract_sqlite.rs b/src/expand_n_contract_sqlite.rs index 99e2395f18188e0854f5572eb620b872a26de96e..5113106680cb13ef3d9974c9d11580902921a245 100644 --- a/src/expand_n_contract_sqlite.rs +++ b/src/expand_n_contract_sqlite.rs @@ -1,3 +1,5 @@ +//! Implementation of expansion-contraction using an SQLite database. + use crate::undirected_graph::UndirectedGraph; use rusqlite::{params, types::FromSql, Connection, ToSql}; @@ -14,6 +16,7 @@ impl FromSql for UndirectedGraph { } // TODO: Store orbits (or orbit representatives) more efficiently. +#[doc(hidden)] struct Orbits { orbits: Vec<usize>, } @@ -33,6 +36,7 @@ impl FromSql for Orbits { } } +#[doc(hidden)] fn create_database(conn: &Connection) -> Result<(), rusqlite::Error> { // NOTE: We don't use AUTOINCREMENT, because we use INSERT statements that can // fail due to uniqueness constraints, and we want our id's to increment by @@ -70,6 +74,7 @@ fn create_database(conn: &Connection) -> Result<(), rusqlite::Error> { Ok(()) } +/// Performs expansion-contraction starting from the wheel with the given number of spokes. pub fn expand_n_contract( num_spokes: usize, database_filename: &String, diff --git a/src/main.rs b/src/main.rs index 1faa8acafbd367b6a393c1771ef15137ac959ca6..e7ea172874e452a956f29f21dc931f570feec164 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,12 @@ +//! Implementation of an expansion-contraction algorithm to find wheel cohomology classes in the graph complex. + mod expand_n_contract; mod expand_n_contract_sqlite; mod undirected_graph; use std::env; use std::process; +/// Parses and checks command line arguments; runs the expansion-contraction algorithm. fn main() -> std::io::Result<()> { let args: Vec<String> = env::args().collect(); let num_args: usize = args.len(); diff --git a/src/undirected_graph.rs b/src/undirected_graph.rs index 704ad50aba843dbcf04123e7dff2738a24d58099..8fdb9808caad96972182a6d49120a3c084adff61 100644 --- a/src/undirected_graph.rs +++ b/src/undirected_graph.rs @@ -1,16 +1,25 @@ +//! Implementation of undirected graphs using the nauty library. + use std::collections::{HashMap, HashSet}; use union_find::{QuickUnionUf, UnionByRank, UnionFind}; // NOTE: Duplicating num_vertices and num_edges in each graph is wasteful. // TODO: Better to have a data structure for a "homogeneous" list/vector of graphs. +/// An undirected graph. +/// +/// A simple undirected graph on vertex set {0, ..., n - 1} where n ≤ 64, using nauty's encoding. #[derive(Debug, Eq, Hash, PartialEq, Clone)] pub struct UndirectedGraph { + /// The number of vertices in the graph. num_vertices: usize, + /// The number of edges in the graph. num_edges: usize, + /// The nauty encoding of the graph. nauty_graph: Vec<u64>, } +#[doc(hidden)] struct EdgeOrbitData { graph: UndirectedGraph, graph_is_odd: bool, @@ -48,9 +57,11 @@ impl std::fmt::Display for UndirectedGraph { impl UndirectedGraph { thread_local! { + #[doc(hidden)] static EDGE_ORBIT_DATA: std::cell::RefCell<EdgeOrbitData> = std::cell::RefCell::new(EdgeOrbitData::new()); } + /// Returns the undirected graph with a given number vertices and a given list of edges. pub fn new(num_vertices: usize, edges: Vec<(usize, usize)>) -> Self { let mut edges_seen: HashSet<(usize, usize)> = HashSet::new(); for (a, b) in &edges { @@ -75,6 +86,7 @@ impl UndirectedGraph { } } + /// Returns the undirected wheel graph with a given number of spokes. pub fn wheel_graph(num_spokes: usize) -> UndirectedGraph { let mut wheel_edges: Vec<(usize, usize)> = (0..num_spokes).map(|i: usize| (0, i + 1)).collect(); @@ -83,6 +95,7 @@ impl UndirectedGraph { UndirectedGraph::new(num_spokes + 1, wheel_edges) } + /// Returns an encoding of the undirected graph as a vector of bytes. pub fn into_bytes(&self) -> Vec<u8> { let mut encoding: Vec<u64> = self.nauty_graph.clone(); encoding.push(self.num_vertices as u64); @@ -90,6 +103,7 @@ impl UndirectedGraph { unsafe { encoding.align_to::<u8>().1.to_vec() } } + /// Returns the undirected graph represented by the given byte encoding. pub fn from_ne_bytes(bytes: &[u8]) -> UndirectedGraph { let mut encoding: Vec<u64> = unsafe { bytes.align_to::<u64>().1.to_vec() }; let num_edges: usize = encoding.pop().unwrap() as usize; @@ -101,6 +115,7 @@ impl UndirectedGraph { } } + /// Returns the graph6 encoding of the undirected graph. pub fn to_graph6(&self) -> String { assert!(self.num_vertices <= 62); let mut graph6: Vec<u8> = vec![]; @@ -128,6 +143,7 @@ impl UndirectedGraph { unsafe { String::from_utf8_unchecked(graph6) } } + /// Returns the undirected graph represented by the given graph6 encoding. pub fn from_graph6(graph6: String) -> UndirectedGraph { let num_vertices: usize = *graph6.as_bytes().first().unwrap() as usize - 63; let mut nauty_graph: Vec<u64> = vec![0; num_vertices]; @@ -156,6 +172,7 @@ impl UndirectedGraph { } } + /// Returns the edge permutation induced by the given isomorphism of graphs with lexicographically ordered edges. fn induced_edge_permutation( g: &UndirectedGraph, h: &UndirectedGraph, @@ -197,6 +214,7 @@ impl UndirectedGraph { perm } + /// Returns the sign of the given permutation. fn permutation_sign(mut permutation: Vec<i32>) -> i32 { let mut sign: i32 = 1; for i in 0..(permutation.len() as i32) { @@ -214,6 +232,7 @@ impl UndirectedGraph { sign } + #[doc(hidden)] #[no_mangle] extern "C" fn process_nauty_automorphism( _count: i32, @@ -259,6 +278,7 @@ impl UndirectedGraph { } } + /// Replaces the undirected graph by its normal form, and returns the sign that relates the original graph to its normal form, as well as the vertex orbits or edge orbits. pub fn normal_form(&mut self, compute_edge_orbits: bool) -> (i32, Vec<usize>) { let mut options: nauty_Traces_sys::optionblk = nauty_Traces_sys::optionblk { getcanon: nauty_Traces_sys::TRUE, @@ -345,6 +365,7 @@ impl UndirectedGraph { } } + /// Inserts an edge into the given vertex of the undirected graph, and re-attaches the incoming edges in all possible ways that do not produce leaves. fn expand_vertex(&self, &position: &usize) -> Vec<(i64, UndirectedGraph)> { let mut expansion: Vec<(i64, UndirectedGraph)> = vec![]; @@ -478,6 +499,7 @@ impl UndirectedGraph { expansion } + /// Returns the expanding differential (the coefficients, graphs, and edge orbits) of the given undirected graph with the given vertex orbits. pub fn expanding_differential( &self, orbits: &[usize], @@ -518,6 +540,7 @@ impl UndirectedGraph { diff } + /// Returns the graphs (and their vertex orbits) obtained by contracting one edge in the undirected graph. pub fn contractions(&self, edge_orbits: &Vec<usize>) -> Vec<(UndirectedGraph, Vec<usize>)> { let mut contractions: Vec<(UndirectedGraph, Vec<usize>)> = vec![]; let mut graphs_seen: HashSet<UndirectedGraph> = HashSet::new();