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.
Files changed (33) hide show
  1. mapFolding/__init__.py +66 -18
  2. mapFolding/basecamp.py +32 -17
  3. mapFolding/beDRY.py +3 -3
  4. mapFolding/oeis.py +121 -25
  5. mapFolding/someAssemblyRequired/__init__.py +48 -27
  6. mapFolding/someAssemblyRequired/_theTypes.py +11 -15
  7. mapFolding/someAssemblyRequired/_tool_Make.py +40 -12
  8. mapFolding/someAssemblyRequired/_tool_Then.py +59 -25
  9. mapFolding/someAssemblyRequired/_toolboxAntecedents.py +151 -276
  10. mapFolding/someAssemblyRequired/_toolboxContainers.py +185 -51
  11. mapFolding/someAssemblyRequired/_toolboxPython.py +165 -44
  12. mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +141 -20
  13. mapFolding/someAssemblyRequired/toolboxNumba.py +93 -52
  14. mapFolding/someAssemblyRequired/transformationTools.py +228 -138
  15. mapFolding/syntheticModules/numbaCount_doTheNeedful.py +0 -1
  16. mapFolding/theSSOT.py +147 -55
  17. mapFolding/toolboxFilesystem.py +1 -1
  18. mapfolding-0.9.0.dist-info/METADATA +177 -0
  19. mapfolding-0.9.0.dist-info/RECORD +46 -0
  20. tests/__init__.py +44 -0
  21. tests/conftest.py +75 -7
  22. tests/test_computations.py +90 -9
  23. tests/test_filesystem.py +32 -33
  24. tests/test_other.py +0 -1
  25. tests/test_tasks.py +2 -2
  26. mapFolding/noHomeYet.py +0 -32
  27. mapFolding/someAssemblyRequired/newInliner.py +0 -22
  28. mapfolding-0.8.5.dist-info/METADATA +0 -190
  29. mapfolding-0.8.5.dist-info/RECORD +0 -48
  30. {mapfolding-0.8.5.dist-info → mapfolding-0.9.0.dist-info}/WHEEL +0 -0
  31. {mapfolding-0.8.5.dist-info → mapfolding-0.9.0.dist-info}/entry_points.txt +0 -0
  32. {mapfolding-0.8.5.dist-info → mapfolding-0.9.0.dist-info}/licenses/LICENSE +0 -0
  33. {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.basecamp as basecamp
193
- dispatcherOriginal = basecamp.getPackageDispatcher
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
- def callableParameterized(*arguments: Any, **keywordArguments: Any) -> Callable[..., Any]:
197
- return callableTarget
198
- basecamp.getPackageDispatcher = callableParameterized
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
- basecamp.getPackageDispatcher = dispatcherOriginal
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)
@@ -1,16 +1,97 @@
1
- from mapFolding.basecamp import countFolds
2
- from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal
3
- from mapFolding.beDRY import validateListDimensions
4
- from mapFolding.noHomeYet import getFoldsTotalKnown
5
- from mapFolding.oeis import settingsOEIS, oeisIDfor_n
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.toolboxFilesystem import getFilenameFoldsTotal, getPathFilenameFoldsTotal, saveFoldsTotal
3
- from mapFolding.beDRY import validateListDimensions
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
- foldsTotal = 123
12
- pathFilename = pathTmpTesting / "foldsTotal.txt"
13
- with unittest.mock.patch("pathlib.Path.write_text", side_effect=OSError("Simulated write failure")):
14
- with unittest.mock.patch("os.getcwd", return_value=str(pathTmpTesting)):
15
- capturedOutput = io.StringIO()
16
- with redirect_stdout(capturedOutput):
17
- saveFoldsTotal(pathFilename, foldsTotal)
18
- fallbackFiles = list(pathTmpTesting.glob("foldsTotalYO_*.txt"))
19
- assert len(fallbackFiles) == 1, "Fallback file was not created upon write failure."
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
- ([11, 13], "p11x13.foldsTotal"),
23
- ([17, 13, 11], "p11x13x17.foldsTotal"),
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
- """Test that getFilenameFoldsTotal generates correct filenames with dimensions sorted."""
27
- mapShape = validateListDimensions(listDimensions)
28
- filenameActual = getFilenameFoldsTotal(mapShape)
29
- assert filenameActual == expectedFilename, f"Expected filename {expectedFilename} but got {filenameActual}"
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
- """Test getPathFilenameFoldsTotal with default path."""
33
- pathFilenameFoldsTotal = getPathFilenameFoldsTotal(mapShapeTestFunctionality)
34
- assert pathFilenameFoldsTotal.is_absolute(), "Path should be absolute"
35
- assert pathFilenameFoldsTotal.name == getFilenameFoldsTotal(mapShapeTestFunctionality), "Filename should match getFilenameFoldsTotal output"
36
- assert pathFilenameFoldsTotal.parent == getPathRootJobDEFAULT(), "Parent directory should match default job root"
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
- """Test getPathFilenameFoldsTotal with relative filename."""
40
- relativeFilename = Path("custom/path/test.foldsTotal")
41
- pathFilenameFoldsTotal = getPathFilenameFoldsTotal(mapShapeTestFunctionality, relativeFilename)
42
- assert pathFilenameFoldsTotal.is_absolute(), "Path should be absolute"
43
- assert pathFilenameFoldsTotal == getPathRootJobDEFAULT() / relativeFilename, "Relative path should be appended to default job root"
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
- """Test that getPathFilenameFoldsTotal creates necessary directories."""
47
- nestedPath = pathTmpTesting / "deep/nested/structure"
48
- pathFilenameFoldsTotal = getPathFilenameFoldsTotal(mapShapeTestFunctionality, nestedPath)
49
- assert pathFilenameFoldsTotal.parent.exists(), "Parent directories should be created"
50
- assert pathFilenameFoldsTotal.parent.is_dir(), "Created path should be a directory"
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.basecamp import countFolds
2
+ from mapFolding import countFolds
3
3
  from mapFolding.beDRY import getTaskDivisions, setProcessorLimit, validateListDimensions, getLeavesTotal
4
- from mapFolding.noHomeYet import getFoldsTotalKnown
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
- [![pip install mapFolding](https://img.shields.io/badge/pip%20install-mapFolding-gray.svg?colorB=3b434b)](https://pypi.org/project/mapFolding/)
55
- [![Static Badge](https://img.shields.io/badge/stinkin'%20badges-don't%20need-b98e5e)](https://youtu.be/g6f_miE91mk&t=4)
56
- [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
57
- ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen)
58
- [![License: CC-BY-NC-4.0](https://img.shields.io/badge/License-CC_BY--NC_4.0-3b434b)](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
- [![How Many Ways Can You Fold a Map?](https://i.ytimg.com/vi/sfH9uIY3ln4/hq720.jpg)](https://www.youtube.com/watch?v=sfH9uIY3ln4)
182
-
183
- ---
184
-
185
- ## My recovery
186
-
187
- [![Static Badge](https://img.shields.io/badge/2011_August-Homeless_since-blue?style=flat)](https://HunterThinks.com/support)
188
- [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC3Gx7kz61009NbhpRtPP7tw)](https://www.youtube.com/@HunterHogan)
189
-
190
- [![CC-BY-NC-4.0](https://github.com/hunterhogan/mapFolding/blob/main/CC-BY-NC-4.0.svg)](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,,