Python bindings for various graph genus and embedding tools
Project description
Graph Genus
State of the art practical algorithms for computing the minimum genus of graphs and the corresponding embeddings. Contains standalone C programs, python bindings, and a web version with 2D and 3D visualizations.
Motivation
A famous problem at the intersection of topology and combinatorial graph theory is the Utility Problem. Say you have three houses and three utilities and you need to connect each house to each utility via a wire. Is there a way to do this without the wires crossing? In terms of graph theory, this is asking whether K3,3 is planar. It is known that it is not. In fact K3,3 is toroidal meaning while it cannot be embedded on a plane without edges crossing, it can be embedded on a torus:
The characterizing property of a torus that allows us to embed K3,3 is that it has a hole (unlike surfaces such as a plane or a sphere). This motivates classifying surfaces by their number of holes, that is, their genus g. The genus of a graph G is then simply the genus of the minimum genus surface on which G can be embedded without edges crossing. For genus zero we use the special name planar and for genus one we use toroidal. Calculating the genus of a graph has a number of applications, particularly in the design of integrated circuits, study of graph minors, VLSI design, infrastructure planning, and more. For an interactive visualization of graph embedding check here.
Usage
The easiest way is to use the web version. This won't be as fast as running it locally and I can't guarantee it will always be up, but it should allow you to explore the algorithm. You can also self-host the web application by installing docker and running cd app followed by . ./run-dev.sh. This will start the web application on localhost:8080.
The easiest way to run locally, is with the graph-genus Python package. Make sure you have Python 3. Then pip install graph-genus and you can use the Python API:
import graph_genus as gg
adjacency_list = [[3, 4, 5], [3, 4, 5], [3, 4, 5],
[0, 1, 2], [0, 1, 2], [0, 1, 2]]
genus, rotation_system = gg.embed(adjacency_list)
- As an optional parameter to
embed, you can usealgorithm="page"(default),algorithm="multi_genus", andalgorithm="none"."page"is especially fast for high girth graphs and scales well in general too."multi_genus"is included with permission from Gunnar Brinkmann, is faster for some graph families, and uses less resources, but handles at most 128 vertices and 512 undirected edges."none"treatsadjacency_listas an already chosen rotation system. - You can also use
output_format="rotation_system"(default),output_format="drawing"for TikZ/LaTeX output of the fundamental polygon, andoutput_format="3D"for OBJ output of the 3D surface with the graph drawn on it. - Use
gg.cite(algorithm, output_format)to retrieve the relevant BibTeX entries.
For local development, install with make -C PAGE all && make -C MultiGenus all && pip install -e . then test with python tests/test_graph_genus_package.py (should take ~2 minutes). Build with source build_wheels.sh, check with source build_wheels_test.sh, and upload with pipx run twine upload dist/*.
To run the algorithms directly without the Python bindings, take a look at the instructions for PAGE and MultiGenus.
Acknowledgements
Austin contributed equally to the ideas behind PAGE. Professor Steinerberger provided guidance on the PAGE publication. Professor Brinkmann provided a fast alternative algorithm, multi_genus, and useful code for visualizing embeddings.
License
This project is licensed under the terms of the GNU General Public License v2.0 (GPLv2). See the LICENSE file for the full text.
Citation
If you use the PAGE algorithm or other code/visualizations from this repository, python package, or webapp, please cite:
@article{Metzger_2026,
title={An efficient genus algorithm based on graph rotations},
volume={349},
ISSN={0012-365X},
url={http://doi.org/10.1016/j.disc.2026.115308},
DOI={10.1016/j.disc.2026.115308},
number={12},
journal={Discrete Mathematics},
publisher={Elsevier BV},
author={Metzger, Alexander and Ulrigg, Austin},
year={2026},
month=Dec, pages={115308}
}
If you use multi_genus, please cite
@article{article,
author = {Brinkmann, Gunnar},
year = {2022},
month = {07},
pages = {#P4.01},
title = {A practical algorithm for the computation of the genus},
volume = {22},
journal = {Ars Mathematica Contemporanea},
doi = {10.26493/1855-3974.2320.c2d}
}
And if you use the fundamental polygon drawings or 3D visualizations, please additionally cite
@misc{brinkmann2025drawingmapsorientedsurfaces,
title={Drawing maps on oriented surfaces},
author={Gunnar Brinkmann},
year={2025},
eprint={2505.01480},
archivePrefix={arXiv},
primaryClass={cs.CG},
url={https://arxiv.org/abs/2505.01480},
}
You may also want to check out the literature this work is based on.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file graph_genus-0.1.1.tar.gz.
File metadata
- Download URL: graph_genus-0.1.1.tar.gz
- Upload date:
- Size: 94.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df0e4a164ca5b25f661c44e22c1ee88d950d63e405881e61c251b4c52d4d9cd0
|
|
| MD5 |
27f2f9f7de55d6e20888ddbdda3c1a85
|
|
| BLAKE2b-256 |
3b1a69fb63202970207778d29bbd544fd709e490a35d76b83a85aea32a804aaf
|
File details
Details for the file graph_genus-0.1.1-py3-none-win_amd64.whl.
File metadata
- Download URL: graph_genus-0.1.1-py3-none-win_amd64.whl
- Upload date:
- Size: 270.8 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
798b55fd53315da66c3cd413d7b1e92284dbecf924153f15aa9ccf4b38150f0a
|
|
| MD5 |
1b4564fdfbef7955d0a791249f47810f
|
|
| BLAKE2b-256 |
9ac460682bd12af656d4e458e3df09d2fbb39b7c50be8a3318509b7358173a59
|
File details
Details for the file graph_genus-0.1.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.
File metadata
- Download URL: graph_genus-0.1.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- Upload date:
- Size: 127.2 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce1acbff90a4ecad5bfa0575542eac89498b2b8a0b611bac76fc520ebe5cdb72
|
|
| MD5 |
c960300c280cdb8241700a03f52ad3f8
|
|
| BLAKE2b-256 |
b249ac2239c316858c379975042cf98d9d59b8f6c2b913702e46483576fd8d33
|
File details
Details for the file graph_genus-0.1.1-py3-none-macosx_15_0_arm64.whl.
File metadata
- Download URL: graph_genus-0.1.1-py3-none-macosx_15_0_arm64.whl
- Upload date:
- Size: 120.4 kB
- Tags: Python 3, macOS 15.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
437c20865433b690a487a15a8f4edb3cb18dc2846ce1ab87bc033f8d89b7789d
|
|
| MD5 |
60b5e26b02656d8401a59370d81bcb01
|
|
| BLAKE2b-256 |
765d45845f5ca00872b2dcea449c498166aad4e97bdf9d457df005b844c43a2c
|