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
@@ -37,7 +37,7 @@ class BasicMeanderProblem:
37
37
 
38
38
  return initialStatesList
39
39
 
40
- def enumerate(self, packedState: int) -> list[int]: # noqa: C901
40
+ def enumerate(self, packedState: int) -> list[int]:
41
41
  """Enumerate next states from previous state."""
42
42
  bitMask = ODD_BITS
43
43
  bitWidth = 64
@@ -1,4 +1,4 @@
1
- def count(bridges: int, dictionaryStateToTotal: dict[int, int]) -> int: # noqa: C901, PLR0912
1
+ def count(bridges: int, dictionaryStateToTotal: dict[int, int]) -> int:
2
2
  while bridges > 0:
3
3
  bridges -= 1
4
4
  archStateLimit = 1 << (2 + (2 * (bridges + 1)))
@@ -0,0 +1,424 @@
1
+ # ruff: noqa: D100 D103
2
+ from functools import cache
3
+ from gc import collect as goByeBye, set_threshold
4
+ from typing import Any
5
+ import numpy
6
+
7
+ Z0Z_bit_lengthSafetyLimit: int = 61
8
+
9
+ type DataArray1D = numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64 | numpy.signedinteger[Any]]]
10
+ type DataArray2columns = numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64]]
11
+ type DataArray3columns = numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint64]]
12
+ type SelectorBoolean = numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.bool_]]
13
+ type SelectorIndices = numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.intp]]
14
+
15
+ # NOTE This code blocks enables semantic references to your data.
16
+ columnsArrayCurveGroups = columnsArrayTotal = 3
17
+ columnΩ: int = (columnsArrayTotal - columnsArrayTotal) - 1
18
+ columnDistinctCrossings = columnΩ = columnΩ + 1
19
+ columnGroupAlpha = columnΩ = columnΩ + 1
20
+ columnGroupZulu = columnΩ = columnΩ + 1
21
+ if columnΩ != columnsArrayTotal - 1:
22
+ message = f"Please inspect the code above this `if` check. '{columnsArrayTotal = }', therefore '{columnΩ = }' must be '{columnsArrayTotal - 1 = }' due to 'zero-indexing.'"
23
+ raise ValueError(message)
24
+ del columnsArrayTotal, columnΩ
25
+
26
+ columnsArrayCurveLocations = columnsArrayTotal = 2
27
+ columnΩ: int = (columnsArrayTotal - columnsArrayTotal) - 1
28
+ columnDistinctCrossings = columnΩ = columnΩ + 1
29
+ columnCurveLocations = columnΩ = columnΩ + 1
30
+ if columnΩ != columnsArrayTotal - 1:
31
+ message = f"Please inspect the code above this `if` check. '{columnsArrayTotal = }', therefore '{columnΩ = }' must be '{columnsArrayTotal - 1 = }' due to 'zero-indexing.'"
32
+ raise ValueError(message)
33
+ del columnsArrayTotal, columnΩ
34
+
35
+ groupAlphaLocator: int = 0x55555555555555555555555555555555
36
+ groupAlphaLocator64: int = 0x5555555555555555
37
+ groupZuluLocator: int = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
38
+ groupZuluLocator64: int = 0xaaaaaaaaaaaaaaaa
39
+
40
+ def convertDictionaryCurveLocations2CurveGroups(dictionaryCurveLocations: dict[int, int]) -> dict[tuple[int, int], int]:
41
+ return {(curveLocations & groupAlphaLocator, (curveLocations & groupZuluLocator) >> 1): distinctCrossings
42
+ for curveLocations, distinctCrossings in dictionaryCurveLocations.items()}
43
+
44
+ @cache
45
+ def walkDyckPath(intWithExtra_0b1: int) -> int:
46
+ """NOTE `gc.set_threshold`: Low numbers nullify the `walkDyckPath` cache."""
47
+ findTheExtra_0b1: int = 0
48
+ flipExtra_0b1_Here: int = 1
49
+ while True:
50
+ flipExtra_0b1_Here <<= 2
51
+ if (intWithExtra_0b1 & flipExtra_0b1_Here) == 0:
52
+ findTheExtra_0b1 += 1
53
+ else:
54
+ findTheExtra_0b1 -= 1
55
+ if findTheExtra_0b1 < 0:
56
+ break
57
+ return flipExtra_0b1_Here
58
+
59
+ def count(bridges: int, dictionaryCurveGroups: dict[tuple[int, int], int], bridgesMinimum: int = 0) -> tuple[int, dict[tuple[int, int], int]]:
60
+ dictionaryCurveLocations: dict[int, int] = {}
61
+ while (bridges > bridgesMinimum):
62
+ bridges -= 1
63
+ curveLocationsMAXIMUM: int = 1 << (2 * bridges + 4)
64
+
65
+ for (groupAlpha, groupZulu), distinctCrossings in dictionaryCurveGroups.items():
66
+ set_threshold(0, 0, 0) # Disable the garbage collector inside this loop to maximize the `walkDyckPath` cache hits.
67
+ groupAlphaCurves: bool = groupAlpha > 1
68
+ groupZuluCurves: bool = groupZulu > 1
69
+ groupAlphaIsEven = groupZuluIsEven = 0
70
+
71
+ # bridgesSimple
72
+ curveLocationAnalysis = ((groupAlpha | (groupZulu << 1)) << 2) | 3
73
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
74
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
75
+
76
+ if groupAlphaCurves:
77
+ curveLocationAnalysis = (groupAlpha >> 2) | (groupZulu << 3) | ((groupAlphaIsEven := 1 - (groupAlpha & 1)) << 1)
78
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
79
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
80
+
81
+ if groupZuluCurves:
82
+ curveLocationAnalysis = (groupZulu >> 1) | (groupAlpha << 2) | (groupZuluIsEven := 1 - (groupZulu & 1))
83
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
84
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
85
+
86
+ # bridgesAligned
87
+ if groupAlphaCurves and groupZuluCurves and (groupAlphaIsEven or groupZuluIsEven):
88
+ if groupAlphaIsEven and not groupZuluIsEven:
89
+ groupAlpha ^= walkDyckPath(groupAlpha) # noqa: PLW2901
90
+ elif groupZuluIsEven and not groupAlphaIsEven:
91
+ groupZulu ^= walkDyckPath(groupZulu) # noqa: PLW2901
92
+
93
+ curveLocationAnalysis: int = ((groupZulu >> 2) << 1) | (groupAlpha >> 2)
94
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
95
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
96
+
97
+ dictionaryCurveGroups = convertDictionaryCurveLocations2CurveGroups(dictionaryCurveLocations)
98
+ dictionaryCurveLocations = {}
99
+ return (bridges, dictionaryCurveGroups)
100
+
101
+ @cache
102
+ def _flipTheExtra_0b1(intWithExtra_0b1: int) -> numpy.uint64:
103
+ return numpy.uint64(intWithExtra_0b1 ^ walkDyckPath(intWithExtra_0b1))
104
+
105
+ flipTheExtra_0b1 = numpy.frompyfunc(_flipTheExtra_0b1, 1, 1)
106
+
107
+ def aggregateCurveLocations2CurveGroups(arrayCurveLocations: DataArray2columns) -> DataArray3columns:
108
+ """Deduplicate `curveLocations` by summing `distinctCrossings`; create curve groups."""
109
+ curveLocations, indices = numpy.unique_inverse(arrayCurveLocations[:, columnCurveLocations])
110
+ arrayCurveGroups: DataArray3columns = numpy.zeros((len(curveLocations), columnsArrayCurveGroups), dtype=numpy.uint64)
111
+ numpy.bitwise_and(curveLocations, groupAlphaLocator64, out=arrayCurveGroups[:, columnGroupAlpha])
112
+ numpy.bitwise_and(curveLocations, groupZuluLocator64, out=arrayCurveGroups[:, columnGroupZulu])
113
+
114
+ curveLocations = None; del curveLocations # noqa: E702
115
+ goByeBye()
116
+
117
+ arrayCurveGroups[:, columnGroupZulu] >>= 1
118
+ numpy.add.at(arrayCurveGroups[:, columnDistinctCrossings], indices, arrayCurveLocations[:, columnDistinctCrossings])
119
+ return arrayCurveGroups
120
+
121
+ def aggregateBridgesSimple2CurveLocations(arrayCurveLocations: DataArray2columns, indexStart: int, curveLocations: DataArray1D, distinctCrossings: DataArray1D) -> int:
122
+ """Deduplicate `curveLocations` by summing `distinctCrossings`."""
123
+ miniCurveLocations, indices = numpy.unique_inverse(curveLocations[numpy.flatnonzero(curveLocations)])
124
+
125
+ indexStop: int = indexStart + int(miniCurveLocations.size)
126
+ arrayCurveLocations[indexStart:indexStop, columnCurveLocations] = miniCurveLocations
127
+
128
+ miniCurveLocations = None; del miniCurveLocations # noqa: E702
129
+ goByeBye()
130
+
131
+ numpy.add.at(arrayCurveLocations[indexStart:indexStop, columnDistinctCrossings], indices, distinctCrossings[numpy.flatnonzero(curveLocations)])
132
+
133
+ return indexStop
134
+
135
+ def aggregateData2CurveLocations(arrayCurveLocations: DataArray2columns, indexStart: int, curveLocations: DataArray1D, distinctCrossings: DataArray1D, selector: SelectorBoolean, limiter: numpy.uint64) -> int:
136
+ """Deduplicate `curveLocations` by summing `distinctCrossings`."""
137
+ miniCurveLocations, indices = numpy.unique_inverse(curveLocations[numpy.flatnonzero(curveLocations < limiter)])
138
+
139
+ indexStop: int = indexStart + int(miniCurveLocations.size)
140
+ arrayCurveLocations[indexStart:indexStop, columnCurveLocations] = miniCurveLocations
141
+
142
+ miniCurveLocations = None; del miniCurveLocations # noqa: E702
143
+ goByeBye()
144
+
145
+ numpy.add.at(arrayCurveLocations[indexStart:indexStop, columnDistinctCrossings], indices, distinctCrossings[numpy.flatnonzero(selector)[numpy.flatnonzero(curveLocations < limiter)]])
146
+
147
+ return indexStop
148
+
149
+ def convertDictionaryCurveGroups2array(dictionaryCurveGroups: dict[tuple[int, int], int]) -> DataArray3columns:
150
+ arrayCurveGroups: DataArray3columns = numpy.tile(numpy.fromiter(dictionaryCurveGroups.values(), dtype=numpy.uint64), (columnsArrayCurveGroups, 1)).T
151
+ arrayCurveGroups[:, columnGroupAlpha:columnGroupZulu+1] = numpy.array(list(dictionaryCurveGroups.keys()), dtype=numpy.uint64)
152
+ return arrayCurveGroups
153
+
154
+ def count64(bridges: int, arrayCurveGroups: DataArray3columns, bridgesMinimum: int = 0) -> tuple[int, DataArray3columns]:
155
+ while bridges > bridgesMinimum and int(arrayCurveGroups[:, columnDistinctCrossings].max()).bit_length() < Z0Z_bit_lengthSafetyLimit:
156
+ bridges -= 1
157
+ curveLocationsMAXIMUM: numpy.uint64 = numpy.uint64(1 << (2 * bridges + 4))
158
+
159
+ set_threshold(1, 1, 1) # Re-enable the garbage collector.
160
+
161
+ allocateGroupAlphaCurves: int = (arrayCurveGroups[:, columnGroupAlpha] > numpy.uint64(1)).sum()
162
+ allocateGroupZuluCurves: int = (arrayCurveGroups[:, columnGroupZulu] > numpy.uint64(1)).sum()
163
+
164
+ selectBridgesAligned: SelectorBoolean = numpy.empty_like(arrayCurveGroups[:, columnGroupAlpha], dtype=bool)
165
+ numpy.equal(numpy.bitwise_and(arrayCurveGroups[:, columnGroupAlpha], 1), 0, out=selectBridgesAligned, dtype=bool)
166
+ numpy.bitwise_or(selectBridgesAligned, (numpy.equal(numpy.bitwise_and(arrayCurveGroups[:, columnGroupZulu], 1), 0, dtype=bool)), out=selectBridgesAligned)
167
+ numpy.bitwise_and(selectBridgesAligned, (arrayCurveGroups[:, columnGroupAlpha] > numpy.uint64(1)), out=selectBridgesAligned)
168
+ numpy.bitwise_and(selectBridgesAligned, (arrayCurveGroups[:, columnGroupZulu] > numpy.uint64(1)), out=selectBridgesAligned)
169
+
170
+ allocateBridgesAligned: int = int(numpy.count_nonzero(selectBridgesAligned))
171
+
172
+ # ----------------------------------------------- bridgesSimple -------------------------------------------------------
173
+ curveLocationsBridgesSimpleLessThanMaximum: DataArray1D = arrayCurveGroups[:, columnGroupZulu].copy()
174
+ numpy.left_shift(curveLocationsBridgesSimpleLessThanMaximum, 1, out=curveLocationsBridgesSimpleLessThanMaximum)
175
+ numpy.bitwise_or(curveLocationsBridgesSimpleLessThanMaximum, arrayCurveGroups[:, columnGroupAlpha], out=curveLocationsBridgesSimpleLessThanMaximum)
176
+ numpy.left_shift(curveLocationsBridgesSimpleLessThanMaximum, 2, out=curveLocationsBridgesSimpleLessThanMaximum)
177
+ numpy.bitwise_or(curveLocationsBridgesSimpleLessThanMaximum, 3, out=curveLocationsBridgesSimpleLessThanMaximum)
178
+ curveLocationsBridgesSimpleLessThanMaximum[curveLocationsBridgesSimpleLessThanMaximum >= curveLocationsMAXIMUM] = 0
179
+
180
+ allocateBridgesSimple: int = int(numpy.count_nonzero(curveLocationsBridgesSimpleLessThanMaximum))
181
+
182
+ # ----------------------------------------------- arrayCurveLocations -------------------------------------------------
183
+ rowsAllocatedTotal: int = allocateGroupAlphaCurves + allocateGroupZuluCurves + allocateBridgesSimple + allocateBridgesAligned
184
+ arrayCurveLocations: DataArray2columns = numpy.zeros((rowsAllocatedTotal, columnsArrayCurveLocations), dtype=arrayCurveGroups.dtype)
185
+
186
+ rowsAggregatedTotal: int = 0
187
+ rowsDeallocatedTotal: int = 0
188
+
189
+ # ----------------------------------------------- bridgesSimple -------------------------------------------------------
190
+ rowsAggregatedTotal = aggregateBridgesSimple2CurveLocations(arrayCurveLocations
191
+ , rowsAggregatedTotal
192
+ , curveLocationsBridgesSimpleLessThanMaximum
193
+ , arrayCurveGroups[:, columnDistinctCrossings]
194
+ )
195
+
196
+ rowsDeallocatedTotal += allocateBridgesSimple
197
+ arrayCurveLocations.resize((((rowsAllocatedTotal - rowsDeallocatedTotal) + rowsAggregatedTotal), columnsArrayCurveLocations))
198
+
199
+ curveLocationsBridgesSimpleLessThanMaximum = None; del curveLocationsBridgesSimpleLessThanMaximum # pyright: ignore[reportAssignmentType] # noqa: E702
200
+ del allocateBridgesSimple
201
+ goByeBye()
202
+
203
+ # ----------------------------------------------- groupAlpha ----------------------------------------------------------
204
+ selectGroupAlphaCurves: SelectorBoolean = arrayCurveGroups[:, columnGroupAlpha] > numpy.uint64(1)
205
+ curveLocationsGroupAlpha: DataArray1D = arrayCurveGroups[selectGroupAlphaCurves, columnGroupAlpha].copy()
206
+
207
+ numpy.bitwise_and(curveLocationsGroupAlpha, 1, out=curveLocationsGroupAlpha)
208
+ numpy.subtract(numpy.uint64(1), curveLocationsGroupAlpha, out=curveLocationsGroupAlpha)
209
+ numpy.left_shift(curveLocationsGroupAlpha, 3, out=curveLocationsGroupAlpha)
210
+ numpy.bitwise_or(curveLocationsGroupAlpha, arrayCurveGroups[selectGroupAlphaCurves, columnGroupAlpha], out=curveLocationsGroupAlpha)
211
+ numpy.right_shift(curveLocationsGroupAlpha, 2, out=curveLocationsGroupAlpha)
212
+ # NOTE (groupAlpha >> 2) | (groupZulu << 3) | ((1 - (groupAlpha & 1)) << 1)
213
+ # TODO eliminate temporary arrayLockbox
214
+ arrayLockbox: numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.uint8]] = numpy.full_like(a=curveLocationsGroupAlpha, fill_value=numpy.uint8(0b111), dtype=numpy.uint8)
215
+ numpy.bitwise_and(arrayLockbox, curveLocationsGroupAlpha, out=arrayLockbox, dtype=numpy.uint8)
216
+ numpy.right_shift(curveLocationsGroupAlpha, 3, out=curveLocationsGroupAlpha)
217
+ numpy.bitwise_or(curveLocationsGroupAlpha, arrayCurveGroups[selectGroupAlphaCurves, columnGroupZulu], out=curveLocationsGroupAlpha)
218
+ numpy.left_shift(curveLocationsGroupAlpha, 3, out=curveLocationsGroupAlpha)
219
+ numpy.bitwise_or(curveLocationsGroupAlpha, arrayLockbox, out=curveLocationsGroupAlpha)
220
+
221
+ arrayLockbox = None; del arrayLockbox # pyright: ignore[reportAssignmentType] # noqa: E702
222
+ goByeBye()
223
+
224
+ rowsAggregatedTotal = aggregateData2CurveLocations(arrayCurveLocations
225
+ , rowsAggregatedTotal
226
+ , curveLocationsGroupAlpha
227
+ , arrayCurveGroups[:, columnDistinctCrossings]
228
+ , selectGroupAlphaCurves
229
+ , curveLocationsMAXIMUM
230
+ )
231
+
232
+ rowsDeallocatedTotal += allocateGroupAlphaCurves
233
+ arrayCurveLocations.resize((((rowsAllocatedTotal - rowsDeallocatedTotal) + rowsAggregatedTotal), columnsArrayCurveLocations))
234
+
235
+ curveLocationsGroupAlpha = None; del curveLocationsGroupAlpha # pyright: ignore[reportAssignmentType] # noqa: E702
236
+ del allocateGroupAlphaCurves
237
+ selectGroupAlphaCurves = None; del selectGroupAlphaCurves # pyright: ignore[reportAssignmentType] # noqa: E702
238
+ goByeBye()
239
+
240
+ # ----------------------------------------------- groupZulu -----------------------------------------------------------
241
+ selectGroupZuluCurves: SelectorBoolean = arrayCurveGroups[:, columnGroupZulu] > numpy.uint64(1)
242
+ curveLocationsGroupZulu: DataArray1D = arrayCurveGroups[selectGroupZuluCurves, columnGroupAlpha].copy()
243
+ numpy.left_shift(curveLocationsGroupZulu, 2, out=curveLocationsGroupZulu)
244
+ # NOTE (groupAlpha << 2)
245
+
246
+ numpy.bitwise_or(curveLocationsGroupZulu, numpy.subtract(numpy.uint64(1), numpy.bitwise_and(arrayCurveGroups[selectGroupZuluCurves, columnGroupZulu], 1)), out=curveLocationsGroupZulu)
247
+ # TODO | (1 - (groupZulu & 1))
248
+
249
+ # NOTE | (groupZulu >> 1)
250
+ numpy.left_shift(curveLocationsGroupZulu, 1, out=curveLocationsGroupZulu)
251
+ numpy.bitwise_or(curveLocationsGroupZulu, arrayCurveGroups[selectGroupZuluCurves, columnGroupZulu], out=curveLocationsGroupZulu)
252
+ numpy.right_shift(curveLocationsGroupZulu, 1, out=curveLocationsGroupZulu)
253
+
254
+ rowsAggregatedTotal = aggregateData2CurveLocations(arrayCurveLocations
255
+ , rowsAggregatedTotal
256
+ , curveLocationsGroupZulu
257
+ , arrayCurveGroups[:, columnDistinctCrossings]
258
+ , selectGroupZuluCurves
259
+ , curveLocationsMAXIMUM
260
+ )
261
+
262
+ rowsDeallocatedTotal += allocateGroupZuluCurves
263
+ arrayCurveLocations.resize((((rowsAllocatedTotal - rowsDeallocatedTotal) + rowsAggregatedTotal), columnsArrayCurveLocations))
264
+
265
+ curveLocationsGroupZulu = None; del curveLocationsGroupZulu # pyright: ignore[reportAssignmentType] # noqa: E702
266
+ del allocateGroupZuluCurves
267
+ selectGroupZuluCurves = None; del selectGroupZuluCurves # pyright: ignore[reportAssignmentType] # noqa: E702
268
+ goByeBye()
269
+
270
+ # ----------------------------------------------- bridgesAligned ------------------------------------------------------
271
+ # `bridgesAligned` = `bridgesGroupAlphaPairedToOdd` UNION WITH `bridgesGroupZuluPairedToOdd` UNION WITH `bridgesAlignedAtEven`
272
+
273
+ # bridgesAligned -------------------------------- bridgesGroupAlphaPairedToOdd ----------------------------------------
274
+ # NOTE this code block MODIFIES `arrayCurveGroups` NOTE
275
+ set_threshold(0, 0, 0) # Disable the garbage collector inside this loop to maximize the `walkDyckPath` cache hits.
276
+
277
+ selectGroupAlphaAtEven: SelectorBoolean = numpy.empty_like(arrayCurveGroups[:, columnGroupAlpha], dtype=bool)
278
+ numpy.equal(numpy.bitwise_and(arrayCurveGroups[:, columnGroupAlpha], 1), 0, out=selectGroupAlphaAtEven, dtype=bool)
279
+
280
+ selectGroupZuluAtEven: SelectorBoolean = numpy.empty_like(arrayCurveGroups[:, columnGroupZulu], dtype=bool)
281
+ numpy.equal(numpy.bitwise_and(arrayCurveGroups[:, columnGroupZulu], 1), 0, out=selectGroupZuluAtEven, dtype=bool)
282
+
283
+ selectBridgesGroupAlphaPairedToOdd: SelectorIndices = numpy.flatnonzero(selectBridgesAligned & selectGroupAlphaAtEven & (~selectGroupZuluAtEven))
284
+ arrayCurveGroups[selectBridgesGroupAlphaPairedToOdd, columnGroupAlpha] = flipTheExtra_0b1(arrayCurveGroups[selectBridgesGroupAlphaPairedToOdd, columnGroupAlpha])
285
+ # Without changing `flipTheExtra_0b1`, above works, but `out=` does not. Why? Elephino.
286
+ # NOTE flipTheExtra_0b1(arrayCurveGroups[selectBridgesGroupAlphaPairedToOdd, columnGroupAlpha], casting='unsafe', out=arrayCurveGroups[selectBridgesGroupAlphaPairedToOdd, columnGroupAlpha])
287
+
288
+ selectBridgesGroupAlphaPairedToOdd = None; del selectBridgesGroupAlphaPairedToOdd # pyright: ignore[reportAssignmentType] # noqa: E702
289
+
290
+ # bridgesAligned -------------------------------- bridgesGroupZuluPairedToOdd ------------------------------------------
291
+ # NOTE this code block MODIFIES `arrayCurveGroups` NOTE
292
+ set_threshold(0, 0, 0) # Disable the garbage collector inside this loop to maximize the `walkDyckPath` cache hits.
293
+ selectBridgesGroupZuluPairedToOdd: SelectorIndices = numpy.flatnonzero(selectBridgesAligned & (~selectGroupAlphaAtEven) & selectGroupZuluAtEven)
294
+ arrayCurveGroups[selectBridgesGroupZuluPairedToOdd, columnGroupZulu] = flipTheExtra_0b1(arrayCurveGroups[selectBridgesGroupZuluPairedToOdd, columnGroupZulu])
295
+
296
+ set_threshold(1, 1, 1) # Re-enable the garbage collector.
297
+ selectBridgesGroupZuluPairedToOdd = None; del selectBridgesGroupZuluPairedToOdd # pyright: ignore[reportAssignmentType] # noqa: E702
298
+ selectGroupAlphaAtEven = None; del selectGroupAlphaAtEven # pyright: ignore[reportAssignmentType] # noqa: E702
299
+ selectGroupZuluAtEven = None; del selectGroupZuluAtEven # pyright: ignore[reportAssignmentType] # noqa: E702
300
+ goByeBye()
301
+
302
+ # NOTE: All computations for `bridgesAlignedAtEven` are handled by the computations for `bridgesAligned`.
303
+
304
+ # ----------------------------------------------- bridgesAligned ------------------------------------------------------
305
+
306
+ curveLocationsBridgesAlignedLessThanMaximum: DataArray1D = numpy.zeros((selectBridgesAligned.sum(),), dtype=numpy.uint64)
307
+ numpy.right_shift(arrayCurveGroups[selectBridgesAligned, columnGroupZulu], 2, out=curveLocationsBridgesAlignedLessThanMaximum)
308
+ numpy.left_shift(curveLocationsBridgesAlignedLessThanMaximum, 3, out=curveLocationsBridgesAlignedLessThanMaximum)
309
+ numpy.bitwise_or(curveLocationsBridgesAlignedLessThanMaximum, arrayCurveGroups[selectBridgesAligned, columnGroupAlpha], out=curveLocationsBridgesAlignedLessThanMaximum)
310
+ numpy.right_shift(curveLocationsBridgesAlignedLessThanMaximum, 2, out=curveLocationsBridgesAlignedLessThanMaximum)
311
+ curveLocationsBridgesAlignedLessThanMaximum[curveLocationsBridgesAlignedLessThanMaximum >= curveLocationsMAXIMUM] = 0
312
+
313
+ Z0Z_indexStart: int = rowsAggregatedTotal
314
+ rowsAggregatedTotal += int(numpy.count_nonzero(curveLocationsBridgesAlignedLessThanMaximum))
315
+
316
+ arrayCurveLocations[Z0Z_indexStart:rowsAggregatedTotal, columnCurveLocations] = curveLocationsBridgesAlignedLessThanMaximum[numpy.flatnonzero(curveLocationsBridgesAlignedLessThanMaximum)]
317
+ arrayCurveLocations[Z0Z_indexStart:rowsAggregatedTotal, columnDistinctCrossings] = arrayCurveGroups[(numpy.flatnonzero(selectBridgesAligned)[numpy.flatnonzero(curveLocationsBridgesAlignedLessThanMaximum)]), columnDistinctCrossings]
318
+
319
+ rowsDeallocatedTotal += allocateBridgesAligned
320
+ arrayCurveLocations.resize((((rowsAllocatedTotal - rowsDeallocatedTotal) + rowsAggregatedTotal), columnsArrayCurveLocations))
321
+
322
+ arrayCurveGroups = None; del arrayCurveGroups # pyright: ignore[reportAssignmentType] # noqa: E702
323
+ curveLocationsBridgesAlignedLessThanMaximum = None; del curveLocationsBridgesAlignedLessThanMaximum # pyright: ignore[reportAssignmentType] # noqa: E702
324
+ del allocateBridgesAligned
325
+ del curveLocationsMAXIMUM
326
+ del rowsAllocatedTotal
327
+ del rowsDeallocatedTotal
328
+ del Z0Z_indexStart
329
+ del rowsAggregatedTotal
330
+ selectBridgesAligned = None; del selectBridgesAligned # pyright: ignore[reportAssignmentType] # noqa: E702
331
+ goByeBye()
332
+
333
+ # ----------------------------------------------- aggregation ---------------------------------------------------------
334
+ arrayCurveGroups = aggregateCurveLocations2CurveGroups(arrayCurveLocations)
335
+
336
+ arrayCurveLocations = None; del arrayCurveLocations # pyright: ignore[reportAssignmentType] # noqa: E702
337
+ goByeBye()
338
+
339
+ return (bridges, arrayCurveGroups)
340
+
341
+ def convertArrayCurveGroups2dictionaryCurveGroups(arrayCurveGroups: DataArray3columns) -> dict[tuple[int, int], int]:
342
+ return {(int(row[columnGroupAlpha]), int(row[columnGroupZulu])): int(row[columnDistinctCrossings]) for row in arrayCurveGroups}
343
+
344
+ def doTheNeedful(n: int, dictionaryCurveLocations: dict[int, int]) -> int:
345
+ """Compute a(n) meanders with the transfer matrix algorithm.
346
+
347
+ Parameters
348
+ ----------
349
+ n : int
350
+ The index in the OEIS ID sequence.
351
+ dictionaryCurveLocations : dict[int, int]
352
+ A dictionary mapping curve locations to their counts.
353
+
354
+ Returns
355
+ -------
356
+ a(n) : int
357
+ The computed value of a(n).
358
+
359
+ Making sausage
360
+ --------------
361
+
362
+ As first computed by Iwan Jensen in 2000, A000682(41) = 6664356253639465480.
363
+ Citation: https://github.com/hunterhogan/mapFolding/blob/main/citations/Jensen.bibtex
364
+ See also https://oeis.org/A000682
365
+
366
+ I'm sure you instantly observed that A000682(41) = (6664356253639465480).bit_length() = 63 bits. And A005316(44) =
367
+ (18276178714484582264).bit_length() = 64 bits.
368
+
369
+ If you ask NumPy 2.3, "What is your relationship with integers with more than 64 bits?"
370
+ NumPy will say, "It's complicated."
371
+
372
+ Therefore, to take advantage of the computational excellence of NumPy when computing A000682(n) for n > 41, I must make some
373
+ adjustments at the total count approaches 64 bits.
374
+
375
+ The second complication is bit-packed integers. I use a loop that starts at `bridges = n` and decrements (`bridges -= 1`)
376
+ `until bridges = 0`. If `bridges > 29`, some of the bit-packed integers have more than 64 bits. "Hey NumPy, can I use
377
+ bit-packed integers with more than 64 bits?" NumPy: "It's complicated." Therefore, while `bridges` is decrementing, I don't
378
+ use NumPy until I believe the bit-packed integers will be less than 64 bits.
379
+
380
+ A third factor that works in my favor is that peak memory usage occurs when all types of integers are well under 64-bits wide.
381
+
382
+ In total, to compute a(n) for "large" n, I use three-stages.
383
+ 1. I use Python primitive `int` contained in a Python primitive `dict`.
384
+ 2. When the bit width of the bit-packed integers connected to `bridges` is small enough to use `numpy.uint64`, I switch to NumPy for the heavy lifting.
385
+ 3. When `distinctCrossings` subtotals might exceed 64 bits, I must switch back to Python primitives.
386
+ """
387
+ count64_bridgesMaximum = 28
388
+ dictionaryCurveGroups: dict[tuple[int, int], int] = convertDictionaryCurveLocations2CurveGroups(dictionaryCurveLocations)
389
+
390
+ if n >= count64_bridgesMaximum:
391
+ n, dictionaryCurveGroups = count(n, dictionaryCurveGroups, count64_bridgesMaximum)
392
+ goByeBye()
393
+ n, arrayCurveGroups = count64(n, convertDictionaryCurveGroups2array(dictionaryCurveGroups))
394
+ if n > 0:
395
+ goByeBye()
396
+
397
+ n, dictionaryCurveGroups = count(n, convertArrayCurveGroups2dictionaryCurveGroups(arrayCurveGroups))
398
+ distinctCrossingsTotal: int = sum(dictionaryCurveGroups.values())
399
+ else:
400
+ distinctCrossingsTotal = int(arrayCurveGroups[0, columnDistinctCrossings])
401
+ return distinctCrossingsTotal
402
+
403
+ def A000682getCurveLocations(n: int) -> dict[int, int]:
404
+ curveLocationsMAXIMUM: int = 1 << (2 * n + 4)
405
+ curveStart: int = 5 - (n & 0b1) * 4
406
+ listCurveLocations: list[int] = [(curveStart << 1) | curveStart]
407
+ while listCurveLocations[-1] < curveLocationsMAXIMUM:
408
+ curveStart = (curveStart << 4) | 0b101
409
+ listCurveLocations.append((curveStart << 1) | curveStart)
410
+ return dict.fromkeys(listCurveLocations, 1)
411
+
412
+ @cache
413
+ def A000682(n: int) -> int:
414
+ return doTheNeedful(n - 1, A000682getCurveLocations(n - 1))
415
+
416
+ def A005316getCurveLocations(n: int) -> dict[int, int]:
417
+ if n & 0b1:
418
+ return {22: 1}
419
+ else:
420
+ return {15: 1}
421
+
422
+ @cache
423
+ def A005316(n: int) -> int:
424
+ return doTheNeedful(n - 1, A005316getCurveLocations(n - 1))
@@ -1,4 +1,4 @@
1
- from astToolkit import extractFunctionDef, Make # noqa: D100
1
+ from astToolkit import extractFunctionDef, identifierDotAttribute, Make # noqa: D100
2
2
  from hunterMakesPy import raiseIfNone
