mapFolding 0.15.3__py3-none-any.whl → 0.15.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.
Files changed (50) hide show
  1. mapFolding/__init__.py +15 -11
  2. mapFolding/_theSSOT.py +55 -62
  3. mapFolding/_theTypes.py +66 -4
  4. mapFolding/algorithms/__init__.py +1 -0
  5. mapFolding/algorithms/matrixMeanders.py +348 -0
  6. mapFolding/algorithms/oeisIDbyFormula.py +113 -0
  7. mapFolding/basecamp.py +55 -3
  8. mapFolding/oeis.py +40 -54
  9. mapFolding/{_oeisFormulas/matrixMeanders64.py → reference/meandersDumpingGround/matrixMeanders64retired.py} +37 -29
  10. mapFolding/someAssemblyRequired/makeAllModules.py +5 -5
  11. mapFolding/syntheticModules/algorithmA007822Numba.py +4 -2
  12. mapFolding/tests/conftest.py +28 -9
  13. mapFolding/tests/test_computations.py +31 -9
  14. mapFolding/tests/test_oeis.py +2 -20
  15. {mapfolding-0.15.3.dist-info → mapfolding-0.15.4.dist-info}/METADATA +1 -1
  16. {mapfolding-0.15.3.dist-info → mapfolding-0.15.4.dist-info}/RECORD +33 -47
  17. {mapfolding-0.15.3.dist-info → mapfolding-0.15.4.dist-info}/entry_points.txt +0 -1
  18. mapFolding/_oeisFormulas/A000136.py +0 -4
  19. mapFolding/_oeisFormulas/A000560.py +0 -4
  20. mapFolding/_oeisFormulas/A000682.py +0 -85
  21. mapFolding/_oeisFormulas/A001010.py +0 -19
  22. mapFolding/_oeisFormulas/A001011.py +0 -5
  23. mapFolding/_oeisFormulas/A005315.py +0 -4
  24. mapFolding/_oeisFormulas/A005316.py +0 -10
  25. mapFolding/_oeisFormulas/A223094.py +0 -7
  26. mapFolding/_oeisFormulas/A259702.py +0 -4
  27. mapFolding/_oeisFormulas/A301620.py +0 -6
  28. mapFolding/_oeisFormulas/Z0Z_aOFn.py +0 -34
  29. mapFolding/_oeisFormulas/Z0Z_notes.py +0 -16
  30. mapFolding/_oeisFormulas/Z0Z_oeisMeanders.py +0 -74
  31. mapFolding/_oeisFormulas/Z0Z_symmetry.py +0 -131
  32. mapFolding/_oeisFormulas/__init__.py +0 -1
  33. mapFolding/_oeisFormulas/matrixMeanders.py +0 -134
  34. mapFolding/_oeisFormulas/matrixMeandersAnnex.py +0 -84
  35. /mapFolding/{daoOfMapFolding.py → algorithms/daoOfMapFolding.py} +0 -0
  36. /mapFolding/reference/{A005316JavaPort.py → meandersDumpingGround/A005316JavaPort.py} +0 -0
  37. /mapFolding/reference/{A005316imperative.py → meandersDumpingGround/A005316imperative.py} +0 -0
  38. /mapFolding/reference/{A005316intOptimized.py → meandersDumpingGround/A005316intOptimized.py} +0 -0
  39. /mapFolding/reference/{A005316optimized128bit.py → meandersDumpingGround/A005316optimized128bit.py} +0 -0
  40. /mapFolding/reference/{A005316primitiveOptimized.py → meandersDumpingGround/A005316primitiveOptimized.py} +0 -0
  41. /mapFolding/reference/{A005316redis.py → meandersDumpingGround/A005316redis.py} +0 -0
  42. /mapFolding/reference/{A005316write2disk.py → meandersDumpingGround/A005316write2disk.py} +0 -0
  43. /mapFolding/reference/{matrixMeandersBaseline.py → meandersDumpingGround/matrixMeandersBaseline.py} +0 -0
  44. /mapFolding/reference/{matrixMeandersBaselineAnnex.py → meandersDumpingGround/matrixMeandersBaselineAnnex.py} +0 -0
  45. /mapFolding/reference/{matrixMeandersBaselineV2.py → meandersDumpingGround/matrixMeandersBaselineV2.py} +0 -0
  46. /mapFolding/reference/{matrixMeandersSimpleQueue.py → meandersDumpingGround/matrixMeandersSimpleQueue.py} +0 -0
  47. /mapFolding/reference/{matrixMeandersSlicePop.py → meandersDumpingGround/matrixMeandersSlicePop.py} +0 -0
  48. {mapfolding-0.15.3.dist-info → mapfolding-0.15.4.dist-info}/WHEEL +0 -0
  49. {mapfolding-0.15.3.dist-info → mapfolding-0.15.4.dist-info}/licenses/LICENSE +0 -0
  50. {mapfolding-0.15.3.dist-info → mapfolding-0.15.4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,113 @@
1
+ from functools import cache
2
+ from mapFolding import countFolds
3
+ from mapFolding.algorithms.matrixMeanders import doTheNeedful
4
+
5
+ @cache
6
+ def A000136(n: int) -> int:
7
+ return n * A000682(n)
8
+
9
+ def A000560(n: int) -> int:
10
+ return A000682(n + 1) // 2
11
+
12
+ def A000682getCurveLocations(n: int) -> dict[int, int]:
13
+ curveLocationsMAXIMUM: int = 1 << (2 * n + 4)
14
+
15
+ curveStart: int = 5 - (n & 0b1) * 4
16
+ listCurveLocations: list[int] = [(curveStart << 1) | curveStart]
17
+
18
+ while listCurveLocations[-1] < curveLocationsMAXIMUM:
19
+ curveStart = (curveStart << 4) | 0b101
20
+ listCurveLocations.append((curveStart << 1) | curveStart)
21
+
22
+ return dict.fromkeys(listCurveLocations, 1)
23
+
24
+ @cache
25
+ def A000682(n: int) -> int:
26
+ return doTheNeedful(n - 1, A000682getCurveLocations(n - 1))
27
+
28
+ def A001010(n: int) -> int:
29
+ """Formulas.
30
+
31
+ a(2n-1) = 2*A007822(n)
32
+ OddQ[n], 2*A007822[[(n - 1)/2 + 1]]]
33
+
34
+ a(2n) = 2*A000682(n+1)
35
+ EvenQ[n], 2*A000682[[n/2 + 1]]
36
+ """
37
+ if n == 1:
38
+ foldsTotal = 1
39
+ elif n & 0b1:
40
+ foldsTotal = 2 * countFolds(oeisID='A007822', oeis_n=(n - 1)//2 + 1, flow='theorem2Numba')
41
+ else:
42
+ foldsTotal = 2 * A000682(n // 2 + 1)
43
+ return foldsTotal
44
+
45
+ def A001011(n: int) -> int:
46
+ if n == 0:
47
+ foldsTotal = 1
48
+ else:
49
+ foldsTotal = (A001010(n) + A000136(n)) // 4
50
+ return foldsTotal
51
+
52
+ def A005316getCurveLocations(n: int) -> dict[int, int]:
53
+ if n & 0b1:
54
+ return {22: 1}
55
+ else:
56
+ return {15: 1}
57
+
58
+ @cache
59
+ def A005316(n: int) -> int:
60
+ return doTheNeedful(n-1, A005316getCurveLocations(n-1))
61
+
62
+ @cache
63
+ def A005315(n: int) -> int:
64
+ if n == 1:
65
+ foldsTotal = 1
66
+ else:
67
+ foldsTotal = A005316(2 * n - 1)
68
+ return foldsTotal
69
+
70
+ def A060206(n: int) -> int:
71
+ return A000682(2 * n + 1)
72
+
73
+ def A077460(n: int) -> int:
74
+ """Formulas.
75
+
76
+ a[0] = a[1] = 1;
77
+ a[n_] := If[OddQ[n], (A005316[[n + 1]] + A005316[[2n]] + A000682[[n]])/4
78
+ a(2n+1) = (A005315(2n+1) + A005316(2n+1) + A060206(n)) / 4.
79
+
80
+ a(2n) = (A005315(2n) + 2 * A005316(2n)) / 4.
81
+ (A005316[[2n]] + 2 A005316[[n + 1]])/4];
82
+
83
+ """
84
+ if n in {0, 1}:
85
+ foldsTotal = 1
86
+ elif n & 0b1:
87
+ foldsTotal = (A005315(n) + A005316(n) + A060206((n - 1) // 2)) // 4
88
+ else:
89
+ foldsTotal = (A005315(n) + 2 * A005316(n)) // 4
90
+
91
+ return foldsTotal
92
+
93
+ def A078591(n: int) -> int:
94
+ return A005315(n) // 2
95
+
96
+ def A178961(n: int) -> int:
97
+ from mapFolding.oeis import dictionaryOEISMeanders # noqa: PLC0415
98
+ A001010valuesKnown: dict[int, int] = dictionaryOEISMeanders['A001010']['valuesKnown']
99
+ foldsTotal: int = 0
100
+ for n下i in range(1, n+1):
101
+ foldsTotal += A001010valuesKnown[n下i]
102
+ return foldsTotal
103
+
104
+ def A223094(n: int) -> int:
105
+ return A000136(n) - A000682(n + 1)
106
+ # TODO A223094 For n >= 3: a(n) = n! - Sum_{k=3..n-1} (a(k)*n!/k!) - A000682(n+1). - _Roger Ford_, Aug 24 2024
107
+
108
+ def A259702(n: int) -> int:
109
+ return A000682(n) // 2 - A000682(n - 1)
110
+
111
+ def A301620(n: int) -> int:
112
+ return A000682(n + 2) - 2 * A000682(n + 1)
113
+ # TODO A301620 a(n) = Sum_{k=3..floor((n+3)/2)} (A259689(n+1,k)*(k-2)). - _Roger Ford_, Dec 10 2018
mapFolding/basecamp.py CHANGED
@@ -8,6 +8,58 @@ from os import PathLike
8
8
  from pathlib import PurePath
9
9
  import contextlib
10
10
 
11
+ """TODO new flow paradigm, incomplete
12
+
13
+ algorithms directory
14
+ manually coded algorithms or formulas
15
+ countFolds will be a stable interface for multidimensional map folding, including synthetic modules
16
+ This has special treatment because people may want to call mapShape not defined in OEIS
17
+ countMeanders will be a stable interface for meanders
18
+ This has special treatment because people may want to call meanders not defined in OEIS
19
+ an enhanced version of oeisIDfor_n will be a stable interface for calling by ID and n
20
+
21
+ General flow structure
22
+ doTheNeedful
23
+ specific to that version of that algorithm
24
+ abstracts the API for that algorithm, so that algorithm (such as multidimensional map folding) has a stable interface
25
+ The last place to do defensive programming
26
+
27
+ - Incomplete: how to count
28
+ - currently in parameters computationDivisions, CPUlimit, and flow
29
+
30
+ - Flow in count______
31
+ - DEFENSIVE PROGRAMMING
32
+ - FAIL EARLY
33
+ - Implement "common foundational logic".
34
+ - IDK what the correct technical term is, but I'm sure other people have researched excellent ways to do this.
35
+ - Example: in `countFolds`, every possible flow path needs `mapShape`. Therefore, `mapShape` is foundational logic that
36
+ all flow paths have in common: "common foundational logic".
37
+ - Example: in `countFolds`, some flow paths have more than one "task division" (i.e., the computation is divided into
38
+ multiple tasks), while other flow paths only have one task division. One reasonable perspective is that computing task
39
+ divisions is NOT "common foundational logic". My perspective for this example: to compute whether or not there are
40
+ task divisions and if so, how many task divisions is identical for all flow paths. Therefore, I handle computing task
41
+ divisions as "common foundational logic".
42
+ - Incomplete
43
+ - Initialize memorialization instructions, if asked
44
+ - MORE DEFENSIVE PROGRAMMING
45
+ - FAIL EARLIER THAN EARLY
46
+ - Incomplete
47
+ - DEFENSIVE PROGRAMMING ON BEHALF of downstream modules and functions
48
+ - FAIL SO EARLY IT IS BEFORE THE USER INSTALLS THE APP
49
+ - Incomplete
50
+ - REPEAT MANY OR ALL OF THE DEFENSIVE PROGRAMMING YOU HAVE ALREADY DONE
51
+
52
+ - Incomplete
53
+ - Pass control to the correct `doTheNeedful`
54
+ - I don't know how to "elegantly" pass control without putting `doTheNeedful` over `count______` in the stack, therefore,
55
+ control will come back here.
56
+ - DO NOT, for the love of puppies and cookies, DO NOT use defensive programming here. Defensive programming AFTER a
57
+ four-week-long computation is a tacit admission of incompetent programming.
58
+ - Follow memorialization instructions: which means pass control to a function will tenaciously follow the instructions.
59
+ - return "a(n)" (as OEIS calls it), such as foldsTotal
60
+
61
+ """
62
+
11
63
  def countFolds(listDimensions: Sequence[int] | None = None
12
64
  , pathLikeWriteFoldsTotal: PathLike[str] | PurePath | None = None
13
65
  , computationDivisions: int | str | None = None
@@ -93,9 +145,9 @@ def countFolds(listDimensions: Sequence[int] | None = None
93
145
  pass
94
146
  else:
95
147
  if oeisID and oeis_n:
96
- from mapFolding.oeis import dictionaryOEIS # noqa: PLC0415
148
+ from mapFolding.oeis import dictionaryOEISMapFolding # noqa: PLC0415
97
149
  with contextlib.suppress(KeyError):
98
- mapShape = dictionaryOEIS[oeisID]['getMapShape'](oeis_n)
150
+ mapShape = dictionaryOEISMapFolding[oeisID]['getMapShape'](oeis_n)
99
151
  if not mapShape and listDimensions:
100
152
  mapShape = validateListDimensions(listDimensions)
101
153
 
@@ -196,7 +248,7 @@ def countFolds(listDimensions: Sequence[int] | None = None
196
248
  from mapFolding.dataBaskets import MapFoldingState # noqa: PLC0415
197
249
  mapFoldingState: MapFoldingState = MapFoldingState(mapShape)
198
250
 
199
- from mapFolding.daoOfMapFolding import doTheNeedful # noqa: PLC0415
251
+ from mapFolding.algorithms.daoOfMapFolding import doTheNeedful # noqa: PLC0415
200
252
  mapFoldingState = doTheNeedful(mapFoldingState)
201
253
  foldsTotal = mapFoldingState.foldsTotal
202
254
 
mapFolding/oeis.py CHANGED
@@ -24,41 +24,20 @@ redundant computation, or extending mathematical knowledge, this integration
24
24
  completes the journey from configuration foundation to mathematical discovery.
25
25
  """
26
26
 
27
- from collections.abc import Callable
28
27
  from datetime import datetime, timedelta, UTC
29
28
  from hunterMakesPy import writeStringToHere
30
29
  from itertools import chain
31
- from mapFolding import countFolds
32
- from mapFolding._theSSOT import cacheDays, pathCache, settingsOEISManuallySelected
30
+ from mapFolding import countFolds, MetadataOEISidMapFolding, MetadataOEISidMeanders, packageSettings
31
+ from mapFolding._theSSOT import pathCache
33
32
  from pathlib import Path
34
- from typing import Final, TypedDict
33
+ from typing import Final
35
34
  from urllib.request import urlopen
36
35
  import argparse
37
36
  import sys
38
37
  import time
39
38
  import warnings
40
39
 
41
- class MetadataOEISid(TypedDict):
42
- """Settings for an implemented OEIS sequence."""
43
-
44
- description: str
45
- """The OEIS.org description of the integer sequence."""
46
- getMapShape: Callable[[int], tuple[int, ...]]
47
- """Function to convert the OEIS sequence index, 'n', to its `mapShape` tuple."""
48
- offset: int
49
- """The starting index, 'n', of the sequence, typically 0 or 1."""
50
- valuesBenchmark: list[int]
51
- """List of index values, 'n', to use when benchmarking the algorithm performance."""
52
- valuesKnown: dict[int, int]
53
- """Dictionary of sequence indices, 'n', to their known values, `foldsTotal`."""
54
- valuesTestParallelization: list[int]
55
- """List of index values, 'n', to use when testing parallelization performance."""
56
- valuesTestValidation: list[int]
57
- """List of index values, 'n', to use when testing validation performance."""
58
- valueUnknown: int
59
- """The smallest value of 'n' for for which `foldsTotal` is unknown."""
60
-
61
- oeisIDsImplemented: Final[list[str]] = sorted([oeisID.upper().strip() for oeisID in settingsOEISManuallySelected])
40
+ oeisIDsImplemented: Final[list[str]] = sorted([oeisID.upper().strip() for oeisID in packageSettings.OEISidMapFoldingManuallySet])
62
41
  """Directly implemented OEIS IDs; standardized, e.g., 'A001415'."""
63
42
 
64
43
  def _standardizeOEISid(oeisID: str) -> str:
@@ -134,13 +113,7 @@ def _parseBFileOEIS(OEISbFile: str) -> dict[int, int]:
134
113
  return OEISsequence
135
114
 
136
115
  def _getOEISofficial(pathFilenameCache: Path, url: str) -> None | str:
137
- """Retrieve OEIS sequence data from cache or online source with intelligent caching.
138
-
139
- (AI generated docstring)
140
-
141
- This function implements a caching strategy that prioritizes local cached data when it exists and
142
- has not expired. Fresh data is retrieved from the OEIS website when the cache is stale or missing,
143
- and the cache is updated for future use.
116
+ """Retrieve OEIS ID data from oeis.org or local cache.
144
117
 
145
118
  Parameters
146
119
  ----------
@@ -154,16 +127,11 @@ def _getOEISofficial(pathFilenameCache: Path, url: str) -> None | str:
154
127
  oeisInformation : str | None
155
128
  The retrieved OEIS sequence information as a string, or `None` if retrieval failed.
156
129
 
157
- Notes
158
- -----
159
- Cache expiration is controlled by the module-level `cacheDays` variable. The function validates
160
- URL schemes and issues warnings for failed retrievals.
161
-
162
130
  """
163
131
  tryCache: bool = False
164
132
  if pathFilenameCache.exists():
165
133
  fileAge: timedelta = datetime.now(tz=UTC) - datetime.fromtimestamp(pathFilenameCache.stat().st_mtime, tz=UTC)
166
- tryCache = fileAge < timedelta(days=cacheDays)
134
+ tryCache = fileAge < timedelta(days=packageSettings.cacheDays)
167
135
 
168
136
  oeisInformation: str | None = None
169
137
  if tryCache:
@@ -176,7 +144,8 @@ def _getOEISofficial(pathFilenameCache: Path, url: str) -> None | str:
176
144
  if not url.startswith(("http:", "https:")):
177
145
  message = "URL must start with 'http:' or 'https:'"
178
146
  raise ValueError(message)
179
- with urlopen(url) as response:
147
+
148
+ with urlopen(url) as response: # noqa: S310
180
149
  oeisInformationRaw = response.read().decode('utf-8')
181
150
  oeisInformation = str(oeisInformationRaw)
182
151
  writeStringToHere(oeisInformation, pathFilenameCache)
@@ -279,7 +248,7 @@ def getOEISidInformation(oeisID: str) -> tuple[str, int]:
279
248
  description: str = ' '.join(listDescriptionDeconstructed)
280
249
  return description, offset
281
250
 
282
- def _makeDictionaryOEIS() -> dict[str, MetadataOEISid]:
251
+ def _makeDictionaryOEIS() -> dict[str, MetadataOEISidMapFolding]:
283
252
  """Construct the comprehensive settings dictionary for all implemented OEIS sequences.
284
253
 
285
254
  (AI generated docstring)
@@ -302,23 +271,23 @@ def _makeDictionaryOEIS() -> dict[str, MetadataOEISid]:
302
271
  objects, containing all metadata and known values needed for computation and validation.
303
272
 
304
273
  """
305
- dictionaryOEIS: dict[str, MetadataOEISid] = {}
274
+ dictionaryOEIS: dict[str, MetadataOEISidMapFolding] = {}
306
275
  for oeisID in oeisIDsImplemented:
307
276
  valuesKnownSherpa: dict[int, int] = getOEISidValues(oeisID)
308
277
  descriptionSherpa, offsetSherpa = getOEISidInformation(oeisID)
309
- dictionaryOEIS[oeisID] = MetadataOEISid(
278
+ dictionaryOEIS[oeisID] = MetadataOEISidMapFolding(
310
279
  description=descriptionSherpa,
311
280
  offset=offsetSherpa,
312
- getMapShape=settingsOEISManuallySelected[oeisID]['getMapShape'],
313
- valuesBenchmark=settingsOEISManuallySelected[oeisID]['valuesBenchmark'],
314
- valuesTestParallelization=settingsOEISManuallySelected[oeisID]['valuesTestParallelization'],
315
- valuesTestValidation=settingsOEISManuallySelected[oeisID]['valuesTestValidation'] + list(range(offsetSherpa, 2)),
281
+ getMapShape=packageSettings.OEISidMapFoldingManuallySet[oeisID]['getMapShape'],
282
+ valuesBenchmark=packageSettings.OEISidMapFoldingManuallySet[oeisID]['valuesBenchmark'],
283
+ valuesTestParallelization=packageSettings.OEISidMapFoldingManuallySet[oeisID]['valuesTestParallelization'],
284
+ valuesTestValidation=packageSettings.OEISidMapFoldingManuallySet[oeisID]['valuesTestValidation'] + list(range(offsetSherpa, 2)),
316
285
  valuesKnown=valuesKnownSherpa,
317
286
  valueUnknown=max(valuesKnownSherpa.keys(), default=0) + 1
318
287
  )
319
288
  return dictionaryOEIS
320
289
 
321
- dictionaryOEIS: dict[str, MetadataOEISid] = _makeDictionaryOEIS()
290
+ dictionaryOEISMapFolding: dict[str, MetadataOEISidMapFolding] = _makeDictionaryOEIS()
322
291
  """Metadata for each OEIS sequence ID."""
323
292
 
324
293
  def makeDictionaryFoldsTotalKnown() -> dict[tuple[int, ...], int]:
@@ -332,7 +301,7 @@ def makeDictionaryFoldsTotalKnown() -> dict[tuple[int, ...], int]:
332
301
 
333
302
  """
334
303
  return dict(chain.from_iterable(zip(map(oeisIDmetadata['getMapShape'], oeisIDmetadata['valuesKnown'].keys())
335
- , oeisIDmetadata['valuesKnown'].values(), strict=True) for oeisID, oeisIDmetadata in dictionaryOEIS.items() if oeisID != 'A007822'))
304
+ , oeisIDmetadata['valuesKnown'].values(), strict=True) for oeisID, oeisIDmetadata in dictionaryOEISMapFolding.items() if oeisID != 'A007822'))
336
305
 
337
306
  def getFoldsTotalKnown(mapShape: tuple[int, ...]) -> int:
338
307
  """Retrieve the known total number of distinct folding patterns for a given map shape.
@@ -378,7 +347,7 @@ def _formatHelpText() -> str:
378
347
 
379
348
  """
380
349
  exampleOEISid: str = oeisIDsImplemented[0]
381
- exampleN: int = dictionaryOEIS[exampleOEISid]['valuesTestValidation'][-1]
350
+ exampleN: int = dictionaryOEISMapFolding[exampleOEISid]['valuesTestValidation'][-1]
382
351
 
383
352
  return (
384
353
  "\nAvailable OEIS sequences:\n"
@@ -406,7 +375,7 @@ def _formatOEISsequenceInfo() -> str:
406
375
 
407
376
  """
408
377
  return "\n".join(
409
- f" {oeisID}: {dictionaryOEIS[oeisID]['description']}"
378
+ f" {oeisID}: {dictionaryOEISMapFolding[oeisID]['description']}"
410
379
  for oeisID in oeisIDsImplemented
411
380
  )
412
381
 
@@ -441,14 +410,14 @@ def oeisIDfor_n(oeisID: str, n: int) -> int:
441
410
  message = f"I received `{n = }` in the form of `{type(n) = }`, but it must be non-negative integer in the form of `{int}`."
442
411
  raise ValueError(message)
443
412
 
444
- mapShape = dictionaryOEIS[oeisID]['getMapShape'](n)
413
+ mapShape = dictionaryOEISMapFolding[oeisID]['getMapShape'](n)
445
414
 
446
415
  if n <= 1 or len(mapShape) < 2:
447
- offset: int = dictionaryOEIS[oeisID]['offset']
416
+ offset: int = dictionaryOEISMapFolding[oeisID]['offset']
448
417
  if n < offset:
449
418
  message = f"OEIS sequence {oeisID} is not defined at {n = }."
450
419
  raise ArithmeticError(message)
451
- foldsTotal: int = dictionaryOEIS[oeisID]['valuesKnown'][n]
420
+ foldsTotal: int = dictionaryOEISMapFolding[oeisID]['valuesKnown'][n]
452
421
  return foldsTotal
453
422
 
454
423
  return countFolds(mapShape, oeisID=oeisID)
@@ -513,7 +482,7 @@ def clearOEIScache() -> None:
513
482
  if not pathCache.exists():
514
483
  print(f"Cache directory, {pathCache}, not found - nothing to clear.") # noqa: T201
515
484
  return
516
- for oeisID in dictionaryOEIS:
485
+ for oeisID in dictionaryOEISMapFolding:
517
486
  ( pathCache / f"{oeisID}.txt" ).unlink(missing_ok=True)
518
487
  ( pathCache / _getFilenameOEISbFile(oeisID) ).unlink(missing_ok=True)
519
488
  print(f"Cache cleared from {pathCache}") # noqa: T201
@@ -534,5 +503,22 @@ def getOEISids() -> None:
534
503
  """
535
504
  print(_formatHelpText()) # noqa: T201
536
505
 
506
+ def _makeDictionaryOEISMeanders() -> dict[str, MetadataOEISidMeanders]:
507
+ dictionary: dict[str, MetadataOEISidMeanders] = {}
508
+ for oeisID in packageSettings.OEISidMeandersManuallySet:
509
+ valuesKnownSherpa: dict[int, int] = getOEISidValues(oeisID)
510
+ descriptionSherpa, offsetSherpa = getOEISidInformation(oeisID)
511
+ dictionary[oeisID] = MetadataOEISidMeanders(
512
+ description=descriptionSherpa,
513
+ offset=offsetSherpa,
514
+ valuesKnown=valuesKnownSherpa,
515
+ valuesTestValidation=packageSettings.OEISidMeandersManuallySet[oeisID]['valuesTestValidation'],
516
+ valueUnknown=max(valuesKnownSherpa.keys(), default=0) + 1,
517
+ )
518
+ return dictionary
519
+
520
+ dictionaryOEISMeanders: dict[str, MetadataOEISidMeanders] = _makeDictionaryOEISMeanders()
521
+
537
522
  if __name__ == "__main__":
538
523
  getOEISids()
524
+
@@ -15,7 +15,6 @@ def make1array(listArrays: list[numpy.ndarray[tuple[int, ...], numpy.dtype[numpy
15
15
  , (arrayCurveLocations & numpy.uint64(0xaaaaaaaaaaaaaaaa)) >> numpy.uint64(1)
16
16
  , arrayCurveLocations
17
17
  ))
18
-
19
18
  for arrayCurveLocations in listArrays:
20
19
  arrayOut[:, indexDistinctCrossings] += numpy.sum(arrayCurveLocations[:, 0] * (arrayCurveLocations[:, -1][:, numpy.newaxis] == arrayOut[:, indexCurveLocations]).T, axis=1)
21
20
 
@@ -42,31 +41,39 @@ def count(bridges: int, startingCurveLocations: dict[int, int]) -> int:
42
41
  # Selector-adjacent
43
42
  curveLocationsMAXIMUM: numpy.uint64 = numpy.uint64(1) << numpy.uint64(2 * bridges + 4)
44
43
  # Selectors, general
45
- selectBifurcationAlphaCurves: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = arrayBifurcations[:, indexBifurcationAlpha] > numpy.uint64(1)
44
+ selectBifurcationAlphaCurves: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = arrayBifurcations[:, indexBifurcationAlpha] != numpy.uint64(1)
46
45
  selectBifurcationAlphaEven: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = (arrayBifurcations[:, indexBifurcationAlpha] & numpy.uint64(1)) == numpy.uint64(0)
47
- selectBifurcationZuluCurves: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = arrayBifurcations[:, indexBifurcationZulu] > numpy.uint64(1)
46
+ selectBifurcationZuluCurves: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = arrayBifurcations[:, indexBifurcationZulu] != numpy.uint64(1)
48
47
  selectBifurcationZuluEven: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = (arrayBifurcations[:, indexBifurcationZulu] & numpy.uint64(1)) == numpy.uint64(0)
49
48
 
50
- # BridgesSimple
49
+ # bridgesSimple
51
50
  selector: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = arrayBifurcations[:, indexDistinctCrossings] >= numpy.uint64(0) # This had better always be `True`.
52
51
  curveLocations: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64]] = (((arrayBifurcations[selector, indexBifurcationAlpha] | (arrayBifurcations[selector, indexBifurcationZulu] << numpy.uint64(1))) << numpy.uint64(2)) | numpy.uint64(3))
53
52
  listArrayCurveLocationsAnalyzed.append(numpy.column_stack((arrayBifurcations[selector, indexDistinctCrossings][curveLocations < curveLocationsMAXIMUM], curveLocations[curveLocations < curveLocationsMAXIMUM])))
54
53
 
55
- # BifurcationAlphaCurves
56
- selector = selectBifurcationAlphaCurves
57
- curveLocations: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64]] = numpy.bitwise_or.reduce((
58
- arrayBifurcations[selector, indexBifurcationAlpha] >> numpy.uint64(2)
59
- , arrayBifurcations[selector, indexBifurcationZulu] << numpy.uint64(3)
60
- , (numpy.uint64(1) - (arrayBifurcations[selector, indexBifurcationAlpha] & numpy.uint64(1))) << numpy.uint64(1)
54
+ # bifurcationAlphaCurves
55
+ this = numpy.bitwise_or.reduce((
56
+ arrayBifurcations[arrayBifurcations[:, indexBifurcationAlpha] != numpy.uint64(1), indexBifurcationAlpha] >> numpy.uint64(2)
57
+ , arrayBifurcations[arrayBifurcations[:, indexBifurcationAlpha] != numpy.uint64(1), indexBifurcationZulu] << numpy.uint64(3)
58
+ , (numpy.uint64(1) - (arrayBifurcations[arrayBifurcations[:, indexBifurcationAlpha] != numpy.uint64(1), indexBifurcationAlpha] & numpy.uint64(1))) << numpy.uint64(1)
61
59
  ))
62
- listArrayCurveLocationsAnalyzed.append(numpy.column_stack((arrayBifurcations[selector, indexDistinctCrossings][curveLocations < curveLocationsMAXIMUM], curveLocations[curveLocations < curveLocationsMAXIMUM])))
60
+ curveLocations: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64]] = numpy.where(this < curveLocationsMAXIMUM, this, numpy.uint64(0))
61
+ # print(curveLocations.astype(numpy.bool_))
62
+ print(curveLocations)
63
+ distinctCrossings = arrayBifurcations[arrayBifurcations[:, indexBifurcationAlpha] != numpy.uint64(1), indexDistinctCrossings]
64
+ print(distinctCrossings)
65
+ listArrayCurveLocationsAnalyzed.append(
66
+ numpy.column_stack((distinctCrossings, curveLocations))
67
+ )
68
+ # print(arrayBifurcations)
69
+ # print(listArrayCurveLocationsAnalyzed[-1])
63
70
 
64
- # BifurcationZuluCurves
71
+ # bifurcationZuluCurves
65
72
  selector = selectBifurcationZuluCurves
66
73
  curveLocations: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64]] = numpy.bitwise_or.reduce((
67
74
  arrayBifurcations[selector, indexBifurcationZulu] >> numpy.uint64(1)
68
75
  , arrayBifurcations[selector, indexBifurcationAlpha] << numpy.uint64(2)
69
- , (1 - (arrayBifurcations[selector, indexBifurcationZulu] & numpy.uint64(1)))
76
+ , (numpy.uint64(1) - (arrayBifurcations[selector, indexBifurcationZulu] & numpy.uint64(1)))
70
77
  ))
71
78
  listArrayCurveLocationsAnalyzed.append(numpy.column_stack((arrayBifurcations[selector, indexDistinctCrossings][curveLocations < curveLocationsMAXIMUM], curveLocations[curveLocations < curveLocationsMAXIMUM])))
72
79
 
@@ -75,24 +82,24 @@ def count(bridges: int, startingCurveLocations: dict[int, int]) -> int:
75
82
  selectBifurcationAlphaCurves, selectBifurcationZuluCurves, selectBifurcationAlphaEven, ~selectBifurcationZuluEven
76
83
  ))
77
84
 
78
- # Initialize
79
- Z0Z_selectBridgesBifurcationAlphaToModify = selector.copy()
85
+ # Initialize
80
86
  XOrHere2makePair = numpy.uint64(1)
81
- selectToModifyByXOR: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.array([])
82
- selectorUnified: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.array([])
83
87
 
84
- while Z0Z_selectBridgesBifurcationAlphaToModify.any():
88
+ while selector.any():
85
89
  XOrHere2makePair <<= numpy.uint64(2)
86
90
 
87
- selectToModifyByXOR: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = (arrayBifurcations[:, indexBifurcationAlpha] & XOrHere2makePair) == numpy.uint64(0)
88
- selectorUnified: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((Z0Z_selectBridgesBifurcationAlphaToModify, selectToModifyByXOR))
91
+ selectUnpaired_0b1: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = (arrayBifurcations[:, indexBifurcationAlpha] & XOrHere2makePair) == numpy.uint64(0)
92
+ selectorUnified: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((selector, selectUnpaired_0b1))
89
93
 
90
94
  # Modify in place
91
95
  arrayBifurcations[selectorUnified, indexBifurcationAlpha] ^= XOrHere2makePair
92
96
 
93
97
  # Remove the modified elements
94
- Z0Z_selectBridgesBifurcationAlphaToModify: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((Z0Z_selectBridgesBifurcationAlphaToModify, ~selectorUnified))
98
+ selector: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((selector, ~selectorUnified))
95
99
 
100
+ selector: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((
101
+ selectBifurcationAlphaCurves, selectBifurcationZuluCurves, selectBifurcationAlphaEven, ~selectBifurcationZuluEven
102
+ ))
96
103
  curveLocations: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64]] = (
97
104
  ((arrayBifurcations[selector, indexBifurcationZulu] >> numpy.uint64(2)) << numpy.uint64(1))
98
105
  | (arrayBifurcations[selector, indexBifurcationAlpha] >> numpy.uint64(2))
@@ -105,24 +112,25 @@ def count(bridges: int, startingCurveLocations: dict[int, int]) -> int:
105
112
  selectBifurcationAlphaCurves, selectBifurcationZuluCurves, ~selectBifurcationAlphaEven, selectBifurcationZuluEven
106
113
  ))
107
114
 
108
- # Initialize
109
- Z0Z_selectBridgesBifurcationZuluToModify: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = selector.copy()
115
+ # Initialize
110
116
  XOrHere2makePair: numpy.uint64 = numpy.uint64(1)
111
- selectToModifyByXOR: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.array([])
112
- selectorUnified: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.array([])
113
117
 
114
- while Z0Z_selectBridgesBifurcationZuluToModify.any():
118
+ while selector.any():
115
119
  XOrHere2makePair <<= numpy.uint64(2)
116
120
 
117
121
  # New condition
118
122
  selectUnpaired_0b1: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = (arrayBifurcations[:, indexBifurcationZulu] & XOrHere2makePair) == numpy.uint64(0)
119
- selectorUnified: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((Z0Z_selectBridgesBifurcationZuluToModify, selectUnpaired_0b1))
123
+ selectorUnified: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((selector, selectUnpaired_0b1))
120
124
 
121
125
  # Modify in place
122
126
  arrayBifurcations[selectorUnified, indexBifurcationZulu] ^= XOrHere2makePair
123
127
 
124
128
  # Remove the modified elements from the selector
125
- Z0Z_selectBridgesBifurcationZuluToModify: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((Z0Z_selectBridgesBifurcationZuluToModify, ~selectorUnified))
129
+ selector: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((selector, ~selectorUnified))
130
+
131
+ selector: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]] = numpy.logical_and.reduce((
132
+ selectBifurcationAlphaCurves, selectBifurcationZuluCurves, ~selectBifurcationAlphaEven, selectBifurcationZuluEven
133
+ ))
126
134
 
127
135
  curveLocations: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64]] = (
128
136
  ((arrayBifurcations[selector, indexBifurcationZulu] >> numpy.uint64(2)) << numpy.uint64(1))
@@ -147,6 +155,6 @@ def count(bridges: int, startingCurveLocations: dict[int, int]) -> int:
147
155
 
148
156
  listArrayCurveLocationsAnalyzed.clear()
149
157
 
150
- print(int(sum(arrayBifurcations[:, 0])))
158
+ # print(int(sum(arrayBifurcations[:, 0])))
151
159
  return int(sum(arrayBifurcations[:, 0]))
152
160
 
@@ -711,16 +711,16 @@ def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
711
711
  return pathFilename
712
712
 
713
713
  if __name__ == '__main__':
714
- astModule = _getModule(logicalPathInfix=None)
714
+ astModule = _getModule(logicalPathInfix='algorithms')
715
715
  pathFilename: PurePath = makeDaoOfMapFoldingNumba(astModule, 'daoOfMapFoldingNumba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
716
716
 
717
- astModule = _getModule(logicalPathInfix=None)
717
+ astModule = _getModule(logicalPathInfix='algorithms')
718
718
  pathFilename = makeDaoOfMapFoldingParallelNumba(astModule, 'countParallelNumba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
719
719
 
720
- astModule: ast.Module = _getModule(logicalPathInfix=None)
720
+ astModule: ast.Module = _getModule(logicalPathInfix='algorithms')
721
721
  makeInitializeState(astModule, 'initializeState', 'transitionOnGroupsOfFolds', logicalPathInfixDEFAULT)
722
722
 
723
- astModule = _getModule(logicalPathInfix=None)
723
+ astModule = _getModule(logicalPathInfix='algorithms')
724
724
  pathFilename = makeTheorem2(astModule, 'theorem2', None, logicalPathInfixDEFAULT, None)
725
725
 
726
726
  astModule = parsePathFilename2astModule(pathFilename)
@@ -733,7 +733,7 @@ if __name__ == '__main__':
733
733
  makeUnRePackDataclass(astImportFrom)
734
734
 
735
735
  # A007822 -----------------------------------------------------------
736
- astModule = _getModule(logicalPathInfix=None)
736
+ astModule = _getModule(logicalPathInfix='algorithms')
737
737
  pathFilename = addSymmetryCheck(astModule, 'algorithmA007822', None, logicalPathInfixDEFAULT, None)
738
738
 
739
739
  astModule = _getModule(moduleIdentifier='algorithmA007822')
@@ -1,4 +1,6 @@
1
- from mapFolding.dataBaskets import Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal, MapFoldingState
1
+ from mapFolding.dataBaskets import (
2
+ Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal,
3
+ MapFoldingState)
2
4
  from numba import jit
3
5
 
4
6
  @jit(cache=True, error_model='numpy', fastmath=True, forceinline=True)
@@ -92,4 +94,4 @@ def doTheNeedful(state: MapFoldingState) -> MapFoldingState:
92
94
  leavesTotal: DatatypeLeavesTotal = state.leavesTotal
93
95
  groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, leavesTotal = count(groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, leavesTotal)
94
96
  state = MapFoldingState(mapShape=mapShape, groupsOfFolds=groupsOfFolds, gap1ndex=gap1ndex, gap1ndexCeiling=gap1ndexCeiling, indexDimension=indexDimension, indexLeaf=indexLeaf, indexMiniGap=indexMiniGap, leaf1ndex=leaf1ndex, leafConnectee=leafConnectee, dimensionsUnconstrained=dimensionsUnconstrained, countDimensionsGapped=countDimensionsGapped, gapRangeStart=gapRangeStart, gapsWhere=gapsWhere, leafAbove=leafAbove, leafBelow=leafBelow, leafComparison=leafComparison)
95
- return state
97
+ return state
@@ -25,7 +25,7 @@ research domain.
25
25
 
26
26
  from collections.abc import Callable, Generator, Sequence
27
27
  from mapFolding import _theSSOT, getLeavesTotal, makeDataContainer, packageSettings, validateListDimensions
28
- from mapFolding.oeis import dictionaryOEIS, oeisIDsImplemented
28
+ from mapFolding.oeis import dictionaryOEISMapFolding, dictionaryOEISMeanders, oeisIDsImplemented
29
29
  from pathlib import Path
30
30
  from typing import Any
31
31
  import numpy
@@ -212,10 +212,10 @@ def oneTestCuzTestsOverwritingTests(oeisID_1random: str) -> tuple[int, ...]:
212
212
 
213
213
  """
214
214
  while True:
215
- n = random.choice(dictionaryOEIS[oeisID_1random]['valuesTestValidation'])
215
+ n = random.choice(dictionaryOEISMapFolding[oeisID_1random]['valuesTestValidation'])
216
216
  if n < 2:
217
217
  continue
218
- listDimensionsCandidate = list(dictionaryOEIS[oeisID_1random]['getMapShape'](n))
218
+ listDimensionsCandidate = list(dictionaryOEISMapFolding[oeisID_1random]['getMapShape'](n))
219
219
 
220
220
  try:
221
221
  return validateListDimensions(listDimensionsCandidate)
@@ -239,10 +239,10 @@ def mapShapeTestCountFolds(oeisID: str) -> tuple[int, ...]:
239
239
 
240
240
  """
241
241
  while True:
242
- n = random.choice(dictionaryOEIS[oeisID]['valuesTestValidation'])
242
+ n = random.choice(dictionaryOEISMapFolding[oeisID]['valuesTestValidation'])
243
243
  if n < 2:
244
244
  continue
245
- listDimensionsCandidate = list(dictionaryOEIS[oeisID]['getMapShape'](n))
245
+ listDimensionsCandidate = list(dictionaryOEISMapFolding[oeisID]['getMapShape'](n))
246
246
 
247
247
  try:
248
248
  return validateListDimensions(listDimensionsCandidate)
@@ -267,10 +267,10 @@ def mapShapeTestFunctionality(oeisID_1random: str) -> tuple[int, ...]:
267
267
 
268
268
  """
269
269
  while True:
270
- n = random.choice(dictionaryOEIS[oeisID_1random]['valuesTestValidation'])
270
+ n = random.choice(dictionaryOEISMapFolding[oeisID_1random]['valuesTestValidation'])
271
271
  if n < 2:
272
272
  continue
273
- listDimensionsCandidate = list(dictionaryOEIS[oeisID_1random]['getMapShape'](n))
273
+ listDimensionsCandidate = list(dictionaryOEISMapFolding[oeisID_1random]['getMapShape'](n))
274
274
 
275
275
  try:
276
276
  return validateListDimensions(listDimensionsCandidate)
@@ -292,8 +292,8 @@ def mapShapeTestParallelization(oeisID: str) -> tuple[int, ...]:
292
292
  Map dimensions suitable for testing parallelization features.
293
293
 
294
294
  """
295
- n = random.choice(dictionaryOEIS[oeisID]['valuesTestParallelization'])
296
- return dictionaryOEIS[oeisID]['getMapShape'](n)
295
+ n = random.choice(dictionaryOEISMapFolding[oeisID]['valuesTestParallelization'])
296
+ return dictionaryOEISMapFolding[oeisID]['getMapShape'](n)
297
297
 
298
298
  @pytest.fixture
299
299
  def mockBenchmarkTimer() -> Generator[unittest.mock.MagicMock | unittest.mock.AsyncMock, Any, None]:
@@ -350,6 +350,25 @@ def oeisID(request: pytest.FixtureRequest) -> Any:
350
350
  """
351
351
  return request.param
352
352
 
353
+ @pytest.fixture(params=tuple(dictionaryOEISMeanders.keys()))
354
+ def oeisIDMeanders(request: pytest.FixtureRequest) -> Any:
355
+ """Parametrized fixture providing all implemented Meanders OEIS sequence identifiers.
356
+
357
+ (AI generated docstring)
358
+
359
+ Parameters
360
+ ----------
361
+ request : pytest.FixtureRequest
362
+ The pytest request object containing the current parameter value.
363
+
364
+ Returns
365
+ -------
366
+ sequenceIdentifier : Any
367
+ OEIS sequence identifier for testing across all implemented Meanders sequences.
368
+
369
+ """
370
+ return request.param
371
+
353
372
  @pytest.fixture
354
373
  def oeisID_1random() -> str:
355
374
  """Return one random valid OEIS ID.