mapFolding 0.16.1__py3-none-any.whl → 0.16.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- easyRun/A000682.py +1 -1
- easyRun/A005316.py +2 -3
- easyRun/NOTcountingFolds.py +6 -5
- easyRun/countFolds.py +1 -1
- easyRun/generateAllModules.py +14 -0
- easyRun/meanders.py +16 -18
- mapFolding/__init__.py +1 -0
- mapFolding/_theSSOT.py +3 -2
- mapFolding/_theTypes.py +3 -0
- mapFolding/algorithms/A086345.py +75 -0
- mapFolding/algorithms/matrixMeanders.py +15 -28
- mapFolding/algorithms/matrixMeandersBeDry.py +34 -116
- mapFolding/algorithms/matrixMeandersNumPy.py +117 -70
- mapFolding/algorithms/matrixMeandersPandas.py +113 -130
- mapFolding/algorithms/oeisIDbyFormula.py +25 -14
- mapFolding/algorithms/symmetricFolds.py +36 -0
- mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +26 -12
- mapFolding/basecamp.py +152 -323
- mapFolding/dataBaskets.py +136 -34
- mapFolding/filesystemToolkit.py +4 -32
- mapFolding/oeis.py +5 -12
- mapFolding/reference/A000682facts.py +785 -1264
- mapFolding/reference/A005316facts.py +958 -923
- mapFolding/reference/A086345Wu.py +25 -0
- mapFolding/reference/matrixMeandersAnalysis/signatures.py +2033 -0
- mapFolding/someAssemblyRequired/A007822/A007822rawMaterials.py +9 -44
- mapFolding/someAssemblyRequired/A007822/_asynchronousAnnex.py +51 -0
- mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +39 -136
- mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +44 -45
- mapFolding/someAssemblyRequired/RecipeJob.py +78 -18
- mapFolding/someAssemblyRequired/__init__.py +3 -8
- mapFolding/someAssemblyRequired/_toolkitContainers.py +32 -3
- mapFolding/someAssemblyRequired/infoBooth.py +40 -23
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +75 -154
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +56 -88
- mapFolding/someAssemblyRequired/makingModules_count.py +91 -85
- mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +7 -65
- mapFolding/someAssemblyRequired/{mapFolding → mapFoldingModules}/makeMapFoldingModules.py +25 -31
- mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +14 -13
- mapFolding/someAssemblyRequired/toolkitMakeModules.py +10 -10
- mapFolding/someAssemblyRequired/toolkitNumba.py +1 -1
- mapFolding/someAssemblyRequired/transformationTools.py +17 -19
- mapFolding/syntheticModules/A007822/algorithm.py +46 -50
- mapFolding/syntheticModules/A007822/asynchronous.py +93 -34
- mapFolding/syntheticModules/A007822/initializeState.py +15 -21
- mapFolding/syntheticModules/A007822/theorem2.py +21 -21
- mapFolding/syntheticModules/A007822/theorem2Numba.py +42 -23
- mapFolding/syntheticModules/A007822/theorem2Trimmed.py +21 -21
- mapFolding/syntheticModules/countParallelNumba.py +3 -7
- mapFolding/syntheticModules/daoOfMapFoldingNumba.py +3 -6
- mapFolding/syntheticModules/meanders/bigInt.py +15 -25
- mapFolding/syntheticModules/theorem2.py +6 -0
- mapFolding/syntheticModules/theorem2Numba.py +26 -2
- mapFolding/syntheticModules/theorem2Trimmed.py +6 -0
- mapFolding/tests/test_computations.py +1 -1
- mapFolding/zCuzDocStoopid/makeDocstrings.py +2 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/METADATA +4 -1
- mapfolding-0.16.4.dist-info/RECORD +106 -0
- mapFolding/_dataPacking.py +0 -68
- mapFolding/reference/meandersDumpingGround/A005316intOptimized.py +0 -122
- mapFolding/reference/meandersDumpingGround/A005316optimized128bit.py +0 -79
- mapFolding/reference/meandersDumpingGround/matrixMeandersBaseline.py +0 -65
- mapFolding/reference/meandersDumpingGround/matrixMeandersBaselineAnnex.py +0 -84
- mapFolding/reference/meandersDumpingGround/matrixMeandersSimpleQueue.py +0 -90
- mapFolding/syntheticModules/A007822/algorithmNumba.py +0 -94
- mapFolding/syntheticModules/A007822/asynchronousAnnex.py +0 -66
- mapFolding/syntheticModules/A007822/asynchronousAnnexNumba.py +0 -85
- mapFolding/syntheticModules/A007822/asynchronousNumba.py +0 -52
- mapFolding/syntheticModules/A007822/asynchronousTheorem2.py +0 -53
- mapFolding/syntheticModules/A007822/asynchronousTrimmed.py +0 -47
- mapFolding/syntheticModules/dataPacking.py +0 -28
- mapFolding/syntheticModules/dataPackingA007822.py +0 -92
- mapfolding-0.16.1.dist-info/RECORD +0 -114
- /mapFolding/someAssemblyRequired/{mapFolding → mapFoldingModules}/__init__.py +0 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/WHEEL +0 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/top_level.txt +0 -0
mapFolding/dataBaskets.py
CHANGED
|
@@ -21,10 +21,10 @@ integrity throughout the recursive analysis while providing the structured data
|
|
|
21
21
|
access patterns that enable efficient result persistence and retrieval.
|
|
22
22
|
"""
|
|
23
23
|
from mapFolding import (
|
|
24
|
-
Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal,
|
|
25
|
-
getConnectionGraph, getLeavesTotal, makeDataContainer
|
|
24
|
+
Array1DElephino, Array1DLeavesTotal, Array2DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal,
|
|
25
|
+
DatatypeLeavesTotal, getConnectionGraph, getLeavesTotal, makeDataContainer)
|
|
26
26
|
from numpy.typing import NDArray
|
|
27
|
-
from typing import
|
|
27
|
+
from typing import TypeAlias
|
|
28
28
|
import dataclasses
|
|
29
29
|
import numpy
|
|
30
30
|
|
|
@@ -111,8 +111,6 @@ class MapFoldingState:
|
|
|
111
111
|
"""Array tracking the leaves above to the current leaf, `leaf1ndex`, during computation."""
|
|
112
112
|
leafBelow: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
113
113
|
"""Array tracking the leaves below to the current leaf, `leaf1ndex`, during computation."""
|
|
114
|
-
leafComparison: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
115
|
-
"""Array for finding symmetric folds."""
|
|
116
114
|
|
|
117
115
|
connectionGraph: Array3DLeavesTotal = dataclasses.field(init=False, metadata={'dtype': Array3DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
|
|
118
116
|
"""Unchanging array representing connections between all leaves."""
|
|
@@ -126,7 +124,7 @@ class MapFoldingState:
|
|
|
126
124
|
|
|
127
125
|
Returns
|
|
128
126
|
-------
|
|
129
|
-
|
|
127
|
+
foldsTotal : DatatypeFoldsTotal
|
|
130
128
|
The complete count of distinct folding patterns achievable with the current map configuration.
|
|
131
129
|
|
|
132
130
|
"""
|
|
@@ -154,6 +152,126 @@ class MapFoldingState:
|
|
|
154
152
|
if self.gapRangeStart is None: self.gapRangeStart = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['gapRangeStart'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
155
153
|
if self.leafAbove is None: self.leafAbove = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafAbove'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
156
154
|
if self.leafBelow is None: self.leafBelow = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafBelow'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
155
|
+
|
|
156
|
+
@dataclasses.dataclass(slots=True)
|
|
157
|
+
class SymmetricFoldsState:
|
|
158
|
+
"""Core computational state for symmetric map folding algorithms.
|
|
159
|
+
|
|
160
|
+
Attributes
|
|
161
|
+
----------
|
|
162
|
+
mapShape : tuple[DatatypeLeavesTotal, ...]
|
|
163
|
+
Dimensions of the map being analyzed for folding patterns.
|
|
164
|
+
groupsOfFolds : DatatypeFoldsTotal = DatatypeFoldsTotal(0)
|
|
165
|
+
Current count of distinct folding pattern groups: each group has `leavesTotal`-many foldings.
|
|
166
|
+
gap1ndex : DatatypeElephino = DatatypeElephino(0)
|
|
167
|
+
The current 1-indexed position of the 'gap' during computation: 1-indexed as opposed to 0-indexed.
|
|
168
|
+
gap1ndexCeiling : DatatypeElephino = DatatypeElephino(0)
|
|
169
|
+
The upper bound of `gap1ndex`.
|
|
170
|
+
indexDimension : DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
171
|
+
The current 0-indexed position of the dimension during computation.
|
|
172
|
+
indexLeaf : DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
173
|
+
The current 0-indexed position of a leaf in a loop during computation: not to be confused with `leaf1ndex`.
|
|
174
|
+
indexMiniGap : DatatypeElephino = DatatypeElephino(0)
|
|
175
|
+
The current 0-indexed position of a 'gap' in a loop during computation.
|
|
176
|
+
leaf1ndex : DatatypeLeavesTotal = DatatypeLeavesTotal(1)
|
|
177
|
+
The current 1-indexed position of the leaf during computation: 1-indexed as opposed to 0-indexed.
|
|
178
|
+
leafConnectee : DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
179
|
+
Target leaf for connection operations.
|
|
180
|
+
dimensionsUnconstrained : DatatypeLeavesTotal = None
|
|
181
|
+
Count of dimensions not subject to folding constraints.
|
|
182
|
+
countDimensionsGapped : Array1DLeavesTotal = None
|
|
183
|
+
Array tracking computed number of dimensions with gaps.
|
|
184
|
+
gapRangeStart : Array1DElephino = None
|
|
185
|
+
Array tracking computed starting positions of gap ranges.
|
|
186
|
+
gapsWhere : Array1DLeavesTotal = None
|
|
187
|
+
Array indicating locations of gaps in the folding pattern.
|
|
188
|
+
leafAbove : Array1DLeavesTotal = None
|
|
189
|
+
Array tracking the leaves above to the current leaf, `leaf1ndex`, during computation.
|
|
190
|
+
leafBelow : Array1DLeavesTotal = None
|
|
191
|
+
Array tracking the leaves below to the current leaf, `leaf1ndex`, during computation.
|
|
192
|
+
leafComparison : Array1DLeavesTotal = None
|
|
193
|
+
Array for finding symmetric folds.
|
|
194
|
+
connectionGraph : Array3DLeavesTotal
|
|
195
|
+
Unchanging array representing connections between all leaves.
|
|
196
|
+
dimensionsTotal : DatatypeLeavesTotal
|
|
197
|
+
Unchanging total number of dimensions in the map.
|
|
198
|
+
leavesTotal : DatatypeLeavesTotal
|
|
199
|
+
Unchanging total number of leaves in the map.
|
|
200
|
+
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
mapShape: tuple[DatatypeLeavesTotal, ...] = dataclasses.field(init=True, metadata={'elementConstructor': 'DatatypeLeavesTotal'})
|
|
204
|
+
"""Dimensions of the map being analyzed for folding patterns."""
|
|
205
|
+
|
|
206
|
+
groupsOfFolds: DatatypeFoldsTotal = dataclasses.field(default=DatatypeFoldsTotal(0), metadata={'theCountingIdentifier': True})
|
|
207
|
+
"""Current count of symmetric folds."""
|
|
208
|
+
|
|
209
|
+
gap1ndex: DatatypeElephino = DatatypeElephino(0) # noqa: RUF009
|
|
210
|
+
"""The current 1-indexed position of the 'gap' during computation: 1-indexed as opposed to 0-indexed."""
|
|
211
|
+
gap1ndexCeiling: DatatypeElephino = DatatypeElephino(0) # noqa: RUF009
|
|
212
|
+
"""The upper bound of `gap1ndex`."""
|
|
213
|
+
indexDimension: DatatypeLeavesTotal = DatatypeLeavesTotal(0) # noqa: RUF009
|
|
214
|
+
"""The current 0-indexed position of the dimension during computation."""
|
|
215
|
+
indexLeaf: DatatypeLeavesTotal = DatatypeLeavesTotal(0) # noqa: RUF009
|
|
216
|
+
"""The current 0-indexed position of a leaf in a loop during computation: not to be confused with `leaf1ndex`."""
|
|
217
|
+
indexMiniGap: DatatypeElephino = DatatypeElephino(0) # noqa: RUF009
|
|
218
|
+
"""The current 0-indexed position of a 'gap' in a loop during computation."""
|
|
219
|
+
leaf1ndex: DatatypeLeavesTotal = DatatypeLeavesTotal(1) # noqa: RUF009
|
|
220
|
+
"""The current 1-indexed position of the leaf during computation: 1-indexed as opposed to 0-indexed."""
|
|
221
|
+
leafConnectee: DatatypeLeavesTotal = DatatypeLeavesTotal(0) # noqa: RUF009
|
|
222
|
+
"""Target leaf for connection operations."""
|
|
223
|
+
|
|
224
|
+
dimensionsUnconstrained: DatatypeLeavesTotal = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
225
|
+
"""Count of dimensions not subject to folding constraints."""
|
|
226
|
+
|
|
227
|
+
countDimensionsGapped: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
228
|
+
"""Array tracking computed number of dimensions with gaps."""
|
|
229
|
+
gapRangeStart: Array1DElephino = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DElephino.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
230
|
+
"""Array tracking computed starting positions of gap ranges."""
|
|
231
|
+
gapsWhere: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
232
|
+
"""Array indicating locations of gaps in the folding pattern."""
|
|
233
|
+
leafAbove: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
234
|
+
"""Array tracking the leaves above to the current leaf, `leaf1ndex`, during computation."""
|
|
235
|
+
leafBelow: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
236
|
+
"""Array tracking the leaves below to the current leaf, `leaf1ndex`, during computation."""
|
|
237
|
+
leafComparison: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
238
|
+
"""Array for finding symmetric folds."""
|
|
239
|
+
|
|
240
|
+
arrayGroupOfFolds: Array2DLeavesTotal = dataclasses.field(init=False, metadata={'dtype': Array2DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
|
|
241
|
+
connectionGraph: Array3DLeavesTotal = dataclasses.field(init=False, metadata={'dtype': Array3DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
|
|
242
|
+
"""Unchanging array representing connections between all leaves."""
|
|
243
|
+
dimensionsTotal: DatatypeLeavesTotal = dataclasses.field(init=False)
|
|
244
|
+
"""Unchanging total number of dimensions in the map."""
|
|
245
|
+
indicesArrayGroupOfFolds: Array2DLeavesTotal = dataclasses.field(init=False, metadata={'dtype': Array2DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
|
|
246
|
+
leavesTotal: DatatypeLeavesTotal = dataclasses.field(init=False)
|
|
247
|
+
"""Unchanging total number of leaves in the map."""
|
|
248
|
+
|
|
249
|
+
def __post_init__(self) -> None:
|
|
250
|
+
"""Ensure all fields have a value.
|
|
251
|
+
|
|
252
|
+
Notes
|
|
253
|
+
-----
|
|
254
|
+
Arrays that are not explicitly provided (None) are automatically allocated with appropriate sizes based on the map
|
|
255
|
+
dimensions. `dimensionsTotal`, `leavesTotal`, and `connectionGraph` cannot be set: they are calculated.
|
|
256
|
+
|
|
257
|
+
"""
|
|
258
|
+
self.dimensionsTotal = DatatypeLeavesTotal(len(self.mapShape))
|
|
259
|
+
self.leavesTotal = DatatypeLeavesTotal(getLeavesTotal(self.mapShape))
|
|
260
|
+
|
|
261
|
+
leavesTotalAsInt = int(self.leavesTotal)
|
|
262
|
+
|
|
263
|
+
self.connectionGraph = getConnectionGraph(self.mapShape, leavesTotalAsInt, self.__dataclass_fields__['connectionGraph'].metadata['dtype'])
|
|
264
|
+
|
|
265
|
+
self.indicesArrayGroupOfFolds = (numpy.arange(leavesTotalAsInt + 1)[:, None] + numpy.arange(leavesTotalAsInt)[None, :]) % (leavesTotalAsInt + 1)
|
|
266
|
+
self.indicesArrayGroupOfFolds[..., leavesTotalAsInt // 2:None] = self.indicesArrayGroupOfFolds[..., leavesTotalAsInt - 1: leavesTotalAsInt - leavesTotalAsInt // 2 - 1: -1]
|
|
267
|
+
self.arrayGroupOfFolds = numpy.zeros_like(self.indicesArrayGroupOfFolds)
|
|
268
|
+
|
|
269
|
+
if self.dimensionsUnconstrained is None: self.dimensionsUnconstrained = DatatypeLeavesTotal(int(self.dimensionsTotal)) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
270
|
+
if self.gapsWhere is None: self.gapsWhere = makeDataContainer(leavesTotalAsInt * leavesTotalAsInt + 1, self.__dataclass_fields__['gapsWhere'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
271
|
+
if self.countDimensionsGapped is None: self.countDimensionsGapped = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['countDimensionsGapped'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
272
|
+
if self.gapRangeStart is None: self.gapRangeStart = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['gapRangeStart'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
273
|
+
if self.leafAbove is None: self.leafAbove = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafAbove'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
274
|
+
if self.leafBelow is None: self.leafBelow = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafBelow'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
157
275
|
if self.leafComparison is None: self.leafComparison = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafComparison'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
158
276
|
|
|
159
277
|
@dataclasses.dataclass
|
|
@@ -280,21 +398,21 @@ class MatrixMeandersState:
|
|
|
280
398
|
"""The index of the meanders problem being solved."""
|
|
281
399
|
oeisID: str
|
|
282
400
|
"""'A000682', semi-meanders, or 'A005316', meanders."""
|
|
283
|
-
|
|
284
|
-
"""The
|
|
401
|
+
boundary: int
|
|
402
|
+
"""The algorithm analyzes `n` boundaries starting at `boundary = n - 1`."""
|
|
285
403
|
dictionaryMeanders: dict[int, int]
|
|
286
404
|
"""A Python `dict` (*dict*ionary) of `arcCode` to `crossings`. The values are stored as Python `int`
|
|
287
405
|
(*int*eger), which may be arbitrarily large. Because of that property, `int` may also be called a 'bignum' (big *num*ber) or
|
|
288
406
|
'bigint' (big *int*eger)."""
|
|
289
407
|
|
|
290
408
|
bitWidth: int = 0
|
|
291
|
-
"""At the start of an iteration enumerated by `
|
|
409
|
+
"""At the start of an iteration enumerated by `boundary`, the number of bits of the largest value `arcCode`. The
|
|
292
410
|
`dataclass` computes a `property` from `bitWidth`."""
|
|
293
411
|
|
|
294
412
|
@property
|
|
295
413
|
def MAXIMUMarcCode(self) -> int:
|
|
296
414
|
"""Compute the maximum value of `arcCode` for the current iteration of the transfer matrix."""
|
|
297
|
-
return 1 << (2 * self.
|
|
415
|
+
return 1 << (2 * self.boundary + 4)
|
|
298
416
|
|
|
299
417
|
@property
|
|
300
418
|
def locatorBits(self) -> int:
|
|
@@ -317,7 +435,8 @@ class MatrixMeandersState:
|
|
|
317
435
|
class MatrixMeandersNumPyState(MatrixMeandersState):
|
|
318
436
|
"""Hold the state of a meanders transfer matrix algorithm computation."""
|
|
319
437
|
|
|
320
|
-
|
|
438
|
+
arrayArcCodes: NDArray[numpy.uint64] = dataclasses.field(default_factory=lambda: numpy.empty((0,), dtype=numpy.uint64))
|
|
439
|
+
arrayCrossings: NDArray[numpy.uint64] = dataclasses.field(default_factory=lambda: numpy.empty((0,), dtype=numpy.uint64))
|
|
321
440
|
|
|
322
441
|
bitWidthLimitArcCode: int | None = None
|
|
323
442
|
bitWidthLimitCrossings: int | None = None
|
|
@@ -330,20 +449,6 @@ class MatrixMeandersNumPyState(MatrixMeandersState):
|
|
|
330
449
|
indexTarget: int = 0
|
|
331
450
|
"""What is being indexed depends on the algorithm flavor."""
|
|
332
451
|
|
|
333
|
-
# TODO Integrate this better into the dataclasses paradigm.
|
|
334
|
-
indicesMeanders: Final[int] = 2
|
|
335
|
-
indexArcCode, indexCrossings = range(indicesMeanders)
|
|
336
|
-
|
|
337
|
-
@property
|
|
338
|
-
def slicerArcCode(self) -> ShapeSlicer:
|
|
339
|
-
"""Get a `ShapeSlicer` to extract the `arcCode` column from `arrayMeanders`."""
|
|
340
|
-
return ShapeSlicer(length=..., indices=self.indexArcCode)
|
|
341
|
-
|
|
342
|
-
@property
|
|
343
|
-
def slicerCrossings(self) -> ShapeSlicer:
|
|
344
|
-
"""Get a `ShapeSlicer` to extract the `crossings` column from `arrayMeanders`."""
|
|
345
|
-
return ShapeSlicer(length=..., indices=self.indexCrossings)
|
|
346
|
-
|
|
347
452
|
def __post_init__(self) -> None:
|
|
348
453
|
"""Post init."""
|
|
349
454
|
if self.bitWidthLimitArcCode is None:
|
|
@@ -371,16 +476,13 @@ class MatrixMeandersNumPyState(MatrixMeandersState):
|
|
|
371
476
|
|
|
372
477
|
def makeDictionary(self) -> None:
|
|
373
478
|
"""Convert from NumPy `ndarray` (*Num*erical *Py*thon *n-d*imensional array) to Python `dict` (*dict*ionary)."""
|
|
374
|
-
self.dictionaryMeanders = {int(key): int(value) for key, value in zip(
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
self.arrayMeanders = numpy.empty((0,), dtype=self.datatypeArcCode)
|
|
479
|
+
self.dictionaryMeanders = {int(key): int(value) for key, value in zip(self.arrayArcCodes, self.arrayCrossings, strict=True)}
|
|
480
|
+
self.arrayArcCodes = numpy.empty((0,), dtype=self.datatypeArcCode)
|
|
481
|
+
self.arrayCrossings = numpy.empty((0,), dtype=self.datatypeCrossings)
|
|
378
482
|
|
|
379
483
|
def makeArray(self) -> None:
|
|
380
484
|
"""Convert from Python `dict` (*dict*ionary) to NumPy `ndarray` (*Num*erical *Py*thon *n-d*imensional array)."""
|
|
381
|
-
|
|
382
|
-
self.
|
|
383
|
-
self.
|
|
384
|
-
self.arrayMeanders[self.slicerCrossings] = list(self.dictionaryMeanders.values())
|
|
385
|
-
self.bitWidth = int(self.arrayMeanders[self.slicerArcCode].max()).bit_length()
|
|
485
|
+
self.arrayArcCodes = numpy.array(list(self.dictionaryMeanders.keys()), dtype=self.datatypeArcCode)
|
|
486
|
+
self.arrayCrossings = numpy.array(list(self.dictionaryMeanders.values()), dtype=self.datatypeCrossings)
|
|
487
|
+
self.bitWidth = int(self.arrayArcCodes.max()).bit_length()
|
|
386
488
|
self.dictionaryMeanders = {}
|
mapFolding/filesystemToolkit.py
CHANGED
|
@@ -56,12 +56,10 @@ def getFilenameFoldsTotal(mapShape: tuple[int, ...]) -> str:
|
|
|
56
56
|
return 'p' + 'x'.join(str(dimension) for dimension in sorted(mapShape)) + '.foldsTotal'
|
|
57
57
|
|
|
58
58
|
def getPathFilenameFoldsTotal(mapShape: tuple[int, ...], pathLikeWriteFoldsTotal: PathLike[str] | PurePath | None = None) -> Path:
|
|
59
|
-
"""Get a standardized
|
|
59
|
+
"""Get a standardized filename and create a configurable path to store the computed `foldsTotal` value.
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
This function resolves paths for storing computation results, handling different input types including directories,
|
|
64
|
-
absolute paths, or relative paths. It ensures that all parent directories exist in the resulting path.
|
|
61
|
+
To help reduce duplicate code and to increase predictability, this function creates a standardized filename, has a default but
|
|
62
|
+
configurable path, and creates the path.
|
|
65
63
|
|
|
66
64
|
Parameters
|
|
67
65
|
----------
|
|
@@ -78,10 +76,9 @@ def getPathFilenameFoldsTotal(mapShape: tuple[int, ...], pathLikeWriteFoldsTotal
|
|
|
78
76
|
Notes
|
|
79
77
|
-----
|
|
80
78
|
The function creates any necessary directories in the path if they don't exist.
|
|
81
|
-
|
|
82
79
|
"""
|
|
83
80
|
if pathLikeWriteFoldsTotal is None:
|
|
84
|
-
pathFilenameFoldsTotal = getPathRootJobDEFAULT() / getFilenameFoldsTotal(mapShape)
|
|
81
|
+
pathFilenameFoldsTotal: Path = getPathRootJobDEFAULT() / getFilenameFoldsTotal(mapShape)
|
|
85
82
|
else:
|
|
86
83
|
pathLikeSherpa = Path(pathLikeWriteFoldsTotal)
|
|
87
84
|
if pathLikeSherpa.is_dir():
|
|
@@ -237,28 +234,3 @@ def saveFoldsTotalFAILearly(pathFilename: PathLike[str] | PurePath) -> None:
|
|
|
237
234
|
if foldsTotalRead != foldsTotal:
|
|
238
235
|
message = f"I wrote a test file to `{pathFilename = }` with contents of `{str(foldsTotal) = }`, but I read `{foldsTotalRead = }` from the file. Python says the values are not equal. Fix that now, so your computation doesn't get corrupted later. And be pro-social."
|
|
239
236
|
raise FileNotFoundError(message)
|
|
240
|
-
|
|
241
|
-
def writeStringToHere(this: str, pathFilename: PathLike[str] | PurePath) -> None:
|
|
242
|
-
"""Write a string to a file, creating parent directories if needed.
|
|
243
|
-
|
|
244
|
-
(AI generated docstring)
|
|
245
|
-
|
|
246
|
-
This utility function provides a consistent interface for writing string content to files across the package. It
|
|
247
|
-
handles path creation and ensures proper string conversion.
|
|
248
|
-
|
|
249
|
-
Parameters
|
|
250
|
-
----------
|
|
251
|
-
this : str
|
|
252
|
-
The string content to write to the file.
|
|
253
|
-
pathFilename : PathLike[str] | PurePath
|
|
254
|
-
The target file path where the string should be written.
|
|
255
|
-
|
|
256
|
-
Notes
|
|
257
|
-
-----
|
|
258
|
-
This function creates all parent directories in the path if they don't exist, making it safe to use with newly
|
|
259
|
-
created directory structures.
|
|
260
|
-
|
|
261
|
-
"""
|
|
262
|
-
pathFilename = Path(pathFilename)
|
|
263
|
-
pathFilename.parent.mkdir(parents=True, exist_ok=True)
|
|
264
|
-
pathFilename.write_text(str(this))
|
mapFolding/oeis.py
CHANGED
|
@@ -306,12 +306,6 @@ def makeDictionaryFoldsTotalKnown() -> dict[tuple[int, ...], int]:
|
|
|
306
306
|
def getFoldsTotalKnown(mapShape: tuple[int, ...]) -> int:
|
|
307
307
|
"""Retrieve the known total number of distinct folding patterns for a given map shape.
|
|
308
308
|
|
|
309
|
-
(AI generated docstring)
|
|
310
|
-
|
|
311
|
-
This function provides rapid access to precalculated folding totals from OEIS sequences without
|
|
312
|
-
requiring computation. It serves as a validation reference for algorithm results and enables
|
|
313
|
-
quick lookup of known values across all implemented sequences.
|
|
314
|
-
|
|
315
309
|
Parameters
|
|
316
310
|
----------
|
|
317
311
|
mapShape : tuple[int, ...]
|
|
@@ -320,17 +314,16 @@ def getFoldsTotalKnown(mapShape: tuple[int, ...]) -> int:
|
|
|
320
314
|
Returns
|
|
321
315
|
-------
|
|
322
316
|
foldingsTotal : int
|
|
323
|
-
The known total number of distinct folding patterns for the given map shape,
|
|
324
|
-
|
|
317
|
+
The known total number of distinct folding patterns for the given map shape, or 0 if the map shape does not match any
|
|
318
|
+
known values in the OEIS sequences.
|
|
325
319
|
|
|
326
320
|
Notes
|
|
327
321
|
-----
|
|
328
|
-
|
|
329
|
-
OEIS data. Map shapes are matched exactly as provided without internal sorting or normalization.
|
|
322
|
+
Map shapes are matched exactly as provided without internal sorting or normalization.
|
|
330
323
|
|
|
331
324
|
"""
|
|
332
|
-
lookupFoldsTotal = makeDictionaryFoldsTotalKnown()
|
|
333
|
-
return lookupFoldsTotal.get(tuple(mapShape),
|
|
325
|
+
lookupFoldsTotal: dict[tuple[int, ...], int] = makeDictionaryFoldsTotalKnown()
|
|
326
|
+
return lookupFoldsTotal.get(tuple(mapShape), 0)
|
|
334
327
|
|
|
335
328
|
def _formatHelpText() -> str:
|
|
336
329
|
"""Format comprehensive help text for both command-line and interactive use.
|