mapFolding 0.16.4__py3-none-any.whl → 0.17.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/NOTcountingFolds.py +28 -11
- easyRun/__init__.py +1 -0
- easyRun/countFolds.py +16 -2
- easyRun/eliminateFolds.py +60 -0
- easyRun/meanders.py +3 -3
- mapFolding/__init__.py +2 -1
- mapFolding/_theTypes.py +0 -1
- mapFolding/algorithms/A086345.py +8 -3
- mapFolding/algorithms/__init__.py +1 -1
- mapFolding/algorithms/constraintPropagation.py +184 -0
- mapFolding/algorithms/elimination.py +131 -0
- mapFolding/algorithms/eliminationCount.py +26 -0
- mapFolding/algorithms/eliminationPinned.py +35 -0
- mapFolding/algorithms/iff.py +206 -0
- mapFolding/algorithms/matrixMeanders.py +59 -18
- mapFolding/algorithms/matrixMeandersNumPyndas.py +841 -0
- mapFolding/algorithms/patternFinder.py +280 -0
- mapFolding/algorithms/pinning2Dn.py +345 -0
- mapFolding/algorithms/pinning2DnAnnex.py +43 -0
- mapFolding/algorithms/symmetricFolds.py +24 -25
- mapFolding/basecamp.py +84 -14
- mapFolding/beDRY.py +14 -1
- mapFolding/dataBaskets.py +86 -71
- mapFolding/reference/irvineJavaPort.py +3 -3
- mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +1 -1
- mapFolding/someAssemblyRequired/A007822/_asynchronousAnnex.py +1 -1
- mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +5 -3
- mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +22 -6
- mapFolding/someAssemblyRequired/RecipeJob.py +14 -24
- mapFolding/someAssemblyRequired/__init__.py +1 -0
- mapFolding/someAssemblyRequired/_toolkitContainers.py +6 -4
- mapFolding/someAssemblyRequired/infoBooth.py +2 -1
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +75 -20
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +9 -10
- mapFolding/someAssemblyRequired/makingModules_count.py +20 -22
- mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +9 -9
- mapFolding/someAssemblyRequired/mapFoldingModules/makeMapFoldingModules.py +6 -5
- mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +6 -6
- mapFolding/someAssemblyRequired/toolkitMakeModules.py +3 -29
- mapFolding/someAssemblyRequired/toolkitNumba.py +2 -1
- mapFolding/someAssemblyRequired/transformationTools.py +2 -3
- mapFolding/syntheticModules/A007822/algorithm.py +8 -8
- mapFolding/syntheticModules/A007822/asynchronous.py +12 -13
- mapFolding/syntheticModules/A007822/initializeState.py +10 -8
- mapFolding/syntheticModules/A007822/theorem2.py +10 -8
- mapFolding/syntheticModules/A007822/theorem2Numba.py +20 -16
- mapFolding/syntheticModules/A007822/theorem2Trimmed.py +10 -8
- mapFolding/syntheticModules/countParallelNumba.py +5 -2
- mapFolding/syntheticModules/daoOfMapFoldingNumba.py +4 -2
- mapFolding/syntheticModules/initializeState.py +1 -1
- mapFolding/syntheticModules/meanders/bigInt.py +52 -15
- mapFolding/syntheticModules/theorem2.py +1 -1
- mapFolding/syntheticModules/theorem2Numba.py +4 -2
- mapFolding/syntheticModules/theorem2Trimmed.py +1 -1
- mapFolding/tests/conftest.py +1 -1
- mapFolding/tests/test_computations.py +21 -4
- mapFolding/tests/verify.py +323 -0
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/METADATA +14 -11
- mapfolding-0.17.1.dist-info/RECORD +112 -0
- easyRun/A000682.py +0 -25
- easyRun/A005316.py +0 -20
- mapFolding/algorithms/matrixMeandersBeDry.py +0 -182
- mapFolding/algorithms/matrixMeandersNumPy.py +0 -333
- mapFolding/algorithms/matrixMeandersPandas.py +0 -334
- mapfolding-0.16.4.dist-info/RECORD +0 -106
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/WHEEL +0 -0
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/top_level.txt +0 -0
|
@@ -31,18 +31,14 @@ improvements through just-in-time compilation, parallel execution, and optimized
|
|
|
31
31
|
tailored for specific computational requirements essential to large-scale map folding research.
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
from astToolkit import
|
|
35
|
-
|
|
36
|
-
from
|
|
37
|
-
from hunterMakesPy import raiseIfNone, writeStringToHere
|
|
34
|
+
from astToolkit import Be, DOT, identifierDotAttribute, NodeTourist, parseLogicalPath2astModule, Then
|
|
35
|
+
from astToolkit.containers import IngredientsFunction
|
|
36
|
+
from hunterMakesPy import raiseIfNone
|
|
38
37
|
from mapFolding import packageSettings
|
|
39
38
|
from mapFolding.someAssemblyRequired import default
|
|
40
39
|
from os import PathLike
|
|
41
40
|
from pathlib import PurePath
|
|
42
|
-
from typing import Any
|
|
43
41
|
import ast
|
|
44
|
-
import io
|
|
45
|
-
import isort
|
|
46
42
|
|
|
47
43
|
def findDataclass(ingredientsFunction: IngredientsFunction) -> tuple[identifierDotAttribute, str, str]:
|
|
48
44
|
"""Dynamically extract information about a `dataclass`: the instance identifier, the identifier, and the logical path module.
|
|
@@ -128,25 +124,3 @@ def getPathFilename(pathRoot: PathLike[str] | PurePath | None = packageSettings.
|
|
|
128
124
|
if pathRoot:
|
|
129
125
|
pathFilename = PurePath(pathRoot, pathFilename)
|
|
130
126
|
return pathFilename
|
|
131
|
-
|
|
132
|
-
def write_astModule(astModule: ast.Module, pathFilename: PathLike[Any] | PurePath | io.TextIOBase, packageName: str | None = None) -> None:
|
|
133
|
-
"""Prototype that will likely be moved to astToolkit.
|
|
134
|
-
|
|
135
|
-
Parameters
|
|
136
|
-
----------
|
|
137
|
-
astModule : ast.Module
|
|
138
|
-
The AST module to be written to a file.
|
|
139
|
-
pathFilename : PathLike[Any] | PurePath
|
|
140
|
-
The file path where the module should be written.
|
|
141
|
-
packageName : str | None = None
|
|
142
|
-
Optional package name to preserve in import optimization.
|
|
143
|
-
"""
|
|
144
|
-
ast.fix_missing_locations(astModule)
|
|
145
|
-
pythonSource: str = ast.unparse(astModule)
|
|
146
|
-
autoflake_additional_imports: list[str] = []
|
|
147
|
-
if packageName:
|
|
148
|
-
autoflake_additional_imports.append(packageName)
|
|
149
|
-
pythonSource = autoflake_fix_code(pythonSource, autoflake_additional_imports, expand_star_imports=False, remove_all_unused_imports=True, remove_duplicate_keys = False, remove_unused_variables = False)
|
|
150
|
-
pythonSource = isort.code(pythonSource)
|
|
151
|
-
writeStringToHere(pythonSource + '\n', pathFilename)
|
|
152
|
-
|
|
@@ -25,7 +25,8 @@ computational modules. The compilation layer integrates seamlessly with the broa
|
|
|
25
25
|
system to produce standalone modules optimized for specific map dimensions and computational contexts.
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
-
from astToolkit import identifierDotAttribute,
|
|
28
|
+
from astToolkit import identifierDotAttribute, Make
|
|
29
|
+
from astToolkit.containers import IngredientsFunction
|
|
29
30
|
from collections.abc import Callable
|
|
30
31
|
from numba.core.compiler import CompilerBase as numbaCompilerBase
|
|
31
32
|
from typing import Any, Final, NotRequired, TYPE_CHECKING, TypedDict
|
|
@@ -25,9 +25,8 @@ This approach enables seamless integration between high-level dataclass-based in
|
|
|
25
25
|
low-level optimized implementations, maintaining code clarity while achieving performance gains
|
|
26
26
|
through specialized compilation paths essential for computationally intensive map folding research.
|
|
27
27
|
"""
|
|
28
|
-
|
|
29
|
-
from astToolkit import
|
|
30
|
-
Be, extractClassDef, identifierDotAttribute, IngredientsFunction, Make, NodeChanger, parseLogicalPath2astModule, Then)
|
|
28
|
+
from astToolkit import Be, extractClassDef, identifierDotAttribute, Make, NodeChanger, parseLogicalPath2astModule, Then
|
|
29
|
+
from astToolkit.containers import IngredientsFunction
|
|
31
30
|
from astToolkit.transformationTools import unparseFindReplace
|
|
32
31
|
from hunterMakesPy import importLogicalPath2Identifier
|
|
33
32
|
from mapFolding.someAssemblyRequired import DeReConstructField2ast, IfThis, ShatteredDataclass
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import numpy
|
|
2
|
-
|
|
3
1
|
from mapFolding.dataBaskets import SymmetricFoldsState
|
|
4
2
|
|
|
5
|
-
|
|
6
3
|
def filterAsymmetricFolds(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
7
4
|
state.indexLeaf = 1
|
|
8
5
|
state.leafComparison[0] = 1
|
|
@@ -12,10 +9,13 @@ def filterAsymmetricFolds(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
12
9
|
state.leafComparison[state.leafConnectee] = (state.indexMiniGap - state.indexLeaf + state.leavesTotal) % state.leavesTotal
|
|
13
10
|
state.indexLeaf = state.indexMiniGap
|
|
14
11
|
state.leafConnectee += 1
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
for listTuples in state.indices:
|
|
13
|
+
state.leafConnectee = 1
|
|
14
|
+
for indexLeft, indexRight in listTuples:
|
|
15
|
+
if state.leafComparison[indexLeft] != state.leafComparison[indexRight]:
|
|
16
|
+
state.leafConnectee = 0
|
|
17
|
+
break
|
|
18
|
+
state.symmetricFolds += state.leafConnectee
|
|
19
19
|
return state
|
|
20
20
|
|
|
21
21
|
def activeLeafGreaterThan0(state: SymmetricFoldsState) -> bool:
|
|
@@ -153,7 +153,7 @@ def count(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
153
153
|
state = undoLastLeafPlacement(state)
|
|
154
154
|
if gapAvailable(state):
|
|
155
155
|
state = insertActiveLeafAtGap(state)
|
|
156
|
-
state.
|
|
156
|
+
state.symmetricFolds = (state.symmetricFolds + 1) // 2
|
|
157
157
|
return state
|
|
158
158
|
|
|
159
159
|
def doTheNeedful(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
from copy import deepcopy
|
|
2
|
-
from queue import Queue
|
|
3
|
-
from threading import Lock, Thread
|
|
4
|
-
|
|
5
|
-
import numpy
|
|
6
|
-
|
|
7
2
|
from mapFolding import DatatypeFoldsTotal
|
|
8
3
|
from mapFolding.dataBaskets import SymmetricFoldsState
|
|
4
|
+
from queue import Queue
|
|
5
|
+
from threading import Lock, Thread
|
|
9
6
|
|
|
10
7
|
listThreads: list[Thread] = []
|
|
11
8
|
queueFutures: Queue[SymmetricFoldsState] = Queue()
|
|
@@ -33,7 +30,7 @@ def _threadDoesSomething() -> None:
|
|
|
33
30
|
break
|
|
34
31
|
state = _filterAsymmetricFolds(state)
|
|
35
32
|
with LOCKsymmetricFoldsTotal:
|
|
36
|
-
symmetricFoldsTotal += state.
|
|
33
|
+
symmetricFoldsTotal += state.symmetricFolds
|
|
37
34
|
|
|
38
35
|
def filterAsymmetricFolds(state: SymmetricFoldsState) -> None:
|
|
39
36
|
queueFutures.put_nowait(deepcopy(state))
|
|
@@ -54,11 +51,13 @@ def _filterAsymmetricFolds(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
54
51
|
state.leafComparison[state.leafConnectee] = (state.indexMiniGap - state.indexLeaf + state.leavesTotal) % state.leavesTotal
|
|
55
52
|
state.indexLeaf = state.indexMiniGap
|
|
56
53
|
state.leafConnectee += 1
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
for listTuples in state.indices:
|
|
55
|
+
state.leafConnectee = 1
|
|
56
|
+
for indexLeft, indexRight in listTuples:
|
|
57
|
+
if state.leafComparison[indexLeft] != state.leafComparison[indexRight]:
|
|
58
|
+
state.leafConnectee = 0
|
|
59
|
+
break
|
|
60
|
+
state.symmetricFolds += state.leafConnectee
|
|
62
61
|
return state
|
|
63
62
|
|
|
64
63
|
def activeLeafGreaterThan0(state: SymmetricFoldsState) -> bool:
|
|
@@ -197,8 +196,8 @@ def count(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
197
196
|
if gapAvailable(state):
|
|
198
197
|
state = insertActiveLeafAtGap(state)
|
|
199
198
|
else:
|
|
200
|
-
state.
|
|
201
|
-
state.
|
|
199
|
+
state.symmetricFolds = getSymmetricFoldsTotal()
|
|
200
|
+
state.symmetricFolds = (state.symmetricFolds + 1) // 2
|
|
202
201
|
return state
|
|
203
202
|
|
|
204
203
|
def doTheNeedful(state: SymmetricFoldsState, maxWorkers: int) -> SymmetricFoldsState:
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from mapFolding.dataBaskets import SymmetricFoldsState
|
|
2
|
-
import numpy
|
|
3
2
|
|
|
4
3
|
def transitionOnGroupsOfFolds(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
5
|
-
while state.
|
|
4
|
+
while state.symmetricFolds == 0:
|
|
6
5
|
if state.leaf1ndex <= 1 or state.leafBelow[0] == 1:
|
|
7
6
|
if state.leaf1ndex > state.leavesTotal:
|
|
8
7
|
state.indexLeaf = 1
|
|
@@ -13,10 +12,13 @@ def transitionOnGroupsOfFolds(state: SymmetricFoldsState) -> SymmetricFoldsState
|
|
|
13
12
|
state.leafComparison[state.leafConnectee] = (state.indexMiniGap - state.indexLeaf + state.leavesTotal) % state.leavesTotal
|
|
14
13
|
state.indexLeaf = state.indexMiniGap
|
|
15
14
|
state.leafConnectee += 1
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
for listTuples in state.indices:
|
|
16
|
+
state.leafConnectee = 1
|
|
17
|
+
for indexLeft, indexRight in listTuples:
|
|
18
|
+
if state.leafComparison[indexLeft] != state.leafComparison[indexRight]:
|
|
19
|
+
state.leafConnectee = 0
|
|
20
|
+
break
|
|
21
|
+
state.symmetricFolds += state.leafConnectee
|
|
20
22
|
else:
|
|
21
23
|
state.dimensionsUnconstrained = state.dimensionsTotal
|
|
22
24
|
state.gap1ndexCeiling = state.gapRangeStart[state.leaf1ndex - 1]
|
|
@@ -58,5 +60,5 @@ def transitionOnGroupsOfFolds(state: SymmetricFoldsState) -> SymmetricFoldsState
|
|
|
58
60
|
state.leafAbove[state.leafBelow[state.leaf1ndex]] = state.leaf1ndex
|
|
59
61
|
state.gapRangeStart[state.leaf1ndex] = state.gap1ndex
|
|
60
62
|
state.leaf1ndex += 1
|
|
61
|
-
state.
|
|
62
|
-
return state
|
|
63
|
+
state.symmetricFolds = (state.symmetricFolds + 1) // 2
|
|
64
|
+
return state
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from mapFolding.dataBaskets import SymmetricFoldsState
|
|
2
2
|
from mapFolding.syntheticModules.A007822.initializeState import transitionOnGroupsOfFolds
|
|
3
|
-
import numpy
|
|
4
3
|
|
|
5
4
|
def count(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
6
5
|
while state.leaf1ndex > 4:
|
|
@@ -14,10 +13,13 @@ def count(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
14
13
|
state.leafComparison[state.leafConnectee] = (state.indexMiniGap - state.indexLeaf + state.leavesTotal) % state.leavesTotal
|
|
15
14
|
state.indexLeaf = state.indexMiniGap
|
|
16
15
|
state.leafConnectee += 1
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
for listTuples in state.indices:
|
|
17
|
+
state.leafConnectee = 1
|
|
18
|
+
for indexLeft, indexRight in listTuples:
|
|
19
|
+
if state.leafComparison[indexLeft] != state.leafComparison[indexRight]:
|
|
20
|
+
state.leafConnectee = 0
|
|
21
|
+
break
|
|
22
|
+
state.symmetricFolds += state.leafConnectee
|
|
21
23
|
else:
|
|
22
24
|
state.dimensionsUnconstrained = state.dimensionsTotal
|
|
23
25
|
state.gap1ndexCeiling = state.gapRangeStart[state.leaf1ndex - 1]
|
|
@@ -59,11 +61,11 @@ def count(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
59
61
|
state.gapRangeStart[state.leaf1ndex] = state.gap1ndex
|
|
60
62
|
state.leaf1ndex += 1
|
|
61
63
|
else:
|
|
62
|
-
state.
|
|
63
|
-
state.
|
|
64
|
+
state.symmetricFolds *= 2
|
|
65
|
+
state.symmetricFolds = (state.symmetricFolds + 1) // 2
|
|
64
66
|
return state
|
|
65
67
|
|
|
66
68
|
def doTheNeedful(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
67
69
|
state = transitionOnGroupsOfFolds(state)
|
|
68
70
|
state = count(state)
|
|
69
|
-
return state
|
|
71
|
+
return state
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
from mapFolding.dataBaskets import
|
|
1
|
+
from mapFolding.dataBaskets import (
|
|
2
|
+
Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal,
|
|
3
|
+
SymmetricFoldsState)
|
|
2
4
|
from mapFolding.syntheticModules.A007822.initializeState import transitionOnGroupsOfFolds
|
|
3
5
|
from numba import jit
|
|
4
|
-
import
|
|
6
|
+
from numba.typed import List
|
|
5
7
|
|
|
6
8
|
@jit(cache=True, error_model='numpy', fastmath=True, forceinline=True)
|
|
7
|
-
def count(
|
|
9
|
+
def count(symmetricFolds: DatatypeFoldsTotal, gap1ndex: DatatypeElephino, gap1ndexCeiling: DatatypeElephino, indexDimension: DatatypeLeavesTotal, indexLeaf: DatatypeLeavesTotal, indexMiniGap: DatatypeElephino, leaf1ndex: DatatypeLeavesTotal, leafConnectee: DatatypeLeavesTotal, dimensionsUnconstrained: DatatypeLeavesTotal, countDimensionsGapped: Array1DLeavesTotal, gapRangeStart: Array1DElephino, gapsWhere: Array1DLeavesTotal, leafAbove: Array1DLeavesTotal, leafBelow: Array1DLeavesTotal, leafComparison: Array1DLeavesTotal, connectionGraph: Array3DLeavesTotal, dimensionsTotal: DatatypeLeavesTotal, indices: list[list[tuple[int, int]]], leavesTotal: DatatypeLeavesTotal) -> tuple[DatatypeFoldsTotal, DatatypeElephino, DatatypeElephino, DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeElephino, DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeLeavesTotal, Array1DLeavesTotal, Array1DElephino, Array1DLeavesTotal, Array1DLeavesTotal, Array1DLeavesTotal, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeLeavesTotal, list[list[tuple[int, int]]], DatatypeLeavesTotal]:
|
|
8
10
|
while leaf1ndex > 4:
|
|
9
11
|
if leafBelow[0] == 1:
|
|
10
12
|
if leaf1ndex > leavesTotal:
|
|
@@ -16,10 +18,13 @@ def count(groupsOfFolds: DatatypeFoldsTotal, gap1ndex: DatatypeElephino, gap1nde
|
|
|
16
18
|
leafComparison[leafConnectee] = (indexMiniGap - indexLeaf + leavesTotal) % leavesTotal
|
|
17
19
|
indexLeaf = indexMiniGap
|
|
18
20
|
leafConnectee += 1
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
for listTuples in indices:
|
|
22
|
+
leafConnectee = 1
|
|
23
|
+
for indexLeft, indexRight in listTuples:
|
|
24
|
+
if leafComparison[indexLeft] != leafComparison[indexRight]:
|
|
25
|
+
leafConnectee = 0
|
|
26
|
+
break
|
|
27
|
+
symmetricFolds += leafConnectee
|
|
23
28
|
else:
|
|
24
29
|
dimensionsUnconstrained = dimensionsTotal
|
|
25
30
|
gap1ndexCeiling = gapRangeStart[leaf1ndex - 1]
|
|
@@ -55,14 +60,14 @@ def count(groupsOfFolds: DatatypeFoldsTotal, gap1ndex: DatatypeElephino, gap1nde
|
|
|
55
60
|
gapRangeStart[leaf1ndex] = gap1ndex
|
|
56
61
|
leaf1ndex += 1
|
|
57
62
|
else:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return (
|
|
63
|
+
symmetricFolds *= 2
|
|
64
|
+
symmetricFolds = (symmetricFolds + 1) // 2
|
|
65
|
+
return (symmetricFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, indices, leavesTotal)
|
|
61
66
|
|
|
62
67
|
def doTheNeedful(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
63
68
|
state = transitionOnGroupsOfFolds(state)
|
|
64
69
|
mapShape: tuple[DatatypeLeavesTotal, ...] = state.mapShape
|
|
65
|
-
|
|
70
|
+
symmetricFolds: DatatypeFoldsTotal = state.symmetricFolds
|
|
66
71
|
gap1ndex: DatatypeElephino = state.gap1ndex
|
|
67
72
|
gap1ndexCeiling: DatatypeElephino = state.gap1ndexCeiling
|
|
68
73
|
indexDimension: DatatypeLeavesTotal = state.indexDimension
|
|
@@ -77,11 +82,10 @@ def doTheNeedful(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
77
82
|
leafAbove: Array1DLeavesTotal = state.leafAbove
|
|
78
83
|
leafBelow: Array1DLeavesTotal = state.leafBelow
|
|
79
84
|
leafComparison: Array1DLeavesTotal = state.leafComparison
|
|
80
|
-
arrayGroupOfFolds: Array2DLeavesTotal = state.arrayGroupOfFolds
|
|
81
85
|
connectionGraph: Array3DLeavesTotal = state.connectionGraph
|
|
82
86
|
dimensionsTotal: DatatypeLeavesTotal = state.dimensionsTotal
|
|
83
|
-
|
|
87
|
+
indices: list[list[tuple[int, int]]] = List(state.indices)
|
|
84
88
|
leavesTotal: DatatypeLeavesTotal = state.leavesTotal
|
|
85
|
-
|
|
86
|
-
state = SymmetricFoldsState(mapShape=mapShape,
|
|
87
|
-
return state
|
|
89
|
+
symmetricFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, indices, leavesTotal = count(symmetricFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, indices, leavesTotal)
|
|
90
|
+
state = SymmetricFoldsState(mapShape=mapShape, symmetricFolds=symmetricFolds, gap1ndex=gap1ndex, gap1ndexCeiling=gap1ndexCeiling, indexDimension=indexDimension, indexLeaf=indexLeaf, indexMiniGap=indexMiniGap, leaf1ndex=leaf1ndex, leafConnectee=leafConnectee, dimensionsUnconstrained=dimensionsUnconstrained, countDimensionsGapped=countDimensionsGapped, gapRangeStart=gapRangeStart, gapsWhere=gapsWhere, leafAbove=leafAbove, leafBelow=leafBelow, leafComparison=leafComparison)
|
|
91
|
+
return state
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from mapFolding.dataBaskets import SymmetricFoldsState
|
|
2
2
|
from mapFolding.syntheticModules.A007822.initializeState import transitionOnGroupsOfFolds
|
|
3
|
-
import numpy
|
|
4
3
|
|
|
5
4
|
def count(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
6
5
|
while state.leaf1ndex > 4:
|
|
@@ -14,10 +13,13 @@ def count(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
14
13
|
state.leafComparison[state.leafConnectee] = (state.indexMiniGap - state.indexLeaf + state.leavesTotal) % state.leavesTotal
|
|
15
14
|
state.indexLeaf = state.indexMiniGap
|
|
16
15
|
state.leafConnectee += 1
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
for listTuples in state.indices:
|
|
17
|
+
state.leafConnectee = 1
|
|
18
|
+
for indexLeft, indexRight in listTuples:
|
|
19
|
+
if state.leafComparison[indexLeft] != state.leafComparison[indexRight]:
|
|
20
|
+
state.leafConnectee = 0
|
|
21
|
+
break
|
|
22
|
+
state.symmetricFolds += state.leafConnectee
|
|
21
23
|
else:
|
|
22
24
|
state.dimensionsUnconstrained = state.dimensionsTotal
|
|
23
25
|
state.gap1ndexCeiling = state.gapRangeStart[state.leaf1ndex - 1]
|
|
@@ -53,11 +55,11 @@ def count(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
|
53
55
|
state.gapRangeStart[state.leaf1ndex] = state.gap1ndex
|
|
54
56
|
state.leaf1ndex += 1
|
|
55
57
|
else:
|
|
56
|
-
state.
|
|
57
|
-
state.
|
|
58
|
+
state.symmetricFolds *= 2
|
|
59
|
+
state.symmetricFolds = (state.symmetricFolds + 1) // 2
|
|
58
60
|
return state
|
|
59
61
|
|
|
60
62
|
def doTheNeedful(state: SymmetricFoldsState) -> SymmetricFoldsState:
|
|
61
63
|
state = transitionOnGroupsOfFolds(state)
|
|
62
64
|
state = count(state)
|
|
63
|
-
return state
|
|
65
|
+
return state
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
from concurrent.futures import Future as ConcurrentFuture, ProcessPoolExecutor
|
|
2
2
|
from copy import deepcopy
|
|
3
|
-
from mapFolding.dataBaskets import
|
|
3
|
+
from mapFolding.dataBaskets import (
|
|
4
|
+
Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal,
|
|
5
|
+
ParallelMapFoldingState)
|
|
4
6
|
from multiprocessing import set_start_method as multiprocessing_set_start_method
|
|
5
7
|
from numba import jit
|
|
8
|
+
|
|
6
9
|
if __name__ == '__main__':
|
|
7
10
|
multiprocessing_set_start_method('spawn')
|
|
8
11
|
|
|
@@ -95,4 +98,4 @@ def doTheNeedful(state: ParallelMapFoldingState, concurrencyLimit: int) -> tuple
|
|
|
95
98
|
listStatesParallel[indexSherpa] = dictionaryConcurrency[indexSherpa].result()
|
|
96
99
|
groupsOfFoldsTotal += listStatesParallel[indexSherpa].groupsOfFolds
|
|
97
100
|
foldsTotal: int = groupsOfFoldsTotal * stateParallel.leavesTotal
|
|
98
|
-
return (foldsTotal, listStatesParallel)
|
|
101
|
+
return (foldsTotal, listStatesParallel)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from mapFolding.dataBaskets import
|
|
1
|
+
from mapFolding.dataBaskets import (
|
|
2
|
+
Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal,
|
|
3
|
+
MapFoldingState)
|
|
2
4
|
from numba import jit
|
|
3
5
|
|
|
4
6
|
@jit(cache=True, error_model='numpy', fastmath=True, forceinline=True)
|
|
@@ -71,4 +73,4 @@ def doTheNeedful(state: MapFoldingState) -> MapFoldingState:
|
|
|
71
73
|
leavesTotal: DatatypeLeavesTotal = state.leavesTotal
|
|
72
74
|
groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, connectionGraph, dimensionsTotal, leavesTotal = count(groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, connectionGraph, dimensionsTotal, leavesTotal)
|
|
73
75
|
state = MapFoldingState(mapShape=mapShape, groupsOfFolds=groupsOfFolds, gap1ndex=gap1ndex, gap1ndexCeiling=gap1ndexCeiling, indexDimension=indexDimension, indexLeaf=indexLeaf, indexMiniGap=indexMiniGap, leaf1ndex=leaf1ndex, leafConnectee=leafConnectee, dimensionsUnconstrained=dimensionsUnconstrained, countDimensionsGapped=countDimensionsGapped, gapRangeStart=gapRangeStart, gapsWhere=gapsWhere, leafAbove=leafAbove, leafBelow=leafBelow)
|
|
74
|
-
return state
|
|
76
|
+
return state
|
|
@@ -1,7 +1,43 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from mapFolding.dataBaskets import MatrixMeandersNumPyState
|
|
1
|
+
from functools import cache
|
|
2
|
+
from mapFolding.algorithms.matrixMeandersNumPyndas import areIntegersWide, MatrixMeandersNumPyState
|
|
4
3
|
|
|
4
|
+
@cache
|
|
5
|
+
def walkDyckPath(intWithExtra_0b1: int) -> int:
|
|
6
|
+
"""Find the bit position for flipping paired curve endpoints in meander transfer matrices.
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
intWithExtra_0b1 : int
|
|
11
|
+
Binary representation of curve locations with an extra bit encoding parity information.
|
|
12
|
+
|
|
13
|
+
Returns
|
|
14
|
+
-------
|
|
15
|
+
flipExtra_0b1_Here : int
|
|
16
|
+
Bit mask indicating the position where the balance condition fails, formatted as 2^(2k).
|
|
17
|
+
|
|
18
|
+
3L33T H@X0R
|
|
19
|
+
------------
|
|
20
|
+
Binary search for first negative balance in shifted bit pairs. Returns 2^(2k) mask for
|
|
21
|
+
bit position k where cumulative balance counter transitions from non-negative to negative.
|
|
22
|
+
|
|
23
|
+
Mathematics
|
|
24
|
+
-----------
|
|
25
|
+
Implements the Dyck path balance verification algorithm from Jensen's transfer matrix
|
|
26
|
+
enumeration. Computes the position where ∑(i=0 to k) (-1)^b_i < 0 for the first time,
|
|
27
|
+
where b_i are the bits of the input at positions 2i.
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
findTheExtra_0b1: int = 0
|
|
31
|
+
flipExtra_0b1_Here: int = 1
|
|
32
|
+
while True:
|
|
33
|
+
flipExtra_0b1_Here <<= 2
|
|
34
|
+
if intWithExtra_0b1 & flipExtra_0b1_Here == 0:
|
|
35
|
+
findTheExtra_0b1 += 1
|
|
36
|
+
else:
|
|
37
|
+
findTheExtra_0b1 -= 1
|
|
38
|
+
if findTheExtra_0b1 < 0:
|
|
39
|
+
break
|
|
40
|
+
return flipExtra_0b1_Here
|
|
5
41
|
|
|
6
42
|
def countBigInt(state: MatrixMeandersNumPyState) -> MatrixMeandersNumPyState:
|
|
7
43
|
"""Count meanders with matrix transfer algorithm using Python `int` (*int*eger) contained in a Python `dict` (*dict*ionary).
|
|
@@ -13,31 +49,31 @@ def countBigInt(state: MatrixMeandersNumPyState) -> MatrixMeandersNumPyState:
|
|
|
13
49
|
|
|
14
50
|
Notes
|
|
15
51
|
-----
|
|
16
|
-
The matrix transfer algorithm is sophisticated, but this implementation is straightforward: compute each
|
|
17
|
-
compute each `arcCode` one at a time, and compute each type of analysis one at a time.
|
|
52
|
+
The matrix transfer algorithm is sophisticated, but this implementation is straightforward: compute each `boundary` one at a
|
|
53
|
+
time, compute each `arcCode` one at a time, and compute each type of analysis one at a time.
|
|
18
54
|
"""
|
|
19
55
|
dictionaryArcCodeToCrossings: dict[int, int] = {}
|
|
20
56
|
while state.boundary > 0 and areIntegersWide(state):
|
|
21
|
-
state.
|
|
22
|
-
state.bitWidth = max(state.dictionaryMeanders.keys()).bit_length()
|
|
57
|
+
state.reduceBoundary()
|
|
23
58
|
dictionaryArcCodeToCrossings = state.dictionaryMeanders.copy()
|
|
24
59
|
state.dictionaryMeanders = {}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
60
|
+
|
|
61
|
+
def analyzeArcCode(arcCode: int, crossings: int) -> None:
|
|
62
|
+
bitsAlpha: int = arcCode & state.bitsLocator
|
|
28
63
|
bitsAlphaHasArcs: bool = bitsAlpha > 1
|
|
29
|
-
bitsZuluHasArcs: bool = bitsZulu > 1
|
|
30
64
|
bitsAlphaIsEven: int = bitsAlpha & 1 ^ 1
|
|
65
|
+
bitsZulu: int = arcCode >> 1 & state.bitsLocator
|
|
66
|
+
bitsZuluHasArcs: bool = bitsZulu > 1
|
|
31
67
|
bitsZuluIsEven: int = bitsZulu & 1 ^ 1
|
|
32
|
-
arcCodeAnalysis = (
|
|
68
|
+
arcCodeAnalysis: int = (bitsZulu << 1 | bitsAlpha) << 2 | 3
|
|
33
69
|
if arcCodeAnalysis < state.MAXIMUMarcCode:
|
|
34
70
|
state.dictionaryMeanders[arcCodeAnalysis] = state.dictionaryMeanders.get(arcCodeAnalysis, 0) + crossings
|
|
35
71
|
if bitsAlphaHasArcs:
|
|
36
|
-
arcCodeAnalysis = bitsAlpha >> 2 | bitsZulu << 3
|
|
72
|
+
arcCodeAnalysis = bitsAlphaIsEven << 1 | bitsAlpha >> 2 | bitsZulu << 3
|
|
37
73
|
if arcCodeAnalysis < state.MAXIMUMarcCode:
|
|
38
74
|
state.dictionaryMeanders[arcCodeAnalysis] = state.dictionaryMeanders.get(arcCodeAnalysis, 0) + crossings
|
|
39
75
|
if bitsZuluHasArcs:
|
|
40
|
-
arcCodeAnalysis =
|
|
76
|
+
arcCodeAnalysis = bitsZuluIsEven | bitsAlpha << 2 | bitsZulu >> 1
|
|
41
77
|
if arcCodeAnalysis < state.MAXIMUMarcCode:
|
|
42
78
|
state.dictionaryMeanders[arcCodeAnalysis] = state.dictionaryMeanders.get(arcCodeAnalysis, 0) + crossings
|
|
43
79
|
if bitsAlphaHasArcs and bitsZuluHasArcs and (bitsAlphaIsEven or bitsZuluIsEven):
|
|
@@ -45,8 +81,9 @@ def countBigInt(state: MatrixMeandersNumPyState) -> MatrixMeandersNumPyState:
|
|
|
45
81
|
bitsAlpha ^= walkDyckPath(bitsAlpha)
|
|
46
82
|
elif bitsZuluIsEven and (not bitsAlphaIsEven):
|
|
47
83
|
bitsZulu ^= walkDyckPath(bitsZulu)
|
|
48
|
-
arcCodeAnalysis
|
|
84
|
+
arcCodeAnalysis = (bitsZulu >> 2 << 3 | bitsAlpha) >> 2
|
|
49
85
|
if arcCodeAnalysis < state.MAXIMUMarcCode:
|
|
50
86
|
state.dictionaryMeanders[arcCodeAnalysis] = state.dictionaryMeanders.get(arcCodeAnalysis, 0) + crossings
|
|
87
|
+
set(map(analyzeArcCode, dictionaryArcCodeToCrossings.keys(), dictionaryArcCodeToCrossings.values()))
|
|
51
88
|
dictionaryArcCodeToCrossings = {}
|
|
52
89
|
return state
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from mapFolding.dataBaskets import
|
|
1
|
+
from mapFolding.dataBaskets import (
|
|
2
|
+
Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal,
|
|
3
|
+
MapFoldingState)
|
|
2
4
|
from mapFolding.syntheticModules.initializeState import transitionOnGroupsOfFolds
|
|
3
5
|
from numba import jit
|
|
4
6
|
|
|
@@ -68,4 +70,4 @@ def doTheNeedful(state: MapFoldingState) -> MapFoldingState:
|
|
|
68
70
|
leavesTotal: DatatypeLeavesTotal = state.leavesTotal
|
|
69
71
|
groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, connectionGraph, dimensionsTotal, leavesTotal = count(groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, connectionGraph, dimensionsTotal, leavesTotal)
|
|
70
72
|
state = MapFoldingState(mapShape=mapShape, groupsOfFolds=groupsOfFolds, gap1ndex=gap1ndex, gap1ndexCeiling=gap1ndexCeiling, indexDimension=indexDimension, indexLeaf=indexLeaf, indexMiniGap=indexMiniGap, leaf1ndex=leaf1ndex, leafConnectee=leafConnectee, dimensionsUnconstrained=dimensionsUnconstrained, countDimensionsGapped=countDimensionsGapped, gapRangeStart=gapRangeStart, gapsWhere=gapsWhere, leafAbove=leafAbove, leafBelow=leafBelow)
|
|
71
|
-
return state
|
|
73
|
+
return state
|
mapFolding/tests/conftest.py
CHANGED
|
@@ -242,7 +242,7 @@ def mapShapeTestCountFolds(oeisIDmapFolding: str) -> tuple[int, ...]:
|
|
|
242
242
|
n = random.choice(dictionaryOEISMapFolding[oeisIDmapFolding]['valuesTestValidation'])
|
|
243
243
|
if n < 2:
|
|
244
244
|
continue
|
|
245
|
-
listDimensionsCandidate = list(dictionaryOEISMapFolding[oeisIDmapFolding]['getMapShape'](n))
|
|
245
|
+
listDimensionsCandidate: list[int] = list(dictionaryOEISMapFolding[oeisIDmapFolding]['getMapShape'](n))
|
|
246
246
|
|
|
247
247
|
try:
|
|
248
248
|
return validateListDimensions(listDimensionsCandidate)
|
|
@@ -25,17 +25,19 @@ The `test_writeJobNumba` function shows how to test dynamically generated code,
|
|
|
25
25
|
which is useful if you're working with the code synthesis features of the package.
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
-
from mapFolding import countFolds, dictionaryOEIS, dictionaryOEISMapFolding, getFoldsTotalKnown, oeisIDfor_n
|
|
28
|
+
from mapFolding import countFolds, dictionaryOEIS, dictionaryOEISMapFolding, eliminateFolds, getFoldsTotalKnown, oeisIDfor_n
|
|
29
29
|
from mapFolding.basecamp import NOTcountingFolds
|
|
30
30
|
from mapFolding.dataBaskets import MapFoldingState
|
|
31
31
|
from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2
|
|
32
32
|
from mapFolding.someAssemblyRequired.toolkitNumba import parametersNumbaLight
|
|
33
33
|
from mapFolding.syntheticModules.initializeState import transitionOnGroupsOfFolds
|
|
34
|
-
from mapFolding.tests.conftest import registrarRecordsTemporaryFilesystemObject, standardizedEqualToCallableReturn
|
|
34
|
+
from mapFolding.tests.conftest import mapShapeTestCountFolds, registrarRecordsTemporaryFilesystemObject, standardizedEqualToCallableReturn
|
|
35
|
+
from numba.core.errors import NumbaPendingDeprecationWarning
|
|
35
36
|
from pathlib import Path, PurePosixPath
|
|
36
37
|
import importlib.util
|
|
37
38
|
import multiprocessing
|
|
38
39
|
import pytest
|
|
40
|
+
import warnings
|
|
39
41
|
|
|
40
42
|
if __name__ == '__main__':
|
|
41
43
|
multiprocessing.set_start_method('spawn')
|
|
@@ -52,7 +54,7 @@ def test_A007822(flow: str) -> None:
|
|
|
52
54
|
"""
|
|
53
55
|
oeisID = 'A007822'
|
|
54
56
|
CPUlimit = .5
|
|
55
|
-
|
|
57
|
+
warnings.filterwarnings('ignore', category=NumbaPendingDeprecationWarning)
|
|
56
58
|
oeis_n = 2
|
|
57
59
|
for oeis_n in dictionaryOEIS[oeisID]['valuesTestValidation']:
|
|
58
60
|
if oeis_n < 2:
|
|
@@ -88,7 +90,22 @@ def test_countFolds(mapShapeTestCountFolds: tuple[int, ...], flow: str) -> None:
|
|
|
88
90
|
"""
|
|
89
91
|
standardizedEqualToCallableReturn(getFoldsTotalKnown(mapShapeTestCountFolds), countFolds, None, None, None, None, mapShapeTestCountFolds, flow)
|
|
90
92
|
|
|
91
|
-
@pytest.mark.parametrize('flow', ['
|
|
93
|
+
# @pytest.mark.parametrize('flow', ['constraintPropagation', 'elimination'])
|
|
94
|
+
# def test_eliminateFolds(mapShapeTestParallelization: tuple[int, ...], flow: str) -> None:
|
|
95
|
+
# """Validate `eliminateFolds` and different flows produce valid results.
|
|
96
|
+
|
|
97
|
+
# Parameters
|
|
98
|
+
# ----------
|
|
99
|
+
# mapShapeTestCountFolds : tuple[int, ...]
|
|
100
|
+
# The map shape dimensions to test fold counting for.
|
|
101
|
+
# flow : str
|
|
102
|
+
# The computational flow algorithm to validate.
|
|
103
|
+
# """
|
|
104
|
+
# pathLikeWriteFoldsTotal: None = None
|
|
105
|
+
# CPUlimit: bool | float | int | None = .25
|
|
106
|
+
# standardizedEqualToCallableReturn(getFoldsTotalKnown(mapShapeTestParallelization), eliminateFolds, mapShapeTestParallelization, pathLikeWriteFoldsTotal, CPUlimit, flow)
|
|
107
|
+
|
|
108
|
+
@pytest.mark.parametrize('flow', ['matrixMeanders', 'matrixNumPy', 'matrixPandas'])
|
|
92
109
|
def test_meanders(oeisIDmeanders: str, flow: str) -> None:
|
|
93
110
|
"""Verify Meanders OEIS sequence value calculations against known reference values.
|
|
94
111
|
|