mapFolding 0.16.4__py3-none-any.whl → 0.17.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. easyRun/A000682.py +2 -2
  2. easyRun/NOTcountingFolds.py +16 -9
  3. easyRun/countFolds.py +10 -3
  4. easyRun/meanders.py +3 -3
  5. mapFolding/algorithms/A000136constraintPropagation.py +95 -0
  6. mapFolding/algorithms/A000136elimination.py +163 -0
  7. mapFolding/algorithms/A000136eliminationParallel.py +77 -0
  8. mapFolding/algorithms/matrixMeanders.py +59 -18
  9. mapFolding/algorithms/matrixMeandersNumPyndas.py +841 -0
  10. mapFolding/algorithms/symmetricFolds.py +24 -25
  11. mapFolding/basecamp.py +30 -14
  12. mapFolding/dataBaskets.py +30 -71
  13. mapFolding/reference/irvineJavaPort.py +3 -3
  14. mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +1 -1
  15. mapFolding/someAssemblyRequired/A007822/_asynchronousAnnex.py +1 -1
  16. mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +5 -3
  17. mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +22 -6
  18. mapFolding/someAssemblyRequired/RecipeJob.py +14 -24
  19. mapFolding/someAssemblyRequired/__init__.py +1 -0
  20. mapFolding/someAssemblyRequired/_toolkitContainers.py +6 -4
  21. mapFolding/someAssemblyRequired/infoBooth.py +2 -1
  22. mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +75 -20
  23. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +9 -10
  24. mapFolding/someAssemblyRequired/makingModules_count.py +20 -22
  25. mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +9 -9
  26. mapFolding/someAssemblyRequired/mapFoldingModules/makeMapFoldingModules.py +6 -5
  27. mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +6 -6
  28. mapFolding/someAssemblyRequired/toolkitMakeModules.py +3 -29
  29. mapFolding/someAssemblyRequired/toolkitNumba.py +2 -1
  30. mapFolding/someAssemblyRequired/transformationTools.py +2 -3
  31. mapFolding/syntheticModules/A007822/algorithm.py +8 -8
  32. mapFolding/syntheticModules/A007822/asynchronous.py +12 -13
  33. mapFolding/syntheticModules/A007822/initializeState.py +10 -8
  34. mapFolding/syntheticModules/A007822/theorem2.py +10 -8
  35. mapFolding/syntheticModules/A007822/theorem2Numba.py +20 -16
  36. mapFolding/syntheticModules/A007822/theorem2Trimmed.py +10 -8
  37. mapFolding/syntheticModules/countParallelNumba.py +5 -2
  38. mapFolding/syntheticModules/daoOfMapFoldingNumba.py +4 -2
  39. mapFolding/syntheticModules/initializeState.py +1 -1
  40. mapFolding/syntheticModules/meanders/bigInt.py +52 -15
  41. mapFolding/syntheticModules/theorem2.py +1 -1
  42. mapFolding/syntheticModules/theorem2Numba.py +4 -2
  43. mapFolding/syntheticModules/theorem2Trimmed.py +1 -1
  44. mapFolding/tests/test_computations.py +28 -2
  45. {mapfolding-0.16.4.dist-info → mapfolding-0.17.0.dist-info}/METADATA +9 -9
  46. {mapfolding-0.16.4.dist-info → mapfolding-0.17.0.dist-info}/RECORD +50 -49
  47. mapFolding/algorithms/matrixMeandersBeDry.py +0 -182
  48. mapFolding/algorithms/matrixMeandersNumPy.py +0 -333
  49. mapFolding/algorithms/matrixMeandersPandas.py +0 -334
  50. {mapfolding-0.16.4.dist-info → mapfolding-0.17.0.dist-info}/WHEEL +0 -0
  51. {mapfolding-0.16.4.dist-info → mapfolding-0.17.0.dist-info}/entry_points.txt +0 -0
  52. {mapfolding-0.16.4.dist-info → mapfolding-0.17.0.dist-info}/licenses/LICENSE +0 -0
  53. {mapfolding-0.16.4.dist-info → mapfolding-0.17.0.dist-info}/top_level.txt +0 -0
