This repository provides tools for searching low-rank decompositions of arbitrary 3-way tensors, in particular encoding bilinear maps. If a bilinear map takes inputs with coordinates Aα΅’, Bβ±Ό and produces outputs Cβ, it can be written as
for some tensor Tα΅’β±Όβ. A rank-r algorithm corresponds to a factorization
which for the matrix multiplication reduces the number of scalar multiplications to r. A famous example is the Strassen's scheme for 2Γ2 matrices:
The main workflow in this project is to first search for such tensor decompositions over a small finite field, most commonly π½β or π½β. Then use Hensel lifting to pass to an extension field mod pα΅, and finally apply rational reconstruction to obtain coefficients over β€ or β. For general matrix multiplication, structured matrix multiplication, polynomial multiplication, generators in scripts/ can be used to generate the corresponding tensors (see docs/generators.md and examples/).
To the best of our knowledge, this is the first open-source flip-graph search implementation that also works over π½β, making it possible to discover schemes with Β½ coefficients after rational reconstruction. The modular search core is inspired by existing π½β-based implementations such as flips and symmetric-flips. In addition, flip-cpd integrates fast Hensel lifting and scheme selection into a single pipeline, so that the full βsearch β lift β selectβ workflow is implemented end-to-end within this repository. The current implementation supports tensors with mode sizes up to 64 and, on standard hardware, achieves about 10β· flip graph steps per second per thread, with multi-threaded search supported.
The core tools are written in C++20 and have no external runtime dependencies beyond the standard library and threads. All third-party headers (CLI11.hpp, cnpy.h, picojson.h) are vendored in third_party/.
One way to build is via CMake:
cmake -S . -B build
cmake --build buildThis will compile all binaries (search2/3, lift2/3, select2/3, select_modular2/3) and place them in the bin/ directory. If you prefer not to use CMake, each tool can also be built directly from the corresponding src/{name}.cpp file with a single compiler invocation. A typical command for a field looks like
g++ -DMOD2 -Ofast -std=c++20 -march=native -Ithird_party -pthread src/search.cpp -o bin/search2and analogously for MOD3 and other sources (lift.cpp, select.cpp, select_modular.cpp).
For generating tensors and running the example notebooks you additionally need Python 3 with a few packages:
numpyandtyperforscripts/generator.py;sympyfor verifying schemes inexamples/.
The C++ tools are organized around three main stages: modular search (search2/search3), lifting to characteristic zero (lift2/lift3), and selection of schemes (select2/select3 and select_modular2/select_modular3). Given a tensor name from data/tensors/, a typical workflow is to run search, then lift, and finally select on the resulting schemes. An end-to-end example of this pipeline is provided in examples/, and docs/cli.md documents all command-line options.
search. These programs perform pool-based flip graph search for low-rank decompositions over a finite field. search2 works over π½β and search3 over π½β. The same 2/3 suffix convention is used for the other tools. They take a tensor name (matching an entry in data/tensors/) and explore the flip graph.
lift. These tools take modular schemes found by search2/search3 and perform Hensel lifting followed by rational reconstruction. Starting from schemes over π½β or π½β, they lift to an extension field mod pα΅ and then reconstruct coefficients over β€ or β. The resulting lifted and rational schemes are written to the corresponding directories under data/.
select. Once a collection of rational schemes is available, these programs read them, analyse possible recursions, and select Pareto-optimal schemes according to rank, number of recursion calls and number of additions. The selected schemes are written both in .npy format and in a human-readable .txt format.
select_modular. These variants run a similar selection and analysis procedure directly on modular schemes, without lifting.
Selected schemes are written to data/schemes_selected/ in two formats: .npy files containing the triplet (U, V, W) in a fixed binary layout, and .txt files with a human-readable description of the same scheme. See examples/ and docs/formats.md for details.
In addition, the repository includes a set of reference schemes from the paper in data/schemes_paper/, provided in both .npy and .txt form. These files can be loaded and analysed with the same tooling as newly generated schemes.
Several extensions are planned:
- support for approximate schemes π½β[Ξ΅] [link];
- flip graph search specialized to commutative schemes [link];
- flip graph search with symmetry [link];
- other base fields, e.g. π½β, π½β[i].
Contributions towards these or related extensions are welcome; feel free to open an issue or a pull request.
If you use this code or the accompanying datasets in academic work, please cite:
@misc{khoruzhii_2025,
title = {Faster Algorithms for Structured Matrix Multiplication via Flip Graph Search},
author = {Kirill Khoruzhii and Patrick GelΓ and Sebastian Pokutta},
year = {2025},
eprint = {2511.10786},
archivePrefix = {arXiv},
url = {https://arxiv.org/abs/2511.10786}
primaryClass = {cs.SC}
}