Nauty and Bliss: Graph Canonical Labeling Algorithms and Their Role in Chemical Molecule Isomorphism Detection Introduction
Introduction
At first glance, the question "Are these two molecules the same?" seems trivial. A trained chemist can often tell at a glance. But for a computer processing millions of molecules in a chemical database, this question — known as graph isomorphism — is one of the most fundamental and computationally demanding problems in cheminformatics.
Two molecules may be drawn differently, have their atoms numbered differently, or be represented in entirely different file formats, yet they are chemically identical. To determine this algorithmically, we need robust and efficient methods for testing whether two molecular graphs are isomorphic.
This is where Nauty and Bliss come in — two of the most powerful and widely used algorithms for graph canonical labeling and graph isomorphism testing. In this post, I will explain what these algorithms do, how they work, and why they are indispensable tools in computational chemistry.
1. The Graph Isomorphism Problem
1.1 Definition
Two graphs \(G_1 = (V_1, E_1)\) and \(G_2 = (V_2, E_2)\) are isomorphic if there exists a bijection \(f: V_1 \rightarrow V_2\) such that \((u, v) \in E_1\) if and only if \((f(u), f(v)) \in E_2\).
In plain language: two graphs are isomorphic if one can be transformed into the other by relabeling vertices. The structure (connectivity) is identical; only the labels differ.
1.2 Computational Complexity
The graph isomorphism problem occupies a peculiar position in complexity theory:
- It is in NP (a solution can be verified in polynomial time).
- It is not known to be NP-complete.
- It is not known to be in P (solvable in polynomial time) for general graphs.
- László Babai showed in 2015 that it can be solved in quasipolynomial time — a landmark theoretical result.
In practice, however, algorithms like Nauty and Bliss solve graph isomorphism extremely efficiently for the vast majority of real-world graphs, including molecular graphs.
1.3 Canonical Labeling as a Solution
Instead of directly testing whether two graphs are isomorphic (a pairwise comparison), a more powerful approach is to compute a canonical form (also called a canonical labeling) for each graph.
A canonical labeling is a unique, deterministic relabeling of the graph's vertices such that:
Two graphs are isomorphic if and only if their canonical forms are identical.
This reduces the isomorphism test to a simple string (or hash) comparison, enabling efficient indexing, deduplication, and lookup of molecules in large databases.
2. Nauty: The Pioneer
2.1 Overview
Nauty (No AUTomorphisms, Yes?) was developed by Brendan McKay at the Australian National University, first released in 1981 and continuously improved over four decades. It is arguably the most influential software for graph automorphism and canonical labeling ever created.
Nauty computes:
- The automorphism group of a graph (all symmetries).
- A canonical labeling of the graph.
2.2 Core Algorithm: Individualization-Refinement
Nauty's algorithm is based on the individualization-refinement paradigm. Here is a high-level description:
Step 1: Vertex Partition Refinement
Start with an initial partition of vertices (e.g., based on vertex degree or atom type in a molecular graph). Then iteratively refine this partition:
- For each cell (group) in the partition, split it based on the adjacency pattern to other cells.
- Continue until the partition is equitable — no further splitting is possible.
This refinement process is similar to the Weisfeiler-Leman (WL) algorithm (specifically, the 1-dimensional WL or "color refinement"). It can distinguish many non-isomorphic graphs but is not sufficient for all cases.
Step 2: Individualization (Branching)
If the equitable partition is not discrete (i.e., some cells still contain multiple vertices), Nauty selects a vertex from a non-singleton cell and individualizes it — placing it in its own cell. This creates a branch in a search tree.
After individualization, refinement is applied again. This process continues recursively until a discrete partition is obtained (every cell has exactly one vertex), which corresponds to a specific labeling of the graph.
Step 3: Pruning and Canonical Selection
The search tree can be exponentially large in theory. Nauty employs several powerful pruning strategies:
- Automorphism detection: When two branches lead to the same partition, the mapping between them reveals an automorphism. This automorphism is used to prune equivalent branches.
- Canonical selection rule: Among all the discrete partitions (leaves of the search tree), Nauty selects one as the canonical form using a deterministic comparison rule (e.g., lexicographic ordering of the adjacency matrix).
Step 4: Output
Nauty outputs:
- A set of generators for the automorphism group.
- The canonical labeling (a permutation that transforms the original graph into its canonical form).
2.3 Performance
Nauty is remarkably fast in practice:
- For most molecular graphs (typically < 100 vertices, sparse, with few symmetries), Nauty runs in microseconds.
- It has been tested on graphs with millions of vertices.
- Performance degrades on highly symmetric graphs (e.g., complete graphs, hypercubes), where the automorphism group is very large.
2.4 Traces
In recent versions, Nauty includes an alternative algorithm called Traces, also by McKay and Piperno. Traces uses a different search strategy (based on breadth-first rather than depth-first exploration of the search tree) and often outperforms classic Nauty on large, sparse graphs.
3. Bliss: A Modern Alternative
3.1 Overview
Bliss (A Tool for Computing Automorphism Groups and Canonical Labelings of Graphs) was developed by Tommi Junttila and Petteri Kaski at Aalto University (Helsinki University of Technology), first published in 2007.
Like Nauty, Bliss computes automorphism groups and canonical labelings. It was designed with a focus on:
- Large, sparse graphs (common in many applications including chemistry).
- Memory efficiency.
- Clean, modern C++ implementation.
3.2 Algorithm
Bliss follows the same general individualization-refinement framework as Nauty but introduces several key innovations:
3.2.1 Refined Partition Refinement
Bliss uses an optimized version of partition refinement that is particularly efficient for sparse graphs. The refinement procedure is implemented with careful attention to data structures and cache performance.
3.2.2 Search Tree Pruning
Bliss introduces novel pruning techniques:
- Component-based pruning: Exploits the connected component structure of the graph to prune the search tree more aggressively.
- Orbit-based pruning: Uses the orbits of the automorphism group (computed so far) to avoid redundant branches.
3.2.3 Cell Selection Heuristics
The choice of which vertex to individualize (the cell selector) has a dramatic impact on the size of the search tree. Bliss experiments with several heuristics:
- First non-singleton cell (F): Simple but often effective.
- Largest first (FL): Choose the largest non-singleton cell.
- First largest (LF): Among the first occurring cells, choose the largest.
- First maximum connected (FMC): Consider connectivity in the selection.
Different heuristics perform better on different graph families. For molecular graphs, the default heuristics typically work well.
3.3 Performance Comparison with Nauty
Extensive benchmarks show:
| Aspect | Nauty/Traces | Bliss |
|---|---|---|
| Small dense graphs | Excellent | Good |
| Large sparse graphs | Good (Traces is strong) | Excellent |
| Highly symmetric graphs | Moderate | Moderate |
| Memory usage | Higher | Lower |
| API/Integration | C, with Fortran-style interface | Clean C++ API |
| Molecular graphs | Excellent | Excellent |
For typical molecular graphs (< 200 atoms, sparse, few symmetries), both Nauty and Bliss are extremely fast and the performance difference is negligible.
4. Application in Chemical Molecule Isomorphism Detection
4.1 Molecules as Graphs
A molecule can be naturally represented as a labeled graph:
- Vertices = atoms, labeled with element type (C, N, O, S, ...), charge, isotope, and other properties.
- Edges = bonds, labeled with bond type (single, double, triple, aromatic) and stereochemistry.
Two molecules are identical (ignoring conformation) if and only if their labeled molecular graphs are isomorphic.
4.2 Why Canonical Labeling Matters for Chemistry
4.2.1 Database Deduplication
Chemical databases like PubChem (> 100 million compounds), ChEMBL, and ZINC need to detect duplicate entries. Computing the canonical form of each molecule allows:
- O(1) lookup using hash tables.
- Efficient deduplication across databases.
Without canonical labeling, checking if a new molecule already exists would require pairwise comparison with every existing entry — computationally infeasible at scale.
4.2.2 Canonical SMILES Generation
SMILES (Simplified Molecular Input Line Entry System) is the most widely used linear notation for molecules. However, the same molecule can be written as many different SMILES strings. For example, ethanol can be written as:
CCO
OCC
C(O)C
[CH3][CH2][OH]
A canonical SMILES is a unique SMILES string for each molecule. Generating canonical SMILES requires solving the graph canonical labeling problem. Under the hood, tools like RDKit and OpenBabel use canonical labeling algorithms (often inspired by or directly using Nauty/Bliss) to produce canonical SMILES.
4.2.3 InChI Generation
The IUPAC International Chemical Identifier (InChI) is another canonical molecular representation. The InChI algorithm uses its own canonical labeling procedure (based on Morgan-like algorithms with tie-breaking rules) to assign a unique identifier to each molecule.
4.2.4 Substructure Search
While substructure search (subgraph isomorphism) is a different problem (NP-complete in general), canonical labeling plays a supporting role:
- Precomputing canonical forms of molecular fragments.
- Pruning search spaces using automorphism information.
- Accelerating pattern matching in chemical databases.
4.2.5 Symmetry Perception
The automorphism group computed by Nauty/Bliss reveals the symmetries of a molecule. This has direct chemical significance:
- Equivalent atoms: Atoms in the same orbit of the automorphism group are chemically equivalent (e.g., the three hydrogens in a methyl group).
- NMR prediction: Equivalent atoms produce the same NMR signal. Symmetry perception is essential for predicting NMR spectra.
- Reaction site enumeration: When enumerating possible reaction sites, equivalent positions need to be identified to avoid redundant calculations.
- Combinatorial library design: Symmetry information reduces redundancy in virtual library enumeration.
4.3 How Canonical Labeling Works for Molecules
When applying Nauty/Bliss to molecular graphs, the process is adapted as follows:
Construct the vertex-colored, edge-colored graph:
- Each atom becomes a vertex colored by its element type (and possibly charge, isotope, etc.).
- Each bond becomes an edge colored by its bond type.
Initialize the partition:
- The initial partition groups atoms by their color (element type). For example, all carbons in one cell, all oxygens in another, etc.
- This dramatically reduces the search space compared to starting with a uniform partition.
Run canonical labeling:
- Nauty/Bliss refines the partition, individualizes vertices, and searches for the canonical form.
- Edge colors are incorporated into the refinement step (adjacency to different bond types provides additional distinguishing information).
Output the canonical permutation:
- The canonical permutation defines a unique ordering of atoms.
- This ordering is used to generate a canonical SMILES, canonical adjacency matrix, or canonical hash.
4.4 Integration in Cheminformatics Toolkits
Several major cheminformatics libraries use or are inspired by Nauty/Bliss:
| Toolkit | Canonical Labeling Method | Notes |
|---|---|---|
| RDKit | Custom Morgan-based algorithm with tie-breaking | Inspired by canonical labeling principles; RDKit also provides optional integration with external tools. |
| OpenBabel | Custom canonical labeling | Uses its own implementation based on similar principles. |
| CDK | Custom algorithm | The Chemistry Development Kit implements its own canonical SMILES generation. |
| InChI | Custom hierarchical algorithm | Uses a layered canonical labeling approach. |
| NetworkX / igraph | Can interface with Nauty/Bliss | General graph libraries that support Nauty/Bliss for canonical labeling. |
| Schrodinger, MOE, etc. | Proprietary implementations | Commercial tools with optimized internal algorithms. |
Some research tools and specialized applications directly call Nauty or Bliss via their C/C++ APIs for high-performance canonical labeling of molecular graphs.
5. Worked Example
Consider two representations of the same molecule, isobutane (2-methylpropane):
Representation 1:
Atom 1: C, connected to 2, 3, 4
Atom 2: C, connected to 1
Atom 3: C, connected to 1
Atom 4: C, connected to 1
Representation 2:
Atom A: C, connected to B
Atom B: C, connected to A, C, D
Atom C: C, connected to B
Atom D: C, connected to B
These look different, but the underlying graphs are isomorphic (both are the star graph \(K_{1,3}\) with all carbon labels).
Step 1: Partition Refinement
- Initial partition: {1, 2, 3, 4} (all carbons) for Representation 1.
- After refinement by degree: {1} (degree 3), {2, 3, 4} (degree 1).
- The partition is now equitable.
For Representation 2:
- After refinement: (degree 3), {A, C, D} (degree 1).
Step 2: Canonical Form
Both representations produce the same canonical adjacency structure:
- One central vertex connected to three leaf vertices.
Nauty/Bliss would output the same canonical hash for both → isomorphism confirmed.
Bonus — Automorphism Group:
The automorphism group is \(S_3\) (symmetric group on 3 elements), corresponding to the 6 permutations of the three equivalent methyl groups. This tells us the three terminal carbons are chemically equivalent.
6. Performance on Molecular Graphs
Molecular graphs have properties that make them particularly amenable to canonical labeling:
| Property | Typical Value | Impact on Algorithm |
|---|---|---|
| Number of vertices | 10–100 (small molecules), up to ~1000 (proteins/polymers) | Small search space |
| Vertex degree | Typically ≤ 4 (carbon is at most 4-connected) | Very sparse graphs |
| Number of distinct labels | 5–10 element types in a typical drug molecule | Good initial partition |
| Symmetry | Low to moderate (most drug molecules have few symmetries) | Small automorphism groups, fast pruning |
As a result, Nauty and Bliss can canonicalize typical drug-like molecules in microseconds. Even for large molecules like natural products or peptides with hundreds of atoms, the computation rarely exceeds milliseconds.
Benchmark Results
In a typical benchmark on a dataset of ~1 million drug-like molecules:
| Operation | Nauty | Bliss |
|---|---|---|
| Average time per molecule | ~5 μs | ~4 μs |
| Max time (complex symmetric molecule) | ~1 ms | ~0.8 ms |
| Memory per molecule | ~10 KB | ~8 KB |
| Throughput | ~200,000 molecules/sec | ~250,000 molecules/sec |
(These numbers are approximate and depend on hardware and implementation details.)
7. Beyond Simple Isomorphism
7.1 Stereoisomer Handling
Canonical labeling of the molecular graph alone does not distinguish stereoisomers (e.g., R vs. S enantiomers, E vs. Z isomers). To handle stereochemistry:
- Stereochemical information must be encoded as additional vertex or edge labels.
- CIP (Cahn-Ingold-Prelog) priority rules are applied after canonical labeling.
- The canonical SMILES or InChI includes stereochemical descriptors.
Nauty/Bliss handles this naturally: stereochemistry is encoded as additional colors, making stereoisomers non-isomorphic in the colored graph.
7.2 Tautomer Handling
Tautomers (molecules that differ by proton position) have different molecular graphs but are often considered "the same" compound. Canonical labeling must be combined with tautomer standardization for proper deduplication.
7.3 Molecular Similarity and Subgraph Isomorphism
While Nauty/Bliss solves exact isomorphism, chemistry often requires:
- Subgraph isomorphism (substructure search): Is molecule A a substructure of molecule B? This is solved by algorithms like VF2 or Ullmann's algorithm, not by canonical labeling.
- Maximum common subgraph (MCS): What is the largest common substructure between two molecules? This is NP-hard in general.
- Graph similarity: How similar are two molecular graphs? Approached via fingerprints, graph kernels, or graph neural networks.
Canonical labeling complements these methods but does not replace them.
8. Practical Usage
8.1 Using Nauty
Nauty is distributed as C source code. A basic usage example:
#include "nauty.h"
// Define graph with MAXN vertices
// Set up adjacency using ADDONEEDGE macro
// Call densenauty() or sparsenauty()
// Compare canonical forms
Nauty also provides command-line tools:
- dreadnaut: Interactive interface for graph manipulation and canonical labeling.
- shortg: Removes isomorphic duplicates from a list of graphs.
- geng: Generates all non-isomorphic graphs of a given size.
8.2 Using Bliss
Bliss provides a clean C++ API:
#include "bliss/graph.hh"
bliss::Graph g(n_vertices);
g.change_color(vertex_id, color); // Set atom type
g.add_edge(v1, v2); // Add bond
// Compute canonical form
const unsigned int* canonical_labeling = g.canonical_form(stats, NULL, NULL);
8.3 Python Wrappers
Both Nauty and Bliss have Python bindings:
- pynauty: Python interface to Nauty.
- PyBliss: Python interface to Bliss.
- igraph: The
igraphlibrary includes Bliss integration viaGraph.canonical_permutation(). - NetworkX: Can interface with external tools for canonical labeling.
Example using igraph:
import igraph as ig
# Create molecular graph
g1 = ig.Graph(edges=[(0,1), (1,2), (1,3)])
g1.vs["label"] = ["C", "C", "C", "C"]
g2 = ig.Graph(edges=[(0,1), (0,2), (0,3)])
g2.vs["label"] = ["C", "C", "C", "C"]
# Get canonical permutation (uses Bliss internally)
perm1 = g1.canonical_permutation(color=g1.vs["label"])
perm2 = g2.canonical_permutation(color=g2.vs["label"])
# Compare canonical forms
g1_canon = g1.permute_vertices(perm1)
g2_canon = g2.permute_vertices(perm2)
print(g1_canon.isomorphic(g2_canon)) # True
9. Comparison with Other Approaches
| Method | Type | Strengths | Limitations |
|---|---|---|---|
| Nauty/Traces | Canonical labeling | Gold standard, very fast, computes automorphisms | C-based, complex API |
| Bliss | Canonical labeling | Fast on sparse graphs, clean API, memory-efficient | Slightly slower on dense graphs |
| VF2 | Subgraph isomorphism | Widely used for substructure search | Does not compute canonical forms |
| Morgan Algorithm | Extended connectivity | Simple, fast, basis for ECFP fingerprints | Not a complete canonical labeling (can fail on some graphs) |
| InChI Algorithm | Hierarchical canonical labeling | Standardized, produces InChI identifiers | Slower, not designed for general graph isomorphism |
| Weisfeiler-Leman (WL) | Color refinement | Fast, O(n log n) | Incomplete — cannot distinguish all non-isomorphic graphs |
| Graph Neural Networks | Learned representations | Can learn task-specific similarity | Approximate, not guaranteed to solve isomorphism |
10. Conclusion
Nauty and Bliss are foundational tools in computational graph theory, and their impact on cheminformatics cannot be overstated. By efficiently solving the graph canonical labeling problem, they enable:
- Unique molecular identification through canonical SMILES, InChI, and hash-based lookups.
- Database deduplication across chemical databases with millions or billions of entries.
- Symmetry perception for NMR prediction, reaction enumeration, and conformational analysis.
- High-throughput virtual screening where rapid isomorphism checks are essential.
For typical molecular graphs — small, sparse, and with limited symmetry — both algorithms perform in microseconds, making them practical for real-time applications. While the two algorithms share the same theoretical framework (individualization-refinement), they differ in implementation details and performance characteristics. Bliss tends to excel on large, sparse graphs with its memory-efficient design, while Nauty (especially with Traces) is often faster on dense or highly symmetric graphs.
As chemical databases continue to grow and computational chemistry demands ever-higher throughput, the importance of efficient canonical labeling algorithms will only increase. Whether you are building a chemical registration system, mining the patent literature, or developing a new virtual screening platform, understanding Nauty and Bliss is essential knowledge for any computational chemist or cheminformatician.
References
- McKay, B. D., & Piperno, A. (2014). Practical graph isomorphism, II. Journal of Symbolic Computation, 60, 94–112.
- Junttila, T., & Kaski, P. (2007). Engineering an efficient canonical labeling tool for large and sparse graphs. Proceedings of the Meeting on Algorithm Engineering & Experiments (ALENEX), 135–149.
- Weininger, D. (1988). SMILES, a chemical language and information system. Journal of Chemical Information and Computer Sciences, 28(1), 31–36.
- Heller, S. R., McNaught, A., Pletnev, I., Stein, S., & Tchekhovskoi, D. (2015). InChI, the IUPAC International Chemical Identifier. Journal of Cheminformatics, 7(1), 23.
- McKay, B. D. (1981). Practical graph isomorphism. Congressus Numerantium, 30, 45–87.
- Babai, L. (2016). Graph isomorphism in quasipolynomial time. Proceedings of the 48th Annual ACM Symposium on Theory of Computing (STOC), 684–697.
- Cordella, L. P., Foggia, P., Sansone, C., & Vento, M. (2004). A (sub)graph isomorphism algorithm for matching large graphs. IEEE Transactions on Pattern Analysis and Machine Intelligence, 26(10), 1367–1372.