mapFolding 0.8.0__py3-none-any.whl → 0.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mapFolding/__init__.py +33 -4
- mapFolding/basecamp.py +16 -2
- mapFolding/beDRY.py +40 -32
- mapFolding/filesystem.py +124 -90
- mapFolding/noHomeYet.py +12 -0
- mapFolding/oeis.py +18 -3
- mapFolding/reference/__init__.py +38 -0
- mapFolding/reference/flattened.py +66 -47
- mapFolding/reference/hunterNumba.py +28 -4
- mapFolding/reference/irvineJavaPort.py +13 -1
- mapFolding/reference/{jax.py → jaxCount.py} +46 -27
- mapFolding/reference/lunnanNumpy.py +19 -5
- mapFolding/reference/lunnanWhile.py +19 -7
- mapFolding/reference/rotatedEntryPoint.py +20 -3
- mapFolding/reference/total_countPlus1vsPlusN.py +226 -203
- mapFolding/someAssemblyRequired/__init__.py +29 -0
- mapFolding/someAssemblyRequired/getLLVMforNoReason.py +32 -14
- mapFolding/someAssemblyRequired/ingredientsNumba.py +22 -1
- mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +193 -0
- mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py +3 -4
- mapFolding/someAssemblyRequired/transformDataStructures.py +168 -0
- mapFolding/someAssemblyRequired/transformationTools.py +233 -225
- mapFolding/theDao.py +19 -5
- mapFolding/theSSOT.py +89 -122
- mapfolding-0.8.2.dist-info/METADATA +187 -0
- mapfolding-0.8.2.dist-info/RECORD +39 -0
- {mapfolding-0.8.0.dist-info → mapfolding-0.8.2.dist-info}/WHEEL +1 -1
- tests/conftest.py +43 -33
- tests/test_computations.py +7 -7
- tests/test_other.py +2 -2
- mapFolding/reference/lunnan.py +0 -153
- mapFolding/someAssemblyRequired/Z0Z_workbench.py +0 -350
- mapFolding/someAssemblyRequired/synthesizeDataConverters.py +0 -117
- mapFolding/syntheticModules/numbaCountHistoricalExample.py +0 -158
- mapFolding/syntheticModules/numba_doTheNeedfulHistoricalExample.py +0 -13
- mapfolding-0.8.0.dist-info/METADATA +0 -157
- mapfolding-0.8.0.dist-info/RECORD +0 -41
- {mapfolding-0.8.0.dist-info → mapfolding-0.8.2.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.8.0.dist-info → mapfolding-0.8.2.dist-info/licenses}/LICENSE +0 -0
- {mapfolding-0.8.0.dist-info → mapfolding-0.8.2.dist-info}/top_level.txt +0 -0
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
from collections.abc import Sequence
|
|
2
|
-
from importlib import import_module
|
|
3
|
-
from inspect import getsource as inspect_getsource
|
|
4
|
-
from mapFolding.beDRY import outfitCountFolds, validateListDimensions
|
|
5
|
-
from mapFolding.filesystem import getPathFilenameFoldsTotal
|
|
6
|
-
from mapFolding.someAssemblyRequired import (
|
|
7
|
-
ast_Identifier,
|
|
8
|
-
extractClassDef,
|
|
9
|
-
ifThis,
|
|
10
|
-
LedgerOfImports,
|
|
11
|
-
Make,
|
|
12
|
-
NodeCollector,
|
|
13
|
-
strDotStrCuzPyStoopid,
|
|
14
|
-
Then,
|
|
15
|
-
Z0Z_executeActionUnlessDescendantMatches,
|
|
16
|
-
)
|
|
17
|
-
from mapFolding.theSSOT import ComputationState, getSourceAlgorithm
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
from types import ModuleType
|
|
20
|
-
from typing import Any, Literal, overload
|
|
21
|
-
import ast
|
|
22
|
-
import pickle
|
|
23
|
-
|
|
24
|
-
# Would `LibCST` be better than `ast` in some cases? https://github.com/hunterhogan/mapFolding/issues/7
|
|
25
|
-
|
|
26
|
-
def shatter_dataclassesDOTdataclass(logicalPathModule: strDotStrCuzPyStoopid, dataclass_Identifier: ast_Identifier, instance_Identifier: ast_Identifier
|
|
27
|
-
)-> tuple[ast.Name, LedgerOfImports, list[ast.AnnAssign], ast.Tuple, list[ast.Name], list[ast.arg], ast.Subscript, ast.Assign, list[ast.keyword]]:
|
|
28
|
-
"""
|
|
29
|
-
Parameters:
|
|
30
|
-
logicalPathModule: gimme string cuz python is stoopid
|
|
31
|
-
dataclass_Identifier: The identifier of the dataclass to be dismantled.
|
|
32
|
-
instance_Identifier: In the synthesized module/function/scope, the identifier that will be used for the instance.
|
|
33
|
-
"""
|
|
34
|
-
module: ast.Module = ast.parse(inspect_getsource(import_module(logicalPathModule)))
|
|
35
|
-
|
|
36
|
-
dataclass = extractClassDef(dataclass_Identifier, module)
|
|
37
|
-
|
|
38
|
-
if not isinstance(dataclass, ast.ClassDef):
|
|
39
|
-
raise ValueError(f"I could not find {dataclass_Identifier=} in {logicalPathModule=}.")
|
|
40
|
-
|
|
41
|
-
ledgerDataclassANDFragments = LedgerOfImports()
|
|
42
|
-
list_ast_argAnnotated4ArgumentsSpecification: list[ast.arg] = []
|
|
43
|
-
list_keyword4DataclassInitialization: list[ast.keyword] = []
|
|
44
|
-
listAnnAssign4DataclassUnpack: list[ast.AnnAssign] = []
|
|
45
|
-
listAnnotations: list[ast.expr] = []
|
|
46
|
-
listNameDataclassFragments4Parameters: list[ast.Name] = []
|
|
47
|
-
|
|
48
|
-
addToLedgerPredicate = ifThis.isAnnAssignAndAnnotationIsName
|
|
49
|
-
addToLedgerAction = Then.Z0Z_ledger(logicalPathModule, ledgerDataclassANDFragments)
|
|
50
|
-
addToLedger = NodeCollector(addToLedgerPredicate, [addToLedgerAction])
|
|
51
|
-
|
|
52
|
-
exclusionPredicate = ifThis.is_keyword_IdentifierEqualsConstantValue('init', False)
|
|
53
|
-
appendKeywordAction = Then.Z0Z_appendKeywordMirroredTo(list_keyword4DataclassInitialization)
|
|
54
|
-
filteredAppendKeywordAction = Z0Z_executeActionUnlessDescendantMatches(exclusionPredicate, appendKeywordAction) # type: ignore
|
|
55
|
-
|
|
56
|
-
collector = NodeCollector(
|
|
57
|
-
ifThis.isAnnAssignAndTargetIsName,
|
|
58
|
-
[Then.Z0Z_appendAnnAssignOf_nameDOTnameTo(instance_Identifier, listAnnAssign4DataclassUnpack)
|
|
59
|
-
, Then.append_targetTo(listNameDataclassFragments4Parameters) # type: ignore
|
|
60
|
-
, lambda node: addToLedger.visit(node)
|
|
61
|
-
, filteredAppendKeywordAction
|
|
62
|
-
, lambda node: list_ast_argAnnotated4ArgumentsSpecification.append(Make.ast_arg(node.target.id, node.annotation)) # type: ignore
|
|
63
|
-
, lambda node: listAnnotations.append(node.annotation) # type: ignore
|
|
64
|
-
]
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
collector.visit(dataclass)
|
|
68
|
-
|
|
69
|
-
astSubscriptPrimitiveTupleAnnotations4FunctionDef_returns = Make.astSubscript(Make.astName('tuple'), Make.astTuple(listAnnotations))
|
|
70
|
-
|
|
71
|
-
ledgerDataclassANDFragments.addImportFromStr(logicalPathModule, dataclass_Identifier)
|
|
72
|
-
|
|
73
|
-
astName_dataclassesDOTdataclass = Make.astName(dataclass_Identifier)
|
|
74
|
-
astTuple4AssignTargetsToFragments: ast.Tuple = Make.astTuple(listNameDataclassFragments4Parameters, ast.Store())
|
|
75
|
-
astAssignDataclassRepack = Make.astAssign(listTargets=[Make.astName(instance_Identifier)], value=Make.astCall(astName_dataclassesDOTdataclass, list_astKeywords=list_keyword4DataclassInitialization))
|
|
76
|
-
return (astName_dataclassesDOTdataclass, ledgerDataclassANDFragments, listAnnAssign4DataclassUnpack,
|
|
77
|
-
astTuple4AssignTargetsToFragments, listNameDataclassFragments4Parameters, list_ast_argAnnotated4ArgumentsSpecification,
|
|
78
|
-
astSubscriptPrimitiveTupleAnnotations4FunctionDef_returns, astAssignDataclassRepack, list_keyword4DataclassInitialization)
|
|
79
|
-
|
|
80
|
-
@overload
|
|
81
|
-
def makeStateJob(listDimensions: Sequence[int], *, writeJob: Literal[True], **keywordArguments: Any) -> Path: ...
|
|
82
|
-
@overload
|
|
83
|
-
def makeStateJob(listDimensions: Sequence[int], *, writeJob: Literal[False], **keywordArguments: Any) -> ComputationState: ...
|
|
84
|
-
def makeStateJob(listDimensions: Sequence[int], *, writeJob: bool = True, **keywordArguments: Any) -> ComputationState | Path:
|
|
85
|
-
"""
|
|
86
|
-
Creates a computation state job for map folding calculations and optionally saves it to disk.
|
|
87
|
-
|
|
88
|
-
This function initializes a computation state for map folding calculations based on the given dimensions,
|
|
89
|
-
sets up the initial counting configuration, and can optionally save the state to a pickle file.
|
|
90
|
-
|
|
91
|
-
Parameters:
|
|
92
|
-
listDimensions: List of integers representing the dimensions of the map to be folded.
|
|
93
|
-
writeJob (True): Whether to save the state to disk.
|
|
94
|
-
**keywordArguments: Additional keyword arguments to pass to the computation state initialization.
|
|
95
|
-
|
|
96
|
-
Returns:
|
|
97
|
-
stateUniversal|pathFilenameJob: The computation state for the map folding calculations, or
|
|
98
|
-
the path to the saved state file if writeJob is True.
|
|
99
|
-
"""
|
|
100
|
-
mapShape = validateListDimensions(listDimensions)
|
|
101
|
-
stateUniversal: ComputationState = outfitCountFolds(mapShape, **keywordArguments)
|
|
102
|
-
|
|
103
|
-
moduleSource: ModuleType = getSourceAlgorithm()
|
|
104
|
-
# TODO `countInitialize` is hardcoded
|
|
105
|
-
stateUniversal = moduleSource.countInitialize(stateUniversal)
|
|
106
|
-
|
|
107
|
-
if not writeJob:
|
|
108
|
-
return stateUniversal
|
|
109
|
-
|
|
110
|
-
pathFilenameChopChop = getPathFilenameFoldsTotal(stateUniversal.mapShape, None)
|
|
111
|
-
suffix = pathFilenameChopChop.suffix
|
|
112
|
-
pathJob = Path(str(pathFilenameChopChop)[0:-len(suffix)])
|
|
113
|
-
pathJob.mkdir(parents=True, exist_ok=True)
|
|
114
|
-
pathFilenameJob = pathJob / 'stateJob.pkl'
|
|
115
|
-
|
|
116
|
-
pathFilenameJob.write_bytes(pickle.dumps(stateUniversal))
|
|
117
|
-
return pathFilenameJob
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
from mapFolding.theSSOT import indexMy, indexTrack
|
|
2
|
-
from numba import uint16, prange, int64, jit
|
|
3
|
-
from numpy import ndarray, dtype, integer
|
|
4
|
-
from typing import Any
|
|
5
|
-
|
|
6
|
-
@jit((uint16[:, :, ::1], uint16[::1], uint16[::1], uint16[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=False, no_cpython_wrapper=False, nopython=True, parallel=False)
|
|
7
|
-
def countInitialize(connectionGraph: ndarray[tuple[int, int, int], dtype[integer[Any]]], gapsWhere: ndarray[tuple[int], dtype[integer[Any]]], my: ndarray[tuple[int], dtype[integer[Any]]], track: ndarray[tuple[int, int], dtype[integer[Any]]]) -> None:
|
|
8
|
-
while my[indexMy.leaf1ndex] > 0:
|
|
9
|
-
if my[indexMy.leaf1ndex] <= 1 or track[indexTrack.leafBelow, 0] == 1:
|
|
10
|
-
my[indexMy.dimensionsUnconstrained] = my[indexMy.dimensionsTotal]
|
|
11
|
-
my[indexMy.gap1ndexCeiling] = track[indexTrack.gapRangeStart, my[indexMy.leaf1ndex] - 1]
|
|
12
|
-
my[indexMy.indexDimension] = 0
|
|
13
|
-
while my[indexMy.indexDimension] < my[indexMy.dimensionsTotal]:
|
|
14
|
-
if connectionGraph[my[indexMy.indexDimension], my[indexMy.leaf1ndex], my[indexMy.leaf1ndex]] == my[indexMy.leaf1ndex]:
|
|
15
|
-
my[indexMy.dimensionsUnconstrained] -= 1
|
|
16
|
-
else:
|
|
17
|
-
my[indexMy.leafConnectee] = connectionGraph[my[indexMy.indexDimension], my[indexMy.leaf1ndex], my[indexMy.leaf1ndex]]
|
|
18
|
-
while my[indexMy.leafConnectee] != my[indexMy.leaf1ndex]:
|
|
19
|
-
gapsWhere[my[indexMy.gap1ndexCeiling]] = my[indexMy.leafConnectee]
|
|
20
|
-
if track[indexTrack.countDimensionsGapped, my[indexMy.leafConnectee]] == 0:
|
|
21
|
-
my[indexMy.gap1ndexCeiling] += 1
|
|
22
|
-
track[indexTrack.countDimensionsGapped, my[indexMy.leafConnectee]] += 1
|
|
23
|
-
my[indexMy.leafConnectee] = connectionGraph[my[indexMy.indexDimension], my[indexMy.leaf1ndex], track[indexTrack.leafBelow, my[indexMy.leafConnectee]]]
|
|
24
|
-
my[indexMy.indexDimension] += 1
|
|
25
|
-
if not my[indexMy.dimensionsUnconstrained]:
|
|
26
|
-
my[indexMy.indexLeaf] = 0
|
|
27
|
-
while my[indexMy.indexLeaf] < my[indexMy.leaf1ndex]:
|
|
28
|
-
gapsWhere[my[indexMy.gap1ndexCeiling]] = my[indexMy.indexLeaf]
|
|
29
|
-
my[indexMy.gap1ndexCeiling] += 1
|
|
30
|
-
my[indexMy.indexLeaf] += 1
|
|
31
|
-
my[indexMy.indexMiniGap] = my[indexMy.gap1ndex]
|
|
32
|
-
while my[indexMy.indexMiniGap] < my[indexMy.gap1ndexCeiling]:
|
|
33
|
-
gapsWhere[my[indexMy.gap1ndex]] = gapsWhere[my[indexMy.indexMiniGap]]
|
|
34
|
-
if track[indexTrack.countDimensionsGapped, gapsWhere[my[indexMy.indexMiniGap]]] == my[indexMy.dimensionsUnconstrained]:
|
|
35
|
-
my[indexMy.gap1ndex] += 1
|
|
36
|
-
track[indexTrack.countDimensionsGapped, gapsWhere[my[indexMy.indexMiniGap]]] = 0
|
|
37
|
-
my[indexMy.indexMiniGap] += 1
|
|
38
|
-
if my[indexMy.leaf1ndex] > 0:
|
|
39
|
-
my[indexMy.gap1ndex] -= 1
|
|
40
|
-
track[indexTrack.leafAbove, my[indexMy.leaf1ndex]] = gapsWhere[my[indexMy.gap1ndex]]
|
|
41
|
-
track[indexTrack.leafBelow, my[indexMy.leaf1ndex]] = track[indexTrack.leafBelow, track[indexTrack.leafAbove, my[indexMy.leaf1ndex]]]
|
|
42
|
-
track[indexTrack.leafBelow, track[indexTrack.leafAbove, my[indexMy.leaf1ndex]]] = my[indexMy.leaf1ndex]
|
|
43
|
-
track[indexTrack.leafAbove, track[indexTrack.leafBelow, my[indexMy.leaf1ndex]]] = my[indexMy.leaf1ndex]
|
|
44
|
-
track[indexTrack.gapRangeStart, my[indexMy.leaf1ndex]] = my[indexMy.gap1ndex]
|
|
45
|
-
my[indexMy.leaf1ndex] += 1
|
|
46
|
-
if my[indexMy.gap1ndex] > 0:
|
|
47
|
-
return
|
|
48
|
-
|
|
49
|
-
@jit((uint16[:, :, ::1], int64[::1], uint16[::1], uint16[::1], uint16[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=True, no_cpython_wrapper=True, nopython=True, parallel=True)
|
|
50
|
-
def countParallel(connectionGraph: ndarray[tuple[int, int, int], dtype[integer[Any]]], foldGroups: ndarray[tuple[int], dtype[integer[Any]]], gapsWhere: ndarray[tuple[int], dtype[integer[Any]]], my: ndarray[tuple[int], dtype[integer[Any]]], track: ndarray[tuple[int, int], dtype[integer[Any]]]) -> None:
|
|
51
|
-
gapsWherePARALLEL = gapsWhere.copy()
|
|
52
|
-
myPARALLEL = my.copy()
|
|
53
|
-
trackPARALLEL = track.copy()
|
|
54
|
-
taskDivisionsPrange = myPARALLEL[indexMy.taskDivisions]
|
|
55
|
-
for indexSherpa in prange(taskDivisionsPrange):
|
|
56
|
-
groupsOfFolds: int = 0
|
|
57
|
-
gapsWhere = gapsWherePARALLEL.copy()
|
|
58
|
-
my = myPARALLEL.copy()
|
|
59
|
-
track = trackPARALLEL.copy()
|
|
60
|
-
my[indexMy.taskIndex] = indexSherpa
|
|
61
|
-
while my[indexMy.leaf1ndex] > 0:
|
|
62
|
-
if my[indexMy.leaf1ndex] <= 1 or track[indexTrack.leafBelow, 0] == 1:
|
|
63
|
-
if my[indexMy.leaf1ndex] > foldGroups[-1]:
|
|
64
|
-
groupsOfFolds += 1
|
|
65
|
-
else:
|
|
66
|
-
my[indexMy.dimensionsUnconstrained] = my[indexMy.dimensionsTotal]
|
|
67
|
-
my[indexMy.gap1ndexCeiling] = track[indexTrack.gapRangeStart, my[indexMy.leaf1ndex] - 1]
|
|
68
|
-
my[indexMy.indexDimension] = 0
|
|
69
|
-
while my[indexMy.indexDimension] < my[indexMy.dimensionsTotal]:
|
|
70
|
-
if connectionGraph[my[indexMy.indexDimension], my[indexMy.leaf1ndex], my[indexMy.leaf1ndex]] == my[indexMy.leaf1ndex]:
|
|
71
|
-
my[indexMy.dimensionsUnconstrained] -= 1
|
|
72
|
-
else:
|
|
73
|
-
my[indexMy.leafConnectee] = connectionGraph[my[indexMy.indexDimension], my[indexMy.leaf1ndex], my[indexMy.leaf1ndex]]
|
|
74
|
-
while my[indexMy.leafConnectee] != my[indexMy.leaf1ndex]:
|
|
75
|
-
if my[indexMy.leaf1ndex] != my[indexMy.taskDivisions] or my[indexMy.leafConnectee] % my[indexMy.taskDivisions] == my[indexMy.taskIndex]:
|
|
76
|
-
gapsWhere[my[indexMy.gap1ndexCeiling]] = my[indexMy.leafConnectee]
|
|
77
|
-
if track[indexTrack.countDimensionsGapped, my[indexMy.leafConnectee]] == 0:
|
|
78
|
-
my[indexMy.gap1ndexCeiling] += 1
|
|
79
|
-
track[indexTrack.countDimensionsGapped, my[indexMy.leafConnectee]] += 1
|
|
80
|
-
my[indexMy.leafConnectee] = connectionGraph[my[indexMy.indexDimension], my[indexMy.leaf1ndex], track[indexTrack.leafBelow, my[indexMy.leafConnectee]]]
|
|
81
|
-
my[indexMy.indexDimension] += 1
|
|
82
|
-
my[indexMy.indexMiniGap] = my[indexMy.gap1ndex]
|
|
83
|
-
while my[indexMy.indexMiniGap] < my[indexMy.gap1ndexCeiling]:
|
|
84
|
-
gapsWhere[my[indexMy.gap1ndex]] = gapsWhere[my[indexMy.indexMiniGap]]
|
|
85
|
-
if track[indexTrack.countDimensionsGapped, gapsWhere[my[indexMy.indexMiniGap]]] == my[indexMy.dimensionsUnconstrained]:
|
|
86
|
-
my[indexMy.gap1ndex] += 1
|
|
87
|
-
track[indexTrack.countDimensionsGapped, gapsWhere[my[indexMy.indexMiniGap]]] = 0
|
|
88
|
-
my[indexMy.indexMiniGap] += 1
|
|
89
|
-
while my[indexMy.leaf1ndex] > 0 and my[indexMy.gap1ndex] == track[indexTrack.gapRangeStart, my[indexMy.leaf1ndex] - 1]:
|
|
90
|
-
my[indexMy.leaf1ndex] -= 1
|
|
91
|
-
track[indexTrack.leafBelow, track[indexTrack.leafAbove, my[indexMy.leaf1ndex]]] = track[indexTrack.leafBelow, my[indexMy.leaf1ndex]]
|
|
92
|
-
track[indexTrack.leafAbove, track[indexTrack.leafBelow, my[indexMy.leaf1ndex]]] = track[indexTrack.leafAbove, my[indexMy.leaf1ndex]]
|
|
93
|
-
if my[indexMy.leaf1ndex] > 0:
|
|
94
|
-
my[indexMy.gap1ndex] -= 1
|
|
95
|
-
track[indexTrack.leafAbove, my[indexMy.leaf1ndex]] = gapsWhere[my[indexMy.gap1ndex]]
|
|
96
|
-
track[indexTrack.leafBelow, my[indexMy.leaf1ndex]] = track[indexTrack.leafBelow, track[indexTrack.leafAbove, my[indexMy.leaf1ndex]]]
|
|
97
|
-
track[indexTrack.leafBelow, track[indexTrack.leafAbove, my[indexMy.leaf1ndex]]] = my[indexMy.leaf1ndex]
|
|
98
|
-
track[indexTrack.leafAbove, track[indexTrack.leafBelow, my[indexMy.leaf1ndex]]] = my[indexMy.leaf1ndex]
|
|
99
|
-
track[indexTrack.gapRangeStart, my[indexMy.leaf1ndex]] = my[indexMy.gap1ndex]
|
|
100
|
-
my[indexMy.leaf1ndex] += 1
|
|
101
|
-
foldGroups[my[indexMy.taskIndex]] = groupsOfFolds
|
|
102
|
-
|
|
103
|
-
@jit((uint16[:, :, ::1], int64[::1], uint16[::1], uint16[::1], uint16[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=True, no_cpython_wrapper=True, nopython=True, parallel=False)
|
|
104
|
-
def countSequential(connectionGraph: ndarray[tuple[int, int, int], dtype[integer[Any]]], foldGroups: ndarray[tuple[int], dtype[integer[Any]]], gapsWhere: ndarray[tuple[int], dtype[integer[Any]]], my: ndarray[tuple[int], dtype[integer[Any]]], track: ndarray[tuple[int, int], dtype[integer[Any]]]) -> None:
|
|
105
|
-
leafBelow = track[indexTrack.leafBelow.value]
|
|
106
|
-
gapRangeStart = track[indexTrack.gapRangeStart.value]
|
|
107
|
-
countDimensionsGapped = track[indexTrack.countDimensionsGapped.value]
|
|
108
|
-
leafAbove = track[indexTrack.leafAbove.value]
|
|
109
|
-
leaf1ndex = my[indexMy.leaf1ndex.value]
|
|
110
|
-
dimensionsUnconstrained = my[indexMy.dimensionsUnconstrained.value]
|
|
111
|
-
dimensionsTotal = my[indexMy.dimensionsTotal.value]
|
|
112
|
-
gap1ndexCeiling = my[indexMy.gap1ndexCeiling.value]
|
|
113
|
-
indexDimension = my[indexMy.indexDimension.value]
|
|
114
|
-
leafConnectee = my[indexMy.leafConnectee.value]
|
|
115
|
-
indexMiniGap = my[indexMy.indexMiniGap.value]
|
|
116
|
-
gap1ndex = my[indexMy.gap1ndex.value]
|
|
117
|
-
taskIndex = my[indexMy.taskIndex.value]
|
|
118
|
-
groupsOfFolds: int = 0
|
|
119
|
-
while leaf1ndex > 0:
|
|
120
|
-
if leaf1ndex <= 1 or leafBelow[0] == 1:
|
|
121
|
-
if leaf1ndex > foldGroups[-1]:
|
|
122
|
-
groupsOfFolds += 1
|
|
123
|
-
else:
|
|
124
|
-
dimensionsUnconstrained = dimensionsTotal
|
|
125
|
-
gap1ndexCeiling = gapRangeStart[leaf1ndex - 1]
|
|
126
|
-
indexDimension = 0
|
|
127
|
-
while indexDimension < dimensionsTotal:
|
|
128
|
-
leafConnectee = connectionGraph[indexDimension, leaf1ndex, leaf1ndex]
|
|
129
|
-
if leafConnectee == leaf1ndex:
|
|
130
|
-
dimensionsUnconstrained -= 1
|
|
131
|
-
else:
|
|
132
|
-
while leafConnectee != leaf1ndex:
|
|
133
|
-
gapsWhere[gap1ndexCeiling] = leafConnectee
|
|
134
|
-
if countDimensionsGapped[leafConnectee] == 0:
|
|
135
|
-
gap1ndexCeiling += 1
|
|
136
|
-
countDimensionsGapped[leafConnectee] += 1
|
|
137
|
-
leafConnectee = connectionGraph[indexDimension, leaf1ndex, leafBelow[leafConnectee]]
|
|
138
|
-
indexDimension += 1
|
|
139
|
-
indexMiniGap = gap1ndex
|
|
140
|
-
while indexMiniGap < gap1ndexCeiling:
|
|
141
|
-
gapsWhere[gap1ndex] = gapsWhere[indexMiniGap]
|
|
142
|
-
if countDimensionsGapped[gapsWhere[indexMiniGap]] == dimensionsUnconstrained:
|
|
143
|
-
gap1ndex += 1
|
|
144
|
-
countDimensionsGapped[gapsWhere[indexMiniGap]] = 0
|
|
145
|
-
indexMiniGap += 1
|
|
146
|
-
while leaf1ndex > 0 and gap1ndex == gapRangeStart[leaf1ndex - 1]:
|
|
147
|
-
leaf1ndex -= 1
|
|
148
|
-
leafBelow[leafAbove[leaf1ndex]] = leafBelow[leaf1ndex]
|
|
149
|
-
leafAbove[leafBelow[leaf1ndex]] = leafAbove[leaf1ndex]
|
|
150
|
-
if leaf1ndex > 0:
|
|
151
|
-
gap1ndex -= 1
|
|
152
|
-
leafAbove[leaf1ndex] = gapsWhere[gap1ndex]
|
|
153
|
-
leafBelow[leaf1ndex] = leafBelow[leafAbove[leaf1ndex]]
|
|
154
|
-
leafBelow[leafAbove[leaf1ndex]] = leaf1ndex
|
|
155
|
-
leafAbove[leafBelow[leaf1ndex]] = leaf1ndex
|
|
156
|
-
gapRangeStart[leaf1ndex] = gap1ndex
|
|
157
|
-
leaf1ndex += 1
|
|
158
|
-
foldGroups[taskIndex] = groupsOfFolds
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from mapFolding import indexMy
|
|
2
|
-
from mapFolding.syntheticModules.numbaCount import countInitialize, countSequential, countParallel
|
|
3
|
-
from numba import uint16, int64, jit
|
|
4
|
-
from numpy import ndarray, dtype, integer
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
@jit((uint16[:, :, ::1], int64[::1], uint16[::1], uint16[::1], uint16[::1], uint16[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=False, no_cpython_wrapper=False, nopython=True, parallel=False)
|
|
8
|
-
def doTheNeedful(connectionGraph: ndarray[tuple[int, int, int], dtype[integer[Any]]], foldGroups: ndarray[tuple[int], dtype[integer[Any]]], gapsWhere: ndarray[tuple[int], dtype[integer[Any]]], mapShape: ndarray[tuple[int], dtype[integer[Any]]], my: ndarray[tuple[int], dtype[integer[Any]]], track: ndarray[tuple[int, int], dtype[integer[Any]]]) -> None:
|
|
9
|
-
countInitialize(connectionGraph, gapsWhere, my, track)
|
|
10
|
-
if my[indexMy.taskDivisions] > 0:
|
|
11
|
-
countParallel(connectionGraph, foldGroups, gapsWhere, my, track)
|
|
12
|
-
else:
|
|
13
|
-
countSequential(connectionGraph, foldGroups, gapsWhere, my, track)
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: mapFolding
|
|
3
|
-
Version: 0.8.0
|
|
4
|
-
Summary: Count distinct ways to fold a map (or a strip of stamps)
|
|
5
|
-
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
|
-
License: CC-BY-NC-4.0
|
|
7
|
-
Project-URL: Donate, https://www.patreon.com/integrated
|
|
8
|
-
Project-URL: Homepage, https://github.com/hunterhogan/mapFolding
|
|
9
|
-
Project-URL: Repository, https://github.com/hunterhogan/mapFolding.git
|
|
10
|
-
Keywords: A001415,A001416,A001417,A001418,A195646,combinatorics,folding,map folding,OEIS,optimization,stamp folding
|
|
11
|
-
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: Environment :: Console
|
|
13
|
-
Classifier: Intended Audience :: Education
|
|
14
|
-
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
-
Classifier: Intended Audience :: Other Audience
|
|
16
|
-
Classifier: Intended Audience :: Science/Research
|
|
17
|
-
Classifier: Natural Language :: English
|
|
18
|
-
Classifier: Operating System :: OS Independent
|
|
19
|
-
Classifier: Programming Language :: Python
|
|
20
|
-
Classifier: Programming Language :: Python :: 3
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
-
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
26
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
-
Classifier: Typing :: Typed
|
|
28
|
-
Requires-Python: >=3.10
|
|
29
|
-
Description-Content-Type: text/markdown
|
|
30
|
-
License-File: LICENSE
|
|
31
|
-
Requires-Dist: autoflake
|
|
32
|
-
Requires-Dist: more_itertools
|
|
33
|
-
Requires-Dist: numba_progress
|
|
34
|
-
Requires-Dist: numba
|
|
35
|
-
Requires-Dist: numpy
|
|
36
|
-
Requires-Dist: python_minifier
|
|
37
|
-
Requires-Dist: tomli
|
|
38
|
-
Requires-Dist: Z0Z_tools
|
|
39
|
-
Provides-Extra: testing
|
|
40
|
-
Requires-Dist: mypy; extra == "testing"
|
|
41
|
-
Requires-Dist: pytest; extra == "testing"
|
|
42
|
-
Requires-Dist: pytest-cov; extra == "testing"
|
|
43
|
-
Requires-Dist: pytest-env; extra == "testing"
|
|
44
|
-
Requires-Dist: pytest-xdist; extra == "testing"
|
|
45
|
-
Requires-Dist: pyupgrade; extra == "testing"
|
|
46
|
-
|
|
47
|
-
# mapFolding: Algorithms for enumerating distinct map/stamp folding patterns 🗺️
|
|
48
|
-
|
|
49
|
-
[](https://pypi.org/project/mapFolding/)
|
|
50
|
-
[](https://youtu.be/g6f_miE91mk&t=4)
|
|
51
|
-
[](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
|
|
52
|
-

|
|
53
|
-
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
54
|
-

|
|
55
|
-

|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## Quick start
|
|
60
|
-
|
|
61
|
-
```sh
|
|
62
|
-
pip install mapFolding
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
`OEIS_for_n` will run a computation from the command line.
|
|
66
|
-
|
|
67
|
-
```cmd
|
|
68
|
-
(mapFolding) C:\apps\mapFolding> OEIS_for_n A001418 5
|
|
69
|
-
186086600 distinct folding patterns.
|
|
70
|
-
Time elapsed: 1.605 seconds
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
Use `mapFolding.oeisIDfor_n()` to compute a(n) for an OEIS ID.
|
|
74
|
-
|
|
75
|
-
```python
|
|
76
|
-
from mapFolding import oeisIDfor_n
|
|
77
|
-
foldsTotal = oeisIDfor_n( 'A001418', 4 )
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## Features
|
|
83
|
-
|
|
84
|
-
### 1. Simple, easy usage based on OEIS IDs
|
|
85
|
-
|
|
86
|
-
`mapFolding` directly implements some IDs from [_The On-Line Encyclopedia of Integer Sequences_](https://oeis.org/) ([BibTex](https://github.com/hunterhogan/mapFolding/blob/main/citations/oeis.bibtex) citation).
|
|
87
|
-
|
|
88
|
-
Use `getOEISids` to get the most up-to-date list of available OEIS IDs.
|
|
89
|
-
|
|
90
|
-
```cmd
|
|
91
|
-
(mapFolding) C:\apps\mapFolding> getOEISids
|
|
92
|
-
|
|
93
|
-
Available OEIS sequences:
|
|
94
|
-
A001415: Number of ways of folding a 2 X n strip of stamps.
|
|
95
|
-
A001416: Number of ways of folding a 3 X n strip of stamps.
|
|
96
|
-
A001417: Number of ways of folding a 2 X 2 X ... X 2 n-dimensional map.
|
|
97
|
-
A001418: Number of ways of folding an n X n sheet of stamps.
|
|
98
|
-
A195646: Number of ways of folding a 3 X 3 X ... X 3 n-dimensional map.
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### 2. **Algorithm Zoo** 🦒
|
|
102
|
-
|
|
103
|
-
- **Lunnon’s 1971 Algorithm**: A painstakingly debugged version of [the original typo-riddled code](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt)
|
|
104
|
-
- The /reference directory.
|
|
105
|
-
- **Numba-JIT Accelerated**: Up to 1000× faster than pure Python ([benchmarks](https://github.com/hunterhogan/mapFolding/blob/mapFolding/notes/Speed%20highlights.md))
|
|
106
|
-
|
|
107
|
-
### 3. **For Researchers** 🔬
|
|
108
|
-
|
|
109
|
-
- Change multiple minute settings, such as the bit width of the data types.
|
|
110
|
-
- Transform the algorithm using AST
|
|
111
|
-
- Create hyper-optimized modules to compute a specific map.
|
|
112
|
-
|
|
113
|
-
### 4. **Customizing your algorithm**
|
|
114
|
-
|
|
115
|
-
- Renovations in progress: ~~mapFolding\someAssemblyRequired\synthesizeNumbaJob.py (and/or synthesizeNumba____.py, as applicable)~~
|
|
116
|
-
- Synthesize a Numba-optimized module for a specific mapShape
|
|
117
|
-
- Synthesize _from_ a module in mapFolding\syntheticModules or from any source you select
|
|
118
|
-
- Use the existing transformation options
|
|
119
|
-
- Or create new ways of transforming the algorithm from its source to a specific job
|
|
120
|
-
- Renovations in progress: ~~mapFolding\someAssemblyRequired\makeJob.py~~
|
|
121
|
-
- Initialize data for a specific mapShape
|
|
122
|
-
- Renovations in progress: ~~mapFolding\someAssemblyRequired\synthesizeNumbaModules.py (and/or synthesizeNumba____.py, as applicable)~~
|
|
123
|
-
- Synthesize one or more Numba-optimized modules for parallel or sequential computation
|
|
124
|
-
- Overwrite the modules in mapFolding\syntheticModules or save the module(s) to a custom path
|
|
125
|
-
- Synthesize _from_ the algorithm(s) in mapFolding\theDao.py or from any source you select
|
|
126
|
-
- Use the existing transformation options
|
|
127
|
-
- Or create new ways of transforming the algorithm from its source to a new module
|
|
128
|
-
- Use your new module in synthesizeNumbaJob.py, above, as the source to create a mapShape-specific job module
|
|
129
|
-
- mapFolding\theDao.py
|
|
130
|
-
- Modify the algorithms for initializing values, parallel computation, and/or sequential computation
|
|
131
|
-
- Use the modified algorithm(s) in synthesizeNumbaModules.py, above, to create Numba-optimized version(s)
|
|
132
|
-
- Then use a Numba-optimized version in synthesizeNumbaJob.py, above, to create a hyper-optimized version for a specific mapShape
|
|
133
|
-
- mapFolding\theSSOT.py
|
|
134
|
-
- Modify broad settings or find functions to modify broad settings, such as data structures and their data types
|
|
135
|
-
- Create new settings or groups of settings
|
|
136
|
-
- mapFolding\beDRY.py
|
|
137
|
-
- Functions to handle common tasks, such as parsing parameters or creating the `connectionGraph` for a mapShape (a Cartesian product decomposition)
|
|
138
|
-
- mapFolding\someAssemblyRequired
|
|
139
|
-
- Create new transformations to optimize the algorithm, such as for JAX, CuPy, or CUDA
|
|
140
|
-
- (mapFolding\reference\jax.py has a once-functional JAX implementation, and synthesizeModuleJAX.py might be a useful starting point)
|
|
141
|
-
|
|
142
|
-
## Map-folding Video
|
|
143
|
-
|
|
144
|
-
~~This caused my neurosis:~~ I enjoyed the following video, which is what introduced me to map folding.
|
|
145
|
-
|
|
146
|
-
"How Many Ways Can You Fold a Map?" by Physics for the Birds, 2024 November 13 ([BibTex](https://github.com/hunterhogan/mapFolding/blob/main/citations/Physics_for_the_Birds.bibtex) citation)
|
|
147
|
-
|
|
148
|
-
[](https://www.youtube.com/watch?v=sfH9uIY3ln4)
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## My recovery
|
|
153
|
-
|
|
154
|
-
[](https://HunterThinks.com/support)
|
|
155
|
-
[](https://www.youtube.com/@HunterHogan)
|
|
156
|
-
|
|
157
|
-
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
mapFolding/__init__.py,sha256=hONqdWnBN1ebgrKZuMIZfI8m-1krSR66L4GTVRwBmw4,203
|
|
2
|
-
mapFolding/basecamp.py,sha256=Ik_oH-MpH8f6k-yBzwm99lfkv3pMDgFFEnSSDyiJjsQ,3861
|
|
3
|
-
mapFolding/beDRY.py,sha256=nn0AEGzrroM3wp91Fts7mmx1VQgG14s0EZsXR-Uy5x8,9049
|
|
4
|
-
mapFolding/filesystem.py,sha256=KqgsO-jaSWAlYib_9ovoXQY76PcQri09_73u0OqMWC8,4094
|
|
5
|
-
mapFolding/noHomeYet.py,sha256=DAppmTJG95Ip1qF1uVLU_vXGz4Lmonp8OYfGXtmOnTE,785
|
|
6
|
-
mapFolding/oeis.py,sha256=ZNt3UBklmpfjdmgbA7pO-ezz2prafr2JvdkpIDapi1w,11853
|
|
7
|
-
mapFolding/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
mapFolding/theDao.py,sha256=E-hisOy_1_iQqS6w4c7S-C-sIgIcwnAPFqooeWuinVY,9008
|
|
9
|
-
mapFolding/theSSOT.py,sha256=r7_9t0dOo_IfBMqmkm1WXOzMfZjyPNco0hl1g9uU_2Y,12710
|
|
10
|
-
mapFolding/reference/flattened.py,sha256=S6D9wiFTlbeoetEqaMLOcA-R22BHOzjqPRujffNxxUM,14875
|
|
11
|
-
mapFolding/reference/hunterNumba.py,sha256=jDS0ORHkIhcJ1rzA5hT49sZHKf3rgJOoGesUCcbKFFY,6054
|
|
12
|
-
mapFolding/reference/irvineJavaPort.py,sha256=7GvBU0tnS6wpFgkYad3465do9jBQW-2bYvbCYyABPHM,3341
|
|
13
|
-
mapFolding/reference/jax.py,sha256=7ji9YWia6Kof0cjcNdiS1GG1rMbC5SBjcyVr_07AeUk,13845
|
|
14
|
-
mapFolding/reference/lunnan.py,sha256=iAbJELfW6RKNMdPcBY9b6rGQ-z1zoRf-1XCurCRMOo8,3951
|
|
15
|
-
mapFolding/reference/lunnanNumpy.py,sha256=rwVP3WIDXimpAuaxhRIuBYU56nVDTKlfGiclw_FkgUU,3765
|
|
16
|
-
mapFolding/reference/lunnanWhile.py,sha256=uRrMT23jTJvoQDlD_FzeIQe_pfMXJG6_bRvs7uhC8z0,3271
|
|
17
|
-
mapFolding/reference/rotatedEntryPoint.py,sha256=USZY3n3zwhSE68ATscUuN66t1qShuEbMI790Gz9JFTw,9352
|
|
18
|
-
mapFolding/reference/total_countPlus1vsPlusN.py,sha256=wpgay-uqPOBd64Z4Pg6tg40j7-4pzWHGMM6v0bnmjhE,6288
|
|
19
|
-
mapFolding/someAssemblyRequired/Z0Z_workbench.py,sha256=g4VkNKp2ts0koqcMSPNbE_ySR2-23Y-5CJBDpvbT6XU,16853
|
|
20
|
-
mapFolding/someAssemblyRequired/__init__.py,sha256=G1uIo1RWcdBjeFPXFwa69kizsZFzkDR55B2uyyY5z7E,680
|
|
21
|
-
mapFolding/someAssemblyRequired/getLLVMforNoReason.py,sha256=2kGRji3FGaALZwUZ6qlEjS7QxOkJK1Si-mAnsWePs_Q,983
|
|
22
|
-
mapFolding/someAssemblyRequired/ingredientsNumba.py,sha256=u5621TzZW7Sp8BXedq0yooyYoFwDDsd9smoqObzRf8g,7359
|
|
23
|
-
mapFolding/someAssemblyRequired/synthesizeDataConverters.py,sha256=J1qLKxqCMQd5JhcrTg9fvpPCfhb5TLz2wXY-J9z-TH8,5792
|
|
24
|
-
mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py,sha256=3yRCEMIf9UCswu6wQvdUK9H3MW6Ossn-wg5eOq8LWz8,22362
|
|
25
|
-
mapFolding/someAssemblyRequired/transformationTools.py,sha256=u2ah47kOqvVGKifuk7rZe4bSm3Z681nJzp73IXavYw4,36297
|
|
26
|
-
mapFolding/syntheticModules/numbaCountHistoricalExample.py,sha256=Oo0Xeex89sLD15iRt3N76OKRFScKl9qwO84-d5sv6lM,11871
|
|
27
|
-
mapFolding/syntheticModules/numbaCount_doTheNeedful.py,sha256=52RuwJVH2fROvWU2dT8wYcQvLgRuvkNZPq01kujCC_U,15725
|
|
28
|
-
mapFolding/syntheticModules/numba_doTheNeedfulHistoricalExample.py,sha256=J9wZ9PW5EVduOQWVze7CgpTHkUjRIvBPG8fNuT3IVpA,1145
|
|
29
|
-
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
-
tests/conftest.py,sha256=rRlXOhihwheHyQ8ggjRBbmgPVERxWjupajguVBzBkVE,10783
|
|
31
|
-
tests/test_computations.py,sha256=YhadlskBh_r5RiefHRy0FlrYQ0FelYbqcSNNSkSJMIY,3368
|
|
32
|
-
tests/test_filesystem.py,sha256=Kou0gj5T72oISao6umYfU6L_W5Hi7QS9_IxTv2hU0Pw,3147
|
|
33
|
-
tests/test_oeis.py,sha256=uxvwmgbnylSDdsVJfuAT0LuYLbIVFwSgdLxHm-xUGBM,5043
|
|
34
|
-
tests/test_other.py,sha256=1uuApByNWPiTf0zaro2dETkvyWQFfMweU_ge4aJuVgM,4244
|
|
35
|
-
tests/test_tasks.py,sha256=hkZygihT8bCEO2zc-2VcxReQrZJBwgLNbYx0YP4lTDg,2853
|
|
36
|
-
mapfolding-0.8.0.dist-info/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
|
|
37
|
-
mapfolding-0.8.0.dist-info/METADATA,sha256=AA0b9jY45EztgHbZQq8SbpBExcDpnmhotXZB4DDO_2A,7670
|
|
38
|
-
mapfolding-0.8.0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
|
39
|
-
mapfolding-0.8.0.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
|
|
40
|
-
mapfolding-0.8.0.dist-info/top_level.txt,sha256=1gP2vFaqPwHujGwb3UjtMlLEGN-943VSYFR7V4gDqW8,17
|
|
41
|
-
mapfolding-0.8.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|