3
3
  from mapFolding.someAssemblyRequired import (
4
4
  identifierCallableSourceDEFAULT, identifierCallableSourceDispatcherDEFAULT, identifierCountingDEFAULT,
@@ -7,7 +7,7 @@ import ast
7
7
 
8
8
  identifierDataclass: str = identifierDataclassInstanceDEFAULT
9
9
  identifierCounting: str = identifierCountingDEFAULT
10
- logicalPathInfixA007822: str = logicalPathInfixDEFAULT + '.A007822'
10
+ logicalPathInfixA007822: identifierDotAttribute = logicalPathInfixDEFAULT + '.A007822'
11
11
  sourceCallableDispatcherA007822: str = identifierCallableSourceDispatcherDEFAULT
12
12
  sourceCallableIdentifierA007822: str = identifierCallableSourceDEFAULT
13
13
 
@@ -33,8 +33,7 @@ def {identifier_filterAsymmetricFolds}({identifierDataclass}: MapFoldingState) -
33
33
  ImaSymmetricFold = False
34
34
  break
35
35
  leafConnectee += 1
36
- if ImaSymmetricFold:
37
- {identifierDataclass}.{identifierCounting} += 1
36
+ {identifierDataclass}.{identifierCounting} += ImaSymmetricFold
38
37
  {identifierDataclass}.indexMiniGap += 1
39
38
 
40
39
  return {identifierDataclass}