mapFolding 0.15.4__py3-none-any.whl → 0.16.1__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 +25 -0
- easyRun/A005316.py +21 -0
- easyRun/NOTcountingFolds.py +36 -0
- easyRun/__init__.py +0 -0
- easyRun/countFolds.py +41 -0
- easyRun/meanders.py +71 -0
- mapFolding/__init__.py +10 -55
- mapFolding/_dataPacking.py +68 -0
- mapFolding/_theSSOT.py +33 -36
- mapFolding/_theTypes.py +21 -4
- mapFolding/algorithms/daoOfMapFolding.py +1 -2
- mapFolding/algorithms/matrixMeanders.py +101 -348
- mapFolding/algorithms/matrixMeandersBeDry.py +264 -0
- mapFolding/algorithms/matrixMeandersNumPy.py +286 -0
- mapFolding/algorithms/matrixMeandersPandas.py +351 -0
- mapFolding/algorithms/oeisIDbyFormula.py +320 -76
- mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +92 -0
- mapFolding/basecamp.py +261 -113
- mapFolding/beDRY.py +2 -30
- mapFolding/dataBaskets.py +120 -4
- mapFolding/oeis.py +13 -33
- mapFolding/reference/A000682facts.py +1276 -0
- mapFolding/reference/A005316facts.py +985 -0
- mapFolding/reference/matrixMeandersAnalysis/__init__.py +1 -0
- mapFolding/reference/matrixMeandersAnalysis/prefixNotationNotes.py +15 -0
- mapFolding/reference/meandersDumpingGround/A005316JavaPort.py +1 -1
- mapFolding/reference/meandersDumpingGround/A005316imperative.py +1 -1
- mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +424 -0
- mapFolding/someAssemblyRequired/A007822/A007822rawMaterials.py +54 -0
- mapFolding/someAssemblyRequired/A007822/__init__.py +0 -0
- mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +197 -0
- mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +74 -0
- mapFolding/someAssemblyRequired/RecipeJob.py +4 -4
- mapFolding/someAssemblyRequired/__init__.py +9 -2
- mapFolding/someAssemblyRequired/_toolIfThis.py +4 -3
- mapFolding/someAssemblyRequired/_toolkitContainers.py +8 -8
- mapFolding/someAssemblyRequired/infoBooth.py +27 -30
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +6 -5
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +6 -4
- mapFolding/someAssemblyRequired/makingModules_count.py +294 -0
- mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +117 -0
- mapFolding/someAssemblyRequired/mapFolding/__init__.py +0 -0
- mapFolding/someAssemblyRequired/mapFolding/makeMapFoldingModules.py +220 -0
- mapFolding/someAssemblyRequired/meanders/__init__.py +0 -0
- mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +64 -0
- mapFolding/someAssemblyRequired/toolkitMakeModules.py +152 -0
- mapFolding/someAssemblyRequired/toolkitNumba.py +1 -1
- mapFolding/someAssemblyRequired/transformationTools.py +1 -0
- mapFolding/syntheticModules/A007822/__init__.py +1 -0
- mapFolding/syntheticModules/{algorithmA007822.py → A007822/algorithm.py} +2 -3
- mapFolding/syntheticModules/{algorithmA007822Numba.py → A007822/algorithmNumba.py} +3 -6
- mapFolding/syntheticModules/A007822/asynchronous.py +148 -0
- mapFolding/syntheticModules/A007822/asynchronousAnnex.py +66 -0
- mapFolding/syntheticModules/A007822/asynchronousAnnexNumba.py +85 -0
- mapFolding/syntheticModules/A007822/asynchronousNumba.py +52 -0
- mapFolding/syntheticModules/A007822/asynchronousTheorem2.py +53 -0
- mapFolding/syntheticModules/A007822/asynchronousTrimmed.py +47 -0
- mapFolding/syntheticModules/{initializeStateA007822.py → A007822/initializeState.py} +1 -2
- mapFolding/syntheticModules/{theorem2A007822.py → A007822/theorem2.py} +1 -2
- mapFolding/syntheticModules/{theorem2A007822Numba.py → A007822/theorem2Numba.py} +6 -4
- mapFolding/syntheticModules/{theorem2A007822Trimmed.py → A007822/theorem2Trimmed.py} +1 -2
- mapFolding/syntheticModules/countParallelNumba.py +5 -2
- mapFolding/syntheticModules/daoOfMapFoldingNumba.py +4 -2
- mapFolding/syntheticModules/dataPacking.py +4 -2
- mapFolding/syntheticModules/dataPackingA007822.py +92 -26
- mapFolding/syntheticModules/meanders/__init__.py +1 -0
- mapFolding/syntheticModules/meanders/bigInt.py +62 -0
- mapFolding/syntheticModules/theorem2Numba.py +3 -2
- mapFolding/tests/conftest.py +28 -13
- mapFolding/tests/test_computations.py +69 -62
- mapFolding/tests/test_oeis.py +6 -6
- mapFolding/zCuzDocStoopid/__init__.py +4 -0
- mapFolding/zCuzDocStoopid/makeDocstrings.py +68 -0
- mapfolding-0.16.1.dist-info/METADATA +99 -0
- mapfolding-0.16.1.dist-info/RECORD +114 -0
- {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/top_level.txt +1 -0
- mapFolding/someAssemblyRequired/A007822rawMaterials.py +0 -46
- mapFolding/someAssemblyRequired/makeAllModules.py +0 -764
- mapfolding-0.15.4.dist-info/METADATA +0 -78
- mapfolding-0.15.4.dist-info/RECORD +0 -78
- {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/WHEEL +0 -0
- {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/licenses/LICENSE +0 -0
mapFolding/dataBaskets.py
CHANGED
|
@@ -22,10 +22,13 @@ access patterns that enable efficient result persistence and retrieval.
|
|
|
22
22
|
"""
|
|
23
23
|
from mapFolding import (
|
|
24
24
|
Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal,
|
|
25
|
-
getConnectionGraph, getLeavesTotal, makeDataContainer)
|
|
25
|
+
getConnectionGraph, getLeavesTotal, makeDataContainer, ShapeArray, ShapeSlicer)
|
|
26
|
+
from numpy.typing import NDArray
|
|
27
|
+
from typing import Final, TypeAlias
|
|
26
28
|
import dataclasses
|
|
29
|
+
import numpy
|
|
27
30
|
|
|
28
|
-
@dataclasses.dataclass
|
|
31
|
+
@dataclasses.dataclass(slots=True)
|
|
29
32
|
class MapFoldingState:
|
|
30
33
|
"""Core computational state for map folding algorithms.
|
|
31
34
|
|
|
@@ -154,8 +157,8 @@ class MapFoldingState:
|
|
|
154
157
|
if self.leafComparison is None: self.leafComparison = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafComparison'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
155
158
|
|
|
156
159
|
@dataclasses.dataclass
|
|
157
|
-
class ParallelMapFoldingState(MapFoldingState):
|
|
158
|
-
"""
|
|
160
|
+
class ParallelMapFoldingState(MapFoldingState): # This identifier because of `dataclassIdentifierParallel: identifierDotAttribute = 'Parallel' + dataclassIdentifier`.
|
|
161
|
+
"""Computational state for task division operations.
|
|
159
162
|
|
|
160
163
|
(AI generated docstring)
|
|
161
164
|
|
|
@@ -268,3 +271,116 @@ class LeafSequenceState(MapFoldingState):
|
|
|
268
271
|
if self.leafSequence is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
269
272
|
self.leafSequence = makeDataContainer(groupsOfFoldsKnown, self.__dataclass_fields__['leafSequence'].metadata['dtype'])
|
|
270
273
|
self.leafSequence[self.groupsOfFolds] = self.leaf1ndex
|
|
274
|
+
|
|
275
|
+
@dataclasses.dataclass(slots=True)
|
|
276
|
+
class MatrixMeandersState:
|
|
277
|
+
"""Hold the state of a meanders transfer matrix algorithm computation."""
|
|
278
|
+
|
|
279
|
+
n: int
|
|
280
|
+
"""The index of the meanders problem being solved."""
|
|
281
|
+
oeisID: str
|
|
282
|
+
"""'A000682', semi-meanders, or 'A005316', meanders."""
|
|
283
|
+
kOfMatrix: int
|
|
284
|
+
"""The number of iterations remaining in the transfer matrix algorithm."""
|
|
285
|
+
dictionaryMeanders: dict[int, int]
|
|
286
|
+
"""A Python `dict` (*dict*ionary) of `arcCode` to `crossings`. The values are stored as Python `int`
|
|
287
|
+
(*int*eger), which may be arbitrarily large. Because of that property, `int` may also be called a 'bignum' (big *num*ber) or
|
|
288
|
+
'bigint' (big *int*eger)."""
|
|
289
|
+
|
|
290
|
+
bitWidth: int = 0
|
|
291
|
+
"""At the start of an iteration enumerated by `kOfMatrix`, the number of bits of the largest value `arcCode`. The
|
|
292
|
+
`dataclass` computes a `property` from `bitWidth`."""
|
|
293
|
+
|
|
294
|
+
@property
|
|
295
|
+
def MAXIMUMarcCode(self) -> int:
|
|
296
|
+
"""Compute the maximum value of `arcCode` for the current iteration of the transfer matrix."""
|
|
297
|
+
return 1 << (2 * self.kOfMatrix + 4)
|
|
298
|
+
|
|
299
|
+
@property
|
|
300
|
+
def locatorBits(self) -> int:
|
|
301
|
+
"""Compute an odd-parity bit-mask with `bitWidth` bits.
|
|
302
|
+
|
|
303
|
+
Notes
|
|
304
|
+
-----
|
|
305
|
+
In binary, `locatorBitsAlpha` has alternating 0s and 1s and ends with a 1, such as '101', '0101', and '10101'. The last
|
|
306
|
+
digit is in the 1's column, but programmers usually call it the "least significant bit" (LSB). If we count the columns
|
|
307
|
+
from the right, the 1's column is column 1, the 2's column is column 2, the 4's column is column 3, and so on. When
|
|
308
|
+
counting this way, `locatorBitsAlpha` has 1s in the columns with odd index numbers. Mathematicians and programmers,
|
|
309
|
+
therefore, tend to call `locatorBitsAlpha` something like the "odd bit-mask", the "odd-parity numbers", or simply "odd
|
|
310
|
+
mask" or "odd numbers". In addition to "odd" being inherently ambiguous in this context, this algorithm also segregates
|
|
311
|
+
odd numbers from even numbers, so I avoid using "odd" and "even" in the names of these bit-masks.
|
|
312
|
+
|
|
313
|
+
"""
|
|
314
|
+
return sum(1 << one for one in range(0, self.bitWidth, 2))
|
|
315
|
+
|
|
316
|
+
@dataclasses.dataclass(slots=True)
|
|
317
|
+
class MatrixMeandersNumPyState(MatrixMeandersState):
|
|
318
|
+
"""Hold the state of a meanders transfer matrix algorithm computation."""
|
|
319
|
+
|
|
320
|
+
arrayMeanders: NDArray[numpy.uint64] = dataclasses.field(default_factory=lambda: numpy.empty((0,), dtype=numpy.uint64))
|
|
321
|
+
|
|
322
|
+
bitWidthLimitArcCode: int | None = None
|
|
323
|
+
bitWidthLimitCrossings: int | None = None
|
|
324
|
+
|
|
325
|
+
datatypeArcCode: TypeAlias = numpy.uint64 # noqa: UP040
|
|
326
|
+
"""The fixed-size integer type used to store `arcCode`."""
|
|
327
|
+
datatypeCrossings: TypeAlias = numpy.uint64 # noqa: UP040
|
|
328
|
+
"""The fixed-size integer type used to store `crossings`."""
|
|
329
|
+
|
|
330
|
+
indexTarget: int = 0
|
|
331
|
+
"""What is being indexed depends on the algorithm flavor."""
|
|
332
|
+
|
|
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
|
+
def __post_init__(self) -> None:
|
|
348
|
+
"""Post init."""
|
|
349
|
+
if self.bitWidthLimitArcCode is None:
|
|
350
|
+
_bitWidthOfFixedSizeInteger: int = numpy.dtype(self.datatypeArcCode).itemsize * 8 # bits
|
|
351
|
+
|
|
352
|
+
_offsetNecessary: int = 3 # For example, `bitsZulu << 3`.
|
|
353
|
+
_offsetSafety: int = 1 # I don't have mathematical proof of how many extra bits I need.
|
|
354
|
+
_offset: int = _offsetNecessary + _offsetSafety
|
|
355
|
+
|
|
356
|
+
self.bitWidthLimitArcCode = _bitWidthOfFixedSizeInteger - _offset
|
|
357
|
+
|
|
358
|
+
del _bitWidthOfFixedSizeInteger, _offsetNecessary, _offsetSafety, _offset
|
|
359
|
+
|
|
360
|
+
if self.bitWidthLimitCrossings is None:
|
|
361
|
+
_bitWidthOfFixedSizeInteger: int = numpy.dtype(self.datatypeCrossings).itemsize * 8 # bits
|
|
362
|
+
|
|
363
|
+
_offsetNecessary: int = 0 # I don't know of any.
|
|
364
|
+
_offsetEstimation: int = 3 # See reference directory.
|
|
365
|
+
_offsetSafety: int = 1
|
|
366
|
+
_offset: int = _offsetNecessary + _offsetEstimation + _offsetSafety
|
|
367
|
+
|
|
368
|
+
self.bitWidthLimitCrossings = _bitWidthOfFixedSizeInteger - _offset
|
|
369
|
+
|
|
370
|
+
del _bitWidthOfFixedSizeInteger, _offsetNecessary, _offsetEstimation, _offsetSafety, _offset
|
|
371
|
+
|
|
372
|
+
def makeDictionary(self) -> None:
|
|
373
|
+
"""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
|
+
self.arrayMeanders[self.slicerArcCode], self.arrayMeanders[self.slicerCrossings]
|
|
376
|
+
, strict=True)}
|
|
377
|
+
self.arrayMeanders = numpy.empty((0,), dtype=self.datatypeArcCode)
|
|
378
|
+
|
|
379
|
+
def makeArray(self) -> None:
|
|
380
|
+
"""Convert from Python `dict` (*dict*ionary) to NumPy `ndarray` (*Num*erical *Py*thon *n-d*imensional array)."""
|
|
381
|
+
shape = ShapeArray(length=len(self.dictionaryMeanders), indices=self.indicesMeanders)
|
|
382
|
+
self.arrayMeanders = numpy.zeros(shape, dtype=self.datatypeArcCode)
|
|
383
|
+
self.arrayMeanders[self.slicerArcCode] = list(self.dictionaryMeanders.keys())
|
|
384
|
+
self.arrayMeanders[self.slicerCrossings] = list(self.dictionaryMeanders.values())
|
|
385
|
+
self.bitWidth = int(self.arrayMeanders[self.slicerArcCode].max()).bit_length()
|
|
386
|
+
self.dictionaryMeanders = {}
|
mapFolding/oeis.py
CHANGED
|
@@ -27,7 +27,7 @@ completes the journey from configuration foundation to mathematical discovery.
|
|
|
27
27
|
from datetime import datetime, timedelta, UTC
|
|
28
28
|
from hunterMakesPy import writeStringToHere
|
|
29
29
|
from itertools import chain
|
|
30
|
-
from mapFolding import countFolds,
|
|
30
|
+
from mapFolding import countFolds, MetadataOEISid, MetadataOEISidMapFolding, packageSettings
|
|
31
31
|
from mapFolding._theSSOT import pathCache
|
|
32
32
|
from pathlib import Path
|
|
33
33
|
from typing import Final
|
|
@@ -248,7 +248,7 @@ def getOEISidInformation(oeisID: str) -> tuple[str, int]:
|
|
|
248
248
|
description: str = ' '.join(listDescriptionDeconstructed)
|
|
249
249
|
return description, offset
|
|
250
250
|
|
|
251
|
-
def
|
|
251
|
+
def _makeDictionaryOEISMapFolding() -> dict[str, MetadataOEISidMapFolding]:
|
|
252
252
|
"""Construct the comprehensive settings dictionary for all implemented OEIS sequences.
|
|
253
253
|
|
|
254
254
|
(AI generated docstring)
|
|
@@ -287,8 +287,8 @@ def _makeDictionaryOEIS() -> dict[str, MetadataOEISidMapFolding]:
|
|
|
287
287
|
)
|
|
288
288
|
return dictionaryOEIS
|
|
289
289
|
|
|
290
|
-
dictionaryOEISMapFolding: dict[str, MetadataOEISidMapFolding] =
|
|
291
|
-
"""Metadata for each OEIS
|
|
290
|
+
dictionaryOEISMapFolding: dict[str, MetadataOEISidMapFolding] = _makeDictionaryOEISMapFolding()
|
|
291
|
+
"""Metadata for each MapFolding OEIS ID."""
|
|
292
292
|
|
|
293
293
|
def makeDictionaryFoldsTotalKnown() -> dict[tuple[int, ...], int]:
|
|
294
294
|
"""Make a `mapShape` to known `foldsTotal` dictionary.
|
|
@@ -418,9 +418,10 @@ def oeisIDfor_n(oeisID: str, n: int) -> int:
|
|
|
418
418
|
message = f"OEIS sequence {oeisID} is not defined at {n = }."
|
|
419
419
|
raise ArithmeticError(message)
|
|
420
420
|
foldsTotal: int = dictionaryOEISMapFolding[oeisID]['valuesKnown'][n]
|
|
421
|
-
|
|
421
|
+
else:
|
|
422
|
+
foldsTotal = countFolds(mapShape=mapShape)
|
|
422
423
|
|
|
423
|
-
return
|
|
424
|
+
return foldsTotal
|
|
424
425
|
|
|
425
426
|
def OEIS_for_n() -> None:
|
|
426
427
|
"""Command-line interface for calculating OEIS sequence values.
|
|
@@ -466,27 +467,6 @@ def OEIS_for_n() -> None:
|
|
|
466
467
|
timeElapsed: float = time.perf_counter() - timeStart
|
|
467
468
|
print(f"Time elapsed: {timeElapsed:.3f} seconds") # noqa: T201
|
|
468
469
|
|
|
469
|
-
def clearOEIScache() -> None:
|
|
470
|
-
"""Delete all cached OEIS sequence files from the local cache directory.
|
|
471
|
-
|
|
472
|
-
(AI generated docstring)
|
|
473
|
-
|
|
474
|
-
This function removes all cached OEIS data files, including both sequence value files (b-files)
|
|
475
|
-
and metadata files, forcing fresh retrieval from the OEIS website on the next access. This is
|
|
476
|
-
useful for clearing stale cache data or troubleshooting network-related issues.
|
|
477
|
-
|
|
478
|
-
The function safely handles missing files and provides user feedback about the cache clearing
|
|
479
|
-
operation. If the cache directory does not exist, an informative message is displayed.
|
|
480
|
-
|
|
481
|
-
"""
|
|
482
|
-
if not pathCache.exists():
|
|
483
|
-
print(f"Cache directory, {pathCache}, not found - nothing to clear.") # noqa: T201
|
|
484
|
-
return
|
|
485
|
-
for oeisID in dictionaryOEISMapFolding:
|
|
486
|
-
( pathCache / f"{oeisID}.txt" ).unlink(missing_ok=True)
|
|
487
|
-
( pathCache / _getFilenameOEISbFile(oeisID) ).unlink(missing_ok=True)
|
|
488
|
-
print(f"Cache cleared from {pathCache}") # noqa: T201
|
|
489
|
-
|
|
490
470
|
def getOEISids() -> None:
|
|
491
471
|
"""Display comprehensive information about all implemented OEIS sequences.
|
|
492
472
|
|
|
@@ -503,21 +483,21 @@ def getOEISids() -> None:
|
|
|
503
483
|
"""
|
|
504
484
|
print(_formatHelpText()) # noqa: T201
|
|
505
485
|
|
|
506
|
-
def
|
|
507
|
-
dictionary: dict[str,
|
|
508
|
-
for oeisID in packageSettings.
|
|
486
|
+
def _makeDictionaryOEIS() -> dict[str, MetadataOEISid]:
|
|
487
|
+
dictionary: dict[str, MetadataOEISid] = {}
|
|
488
|
+
for oeisID in packageSettings.OEISidManuallySet:
|
|
509
489
|
valuesKnownSherpa: dict[int, int] = getOEISidValues(oeisID)
|
|
510
490
|
descriptionSherpa, offsetSherpa = getOEISidInformation(oeisID)
|
|
511
|
-
dictionary[oeisID] =
|
|
491
|
+
dictionary[oeisID] = MetadataOEISid(
|
|
512
492
|
description=descriptionSherpa,
|
|
513
493
|
offset=offsetSherpa,
|
|
514
494
|
valuesKnown=valuesKnownSherpa,
|
|
515
|
-
valuesTestValidation=packageSettings.
|
|
495
|
+
valuesTestValidation=[*(packageSettings.OEISidManuallySet[oeisID]['valuesTestValidation']), offsetSherpa],
|
|
516
496
|
valueUnknown=max(valuesKnownSherpa.keys(), default=0) + 1,
|
|
517
497
|
)
|
|
518
498
|
return dictionary
|
|
519
499
|
|
|
520
|
-
|
|
500
|
+
dictionaryOEIS: dict[str, MetadataOEISid] = _makeDictionaryOEIS()
|
|
521
501
|
|
|
522
502
|
if __name__ == "__main__":
|
|
523
503
|
getOEISids()
|