mapFolding 0.15.4__py3-none-any.whl → 0.16.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. easyRun/A000682.py +25 -0
  2. easyRun/A005316.py +21 -0
  3. easyRun/NOTcountingFolds.py +36 -0
  4. easyRun/__init__.py +0 -0
  5. easyRun/countFolds.py +41 -0
  6. easyRun/meanders.py +71 -0
  7. mapFolding/__init__.py +10 -55
  8. mapFolding/_dataPacking.py +68 -0
  9. mapFolding/_theSSOT.py +33 -36
  10. mapFolding/_theTypes.py +21 -4
  11. mapFolding/algorithms/daoOfMapFolding.py +1 -2
  12. mapFolding/algorithms/matrixMeanders.py +101 -348
  13. mapFolding/algorithms/matrixMeandersBeDry.py +264 -0
  14. mapFolding/algorithms/matrixMeandersNumPy.py +286 -0
  15. mapFolding/algorithms/matrixMeandersPandas.py +351 -0
  16. mapFolding/algorithms/oeisIDbyFormula.py +320 -76
  17. mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +92 -0
  18. mapFolding/basecamp.py +261 -113
  19. mapFolding/beDRY.py +2 -30
  20. mapFolding/dataBaskets.py +120 -4
  21. mapFolding/oeis.py +13 -33
  22. mapFolding/reference/A000682facts.py +1276 -0
  23. mapFolding/reference/A005316facts.py +985 -0
  24. mapFolding/reference/matrixMeandersAnalysis/__init__.py +1 -0
  25. mapFolding/reference/matrixMeandersAnalysis/prefixNotationNotes.py +15 -0
  26. mapFolding/reference/meandersDumpingGround/A005316JavaPort.py +1 -1
  27. mapFolding/reference/meandersDumpingGround/A005316imperative.py +1 -1
  28. mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +424 -0
  29. mapFolding/someAssemblyRequired/A007822/A007822rawMaterials.py +54 -0
  30. mapFolding/someAssemblyRequired/A007822/__init__.py +0 -0
  31. mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +197 -0
  32. mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +74 -0
  33. mapFolding/someAssemblyRequired/RecipeJob.py +4 -4
  34. mapFolding/someAssemblyRequired/__init__.py +9 -2
  35. mapFolding/someAssemblyRequired/_toolIfThis.py +4 -3
  36. mapFolding/someAssemblyRequired/_toolkitContainers.py +8 -8
  37. mapFolding/someAssemblyRequired/infoBooth.py +27 -30
  38. mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +6 -5
  39. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +6 -4
  40. mapFolding/someAssemblyRequired/makingModules_count.py +294 -0
  41. mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +117 -0
  42. mapFolding/someAssemblyRequired/mapFolding/__init__.py +0 -0
  43. mapFolding/someAssemblyRequired/mapFolding/makeMapFoldingModules.py +220 -0
  44. mapFolding/someAssemblyRequired/meanders/__init__.py +0 -0
  45. mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +64 -0
  46. mapFolding/someAssemblyRequired/toolkitMakeModules.py +152 -0
  47. mapFolding/someAssemblyRequired/toolkitNumba.py +1 -1
  48. mapFolding/someAssemblyRequired/transformationTools.py +1 -0
  49. mapFolding/syntheticModules/A007822/__init__.py +1 -0
  50. mapFolding/syntheticModules/{algorithmA007822.py → A007822/algorithm.py} +2 -3
  51. mapFolding/syntheticModules/{algorithmA007822Numba.py → A007822/algorithmNumba.py} +3 -6
  52. mapFolding/syntheticModules/A007822/asynchronous.py +148 -0
  53. mapFolding/syntheticModules/A007822/asynchronousAnnex.py +66 -0
  54. mapFolding/syntheticModules/A007822/asynchronousAnnexNumba.py +85 -0
  55. mapFolding/syntheticModules/A007822/asynchronousNumba.py +52 -0
  56. mapFolding/syntheticModules/A007822/asynchronousTheorem2.py +53 -0
  57. mapFolding/syntheticModules/A007822/asynchronousTrimmed.py +47 -0
  58. mapFolding/syntheticModules/{initializeStateA007822.py → A007822/initializeState.py} +1 -2
  59. mapFolding/syntheticModules/{theorem2A007822.py → A007822/theorem2.py} +1 -2
  60. mapFolding/syntheticModules/{theorem2A007822Numba.py → A007822/theorem2Numba.py} +6 -4
  61. mapFolding/syntheticModules/{theorem2A007822Trimmed.py → A007822/theorem2Trimmed.py} +1 -2
  62. mapFolding/syntheticModules/countParallelNumba.py +5 -2
  63. mapFolding/syntheticModules/daoOfMapFoldingNumba.py +4 -2
  64. mapFolding/syntheticModules/dataPacking.py +4 -2
  65. mapFolding/syntheticModules/dataPackingA007822.py +92 -26
  66. mapFolding/syntheticModules/meanders/__init__.py +1 -0
  67. mapFolding/syntheticModules/meanders/bigInt.py +62 -0
  68. mapFolding/syntheticModules/theorem2Numba.py +3 -2
  69. mapFolding/tests/conftest.py +28 -13
  70. mapFolding/tests/test_computations.py +69 -62
  71. mapFolding/tests/test_oeis.py +6 -6
  72. mapFolding/zCuzDocStoopid/__init__.py +4 -0
  73. mapFolding/zCuzDocStoopid/makeDocstrings.py +68 -0
  74. mapfolding-0.16.1.dist-info/METADATA +99 -0
  75. mapfolding-0.16.1.dist-info/RECORD +114 -0
  76. {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/top_level.txt +1 -0
  77. mapFolding/someAssemblyRequired/A007822rawMaterials.py +0 -46
  78. mapFolding/someAssemblyRequired/makeAllModules.py +0 -764
  79. mapfolding-0.15.4.dist-info/METADATA +0 -78
  80. mapfolding-0.15.4.dist-info/RECORD +0 -78
  81. {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/WHEEL +0 -0
  82. {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/entry_points.txt +0 -0
  83. {mapfolding-0.15.4.dist-info → mapfolding-0.16.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,764 +0,0 @@
1
- """
2
- Map folding AST transformation system: Comprehensive transformation orchestration and module generation.
3
-
4
- This module provides the orchestration layer of the map folding AST transformation system,
5
- implementing comprehensive tools that coordinate all transformation stages to generate optimized
6
- implementations with diverse computational strategies and performance characteristics. Building
7
- upon the foundational pattern recognition, structural decomposition, core transformation tools,
8
- Numba integration, and configuration management established in previous layers, this module
9
- executes complete transformation processes that convert high-level dataclass-based algorithms
10
- into specialized variants optimized for specific execution contexts.
11
-
12
- The transformation orchestration addresses the full spectrum of optimization requirements for
13
- map folding computational research through systematic application of the complete transformation
14
- toolkit. The comprehensive approach decomposes dataclass parameters into primitive values for
15
- Numba compatibility while removing object-oriented overhead and preserving computational logic,
16
- generates concurrent execution variants using ProcessPoolExecutor with task division and result
17
- aggregation, creates dedicated modules for counting variable setup with transformed loop conditions,
18
- and provides theorem-specific transformations with configurable optimization levels including
19
- trimmed variants and Numba-accelerated implementations.
20
-
21
- The orchestration process operates through systematic AST manipulation that analyzes source
22
- algorithms to extract dataclass dependencies, transforms data access patterns, applies performance
23
- optimizations, and generates specialized modules with consistent naming conventions and filesystem
24
- organization. The comprehensive transformation process coordinates pattern recognition for structural
25
- analysis, dataclass decomposition for parameter optimization, function transformation for signature
26
- adaptation, Numba integration for compilation optimization, and configuration management for
27
- systematic generation control.
28
-
29
- Generated modules maintain algorithmic correctness while providing significant performance
30
- improvements through just-in-time compilation, parallel execution, and optimized data structures
31
- tailored for specific computational requirements essential to large-scale map folding research.
32
- """
33
-
34
- from astToolkit import (
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
40
- from mapFolding import packageSettings
41
- from mapFolding.someAssemblyRequired import (
42
- dataclassInstanceIdentifierDEFAULT, DeReConstructField2ast, IfThis, ShatteredDataclass,
43
- sourceCallableDispatcherDEFAULT)
44
- from mapFolding.someAssemblyRequired.A007822rawMaterials import (
45
- FunctionDef_filterAsymmetricFolds, Z0Z_adjustFoldsTotal, Z0Z_incrementCount)
46
- from mapFolding.someAssemblyRequired.infoBooth import (
47
- algorithmSourceModuleDEFAULT, dataPackingModuleIdentifierDEFAULT, logicalPathInfixDEFAULT,
48
- sourceCallableIdentifierDEFAULT, theCountingIdentifierDEFAULT)
49
- from mapFolding.someAssemblyRequired.toolkitNumba import decorateCallableWithNumba, parametersNumbaLight
50
- from mapFolding.someAssemblyRequired.transformationTools import (
51
- removeDataclassFromFunction, shatter_dataclassesDOTdataclass, unpackDataclassCallFunctionRepackDataclass)
52
- from os import PathLike
53
- from pathlib import PurePath
54
- from typing import Any, cast, TYPE_CHECKING
55
- import ast
56
- import dataclasses
57
-
58
- if TYPE_CHECKING:
59
- from collections.abc import Sequence
60
-
61
- def _findDataclass(ingredientsFunction: IngredientsFunction) -> tuple[str, str, str]:
62
- """Extract dataclass information from a function's AST for transformation operations.
63
-
64
- (AI generated docstring)
65
-
66
- Analyzes the first parameter of a function to identify the dataclass type annotation
67
- and instance identifier, then locates the module where the dataclass is defined by
68
- examining the function's import statements. This information is essential for
69
- dataclass decomposition and transformation operations.
70
-
71
- Parameters
72
- ----------
73
- ingredientsFunction : IngredientsFunction
74
- Function container with AST and import information.
75
-
76
- Returns
77
- -------
78
- dataclassLogicalPathModule : str
79
- Module logical path where the dataclass is defined.
80
- dataclassIdentifier : str
81
- Class name of the dataclass.
82
- dataclassInstanceIdentifier : str
83
- Parameter name for the dataclass instance.
84
-
85
- Raises
86
- ------
87
- ValueError
88
- If dataclass information cannot be extracted from the function.
89
-
90
- """
91
- dataclassName: ast.expr = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.annotation)).captureLastMatch(ingredientsFunction.astFunctionDef))
92
- dataclassIdentifier: str = raiseIfNone(NodeTourist(Be.Name, Then.extractIt(DOT.id)).captureLastMatch(dataclassName))
93
- dataclassLogicalPathModule = None
94
- for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports._dictionaryImportFrom.items(): # noqa: SLF001
95
- for nameTuple in listNameTuples:
96
- if nameTuple[0] == dataclassIdentifier:
97
- dataclassLogicalPathModule = moduleWithLogicalPath
98
- break
99
- if dataclassLogicalPathModule:
100
- break
101
- dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
102
- return raiseIfNone(dataclassLogicalPathModule), dataclassIdentifier, dataclassInstanceIdentifier
103
-
104
- def _getLogicalPath(identifierPackage: str | None = None, logicalPathInfix: str | None = None, *moduleIdentifier: str | None) -> identifierDotAttribute:
105
- listLogicalPathParts: list[str] = []
106
- if identifierPackage:
107
- listLogicalPathParts.append(identifierPackage)
108
- if logicalPathInfix:
109
- listLogicalPathParts.append(logicalPathInfix)
110
- if moduleIdentifier:
111
- listLogicalPathParts.extend([module for module in moduleIdentifier if module is not None])
112
- return '.'.join(listLogicalPathParts)
113
-
114
- def _getModule(identifierPackage: str | None = packageSettings.identifierPackage, logicalPathInfix: str | None = logicalPathInfixDEFAULT, moduleIdentifier: str | None = algorithmSourceModuleDEFAULT) -> ast.Module:
115
- logicalPathSourceModule: identifierDotAttribute = _getLogicalPath(identifierPackage, logicalPathInfix, moduleIdentifier)
116
- astModule: ast.Module = parseLogicalPath2astModule(logicalPathSourceModule)
117
- return astModule
118
-
119
- def _getPathFilename(pathRoot: PathLike[str] | PurePath | None = packageSettings.pathPackage, logicalPathInfix: PathLike[str] | PurePath | str | None = None, moduleIdentifier: str = '', fileExtension: str = packageSettings.fileExtension) -> PurePath:
120
- """Construct filesystem path for generated module files.
121
-
122
- (AI generated docstring)
123
-
124
- Builds the complete filesystem path where generated modules will be written,
125
- combining root path, optional infix directory, module name, and file extension.
126
- This ensures consistent file organization across all generated code.
127
-
128
- Parameters
129
- ----------
130
- pathRoot : PathLike[str] | PurePath | None = packageSettings.pathPackage
131
- Base directory for the package structure.
132
- logicalPathInfix : PathLike[str] | PurePath | str | None = None
133
- Subdirectory for organizing generated modules.
134
- moduleIdentifier : str = ''
135
- Name of the specific module file.
136
- fileExtension : str = packageSettings.fileExtension
137
- File extension for Python modules.
138
-
139
- Returns
140
- -------
141
- pathFilename : PurePath
142
- Complete filesystem path for the generated module file.
143
-
144
- """
145
- pathFilename = PurePath(moduleIdentifier + fileExtension)
146
- if logicalPathInfix:
147
- pathFilename = PurePath(logicalPathInfix, pathFilename)
148
- if pathRoot:
149
- pathFilename = PurePath(pathRoot, pathFilename)
150
- return pathFilename
151
-
152
- # TODO Where is the generalized form of these functions?!
153
-
154
- def addSymmetryCheck(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
155
- """Add logic to check for symmetric folds."""
156
- imports=LedgerOfImports(astModule)
157
-
158
- astFunctionDef_count: ast.FunctionDef = raiseIfNone(NodeTourist(
159
- findThis = Be.FunctionDef.nameIs(IfThis.isIdentifier(sourceCallableIdentifierDEFAULT))
160
- , doThat = Then.extractIt
161
- ).captureLastMatch(astModule))
162
-
163
- # NOTE 2025 August 7. I am SHOCKED to discover that `astFunctionDef_count: ast.FunctionDef` returned by `NodeTourist` (subclass of
164
- # `ast.NodeVisitor`) is a so-called mutable `object`!!!!!!
165
- # !!!!!! Using the mutability of `ast.AST` subclasses, makes `astToolkit` SIGNIFICANTLY more powerful and solves "obstacles" I
166
- # have been trying to overcome.
167
- # (Side note: fuck you, Python, for your idiotic paradigms around mutability, its documentation, its identifiers, and its types.)
168
-
169
- NodeChanger(Be.Return, Then.insertThisAbove([Z0Z_adjustFoldsTotal])).visit(astFunctionDef_count)
170
-
171
- NodeChanger(
172
- findThis=Be.AugAssign.targetIs(IfThis.isAttributeNamespaceIdentifier(dataclassInstanceIdentifierDEFAULT, theCountingIdentifierDEFAULT))
173
- , doThat=Then.replaceWith(Z0Z_incrementCount)
174
- ).visit(astFunctionDef_count)
175
-
176
- ingredientsFunction=IngredientsFunction(FunctionDef_filterAsymmetricFolds)
177
-
178
- NodeChanger(Be.ImportFrom, Then.removeIt).visit(astModule)
179
-
180
- ingredientsModule = IngredientsModule(ingredientsFunction=ingredientsFunction, epilogue=astModule, imports=imports)
181
-
182
- pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
183
-
184
- write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
185
-
186
- return pathFilename
187
-
188
- def makeDaoOfMapFoldingNumba(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
189
- """Generate Numba-optimized sequential implementation of map folding algorithm.
190
-
191
- (AI generated docstring)
192
-
193
- Creates a high-performance sequential version of the map folding algorithm by
194
- decomposing dataclass parameters into individual primitive values, removing
195
- dataclass dependencies that are incompatible with Numba, applying Numba
196
- decorators for just-in-time compilation, and optionally including a dispatcher
197
- function for dataclass integration.
198
-
199
- The generated module provides significant performance improvements over the
200
- original dataclass-based implementation while maintaining algorithmic correctness.
201
- The transformation preserves all computational logic while restructuring data
202
- access patterns for optimal Numba compilation.
203
-
204
- Parameters
205
- ----------
206
- astModule : ast.Module
207
- Source module containing the base algorithm.
208
- moduleIdentifier : str
209
- Name for the generated optimized module.
210
- callableIdentifier : str | None = None
211
- Name for the main computational function.
212
- logicalPathInfix : PathLike[str] | PurePath | str | None = None
213
- Directory path for organizing the generated module.
214
- sourceCallableDispatcher : str | None = None
215
- Optional dispatcher function for dataclass integration.
216
-
217
- Returns
218
- -------
219
- pathFilename : PurePath
220
- Filesystem path where the optimized module was written.
221
-
222
- """
223
- sourceCallableIdentifier: identifierDotAttribute = sourceCallableIdentifierDEFAULT
224
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
225
- ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
226
-
227
- shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
228
-
229
- ingredientsFunction.imports.update(shatteredDataclass.imports)
230
- ingredientsFunction: IngredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
231
- ingredientsFunction = removeUnusedParameters(ingredientsFunction)
232
- ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
233
-
234
- ingredientsModule = IngredientsModule(ingredientsFunction)
235
-
236
- if sourceCallableDispatcher is not None:
237
-
238
- ingredientsFunctionDispatcher: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableDispatcher)
239
- ingredientsFunctionDispatcher.imports.update(shatteredDataclass.imports)
240
- targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
241
- ingredientsFunctionDispatcher = unpackDataclassCallFunctionRepackDataclass(ingredientsFunctionDispatcher, targetCallableIdentifier, shatteredDataclass)
242
- astTuple: ast.Tuple = cast('ast.Tuple', raiseIfNone(NodeTourist(Be.Return.valueIs(Be.Tuple)
243
- , doThat=Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef)))
244
- astTuple.ctx = ast.Store()
245
-
246
- changeAssignCallToTarget = NodeChanger(
247
- findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
248
- , doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts))))
249
- changeAssignCallToTarget.visit(ingredientsFunctionDispatcher.astFunctionDef)
250
-
251
- ingredientsModule.appendIngredientsFunction(ingredientsFunctionDispatcher)
252
-
253
- ingredientsModule.removeImportFromModule('numpy')
254
-
255
- pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
256
-
257
- write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
258
-
259
- return pathFilename
260
-
261
- def makeDaoOfMapFoldingParallelNumba(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
262
- """Generate parallel implementation with concurrent execution and task division.
263
-
264
- Parameters
265
- ----------
266
- astModule : ast.Module
267
- Source module containing the base algorithm.
268
- moduleIdentifier : str
269
- Name for the generated parallel module.
270
- callableIdentifier : str | None = None
271
- Name for the core parallel counting 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 identifier.
276
-
277
- Returns
278
- -------
279
- pathFilename : PurePath
280
- Filesystem path where the parallel module was written.
281
-
282
- """
283
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
284
- if callableIdentifier is None:
285
- callableIdentifier = sourceCallableIdentifier
286
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
287
- ingredientsFunction.astFunctionDef.name = callableIdentifier
288
-
289
- dataclassName: ast.expr = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.annotation)).captureLastMatch(ingredientsFunction.astFunctionDef))
290
- dataclassIdentifier: str = raiseIfNone(NodeTourist(Be.Name, Then.extractIt(DOT.id)).captureLastMatch(dataclassName))
291
-
292
- dataclassLogicalPathModule = None
293
- for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports._dictionaryImportFrom.items(): # noqa: SLF001
294
- for nameTuple in listNameTuples:
295
- if nameTuple[0] == dataclassIdentifier:
296
- dataclassLogicalPathModule = moduleWithLogicalPath
297
- break
298
- if dataclassLogicalPathModule:
299
- break
300
- if dataclassLogicalPathModule is None:
301
- raise Exception # noqa: TRY002
302
- dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
303
- shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(dataclassLogicalPathModule, dataclassIdentifier, dataclassInstanceIdentifier)
304
-
305
- # START add the parallel state fields to the count function ------------------------------------------------
306
- dataclassBaseFields: tuple[dataclasses.Field[Any], ...] = dataclasses.fields(importLogicalPath2Identifier(dataclassLogicalPathModule, dataclassIdentifier)) # pyright: ignore [reportArgumentType]
307
- dataclassIdentifierParallel: identifierDotAttribute = 'Parallel' + dataclassIdentifier
308
- dataclassFieldsParallel: tuple[dataclasses.Field[Any], ...] = dataclasses.fields(importLogicalPath2Identifier(dataclassLogicalPathModule, dataclassIdentifierParallel)) # pyright: ignore [reportArgumentType]
309
- onlyParallelFields: list[dataclasses.Field[Any]] = [field for field in dataclassFieldsParallel if field.name not in [fieldBase.name for fieldBase in dataclassBaseFields]]
310
-
311
- Official_fieldOrder: list[str] = []
312
- dictionaryDeReConstruction: dict[str, DeReConstructField2ast] = {}
313
-
314
- dataclassClassDef: ast.ClassDef | None = extractClassDef(parseLogicalPath2astModule(dataclassLogicalPathModule), dataclassIdentifierParallel)
315
- if not dataclassClassDef:
316
- message = f"I could not find `{dataclassIdentifierParallel = }` in `{dataclassLogicalPathModule = }`."
317
- raise ValueError(message)
318
-
319
- for aField in onlyParallelFields:
320
- Official_fieldOrder.append(aField.name)
321
- dictionaryDeReConstruction[aField.name] = DeReConstructField2ast(dataclassLogicalPathModule, dataclassClassDef, dataclassInstanceIdentifier, aField)
322
-
323
- shatteredDataclassParallel = ShatteredDataclass(
324
- countingVariableAnnotation=shatteredDataclass.countingVariableAnnotation,
325
- countingVariableName=shatteredDataclass.countingVariableName,
326
- field2AnnAssign={**shatteredDataclass.field2AnnAssign, **{dictionaryDeReConstruction[field].name: dictionaryDeReConstruction[field].astAnnAssignConstructor for field in Official_fieldOrder}},
327
- Z0Z_field2AnnAssign={**shatteredDataclass.Z0Z_field2AnnAssign, **{dictionaryDeReConstruction[field].name: dictionaryDeReConstruction[field].Z0Z_hack for field in Official_fieldOrder}},
328
- list_argAnnotated4ArgumentsSpecification=shatteredDataclass.list_argAnnotated4ArgumentsSpecification + [dictionaryDeReConstruction[field].ast_argAnnotated for field in Official_fieldOrder],
329
- list_keyword_field__field4init=shatteredDataclass.list_keyword_field__field4init + [dictionaryDeReConstruction[field].ast_keyword_field__field for field in Official_fieldOrder if dictionaryDeReConstruction[field].init],
330
- listAnnotations=shatteredDataclass.listAnnotations + [dictionaryDeReConstruction[field].astAnnotation for field in Official_fieldOrder],
331
- listName4Parameters=shatteredDataclass.listName4Parameters + [dictionaryDeReConstruction[field].astName for field in Official_fieldOrder],
332
- listUnpack=shatteredDataclass.listUnpack + [Make.AnnAssign(dictionaryDeReConstruction[field].astName, dictionaryDeReConstruction[field].astAnnotation, dictionaryDeReConstruction[field].ast_nameDOTname) for field in Official_fieldOrder],
333
- map_stateDOTfield2Name={**shatteredDataclass.map_stateDOTfield2Name, **{dictionaryDeReConstruction[field].ast_nameDOTname: dictionaryDeReConstruction[field].astName for field in Official_fieldOrder}},
334
- )
335
- shatteredDataclassParallel.fragments4AssignmentOrParameters = Make.Tuple(shatteredDataclassParallel.listName4Parameters, ast.Store())
336
- shatteredDataclassParallel.repack = Make.Assign([Make.Name(dataclassInstanceIdentifier)], value=Make.Call(Make.Name(dataclassIdentifierParallel), list_keyword=shatteredDataclassParallel.list_keyword_field__field4init))
337
- shatteredDataclassParallel.signatureReturnAnnotation = Make.Subscript(Make.Name('tuple'), Make.Tuple(shatteredDataclassParallel.listAnnotations))
338
-
339
- shatteredDataclassParallel.imports.update(*(dictionaryDeReConstruction[field].ledger for field in Official_fieldOrder))
340
- shatteredDataclassParallel.imports.addImportFrom_asStr(dataclassLogicalPathModule, dataclassIdentifierParallel)
341
- shatteredDataclassParallel.imports.update(shatteredDataclass.imports)
342
- shatteredDataclassParallel.imports.removeImportFrom(dataclassLogicalPathModule, dataclassIdentifier)
343
-
344
- # END add the parallel state fields to the count function ------------------------------------------------
345
-
346
- ingredientsFunction.imports.update(shatteredDataclassParallel.imports)
347
- ingredientsFunction: IngredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclassParallel)
348
-
349
- # START add the parallel logic to the count function ------------------------------------------------
350
-
351
- findThis = Be.While.testIs(Be.Compare.leftIs(IfThis.isNameIdentifier('leafConnectee')))
352
- captureCountGapsCodeBlock: NodeTourist[ast.While, Sequence[ast.stmt]] = NodeTourist(findThis, doThat = Then.extractIt(DOT.body))
353
- countGapsCodeBlock: Sequence[ast.stmt] = raiseIfNone(captureCountGapsCodeBlock.captureLastMatch(ingredientsFunction.astFunctionDef))
354
-
355
- thisIsMyTaskIndexCodeBlock = ast.If(ast.BoolOp(ast.Or()
356
- , values=[ast.Compare(ast.Name('leaf1ndex'), ops=[ast.NotEq()], comparators=[ast.Name('taskDivisions')])
357
- , ast.Compare(Make.Mod.join([ast.Name('leafConnectee'), ast.Name('taskDivisions')]), ops=[ast.Eq()], comparators=[ast.Name('taskIndex')])])
358
- , body=list(countGapsCodeBlock[0:-1]))
359
-
360
- countGapsCodeBlockNew: list[ast.stmt] = [thisIsMyTaskIndexCodeBlock, countGapsCodeBlock[-1]]
361
- NodeChanger[ast.While, hasDOTbody](findThis, doThat = Grab.bodyAttribute(Then.replaceWith(countGapsCodeBlockNew))).visit(ingredientsFunction.astFunctionDef)
362
-
363
- # END add the parallel logic to the count function ------------------------------------------------
364
-
365
- ingredientsFunction = removeUnusedParameters(ingredientsFunction)
366
-
367
- ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
368
-
369
- # START unpack/repack the dataclass function ------------------------------------------------
370
- sourceCallableIdentifier = sourceCallableDispatcherDEFAULT
371
-
372
- unRepackDataclass: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableIdentifier)
373
- unRepackDataclass.astFunctionDef.name = 'unRepack' + dataclassIdentifierParallel
374
- unRepackDataclass.imports.update(shatteredDataclassParallel.imports)
375
- NodeChanger(
376
- findThis = Be.arg.annotationIs(Be.Name.idIs(lambda thisAttribute: thisAttribute == dataclassIdentifier)) # pyright: ignore[reportArgumentType]
377
- , doThat = Grab.annotationAttribute(Grab.idAttribute(Then.replaceWith(dataclassIdentifierParallel)))
378
- ).visit(unRepackDataclass.astFunctionDef)
379
- unRepackDataclass.astFunctionDef.returns = Make.Name(dataclassIdentifierParallel)
380
- targetCallableIdentifier: identifierDotAttribute = ingredientsFunction.astFunctionDef.name
381
- unRepackDataclass = unpackDataclassCallFunctionRepackDataclass(unRepackDataclass, targetCallableIdentifier, shatteredDataclassParallel)
382
-
383
- astTuple: ast.Tuple = raiseIfNone(NodeTourist[ast.Return, ast.Tuple](Be.Return, Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef)) # pyright: ignore[reportArgumentType]
384
- astTuple.ctx = ast.Store()
385
- changeAssignCallToTarget: NodeChanger[ast.Assign, ast.Assign] = NodeChanger(
386
- findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
387
- , doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts)))
388
- )
389
- changeAssignCallToTarget.visit(unRepackDataclass.astFunctionDef)
390
-
391
- ingredientsDoTheNeedful: IngredientsFunction = IngredientsFunction(
392
- astFunctionDef = Make.FunctionDef('doTheNeedful'
393
- , argumentSpecification=Make.arguments(list_arg=[Make.arg('state', annotation=Make.Name(dataclassIdentifierParallel)), Make.arg('concurrencyLimit', annotation=Make.Name('int'))])
394
- , body=[Make.Assign([Make.Name('stateParallel', ast.Store())], value=Make.Call(Make.Name('deepcopy'), listParameters=[Make.Name('state')]))
395
- , Make.AnnAssign(Make.Name('listStatesParallel', ast.Store()), annotation=Make.Subscript(value=Make.Name('list'), slice=Make.Name(dataclassIdentifierParallel))
396
- , value=Make.Mult.join([Make.List([Make.Name('stateParallel')]), Make.Attribute(Make.Name('stateParallel'), 'taskDivisions')]))
397
- , Make.AnnAssign(Make.Name('groupsOfFoldsTotal', ast.Store()), annotation=Make.Name('int'), value=Make.Constant(value=0))
398
-
399
- , Make.AnnAssign(Make.Name('dictionaryConcurrency', ast.Store()), annotation=Make.Subscript(value=Make.Name('dict'), slice=Make.Tuple([Make.Name('int'), Make.Subscript(value=Make.Name('ConcurrentFuture'), slice=Make.Name(dataclassIdentifierParallel))])), value=Make.Dict())
400
- , Make.With(items=[Make.withitem(context_expr=Make.Call(Make.Name('ProcessPoolExecutor'), listParameters=[Make.Name('concurrencyLimit')]), optional_vars=Make.Name('concurrencyManager', ast.Store()))]
401
- , body=[Make.For(Make.Name('indexSherpa', ast.Store()), iter=Make.Call(Make.Name('range'), listParameters=[Make.Attribute(Make.Name('stateParallel'), 'taskDivisions')])
402
- , body=[Make.Assign([Make.Name('state', ast.Store())], value=Make.Call(Make.Name('deepcopy'), listParameters=[Make.Name('stateParallel')]))
403
- , Make.Assign([Make.Attribute(Make.Name('state'), 'taskIndex', context=ast.Store())], value=Make.Name('indexSherpa'))
404
- , Make.Assign([Make.Subscript(Make.Name('dictionaryConcurrency'), slice=Make.Name('indexSherpa'), context=ast.Store())], value=Make.Call(Make.Attribute(Make.Name('concurrencyManager'), 'submit'), listParameters=[Make.Name(unRepackDataclass.astFunctionDef.name), Make.Name('state')]))])
405
- , Make.For(Make.Name('indexSherpa', ast.Store()), iter=Make.Call(Make.Name('range'), listParameters=[Make.Attribute(Make.Name('stateParallel'), 'taskDivisions')])
406
- , body=[Make.Assign([Make.Subscript(Make.Name('listStatesParallel'), slice=Make.Name('indexSherpa'), context=ast.Store())], value=Make.Call(Make.Attribute(Make.Subscript(Make.Name('dictionaryConcurrency'), slice=Make.Name('indexSherpa')), 'result')))
407
- , Make.AugAssign(Make.Name('groupsOfFoldsTotal', ast.Store()), op=ast.Add(), value=Make.Attribute(Make.Subscript(Make.Name('listStatesParallel'), slice=Make.Name('indexSherpa')), 'groupsOfFolds'))])])
408
-
409
- , Make.AnnAssign(Make.Name('foldsTotal', ast.Store()), annotation=Make.Name('int'), value=Make.Mult.join([Make.Name('groupsOfFoldsTotal'), Make.Attribute(Make.Name('stateParallel'), 'leavesTotal')]))
410
- , Make.Return(Make.Tuple([Make.Name('foldsTotal'), Make.Name('listStatesParallel')]))]
411
- , returns=Make.Subscript(Make.Name('tuple'), slice=Make.Tuple([Make.Name('int'), Make.Subscript(Make.Name('list'), slice=Make.Name(dataclassIdentifierParallel))])))
412
- , imports = LedgerOfImports(Make.Module([Make.ImportFrom('concurrent.futures', list_alias=[Make.alias('Future', asName='ConcurrentFuture'), Make.alias('ProcessPoolExecutor')]),
413
- Make.ImportFrom('copy', list_alias=[Make.alias('deepcopy')]),
414
- Make.ImportFrom('multiprocessing', list_alias=[Make.alias('set_start_method', asName='multiprocessing_set_start_method')])])
415
- )
416
- )
417
-
418
- ingredientsModule = IngredientsModule([ingredientsFunction, unRepackDataclass, ingredientsDoTheNeedful]
419
- , prologue = Make.Module([Make.If(test=Make.Compare(left=Make.Name('__name__'), ops=[Make.Eq()], comparators=[Make.Constant('__main__')]), body=[Make.Expr(Make.Call(Make.Name('multiprocessing_set_start_method'), listParameters=[Make.Constant('spawn')]))])])
420
- )
421
- ingredientsModule.removeImportFromModule('numpy')
422
-
423
- pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
424
-
425
- write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
426
-
427
- return pathFilename
428
-
429
- def makeInitializeState(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
430
- """Generate initialization module for counting variable setup.
431
-
432
- (AI generated docstring)
433
-
434
- Creates a specialized module containing initialization logic for the counting variables
435
- used in map folding computations. The generated function transforms the original
436
- algorithm's loop conditions to use equality comparisons instead of greater-than
437
- comparisons, optimizing the initialization phase.
438
-
439
- This transformation is particularly important for ensuring that counting variables
440
- are properly initialized before the main computational loops begin executing.
441
-
442
- Parameters
443
- ----------
444
- astModule : ast.Module
445
- Source module containing the base algorithm.
446
- moduleIdentifier : str
447
- Name for the generated initialization module.
448
- callableIdentifier : str | None = None
449
- Name for the initialization function.
450
- logicalPathInfix : PathLike[str] | PurePath | str | None = None
451
- Directory path for organizing the generated module.
452
- sourceCallableDispatcher : str | None = None
453
- Optional dispatcher function identifier.
454
-
455
- Returns
456
- -------
457
- pathFilename : PurePath
458
- Filesystem path where the initialization module was written.
459
-
460
- """
461
- sourceCallableIdentifier: identifierDotAttribute = sourceCallableIdentifierDEFAULT
462
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
463
- ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
464
-
465
- dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
466
- theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
467
-
468
- findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
469
- doThat = Grab.testAttribute(Grab.andDoAllOf([Grab.opsAttribute(Then.replaceWith([ast.Eq()])), Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier)))]))
470
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef.body[0])
471
-
472
- pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
473
- write_astModule(IngredientsModule(ingredientsFunction), pathFilename, packageSettings.identifierPackage)
474
-
475
- return pathFilename
476
-
477
- def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
478
- """Generate module by applying optimization predicted by Theorem 2.
479
-
480
- Parameters
481
- ----------
482
- astModule : ast.Module
483
- Source module containing the base algorithm.
484
- moduleIdentifier : str
485
- Name for the generated theorem-optimized module.
486
- callableIdentifier : str | None = None
487
- Name for the optimized computational function.
488
- logicalPathInfix : PathLike[str] | PurePath | str | None = None
489
- Directory path for organizing the generated module.
490
- sourceCallableDispatcher : str | None = None
491
- Currently not implemented for this transformation.
492
-
493
- Returns
494
- -------
495
- pathFilename : PurePath
496
- Filesystem path where the theorem-optimized module was written.
497
-
498
- Raises
499
- ------
500
- NotImplementedError
501
- If `sourceCallableDispatcher` is provided.
502
-
503
- """
504
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
505
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
506
- ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
507
-
508
- dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
509
-
510
- theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
511
- doubleTheCount: ast.AugAssign = Make.AugAssign(Make.Attribute(Make.Name(dataclassInstanceIdentifier), theCountingIdentifier), Make.Mult(), Make.Constant(2))
512
-
513
- NodeChanger(
514
- findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
515
- , doThat = Grab.orelseAttribute(Then.replaceWith([doubleTheCount]))
516
- ).visit(ingredientsFunction.astFunctionDef)
517
-
518
- NodeChanger(
519
- findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
520
- , doThat = Grab.testAttribute(Grab.comparatorsAttribute(Then.replaceWith([Make.Constant(4)])))
521
- ).visit(ingredientsFunction.astFunctionDef)
522
-
523
- insertLeaf = NodeTourist(
524
- findThis = IfThis.isIfAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
525
- , doThat = Then.extractIt(DOT.body)
526
- ).captureLastMatch(ingredientsFunction.astFunctionDef)
527
- NodeChanger(
528
- findThis = IfThis.isIfAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
529
- , doThat = Then.replaceWith(insertLeaf)
530
- ).visit(ingredientsFunction.astFunctionDef)
531
-
532
- NodeChanger(
533
- findThis = IfThis.isAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
534
- , doThat = Then.removeIt
535
- ).visit(ingredientsFunction.astFunctionDef)
536
-
537
- NodeChanger(
538
- findThis = IfThis.isAttributeNamespaceIdentifierLessThanOrEqual0(dataclassInstanceIdentifier, 'leaf1ndex')
539
- , doThat = Then.removeIt
540
- ).visit(ingredientsFunction.astFunctionDef)
541
-
542
- ingredientsModule = IngredientsModule(ingredientsFunction)
543
-
544
- if sourceCallableDispatcher is not None:
545
- message = 'sourceCallableDispatcher is not implemented yet'
546
- raise NotImplementedError(message)
547
-
548
- pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
549
-
550
- write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
551
-
552
- return pathFilename
553
-
554
- def makeUnRePackDataclass(astImportFrom: ast.ImportFrom, moduleIdentifier: identifierDotAttribute = dataPackingModuleIdentifierDEFAULT) -> None:
555
- """Generate interface module for dataclass unpacking and repacking operations.
556
-
557
- Parameters
558
- ----------
559
- astImportFrom : ast.ImportFrom
560
- Import statement specifying the target optimized function to call.
561
-
562
- Returns
563
- -------
564
- None
565
- The generated module is written directly to the filesystem.
566
-
567
- """
568
- callableIdentifierHARDCODED: str = 'sequential'
569
-
570
- algorithmSourceModule: identifierDotAttribute = algorithmSourceModuleDEFAULT
571
- sourceCallableIdentifier: identifierDotAttribute = sourceCallableDispatcherDEFAULT
572
- logicalPathSourceModule: identifierDotAttribute = '.'.join([packageSettings.identifierPackage, algorithmSourceModule]) # noqa: FLY002
573
-
574
- logicalPathInfix: identifierDotAttribute = logicalPathInfixDEFAULT
575
- callableIdentifier: identifierDotAttribute = callableIdentifierHARDCODED
576
-
577
- ingredientsFunction: IngredientsFunction = astModuleToIngredientsFunction(parseLogicalPath2astModule(logicalPathSourceModule), sourceCallableIdentifier)
578
- ingredientsFunction.astFunctionDef.name = callableIdentifier
579
-
580
- shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
581
-
582
- ingredientsFunction.imports.update(shatteredDataclass.imports)
583
- ingredientsFunction.imports.addAst(astImportFrom)
584
- targetCallableIdentifier = astImportFrom.names[0].name
585
- ingredientsFunction = raiseIfNone(unpackDataclassCallFunctionRepackDataclass(ingredientsFunction, targetCallableIdentifier, shatteredDataclass))
586
- targetFunctionDef: ast.FunctionDef = raiseIfNone(extractFunctionDef(parseLogicalPath2astModule(raiseIfNone(astImportFrom.module)), targetCallableIdentifier))
587
- astTuple: ast.Tuple = cast('ast.Tuple', raiseIfNone(NodeTourist(Be.Return.valueIs(Be.Tuple)
588
- , doThat=Then.extractIt(DOT.value)).captureLastMatch(targetFunctionDef)))
589
- astTuple.ctx = ast.Store()
590
-
591
- changeAssignCallToTarget = NodeChanger(
592
- findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
593
- , doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts))))
594
- changeAssignCallToTarget.visit(ingredientsFunction.astFunctionDef)
595
-
596
- ingredientsModule = IngredientsModule(ingredientsFunction)
597
- ingredientsModule.removeImportFromModule('numpy')
598
-
599
- pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
600
-
601
- write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
602
-
603
- 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
604
- """Generate Numba-accelerated Theorem 2 implementation with dataclass decomposition.
605
-
606
- (AI generated docstring)
607
-
608
- Creates a highly optimized version of the Theorem 2 algorithm by combining the
609
- mathematical optimizations of Theorem 2 with Numba just-in-time compilation.
610
- The transformation includes dataclass decomposition to convert structured
611
- parameters into primitives, removal of Python object dependencies incompatible
612
- with Numba, application of Numba decorators for maximum performance, and type
613
- annotation optimization for efficient compilation.
614
-
615
- This represents the highest level of optimization available for Theorem 2
616
- implementations, providing both mathematical efficiency through theorem
617
- application and computational efficiency through Numba acceleration.
618
- The result is suitable for production use in high-performance computing
619
- environments where maximum speed is required.
620
-
621
- Parameters
622
- ----------
623
- astModule : ast.Module
624
- Source module containing the Theorem 2 implementation.
625
- moduleIdentifier : str
626
- Name for the generated Numba-accelerated module.
627
- callableIdentifier : str | None = None
628
- Name for the accelerated computational function.
629
- logicalPathInfix : PathLike[str] | PurePath | str | None = None
630
- Directory path for organizing the generated module.
631
- sourceCallableDispatcher : str | None = None
632
- Optional dispatcher function identifier (unused).
633
-
634
- Returns
635
- -------
636
- pathFilename : PurePath
637
- Filesystem path where the accelerated module was written.
638
-
639
- """
640
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
641
- if callableIdentifier is None:
642
- callableIdentifier = sourceCallableIdentifier
643
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
644
- ingredientsFunction.astFunctionDef.name = callableIdentifier
645
-
646
- shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
647
-
648
- ingredientsFunction.imports.update(shatteredDataclass.imports)
649
- ingredientsFunction: IngredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
650
- ingredientsFunction = removeUnusedParameters(ingredientsFunction)
651
- ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
652
-
653
- ingredientsModule = IngredientsModule(ingredientsFunction)
654
- ingredientsModule.removeImportFromModule('numpy')
655
-
656
- pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
657
-
658
- write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
659
-
660
- return pathFilename
661
-
662
- 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
663
- """Generate constrained Theorem 2 implementation by removing unnecessary logic.
664
-
665
- (AI generated docstring)
666
-
667
- Creates a trimmed version of the Theorem 2 implementation by eliminating conditional logic that is not needed under specific
668
- constraint assumptions. This transformation removes checks for unconstrained dimensions, simplifying the algorithm for cases
669
- where dimensional constraints are guaranteed to be satisfied by external conditions.
670
-
671
- The trimming operation is particularly valuable for generating lean implementations where the calling context ensures that
672
- certain conditions will always be met, allowing the removal of defensive programming constructs that add computational
673
- overhead without providing benefits in the constrained environment.
674
-
675
- Parameters
676
- ----------
677
- astModule : ast.Module
678
- Source module containing the Theorem 2 implementation.
679
- moduleIdentifier : str
680
- Name for the generated trimmed module.
681
- callableIdentifier : str | None = None
682
- Name for the trimmed computational function.
683
- logicalPathInfix : PathLike[str] | PurePath | str | None = None
684
- Directory path for organizing the generated module.
685
- sourceCallableDispatcher : str | None = None
686
- Optional dispatcher function identifier (unused).
687
-
688
- Returns
689
- -------
690
- pathFilename : PurePath
691
- Filesystem path where the trimmed module was written.
692
-
693
- """
694
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
695
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
696
- ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
697
-
698
- dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
699
-
700
- findThis = IfThis.isIfUnaryNotAttributeNamespaceIdentifier(dataclassInstanceIdentifier, 'dimensionsUnconstrained')
701
- doThat = Then.removeIt
702
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
703
-
704
- ingredientsModule = IngredientsModule(ingredientsFunction)
705
- ingredientsModule.removeImportFromModule('numpy')
706
-
707
- pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
708
-
709
- write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
710
-
711
- return pathFilename
712
-
713
- if __name__ == '__main__':
714
- astModule = _getModule(logicalPathInfix='algorithms')
715
- pathFilename: PurePath = makeDaoOfMapFoldingNumba(astModule, 'daoOfMapFoldingNumba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
716
-
717
- astModule = _getModule(logicalPathInfix='algorithms')
718
- pathFilename = makeDaoOfMapFoldingParallelNumba(astModule, 'countParallelNumba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
719
-
720
- astModule: ast.Module = _getModule(logicalPathInfix='algorithms')
721
- makeInitializeState(astModule, 'initializeState', 'transitionOnGroupsOfFolds', logicalPathInfixDEFAULT)
722
-
723
- astModule = _getModule(logicalPathInfix='algorithms')
724
- pathFilename = makeTheorem2(astModule, 'theorem2', None, logicalPathInfixDEFAULT, None)
725
-
726
- astModule = parsePathFilename2astModule(pathFilename)
727
- pathFilename = trimTheorem2(astModule, 'theorem2Trimmed', None, logicalPathInfixDEFAULT, None)
728
-
729
- astModule = parsePathFilename2astModule(pathFilename)
730
- pathFilename = numbaOnTheorem2(astModule, 'theorem2Numba', None, logicalPathInfixDEFAULT, None)
731
-
732
- astImportFrom: ast.ImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.identifierPackage, logicalPathInfixDEFAULT, 'theorem2Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
733
- makeUnRePackDataclass(astImportFrom)
734
-
735
- # A007822 -----------------------------------------------------------
736
- astModule = _getModule(logicalPathInfix='algorithms')
737
- pathFilename = addSymmetryCheck(astModule, 'algorithmA007822', None, logicalPathInfixDEFAULT, None)
738
-
739
- astModule = _getModule(moduleIdentifier='algorithmA007822')
740
- pathFilename: PurePath = makeDaoOfMapFoldingNumba(astModule, 'algorithmA007822Numba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
741
-
742
- # I can't handle parallel right now.
743
-
744
- # TODO Implement logic that lets me amend modules instead of only overwriting them. "initializeState" could/should include state
745
- # initialization for multiple algorithms.
746
- astModule = _getModule(moduleIdentifier='algorithmA007822')
747
- # NOTE `initializeState.transitionOnGroupsOfFolds` will collide with `initializeStateA007822.transitionOnGroupsOfFolds` if the
748
- # modules are merged. This problem is a side effect of the problem with `MapFoldingState.groupsOfFolds` and
749
- # `MapFoldingState.foldsTotal`. If I fix that issue, then the identifier `initializeStateA007822.transitionOnGroupsOfFolds` will
750
- # naturally change to something more appropriate (and remove the collision).
751
- makeInitializeState(astModule, 'initializeStateA007822', 'transitionOnGroupsOfFolds', logicalPathInfixDEFAULT)
752
-
753
- astModule = _getModule(moduleIdentifier='algorithmA007822')
754
- pathFilename = makeTheorem2(astModule, 'theorem2A007822', None, logicalPathInfixDEFAULT, None)
755
-
756
- astModule = parsePathFilename2astModule(pathFilename)
757
- pathFilename = trimTheorem2(astModule, 'theorem2A007822Trimmed', None, logicalPathInfixDEFAULT, None)
758
-
759
- astModule = parsePathFilename2astModule(pathFilename)
760
- pathFilename = numbaOnTheorem2(astModule, 'theorem2A007822Numba', None, logicalPathInfixDEFAULT, None)
761
-
762
- astImportFrom: ast.ImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.identifierPackage, logicalPathInfixDEFAULT, 'theorem2A007822Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
763
- makeUnRePackDataclass(astImportFrom, 'dataPackingA007822')
764
-