mapFolding 0.16.0__py3-none-any.whl → 0.16.2__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.
Files changed (77) hide show
  1. easyRun/A000682.py +25 -0
  2. easyRun/A005316.py +20 -0
  3. easyRun/NOTcountingFolds.py +36 -0
  4. easyRun/__init__.py +0 -0
  5. easyRun/countFolds.py +41 -0
  6. easyRun/meanders.py +69 -0
  7. mapFolding/__init__.py +8 -51
  8. mapFolding/_dataPacking.py +68 -0
  9. mapFolding/_theSSOT.py +33 -37
  10. mapFolding/_theTypes.py +21 -4
  11. mapFolding/algorithms/matrixMeanders.py +86 -517
  12. mapFolding/algorithms/matrixMeandersBeDry.py +182 -0
  13. mapFolding/algorithms/matrixMeandersNumPy.py +333 -0
  14. mapFolding/algorithms/matrixMeandersPandas.py +334 -0
  15. mapFolding/algorithms/oeisIDbyFormula.py +50 -29
  16. mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +51 -29
  17. mapFolding/basecamp.py +167 -206
  18. mapFolding/beDRY.py +2 -30
  19. mapFolding/dataBaskets.py +75 -49
  20. mapFolding/oeis.py +11 -32
  21. mapFolding/reference/A000682facts.py +787 -652
  22. mapFolding/reference/A005316facts.py +961 -3
  23. mapFolding/reference/matrixMeandersAnalysis/prefixNotationNotes.py +15 -0
  24. mapFolding/reference/matrixMeandersAnalysis/signatures.py +2030 -0
  25. mapFolding/reference/meandersDumpingGround/A005316JavaPort.py +1 -1
  26. mapFolding/reference/meandersDumpingGround/A005316imperative.py +1 -1
  27. mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +424 -0
  28. mapFolding/someAssemblyRequired/A007822/A007822rawMaterials.py +3 -4
  29. mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +103 -29
  30. mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +18 -14
  31. mapFolding/someAssemblyRequired/RecipeJob.py +2 -2
  32. mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +7 -6
  33. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +3 -4
  34. mapFolding/someAssemblyRequired/makingModules_count.py +88 -87
  35. mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +10 -9
  36. mapFolding/someAssemblyRequired/mapFolding/makeMapFoldingModules.py +3 -3
  37. mapFolding/someAssemblyRequired/meanders/__init__.py +0 -0
  38. mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +63 -0
  39. mapFolding/someAssemblyRequired/toolkitMakeModules.py +37 -37
  40. mapFolding/someAssemblyRequired/transformationTools.py +8 -8
  41. mapFolding/syntheticModules/A007822/algorithm.py +3 -3
  42. mapFolding/syntheticModules/A007822/algorithmNumba.py +1 -2
  43. mapFolding/syntheticModules/A007822/asynchronous.py +6 -4
  44. mapFolding/syntheticModules/A007822/asynchronousAnnex.py +5 -7
  45. mapFolding/syntheticModules/A007822/asynchronousAnnexNumba.py +70 -0
  46. mapFolding/syntheticModules/A007822/asynchronousNumba.py +79 -0
  47. mapFolding/syntheticModules/A007822/asynchronousTheorem2.py +15 -3
  48. mapFolding/syntheticModules/A007822/asynchronousTrimmed.py +12 -3
  49. mapFolding/syntheticModules/A007822/initializeState.py +1 -2
  50. mapFolding/syntheticModules/A007822/theorem2.py +7 -2
  51. mapFolding/syntheticModules/A007822/theorem2Numba.py +31 -4
  52. mapFolding/syntheticModules/A007822/theorem2Trimmed.py +8 -3
  53. mapFolding/syntheticModules/countParallelNumba.py +5 -2
  54. mapFolding/syntheticModules/dataPacking.py +1 -1
  55. mapFolding/syntheticModules/dataPackingA007822.py +92 -26
  56. mapFolding/syntheticModules/meanders/__init__.py +1 -0
  57. mapFolding/syntheticModules/meanders/bigInt.py +52 -0
  58. mapFolding/syntheticModules/theorem2.py +6 -0
  59. mapFolding/syntheticModules/theorem2Numba.py +8 -2
  60. mapFolding/syntheticModules/theorem2Trimmed.py +6 -0
  61. mapFolding/tests/conftest.py +28 -13
  62. mapFolding/tests/test_computations.py +68 -61
  63. mapFolding/tests/test_oeis.py +6 -6
  64. mapFolding/zCuzDocStoopid/__init__.py +4 -1
  65. mapFolding/zCuzDocStoopid/makeDocstrings.py +35 -28
  66. mapfolding-0.16.2.dist-info/METADATA +99 -0
  67. mapfolding-0.16.2.dist-info/RECORD +115 -0
  68. {mapfolding-0.16.0.dist-info → mapfolding-0.16.2.dist-info}/top_level.txt +1 -0
  69. mapFolding/algorithms/getBucketsTotal.py +0 -137
  70. mapFolding/reference/matrixMeandersAnalysis/evenEven.py +0 -144
  71. mapFolding/reference/matrixMeandersAnalysis/oddEven.py +0 -54
  72. mapFolding/trim_memory.py +0 -62
  73. mapfolding-0.16.0.dist-info/METADATA +0 -85
  74. mapfolding-0.16.0.dist-info/RECORD +0 -100
  75. {mapfolding-0.16.0.dist-info → mapfolding-0.16.2.dist-info}/WHEEL +0 -0
  76. {mapfolding-0.16.0.dist-info → mapfolding-0.16.2.dist-info}/entry_points.txt +0 -0
  77. {mapfolding-0.16.0.dist-info → mapfolding-0.16.2.dist-info}/licenses/LICENSE +0 -0
