mapFolding 0.16.1__py3-none-any.whl → 0.16.4__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/A000682.py +1 -1
- easyRun/A005316.py +2 -3
- easyRun/NOTcountingFolds.py +6 -5
- easyRun/countFolds.py +1 -1
- easyRun/generateAllModules.py +14 -0
- easyRun/meanders.py +16 -18
- mapFolding/__init__.py +1 -0
- mapFolding/_theSSOT.py +3 -2
- mapFolding/_theTypes.py +3 -0
- mapFolding/algorithms/A086345.py +75 -0
- mapFolding/algorithms/matrixMeanders.py +15 -28
- mapFolding/algorithms/matrixMeandersBeDry.py +34 -116
- mapFolding/algorithms/matrixMeandersNumPy.py +117 -70
- mapFolding/algorithms/matrixMeandersPandas.py +113 -130
- mapFolding/algorithms/oeisIDbyFormula.py +25 -14
- mapFolding/algorithms/symmetricFolds.py +36 -0
- mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +26 -12
- mapFolding/basecamp.py +152 -323
- mapFolding/dataBaskets.py +136 -34
- mapFolding/filesystemToolkit.py +4 -32
- mapFolding/oeis.py +5 -12
- mapFolding/reference/A000682facts.py +785 -1264
- mapFolding/reference/A005316facts.py +958 -923
- mapFolding/reference/A086345Wu.py +25 -0
- mapFolding/reference/matrixMeandersAnalysis/signatures.py +2033 -0
- mapFolding/someAssemblyRequired/A007822/A007822rawMaterials.py +9 -44
- mapFolding/someAssemblyRequired/A007822/_asynchronousAnnex.py +51 -0
- mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +39 -136
- mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +44 -45
- mapFolding/someAssemblyRequired/RecipeJob.py +78 -18
- mapFolding/someAssemblyRequired/__init__.py +3 -8
- mapFolding/someAssemblyRequired/_toolkitContainers.py +32 -3
- mapFolding/someAssemblyRequired/infoBooth.py +40 -23
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +75 -154
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +56 -88
- mapFolding/someAssemblyRequired/makingModules_count.py +91 -85
- mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +7 -65
- mapFolding/someAssemblyRequired/{mapFolding → mapFoldingModules}/makeMapFoldingModules.py +25 -31
- mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +14 -13
- mapFolding/someAssemblyRequired/toolkitMakeModules.py +10 -10
- mapFolding/someAssemblyRequired/toolkitNumba.py +1 -1
- mapFolding/someAssemblyRequired/transformationTools.py +17 -19
- mapFolding/syntheticModules/A007822/algorithm.py +46 -50
- mapFolding/syntheticModules/A007822/asynchronous.py +93 -34
- mapFolding/syntheticModules/A007822/initializeState.py +15 -21
- mapFolding/syntheticModules/A007822/theorem2.py +21 -21
- mapFolding/syntheticModules/A007822/theorem2Numba.py +42 -23
- mapFolding/syntheticModules/A007822/theorem2Trimmed.py +21 -21
- mapFolding/syntheticModules/countParallelNumba.py +3 -7
- mapFolding/syntheticModules/daoOfMapFoldingNumba.py +3 -6
- mapFolding/syntheticModules/meanders/bigInt.py +15 -25
- mapFolding/syntheticModules/theorem2.py +6 -0
- mapFolding/syntheticModules/theorem2Numba.py +26 -2
- mapFolding/syntheticModules/theorem2Trimmed.py +6 -0
- mapFolding/tests/test_computations.py +1 -1
- mapFolding/zCuzDocStoopid/makeDocstrings.py +2 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/METADATA +4 -1
- mapfolding-0.16.4.dist-info/RECORD +106 -0
- mapFolding/_dataPacking.py +0 -68
- mapFolding/reference/meandersDumpingGround/A005316intOptimized.py +0 -122
- mapFolding/reference/meandersDumpingGround/A005316optimized128bit.py +0 -79
- mapFolding/reference/meandersDumpingGround/matrixMeandersBaseline.py +0 -65
- mapFolding/reference/meandersDumpingGround/matrixMeandersBaselineAnnex.py +0 -84
- mapFolding/reference/meandersDumpingGround/matrixMeandersSimpleQueue.py +0 -90
- mapFolding/syntheticModules/A007822/algorithmNumba.py +0 -94
- mapFolding/syntheticModules/A007822/asynchronousAnnex.py +0 -66
- mapFolding/syntheticModules/A007822/asynchronousAnnexNumba.py +0 -85
- mapFolding/syntheticModules/A007822/asynchronousNumba.py +0 -52
- mapFolding/syntheticModules/A007822/asynchronousTheorem2.py +0 -53
- mapFolding/syntheticModules/A007822/asynchronousTrimmed.py +0 -47
- mapFolding/syntheticModules/dataPacking.py +0 -28
- mapFolding/syntheticModules/dataPackingA007822.py +0 -92
- mapfolding-0.16.1.dist-info/RECORD +0 -114
- /mapFolding/someAssemblyRequired/{mapFolding → mapFoldingModules}/__init__.py +0 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/WHEEL +0 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.16.1.dist-info → mapfolding-0.16.4.dist-info}/top_level.txt +0 -0
|
@@ -4,59 +4,31 @@ https://docs.exaloop.io/start/install/
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from astToolkit import (
|
|
7
|
-
Be,
|
|
8
|
-
|
|
7
|
+
Be, extractFunctionDef, Grab, identifierDotAttribute, IngredientsFunction, IngredientsModule, Make, NodeChanger,
|
|
8
|
+
parseLogicalPath2astModule, Then)
|
|
9
9
|
from astToolkit.transformationTools import removeUnusedParameters, write_astModule
|
|
10
|
-
from hunterMakesPy import
|
|
11
|
-
from mapFolding import DatatypeLeavesTotal, getPathFilenameFoldsTotal
|
|
10
|
+
from hunterMakesPy import raiseIfNone
|
|
11
|
+
from mapFolding import DatatypeLeavesTotal, getPathFilenameFoldsTotal, packageSettings
|
|
12
12
|
from mapFolding.dataBaskets import MapFoldingState
|
|
13
|
-
from mapFolding.someAssemblyRequired import IfThis
|
|
14
|
-
from mapFolding.someAssemblyRequired.RecipeJob import
|
|
15
|
-
|
|
13
|
+
from mapFolding.someAssemblyRequired import DatatypeConfiguration, default, IfThis
|
|
14
|
+
from mapFolding.someAssemblyRequired.RecipeJob import (
|
|
15
|
+
customizeDatatypeViaImport, moveShatteredDataclass_arg2body, RecipeJobTheorem2)
|
|
16
|
+
from mapFolding.syntheticModules.initializeState import transitionOnGroupsOfFolds
|
|
16
17
|
from pathlib import Path, PurePosixPath
|
|
17
|
-
from typing import cast,
|
|
18
|
-
import ast
|
|
18
|
+
from typing import cast, TYPE_CHECKING
|
|
19
19
|
import subprocess
|
|
20
20
|
import sys
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
23
|
from io import TextIOBase
|
|
24
|
+
import ast
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
"""Configuration for mapping framework datatypes to compiled datatypes.
|
|
26
|
+
# TODO Converge with `makeJobTheorem2Numba`.
|
|
27
27
|
|
|
28
|
-
This configuration class defines how abstract datatypes used in the map folding framework should be replaced with compiled
|
|
29
|
-
datatypes during code generation. Each configuration specifies the source module, target type name, and optional import alias
|
|
30
|
-
for the transformation.
|
|
31
|
-
|
|
32
|
-
Attributes
|
|
33
|
-
----------
|
|
34
|
-
datatypeIdentifier : str
|
|
35
|
-
Framework datatype identifier to be replaced.
|
|
36
|
-
typeModule : identifierDotAttribute
|
|
37
|
-
Module containing the target datatype (e.g., 'codon', 'numpy').
|
|
38
|
-
typeIdentifier : str
|
|
39
|
-
Concrete type name in the target module.
|
|
40
|
-
type_asname : str | None = None
|
|
41
|
-
Optional import alias for the type.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
datatypeIdentifier: str
|
|
45
|
-
typeModule: identifierDotAttribute
|
|
46
|
-
typeIdentifier: str
|
|
47
|
-
type_asname: str | None = None
|
|
48
|
-
|
|
49
|
-
# TODO replace with dynamic system. Probably use `Final` in the dataclass.
|
|
50
|
-
listIdentifiersStaticValuesHARDCODED: list[str] = ['dimensionsTotal', 'leavesTotal']
|
|
51
|
-
|
|
52
|
-
# TODO Dynamically calculate the bitwidth of each datatype.
|
|
53
28
|
listDatatypeConfigurations: list[DatatypeConfiguration] = [
|
|
54
29
|
DatatypeConfiguration(datatypeIdentifier='DatatypeLeavesTotal', typeModule='numpy', typeIdentifier='uint8', type_asname='DatatypeLeavesTotal'),
|
|
55
30
|
DatatypeConfiguration(datatypeIdentifier='DatatypeElephino', typeModule='numpy', typeIdentifier='uint8', type_asname='DatatypeElephino'),
|
|
56
31
|
DatatypeConfiguration(datatypeIdentifier='DatatypeFoldsTotal', typeModule='numpy', typeIdentifier='int64', type_asname='DatatypeFoldsTotal'),
|
|
57
|
-
]
|
|
58
|
-
|
|
59
|
-
listNumPy_dtype: list[DatatypeConfiguration] = [
|
|
60
32
|
DatatypeConfiguration(datatypeIdentifier='Array1DLeavesTotal', typeModule='numpy', typeIdentifier='uint8', type_asname='Array1DLeavesTotal'),
|
|
61
33
|
DatatypeConfiguration(datatypeIdentifier='Array1DElephino', typeModule='numpy', typeIdentifier='uint8', type_asname='Array1DElephino'),
|
|
62
34
|
DatatypeConfiguration(datatypeIdentifier='Array3DLeavesTotal', typeModule='numpy', typeIdentifier='uint8', type_asname='Array3DLeavesTotal'),
|
|
@@ -78,55 +50,60 @@ def _addWriteFoldsTotal(ingredientsFunction: IngredientsFunction, job: RecipeJob
|
|
|
78
50
|
|
|
79
51
|
return ingredientsFunction
|
|
80
52
|
|
|
81
|
-
def
|
|
82
|
-
|
|
83
|
-
ingredientsFunction.imports.removeImportFrom(datatypeConfig.typeModule, None, datatypeConfig.datatypeIdentifier)
|
|
84
|
-
ingredientsFunction.imports.addImportFrom_asStr(datatypeConfig.typeModule, datatypeConfig.typeIdentifier, datatypeConfig.type_asname)
|
|
85
|
-
|
|
86
|
-
ingredientsFunction.imports.removeImportFromModule('mapFolding.dataBaskets')
|
|
53
|
+
def _variableCompatibility(ingredientsFunction: IngredientsFunction, job: RecipeJobTheorem2) -> IngredientsFunction:
|
|
54
|
+
"""Ensure the variable is compiled to the correct type.
|
|
87
55
|
|
|
88
|
-
|
|
56
|
+
Add a type constructor to `identifier` to ensure compatibility if
|
|
57
|
+
- an incompatible type might be assigned to it,
|
|
58
|
+
- it might be compared with an incompatible type,
|
|
59
|
+
- it is used as an indexer but its type is not a valid indexer type.
|
|
89
60
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
61
|
+
Parameters
|
|
62
|
+
----------
|
|
63
|
+
ingredientsFunction : IngredientsFunction
|
|
64
|
+
Function to modify.
|
|
65
|
+
job : RecipeJobTheorem2
|
|
66
|
+
Configuration settings with identifiers and their type annotations.
|
|
93
67
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
68
|
+
Returns
|
|
69
|
+
-------
|
|
70
|
+
ingredientsFunction : IngredientsFunction
|
|
71
|
+
Modified function.
|
|
72
|
+
"""
|
|
97
73
|
for ast_arg in job.shatteredDataclass.list_argAnnotated4ArgumentsSpecification:
|
|
98
|
-
identifier = ast_arg.arg
|
|
99
|
-
annotation = raiseIfNone(ast_arg.annotation)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
74
|
+
identifier: str = ast_arg.arg
|
|
75
|
+
annotation: ast.expr = raiseIfNone(ast_arg.annotation)
|
|
76
|
+
|
|
77
|
+
# ------- `identifier` is target of Augmented Assignment, or --------------
|
|
78
|
+
# ------- `identifier` is target of Assignment and value is Constant. -----
|
|
79
|
+
NodeChanger(
|
|
80
|
+
IfThis.isAnyOf(
|
|
81
|
+
Be.AugAssign.targetIs(IfThis.isNestedNameIdentifier(identifier))
|
|
82
|
+
, IfThis.isAllOf(Be.Assign.targetsIs(Be.at(0, IfThis.isNestedNameIdentifier(identifier)))
|
|
83
|
+
, Be.Assign.valueIs(Be.Constant))
|
|
107
84
|
)
|
|
108
85
|
, doThat=lambda node, annotation=annotation: Grab.valueAttribute(Then.replaceWith(Make.Call(annotation, listParameters=[node.value])))(node)
|
|
109
86
|
).visit(ingredientsFunction.astFunctionDef)
|
|
110
87
|
|
|
111
|
-
|
|
88
|
+
# ------- `identifier` - 1. ----------------------------------------------
|
|
112
89
|
NodeChanger(Be.BinOp.leftIs(IfThis.isNestedNameIdentifier(identifier))
|
|
113
90
|
, doThat=lambda node, annotation=annotation: Grab.rightAttribute(Then.replaceWith(Make.Call(annotation, listParameters=[node.right])))(node)
|
|
114
91
|
).visit(ingredientsFunction.astFunctionDef)
|
|
115
92
|
|
|
116
|
-
|
|
93
|
+
# ------- `identifier` in Comparison. -------------------------------------
|
|
117
94
|
NodeChanger(Be.Compare.leftIs(IfThis.isNestedNameIdentifier(identifier))
|
|
118
95
|
, doThat=lambda node, annotation=annotation: Grab.comparatorsAttribute(lambda at, annotation=annotation: Then.replaceWith([Make.Call(annotation, listParameters=[node.comparators[0]])])(at[0]))(node)
|
|
119
96
|
).visit(ingredientsFunction.astFunctionDef)
|
|
120
97
|
|
|
121
|
-
|
|
98
|
+
# ------- `identifier` has exactly one index value. -----------------------
|
|
122
99
|
NodeChanger(IfThis.isAllOf(Be.Subscript.valueIs(IfThis.isNestedNameIdentifier(identifier))
|
|
123
100
|
, lambda node: not Be.Subscript.sliceIs(Be.Tuple)(node))
|
|
124
101
|
, doThat=lambda node: Grab.sliceAttribute(Then.replaceWith(Make.Call(Make.Name('int'), listParameters=[node.slice])))(node)
|
|
125
102
|
).visit(ingredientsFunction.astFunctionDef)
|
|
126
103
|
|
|
127
|
-
|
|
104
|
+
# ------- `identifier` has multiple index values. -------------------------
|
|
128
105
|
NodeChanger(IfThis.isAllOf(Be.Subscript.valueIs(IfThis.isNestedNameIdentifier(identifier))
|
|
129
|
-
|
|
106
|
+
, Be.Subscript.sliceIs(Be.Tuple))
|
|
130
107
|
, doThat=lambda node: Grab.sliceAttribute(Grab.eltsAttribute(
|
|
131
108
|
Then.replaceWith([
|
|
132
109
|
Make.Call(Make.Name('int'), listParameters=[cast('ast.Tuple', node.slice).elts[index]])
|
|
@@ -135,19 +112,6 @@ def _variableCompatibility(ingredientsFunction: IngredientsFunction, job: Recipe
|
|
|
135
112
|
|
|
136
113
|
return ingredientsFunction
|
|
137
114
|
|
|
138
|
-
def _move_arg2body(identifier: str, job: RecipeJobTheorem2) -> ast.AnnAssign | ast.Assign:
|
|
139
|
-
Ima___Assign, elementConstructor = job.shatteredDataclass.Z0Z_field2AnnAssign[identifier]
|
|
140
|
-
match elementConstructor:
|
|
141
|
-
case 'scalar':
|
|
142
|
-
cast('ast.Constant', cast('ast.Call', Ima___Assign.value).args[0]).value = int(job.state.__dict__[identifier])
|
|
143
|
-
case 'array':
|
|
144
|
-
dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[identifier], assumeAddSpaces=True)
|
|
145
|
-
dataAs_ast_expr: ast.expr = _pythonCode2expr(dataAsStrRLE)
|
|
146
|
-
cast('ast.Call', Ima___Assign.value).args = [dataAs_ast_expr]
|
|
147
|
-
case _:
|
|
148
|
-
pass
|
|
149
|
-
return Ima___Assign
|
|
150
|
-
|
|
151
115
|
def makeJob(job: RecipeJobTheorem2) -> None:
|
|
152
116
|
"""Generate an optimized module for map folding calculations.
|
|
153
117
|
|
|
@@ -157,22 +121,21 @@ def makeJob(job: RecipeJobTheorem2) -> None:
|
|
|
157
121
|
Parameters
|
|
158
122
|
----------
|
|
159
123
|
job : RecipeJobTheorem2
|
|
160
|
-
Configuration recipe containing source locations, target paths, and state.
|
|
124
|
+
Configuration recipe containing source locations, target paths, raw materials, and state.
|
|
161
125
|
|
|
162
126
|
"""
|
|
163
127
|
ingredientsCount: IngredientsFunction = IngredientsFunction(raiseIfNone(extractFunctionDef(job.source_astModule, job.countCallable)))
|
|
164
128
|
ingredientsCount.astFunctionDef.decorator_list = []
|
|
165
129
|
|
|
166
130
|
# Replace identifiers-with-static-values with their values.
|
|
167
|
-
|
|
168
|
-
for identifier in listIdentifiersStaticValues:
|
|
131
|
+
for identifier in job.shatteredDataclass.listIdentifiersStaticScalars:
|
|
169
132
|
NodeChanger(IfThis.isNameIdentifier(identifier)
|
|
170
|
-
, Then.replaceWith(Make.Constant(int(job.state.
|
|
133
|
+
, Then.replaceWith(Make.Constant(int(eval(f"job.state.{identifier}")))) # noqa: S307
|
|
171
134
|
).visit(ingredientsCount.astFunctionDef)
|
|
172
135
|
|
|
173
136
|
ingredientsCount.imports.update(job.shatteredDataclass.imports)
|
|
174
137
|
ingredientsCount = removeUnusedParameters(ingredientsCount)
|
|
175
|
-
NodeChanger(Be.arg, lambda removeIt: ingredientsCount.astFunctionDef.body.insert(0,
|
|
138
|
+
NodeChanger(Be.arg, lambda removeIt: ingredientsCount.astFunctionDef.body.insert(0, moveShatteredDataclass_arg2body(removeIt.arg, job))).visit(ingredientsCount.astFunctionDef)
|
|
176
139
|
|
|
177
140
|
ingredientsCount = _addWriteFoldsTotal(ingredientsCount, job)
|
|
178
141
|
ingredientsCount = _variableCompatibility(ingredientsCount, job)
|
|
@@ -181,11 +144,14 @@ def makeJob(job: RecipeJobTheorem2) -> None:
|
|
|
181
144
|
Make.If(Make.Compare(Make.Name('__name__'), [Make.Eq()], [Make.Constant('__main__')])
|
|
182
145
|
, body=[Make.Expr(Make.Call(Make.Name(job.countCallable)))])]))
|
|
183
146
|
|
|
184
|
-
ingredientsCount, ingredientsModule =
|
|
147
|
+
ingredientsCount, ingredientsModule = customizeDatatypeViaImport(ingredientsCount, ingredientsModule, listDatatypeConfigurations)
|
|
148
|
+
|
|
149
|
+
ingredientsCount.imports.removeImportFromModule('mapFolding.dataBaskets')
|
|
185
150
|
|
|
186
151
|
ingredientsModule.appendIngredientsFunction(ingredientsCount)
|
|
187
152
|
|
|
188
153
|
if sys.platform == 'linux':
|
|
154
|
+
Path(job.pathFilenameModule).parent.mkdir(parents=True, exist_ok=True)
|
|
189
155
|
buildCommand: list[str] = ['codon', 'build', '--exe', '--release',
|
|
190
156
|
'--fast-math', '--enable-unsafe-fp-math', '--disable-exceptions',
|
|
191
157
|
'--mcpu=native',
|
|
@@ -200,6 +166,7 @@ def makeJob(job: RecipeJobTheorem2) -> None:
|
|
|
200
166
|
sys.stdout.write(f"sudo systemd-run --unit={job.moduleIdentifier} --nice=-10 --property=CPUAffinity=0 {job.pathFilenameModule.with_suffix('')}\n")
|
|
201
167
|
else:
|
|
202
168
|
write_astModule(ingredientsModule, pathFilename=job.pathFilenameModule, packageName=job.packageIdentifier)
|
|
169
|
+
sys.stdout.write(f"python {Path(job.pathFilenameModule)}\n")
|
|
203
170
|
|
|
204
171
|
def fromMapShape(mapShape: tuple[DatatypeLeavesTotal, ...]) -> None:
|
|
205
172
|
"""Create a binary executable for a map-folding job from map dimensions.
|
|
@@ -214,14 +181,15 @@ def fromMapShape(mapShape: tuple[DatatypeLeavesTotal, ...]) -> None:
|
|
|
214
181
|
along one axis.
|
|
215
182
|
|
|
216
183
|
"""
|
|
217
|
-
state = transitionOnGroupsOfFolds(MapFoldingState(mapShape))
|
|
184
|
+
state: MapFoldingState = transitionOnGroupsOfFolds(MapFoldingState(mapShape))
|
|
218
185
|
pathModule = PurePosixPath(Path.home(), 'mapFolding', 'jobs')
|
|
219
|
-
|
|
186
|
+
logicalPath2astModule: identifierDotAttribute = f'{packageSettings.identifierPackage}.{default['logicalPath']['synthetic']}.theorem2Numba'
|
|
187
|
+
source_astModule: ast.Module = parseLogicalPath2astModule(logicalPath2astModule)
|
|
220
188
|
pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
|
|
221
189
|
aJob = RecipeJobTheorem2(state, source_astModule=source_astModule, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
|
|
222
190
|
makeJob(aJob)
|
|
223
191
|
|
|
224
192
|
if __name__ == '__main__':
|
|
225
|
-
mapShape = (1,
|
|
193
|
+
mapShape: tuple[DatatypeLeavesTotal, ...] = (1, 14)
|
|
226
194
|
fromMapShape(mapShape)
|
|
227
195
|
|
|
@@ -9,41 +9,25 @@ from astToolkit import (
|
|
|
9
9
|
from astToolkit.transformationTools import inlineFunctionDef, removeUnusedParameters, write_astModule
|
|
10
10
|
from hunterMakesPy import raiseIfNone
|
|
11
11
|
from mapFolding import packageSettings
|
|
12
|
-
from mapFolding.someAssemblyRequired import
|
|
13
|
-
|
|
14
|
-
from mapFolding.someAssemblyRequired.A007822.A007822rawMaterials import astExprCall_filterAsymmetricFoldsLeafBelow
|
|
15
|
-
from mapFolding.someAssemblyRequired.toolkitMakeModules import findDataclass, getPathFilename
|
|
12
|
+
from mapFolding.someAssemblyRequired import default, IfThis, ShatteredDataclass
|
|
13
|
+
from mapFolding.someAssemblyRequired.toolkitMakeModules import findDataclass, getLogicalPath, getPathFilename
|
|
16
14
|
from mapFolding.someAssemblyRequired.toolkitNumba import decorateCallableWithNumba, parametersNumbaLight
|
|
17
15
|
from mapFolding.someAssemblyRequired.transformationTools import (
|
|
18
16
|
removeDataclassFromFunction, shatter_dataclassesDOTdataclass, unpackDataclassCallFunctionRepackDataclass)
|
|
19
|
-
from os import PathLike
|
|
20
17
|
from pathlib import PurePath
|
|
21
18
|
from typing import cast
|
|
22
19
|
import ast
|
|
23
20
|
|
|
24
|
-
def
|
|
25
|
-
"""Generate Numba-optimized sequential implementation of
|
|
26
|
-
|
|
27
|
-
(AI generated docstring)
|
|
28
|
-
|
|
29
|
-
Creates a high-performance sequential version of the map folding algorithm by
|
|
30
|
-
decomposing dataclass parameters into individual primitive values, removing
|
|
31
|
-
dataclass dependencies that are incompatible with Numba, applying Numba
|
|
32
|
-
decorators for just-in-time compilation, and optionally including a dispatcher
|
|
33
|
-
function for dataclass integration.
|
|
34
|
-
|
|
35
|
-
The generated module provides significant performance improvements over the
|
|
36
|
-
original dataclass-based implementation while maintaining algorithmic correctness.
|
|
37
|
-
The transformation preserves all computational logic while restructuring data
|
|
38
|
-
access patterns for optimal Numba compilation.
|
|
21
|
+
def makeMapFoldingNumba(astModule: ast.Module, identifierModule: str, identifierCallable: str | None = None, logicalPathInfix: identifierDotAttribute | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
22
|
+
"""Generate Numba-optimized sequential implementation of an algorithm.
|
|
39
23
|
|
|
40
24
|
Parameters
|
|
41
25
|
----------
|
|
42
26
|
astModule : ast.Module
|
|
43
27
|
Source module containing the base algorithm.
|
|
44
|
-
|
|
28
|
+
identifierModule : str
|
|
45
29
|
Name for the generated optimized module.
|
|
46
|
-
|
|
30
|
+
identifierCallable : str | None = None
|
|
47
31
|
Name for the main computational function.
|
|
48
32
|
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
49
33
|
Directory path for organizing the generated module.
|
|
@@ -56,9 +40,9 @@ def makeDaoOfMapFoldingNumba(astModule: ast.Module, moduleIdentifier: str, calla
|
|
|
56
40
|
Filesystem path where the optimized module was written.
|
|
57
41
|
|
|
58
42
|
"""
|
|
59
|
-
sourceCallableIdentifier:
|
|
43
|
+
sourceCallableIdentifier: str = default['function']['counting']
|
|
60
44
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
61
|
-
ingredientsFunction.astFunctionDef.name =
|
|
45
|
+
ingredientsFunction.astFunctionDef.name = identifierCallable or sourceCallableIdentifier
|
|
62
46
|
|
|
63
47
|
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*findDataclass(ingredientsFunction))
|
|
64
48
|
|
|
@@ -88,46 +72,46 @@ def makeDaoOfMapFoldingNumba(astModule: ast.Module, moduleIdentifier: str, calla
|
|
|
88
72
|
|
|
89
73
|
ingredientsModule.removeImportFromModule('numpy')
|
|
90
74
|
|
|
91
|
-
pathFilename: PurePath = getPathFilename(packageSettings.pathPackage, logicalPathInfix,
|
|
75
|
+
pathFilename: PurePath = getPathFilename(packageSettings.pathPackage, logicalPathInfix, identifierModule)
|
|
92
76
|
|
|
93
77
|
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
94
78
|
|
|
95
79
|
return pathFilename
|
|
96
80
|
|
|
97
|
-
def makeTheorem2(astModule: ast.Module,
|
|
81
|
+
def makeTheorem2(astModule: ast.Module, identifierModule: str, identifierCallable: str | None = None, logicalPathInfix: identifierDotAttribute | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
98
82
|
"""Generate module by applying optimization predicted by Theorem 2.
|
|
99
83
|
|
|
100
84
|
Parameters
|
|
101
85
|
----------
|
|
102
86
|
astModule : ast.Module
|
|
103
87
|
Source module containing the base algorithm.
|
|
104
|
-
|
|
88
|
+
identifierModule : str
|
|
105
89
|
Name for the generated theorem-optimized module.
|
|
106
|
-
|
|
90
|
+
identifierCallable : str | None = None
|
|
107
91
|
Name for the optimized computational function.
|
|
108
92
|
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
109
93
|
Directory path for organizing the generated module.
|
|
110
94
|
sourceCallableDispatcher : str | None = None
|
|
111
|
-
|
|
95
|
+
Optional dispatcher function identifier.
|
|
112
96
|
|
|
113
97
|
Returns
|
|
114
98
|
-------
|
|
115
99
|
pathFilename : PurePath
|
|
116
100
|
Filesystem path where the theorem-optimized module was written.
|
|
101
|
+
"""
|
|
102
|
+
identifierCallableInitializeDataclassHARDCODED = 'transitionOnGroupsOfFolds'
|
|
103
|
+
identifierModuleInitializeDataclassHARDCODED = 'initializeState'
|
|
117
104
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
NotImplementedError
|
|
121
|
-
If `sourceCallableDispatcher` is provided.
|
|
105
|
+
identifierCallableInitializeDataclass = identifierCallableInitializeDataclassHARDCODED
|
|
106
|
+
identifierModuleInitializeDataclass = identifierModuleInitializeDataclassHARDCODED
|
|
122
107
|
|
|
123
|
-
|
|
124
|
-
sourceCallableIdentifier = identifierCallableSourceDEFAULT
|
|
108
|
+
sourceCallableIdentifier = default['function']['counting']
|
|
125
109
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
126
|
-
ingredientsFunction.astFunctionDef.name =
|
|
110
|
+
ingredientsFunction.astFunctionDef.name = identifierCallable or sourceCallableIdentifier
|
|
127
111
|
|
|
128
|
-
dataclassInstanceIdentifier:
|
|
112
|
+
dataclassInstanceIdentifier: str = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
129
113
|
|
|
130
|
-
theCountingIdentifier:
|
|
114
|
+
theCountingIdentifier: str = default['variable']['counting']
|
|
131
115
|
doubleTheCount: ast.AugAssign = Make.AugAssign(Make.Attribute(Make.Name(dataclassInstanceIdentifier), theCountingIdentifier), Make.Mult(), Make.Constant(2))
|
|
132
116
|
|
|
133
117
|
NodeChanger(
|
|
@@ -171,40 +155,41 @@ def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
|
|
|
171
155
|
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
172
156
|
|
|
173
157
|
if sourceCallableDispatcher is not None:
|
|
174
|
-
|
|
175
|
-
|
|
158
|
+
ingredientsFunctionDispatcher: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableDispatcher)
|
|
159
|
+
targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
|
|
176
160
|
|
|
177
|
-
|
|
161
|
+
# Update any calls to the original function name with the new target function name
|
|
162
|
+
NodeChanger(
|
|
163
|
+
findThis = Be.Call.funcIs(Be.Name.idIs(IfThis.isIdentifier(default['function']['counting'])))
|
|
164
|
+
, doThat = Grab.funcAttribute(Grab.idAttribute(Then.replaceWith(targetCallableIdentifier)))
|
|
165
|
+
).visit(ingredientsFunctionDispatcher.astFunctionDef)
|
|
178
166
|
|
|
179
|
-
|
|
167
|
+
AssignInitializedDataclass: ast.Assign = Make.Assign([Make.Name(dataclassInstanceIdentifier)], value=Make.Call(Make.Name(identifierCallableInitializeDataclass), [Make.Name(dataclassInstanceIdentifier)]))
|
|
180
168
|
|
|
181
|
-
|
|
169
|
+
# Insert the transitionOnGroupsOfFolds call at the beginning of the function
|
|
170
|
+
ingredientsFunctionDispatcher.astFunctionDef.body.insert(0, AssignInitializedDataclass)
|
|
182
171
|
|
|
183
|
-
|
|
184
|
-
|
|
172
|
+
dotModule: identifierDotAttribute = getLogicalPath(packageSettings.identifierPackage, logicalPathInfix, identifierModuleInitializeDataclass)
|
|
173
|
+
ingredientsFunctionDispatcher.imports.addImportFrom_asStr(dotModule, identifierCallableInitializeDataclass)
|
|
185
174
|
|
|
186
|
-
|
|
175
|
+
ingredientsModule.appendIngredientsFunction(ingredientsFunctionDispatcher)
|
|
187
176
|
|
|
188
|
-
|
|
189
|
-
mathematical optimizations of Theorem 2 with Numba just-in-time compilation.
|
|
190
|
-
The transformation includes dataclass decomposition to convert structured
|
|
191
|
-
parameters into primitives, removal of Python object dependencies incompatible
|
|
192
|
-
with Numba, application of Numba decorators for maximum performance, and type
|
|
193
|
-
annotation optimization for efficient compilation.
|
|
177
|
+
pathFilename: PurePath = getPathFilename(packageSettings.pathPackage, logicalPathInfix, identifierModule)
|
|
194
178
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
179
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
180
|
+
|
|
181
|
+
return pathFilename
|
|
182
|
+
|
|
183
|
+
def numbaOnTheorem2(astModule: ast.Module, identifierModule: str, identifierCallable: str | None = None, logicalPathInfix: identifierDotAttribute | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
184
|
+
"""Generate Numba-accelerated Theorem 2 implementation with dataclass decomposition.
|
|
200
185
|
|
|
201
186
|
Parameters
|
|
202
187
|
----------
|
|
203
188
|
astModule : ast.Module
|
|
204
189
|
Source module containing the Theorem 2 implementation.
|
|
205
|
-
|
|
190
|
+
identifierModule : str
|
|
206
191
|
Name for the generated Numba-accelerated module.
|
|
207
|
-
|
|
192
|
+
identifierCallable : str | None = None
|
|
208
193
|
Name for the accelerated computational function.
|
|
209
194
|
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
210
195
|
Directory path for organizing the generated module.
|
|
@@ -217,13 +202,13 @@ def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdenti
|
|
|
217
202
|
Filesystem path where the accelerated module was written.
|
|
218
203
|
|
|
219
204
|
"""
|
|
220
|
-
sourceCallableIdentifier =
|
|
221
|
-
if callableIdentifier is None:
|
|
222
|
-
callableIdentifier = sourceCallableIdentifier
|
|
205
|
+
sourceCallableIdentifier = default['function']['counting']
|
|
223
206
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
224
|
-
ingredientsFunction.astFunctionDef.name =
|
|
207
|
+
ingredientsFunction.astFunctionDef.name = identifierCallable or sourceCallableIdentifier
|
|
225
208
|
|
|
226
|
-
|
|
209
|
+
logicalPathDataclass, identifierDataclass, identifierDataclassInstance = findDataclass(ingredientsFunction)
|
|
210
|
+
|
|
211
|
+
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(logicalPathDataclass, identifierDataclass, identifierDataclassInstance)
|
|
227
212
|
|
|
228
213
|
ingredientsFunction.imports.update(shatteredDataclass.imports)
|
|
229
214
|
ingredientsFunction: IngredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
|
|
@@ -233,32 +218,40 @@ def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdenti
|
|
|
233
218
|
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
234
219
|
ingredientsModule.removeImportFromModule('numpy')
|
|
235
220
|
|
|
236
|
-
|
|
221
|
+
if sourceCallableDispatcher is not None:
|
|
222
|
+
ingredientsFunctionDispatcher: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableDispatcher)
|
|
223
|
+
ingredientsFunctionDispatcher.imports.update(shatteredDataclass.imports)
|
|
224
|
+
targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
|
|
225
|
+
ingredientsFunctionDispatcher = unpackDataclassCallFunctionRepackDataclass(ingredientsFunctionDispatcher, targetCallableIdentifier, shatteredDataclass)
|
|
226
|
+
astTuple: ast.Tuple = cast('ast.Tuple', raiseIfNone(NodeTourist(Be.Return.valueIs(Be.Tuple)
|
|
227
|
+
, doThat=Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef)))
|
|
228
|
+
astTuple.ctx = Make.Store()
|
|
237
229
|
|
|
238
|
-
|
|
230
|
+
changeAssignCallToTarget = NodeChanger(
|
|
231
|
+
findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
|
|
232
|
+
, doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts))))
|
|
233
|
+
changeAssignCallToTarget.visit(ingredientsFunctionDispatcher.astFunctionDef)
|
|
239
234
|
|
|
240
|
-
|
|
235
|
+
ingredientsModule.appendIngredientsFunction(ingredientsFunctionDispatcher)
|
|
241
236
|
|
|
242
|
-
|
|
243
|
-
|
|
237
|
+
ingredientsModule.removeImportFromModule('numpy')
|
|
238
|
+
|
|
239
|
+
pathFilename: PurePath = getPathFilename(packageSettings.pathPackage, logicalPathInfix, identifierModule)
|
|
244
240
|
|
|
245
|
-
(
|
|
241
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
246
242
|
|
|
247
|
-
|
|
248
|
-
constraint assumptions. This transformation removes checks for unconstrained dimensions, simplifying the algorithm for cases
|
|
249
|
-
where dimensional constraints are guaranteed to be satisfied by external conditions.
|
|
243
|
+
return pathFilename
|
|
250
244
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
overhead without providing benefits in the constrained environment.
|
|
245
|
+
def trimTheorem2(astModule: ast.Module, identifierModule: str, identifierCallable: str | None = None, logicalPathInfix: identifierDotAttribute | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
246
|
+
"""Generate constrained Theorem 2 implementation by removing unnecessary logic.
|
|
254
247
|
|
|
255
248
|
Parameters
|
|
256
249
|
----------
|
|
257
250
|
astModule : ast.Module
|
|
258
251
|
Source module containing the Theorem 2 implementation.
|
|
259
|
-
|
|
252
|
+
identifierModule : str
|
|
260
253
|
Name for the generated trimmed module.
|
|
261
|
-
|
|
254
|
+
identifierCallable : str | None = None
|
|
262
255
|
Name for the trimmed computational function.
|
|
263
256
|
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
264
257
|
Directory path for organizing the generated module.
|
|
@@ -271,20 +264,33 @@ def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
|
|
|
271
264
|
Filesystem path where the trimmed module was written.
|
|
272
265
|
|
|
273
266
|
"""
|
|
274
|
-
sourceCallableIdentifier =
|
|
267
|
+
sourceCallableIdentifier: str = default['function']['counting']
|
|
275
268
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
276
|
-
ingredientsFunction.astFunctionDef.name =
|
|
269
|
+
ingredientsFunction.astFunctionDef.name = identifierCallable or sourceCallableIdentifier
|
|
277
270
|
|
|
278
|
-
|
|
271
|
+
identifierDataclassInstance: str = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
279
272
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
273
|
+
NodeChanger(
|
|
274
|
+
findThis = IfThis.isIfUnaryNotAttributeNamespaceIdentifier(identifierDataclassInstance, 'dimensionsUnconstrained')
|
|
275
|
+
, doThat = Then.removeIt
|
|
276
|
+
).visit(ingredientsFunction.astFunctionDef)
|
|
283
277
|
|
|
284
278
|
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
285
279
|
ingredientsModule.removeImportFromModule('numpy')
|
|
286
280
|
|
|
287
|
-
|
|
281
|
+
if sourceCallableDispatcher is not None:
|
|
282
|
+
ingredientsFunctionDispatcher: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableDispatcher)
|
|
283
|
+
targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
|
|
284
|
+
|
|
285
|
+
# Update any calls to the original function name with the new target function name
|
|
286
|
+
NodeChanger(
|
|
287
|
+
findThis = Be.Call.funcIs(Be.Name.idIs(IfThis.isIdentifier(default['function']['counting'])))
|
|
288
|
+
, doThat = Grab.funcAttribute(Grab.idAttribute(Then.replaceWith(targetCallableIdentifier)))
|
|
289
|
+
).visit(ingredientsFunctionDispatcher.astFunctionDef)
|
|
290
|
+
|
|
291
|
+
ingredientsModule.appendIngredientsFunction(ingredientsFunctionDispatcher)
|
|
292
|
+
|
|
293
|
+
pathFilename: PurePath = getPathFilename(packageSettings.pathPackage, logicalPathInfix, identifierModule)
|
|
288
294
|
|
|
289
295
|
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
290
296
|
|