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.
Files changed (65) hide show
  1. {mapfolding-0.11.1 → mapfolding-0.11.2}/PKG-INFO +16 -8
  2. {mapfolding-0.11.1 → mapfolding-0.11.2}/README.md +15 -7
  3. mapfolding-0.11.2/mapFolding/__init__.py +75 -0
  4. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/basecamp.py +13 -10
  5. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/beDRY.py +113 -2
  6. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/dataBaskets.py +24 -2
  7. mapfolding-0.11.1/mapFolding/toolboxFilesystem.py → mapfolding-0.11.2/mapFolding/filesystemToolkit.py +3 -3
  8. mapfolding-0.11.2/mapFolding/infoBooth.py +96 -0
  9. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/oeis.py +3 -2
  10. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/RecipeJob.py +3 -4
  11. mapfolding-0.11.2/mapFolding/someAssemblyRequired/Z0Z_makeSomeModules.py +490 -0
  12. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/__init__.py +3 -3
  13. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/_toolIfThis.py +5 -5
  14. mapfolding-0.11.1/mapFolding/someAssemblyRequired/_toolboxContainers.py → mapfolding-0.11.2/mapFolding/someAssemblyRequired/_toolkitContainers.py +6 -7
  15. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +8 -7
  16. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +3 -2
  17. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/transformationTools.py +11 -10
  18. mapfolding-0.11.2/mapFolding/syntheticModules/countParallel.py +98 -0
  19. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/dataPacking.py +1 -1
  20. mapfolding-0.11.2/mapFolding/syntheticModules/numbaCount.py +202 -0
  21. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/theDao.py +1 -1
  22. mapfolding-0.11.2/mapFolding/theSSOT.py +29 -0
  23. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/PKG-INFO +16 -8
  24. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/SOURCES.txt +5 -3
  25. {mapfolding-0.11.1 → mapfolding-0.11.2}/pyproject.toml +2 -2
  26. {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/conftest.py +7 -9
  27. {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_computations.py +1 -1
  28. {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_filesystem.py +1 -2
  29. {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_other.py +1 -1
  30. {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/test_tasks.py +1 -3
  31. mapfolding-0.11.1/mapFolding/__init__.py +0 -115
  32. mapfolding-0.11.1/mapFolding/someAssemblyRequired/Z0Z_makeSomeModules.py +0 -325
  33. mapfolding-0.11.1/mapFolding/syntheticModules/numbaCount.py +0 -201
  34. mapfolding-0.11.1/mapFolding/theSSOT.py +0 -268
  35. {mapfolding-0.11.1 → mapfolding-0.11.2}/LICENSE +0 -0
  36. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/daoOfMapFolding.py +0 -0
  37. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/datatypes.py +0 -0
  38. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/py.typed +0 -0
  39. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/__init__.py +0 -0
  40. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/flattened.py +0 -0
  41. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/hunterNumba.py +0 -0
  42. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/irvineJavaPort.py +0 -0
  43. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/jaxCount.py +0 -0
  44. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/jobsCompleted/[2x19]/p2x19.py +0 -0
  45. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/jobsCompleted/__init__.py +0 -0
  46. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/jobsCompleted/p2x19/p2x19.py +0 -0
  47. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/lunnonNumpy.py +0 -0
  48. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/lunnonWhile.py +0 -0
  49. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/rotatedEntryPoint.py +0 -0
  50. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/reference/total_countPlus1vsPlusN.py +0 -0
  51. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/someAssemblyRequired/getLLVMforNoReason.py +0 -0
  52. /mapfolding-0.11.1/mapFolding/someAssemblyRequired/toolboxNumba.py → /mapfolding-0.11.2/mapFolding/someAssemblyRequired/toolkitNumba.py +0 -0
  53. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/__init__.py +0 -0
  54. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/daoOfMapFolding.py +0 -0
  55. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/initializeCount.py +0 -0
  56. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/theorem2.py +0 -0
  57. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/theorem2Numba.py +0 -0
  58. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding/syntheticModules/theorem2Trimmed.py +0 -0
  59. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/dependency_links.txt +0 -0
  60. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/entry_points.txt +0 -0
  61. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/requires.txt +0 -0
  62. {mapfolding-0.11.1 → mapfolding-0.11.2}/mapFolding.egg-info/top_level.txt +0 -0
  63. {mapfolding-0.11.1 → mapfolding-0.11.2}/setup.cfg +0 -0
  64. {mapfolding-0.11.1 → mapfolding-0.11.2}/tests/__init__.py +0 -0
  65. {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.1
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) # Returns 186,086,600
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
+ [![Static Badge](https://img.shields.io/badge/2011_August-Homeless_since-blue?style=flat)](https://HunterThinks.com/support)
178
+ [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC3Gx7kz61009NbhpRtPP7tw)](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
  [![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/)
@@ -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) # Returns 186,086,600
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
+ [![Static Badge](https://img.shields.io/badge/2011_August-Homeless_since-blue?style=flat)](https://HunterThinks.com/support)
122
+ [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC3Gx7kz61009NbhpRtPP7tw)](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
  [![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,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 doTheNeedful
167
- mapFoldingState = doTheNeedful(mapFoldingState)
164
+ from mapFolding.syntheticModules.dataPacking import sequential
165
+ mapFoldingState = sequential(mapFoldingState)
168
166
 
169
167
  foldsTotal = mapFoldingState.foldsTotal
170
168
 
171
- # NOTE treat this as a default?
172
- # flow based on `The` and `ComputationState` ====================================
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
- computationStateInitialized: ComputationState = outfitCountFolds(mapShape, computationDivisions, concurrencyLimit)
176
- computationStateComplete: ComputationState = The.dispatcher(computationStateInitialized)
177
+ from mapFolding.dataBaskets import MapFoldingState
178
+ mapFoldingState: MapFoldingState = MapFoldingState(mapShape)
177
179
 
178
- computationStateComplete.getFoldsTotal()
179
- foldsTotal = computationStateComplete.foldsTotal
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 ComputationState, NumPyIntegerType
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.beDRY import getConnectionGraph, getLeavesTotal, makeDataContainer
2
- from mapFolding.datatypes import Array3D, Array1DElephino, Array1DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal
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 The
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=The.packageName, appauthor=False, ensure_exists=True))
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") / The.packageName
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, The, TypedDict, writeStringToHere
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 = The.pathPackage / ".cache"
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.toolboxNumba import theNumbaFlow
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