mapFolding/dataBaskets.py CHANGED
@@ -23,10 +23,12 @@ access patterns that enable efficient result persistence and retrieval.
23
23
  from mapFolding import (
24
24
  Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal,
25
25
  getConnectionGraph, getLeavesTotal, makeDataContainer)
26
+ from numpy.typing import NDArray
27
+ from typing import TypeAlias
26
28
  import dataclasses
27
29
  import numpy
28
30
 
29
- @dataclasses.dataclass
31
+ @dataclasses.dataclass(slots=True)
30
32
  class MapFoldingState:
31
33
  """Core computational state for map folding algorithms.
32
34
 
@@ -155,8 +157,8 @@ class MapFoldingState:
155
157
  if self.leafComparison is None: self.leafComparison = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafComparison'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
156
158
 
157
159
  @dataclasses.dataclass
158
- class ParallelMapFoldingState(MapFoldingState):
159
- """Experimental computational state for task division operations.
160
+ class ParallelMapFoldingState(MapFoldingState): # This identifier because of `dataclassIdentifierParallel: identifierDotAttribute = 'Parallel' + dataclassIdentifier`.
161
+ """Computational state for task division operations.
160
162
 
161
163
  (AI generated docstring)
162
164
 
@@ -270,75 +272,99 @@ class LeafSequenceState(MapFoldingState):
270
272
  self.leafSequence = makeDataContainer(groupsOfFoldsKnown, self.__dataclass_fields__['leafSequence'].metadata['dtype'])
271
273
  self.leafSequence[self.groupsOfFolds] = self.leaf1ndex
272
274
 
273
-
274
- @dataclasses.dataclass
275
+ @dataclasses.dataclass(slots=True)
275
276
  class MatrixMeandersState:
276
- """State."""
277
+ """Hold the state of a meanders transfer matrix algorithm computation."""
277
278
 
278
279
  n: int
280
+ """The index of the meanders problem being solved."""
279
281
  oeisID: str
280
- kOfMatrix: int
281
- dictionaryCurveLocations: dict[int, int]
282
+ """'A000682', semi-meanders, or 'A005316', meanders."""
283
+ boundary: int
284
+ """The algorithm analyzes `n` boundaries starting at `boundary = n - 1`."""
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)."""
282
289
 
283
- datatypeCurveLocations: type = numpy.uint64
284
- datatypeDistinctCrossings: type = numpy.uint64
290
+ bitWidth: int = 0
291
+ """At the start of an iteration enumerated by `boundary`, the number of bits of the largest value `arcCode`. The
292
+ `dataclass` computes a `property` from `bitWidth`."""
285
293
 
286
- bitWidthCurveLocationsMaximum: int | None = None
287
- bitWidthDistinctCrossingsMaximum: int | None = None
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.boundary + 4)
288
298
 
289
- bitWidth: int = 0
290
- indexStartAnalyzed: int = 0
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
+ arrayArcCodes: NDArray[numpy.uint64] = dataclasses.field(default_factory=lambda: numpy.empty((0,), dtype=numpy.uint64))
321
+ arrayCrossings: NDArray[numpy.uint64] = dataclasses.field(default_factory=lambda: numpy.empty((0,), dtype=numpy.uint64))
322
+
323
+ bitWidthLimitArcCode: int | None = None
324
+ bitWidthLimitCrossings: int | None = None
325
+
326
+ datatypeArcCode: TypeAlias = numpy.uint64 # noqa: UP040
327
+ """The fixed-size integer type used to store `arcCode`."""
328
+ datatypeCrossings: TypeAlias = numpy.uint64 # noqa: UP040
329
+ """The fixed-size integer type used to store `crossings`."""
330
+
331
+ indexTarget: int = 0
332
+ """What is being indexed depends on the algorithm flavor."""
291
333
 
