mapFolding 0.7.1__py3-none-any.whl → 0.8.1__py3-none-any.whl
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/__init__.py +33 -4
- mapFolding/basecamp.py +14 -0
- mapFolding/beDRY.py +93 -82
- mapFolding/filesystem.py +124 -90
- mapFolding/noHomeYet.py +14 -2
- mapFolding/oeis.py +18 -3
- mapFolding/reference/flattened.py +46 -45
- mapFolding/reference/hunterNumba.py +4 -4
- mapFolding/reference/irvineJavaPort.py +1 -1
- mapFolding/reference/lunnanNumpy.py +3 -4
- mapFolding/reference/lunnanWhile.py +5 -7
- mapFolding/reference/rotatedEntryPoint.py +2 -3
- mapFolding/someAssemblyRequired/__init__.py +33 -3
- mapFolding/someAssemblyRequired/getLLVMforNoReason.py +32 -15
- mapFolding/someAssemblyRequired/ingredientsNumba.py +108 -2
- mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +196 -0
- mapFolding/someAssemblyRequired/{synthesizeNumbaJob.py → synthesizeNumbaJobVESTIGIAL.py} +19 -23
- mapFolding/someAssemblyRequired/transformDataStructures.py +162 -0
- mapFolding/someAssemblyRequired/transformationTools.py +607 -252
- mapFolding/syntheticModules/numbaCount_doTheNeedful.py +197 -12
- mapFolding/theDao.py +37 -16
- mapFolding/theSSOT.py +47 -44
- {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info}/METADATA +51 -46
- mapfolding-0.8.1.dist-info/RECORD +39 -0
- {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info}/WHEEL +1 -1
- tests/conftest.py +2 -3
- tests/test_filesystem.py +0 -2
- tests/test_other.py +2 -3
- tests/test_tasks.py +0 -4
- mapFolding/reference/lunnan.py +0 -153
- mapFolding/someAssemblyRequired/Z0Z_workbench.py +0 -33
- mapFolding/someAssemblyRequired/synthesizeCountingFunctions.py +0 -7
- mapFolding/someAssemblyRequired/synthesizeDataConverters.py +0 -135
- mapFolding/someAssemblyRequired/synthesizeNumba.py +0 -91
- mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +0 -91
- mapFolding/someAssemblyRequired/whatWillBe.py +0 -357
- mapFolding/syntheticModules/dataNamespaceFlattened.py +0 -30
- mapFolding/syntheticModules/multiprocessingCount_doTheNeedful.py +0 -216
- mapFolding/syntheticModules/numbaCount.py +0 -90
- mapFolding/syntheticModules/numbaCountExample.py +0 -158
- mapFolding/syntheticModules/numbaCountSequential.py +0 -111
- mapFolding/syntheticModules/numba_doTheNeedful.py +0 -12
- mapFolding/syntheticModules/numba_doTheNeedfulExample.py +0 -13
- mapfolding-0.7.1.dist-info/RECORD +0 -51
- /mapFolding/{syntheticModules → reference}/__init__.py +0 -0
- {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info/licenses}/LICENSE +0 -0
- {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info}/top_level.txt +0 -0
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: mapFolding
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.8.1
|
|
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
|
|
7
7
|
Project-URL: Donate, https://www.patreon.com/integrated
|
|
8
8
|
Project-URL: Homepage, https://github.com/hunterhogan/mapFolding
|
|
9
9
|
Project-URL: Repository, https://github.com/hunterhogan/mapFolding.git
|
|
10
|
-
Keywords: A001415,A001416,A001417,A001418,A195646,combinatorics,folding,map folding,OEIS,optimization,stamp folding
|
|
10
|
+
Keywords: A001415,A001416,A001417,A001418,A195646,algorithmic optimization,AST manipulation,code generation,code transformation,combinatorics,computational geometry,dataclass transformation,folding pattern enumeration,just-in-time compilation,map folding,Numba optimization,OEIS,performance optimization,source code analysis,stamp folding
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
13
14
|
Classifier: Intended Audience :: Education
|
|
14
|
-
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
-
Classifier: Intended Audience :: Other Audience
|
|
16
15
|
Classifier: Intended Audience :: Science/Research
|
|
17
16
|
Classifier: Natural Language :: English
|
|
18
17
|
Classifier: Operating System :: OS Independent
|
|
@@ -23,7 +22,10 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
23
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
23
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
24
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
26
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
26
27
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
28
|
+
Classifier: Topic :: Software Development :: Compilers
|
|
27
29
|
Classifier: Typing :: Typed
|
|
28
30
|
Requires-Python: >=3.10
|
|
29
31
|
Description-Content-Type: text/markdown
|
|
@@ -38,12 +40,12 @@ Requires-Dist: tomli
|
|
|
38
40
|
Requires-Dist: Z0Z_tools
|
|
39
41
|
Provides-Extra: testing
|
|
40
42
|
Requires-Dist: mypy; extra == "testing"
|
|
43
|
+
Requires-Dist: pytest; extra == "testing"
|
|
41
44
|
Requires-Dist: pytest-cov; extra == "testing"
|
|
42
45
|
Requires-Dist: pytest-env; extra == "testing"
|
|
43
46
|
Requires-Dist: pytest-xdist; extra == "testing"
|
|
44
|
-
Requires-Dist: pytest; extra == "testing"
|
|
45
47
|
Requires-Dist: pyupgrade; extra == "testing"
|
|
46
|
-
|
|
48
|
+
Dynamic: license-file
|
|
47
49
|
|
|
48
50
|
# mapFolding: Algorithms for enumerating distinct map/stamp folding patterns 🗺️
|
|
49
51
|
|
|
@@ -52,8 +54,6 @@ Requires-Dist: updateCitation; extra == "testing"
|
|
|
52
54
|
[](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
|
|
53
55
|

|
|
54
56
|
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
55
|
-

|
|
56
|
-

|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
@@ -101,44 +101,49 @@ Available OEIS sequences:
|
|
|
101
101
|
|
|
102
102
|
### 2. **Algorithm Zoo** 🦒
|
|
103
103
|
|
|
104
|
-
- **Lunnon
|
|
104
|
+
- **Lunnon's 1971 Algorithm**: A painstakingly debugged version of [the original typo-riddled code](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt)
|
|
105
105
|
- The /reference directory.
|
|
106
106
|
- **Numba-JIT Accelerated**: Up to 1000× faster than pure Python ([benchmarks](https://github.com/hunterhogan/mapFolding/blob/mapFolding/notes/Speed%20highlights.md))
|
|
107
107
|
|
|
108
|
-
### 3. **For Researchers** 🔬
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
-
|
|
131
|
-
-
|
|
132
|
-
- Use
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
|
|
137
|
-
-
|
|
138
|
-
|
|
139
|
-
-
|
|
140
|
-
|
|
141
|
-
|
|
108
|
+
### 3. **For Researchers and Power Users** 🔬
|
|
109
|
+
|
|
110
|
+
This package provides a sophisticated code transformation framework that can turn readable algorithm implementations into highly-optimized computational engines:
|
|
111
|
+
|
|
112
|
+
- **Algorithmic Exploration**: Study the core algorithm in `theDao.py`, which uses a functional state-transformation approach with clear, isolated functions
|
|
113
|
+
- **Performance Optimization**: Generate specialized implementations with the `someAssemblyRequired` transformation pipeline:
|
|
114
|
+
- AST-based code analysis and manipulation
|
|
115
|
+
- Dataclass "shattering" to decompose complex state objects into primitive components
|
|
116
|
+
- Just-in-time compilation with Numba and various optimization profiles
|
|
117
|
+
- LLVM IR extraction for low-level algorithmic analysis
|
|
118
|
+
|
|
119
|
+
- **Extensible Design**: The transformation framework is abstract and generic, enabling:
|
|
120
|
+
- Creation of new optimization targets beyond the included Numba implementation
|
|
121
|
+
- Customization of compilation parameters and optimization levels
|
|
122
|
+
- Development of specialized algorithms for specific map dimensions
|
|
123
|
+
|
|
124
|
+
### 4. **Customization and Extension Guide**
|
|
125
|
+
|
|
126
|
+
The package architecture supports multiple levels of customization:
|
|
127
|
+
|
|
128
|
+
- **Basic Usage**: Work with the high-level API in `basecamp.py` for standard computations
|
|
129
|
+
- **Algorithm Modification**:
|
|
130
|
+
- Modify the core algorithm in `theDao.py` while preserving its functional approach
|
|
131
|
+
- 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
|
+
|
|
134
|
+
- **Advanced Transformation**:
|
|
135
|
+
- The `someAssemblyRequired` package provides tools to transform code at the AST level:
|
|
136
|
+
- `transformationTools.py` contains utilities for AST manipulation and code generation
|
|
137
|
+
- `transformDataStructures.py` handles complex data structure transformations
|
|
138
|
+
- `ingredientsNumba.py` provides Numba-specific configuration profiles
|
|
139
|
+
- `synthesizeNumbaFlow.py` orchestrates the transformation process
|
|
140
|
+
|
|
141
|
+
- **Custom Deployment**:
|
|
142
|
+
- Generate specialized implementations for specific dimensions
|
|
143
|
+
- Create optimized modules that can be executed as standalone scripts
|
|
144
|
+
- Extract LLVM IR for further analysis or optimization
|
|
145
|
+
|
|
146
|
+
The package's multi-level design allows you to start with simple API calls and progressively delve deeper into optimization as your computational needs grow.
|
|
142
147
|
|
|
143
148
|
## Map-folding Video
|
|
144
149
|
|
|
@@ -155,4 +160,4 @@ Available OEIS sequences:
|
|
|
155
160
|
[](https://HunterThinks.com/support)
|
|
156
161
|
[](https://www.youtube.com/@HunterHogan)
|
|
157
162
|
|
|
158
|
-
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
mapFolding/__init__.py,sha256=hYxPUBU6A1_XCbKEseSDamooTsb1mzN_XHqaRLPvpGk,1701
|
|
2
|
+
mapFolding/basecamp.py,sha256=7ghnbEcgMaGJYCy08GpOg0O28gY5P36ZibJkjs_r-Rg,4481
|
|
3
|
+
mapFolding/beDRY.py,sha256=WRbvissfUGAmYbj1o0ZpGvq_9hwllDqpNwuC2_yxFyM,9785
|
|
4
|
+
mapFolding/filesystem.py,sha256=-pYpWugd0p3TrAz7xf9YIJW-pn1X-iRCGtJgEAF9Rns,5923
|
|
5
|
+
mapFolding/noHomeYet.py,sha256=UKZeWlyn0SKlF9dhYoud7E6gWXpiSEekZOOoJp88WeI,1362
|
|
6
|
+
mapFolding/oeis.py,sha256=xArJ8X3HqzopKIKYdKwxk7Y62vtXZFxvZ0jEqv-8GO0,12625
|
|
7
|
+
mapFolding/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
mapFolding/theDao.py,sha256=Blzm5j24x1BE2nvgXjdzHEeuc2na6kAH9b_eP6PcwlI,9836
|
|
9
|
+
mapFolding/theSSOT.py,sha256=pyetKz_Yuofm_z2XhNaQT_CWTatuAykZO2bxEPy9wS4,13670
|
|
10
|
+
mapFolding/reference/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
mapFolding/reference/flattened.py,sha256=KEIR8hhOW0NHDX52LHJrrTUY5QaCzexZF0S6P2wvogY,15209
|
|
12
|
+
mapFolding/reference/hunterNumba.py,sha256=9MEy2szRSENZc9l1_VnRqBnnd71z4KjoPwOWnOwb9Pw,6105
|
|
13
|
+
mapFolding/reference/irvineJavaPort.py,sha256=UkOSX0_dkKR84hp8aqHPuf7KLz_nVnji9M0IF_hRVm8,3418
|
|
14
|
+
mapFolding/reference/jax.py,sha256=7ji9YWia6Kof0cjcNdiS1GG1rMbC5SBjcyVr_07AeUk,13845
|
|
15
|
+
mapFolding/reference/lunnanNumpy.py,sha256=isI0dOYZM1CZi1P4NEojl9L2Kh45mOYtc2C8yXUit8E,3731
|
|
16
|
+
mapFolding/reference/lunnanWhile.py,sha256=z1hcE6SeK0CFJSS4LggmzzsLNjU3dU26LsL5y_ZGBxM,3231
|
|
17
|
+
mapFolding/reference/rotatedEntryPoint.py,sha256=S3y5hSUTYOR_lKBnd5SwufvjNvg3UP-Je4wpYRB-_78,9328
|
|
18
|
+
mapFolding/reference/total_countPlus1vsPlusN.py,sha256=wpgay-uqPOBd64Z4Pg6tg40j7-4pzWHGMM6v0bnmjhE,6288
|
|
19
|
+
mapFolding/someAssemblyRequired/__init__.py,sha256=xA5a-nZjXIwcqEOig5PEZSxde4_m3JJ5Pb0CN4aiRjw,2488
|
|
20
|
+
mapFolding/someAssemblyRequired/getLLVMforNoReason.py,sha256=bGI8RZY-RnyR9TNF0r0OXwA6fm4TYH2cHy7WzhsnddQ,1895
|
|
21
|
+
mapFolding/someAssemblyRequired/ingredientsNumba.py,sha256=g6Z7t35NpoDskzm0OLwTQhHw5CYiYktVYxI2NhCQHww,8435
|
|
22
|
+
mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py,sha256=EtzULVeivQ_4G2E2UKqXoZLx6XwRcbBDzhtzwCTOEfs,10627
|
|
23
|
+
mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py,sha256=RBSrtr7US2P7mkY-EA-b2WIOxjs2b0WJaCln1ERxOcI,22314
|
|
24
|
+
mapFolding/someAssemblyRequired/transformDataStructures.py,sha256=0qtILOuH8I4CWFog64SPAyOWTylCa2Yh7L_hILrQY9Q,8279
|
|
25
|
+
mapFolding/someAssemblyRequired/transformationTools.py,sha256=vLRKAtaXa9RmoISUbFvQIWHDHor6CYctm7NEgU11T_E,40743
|
|
26
|
+
mapFolding/syntheticModules/numbaCount_doTheNeedful.py,sha256=52RuwJVH2fROvWU2dT8wYcQvLgRuvkNZPq01kujCC_U,15725
|
|
27
|
+
mapfolding-0.8.1.dist-info/licenses/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
|
|
28
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
+
tests/conftest.py,sha256=rRlXOhihwheHyQ8ggjRBbmgPVERxWjupajguVBzBkVE,10783
|
|
30
|
+
tests/test_computations.py,sha256=YhadlskBh_r5RiefHRy0FlrYQ0FelYbqcSNNSkSJMIY,3368
|
|
31
|
+
tests/test_filesystem.py,sha256=Kou0gj5T72oISao6umYfU6L_W5Hi7QS9_IxTv2hU0Pw,3147
|
|
32
|
+
tests/test_oeis.py,sha256=uxvwmgbnylSDdsVJfuAT0LuYLbIVFwSgdLxHm-xUGBM,5043
|
|
33
|
+
tests/test_other.py,sha256=1uuApByNWPiTf0zaro2dETkvyWQFfMweU_ge4aJuVgM,4244
|
|
34
|
+
tests/test_tasks.py,sha256=hkZygihT8bCEO2zc-2VcxReQrZJBwgLNbYx0YP4lTDg,2853
|
|
35
|
+
mapfolding-0.8.1.dist-info/METADATA,sha256=Upa7kSAeKLeSk33CiII-W08xLugqgnqwIBVQu4VLEQg,7892
|
|
36
|
+
mapfolding-0.8.1.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
|
|
37
|
+
mapfolding-0.8.1.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
|
|
38
|
+
mapfolding-0.8.1.dist-info/top_level.txt,sha256=1gP2vFaqPwHujGwb3UjtMlLEGN-943VSYFR7V4gDqW8,17
|
|
39
|
+
mapfolding-0.8.1.dist-info/RECORD,,
|
tests/conftest.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections.abc import Callable, Generator, Sequence
|
|
2
|
-
from mapFolding.theSSOT import getAlgorithmDispatcher, getSourceAlgorithm, getPackageDispatcher, theModuleOfSyntheticModules,
|
|
2
|
+
from mapFolding.theSSOT import getAlgorithmDispatcher, getSourceAlgorithm, getPackageDispatcher, theModuleOfSyntheticModules, raiseIfNoneGitHubIssueNumber3
|
|
3
3
|
from mapFolding.beDRY import getLeavesTotal, validateListDimensions, makeDataContainer
|
|
4
4
|
from mapFolding.oeis import oeisIDsImplemented, settingsOEIS
|
|
5
5
|
from pathlib import Path
|
|
@@ -10,7 +10,6 @@ import random
|
|
|
10
10
|
import shutil
|
|
11
11
|
import unittest.mock
|
|
12
12
|
import uuid
|
|
13
|
-
# TODO learn how to run tests and coverage analysis without `env = ["NUMBA_DISABLE_JIT=1"]`
|
|
14
13
|
|
|
15
14
|
# SSOT for test data paths and filenames
|
|
16
15
|
pathDataSamples = Path("tests/dataSamples")
|
|
@@ -215,7 +214,7 @@ def syntheticDispatcherFixture(useThisDispatcher: Callable[..., Any]) -> Callabl
|
|
|
215
214
|
dispatcherSynthetic = stuff
|
|
216
215
|
|
|
217
216
|
if dispatcherSynthetic is None:
|
|
218
|
-
raise
|
|
217
|
+
raise raiseIfNoneGitHubIssueNumber3
|
|
219
218
|
|
|
220
219
|
dispatcherSpec = importlib.util.spec_from_file_location(dispatcherSynthetic.callableSynthesized, dispatcherSynthetic.pathFilenameForMe)
|
|
221
220
|
if dispatcherSpec is None:
|
tests/test_filesystem.py
CHANGED
|
@@ -3,9 +3,7 @@ from mapFolding.filesystem import getFilenameFoldsTotal, getPathFilenameFoldsTot
|
|
|
3
3
|
from mapFolding.beDRY import validateListDimensions
|
|
4
4
|
from mapFolding.theSSOT import getPathJobRootDEFAULT
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Any
|
|
7
6
|
import io
|
|
8
|
-
import numpy
|
|
9
7
|
import pytest
|
|
10
8
|
import unittest.mock
|
|
11
9
|
|
tests/test_other.py
CHANGED
|
@@ -42,8 +42,8 @@ import sys
|
|
|
42
42
|
(tuple([3, 5, 7]), [3, 5, 7], (3, 5, 7)), # tuple sequence type
|
|
43
43
|
])
|
|
44
44
|
def test_listDimensionsAsParameter(listDimensions: None | list[str] | list[int] | list[float] | list[None] | list[bool] | list[list[int]] | list[complex] | range | tuple[int, ...],
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
expected_intInnit: type[ValueError] | list[int] | type[TypeError],
|
|
46
|
+
expected_validateListDimensions: type[ValueError] | type[NotImplementedError] | tuple[int, ...] | type[TypeError]) -> None:
|
|
47
47
|
"""Test both validateListDimensions and getLeavesTotal with the same inputs."""
|
|
48
48
|
standardizedEqualToCallableReturn(expected_intInnit, intInnit, listDimensions)
|
|
49
49
|
standardizedEqualToCallableReturn(expected_validateListDimensions, validateListDimensions, listDimensions)
|
|
@@ -56,7 +56,6 @@ def test_getLeavesTotal_edge_cases() -> None:
|
|
|
56
56
|
# Input preservation
|
|
57
57
|
mapShape = (2, 3)
|
|
58
58
|
standardizedEqualToCallableReturn(6, getLeavesTotal, mapShape)
|
|
59
|
-
# Remove the lambda entirely for a simpler approach
|
|
60
59
|
assert mapShape == (2, 3), "Input tuple was modified"
|
|
61
60
|
|
|
62
61
|
@pytest.mark.parametrize("nameOfTest,callablePytest", PytestFor_intInnit())
|
tests/test_tasks.py
CHANGED
|
@@ -12,10 +12,6 @@ import pytest
|
|
|
12
12
|
if __name__ == '__main__':
|
|
13
13
|
multiprocessing.set_start_method('spawn')
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
# TODO add a test. `C` = number of logical cores available. `n = C + 1`. Ensure that `[2,n]` is computed correctly.
|
|
17
|
-
# Or, probably smarter: limit the number of cores, then run a test with C+1.
|
|
18
|
-
|
|
19
15
|
def test_countFoldsComputationDivisionsInvalid(mapShapeTestFunctionality: tuple[int, ...]) -> None:
|
|
20
16
|
standardizedEqualToCallableReturn(ValueError, countFolds, mapShapeTestFunctionality, None, {"wrong": "value"})
|
|
21
17
|
|
mapFolding/reference/lunnan.py
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
An unnecessarily literal translation of the original Atlas Autocode code by W. F. Lunnon to Python.
|
|
3
|
-
W. F. Lunnon, Multi-dimensional map-folding, The Computer Journal, Volume 14, Issue 1, 1971, Pages 75-80, https://doi.org/10.1093/comjnl/14.1.75
|
|
4
|
-
"""# NOTE not functional yet
|
|
5
|
-
def foldings(p, job=None):
|
|
6
|
-
"""An unnecessarily literal translation of the original Atlas Autocode code."""
|
|
7
|
-
p = list(p)
|
|
8
|
-
p.append(None) # NOTE mimics Atlas `array` type
|
|
9
|
-
p.insert(0, None) # NOTE mimics Atlas `array` type
|
|
10
|
-
|
|
11
|
-
if job is None:
|
|
12
|
-
global G
|
|
13
|
-
G = 0
|
|
14
|
-
def job(A, B):
|
|
15
|
-
global G
|
|
16
|
-
G = G + 1
|
|
17
|
-
return foldings(p, job)
|
|
18
|
-
# perform job (A, B) on each folding of a p[1] x ... x p[d] map,
|
|
19
|
-
# where A and B are the above and below vectors. p[d + 1] < 0 terminates p;
|
|
20
|
-
|
|
21
|
-
d: int
|
|
22
|
-
n: int
|
|
23
|
-
j: int
|
|
24
|
-
i: int
|
|
25
|
-
m: int
|
|
26
|
-
l: int
|
|
27
|
-
g: int
|
|
28
|
-
gg: int
|
|
29
|
-
dd: int
|
|
30
|
-
|
|
31
|
-
n = 1
|
|
32
|
-
i, d = 0, 0
|
|
33
|
-
|
|
34
|
-
while (i := i + 1) and p[i] is not None:
|
|
35
|
-
d = i
|
|
36
|
-
n = n * p[i]
|
|
37
|
-
|
|
38
|
-
# d dimensions and n leaves;
|
|
39
|
-
|
|
40
|
-
# A: list[int] = [None] * (n + 1) # type: ignore
|
|
41
|
-
# B: list[int] = [None] * (n + 1) # type: ignore
|
|
42
|
-
# count: list[int] = [None] * (n + 1) # type: ignore
|
|
43
|
-
# gapter: list[int] = [None] * (n + 1) # type: ignore
|
|
44
|
-
# gap: list[int] = [None] * (n * n + 1) # type: ignore
|
|
45
|
-
A: list[int] = [0] * (n + 1) # type: ignore
|
|
46
|
-
B: list[int] = [0] * (n + 1) # type: ignore
|
|
47
|
-
count: list[int] = [0] * (n + 1) # type: ignore
|
|
48
|
-
gapter: list[int] = [0] * (n + 1) # type: ignore
|
|
49
|
-
gap: list[int] = [0] * (n * n + 1) # type: ignore
|
|
50
|
-
|
|
51
|
-
# B[m] is the leaf below leaf m in the current folding,
|
|
52
|
-
# A[m] the leaf above. count[m] is the no. of sections in which
|
|
53
|
-
# there is a gap for the new leaf l below leaf m,
|
|
54
|
-
# gap[gapter[l - 1] + j] is the j-th (possible or actual) gap for leaf l,
|
|
55
|
-
# and later gap[gapter[l]] is the gap where leaf l is currently inserted;
|
|
56
|
-
|
|
57
|
-
P: list[int] = [0] * (d + 1) # type: ignore
|
|
58
|
-
C: list[list[int]] = [[0] * (n + 1) for dimension1 in range(d + 1)] # type: ignore
|
|
59
|
-
# D: list[list[list[int]]] = [[[None] * (n + 1) for dimension2 in range(n + 1)] for dimension1 in range(d + 1)] # type: ignore
|
|
60
|
-
D: list[list[list[int]]] = [[[0] * (n + 1) for dimension2 in range(n + 1)] for dimension1 in range(d + 1)]
|
|
61
|
-
|
|
62
|
-
P[0] = 1
|
|
63
|
-
for i in range(1, d + 1):
|
|
64
|
-
P[i] = P[i - 1] * p[i]
|
|
65
|
-
|
|
66
|
-
for i in range(1, d + 1):
|
|
67
|
-
for m in range(1, n + 1):
|
|
68
|
-
C[i][m] = ((m - 1) // P[i - 1]) - ((m - 1) // P[i]) * p[i] + 1
|
|
69
|
-
|
|
70
|
-
for i in range(1, d + 1):
|
|
71
|
-
for l in range(1, n + 1):
|
|
72
|
-
for m in range(1, l + 1):
|
|
73
|
-
D[i][l][m] = (0 if m == 0
|
|
74
|
-
else
|
|
75
|
-
((m if C[i][m] == 1
|
|
76
|
-
else m - P[i - 1])
|
|
77
|
-
if C[i][l] - C[i][m] == (C[i][l] - C[i][m]) // 2 * 2
|
|
78
|
-
else
|
|
79
|
-
(m if C[i][m] == p[i] or m + P[i - 1] > l
|
|
80
|
-
else m + P[i - 1])))
|
|
81
|
-
# P[i] = p[1] x ... x p[i], C[i][m] = i-th co-ordinate of leaf m,
|
|
82
|
-
# D[i][l][m] = leaf connected to m in section i when inserting l;
|
|
83
|
-
|
|
84
|
-
for m in range(n + 1):
|
|
85
|
-
count[m] = 0
|
|
86
|
-
|
|
87
|
-
A[0], B[0], g, l = 0, 0, 0, 0
|
|
88
|
-
|
|
89
|
-
state = 'entry'
|
|
90
|
-
while True:
|
|
91
|
-
if state == 'entry':
|
|
92
|
-
gapter[l] = g
|
|
93
|
-
l = l + 1
|
|
94
|
-
if l <= n:
|
|
95
|
-
state = 'down'
|
|
96
|
-
continue
|
|
97
|
-
else:
|
|
98
|
-
job(A, B)
|
|
99
|
-
state = 'up'
|
|
100
|
-
continue
|
|
101
|
-
|
|
102
|
-
elif state == 'down':
|
|
103
|
-
dd = 0
|
|
104
|
-
gg = gapter[l - 1]
|
|
105
|
-
g = gg
|
|
106
|
-
for i in range(1, d + 1):
|
|
107
|
-
if D[i][l][l] == l:
|
|
108
|
-
dd = dd + 1
|
|
109
|
-
else:
|
|
110
|
-
m = D[i][l][l]
|
|
111
|
-
while m != l:
|
|
112
|
-
gap[gg] = m
|
|
113
|
-
if count[m] == 0:
|
|
114
|
-
gg = gg + 1
|
|
115
|
-
count[m] = count[m] + 1
|
|
116
|
-
m = D[i][l][B[m]]
|
|
117
|
-
|
|
118
|
-
if dd == d:
|
|
119
|
-
for m in range(l):
|
|
120
|
-
gap[gg] = m
|
|
121
|
-
gg = gg + 1
|
|
122
|
-
|
|
123
|
-
for j in range(g, gg):
|
|
124
|
-
gap[g] = gap[j]
|
|
125
|
-
if count[gap[j]] == d - dd:
|
|
126
|
-
g = g + 1
|
|
127
|
-
count[gap[j]] = 0
|
|
128
|
-
state = 'along'
|
|
129
|
-
continue
|
|
130
|
-
|
|
131
|
-
elif state == 'along':
|
|
132
|
-
if g == gapter[l - 1]:
|
|
133
|
-
state = 'up'
|
|
134
|
-
continue
|
|
135
|
-
g = g - 1
|
|
136
|
-
A[l] = gap[g]
|
|
137
|
-
B[l] = B[A[l]]
|
|
138
|
-
B[A[l]] = l
|
|
139
|
-
A[B[l]] = l
|
|
140
|
-
state = 'entry'
|
|
141
|
-
continue
|
|
142
|
-
|
|
143
|
-
elif state == 'up':
|
|
144
|
-
l = l - 1
|
|
145
|
-
B[A[l]] = B[l]
|
|
146
|
-
A[B[l]] = A[l]
|
|
147
|
-
if l > 0:
|
|
148
|
-
state = 'along'
|
|
149
|
-
continue
|
|
150
|
-
else:
|
|
151
|
-
break
|
|
152
|
-
|
|
153
|
-
return G #if job.__closure__ else None
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
from mapFolding.someAssemblyRequired.synthesizeDataConverters import makeDataclassConverter
|
|
2
|
-
from mapFolding.someAssemblyRequired.whatWillBe import IngredientsFunction, IngredientsModule, numbaFlow
|
|
3
|
-
from mapFolding.someAssemblyRequired.synthesizeCountingFunctions import Z0Z_makeCountingFunction
|
|
4
|
-
import ast
|
|
5
|
-
|
|
6
|
-
if __name__ == '__main__':
|
|
7
|
-
ingredientsFunctionDataConverter = makeDataclassConverter(
|
|
8
|
-
dataclassIdentifier=numbaFlow.sourceDataclassIdentifier
|
|
9
|
-
, logicalPathModuleDataclass=numbaFlow.logicalPathModuleDataclass
|
|
10
|
-
, dataclassInstance=numbaFlow.dataclassInstance
|
|
11
|
-
|
|
12
|
-
, dispatcherCallable=numbaFlow.dispatcherCallable
|
|
13
|
-
, logicalPathModuleDispatcher=numbaFlow.logicalPathModuleDispatcher
|
|
14
|
-
, dataConverterCallable=numbaFlow.dataConverterCallable
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
# initialize with theDao
|
|
18
|
-
dataInitializationHack = "state=makeStateJob(state.mapShape,writeJob=False)"
|
|
19
|
-
ingredientsFunctionDataConverter.FunctionDef.body.insert(0, ast.parse(dataInitializationHack).body[0])
|
|
20
|
-
ingredientsFunctionDataConverter.imports.addImportFromStr('mapFolding.someAssemblyRequired', 'makeStateJob')
|
|
21
|
-
|
|
22
|
-
ingredientsSequential = Z0Z_makeCountingFunction(numbaFlow.sequentialCallable
|
|
23
|
-
, numbaFlow.sourceAlgorithm
|
|
24
|
-
, inline=True
|
|
25
|
-
, dataclass=False)
|
|
26
|
-
|
|
27
|
-
ingredientsModuleDataConverter = IngredientsModule(
|
|
28
|
-
name=numbaFlow.dataConverterModule,
|
|
29
|
-
ingredientsFunction=ingredientsFunctionDataConverter,
|
|
30
|
-
logicalPathINFIX=numbaFlow.Z0Z_flowLogicalPathRoot,
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
ingredientsModuleDataConverter.writeModule()
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
from collections.abc import Sequence
|
|
2
|
-
from importlib import import_module
|
|
3
|
-
from inspect import getsource as inspect_getsource
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from types import ModuleType
|
|
6
|
-
from typing import Any, cast, overload, Literal
|
|
7
|
-
import ast
|
|
8
|
-
import pickle
|
|
9
|
-
from mapFolding.beDRY import ComputationState, outfitCountFolds, validateListDimensions
|
|
10
|
-
from mapFolding.filesystem import getPathFilenameFoldsTotal
|
|
11
|
-
from mapFolding.someAssemblyRequired import (
|
|
12
|
-
ast_Identifier,
|
|
13
|
-
executeActionUnlessDescendantMatches,
|
|
14
|
-
extractClassDef,
|
|
15
|
-
ifThis,
|
|
16
|
-
IngredientsFunction,
|
|
17
|
-
LedgerOfImports,
|
|
18
|
-
Make,
|
|
19
|
-
NodeCollector,
|
|
20
|
-
strDotStrCuzPyStoopid,
|
|
21
|
-
Then,
|
|
22
|
-
)
|
|
23
|
-
from mapFolding.theSSOT import getSourceAlgorithm
|
|
24
|
-
|
|
25
|
-
def shatter_dataclassesDOTdataclass(logicalPathModule: strDotStrCuzPyStoopid, dataclass_Identifier: ast_Identifier, instance_Identifier: ast_Identifier
|
|
26
|
-
) -> tuple[ast.Name, LedgerOfImports, list[ast.AnnAssign], list[ast.Name], list[ast.keyword], ast.Tuple]:
|
|
27
|
-
"""
|
|
28
|
-
Parameters:
|
|
29
|
-
logicalPathModule: gimme string cuz python is stoopid
|
|
30
|
-
dataclass_Identifier: The identifier of the dataclass to be dismantled.
|
|
31
|
-
instance_Identifier: In the synthesized module/function/scope, the identifier that will be used for the instance.
|
|
32
|
-
"""
|
|
33
|
-
module: ast.Module = ast.parse(inspect_getsource(import_module(logicalPathModule)))
|
|
34
|
-
|
|
35
|
-
dataclass = extractClassDef(dataclass_Identifier, module)
|
|
36
|
-
|
|
37
|
-
if not isinstance(dataclass, ast.ClassDef):
|
|
38
|
-
raise ValueError(f"I could not find {dataclass_Identifier=} in {logicalPathModule=}.")
|
|
39
|
-
|
|
40
|
-
list_astAnnAssign: list[ast.AnnAssign] = []
|
|
41
|
-
listKeywordForDataclassInitialization: list[ast.keyword] = []
|
|
42
|
-
list_astNameDataclassFragments: list[ast.Name] = []
|
|
43
|
-
ledgerDataclassAndFragments = LedgerOfImports()
|
|
44
|
-
|
|
45
|
-
addToLedgerPredicate = ifThis.isAnnAssignAndAnnotationIsName
|
|
46
|
-
addToLedgerAction = Then.Z0Z_ledger(logicalPathModule, ledgerDataclassAndFragments)
|
|
47
|
-
addToLedger = NodeCollector(addToLedgerPredicate, [addToLedgerAction])
|
|
48
|
-
|
|
49
|
-
exclusionPredicate = ifThis.is_keyword_IdentifierEqualsConstantValue('init', False)
|
|
50
|
-
appendKeywordAction = Then.Z0Z_appendKeywordMirroredTo(listKeywordForDataclassInitialization)
|
|
51
|
-
filteredAppendKeywordAction = executeActionUnlessDescendantMatches(exclusionPredicate, appendKeywordAction)
|
|
52
|
-
|
|
53
|
-
collector = NodeCollector(
|
|
54
|
-
ifThis.isAnnAssignAndTargetIsName,
|
|
55
|
-
[Then.Z0Z_appendAnnAssignOfNameDOTnameTo(instance_Identifier, list_astAnnAssign)
|
|
56
|
-
, Then.append_targetTo(list_astNameDataclassFragments)
|
|
57
|
-
, lambda node: addToLedger.visit(node)
|
|
58
|
-
, filteredAppendKeywordAction
|
|
59
|
-
]
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
collector.visit(dataclass)
|
|
63
|
-
|
|
64
|
-
ledgerDataclassAndFragments.addImportFromStr(logicalPathModule, dataclass_Identifier)
|
|
65
|
-
|
|
66
|
-
astNameDataclass = Make.astName(dataclass_Identifier)
|
|
67
|
-
astTupleForAssignTargetsToFragments: ast.Tuple = Make.astTuple(list_astNameDataclassFragments, ast.Store())
|
|
68
|
-
return astNameDataclass, ledgerDataclassAndFragments, list_astAnnAssign, list_astNameDataclassFragments, listKeywordForDataclassInitialization, astTupleForAssignTargetsToFragments
|
|
69
|
-
|
|
70
|
-
def makeDataclassConverter(dataclassIdentifier: str,
|
|
71
|
-
logicalPathModuleDataclass: str,
|
|
72
|
-
dataclassInstance: str,
|
|
73
|
-
dispatcherCallable: str,
|
|
74
|
-
logicalPathModuleDispatcher: str,
|
|
75
|
-
dataConverterCallable: str,
|
|
76
|
-
) -> IngredientsFunction:
|
|
77
|
-
|
|
78
|
-
astNameDataclass, ledgerDataclassAndFragments, list_astAnnAssign, list_astNameDataclassFragments, list_astKeywordDataclassFragments, astTupleForAssignTargetsToFragments = shatter_dataclassesDOTdataclass(logicalPathModuleDataclass, dataclassIdentifier, dataclassInstance)
|
|
79
|
-
|
|
80
|
-
ingredientsFunction = IngredientsFunction(
|
|
81
|
-
FunctionDef = Make.astFunctionDef(name=dataConverterCallable
|
|
82
|
-
, argumentsSpecification=Make.astArgumentsSpecification(args=[Make.astArg(dataclassInstance, astNameDataclass)])
|
|
83
|
-
, body = cast(list[ast.stmt], list_astAnnAssign)
|
|
84
|
-
, returns = astNameDataclass
|
|
85
|
-
)
|
|
86
|
-
, imports = ledgerDataclassAndFragments
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
callToDispatcher = Make.astAssign(listTargets=[astTupleForAssignTargetsToFragments]
|
|
90
|
-
, value=Make.astCall(Make.astName(dispatcherCallable), args=list_astNameDataclassFragments))
|
|
91
|
-
ingredientsFunction.FunctionDef.body.append(callToDispatcher)
|
|
92
|
-
ingredientsFunction.imports.addImportFromStr(logicalPathModuleDispatcher, dispatcherCallable)
|
|
93
|
-
|
|
94
|
-
ingredientsFunction.FunctionDef.body.append(Make.astReturn(Make.astCall(astNameDataclass, list_astKeywords=list_astKeywordDataclassFragments)))
|
|
95
|
-
|
|
96
|
-
return ingredientsFunction
|
|
97
|
-
|
|
98
|
-
@overload
|
|
99
|
-
def makeStateJob(listDimensions: Sequence[int], *, writeJob: Literal[True], **keywordArguments: Any) -> Path: ...
|
|
100
|
-
@overload
|
|
101
|
-
def makeStateJob(listDimensions: Sequence[int], *, writeJob: Literal[False], **keywordArguments: Any) -> ComputationState: ...
|
|
102
|
-
def makeStateJob(listDimensions: Sequence[int], *, writeJob: bool = True, **keywordArguments: Any) -> ComputationState | Path:
|
|
103
|
-
"""
|
|
104
|
-
Creates a computation state job for map folding calculations and optionally saves it to disk.
|
|
105
|
-
|
|
106
|
-
This function initializes a computation state for map folding calculations based on the given dimensions,
|
|
107
|
-
sets up the initial counting configuration, and can optionally save the state to a pickle file.
|
|
108
|
-
|
|
109
|
-
Parameters:
|
|
110
|
-
listDimensions: List of integers representing the dimensions of the map to be folded.
|
|
111
|
-
writeJob (True): Whether to save the state to disk.
|
|
112
|
-
**keywordArguments: Additional keyword arguments to pass to the computation state initialization.
|
|
113
|
-
|
|
114
|
-
Returns:
|
|
115
|
-
stateUniversal|pathFilenameJob: The computation state for the map folding calculations, or
|
|
116
|
-
the path to the saved state file if writeJob is True.
|
|
117
|
-
"""
|
|
118
|
-
mapShape = validateListDimensions(listDimensions)
|
|
119
|
-
stateUniversal = outfitCountFolds(mapShape, **keywordArguments)
|
|
120
|
-
|
|
121
|
-
moduleSource: ModuleType = getSourceAlgorithm()
|
|
122
|
-
# TODO `countInitialize` is hardcoded
|
|
123
|
-
stateUniversal: ComputationState = moduleSource.countInitialize(stateUniversal)
|
|
124
|
-
|
|
125
|
-
if not writeJob:
|
|
126
|
-
return stateUniversal
|
|
127
|
-
|
|
128
|
-
pathFilenameChopChop = getPathFilenameFoldsTotal(stateUniversal.mapShape, None)
|
|
129
|
-
suffix = pathFilenameChopChop.suffix
|
|
130
|
-
pathJob = Path(str(pathFilenameChopChop)[0:-len(suffix)])
|
|
131
|
-
pathJob.mkdir(parents=True, exist_ok=True)
|
|
132
|
-
pathFilenameJob = pathJob / 'stateJob.pkl'
|
|
133
|
-
|
|
134
|
-
pathFilenameJob.write_bytes(pickle.dumps(stateUniversal))
|
|
135
|
-
return pathFilenameJob
|