mapFolding 0.12.2__py3-none-any.whl → 0.12.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 +4 -2
- mapFolding/_theSSOT.py +32 -88
- mapFolding/{datatypes.py → _theTypes.py} +25 -3
- mapFolding/basecamp.py +39 -34
- mapFolding/beDRY.py +79 -54
- mapFolding/dataBaskets.py +117 -74
- mapFolding/filesystemToolkit.py +140 -91
- mapFolding/oeis.py +242 -144
- mapFolding/reference/flattened.py +1 -1
- mapFolding/someAssemblyRequired/RecipeJob.py +68 -53
- mapFolding/someAssemblyRequired/__init__.py +40 -15
- mapFolding/someAssemblyRequired/_toolIfThis.py +82 -54
- mapFolding/someAssemblyRequired/_toolkitContainers.py +19 -16
- mapFolding/someAssemblyRequired/getLLVMforNoReason.py +35 -26
- mapFolding/someAssemblyRequired/makeAllModules.py +348 -275
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +81 -57
- mapFolding/someAssemblyRequired/toolkitNumba.py +80 -50
- mapFolding/someAssemblyRequired/transformationTools.py +63 -40
- {mapfolding-0.12.2.dist-info → mapfolding-0.12.3.dist-info}/METADATA +7 -11
- {mapfolding-0.12.2.dist-info → mapfolding-0.12.3.dist-info}/RECORD +28 -28
- tests/test_computations.py +26 -8
- tests/test_oeis.py +8 -7
- tests/test_other.py +3 -3
- tests/test_tasks.py +2 -4
- {mapfolding-0.12.2.dist-info → mapfolding-0.12.3.dist-info}/WHEEL +0 -0
- {mapfolding-0.12.2.dist-info → mapfolding-0.12.3.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.12.2.dist-info → mapfolding-0.12.3.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.12.2.dist-info → mapfolding-0.12.3.dist-info}/top_level.txt +0 -0
|
@@ -32,61 +32,63 @@ tailored for specific computational requirements essential to large-scale map fo
|
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
from astToolkit import (
|
|
35
|
-
astModuleToIngredientsFunction, Be,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
from
|
|
40
|
-
inlineFunctionDef, removeUnusedParameters, write_astModule,
|
|
41
|
-
)
|
|
42
|
-
from collections.abc import Sequence
|
|
35
|
+
astModuleToIngredientsFunction, Be, DOT, extractClassDef, extractFunctionDef, Grab, hasDOTbody, identifierDotAttribute,
|
|
36
|
+
IngredientsFunction, IngredientsModule, LedgerOfImports, Make, NodeChanger, NodeTourist, parseLogicalPath2astModule,
|
|
37
|
+
parsePathFilename2astModule, Then)
|
|
38
|
+
from astToolkit.transformationTools import inlineFunctionDef, removeUnusedParameters, write_astModule
|
|
39
|
+
from hunterMakesPy import importLogicalPath2Identifier, raiseIfNone
|
|
43
40
|
from mapFolding import packageSettings
|
|
44
41
|
from mapFolding.someAssemblyRequired import (
|
|
45
|
-
DeReConstructField2ast, IfThis, ShatteredDataclass, sourceCallableDispatcherDEFAULT
|
|
46
|
-
)
|
|
42
|
+
DeReConstructField2ast, IfThis, ShatteredDataclass, sourceCallableDispatcherDEFAULT)
|
|
47
43
|
from mapFolding.someAssemblyRequired.infoBooth import (
|
|
48
44
|
algorithmSourceModuleDEFAULT, dataPackingModuleIdentifierDEFAULT, logicalPathInfixDEFAULT,
|
|
49
|
-
sourceCallableIdentifierDEFAULT, theCountingIdentifierDEFAULT
|
|
50
|
-
|
|
51
|
-
from mapFolding.someAssemblyRequired.toolkitNumba import (
|
|
52
|
-
decorateCallableWithNumba, parametersNumbaLight,
|
|
53
|
-
)
|
|
45
|
+
sourceCallableIdentifierDEFAULT, theCountingIdentifierDEFAULT)
|
|
46
|
+
from mapFolding.someAssemblyRequired.toolkitNumba import decorateCallableWithNumba, parametersNumbaLight
|
|
54
47
|
from mapFolding.someAssemblyRequired.transformationTools import (
|
|
55
|
-
removeDataclassFromFunction, shatter_dataclassesDOTdataclass,
|
|
56
|
-
unpackDataclassCallFunctionRepackDataclass,
|
|
57
|
-
)
|
|
48
|
+
removeDataclassFromFunction, shatter_dataclassesDOTdataclass, unpackDataclassCallFunctionRepackDataclass)
|
|
58
49
|
from os import PathLike
|
|
59
50
|
from pathlib import PurePath
|
|
60
|
-
from typing import Any, cast
|
|
61
|
-
from Z0Z_tools import importLogicalPath2Callable, raiseIfNone
|
|
51
|
+
from typing import Any, cast, TYPE_CHECKING
|
|
62
52
|
import ast
|
|
63
53
|
import dataclasses
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
if TYPE_CHECKING:
|
|
56
|
+
from collections.abc import Sequence
|
|
57
|
+
|
|
58
|
+
def _findDataclass(ingredientsFunction: IngredientsFunction) -> tuple[str, str, str]:
|
|
59
|
+
"""Extract dataclass information from a function's AST for transformation operations.
|
|
60
|
+
|
|
61
|
+
(AI generated docstring)
|
|
68
62
|
|
|
69
63
|
Analyzes the first parameter of a function to identify the dataclass type annotation
|
|
70
64
|
and instance identifier, then locates the module where the dataclass is defined by
|
|
71
65
|
examining the function's import statements. This information is essential for
|
|
72
66
|
dataclass decomposition and transformation operations.
|
|
73
67
|
|
|
74
|
-
Parameters
|
|
75
|
-
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
ingredientsFunction : IngredientsFunction
|
|
71
|
+
Function container with AST and import information.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
dataclassLogicalPathModule : str
|
|
76
|
+
Module logical path where the dataclass is defined.
|
|
77
|
+
dataclassIdentifier : str
|
|
78
|
+
Class name of the dataclass.
|
|
79
|
+
dataclassInstanceIdentifier : str
|
|
80
|
+
Parameter name for the dataclass instance.
|
|
81
|
+
|
|
82
|
+
Raises
|
|
83
|
+
------
|
|
84
|
+
ValueError
|
|
85
|
+
If dataclass information cannot be extracted from the function.
|
|
76
86
|
|
|
77
|
-
Returns:
|
|
78
|
-
dataclassLogicalPathModule: Module logical path where the dataclass is defined
|
|
79
|
-
dataclassIdentifier: Class name of the dataclass
|
|
80
|
-
dataclassInstanceIdentifier: Parameter name for the dataclass instance
|
|
81
|
-
|
|
82
|
-
Raises:
|
|
83
|
-
ValueError: If dataclass information cannot be extracted from the function
|
|
84
87
|
"""
|
|
85
|
-
|
|
86
88
|
dataclassName: ast.expr = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.annotation)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
87
89
|
dataclassIdentifier: str = raiseIfNone(NodeTourist(Be.Name, Then.extractIt(DOT.id)).captureLastMatch(dataclassName))
|
|
88
90
|
dataclassLogicalPathModule = None
|
|
89
|
-
for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports._dictionaryImportFrom.items():
|
|
91
|
+
for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports._dictionaryImportFrom.items(): # noqa: SLF001
|
|
90
92
|
for nameTuple in listNameTuples:
|
|
91
93
|
if nameTuple[0] == dataclassIdentifier:
|
|
92
94
|
dataclassLogicalPathModule = moduleWithLogicalPath
|
|
@@ -97,23 +99,31 @@ def findDataclass(ingredientsFunction: IngredientsFunction) -> tuple[str, str, s
|
|
|
97
99
|
return raiseIfNone(dataclassLogicalPathModule), dataclassIdentifier, dataclassInstanceIdentifier
|
|
98
100
|
|
|
99
101
|
def _getLogicalPath(packageName: str | None = None, logicalPathInfix: str | None = None, moduleIdentifier: str | None = None, *modules: str) -> identifierDotAttribute:
|
|
100
|
-
"""
|
|
101
|
-
|
|
102
|
+
"""Construct logical module path by joining package and module components.
|
|
103
|
+
|
|
104
|
+
(AI generated docstring)
|
|
102
105
|
|
|
103
106
|
Builds a dot-separated logical path string from optional package name, infix path
|
|
104
107
|
components, and module identifiers. This standardizes module path construction
|
|
105
108
|
across the code generation system and ensures consistent naming conventions.
|
|
106
109
|
|
|
107
|
-
Parameters
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
packageName : str | None = None
|
|
113
|
+
Root package name for the logical path.
|
|
114
|
+
logicalPathInfix : str | None = None
|
|
115
|
+
Middle path component (typically 'syntheticModules').
|
|
116
|
+
moduleIdentifier : str | None = None
|
|
117
|
+
Primary module identifier.
|
|
118
|
+
*modules : str
|
|
119
|
+
Additional module path components to append.
|
|
120
|
+
|
|
121
|
+
Returns
|
|
122
|
+
-------
|
|
123
|
+
logicalPath : identifierDotAttribute
|
|
124
|
+
Dot-separated logical path string suitable for module import operations.
|
|
112
125
|
|
|
113
|
-
Returns:
|
|
114
|
-
logicalPath: Dot-separated logical path string suitable for module import operations
|
|
115
126
|
"""
|
|
116
|
-
|
|
117
127
|
listLogicalPathParts: list[str] = []
|
|
118
128
|
if packageName:
|
|
119
129
|
listLogicalPathParts.append(packageName)
|
|
@@ -123,49 +133,63 @@ def _getLogicalPath(packageName: str | None = None, logicalPathInfix: str | None
|
|
|
123
133
|
listLogicalPathParts.append(moduleIdentifier)
|
|
124
134
|
if modules:
|
|
125
135
|
listLogicalPathParts.extend(modules)
|
|
126
|
-
|
|
127
|
-
return logicalPath
|
|
136
|
+
return '.'.join(listLogicalPathParts)
|
|
128
137
|
|
|
129
|
-
def
|
|
130
|
-
"""
|
|
131
|
-
|
|
138
|
+
def _getModule(packageName: str | None = packageSettings.identifierPackage, logicalPathInfix: str | None = logicalPathInfixDEFAULT, moduleIdentifier: str | None = algorithmSourceModuleDEFAULT) -> ast.Module:
|
|
139
|
+
"""Load source algorithm module as AST for transformation operations.
|
|
140
|
+
|
|
141
|
+
(AI generated docstring)
|
|
132
142
|
|
|
133
143
|
Retrieves the specified module and parses it into an AST representation that can
|
|
134
144
|
be manipulated by the transformation tools. This provides the foundation for all
|
|
135
145
|
code generation operations by making the source algorithms available for analysis
|
|
136
146
|
and modification.
|
|
137
147
|
|
|
138
|
-
Parameters
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
packageName : str | None = packageSettings.identifierPackage
|
|
151
|
+
Package containing the source module.
|
|
152
|
+
logicalPathInfix : str | None = logicalPathInfixDEFAULT
|
|
153
|
+
Path component within the package structure.
|
|
154
|
+
moduleIdentifier : str | None = algorithmSourceModuleDEFAULT
|
|
155
|
+
Specific module containing the algorithms.
|
|
142
156
|
|
|
143
|
-
Returns
|
|
144
|
-
|
|
145
|
-
|
|
157
|
+
Returns
|
|
158
|
+
-------
|
|
159
|
+
astModule : ast.Module
|
|
160
|
+
AST module representation ready for transformation operations.
|
|
146
161
|
|
|
162
|
+
"""
|
|
147
163
|
logicalPathSourceModule: identifierDotAttribute = _getLogicalPath(packageName, logicalPathInfix, moduleIdentifier)
|
|
148
164
|
astModule: ast.Module = parseLogicalPath2astModule(logicalPathSourceModule)
|
|
149
165
|
return astModule
|
|
150
166
|
|
|
151
167
|
def _getPathFilename(pathRoot: PathLike[str] | PurePath | None = packageSettings.pathPackage, logicalPathInfix: PathLike[str] | PurePath | str | None = None, moduleIdentifier: str = '', fileExtension: str = packageSettings.fileExtension) -> PurePath:
|
|
152
|
-
"""
|
|
153
|
-
|
|
168
|
+
"""Construct filesystem path for generated module files.
|
|
169
|
+
|
|
170
|
+
(AI generated docstring)
|
|
154
171
|
|
|
155
172
|
Builds the complete filesystem path where generated modules will be written,
|
|
156
173
|
combining root path, optional infix directory, module name, and file extension.
|
|
157
174
|
This ensures consistent file organization across all generated code.
|
|
158
175
|
|
|
159
|
-
Parameters
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
176
|
+
Parameters
|
|
177
|
+
----------
|
|
178
|
+
pathRoot : PathLike[str] | PurePath | None = packageSettings.pathPackage
|
|
179
|
+
Base directory for the package structure.
|
|
180
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
181
|
+
Subdirectory for organizing generated modules.
|
|
182
|
+
moduleIdentifier : str = ''
|
|
183
|
+
Name of the specific module file.
|
|
184
|
+
fileExtension : str = packageSettings.fileExtension
|
|
185
|
+
File extension for Python modules.
|
|
186
|
+
|
|
187
|
+
Returns
|
|
188
|
+
-------
|
|
189
|
+
pathFilename : PurePath
|
|
190
|
+
Complete filesystem path for the generated module file.
|
|
164
191
|
|
|
165
|
-
Returns:
|
|
166
|
-
pathFilename: Complete filesystem path for the generated module file
|
|
167
192
|
"""
|
|
168
|
-
|
|
169
193
|
pathFilename = PurePath(moduleIdentifier + fileExtension)
|
|
170
194
|
if logicalPathInfix:
|
|
171
195
|
pathFilename = PurePath(logicalPathInfix, pathFilename)
|
|
@@ -173,9 +197,10 @@ def _getPathFilename(pathRoot: PathLike[str] | PurePath | None = packageSettings
|
|
|
173
197
|
pathFilename = PurePath(pathRoot, pathFilename)
|
|
174
198
|
return pathFilename
|
|
175
199
|
|
|
176
|
-
def makeInitializeGroupsOfFolds(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
177
|
-
"""
|
|
178
|
-
|
|
200
|
+
def makeInitializeGroupsOfFolds(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
|
|
201
|
+
"""Generate initialization module for counting variable setup.
|
|
202
|
+
|
|
203
|
+
(AI generated docstring)
|
|
179
204
|
|
|
180
205
|
Creates a specialized module containing initialization logic for the counting variables
|
|
181
206
|
used in map folding computations. The generated function transforms the original
|
|
@@ -185,70 +210,81 @@ def makeInitializeGroupsOfFolds(astModule: ast.Module, moduleIdentifier: str, ca
|
|
|
185
210
|
This transformation is particularly important for ensuring that counting variables
|
|
186
211
|
are properly initialized before the main computational loops begin executing.
|
|
187
212
|
|
|
188
|
-
Parameters
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
astModule : ast.Module
|
|
216
|
+
Source module containing the base algorithm.
|
|
217
|
+
moduleIdentifier : str
|
|
218
|
+
Name for the generated initialization module.
|
|
219
|
+
callableIdentifier : str | None = None
|
|
220
|
+
Name for the initialization function.
|
|
221
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
222
|
+
Directory path for organizing the generated module.
|
|
223
|
+
sourceCallableDispatcher : str | None = None
|
|
224
|
+
Optional dispatcher function identifier.
|
|
225
|
+
|
|
226
|
+
Returns
|
|
227
|
+
-------
|
|
228
|
+
pathFilename : PurePath
|
|
229
|
+
Filesystem path where the initialization module was written.
|
|
194
230
|
|
|
195
|
-
Returns:
|
|
196
|
-
pathFilename: Filesystem path where the initialization module was written
|
|
197
231
|
"""
|
|
198
|
-
|
|
199
232
|
sourceCallableIdentifier: identifierDotAttribute = sourceCallableIdentifierDEFAULT
|
|
200
|
-
if callableIdentifier is None:
|
|
201
|
-
callableIdentifier = sourceCallableIdentifier
|
|
202
233
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
203
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
234
|
+
ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
|
|
204
235
|
|
|
205
236
|
dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
206
237
|
theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
|
|
207
238
|
|
|
208
239
|
findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
209
|
-
doThat = Grab.testAttribute(Grab.andDoAllOf([Grab.opsAttribute(Then.replaceWith([ast.Eq()])), Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier)))]))
|
|
240
|
+
doThat = Grab.testAttribute(Grab.andDoAllOf([Grab.opsAttribute(Then.replaceWith([ast.Eq()])), Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier)))]))
|
|
210
241
|
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef.body[0])
|
|
211
242
|
|
|
212
|
-
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
213
243
|
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
214
|
-
write_astModule(
|
|
244
|
+
write_astModule(IngredientsModule(ingredientsFunction), pathFilename, packageSettings.identifierPackage)
|
|
215
245
|
|
|
216
246
|
return pathFilename
|
|
217
247
|
|
|
218
248
|
def makeDaoOfMapFolding(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
219
|
-
"""
|
|
220
|
-
Generate Numba-optimized sequential implementation of map folding algorithm.
|
|
249
|
+
"""Generate Numba-optimized sequential implementation of map folding algorithm.
|
|
221
250
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
251
|
+
(AI generated docstring)
|
|
252
|
+
|
|
253
|
+
Creates a high-performance sequential version of the map folding algorithm by
|
|
254
|
+
decomposing dataclass parameters into individual primitive values, removing
|
|
255
|
+
dataclass dependencies that are incompatible with Numba, applying Numba
|
|
256
|
+
decorators for just-in-time compilation, and optionally including a dispatcher
|
|
257
|
+
function for dataclass integration.
|
|
227
258
|
|
|
228
259
|
The generated module provides significant performance improvements over the
|
|
229
260
|
original dataclass-based implementation while maintaining algorithmic correctness.
|
|
230
261
|
The transformation preserves all computational logic while restructuring data
|
|
231
262
|
access patterns for optimal Numba compilation.
|
|
232
263
|
|
|
233
|
-
Parameters
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
264
|
+
Parameters
|
|
265
|
+
----------
|
|
266
|
+
astModule : ast.Module
|
|
267
|
+
Source module containing the base algorithm.
|
|
268
|
+
moduleIdentifier : str
|
|
269
|
+
Name for the generated optimized module.
|
|
270
|
+
callableIdentifier : str | None = None
|
|
271
|
+
Name for the main computational function.
|
|
272
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
273
|
+
Directory path for organizing the generated module.
|
|
274
|
+
sourceCallableDispatcher : str | None = None
|
|
275
|
+
Optional dispatcher function for dataclass integration.
|
|
276
|
+
|
|
277
|
+
Returns
|
|
278
|
+
-------
|
|
279
|
+
pathFilename : PurePath
|
|
280
|
+
Filesystem path where the optimized module was written.
|
|
239
281
|
|
|
240
|
-
Returns:
|
|
241
|
-
pathFilename: Filesystem path where the optimized module was written
|
|
242
282
|
"""
|
|
243
|
-
|
|
244
283
|
sourceCallableIdentifier: identifierDotAttribute = sourceCallableIdentifierDEFAULT
|
|
245
284
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
285
|
+
ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
|
|
246
286
|
|
|
247
|
-
|
|
248
|
-
callableIdentifier = sourceCallableIdentifier
|
|
249
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
250
|
-
|
|
251
|
-
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*findDataclass(ingredientsFunction))
|
|
287
|
+
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
|
|
252
288
|
|
|
253
289
|
ingredientsFunction.imports.update(shatteredDataclass.imports)
|
|
254
290
|
ingredientsFunction: IngredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
|
|
@@ -263,12 +299,13 @@ def makeDaoOfMapFolding(astModule: ast.Module, moduleIdentifier: str, callableId
|
|
|
263
299
|
ingredientsFunctionDispatcher.imports.update(shatteredDataclass.imports)
|
|
264
300
|
targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
|
|
265
301
|
ingredientsFunctionDispatcher = unpackDataclassCallFunctionRepackDataclass(ingredientsFunctionDispatcher, targetCallableIdentifier, shatteredDataclass)
|
|
266
|
-
astTuple: ast.
|
|
267
|
-
|
|
302
|
+
astTuple: ast.Tuple = cast('ast.Tuple', raiseIfNone(NodeTourist[ast.Return, ast.expr | None](Be.Return.valueIs(Be.Tuple)
|
|
303
|
+
, doThat=Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef)))
|
|
304
|
+
astTuple.ctx = ast.Store()
|
|
268
305
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
306
|
+
changeAssignCallToTarget = NodeChanger(
|
|
307
|
+
findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
|
|
308
|
+
, doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts))))
|
|
272
309
|
changeAssignCallToTarget.visit(ingredientsFunctionDispatcher.astFunctionDef)
|
|
273
310
|
|
|
274
311
|
ingredientsModule.appendIngredientsFunction(ingredientsFunctionDispatcher)
|
|
@@ -277,40 +314,42 @@ def makeDaoOfMapFolding(astModule: ast.Module, moduleIdentifier: str, callableId
|
|
|
277
314
|
|
|
278
315
|
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
279
316
|
|
|
280
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.
|
|
317
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
281
318
|
|
|
282
319
|
return pathFilename
|
|
283
320
|
|
|
284
|
-
def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
285
|
-
"""
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
Returns
|
|
311
|
-
|
|
312
|
-
|
|
321
|
+
def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001, PLR0915
|
|
322
|
+
"""Generate parallel implementation with concurrent execution and task division.
|
|
323
|
+
|
|
324
|
+
This version of the algorithm: Creates a parallel processing version of the map folding algorithm that distributes
|
|
325
|
+
computational work across multiple processes using `ProcessPoolExecutor`. The implementation includes dataclass decomposition
|
|
326
|
+
for both base and parallel state fields, task division logic that partitions work based on leaf indices, concurrent execution
|
|
327
|
+
management with future objects, result aggregation from multiple parallel computations, and Numba optimization for the core
|
|
328
|
+
computational kernels.
|
|
329
|
+
|
|
330
|
+
The generated module contains multiple functions including core counting function with parallel-aware task filtering,
|
|
331
|
+
dataclass unpacking/repacking function for process communication, and main dispatcher function that manages the parallel
|
|
332
|
+
execution pipeline.
|
|
333
|
+
|
|
334
|
+
Parameters
|
|
335
|
+
----------
|
|
336
|
+
astModule : ast.Module
|
|
337
|
+
Source module containing the base algorithm.
|
|
338
|
+
moduleIdentifier : str
|
|
339
|
+
Name for the generated parallel module.
|
|
340
|
+
callableIdentifier : str | None = None
|
|
341
|
+
Name for the core parallel counting function.
|
|
342
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
343
|
+
Directory path for organizing the generated module.
|
|
344
|
+
sourceCallableDispatcher : str | None = None
|
|
345
|
+
Optional dispatcher function identifier.
|
|
346
|
+
|
|
347
|
+
Returns
|
|
348
|
+
-------
|
|
349
|
+
pathFilename : PurePath
|
|
350
|
+
Filesystem path where the parallel module was written.
|
|
313
351
|
|
|
352
|
+
"""
|
|
314
353
|
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
315
354
|
if callableIdentifier is None:
|
|
316
355
|
callableIdentifier = sourceCallableIdentifier
|
|
@@ -321,7 +360,7 @@ def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, ca
|
|
|
321
360
|
dataclassIdentifier: str = raiseIfNone(NodeTourist(Be.Name, Then.extractIt(DOT.id)).captureLastMatch(dataclassName))
|
|
322
361
|
|
|
323
362
|
dataclassLogicalPathModule = None
|
|
324
|
-
for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports._dictionaryImportFrom.items():
|
|
363
|
+
for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports._dictionaryImportFrom.items(): # noqa: SLF001
|
|
325
364
|
for nameTuple in listNameTuples:
|
|
326
365
|
if nameTuple[0] == dataclassIdentifier:
|
|
327
366
|
dataclassLogicalPathModule = moduleWithLogicalPath
|
|
@@ -329,22 +368,23 @@ def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, ca
|
|
|
329
368
|
if dataclassLogicalPathModule:
|
|
330
369
|
break
|
|
331
370
|
if dataclassLogicalPathModule is None:
|
|
332
|
-
raise Exception
|
|
371
|
+
raise Exception # noqa: TRY002
|
|
333
372
|
dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
334
373
|
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(dataclassLogicalPathModule, dataclassIdentifier, dataclassInstanceIdentifier)
|
|
335
374
|
|
|
336
|
-
#
|
|
337
|
-
dataclassBaseFields: tuple[dataclasses.Field[Any], ...] = dataclasses.fields(
|
|
375
|
+
# START add the parallel state fields to the count function ------------------------------------------------
|
|
376
|
+
dataclassBaseFields: tuple[dataclasses.Field[Any], ...] = dataclasses.fields(importLogicalPath2Identifier(dataclassLogicalPathModule, dataclassIdentifier)) # pyright: ignore [reportArgumentType]
|
|
338
377
|
dataclassIdentifierParallel: identifierDotAttribute = 'Parallel' + dataclassIdentifier
|
|
339
|
-
dataclassFieldsParallel: tuple[dataclasses.Field[Any], ...] = dataclasses.fields(
|
|
378
|
+
dataclassFieldsParallel: tuple[dataclasses.Field[Any], ...] = dataclasses.fields(importLogicalPath2Identifier(dataclassLogicalPathModule, dataclassIdentifierParallel)) # pyright: ignore [reportArgumentType]
|
|
340
379
|
onlyParallelFields: list[dataclasses.Field[Any]] = [field for field in dataclassFieldsParallel if field.name not in [fieldBase.name for fieldBase in dataclassBaseFields]]
|
|
341
380
|
|
|
342
381
|
Official_fieldOrder: list[str] = []
|
|
343
382
|
dictionaryDeReConstruction: dict[str, DeReConstructField2ast] = {}
|
|
344
383
|
|
|
345
384
|
dataclassClassDef: ast.ClassDef | None = extractClassDef(parseLogicalPath2astModule(dataclassLogicalPathModule), dataclassIdentifierParallel)
|
|
346
|
-
if not
|
|
347
|
-
|
|
385
|
+
if not dataclassClassDef:
|
|
386
|
+
message = f"I could not find `{dataclassIdentifierParallel = }` in `{dataclassLogicalPathModule = }`."
|
|
387
|
+
raise ValueError(message)
|
|
348
388
|
|
|
349
389
|
for aField in onlyParallelFields:
|
|
350
390
|
Official_fieldOrder.append(aField.name)
|
|
@@ -371,16 +411,15 @@ def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, ca
|
|
|
371
411
|
shatteredDataclassParallel.imports.update(shatteredDataclass.imports)
|
|
372
412
|
shatteredDataclassParallel.imports.removeImportFrom(dataclassLogicalPathModule, dataclassIdentifier)
|
|
373
413
|
|
|
374
|
-
#
|
|
414
|
+
# END add the parallel state fields to the count function ------------------------------------------------
|
|
375
415
|
|
|
376
416
|
ingredientsFunction.imports.update(shatteredDataclassParallel.imports)
|
|
377
417
|
ingredientsFunction: IngredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclassParallel)
|
|
378
418
|
|
|
379
|
-
#
|
|
419
|
+
# START add the parallel logic to the count function ------------------------------------------------
|
|
380
420
|
|
|
381
|
-
findThis =
|
|
382
|
-
doThat = Then.extractIt(DOT.body)
|
|
383
|
-
captureCountGapsCodeBlock: NodeTourist[ast.While, Sequence[ast.stmt]] = NodeTourist(findThis, doThat)
|
|
421
|
+
findThis = Be.While.testIs(Be.Compare.leftIs(IfThis.isNameIdentifier('leafConnectee')))
|
|
422
|
+
captureCountGapsCodeBlock: NodeTourist[ast.While, Sequence[ast.stmt]] = NodeTourist(findThis, doThat = Then.extractIt(DOT.body))
|
|
384
423
|
countGapsCodeBlock: Sequence[ast.stmt] = raiseIfNone(captureCountGapsCodeBlock.captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
385
424
|
|
|
386
425
|
thisIsMyTaskIndexCodeBlock = ast.If(ast.BoolOp(ast.Or()
|
|
@@ -389,34 +428,34 @@ def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, ca
|
|
|
389
428
|
, body=list(countGapsCodeBlock[0:-1]))
|
|
390
429
|
|
|
391
430
|
countGapsCodeBlockNew: list[ast.stmt] = [thisIsMyTaskIndexCodeBlock, countGapsCodeBlock[-1]]
|
|
431
|
+
NodeChanger[ast.While, hasDOTbody](findThis, doThat = Grab.bodyAttribute(Then.replaceWith(countGapsCodeBlockNew))).visit(ingredientsFunction.astFunctionDef)
|
|
392
432
|
|
|
393
|
-
|
|
394
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
395
|
-
|
|
396
|
-
# End add the parallel logic to the count function ================================================
|
|
433
|
+
# END add the parallel logic to the count function ------------------------------------------------
|
|
397
434
|
|
|
398
435
|
ingredientsFunction = removeUnusedParameters(ingredientsFunction)
|
|
399
436
|
|
|
400
437
|
ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
|
|
401
438
|
|
|
402
|
-
#
|
|
439
|
+
# START unpack/repack the dataclass function ------------------------------------------------
|
|
403
440
|
sourceCallableIdentifier = sourceCallableDispatcherDEFAULT
|
|
404
441
|
|
|
405
442
|
unRepackDataclass: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableIdentifier)
|
|
406
443
|
unRepackDataclass.astFunctionDef.name = 'unRepack' + dataclassIdentifierParallel
|
|
407
444
|
unRepackDataclass.imports.update(shatteredDataclassParallel.imports)
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
445
|
+
NodeChanger(
|
|
446
|
+
findThis = Be.arg.annotationIs(Be.Name.idIs(lambda thisAttribute: thisAttribute == dataclassIdentifier)) # pyright: ignore[reportArgumentType]
|
|
447
|
+
, doThat = Grab.annotationAttribute(Grab.idAttribute(Then.replaceWith(dataclassIdentifierParallel)))
|
|
448
|
+
).visit(unRepackDataclass.astFunctionDef)
|
|
411
449
|
unRepackDataclass.astFunctionDef.returns = Make.Name(dataclassIdentifierParallel)
|
|
412
450
|
targetCallableIdentifier: identifierDotAttribute = ingredientsFunction.astFunctionDef.name
|
|
413
451
|
unRepackDataclass = unpackDataclassCallFunctionRepackDataclass(unRepackDataclass, targetCallableIdentifier, shatteredDataclassParallel)
|
|
414
452
|
|
|
415
|
-
astTuple: ast.
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
453
|
+
astTuple: ast.Tuple = raiseIfNone(NodeTourist[ast.Return, ast.Tuple](Be.Return, Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef)) # pyright: ignore[reportArgumentType]
|
|
454
|
+
astTuple.ctx = ast.Store()
|
|
455
|
+
changeAssignCallToTarget: NodeChanger[ast.Assign, ast.Assign] = NodeChanger(
|
|
456
|
+
findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
|
|
457
|
+
, doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts)))
|
|
458
|
+
)
|
|
420
459
|
changeAssignCallToTarget.visit(unRepackDataclass.astFunctionDef)
|
|
421
460
|
|
|
422
461
|
ingredientsDoTheNeedful: IngredientsFunction = IngredientsFunction(
|
|
@@ -442,7 +481,7 @@ def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, ca
|
|
|
442
481
|
, returns=Make.Subscript(Make.Name('tuple'), slice=Make.Tuple([Make.Name('int'), Make.Subscript(Make.Name('list'), slice=Make.Name(dataclassIdentifierParallel))])))
|
|
443
482
|
, imports = LedgerOfImports(Make.Module([Make.ImportFrom('concurrent.futures', list_alias=[Make.alias('Future', asName='ConcurrentFuture'), Make.alias('ProcessPoolExecutor')]),
|
|
444
483
|
Make.ImportFrom('copy', list_alias=[Make.alias('deepcopy')]),
|
|
445
|
-
Make.ImportFrom('multiprocessing', list_alias=[Make.alias('set_start_method', asName='multiprocessing_set_start_method')])
|
|
484
|
+
Make.ImportFrom('multiprocessing', list_alias=[Make.alias('set_start_method', asName='multiprocessing_set_start_method')])])
|
|
446
485
|
)
|
|
447
486
|
)
|
|
448
487
|
|
|
@@ -453,88 +492,104 @@ def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, ca
|
|
|
453
492
|
|
|
454
493
|
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
455
494
|
|
|
456
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.
|
|
495
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
457
496
|
|
|
458
497
|
return pathFilename
|
|
459
498
|
|
|
460
499
|
def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
461
|
-
"""
|
|
462
|
-
Generate optimized implementation applying Theorem 2 mathematical optimizations.
|
|
500
|
+
"""Generate optimized implementation applying Theorem 2 mathematical optimizations.
|
|
463
501
|
|
|
464
|
-
|
|
465
|
-
optimizations for improved computational efficiency. The transformation includes:
|
|
502
|
+
(AI generated docstring)
|
|
466
503
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
504
|
+
Creates a specialized version of the map folding algorithm that applies Theorem 2
|
|
505
|
+
optimizations for improved computational efficiency. The transformation includes
|
|
506
|
+
modifying loop termination conditions from general cases to Theorem 2 specifics,
|
|
507
|
+
restructuring conditional logic to eliminate unnecessary branch evaluations,
|
|
508
|
+
adding count doubling operations to leverage mathematical properties, and
|
|
509
|
+
removing redundant computations that are not needed under Theorem 2 constraints.
|
|
471
510
|
|
|
472
511
|
Theorem 2 provides mathematical guarantees that allow certain computational
|
|
473
512
|
shortcuts and optimizations that would not be valid in the general case. This
|
|
474
513
|
implementation capitalizes on those properties to achieve significant performance
|
|
475
514
|
improvements for maps that satisfy Theorem 2 conditions.
|
|
476
515
|
|
|
477
|
-
Parameters
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
516
|
+
Parameters
|
|
517
|
+
----------
|
|
518
|
+
astModule : ast.Module
|
|
519
|
+
Source module containing the base algorithm.
|
|
520
|
+
moduleIdentifier : str
|
|
521
|
+
Name for the generated theorem-optimized module.
|
|
522
|
+
callableIdentifier : str | None = None
|
|
523
|
+
Name for the optimized computational function.
|
|
524
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
525
|
+
Directory path for organizing the generated module.
|
|
526
|
+
sourceCallableDispatcher : str | None = None
|
|
527
|
+
Currently not implemented for this transformation.
|
|
528
|
+
|
|
529
|
+
Returns
|
|
530
|
+
-------
|
|
531
|
+
pathFilename : PurePath
|
|
532
|
+
Filesystem path where the theorem-optimized module was written.
|
|
533
|
+
|
|
534
|
+
Raises
|
|
535
|
+
------
|
|
536
|
+
NotImplementedError
|
|
537
|
+
If `sourceCallableDispatcher` is provided.
|
|
483
538
|
|
|
484
|
-
Returns:
|
|
485
|
-
pathFilename: Filesystem path where the theorem-optimized module was written
|
|
486
|
-
|
|
487
|
-
Raises:
|
|
488
|
-
NotImplementedError: If sourceCallableDispatcher is provided
|
|
489
539
|
"""
|
|
490
|
-
|
|
491
540
|
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
492
|
-
if callableIdentifier is None:
|
|
493
|
-
callableIdentifier = sourceCallableIdentifier
|
|
494
541
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
495
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
542
|
+
ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
|
|
496
543
|
|
|
497
544
|
dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
498
545
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
NodeChanger(
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
546
|
+
NodeChanger(
|
|
547
|
+
findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
548
|
+
, doThat = Grab.testAttribute(Grab.comparatorsAttribute(Then.replaceWith([Make.Constant(4)])))
|
|
549
|
+
).visit(ingredientsFunction.astFunctionDef)
|
|
550
|
+
|
|
551
|
+
insertLeaf = NodeTourist(
|
|
552
|
+
findThis = IfThis.isIfAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
553
|
+
, doThat = Then.extractIt(DOT.body)
|
|
554
|
+
).captureLastMatch(ingredientsFunction.astFunctionDef)
|
|
555
|
+
NodeChanger(
|
|
556
|
+
findThis = IfThis.isIfAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
557
|
+
, doThat = Then.replaceWith(insertLeaf)
|
|
558
|
+
).visit(ingredientsFunction.astFunctionDef)
|
|
559
|
+
|
|
560
|
+
NodeChanger(
|
|
561
|
+
findThis = IfThis.isAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
562
|
+
, doThat = Then.removeIt
|
|
563
|
+
).visit(ingredientsFunction.astFunctionDef)
|
|
564
|
+
|
|
565
|
+
NodeChanger(
|
|
566
|
+
findThis = IfThis.isAttributeNamespaceIdentifierLessThanOrEqual0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
567
|
+
, doThat = Then.removeIt
|
|
568
|
+
).visit(ingredientsFunction.astFunctionDef)
|
|
517
569
|
|
|
518
570
|
theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
|
|
519
571
|
doubleTheCount: ast.AugAssign = Make.AugAssign(Make.Attribute(ast.Name(dataclassInstanceIdentifier), theCountingIdentifier), ast.Mult(), Make.Constant(2))
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
572
|
+
NodeChanger(
|
|
573
|
+
findThis = Be.Return
|
|
574
|
+
, doThat = Then.insertThisAbove([doubleTheCount])
|
|
575
|
+
).visit(ingredientsFunction.astFunctionDef)
|
|
523
576
|
|
|
524
577
|
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
525
578
|
|
|
526
579
|
if sourceCallableDispatcher is not None:
|
|
527
|
-
|
|
580
|
+
message = 'sourceCallableDispatcher is not implemented yet'
|
|
581
|
+
raise NotImplementedError(message)
|
|
528
582
|
|
|
529
583
|
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
530
584
|
|
|
531
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.
|
|
585
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
532
586
|
|
|
533
587
|
return pathFilename
|
|
534
588
|
|
|
535
|
-
def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
536
|
-
"""
|
|
537
|
-
|
|
589
|
+
def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
|
|
590
|
+
"""Generate constrained Theorem 2 implementation by removing unnecessary logic.
|
|
591
|
+
|
|
592
|
+
(AI generated docstring)
|
|
538
593
|
|
|
539
594
|
Creates a trimmed version of the Theorem 2 implementation by eliminating
|
|
540
595
|
conditional logic that is not needed under specific constraint assumptions.
|
|
@@ -547,22 +602,28 @@ def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
|
|
|
547
602
|
allowing the removal of defensive programming constructs that add computational
|
|
548
603
|
overhead without providing benefits in the constrained environment.
|
|
549
604
|
|
|
550
|
-
Parameters
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
605
|
+
Parameters
|
|
606
|
+
----------
|
|
607
|
+
astModule : ast.Module
|
|
608
|
+
Source module containing the Theorem 2 implementation.
|
|
609
|
+
moduleIdentifier : str
|
|
610
|
+
Name for the generated trimmed module.
|
|
611
|
+
callableIdentifier : str | None = None
|
|
612
|
+
Name for the trimmed computational function.
|
|
613
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
614
|
+
Directory path for organizing the generated module.
|
|
615
|
+
sourceCallableDispatcher : str | None = None
|
|
616
|
+
Optional dispatcher function identifier (unused).
|
|
617
|
+
|
|
618
|
+
Returns
|
|
619
|
+
-------
|
|
620
|
+
pathFilename : PurePath
|
|
621
|
+
Filesystem path where the trimmed module was written.
|
|
556
622
|
|
|
557
|
-
Returns:
|
|
558
|
-
pathFilename: Filesystem path where the trimmed module was written
|
|
559
623
|
"""
|
|
560
|
-
|
|
561
624
|
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
562
|
-
if callableIdentifier is None:
|
|
563
|
-
callableIdentifier = sourceCallableIdentifier
|
|
564
625
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
565
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
626
|
+
ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
|
|
566
627
|
|
|
567
628
|
dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
568
629
|
|
|
@@ -575,22 +636,21 @@ def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
|
|
|
575
636
|
|
|
576
637
|
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
577
638
|
|
|
578
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.
|
|
639
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
579
640
|
|
|
580
641
|
return pathFilename
|
|
581
642
|
|
|
582
|
-
def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
583
|
-
"""
|
|
584
|
-
|
|
643
|
+
def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
|
|
644
|
+
"""Generate Numba-accelerated Theorem 2 implementation with dataclass decomposition.
|
|
645
|
+
|
|
646
|
+
(AI generated docstring)
|
|
585
647
|
|
|
586
648
|
Creates a highly optimized version of the Theorem 2 algorithm by combining the
|
|
587
649
|
mathematical optimizations of Theorem 2 with Numba just-in-time compilation.
|
|
588
|
-
The transformation includes
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
3. Application of Numba decorators for maximum performance
|
|
593
|
-
4. Type annotation optimization for efficient compilation
|
|
650
|
+
The transformation includes dataclass decomposition to convert structured
|
|
651
|
+
parameters into primitives, removal of Python object dependencies incompatible
|
|
652
|
+
with Numba, application of Numba decorators for maximum performance, and type
|
|
653
|
+
annotation optimization for efficient compilation.
|
|
594
654
|
|
|
595
655
|
This represents the highest level of optimization available for Theorem 2
|
|
596
656
|
implementations, providing both mathematical efficiency through theorem
|
|
@@ -598,24 +658,32 @@ def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdenti
|
|
|
598
658
|
The result is suitable for production use in high-performance computing
|
|
599
659
|
environments where maximum speed is required.
|
|
600
660
|
|
|
601
|
-
Parameters
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
661
|
+
Parameters
|
|
662
|
+
----------
|
|
663
|
+
astModule : ast.Module
|
|
664
|
+
Source module containing the Theorem 2 implementation.
|
|
665
|
+
moduleIdentifier : str
|
|
666
|
+
Name for the generated Numba-accelerated module.
|
|
667
|
+
callableIdentifier : str | None = None
|
|
668
|
+
Name for the accelerated computational function.
|
|
669
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
670
|
+
Directory path for organizing the generated module.
|
|
671
|
+
sourceCallableDispatcher : str | None = None
|
|
672
|
+
Optional dispatcher function identifier (unused).
|
|
673
|
+
|
|
674
|
+
Returns
|
|
675
|
+
-------
|
|
676
|
+
pathFilename : PurePath
|
|
677
|
+
Filesystem path where the accelerated module was written.
|
|
607
678
|
|
|
608
|
-
Returns:
|
|
609
|
-
Filesystem path where the accelerated module was written
|
|
610
679
|
"""
|
|
611
|
-
|
|
612
680
|
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
613
681
|
if callableIdentifier is None:
|
|
614
682
|
callableIdentifier = sourceCallableIdentifier
|
|
615
683
|
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
616
684
|
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
617
685
|
|
|
618
|
-
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*
|
|
686
|
+
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
|
|
619
687
|
|
|
620
688
|
ingredientsFunction.imports.update(shatteredDataclass.imports)
|
|
621
689
|
ingredientsFunction: IngredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
|
|
@@ -627,39 +695,42 @@ def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdenti
|
|
|
627
695
|
|
|
628
696
|
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
629
697
|
|
|
630
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.
|
|
698
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
631
699
|
|
|
632
700
|
return pathFilename
|
|
633
701
|
|
|
634
702
|
def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
|
|
635
|
-
"""
|
|
636
|
-
|
|
703
|
+
"""Generate interface module for dataclass unpacking and repacking operations.
|
|
704
|
+
|
|
705
|
+
(AI generated docstring)
|
|
637
706
|
|
|
638
707
|
Creates a specialized module that serves as an interface between dataclass-based
|
|
639
708
|
calling code and optimized implementations that operate on decomposed primitive
|
|
640
|
-
values. The generated module includes
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
3. Repacking of results back into appropriate dataclass instances
|
|
645
|
-
4. Import management for all required dependencies
|
|
709
|
+
values. The generated module includes a function that unpacks dataclass instances
|
|
710
|
+
into individual primitive values, calls to the specified optimized target function
|
|
711
|
+
with decomposed parameters, repacking of results back into appropriate dataclass
|
|
712
|
+
instances, and import management for all required dependencies.
|
|
646
713
|
|
|
647
714
|
This bridge module enables seamless integration between high-level dataclass-based
|
|
648
715
|
APIs and low-level optimized implementations, maintaining type safety and usability
|
|
649
716
|
while leveraging performance optimizations that require primitive value operations.
|
|
650
717
|
|
|
651
|
-
Parameters
|
|
652
|
-
|
|
718
|
+
Parameters
|
|
719
|
+
----------
|
|
720
|
+
astImportFrom : ast.ImportFrom
|
|
721
|
+
Import statement specifying the target optimized function to call.
|
|
653
722
|
|
|
654
|
-
Returns
|
|
655
|
-
|
|
656
|
-
|
|
723
|
+
Returns
|
|
724
|
+
-------
|
|
725
|
+
None
|
|
726
|
+
The generated module is written directly to the filesystem.
|
|
657
727
|
|
|
728
|
+
"""
|
|
658
729
|
callableIdentifierHARDCODED: str = 'sequential'
|
|
659
730
|
|
|
660
731
|
algorithmSourceModule: identifierDotAttribute = algorithmSourceModuleDEFAULT
|
|
661
732
|
sourceCallableIdentifier: identifierDotAttribute = sourceCallableDispatcherDEFAULT
|
|
662
|
-
logicalPathSourceModule: identifierDotAttribute = '.'.join([packageSettings.
|
|
733
|
+
logicalPathSourceModule: identifierDotAttribute = '.'.join([packageSettings.identifierPackage, algorithmSourceModule]) # noqa: FLY002
|
|
663
734
|
|
|
664
735
|
logicalPathInfix: identifierDotAttribute = logicalPathInfixDEFAULT
|
|
665
736
|
moduleIdentifier: identifierDotAttribute = dataPackingModuleIdentifierDEFAULT
|
|
@@ -668,38 +739,40 @@ def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
|
|
|
668
739
|
ingredientsFunction: IngredientsFunction = astModuleToIngredientsFunction(parseLogicalPath2astModule(logicalPathSourceModule), sourceCallableIdentifier)
|
|
669
740
|
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
670
741
|
|
|
671
|
-
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*
|
|
742
|
+
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
|
|
672
743
|
|
|
673
744
|
ingredientsFunction.imports.update(shatteredDataclass.imports)
|
|
674
745
|
ingredientsFunction.imports.addAst(astImportFrom)
|
|
675
746
|
targetCallableIdentifier = astImportFrom.names[0].name
|
|
676
747
|
ingredientsFunction = raiseIfNone(unpackDataclassCallFunctionRepackDataclass(ingredientsFunction, targetCallableIdentifier, shatteredDataclass))
|
|
677
748
|
targetFunctionDef: ast.FunctionDef = raiseIfNone(extractFunctionDef(parseLogicalPath2astModule(raiseIfNone(astImportFrom.module)), targetCallableIdentifier))
|
|
678
|
-
astTuple: ast.
|
|
679
|
-
|
|
749
|
+
astTuple: ast.Tuple = cast('ast.Tuple', raiseIfNone(NodeTourist[ast.Return, ast.expr | None](Be.Return.valueIs(Be.Tuple)
|
|
750
|
+
, doThat=Then.extractIt(DOT.value)).captureLastMatch(targetFunctionDef)))
|
|
751
|
+
astTuple.ctx = ast.Store()
|
|
680
752
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
753
|
+
changeAssignCallToTarget = NodeChanger(
|
|
754
|
+
findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
|
|
755
|
+
, doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts))))
|
|
756
|
+
changeAssignCallToTarget.visit(ingredientsFunction.astFunctionDef)
|
|
684
757
|
|
|
685
758
|
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
686
759
|
ingredientsModule.removeImportFromModule('numpy')
|
|
687
760
|
|
|
688
761
|
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
689
762
|
|
|
690
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.
|
|
763
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
691
764
|
|
|
692
765
|
if __name__ == '__main__':
|
|
693
|
-
astModule: ast.Module =
|
|
766
|
+
astModule: ast.Module = _getModule(logicalPathInfix=None)
|
|
694
767
|
makeInitializeGroupsOfFolds(astModule, 'initializeCount', 'initializeGroupsOfFolds', logicalPathInfixDEFAULT)
|
|
695
768
|
|
|
696
|
-
astModule =
|
|
769
|
+
astModule = _getModule(logicalPathInfix=None)
|
|
697
770
|
pathFilename: PurePath = makeDaoOfMapFolding(astModule, 'daoOfMapFolding', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
|
|
698
771
|
|
|
699
|
-
astModule =
|
|
772
|
+
astModule = _getModule(logicalPathInfix=None)
|
|
700
773
|
pathFilename = makeDaoOfMapFoldingParallel(astModule, 'countParallel', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
|
|
701
774
|
|
|
702
|
-
astModule =
|
|
775
|
+
astModule = _getModule(logicalPathInfix=None)
|
|
703
776
|
pathFilename = makeTheorem2(astModule, 'theorem2', None, logicalPathInfixDEFAULT, None)
|
|
704
777
|
|
|
705
778
|
astModule = parsePathFilename2astModule(pathFilename)
|
|
@@ -708,5 +781,5 @@ if __name__ == '__main__':
|
|
|
708
781
|
astModule = parsePathFilename2astModule(pathFilename)
|
|
709
782
|
pathFilename = numbaOnTheorem2(astModule, 'theorem2Numba', None, logicalPathInfixDEFAULT, None)
|
|
710
783
|
|
|
711
|
-
astImportFrom: ast.ImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.
|
|
784
|
+
astImportFrom: ast.ImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.identifierPackage, logicalPathInfixDEFAULT, 'theorem2Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
|
|
712
785
|
makeUnRePackDataclass(astImportFrom)
|