mapFolding
mapFolding is a typed Python research package for exact enumeration of map foldings, stamp foldings, semi-meanders, and meanders. It provides counting algorithms, access to their computation states, and tools for transforming readable algorithm source into specialized implementations.
A map-folding problem asks how many ways the labeled panels of a map can be stacked while preserving their connections. A strip of stamps is the one-dimensional case. Related meander problems count configurations of non-self-intersecting curves crossing a line or ray.
Earlier versions of this project computed the terms for 2 × 19 and 2 × 20 stamp strips, extending OEIS A001415.
Research with mapFolding
You can use the package to calculate sequence terms, dissect an algorithm's state, develop a different counting method, or study the effects of source transformations. The main routes through the code are:
| Work | Where to begin |
|---|---|
| Count foldings or meanders | basecamp.py selects an algorithm and prepares its state. |
| Work with integer sequences | oeis/ provides sequence dispatch, exact formula relationships, metadata, known values, and triangle utilities. |
| Inspect or change a computation | dataBaskets.py describes the state containers; algorithms/ contains source implementations. |
| Transform or specialize an algorithm | kitAST/ generates variants and jobs, with derived implementations in synthesized/. |
| Explore a different search strategy | _e/ contains elimination, constraint propagation, insertion, and search-space analysis. |
| Validate a new implementation | test_computations.py compares implementations with known sequence values. |
The module, function, and class docstrings explain parameters, state layouts, mathematical relationships, and implementation details. Use them when choosing an experiment or following a computation through the package.
Counting and sequence access
The main counting functions are in mapFolding.basecamp; sequence functions are in mapFolding.oeis.
| Task | Interface | Result |
|---|---|---|
| Count foldings for supplied dimensions | countFolds(mapShape, ...) |
Integer count |
| Count rotationally symmetric stamp foldings | countFoldsSymmetric(mapShape, ...) |
Integer count |
| Count semi-meanders, open meanders, or closed meanders | countMeanders(kind, n, ...) |
Completed StateMeanders |
| Calculate a supported OEIS term | oeisIDfor_n(oeisID, n, ...) |
Integer value of a(n) |
| Convert a folding-sequence index to dimensions | makeMapShape(oeisID, n) |
Dimension tuple |
| Retrieve known sequence values | getValuesKnown(oeisID) |
Dictionary of indices and values |
| Inspect sequence metadata | getMetadata(oeisID) |
Description, offset, known values, and row settings |
For example, (2, 6) describes a 2 × 6 map, and (2, 2, 2) describes a three-dimensional map with eight panels. Dimensions count panels along each axis.
Map dimensions and OEIS indices
| Sequence | Problem | mapShape at index n |
|---|---|---|
| A000136 | Strip of n labeled stamps |
(1, n) |
| A001415 | 2 × n strip |
(2, n) |
| A001416 | 3 × n strip |
(3, n) |
| A001417 | n-dimensional map with every dimension of length two |
(2,) * n |
| A195646 | n-dimensional map with every dimension of length three |
(3,) * n |
| A001418 | n × n sheet |
(n, n) |
| A007822 | Symmetric foldings of 2n + 1 stamps |
(1, 2 * n) |
For A007822, countFoldsSymmetric uses an even-length computational strip to count the symmetric foldings of the odd-length strip in the sequence description. makeMapShape supplies that computational shape.
Meanders and computation state
countMeanders('semi', n) computes A000682, and countMeanders('meanders', n) computes the open-meander sequence A005316. The 'closed' selector computes A005315 using the corresponding odd-index open-meander term.
The returned state retains the boundary position and transfer counts for inspection. Read the
completed count from its totalMeanders property:
state.totalMeanders
totalMeanders sums the active lookup counts and countAddend, which retains completed
contributions removed by pruning. The property reflects the current state; before counting finishes,
its value represents intermediate counts rather than the final sequence term.
You can also supply an existing StateMeanders through the state argument to continue that computation. See the state and counting-function docstrings for the relevant fields and behavior.
Sequence formulas and reference data
oeisIDfor_n dispatches to a folding, symmetric-folding, or meander algorithm, or to an exact formula connecting related sequences. For sequences with selectable identities, its f argument chooses a formula. The formulas and their docstrings are in oeis/byFormula.py.
The getOEISids console command lists registered sequences and usage examples. The registry also includes related sequences used as reference data; consult oeisIDfor_n and byFormula for computation support. The OEIS_for_n command evaluates a supported term from its sequence identifier and index.
OEIS metadata and b-files are loaded when the metadata module is imported. Local files have a 30-day freshness interval; missing or stale entries trigger a request to oeis.org, and stale data remains available if a refresh fails.
Algorithm experiments
The package includes several approaches to the same combinatorial problems:
- Map folding: insertion-search algorithms derived from Lunnon's work, including variants that apply symmetry restrictions from his theorems.
- Meanders: transfer-matrix counting based on Jensen's approach, with dictionary, NumPy, Pandas, Polars, and pruning variants.
- Permutation generation: stamp-folding and meander algorithms based on Sawada and Li's work, with experimental bilateral variants.
- Elimination: possible leaf positions, pile assignments, and constraint propagation in
mapFolding._e.
Counting entry points accept a flow preference. Omit it to use the default route. Available variants and dispatch rules change as the research develops; basecamp.py and the relevant easyRun runner show the current choices.
The transformation pipeline in kitAST can inline functions, decompose state dataclasses, specialize initialized values for a map shape, and prepare Numba or Linux Codon jobs. RecipeJob.py describes job configuration; easyRun/synthesizeModules.py coordinates module regeneration. For changes that should survive regeneration, edit the source algorithm or its transformation.
General-purpose transformation tools developed alongside this project live in astToolkit and astToolFactory. The transformations retained here serve mapFolding algorithms and jobs.
Computation cost and saved results
Exact enumeration becomes expensive quickly. Running time, memory use, and the appropriate implementation depend on the problem and its size; measure smaller cases before committing to a long computation.
Pass pathLikeWrite to a counting function to save the total. An existing directory receives a generated filename; an explicit filename is also supported. The destination is write-tested before counting, leaving a test value until the result replaces it. An existing target file is rejected. These output files save totals; they do not checkpoint a running search.
countFolds can divide work using an integer, computationDivisions='cpu', or computationDivisions='maximum'. Tasks repeat substantial preparatory work, so division can increase elapsed time. Leave computationDivisions=None unless task division is part of your experiment; see the function's docstring for the tradeoffs.
Repository guide
| Path | Contents |
|---|---|
mapFolding/dataStructures.py, theTypes.py, and theSSOT.py |
Array storage, domain types, and shared settings |
mapFolding/kitFilesystem.py |
Result files, caches, and computation-data storage |
mapFolding/jobs/ |
Computation jobs specialized for particular map shapes |
mapFolding/tests/ and mapFolding/_e/tests/ |
Correctness checks, dispatch and filesystem tests, and stored data samples |
easyRun/ |
Editable runners for computations, benchmarks, synthesis, and exploration |
mapFolding/_e/research/ and research/ |
Analysis tools, folding data, and research materials |
archive/ and development/ |
Historical code, notes, and development materials |
citations/ |
Software citation metadata and BibTeX references |
Citation and references
To cite this software, use CITATION.cff. The mathematical and implementation references below have BibTeX entries in citations/.
Folding and meander algorithms
- Albert Sadé (1949), Sur les Chevauchements des Permutations. PDF · BibTeX.
- John E. Koehler (1968), Folding a strip of stamps. DOI · BibTeX.
- W. F. Lunnon (1968), A map-folding problem. DOI · PDF · BibTeX.
- W. F. Lunnon (1971), Multi-dimensional map-folding. The basis for the multidimensional counting algorithms. DOI · PDF · BibTeX.
- Iwan Jensen (2000), A transfer matrix approach to the enumeration of plane meanders. The transfer-matrix method underlying the matrix-meander algorithms. DOI · Preprint · TeX source · BibTeX.
- Joe Sawada and Roy Li (2012), Stamp Foldings, Semi-Meanders, and Open Meanders: Fast Generation Algorithms. Permutation-based generation methods used in the experimental permutation algorithms. DOI · PDF · BibTeX.
- Stéphane Legendre (2014), Foldings and meanders. Relationships between folding and meander sequences, with folding-validity conditions. PDF · Preprint · TeX source · BibTeX.
Related research
- Nathan Clisby and Iwan Jensen (2012), A new transfer-matrix algorithm for exact enumerations: self-avoiding polygons on the square lattice. Further transfer-matrix techniques for exact counting, demonstrated on lattice polygons. DOI · Preprint · BibTeX.
- Yiyang Jia, Jun Mitani, and Ryuhei Uehara (2020), Valid Orderings of Layers When Simple-Folding a Map. A linear-time test for whether a supplied layer ordering is valid under simple folding, providing context for the role of the folding model in validity tests. DOI · Article and PDF · BibTeX.
Sequence data and other implementations
- The On-Line Encyclopedia of Integer Sequences. Sequence definitions, known values, formulas, and computation records. OEIS · BibTeX.
- jOEIS: Java Online Encyclopedia of Integer Sequences. Repository · Sean A. Irvine's A001415 implementation · BibTeX.
- Andrew Howroyd's meander implementation. C# source and description · BibTeX.
Installation
mapFolding requires Python 3.13 or newer. Install the published package from PyPI:
pip install mapFolding
NumPy and Numba are included in the base dependencies. Optional extras add other implementations and development tools:
| Extra | Purpose |
|---|---|
pandas |
Pandas and Arrow meander implementations |
polars |
Polars meander implementation |
codon |
Codon-compiled jobs on Linux |
ortools |
Experimental constraint propagation; installed only on Python versions below 3.15 |
testing |
Test dependencies and optional implementations exercised by the tests |
development |
Profiling, notebooks, type stubs, and development tools |
For example:
pip install "mapFolding[pandas,polars]"
Development and supplemental materials
Clone the repository to work on the algorithms or access its archives, notes, and research materials:
git clone https://github.com/hunterhogan/mapFolding.git
cd mapFolding
python -m venv .venv
Activate the environment before installing. On PowerShell:
. .\.venv\Scripts\Activate.ps1
$env:PYTHONUTF8 = '1'
$env:PYTHONIOENCODING = 'utf-8'
On a POSIX shell:
. .venv/bin/activate
Then install the development and testing extras:
pip install -e ".[development,testing]"
Run project commands from the repository root with the environment active. For example, to check the main counting implementations:
pytest mapFolding/tests/test_computations.py
The tests compare algorithm variants with known OEIS values and exercise generated jobs. When adding a counting implementation, extend the relevant test cases in test_computations.py; supporting behavior has its own tests in mapFolding/tests and mapFolding/_e/tests.
Computation targets
These are my computation plans and estimates for my hardware, including work with unpublished algorithms.
- Folds of multidimensional map (2, 2, 2, 2, 2, 2, 2, 2), which is A001417(8): estimated 14 days with my current hardware and a non-published algorithm.
- Folds of multidimensional map (2, 21), which is A001415(21): estimated 6 days with my current hardware and one of the compiled "Theorem 2" algorithm versions.
- Folds of multidimensional map (2, 22), which is A001415(22): estimated 15 days with my current hardware and one of the compiled "Theorem 2" algorithm versions.
- Folds of multidimensional map (3, 15), which is A001416(15): estimated 11 days with my current hardware and one of the compiled "Theorem 2" algorithm versions.
- Semi-meanders with 50 crossings, which is A000682(50): estimated 1–2 hours if I had 64 GB of system memory.
Computation times assume:
- No power interruptions. (I don't have a UPS, and in the last two months the longest gap between power interruptions was 8 days 6 hours.)
- No system crashes.
- Single-core computations are given priority over other tasks.
- The core of single-core computations is regularly boosted.
- No heat issues.
Maintainer's working notes
This is my ongoing to-do list across this package and related projects. It records experiments, unresolved problems, and reminders to myself.
- Acceleration
- Codon: new release, new features.
- Remote execution
- Google Colab: memmap causes everything to go to "disk" and the physical memory is unused.
- GitHub Codespaces: ignores memmap and terminates on OOM.
- astToolkit: figure out a better container system than Ingredients Module, Ingredients Function, etc.
- Dao of map folding
- Overhaul how I store and access type metadata for ndarray and other containers. Affects:
- StateMapFolding
- Shatter dataclass
- ast transformations
- Run 2^8 without a crash or power outage.
- Compute (2, 21), (2, 22), and (3, 15).
- Overhaul how I store and access type metadata for ndarray and other containers. Affects:
- Symmetric 1xn
- Symmetry algorithm is too slow.
- Asynchronous + accelerated doesn't work yet.
- Matrix Meanders
- I need a lot more tools in kitAST.
- I hate
getTotalBucketsbut it should be a brilliant function.
- Permutations
- The base algorithm is a dumpster fire.
- Bilateral concurrent can't produce a folding, but uses too much memory and is too slow to count folds.
- Reduce arches: slower than counting by hand.
- _e
- Constraint propagation or SAT
- ortools won't apply concurrency, and I don't know how to think about divisions of the problem space that actually reduce computation time.
- Understanding other packages is harder than a self-enema with a firehouse.
- 2^n-dimensional (aka elimination by crease)
- Computation algorithms needed for: conditional predecessors, conditional successors, DomainLeaf首零Plus零 in dimension零, the range of a pile (aka pile options, aka choices leaf), pinPile二ByCrease, pinPile二Ante首ByCrease, and pinPile零Ante首零AfterDepth4.
- Acceleration.
- Bug in
boxOfFunctionsReduction2上nDimensional. - Finish collecting 2^7 data.
- Fastest algorithm for 2^5. Can't complete 2^6. I mean, wtf?
PermutationSpaceand its OOP structure: I don't really know what I am doing.- The reduce-it concept is strong: reorient more code around it. Resolve the tension with
PermutationSpace._solidifyLeafSpace().
- Elimination: atrophied.
- Insert leaves: But for the data storage, it would be powerful. IDK anything about data compression. I lost the code I wrote for the notation I created to store graphs, and it seems I am too stupid to recreate or reverse engineer my own code from my own files AND OTHER FUNCTIONS. fml. Ironically, LLMs can't figure it out either because I guess my idea was novel. F.M.L.
- Constraint propagation or SAT
Hunter, this list is incomplete: you quit writing after you got upset. Resume at mapFolding.kitAST.
My recovery
Metadata
Release files for mapFolding 0.37.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mapfolding-0.37.2.tar.gz | 447.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mapfolding-0.37.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.0 MB
Release files / mapfolding-0.37.2.tar.gz
| Download URL | mapfolding-0.37.2.tar.gz |
|---|---|
| Size | 447.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ee2c258e0d9084f2dcebf57292763f234bc4f204c12500b79db4600448f67716
|
|
BLAKE2b-256 checksum How to use checksums |
372ec867287da3e2f68279c440910cf39b5a74e25c7bac9e4edb010b42f2f2ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / mapfolding-0.37.2-py3-none-any.whl
| Download URL | mapfolding-0.37.2-py3-none-any.whl |
|---|---|
| Size | 553.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c6ff014a980d73949fec06769611dfed134db4d50409c95c756f2b77da0d8ba5
|
|
BLAKE2b-256 checksum How to use checksums |
5f44854e8fe0c925be93a714e61676898ee7afef3953c72bdb0fd89ee3009d58
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|