mapFolding 0.8.1__tar.gz → 0.8.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mapfolding-0.8.1 → mapfolding-0.8.2}/PKG-INFO +54 -30
- mapfolding-0.8.2/README.md +138 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/basecamp.py +2 -2
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/beDRY.py +24 -31
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/oeis.py +2 -2
- mapfolding-0.8.2/mapFolding/reference/__init__.py +38 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/reference/flattened.py +20 -2
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/reference/hunterNumba.py +24 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/reference/irvineJavaPort.py +12 -0
- mapfolding-0.8.1/mapFolding/reference/jax.py → mapfolding-0.8.2/mapFolding/reference/jaxCount.py +46 -27
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/reference/lunnanNumpy.py +16 -1
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/reference/lunnanWhile.py +15 -1
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/reference/rotatedEntryPoint.py +18 -0
- mapfolding-0.8.2/mapFolding/reference/total_countPlus1vsPlusN.py +234 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +5 -8
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/someAssemblyRequired/transformDataStructures.py +10 -4
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/someAssemblyRequired/transformationTools.py +19 -28
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/theSSOT.py +70 -121
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding.egg-info/PKG-INFO +54 -30
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding.egg-info/SOURCES.txt +1 -1
- {mapfolding-0.8.1 → mapfolding-0.8.2}/pyproject.toml +1 -1
- {mapfolding-0.8.1 → mapfolding-0.8.2}/tests/conftest.py +43 -33
- {mapfolding-0.8.1 → mapfolding-0.8.2}/tests/test_computations.py +7 -7
- {mapfolding-0.8.1 → mapfolding-0.8.2}/tests/test_other.py +2 -2
- mapfolding-0.8.1/README.md +0 -114
- mapfolding-0.8.1/mapFolding/reference/total_countPlus1vsPlusN.py +0 -211
- mapfolding-0.8.1/tests/__init__.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/LICENSE +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/__init__.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/filesystem.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/noHomeYet.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/py.typed +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/someAssemblyRequired/__init__.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/someAssemblyRequired/getLLVMforNoReason.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/someAssemblyRequired/ingredientsNumba.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/syntheticModules/numbaCount_doTheNeedful.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding/theDao.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding.egg-info/dependency_links.txt +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding.egg-info/entry_points.txt +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding.egg-info/requires.txt +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/mapFolding.egg-info/top_level.txt +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/setup.cfg +0 -0
- {mapfolding-0.8.1/mapFolding/reference → mapfolding-0.8.2/tests}/__init__.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/tests/test_filesystem.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/tests/test_oeis.py +0 -0
- {mapfolding-0.8.1 → mapfolding-0.8.2}/tests/test_tasks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mapFolding
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
4
4
|
Summary: Map folding algorithm with code transformation framework for optimizing numerical computations
|
|
5
5
|
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
6
|
License: CC-BY-NC-4.0
|
|
@@ -99,51 +99,75 @@ Available OEIS sequences:
|
|
|
99
99
|
A195646: Number of ways of folding a 3 X 3 X ... X 3 n-dimensional map.
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
### 2. **Algorithm Zoo** 🦒
|
|
102
|
+
### 2. **Algorithm Zoo: A Historical and Performance Journey** 🦒
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
- The /reference directory.
|
|
106
|
-
- **Numba-JIT Accelerated**: Up to 1000× faster than pure Python ([benchmarks](https://github.com/hunterhogan/mapFolding/blob/mapFolding/notes/Speed%20highlights.md))
|
|
104
|
+
This package offers a comprehensive collection of map folding algorithm implementations that showcase its evolution from historical origins to high-performance computation:
|
|
107
105
|
|
|
108
|
-
|
|
106
|
+
- **Historical Implementations**:
|
|
107
|
+
- Carefully restored versions of Lunnon's 1971 original [algorithm](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt) with corrections
|
|
108
|
+
- Atlas Autocode reconstruction in the `reference/foldings.AA` file
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
- **Direct Translations**:
|
|
111
|
+
- Python translations following the original control flow (`lunnanWhile.py`)
|
|
112
|
+
- NumPy-based vectorized implementations (`lunnanNumpy.py`)
|
|
111
113
|
|
|
112
|
-
- **
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
- Just-in-time compilation with Numba and various optimization profiles
|
|
117
|
-
- LLVM IR extraction for low-level algorithmic analysis
|
|
114
|
+
- **Modern Implementations**:
|
|
115
|
+
- Java port adaptations (`irvineJavaPort.py`) providing cleaner procedural implementations
|
|
116
|
+
- Experimental JAX version (`jaxCount.py`) exploring GPU acceleration potential
|
|
117
|
+
- Semantically decomposed version (`flattened.py`) with clear function boundaries
|
|
118
118
|
|
|
119
|
-
- **
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
- Development of specialized algorithms for specific map dimensions
|
|
119
|
+
- **Performance Optimized**:
|
|
120
|
+
- Numba-JIT accelerated implementations up to 1000× faster than pure Python (see [benchmarks](https://github.com/hunterhogan/mapFolding/blob/mapFolding/notes/Speed%20highlights.md))
|
|
121
|
+
- Algorithmic optimizations showcasing subtle yet powerful performance differences (`total_countPlus1vsPlusN.py`)
|
|
123
122
|
|
|
124
|
-
|
|
123
|
+
The `reference` directory serves as both a historical archive and an educational resource for understanding algorithm evolution.
|
|
125
124
|
|
|
126
|
-
|
|
125
|
+
### 3. **Algorithmic Transformation: From Readability to Speed** 🔬
|
|
127
126
|
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
The package provides a sophisticated transformation framework that bridges the gap between human-readable algorithms and high-performance computation:
|
|
128
|
+
|
|
129
|
+
- **Core Algorithm Understanding**:
|
|
130
|
+
- Study the functional state-transformation approach in `theDao.py` with clear, isolated functions
|
|
131
|
+
- Explore the semantic decomposition in `reference/flattened.py` to understand algorithm sections
|
|
132
|
+
|
|
133
|
+
- **Code Transformation Pipeline**:
|
|
134
|
+
- **AST Manipulation**: Analyzes and transforms the algorithm's abstract syntax tree
|
|
135
|
+
- **Dataclass "Shattering"**: Decomposes complex state objects into primitive components
|
|
136
|
+
- **Optimization Applications**: Applies domain-specific optimizations for numerical computation
|
|
137
|
+
- **LLVM Integration**: Extracts LLVM IR for low-level algorithmic analysis
|
|
138
|
+
|
|
139
|
+
- **Performance Breakthroughs**:
|
|
140
|
+
- Learn why nearly identical algorithms can have dramatically different performance (`total_countPlus1vsPlusN.py`)
|
|
141
|
+
- See how memory layout and increment strategy impact computation speed
|
|
142
|
+
- Understand the batching technique that yields order-of-magnitude improvements
|
|
143
|
+
|
|
144
|
+
### 4. **Multi-Level Architecture: From Simple API to Full Customization**
|
|
145
|
+
|
|
146
|
+
The package's architecture supports multiple levels of engagement:
|
|
147
|
+
|
|
148
|
+
- **Basic Usage**:
|
|
149
|
+
- Work with the high-level API in `basecamp.py` for standard computations
|
|
150
|
+
- Access OEIS sequence calculations with minimal code
|
|
151
|
+
|
|
152
|
+
- **Algorithm Exploration**:
|
|
153
|
+
- Compare different implementations in the `reference` directory to understand trade-offs
|
|
130
154
|
- Modify the core algorithm in `theDao.py` while preserving its functional approach
|
|
131
155
|
- Configure system-wide settings in `theSSOT.py` to adjust data types and performance characteristics
|
|
132
|
-
- Use utility functions in `beDRY.py` for common operations
|
|
133
156
|
|
|
134
157
|
- **Advanced Transformation**:
|
|
135
|
-
-
|
|
136
|
-
|
|
137
|
-
- `
|
|
138
|
-
- `
|
|
139
|
-
- `
|
|
158
|
+
- Use the `someAssemblyRequired` package to transform algorithms at the AST level
|
|
159
|
+
- Create optimized variants with different compilation settings using:
|
|
160
|
+
- `transformationTools.py` for AST manipulation
|
|
161
|
+
- `transformDataStructures.py` for complex data structure transformations
|
|
162
|
+
- `ingredientsNumba.py` for Numba-specific optimization profiles
|
|
163
|
+
- `synthesizeNumbaFlow.py` to orchestrate the transformation process
|
|
140
164
|
|
|
141
165
|
- **Custom Deployment**:
|
|
142
166
|
- Generate specialized implementations for specific dimensions
|
|
143
|
-
- Create optimized modules
|
|
144
|
-
- Extract LLVM IR for further analysis
|
|
167
|
+
- Create optimized standalone modules for production use
|
|
168
|
+
- Extract LLVM IR for further analysis and optimization
|
|
145
169
|
|
|
146
|
-
The package's multi-level design allows you to start with simple API calls and progressively
|
|
170
|
+
The package's multi-level design allows you to start with simple API calls and progressively explore deeper optimization techniques as your computational needs grow.
|
|
147
171
|
|
|
148
172
|
## Map-folding Video
|
|
149
173
|
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# mapFolding: Algorithms for enumerating distinct map/stamp folding patterns 🗺️
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/mapFolding/)
|
|
4
|
+
[](https://youtu.be/g6f_miE91mk&t=4)
|
|
5
|
+
[](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
|
|
6
|
+

|
|
7
|
+
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pip install mapFolding
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`OEIS_for_n` will run a computation from the command line.
|
|
18
|
+
|
|
19
|
+
```cmd
|
|
20
|
+
(mapFolding) C:\apps\mapFolding> OEIS_for_n A001418 5
|
|
21
|
+
186086600 distinct folding patterns.
|
|
22
|
+
Time elapsed: 1.605 seconds
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Use `mapFolding.oeisIDfor_n()` to compute a(n) for an OEIS ID.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from mapFolding import oeisIDfor_n
|
|
29
|
+
foldsTotal = oeisIDfor_n( 'A001418', 4 )
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
### 1. Simple, easy usage based on OEIS IDs
|
|
37
|
+
|
|
38
|
+
`mapFolding` directly implements some IDs from [_The On-Line Encyclopedia of Integer Sequences_](https://oeis.org/) ([BibTex](https://github.com/hunterhogan/mapFolding/blob/main/citations/oeis.bibtex) citation).
|
|
39
|
+
|
|
40
|
+
Use `getOEISids` to get the most up-to-date list of available OEIS IDs.
|
|
41
|
+
|
|
42
|
+
```cmd
|
|
43
|
+
(mapFolding) C:\apps\mapFolding> getOEISids
|
|
44
|
+
|
|
45
|
+
Available OEIS sequences:
|
|
46
|
+
A001415: Number of ways of folding a 2 X n strip of stamps.
|
|
47
|
+
A001416: Number of ways of folding a 3 X n strip of stamps.
|
|
48
|
+
A001417: Number of ways of folding a 2 X 2 X ... X 2 n-dimensional map.
|
|
49
|
+
A001418: Number of ways of folding an n X n sheet of stamps.
|
|
50
|
+
A195646: Number of ways of folding a 3 X 3 X ... X 3 n-dimensional map.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. **Algorithm Zoo: A Historical and Performance Journey** 🦒
|
|
54
|
+
|
|
55
|
+
This package offers a comprehensive collection of map folding algorithm implementations that showcase its evolution from historical origins to high-performance computation:
|
|
56
|
+
|
|
57
|
+
- **Historical Implementations**:
|
|
58
|
+
- Carefully restored versions of Lunnon's 1971 original [algorithm](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt) with corrections
|
|
59
|
+
- Atlas Autocode reconstruction in the `reference/foldings.AA` file
|
|
60
|
+
|
|
61
|
+
- **Direct Translations**:
|
|
62
|
+
- Python translations following the original control flow (`lunnanWhile.py`)
|
|
63
|
+
- NumPy-based vectorized implementations (`lunnanNumpy.py`)
|
|
64
|
+
|
|
65
|
+
- **Modern Implementations**:
|
|
66
|
+
- Java port adaptations (`irvineJavaPort.py`) providing cleaner procedural implementations
|
|
67
|
+
- Experimental JAX version (`jaxCount.py`) exploring GPU acceleration potential
|
|
68
|
+
- Semantically decomposed version (`flattened.py`) with clear function boundaries
|
|
69
|
+
|
|
70
|
+
- **Performance Optimized**:
|
|
71
|
+
- Numba-JIT accelerated implementations up to 1000× faster than pure Python (see [benchmarks](https://github.com/hunterhogan/mapFolding/blob/mapFolding/notes/Speed%20highlights.md))
|
|
72
|
+
- Algorithmic optimizations showcasing subtle yet powerful performance differences (`total_countPlus1vsPlusN.py`)
|
|
73
|
+
|
|
74
|
+
The `reference` directory serves as both a historical archive and an educational resource for understanding algorithm evolution.
|
|
75
|
+
|
|
76
|
+
### 3. **Algorithmic Transformation: From Readability to Speed** 🔬
|
|
77
|
+
|
|
78
|
+
The package provides a sophisticated transformation framework that bridges the gap between human-readable algorithms and high-performance computation:
|
|
79
|
+
|
|
80
|
+
- **Core Algorithm Understanding**:
|
|
81
|
+
- Study the functional state-transformation approach in `theDao.py` with clear, isolated functions
|
|
82
|
+
- Explore the semantic decomposition in `reference/flattened.py` to understand algorithm sections
|
|
83
|
+
|
|
84
|
+
- **Code Transformation Pipeline**:
|
|
85
|
+
- **AST Manipulation**: Analyzes and transforms the algorithm's abstract syntax tree
|
|
86
|
+
- **Dataclass "Shattering"**: Decomposes complex state objects into primitive components
|
|
87
|
+
- **Optimization Applications**: Applies domain-specific optimizations for numerical computation
|
|
88
|
+
- **LLVM Integration**: Extracts LLVM IR for low-level algorithmic analysis
|
|
89
|
+
|
|
90
|
+
- **Performance Breakthroughs**:
|
|
91
|
+
- Learn why nearly identical algorithms can have dramatically different performance (`total_countPlus1vsPlusN.py`)
|
|
92
|
+
- See how memory layout and increment strategy impact computation speed
|
|
93
|
+
- Understand the batching technique that yields order-of-magnitude improvements
|
|
94
|
+
|
|
95
|
+
### 4. **Multi-Level Architecture: From Simple API to Full Customization**
|
|
96
|
+
|
|
97
|
+
The package's architecture supports multiple levels of engagement:
|
|
98
|
+
|
|
99
|
+
- **Basic Usage**:
|
|
100
|
+
- Work with the high-level API in `basecamp.py` for standard computations
|
|
101
|
+
- Access OEIS sequence calculations with minimal code
|
|
102
|
+
|
|
103
|
+
- **Algorithm Exploration**:
|
|
104
|
+
- Compare different implementations in the `reference` directory to understand trade-offs
|
|
105
|
+
- Modify the core algorithm in `theDao.py` while preserving its functional approach
|
|
106
|
+
- Configure system-wide settings in `theSSOT.py` to adjust data types and performance characteristics
|
|
107
|
+
|
|
108
|
+
- **Advanced Transformation**:
|
|
109
|
+
- Use the `someAssemblyRequired` package to transform algorithms at the AST level
|
|
110
|
+
- Create optimized variants with different compilation settings using:
|
|
111
|
+
- `transformationTools.py` for AST manipulation
|
|
112
|
+
- `transformDataStructures.py` for complex data structure transformations
|
|
113
|
+
- `ingredientsNumba.py` for Numba-specific optimization profiles
|
|
114
|
+
- `synthesizeNumbaFlow.py` to orchestrate the transformation process
|
|
115
|
+
|
|
116
|
+
- **Custom Deployment**:
|
|
117
|
+
- Generate specialized implementations for specific dimensions
|
|
118
|
+
- Create optimized standalone modules for production use
|
|
119
|
+
- Extract LLVM IR for further analysis and optimization
|
|
120
|
+
|
|
121
|
+
The package's multi-level design allows you to start with simple API calls and progressively explore deeper optimization techniques as your computational needs grow.
|
|
122
|
+
|
|
123
|
+
## Map-folding Video
|
|
124
|
+
|
|
125
|
+
~~This caused my neurosis:~~ I enjoyed the following video, which is what introduced me to map folding.
|
|
126
|
+
|
|
127
|
+
"How Many Ways Can You Fold a Map?" by Physics for the Birds, 2024 November 13 ([BibTex](https://github.com/hunterhogan/mapFolding/blob/main/citations/Physics_for_the_Birds.bibtex) citation)
|
|
128
|
+
|
|
129
|
+
[](https://www.youtube.com/watch?v=sfH9uIY3ln4)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## My recovery
|
|
134
|
+
|
|
135
|
+
[](https://HunterThinks.com/support)
|
|
136
|
+
[](https://www.youtube.com/@HunterHogan)
|
|
137
|
+
|
|
138
|
+
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
@@ -15,7 +15,7 @@ implementation, and optional persistence of results.
|
|
|
15
15
|
from collections.abc import Sequence
|
|
16
16
|
from mapFolding.beDRY import outfitCountFolds, setCPUlimit, validateListDimensions
|
|
17
17
|
from mapFolding.filesystem import getPathFilenameFoldsTotal, saveFoldsTotal
|
|
18
|
-
from mapFolding.theSSOT import ComputationState, getPackageDispatcher
|
|
18
|
+
from mapFolding.theSSOT import ComputationState, getPackageDispatcher, The
|
|
19
19
|
from os import PathLike
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
|
|
@@ -54,7 +54,7 @@ def countFolds(listDimensions: Sequence[int]
|
|
|
54
54
|
If you want to compute a large `foldsTotal`, dividing the computation into tasks is usually a bad idea. Dividing the algorithm into tasks is inherently inefficient: efficient division into tasks means there would be no overlap in the work performed by each task. When dividing this algorithm, the amount of overlap is between 50% and 90% by all tasks: at least 50% of the work done by every task must be done by _all_ tasks. If you improve the computation time, it will only change by -10 to -50% depending on (at the very least) the ratio of the map dimensions and the number of leaves. If an undivided computation would take 10 hours on your computer, for example, the computation will still take at least 5 hours but you might reduce the time to 9 hours. Most of the time, however, you will increase the computation time. If logicalCores >= leavesTotal, it will probably be faster. If logicalCores <= 2 * leavesTotal, it will almost certainly be slower for all map dimensions.
|
|
55
55
|
"""
|
|
56
56
|
mapShape: tuple[int, ...] = validateListDimensions(listDimensions)
|
|
57
|
-
concurrencyLimit: int = setCPUlimit(CPUlimit)
|
|
57
|
+
concurrencyLimit: int = setCPUlimit(CPUlimit, The.concurrencyPackage)
|
|
58
58
|
computationStateInitialized: ComputationState = outfitCountFolds(mapShape, computationDivisions, concurrencyLimit)
|
|
59
59
|
|
|
60
60
|
dispatcherCallableProxy = getPackageDispatcher()
|
|
@@ -15,12 +15,15 @@ particularly for initializing computation state, validating inputs, and creating
|
|
|
15
15
|
structures needed by the folding algorithms.
|
|
16
16
|
"""
|
|
17
17
|
from collections.abc import Sequence
|
|
18
|
-
from mapFolding.theSSOT import
|
|
18
|
+
from mapFolding.theSSOT import ComputationState
|
|
19
|
+
from numpy import dtype as numpy_dtype, integer, ndarray
|
|
19
20
|
from sys import maxsize as sysMaxsize
|
|
20
|
-
from typing import Any
|
|
21
|
+
from typing import Any, TypeVar
|
|
21
22
|
from Z0Z_tools import defineConcurrencyLimit, intInnit, oopsieKwargsie
|
|
22
23
|
import numpy
|
|
23
24
|
|
|
25
|
+
numpyIntegerType = TypeVar('numpyIntegerType', bound=integer[Any])
|
|
26
|
+
|
|
24
27
|
def getLeavesTotal(mapShape: tuple[int, ...]) -> int:
|
|
25
28
|
productDimensions = 1
|
|
26
29
|
for dimension in mapShape:
|
|
@@ -81,25 +84,16 @@ def getTaskDivisions(computationDivisions: int | str | None, concurrencyLimit: i
|
|
|
81
84
|
raise ValueError(f"Problem: `taskDivisions`, ({taskDivisions}), is greater than `leavesTotal`, ({leavesTotal}), which will cause duplicate counting of the folds.\n\nChallenge: you cannot directly set `taskDivisions` or `leavesTotal`. They are derived from parameters that may or may not still be named `computationDivisions`, `CPUlimit` , and `listDimensions` and from dubious-quality Python code.")
|
|
82
85
|
return int(max(0, taskDivisions))
|
|
83
86
|
|
|
84
|
-
def
|
|
85
|
-
"""An imperfect way to reduce code duplication."""
|
|
86
|
-
if 'numpy' == getDatatypePackage():
|
|
87
|
-
numpyDtype = datatype or getNumpyDtypeDefault()
|
|
88
|
-
else:
|
|
89
|
-
raise NotImplementedError("Somebody done broke it.")
|
|
90
|
-
return numpyDtype
|
|
91
|
-
|
|
92
|
-
def makeConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int, datatype: type[numpy.signedinteger[Any]] | None = None) -> Array3D:
|
|
93
|
-
numpyDtype = interpretParameter_datatype(datatype)
|
|
87
|
+
def makeConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int, datatype: type[numpyIntegerType]) -> ndarray[tuple[int, int, int], numpy_dtype[numpyIntegerType]]:
|
|
94
88
|
dimensionsTotal = len(mapShape)
|
|
95
|
-
cumulativeProduct = numpy.multiply.accumulate([1] + list(mapShape), dtype=
|
|
96
|
-
arrayDimensions = numpy.array(mapShape, dtype=
|
|
97
|
-
coordinateSystem = numpy.zeros((dimensionsTotal, leavesTotal + 1), dtype=
|
|
89
|
+
cumulativeProduct = numpy.multiply.accumulate([1] + list(mapShape), dtype=datatype)
|
|
90
|
+
arrayDimensions = numpy.array(mapShape, dtype=datatype)
|
|
91
|
+
coordinateSystem = numpy.zeros((dimensionsTotal, leavesTotal + 1), dtype=datatype)
|
|
98
92
|
for indexDimension in range(dimensionsTotal):
|
|
99
93
|
for leaf1ndex in range(1, leavesTotal + 1):
|
|
100
94
|
coordinateSystem[indexDimension, leaf1ndex] = (((leaf1ndex - 1) // cumulativeProduct[indexDimension]) % arrayDimensions[indexDimension] + 1)
|
|
101
95
|
|
|
102
|
-
connectionGraph = numpy.zeros((dimensionsTotal, leavesTotal + 1, leavesTotal + 1), dtype=
|
|
96
|
+
connectionGraph = numpy.zeros((dimensionsTotal, leavesTotal + 1, leavesTotal + 1), dtype=datatype)
|
|
103
97
|
for indexDimension in range(dimensionsTotal):
|
|
104
98
|
for activeLeaf1ndex in range(1, leavesTotal + 1):
|
|
105
99
|
for connectee1ndex in range(1, activeLeaf1ndex + 1):
|
|
@@ -116,9 +110,8 @@ def makeConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int, datatype: t
|
|
|
116
110
|
connectionGraph[indexDimension, activeLeaf1ndex, connectee1ndex] = connectee1ndex + cumulativeProduct[indexDimension]
|
|
117
111
|
return connectionGraph
|
|
118
112
|
|
|
119
|
-
def makeDataContainer(shape: int | tuple[int, ...], datatype: type[
|
|
120
|
-
|
|
121
|
-
return numpy.zeros(shape, dtype=numpyDtype)
|
|
113
|
+
def makeDataContainer(shape: int | tuple[int, ...], datatype: type[numpyIntegerType]) -> ndarray[Any, numpy_dtype[numpyIntegerType]]:
|
|
114
|
+
return numpy.zeros(shape, dtype=datatype)
|
|
122
115
|
|
|
123
116
|
def outfitCountFolds(mapShape: tuple[int, ...], computationDivisions: int | str | None = None, concurrencyLimit: int = 1) -> ComputationState:
|
|
124
117
|
leavesTotal = getLeavesTotal(mapShape)
|
|
@@ -126,7 +119,7 @@ def outfitCountFolds(mapShape: tuple[int, ...], computationDivisions: int | str
|
|
|
126
119
|
computationStateInitialized = ComputationState(mapShape, leavesTotal, taskDivisions, concurrencyLimit)
|
|
127
120
|
return computationStateInitialized
|
|
128
121
|
|
|
129
|
-
def setCPUlimit(CPUlimit: Any | None) -> int:
|
|
122
|
+
def setCPUlimit(CPUlimit: Any | None, concurrencyPackage: str | None = None) -> int:
|
|
130
123
|
"""Sets CPU limit for concurrent operations.
|
|
131
124
|
|
|
132
125
|
If the concurrency is managed by `numba`, the maximum number of CPUs is retrieved from `numba.get_num_threads()` and not by polling the hardware. Therefore, if there are
|
|
@@ -154,17 +147,17 @@ def setCPUlimit(CPUlimit: Any | None) -> int:
|
|
|
154
147
|
if not (CPUlimit is None or isinstance(CPUlimit, (bool, int, float))):
|
|
155
148
|
CPUlimit = oopsieKwargsie(CPUlimit)
|
|
156
149
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
150
|
+
match concurrencyPackage:
|
|
151
|
+
case 'multiprocessing' | None:
|
|
152
|
+
# When to use multiprocessing.set_start_method https://github.com/hunterhogan/mapFolding/issues/6
|
|
153
|
+
concurrencyLimit: int = defineConcurrencyLimit(CPUlimit)
|
|
154
|
+
case 'numba':
|
|
155
|
+
from numba import get_num_threads, set_num_threads
|
|
156
|
+
concurrencyLimit = defineConcurrencyLimit(CPUlimit, get_num_threads())
|
|
157
|
+
set_num_threads(concurrencyLimit)
|
|
158
|
+
concurrencyLimit = get_num_threads()
|
|
159
|
+
case _:
|
|
160
|
+
raise NotImplementedError(f"I received {concurrencyPackage=} but I don't know what to do with that.")
|
|
168
161
|
return concurrencyLimit
|
|
169
162
|
|
|
170
163
|
def validateListDimensions(listDimensions: Sequence[int]) -> tuple[int, ...]:
|
|
@@ -16,7 +16,7 @@ literature and extend sequences beyond their currently known terms.
|
|
|
16
16
|
"""
|
|
17
17
|
from collections.abc import Callable
|
|
18
18
|
from datetime import datetime, timedelta
|
|
19
|
-
from mapFolding.theSSOT import
|
|
19
|
+
from mapFolding.theSSOT import The
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
from typing import Any, Final, TYPE_CHECKING
|
|
22
22
|
import argparse
|
|
@@ -38,7 +38,7 @@ cacheDays = 7
|
|
|
38
38
|
"""
|
|
39
39
|
Section: make `settingsOEIS`"""
|
|
40
40
|
|
|
41
|
-
pathCache: Path =
|
|
41
|
+
pathCache: Path = The.pathPackage / ".cache"
|
|
42
42
|
|
|
43
43
|
class SettingsOEIS(TypedDict):
|
|
44
44
|
description: str
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Historical and reference implementations of map-folding algorithms.
|
|
3
|
+
|
|
4
|
+
This directory contains various implementations of the map-folding algorithm,
|
|
5
|
+
serving both as historical references and as benchmarks for performance comparison.
|
|
6
|
+
These implementations range from direct translations of Lunnon's original 1971 code
|
|
7
|
+
to highly specialized versions using modern optimization techniques.
|
|
8
|
+
|
|
9
|
+
Categories of reference implementations:
|
|
10
|
+
|
|
11
|
+
1. Historical transcripts:
|
|
12
|
+
- foldings.txt - Original algorithm from Lunnon's 1971 paper
|
|
13
|
+
- foldings.AA - Reconstructed Atlas Autocode version with corrections
|
|
14
|
+
|
|
15
|
+
2. Direct translations:
|
|
16
|
+
- lunnanWhile.py - Python translation using while loops
|
|
17
|
+
- lunnanNumpy.py - NumPy-based translation with array operations
|
|
18
|
+
|
|
19
|
+
3. Alternative implementations:
|
|
20
|
+
- irvineJavaPort.py - Port from Sean A. Irvine's Java implementation
|
|
21
|
+
- hunterNumba.py - Numba-optimized implementation
|
|
22
|
+
- jaxCount.py - JAX implementation for GPU acceleration
|
|
23
|
+
- flattened.py - Semantically decomposed version with operation grouping
|
|
24
|
+
|
|
25
|
+
4. Specialized variants:
|
|
26
|
+
- total_countPlus1vsPlusN.py - Optimized counting with different increment strategies
|
|
27
|
+
- rotatedEntryPoint.py - Alternative entry point implementation (demonstration)
|
|
28
|
+
|
|
29
|
+
These reference implementations are valuable for:
|
|
30
|
+
- Understanding the algorithm's historical development
|
|
31
|
+
- Comparing performance characteristics across implementation strategies
|
|
32
|
+
- Studying optimization techniques and their effects
|
|
33
|
+
- Verifying the correctness of the core algorithm against known solutions
|
|
34
|
+
|
|
35
|
+
Note: These implementations are for reference only and not used in the production
|
|
36
|
+
code path of the package. The active implementation resides in theDao.py with
|
|
37
|
+
optimized variants generated by the someAssemblyRequired framework.
|
|
38
|
+
"""
|
|
@@ -1,5 +1,23 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""
|
|
2
|
+
Semantically decomposed implementation of Lunnon's algorithm with operation grouping.
|
|
3
|
+
|
|
4
|
+
This implementation restructures the map folding algorithm into semantic sections with
|
|
5
|
+
clear function boundaries, making the algorithm more readable and understandable. Each
|
|
6
|
+
operation is isolated into its own named function, providing a clear mapping between
|
|
7
|
+
the mathematical concepts and their implementation.
|
|
8
|
+
|
|
9
|
+
Key characteristics:
|
|
10
|
+
- Breaks down the algorithm into small, single-purpose functions
|
|
11
|
+
- Uses descriptive function names that explain what each part does
|
|
12
|
+
- Clearly separates logical sections of the algorithm
|
|
13
|
+
- Provides a more maintainable and educational view of the algorithm
|
|
14
|
+
- Uses Python's type hints for better code understanding
|
|
15
|
+
|
|
16
|
+
This implementation serves as a bridge between the historical implementations and the
|
|
17
|
+
modern functional approach used in the main package. It's particularly valuable for
|
|
18
|
+
understanding the algorithm's operation before diving into the highly optimized versions.
|
|
19
|
+
"""
|
|
20
|
+
|
|
3
21
|
from collections.abc import Sequence
|
|
4
22
|
from numpy import integer
|
|
5
23
|
from numpy.typing import NDArray
|
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
"""
|
|
2
|
+
High-performance Numba-accelerated implementation of Lunnon's algorithm.
|
|
3
|
+
|
|
4
|
+
This implementation focuses on maximum computational performance by leveraging Numba's
|
|
5
|
+
just-in-time (JIT) compilation capabilities to generate native machine code. It represents
|
|
6
|
+
a manually optimized version that served as inspiration for the automated transformation
|
|
7
|
+
framework in the someAssemblyRequired package.
|
|
8
|
+
|
|
9
|
+
Key characteristics:
|
|
10
|
+
- Optimized data structures using NumPy typed arrays with appropriate data types
|
|
11
|
+
- Function decorators for Numba JIT compilation with performance-oriented settings
|
|
12
|
+
- Memory-efficient implementation with careful type management
|
|
13
|
+
- Reduced Python overhead through native code execution
|
|
14
|
+
- Algorithmic optimizations tailored for numerical computation
|
|
15
|
+
|
|
16
|
+
Performance considerations:
|
|
17
|
+
- Up to 1000× faster than pure Python implementations
|
|
18
|
+
- Optimized for larger map dimensions where computational demands increase exponentially
|
|
19
|
+
- Incorporates lessons from multiple implementation strategies
|
|
20
|
+
|
|
21
|
+
Note: This serves as a reference for manually-optimized code before the development of
|
|
22
|
+
the automated transformation pipeline in the main package.
|
|
23
|
+
"""
|
|
24
|
+
|
|
1
25
|
from typing import Any
|
|
2
26
|
import numba
|
|
3
27
|
import numpy
|
|
@@ -2,8 +2,20 @@
|
|
|
2
2
|
Ported from the Java version by Sean A. Irvine:
|
|
3
3
|
https://github.com/archmageirvine/joeis/blob/80e3e844b11f149704acbab520bc3a3a25ac34ff/src/irvine/oeis/a001/A001415.java
|
|
4
4
|
|
|
5
|
+
This implementation is a conversion from a well-known Java implementation of Lunnon's algorithm
|
|
6
|
+
by Sean A. Irvine, a contributor to the OEIS project. It provides a clean, procedural implementation
|
|
7
|
+
with straightforward variable naming and control flow that may be more approachable for
|
|
8
|
+
programmers familiar with modern languages.
|
|
9
|
+
|
|
10
|
+
Key characteristics:
|
|
11
|
+
- Clear variable naming following modern programming conventions
|
|
12
|
+
- Procedural implementation style similar to Java but adapted for Python
|
|
13
|
+
- Follows the same algorithmic structure as Lunnon's original but with cleaner organization
|
|
14
|
+
- Uses primitive Python data structures (lists) without NumPy dependencies
|
|
15
|
+
|
|
5
16
|
Citation: https://github.com/hunterhogan/mapFolding/blob/134f2e6ecdf59fb6f6829c775475544a6aaaa800/citations/jOEIS.bibtex
|
|
6
17
|
"""
|
|
18
|
+
|
|
7
19
|
def foldings(p: list[int], res: int = 0, mod: int = 0) -> int:
|
|
8
20
|
"""
|
|
9
21
|
Compute the total number of foldings for a map with dimensions specified in p.
|