pygmtools: one API for classical and neural graph matching in Python
A Python Graph Matching Toolkit.
At a glance
- What is it?
- pygmtools wraps linear, quadratic, multi-graph and neural graph matching solvers behind a single interface that switches between numpy, PyTorch, Paddle, Jittor, TensorFlow and MindSpore. It is a research toolkit, and the backend abstraction is both its main selling point and the thing you have to verify before committing.
- Who is it for?
- Adopt pygmtools if your work is graph matching research or a pipeline that needs a matching layer with a differentiable path into a neural network, and you are willing to pin a version. Do not adopt it as a general-purpose assignment library for production scheduling or resource allocation: the combinatorial solvers are research implementations with a research API, and the neural solvers expect graph-structured input rather than a cost matrix.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 103 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem pygmtools targets: correspondence between graphs
Graph matching asks for a node-to-node correspondence between two or more graphs. The README describes it as a fundamental yet challenging problem in pattern recognition and data mining, and notes that the underlying formulation is an NP-hard combinatorial optimization problem. That framing matters, because it tells you what the library is and is not. It is not a general assignment solver for arbitrary cost matrices. It is a collection of algorithms that operate on the graph matching formulation, where the objective usually includes both node affinities and edge affinities, and where the exact answer is generally out of reach at realistic sizes.
The intended audience is researchers. The README says plainly that doing graph matching in Python used to be difficult and that the library exists to make researchers' lives easier. The published venue reinforces that: the project states it is published in JMLR and asks users to cite the paper if the tools are useful in their research. If you are building a product feature that happens to need bipartite matching, the Hungarian implementation here will work, but you are paying for a much larger dependency than the task requires.
Four solver families, two of them differentiable
The API is organized around solver families rather than around a single entry point. Two-graph solvers cover linear assignment (the differentiable soft Sinkhorn algorithm and the exact Hungarian solver) and quadratic assignment (spectral graph matching, random-walk-based graph matching, and the discrete integer projected fixed point method). Multi-graph solvers include CAO, a Floyd shortest path variant, and a graduated-assignment solver that anneals Sinkhorn's temperature. Neural solvers include PCA-GM and IPCA-GM, CIE, NGM, and GENN-A* for graph edit distance.
The split between differentiable and discrete is the design decision that matters most. Sinkhorn, spectral matching and the random-walk solver are described as soft and differentiable, so gradients flow through the matching step. IPFP is described as discrete and non-differentiable. If you intend to train a model end to end, that distinction determines which solvers are usable, and it is not a detail you can paper over with a wrapper. The multi-graph solvers take a different route: CAO optimizes the affinity score while gradually infusing consistency, and the graduated-assignment solver reaches a discrete result by lowering temperature rather than by a hard rounding step. Each solver links to its own API page and its own reference in the documentation, which is the right structure for a research library but also means there is no single canonical tutorial for the whole set.
Backend switching is the architecture, and it constrains everything
pygmtools is designed to support multiple backends behind the same set of API. numpy is the default and is CPU only. PyTorch, Paddle, Jittor, TensorFlow and MindSpore are listed as the deep learning backends, with GPU support. The README states that installation gives you the numpy backend, and that other backends follow their own official installation instructions.
This is a real architectural commitment, not a marketing bullet. Supporting six numerical backends with one API means every solver has to be expressed in operations that all of them provide, and it means the library carries dispatch logic that has to be correct across versions of six separate projects. The upside is that a solver you prototype on CPU with numpy can move to a GPU backend without rewriting the call site. The cost is that the numpy path is the only one you get for free, and the deep learning paths inherit the version constraints of whichever framework you pair with them. The README's own framing is that the operations are designed to preserve gradients and to support batched operations, which is the part that makes the neural solvers trainable rather than merely runnable.
Installing and running the first call
The stable release is on PyPI, so the install is a single command:
pip install pygmtools
The README also documents a source install that pulls the current main branch:
pip install -U https://github.com/Thinklab-SJTU/pygmtools/archive/master.zip
Dependencies are declared and installed automatically by pip. The listed requirements are Python >= 3.8, requests >= 2.25.1, scipy >= 1.4.1, Pillow >= 7.2.0, numpy >= 1.18.5, easydict >= 1.7, appdirs >= 1.4.4, tqdm >= 4.64.1, networkx >= 2.8.8, aiohttp and async-timeout. Note the presence of aiohttp and async-timeout in a library whose core work is matrix computation. The README does not explain what the asynchronous HTTP dependency is for, and I cannot confirm its role from the supplied material. If you are auditing dependencies for a locked environment, that is a question to resolve before rollout rather than after.
After install, the README states that pygmtools is available with the numpy backend, which is the default. To use a neural solver on GPU you install the relevant framework separately and follow its own instructions. The documentation site at pygmtools.readthedocs.io holds the per-solver API pages, and each solver name in the README links to its autosummary page, so the reference documentation is the place to look for exact call signatures and argument names.
Where the toolkit stops being the right choice
The first limitation is inherent to the problem, not to the code. Graph matching is NP-hard, so every solver here is either an exact method that will not scale to large graphs, a relaxation that returns an approximate or soft result, or a learned model whose accuracy depends on training data that matches your domain. The README does not publish accuracy or runtime figures, and I have not run any of these solvers, so I cannot tell you where the practical size ceiling sits for a given solver. That is something you have to measure on your own graph sizes before you design around it.
The second limitation is the backend matrix. A library that targets six numerical frameworks has to track six release cadences. The version constraints in the README (numpy >= 1.18.5, scipy >= 1.4.1, networkx >= 2.8.8) are floors, not tested upper bounds. If your environment pins, say, an older networkx for unrelated reasons, nothing in the supplied material tells you whether the combination is supported.
The third is scope creep. The neural solvers require graph-structured input and, for the learned models, trained weights. If your problem is a plain rectangular assignment with a cost matrix and no edge structure, the quadratic and neural machinery is dead weight, and a smaller specialized library will be easier to reason about. The project is also explicitly research-oriented: the README's own call to action is a citation request, not a support commitment. A NOASSERTION licence identifier is the final caution. It means the repository's licence could not be classified automatically, so read the actual licence file before you ship anything built on it. Nothing here is legal advice, but an unclassified licence is a question for whoever signs off on dependencies, not a detail to skip.
Compared with a general assignment library such as SciPy
The obvious alternative for the linear case is scipy.optimize.linear_sum_assignment, which solves the assignment problem exactly and is already a dependency of pygmtools. The difference is scope. SciPy gives you one exact solver for a cost matrix. pygmtools gives you that class of solver plus quadratic assignment, multi-graph consistency across more than two graphs, and differentiable relaxations that can sit inside a neural network's forward pass.
If your task is matching two sets of points under a known cost, SciPy is the smaller and better understood tool, and it is already installed. You should reach for pygmtools when the matching problem has edge structure that a cost matrix cannot express, when you need consistency across a collection of graphs rather than a pairwise answer, or when the matching step has to be differentiable because it lives inside a training loop. Those three conditions are what the extra solvers and the extra backends are paying for. If none of them applies, the dependency is not earning its place.
Release cadence and the cost of staying current
The release history shows 0.5.3 in June 2024, 0.5.5 in September 2025, and 0.6.0 in April 2026, with the last push to the default branch in June 2026. That is a slow but live cadence: roughly one to two releases a year, with continued activity between them. For a research library that is a reasonable signal, but it also means you should not expect prompt fixes for an environment conflict. Plan to pin a version and test upgrades deliberately rather than tracking main.
The upgrade cost is concentrated in two places. The first is the backend frameworks. A pygmtools upgrade that changes how it dispatches to PyTorch or TensorFlow interacts with whatever version of that framework you run, so a version bump here is really a joint upgrade of two packages. The second is the API surface. With this many solvers, each with its own autosummary page, the chance that a minor release renames or adjusts one solver's arguments is higher than in a library with a single entry point. If you use one solver, you carry the risk of the whole surface. The mitigation is boring and specific: pin the version in your requirements, and when you upgrade, run the solvers you actually call against a stored input and compare outputs before you trust the new version.
Who should install it, and what to check first
pygmtools fits a research group or a lab pipeline that needs several matching algorithms behind one interface and wants to move between CPU prototyping and GPU training without rewriting call sites. It also fits a project that needs a differentiable matching layer inside a neural model, where the soft Sinkhorn or spectral solvers are the reason to be here at all.
It does not fit a service that needs one exact bipartite matching per request, and it does not fit a team that cannot absorb a dependency on a research library with a NOASSERTION licence and a yearly release rhythm.
Before adopting, do three concrete things. Run pip install pygmtools and confirm the numpy backend is what you get, since the README says that is the default and every other backend is a separate install. Pick one solver from each family you plan to use and run it on your own graph sizes, because no accuracy or runtime figures are published and the NP-hard formulation means the ceiling is data-dependent. Read the licence file in the repository, since the automated classification returned NOASSERTION and that is the one item on this list that can stop a deployment after the code already works.
Editorial conclusion
Adopt pygmtools if your work is graph matching research or a pipeline that needs a matching layer with a differentiable path into a neural network, and you are willing to pin a version. Do not adopt it as a general-purpose assignment library for production scheduling or resource allocation: the combinatorial solvers are research implementations with a research API, and the neural solvers expect graph-structured input rather than a cost matrix. Before you commit, install it, confirm which backend you actually get by default, and run one solver from each family you intend to use on your own data shape.
Community notes