292
334
  def __post_init__(self) -> None:
293
335
  """Post init."""
294
- if self.bitWidthCurveLocationsMaximum is None:
295
- _bitWidthOfFixedSizeInteger: int = numpy.dtype(self.datatypeCurveLocations).itemsize * 8 # bits
336
+ if self.bitWidthLimitArcCode is None:
337
+ _bitWidthOfFixedSizeInteger: int = numpy.dtype(self.datatypeArcCode).itemsize * 8 # bits
296
338
 
297
- _offsetNecessary: int = 3 # For example, `groupZulu << 3`.
339
+ _offsetNecessary: int = 3 # For example, `bitsZulu << 3`.
298
340
  _offsetSafety: int = 1 # I don't have mathematical proof of how many extra bits I need.
299
341
  _offset: int = _offsetNecessary + _offsetSafety
300
342
 
301
- self.bitWidthCurveLocationsMaximum = _bitWidthOfFixedSizeInteger - _offset
343
+ self.bitWidthLimitArcCode = _bitWidthOfFixedSizeInteger - _offset
302
344
 
303
345
  del _bitWidthOfFixedSizeInteger, _offsetNecessary, _offsetSafety, _offset
304
346
 
305
- if self.bitWidthDistinctCrossingsMaximum is None:
306
- _bitWidthOfFixedSizeInteger: int = numpy.dtype(self.datatypeDistinctCrossings).itemsize * 8 # bits
347
+ if self.bitWidthLimitCrossings is None:
348
+ _bitWidthOfFixedSizeInteger: int = numpy.dtype(self.datatypeCrossings).itemsize * 8 # bits
307
349
 
308
350
  _offsetNecessary: int = 0 # I don't know of any.
309
351
  _offsetEstimation: int = 3 # See reference directory.
310
352
  _offsetSafety: int = 1
311
353
  _offset: int = _offsetNecessary + _offsetEstimation + _offsetSafety
312
354
 
313
- self.bitWidthDistinctCrossingsMaximum = _bitWidthOfFixedSizeInteger - _offset
355
+ self.bitWidthLimitCrossings = _bitWidthOfFixedSizeInteger - _offset
314
356
 
315
357
  del _bitWidthOfFixedSizeInteger, _offsetNecessary, _offsetEstimation, _offsetSafety, _offset
316
358
 
317
- @property
318
- def MAXIMUMcurveLocations(self) -> int:
319
- """Compute the maximum value of `curveLocations` for the current iteration of the transfer matrix."""
320
- return 1 << (2 * self.kOfMatrix + 4)
321
-
322
- @property
323
- def locatorGroupAlpha(self) -> int:
324
- """Compute an odd-parity bit-mask with `bitWidth` bits.
325
-
326
- Notes
327
- -----
328
- In binary, `locatorGroupAlpha` has alternating 0s and 1s and ends with a 1, such as '101', '0101', and '10101'. The last
329
- digit is in the 1's column, but programmers usually call it the "least significant bit" (LSB). If we count the columns
330
- 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
331
- counting this way, `locatorGroupAlpha` has 1s in the columns with odd index numbers. Mathematicians and programmers,
332
- therefore, tend to call `locatorGroupAlpha` something like the "odd bit-mask", the "odd-parity numbers", or simply "odd
333
- mask" or "odd numbers". In addition to "odd" being inherently ambiguous in this context, this algorithm also segregates
334
- odd numbers from even numbers, so I avoid using "odd" and "even" in the names of these bit-masks.
335
-
336
- """
337
- return sum(1 << one for one in range(0, self.bitWidth, 2))
338
-
339
- @property
340
- def locatorGroupZulu(self) -> int:
341
- """Compute an even-parity bit-mask with `bitWidth` bits."""
342
- return sum(1 << one for one in range(1, self.bitWidth, 2))
343
-
344
-
359
+ def makeDictionary(self) -> None:
360
+ """Convert from NumPy `ndarray` (*Num*erical *Py*thon *n-d*imensional array) to Python `dict` (*dict*ionary)."""
361
+ self.dictionaryMeanders = {int(key): int(value) for key, value in zip(self.arrayArcCodes, self.arrayCrossings, strict=True)}
362
+ self.arrayArcCodes = numpy.empty((0,), dtype=self.datatypeArcCode)
363
+ self.arrayCrossings = numpy.empty((0,), dtype=self.datatypeCrossings)
364
+
365
+ def makeArray(self) -> None:
366
+ """Convert from Python `dict` (*dict*ionary) to NumPy `ndarray` (*Num*erical *Py*thon *n-d*imensional array)."""
367
+ self.arrayArcCodes = numpy.array(list(self.dictionaryMeanders.keys()), dtype=self.datatypeArcCode)
368
+ self.arrayCrossings = numpy.array(list(self.dictionaryMeanders.values()), dtype=self.datatypeCrossings)
369
+ self.bitWidth = int(self.arrayArcCodes.max()).bit_length()
370
+ 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, MetadataOEISidMapFolding, MetadataOEISidMeanders, packageSettings
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 _makeDictionaryOEIS() -> dict[str, MetadataOEISidMapFolding]:
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] = _makeDictionaryOEIS()
291
- """Metadata for each OEIS sequence ID."""
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.
@@ -419,7 +419,7 @@ def oeisIDfor_n(oeisID: str, n: int) -> int:
419
419
  raise ArithmeticError(message)
