Knoodle

July 18, 2026 · View on GitHub

by Henrik Schumacher and Jason Cantarella

A collection of tools for computational knot theory. Knoodle includes, PlanarDiagram (a class to manipulate planar diagrams, including rerouting of overstrands and understrands (see PlanarDiagram::Simplify5), REAPR (a fast algorithm for simplifying knot diagrams), ClisbyTree (a fast algorithm for generating self-avoiding polygons in the "pearl-necklace" model of self-avoidance).

Installation

To use the Knoodle classes in your own programs, clone this repository. To make sure that all submodules are cloned, too, please clone by running the following in the command line:

git clone --depth 1 --recurse-submodules --shallow-submodules git@github.com:HenrikSchumacher/Knoodle.git

Knoodle's command line tools polyfold, knoodlesimplify, knoodledraw, and knoodleidentify (but not the Knoodle headers themselves) can be installed via homebrew on a wide variety of systems. The native platform is MacOS/Apple Clang. Installation is continuously tested via GitHub Actions on the ubuntu-latest and macos-26 runners, and WSL2 uses the same Linuxbrew path as native Linux. It should install on a wide variety of linux systems with the following commands:

brew tap designbynumbers/cantarellalab
brew install knoodle

On Linux and WSL2 the formula builds with Homebrew's gcc; on macOS it uses Apple Clang. The build compiles from source with CPU-specific optimizations and typically takes several minutes.

Windows (WSL2)

The command line tools install under WSL2 using Linuxbrew, exactly as on native Linux. Use WSL 2 (not WSL 1), and a recent Ubuntu (24.04 recommended). The compile is template-heavy and memory-hungry, and WSL2 defaults to ~50% of host RAM, so on a modest machine the compiler may be killed mid-build (internal compiler error: Killed (program cc1plus)). If that happens, raise the limit by creating C:\Users\<you>\.wslconfig with:

[wsl2]
memory=8GB
swap=8GB

then run wsl --shutdown in Windows PowerShell, reopen your distro, and retry brew install knoodle.

Please contact us if you are interested and need support.

PolyFold

The command-line tool PolyFold can be compiled by running make in the subdirectory PolyFold. After compiling:

./PolyFold --help

Allowed options:
  -h [ --help ]                   produce help message
  -d [ --diam ] arg (=1)          set hard sphere diameter
  -n [ --edge-count ] arg         set number of edges
  -b [ --burn-in ] arg            set number of burn-in steps
  -s [ --skip ] arg               set number of steps skipped between samples
  -N [ --sample-count ] arg       set number of samples
  -o [ --output ] arg             set output directory
  -i [ --input ] arg              set input file
  -T [ --tag ] arg                set a tag to append to output directory
  -e [ --extend ]                 extend name of output directory by 
                                  information about the experiment, then append
                                  value of --tag option
  -v [ --verbosity ] arg (=1)     how much information should be printed to 
                                  Log.txt file.
  --pcg-multiplier arg            specify 128 bit unsigned integer used by 
                                  pcg64 for the "multiplier" (implementation 
                                  dependent -- better not touch it unless you 
                                  really know what you do)
  --pcg-increment arg             specify 128 bit unsigned integer used by 
                                  pcg64 for the "increment" (every processor 
                                  should have its own)
  --pcg-state arg                 specify 128 bit unsigned integer used by 
                                  pcg64 for the state (use this for seeding)
  -m [ --low-mem ]                force deallocation of large data structures; 
                                  this will be a bit slower but peak memory 
                                  will be less
  -a [ --angles ]                 compute statistics on curvature and torsion 
                                  angles and report them in file "Info.m"
  -g [ --squared-gyradius ]       compute squared radius of gyration and report
                                  in file "Info.m"
  -c [ --pd-code ]                compute pd codes and print to file 
                                  "PDCodes.tsv"
  -B [ --bounding-boxes ]         compute statistics of bounding boxes and 
                                  report them in file "Info.m"
  -P [ --polygons ] arg (=-1)     print every [arg] sample to file; if [arg] is
                                  negative, no samples are written to file ; if
                                  [arg] is 0, then only the polygon directly 
                                  after burn-in and the final sample are 
                                  written to file
  --histograms arg (=0)           create histograms for curvature and torsion 
                                  angles with [arg] bins
  -C [ --checks ] arg (=1)        whether to perform hard sphere collision 
                                  checks
  -R [ --reflections ] arg (=0.5) probability that a pivot move is orientation 
                                  reversing
  -H [ --hierarchical ] arg (=0)  whether to use hierarchical moves for burn-in
                                  and sampling
  -S [ --shift ] arg (=1)         shift vertex indices randomly in each sample
  -Z [ --recenter ] arg (=1)      translate each sample so that its barycenter 
                                  is the origin

PolyFold produces a directory containing files named "Tools_Log.txt" (for debugging; it should be empty), "Info.m" (a Mathematica file which holds an Association giving information about the run and the samples), "PDCodes.tsv" (if the -c option is given) and "Polygon_.tsv" (unless the -P-1 option is used).

Command-line tools

Knoodle ships three command-line knot tools — knoodlesimplify, knoodledraw, and knoodleidentify — which are installed by the homebrew formula alongside PolyFold. They can also be compiled by running make in the tools subdirectory. The three tools share a common set of input formats and are designed to compose as Unix filters, so a typical pipeline looks like:

knoodlesimplify --streaming-mode < input.tsv | knoodledraw
generator | knoodleidentify

Input formats

All three tools auto-detect their input. You can give a tool a single file, several files, an entire directory of files, or pipe data to it on stdin. The recognized formats are tsv files with varying number of columns:

ColumnsMeaning
4unsigned PD code (4 arc labels per crossing)
5signed PD code (4 arcs + handedness)
6unsigned PD code + link-component colors
7signed PD code + link-component colors
33D geometry (x, y, z coordinates)

and also .kndlxyz files, which describe a multi-component 3D link embedding as a collection of polylines. .kndlxyz is the multi-component extension of the 3-column 3D geometry format. It is plain text in which each non-blank line is one vertex, given as three whitespace-separated real numbers:

  <x>  <y>  <z>

A block of consecutive vertex lines describes a single closed polygonal link component (the last vertex is joined back to the first). A blank line separates one component from the next, so a file with k blank-line-delimited blocks is a k-component link. Components are numbered/colored in the order they appear (0, 1, 2, …). The geometry is projected to a diagram the same way as 3-column input — by default down the z-axis — so use --randomize-projection if any segments are vertical. A file containing only non-blank lines with coordinates is parsed as a knot (one-component link) as one would expect.

Within a file or stream, knots and connected summands are separated by lines containing k and s, exactly as they are in polyfold output (see the PolyFold section above). When the input is 3D geometry, the default projection is down the z-axis, so pass --randomize-projection if your geometry contains vertical segments.

knoodlesimplify

knoodlesimplify is a convenient interface to the knot simplifications in Knoodle. It reads diagrams (as PD codes or 3D polygons) and writes simplified PD codes. With --streaming-mode it reads from stdin and writes to stdout, so it can be dropped into a pipeline; it is also a quick and robust way to convert polygons to PD codes (use -s=0 to project a polygon to a PD code with no simplification).

Usage: knoodlesimplify [options] [input_files...]

Simplification options:
  -s=N, --simplify-level=N    Set simplification level:
                                0          No simplification (PD code only)
                                3          Simplify3 (Reidemeister I + II)
                                4          Simplify4 (+ path rerouting)
                                5          Simplify5 (+ summand detection)
                                6+/max/full/reapr
                                           Full Reapr pipeline (default)
  --max-reapr-attempts=K      Maximum iterations for Reapr (default: 25)
  --no-compaction             Skip compaction in OrthoDraw (Reapr only)
  --reapr-energy=E            Set Reapr energy function (Reapr only):
                                TV, Height, TV_MCF

Input options:
  --input=FILE                Specify input file (can use multiple times)
  --streaming-mode            Read from stdin, write to stdout
  --randomize-projection      Apply random shear to 3D geometry projection

Output options:
  --output=FILE               Write all output to FILE
  -q, --quiet                 Suppress per-knot reports, show counter only

Other:
  -h, --help                  Show this help message

knoodledraw

knoodledraw reads knot/link diagrams and produces ASCII-art (or Unicode box-drawing) pictures of them. It is a Unix filter: with no input files it reads from stdin, so it pairs naturally with knoodlesimplify. Labels for crossings, arcs, faces, and link components can be combined (e.g. -calf), and the layout, quality, and highlighting are all tunable.

Usage: knoodledraw [options] [input_files...]

Reads knot/link diagrams and produces ASCII art drawings.
If no input files are given, reads from stdin (Unix filter mode).

Quality presets:
  --quality=PRESET            fast, default, best, debug

Grid and spacing:
  --x-grid-size=N             Horizontal grid size (default: 4/6/8 for 0/1/2+ labels)
  --y-grid-size=N             Vertical grid size (default: 2/3/4 for 0/1/2+ labels)
  --x-gap-size=N              Horizontal gap size (default: 1)
  --y-gap-size=N              Vertical gap size (default: 1)
  --x-rounding-radius=N       Horizontal rounding radius (default: 4)
  --y-rounding-radius=N       Vertical rounding radius (default: 4)

Label options (combinable, e.g. -calf):
  -c, --label-crossings       Show crossing numbers (0-based)
  -a, --label-arcs            Show arc numbers (0-based)
  -f, --label-faces           Show face numbers (0-based)
  -l, --label-components      Color/label link components

Output options:
  --ascii                     Use plain ASCII output (default: Unicode box-drawing)
  --highlight=ELEMENTS        Highlight elements (a=arc, c=crossing, f=face)
                              e.g. --highlight="a0,c3,f2"; multiple flags allowed
  --checkerboard-coloring     Highlight alternating faces (checkerboard pattern)

Algorithm options:
  --bend-method=METHOD        mcf (default), clp
  --compaction=METHOD         topo-number, topo-order, length-mcf (default),
                              length-clp, area-clp
  --randomize-bends=N         [experimental] Randomization rounds (default: 0)

Boolean tuning (--flag / --no-flag):
  redistribute-bends (on)     Redistribute bends after optimization
  turn-regularize (on)        Regularize turns
  saturate-regions (on)       Saturate regions
  saturate-exterior (on)      Saturate exterior region
  filter-saturating-edges (on) Filter saturating edges
  randomize-virtual-edges (off) Randomize virtual edges
  dual-simplex (off)          Use dual simplex method

Input options:
  --randomize-projection      Apply random shear to 3D geometry projection

Other:
  -h, --help                  Show this help message

Examples:

  knoodlesimplify --streaming-mode < input.tsv | knoodledraw
  knoodledraw diagram.tsv
  knoodledraw --quality=fast --ascii diagram.tsv
  knoodledraw --quality=debug --ascii diagram.tsv

knoodleidentify

knoodleidentify identifies the knot type of each input diagram by looking it up in the Knoodle Knot Lookup Table (KLUT). It reads raw diagrams (the same formats as knoodlesimplify) and simplifies them internally — so feed it the same stream you would feed knoodlesimplify, not the output of knoodlesimplify. For each input it decomposes the knot into prime summands, simplifies (escalating with ReAPR when needed), and looks each summand up, writing one line per knot.

By default each line is a Wolfram Language association mapping each distinct prime summand to its multiplicity, which parses directly via ToExpression, e.g.

<| KnotSymbol[3,1,True,"e/r"] -> 2, KnotSymbol[5,1,True,"m/mr"] -> 1 |> An unknot yields <||>. A summand that cannot be placed in the table carries its signed PD code for offline analysis (e.g. Unidentified[15, {{1,2,3,4,-1}, ...}]).

Usage: knoodleidentify [options] [input_files...]

Examples:
  generator | knoodleidentify        # identify a piped stream of diagrams
  knoodleidentify diagrams.tsv       # identify diagrams from a file
  knoodleidentify                    # read diagrams from the terminal (Ctrl-D)

Options:
  --data-dir=PATH     KLUT data directory containing Klut_Keys_NN.bin
                      and Klut_Values_NN.tsv. Default: $KNOODLE_KLUT_DIR,
                      else data/Klut next to this executable's parent,
                      else ./data/Klut.
  --max-crossings=N   Use subtables up to N crossings (3-13, default 13).
  --expanded          One line per knot, summands joined by ' # ' (uses
                      the raw K[...] table names).
  --tsv               Per-summand output: knot_index, summand_index,
                      crossing_count, name (tab-separated).
  --quiet             Suppress the stderr summary and per-summand warnings.
  -h, --help          Show this help.

The knot-symbol forms (in the default and --tsv output) are: KnotSymbol[c,i,a,"sym"] for an identified knot (c crossings, index i, alternating flag a, symmetry coset "sym"); Unidentified[N,PD] for a diagram with more than 13 crossings (over the table range); NotFound[N,PD] for a diagram of 13 or fewer crossings left unresolved after ReAPR (this should not happen); Link[N] for multi-component input (the table is knots-only); and Invalid[] for an invalid diagram or internal error. Unknot summands are the connect-sum identity and are omitted.