Skip to main content

K3,3 embedding: logo for graph genus repo

Graph Genus

DOI arXiv PyPI Version maintenance-status

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:

K3,3 Torus Embedding

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 use algorithm="page" (default), algorithm="multi_genus", and algorithm="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" treats adjacency_list as 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, and output_format="3D" for OBJ output of the 3D surface with the graph drawn on it.
  • PAGE additionally allows the low_memory=True option for very large graphs with tens of thousands of edges.
  • 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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graph_genus-0.1.2.tar.gz (104.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

graph_genus-0.1.2-py3-none-win_amd64.whl (328.7 kB view details)

Uploaded Python 3Windows x86-64

graph_genus-0.1.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (141.6 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

graph_genus-0.1.2-py3-none-macosx_15_0_arm64.whl (132.0 kB view details)

Uploaded Python 3macOS 15.0+ ARM64

File details

Details for the file graph_genus-0.1.2.tar.gz.

File metadata

  • Download URL: graph_genus-0.1.2.tar.gz
  • Upload date:
  • Size: 104.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for graph_genus-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3b936af120947da7dd748abf89374e6dfcc3f7c157574531123cd2153229a91a
MD5 4da730c85e3911ab35ef7a383629428c
BLAKE2b-256 4ab797746e786ea9de9d7774a0670d8d4498b5e52c80560665cb8ae3f1753e93

See more details on using hashes here.

File details

Details for the file graph_genus-0.1.2-py3-none-win_amd64.whl.

File metadata

  • Download URL: graph_genus-0.1.2-py3-none-win_amd64.whl
  • Upload date:
  • Size: 328.7 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for graph_genus-0.1.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 440f6b43ce2189665c8a6482839247710e4d90c744f8fcc643a7274d09e6d29b
MD5 9fd33b4f921a6d72e8da6b8710b3f745
BLAKE2b-256 5408799cb4c28c09f3bf78b7d62f90632ff2c76ad86be62a04f78a07c051b8a9

See more details on using hashes here.

File details

Details for the file graph_genus-0.1.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for graph_genus-0.1.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 6d2955415c95ebcce6417d76f916eb228603cf6df81b79fdc4d1fcf685307205
MD5 b14529fe6a2cb8c83442ed87001cdc0b
BLAKE2b-256 4f6754edc679f1e773d26d73887c07ad5672717f189f66f581756eb011012cfa

See more details on using hashes here.

File details

Details for the file graph_genus-0.1.2-py3-none-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for graph_genus-0.1.2-py3-none-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 1d2bd980f5a9c824ab60f496acbe0897ffa159e13318892f2d2e520f995294af
MD5 84178e658dba721c1059f843bcf4462d
BLAKE2b-256 a0cebf0d82003c96577b473ffaacd72196d105277044d31a358f55b2553f693c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page