@@ -1,333 +0,0 @@
1
- from gc import collect as goByeBye
2
- from mapFolding import ShapeArray, ShapeSlicer
3
- from mapFolding.algorithms.matrixMeandersBeDry import areIntegersWide, flipTheExtra_0b1AsUfunc, getBucketsTotal
4
- from mapFolding.dataBaskets import MatrixMeandersNumPyState
5
- from mapFolding.syntheticModules.meanders.bigInt import countBigInt
6
- from numpy import (
7
- bitwise_and, bitwise_left_shift, bitwise_or, bitwise_right_shift, bitwise_xor, greater, less_equal, multiply, subtract)
8
- from numpy.typing import NDArray
9
- from typing import Any, TYPE_CHECKING
10
- import numpy
11
-
12
- if TYPE_CHECKING:
13
- from numpy.lib._arraysetops_impl import UniqueInverseResult
14
-
15
- """More ideas for memory efficiency:
16
- - In `recordAnalysis`, use `numpy.unique_inverse` on the newly added `arcCode`.
17
- - In `recordAnalysis`, use `numpy.unique_inverse` on `arrayAnalyzed` after adding new `arcCode`.
18
- - By deduplicating more often, I can decrease the allocated size of `arrayAnalyzed`. However, that may reduce the usefulness of `makeStorage`.
19
- - I suspect that `makeStorage(numpy.flatnonzero(prepArea)...` contains a latent array.
20
- - In every case (or almost every case) I use a selector, I _feel_ like there is more memory efficient way I don't know about.
21
- - It's not clear to me whether or not I am instructing numpy to release _all_ memory I no longer need.
22
- - Hypothetically, `arcCode` might be compressible, but IDK no nothing.
23
- - `numpy.unique_inverse` uses a ton of memory, but I've failed to find a better way. BUT I might be able to improve
24
- `aggregateAnalyzed` now that `arrayArcCodes` is a single axis.
25
- - For analyzeBitsAlpha and analyzeBitsZulu, find an equivalent formula that does not require a secondary stack.
26
- - analyzeAligned requires a ton of memory. By analyzing it before the other three analyses (therefore `arrayAnalyzed` is empty)
27
- and using `makeStorage`, I've offset much of the usage, but I don't have confidence it's a good flow.
28
-
29
- To mitigate memory problems:
30
- - Put `arrayAnalyzed` in a `numpy.memmap`.
31
- """
32
-
33
- indicesPrepArea: int = 1
34
- indexAnalysis = 0
35
- slicerAnalysis: ShapeSlicer = ShapeSlicer(length=..., indices=indexAnalysis)
36
-
37
- indicesAnalyzed: int = 2
38
- indexArcCode, indexCrossings = range(indicesAnalyzed)
39
- slicerArcCode: ShapeSlicer = ShapeSlicer(length=..., indices=indexArcCode)
40
- slicerCrossings: ShapeSlicer = ShapeSlicer(length=..., indices=indexCrossings)
41
-
42
- def countNumPy(state: MatrixMeandersNumPyState) -> MatrixMeandersNumPyState:
43
- """Count crossings with transfer matrix algorithm implemented in NumPy (*Num*erical *Py*thon).
44
-
45
- Parameters
46
- ----------
47
- state : MatrixMeandersState
48
- The algorithm state.
49
-
50
- Returns
51
- -------
52
- state : MatrixMeandersState
53
- Updated state including `boundary` and `arrayMeanders`.
54
- """
55
- while state.boundary > 0 and not areIntegersWide(state):
56
- def aggregateAnalyzed(arrayAnalyzed: NDArray[numpy.uint64], state: MatrixMeandersNumPyState) -> MatrixMeandersNumPyState:
57
- """Create new `arrayMeanders` by deduplicating `arcCode` and summing `crossings`."""
58
- unique: UniqueInverseResult[numpy.uint64] = numpy.unique_inverse(arrayAnalyzed[slicerArcCode])
59
-
60
- state.arrayArcCodes = unique.values
61
- state.arrayCrossings = numpy.zeros_like(state.arrayArcCodes, dtype=state.datatypeCrossings)
62
- numpy.add.at(state.arrayCrossings, unique.inverse_indices, arrayAnalyzed[slicerCrossings])
63
- del unique
64
-
65
- return state
66
-
67
- def makeStorage[个: numpy.integer[Any]](dataTarget: NDArray[个], state: MatrixMeandersNumPyState, storageTarget: NDArray[numpy.uint64], indexAssignment: int = indexArcCode) -> NDArray[个]:
68
- """Store `dataTarget` in `storageTarget` on `indexAssignment` if there is enough space, otherwise allocate a new array."""
69
- lengthStorageTarget: int = len(storageTarget)
70
- storageAvailable: int = lengthStorageTarget - state.indexTarget
71
- lengthDataTarget: int = len(dataTarget)
72
-
73
- if storageAvailable >= lengthDataTarget:
74
- indexStart: int = lengthStorageTarget - lengthDataTarget
75
- sliceStorage: slice = slice(indexStart, lengthStorageTarget)
76
- del indexStart
77
- slicerStorageAtIndex: ShapeSlicer = ShapeSlicer(length=sliceStorage, indices=indexAssignment)
78
- del sliceStorage
79
- storageTarget[slicerStorageAtIndex] = dataTarget.copy()
80
- arrayStorage = storageTarget[slicerStorageAtIndex].view() # pyright: ignore[reportAssignmentType]
81
- del slicerStorageAtIndex
82
- else:
83
- arrayStorage: NDArray[个] = dataTarget.copy()
84
-
85
- del storageAvailable, lengthDataTarget, lengthStorageTarget
86
-
87
- return arrayStorage
88
-
89
- def recordAnalysis(arrayAnalyzed: NDArray[numpy.uint64], state: MatrixMeandersNumPyState, arcCode: NDArray[numpy.uint64]) -> MatrixMeandersNumPyState:
90
- """Record valid `arcCode` and corresponding `crossings` in `arrayAnalyzed`."""
91
- selectorOverLimit = arcCode > state.MAXIMUMarcCode
92
- arcCode[selectorOverLimit] = 0
93
- del selectorOverLimit
94
-
95
- selectorAnalysis: NDArray[numpy.intp] = numpy.flatnonzero(arcCode)
96
-
97
- indexStop: int = state.indexTarget + len(selectorAnalysis)
98
- sliceAnalysis: slice = slice(state.indexTarget, indexStop)
99
- state.indexTarget = indexStop
100
- del indexStop
101
-
102
- slicerArcCodeAnalysis = ShapeSlicer(length=sliceAnalysis, indices=indexArcCode)
103
- slicerCrossingsAnalysis = ShapeSlicer(length=sliceAnalysis, indices=indexCrossings)
104
- del sliceAnalysis
105
-
106
- arrayAnalyzed[slicerArcCodeAnalysis] = arcCode[selectorAnalysis]
107
- del slicerArcCodeAnalysis
108
-
109
- arrayAnalyzed[slicerCrossingsAnalysis] = state.arrayCrossings[selectorAnalysis]
110
- del slicerCrossingsAnalysis, selectorAnalysis
111
- goByeBye()
112
- return state
113
-
114
- state.bitWidth = int(state.arrayArcCodes.max()).bit_length()
115
-
116
- lengthArrayAnalyzed: int = getBucketsTotal(state, 1.2)
117
- shape = ShapeArray(length=lengthArrayAnalyzed, indices=indicesAnalyzed)
118
- del lengthArrayAnalyzed
119
- goByeBye()
120
-
121
- arrayAnalyzed: NDArray[numpy.uint64] = numpy.zeros(shape, dtype=state.datatypeArcCode)
122
- del shape
123
-
124
- shape = ShapeArray(length=len(state.arrayArcCodes), indices=indicesPrepArea)
125
- arrayPrepArea: NDArray[numpy.uint64] = numpy.zeros(shape, dtype=state.datatypeArcCode)
126
- del shape
127
-
128
- prepArea: NDArray[numpy.uint64] = arrayPrepArea[slicerAnalysis].view()
129
-
130
- state.indexTarget = 0
131
-
132
- state.boundary -= 1
133
-
134
- # =============== analyze aligned ===== if bitsAlpha > 1 and bitsZulu > 1 =============================================
135
- arrayBitsAlpha: NDArray[numpy.uint64] = bitwise_and(state.arrayArcCodes, state.locatorBits) # NOTE extra array
136
- # ======= > * > bitsAlpha 1 bitsZulu 1 ====================
137
- greater(arrayBitsAlpha, 1, out=prepArea)
138
- bitsZuluStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexCrossings)
139
- bitwise_right_shift(bitsZuluStack, 1, out=bitsZuluStack) # O indexArcCode X indexCrossings
140
- bitwise_and(bitsZuluStack, state.locatorBits, out=bitsZuluStack)
141
- multiply(bitsZuluStack, prepArea, out=prepArea)
142
- greater(prepArea, 1, out=prepArea)
143
- selectorGreaterThan1: NDArray[numpy.uint64] = makeStorage(prepArea, state, arrayAnalyzed, indexArcCode)
144
- # X indexArcCode X indexCrossings
145
- # ======= if bitsAlphaAtEven and not bitsZuluAtEven =======
146
- # ======= ^ & | ^ & bitsZulu 1 1 bitsAlpha 1 1 ============
147
- bitwise_and(bitsZuluStack, 1, out=prepArea)
148
- del bitsZuluStack # X indexArcCode O indexCrossings
149
- bitwise_xor(prepArea, 1, out=prepArea)
150
- bitwise_or(arrayBitsAlpha, prepArea, out=prepArea)
151
- bitwise_and(prepArea, 1, out=prepArea)
152
- bitwise_xor(prepArea, 1, out=prepArea)
153
-
154
- bitwise_and(selectorGreaterThan1, prepArea, out=prepArea)
155
- selectorAlignAlpha: NDArray[numpy.intp] = makeStorage(numpy.flatnonzero(prepArea), state, arrayAnalyzed, indexCrossings)
156
- # X indexArcCode X indexCrossings
157
- arrayBitsAlpha[selectorAlignAlpha] = flipTheExtra_0b1AsUfunc(arrayBitsAlpha[selectorAlignAlpha])
158
- del selectorAlignAlpha # X indexArcCode O indexCrossings
159
-
160
- # ======= if bitsZuluAtEven and not bitsAlphaAtEven =======
161
- # ======= ^ & | ^ & bitsAlpha 1 1 bitsZulu 1 1 ============
162
- bitsAlphaStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexCrossings)
163
- bitwise_and(bitsAlphaStack, state.locatorBits, out=bitsAlphaStack)
164
- bitwise_and(bitsAlphaStack, 1, out=prepArea)
165
- del bitsAlphaStack # X indexArcCode O indexCrossings
166
- bitwise_xor(prepArea, 1, out=prepArea)
167
- bitsZuluStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexCrossings)
168
- bitwise_right_shift(bitsZuluStack, 1, out=bitsZuluStack)
169
- bitwise_and(bitsZuluStack, state.locatorBits, out=bitsZuluStack)
170
- bitwise_or(bitsZuluStack, prepArea, out=prepArea)
171
- del bitsZuluStack # X indexArcCode O indexCrossings
172
- bitwise_and(prepArea, 1, out=prepArea)
173
- bitwise_xor(prepArea, 1, out=prepArea)
174
-
175
- bitwise_and(selectorGreaterThan1, prepArea, out=prepArea)
176
- selectorAlignZulu: NDArray[numpy.intp] = makeStorage(numpy.flatnonzero(prepArea), state, arrayAnalyzed, indexCrossings)
177
- # X indexArcCode X indexCrossings
178
- # ======= bitsAlphaAtEven or bitsZuluAtEven ===============
179
- bitwise_and(state.arrayArcCodes, state.locatorBits, out=prepArea)
180
- # ======= ^ & & bitsAlpha 1 bitsZulu 1 ====================
181
- bitwise_and(prepArea, 1, out=prepArea)
182
- sherpaBitsZulu: NDArray[numpy.uint64] = bitwise_right_shift(state.arrayArcCodes, 1) # NOTE 2° extra array
183
- bitwise_and(sherpaBitsZulu, state.locatorBits, out=sherpaBitsZulu)
184
- bitwise_and(sherpaBitsZulu, prepArea, out=prepArea)
185
- del sherpaBitsZulu # NOTE del 2° extra array
186
- bitwise_xor(prepArea, 1, out=prepArea)
187
-
188
- bitwise_and(selectorGreaterThan1, prepArea, out=prepArea) # selectorBitsAtEven
189
- del selectorGreaterThan1 # O indexArcCode X indexCrossings
190
- bitwise_xor(prepArea, 1, out=prepArea)
191
- selectorDisqualified: NDArray[numpy.intp] = makeStorage(numpy.flatnonzero(prepArea), state, arrayAnalyzed, indexArcCode)
192
- # X indexArcCode X indexCrossings
193
- bitwise_right_shift(state.arrayArcCodes, 1, out=prepArea)
194
- bitwise_and(prepArea, state.locatorBits, out=prepArea)
195
-
196
- prepArea[selectorAlignZulu] = flipTheExtra_0b1AsUfunc(prepArea[selectorAlignZulu])
197
- del selectorAlignZulu # X indexArcCode O indexCrossings
198
-
199
- bitsZuluStack: NDArray[numpy.uint64] = makeStorage(prepArea, state, arrayAnalyzed, indexCrossings)
200
-
201
- # ======= (((bitsZulu >> 2) << 3) | bitsAlpha) >> 2 =======
202
- # ======= >> | << >> bitsZulu 2 3 bitsAlpha 2 =============
203
- bitwise_right_shift(bitsZuluStack, 2, out=prepArea)
204
- del bitsZuluStack # X indexArcCode O indexCrossings
205
- bitwise_left_shift(prepArea, 3, out=prepArea)
206
- bitwise_or(arrayBitsAlpha, prepArea, out=prepArea)
207
- del arrayBitsAlpha # NOTE del extra array
208
- bitwise_right_shift(prepArea, 2, out=prepArea)
209
-
210
- prepArea[selectorDisqualified] = 0
211
- del selectorDisqualified # O indexArcCode O indexCrossings
212
-
213
- state = recordAnalysis(arrayAnalyzed, state, prepArea)
214
-
215
- # ----------------- analyze bitsAlpha ------- (bitsAlpha >> 2) | (bitsZulu << 3) | ((1 - (bitsAlpha & 1)) << 1) ---------
216
- bitsAlphaStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexArcCode)
217
- bitwise_and(bitsAlphaStack, state.locatorBits, out=bitsAlphaStack) # X indexArcCode O indexCrossings
218
- # ------- >> | << | (<< - 1 & bitsAlpha 1 1) << bitsZulu 3 2 bitsAlpha 2 ----------
219
- bitwise_and(bitsAlphaStack, 1, out=bitsAlphaStack)
220
- subtract(1, bitsAlphaStack, out=bitsAlphaStack)
221
- bitwise_left_shift(bitsAlphaStack, 1, out=bitsAlphaStack)
222
- bitsZuluStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexCrossings)
223
- bitwise_right_shift(bitsZuluStack, 1, out=bitsZuluStack)
224
- bitwise_and(bitsZuluStack, state.locatorBits, out=bitsZuluStack)
225
- bitwise_left_shift(bitsZuluStack, 3, out=prepArea)
226
- del bitsZuluStack # X indexArcCode O indexCrossings
227
- bitwise_or(bitsAlphaStack, prepArea, out=prepArea)
228
- del bitsAlphaStack # O indexArcCode O indexCrossings
229
- bitwise_left_shift(prepArea, 2, out=prepArea)
230
- bitsAlphaStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexCrossings)
231
- bitwise_and(bitsAlphaStack, state.locatorBits, out=bitsAlphaStack) # O indexArcCode X indexCrossings
232
- bitwise_or(bitsAlphaStack, prepArea, out=prepArea)
233
- bitwise_right_shift(prepArea, 2, out=prepArea)
234
-
235
- # ------- if bitsAlpha > 1 ------------ > bitsAlpha 1 -----
236
- less_equal(bitsAlphaStack, 1, out=bitsAlphaStack)
237
- selectorUnderLimit: NDArray[numpy.intp] = makeStorage(numpy.flatnonzero(bitsAlphaStack), state, arrayAnalyzed, indexArcCode)
238
- del bitsAlphaStack # X indexArcCode O indexCrossings
239
- prepArea[selectorUnderLimit] = 0
240
- del selectorUnderLimit # O indexArcCode O indexCrossings
241
-
242
- state = recordAnalysis(arrayAnalyzed, state, prepArea)
243
-
244
- # ----------------- analyze bitsZulu ---------- (bitsZulu >> 1) | (bitsAlpha << 2) | (1 - (bitsZulu & 1)) -------------
245
- arrayBitsZulu: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexCrossings)
246
- arrayBitsZulu = bitwise_right_shift(arrayBitsZulu, 1) # O indexArcCode X indexCrossings
247
- arrayBitsZulu = bitwise_and(arrayBitsZulu, state.locatorBits)
248
- # ------- >> | << | (- 1 & bitsZulu 1) << bitsAlpha 2 1 bitsZulu 1 ----------
249
- bitwise_and(arrayBitsZulu, 1, out=arrayBitsZulu)
250
- subtract(1, arrayBitsZulu, out=arrayBitsZulu)
251
- bitsAlphaStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexArcCode)
252
- bitwise_and(bitsAlphaStack, state.locatorBits, out=bitsAlphaStack) # X indexArcCode X indexCrossings
253
- bitwise_left_shift(bitsAlphaStack, 2, out=prepArea)
254
- del bitsAlphaStack # O indexArcCode X indexCrossings
255
- bitwise_or(arrayBitsZulu, prepArea, out=prepArea)
256
- del arrayBitsZulu # O indexArcCode O indexCrossings
257
- bitwise_left_shift(prepArea, 1, out=prepArea)
258
- bitsZuluStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexCrossings)
259
- bitwise_right_shift(bitsZuluStack, 1, out=bitsZuluStack) # O indexArcCode X indexCrossings
260
- bitwise_and(bitsZuluStack, state.locatorBits, out=bitsZuluStack)
261
- bitwise_or(bitsZuluStack, prepArea, out=prepArea)
262
- bitwise_right_shift(prepArea, 1, out=prepArea)
263
-
264
- # ------- if bitsZulu > 1 ------------- > bitsZulu 1 ------
265
- less_equal(bitsZuluStack, 1, out=bitsZuluStack)
266
- selectorUnderLimit = makeStorage(numpy.flatnonzero(bitsZuluStack), state, arrayAnalyzed, indexArcCode)
267
- del bitsZuluStack # X indexArcCode O indexCrossings
268
- prepArea[selectorUnderLimit] = 0
269
- del selectorUnderLimit # O indexArcCode O indexCrossings
270
-
271
- state = recordAnalysis(arrayAnalyzed, state, prepArea)
272
-
273
- # ----------------- analyze simple ------------------------ ((bitsAlpha | (bitsZulu << 1)) << 2) | 3 ------------------
274
- bitsZuluStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexCrossings)
275
- bitwise_right_shift(bitsZuluStack, 1, out=bitsZuluStack) # O indexArcCode X indexCrossings
276
- bitwise_and(bitsZuluStack, state.locatorBits, out=bitsZuluStack)
277
- # ------- | << | bitsAlpha << bitsZulu 1 2 3 --------------
278
- bitwise_left_shift(bitsZuluStack, 1, out=prepArea)
279
- del bitsZuluStack # O indexArcCode O indexCrossings
280
- bitsAlphaStack: NDArray[numpy.uint64] = makeStorage(state.arrayArcCodes, state, arrayAnalyzed, indexArcCode)
281
- bitwise_and(bitsAlphaStack, state.locatorBits, out=bitsAlphaStack) # X indexArcCode O indexCrossings
282
- bitwise_or(bitsAlphaStack, prepArea, out=prepArea)
283
- del bitsAlphaStack # O indexArcCode O indexCrossings
284
- bitwise_left_shift(prepArea, 2, out=prepArea)
285
- bitwise_or(prepArea, 3, out=prepArea)
286
-
287
- state = recordAnalysis(arrayAnalyzed, state, prepArea)
288
-
289
- del prepArea, arrayPrepArea
290
- # ----------------------------------------------- aggregation ---------------------------------------------------------
291
- state.arrayArcCodes = numpy.zeros((0,), dtype=state.datatypeArcCode)
292
- arrayAnalyzed.resize((state.indexTarget, indicesAnalyzed))
293
-
294
- goByeBye()
295
- state = aggregateAnalyzed(arrayAnalyzed, state)
296
-
297
- del arrayAnalyzed
298
-
299
- if state.n >= 45:
300
- # oeisID,n,boundary,buckets,arcCodes,arcCodeBitWidth,crossingsBitWidth
301
- print(state.oeisID, state.n, state.boundary+1, state.indexTarget, len(state.arrayArcCodes), int(state.arrayArcCodes.max()).bit_length(), int(state.arrayCrossings.max()).bit_length(), sep=',') # noqa: T201
302
- return state
303
-
304
- def doTheNeedful(state: MatrixMeandersNumPyState) -> int:
305
- """Compute `crossings` with a transfer matrix algorithm implemented in NumPy.
306
-
307
- Parameters
308
- ----------
309
- state : MatrixMeandersState
310
- The algorithm state.
311
-
312
- Returns
313
- -------
314
- crossings : int
315
- The computed value of `crossings`.
316
-
317
- Notes
318
- -----
319
- Citation: https://github.com/hunterhogan/mapFolding/blob/main/citations/Jensen.bibtex
320
-
321
- See Also
322
- --------
323
- https://oeis.org/A000682
324
- https://oeis.org/A005316
325
- """
326
- while state.boundary > 0:
327
- if areIntegersWide(state):
328
- state = countBigInt(state)
329
- else:
330
- state.makeArray()
331
- state = countNumPy(state)
332
- state.makeDictionary()
333
- return sum(state.dictionaryMeanders.values())
@@ -1,334 +0,0 @@
1
- from gc import collect as goByeBye
2
- from mapFolding.algorithms.matrixMeandersBeDry import areIntegersWide, flipTheExtra_0b1AsUfunc, getBucketsTotal
3
- from mapFolding.dataBaskets import MatrixMeandersNumPyState
4
- from mapFolding.syntheticModules.meanders.bigInt import countBigInt
5
- from warnings import warn
6
- import pandas
7
-
8
- def countPandas(state: MatrixMeandersNumPyState) -> MatrixMeandersNumPyState:
9
- """Count meanders with matrix transfer algorithm using pandas DataFrame.
10
-
11
- Parameters
12
- ----------
13
- state : MatrixMeandersState
14
- The algorithm state containing current `boundary`, `dictionaryMeanders`, and thresholds.
15
-
16
- Returns
17
- -------
18
- state : MatrixMeandersState
19
- Updated state with new `boundary` and `dictionaryMeanders`.
20
- """
21
- dataframeAnalyzed = pandas.DataFrame({
22
- 'analyzed': pandas.Series(name='analyzed', data=state.dictionaryMeanders.keys(), copy=False, dtype=state.datatypeArcCode)
23
- , 'crossings': pandas.Series(name='crossings', data=state.dictionaryMeanders.values(), copy=False, dtype=state.datatypeCrossings)
24
- }
25
- )
26
- state.dictionaryMeanders.clear()
27
-
28
- while (state.boundary > 0 and not areIntegersWide(state, dataframe=dataframeAnalyzed)):
29
-
30
- def aggregateArcCodes() -> None:
31
- nonlocal dataframeAnalyzed
32
- dataframeAnalyzed = dataframeAnalyzed.iloc[0:state.indexTarget].groupby('analyzed', sort=False)['crossings'].aggregate('sum').reset_index()
33
-
34
- def analyzeArcCodesAligned(dataframeMeanders: pandas.DataFrame) -> pandas.DataFrame:
35
- """Compute `arcCode` from `bitsAlpha` and `bitsZulu` if at least one is an even number.
36
-
37
- Before computing `arcCode`, some values of `bitsAlpha` and `bitsZulu` are modified.
38
-
39
- Warning
40
- -------
41
- This function deletes rows from `dataframeMeanders`. Always run this analysis last.
42
-
43
- Formula
44
- -------
45
- ```python
46
- if bitsAlpha > 1 and bitsZulu > 1 and (bitsAlphaIsEven or bitsZuluIsEven):
47
- arcCode = (bitsAlpha >> 2) | ((bitsZulu >> 2) << 1)
48
- ```
49
- """
50
- # NOTE Step 1 drop unqualified rows
51
- # ======= > * > bitsAlpha 1 bitsZulu 1 ====================
52
- dataframeMeanders['analyzed'] = dataframeMeanders['arcCode'].copy() # `bitsAlpha`
53
- dataframeMeanders['analyzed'] &= state.locatorBits # `bitsAlpha`
54
-
55
- dataframeMeanders['analyzed'] = dataframeMeanders['analyzed'].gt(1) # if bitsAlphaHasArcs
56
-
57
- bitsTarget: pandas.Series = dataframeMeanders['arcCode'].copy() # `bitsZulu`
58
- bitsTarget //= 2**1 # `bitsZulu` (bitsZulu >> 1)
59
- bitsTarget &= state.locatorBits # `bitsZulu`
60
-
61
- dataframeMeanders['analyzed'] *= bitsTarget
62
- del bitsTarget
63
- dataframeMeanders = dataframeMeanders.loc[(dataframeMeanders['analyzed'] > 1)] # if (bitsAlphaHasArcs and bitsZuluHasArcs)
64
-
65
- # ======= ^ & & bitsAlpha 1 bitsZulu 1 ====================
66
- dataframeMeanders.loc[:, 'analyzed'] = dataframeMeanders['arcCode'].copy() # `bitsAlpha`
67
- dataframeMeanders.loc[:, 'analyzed'] &= state.locatorBits # `bitsAlpha`
68
-
69
- dataframeMeanders.loc[:, 'analyzed'] &= 1 # `bitsAlpha`
70
-
71
- bitsTarget: pandas.Series = dataframeMeanders['arcCode'].copy() # `bitsZulu`
72
- bitsTarget //= 2**1 # `bitsZulu` (bitsZulu >> 1)
73
- bitsTarget &= state.locatorBits # `bitsZulu`
74
-
75
- dataframeMeanders.loc[:, 'analyzed'] &= bitsTarget
76
- del bitsTarget
77
- dataframeMeanders.loc[:, 'analyzed'] ^= 1
78
-
79
- dataframeMeanders = dataframeMeanders.loc[(dataframeMeanders['analyzed'] > 0)] # if (bitsAlphaIsEven or bitsZuluIsEven)
80
-
81
- # NOTE Step 2 modify rows
82
- # Make a selector for bitsZuluAtOdd, so you can modify bitsAlpha
83
- dataframeMeanders.loc[:, 'analyzed'] = dataframeMeanders['arcCode'].copy() # `bitsZulu`
84
- dataframeMeanders.loc[:, 'analyzed'] //= 2**1 # `bitsZulu` (bitsZulu >> 1)
85
- dataframeMeanders.loc[:, 'analyzed'] &= 1 # selectorBitsZuluAtOdd
86
-
87
- bitsTarget = dataframeMeanders['arcCode'].copy() # `bitsAlpha`
88
- bitsTarget &= state.locatorBits # `bitsAlpha`
89
-
90
- # if bitsAlphaAtEven and not bitsZuluAtEven, modify bitsAlphaPairedToOdd
91
- bitsTarget.loc[(dataframeMeanders['analyzed'] > 0)] = state.datatypeArcCode(
92
- flipTheExtra_0b1AsUfunc(bitsTarget.loc[(dataframeMeanders['analyzed'] > 0)]))
93
-
94
- dataframeMeanders.loc[:, 'analyzed'] = dataframeMeanders['arcCode'].copy() # `bitsZulu`
95
- dataframeMeanders.loc[:, 'analyzed'] //= 2**1 # `bitsZulu` (bitsZulu >> 1)
96
- dataframeMeanders.loc[:, 'analyzed'] &= state.locatorBits # `bitsZulu`
97
-
98
- # if bitsZuluAtEven and not bitsAlphaAtEven, modify bitsZuluPairedToOdd
99
- dataframeMeanders.loc[((dataframeMeanders.loc[:, 'arcCode'] & 1) > 0), 'analyzed'] = state.datatypeArcCode(
100
- flipTheExtra_0b1AsUfunc(dataframeMeanders.loc[((dataframeMeanders.loc[:, 'arcCode'] & 1) > 0), 'analyzed']))
101
-
102
- # NOTE Step 3 compute arcCode
103
- # ======= >> | << >> bitsZulu 2 3 bitsAlpha 2 =============
104
- dataframeMeanders.loc[:, 'analyzed'] //= 2**2 # (bitsZulu >> 2)
105
- dataframeMeanders.loc[:, 'analyzed'] *= 2**3 # (bitsZulu << 3)
106
- dataframeMeanders.loc[:, 'analyzed'] |= bitsTarget
107
- del bitsTarget
108
- dataframeMeanders.loc[:, 'analyzed'] //= 2**2 # (... >> 2)
109
-
110
- dataframeMeanders.loc[dataframeMeanders['analyzed'] >= state.MAXIMUMarcCode, 'analyzed'] = 0
111
-
112
- return dataframeMeanders
113
-
114
- def analyzeArcCodesSimple(dataframeMeanders: pandas.DataFrame) -> pandas.DataFrame:
115
- """Compute arcCode with the 'simple' formula.
116
-
117
- Formula
118
- -------
119
- ```python
120
- arcCode = ((bitsAlpha | (bitsZulu << 1)) << 2) | 3
121
- ```
122
-
123
- Notes
124
- -----
125
- Using `+= 3` instead of `|= 3` is valid in this specific case. Left shift by two means the last bits are '0b00'. '0 + 3'
126
- is '0b11', and '0b00 | 0b11' is also '0b11'.
127
-
128
- """
129
- dataframeMeanders['analyzed'] = dataframeMeanders['arcCode']
130
- dataframeMeanders.loc[:, 'analyzed'] &= state.locatorBits
131
-
132
- bitsZulu: pandas.Series = dataframeMeanders['arcCode'].copy()
133
- bitsZulu //= 2**1 # (bitsZulu >> 1)
134
- bitsZulu &= state.locatorBits # `bitsZulu`
135
-
136
- bitsZulu *= 2**1 # (bitsZulu << 1)
137
-
138
- dataframeMeanders.loc[:, 'analyzed'] |= bitsZulu # ((bitsAlpha | (bitsZulu ...))
139
-
140
- del bitsZulu
141
-
142
- dataframeMeanders.loc[:, 'analyzed'] *= 2**2 # (... << 2)
143
- dataframeMeanders.loc[:, 'analyzed'] += 3 # (...) | 3
144
- dataframeMeanders.loc[dataframeMeanders['analyzed'] >= state.MAXIMUMarcCode, 'analyzed'] = 0
145
-
146
- return dataframeMeanders
147
-
148
- def analyzeBitsAlpha(dataframeMeanders: pandas.DataFrame) -> pandas.DataFrame:
149
- """Compute `arcCode` from `bitsAlpha`.
150
-
151
- Formula
152
- -------
153
- ```python
154
- if bitsAlpha > 1:
155
- arcCode = ((1 - (bitsAlpha & 1)) << 1) | (bitsZulu << 3) | (bitsAlpha >> 2)
156
- # `(1 - (bitsAlpha & 1)` is an evenness test.
157
- ```
158
- """
159
- dataframeMeanders['analyzed'] = dataframeMeanders['arcCode']
160
- dataframeMeanders.loc[:, 'analyzed'] &= 1 # (bitsAlpha & 1)
161
- dataframeMeanders.loc[:, 'analyzed'] ^= 1 # (1 - (bitsAlpha ...))
162
-
163
- dataframeMeanders.loc[:, 'analyzed'] *= 2**1 # ((bitsAlpha ...) << 1)
164
-
165
- bitsTarget: pandas.Series = dataframeMeanders['arcCode'].copy() # `bitsZulu`
166
- bitsTarget //= 2**1 # `bitsZulu` (bitsZulu >> 1)
167
- bitsTarget &= state.locatorBits # `bitsZulu`
168
-
169
- bitsTarget *= 2**3 # (bitsZulu << 3)
170
- dataframeMeanders.loc[:, 'analyzed'] |= bitsTarget # ... | (bitsZulu ...)
171
-
172
- del bitsTarget
173
-
174
- """NOTE In this code block, I rearranged the "formula" to use `bitsTarget` for two goals. 1. `(bitsAlpha >> 2)`.
175
- 2. `if bitsAlpha > 1`. The trick is in the equivalence of v1 and v2.
176
- v1: BITScow | (BITSwalk >> 2)
177
- v2: ((BITScow << 2) | BITSwalk) >> 2
178
-
179
- The "formula" calls for v1, but by using v2, `bitsTarget` is not changed. Therefore, because `bitsTarget` is
180
- `bitsAlpha`, I can use `bitsTarget` for goal 2, `if bitsAlpha > 1`.
181
- """
182
- dataframeMeanders.loc[:, 'analyzed'] *= 2**2 # ... | (bitsAlpha >> 2)
183
-
184
- bitsTarget = dataframeMeanders['arcCode'].copy() # `bitsAlpha`
185
- bitsTarget &= state.locatorBits # `bitsAlpha`
186
-
187
- dataframeMeanders.loc[:, 'analyzed'] |= bitsTarget # ... | (bitsAlpha)
188
- dataframeMeanders.loc[:, 'analyzed'] //= 2**2 # (... >> 2)
189
-
190
- dataframeMeanders.loc[(bitsTarget <= 1), 'analyzed'] = 0 # if bitsAlpha > 1
191
-
192
- del bitsTarget
193
-
194
- dataframeMeanders.loc[dataframeMeanders['analyzed'] >= state.MAXIMUMarcCode, 'analyzed'] = 0
195
-
196
- return dataframeMeanders
197
-
198
- def analyzeBitsZulu(dataframeMeanders: pandas.DataFrame) -> pandas.DataFrame:
199
- """Compute `arcCode` from `bitsZulu`.
200
-
201
- Formula
202
- -------
203
- ```python
204
- if bitsZulu > 1:
205
- arcCode = (1 - (bitsZulu & 1)) | (bitsAlpha << 2) | (bitsZulu >> 1)
206
- ```
207
- """
208
- # NOTE `(1 - (bitsZulu & 1))` is an evenness test: we want a single bit as the answer.
209
- dataframeMeanders.loc[:, 'analyzed'] = dataframeMeanders['arcCode'] # `bitsZulu`
210
- dataframeMeanders.loc[:, 'analyzed'] //= 2**1 # `bitsZulu` (bitsZulu >> 1)
211
- dataframeMeanders.loc[:, 'analyzed'] &= 1 # `bitsZulu`
212
- dataframeMeanders.loc[:, 'analyzed'] &= 1 # (bitsZulu & 1)
213
- dataframeMeanders.loc[:, 'analyzed'] ^= 1 # (1 - (bitsZulu ...))
214
-
215
- bitsTarget: pandas.Series = dataframeMeanders['arcCode'].copy() # `bitsAlpha`
216
- bitsTarget &= state.locatorBits # `bitsAlpha`
217
-
218
- bitsTarget *= 2**2 # (bitsAlpha << 2)
219
- dataframeMeanders.loc[:, 'analyzed'] |= bitsTarget # ... | (bitsAlpha ...)
220
- del bitsTarget
221
-
222
- # NOTE Same trick as in `analyzeBitsAlpha`.
223
- dataframeMeanders.loc[:, 'analyzed'] *= 2**1 # (... << 1)
224
-
225
- bitsTarget = dataframeMeanders['arcCode'].copy() # `bitsZulu`
226
- bitsTarget //= 2**1 # `bitsZulu` (bitsZulu >> 1)
227
- bitsTarget &= state.locatorBits # `bitsZulu`
228
-
229
- dataframeMeanders.loc[:, 'analyzed'] |= bitsTarget # ... | (bitsZulu)
230
- dataframeMeanders.loc[:, 'analyzed'] //= 2**1 # (... >> 1)
231
-
232
- dataframeMeanders.loc[bitsTarget <= 1, 'analyzed'] = 0 # if bitsZulu > 1
233
- del bitsTarget
234
-
235
- dataframeMeanders.loc[dataframeMeanders['analyzed'] >= state.MAXIMUMarcCode, 'analyzed'] = 0
236
-
237
- return dataframeMeanders
238
-
239
- def recordArcCodes(dataframeMeanders: pandas.DataFrame) -> pandas.DataFrame:
240
- nonlocal dataframeAnalyzed
241
-
242
- indexStopAnalyzed: int = state.indexTarget + int((dataframeMeanders['analyzed'] > 0).sum())
243
-
244
- if indexStopAnalyzed > state.indexTarget:
245
- if len(dataframeAnalyzed.index) < indexStopAnalyzed:
246
- warn(f"Lengthened `dataframeAnalyzed` from {len(dataframeAnalyzed.index)} to {indexStopAnalyzed=}; n={state.n}, {state.boundary=}.", stacklevel=2)
247
- dataframeAnalyzed = dataframeAnalyzed.reindex(index=pandas.RangeIndex(indexStopAnalyzed), fill_value=0)
248
-
249
- dataframeAnalyzed.loc[state.indexTarget:indexStopAnalyzed - 1, ['analyzed']] = (
250
- dataframeMeanders.loc[(dataframeMeanders['analyzed'] > 0), ['analyzed']
251
- ].to_numpy(dtype=state.datatypeArcCode, copy=False)
252
- )
253
-
254
- dataframeAnalyzed.loc[state.indexTarget:indexStopAnalyzed - 1, ['crossings']] = (
255
- dataframeMeanders.loc[(dataframeMeanders['analyzed'] > 0), ['crossings']
256
- ].to_numpy(dtype=state.datatypeCrossings, copy=False)
257
- )
258
-
259
- state.indexTarget = indexStopAnalyzed
260
-
261
- del indexStopAnalyzed
262
-
263
- return dataframeMeanders
264
-
265
- dataframeMeanders = pandas.DataFrame({
266
- 'arcCode': pandas.Series(name='arcCode', data=dataframeAnalyzed['analyzed'], copy=False, dtype=state.datatypeArcCode)
267
- , 'analyzed': pandas.Series(name='analyzed', data=0, dtype=state.datatypeArcCode)
268
- , 'crossings': pandas.Series(name='crossings', data=dataframeAnalyzed['crossings'], copy=False, dtype=state.datatypeCrossings)
269
- }
270
- )
271
-
272
- del dataframeAnalyzed
273
- goByeBye()
274
-
275
- state.bitWidth = int(dataframeMeanders['arcCode'].max()).bit_length()
276
- length: int = getBucketsTotal(state)
277
- dataframeAnalyzed = pandas.DataFrame({
278
- 'analyzed': pandas.Series(name='analyzed', data=0, index=pandas.RangeIndex(length), dtype=state.datatypeArcCode)
279
- , 'crossings': pandas.Series(name='crossings', data=0, index=pandas.RangeIndex(length), dtype=state.datatypeCrossings)
280
- }, index=pandas.RangeIndex(length)
281
- )
282
-
283
- state.boundary -= 1
284
-
285
- state.indexTarget = 0
286
-
287
- dataframeMeanders: pandas.DataFrame = analyzeArcCodesSimple(dataframeMeanders)
288
- dataframeMeanders = recordArcCodes(dataframeMeanders)
289
-
290
- dataframeMeanders = analyzeBitsAlpha(dataframeMeanders)
291
- dataframeMeanders = recordArcCodes(dataframeMeanders)
292
-
293
- dataframeMeanders = analyzeBitsZulu(dataframeMeanders)
294
- dataframeMeanders = recordArcCodes(dataframeMeanders)
295
-
296
- dataframeMeanders = analyzeArcCodesAligned(dataframeMeanders)
297
- dataframeMeanders = recordArcCodes(dataframeMeanders)
298
- del dataframeMeanders
299
- goByeBye()
300
-
301
- aggregateArcCodes()
302
-
303
- state.dictionaryMeanders = dataframeAnalyzed.set_index('analyzed')['crossings'].to_dict()
304
- del dataframeAnalyzed
305
- return state
306
-
307
- def doTheNeedful(state: MatrixMeandersNumPyState) -> int:
308
- """Compute `crossings` with a transfer matrix algorithm implemented in pandas.
309
-
310
- Parameters
311
- ----------
312
- state : MatrixMeandersState
313
- The algorithm state.
314
-
315
- Returns
316
- -------
317
- crossings : int
318
- The computed value of `crossings`.
319
-
320
- Notes
321
- -----
322
- Citation: https://github.com/hunterhogan/mapFolding/blob/main/citations/Jensen.bibtex
323
-
324
- See Also
325
- --------
326
- https://oeis.org/A000682
327
- https://oeis.org/A005316
328
- """
329
- while state.boundary > 0:
330
- if areIntegersWide(state):
331
- state = countBigInt(state)
332
- else:
333
- state = countPandas(state)
334
- return sum(state.dictionaryMeanders.values())