1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! # Graph Canon
//!
//! This crate provides a graph canonization algorithm for directed and undirected graphs
//! by calling the C library [nauty](https://pallini.di.uniroma1.it/) via [nauty-Traces-sys](https://crates.io/crates/nauty-Traces-sys)
//!
//! This crate is built on top of the [petgraph](https://crates.io/crates/petgraph) crate, but is
//! considerably faster than an existing crate [nauty-pet](https://crates.io/crates/nauty-pet) that
//! uses similar techniques because it is **very** barebones.
//!
//! ## Example
//!
//! ### Hashable Labels
//! If you are just looking to create a hashable object to determine isomorphism
//! then it is simples to use the `CanonLabeling` struct.
//!
//! This can be created from a `Graph` object directly.
//!
//! #### Directed Graphs
//! ```
//! use petgraph::{Directed, Graph};
//! use graph_canon::CanonLabeling;
//!
//! let e1 = vec![(0, 1), (0, 2), (1, 2)]; // Isomorphic
//! let e2 = vec![(1, 0), (1, 2), (0, 2)]; // Isomorphic
//! let e3 = vec![(1, 0), (1, 2), (2, 1)]; // Non-Isomorphic
//!
//! let g1 = Graph::<(), (), Directed>::from_edges(&e1);
//! let g2 = Graph::<(), (), Directed>::from_edges(&e2);
//! let g3 = Graph::<(), (), Directed>::from_edges(&e3);
//!
//! let l1 = CanonLabeling::new(&g1);
//! let l2 = CanonLabeling::new(&g2);
//! let l3 = CanonLabeling::new(&g3);
//!
//! assert_eq!(l1, l2);
//! assert_ne!(l1, l3);
//! ```
//!
//! #### Undirected Graphs
//! ```
//! use petgraph::{Undirected, Graph};
//! use graph_canon::CanonLabeling;
//!
//! let e1 = vec![(0, 1), (0, 2), (1, 2)]; // Isomorphic
//! let e2 = vec![(1, 0), (1, 2), (0, 2)]; // Isomorphic
//! let e3 = vec![(1, 0), (1, 2)];         // Non-Isomorphic
//!
//! let g1 = Graph::<(), (), Undirected>::from_edges(&e1);
//! let g2 = Graph::<(), (), Undirected>::from_edges(&e2);
//! let g3 = Graph::<(), (), Undirected>::from_edges(&e3);
//!
//! let l1 = CanonLabeling::new(&g1);
//! let l2 = CanonLabeling::new(&g2);
//! let l3 = CanonLabeling::new(&g3);
//!
//! assert_eq!(l1, l2);
//! assert_ne!(l1, l3);
//! ```
//!
//! ### Recovering the Canonical `Graph`
//!
//! If instead you are interested in working with the graph itself,
//! you can use the `canonize` function to return a new `Graph` object
//!
//! #### Directed Graphs
//! ```
//! use petgraph::{Directed, Graph};
//! use graph_canon::canonize;
//!
//! let edges = vec![(0, 1), (0, 2), (1, 2)];
//! let graph = Graph::<(), (), Directed>::from_edges(&edges);
//! let canon = canonize(&graph);
//! assert_eq!(canon.edge_count(), 3);
//! ```
//!
//! #### Undirected Graphs
//! ```
//! use petgraph::{Undirected, Graph};
//! use graph_canon::canonize;
//!
//! let edges = vec![(0, 1), (0, 2), (1, 2)];
//! let graph = Graph::<(), (), Undirected>::from_edges(&edges);
//! let canon = canonize(&graph);
//!
//! // There are currently twice as many edges but may change in the future
//! assert_eq!(canon.edge_count(), 6);
//! ```

pub mod canon;
pub mod dense;
pub use canon::{canonize, CanonLabeling};
pub use dense::DenseGraph;