mapFolding 0.7.1__tar.gz → 0.8.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. {mapfolding-0.7.1 → mapfolding-0.8.1}/PKG-INFO +51 -46
  2. {mapfolding-0.7.1 → mapfolding-0.8.1}/README.md +41 -38
  3. mapfolding-0.8.1/mapFolding/__init__.py +38 -0
  4. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/basecamp.py +14 -0
  5. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/beDRY.py +93 -82
  6. mapfolding-0.8.1/mapFolding/filesystem.py +129 -0
  7. mapfolding-0.8.1/mapFolding/noHomeYet.py +32 -0
  8. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/oeis.py +18 -3
  9. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/reference/flattened.py +46 -45
  10. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/reference/hunterNumba.py +4 -4
  11. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/reference/irvineJavaPort.py +1 -1
  12. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/reference/lunnanNumpy.py +3 -4
  13. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/reference/lunnanWhile.py +5 -7
  14. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/reference/rotatedEntryPoint.py +2 -3
  15. mapfolding-0.8.1/mapFolding/someAssemblyRequired/__init__.py +46 -0
  16. mapfolding-0.8.1/mapFolding/someAssemblyRequired/getLLVMforNoReason.py +38 -0
  17. mapfolding-0.8.1/mapFolding/someAssemblyRequired/ingredientsNumba.py +206 -0
  18. mapfolding-0.8.1/mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +196 -0
  19. mapfolding-0.7.1/mapFolding/someAssemblyRequired/synthesizeNumbaJob.py → mapfolding-0.8.1/mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py +19 -23
  20. mapfolding-0.8.1/mapFolding/someAssemblyRequired/transformDataStructures.py +162 -0
  21. mapfolding-0.8.1/mapFolding/someAssemblyRequired/transformationTools.py +780 -0
  22. mapfolding-0.8.1/mapFolding/syntheticModules/numbaCount_doTheNeedful.py +198 -0
  23. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/theDao.py +37 -16
  24. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/theSSOT.py +47 -44
  25. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding.egg-info/PKG-INFO +51 -46
  26. mapfolding-0.8.1/mapFolding.egg-info/SOURCES.txt +42 -0
  27. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding.egg-info/requires.txt +1 -2
  28. {mapfolding-0.7.1 → mapfolding-0.8.1}/pyproject.toml +23 -16
  29. {mapfolding-0.7.1 → mapfolding-0.8.1}/tests/conftest.py +2 -3
  30. {mapfolding-0.7.1 → mapfolding-0.8.1}/tests/test_filesystem.py +0 -2
  31. {mapfolding-0.7.1 → mapfolding-0.8.1}/tests/test_other.py +2 -3
  32. {mapfolding-0.7.1 → mapfolding-0.8.1}/tests/test_tasks.py +0 -4
  33. mapfolding-0.7.1/mapFolding/__init__.py +0 -9
  34. mapfolding-0.7.1/mapFolding/filesystem.py +0 -95
  35. mapfolding-0.7.1/mapFolding/noHomeYet.py +0 -20
  36. mapfolding-0.7.1/mapFolding/reference/lunnan.py +0 -153
  37. mapfolding-0.7.1/mapFolding/someAssemblyRequired/Z0Z_workbench.py +0 -33
  38. mapfolding-0.7.1/mapFolding/someAssemblyRequired/__init__.py +0 -16
  39. mapfolding-0.7.1/mapFolding/someAssemblyRequired/getLLVMforNoReason.py +0 -21
  40. mapfolding-0.7.1/mapFolding/someAssemblyRequired/ingredientsNumba.py +0 -100
  41. mapfolding-0.7.1/mapFolding/someAssemblyRequired/synthesizeCountingFunctions.py +0 -7
  42. mapfolding-0.7.1/mapFolding/someAssemblyRequired/synthesizeDataConverters.py +0 -135
  43. mapfolding-0.7.1/mapFolding/someAssemblyRequired/synthesizeNumba.py +0 -91
  44. mapfolding-0.7.1/mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +0 -91
  45. mapfolding-0.7.1/mapFolding/someAssemblyRequired/transformationTools.py +0 -425
  46. mapfolding-0.7.1/mapFolding/someAssemblyRequired/whatWillBe.py +0 -357
  47. mapfolding-0.7.1/mapFolding/syntheticModules/dataNamespaceFlattened.py +0 -30
  48. mapfolding-0.7.1/mapFolding/syntheticModules/multiprocessingCount_doTheNeedful.py +0 -216
  49. mapfolding-0.7.1/mapFolding/syntheticModules/numbaCount.py +0 -90
  50. mapfolding-0.7.1/mapFolding/syntheticModules/numbaCountExample.py +0 -158
  51. mapfolding-0.7.1/mapFolding/syntheticModules/numbaCountSequential.py +0 -111
  52. mapfolding-0.7.1/mapFolding/syntheticModules/numbaCount_doTheNeedful.py +0 -13
  53. mapfolding-0.7.1/mapFolding/syntheticModules/numba_doTheNeedful.py +0 -12
  54. mapfolding-0.7.1/mapFolding/syntheticModules/numba_doTheNeedfulExample.py +0 -13
  55. mapfolding-0.7.1/mapFolding.egg-info/SOURCES.txt +0 -99
  56. {mapfolding-0.7.1 → mapfolding-0.8.1}/LICENSE +0 -0
  57. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/py.typed +0 -0
  58. {mapfolding-0.7.1/mapFolding/syntheticModules → mapfolding-0.8.1/mapFolding/reference}/__init__.py +0 -0
  59. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/reference/jax.py +0 -0
  60. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding/reference/total_countPlus1vsPlusN.py +0 -0
  61. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding.egg-info/dependency_links.txt +0 -0
  62. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding.egg-info/entry_points.txt +0 -0
  63. {mapfolding-0.7.1 → mapfolding-0.8.1}/mapFolding.egg-info/top_level.txt +0 -0
  64. {mapfolding-0.7.1 → mapfolding-0.8.1}/setup.cfg +0 -0
  65. {mapfolding-0.7.1 → mapfolding-0.8.1}/tests/__init__.py +0 -0
  66. {mapfolding-0.7.1 → mapfolding-0.8.1}/tests/test_computations.py +0 -0
  67. {mapfolding-0.7.1 → mapfolding-0.8.1}/tests/test_oeis.py +0 -0
