mapFolding 0.4.2__py3-none-any.whl → 0.4.3__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 +2 -1
- mapFolding/basecamp.py +1 -1
- mapFolding/beDRY.py +61 -39
- mapFolding/oeis.py +18 -17
- mapFolding/someAssemblyRequired/synthesizeNumba.py +40 -48
- mapFolding/someAssemblyRequired/synthesizeNumbaGeneralized.py +83 -12
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +12 -23
- mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +82 -30
- mapFolding/syntheticModules/numbaCount.py +158 -0
- mapFolding/syntheticModules/numba_doTheNeedful.py +5 -12
- mapFolding/theDao.py +75 -75
- mapFolding/theSSOT.py +50 -189
- mapFolding/theSSOTdatatypes.py +168 -0
- {mapFolding-0.4.2.dist-info → mapFolding-0.4.3.dist-info}/METADATA +1 -1
- mapFolding-0.4.3.dist-info/RECORD +40 -0
- tests/conftest.py +30 -1
- tests/test_computations.py +27 -63
- tests/test_oeis.py +7 -10
- mapFolding/syntheticModules/numba_countInitialize.py +0 -52
- mapFolding/syntheticModules/numba_countParallel.py +0 -65
- mapFolding/syntheticModules/numba_countSequential.py +0 -67
- mapFolding/theSSOTnumba.py +0 -125
- mapFolding-0.4.2.dist-info/RECORD +0 -42
- {mapFolding-0.4.2.dist-info → mapFolding-0.4.3.dist-info}/LICENSE +0 -0
- {mapFolding-0.4.2.dist-info → mapFolding-0.4.3.dist-info}/WHEEL +0 -0
- {mapFolding-0.4.2.dist-info → mapFolding-0.4.3.dist-info}/entry_points.txt +0 -0
- {mapFolding-0.4.2.dist-info → mapFolding-0.4.3.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from mapFolding import (
|
|
2
2
|
computationState,
|
|
3
3
|
EnumIndices,
|
|
4
|
-
|
|
4
|
+
formatFilenameModuleDEFAULT,
|
|
5
5
|
FREAKOUT,
|
|
6
6
|
getAlgorithmDispatcher,
|
|
7
7
|
getAlgorithmSource,
|
|
@@ -36,7 +36,7 @@ from numpy import integer
|
|
|
36
36
|
from numpy.typing import NDArray
|
|
37
37
|
from types import ModuleType
|
|
38
38
|
from typing import Any, Callable, cast, Dict, List, Optional, Sequence, Set, Tuple, Type, Union
|
|
39
|
-
from Z0Z_tools import autoDecodingRLE
|
|
39
|
+
from Z0Z_tools import autoDecodingRLE, updateExtendPolishDictionaryLists
|
|
40
40
|
import ast
|
|
41
41
|
import autoflake
|
|
42
42
|
import collections
|
|
@@ -49,9 +49,41 @@ import numpy
|
|
|
49
49
|
import os
|
|
50
50
|
import pathlib
|
|
51
51
|
import python_minifier
|
|
52
|
+
import warnings
|
|
52
53
|
|
|
53
54
|
youOughtaKnow = collections.namedtuple('youOughtaKnow', ['callableSynthesized', 'pathFilenameForMe', 'astForCompetentProgrammers'])
|
|
54
55
|
|
|
56
|
+
# idk how to use this
|
|
57
|
+
class ASTBodyTransformer:
|
|
58
|
+
"""
|
|
59
|
+
A helper class to apply multiple transformations on an AST FunctionDef's body.
|
|
60
|
+
This abstraction eliminates the need to write repetitive loops for removals,
|
|
61
|
+
replacements, or insertions.
|
|
62
|
+
"""
|
|
63
|
+
def __init__(self, functionDefinition: ast.FunctionDef) -> None:
|
|
64
|
+
self.functionDefinition = functionDefinition
|
|
65
|
+
|
|
66
|
+
def replaceIn_body(self, predicate: Callable[[ast.stmt], bool], replacementBuilder: Callable[[ast.stmt], Optional[ast.stmt]]) -> None:
|
|
67
|
+
newBody: List[ast.stmt] = []
|
|
68
|
+
for statement in self.functionDefinition.body:
|
|
69
|
+
if predicate(statement):
|
|
70
|
+
replacementStatement = replacementBuilder(statement)
|
|
71
|
+
if replacementStatement is not None:
|
|
72
|
+
newBody.append(replacementStatement)
|
|
73
|
+
else:
|
|
74
|
+
newBody.append(statement)
|
|
75
|
+
self.functionDefinition.body = newBody
|
|
76
|
+
|
|
77
|
+
def atIndexInsert(self, index: int, statement: ast.stmt) -> None:
|
|
78
|
+
self.functionDefinition.body.insert(index, statement)
|
|
79
|
+
|
|
80
|
+
def removeAllOf(self, predicate: Callable[[ast.stmt], bool]) -> None:
|
|
81
|
+
self.replaceIn_body(predicate, lambda stmt: None)
|
|
82
|
+
|
|
83
|
+
def Z0Z_apply(self) -> ast.FunctionDef:
|
|
84
|
+
ast.fix_missing_locations(self.functionDefinition)
|
|
85
|
+
return self.functionDefinition
|
|
86
|
+
|
|
55
87
|
# Generic
|
|
56
88
|
class ifThis:
|
|
57
89
|
"""Generic AST node predicate builder."""
|
|
@@ -71,10 +103,27 @@ class ifThis:
|
|
|
71
103
|
def isCallWithName(callableName: str) -> Callable[[ast.AST], bool]:
|
|
72
104
|
return lambda node: (isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == callableName)
|
|
73
105
|
|
|
106
|
+
@staticmethod
|
|
107
|
+
def isAssignTarget(identifier: str):
|
|
108
|
+
return lambda node: (isinstance(node, ast.Assign)
|
|
109
|
+
and node.targets
|
|
110
|
+
and isinstance(node.targets[0], ast.Name)
|
|
111
|
+
and node.targets[0].id == identifier)
|
|
112
|
+
|
|
74
113
|
@staticmethod
|
|
75
114
|
def anyOf(*predicates: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
|
|
76
115
|
return lambda node: any(pred(node) for pred in predicates)
|
|
77
116
|
|
|
117
|
+
@staticmethod
|
|
118
|
+
def isUnpackingAnArray(identifier:str):
|
|
119
|
+
return lambda node: (isinstance(node, ast.Assign)
|
|
120
|
+
and isinstance(node.targets[0], ast.Name)
|
|
121
|
+
and isinstance(node.value, ast.Subscript)
|
|
122
|
+
and isinstance(node.value.value, ast.Name)
|
|
123
|
+
and node.value.value.id == identifier
|
|
124
|
+
and isinstance(node.value.slice, ast.Attribute)
|
|
125
|
+
)
|
|
126
|
+
|
|
78
127
|
class Then:
|
|
79
128
|
"""Generic actions."""
|
|
80
129
|
@staticmethod
|
|
@@ -103,9 +152,8 @@ class NodeReplacer(ast.NodeTransformer):
|
|
|
103
152
|
None from the replacement builder indicates that the node should be removed.
|
|
104
153
|
|
|
105
154
|
Attributes:
|
|
106
|
-
findMe
|
|
107
|
-
nodeReplacementBuilder
|
|
108
|
-
or None to remove the node.
|
|
155
|
+
findMe: A function that determines whether a node should be replaced.
|
|
156
|
+
nodeReplacementBuilder: A function that returns a new node or None to remove the node.
|
|
109
157
|
|
|
110
158
|
Methods:
|
|
111
159
|
visit(node: ast.AST) -> Optional[ast.AST]:
|
|
@@ -142,19 +190,42 @@ class UniversalImportTracker:
|
|
|
142
190
|
self.setImport.add(alias.name)
|
|
143
191
|
elif isinstance(astImport_, ast.ImportFrom):
|
|
144
192
|
if astImport_.module is not None:
|
|
145
|
-
self.dictionaryImportFrom[astImport_.module].update(alias.name for alias in astImport_.names)
|
|
193
|
+
self.dictionaryImportFrom[astImport_.module].update((alias.name, alias.asname) for alias in astImport_.names)
|
|
146
194
|
|
|
147
|
-
def
|
|
148
|
-
self.
|
|
195
|
+
def addImportStr(self, module: str) -> None:
|
|
196
|
+
self.setImport.add(module)
|
|
149
197
|
|
|
150
|
-
def
|
|
151
|
-
self.
|
|
198
|
+
def addImportFromStr(self, module: str, name: str, asname: Optional[str] = None) -> None:
|
|
199
|
+
self.dictionaryImportFrom[module].add((name, asname))
|
|
152
200
|
|
|
153
201
|
def makeListAst(self) -> List[Union[ast.ImportFrom, ast.Import]]:
|
|
154
|
-
listAstImportFrom = [
|
|
155
|
-
|
|
202
|
+
listAstImportFrom = []
|
|
203
|
+
for module, setOfNameTuples in sorted(self.dictionaryImportFrom.items()):
|
|
204
|
+
listAliases = []
|
|
205
|
+
for name, asname in setOfNameTuples:
|
|
206
|
+
listAliases.append(ast.alias(name=name, asname=asname))
|
|
207
|
+
listAstImportFrom.append(ast.ImportFrom(module=module, names=listAliases, level=0))
|
|
208
|
+
|
|
209
|
+
listAstImport = [ast.Import(names=[ast.alias(name=name, asname=None)]) for name in sorted(self.setImport)]
|
|
156
210
|
return listAstImportFrom + listAstImport
|
|
157
211
|
|
|
212
|
+
def update(self, *fromTracker: 'UniversalImportTracker') -> None:
|
|
213
|
+
"""
|
|
214
|
+
Update this tracker with imports from one or more other trackers.
|
|
215
|
+
|
|
216
|
+
Parameters:
|
|
217
|
+
*fromTracker: One or more UniversalImportTracker objects to merge from.
|
|
218
|
+
"""
|
|
219
|
+
# Merge all import-from dictionaries
|
|
220
|
+
dictionaryMerged = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(tracker.dictionaryImportFrom for tracker in fromTracker), destroyDuplicates=True, reorderLists=True)
|
|
221
|
+
|
|
222
|
+
# Convert lists back to sets for each module's imports
|
|
223
|
+
self.dictionaryImportFrom = {module: set(listNames) for module, listNames in dictionaryMerged.items()}
|
|
224
|
+
|
|
225
|
+
# Update direct imports
|
|
226
|
+
for tracker in fromTracker:
|
|
227
|
+
self.setImport.update(tracker.setImport)
|
|
228
|
+
|
|
158
229
|
# Intricate and specialized
|
|
159
230
|
class RecursiveInliner(ast.NodeTransformer):
|
|
160
231
|
"""
|
|
@@ -64,6 +64,7 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
64
64
|
pythonSource = inspect.getsource(algorithmSource)
|
|
65
65
|
astModule = ast.parse(pythonSource)
|
|
66
66
|
setFunctionDef = {statement for statement in astModule.body if isinstance(statement, ast.FunctionDef)}
|
|
67
|
+
|
|
67
68
|
if not callableTarget:
|
|
68
69
|
if len(setFunctionDef) == 1:
|
|
69
70
|
FunctionDefTarget = setFunctionDef.pop()
|
|
@@ -71,7 +72,8 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
71
72
|
else:
|
|
72
73
|
raise ValueError(f"I did not receive a `callableTarget` and {algorithmSource.__name__=} has more than one callable: {setFunctionDef}. Please select one.")
|
|
73
74
|
else:
|
|
74
|
-
|
|
75
|
+
listFunctionDefTarget = [statement for statement in setFunctionDef if statement.name == callableTarget]
|
|
76
|
+
FunctionDefTarget = listFunctionDefTarget[0] if listFunctionDefTarget else None
|
|
75
77
|
if not FunctionDefTarget: raise ValueError(f"I received `{callableTarget=}` and {algorithmSource.__name__=}, but I could not find that function in that source.")
|
|
76
78
|
|
|
77
79
|
# NOTE `allImports` is a complementary container to `FunctionDefTarget`; the `FunctionDefTarget` cannot track its own imports very well.
|
|
@@ -86,13 +88,15 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
86
88
|
case 'my':
|
|
87
89
|
FunctionDefTarget, allImports = findAndReplaceArraySubscriptIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], ['taskIndex', 'dimensionsTotal'], allImports)
|
|
88
90
|
case 'track':
|
|
89
|
-
FunctionDefTarget, allImports =
|
|
91
|
+
FunctionDefTarget, allImports = findAndReplaceTrackArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
90
92
|
case 'connectionGraph':
|
|
91
93
|
FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
92
94
|
case 'gapsWhere':
|
|
93
95
|
FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
94
96
|
case 'foldGroups':
|
|
95
97
|
FunctionDefTarget = removeAssignTargetFrom_body(FunctionDefTarget, pirateScowl.arg)
|
|
98
|
+
# FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
99
|
+
# continue
|
|
96
100
|
FunctionDefTarget.args.args.remove(pirateScowl)
|
|
97
101
|
|
|
98
102
|
# NOTE replace identifiers with static values with their values
|
|
@@ -110,8 +114,6 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
110
114
|
FunctionDefTarget, allImports = insertReturnStatementIn_body(FunctionDefTarget, stateJob['foldGroups'], allImports)
|
|
111
115
|
|
|
112
116
|
# NOTE add the perfect decorator
|
|
113
|
-
datatype = hackSSOTdatatype(Z0Z_identifierCountFolds)
|
|
114
|
-
FunctionDefTarget.returns = ast.Name(id=datatype, ctx=ast.Load())
|
|
115
117
|
FunctionDefTarget, allImports = decorateCallableWithNumba(FunctionDefTarget, allImports, parametersNumba)
|
|
116
118
|
if thisIsNumbaDotJit(FunctionDefTarget.decorator_list[0]):
|
|
117
119
|
astCall = cast(ast.Call, FunctionDefTarget.decorator_list[0])
|
|
@@ -124,21 +126,7 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
124
126
|
ast.fix_missing_locations(astModule)
|
|
125
127
|
pythonSource = ast.unparse(astModule)
|
|
126
128
|
pythonSource = autoflake.fix_code(pythonSource, ['mapFolding', 'numba', 'numpy'])
|
|
127
|
-
pythonSource = python_minifier.minify(pythonSource, remove_annotations = False,
|
|
128
|
-
remove_pass = False,
|
|
129
|
-
remove_literal_statements = False,
|
|
130
|
-
combine_imports = True,
|
|
131
|
-
hoist_literals = False,
|
|
132
|
-
rename_locals = False,
|
|
133
|
-
rename_globals = False,
|
|
134
|
-
remove_object_base = False,
|
|
135
|
-
convert_posargs_to_args = False,
|
|
136
|
-
preserve_shebang = True,
|
|
137
|
-
remove_asserts = False,
|
|
138
|
-
remove_debug = False,
|
|
139
|
-
remove_explicit_return_none = False,
|
|
140
|
-
remove_builtin_exception_brackets = False,
|
|
141
|
-
constant_folding = False)
|
|
129
|
+
# pythonSource = python_minifier.minify(pythonSource, remove_annotations = False, remove_pass = False, remove_literal_statements = False, combine_imports = True, hoist_literals = False, rename_locals = False, rename_globals = False, remove_object_base = False, convert_posargs_to_args = False, preserve_shebang = True, remove_asserts = False, remove_debug = False, remove_explicit_return_none = False, remove_builtin_exception_brackets = False, constant_folding = False)
|
|
142
130
|
|
|
143
131
|
# NOTE put on disk
|
|
144
132
|
if pathFilenameWriteJob is None:
|
|
@@ -155,17 +143,18 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
155
143
|
|
|
156
144
|
if __name__ == '__main__':
|
|
157
145
|
mapShape = [5,5]
|
|
158
|
-
from mapFolding.syntheticModules import
|
|
159
|
-
algorithmSource: ModuleType =
|
|
146
|
+
from mapFolding.syntheticModules import numbaCount
|
|
147
|
+
algorithmSource: ModuleType = numbaCount
|
|
160
148
|
|
|
161
|
-
callableTarget =
|
|
149
|
+
callableTarget = 'countSequential'
|
|
162
150
|
|
|
163
151
|
parametersNumba = parametersNumbaDEFAULT
|
|
152
|
+
parametersNumba['boundscheck'] = True
|
|
164
153
|
|
|
165
154
|
pathFilenameWriteJob = None
|
|
166
155
|
|
|
167
156
|
setDatatypeFoldsTotal('int64', sourGrapes=True)
|
|
168
|
-
setDatatypeElephino('
|
|
157
|
+
setDatatypeElephino('int16', sourGrapes=True)
|
|
169
158
|
setDatatypeLeavesTotal('uint8', sourGrapes=True)
|
|
170
159
|
Z0Z_setDatatypeModuleScalar('numba')
|
|
171
160
|
Z0Z_setDecoratorCallable('jit')
|
|
@@ -4,42 +4,82 @@ everything I am doing. I would rather benefit from humanity's
|
|
|
4
4
|
collective wisdom."""
|
|
5
5
|
from mapFolding.someAssemblyRequired.synthesizeNumba import *
|
|
6
6
|
|
|
7
|
-
def
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
def getFunctionDef(algorithmSource: ModuleType, *arguments, **keywordArguments) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
8
|
+
pythonSource = inspect.getsource(algorithmSource)
|
|
9
|
+
astModule: ast.Module = ast.parse(pythonSource, type_comments=True)
|
|
10
|
+
FunctionDefTarget, allImports = makeFunctionDef(astModule, *arguments, **keywordArguments)
|
|
11
|
+
return FunctionDefTarget, allImports
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
def makePythonSource(listFunctionDefs: List[ast.FunctionDef], listAstImports: List[ast.Import|ast.ImportFrom], additional_imports: List[str]) -> str:
|
|
14
|
+
astModule = ast.Module(body=cast(List[ast.stmt], listAstImports + listFunctionDefs), type_ignores=[])
|
|
15
|
+
ast.fix_missing_locations(astModule)
|
|
16
|
+
pythonSource = ast.unparse(astModule)
|
|
17
|
+
if not pythonSource: raise FREAKOUT
|
|
18
|
+
pythonSource = autoflake.fix_code(pythonSource, additional_imports)
|
|
19
|
+
return pythonSource
|
|
20
|
+
|
|
21
|
+
def writePythonAsModule(pythonSource: str, listCallableSynthesized: List[str], relativePathWrite: Optional[pathlib.Path], filenameWrite: Optional[str], formatFilenameWrite: Optional[str]) -> List[youOughtaKnow]:
|
|
22
|
+
pathFilename = None
|
|
23
|
+
if not relativePathWrite:
|
|
24
|
+
pathWrite = getPathSyntheticModules()
|
|
25
|
+
else:
|
|
26
|
+
pathWrite = getPathPackage() / relativePathWrite
|
|
14
27
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
pythonSource = makeAstModuleForOneCallable(pythonSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
|
|
18
|
-
if not pythonSource: raise FREAKOUT
|
|
19
|
-
pythonSource = autoflake.fix_code(pythonSource, ['mapFolding', 'numba', 'numpy'])
|
|
28
|
+
if not formatFilenameWrite:
|
|
29
|
+
formatFilenameWrite = formatFilenameModuleDEFAULT
|
|
20
30
|
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
if not filenameWrite:
|
|
32
|
+
if len(listCallableSynthesized) == 1:
|
|
33
|
+
callableTarget = listCallableSynthesized[0]
|
|
23
34
|
else:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
callableTarget = 'count'
|
|
36
|
+
filenameWrite = formatFilenameWrite.format(callableTarget=callableTarget)
|
|
37
|
+
else:
|
|
38
|
+
if not filenameWrite.endswith('.py'):
|
|
39
|
+
warnings.warn(f"Filename {filenameWrite=} does not end with '.py'.")
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
pathFilename = pathWrite / filenameWrite
|
|
30
42
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
pathFilename.write_text(pythonSource)
|
|
44
|
+
|
|
45
|
+
howIsThisStillAThing = getPathPackage().parent
|
|
46
|
+
dumbassPythonNamespace = pathFilename.relative_to(howIsThisStillAThing).with_suffix('').parts
|
|
47
|
+
ImaModule = '.'.join(dumbassPythonNamespace)
|
|
48
|
+
|
|
49
|
+
listStuffYouOughtaKnow: List[youOughtaKnow] = []
|
|
50
|
+
|
|
51
|
+
for callableTarget in listCallableSynthesized:
|
|
34
52
|
astImportFrom = ast.ImportFrom(module=ImaModule, names=[ast.alias(name=callableTarget, asname=None)], level=0)
|
|
53
|
+
stuff = youOughtaKnow(callableSynthesized=callableTarget, pathFilenameForMe=pathFilename, astForCompetentProgrammers=astImportFrom)
|
|
54
|
+
listStuffYouOughtaKnow.append(stuff)
|
|
35
55
|
|
|
36
|
-
|
|
56
|
+
return listStuffYouOughtaKnow
|
|
37
57
|
|
|
58
|
+
def makeFlowNumbaOptimized(listCallablesInline: List[str]
|
|
59
|
+
, callableDispatcher: Optional[bool] = False
|
|
60
|
+
, algorithmSource: Optional[ModuleType] = None
|
|
61
|
+
, relativePathWrite: Optional[pathlib.Path] = None
|
|
62
|
+
, filenameModuleWrite: Optional[str] = None
|
|
63
|
+
, formatFilenameWrite: Optional[str] = None
|
|
64
|
+
) -> List[youOughtaKnow]:
|
|
65
|
+
if relativePathWrite and relativePathWrite.is_absolute():
|
|
66
|
+
raise ValueError("The path to write the module must be relative to the root of the package.")
|
|
67
|
+
if not algorithmSource:
|
|
68
|
+
algorithmSource = getAlgorithmSource()
|
|
69
|
+
|
|
70
|
+
Z0Z_filenameModuleWrite = 'numbaCount.py'
|
|
71
|
+
|
|
72
|
+
listStuffYouOughtaKnow: List[youOughtaKnow] = []
|
|
73
|
+
additional_imports = ['mapFolding', 'numba', 'numpy']
|
|
74
|
+
|
|
75
|
+
listFunctionDefs: List[ast.FunctionDef] = []
|
|
76
|
+
allImportsModule = UniversalImportTracker()
|
|
38
77
|
for callableTarget in listCallablesInline:
|
|
39
78
|
parametersNumba = None
|
|
40
79
|
inlineCallables = True
|
|
41
80
|
unpackArrays = False
|
|
42
81
|
allImports = None
|
|
82
|
+
filenameWrite = None
|
|
43
83
|
match callableTarget:
|
|
44
84
|
case 'countParallel':
|
|
45
85
|
parametersNumba = parametersNumbaSuperJitParallel
|
|
@@ -48,7 +88,17 @@ def makeFlowNumbaOptimized(listCallablesInline: List[str], callableDispatcher: O
|
|
|
48
88
|
unpackArrays = True
|
|
49
89
|
case 'countInitialize':
|
|
50
90
|
parametersNumba = parametersNumbaDEFAULT
|
|
51
|
-
|
|
91
|
+
FunctionDefTarget, allImports = getFunctionDef(algorithmSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
|
|
92
|
+
listFunctionDefs.append(FunctionDefTarget)
|
|
93
|
+
allImportsModule.update(allImports)
|
|
94
|
+
|
|
95
|
+
listAstImports = allImportsModule.makeListAst()
|
|
96
|
+
pythonSource = makePythonSource(listFunctionDefs, listAstImports, additional_imports)
|
|
97
|
+
|
|
98
|
+
filenameWrite = filenameModuleWrite or Z0Z_filenameModuleWrite
|
|
99
|
+
|
|
100
|
+
listStuff = writePythonAsModule(pythonSource, listCallablesInline, relativePathWrite, filenameWrite, formatFilenameWrite)
|
|
101
|
+
listStuffYouOughtaKnow.extend(listStuff)
|
|
52
102
|
|
|
53
103
|
if callableDispatcher:
|
|
54
104
|
callableTarget = getAlgorithmDispatcher().__name__
|
|
@@ -56,22 +106,24 @@ def makeFlowNumbaOptimized(listCallablesInline: List[str], callableDispatcher: O
|
|
|
56
106
|
inlineCallables = False
|
|
57
107
|
unpackArrays = False
|
|
58
108
|
allImports = UniversalImportTracker()
|
|
109
|
+
filenameWrite = None
|
|
59
110
|
for stuff in listStuffYouOughtaKnow:
|
|
60
111
|
statement = stuff.astForCompetentProgrammers
|
|
61
112
|
if isinstance(statement, (ast.Import, ast.ImportFrom)):
|
|
62
113
|
allImports.addAst(statement)
|
|
114
|
+
FunctionDefTarget, allImports = getFunctionDef(algorithmSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
|
|
115
|
+
listAstImports = allImports.makeListAst()
|
|
116
|
+
|
|
117
|
+
pythonSource = makePythonSource([FunctionDefTarget], listAstImports, additional_imports)
|
|
63
118
|
|
|
64
|
-
|
|
119
|
+
listStuff = writePythonAsModule(pythonSource, [callableTarget], relativePathWrite, filenameWrite, formatFilenameWrite)
|
|
120
|
+
listStuffYouOughtaKnow.extend(listStuff)
|
|
65
121
|
|
|
66
122
|
return listStuffYouOughtaKnow
|
|
67
123
|
|
|
68
124
|
if __name__ == '__main__':
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
setDatatypeElephino('uint8', sourGrapes=True)
|
|
72
|
-
setDatatypeLeavesTotal('uint8', sourGrapes=True)
|
|
73
|
-
Z0Z_setDatatypeModuleScalar('numba')
|
|
74
|
-
Z0Z_setDecoratorCallable('jit')
|
|
125
|
+
# Z0Z_setDatatypeModuleScalar('numba')
|
|
126
|
+
# Z0Z_setDecoratorCallable('jit')
|
|
75
127
|
listCallablesInline: List[str] = ['countInitialize', 'countParallel', 'countSequential']
|
|
76
128
|
callableDispatcher = True
|
|
77
129
|
makeFlowNumbaOptimized(listCallablesInline, callableDispatcher)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
from mapFolding import indexMy, indexTrack
|
|
2
|
+
from numba import jit, int64, prange, uint16
|
|
3
|
+
from numpy import ndarray, dtype, integer
|
|
4
|
+
from typing import Tuple, 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.value] > 0:
|
|
9
|
+
if my[indexMy.leaf1ndex.value] <= 1 or track[indexTrack.leafBelow.value, 0] == 1:
|
|
10
|
+
my[indexMy.dimensionsUnconstrained.value] = my[indexMy.dimensionsTotal.value]
|
|
11
|
+
my[indexMy.gap1ndexCeiling.value] = track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]
|
|
12
|
+
my[indexMy.indexDimension.value] = 0
|
|
13
|
+
while my[indexMy.indexDimension.value] < my[indexMy.dimensionsTotal.value]:
|
|
14
|
+
if connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]] == my[indexMy.leaf1ndex.value]:
|
|
15
|
+
my[indexMy.dimensionsUnconstrained.value] -= 1
|
|
16
|
+
else:
|
|
17
|
+
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]]
|
|
18
|
+
while my[indexMy.leafConnectee.value] != my[indexMy.leaf1ndex.value]:
|
|
19
|
+
gapsWhere[my[indexMy.gap1ndexCeiling.value]] = my[indexMy.leafConnectee.value]
|
|
20
|
+
if track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] == 0:
|
|
21
|
+
my[indexMy.gap1ndexCeiling.value] += 1
|
|
22
|
+
track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] += 1
|
|
23
|
+
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], track[indexTrack.leafBelow.value, my[indexMy.leafConnectee.value]]]
|
|
24
|
+
my[indexMy.indexDimension.value] += 1
|
|
25
|
+
if not my[indexMy.dimensionsUnconstrained.value]:
|
|
26
|
+
my[indexMy.indexLeaf.value] = 0
|
|
27
|
+
while my[indexMy.indexLeaf.value] < my[indexMy.leaf1ndex.value]:
|
|
28
|
+
gapsWhere[my[indexMy.gap1ndexCeiling.value]] = my[indexMy.indexLeaf.value]
|
|
29
|
+
my[indexMy.gap1ndexCeiling.value] += 1
|
|
30
|
+
my[indexMy.indexLeaf.value] += 1
|
|
31
|
+
my[indexMy.indexMiniGap.value] = my[indexMy.gap1ndex.value]
|
|
32
|
+
while my[indexMy.indexMiniGap.value] < my[indexMy.gap1ndexCeiling.value]:
|
|
33
|
+
gapsWhere[my[indexMy.gap1ndex.value]] = gapsWhere[my[indexMy.indexMiniGap.value]]
|
|
34
|
+
if track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] == my[indexMy.dimensionsUnconstrained.value]:
|
|
35
|
+
my[indexMy.gap1ndex.value] += 1
|
|
36
|
+
track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] = 0
|
|
37
|
+
my[indexMy.indexMiniGap.value] += 1
|
|
38
|
+
if my[indexMy.leaf1ndex.value] > 0:
|
|
39
|
+
my[indexMy.gap1ndex.value] -= 1
|
|
40
|
+
track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]] = gapsWhere[my[indexMy.gap1ndex.value]]
|
|
41
|
+
track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]] = track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]]
|
|
42
|
+
track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
|
|
43
|
+
track[indexTrack.leafAbove.value, track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
|
|
44
|
+
track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value]] = my[indexMy.gap1ndex.value]
|
|
45
|
+
my[indexMy.leaf1ndex.value] += 1
|
|
46
|
+
if my[indexMy.gap1ndex.value] > 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.value]
|
|
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.value] = indexSherpa
|
|
61
|
+
while my[indexMy.leaf1ndex.value] > 0:
|
|
62
|
+
if my[indexMy.leaf1ndex.value] <= 1 or track[indexTrack.leafBelow.value, 0] == 1:
|
|
63
|
+
if my[indexMy.leaf1ndex.value] > foldGroups[-1]:
|
|
64
|
+
groupsOfFolds += 1
|
|
65
|
+
else:
|
|
66
|
+
my[indexMy.dimensionsUnconstrained.value] = my[indexMy.dimensionsTotal.value]
|
|
67
|
+
my[indexMy.gap1ndexCeiling.value] = track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]
|
|
68
|
+
my[indexMy.indexDimension.value] = 0
|
|
69
|
+
while my[indexMy.indexDimension.value] < my[indexMy.dimensionsTotal.value]:
|
|
70
|
+
if connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]] == my[indexMy.leaf1ndex.value]:
|
|
71
|
+
my[indexMy.dimensionsUnconstrained.value] -= 1
|
|
72
|
+
else:
|
|
73
|
+
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]]
|
|
74
|
+
while my[indexMy.leafConnectee.value] != my[indexMy.leaf1ndex.value]:
|
|
75
|
+
if my[indexMy.leaf1ndex.value] != my[indexMy.taskDivisions.value] or my[indexMy.leafConnectee.value] % my[indexMy.taskDivisions.value] == my[indexMy.taskIndex.value]:
|
|
76
|
+
gapsWhere[my[indexMy.gap1ndexCeiling.value]] = my[indexMy.leafConnectee.value]
|
|
77
|
+
if track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] == 0:
|
|
78
|
+
my[indexMy.gap1ndexCeiling.value] += 1
|
|
79
|
+
track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] += 1
|
|
80
|
+
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], track[indexTrack.leafBelow.value, my[indexMy.leafConnectee.value]]]
|
|
81
|
+
my[indexMy.indexDimension.value] += 1
|
|
82
|
+
my[indexMy.indexMiniGap.value] = my[indexMy.gap1ndex.value]
|
|
83
|
+
while my[indexMy.indexMiniGap.value] < my[indexMy.gap1ndexCeiling.value]:
|
|
84
|
+
gapsWhere[my[indexMy.gap1ndex.value]] = gapsWhere[my[indexMy.indexMiniGap.value]]
|
|
85
|
+
if track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] == my[indexMy.dimensionsUnconstrained.value]:
|
|
86
|
+
my[indexMy.gap1ndex.value] += 1
|
|
87
|
+
track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] = 0
|
|
88
|
+
my[indexMy.indexMiniGap.value] += 1
|
|
89
|
+
while my[indexMy.leaf1ndex.value] > 0 and my[indexMy.gap1ndex.value] == track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]:
|
|
90
|
+
my[indexMy.leaf1ndex.value] -= 1
|
|
91
|
+
track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]] = track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]
|
|
92
|
+
track[indexTrack.leafAbove.value, track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]] = track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]
|
|
93
|
+
if my[indexMy.leaf1ndex.value] > 0:
|
|
94
|
+
my[indexMy.gap1ndex.value] -= 1
|
|
95
|
+
track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]] = gapsWhere[my[indexMy.gap1ndex.value]]
|
|
96
|
+
track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]] = track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]]
|
|
97
|
+
track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
|
|
98
|
+
track[indexTrack.leafAbove.value, track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
|
|
99
|
+
track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value]] = my[indexMy.gap1ndex.value]
|
|
100
|
+
my[indexMy.leaf1ndex.value] += 1
|
|
101
|
+
foldGroups[my[indexMy.taskIndex.value]] = 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,17 +1,10 @@
|
|
|
1
|
-
from mapFolding.syntheticModules.numba_countInitialize import countInitialize
|
|
2
|
-
from mapFolding.syntheticModules.numba_countParallel import countParallel
|
|
3
|
-
from mapFolding.syntheticModules.numba_countSequential import countSequential
|
|
4
1
|
from mapFolding import indexMy
|
|
5
|
-
from
|
|
6
|
-
from numba import jit
|
|
7
|
-
from
|
|
8
|
-
from
|
|
9
|
-
from numpy import ndarray
|
|
10
|
-
from numpy import integer
|
|
11
|
-
from typing import Tuple
|
|
12
|
-
from typing import Any
|
|
2
|
+
from mapFolding.syntheticModules.numbaCount import countParallel, countSequential, countInitialize
|
|
3
|
+
from numba import jit, int64, uint16
|
|
4
|
+
from numpy import ndarray, dtype, integer
|
|
5
|
+
from typing import Tuple, Any
|
|
13
6
|
|
|
14
|
-
@jit((
|
|
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)
|
|
15
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:
|
|
16
9
|
countInitialize(connectionGraph, gapsWhere, my, track)
|
|
17
10
|
if my[indexMy.taskDivisions.value] > 0:
|