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

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