mapFolding 0.15.3__py3-none-any.whl → 0.16.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.
- mapFolding/__init__.py +22 -20
- mapFolding/_theSSOT.py +56 -62
- mapFolding/_theTypes.py +66 -4
- mapFolding/algorithms/__init__.py +1 -0
- mapFolding/{daoOfMapFolding.py → algorithms/daoOfMapFolding.py} +1 -2
- mapFolding/algorithms/getBucketsTotal.py +137 -0
- mapFolding/algorithms/matrixMeanders.py +519 -0
- mapFolding/algorithms/oeisIDbyFormula.py +347 -0
- mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +84 -0
- mapFolding/basecamp.py +151 -14
- mapFolding/dataBaskets.py +74 -0
- mapFolding/oeis.py +43 -56
- mapFolding/reference/A000682facts.py +662 -0
- mapFolding/reference/A005316facts.py +62 -0
- mapFolding/reference/matrixMeandersAnalysis/__init__.py +1 -0
- mapFolding/reference/matrixMeandersAnalysis/evenEven.py +144 -0
- mapFolding/reference/matrixMeandersAnalysis/oddEven.py +54 -0
- mapFolding/{_oeisFormulas/matrixMeanders64.py → reference/meandersDumpingGround/matrixMeanders64retired.py} +37 -29
- mapFolding/someAssemblyRequired/A007822/A007822rawMaterials.py +55 -0
- mapFolding/someAssemblyRequired/A007822/__init__.py +0 -0
- mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +185 -0
- mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +71 -0
- mapFolding/someAssemblyRequired/RecipeJob.py +2 -2
- 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 +1 -1
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +5 -2
- mapFolding/someAssemblyRequired/makingModules_count.py +301 -0
- mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +120 -0
- mapFolding/someAssemblyRequired/mapFolding/__init__.py +0 -0
- mapFolding/someAssemblyRequired/mapFolding/makeMapFoldingModules.py +220 -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/A007822/asynchronous.py +148 -0
- mapFolding/syntheticModules/A007822/asynchronousAnnex.py +68 -0
- mapFolding/syntheticModules/A007822/asynchronousTheorem2.py +53 -0
- mapFolding/syntheticModules/A007822/asynchronousTrimmed.py +47 -0
- mapFolding/syntheticModules/dataPackingA007822.py +1 -1
- mapFolding/tests/conftest.py +28 -9
- mapFolding/tests/test_computations.py +32 -10
- mapFolding/tests/test_oeis.py +2 -20
- mapFolding/trim_memory.py +62 -0
- mapFolding/zCuzDocStoopid/__init__.py +1 -0
- mapFolding/zCuzDocStoopid/makeDocstrings.py +63 -0
- {mapfolding-0.15.3.dist-info → mapfolding-0.16.0.dist-info}/METADATA +9 -2
- mapfolding-0.16.0.dist-info/RECORD +100 -0
- {mapfolding-0.15.3.dist-info → mapfolding-0.16.0.dist-info}/entry_points.txt +0 -1
- mapFolding/_oeisFormulas/A000136.py +0 -4
- mapFolding/_oeisFormulas/A000560.py +0 -4
- mapFolding/_oeisFormulas/A000682.py +0 -85
- mapFolding/_oeisFormulas/A001010.py +0 -19
- mapFolding/_oeisFormulas/A001011.py +0 -5
- mapFolding/_oeisFormulas/A005315.py +0 -4
- mapFolding/_oeisFormulas/A005316.py +0 -10
- mapFolding/_oeisFormulas/A223094.py +0 -7
- mapFolding/_oeisFormulas/A259702.py +0 -4
- mapFolding/_oeisFormulas/A301620.py +0 -6
- mapFolding/_oeisFormulas/Z0Z_aOFn.py +0 -34
- mapFolding/_oeisFormulas/Z0Z_notes.py +0 -16
- mapFolding/_oeisFormulas/Z0Z_oeisMeanders.py +0 -74
- mapFolding/_oeisFormulas/Z0Z_symmetry.py +0 -131
- mapFolding/_oeisFormulas/__init__.py +0 -1
- mapFolding/_oeisFormulas/matrixMeanders.py +0 -134
- mapFolding/_oeisFormulas/matrixMeandersAnnex.py +0 -84
- mapFolding/someAssemblyRequired/A007822rawMaterials.py +0 -46
- mapFolding/someAssemblyRequired/makeAllModules.py +0 -764
- mapfolding-0.15.3.dist-info/RECORD +0 -92
- /mapFolding/reference/{A005316JavaPort.py → meandersDumpingGround/A005316JavaPort.py} +0 -0
- /mapFolding/reference/{A005316imperative.py → meandersDumpingGround/A005316imperative.py} +0 -0
- /mapFolding/reference/{A005316intOptimized.py → meandersDumpingGround/A005316intOptimized.py} +0 -0
- /mapFolding/reference/{A005316optimized128bit.py → meandersDumpingGround/A005316optimized128bit.py} +0 -0
- /mapFolding/reference/{A005316primitiveOptimized.py → meandersDumpingGround/A005316primitiveOptimized.py} +0 -0
- /mapFolding/reference/{A005316redis.py → meandersDumpingGround/A005316redis.py} +0 -0
- /mapFolding/reference/{A005316write2disk.py → meandersDumpingGround/A005316write2disk.py} +0 -0
- /mapFolding/reference/{matrixMeandersBaseline.py → meandersDumpingGround/matrixMeandersBaseline.py} +0 -0
- /mapFolding/reference/{matrixMeandersBaselineAnnex.py → meandersDumpingGround/matrixMeandersBaselineAnnex.py} +0 -0
- /mapFolding/reference/{matrixMeandersBaselineV2.py → meandersDumpingGround/matrixMeandersBaselineV2.py} +0 -0
- /mapFolding/reference/{matrixMeandersSimpleQueue.py → meandersDumpingGround/matrixMeandersSimpleQueue.py} +0 -0
- /mapFolding/reference/{matrixMeandersSlicePop.py → meandersDumpingGround/matrixMeandersSlicePop.py} +0 -0
- /mapFolding/syntheticModules/{algorithmA007822.py → A007822/algorithm.py} +0 -0
- /mapFolding/syntheticModules/{algorithmA007822Numba.py → A007822/algorithmNumba.py} +0 -0
- /mapFolding/syntheticModules/{initializeStateA007822.py → A007822/initializeState.py} +0 -0
- /mapFolding/syntheticModules/{theorem2A007822.py → A007822/theorem2.py} +0 -0
- /mapFolding/syntheticModules/{theorem2A007822Numba.py → A007822/theorem2Numba.py} +0 -0
- /mapFolding/syntheticModules/{theorem2A007822Trimmed.py → A007822/theorem2Trimmed.py} +0 -0
- {mapfolding-0.15.3.dist-info → mapfolding-0.16.0.dist-info}/WHEEL +0 -0
- {mapfolding-0.15.3.dist-info → mapfolding-0.16.0.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.15.3.dist-info → mapfolding-0.16.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
"""Count meanders with matrix transfer algorithm.
|
|
2
|
+
|
|
3
|
+
Notes
|
|
4
|
+
-----
|
|
5
|
+
- Odd/even of `groupAlpha` == the odd/even of `curveLocations`. Proof: `groupAlphaIsEven = curveLocations & 1 & 1 ^ 1`.
|
|
6
|
+
- Odd/even of `groupZulu` == `curveLocations` second-least significant bit. So `groupZuluIsEven = bool(curveLocations & 2 ^ 2)`.
|
|
7
|
+
"""
|
|
8
|
+
from functools import cache
|
|
9
|
+
from gc import collect as goByeBye
|
|
10
|
+
from hunterMakesPy import raiseIfNone
|
|
11
|
+
from mapFolding import MatrixMeandersState
|
|
12
|
+
from mapFolding.algorithms.getBucketsTotal import getBucketsTotal
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from warnings import warn
|
|
15
|
+
import numpy
|
|
16
|
+
import pandas
|
|
17
|
+
|
|
18
|
+
pathRoot: Path = Path.cwd() / 'curves'
|
|
19
|
+
pathRoot.mkdir(exist_ok=True, parents=True)
|
|
20
|
+
|
|
21
|
+
@cache
|
|
22
|
+
def _flipTheExtra_0b1(intWithExtra_0b1: numpy.uint64) -> numpy.uint64:
|
|
23
|
+
return numpy.uint64(intWithExtra_0b1 ^ walkDyckPath(int(intWithExtra_0b1)))
|
|
24
|
+
|
|
25
|
+
flipTheExtra_0b1AsUfunc = numpy.frompyfunc(_flipTheExtra_0b1, 1, 1)
|
|
26
|
+
|
|
27
|
+
def outfitDictionaryCurveGroups(state: MatrixMeandersState) -> dict[tuple[int, int], int]:
|
|
28
|
+
"""Outfit `dictionaryCurveGroups` so it may manage the computations for one iteration of the transfer matrix.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
state : MatrixMeandersState
|
|
33
|
+
The current state of the computation, including `dictionaryCurveLocations`.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
dictionaryCurveGroups : dict[tuple[int, int], int]
|
|
38
|
+
A dictionary of `(groupAlpha, groupZulu)` to `distinctCrossings`.
|
|
39
|
+
"""
|
|
40
|
+
state.bitWidth = max(state.dictionaryCurveLocations.keys()).bit_length()
|
|
41
|
+
return {(curveLocations & state.locatorGroupAlpha, (curveLocations & state.locatorGroupZulu) >> 1): distinctCrossings
|
|
42
|
+
for curveLocations, distinctCrossings in state.dictionaryCurveLocations.items()}
|
|
43
|
+
|
|
44
|
+
@cache
|
|
45
|
+
def walkDyckPath(intWithExtra_0b1: int) -> int:
|
|
46
|
+
"""Find the bit position for flipping paired curve endpoints in meander transfer matrices.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
intWithExtra_0b1 : int
|
|
51
|
+
Binary representation of curve locations with an extra bit encoding parity information.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
flipExtra_0b1_Here : int
|
|
56
|
+
Bit mask indicating the position where the balance condition fails, formatted as 2^(2k).
|
|
57
|
+
|
|
58
|
+
3L33T H@X0R
|
|
59
|
+
------------
|
|
60
|
+
Binary search for first negative balance in shifted bit pairs. Returns 2^(2k) mask for
|
|
61
|
+
bit position k where cumulative balance counter transitions from non-negative to negative.
|
|
62
|
+
|
|
63
|
+
Mathematics
|
|
64
|
+
-----------
|
|
65
|
+
Implements the Dyck path balance verification algorithm from Jensen's transfer matrix
|
|
66
|
+
enumeration. Computes the position where ∑(i=0 to k) (-1)^b_i < 0 for the first time,
|
|
67
|
+
where b_i are the bits of the input at positions 2i.
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
findTheExtra_0b1: int = 0
|
|
71
|
+
flipExtra_0b1_Here: int = 1
|
|
72
|
+
while True:
|
|
73
|
+
flipExtra_0b1_Here <<= 2
|
|
74
|
+
if (intWithExtra_0b1 & flipExtra_0b1_Here) == 0:
|
|
75
|
+
findTheExtra_0b1 += 1
|
|
76
|
+
else:
|
|
77
|
+
findTheExtra_0b1 -= 1
|
|
78
|
+
if findTheExtra_0b1 < 0:
|
|
79
|
+
break
|
|
80
|
+
return flipExtra_0b1_Here
|
|
81
|
+
|
|
82
|
+
def areIntegersWide(state: MatrixMeandersState, dataframe: pandas.DataFrame | None = None, *, fixedSizeMAXIMUMcurveLocations: bool = False) -> bool:
|
|
83
|
+
"""Check if the largest values are wider than the maximum limits.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
state : MatrixMeandersState
|
|
88
|
+
The current state of the computation, including `dictionaryCurveLocations`.
|
|
89
|
+
dataframe : pandas.DataFrame | None = None
|
|
90
|
+
Optional DataFrame containing 'analyzed' and 'distinctCrossings' columns. If provided, use this instead of `state.dictionaryCurveLocations`.
|
|
91
|
+
fixedSizeMAXIMUMcurveLocations : bool = False
|
|
92
|
+
Set this to `True` if you cast `state.MAXIMUMcurveLocations` to the same fixed size integer type as `state.datatypeCurveLocations`.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
wider : bool
|
|
97
|
+
True if at least one integer is too wide.
|
|
98
|
+
|
|
99
|
+
Notes
|
|
100
|
+
-----
|
|
101
|
+
Casting `state.MAXIMUMcurveLocations` to a fixed-size 64-bit unsigned integer might cause the flow to be a little more
|
|
102
|
+
complicated because `MAXIMUMcurveLocations` is usually 1-bit larger than the `max(curveLocations)` value.
|
|
103
|
+
|
|
104
|
+
If you start the algorithm with very large `curveLocations` in your `dictionaryCurveLocations` (*i.e.,* A000682), then the
|
|
105
|
+
flow will go to a function that does not use fixed size integers. When the integers are below the limits (*e.g.,*
|
|
106
|
+
`bitWidthCurveLocationsMaximum`), the flow will go to a function with fixed size integers. In that case, casting
|
|
107
|
+
`MAXIMUMcurveLocations` to a fixed size merely delays the transition from one function to the other by one iteration.
|
|
108
|
+
|
|
109
|
+
If you start with small values in `dictionaryCurveLocations`, however, then the flow goes to the function with fixed size
|
|
110
|
+
integers and usually stays there until `distinctCrossings` is huge, which is near the end of the computation. If you cast
|
|
111
|
+
`MAXIMUMcurveLocations` into a 64-bit unsigned integer, however, then around `state.kOfMatrix == 28`, the bit width of
|
|
112
|
+
`MAXIMUMcurveLocations` might exceed the limit. That will cause the flow to go to the function that does not have fixed size
|
|
113
|
+
integers for a few iterations before returning to the function with fixed size integers.
|
|
114
|
+
"""
|
|
115
|
+
if dataframe is None:
|
|
116
|
+
curveLocationsWidest: int = max(state.dictionaryCurveLocations.keys()).bit_length()
|
|
117
|
+
distinctCrossingsWidest: int = max(state.dictionaryCurveLocations.values()).bit_length()
|
|
118
|
+
else:
|
|
119
|
+
curveLocationsWidest = int(dataframe['analyzed'].max()).bit_length()
|
|
120
|
+
distinctCrossingsWidest = int(dataframe['distinctCrossings'].max()).bit_length()
|
|
121
|
+
|
|
122
|
+
MAXIMUMcurveLocations: int = 0
|
|
123
|
+
if fixedSizeMAXIMUMcurveLocations:
|
|
124
|
+
MAXIMUMcurveLocations = state.MAXIMUMcurveLocations
|
|
125
|
+
|
|
126
|
+
return (curveLocationsWidest > raiseIfNone(state.bitWidthCurveLocationsMaximum)
|
|
127
|
+
or distinctCrossingsWidest > raiseIfNone(state.bitWidthDistinctCrossingsMaximum)
|
|
128
|
+
or MAXIMUMcurveLocations > raiseIfNone(state.bitWidthCurveLocationsMaximum)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def countBigInt(state: MatrixMeandersState) -> MatrixMeandersState:
|
|
132
|
+
"""Count meanders with matrix transfer algorithm using Python primitive `int` contained in a Python primitive `dict`.
|
|
133
|
+
|
|
134
|
+
Parameters
|
|
135
|
+
----------
|
|
136
|
+
state : MatrixMeandersState
|
|
137
|
+
The algorithm state containing current `kOfMatrix`, `dictionaryCurveLocations`, and thresholds.
|
|
138
|
+
|
|
139
|
+
Notes
|
|
140
|
+
-----
|
|
141
|
+
The algorithm is sophisticated, but this implementation is straightforward. Compute each index one at a time, compute each
|
|
142
|
+
`curveLocations` one at a time, and compute each type of analysis one at a time.
|
|
143
|
+
"""
|
|
144
|
+
dictionaryCurveGroups: dict[tuple[int, int], int] = {}
|
|
145
|
+
|
|
146
|
+
while (state.kOfMatrix > 0 and areIntegersWide(state)):
|
|
147
|
+
state.kOfMatrix -= 1
|
|
148
|
+
|
|
149
|
+
dictionaryCurveGroups = outfitDictionaryCurveGroups(state)
|
|
150
|
+
state.dictionaryCurveLocations.clear()
|
|
151
|
+
goByeBye()
|
|
152
|
+
|
|
153
|
+
for (groupAlpha, groupZulu), distinctCrossings in dictionaryCurveGroups.items():
|
|
154
|
+
groupAlphaCurves: bool = groupAlpha > 1
|
|
155
|
+
groupZuluHasCurves: bool = groupZulu > 1
|
|
156
|
+
groupAlphaIsEven = groupZuluIsEven = 0
|
|
157
|
+
|
|
158
|
+
curveLocationAnalysis = ((groupAlpha | (groupZulu << 1)) << 2) | 3
|
|
159
|
+
# simple
|
|
160
|
+
if curveLocationAnalysis < state.MAXIMUMcurveLocations:
|
|
161
|
+
state.dictionaryCurveLocations[curveLocationAnalysis] = state.dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
162
|
+
|
|
163
|
+
if groupAlphaCurves:
|
|
164
|
+
curveLocationAnalysis = (groupAlpha >> 2) | (groupZulu << 3) | ((groupAlphaIsEven := 1 - (groupAlpha & 1)) << 1)
|
|
165
|
+
if curveLocationAnalysis < state.MAXIMUMcurveLocations:
|
|
166
|
+
state.dictionaryCurveLocations[curveLocationAnalysis] = state.dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
167
|
+
|
|
168
|
+
if groupZuluHasCurves:
|
|
169
|
+
curveLocationAnalysis = (groupZulu >> 1) | (groupAlpha << 2) | (groupZuluIsEven := 1 - (groupZulu & 1))
|
|
170
|
+
if curveLocationAnalysis < state.MAXIMUMcurveLocations:
|
|
171
|
+
state.dictionaryCurveLocations[curveLocationAnalysis] = state.dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
172
|
+
|
|
173
|
+
if groupAlphaCurves and groupZuluHasCurves and (groupAlphaIsEven or groupZuluIsEven):
|
|
174
|
+
# aligned
|
|
175
|
+
if groupAlphaIsEven and not groupZuluIsEven:
|
|
176
|
+
groupAlpha ^= walkDyckPath(groupAlpha) # noqa: PLW2901
|
|
177
|
+
elif groupZuluIsEven and not groupAlphaIsEven:
|
|
178
|
+
groupZulu ^= walkDyckPath(groupZulu) # noqa: PLW2901
|
|
179
|
+
|
|
180
|
+
curveLocationAnalysis: int = ((groupZulu >> 2) << 1) | (groupAlpha >> 2)
|
|
181
|
+
if curveLocationAnalysis < state.MAXIMUMcurveLocations:
|
|
182
|
+
state.dictionaryCurveLocations[curveLocationAnalysis] = state.dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
183
|
+
|
|
184
|
+
return state
|
|
185
|
+
|
|
186
|
+
# ruff: noqa: B023
|
|
187
|
+
|
|
188
|
+
def countPandas(state: MatrixMeandersState) -> MatrixMeandersState:
|
|
189
|
+
"""Count meanders with matrix transfer algorithm using pandas DataFrame.
|
|
190
|
+
|
|
191
|
+
Parameters
|
|
192
|
+
----------
|
|
193
|
+
state : MatrixMeandersState
|
|
194
|
+
The algorithm state containing current `kOfMatrix`, `dictionaryCurveLocations`, and thresholds.
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
state : MatrixMeandersState
|
|
199
|
+
Updated state with new `kOfMatrix` and `dictionaryCurveLocations`.
|
|
200
|
+
"""
|
|
201
|
+
dataframeAnalyzed = pandas.DataFrame({
|
|
202
|
+
'analyzed': pandas.Series(name='analyzed', data=state.dictionaryCurveLocations.keys(), copy=False, dtype=state.datatypeCurveLocations)
|
|
203
|
+
, 'distinctCrossings': pandas.Series(name='distinctCrossings', data=state.dictionaryCurveLocations.values(), copy=False, dtype=state.datatypeDistinctCrossings)
|
|
204
|
+
}, dtype=state.datatypeCurveLocations
|
|
205
|
+
)
|
|
206
|
+
state.dictionaryCurveLocations.clear()
|
|
207
|
+
|
|
208
|
+
while (state.kOfMatrix > 0 and not areIntegersWide(state, dataframeAnalyzed)):
|
|
209
|
+
|
|
210
|
+
def aggregateCurveLocations() -> None:
|
|
211
|
+
nonlocal dataframeAnalyzed
|
|
212
|
+
dataframeAnalyzed = dataframeAnalyzed.iloc[0:state.indexStartAnalyzed].groupby('analyzed', sort=False)['distinctCrossings'].aggregate('sum').reset_index()
|
|
213
|
+
|
|
214
|
+
def analyzeCurveLocationsAligned() -> None:
|
|
215
|
+
"""Compute `curveLocations` from `groupAlpha` and `groupZulu` if at least one is an even number.
|
|
216
|
+
|
|
217
|
+
Before computing `curveLocations`, some values of `groupAlpha` and `groupZulu` are modified.
|
|
218
|
+
|
|
219
|
+
Warning
|
|
220
|
+
-------
|
|
221
|
+
This function deletes rows from `dataframeCurveLocations`. Always run this analysis last.
|
|
222
|
+
|
|
223
|
+
Formula
|
|
224
|
+
-------
|
|
225
|
+
```python
|
|
226
|
+
if groupAlpha > 1 and groupZulu > 1 and (groupAlphaIsEven or groupZuluIsEven):
|
|
227
|
+
curveLocations = (groupAlpha >> 2) | ((groupZulu >> 2) << 1)
|
|
228
|
+
```
|
|
229
|
+
"""
|
|
230
|
+
nonlocal dataframeCurveLocations
|
|
231
|
+
|
|
232
|
+
# NOTE Step 1 drop unqualified rows
|
|
233
|
+
|
|
234
|
+
ImaGroupZulpha: pandas.Series = dataframeCurveLocations['curveLocations'].copy() # Ima `groupAlpha`.
|
|
235
|
+
ImaGroupZulpha &= state.locatorGroupAlpha # Ima `groupAlpha`.
|
|
236
|
+
|
|
237
|
+
dataframeCurveLocations = dataframeCurveLocations.loc[(ImaGroupZulpha > 1)] # if groupAlphaHasCurves
|
|
238
|
+
|
|
239
|
+
del ImaGroupZulpha
|
|
240
|
+
|
|
241
|
+
ImaGroupZulpha = dataframeCurveLocations['curveLocations'].copy() # Ima `groupZulu`.
|
|
242
|
+
ImaGroupZulpha &= state.locatorGroupZulu # Ima `groupZulu`.
|
|
243
|
+
ImaGroupZulpha //= 2**1 # Ima `groupZulu` (groupZulu >> 1)
|
|
244
|
+
|
|
245
|
+
dataframeCurveLocations = dataframeCurveLocations.loc[(ImaGroupZulpha > 1)] # if groupZuluHasCurves
|
|
246
|
+
|
|
247
|
+
del ImaGroupZulpha
|
|
248
|
+
|
|
249
|
+
ImaGroupZulpha = dataframeCurveLocations['curveLocations'].copy() # Ima `groupZulu`.
|
|
250
|
+
ImaGroupZulpha &= 0b10 # Ima `groupZulu`.
|
|
251
|
+
ImaGroupZulpha //= 2**1 # Ima `groupZulu` (groupZulu >> 1)
|
|
252
|
+
ImaGroupZulpha &= 1 # (groupZulu & 1)
|
|
253
|
+
ImaGroupZulpha ^= 1 # (1 - (groupZulu ...))
|
|
254
|
+
dataframeCurveLocations.loc[:, 'analyzed'] = ImaGroupZulpha # selectorGroupZuluAtEven
|
|
255
|
+
|
|
256
|
+
del ImaGroupZulpha
|
|
257
|
+
|
|
258
|
+
ImaGroupZulpha = dataframeCurveLocations['curveLocations'].copy() # Ima `groupAlpha`.
|
|
259
|
+
ImaGroupZulpha &= 1 # (groupAlpha & 1)
|
|
260
|
+
ImaGroupZulpha ^= 1 # (1 - (groupAlpha ...))
|
|
261
|
+
ImaGroupZulpha = ImaGroupZulpha.astype(bool) # selectorGroupAlphaAtODD
|
|
262
|
+
|
|
263
|
+
dataframeCurveLocations = dataframeCurveLocations.loc[(ImaGroupZulpha) | (dataframeCurveLocations.loc[:, 'analyzed'])] # if (groupAlphaIsEven or groupZuluIsEven)
|
|
264
|
+
|
|
265
|
+
del ImaGroupZulpha
|
|
266
|
+
|
|
267
|
+
# NOTE Step 2 modify rows
|
|
268
|
+
|
|
269
|
+
# Make a selector for groupZuluAtEven, so you can modify groupAlpha
|
|
270
|
+
ImaGroupZulpha = dataframeCurveLocations['curveLocations'].copy() # Ima `groupZulu`.
|
|
271
|
+
ImaGroupZulpha &= 0b10 # Ima `groupZulu`.
|
|
272
|
+
ImaGroupZulpha //= 2**1 # Ima `groupZulu` (groupZulu >> 1)
|
|
273
|
+
ImaGroupZulpha &= 1 # (groupZulu & 1)
|
|
274
|
+
ImaGroupZulpha ^= 1 # (1 - (groupZulu ...))
|
|
275
|
+
ImaGroupZulpha = ImaGroupZulpha.astype(bool) # selectorGroupZuluAtEven
|
|
276
|
+
|
|
277
|
+
dataframeCurveLocations.loc[:, 'analyzed'] = dataframeCurveLocations['curveLocations'] # Ima `groupAlpha`.
|
|
278
|
+
dataframeCurveLocations.loc[:, 'analyzed'] &= state.locatorGroupAlpha # (groupAlpha)
|
|
279
|
+
|
|
280
|
+
# if groupAlphaIsEven and not groupZuluIsEven, modifyGroupAlphaPairedToOdd
|
|
281
|
+
dataframeCurveLocations.loc[(~ImaGroupZulpha), 'analyzed'] = state.datatypeCurveLocations( # pyright: ignore[reportCallIssue, reportArgumentType]
|
|
282
|
+
flipTheExtra_0b1AsUfunc(dataframeCurveLocations.loc[(~ImaGroupZulpha), 'analyzed']))
|
|
283
|
+
|
|
284
|
+
del ImaGroupZulpha
|
|
285
|
+
|
|
286
|
+
# if groupZuluIsEven and not groupAlphaIsEven, modifyGroupZuluPairedToOdd
|
|
287
|
+
ImaGroupZulpha = dataframeCurveLocations['curveLocations'].copy() # Ima `groupZulu`.
|
|
288
|
+
ImaGroupZulpha &= state.locatorGroupZulu # Ima `groupZulu`.
|
|
289
|
+
ImaGroupZulpha //= 2**1 # Ima `groupZulu` (groupZulu >> 1)
|
|
290
|
+
|
|
291
|
+
ImaGroupZulpha.loc[(dataframeCurveLocations.loc[:, 'curveLocations'] & 1).astype(bool)] = state.datatypeCurveLocations( # pyright: ignore[reportArgumentType, reportCallIssue]
|
|
292
|
+
flipTheExtra_0b1AsUfunc(ImaGroupZulpha.loc[(dataframeCurveLocations.loc[:, 'curveLocations'] & 1).astype(bool)])) # pyright: ignore[reportCallIssue, reportUnknownArgumentType, reportArgumentType]
|
|
293
|
+
|
|
294
|
+
# NOTE Step 3 compute curveLocations
|
|
295
|
+
|
|
296
|
+
dataframeCurveLocations.loc[:, 'analyzed'] //= 2**2 # (groupAlpha >> 2)
|
|
297
|
+
|
|
298
|
+
ImaGroupZulpha //= 2**2 # (groupZulu >> 2)
|
|
299
|
+
ImaGroupZulpha *= 2**1 # ((groupZulu ...) << 1)
|
|
300
|
+
|
|
301
|
+
dataframeCurveLocations.loc[:, 'analyzed'] |= ImaGroupZulpha # ... | (groupZulu ...)
|
|
302
|
+
|
|
303
|
+
del ImaGroupZulpha
|
|
304
|
+
|
|
305
|
+
dataframeCurveLocations.loc[dataframeCurveLocations['analyzed'] >= state.MAXIMUMcurveLocations, 'analyzed'] = 0
|
|
306
|
+
|
|
307
|
+
def analyzeCurveLocationsAlpha() -> None:
|
|
308
|
+
"""Compute `curveLocations` from `groupAlpha`.
|
|
309
|
+
|
|
310
|
+
Formula
|
|
311
|
+
-------
|
|
312
|
+
```python
|
|
313
|
+
if groupAlpha > 1:
|
|
314
|
+
curveLocations = ((1 - (groupAlpha & 1)) << 1) | (groupZulu << 3) | (groupAlpha >> 2)
|
|
315
|
+
# `(1 - (groupAlpha & 1)` is an evenness test.
|
|
316
|
+
```
|
|
317
|
+
"""
|
|
318
|
+
nonlocal dataframeCurveLocations
|
|
319
|
+
dataframeCurveLocations['analyzed'] = dataframeCurveLocations['curveLocations']
|
|
320
|
+
dataframeCurveLocations.loc[:, 'analyzed'] &= 1 # (groupAlpha & 1)
|
|
321
|
+
dataframeCurveLocations.loc[:, 'analyzed'] ^= 1 # (1 - (groupAlpha ...))
|
|
322
|
+
|
|
323
|
+
dataframeCurveLocations.loc[:, 'analyzed'] *= 2**1 # ((groupAlpha ...) << 1)
|
|
324
|
+
|
|
325
|
+
ImaGroupZulpha: pandas.Series = dataframeCurveLocations['curveLocations'].copy() # Ima `groupZulu`.
|
|
326
|
+
ImaGroupZulpha &= state.locatorGroupZulu # Ima `groupZulu`.
|
|
327
|
+
ImaGroupZulpha //= 2**1 # Ima `groupZulu` (groupZulu >> 1)
|
|
328
|
+
|
|
329
|
+
ImaGroupZulpha *= 2**3 # (groupZulu << 3)
|
|
330
|
+
dataframeCurveLocations.loc[:, 'analyzed'] |= ImaGroupZulpha # ... | (groupZulu ...)
|
|
331
|
+
|
|
332
|
+
del ImaGroupZulpha
|
|
333
|
+
|
|
334
|
+
dataframeCurveLocations.loc[:, 'analyzed'] *= 2**2 # ... | (groupAlpha >> 2)
|
|
335
|
+
|
|
336
|
+
ImaGroupZulpha = dataframeCurveLocations['curveLocations'].copy() # Ima `groupAlpha`.
|
|
337
|
+
ImaGroupZulpha &= state.locatorGroupAlpha # Ima `groupAlpha`.
|
|
338
|
+
|
|
339
|
+
dataframeCurveLocations.loc[:, 'analyzed'] |= ImaGroupZulpha # ... | (groupAlpha)
|
|
340
|
+
dataframeCurveLocations.loc[:, 'analyzed'] //= 2**2 # (... >> 2)
|
|
341
|
+
|
|
342
|
+
dataframeCurveLocations.loc[(ImaGroupZulpha <= 1), 'analyzed'] = 0 # if groupAlpha > 1
|
|
343
|
+
|
|
344
|
+
del ImaGroupZulpha
|
|
345
|
+
|
|
346
|
+
dataframeCurveLocations.loc[dataframeCurveLocations['analyzed'] >= state.MAXIMUMcurveLocations, 'analyzed'] = 0
|
|
347
|
+
|
|
348
|
+
def analyzeCurveLocationsSimple() -> None:
|
|
349
|
+
"""Compute curveLocations with the 'simple' bridges formula.
|
|
350
|
+
|
|
351
|
+
Formula
|
|
352
|
+
-------
|
|
353
|
+
```python
|
|
354
|
+
curveLocations = ((groupAlpha | (groupZulu << 1)) << 2) | 3
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Notes
|
|
358
|
+
-----
|
|
359
|
+
Using `+= 3` instead of `|= 3` is valid in this specific case. Left shift by two means the last bits are '0b00'. '0 + 3'
|
|
360
|
+
is '0b11', and '0b00 | 0b11' is also '0b11'.
|
|
361
|
+
|
|
362
|
+
"""
|
|
363
|
+
nonlocal dataframeCurveLocations
|
|
364
|
+
dataframeCurveLocations['analyzed'] = dataframeCurveLocations['curveLocations']
|
|
365
|
+
dataframeCurveLocations.loc[:, 'analyzed'] &= state.locatorGroupAlpha
|
|
366
|
+
|
|
367
|
+
groupZulu: pandas.Series = dataframeCurveLocations['curveLocations'].copy()
|
|
368
|
+
groupZulu &= state.locatorGroupZulu
|
|
369
|
+
groupZulu //= 2**1 # (groupZulu >> 1)
|
|
370
|
+
groupZulu *= 2**1 # (groupZulu << 1)
|
|
371
|
+
|
|
372
|
+
dataframeCurveLocations.loc[:, 'analyzed'] |= groupZulu # ((groupAlpha | (groupZulu ...))
|
|
373
|
+
|
|
374
|
+
del groupZulu
|
|
375
|
+
|
|
376
|
+
dataframeCurveLocations.loc[:, 'analyzed'] *= 2**2 # (... << 2)
|
|
377
|
+
dataframeCurveLocations.loc[:, 'analyzed'] += 3 # (...) | 3
|
|
378
|
+
dataframeCurveLocations.loc[dataframeCurveLocations['analyzed'] >= state.MAXIMUMcurveLocations, 'analyzed'] = 0
|
|
379
|
+
|
|
380
|
+
def analyzeCurveLocationsZulu() -> None:
|
|
381
|
+
"""Compute `curveLocations` from `groupZulu`.
|
|
382
|
+
|
|
383
|
+
Formula
|
|
384
|
+
-------
|
|
385
|
+
```python
|
|
386
|
+
if groupZulu > 1:
|
|
387
|
+
curveLocations = (1 - (groupZulu & 1)) | (groupAlpha << 2) | (groupZulu >> 1)
|
|
388
|
+
```
|
|
389
|
+
"""
|
|
390
|
+
nonlocal dataframeCurveLocations
|
|
391
|
+
dataframeCurveLocations.loc[:, 'analyzed'] = dataframeCurveLocations['curveLocations'] # Ima `groupZulu`.
|
|
392
|
+
dataframeCurveLocations.loc[:, 'analyzed'] &= 0b10 # Ima `groupZulu`.
|
|
393
|
+
dataframeCurveLocations.loc[:, 'analyzed'] //= 2**1 # Ima `groupZulu` (groupZulu >> 1)
|
|
394
|
+
dataframeCurveLocations.loc[:, 'analyzed'] &= 1 # (groupZulu & 1)
|
|
395
|
+
dataframeCurveLocations.loc[:, 'analyzed'] ^= 1 # (1 - (groupZulu ...))
|
|
396
|
+
|
|
397
|
+
ImaGroupZulpha: pandas.Series = dataframeCurveLocations['curveLocations'].copy() # Ima `groupAlpha`.
|
|
398
|
+
ImaGroupZulpha &= state.locatorGroupAlpha # Ima `groupAlpha`.
|
|
399
|
+
|
|
400
|
+
ImaGroupZulpha *= 2**2 # (groupAlpha << 2)
|
|
401
|
+
dataframeCurveLocations.loc[:, 'analyzed'] |= ImaGroupZulpha # ... | (groupAlpha ...)
|
|
402
|
+
|
|
403
|
+
del ImaGroupZulpha
|
|
404
|
+
|
|
405
|
+
ImaGroupZulpha = dataframeCurveLocations['curveLocations'].copy() # Ima `groupZulu`.
|
|
406
|
+
ImaGroupZulpha &= state.locatorGroupZulu # Ima `groupZulu`.
|
|
407
|
+
ImaGroupZulpha //= 2**1 # Ima `groupZulu` (groupZulu >> 1)
|
|
408
|
+
|
|
409
|
+
ImaGroupZulpha //= 2**1 # (groupZulu >> 1)
|
|
410
|
+
|
|
411
|
+
dataframeCurveLocations.loc[:, 'analyzed'] |= ImaGroupZulpha # ... | (groupZulu ...)
|
|
412
|
+
|
|
413
|
+
del ImaGroupZulpha
|
|
414
|
+
|
|
415
|
+
ImaGroupZulpha = dataframeCurveLocations['curveLocations'].copy() # Ima `groupZulu`.
|
|
416
|
+
ImaGroupZulpha &= state.locatorGroupZulu # Ima `groupZulu`.
|
|
417
|
+
ImaGroupZulpha //= 2**1 # Ima `groupZulu` (groupZulu >> 1)
|
|
418
|
+
|
|
419
|
+
dataframeCurveLocations.loc[ImaGroupZulpha <= 1, 'analyzed'] = 0 # if groupZulu > 1
|
|
420
|
+
|
|
421
|
+
del ImaGroupZulpha
|
|
422
|
+
|
|
423
|
+
dataframeCurveLocations.loc[dataframeCurveLocations['analyzed'] >= state.MAXIMUMcurveLocations, 'analyzed'] = 0
|
|
424
|
+
|
|
425
|
+
def recordCurveLocations() -> None:
|
|
426
|
+
nonlocal dataframeAnalyzed
|
|
427
|
+
|
|
428
|
+
indexStopAnalyzed: int = state.indexStartAnalyzed + int((dataframeCurveLocations['analyzed'] > 0).sum()) # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType]
|
|
429
|
+
|
|
430
|
+
if indexStopAnalyzed > state.indexStartAnalyzed:
|
|
431
|
+
if len(dataframeAnalyzed.index) < indexStopAnalyzed:
|
|
432
|
+
warn(f"Lengthened `dataframeAnalyzed` from {len(dataframeAnalyzed.index)} to {indexStopAnalyzed=}; n={state.n}, {state.kOfMatrix=}.", stacklevel=2)
|
|
433
|
+
dataframeAnalyzed = dataframeAnalyzed.reindex(index=pandas.RangeIndex(indexStopAnalyzed), fill_value=0)
|
|
434
|
+
|
|
435
|
+
dataframeAnalyzed.loc[state.indexStartAnalyzed:indexStopAnalyzed - 1, ['analyzed', 'distinctCrossings']] = (
|
|
436
|
+
dataframeCurveLocations.loc[(dataframeCurveLocations['analyzed'] > 0), ['analyzed', 'distinctCrossings']
|
|
437
|
+
].to_numpy(dtype=state.datatypeCurveLocations, copy=False)
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
state.indexStartAnalyzed = indexStopAnalyzed
|
|
441
|
+
|
|
442
|
+
del indexStopAnalyzed
|
|
443
|
+
|
|
444
|
+
dataframeCurveLocations = pandas.DataFrame({
|
|
445
|
+
'curveLocations': pandas.Series(name='curveLocations', data=dataframeAnalyzed['analyzed'], copy=False, dtype=state.datatypeCurveLocations)
|
|
446
|
+
, 'analyzed': pandas.Series(name='analyzed', data=0, dtype=state.datatypeCurveLocations)
|
|
447
|
+
, 'distinctCrossings': pandas.Series(name='distinctCrossings', data=dataframeAnalyzed['distinctCrossings'], copy=False, dtype=state.datatypeDistinctCrossings)
|
|
448
|
+
} # pyright: ignore[reportUnknownArgumentType]
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
del dataframeAnalyzed
|
|
452
|
+
goByeBye()
|
|
453
|
+
|
|
454
|
+
state.bitWidth = int(dataframeCurveLocations['curveLocations'].max()).bit_length()
|
|
455
|
+
length: int = getBucketsTotal(state)
|
|
456
|
+
dataframeAnalyzed = pandas.DataFrame({
|
|
457
|
+
'analyzed': pandas.Series(0, pandas.RangeIndex(length), dtype=state.datatypeCurveLocations, name='analyzed')
|
|
458
|
+
, 'distinctCrossings': pandas.Series(0, pandas.RangeIndex(length), dtype=state.datatypeDistinctCrossings, name='distinctCrossings')
|
|
459
|
+
}, index=pandas.RangeIndex(length), columns=['analyzed', 'distinctCrossings'], dtype=state.datatypeCurveLocations # pyright: ignore[reportUnknownArgumentType]
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
state.kOfMatrix -= 1
|
|
463
|
+
|
|
464
|
+
state.indexStartAnalyzed = 0
|
|
465
|
+
|
|
466
|
+
analyzeCurveLocationsSimple()
|
|
467
|
+
recordCurveLocations()
|
|
468
|
+
|
|
469
|
+
analyzeCurveLocationsAlpha()
|
|
470
|
+
recordCurveLocations()
|
|
471
|
+
|
|
472
|
+
analyzeCurveLocationsZulu()
|
|
473
|
+
recordCurveLocations()
|
|
474
|
+
|
|
475
|
+
analyzeCurveLocationsAligned()
|
|
476
|
+
recordCurveLocations()
|
|
477
|
+
del dataframeCurveLocations
|
|
478
|
+
goByeBye()
|
|
479
|
+
|
|
480
|
+
aggregateCurveLocations()
|
|
481
|
+
|
|
482
|
+
if state.n >= 45: # for data collection
|
|
483
|
+
print(state.n, state.kOfMatrix+1, state.indexStartAnalyzed, sep=',') # noqa: T201
|
|
484
|
+
|
|
485
|
+
state.dictionaryCurveLocations = dataframeAnalyzed.set_index('analyzed')['distinctCrossings'].to_dict()
|
|
486
|
+
return state
|
|
487
|
+
|
|
488
|
+
def doTheNeedful(state: MatrixMeandersState) -> int:
|
|
489
|
+
"""Compute a(n) meanders with the transfer matrix algorithm.
|
|
490
|
+
|
|
491
|
+
Parameters
|
|
492
|
+
----------
|
|
493
|
+
state : MatrixMeandersState
|
|
494
|
+
The algorithm state containing current `kOfMatrix`, `dictionaryCurveLocations`, and thresholds.
|
|
495
|
+
|
|
496
|
+
Returns
|
|
497
|
+
-------
|
|
498
|
+
a(n) : int
|
|
499
|
+
The computed value of a(n).
|
|
500
|
+
|
|
501
|
+
Notes
|
|
502
|
+
-----
|
|
503
|
+
Citation: https://github.com/hunterhogan/mapFolding/blob/main/citations/Jensen.bibtex
|
|
504
|
+
|
|
505
|
+
See Also
|
|
506
|
+
--------
|
|
507
|
+
https://oeis.org/A000682
|
|
508
|
+
https://oeis.org/A005316
|
|
509
|
+
"""
|
|
510
|
+
while state.kOfMatrix > 0:
|
|
511
|
+
goByeBye()
|
|
512
|
+
|
|
513
|
+
if areIntegersWide(state):
|
|
514
|
+
state = countBigInt(state)
|
|
515
|
+
else:
|
|
516
|
+
state = countPandas(state)
|
|
517
|
+
|
|
518
|
+
return sum(state.dictionaryCurveLocations.values())
|
|
519
|
+
|