mapFolding 0.11.1__tar.gz → 0.11.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mapfolding-0.11.1 → mapfolding-0.11.2}/PKG-INFO +16 -8
- {mapfolding-0.11.1 → mapfolding-0.11.2}/README.md +15 -7
- mapfolding-0.11.2/mapFolding/__init__.py +75 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/basecamp.py +13 -10
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/beDRY.py +113 -2
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/dataBaskets.py +24 -2
- mapfolding-0.11.1/mapFolding/toolboxFilesystem.py → mapfolding-0.11.2/mapFolding/filesystemToolkit.py +3 -3
- mapfolding-0.11.2/mapFolding/infoBooth.py +96 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/oeis.py +3 -2
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/RecipeJob.py +3 -4
- mapfolding-0.11.2/mapFolding/someAssemblyRequired/Z0Z_makeSomeModules.py +490 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/__init__.py +3 -3
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/_toolIfThis.py +5 -5
- mapfolding-0.11.1/mapFolding/someAssemblyRequired/_toolboxContainers.py → mapfolding-0.11.2/mapFolding/someAssemblyRequired/_toolkitContainers.py +6 -7
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +8 -7
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +3 -2
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/transformationTools.py +11 -10
- mapfolding-0.11.2/mapFolding/syntheticModules/countParallel.py +98 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/dataPacking.py +1 -1
- mapfolding-0.11.2/mapFolding/syntheticModules/numbaCount.py +202 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/theDao.py +1 -1
- mapfolding-0.11.2/mapFolding/theSSOT.py +29 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/PKG-INFO +16 -8
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/SOURCES.txt +5 -3
- {mapfolding-0.11.1 → mapfolding-0.11.2}/pyproject.toml +2 -2
- {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/conftest.py +7 -9
- {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_computations.py +1 -1
- {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_filesystem.py +1 -2
- {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_other.py +1 -1
- {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_tasks.py +1 -3
- mapfolding-0.11.1/mapFolding/__init__.py +0 -115
- mapfolding-0.11.1/mapFolding/someAssemblyRequired/Z0Z_makeSomeModules.py +0 -325
- mapfolding-0.11.1/mapFolding/syntheticModules/numbaCount.py +0 -201
- mapfolding-0.11.1/mapFolding/theSSOT.py +0 -268
- {mapfolding-0.11.1 → mapfolding-0.11.2}/LICENSE +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/daoOfMapFolding.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/datatypes.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/py.typed +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/__init__.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/flattened.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/hunterNumba.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/irvineJavaPort.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/jaxCount.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/jobsCompleted/[2x19]/p2x19.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/jobsCompleted/__init__.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/jobsCompleted/p2x19/p2x19.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/lunnonNumpy.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/lunnonWhile.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/rotatedEntryPoint.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/total_countPlus1vsPlusN.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/getLLVMforNoReason.py +0 -0
- /mapfolding-0.11.1/mapFolding/someAssemblyRequired/toolboxNumba.py → /mapfolding-0.11.2/mapFolding/someAssemblyRequired/toolkitNumba.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/__init__.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/daoOfMapFolding.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/initializeCount.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/theorem2.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/theorem2Numba.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/theorem2Trimmed.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/dependency_links.txt +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/entry_points.txt +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/requires.txt +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/top_level.txt +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/setup.cfg +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/__init__.py +0 -0
- {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_oeis.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mapFolding
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.2
|
|
4
4
|
Summary: Map folding algorithm with code transformation framework for optimizing numerical computations
|
|
5
5
|
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
6
|
License: CC-BY-NC-4.0
|
|
@@ -67,12 +67,6 @@ Dynamic: license-file
|
|
|
67
67
|
- You're interested in solving mathematical puzzles through code
|
|
68
68
|
- You're learning about Numba and advanced Python optimization
|
|
69
69
|
|
|
70
|
-
**This package is NOT for you if:**
|
|
71
|
-
|
|
72
|
-
- You're looking for a general-purpose folding simulation tool
|
|
73
|
-
- You need commercial-ready mapping software
|
|
74
|
-
- You want simple visualization of folding patterns
|
|
75
|
-
|
|
76
70
|
## What Does This Package Actually Do?
|
|
77
71
|
|
|
78
72
|
`mapFolding` solves a specific mathematical problem: counting the number of distinct ways to fold a rectangular map. While this may sound niche, it's a fascinating computational challenge that demonstrates:
|
|
@@ -87,7 +81,7 @@ The package has achieved new computational records, including first-ever calcula
|
|
|
87
81
|
```python
|
|
88
82
|
# Compute the number of ways to fold a 5×5 grid:
|
|
89
83
|
from mapFolding import oeisIDfor_n
|
|
90
|
-
foldsTotal = oeisIDfor_n('A001418', 5)
|
|
84
|
+
foldsTotal = oeisIDfor_n('A001418', 5)
|
|
91
85
|
```
|
|
92
86
|
|
|
93
87
|
## Key Benefits for Computational Enthusiasts
|
|
@@ -178,4 +172,18 @@ If you've read this far and are intrigued by computational puzzles, algorithm op
|
|
|
178
172
|
|
|
179
173
|
Whether you use it to solve map folding problems or to study its optimization techniques, `mapFolding` offers a unique window into advanced Python programming approaches.
|
|
180
174
|
|
|
175
|
+
## My recovery
|
|
176
|
+
|
|
177
|
+
[](https://HunterThinks.com/support)
|
|
178
|
+
[](https://www.youtube.com/@HunterHogan)
|
|
179
|
+
|
|
180
|
+
## How to code
|
|
181
|
+
|
|
182
|
+
Coding One Step at a Time:
|
|
183
|
+
|
|
184
|
+
0. WRITE CODE.
|
|
185
|
+
1. Don't write stupid code that's hard to revise.
|
|
186
|
+
2. Write good code.
|
|
187
|
+
3. When revising, write better code.
|
|
188
|
+
|
|
181
189
|
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
@@ -11,12 +11,6 @@
|
|
|
11
11
|
- You're interested in solving mathematical puzzles through code
|
|
12
12
|
- You're learning about Numba and advanced Python optimization
|
|
13
13
|
|
|
14
|
-
**This package is NOT for you if:**
|
|
15
|
-
|
|
16
|
-
- You're looking for a general-purpose folding simulation tool
|
|
17
|
-
- You need commercial-ready mapping software
|
|
18
|
-
- You want simple visualization of folding patterns
|
|
19
|
-
|
|
20
14
|
## What Does This Package Actually Do?
|
|
21
15
|
|
|
22
16
|
`mapFolding` solves a specific mathematical problem: counting the number of distinct ways to fold a rectangular map. While this may sound niche, it's a fascinating computational challenge that demonstrates:
|
|
@@ -31,7 +25,7 @@ The package has achieved new computational records, including first-ever calcula
|
|
|
31
25
|
```python
|
|
32
26
|
# Compute the number of ways to fold a 5×5 grid:
|
|
33
27
|
from mapFolding import oeisIDfor_n
|
|
34
|
-
foldsTotal = oeisIDfor_n('A001418', 5)
|
|
28
|
+
foldsTotal = oeisIDfor_n('A001418', 5)
|
|
35
29
|
```
|
|
36
30
|
|
|
37
31
|
## Key Benefits for Computational Enthusiasts
|
|
@@ -122,4 +116,18 @@ If you've read this far and are intrigued by computational puzzles, algorithm op
|
|
|
122
116
|
|
|
123
117
|
Whether you use it to solve map folding problems or to study its optimization techniques, `mapFolding` offers a unique window into advanced Python programming approaches.
|
|
124
118
|
|
|
119
|
+
## My recovery
|
|
120
|
+
|
|
121
|
+
[](https://HunterThinks.com/support)
|
|
122
|
+
[](https://www.youtube.com/@HunterHogan)
|
|
123
|
+
|
|
124
|
+
## How to code
|
|
125
|
+
|
|
126
|
+
Coding One Step at a Time:
|
|
127
|
+
|
|
128
|
+
0. WRITE CODE.
|
|
129
|
+
1. Don't write stupid code that's hard to revise.
|
|
130
|
+
2. Write good code.
|
|
131
|
+
3. When revising, write better code.
|
|
132
|
+
|
|
125
133
|
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from typing import Any, TypeAlias
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
yourPythonIsOld: TypeAlias = Any
|
|
5
|
+
# ruff: noqa: E402
|
|
6
|
+
|
|
7
|
+
if sys.version_info >= (3, 11):
|
|
8
|
+
from typing import TypedDict as TypedDict
|
|
9
|
+
from typing import NotRequired as NotRequired
|
|
10
|
+
else:
|
|
11
|
+
try:
|
|
12
|
+
from typing_extensions import TypedDict as TypedDict
|
|
13
|
+
from typing_extensions import NotRequired as NotRequired
|
|
14
|
+
except Exception:
|
|
15
|
+
TypedDict = dict[yourPythonIsOld, yourPythonIsOld]
|
|
16
|
+
from collections.abc import Iterable
|
|
17
|
+
NotRequired: TypeAlias = Iterable
|
|
18
|
+
|
|
19
|
+
from mapFolding.datatypes import (
|
|
20
|
+
Array1DElephino as Array1DElephino,
|
|
21
|
+
Array1DFoldsTotal as Array1DFoldsTotal,
|
|
22
|
+
Array1DLeavesTotal as Array1DLeavesTotal,
|
|
23
|
+
Array3D as Array3D,
|
|
24
|
+
DatatypeElephino as DatatypeElephino,
|
|
25
|
+
DatatypeFoldsTotal as DatatypeFoldsTotal,
|
|
26
|
+
DatatypeLeavesTotal as DatatypeLeavesTotal,
|
|
27
|
+
NumPyElephino as NumPyElephino,
|
|
28
|
+
NumPyFoldsTotal as NumPyFoldsTotal,
|
|
29
|
+
NumPyIntegerType as NumPyIntegerType,
|
|
30
|
+
NumPyLeavesTotal as NumPyLeavesTotal,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from mapFolding.theSSOT import PackageSettings as PackageSettings, packageSettings as packageSettings
|
|
34
|
+
|
|
35
|
+
from mapFolding.beDRY import (
|
|
36
|
+
ComputationState as ComputationState,
|
|
37
|
+
getConnectionGraph as getConnectionGraph,
|
|
38
|
+
getLeavesTotal as getLeavesTotal,
|
|
39
|
+
getTaskDivisions as getTaskDivisions,
|
|
40
|
+
makeDataContainer as makeDataContainer,
|
|
41
|
+
outfitCountFolds as outfitCountFolds,
|
|
42
|
+
setProcessorLimit as setProcessorLimit,
|
|
43
|
+
validateListDimensions as validateListDimensions,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
from mapFolding.dataBaskets import MapFoldingState as MapFoldingState
|
|
47
|
+
|
|
48
|
+
from mapFolding.infoBooth import (
|
|
49
|
+
PackageInformation as PackageInformation,
|
|
50
|
+
raiseIfNoneGitHubIssueNumber3 as raiseIfNoneGitHubIssueNumber3,
|
|
51
|
+
The as The,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
from mapFolding.theDao import (
|
|
55
|
+
countInitialize as countInitialize,
|
|
56
|
+
doTheNeedful as doTheNeedful,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
from mapFolding.filesystemToolkit import (
|
|
60
|
+
getFilenameFoldsTotal as getFilenameFoldsTotal,
|
|
61
|
+
getPathFilenameFoldsTotal as getPathFilenameFoldsTotal,
|
|
62
|
+
getPathRootJobDEFAULT as getPathRootJobDEFAULT,
|
|
63
|
+
saveFoldsTotal as saveFoldsTotal,
|
|
64
|
+
saveFoldsTotalFAILearly as saveFoldsTotalFAILearly,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
from mapFolding.basecamp import countFolds as countFolds
|
|
68
|
+
|
|
69
|
+
from mapFolding.oeis import (
|
|
70
|
+
clearOEIScache as clearOEIScache,
|
|
71
|
+
getFoldsTotalKnown as getFoldsTotalKnown,
|
|
72
|
+
getOEISids as getOEISids,
|
|
73
|
+
OEIS_for_n as OEIS_for_n,
|
|
74
|
+
oeisIDfor_n as oeisIDfor_n,
|
|
75
|
+
)
|
|
@@ -11,9 +11,7 @@ appropriate algorithm implementation, and optional persistence of results.
|
|
|
11
11
|
|
|
12
12
|
from collections.abc import Sequence
|
|
13
13
|
from mapFolding import (
|
|
14
|
-
ComputationState,
|
|
15
14
|
getPathFilenameFoldsTotal,
|
|
16
|
-
outfitCountFolds,
|
|
17
15
|
saveFoldsTotal,
|
|
18
16
|
saveFoldsTotalFAILearly,
|
|
19
17
|
setProcessorLimit,
|
|
@@ -163,20 +161,25 @@ def countFolds(listDimensions: Sequence[int] | None = None
|
|
|
163
161
|
from mapFolding.syntheticModules.initializeCount import initializeGroupsOfFolds
|
|
164
162
|
mapFoldingState = initializeGroupsOfFolds(mapFoldingState)
|
|
165
163
|
|
|
166
|
-
from mapFolding.syntheticModules.dataPacking import
|
|
167
|
-
mapFoldingState =
|
|
164
|
+
from mapFolding.syntheticModules.dataPacking import sequential
|
|
165
|
+
mapFoldingState = sequential(mapFoldingState)
|
|
168
166
|
|
|
169
167
|
foldsTotal = mapFoldingState.foldsTotal
|
|
170
168
|
|
|
171
|
-
|
|
172
|
-
|
|
169
|
+
elif taskDivisions > 1:
|
|
170
|
+
from mapFolding.dataBaskets import ParallelMapFoldingState
|
|
171
|
+
parallelMapFoldingState: ParallelMapFoldingState = ParallelMapFoldingState(mapShape, taskDivisions=taskDivisions)
|
|
172
|
+
|
|
173
|
+
from mapFolding.syntheticModules.countParallel import doTheNeedful
|
|
174
|
+
foldsTotal, listStatesParallel = doTheNeedful(parallelMapFoldingState, concurrencyLimit)
|
|
173
175
|
|
|
174
176
|
else:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
from mapFolding.dataBaskets import MapFoldingState
|
|
178
|
+
mapFoldingState: MapFoldingState = MapFoldingState(mapShape)
|
|
177
179
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
+
from mapFolding.syntheticModules.daoOfMapFolding import doTheNeedful
|
|
181
|
+
mapFoldingState = doTheNeedful(mapFoldingState)
|
|
182
|
+
foldsTotal = mapFoldingState.foldsTotal
|
|
180
183
|
|
|
181
184
|
# Follow memorialization instructions ===========================================
|
|
182
185
|
|
|
@@ -18,12 +18,13 @@ These utilities form a stable internal API that other modules depend on, particu
|
|
|
18
18
|
theDao (core algorithm), and the synthetic module generators that produce optimized implementations.
|
|
19
19
|
"""
|
|
20
20
|
from collections.abc import Sequence
|
|
21
|
-
from mapFolding import
|
|
21
|
+
from mapFolding import Array1DElephino, Array1DFoldsTotal, Array1DLeavesTotal, Array3D, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal, NumPyIntegerType
|
|
22
22
|
from numpy import dtype as numpy_dtype, int64 as numpy_int64, ndarray
|
|
23
23
|
from sys import maxsize as sysMaxsize
|
|
24
24
|
from typing import Any
|
|
25
25
|
from Z0Z_tools import defineConcurrencyLimit, intInnit, oopsieKwargsie
|
|
26
26
|
import numpy
|
|
27
|
+
import dataclasses
|
|
27
28
|
|
|
28
29
|
def getLeavesTotal(mapShape: tuple[int, ...]) -> int:
|
|
29
30
|
"""
|
|
@@ -59,7 +60,6 @@ def getTaskDivisions(computationDivisions: int | str | None, concurrencyLimit: i
|
|
|
59
60
|
"""
|
|
60
61
|
Determines whether to divide the computation into tasks and how many divisions.
|
|
61
62
|
|
|
62
|
-
|
|
63
63
|
Parameters
|
|
64
64
|
----------
|
|
65
65
|
computationDivisions: None
|
|
@@ -208,6 +208,117 @@ def makeDataContainer(shape: int | tuple[int, ...], datatype: type[NumPyIntegerT
|
|
|
208
208
|
"""
|
|
209
209
|
return numpy.zeros(shape, dtype=datatype)
|
|
210
210
|
|
|
211
|
+
|
|
212
|
+
@dataclasses.dataclass
|
|
213
|
+
class ComputationState:
|
|
214
|
+
"""
|
|
215
|
+
Represents the complete state of a map folding computation.
|
|
216
|
+
|
|
217
|
+
This dataclass encapsulates all the information required to compute the number of possible ways to fold a map,
|
|
218
|
+
including the map dimensions, leaf connections, computation progress, and fold counting. It serves as the central
|
|
219
|
+
data structure that flows through the entire computational algorithm.
|
|
220
|
+
|
|
221
|
+
Fields are categorized into:
|
|
222
|
+
1. Input parameters (`mapShape`, `leavesTotal`, etc.).
|
|
223
|
+
2. Core computational structures (`connectionGraph`, etc.).
|
|
224
|
+
3. Tracking variables for the folding algorithm state.
|
|
225
|
+
4. Result accumulation fields (`foldsTotal`, `groupsOfFolds`).
|
|
226
|
+
"""
|
|
227
|
+
# NOTE Python is anti-DRY, again, `DatatypeLeavesTotal` metadata needs to match the type
|
|
228
|
+
mapShape: tuple[DatatypeLeavesTotal, ...] = dataclasses.field(init=True, metadata={'elementConstructor': 'DatatypeLeavesTotal'})
|
|
229
|
+
"""Dimensions of the map to be folded, as a tuple of integers."""
|
|
230
|
+
|
|
231
|
+
leavesTotal: DatatypeLeavesTotal
|
|
232
|
+
"""Total number of leaves (unit squares) in the map, equal to the product of all dimensions."""
|
|
233
|
+
|
|
234
|
+
taskDivisions: DatatypeLeavesTotal
|
|
235
|
+
"""Number of parallel tasks to divide the computation into. Zero means sequential computation."""
|
|
236
|
+
|
|
237
|
+
concurrencyLimit: DatatypeElephino
|
|
238
|
+
"""Maximum number of concurrent processes to use during computation."""
|
|
239
|
+
|
|
240
|
+
connectionGraph: Array3D = dataclasses.field(init=False, metadata={'dtype': Array3D.__args__[1].__args__[0]}) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
|
|
241
|
+
"""3D array encoding the connections between leaves in all dimensions."""
|
|
242
|
+
|
|
243
|
+
dimensionsTotal: DatatypeLeavesTotal = dataclasses.field(init=False)
|
|
244
|
+
"""Total number of dimensions in the map shape."""
|
|
245
|
+
|
|
246
|
+
# I am using `dataclasses.field` metadata and `typeAlias.__args__[1].__args__[0]` to make the code more DRY. https://github.com/hunterhogan/mapFolding/issues/9
|
|
247
|
+
countDimensionsGapped: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
248
|
+
"""Tracks how many dimensions are gapped for each leaf."""
|
|
249
|
+
|
|
250
|
+
dimensionsUnconstrained: DatatypeLeavesTotal = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
251
|
+
"""Number of dimensions that are not constrained in the current folding state."""
|
|
252
|
+
|
|
253
|
+
gapRangeStart: Array1DElephino = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DElephino.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
254
|
+
"""Starting index for the gap range for each leaf."""
|
|
255
|
+
|
|
256
|
+
gapsWhere: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
257
|
+
"""Tracks where gaps occur in the folding pattern."""
|
|
258
|
+
|
|
259
|
+
leafAbove: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
260
|
+
"""For each leaf, stores the index of the leaf above it in the folding pattern."""
|
|
261
|
+
|
|
262
|
+
leafBelow: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
263
|
+
"""For each leaf, stores the index of the leaf below it in the folding pattern."""
|
|
264
|
+
|
|
265
|
+
foldGroups: Array1DFoldsTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DFoldsTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
266
|
+
"""Accumulator for fold groups across parallel tasks."""
|
|
267
|
+
|
|
268
|
+
foldsTotal: DatatypeFoldsTotal = DatatypeFoldsTotal(0)
|
|
269
|
+
"""The final computed total number of distinct folding patterns."""
|
|
270
|
+
|
|
271
|
+
gap1ndex: DatatypeElephino = DatatypeElephino(0)
|
|
272
|
+
"""Current index into gaps array during algorithm execution."""
|
|
273
|
+
|
|
274
|
+
gap1ndexCeiling: DatatypeElephino = DatatypeElephino(0)
|
|
275
|
+
"""Upper limit for gap index during the current algorithm phase."""
|
|
276
|
+
|
|
277
|
+
groupsOfFolds: DatatypeFoldsTotal = dataclasses.field(default=DatatypeFoldsTotal(0), metadata={'theCountingIdentifier': True})
|
|
278
|
+
"""Accumulator for the number of fold groups found during computation."""
|
|
279
|
+
|
|
280
|
+
indexDimension: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
281
|
+
"""Current dimension being processed during algorithm execution."""
|
|
282
|
+
|
|
283
|
+
indexLeaf: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
284
|
+
"""Current leaf index during iteration."""
|
|
285
|
+
|
|
286
|
+
indexMiniGap: DatatypeElephino = DatatypeElephino(0)
|
|
287
|
+
"""Index used when filtering common gaps."""
|
|
288
|
+
|
|
289
|
+
leaf1ndex: DatatypeLeavesTotal = DatatypeLeavesTotal(1)
|
|
290
|
+
"""Active leaf being processed in the folding algorithm. Starts at 1, not 0."""
|
|
291
|
+
|
|
292
|
+
leafConnectee: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
293
|
+
"""Leaf that is being connected to the active leaf."""
|
|
294
|
+
|
|
295
|
+
taskIndex: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
296
|
+
"""Index of the current parallel task when using task divisions."""
|
|
297
|
+
|
|
298
|
+
def __post_init__(self) -> None:
|
|
299
|
+
from mapFolding.beDRY import getConnectionGraph, makeDataContainer
|
|
300
|
+
self.dimensionsTotal = DatatypeLeavesTotal(len(self.mapShape))
|
|
301
|
+
leavesTotalAsInt = int(self.leavesTotal)
|
|
302
|
+
self.connectionGraph = getConnectionGraph(self.mapShape, leavesTotalAsInt, self.__dataclass_fields__['connectionGraph'].metadata['dtype'])
|
|
303
|
+
|
|
304
|
+
if self.dimensionsUnconstrained is None: self.dimensionsUnconstrained = DatatypeLeavesTotal(int(self.dimensionsTotal)) # pyright: ignore[reportUnnecessaryComparison]
|
|
305
|
+
|
|
306
|
+
if self.foldGroups is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
307
|
+
self.foldGroups = makeDataContainer(max(2, int(self.taskDivisions) + 1), self.__dataclass_fields__['foldGroups'].metadata['dtype'])
|
|
308
|
+
self.foldGroups[-1] = self.leavesTotal
|
|
309
|
+
|
|
310
|
+
# Dataclasses, Default factories, and arguments in `ComputationState` https://github.com/hunterhogan/mapFolding/issues/12
|
|
311
|
+
if self.gapsWhere is None: self.gapsWhere = makeDataContainer(leavesTotalAsInt * leavesTotalAsInt + 1, self.__dataclass_fields__['gapsWhere'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
312
|
+
|
|
313
|
+
if self.countDimensionsGapped is None: self.countDimensionsGapped = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['countDimensionsGapped'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
314
|
+
if self.gapRangeStart is None: self.gapRangeStart = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['gapRangeStart'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
315
|
+
if self.leafAbove is None: self.leafAbove = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafAbove'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
316
|
+
if self.leafBelow is None: self.leafBelow = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafBelow'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
317
|
+
|
|
318
|
+
# Automatic, or not, calculation in dataclass `ComputationState` https://github.com/hunterhogan/mapFolding/issues/14
|
|
319
|
+
def getFoldsTotal(self) -> None:
|
|
320
|
+
self.foldsTotal = DatatypeFoldsTotal(self.foldGroups[0:-1].sum() * self.leavesTotal)
|
|
321
|
+
|
|
211
322
|
def outfitCountFolds(mapShape: tuple[int, ...], computationDivisions: int | str | None = None, concurrencyLimit: int = 1) -> ComputationState:
|
|
212
323
|
"""
|
|
213
324
|
Initialize a `ComputationState` with validated parameters for map folding calculation.
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
from mapFolding
|
|
2
|
-
|
|
1
|
+
from mapFolding import (
|
|
2
|
+
Array1DElephino,
|
|
3
|
+
Array1DLeavesTotal,
|
|
4
|
+
Array3D,
|
|
5
|
+
DatatypeElephino,
|
|
6
|
+
DatatypeFoldsTotal,
|
|
7
|
+
DatatypeLeavesTotal,
|
|
8
|
+
getConnectionGraph,
|
|
9
|
+
getLeavesTotal,
|
|
10
|
+
makeDataContainer,
|
|
11
|
+
)
|
|
3
12
|
import dataclasses
|
|
4
13
|
|
|
5
14
|
@dataclasses.dataclass
|
|
@@ -48,6 +57,19 @@ class MapFoldingState:
|
|
|
48
57
|
if self.leafAbove is None: self.leafAbove = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafAbove'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
49
58
|
if self.leafBelow is None: self.leafBelow = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafBelow'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
50
59
|
|
|
60
|
+
@dataclasses.dataclass
|
|
61
|
+
class ParallelMapFoldingState(MapFoldingState):
|
|
62
|
+
taskDivisions: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
63
|
+
"""Number of tasks into which to divide the computation. If the value is greater than `leavesTotal`, the computation will be wrong. Default is `leavesTotal`."""
|
|
64
|
+
|
|
65
|
+
taskIndex: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
66
|
+
"""Index of the current task when using task divisions."""
|
|
67
|
+
|
|
68
|
+
def __post_init__(self) -> None:
|
|
69
|
+
super().__post_init__()
|
|
70
|
+
if self.taskDivisions == 0:
|
|
71
|
+
self.taskDivisions = DatatypeLeavesTotal(int(self.leavesTotal))
|
|
72
|
+
|
|
51
73
|
@dataclasses.dataclass
|
|
52
74
|
class LeafSequenceState(MapFoldingState):
|
|
53
75
|
leafSequence: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
@@ -21,7 +21,7 @@ The functions here adhere to a consistent approach to path handling:
|
|
|
21
21
|
- Progressive fallback strategies for saving critical computation results.
|
|
22
22
|
- Preemptive filesystem validation to detect issues before computation begins.
|
|
23
23
|
"""
|
|
24
|
-
from mapFolding import
|
|
24
|
+
from mapFolding import packageSettings
|
|
25
25
|
from os import PathLike
|
|
26
26
|
from pathlib import Path, PurePath
|
|
27
27
|
from sys import modules as sysModules
|
|
@@ -101,9 +101,9 @@ def getPathRootJobDEFAULT() -> Path:
|
|
|
101
101
|
- For Google Colab, uses a specific path in Google Drive.
|
|
102
102
|
- Creates the directory if it doesn't exist.
|
|
103
103
|
"""
|
|
104
|
-
pathJobDEFAULT = Path(platformdirs.user_data_dir(appname=
|
|
104
|
+
pathJobDEFAULT = Path(platformdirs.user_data_dir(appname=packageSettings.packageName, appauthor=False, ensure_exists=True))
|
|
105
105
|
if 'google.colab' in sysModules:
|
|
106
|
-
pathJobDEFAULT = Path("/content/drive/MyDrive") /
|
|
106
|
+
pathJobDEFAULT = Path("/content/drive/MyDrive") / packageSettings.packageName
|
|
107
107
|
pathJobDEFAULT.mkdir(parents=True, exist_ok=True)
|
|
108
108
|
return pathJobDEFAULT
|
|
109
109
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from importlib import import_module as importlib_import_module
|
|
3
|
+
from mapFolding import ComputationState, PackageSettings
|
|
4
|
+
from types import ModuleType
|
|
5
|
+
import dataclasses
|
|
6
|
+
|
|
7
|
+
@dataclasses.dataclass
|
|
8
|
+
class PackageInformation(PackageSettings):
|
|
9
|
+
"""
|
|
10
|
+
In _all_ of the root directory and "syntheticModules", the _only_ `PackageInformation` that are used are:
|
|
11
|
+
The.concurrencyPackage
|
|
12
|
+
The.dispatcher
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
logicalPathModuleDispatcher: str | None = None
|
|
16
|
+
"""Logical import path to the module containing the dispatcher function."""
|
|
17
|
+
|
|
18
|
+
callableDispatcher: str | None = None
|
|
19
|
+
"""Name of the function within the dispatcher module that will be called."""
|
|
20
|
+
|
|
21
|
+
concurrencyPackage: str | None = None
|
|
22
|
+
"""Package to use for concurrent execution (e.g., 'multiprocessing', 'numba')."""
|
|
23
|
+
|
|
24
|
+
# "Evaluate When Packaging" and "Evaluate When Installing" https://github.com/hunterhogan/mapFolding/issues/18
|
|
25
|
+
dataclassIdentifier: str = dataclasses.field(default='ComputationState', metadata={'evaluateWhen': 'packaging'})
|
|
26
|
+
"""Name of the dataclass used to track computation state."""
|
|
27
|
+
|
|
28
|
+
dataclassInstance: str = dataclasses.field(default='state', metadata={'evaluateWhen': 'packaging'})
|
|
29
|
+
"""Default variable name for instances of the computation state dataclass."""
|
|
30
|
+
|
|
31
|
+
dataclassInstanceTaskDistributionSuffix: str = dataclasses.field(default='Parallel', metadata={'evaluateWhen': 'packaging'})
|
|
32
|
+
"""Suffix added to dataclassInstance for parallel task distribution."""
|
|
33
|
+
|
|
34
|
+
dataclassModule: str = dataclasses.field(default='beDRY', metadata={'evaluateWhen': 'packaging'})
|
|
35
|
+
"""Module containing the computation state dataclass definition."""
|
|
36
|
+
|
|
37
|
+
datatypePackage: str = dataclasses.field(default='numpy', metadata={'evaluateWhen': 'packaging'})
|
|
38
|
+
"""Package providing the numeric data types used in computation."""
|
|
39
|
+
|
|
40
|
+
sourceAlgorithm: str = dataclasses.field(default='theDao', metadata={'evaluateWhen': 'packaging'})
|
|
41
|
+
"""Module containing the reference implementation of the algorithm."""
|
|
42
|
+
|
|
43
|
+
sourceCallableDispatcher: str = dataclasses.field(default='doTheNeedful', metadata={'evaluateWhen': 'packaging'})
|
|
44
|
+
"""Name of the function that dispatches computation in the source algorithm."""
|
|
45
|
+
|
|
46
|
+
sourceCallableInitialize: str = dataclasses.field(default='countInitialize', metadata={'evaluateWhen': 'packaging'})
|
|
47
|
+
"""Name of the function that initializes computation in the source algorithm."""
|
|
48
|
+
|
|
49
|
+
sourceCallableParallel: str = dataclasses.field(default='countParallel', metadata={'evaluateWhen': 'packaging'})
|
|
50
|
+
"""Name of the function that performs parallel computation in the source algorithm."""
|
|
51
|
+
|
|
52
|
+
sourceCallableSequential: str = dataclasses.field(default='countSequential', metadata={'evaluateWhen': 'packaging'})
|
|
53
|
+
"""Name of the function that performs sequential computation in the source algorithm."""
|
|
54
|
+
|
|
55
|
+
sourceConcurrencyManagerIdentifier: str = dataclasses.field(default='submit', metadata={'evaluateWhen': 'packaging'})
|
|
56
|
+
"""Method name used to submit tasks to the concurrency manager."""
|
|
57
|
+
|
|
58
|
+
sourceConcurrencyManagerNamespace: str = dataclasses.field(default='concurrencyManager', metadata={'evaluateWhen': 'packaging'})
|
|
59
|
+
"""Variable name used for the concurrency manager instance."""
|
|
60
|
+
|
|
61
|
+
sourceConcurrencyPackage: str = dataclasses.field(default='multiprocessing', metadata={'evaluateWhen': 'packaging'})
|
|
62
|
+
"""Default package used for concurrency in the source algorithm."""
|
|
63
|
+
|
|
64
|
+
dataclassInstanceTaskDistribution: str = dataclasses.field(default=None, metadata={'evaluateWhen': 'packaging'}) # pyright: ignore[reportAssignmentType]
|
|
65
|
+
"""Variable name for the parallel distribution instance of the computation state."""
|
|
66
|
+
|
|
67
|
+
logicalPathModuleDataclass: str = dataclasses.field(default=None, metadata={'evaluateWhen': 'packaging'}) # pyright: ignore[reportAssignmentType]
|
|
68
|
+
"""Fully qualified import path to the module containing the computation state dataclass."""
|
|
69
|
+
|
|
70
|
+
logicalPathModuleSourceAlgorithm: str = dataclasses.field(default=None, metadata={'evaluateWhen': 'packaging'}) # pyright: ignore[reportAssignmentType]
|
|
71
|
+
"""Fully qualified import path to the module containing the source algorithm."""
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def dispatcher(self) -> Callable[['ComputationState'], 'ComputationState']:
|
|
75
|
+
""" _The_ callable that connects `countFolds` to the logic that does the work."""
|
|
76
|
+
logicalPath: str = self.logicalPathModuleDispatcher or self.logicalPathModuleSourceAlgorithm
|
|
77
|
+
identifier: str = self.callableDispatcher or self.sourceCallableDispatcher
|
|
78
|
+
moduleImported: ModuleType = importlib_import_module(logicalPath)
|
|
79
|
+
return getattr(moduleImported, identifier)
|
|
80
|
+
|
|
81
|
+
def __post_init__(self) -> None:
|
|
82
|
+
if self.dataclassInstanceTaskDistribution is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
83
|
+
self.dataclassInstanceTaskDistribution = self.dataclassInstance + self.dataclassInstanceTaskDistributionSuffix
|
|
84
|
+
|
|
85
|
+
if self.logicalPathModuleDataclass is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
86
|
+
self.logicalPathModuleDataclass = '.'.join([self.packageName, self.dataclassModule])
|
|
87
|
+
if self.logicalPathModuleSourceAlgorithm is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
88
|
+
self.logicalPathModuleSourceAlgorithm = '.'.join([self.packageName, self.sourceAlgorithm])
|
|
89
|
+
|
|
90
|
+
class raiseIfNoneGitHubIssueNumber3(Exception): pass
|
|
91
|
+
|
|
92
|
+
logicalPathModuleDispatcherHARDCODED: str = 'mapFolding.syntheticModules.numbaCount'
|
|
93
|
+
callableDispatcherHARDCODED: str = 'doTheNeedful'
|
|
94
|
+
concurrencyPackageHARDCODED = 'multiprocessing'
|
|
95
|
+
|
|
96
|
+
The = PackageInformation(logicalPathModuleDispatcher=logicalPathModuleDispatcherHARDCODED, callableDispatcher=callableDispatcherHARDCODED, concurrencyPackage=concurrencyPackageHARDCODED)
|
|
@@ -20,9 +20,10 @@ mathematical definition in OEIS and the computational implementation in the pack
|
|
|
20
20
|
from collections.abc import Callable
|
|
21
21
|
from datetime import datetime, timedelta
|
|
22
22
|
from functools import cache
|
|
23
|
-
from mapFolding import countFolds,
|
|
23
|
+
from mapFolding import countFolds, packageSettings, TypedDict
|
|
24
24
|
from pathlib import Path
|
|
25
25
|
from typing import Any, Final
|
|
26
|
+
from Z0Z_tools import writeStringToHere
|
|
26
27
|
import argparse
|
|
27
28
|
import random
|
|
28
29
|
import sys
|
|
@@ -33,7 +34,7 @@ import warnings
|
|
|
33
34
|
|
|
34
35
|
cacheDays = 30
|
|
35
36
|
|
|
36
|
-
pathCache: Path =
|
|
37
|
+
pathCache: Path = packageSettings.pathPackage / ".cache"
|
|
37
38
|
|
|
38
39
|
class SettingsOEIS(TypedDict):
|
|
39
40
|
description: str
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
from mapFolding import ComputationState, getPathFilenameFoldsTotal, getPathRootJobDEFAULT, MapFoldingState
|
|
2
|
+
from mapFolding import DatatypeElephino as TheDatatypeElephino, DatatypeFoldsTotal as TheDatatypeFoldsTotal, DatatypeLeavesTotal as TheDatatypeLeavesTotal
|
|
1
3
|
from mapFolding.someAssemblyRequired import ShatteredDataclass, ast_Identifier, parseLogicalPath2astModule, parsePathFilename2astModule, str_nameDOTname
|
|
2
|
-
from mapFolding.someAssemblyRequired.
|
|
4
|
+
from mapFolding.someAssemblyRequired.toolkitNumba import theNumbaFlow
|
|
3
5
|
from mapFolding.someAssemblyRequired.transformationTools import shatter_dataclassesDOTdataclass
|
|
4
|
-
from mapFolding.theSSOT import ComputationState, DatatypeElephino as TheDatatypeElephino, DatatypeFoldsTotal as TheDatatypeFoldsTotal, DatatypeLeavesTotal as TheDatatypeLeavesTotal
|
|
5
|
-
from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal, getPathRootJobDEFAULT
|
|
6
|
-
from mapFolding.dataBaskets import MapFoldingState
|
|
7
6
|
from pathlib import Path, PurePosixPath
|
|
8
7
|
from typing import TypeAlias
|
|
9
8
|
import dataclasses
|