@@ -1,18 +1,17 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: mapFolding
3
- Version: 0.7.1
4
- Summary: Count distinct ways to fold a map (or a strip of stamps)
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
- Requires-Dist: updateCitation; extra == "testing"
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
  [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
53
55
  ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen)
54
56
  [![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/)
55
- ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding)
56
- ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
57
57
 
58
58
  ---
59
59
 
@@ -101,44 +101,49 @@ Available OEIS sequences:
101
101
 
102
102
  ### 2. **Algorithm Zoo** 🦒
103
103
 
104
- - **Lunnons 1971 Algorithm**: A painstakingly debugged version of [the original typo-riddled code](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt)
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
- - Change multiple minute settings, such as the bit width of the data types.
111
- - Transform the algorithm using AST
112
- - Create hyper-optimized modules to compute a specific map.
113
-
114
- ### 4. **Customizing your algorithm**
115
-
116
- - mapFolding\someAssemblyRequired\synthesizeNumbaJob.py (and/or synthesizeNumba____.py, as applicable)
117
- - Synthesize a Numba-optimized module for a specific mapShape
118
- - Synthesize _from_ a module in mapFolding\syntheticModules or from any source you select
119
- - Use the existing transformation options
120
- - Or create new ways of transforming the algorithm from its source to a specific job
121
- - mapFolding\someAssemblyRequired\makeJob.py
122
- - Initialize data for a specific mapShape
123
- - mapFolding\someAssemblyRequired\synthesizeNumbaModules.py (and/or synthesizeNumba____.py, as applicable)
124
- - Synthesize one or more Numba-optimized modules for parallel or sequential computation
125
- - Overwrite the modules in mapFolding\syntheticModules or save the module(s) to a custom path
126
- - Synthesize _from_ the algorithm(s) in mapFolding\theDao.py or from any source you select
127
- - Use the existing transformation options
128
- - Or create new ways of transforming the algorithm from its source to a new module
129
- - Use your new module in synthesizeNumbaJob.py, above, as the source to create a mapShape-specific job module
130
- - mapFolding\theDao.py
131
- - Modify the algorithms for initializing values, parallel computation, and/or sequential computation
132
- - Use the modified algorithm(s) in synthesizeNumbaModules.py, above, to create Numba-optimized version(s)
133
- - Then use a Numba-optimized version in synthesizeNumbaJob.py, above, to create a hyper-optimized version for a specific mapShape
134
- - mapFolding\theSSOT.py (and/or theSSOTnumba.py and/ or theSSOT____.py, if they exist)
135
- - Modify broad settings or find functions to modify broad settings, such as data structures and their data types
136
- - Create new settings or groups of settings
137
- - mapFolding\beDRY.py
138
- - Functions to handle common tasks, such as parsing parameters or creating the `connectionGraph` for a mapShape (a Cartesian product decomposition)
139
- - mapFolding\someAssemblyRequired
140
- - Create new transformations to optimize the algorithm, such as for JAX, CuPy, or CUDA
141
- - (mapFolding\reference\jax.py has a once-functional JAX implementation, and synthesizeModuleJAX.py might be a useful starting point)
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
  [![Static Badge](https://img.shields.io/badge/2011_August-Homeless_since-blue?style=flat)](https://HunterThinks.com/support)
156
161
  [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC3Gx7kz61009NbhpRtPP7tw)](https://www.youtube.com/@HunterHogan)
157
162
 
158
- [![CC-BY-NC-4.0](https://github.com/hunterhogan/mapFolding/blob/main/CC-BY-NC-4.0.png)](https://creativecommons.org/licenses/by-nc/4.0/)
163
+ [![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/)
@@ -5,8 +5,6 @@
5
5
  [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
6
6
  ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen)
7
7
  [![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/)
8
- ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding)
9
- ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
10
8
 
11
9
  ---
12
10
 
@@ -54,44 +52,49 @@ Available OEIS sequences:
54
52
 
55
53
  ### 2. **Algorithm Zoo** 🦒
56
54
 
57
- - **Lunnons 1971 Algorithm**: A painstakingly debugged version of [the original typo-riddled code](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt)
55
+ - **Lunnon's 1971 Algorithm**: A painstakingly debugged version of [the original typo-riddled code](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt)
58
56
  - The /reference directory.
59
57
  - **Numba-JIT Accelerated**: Up to 1000× faster than pure Python ([benchmarks](https://github.com/hunterhogan/mapFolding/blob/mapFolding/notes/Speed%20highlights.md))
60
58
 
61
- ### 3. **For Researchers** 🔬
62
-
63
- - Change multiple minute settings, such as the bit width of the data types.
64
- - Transform the algorithm using AST
65
- - Create hyper-optimized modules to compute a specific map.
66
-
67
- ### 4. **Customizing your algorithm**
68
-
69
- - mapFolding\someAssemblyRequired\synthesizeNumbaJob.py (and/or synthesizeNumba____.py, as applicable)
70
- - Synthesize a Numba-optimized module for a specific mapShape
71
- - Synthesize _from_ a module in mapFolding\syntheticModules or from any source you select
72
- - Use the existing transformation options
73
- - Or create new ways of transforming the algorithm from its source to a specific job
74
- - mapFolding\someAssemblyRequired\makeJob.py
75
- - Initialize data for a specific mapShape
76
- - mapFolding\someAssemblyRequired\synthesizeNumbaModules.py (and/or synthesizeNumba____.py, as applicable)
77
- - Synthesize one or more Numba-optimized modules for parallel or sequential computation
78
- - Overwrite the modules in mapFolding\syntheticModules or save the module(s) to a custom path
79
- - Synthesize _from_ the algorithm(s) in mapFolding\theDao.py or from any source you select
80
- - Use the existing transformation options
81
- - Or create new ways of transforming the algorithm from its source to a new module
82
- - Use your new module in synthesizeNumbaJob.py, above, as the source to create a mapShape-specific job module
83
- - mapFolding\theDao.py
84
- - Modify the algorithms for initializing values, parallel computation, and/or sequential computation
85
- - Use the modified algorithm(s) in synthesizeNumbaModules.py, above, to create Numba-optimized version(s)
86
- - Then use a Numba-optimized version in synthesizeNumbaJob.py, above, to create a hyper-optimized version for a specific mapShape
87
- - mapFolding\theSSOT.py (and/or theSSOTnumba.py and/ or theSSOT____.py, if they exist)
88
- - Modify broad settings or find functions to modify broad settings, such as data structures and their data types
89
- - Create new settings or groups of settings
90
- - mapFolding\beDRY.py
91
- - Functions to handle common tasks, such as parsing parameters or creating the `connectionGraph` for a mapShape (a Cartesian product decomposition)
92
- - mapFolding\someAssemblyRequired
93
- - Create new transformations to optimize the algorithm, such as for JAX, CuPy, or CUDA
94
- - (mapFolding\reference\jax.py has a once-functional JAX implementation, and synthesizeModuleJAX.py might be a useful starting point)
59
+ ### 3. **For Researchers and Power Users** 🔬
60
+
61
+ This package provides a sophisticated code transformation framework that can turn readable algorithm implementations into highly-optimized computational engines:
62
+
63
+ - **Algorithmic Exploration**: Study the core algorithm in `theDao.py`, which uses a functional state-transformation approach with clear, isolated functions
64
+ - **Performance Optimization**: Generate specialized implementations with the `someAssemblyRequired` transformation pipeline:
65
+ - AST-based code analysis and manipulation
66
+ - Dataclass "shattering" to decompose complex state objects into primitive components
67
+ - Just-in-time compilation with Numba and various optimization profiles
68
+ - LLVM IR extraction for low-level algorithmic analysis
69
+
70
+ - **Extensible Design**: The transformation framework is abstract and generic, enabling:
71
+ - Creation of new optimization targets beyond the included Numba implementation
72
+ - Customization of compilation parameters and optimization levels
73
+ - Development of specialized algorithms for specific map dimensions
74
+
75
+ ### 4. **Customization and Extension Guide**
76
+
77
+ The package architecture supports multiple levels of customization:
78
+
79
+ - **Basic Usage**: Work with the high-level API in `basecamp.py` for standard computations
80
+ - **Algorithm Modification**:
81
+ - Modify the core algorithm in `theDao.py` while preserving its functional approach
82
+ - Configure system-wide settings in `theSSOT.py` to adjust data types and performance characteristics
83
+ - Use utility functions in `beDRY.py` for common operations
84
+
85
+ - **Advanced Transformation**:
86
+ - The `someAssemblyRequired` package provides tools to transform code at the AST level:
87
+ - `transformationTools.py` contains utilities for AST manipulation and code generation
88
+ - `transformDataStructures.py` handles complex data structure transformations
89
+ - `ingredientsNumba.py` provides Numba-specific configuration profiles
90
+ - `synthesizeNumbaFlow.py` orchestrates the transformation process
91
+
92
+ - **Custom Deployment**:
93
+ - Generate specialized implementations for specific dimensions
94
+ - Create optimized modules that can be executed as standalone scripts
95
+ - Extract LLVM IR for further analysis or optimization
96
+
97
+ 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.
95
98
 
96
99
  ## Map-folding Video
97
100
 
@@ -108,4 +111,4 @@ Available OEIS sequences:
108
111
  [![Static Badge](https://img.shields.io/badge/2011_August-Homeless_since-blue?style=flat)](https://HunterThinks.com/support)
109
112
  [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC3Gx7kz61009NbhpRtPP7tw)](https://www.youtube.com/@HunterHogan)
110
113
 
111
- [![CC-BY-NC-4.0](https://github.com/hunterhogan/mapFolding/blob/main/CC-BY-NC-4.0.png)](https://creativecommons.org/licenses/by-nc/4.0/)
114
+ [![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/)
@@ -0,0 +1,38 @@
1
+ """
2
+ Map folding enumeration and counting algorithms with optimization capabilities.
3
+
4
+ This package implements algorithms to count and enumerate the various ways
5
+ a rectangular map can be folded, based on the mathematical problem described
6
+ in Lunnon's 1971 paper. It provides multiple layers of functionality, from
7
+ high-level user interfaces to low-level algorithmic optimizations and code
8
+ transformation tools.
9
+
10
+ Core modules:
11
+ - basecamp: Public API with simplified interfaces for end users
12
+ - theDao: Core computational algorithm using a functional state-transformation approach
13
+ - beDRY: Utility functions for common operations and parameter management
14
+ - theSSOT: Single Source of Truth for configuration, types, and state management
15
+ - oeis: Interface to the Online Encyclopedia of Integer Sequences for known results
16
+
17
+ Extended functionality:
18
+ - someAssemblyRequired: Code transformation framework that optimizes the core algorithm
19
+ through AST manipulation, dataclass transformation, and compilation techniques
20
+
21
+ Special directories:
22
+ - .cache/: Stores cached data from external sources like OEIS to improve performance
23
+ - syntheticModules/: Contains dynamically generated, optimized implementations of the
24
+ core algorithm created by the code transformation framework
25
+
26
+ This package strives to balance algorithm readability and understandability with
27
+ high-performance computation capabilities, allowing users to compute map folding
28
+ totals for larger dimensions than previously feasible.
29
+ """
30
+ from mapFolding.basecamp import countFolds as countFolds
31
+ from mapFolding.oeis import clearOEIScache, getOEISids, OEIS_for_n
32
+
33
+ __all__ = [
34
+ 'clearOEIScache',
35
+ 'countFolds',
36
+ 'getOEISids',
37
+ 'OEIS_for_n',
38
+ ]
@@ -1,3 +1,17 @@
1
+ """
2
+ Public API for the map folding algorithm with simplified interface.
3
+
4
+ This module provides the main entry point for users of the mapFolding package,
5
+ abstracting away the complexities of the computational algorithm. It offers
6
+ a high-level interface to count the total number of possible ways to fold
7
+ a rectangular map of specified dimensions, with options for customizing the
8
+ computation process and saving results.
9
+
10
+ The primary function is countFolds, which handles parameter validation,
11
+ computation state management, dispatching to the appropriate algorithm
12
+ implementation, and optional persistence of results.
13
+ """
14
+
1
15
  from collections.abc import Sequence
2
16
  from mapFolding.beDRY import outfitCountFolds, setCPUlimit, validateListDimensions
3
17
  from mapFolding.filesystem import getPathFilenameFoldsTotal, saveFoldsTotal
@@ -1,30 +1,26 @@
1
- """A relatively stable API for oft-needed functionality."""
2
- from mapFolding.theSSOT import (
3
- Array3D,
4
- ComputationState,
5
- getDatatypePackage,
6
- getNumpyDtypeDefault,
7
- )
1
+ """
2
+ Utility functions for maintaining DRY (Don't Repeat Yourself) principles in the mapFolding package.
3
+
4
+ This module provides a collection of helper functions that abstract common operations needed
5
+ throughout the package, preventing code duplication and ensuring consistency. The functions
6
+ manage core aspects of the computation process, including:
7
+
8
+ 1. Resource allocation and system limits management
9
+ 2. Data structure initialization and manipulation
10
+ 3. Parameter validation and interpretation
11
+ 4. Construction of specialized arrays and matrices for the folding algorithm
12
+
13
+ The functions in this module serve as a relatively stable API for other modules to use,
14
+ particularly for initializing computation state, validating inputs, and creating data
15
+ structures needed by the folding algorithms.
16
+ """
8
17
  from collections.abc import Sequence
18
+ from mapFolding.theSSOT import Array3D, ComputationState, getDatatypePackage, getNumpyDtypeDefault
9
19
  from sys import maxsize as sysMaxsize
10
20
  from typing import Any
11
21
  from Z0Z_tools import defineConcurrencyLimit, intInnit, oopsieKwargsie
12
22
  import numpy
13
23
 
14
- def validateListDimensions(listDimensions: Sequence[int]) -> tuple[int, ...]:
15
- if not listDimensions:
16
- raise ValueError("listDimensions is a required parameter.")
17
- listValidated: list[int] = intInnit(listDimensions, 'listDimensions')
18
- listNonNegative: list[int] = []
19
- for dimension in listValidated:
20
- if dimension < 0:
21
- raise ValueError(f"Dimension {dimension} must be non-negative")
22
- listNonNegative.append(dimension)
23
- dimensionsValid = [dimension for dimension in listNonNegative if dimension > 0]
24
- if len(dimensionsValid) < 2:
25
- raise NotImplementedError(f"This function requires listDimensions, {listDimensions}, to have at least two dimensions greater than 0. You may want to look at https://oeis.org/.")
26
- return tuple(sorted(dimensionsValid))
27
-
28
24
  def getLeavesTotal(mapShape: tuple[int, ...]) -> int:
29
25
  productDimensions = 1
30
26
  for dimension in mapShape:
@@ -33,7 +29,59 @@ def getLeavesTotal(mapShape: tuple[int, ...]) -> int:
33
29
  productDimensions *= dimension
34
30
  return productDimensions
35
31
 
36
- def getNumpyDtype(datatype: type[numpy.signedinteger[Any]] | None = None) -> type[numpy.signedinteger[Any]]:
32
+ def getTaskDivisions(computationDivisions: int | str | None, concurrencyLimit: int, leavesTotal: int) -> int:
33
+ """
34
+ Determines whether to divide the computation into tasks and how many divisions.
35
+
36
+ Parameters
37
+ ----------
38
+ computationDivisions (None)
39
+ Specifies how to divide computations:
40
+ - `None`: no division of the computation into tasks; sets task divisions to 0.
41
+ - int: direct set the number of task divisions; cannot exceed the map's total leaves.
42
+ - `'maximum'`: divides into `leavesTotal`-many `taskDivisions`.
43
+ - `'cpu'`: limits the divisions to the number of available CPUs, i.e. `concurrencyLimit`.
44
+ concurrencyLimit
45
+ Maximum number of concurrent tasks allowed.
46
+ CPUlimit
47
+ for error reporting.
48
+ listDimensions
49
+ for error reporting.
50
+
51
+ Returns
52
+ -------
53
+ taskDivisions
54
+ How many tasks must finish before the job can compute the total number of folds; `0` means no tasks, only job.
55
+
56
+ Raises
57
+ ------
58
+ ValueError
59
+ If computationDivisions is an unsupported type or if resulting task divisions exceed total leaves.
60
+
61
+ Notes
62
+ -----
63
+ Task divisions should not exceed total leaves or the folds will be over-counted.
64
+ """
65
+ taskDivisions = 0
66
+ if not computationDivisions:
67
+ pass
68
+ elif isinstance(computationDivisions, int):
69
+ taskDivisions = computationDivisions
70
+ elif isinstance(computationDivisions, str): # type: ignore
71
+ # 'Unnecessary isinstance call; "str" is always an instance of "str", so sayeth Pylance'. Yeah, well "User is not always an instance of "correct input" so sayeth the programmer.
72
+ computationDivisions = computationDivisions.lower()
73
+ if computationDivisions == 'maximum':
74
+ taskDivisions = leavesTotal
75
+ elif computationDivisions == 'cpu':
76
+ taskDivisions = min(concurrencyLimit, leavesTotal)
77
+ else:
78
+ raise ValueError(f"I received {computationDivisions} for the parameter, `computationDivisions`, but the so-called programmer didn't implement code for that.")
79
+
80
+ if taskDivisions > leavesTotal:
81
+ raise ValueError(f"Problem: `taskDivisions`, ({taskDivisions}), is greater than `leavesTotal`, ({leavesTotal}), which will cause duplicate counting of the folds.\n\nChallenge: you cannot directly set `taskDivisions` or `leavesTotal`. They are derived from parameters that may or may not still be named `computationDivisions`, `CPUlimit` , and `listDimensions` and from dubious-quality Python code.")
82
+ return int(max(0, taskDivisions))
83
+
84
+ def interpretParameter_datatype(datatype: type[numpy.signedinteger[Any]] | None = None) -> type[numpy.signedinteger[Any]]:
37
85
  """An imperfect way to reduce code duplication."""
38
86
  if 'numpy' == getDatatypePackage():
39
87
  numpyDtype = datatype or getNumpyDtypeDefault()
@@ -42,7 +90,7 @@ def getNumpyDtype(datatype: type[numpy.signedinteger[Any]] | None = None) -> typ
42
90
  return numpyDtype
43
91
 
44
92
  def makeConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int, datatype: type[numpy.signedinteger[Any]] | None = None) -> Array3D:
45
- numpyDtype = getNumpyDtype(datatype)
93
+ numpyDtype = interpretParameter_datatype(datatype)
46
94
  dimensionsTotal = len(mapShape)
47
95
  cumulativeProduct = numpy.multiply.accumulate([1] + list(mapShape), dtype=numpyDtype)
48
96
  arrayDimensions = numpy.array(mapShape, dtype=numpyDtype)
@@ -69,9 +117,15 @@ def makeConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int, datatype: t
69
117
  return connectionGraph
70
118
 
71
119
  def makeDataContainer(shape: int | tuple[int, ...], datatype: type[numpy.signedinteger[Any]] | None = None) -> numpy.ndarray[Any, numpy.dtype[numpy.signedinteger[Any]]]:
72
- numpyDtype = getNumpyDtype(datatype)
120
+ numpyDtype = interpretParameter_datatype(datatype)
73
121
  return numpy.zeros(shape, dtype=numpyDtype)
74
122
 
123
+ def outfitCountFolds(mapShape: tuple[int, ...], computationDivisions: int | str | None = None, concurrencyLimit: int = 1) -> ComputationState:
124
+ leavesTotal = getLeavesTotal(mapShape)
125
+ taskDivisions = getTaskDivisions(computationDivisions, concurrencyLimit, leavesTotal)
126
+ computationStateInitialized = ComputationState(mapShape, leavesTotal, taskDivisions, concurrencyLimit)
127
+ return computationStateInitialized
128
+
75
129
  def setCPUlimit(CPUlimit: Any | None) -> int:
76
130
  """Sets CPU limit for concurrent operations.
77
131
 
@@ -106,66 +160,23 @@ def setCPUlimit(CPUlimit: Any | None) -> int:
106
160
  concurrencyLimit: int = defineConcurrencyLimit(CPUlimit, get_num_threads())
107
161
  set_num_threads(concurrencyLimit)
108
162
  concurrencyLimit = get_num_threads()
109
- elif concurrencyPackage == 'algorithm':
163
+ elif concurrencyPackage == 'multiprocessing':
110
164
  # When to use multiprocessing.set_start_method https://github.com/hunterhogan/mapFolding/issues/6
111
- concurrencyLimit: int = defineConcurrencyLimit(CPUlimit)
165
+ concurrencyLimit = defineConcurrencyLimit(CPUlimit)
112
166
  else:
113
167
  raise NotImplementedError(f"I received {concurrencyPackage=} but I don't know what to do with that.")
114
168
  return concurrencyLimit
115
169
 
116
- def getTaskDivisions(computationDivisions: int | str | None, concurrencyLimit: int, leavesTotal: int) -> int:
117
- """
118
- Determines whether to divide the computation into tasks and how many divisions.
119
-
120
- Parameters
121
- ----------
122
- computationDivisions (None)
123
- Specifies how to divide computations:
124
- - `None`: no division of the computation into tasks; sets task divisions to 0.
125
- - int: direct set the number of task divisions; cannot exceed the map's total leaves.
126
- - `'maximum'`: divides into `leavesTotal`-many `taskDivisions`.
127
- - `'cpu'`: limits the divisions to the number of available CPUs, i.e. `concurrencyLimit`.
128
- concurrencyLimit
129
- Maximum number of concurrent tasks allowed.
130
- CPUlimit
131
- for error reporting.
132
- listDimensions
133
- for error reporting.
134
-
135
- Returns
136
- -------
137
- taskDivisions
138
- How many tasks must finish before the job can compute the total number of folds; `0` means no tasks, only job.
139
-
140
- Raises
141
- ------
142
- ValueError
143
- If computationDivisions is an unsupported type or if resulting task divisions exceed total leaves.
144
-
145
- Notes
146
- -----
147
- Task divisions should not exceed total leaves or the folds will be over-counted.
148
- """
149
- taskDivisions = 0
150
- if not computationDivisions:
151
- pass
152
- elif isinstance(computationDivisions, int):
153
- taskDivisions = computationDivisions
154
- elif isinstance(computationDivisions, str): # type: ignore 'Unnecessary isinstance call; "str" is always an instance of "str", so sayeth Pylance'. Yeah, well "User is not always an instance of "correct input" so sayeth the programmer.
155
- computationDivisions = computationDivisions.lower()
156
- if computationDivisions == 'maximum':
157
- taskDivisions = leavesTotal
158
- elif computationDivisions == 'cpu':
159
- taskDivisions = min(concurrencyLimit, leavesTotal)
160
- else:
161
- raise ValueError(f"I received {computationDivisions} for the parameter, `computationDivisions`, but the so-called programmer didn't implement code for that.")
162
-
163
- if taskDivisions > leavesTotal:
164
- raise ValueError(f"Problem: `taskDivisions`, ({taskDivisions}), is greater than `leavesTotal`, ({leavesTotal}), which will cause duplicate counting of the folds.\n\nChallenge: you cannot directly set `taskDivisions` or `leavesTotal`. They are derived from parameters that may or may not still be named `computationDivisions`, `CPUlimit` , and `listDimensions` and from dubious-quality Python code.")
165
- return int(max(0, taskDivisions))
166
-
167
- def outfitCountFolds(mapShape: tuple[int, ...], computationDivisions: int | str | None = None, concurrencyLimit: int = 1) -> ComputationState:
168
- leavesTotal = getLeavesTotal(mapShape)
169
- taskDivisions = getTaskDivisions(computationDivisions, concurrencyLimit, leavesTotal)
170
- computationStateInitialized = ComputationState(mapShape, leavesTotal, taskDivisions, concurrencyLimit)
171
- return computationStateInitialized
170
+ def validateListDimensions(listDimensions: Sequence[int]) -> tuple[int, ...]:
171
+ if not listDimensions:
172
+ raise ValueError("listDimensions is a required parameter.")
173
+ listValidated: list[int] = intInnit(listDimensions, 'listDimensions')
174
+ listNonNegative: list[int] = []
175
+ for dimension in listValidated:
176
+ if dimension < 0:
177
+ raise ValueError(f"Dimension {dimension} must be non-negative")
178
+ listNonNegative.append(dimension)
179
+ dimensionsValid = [dimension for dimension in listNonNegative if dimension > 0]
180
+ if len(dimensionsValid) < 2:
181
+ raise NotImplementedError(f"This function requires listDimensions, {listDimensions}, to have at least two dimensions greater than 0. You may want to look at https://oeis.org/.")
182
+ return tuple(sorted(dimensionsValid))