420
420
  foldsTotal: int = dictionaryOEISMapFolding[oeisID]['valuesKnown'][n]
421
421
  else:
422
- foldsTotal = countFolds(oeisID=oeisID, oeis_n=n)
422
+ foldsTotal = countFolds(mapShape=mapShape)
423
423
 
424
424
  return foldsTotal
425
425
 
@@ -467,27 +467,6 @@ def OEIS_for_n() -> None:
467
467
  timeElapsed: float = time.perf_counter() - timeStart
468
468
  print(f"Time elapsed: {timeElapsed:.3f} seconds") # noqa: T201
469
469
 
470
- def clearOEIScache() -> None:
471
- """Delete all cached OEIS sequence files from the local cache directory.
472
-
473
- (AI generated docstring)
474
-
475
- This function removes all cached OEIS data files, including both sequence value files (b-files)
476
- and metadata files, forcing fresh retrieval from the OEIS website on the next access. This is
477
- useful for clearing stale cache data or troubleshooting network-related issues.
478
-
479
- The function safely handles missing files and provides user feedback about the cache clearing
480
- operation. If the cache directory does not exist, an informative message is displayed.
481
-
482
- """
483
- if not pathCache.exists():
484
- print(f"Cache directory, {pathCache}, not found - nothing to clear.") # noqa: T201
485
- return
486
- for oeisID in dictionaryOEISMapFolding:
487
- ( pathCache / f"{oeisID}.txt" ).unlink(missing_ok=True)
488
- ( pathCache / _getFilenameOEISbFile(oeisID) ).unlink(missing_ok=True)
489
- print(f"Cache cleared from {pathCache}") # noqa: T201
490
-
491
470
  def getOEISids() -> None:
492
471
  """Display comprehensive information about all implemented OEIS sequences.
493
472
 
@@ -504,21 +483,21 @@ def getOEISids() -> None:
504
483
  """
505
484
  print(_formatHelpText()) # noqa: T201
506
485
 
507
- def _makeDictionaryOEISMeanders() -> dict[str, MetadataOEISidMeanders]:
508
- dictionary: dict[str, MetadataOEISidMeanders] = {}
509
- for oeisID in packageSettings.OEISidMeandersManuallySet:
486
+ def _makeDictionaryOEIS() -> dict[str, MetadataOEISid]:
487
+ dictionary: dict[str, MetadataOEISid] = {}
488
+ for oeisID in packageSettings.OEISidManuallySet:
510
489
  valuesKnownSherpa: dict[int, int] = getOEISidValues(oeisID)
511
490
  descriptionSherpa, offsetSherpa = getOEISidInformation(oeisID)
512
- dictionary[oeisID] = MetadataOEISidMeanders(
491
+ dictionary[oeisID] = MetadataOEISid(
513
492
  description=descriptionSherpa,
514
493
  offset=offsetSherpa,
515
494
  valuesKnown=valuesKnownSherpa,
516
- valuesTestValidation=packageSettings.OEISidMeandersManuallySet[oeisID]['valuesTestValidation'],
495
+ valuesTestValidation=[*(packageSettings.OEISidManuallySet[oeisID]['valuesTestValidation']), offsetSherpa],
517
496
  valueUnknown=max(valuesKnownSherpa.keys(), default=0) + 1,
518
497
  )
519
498
  return dictionary
520
499
 
521
- dictionaryOEISMeanders: dict[str, MetadataOEISidMeanders] = _makeDictionaryOEISMeanders()
500
+ dictionaryOEIS: dict[str, MetadataOEISid] = _makeDictionaryOEIS()
522
501
 
523
502
  if __name__ == "__main__":
524
503
  getOEISids()