mapFolding 0.8.5__py3-none-any.whl → 0.9.0__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 +66 -18
- mapFolding/basecamp.py +32 -17
- mapFolding/beDRY.py +3 -3
- mapFolding/oeis.py +121 -25
- mapFolding/someAssemblyRequired/__init__.py +48 -27
- mapFolding/someAssemblyRequired/_theTypes.py +11 -15
- mapFolding/someAssemblyRequired/_tool_Make.py +40 -12
- mapFolding/someAssemblyRequired/_tool_Then.py +59 -25
- mapFolding/someAssemblyRequired/_toolboxAntecedents.py +151 -276
- mapFolding/someAssemblyRequired/_toolboxContainers.py +185 -51
- mapFolding/someAssemblyRequired/_toolboxPython.py +165 -44
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +141 -20
- mapFolding/someAssemblyRequired/toolboxNumba.py +93 -52
- mapFolding/someAssemblyRequired/transformationTools.py +228 -138
- mapFolding/syntheticModules/numbaCount_doTheNeedful.py +0 -1
- mapFolding/theSSOT.py +147 -55
- mapFolding/toolboxFilesystem.py +1 -1
- mapfolding-0.9.0.dist-info/METADATA +177 -0
- mapfolding-0.9.0.dist-info/RECORD +46 -0
- tests/__init__.py +44 -0
- tests/conftest.py +75 -7
- tests/test_computations.py +90 -9
- tests/test_filesystem.py +32 -33
- tests/test_other.py +0 -1
- tests/test_tasks.py +2 -2
- mapFolding/noHomeYet.py +0 -32
- mapFolding/someAssemblyRequired/newInliner.py +0 -22
- mapfolding-0.8.5.dist-info/METADATA +0 -190
- mapfolding-0.8.5.dist-info/RECORD +0 -48
- {mapfolding-0.8.5.dist-info → mapfolding-0.9.0.dist-info}/WHEEL +0 -0
- {mapfolding-0.8.5.dist-info → mapfolding-0.9.0.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.8.5.dist-info → mapfolding-0.9.0.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.8.5.dist-info → mapfolding-0.9.0.dist-info}/top_level.txt +0 -0
tests/conftest.py
CHANGED
|
@@ -1,8 +1,65 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test Configuration and Shared Fixtures
|
|
3
|
+
|
|
4
|
+
This module provides the foundation for the mapFolding test suite, offering fixtures and
|
|
5
|
+
utilities that enable consistent, reliable testing across the package. It's particularly
|
|
6
|
+
valuable for users who want to test their own customizations.
|
|
7
|
+
|
|
8
|
+
## Key Testing Facilities
|
|
9
|
+
|
|
10
|
+
### File System Management
|
|
11
|
+
|
|
12
|
+
The module implements a robust temporary file system management approach:
|
|
13
|
+
- Creates a registry of temporary files and directories
|
|
14
|
+
- Ensures proper cleanup after tests
|
|
15
|
+
- Provides fixtures that automatically handle cleanup
|
|
16
|
+
|
|
17
|
+
### Test-Specific Fixtures
|
|
18
|
+
|
|
19
|
+
Several fixtures enable specialized testing scenarios:
|
|
20
|
+
|
|
21
|
+
1. **Dispatcher Fixtures**:
|
|
22
|
+
- `useThisDispatcher`: Core fixture for patching the algorithm dispatcher
|
|
23
|
+
- `useAlgorithmSourceDispatcher`: Tests with the source algorithm implementation
|
|
24
|
+
- `syntheticDispatcherFixture`: Tests with generated Numba-optimized implementation
|
|
25
|
+
|
|
26
|
+
2. **Test Data Fixtures**:
|
|
27
|
+
- `oeisID`, `oeisID_1random`: Provide OEIS sequence identifiers for testing
|
|
28
|
+
- `listDimensionsTestCountFolds`: Provides dimensions suitable for algorithm testing
|
|
29
|
+
- `listDimensionsTestParallelization`: Provides dimensions suitable for parallel testing
|
|
30
|
+
- `mapShapeTestFunctionality`: Provides map shapes suitable for functional testing
|
|
31
|
+
|
|
32
|
+
3. **Path Fixtures**:
|
|
33
|
+
- `pathTmpTesting`: Creates a temporary directory for test-specific files
|
|
34
|
+
- `pathFilenameTmpTesting`: Creates a temporary file with appropriate extension
|
|
35
|
+
- `pathCacheTesting`: Creates a temporary OEIS cache directory
|
|
36
|
+
|
|
37
|
+
### Standardized Test Utilities
|
|
38
|
+
|
|
39
|
+
The module provides utilities that create consistent test outputs:
|
|
40
|
+
|
|
41
|
+
- `standardizedEqualToCallableReturn`: Core utility that handles testing function return values
|
|
42
|
+
or exceptions with uniform error messages
|
|
43
|
+
- `standardizedSystemExit`: Tests code that should exit the program with specific status codes
|
|
44
|
+
- `uniformTestMessage`: Creates consistent error messages for test failures
|
|
45
|
+
|
|
46
|
+
## Using These Fixtures for Custom Tests
|
|
47
|
+
|
|
48
|
+
The most important fixtures for testing custom implementations are:
|
|
49
|
+
|
|
50
|
+
1. `syntheticDispatcherFixture`: Creates and patches a Numba-optimized module from a recipe
|
|
51
|
+
2. `pathTmpTesting`: Provides a clean temporary directory for test files
|
|
52
|
+
3. `standardizedEqualToCallableReturn`: Simplifies test assertions with clear error messages
|
|
53
|
+
|
|
54
|
+
These can be adapted by copying and modifying them to test custom recipes and jobs.
|
|
55
|
+
See the examples in `test_computations.py` for guidance on adapting these fixtures.
|
|
56
|
+
"""
|
|
57
|
+
|
|
1
58
|
from collections.abc import Callable, Generator, Sequence
|
|
59
|
+
from mapFolding import ComputationState, The
|
|
2
60
|
from mapFolding.beDRY import getLeavesTotal, validateListDimensions, makeDataContainer
|
|
3
61
|
from mapFolding.oeis import oeisIDsImplemented, settingsOEIS
|
|
4
62
|
from mapFolding.someAssemblyRequired import importLogicalPath2Callable, RecipeSynthesizeFlow
|
|
5
|
-
from mapFolding.theSSOT import ComputationState, The, getPackageDispatcher
|
|
6
63
|
from pathlib import Path, PurePosixPath
|
|
7
64
|
from types import ModuleType
|
|
8
65
|
from typing import Any
|
|
@@ -189,16 +246,27 @@ def useThisDispatcher() -> Generator[Callable[..., None], Any, None]:
|
|
|
189
246
|
Returns
|
|
190
247
|
A context manager for patching the dispatcher
|
|
191
248
|
"""
|
|
192
|
-
import mapFolding.
|
|
193
|
-
|
|
249
|
+
import mapFolding.theSSOT as theSSOT
|
|
250
|
+
from mapFolding.theSSOT import The
|
|
251
|
+
|
|
252
|
+
# Store original property method
|
|
253
|
+
original_dispatcher_property = theSSOT.PackageSettings.dispatcher
|
|
194
254
|
|
|
195
255
|
def patchDispatcher(callableTarget: Callable[..., Any]) -> None:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
256
|
+
"""Patch the dispatcher property to return the target callable."""
|
|
257
|
+
# Create a new property that returns the target callable
|
|
258
|
+
def patched_dispatcher(self: theSSOT.PackageSettings) -> Callable[['ComputationState'], 'ComputationState']:
|
|
259
|
+
def wrapper(state: 'ComputationState') -> 'ComputationState':
|
|
260
|
+
return callableTarget(state)
|
|
261
|
+
return wrapper
|
|
262
|
+
|
|
263
|
+
# Replace the property with our patched version
|
|
264
|
+
theSSOT.PackageSettings.dispatcher = property(patched_dispatcher) # type: ignore
|
|
199
265
|
|
|
200
266
|
yield patchDispatcher
|
|
201
|
-
|
|
267
|
+
|
|
268
|
+
# Restore the original property
|
|
269
|
+
theSSOT.PackageSettings.dispatcher = original_dispatcher_property # type: ignore
|
|
202
270
|
|
|
203
271
|
def getAlgorithmDispatcher() -> Callable[[ComputationState], ComputationState]:
|
|
204
272
|
moduleImported: ModuleType = importlib.import_module(The.logicalPathModuleSourceAlgorithm)
|
tests/test_computations.py
CHANGED
|
@@ -1,16 +1,97 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"""
|
|
2
|
+
Core Algorithm and Module Generation Testing
|
|
3
|
+
|
|
4
|
+
This module provides tests for validating algorithm correctness and testing
|
|
5
|
+
code generation functionality. It's designed not only to test the package's
|
|
6
|
+
functionality but also to serve as a template for users testing their own
|
|
7
|
+
custom implementations.
|
|
8
|
+
|
|
9
|
+
## Key Testing Categories
|
|
10
|
+
|
|
11
|
+
1. Algorithm Validation Tests
|
|
12
|
+
- `test_algorithmSourceParallel` - Tests the source algorithm in parallel mode
|
|
13
|
+
- `test_algorithmSourceSequential` - Tests the source algorithm in sequential mode
|
|
14
|
+
- `test_aOFn_calculate_value` - Tests OEIS sequence value calculations
|
|
15
|
+
|
|
16
|
+
2. Synthetic Module Tests
|
|
17
|
+
- `test_syntheticParallel` - Tests generated Numba-optimized code in parallel mode
|
|
18
|
+
- `test_syntheticSequential` - Tests generated Numba-optimized code in sequential mode
|
|
19
|
+
|
|
20
|
+
3. Job Testing
|
|
21
|
+
- `test_writeJobNumba` - Tests job-specific module generation and execution
|
|
22
|
+
|
|
23
|
+
## How to Test Your Custom Implementations
|
|
24
|
+
|
|
25
|
+
### Testing Custom Recipes (RecipeSynthesizeFlow):
|
|
26
|
+
|
|
27
|
+
1. Copy the `syntheticDispatcherFixture` from conftest.py
|
|
28
|
+
2. Modify it to use your custom recipe configuration
|
|
29
|
+
3. Copy and adapt `test_syntheticParallel` and `test_syntheticSequential`
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
@pytest.fixture
|
|
35
|
+
def myCustomRecipeFixture(useThisDispatcher, pathTmpTesting):
|
|
36
|
+
# Create your custom recipe configuration
|
|
37
|
+
myRecipe = RecipeSynthesizeFlow(
|
|
38
|
+
pathPackage=PurePosixPath(pathTmpTesting.absolute()),
|
|
39
|
+
# Add your custom configuration
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Generate the module
|
|
43
|
+
makeNumbaFlow(myRecipe)
|
|
44
|
+
|
|
45
|
+
# Import and patch the dispatcher
|
|
46
|
+
# ... (similar to syntheticDispatcherFixture)
|
|
47
|
+
|
|
48
|
+
return customDispatcher
|
|
49
|
+
|
|
50
|
+
def test_myCustomRecipeParallel(myCustomRecipeFixture, listDimensionsTestParallelization):
|
|
51
|
+
# Test with the standardized validation utility
|
|
52
|
+
standardizedEqualToCallableReturn(
|
|
53
|
+
getFoldsTotalKnown(tuple(listDimensionsTestParallelization)),
|
|
54
|
+
countFolds,
|
|
55
|
+
listDimensionsTestParallelization,
|
|
56
|
+
None,
|
|
57
|
+
'maximum'
|
|
58
|
+
)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Testing Custom Jobs (RecipeJob):
|
|
62
|
+
|
|
63
|
+
1. Copy and adapt `test_writeJobNumba`
|
|
64
|
+
2. Modify it to use your custom job configuration
|
|
65
|
+
|
|
66
|
+
Example:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
def test_myCustomJob(oneTestCuzTestsOverwritingTests, pathFilenameTmpTesting):
|
|
70
|
+
# Create your custom job configuration
|
|
71
|
+
myJob = RecipeJob(
|
|
72
|
+
state=makeInitializedComputationState(validateListDimensions(oneTestCuzTestsOverwritingTests)),
|
|
73
|
+
# Add your custom configuration
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
spices = SpicesJobNumba()
|
|
77
|
+
# Customize spices if needed
|
|
78
|
+
|
|
79
|
+
# Generate and test the job
|
|
80
|
+
makeJobNumba(myJob, spices)
|
|
81
|
+
# Test execution similar to test_writeJobNumba
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
All tests leverage standardized utilities like `standardizedEqualToCallableReturn`
|
|
85
|
+
that provide consistent, informative error messages and simplify test validation.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
from mapFolding import countFolds, getFoldsTotalKnown, oeisIDfor_n, validateListDimensions
|
|
89
|
+
from mapFolding.oeis import settingsOEIS
|
|
6
90
|
from mapFolding.someAssemblyRequired.transformationTools import makeInitializedComputationState
|
|
7
91
|
from pathlib import Path, PurePosixPath
|
|
8
92
|
from tests.conftest import standardizedEqualToCallableReturn, registrarRecordsTmpObject
|
|
9
|
-
from types import ModuleType
|
|
10
93
|
import importlib.util
|
|
11
94
|
import multiprocessing
|
|
12
|
-
import threading
|
|
13
|
-
from copy import deepcopy
|
|
14
95
|
import pytest
|
|
15
96
|
|
|
16
97
|
if __name__ == '__main__':
|
|
@@ -26,7 +107,7 @@ def test_aOFn_calculate_value(oeisID: str) -> None:
|
|
|
26
107
|
for n in settingsOEIS[oeisID]['valuesTestValidation']:
|
|
27
108
|
standardizedEqualToCallableReturn(settingsOEIS[oeisID]['valuesKnown'][n], oeisIDfor_n, oeisID, n)
|
|
28
109
|
|
|
29
|
-
def test_syntheticParallel(syntheticDispatcherFixture: None, listDimensionsTestParallelization: list[int]):
|
|
110
|
+
def test_syntheticParallel(syntheticDispatcherFixture: None, listDimensionsTestParallelization: list[int]) -> None:
|
|
30
111
|
standardizedEqualToCallableReturn(getFoldsTotalKnown(tuple(listDimensionsTestParallelization)), countFolds, listDimensionsTestParallelization, None, 'maximum')
|
|
31
112
|
|
|
32
113
|
def test_syntheticSequential(syntheticDispatcherFixture: None, listDimensionsTestCountFolds: list[int]) -> None:
|
tests/test_filesystem.py
CHANGED
|
@@ -1,50 +1,49 @@
|
|
|
1
1
|
from contextlib import redirect_stdout
|
|
2
|
-
from mapFolding
|
|
3
|
-
from mapFolding.
|
|
4
|
-
from mapFolding.toolboxFilesystem import getPathRootJobDEFAULT
|
|
2
|
+
from mapFolding import validateListDimensions, getPathRootJobDEFAULT, getPathFilenameFoldsTotal, saveFoldsTotal
|
|
3
|
+
from mapFolding.toolboxFilesystem import getFilenameFoldsTotal
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
import io
|
|
7
6
|
import pytest
|
|
8
7
|
import unittest.mock
|
|
9
8
|
|
|
10
9
|
def test_saveFoldsTotal_fallback(pathTmpTesting: Path) -> None:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
foldsTotal = 123
|
|
11
|
+
pathFilename = pathTmpTesting / "foldsTotal.txt"
|
|
12
|
+
with unittest.mock.patch("pathlib.Path.write_text", side_effect=OSError("Simulated write failure")):
|
|
13
|
+
with unittest.mock.patch("os.getcwd", return_value=str(pathTmpTesting)):
|
|
14
|
+
capturedOutput = io.StringIO()
|
|
15
|
+
with redirect_stdout(capturedOutput):
|
|
16
|
+
saveFoldsTotal(pathFilename, foldsTotal)
|
|
17
|
+
fallbackFiles = list(pathTmpTesting.glob("foldsTotalYO_*.txt"))
|
|
18
|
+
assert len(fallbackFiles) == 1, "Fallback file was not created upon write failure."
|
|
20
19
|
|
|
21
20
|
@pytest.mark.parametrize("listDimensions, expectedFilename", [
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
([11, 13], "p11x13.foldsTotal"),
|
|
22
|
+
([17, 13, 11], "p11x13x17.foldsTotal"),
|
|
24
23
|
])
|
|
25
24
|
def test_getFilenameFoldsTotal(listDimensions: list[int], expectedFilename: str) -> None:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
"""Test that getFilenameFoldsTotal generates correct filenames with dimensions sorted."""
|
|
26
|
+
mapShape = validateListDimensions(listDimensions)
|
|
27
|
+
filenameActual = getFilenameFoldsTotal(mapShape)
|
|
28
|
+
assert filenameActual == expectedFilename, f"Expected filename {expectedFilename} but got {filenameActual}"
|
|
30
29
|
|
|
31
30
|
def test_getPathFilenameFoldsTotal_defaultPath(mapShapeTestFunctionality: tuple[int, ...]) -> None:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
"""Test getPathFilenameFoldsTotal with default path."""
|
|
32
|
+
pathFilenameFoldsTotal = getPathFilenameFoldsTotal(mapShapeTestFunctionality)
|
|
33
|
+
assert pathFilenameFoldsTotal.is_absolute(), "Path should be absolute"
|
|
34
|
+
assert pathFilenameFoldsTotal.name == getFilenameFoldsTotal(mapShapeTestFunctionality), "Filename should match getFilenameFoldsTotal output"
|
|
35
|
+
assert pathFilenameFoldsTotal.parent == getPathRootJobDEFAULT(), "Parent directory should match default job root"
|
|
37
36
|
|
|
38
37
|
def test_getPathFilenameFoldsTotal_relativeFilename(mapShapeTestFunctionality: tuple[int, ...]) -> None:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
"""Test getPathFilenameFoldsTotal with relative filename."""
|
|
39
|
+
relativeFilename = Path("custom/path/test.foldsTotal")
|
|
40
|
+
pathFilenameFoldsTotal = getPathFilenameFoldsTotal(mapShapeTestFunctionality, relativeFilename)
|
|
41
|
+
assert pathFilenameFoldsTotal.is_absolute(), "Path should be absolute"
|
|
42
|
+
assert pathFilenameFoldsTotal == getPathRootJobDEFAULT() / relativeFilename, "Relative path should be appended to default job root"
|
|
44
43
|
|
|
45
44
|
def test_getPathFilenameFoldsTotal_createsDirs(pathTmpTesting: Path, mapShapeTestFunctionality: tuple[int, ...]) -> None:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
"""Test that getPathFilenameFoldsTotal creates necessary directories."""
|
|
46
|
+
nestedPath = pathTmpTesting / "deep/nested/structure"
|
|
47
|
+
pathFilenameFoldsTotal = getPathFilenameFoldsTotal(mapShapeTestFunctionality, nestedPath)
|
|
48
|
+
assert pathFilenameFoldsTotal.parent.exists(), "Parent directories should be created"
|
|
49
|
+
assert pathFilenameFoldsTotal.parent.is_dir(), "Created path should be a directory"
|
tests/test_other.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from collections.abc import Callable
|
|
2
2
|
from mapFolding.beDRY import getLeavesTotal, setProcessorLimit, validateListDimensions
|
|
3
|
-
from mapFolding.theSSOT import The
|
|
4
3
|
from tests.conftest import standardizedEqualToCallableReturn
|
|
5
4
|
from typing import Any, Literal
|
|
6
5
|
from Z0Z_tools import intInnit
|
tests/test_tasks.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from collections.abc import Callable
|
|
2
|
-
from mapFolding
|
|
2
|
+
from mapFolding import countFolds
|
|
3
3
|
from mapFolding.beDRY import getTaskDivisions, setProcessorLimit, validateListDimensions, getLeavesTotal
|
|
4
|
-
from mapFolding.
|
|
4
|
+
from mapFolding.oeis import getFoldsTotalKnown
|
|
5
5
|
from tests.conftest import standardizedEqualToCallableReturn
|
|
6
6
|
from typing import Literal
|
|
7
7
|
from Z0Z_tools.pytestForYourUse import PytestFor_defineConcurrencyLimit
|
mapFolding/noHomeYet.py
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Interface for retrieving known map folding totals from OEIS (Online Encyclopedia of Integer Sequences).
|
|
3
|
-
|
|
4
|
-
This module provides utilities for accessing pre-computed map folding totals that are known
|
|
5
|
-
from mathematical literature and stored in the OEIS. The functions cache results for
|
|
6
|
-
performance and provide lookups based on map dimensions.
|
|
7
|
-
|
|
8
|
-
The main functions are:
|
|
9
|
-
- makeDictionaryFoldsTotalKnown: Creates a dictionary of known folding totals indexed by map dimensions
|
|
10
|
-
- getFoldsTotalKnown: Retrieves the folding total for a specific map shape, returning -1 if unknown
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from functools import cache
|
|
14
|
-
from mapFolding.oeis import settingsOEIS
|
|
15
|
-
|
|
16
|
-
@cache
|
|
17
|
-
def makeDictionaryFoldsTotalKnown() -> dict[tuple[int, ...], int]:
|
|
18
|
-
"""Returns a dictionary mapping dimension tuples to their known folding totals."""
|
|
19
|
-
dictionaryMapDimensionsToFoldsTotalKnown: dict[tuple[int, ...], int] = {}
|
|
20
|
-
|
|
21
|
-
for settings in settingsOEIS.values():
|
|
22
|
-
sequence = settings['valuesKnown']
|
|
23
|
-
|
|
24
|
-
for n, foldingsTotal in sequence.items():
|
|
25
|
-
mapShape = settings['getMapShape'](n)
|
|
26
|
-
mapShape = tuple(sorted(mapShape))
|
|
27
|
-
dictionaryMapDimensionsToFoldsTotalKnown[mapShape] = foldingsTotal
|
|
28
|
-
return dictionaryMapDimensionsToFoldsTotalKnown
|
|
29
|
-
|
|
30
|
-
def getFoldsTotalKnown(mapShape: tuple[int, ...]) -> int:
|
|
31
|
-
lookupFoldsTotal = makeDictionaryFoldsTotalKnown()
|
|
32
|
-
return lookupFoldsTotal.get(tuple(mapShape), -1)
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
from copy import deepcopy
|
|
3
|
-
from mapFolding.someAssemblyRequired import ast_Identifier, RecipeSynthesizeFlow, Then, be, ifThis, DOT, 又, NodeChanger
|
|
4
|
-
from mapFolding.someAssemblyRequired.transformationTools import makeDictionary4InliningFunction, makeDictionaryFunctionDef
|
|
5
|
-
from typing import cast
|
|
6
|
-
import ast
|
|
7
|
-
|
|
8
|
-
def inlineFunctionDef(astFunctionDef: ast.FunctionDef, dictionary4Inlining: dict[ast_Identifier, ast.FunctionDef]) -> ast.FunctionDef:
|
|
9
|
-
|
|
10
|
-
return astFunctionDef
|
|
11
|
-
|
|
12
|
-
# Test code
|
|
13
|
-
testFlow: RecipeSynthesizeFlow = RecipeSynthesizeFlow()
|
|
14
|
-
dictionary4Inlining: dict[ast_Identifier, ast.FunctionDef] = makeDictionary4InliningFunction(
|
|
15
|
-
testFlow.sourceCallableSequential,
|
|
16
|
-
(dictionaryFunctionDef := makeDictionaryFunctionDef(testFlow.source_astModule)))
|
|
17
|
-
|
|
18
|
-
astFunctionDef = dictionaryFunctionDef[testFlow.sourceCallableSequential]
|
|
19
|
-
|
|
20
|
-
astFunctionDefTransformed = inlineFunctionDef(
|
|
21
|
-
astFunctionDef,
|
|
22
|
-
dictionary4Inlining)
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: mapFolding
|
|
3
|
-
Version: 0.8.5
|
|
4
|
-
Summary: Map folding algorithm with code transformation framework for optimizing numerical computations
|
|
5
|
-
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
|
-
License: CC-BY-NC-4.0
|
|
7
|
-
Project-URL: Donate, https://www.patreon.com/integrated
|
|
8
|
-
Project-URL: Homepage, https://github.com/hunterhogan/mapFolding
|
|
9
|
-
Project-URL: Repository, https://github.com/hunterhogan/mapFolding.git
|
|
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
|
-
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: Environment :: Console
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: Intended Audience :: Education
|
|
15
|
-
Classifier: Intended Audience :: Science/Research
|
|
16
|
-
Classifier: Natural Language :: English
|
|
17
|
-
Classifier: Operating System :: OS Independent
|
|
18
|
-
Classifier: Programming Language :: Python
|
|
19
|
-
Classifier: Programming Language :: Python :: 3
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
-
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
25
|
-
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
26
|
-
Classifier: Topic :: Software Development :: Code Generators
|
|
27
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
28
|
-
Classifier: Topic :: Software Development :: Compilers
|
|
29
|
-
Classifier: Typing :: Typed
|
|
30
|
-
Requires-Python: >=3.10
|
|
31
|
-
Description-Content-Type: text/markdown
|
|
32
|
-
License-File: LICENSE
|
|
33
|
-
Requires-Dist: autoflake
|
|
34
|
-
Requires-Dist: more_itertools
|
|
35
|
-
Requires-Dist: numba_progress
|
|
36
|
-
Requires-Dist: numba
|
|
37
|
-
Requires-Dist: numpy
|
|
38
|
-
Requires-Dist: platformdirs
|
|
39
|
-
Requires-Dist: python_minifier
|
|
40
|
-
Requires-Dist: tomli
|
|
41
|
-
Requires-Dist: Z0Z_tools
|
|
42
|
-
Provides-Extra: testing
|
|
43
|
-
Requires-Dist: mypy; extra == "testing"
|
|
44
|
-
Requires-Dist: pytest; extra == "testing"
|
|
45
|
-
Requires-Dist: pytest-cov; extra == "testing"
|
|
46
|
-
Requires-Dist: pytest-env; extra == "testing"
|
|
47
|
-
Requires-Dist: pytest-xdist; extra == "testing"
|
|
48
|
-
Requires-Dist: pyupgrade; extra == "testing"
|
|
49
|
-
Requires-Dist: ruff; extra == "testing"
|
|
50
|
-
Dynamic: license-file
|
|
51
|
-
|
|
52
|
-
# mapFolding: Algorithms for enumerating distinct map/stamp folding patterns 🗺️
|
|
53
|
-
|
|
54
|
-
[](https://pypi.org/project/mapFolding/)
|
|
55
|
-
[](https://youtu.be/g6f_miE91mk&t=4)
|
|
56
|
-
[](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
|
|
57
|
-

|
|
58
|
-
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## Quick start
|
|
63
|
-
|
|
64
|
-
```sh
|
|
65
|
-
pip install mapFolding
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
`OEIS_for_n` will run a computation from the command line.
|
|
69
|
-
|
|
70
|
-
```cmd
|
|
71
|
-
(mapFolding) C:\apps\mapFolding> OEIS_for_n A001418 5
|
|
72
|
-
186086600 distinct folding patterns.
|
|
73
|
-
Time elapsed: 1.605 seconds
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Use `mapFolding.oeisIDfor_n()` to compute a(n) for an OEIS ID.
|
|
77
|
-
|
|
78
|
-
```python
|
|
79
|
-
from mapFolding import oeisIDfor_n
|
|
80
|
-
foldsTotal = oeisIDfor_n( 'A001418', 4 )
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## Features
|
|
86
|
-
|
|
87
|
-
### 1. Simple, easy usage based on OEIS IDs
|
|
88
|
-
|
|
89
|
-
`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).
|
|
90
|
-
|
|
91
|
-
Use `getOEISids` to get the most up-to-date list of available OEIS IDs.
|
|
92
|
-
|
|
93
|
-
```cmd
|
|
94
|
-
(mapFolding) C:\apps\mapFolding> getOEISids
|
|
95
|
-
|
|
96
|
-
Available OEIS sequences:
|
|
97
|
-
A001415: Number of ways of folding a 2 X n strip of stamps. (Now extended to n=20!)
|
|
98
|
-
A001416: Number of ways of folding a 3 X n strip of stamps.
|
|
99
|
-
A001417: Number of ways of folding a 2 X 2 X ... X 2 n-dimensional map.
|
|
100
|
-
A001418: Number of ways of folding an n X n sheet of stamps.
|
|
101
|
-
A195646: Number of ways of folding a 3 X 3 X ... X 3 n-dimensional map.
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 2. **Algorithm Zoo: A Historical and Performance Journey** 🦒
|
|
105
|
-
|
|
106
|
-
This package offers a comprehensive collection of map folding algorithm implementations that showcase its evolution from historical origins to high-performance computation:
|
|
107
|
-
|
|
108
|
-
- **Historical Implementations**:
|
|
109
|
-
- Carefully restored versions of Lunnon's 1971 original [algorithm](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt) with corrections
|
|
110
|
-
- Atlas Autocode reconstruction in the `reference/foldings.AA` file
|
|
111
|
-
|
|
112
|
-
- **Direct Translations**:
|
|
113
|
-
- Python translations following the original control flow (`lunnanWhile.py`)
|
|
114
|
-
- NumPy-based vectorized implementations (`lunnanNumpy.py`)
|
|
115
|
-
|
|
116
|
-
- **Modern Implementations**:
|
|
117
|
-
- Java port adaptations (`irvineJavaPort.py`) providing cleaner procedural implementations
|
|
118
|
-
- Experimental JAX version (`jaxCount.py`) exploring GPU acceleration potential
|
|
119
|
-
- Semantically decomposed version (`flattened.py`) with clear function boundaries
|
|
120
|
-
|
|
121
|
-
- **Performance Optimized**:
|
|
122
|
-
- Numba-JIT accelerated implementations up to 1000× faster than pure Python (see [benchmarks](https://github.com/hunterhogan/mapFolding/blob/mapFolding/notes/Speed%20highlights.md))
|
|
123
|
-
- Algorithmic optimizations showcasing subtle yet powerful performance differences (`total_countPlus1vsPlusN.py`)
|
|
124
|
-
- **New Computations**: First-ever calculations for 2×19 and 2×20 maps in the `reference/jobsCompleted/` directory
|
|
125
|
-
|
|
126
|
-
The `reference` directory serves as both a historical archive and an educational resource for understanding algorithm evolution.
|
|
127
|
-
|
|
128
|
-
### 3. **Algorithmic Transformation: From Readability to Speed** 🔬
|
|
129
|
-
|
|
130
|
-
The package provides a sophisticated transformation framework that bridges the gap between human-readable algorithms and high-performance computation:
|
|
131
|
-
|
|
132
|
-
- **Core Algorithm Understanding**:
|
|
133
|
-
- Study the functional state-transformation approach in `theDao.py` with clear, isolated functions
|
|
134
|
-
- Explore the semantic decomposition in `reference/flattened.py` to understand algorithm sections
|
|
135
|
-
|
|
136
|
-
- **Code Transformation Assembly-line**:
|
|
137
|
-
- **AST Manipulation**: Analyzes and transforms the algorithm's abstract syntax tree
|
|
138
|
-
- **Dataclass "Shattering"**: Decomposes complex state objects into primitive components
|
|
139
|
-
- **Optimization Applications**: Applies domain-specific optimizations for numerical computation
|
|
140
|
-
- **LLVM Integration**: Extracts LLVM IR for low-level algorithmic analysis
|
|
141
|
-
|
|
142
|
-
- **Performance Breakthroughs**:
|
|
143
|
-
- Learn why nearly identical algorithms can have dramatically different performance (`total_countPlus1vsPlusN.py`)
|
|
144
|
-
- See how memory layout and increment strategy impact computation speed
|
|
145
|
-
- Understand the batching technique that yields order-of-magnitude improvements
|
|
146
|
-
|
|
147
|
-
### 4. **Multi-Level Architecture: From Simple API to Full Customization**
|
|
148
|
-
|
|
149
|
-
The package's architecture supports multiple levels of engagement:
|
|
150
|
-
|
|
151
|
-
- **Basic Usage**:
|
|
152
|
-
- Work with the high-level API in `basecamp.py` for standard computations
|
|
153
|
-
- Access OEIS sequence calculations with minimal code
|
|
154
|
-
|
|
155
|
-
- **Algorithm Exploration**:
|
|
156
|
-
- Compare different implementations in the `reference` directory to understand trade-offs
|
|
157
|
-
- Modify the core algorithm in `theDao.py` while preserving its functional approach
|
|
158
|
-
- Configure system-wide settings in `theSSOT.py` to adjust data types and performance characteristics
|
|
159
|
-
|
|
160
|
-
- **Advanced Transformation**:
|
|
161
|
-
- Use the `someAssemblyRequired` package to transform algorithms at the AST level
|
|
162
|
-
- Create optimized variants with different compilation settings using:
|
|
163
|
-
- `transformationTools.py` for AST manipulation
|
|
164
|
-
- `transformDataStructures.py` for complex data structure transformations
|
|
165
|
-
- `ingredientsNumba.py` for Numba-specific optimization profiles
|
|
166
|
-
- `synthesizeNumbaFlow.py` to orchestrate the transformation process
|
|
167
|
-
|
|
168
|
-
- **Custom Deployment**:
|
|
169
|
-
- Generate specialized implementations for specific dimensions
|
|
170
|
-
- Create optimized standalone modules for production use
|
|
171
|
-
- Extract LLVM IR for further analysis and optimization
|
|
172
|
-
|
|
173
|
-
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.
|
|
174
|
-
|
|
175
|
-
## Map-folding Video
|
|
176
|
-
|
|
177
|
-
~~This caused my neurosis:~~ I enjoyed the following video, which is what introduced me to map folding.
|
|
178
|
-
|
|
179
|
-
"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)
|
|
180
|
-
|
|
181
|
-
[](https://www.youtube.com/watch?v=sfH9uIY3ln4)
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## My recovery
|
|
186
|
-
|
|
187
|
-
[](https://HunterThinks.com/support)
|
|
188
|
-
[](https://www.youtube.com/@HunterHogan)
|
|
189
|
-
|
|
190
|
-
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
mapFolding/__init__.py,sha256=LBgk-iW95pzqkFGY8PbcnU0oHy0AXwJGo18mM0g8wEw,2227
|
|
2
|
-
mapFolding/basecamp.py,sha256=-__EJ2to84ssS4Fm0CAuQjRnghI9VA4cXZoWGYud1r0,4782
|
|
3
|
-
mapFolding/beDRY.py,sha256=2GPO4A8XcxoEJXB_3sro4ZFQ5gcU7ywc1-c8HLEvEv0,15280
|
|
4
|
-
mapFolding/noHomeYet.py,sha256=UKZeWlyn0SKlF9dhYoud7E6gWXpiSEekZOOoJp88WeI,1362
|
|
5
|
-
mapFolding/oeis.py,sha256=EzEnbRi_4qt8Na2tiMcvL23FXpcJEkXTwuXDYDFH_XI,12631
|
|
6
|
-
mapFolding/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
mapFolding/theDao.py,sha256=MVopt1LzhdIQYA97SEoq9bdzct6hbK0lEyPxBAAlVTc,9934
|
|
8
|
-
mapFolding/theSSOT.py,sha256=i3R_G702U7VQOil61ky60JGGsSEOk_x1555rg8yI0Tc,11978
|
|
9
|
-
mapFolding/toolboxFilesystem.py,sha256=WoqRjXqTXy5GYNmbfzWtzv1uufm7vYcgT4zJ9ffhRYY,9982
|
|
10
|
-
mapFolding/reference/__init__.py,sha256=UIEU8BJR_YDzjFQcLel3XtHzOCJiOUGlGiWzOzbvhik,2206
|
|
11
|
-
mapFolding/reference/flattened.py,sha256=QK1xG9SllqCoi68e86Hyl9d9ATUAAFNpTQI-3zmcp5I,16072
|
|
12
|
-
mapFolding/reference/hunterNumba.py,sha256=iLfyqwGdAh6c5GbapnKsWhAsNsR3O-fyGGHAdohluLw,7258
|
|
13
|
-
mapFolding/reference/irvineJavaPort.py,sha256=UEfIX4QbPLl5jnyfYIyX5YRR3_rYvPUikK8jLehsFko,4076
|
|
14
|
-
mapFolding/reference/jaxCount.py,sha256=TuDNKOnyhQfuixKmIxO9Algv7dvy7KMGhgsV3h96FGE,14853
|
|
15
|
-
mapFolding/reference/lunnanNumpy.py,sha256=mMgrgbrBpe4nmo72ThEI-MGH0OwEHmfMPczSXHp2qKo,4357
|
|
16
|
-
mapFolding/reference/lunnanWhile.py,sha256=ZL8GAQtPs5nJZSgoDl5USrLSS_zs03y98y1Z9E4jOmQ,3799
|
|
17
|
-
mapFolding/reference/rotatedEntryPoint.py,sha256=5ughpKUT2JQhoAKgoDUdYNjgWQYPGV8v-7dWEAdDmfE,10274
|
|
18
|
-
mapFolding/reference/total_countPlus1vsPlusN.py,sha256=yJZAVLVdoXqHag2_N6_6CT-Q6HXBgRro-eny93-Rlpw,9307
|
|
19
|
-
mapFolding/reference/jobsCompleted/__init__.py,sha256=TU93ZGUW1xEkT6d9mQFn_rp5DvRy0ZslEB2Q6MF5ZDc,2596
|
|
20
|
-
mapFolding/reference/jobsCompleted/[2x19]/p2x19.py,sha256=_tvYtfzMWVo2VtUbIAieoscb4N8FFflgTdW4-ljBUuA,19626
|
|
21
|
-
mapFolding/reference/jobsCompleted/p2x19/p2x19.py,sha256=eZEw4Me4ocTt6VXoK2-Sbd5SowZtxRIbN9dZmc7OCVg,6395
|
|
22
|
-
mapFolding/someAssemblyRequired/__init__.py,sha256=c2GFI2HSId2_R_aoJWBID-P9AMF3zoHJzOc10XS6DHc,2669
|
|
23
|
-
mapFolding/someAssemblyRequired/_theTypes.py,sha256=SG82WTtQy83BmInlHZHY8Nh3Kp161NcEFSA6-UU5wuE,4623
|
|
24
|
-
mapFolding/someAssemblyRequired/_tool_Make.py,sha256=8ezrMDAdUY6m1raFp-G8vNXrHEr8IGfnZJ-aMVKzGf0,7092
|
|
25
|
-
mapFolding/someAssemblyRequired/_tool_Then.py,sha256=QxuoBqj4iOeKWITjV3DcV8c25fLx3Q6mhUORD7-mCzc,2758
|
|
26
|
-
mapFolding/someAssemblyRequired/_toolboxAntecedents.py,sha256=GEAuniYRj6yOtrJO_6sGZMzsVARdejts8NXhR_0np_c,21914
|
|
27
|
-
mapFolding/someAssemblyRequired/_toolboxContainers.py,sha256=iPLZbFcGB6dKtX3WkopnM-2OtMcVuxXQT46iFhzpdfY,17815
|
|
28
|
-
mapFolding/someAssemblyRequired/_toolboxPython.py,sha256=za30092eT00tj5ctqUCRrEuq5DGeJZN-vV9T4Dro-1w,3483
|
|
29
|
-
mapFolding/someAssemblyRequired/getLLVMforNoReason.py,sha256=9RPU6vK_eUg64GtVFI_nZnvUryXw8gfHJs9NyDYHIvg,2745
|
|
30
|
-
mapFolding/someAssemblyRequired/newInliner.py,sha256=Tm9PSzt66oIXPVrN9VdQwEYBba2iEOF5X3aEsOOF-FE,946
|
|
31
|
-
mapFolding/someAssemblyRequired/synthesizeNumbaJob.py,sha256=0L5ccqBusof6MzKatKnpUmFUNkAtbapzl_Fxmofi4DE,8684
|
|
32
|
-
mapFolding/someAssemblyRequired/toolboxNumba.py,sha256=rluEmsSJOQCl2L6LlJzIc3AfeRxU6cp-sCf-rQFW-og,22613
|
|
33
|
-
mapFolding/someAssemblyRequired/transformationTools.py,sha256=iIvRxSL45qTyl0d0ztHa9BP1MrOikfXE4HBqLlNMENc,20081
|
|
34
|
-
mapFolding/syntheticModules/__init__.py,sha256=evVFqhCGa-WZKDiLcnQWjs-Bj34eRnfSLqz_d7dFYZY,83
|
|
35
|
-
mapFolding/syntheticModules/numbaCount_doTheNeedful.py,sha256=3thXThbv2Xo0t_cRGzMbHPFXTBmLClmKejR_Ibu_jOo,15697
|
|
36
|
-
mapfolding-0.8.5.dist-info/licenses/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
|
|
37
|
-
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
-
tests/conftest.py,sha256=LfogHLu7PULSECwhLQgGCgqSvDMBc5b9RGWBls3YBrM,11364
|
|
39
|
-
tests/test_computations.py,sha256=XjCej6M6lesfKB_ulWq3O-ryXBsJuuwnJ6_XjKOvgDY,3552
|
|
40
|
-
tests/test_filesystem.py,sha256=YEHNU6tUCTj9C65cKs3ETgt3OZTGVnNjxgu4aH6C9uU,3164
|
|
41
|
-
tests/test_oeis.py,sha256=uxvwmgbnylSDdsVJfuAT0LuYLbIVFwSgdLxHm-xUGBM,5043
|
|
42
|
-
tests/test_other.py,sha256=O05PFAK70Skf-k99Wcg4ASLpMpBH-WkELtk6MnynDx0,4293
|
|
43
|
-
tests/test_tasks.py,sha256=S-6PNfM__Npw0zVojgzn5M-6ODBKDyRH5ccMTqQF9C4,2865
|
|
44
|
-
mapfolding-0.8.5.dist-info/METADATA,sha256=vrusTb9uu8FQ3UksfFkVZ3txtYPNufYa3db-Rk6H1y0,9359
|
|
45
|
-
mapfolding-0.8.5.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
46
|
-
mapfolding-0.8.5.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
|
|
47
|
-
mapfolding-0.8.5.dist-info/top_level.txt,sha256=1gP2vFaqPwHujGwb3UjtMlLEGN-943VSYFR7V4gDqW8,17
|
|
48
|
-
mapfolding-0.8.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|