mapFolding 0.15.4__py3-none-any.whl → 0.16.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- easyRun/A000682.py +25 -0
- easyRun/A005316.py +21 -0
- easyRun/NOTcountingFolds.py +36 -0
- easyRun/__init__.py +0 -0
- easyRun/countFolds.py +41 -0
- easyRun/meanders.py +71 -0
- mapFolding/__init__.py +10 -55
- mapFolding/_dataPacking.py +68 -0
- mapFolding/_theSSOT.py +33 -36
- mapFolding/_theTypes.py +21 -4
- mapFolding/algorithms/daoOfMapFolding.py +1 -2
- mapFolding/algorithms/matrixMeanders.py +101 -348
- mapFolding/algorithms/matrixMeandersBeDry.py +264 -0
- mapFolding/algorithms/matrixMeandersNumPy.py +286 -0
- mapFolding/algorithms/matrixMeandersPandas.py +351 -0
- mapFolding/algorithms/oeisIDbyFormula.py +320 -76
- mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +92 -0
- mapFolding/basecamp.py +261 -113
- mapFolding/beDRY.py +2 -30
- mapFolding/dataBaskets.py +120 -4
- mapFolding/oeis.py +13 -33
- mapFolding/reference/A000682facts.py +1276 -0
- mapFolding/reference/A005316facts.py +985 -0
- mapFolding/reference/matrixMeandersAnalysis/__init__.py +1 -0
- mapFolding/reference/matrixMeandersAnalysis/prefixNotationNotes.py +15 -0
- mapFolding/reference/meandersDumpingGround/A005316JavaPort.py +1 -1
- mapFolding/reference/meandersDumpingGround/A005316imperative.py +1 -1
- mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +424 -0
- mapFolding/someAssemblyRequired/A007822/A007822rawMaterials.py +54 -0
- mapFolding/someAssemblyRequired/A007822/__init__.py +0 -0
- mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +197 -0
- mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +74 -0
- mapFolding/someAssemblyRequired/RecipeJob.py +4 -4
- mapFolding/someAssemblyRequired/__init__.py +9 -2
- mapFolding/someAssemblyRequired/_toolIfThis.py +4 -3
- mapFolding/someAssemblyRequired/_toolkitContainers.py +8 -8
- mapFolding/someAssemblyRequired/infoBooth.py +27 -30
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +6 -5
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +6 -4
- mapFolding/someAssemblyRequired/makingModules_count.py +294 -0
- mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +117 -0
- mapFolding/someAssemblyRequired/mapFolding/__init__.py +0 -0
- mapFolding/someAssemblyRequired/mapFolding/makeMapFoldingModules.py +220 -0
- mapFolding/someAssemblyRequired/meanders/__init__.py +0 -0
- mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +64 -0
- mapFolding/someAssemblyRequired/toolkitMakeModules.py +152 -0
- mapFolding/someAssemblyRequired/toolkitNumba.py +1 -1
- mapFolding/someAssemblyRequired/transformationTools.py +1 -0
- mapFolding/syntheticModules/A007822/__init__.py +1 -0
- mapFolding/syntheticModules/{algorithmA007822.py → A007822/algorithm.py} +2 -3
- mapFolding/syntheticModules/{algorithmA007822Numba.py → A007822/algorithmNumba.py} +3 -6
- mapFolding/syntheticModules/A007822/asynchronous.py +148 -0
- mapFolding/syntheticModules/A007822/asynchronousAnnex.py +66 -0
- mapFolding/syntheticModules/A007822/asynchronousAnnexNumba.py +85 -0
- mapFolding/syntheticModules/A007822/asynchronousNumba.py +52 -0
- mapFolding/syntheticModules/A007822/asynchronousTheorem2.py +53 -0
- mapFolding/syntheticModules/A007822/asynchronousTrimmed.py +47 -0
- mapFolding/syntheticModules/{initializeStateA007822.py → A007822/initializeState.py} +1 -2
- mapFolding/syntheticModules/{theorem2A007822.py → A007822/theorem2.py} +1 -2
- mapFolding/syntheticModules/{theorem2A007822Numba.py → A007822/theorem2Numba.py} +6 -4
- mapFolding/syntheticModules/{theorem2A007822Trimmed.py → A007822/theorem2Trimmed.py} +1 -2
- mapFolding/syntheticModules/countParallelNumba.py +5 -2
- mapFolding/syntheticModules/daoOfMapFoldingNumba.py +4 -2
- mapFolding/syntheticModules/dataPacking.py +4 -2
- mapFolding/syntheticModules/dataPackingA007822.py +92 -26
- mapFolding/syntheticModules/meanders/__init__.py +1 -0
- mapFolding/syntheticModules/meanders/bigInt.py +62 -0
- mapFolding/syntheticModules/theorem2Numba.py +3 -2
- mapFolding/tests/conftest.py +28 -13
- mapFolding/tests/test_computations.py +69 -62
- mapFolding/tests/test_oeis.py +6 -6
- mapFolding/zCuzDocStoopid/__init__.py +4 -0
- mapFolding/zCuzDocStoopid/makeDocstrings.py +68 -0
- mapfolding-0.16.1.dist-info/METADATA +99 -0
- mapfolding-0.16.1.dist-info/RECORD +114 -0
- {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/top_level.txt +1 -0
- mapFolding/someAssemblyRequired/A007822rawMaterials.py +0 -46
- mapFolding/someAssemblyRequired/makeAllModules.py +0 -764
- mapfolding-0.15.4.dist-info/METADATA +0 -78
- mapfolding-0.15.4.dist-info/RECORD +0 -78
- {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/WHEEL +0 -0
- {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,348 +1,101 @@
|
|
|
1
|
-
|
|
2
|
-
from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
findUnpaired_0b1 += 1 if (groupZulu & XOrHere2makePair) == 0 else -1
|
|
103
|
-
groupZulu ^= XOrHere2makePair # noqa: PLW2901
|
|
104
|
-
|
|
105
|
-
# Cases 1, 2, and 3 all compute curveLocationAnalysis
|
|
106
|
-
curveLocationAnalysis = ((groupZulu >> 2) << 1) | (groupAlpha >> 2)
|
|
107
|
-
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
108
|
-
dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
109
|
-
|
|
110
|
-
dictionaryCurveGroups = convertDictionaryCurveLocations2CurveGroups(dictionaryCurveLocations)
|
|
111
|
-
dictionaryCurveLocations = {}
|
|
112
|
-
|
|
113
|
-
return (bridges, dictionaryCurveGroups)
|
|
114
|
-
|
|
115
|
-
@cache
|
|
116
|
-
def walkDyckPath(intWithExtra_0b1: int) -> int:
|
|
117
|
-
findTheExtra_0b1: int = 0
|
|
118
|
-
flipExtra_0b1_Here: int = 1
|
|
119
|
-
while True:
|
|
120
|
-
flipExtra_0b1_Here <<= 2
|
|
121
|
-
if (intWithExtra_0b1 & flipExtra_0b1_Here) == 0:
|
|
122
|
-
findTheExtra_0b1 += 1
|
|
123
|
-
else:
|
|
124
|
-
findTheExtra_0b1 -= 1
|
|
125
|
-
if findTheExtra_0b1 < 0:
|
|
126
|
-
break
|
|
127
|
-
return flipExtra_0b1_Here
|
|
128
|
-
|
|
129
|
-
@cache
|
|
130
|
-
def _flipTheExtra_0b1(avoidingLookupsInPerRowLoop: int) -> numpy.uint64:
|
|
131
|
-
"""Be a docstring."""
|
|
132
|
-
return numpy.uint64(avoidingLookupsInPerRowLoop ^ walkDyckPath(avoidingLookupsInPerRowLoop))
|
|
133
|
-
|
|
134
|
-
# TODO there is a better way to do this.
|
|
135
|
-
flipTheExtra_0b1 = numpy.vectorize(_flipTheExtra_0b1, otypes=[numpy.uint64])
|
|
136
|
-
"""The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop."""
|
|
137
|
-
|
|
138
|
-
def aggregateCurveLocations(arrayCurveLocations: DataArray2columns) -> DataArray3columns:
|
|
139
|
-
arrayCurveGroups: DataArray3columns = numpy.tile(
|
|
140
|
-
A=numpy.unique(arrayCurveLocations[:, columnCurveLocations])
|
|
141
|
-
, reps=(columnsArrayCurveGroups, 1)
|
|
142
|
-
).T
|
|
143
|
-
arrayCurveGroups[:, columnDistinctCrossings] = 0
|
|
144
|
-
numpy.add.at(
|
|
145
|
-
arrayCurveGroups[:, columnDistinctCrossings]
|
|
146
|
-
, numpy.searchsorted(
|
|
147
|
-
a=arrayCurveGroups[:, columnCurveLocations]
|
|
148
|
-
, v=arrayCurveLocations[:, columnCurveLocations])
|
|
149
|
-
, arrayCurveLocations[:, columnDistinctCrossings]
|
|
150
|
-
)
|
|
151
|
-
# I'm computing groupZulu from curveLocations that are physically in `arrayCurveGroups`, so I'm using `columnCurveLocations`.
|
|
152
|
-
numpy.bitwise_and(arrayCurveGroups[:, columnCurveLocations], numpy.uint64(groupZuluLocator64), out=arrayCurveGroups[:, columnGroupZulu])
|
|
153
|
-
numpy.right_shift(arrayCurveGroups[:, columnGroupZulu], 1, out=arrayCurveGroups[:, columnGroupZulu])
|
|
154
|
-
# NOTE Do not alphabetize these operations. This column has curveLocations data that groupZulu needs.
|
|
155
|
-
arrayCurveGroups[:, columnGroupAlpha] &= groupAlphaLocator64
|
|
156
|
-
return arrayCurveGroups
|
|
157
|
-
|
|
158
|
-
def convertDictionaryCurveGroups2array(dictionaryCurveGroups: dict[tuple[int, int], int]) -> DataArray3columns:
|
|
159
|
-
arrayCurveGroups: DataArray3columns = numpy.tile(numpy.fromiter(dictionaryCurveGroups.values(), dtype=numpy.uint64), (columnsArrayCurveGroups, 1)).T
|
|
160
|
-
arrayKeys: DataArray2columns = numpy.array(list(dictionaryCurveGroups.keys()), dtype=numpy.uint64)
|
|
161
|
-
arrayCurveGroups[:, columnGroupAlpha] = arrayKeys[:, 0]
|
|
162
|
-
arrayCurveGroups[:, columnGroupZulu] = arrayKeys[:, 1]
|
|
163
|
-
return arrayCurveGroups
|
|
164
|
-
|
|
165
|
-
def count64(bridges: int, arrayCurveGroups: DataArray3columns, bridgesMinimum: int = 0) -> tuple[int, DataArray3columns]:
|
|
166
|
-
|
|
167
|
-
while bridges > bridgesMinimum and int(arrayCurveGroups[:, columnDistinctCrossings].max()).bit_length() < Z0Z_bit_lengthSafetyLimit:
|
|
168
|
-
bridges -= 1
|
|
169
|
-
curveLocationsMAXIMUM: numpy.uint64 = numpy.uint64(1 << (2 * bridges + 4))
|
|
170
|
-
|
|
171
|
-
selectGroupAlphaCurves: SelectorBoolean = arrayCurveGroups[:, columnGroupAlpha] > numpy.uint64(1)
|
|
172
|
-
curveLocationsGroupAlpha: DataArray1D = ((arrayCurveGroups[selectGroupAlphaCurves, columnGroupAlpha] >> 2)
|
|
173
|
-
| (arrayCurveGroups[selectGroupAlphaCurves, columnGroupZulu] << 3)
|
|
174
|
-
| ((numpy.uint64(1) - (arrayCurveGroups[selectGroupAlphaCurves, columnGroupAlpha] & 1)) << 1)
|
|
175
|
-
)
|
|
176
|
-
selectGroupAlphaCurvesLessThanMaximum: SelectorIndices = numpy.flatnonzero(selectGroupAlphaCurves)[numpy.flatnonzero(curveLocationsGroupAlpha < curveLocationsMAXIMUM)]
|
|
177
|
-
|
|
178
|
-
selectGroupZuluCurves: SelectorBoolean = arrayCurveGroups[:, columnGroupZulu] > numpy.uint64(1)
|
|
179
|
-
curveLocationsGroupZulu: DataArray1D = (arrayCurveGroups[selectGroupZuluCurves, columnGroupZulu] >> 1
|
|
180
|
-
| arrayCurveGroups[selectGroupZuluCurves, columnGroupAlpha] << 2
|
|
181
|
-
| (numpy.uint64(1) - (arrayCurveGroups[selectGroupZuluCurves, columnGroupZulu] & 1))
|
|
182
|
-
)
|
|
183
|
-
selectGroupZuluCurvesLessThanMaximum: SelectorIndices = numpy.flatnonzero(selectGroupZuluCurves)[numpy.flatnonzero(curveLocationsGroupZulu < curveLocationsMAXIMUM)]
|
|
184
|
-
|
|
185
|
-
selectBridgesSimpleLessThanMaximum: SelectorIndices = numpy.flatnonzero(
|
|
186
|
-
((arrayCurveGroups[:, columnGroupAlpha] << 2) | (arrayCurveGroups[:, columnGroupZulu] << 3) | 3) < curveLocationsMAXIMUM
|
|
187
|
-
) # Computation, but including `< curveLocationsMAXIMUM` is ~2% of total time.
|
|
188
|
-
|
|
189
|
-
# Selectors for bridgesAligned -------------------------------------------------
|
|
190
|
-
selectGroupAlphaAtEven: SelectorBoolean = (arrayCurveGroups[:, columnGroupAlpha] & 1) == numpy.uint64(0)
|
|
191
|
-
selectGroupZuluAtEven: SelectorBoolean = (arrayCurveGroups[:, columnGroupZulu] & 1) == numpy.uint64(0)
|
|
192
|
-
selectBridgesAligned: SelectorBoolean = selectGroupAlphaCurves & selectGroupZuluCurves & (selectGroupAlphaAtEven | selectGroupZuluAtEven)
|
|
193
|
-
|
|
194
|
-
SliceΩ: slice[int, int, Literal[1]] = slice(0,0)
|
|
195
|
-
sliceAllocateGroupAlpha = SliceΩ = slice(SliceΩ.stop, SliceΩ.stop + selectGroupAlphaCurvesLessThanMaximum.size)
|
|
196
|
-
sliceAllocateGroupZulu = SliceΩ = slice(SliceΩ.stop, SliceΩ.stop + selectGroupZuluCurvesLessThanMaximum.size)
|
|
197
|
-
sliceAllocateBridgesSimple = SliceΩ = slice(SliceΩ.stop, SliceΩ.stop + selectBridgesSimpleLessThanMaximum.size)
|
|
198
|
-
sliceAllocateBridgesAligned = SliceΩ = slice(SliceΩ.stop, SliceΩ.stop + selectBridgesAligned.size)
|
|
199
|
-
|
|
200
|
-
arrayCurveLocations: DataArray2columns = numpy.zeros((SliceΩ.stop, columnsArrayCurveLocations), dtype=arrayCurveGroups.dtype)
|
|
201
|
-
|
|
202
|
-
arrayCurveLocations[sliceAllocateGroupAlpha, columnCurveLocations] = curveLocationsGroupAlpha[numpy.flatnonzero(curveLocationsGroupAlpha < curveLocationsMAXIMUM)]
|
|
203
|
-
arrayCurveLocations[sliceAllocateGroupAlpha, columnDistinctCrossings] = arrayCurveGroups[selectGroupAlphaCurvesLessThanMaximum, columnDistinctCrossings]
|
|
204
|
-
|
|
205
|
-
arrayCurveLocations[sliceAllocateGroupZulu, columnCurveLocations] = curveLocationsGroupZulu[numpy.flatnonzero(curveLocationsGroupZulu < curveLocationsMAXIMUM)]
|
|
206
|
-
arrayCurveLocations[sliceAllocateGroupZulu, columnDistinctCrossings] = arrayCurveGroups[selectGroupZuluCurvesLessThanMaximum, columnDistinctCrossings]
|
|
207
|
-
|
|
208
|
-
# TODO Uh, it sure looks like I am doing this computation twice. Computation (without assignment) ~ 1.5% of total time.
|
|
209
|
-
arrayCurveLocations[sliceAllocateBridgesSimple, columnCurveLocations] = (
|
|
210
|
-
(arrayCurveGroups[selectBridgesSimpleLessThanMaximum, columnGroupAlpha] << 2)
|
|
211
|
-
| (arrayCurveGroups[selectBridgesSimpleLessThanMaximum, columnGroupZulu] << 3)
|
|
212
|
-
| 3
|
|
213
|
-
)
|
|
214
|
-
arrayCurveLocations[sliceAllocateBridgesSimple, columnDistinctCrossings] = arrayCurveGroups[selectBridgesSimpleLessThanMaximum, columnDistinctCrossings]
|
|
215
|
-
|
|
216
|
-
curveLocationsGroupAlpha = None; del curveLocationsGroupAlpha # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
217
|
-
curveLocationsGroupZulu = None; del curveLocationsGroupZulu # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
218
|
-
selectBridgesSimpleLessThanMaximum = None; del selectBridgesSimpleLessThanMaximum # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
219
|
-
selectGroupAlphaCurvesLessThanMaximum = None; del selectGroupAlphaCurvesLessThanMaximum # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
220
|
-
selectGroupZuluCurvesLessThanMaximum = None; del selectGroupZuluCurvesLessThanMaximum # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
221
|
-
goByeBye()
|
|
222
|
-
|
|
223
|
-
# NOTE this MODIFIES `arrayCurveGroups` for bridgesPairedToOdd ---------------------------------------------------------------------------------------
|
|
224
|
-
selectBridgesGroupAlphaPairedToOdd: SelectorIndices = numpy.flatnonzero(selectBridgesAligned & selectGroupAlphaAtEven & (~selectGroupZuluAtEven))
|
|
225
|
-
arrayCurveGroups[selectBridgesGroupAlphaPairedToOdd, columnGroupAlpha] = flipTheExtra_0b1(
|
|
226
|
-
arrayCurveGroups[selectBridgesGroupAlphaPairedToOdd, columnGroupAlpha]
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
selectBridgesGroupZuluPairedToOdd: SelectorIndices = numpy.flatnonzero(selectBridgesAligned & (~selectGroupAlphaAtEven) & selectGroupZuluAtEven)
|
|
230
|
-
arrayCurveGroups[selectBridgesGroupZuluPairedToOdd, columnGroupZulu] = flipTheExtra_0b1(
|
|
231
|
-
arrayCurveGroups[selectBridgesGroupZuluPairedToOdd, columnGroupZulu]
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
selectBridgesGroupAlphaPairedToOdd = None; del selectBridgesGroupAlphaPairedToOdd # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
235
|
-
selectBridgesGroupZuluPairedToOdd = None; del selectBridgesGroupZuluPairedToOdd # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
236
|
-
selectGroupAlphaAtEven = None; del selectGroupAlphaAtEven # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
237
|
-
selectGroupAlphaCurves = None; del selectGroupAlphaCurves # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
238
|
-
selectGroupZuluAtEven = None; del selectGroupZuluAtEven # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
239
|
-
selectGroupZuluCurves = None; del selectGroupZuluCurves # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
240
|
-
goByeBye()
|
|
241
|
-
|
|
242
|
-
# bridgesAligned; bridgesAlignedAtEven, bridgesGroupAlphaPairedToOdd, bridgesGroupZuluPairedToOdd ------------------------------------------------------------------
|
|
243
|
-
curveLocationsBridgesAligned: DataArray1D = (((arrayCurveGroups[selectBridgesAligned, columnGroupZulu] >> 2) << 1)
|
|
244
|
-
| (arrayCurveGroups[selectBridgesAligned, columnGroupAlpha] >> 2)
|
|
245
|
-
)
|
|
246
|
-
selectBridgesAlignedLessThanMaximum: SelectorIndices = numpy.flatnonzero(selectBridgesAligned)[numpy.flatnonzero(curveLocationsBridgesAligned < curveLocationsMAXIMUM)]
|
|
247
|
-
|
|
248
|
-
sliceAllocateBridgesAligned = SliceΩ = slice(sliceAllocateBridgesAligned.start, sliceAllocateBridgesAligned.stop - selectBridgesAligned.size + selectBridgesAlignedLessThanMaximum.size)
|
|
249
|
-
arrayCurveLocations[sliceAllocateBridgesAligned, columnDistinctCrossings] = arrayCurveGroups[selectBridgesAlignedLessThanMaximum, columnDistinctCrossings]
|
|
250
|
-
arrayCurveLocations[sliceAllocateBridgesAligned, columnCurveLocations] = curveLocationsBridgesAligned[numpy.flatnonzero(curveLocationsBridgesAligned < curveLocationsMAXIMUM)]
|
|
251
|
-
|
|
252
|
-
arrayCurveGroups = None; del arrayCurveGroups # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
253
|
-
curveLocationsBridgesAligned = None; del curveLocationsBridgesAligned # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
254
|
-
del curveLocationsMAXIMUM
|
|
255
|
-
selectBridgesAligned = None; del selectBridgesAligned # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
256
|
-
selectBridgesAlignedLessThanMaximum = None; del selectBridgesAlignedLessThanMaximum # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
257
|
-
goByeBye()
|
|
258
|
-
|
|
259
|
-
arrayCurveLocations.resize((SliceΩ.stop, columnsArrayCurveLocations))
|
|
260
|
-
arrayCurveGroups = aggregateCurveLocations(arrayCurveLocations)
|
|
261
|
-
|
|
262
|
-
arrayCurveLocations = None; del arrayCurveLocations # pyright: ignore[reportAssignmentType] # noqa: E702
|
|
263
|
-
del sliceAllocateBridgesAligned
|
|
264
|
-
del sliceAllocateBridgesSimple
|
|
265
|
-
del sliceAllocateGroupAlpha
|
|
266
|
-
del sliceAllocateGroupZulu
|
|
267
|
-
del SliceΩ
|
|
268
|
-
goByeBye()
|
|
269
|
-
|
|
270
|
-
return (bridges, arrayCurveGroups)
|
|
271
|
-
|
|
272
|
-
def convertArrayCurveGroups2dictionaryCurveGroups(arrayCurveGroups: DataArray3columns) -> dict[tuple[int, int], int]:
|
|
273
|
-
return {(int(row[columnGroupAlpha]), int(row[columnGroupZulu])): int(row[columnDistinctCrossings]) for row in arrayCurveGroups}
|
|
274
|
-
|
|
275
|
-
def doTheNeedful(n: int, dictionaryCurveLocations: dict[int, int]) -> int:
|
|
276
|
-
"""Compute a(n) meanders with the transfer matrix algorithm.
|
|
277
|
-
|
|
278
|
-
Parameters
|
|
279
|
-
----------
|
|
280
|
-
n : int
|
|
281
|
-
The index in the OEIS ID sequence.
|
|
282
|
-
dictionaryCurveLocations : dict[int, int]
|
|
283
|
-
A dictionary mapping curve locations to their counts.
|
|
284
|
-
|
|
285
|
-
Returns
|
|
286
|
-
-------
|
|
287
|
-
a(n) : int
|
|
288
|
-
The computed value of a(n).
|
|
289
|
-
|
|
290
|
-
Making sausage
|
|
291
|
-
--------------
|
|
292
|
-
|
|
293
|
-
As first computed by Iwan Jensen in 2000, A000682(41) = 6664356253639465480.
|
|
294
|
-
Citation: https://github.com/hunterhogan/mapFolding/blob/main/citations/Jensen.bibtex
|
|
295
|
-
See also https://oeis.org/A000682
|
|
296
|
-
|
|
297
|
-
I'm sure you instantly observed that A000682(41) = (6664356253639465480).bit_length() = 63 bits. And A005316(44) =
|
|
298
|
-
(18276178714484582264).bit_length() = 64 bits.
|
|
299
|
-
|
|
300
|
-
If you ask NumPy 2.3, "What is your relationship with integers with more than 64 bits?"
|
|
301
|
-
NumPy will say, "It's complicated."
|
|
302
|
-
|
|
303
|
-
Therefore, to take advantage of the computational excellence of NumPy when computing A000682(n) for n > 41, I must make some
|
|
304
|
-
adjustments at the total count approaches 64 bits.
|
|
305
|
-
|
|
306
|
-
The second complication is bit-packed integers. I use a loop that starts at `bridges = n` and decrements (`bridges -= 1`)
|
|
307
|
-
`until bridges = 0`. If `bridges > 29`, some of the bit-packed integers have more than 64 bits. "Hey NumPy, can I use
|
|
308
|
-
bit-packed integers with more than 64 bits?" NumPy: "It's complicated." Therefore, while `bridges` is decrementing, I don't
|
|
309
|
-
use NumPy until I believe the bit-packed integers will be less than 64 bits.
|
|
310
|
-
|
|
311
|
-
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.
|
|
312
|
-
|
|
313
|
-
In total, to compute a(n) for "large" n, I use three-stages.
|
|
314
|
-
1. I use Python primitive `int` contained in a Python primitive `dict`.
|
|
315
|
-
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.
|
|
316
|
-
3. When `distinctCrossings` subtotals might exceed 64 bits, I must switch back to Python primitives.
|
|
317
|
-
"""
|
|
318
|
-
# NOTE '29' is based on two things. 1) `bridges = 29`, groupZuluLocator = 0xaaaaaaaaaaaaaaaa.bit_length() = 64. 2) If `bridges =
|
|
319
|
-
# 30` or a larger number, `OverflowError: int too big to convert`. Conclusion: '29' isn't necessarily correct or the best value:
|
|
320
|
-
# it merely fits within my limited ability to assess the correct value.
|
|
321
|
-
# NOTE the above was written when I had the `bridges >= bridgesMinimum` bug. So, apply '-1' to everything.
|
|
322
|
-
# NOTE This default value is necessary: it prevents `count64` from returning an incomplete dictionary when that is not necessary.
|
|
323
|
-
# TODO `count64_bridgesMaximum` might be a VERY good idea as a second safeguard against overflowing distinctCrossingsTotal. But
|
|
324
|
-
# I'm pretty sure I should use an actual check on maximum bit-width in arrayCurveGroups[:, columnDistinctCrossings] at the start
|
|
325
|
-
# of each while loop. Tests on A000682 showed that the max bit-width of arrayCurveGroups[:, columnDistinctCrossings] always
|
|
326
|
-
# increased by 1 or 2 bits on each iteration: never 0 and never 3. I did not test A005316. And I do not have a mathematical proof of the limit.
|
|
327
|
-
|
|
328
|
-
count64_bridgesMaximum = 28
|
|
329
|
-
bridgesMinimum = 0
|
|
330
|
-
distinctCrossings64bitLimitAsValueOf_n = 41
|
|
331
|
-
distinctCrossingsSubtotal64bitLimitAsValueOf_n_WAG = distinctCrossings64bitLimitAsValueOf_n - 3
|
|
332
|
-
distinctCrossings64bitLimitSafetyMargin = 4
|
|
333
|
-
|
|
334
|
-
dictionaryCurveGroups: dict[tuple[int, int], int] = convertDictionaryCurveLocations2CurveGroups(dictionaryCurveLocations)
|
|
335
|
-
|
|
336
|
-
if n >= count64_bridgesMaximum:
|
|
337
|
-
if n >= distinctCrossingsSubtotal64bitLimitAsValueOf_n_WAG:
|
|
338
|
-
bridgesMinimum = n - distinctCrossingsSubtotal64bitLimitAsValueOf_n_WAG + distinctCrossings64bitLimitSafetyMargin
|
|
339
|
-
n, dictionaryCurveGroups = count(n, dictionaryCurveGroups, count64_bridgesMaximum)
|
|
340
|
-
gc.collect()
|
|
341
|
-
n, arrayCurveGroups = count64(n, convertDictionaryCurveGroups2array(dictionaryCurveGroups), bridgesMinimum)
|
|
342
|
-
if n > 0:
|
|
343
|
-
gc.collect()
|
|
344
|
-
n, dictionaryCurveGroups = count(n, convertArrayCurveGroups2dictionaryCurveGroups(arrayCurveGroups), bridgesMinimum=0)
|
|
345
|
-
distinctCrossingsTotal = sum(dictionaryCurveGroups.values())
|
|
346
|
-
else:
|
|
347
|
-
distinctCrossingsTotal = int(arrayCurveGroups[0, columnDistinctCrossings])
|
|
348
|
-
return distinctCrossingsTotal
|
|
1
|
+
from mapFolding.algorithms.matrixMeandersBeDry import walkDyckPath
|
|
2
|
+
from mapFolding.dataBaskets import MatrixMeandersState
|
|
3
|
+
|
|
4
|
+
def outfitDictionaryBitGroups(state: MatrixMeandersState) -> dict[tuple[int, int], int]:
|
|
5
|
+
"""Outfit `dictionaryBitGroups` so it may manage the computations for one iteration of the transfer matrix.
|
|
6
|
+
|
|
7
|
+
Parameters
|
|
8
|
+
----------
|
|
9
|
+
state : MatrixMeandersState
|
|
10
|
+
The current state of the computation, including `dictionaryMeanders`.
|
|
11
|
+
|
|
12
|
+
Returns
|
|
13
|
+
-------
|
|
14
|
+
dictionaryBitGroups : dict[tuple[int, int], int]
|
|
15
|
+
A dictionary of `(bitsAlpha, bitsZulu)` to `crossings`.
|
|
16
|
+
"""
|
|
17
|
+
state.bitWidth = max(state.dictionaryMeanders.keys()).bit_length()
|
|
18
|
+
return {(arcCode & state.locatorBits, (arcCode >> 1) & state.locatorBits): crossings
|
|
19
|
+
for arcCode, crossings in state.dictionaryMeanders.items()}
|
|
20
|
+
|
|
21
|
+
def count(state: MatrixMeandersState) -> MatrixMeandersState:
|
|
22
|
+
"""Count meanders with matrix transfer algorithm using Python `int` (*int*eger) contained in a Python `dict` (*dict*ionary).
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
state : MatrixMeandersState
|
|
27
|
+
The algorithm state.
|
|
28
|
+
|
|
29
|
+
Notes
|
|
30
|
+
-----
|
|
31
|
+
The matrix transfer algorithm is sophisticated, but this implementation is straightforward: compute each index one at a time,
|
|
32
|
+
compute each `arcCode` one at a time, and compute each type of analysis one at a time.
|
|
33
|
+
"""
|
|
34
|
+
dictionaryBitGroups: dict[tuple[int, int], int] = {}
|
|
35
|
+
|
|
36
|
+
while state.kOfMatrix > 0:
|
|
37
|
+
state.kOfMatrix -= 1
|
|
38
|
+
|
|
39
|
+
dictionaryBitGroups = outfitDictionaryBitGroups(state)
|
|
40
|
+
state.dictionaryMeanders = {}
|
|
41
|
+
|
|
42
|
+
for (bitsAlpha, bitsZulu), crossings in dictionaryBitGroups.items():
|
|
43
|
+
bitsAlphaHasArcs: bool = bitsAlpha > 1
|
|
44
|
+
bitsZuluHasArcs: bool = bitsZulu > 1
|
|
45
|
+
bitsAlphaIsEven = bitsZuluIsEven = 0
|
|
46
|
+
|
|
47
|
+
arcCodeAnalysis = ((bitsAlpha | (bitsZulu << 1)) << 2) | 3
|
|
48
|
+
# simple
|
|
49
|
+
if arcCodeAnalysis < state.MAXIMUMarcCode:
|
|
50
|
+
state.dictionaryMeanders[arcCodeAnalysis] = state.dictionaryMeanders.get(arcCodeAnalysis, 0) + crossings
|
|
51
|
+
|
|
52
|
+
if bitsAlphaHasArcs:
|
|
53
|
+
arcCodeAnalysis = (bitsAlpha >> 2) | (bitsZulu << 3) | ((bitsAlphaIsEven := 1 - (bitsAlpha & 1)) << 1)
|
|
54
|
+
if arcCodeAnalysis < state.MAXIMUMarcCode:
|
|
55
|
+
state.dictionaryMeanders[arcCodeAnalysis] = state.dictionaryMeanders.get(arcCodeAnalysis, 0) + crossings
|
|
56
|
+
|
|
57
|
+
if bitsZuluHasArcs:
|
|
58
|
+
arcCodeAnalysis = (bitsZulu >> 1) | (bitsAlpha << 2) | (bitsZuluIsEven := 1 - (bitsZulu & 1))
|
|
59
|
+
if arcCodeAnalysis < state.MAXIMUMarcCode:
|
|
60
|
+
state.dictionaryMeanders[arcCodeAnalysis] = state.dictionaryMeanders.get(arcCodeAnalysis, 0) + crossings
|
|
61
|
+
|
|
62
|
+
if bitsAlphaHasArcs and bitsZuluHasArcs and (bitsAlphaIsEven or bitsZuluIsEven):
|
|
63
|
+
# aligned
|
|
64
|
+
if bitsAlphaIsEven and not bitsZuluIsEven:
|
|
65
|
+
bitsAlpha ^= walkDyckPath(bitsAlpha) # noqa: PLW2901
|
|
66
|
+
elif bitsZuluIsEven and not bitsAlphaIsEven:
|
|
67
|
+
bitsZulu ^= walkDyckPath(bitsZulu) # noqa: PLW2901
|
|
68
|
+
|
|
69
|
+
arcCodeAnalysis: int = ((bitsZulu >> 2) << 1) | (bitsAlpha >> 2)
|
|
70
|
+
if arcCodeAnalysis < state.MAXIMUMarcCode:
|
|
71
|
+
state.dictionaryMeanders[arcCodeAnalysis] = state.dictionaryMeanders.get(arcCodeAnalysis, 0) + crossings
|
|
72
|
+
|
|
73
|
+
dictionaryBitGroups = {}
|
|
74
|
+
|
|
75
|
+
return state
|
|
76
|
+
|
|
77
|
+
def doTheNeedful(state: MatrixMeandersState) -> int:
|
|
78
|
+
"""Compute `crossings` with a transfer matrix algorithm.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
state : MatrixMeandersState
|
|
83
|
+
The algorithm state.
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
crossings : int
|
|
88
|
+
The computed value of `crossings`.
|
|
89
|
+
|
|
90
|
+
Notes
|
|
91
|
+
-----
|
|
92
|
+
Citation: https://github.com/hunterhogan/mapFolding/blob/main/citations/Jensen.bibtex
|
|
93
|
+
|
|
94
|
+
See Also
|
|
95
|
+
--------
|
|
96
|
+
https://oeis.org/A000682
|
|
97
|
+
https://oeis.org/A005316
|
|
98
|
+
"""
|
|
99
|
+
state = count(state)
|
|
100
|
+
|
|
101
|
+
return sum(state.dictionaryMeanders.values())
|