mapFolding 0.13.0__py3-none-any.whl → 0.14.0__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 (43) hide show
  1. mapFolding/_oeisFormulas/A000136.py +4 -0
  2. mapFolding/_oeisFormulas/A000560.py +4 -0
  3. mapFolding/_oeisFormulas/A000682.py +17 -0
  4. mapFolding/_oeisFormulas/A005315.py +4 -0
  5. mapFolding/_oeisFormulas/A005316.py +10 -0
  6. mapFolding/_oeisFormulas/A223094.py +7 -0
  7. mapFolding/_oeisFormulas/A259702.py +4 -0
  8. mapFolding/_oeisFormulas/A301620.py +6 -0
  9. mapFolding/_oeisFormulas/Z0Z_aOFn.py +19 -0
  10. mapFolding/_oeisFormulas/Z0Z_oeisMeanders.py +53 -0
  11. mapFolding/_oeisFormulas/__init__.py +1 -0
  12. mapFolding/_oeisFormulas/matrixMeanders.py +65 -0
  13. mapFolding/_oeisFormulas/matrixMeandersAnnex.py +84 -0
  14. mapFolding/_theSSOT.py +68 -26
  15. mapFolding/basecamp.py +2 -2
  16. mapFolding/beDRY.py +1 -1
  17. mapFolding/oeis.py +56 -167
  18. mapFolding/reference/A005316JavaPort.py +134 -0
  19. mapFolding/reference/A005316imperative.py +101 -0
  20. mapFolding/reference/A005316intOptimized.py +122 -0
  21. mapFolding/reference/A005316optimized128bit.py +79 -0
  22. mapFolding/reference/A005316primitiveOptimized.py +97 -0
  23. mapFolding/reference/A005316redis.py +118 -0
  24. mapFolding/reference/A005316write2disk.py +169 -0
  25. mapFolding/reference/irvineJavaPort.py +4 -8
  26. mapFolding/reference/matrixMeandersBaseline.py +65 -0
  27. mapFolding/reference/matrixMeandersBaselineAnnex.py +84 -0
  28. mapFolding/someAssemblyRequired/RecipeJob.py +3 -4
  29. mapFolding/someAssemblyRequired/_toolkitContainers.py +3 -3
  30. mapFolding/someAssemblyRequired/makeAllModules.py +2 -2
  31. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +109 -141
  32. mapFolding/someAssemblyRequired/toolkitNumba.py +9 -7
  33. mapFolding/tests/conftest.py +13 -13
  34. mapFolding/tests/test_computations.py +4 -4
  35. mapFolding/tests/test_oeis.py +7 -14
  36. mapfolding-0.14.0.dist-info/METADATA +78 -0
  37. mapfolding-0.14.0.dist-info/RECORD +76 -0
  38. mapfolding-0.13.0.dist-info/METADATA +0 -154
  39. mapfolding-0.13.0.dist-info/RECORD +0 -54
  40. {mapfolding-0.13.0.dist-info → mapfolding-0.14.0.dist-info}/WHEEL +0 -0
  41. {mapfolding-0.13.0.dist-info → mapfolding-0.14.0.dist-info}/entry_points.txt +0 -0
  42. {mapfolding-0.13.0.dist-info → mapfolding-0.14.0.dist-info}/licenses/LICENSE +0 -0
  43. {mapfolding-0.13.0.dist-info → mapfolding-0.14.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,4 @@
1
+ from mapFolding._oeisFormulas.A000682 import A000682
2
+
3
+ def A000136(n: int) -> int:
4
+ return n * A000682(n)
@@ -0,0 +1,4 @@
1
+ from mapFolding._oeisFormulas.A000682 import A000682
2
+
3
+ def A000560(n: int) -> int:
4
+ return A000682(n + 1) // 2
@@ -0,0 +1,17 @@
1
+ from mapFolding._oeisFormulas.matrixMeanders import count, curveMaximum
2
+
3
+ def initializeA000682(n: int) -> dict[int, int]:
4
+ curveLocationsMAXIMUM = curveMaximum[n].curveLocationsMAXIMUM
5
+
6
+ curveSeed: int = 5 - (n & 0b1) * 4
7
+ listCurveLocations = [(curveSeed << 1) | curveSeed]
8
+
9
+ while listCurveLocations[-1] < curveLocationsMAXIMUM:
10
+ curveSeed = (curveSeed << 4) | 0b101
11
+ listCurveLocations.append((curveSeed << 1) | curveSeed)
12
+
13
+ return dict.fromkeys(listCurveLocations, 1)
14
+
15
+ def A000682(n: int) -> int:
16
+ return count(n - 1, initializeA000682(n - 1))
17
+
@@ -0,0 +1,4 @@
1
+ from mapFolding._oeisFormulas.A005316 import A005316
2
+
3
+ def A005315(n: int) -> int:
4
+ return A005316(2 * n - 1)
@@ -0,0 +1,10 @@
1
+ from mapFolding._oeisFormulas.matrixMeanders import count
2
+
3
+ def initializeA005316(n: int) -> dict[int, int]:
4
+ if n & 0b1:
5
+ return {22: 1}
6
+ else:
7
+ return {15: 1}
8
+
9
+ def A005316(n: int) -> int:
10
+ return count(n-1, initializeA005316(n-1))
@@ -0,0 +1,7 @@
1
+ from mapFolding._oeisFormulas.A000136 import A000136
2
+ from mapFolding._oeisFormulas.A000682 import A000682
3
+
4
+ def A223094(n: int) -> int:
5
+ return A000136(n) - A000682(n + 1)
6
+
7
+ # %F A223094 For n >= 3: a(n) = n! - Sum_{k=3..n-1} (a(k)*n!/k!) - A000682(n+1). - _Roger Ford_, Aug 24 2024
@@ -0,0 +1,4 @@
1
+ from mapFolding._oeisFormulas.A000682 import A000682
2
+
3
+ def A259702(n: int) -> int:
4
+ return A000682(n) // 2 - A000682(n - 1)
@@ -0,0 +1,6 @@
1
+ from mapFolding._oeisFormulas.A000682 import A000682
2
+
3
+ def A301620(n: int) -> int:
4
+ return A000682(n + 2) - 2 * A000682(n + 1)
5
+
6
+ # %F A301620 a(n) = Sum_{k=3..floor((n+3)/2)} (A259689(n+1,k)*(k-2)). - _Roger Ford_, Dec 10 2018
@@ -0,0 +1,19 @@
1
+ from mapFolding._oeisFormulas.A000136 import A000136
2
+ from mapFolding._oeisFormulas.matrixMeanders import curveMaximum
3
+ from mapFolding.oeis import dictionaryOEIS
4
+ import sys
5
+ import time
6
+
7
+ # ruff: noqa: ERA001
8
+
9
+ if __name__ == '__main__':
10
+ oeisID = 'A000136'
11
+ for n in range(3,30):
12
+
13
+ # print(n)
14
+
15
+ timeStart = time.perf_counter()
16
+ foldsTotal = A000136(n)
17
+ # sys.stdout.write(f"{n} {foldsTotal} {time.perf_counter() - timeStart:.2f}\n")
18
+ sys.stdout.write(f"{foldsTotal == dictionaryOEIS[oeisID]['valuesKnown'][n]} {n} {foldsTotal} {time.perf_counter() - timeStart:.2f}\n")
19
+
@@ -0,0 +1,53 @@
1
+ from mapFolding._oeisFormulas.A000560 import A000560
2
+ from mapFolding._oeisFormulas.A000682 import A000682
3
+ from mapFolding._oeisFormulas.A005315 import A005315
4
+ from mapFolding._oeisFormulas.A005316 import A005316
5
+ from mapFolding._oeisFormulas.A223094 import A223094
6
+ from mapFolding._oeisFormulas.A259702 import A259702
7
+ from mapFolding._oeisFormulas.A301620 import A301620
8
+ from mapFolding.oeis import getOEISidInformation, getOEISidValues
9
+ import sys
10
+
11
+ oeisIDsMeanders: list[str] = [
12
+ 'A000560',
13
+ 'A000682',
14
+ 'A005315',
15
+ 'A005316',
16
+ 'A223094',
17
+ 'A259702',
18
+ 'A301620',
19
+ ]
20
+
21
+ dictionaryOEISMeanders: dict[str, dict[str, dict[int, int] | str | int]] = {
22
+ oeisID: {
23
+ 'valuesKnown': getOEISidValues(oeisID),
24
+ 'description': getOEISidInformation(oeisID)[0],
25
+ 'offset': getOEISidInformation(oeisID)[1],
26
+ }
27
+ for oeisID in oeisIDsMeanders
28
+ }
29
+
30
+ # ruff: noqa: S101
31
+ # pyright: reportIndexIssue=false
32
+
33
+ rangeTest = range(5, 13)
34
+
35
+ if __name__ == '__main__':
36
+ for n in rangeTest:
37
+
38
+ A000560for_n = A000560(n)
39
+ assert A000560for_n == dictionaryOEISMeanders['A000560']['valuesKnown'][n]
40
+ A000682for_n = A000682(n)
41
+ assert A000682for_n == dictionaryOEISMeanders['A000682']['valuesKnown'][n]
42
+ A005315for_n = A005315(n)
43
+ assert A005315for_n == dictionaryOEISMeanders['A005315']['valuesKnown'][n]
44
+ A005316for_n = A005316(n)
45
+ assert A005316for_n == dictionaryOEISMeanders['A005316']['valuesKnown'][n]
46
+ A223094for_n = A223094(n)
47
+ assert A223094for_n == dictionaryOEISMeanders['A223094']['valuesKnown'][n]
48
+ A259702for_n = A259702(n)
49
+ assert A259702for_n == dictionaryOEISMeanders['A259702']['valuesKnown'][n]
50
+ A301620for_n = A301620(n)
51
+ assert A301620for_n == dictionaryOEISMeanders['A301620']['valuesKnown'][n]
52
+
53
+ sys.stdout.write(f"\nTrue for {str(rangeTest)}\n")
@@ -0,0 +1 @@
1
+ """OEIS formula collection and analysis."""
@@ -0,0 +1,65 @@
1
+ from mapFolding._oeisFormulas.matrixMeandersAnnex import curveMaximum as curveMaximum
2
+
3
+ dictionaryCurveLocations: dict[int, int] = {}
4
+
5
+ def getCurveLocations() -> dict[int, int]:
6
+ global dictionaryCurveLocations # noqa: PLW0603
7
+ sherpa = dictionaryCurveLocations.copy()
8
+ dictionaryCurveLocations = {}
9
+ return sherpa
10
+
11
+ def recordAnalysis(curveLocationAnalysis: int, curveLocationsMAXIMUM: int, distinctCrossings: int) -> None:
12
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
13
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
14
+
15
+ def initializeCurveLocations(startingCurveLocations: dict[int, int]) -> None:
16
+ global dictionaryCurveLocations # noqa: PLW0603
17
+ dictionaryCurveLocations = startingCurveLocations.copy()
18
+
19
+ def count(bridges: int, startingCurveLocations: dict[int, int]) -> int:
20
+ initializeCurveLocations(startingCurveLocations)
21
+
22
+ while bridges > 0:
23
+ bridges -= 1
24
+ curveLocationsMAXIMUM, bifurcationEvenLocator, bifurcationOddLocator = curveMaximum[bridges]
25
+
26
+ for curveLocations, distinctCrossings in getCurveLocations().items():
27
+ bifurcationEven = (curveLocations & bifurcationEvenLocator) >> 1
28
+ bifurcationOdd = curveLocations & bifurcationOddLocator
29
+
30
+ bifurcationEvenFinalZero = (bifurcationEven & 0b1) == 0
31
+ bifurcationEvenHasCurves = bifurcationEven != 1
32
+ bifurcationOddFinalZero = (bifurcationOdd & 0b1) == 0
33
+ bifurcationOddHasCurves = bifurcationOdd != 1
34
+
35
+ if bifurcationEvenHasCurves:
36
+ curveLocationAnalysis = (bifurcationEven >> 1) | (bifurcationOdd << 2) | bifurcationEvenFinalZero
37
+ recordAnalysis(curveLocationAnalysis, curveLocationsMAXIMUM, distinctCrossings)
38
+
39
+ if bifurcationOddHasCurves:
40
+ curveLocationAnalysis = (bifurcationOdd >> 2) | (bifurcationEven << 3) | (bifurcationOddFinalZero << 1)
41
+ recordAnalysis(curveLocationAnalysis, curveLocationsMAXIMUM, distinctCrossings)
42
+
43
+ curveLocationAnalysis = ((bifurcationOdd | (bifurcationEven << 1)) << 2) | 3
44
+ recordAnalysis(curveLocationAnalysis, curveLocationsMAXIMUM, distinctCrossings)
45
+
46
+ if bifurcationEvenHasCurves and bifurcationOddHasCurves and (bifurcationEvenFinalZero or bifurcationOddFinalZero):
47
+ XOrHere2makePair = 0b1
48
+ findUnpairedBinary1 = 0
49
+
50
+ if bifurcationEvenFinalZero and not bifurcationOddFinalZero:
51
+ while findUnpairedBinary1 >= 0:
52
+ XOrHere2makePair <<= 2
53
+ findUnpairedBinary1 += 1 if (bifurcationEven & XOrHere2makePair) == 0 else -1
54
+ bifurcationEven ^= XOrHere2makePair
55
+
56
+ elif bifurcationOddFinalZero and not bifurcationEvenFinalZero:
57
+ while findUnpairedBinary1 >= 0:
58
+ XOrHere2makePair <<= 2
59
+ findUnpairedBinary1 += 1 if (bifurcationOdd & XOrHere2makePair) == 0 else -1
60
+ bifurcationOdd ^= XOrHere2makePair
61
+
62
+ curveLocationAnalysis = ((bifurcationEven >> 2) << 1) | (bifurcationOdd >> 2)
63
+ recordAnalysis(curveLocationAnalysis, curveLocationsMAXIMUM, distinctCrossings)
64
+
65
+ return sum(getCurveLocations().values())
@@ -0,0 +1,84 @@
1
+ from typing import NamedTuple
2
+ import sys
3
+
4
+ class limitLocators(NamedTuple):
5
+ curveLocationsMAXIMUM: int
6
+ bifurcationEvenLocator: int
7
+ bifurcationOddLocator: int
8
+
9
+ curveMaximum: dict[int, limitLocators] = {
10
+ 0: limitLocators(16, 0x2a, 0x15),
11
+ 1: limitLocators(64, 0xaa, 0x55),
12
+ 2: limitLocators(256, 0x2aa, 0x155),
13
+ 3: limitLocators(1024, 0xaaa, 0x555),
14
+ 4: limitLocators(4096, 0x2aaa, 0x1555),
15
+ 5: limitLocators(16384, 0xaaaa, 0x5555),
16
+ 6: limitLocators(65536, 0x2aaaa, 0x15555),
17
+ 7: limitLocators(262144, 0xaaaaa, 0x55555),
18
+ 8: limitLocators(1048576, 0x2aaaaa, 0x155555),
19
+ 9: limitLocators(4194304, 0xaaaaaa, 0x555555),
20
+ 10: limitLocators(16777216, 0x2aaaaaa, 0x1555555),
21
+ 11: limitLocators(67108864, 0xaaaaaaa, 0x5555555),
22
+ 12: limitLocators(268435456, 0x2aaaaaaa, 0x15555555),
23
+ 13: limitLocators(1073741824, 0xaaaaaaaa, 0x55555555),
24
+ 14: limitLocators(4294967296, 0x2aaaaaaaa, 0x155555555),
25
+ 15: limitLocators(17179869184, 0xaaaaaaaaa, 0x555555555),
26
+ 16: limitLocators(68719476736, 0x2aaaaaaaaa, 0x1555555555),
27
+ 17: limitLocators(274877906944, 0xaaaaaaaaaa, 0x5555555555),
28
+ 18: limitLocators(1099511627776, 0x2aaaaaaaaaa, 0x15555555555),
29
+ 19: limitLocators(4398046511104, 0xaaaaaaaaaaa, 0x55555555555),
30
+ 20: limitLocators(17592186044416, 0x2aaaaaaaaaaa, 0x155555555555),
31
+ 21: limitLocators(70368744177664, 0xaaaaaaaaaaaa, 0x555555555555),
32
+ 22: limitLocators(281474976710656, 0x2aaaaaaaaaaaa, 0x1555555555555),
33
+ 23: limitLocators(1125899906842624, 0xaaaaaaaaaaaaa, 0x5555555555555),
34
+ 24: limitLocators(4503599627370496, 0x2aaaaaaaaaaaaa, 0x15555555555555),
35
+ 25: limitLocators(18014398509481984, 0xaaaaaaaaaaaaaa, 0x55555555555555),
36
+ 26: limitLocators(72057594037927936, 0x2aaaaaaaaaaaaaa, 0x155555555555555),
37
+ 27: limitLocators(288230376151711744, 0xaaaaaaaaaaaaaaa, 0x555555555555555),
38
+ 28: limitLocators(1152921504606846976, 0x2aaaaaaaaaaaaaaa, 0x1555555555555555),
39
+ 29: limitLocators(4611686018427387904, 0xaaaaaaaaaaaaaaaa, 0x5555555555555555),
40
+ 30: limitLocators(18446744073709551616, 0x2aaaaaaaaaaaaaaaa, 0x15555555555555555),
41
+ 31: limitLocators(73786976294838206464, 0xaaaaaaaaaaaaaaaaa, 0x55555555555555555),
42
+ 32: limitLocators(295147905179352825856, 0x2aaaaaaaaaaaaaaaaa, 0x155555555555555555),
43
+ 33: limitLocators(1180591620717411303424, 0xaaaaaaaaaaaaaaaaaa, 0x555555555555555555),
44
+ 34: limitLocators(4722366482869645213696, 0x2aaaaaaaaaaaaaaaaaa, 0x1555555555555555555),
45
+ 35: limitLocators(18889465931478580854784, 0xaaaaaaaaaaaaaaaaaaa, 0x5555555555555555555),
46
+ 36: limitLocators(75557863725914323419136, 0x2aaaaaaaaaaaaaaaaaaa, 0x15555555555555555555),
47
+ 37: limitLocators(302231454903657293676544, 0xaaaaaaaaaaaaaaaaaaaa, 0x55555555555555555555),
48
+ 38: limitLocators(1208925819614629174706176, 0x2aaaaaaaaaaaaaaaaaaaa, 0x155555555555555555555),
49
+ 39: limitLocators(4835703278458516698824704, 0xaaaaaaaaaaaaaaaaaaaaa, 0x555555555555555555555),
50
+ 40: limitLocators(19342813113834066795298816, 0x2aaaaaaaaaaaaaaaaaaaaa, 0x1555555555555555555555),
51
+ 41: limitLocators(77371252455336267181195264, 0xaaaaaaaaaaaaaaaaaaaaaa, 0x5555555555555555555555),
52
+ 42: limitLocators(309485009821345068724781056, 0x2aaaaaaaaaaaaaaaaaaaaaa, 0x15555555555555555555555),
53
+ 43: limitLocators(1237940039285380274899124224, 0xaaaaaaaaaaaaaaaaaaaaaaa, 0x55555555555555555555555),
54
+ 44: limitLocators(4951760157141521099596496896, 0x2aaaaaaaaaaaaaaaaaaaaaaa, 0x155555555555555555555555),
55
+ 45: limitLocators(19807040628566084398385987584, 0xaaaaaaaaaaaaaaaaaaaaaaaa, 0x555555555555555555555555),
56
+ 46: limitLocators(79228162514264337593543950336, 0x2aaaaaaaaaaaaaaaaaaaaaaaa, 0x1555555555555555555555555),
57
+ 47: limitLocators(316912650057057350374175801344, 0xaaaaaaaaaaaaaaaaaaaaaaaaa, 0x5555555555555555555555555),
58
+ 48: limitLocators(1267650600228229401496703205376, 0x2aaaaaaaaaaaaaaaaaaaaaaaaa, 0x15555555555555555555555555),
59
+ 49: limitLocators(5070602400912917605986812821504, 0xaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x55555555555555555555555555),
60
+ 50: limitLocators(20282409603651670423947251286016, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaa, 0x155555555555555555555555555),
61
+ 51: limitLocators(81129638414606681695789005144064, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x555555555555555555555555555),
62
+ 52: limitLocators(324518553658426726783156020576256, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x1555555555555555555555555555),
63
+ 53: limitLocators(1298074214633706907132624082305024, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x5555555555555555555555555555),
64
+ 54: limitLocators(5192296858534827628530496329220096, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x15555555555555555555555555555),
65
+ 55: limitLocators(20769187434139310514121985316880384, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x55555555555555555555555555555),
66
+ 56: limitLocators(83076749736557242056487941267521536, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x155555555555555555555555555555),
67
+ 57: limitLocators(332306998946228968225951765070086144, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x555555555555555555555555555555),
68
+ 58: limitLocators(1329227995784915872903807060280344576, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x1555555555555555555555555555555),
69
+ 59: limitLocators(5316911983139663491615228241121378304, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x5555555555555555555555555555555),
70
+ 60: limitLocators(21267647932558653966460912964485513216, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x15555555555555555555555555555555),
71
+ 61: limitLocators(85070591730234615865843651857942052864, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x55555555555555555555555555555555),
72
+ }
73
+
74
+ def makeCurveMaximum() -> None:
75
+ sys.stdout.write("curveMaximum: dict[int, limitLocators] = {\n")
76
+ for n in range(62):
77
+ curveLocationsMAXIMUM = 1 << (2 * n + 4)
78
+ bifurcationOddLocator = int('01' * ((curveLocationsMAXIMUM.bit_length() + 1) // 2), 2)
79
+ sys.stdout.write(f"{n}: limitLocators({curveLocationsMAXIMUM}, {hex(bifurcationOddLocator << 1)}, {hex(bifurcationOddLocator)}),\n")
80
+ sys.stdout.write("}\n")
81
+
82
+ if __name__ == '__main__':
83
+ makeCurveMaximum()
84
+
mapFolding/_theSSOT.py CHANGED
@@ -1,36 +1,31 @@
1
- """
2
- Foundation layer for the map folding computational ecosystem.
3
-
4
- (AI generated docstring)
5
-
6
- This module establishes the fundamental configuration infrastructure that underpins
7
- all map folding operations. Map folding, as defined by Lunnon's 1971 algorithm,
8
- requires precise coordination of computational resources, type systems, and data
9
- flow management to solve the complex combinatorial problem of counting distinct
10
- folding patterns across multi-dimensional maps.
11
-
12
- The Single Source Of Truth (SSOT) principle governs this foundation, ensuring that
13
- package identity, filesystem locations, and concurrency configuration remain
14
- consistent across all computational phases. During packaging, static metadata is
15
- resolved from pyproject.toml. During installation, filesystem-dependent paths are
16
- dynamically discovered. During runtime, the `packageSettings` instance provides
17
- unified access to all configuration values, enabling the sophisticated computational
18
- framework that follows.
19
-
20
- This configuration foundation supports the type system definition, core utility
21
- functions, computational state management, result persistence, and ultimately the
22
- main computational interface that users interact with to solve map folding problems.
1
+ """Primary goal: access and configure package settings and metadata.
2
+
3
+ Secondary goal: store hardcoded values until I implement a dynamic solution.
23
4
  """
24
5
 
6
+ from collections.abc import Callable
25
7
  from hunterMakesPy import PackageSettings
8
+ from pathlib import Path
9
+ from typing import TypedDict
26
10
  import dataclasses
11
+ import random
27
12
 
28
- packageNameHARDCODED = "mapFolding"
29
- """Hardcoded package name used as fallback when dynamic resolution fails."""
30
-
13
+ # TODO eliminate hardcoding
31
14
  concurrencyPackageHARDCODED = 'multiprocessing'
32
15
  """Default package identifier for concurrent execution operations."""
33
16
 
17
+ class MetadataOEISidManuallySet(TypedDict):
18
+ """Settings that are best selected by a human instead of algorithmically."""
19
+
20
+ getMapShape: Callable[[int], tuple[int, ...]]
21
+ """Function to convert the OEIS sequence index, 'n', to its `mapShape` tuple."""
22
+ valuesBenchmark: list[int]
23
+ """List of index values, 'n', to use when benchmarking the algorithm performance."""
24
+ valuesTestParallelization: list[int]
25
+ """List of index values, 'n', to use when testing parallelization performance."""
26
+ valuesTestValidation: list[int]
27
+ """List of index values, 'n', to use when testing validation performance."""
28
+
34
29
  @dataclasses.dataclass
35
30
  class mapFoldingPackageSettings(PackageSettings):
36
31
  """Centralized configuration container for all package-wide settings.
@@ -72,10 +67,57 @@ class mapFoldingPackageSettings(PackageSettings):
72
67
  specialized numerical computations.
73
68
  """
74
69
 
70
+ identifierPackageFALLBACK = "mapFolding"
71
+ """Hardcoded package name used as fallback when dynamic resolution fails."""
72
+
75
73
  concurrencyPackage = concurrencyPackageHARDCODED
76
74
  """Active concurrency package configuration for the current session."""
77
75
 
76
+ # TODO I made a `TypedDict` before I knew how to make dataclasses and classes. Think about other data structures.
77
+ settingsOEISManuallySelected: dict[str, MetadataOEISidManuallySet] = {
78
+ 'A000136': {
79
+ 'getMapShape': lambda n: tuple(sorted([1, n])),
80
+ 'valuesBenchmark': [14],
81
+ 'valuesTestParallelization': [*range(3, 7)],
82
+ 'valuesTestValidation': [random.randint(2, 9)], # noqa: S311
83
+ },
84
+ 'A001415': {
85
+ 'getMapShape': lambda n: tuple(sorted([2, n])),
86
+ 'valuesBenchmark': [14],
87
+ 'valuesTestParallelization': [*range(3, 7)],
88
+ 'valuesTestValidation': [random.randint(2, 9)], # noqa: S311
89
+ },
90
+ 'A001416': {
91
+ 'getMapShape': lambda n: tuple(sorted([3, n])),
92
+ 'valuesBenchmark': [9],
93
+ 'valuesTestParallelization': [*range(3, 5)],
94
+ 'valuesTestValidation': [random.randint(2, 6)], # noqa: S311
95
+ },
96
+ 'A001417': {
97
+ 'getMapShape': lambda n: tuple(2 for _dimension in range(n)),
98
+ 'valuesBenchmark': [6],
99
+ 'valuesTestParallelization': [*range(2, 4)],
100
+ 'valuesTestValidation': [random.randint(2, 4)], # noqa: S311
101
+ },
102
+ 'A195646': {
103
+ 'getMapShape': lambda n: tuple(3 for _dimension in range(n)),
104
+ 'valuesBenchmark': [3],
105
+ 'valuesTestParallelization': [*range(2, 3)],
106
+ 'valuesTestValidation': [2],
107
+ },
108
+ 'A001418': {
109
+ 'getMapShape': lambda n: (n, n),
110
+ 'valuesBenchmark': [5],
111
+ 'valuesTestParallelization': [*range(2, 4)],
112
+ 'valuesTestValidation': [random.randint(2, 4)], # noqa: S311
113
+ },
114
+ }
115
+
78
116
  packageSettings = mapFoldingPackageSettings(
79
- identifierPackageFALLBACK=packageNameHARDCODED
117
+ identifierPackageFALLBACK=identifierPackageFALLBACK
80
118
  , concurrencyPackage=concurrencyPackage)
81
119
  """Global package settings."""
120
+ cacheDays = 30
121
+ """Number of days to retain cached OEIS data before refreshing from the online source."""
122
+ pathCache: Path = packageSettings.pathPackage / ".cache"
123
+ """Local directory path for storing cached OEIS sequence data and metadata."""
mapFolding/basecamp.py CHANGED
@@ -96,9 +96,9 @@ def countFolds(listDimensions: Sequence[int] | None = None # noqa: C901, PLR091
96
96
  pass
97
97
  else:
98
98
  if oeisID and oeis_n:
99
- from mapFolding.oeis import settingsOEIS # noqa: PLC0415
99
+ from mapFolding.oeis import dictionaryOEIS # noqa: PLC0415
100
100
  with contextlib.suppress(KeyError):
101
- mapShape = settingsOEIS[oeisID]['getMapShape'](oeis_n)
101
+ mapShape = dictionaryOEIS[oeisID]['getMapShape'](oeis_n)
102
102
  if not mapShape and listDimensions:
103
103
  mapShape = validateListDimensions(listDimensions)
104
104
 
mapFolding/beDRY.py CHANGED
@@ -319,7 +319,7 @@ def validateListDimensions(listDimensions: Sequence[int]) -> tuple[int, ...]:
319
319
  message = f"I received `{dimension = }` in `{listDimensions = }`, but all dimensions must be a non-negative integer."
320
320
  raise ValueError(message)
321
321
  mapDimensions.append(dimension)
322
- if len(mapDimensions) < 2: # noqa: PLR2004
322
+ if len(mapDimensions) < 2:
323
323
  message = f"This function requires `{listDimensions = }` to have at least two dimensions greater than 0. You may want to look at https://oeis.org/."
324
324
  raise NotImplementedError(message)
325
325