mapFolding 0.9.3__py3-none-any.whl → 0.9.5__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 (36) hide show
  1. mapFolding/__init__.py +41 -7
  2. mapFolding/basecamp.py +100 -9
  3. mapFolding/beDRY.py +7 -15
  4. mapFolding/dataBaskets.py +12 -0
  5. mapFolding/datatypes.py +4 -4
  6. mapFolding/oeis.py +2 -7
  7. mapFolding/someAssemblyRequired/RecipeJob.py +97 -3
  8. mapFolding/someAssemblyRequired/Z0Z_makeSomeModules.py +326 -0
  9. mapFolding/someAssemblyRequired/__init__.py +37 -29
  10. mapFolding/someAssemblyRequired/_theTypes.py +19 -19
  11. mapFolding/someAssemblyRequired/_tool_Make.py +12 -6
  12. mapFolding/someAssemblyRequired/_tool_Then.py +59 -21
  13. mapFolding/someAssemblyRequired/_toolboxAST.py +57 -0
  14. mapFolding/someAssemblyRequired/_toolboxAntecedents.py +123 -40
  15. mapFolding/someAssemblyRequired/_toolboxContainers.py +128 -37
  16. mapFolding/someAssemblyRequired/_toolboxPython.py +52 -50
  17. mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +274 -0
  18. mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +6 -4
  19. mapFolding/someAssemblyRequired/toolboxNumba.py +3 -27
  20. mapFolding/someAssemblyRequired/transformationTools.py +47 -177
  21. mapFolding/syntheticModules/daoOfMapFolding.py +74 -0
  22. mapFolding/syntheticModules/dataPacking.py +25 -0
  23. mapFolding/syntheticModules/initializeCount.py +49 -0
  24. mapFolding/syntheticModules/theorem2.py +49 -0
  25. mapFolding/syntheticModules/theorem2Numba.py +45 -0
  26. mapFolding/syntheticModules/theorem2Trimmed.py +43 -0
  27. {mapfolding-0.9.3.dist-info → mapfolding-0.9.5.dist-info}/METADATA +2 -1
  28. mapfolding-0.9.5.dist-info/RECORD +59 -0
  29. {mapfolding-0.9.3.dist-info → mapfolding-0.9.5.dist-info}/WHEEL +1 -1
  30. tests/test_computations.py +4 -2
  31. mapFolding/Z0Z_flowControl.py +0 -99
  32. mapfolding-0.9.3.dist-info/RECORD +0 -51
  33. /mapFolding/{theDaoOfMapFolding.py → daoOfMapFolding.py} +0 -0
  34. {mapfolding-0.9.3.dist-info → mapfolding-0.9.5.dist-info}/entry_points.txt +0 -0
  35. {mapfolding-0.9.3.dist-info → mapfolding-0.9.5.dist-info}/licenses/LICENSE +0 -0
  36. {mapfolding-0.9.3.dist-info → mapfolding-0.9.5.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,17 @@
1
1
  """
2
2
  Core AST Traversal and Transformation Utilities for Python Code Manipulation
3
3
 
4
- This module provides the foundation for traversing and modifying Python Abstract
5
- Syntax Trees (ASTs). It contains two primary classes:
4
+ This module provides the foundation for traversing and modifying Python Abstract Syntax Trees (ASTs). It contains two
5
+ primary classes:
6
6
 
7
- 1. NodeTourist: Implements the visitor pattern to traverse an AST and extract information
8
- from nodes that match specific predicates without modifying the AST.
7
+ 1. NodeTourist: Implements the visitor pattern to traverse an AST and extract information from nodes that match specific
8
+ predicates without modifying the AST.
9
9
 
10
- 2. NodeChanger: Extends ast.NodeTransformer to selectively transform AST nodes that
11
- match specific predicates, enabling targeted code modifications.
10
+ 2. NodeChanger: Extends ast.NodeTransformer to selectively transform AST nodes that match specific predicates, enabling
11
+ targeted code modifications.
12
12
 
13
- The module also provides utilities for importing modules, loading callables from files,
14
- and parsing Python code into AST structures, creating a complete workflow for code
15
- analysis and transformation.
13
+ The module also provides utilities for importing modules, loading callables from files, and parsing Python code into AST
14
+ structures, creating a complete workflow for code analysis and transformation.
16
15
  """
17
16
 
18
17
  from collections.abc import Callable
@@ -32,13 +31,12 @@ class NodeTourist(ast.NodeVisitor):
32
31
  """
33
32
  Visit and extract information from AST nodes that match a predicate.
34
33
 
35
- NodeTourist implements the visitor pattern to traverse an AST, applying
36
- a predicate function to each node and capturing nodes or their attributes
37
- when they match. Unlike NodeChanger, it doesn't modify the AST but collects
34
+ NodeTourist implements the visitor pattern to traverse an AST, applying a predicate function to each node and
35
+ capturing nodes or their attributes when they match. Unlike NodeChanger, it doesn't modify the AST but collects
38
36
  information during traversal.
39
37
 
40
- This class is particularly useful for analyzing AST structures, extracting
41
- specific nodes or node properties, and gathering information about code patterns.
38
+ This class is particularly useful for analyzing AST structures, extracting specific nodes or node properties, and
39
+ gathering information about code patterns.
42
40
  """
43
41
  def __init__(self, findThis: Callable[..., Any], doThat: Callable[..., Any]) -> None:
44
42
  self.findThis = findThis
@@ -61,12 +59,12 @@ class NodeChanger(ast.NodeTransformer):
61
59
  """
62
60
  Transform AST nodes that match a predicate by applying a transformation function.
63
61
 
64
- NodeChanger is an AST node transformer that applies a targeted transformation
65
- to nodes matching a specific predicate. It traverses the AST and only modifies
66
- nodes that satisfy the predicate condition, leaving other nodes unchanged.
62
+ NodeChanger is an AST node transformer that applies a targeted transformation to nodes matching a specific
63
+ predicate. It traverses the AST and only modifies nodes that satisfy the predicate condition, leaving other nodes
64
+ unchanged.
67
65
 
68
- This class extends ast.NodeTransformer and implements the visitor pattern
69
- to systematically process and transform an AST tree.
66
+ This class extends ast.NodeTransformer and implements the visitor pattern to systematically process and transform an
67
+ AST tree.
70
68
  """
71
69
  def __init__(self, findThis: Callable[..., Any], doThat: Callable[..., Any]) -> None:
72
70
  self.findThis = findThis
@@ -81,18 +79,18 @@ def importLogicalPath2Callable(logicalPathModule: str_nameDOTname, identifier: a
81
79
  """
82
80
  Import a callable object (function or class) from a module based on its logical path.
83
81
 
84
- This function imports a module using `importlib.import_module()` and then retrieves
85
- a specific attribute (function, class, or other object) from that module.
82
+ This function imports a module using `importlib.import_module()` and then retrieves a specific attribute (function,
83
+ class, or other object) from that module.
86
84
 
87
85
  Parameters
88
86
  ----------
89
- logicalPathModule : str
87
+ logicalPathModule
90
88
  The logical path to the module, using dot notation (e.g., 'package.subpackage.module').
91
- identifier : str
89
+ identifier
92
90
  The name of the callable object to retrieve from the module.
93
- packageIdentifierIfRelative : str, optional
94
- The package name to use as the anchor point if `logicalPathModule` is a relative import.
95
- If None, absolute import is assumed.
91
+ packageIdentifierIfRelative : None
92
+ The package name to use as the anchor point if `logicalPathModule` is a relative import. If None, absolute
93
+ import is assumed.
96
94
 
97
95
  Returns
98
96
  -------
@@ -105,16 +103,17 @@ def importLogicalPath2Callable(logicalPathModule: str_nameDOTname, identifier: a
105
103
  def importPathFilename2Callable(pathFilename: PathLike[Any] | PurePath, identifier: ast_Identifier, moduleIdentifier: ast_Identifier | None = None) -> Callable[..., Any]:
106
104
  """
107
105
  Load a callable (function, class, etc.) from a Python file.
108
- This function imports a specified Python file as a module, extracts a callable object
109
- from it by name, and returns that callable.
106
+
107
+ This function imports a specified Python file as a module, extracts a callable object from it by name, and returns
108
+ that callable.
110
109
 
111
110
  Parameters
112
111
  ----------
113
- pathFilename : Union[PathLike[Any], PurePath]
112
+ pathFilename
114
113
  Path to the Python file to import.
115
- identifier : str
114
+ identifier
116
115
  Name of the callable to extract from the imported module.
117
- moduleIdentifier : Optional[str]
116
+ moduleIdentifier
118
117
  Name to use for the imported module. If None, the filename stem is used.
119
118
 
120
119
  Returns
@@ -138,49 +137,52 @@ def importPathFilename2Callable(pathFilename: PathLike[Any] | PurePath, identifi
138
137
  importlibSpecification.loader.exec_module(moduleImported_jk_hahaha)
139
138
  return getattr(moduleImported_jk_hahaha, identifier)
140
139
 
141
- def parseLogicalPath2astModule(logicalPathModule: str_nameDOTname, packageIdentifierIfRelative: ast_Identifier|None=None, mode: Literal['exec'] = 'exec') -> ast.Module:
140
+ def parseLogicalPath2astModule(logicalPathModule: str_nameDOTname, packageIdentifierIfRelative: ast_Identifier | None = None, mode: Literal['exec'] = 'exec') -> ast.Module:
142
141
  """
143
- Parse a logical Python module path into an AST Module.
142
+ Parse a logical Python module path into an `ast.Module`.
144
143
 
145
- This function imports a module using its logical path (e.g., 'package.subpackage.module')
146
- and converts its source code into an Abstract Syntax Tree (AST) Module object.
144
+ This function imports a module using its logical path (e.g., 'package.subpackage.module') and converts its source
145
+ code into an Abstract Syntax Tree (AST) Module object.
147
146
 
148
147
  Parameters
149
148
  ----------
150
- logicalPathModule : str
149
+ logicalPathModule
151
150
  The logical path to the module using dot notation (e.g., 'package.module').
152
- packageIdentifierIfRelative : ast.Identifier or None, optional
151
+ packageIdentifierIfRelative : None
153
152
  The package identifier to use if the module path is relative, defaults to None.
154
- mode : Literal['exec'], optional
155
- The parsing mode to use, defaults to 'exec'.
153
+ mode : Literal['exec']
154
+ The mode parameter for `ast.parse`. Default is `Literal['exec']`. Options are `Literal['exec']`, `"exec"` (which
155
+ is _not_ the same as `Literal['exec']`), `Literal['eval']`, `Literal['func_type']`, `Literal['single']`. See
156
+ `ast.parse` documentation for some details and much confusion.
156
157
 
157
158
  Returns
158
159
  -------
159
- ast.Module
160
+ astModule
160
161
  An AST Module object representing the parsed source code of the imported module.
161
162
  """
162
163
  moduleImported: ModuleType = importlib.import_module(logicalPathModule, packageIdentifierIfRelative)
163
164
  sourcePython: str = inspect_getsource(moduleImported)
164
- return ast.parse(sourcePython, mode=mode)
165
+ return ast.parse(sourcePython, mode)
165
166
 
166
167
  def parsePathFilename2astModule(pathFilename: PathLike[Any] | PurePath, mode: Literal['exec'] = 'exec') -> ast.Module:
167
168
  """
168
- Parse a file from a given path into an ast.Module.
169
+ Parse a file from a given path into an `ast.Module`.
169
170
 
170
- This function reads the content of a file specified by `pathFilename` and parses it into an
171
- Abstract Syntax Tree (AST) Module using Python's ast module.
171
+ This function reads the content of a file specified by `pathFilename` and parses it into an Abstract Syntax Tree
172
+ (AST) Module using Python's ast module.
172
173
 
173
174
  Parameters
174
175
  ----------
175
- pathFilename : PathLike[Any] | PurePath
176
+ pathFilename
176
177
  The path to the file to be parsed. Can be a string path, PathLike object, or PurePath object.
177
- mode : Literal['exec'], optional
178
- The mode parameter for ast.parse. Default is 'exec'.
179
- Options are 'exec', 'eval', or 'single'. See ast.parse documentation for details.
178
+ mode : Literal['exec']
179
+ The mode parameter for `ast.parse`. Default is `Literal['exec']`. Options are `Literal['exec']`, `"exec"` (which
180
+ is _not_ the same as `Literal['exec']`), `Literal['eval']`, `Literal['func_type']`, `Literal['single']`. See
181
+ `ast.parse` documentation for some details and much confusion.
180
182
 
181
183
  Returns
182
184
  -------
183
- ast.Module
185
+ astModule
184
186
  The parsed abstract syntax tree module.
185
187
  """
186
- return ast.parse(Path(pathFilename).read_text(), mode=mode)
188
+ return ast.parse(Path(pathFilename).read_text(), mode)
@@ -0,0 +1,274 @@
1
+ from mapFolding import getPathFilenameFoldsTotal, raiseIfNoneGitHubIssueNumber3, The
2
+ from mapFolding.someAssemblyRequired import (
3
+ ast_Identifier,
4
+ be,
5
+ extractFunctionDef,
6
+ ifThis,
7
+ IngredientsFunction,
8
+ IngredientsModule,
9
+ LedgerOfImports,
10
+ Make,
11
+ NodeChanger,
12
+ NodeTourist,
13
+ str_nameDOTname,
14
+ Then,
15
+ )
16
+ from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2Numba
17
+ from mapFolding.someAssemblyRequired.toolboxNumba import parametersNumbaLight, SpicesJobNumba, decorateCallableWithNumba
18
+ from mapFolding.someAssemblyRequired.transformationTools import dictionaryEstimates, write_astModule, makeInitializedComputationState
19
+ from mapFolding.syntheticModules.initializeCount import initializeGroupsOfFolds
20
+ from mapFolding.dataBaskets import MapFoldingState
21
+ from pathlib import PurePosixPath
22
+ from typing import cast, NamedTuple
23
+ from Z0Z_tools import autoDecodingRLE
24
+ import ast
25
+ """Synthesize one file to compute `foldsTotal` of `mapShape`."""
26
+
27
+ list_IdentifiersNotUsedAllHARDCODED = ['concurrencyLimit', 'foldsTotal', 'mapShape',]
28
+ list_IdentifiersNotUsedParallelSequentialHARDCODED = ['indexLeaf']
29
+ list_IdentifiersNotUsedSequentialHARDCODED = ['foldGroups', 'taskDivisions', 'taskIndex',]
30
+
31
+ list_IdentifiersReplacedHARDCODED = ['groupsOfFolds',]
32
+
33
+ list_IdentifiersStaticValuesHARDCODED = ['dimensionsTotal', 'leavesTotal',]
34
+
35
+ list_IdentifiersNotUsedHARDCODED = list_IdentifiersStaticValuesHARDCODED + list_IdentifiersReplacedHARDCODED + list_IdentifiersNotUsedAllHARDCODED + list_IdentifiersNotUsedParallelSequentialHARDCODED + list_IdentifiersNotUsedSequentialHARDCODED
36
+
37
+ def addLauncherNumbaProgress(ingredientsModule: IngredientsModule, ingredientsFunction: IngredientsFunction, job: RecipeJobTheorem2Numba, spices: SpicesJobNumba) -> tuple[IngredientsModule, IngredientsFunction]:
38
+ """
39
+ Add progress tracking capabilities to a Numba-optimized function.
40
+
41
+ This function modifies both the module and the function to integrate Numba-compatible
42
+ progress tracking for long-running calculations. It performs several key transformations:
43
+
44
+ 1. Adds a progress bar parameter to the function signature
45
+ 2. Replaces counting increments with progress bar updates
46
+ 3. Creates a launcher section that displays and updates progress
47
+ 4. Configures file output to save results upon completion
48
+
49
+ The progress tracking is particularly important for map folding calculations
50
+ which can take hours or days to complete, providing visual feedback and
51
+ estimated completion times.
52
+
53
+ Parameters:
54
+ ingredientsModule: The module where the function is defined.
55
+ ingredientsFunction: The function to modify with progress tracking.
56
+ job: Configuration specifying shape details and output paths.
57
+ spices: Configuration specifying progress bar details.
58
+
59
+ Returns:
60
+ A tuple containing the modified module and function with progress tracking.
61
+ """
62
+ linesLaunch: str = f"""
63
+ if __name__ == '__main__':
64
+ with ProgressBar(total={job.foldsTotalEstimated}, update_interval=2) as statusUpdate:
65
+ {job.countCallable}(statusUpdate)
66
+ foldsTotal = statusUpdate.n * {job.state.leavesTotal}
67
+ print('\\nmap {job.state.mapShape} =', foldsTotal)
68
+ writeStream = open('{job.pathFilenameFoldsTotal.as_posix()}', 'w')
69
+ writeStream.write(str(foldsTotal))
70
+ writeStream.close()
71
+ """
72
+ numba_progressPythonClass: ast_Identifier = 'ProgressBar'
73
+ numba_progressNumbaType: ast_Identifier = 'ProgressBarType'
74
+ ingredientsModule.imports.addImportFrom_asStr('numba_progress', numba_progressPythonClass)
75
+ ingredientsModule.imports.addImportFrom_asStr('numba_progress', numba_progressNumbaType)
76
+
77
+ ast_argNumbaProgress = ast.arg(arg=spices.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
78
+ ingredientsFunction.astFunctionDef.args.args.append(ast_argNumbaProgress)
79
+
80
+ findThis = ifThis.isAugAssign_targetIs(ifThis.isName_Identifier(job.shatteredDataclass.countingVariableName.id))
81
+ doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(spices.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
82
+ countWithProgressBar = NodeChanger(findThis, doThat)
83
+ countWithProgressBar.visit(ingredientsFunction.astFunctionDef)
84
+
85
+ removeReturnStatement = NodeChanger(be.Return, Then.removeIt)
86
+ removeReturnStatement.visit(ingredientsFunction.astFunctionDef)
87
+ ingredientsFunction.astFunctionDef.returns = Make.Constant(value=None)
88
+
89
+ ingredientsModule.appendLauncher(ast.parse(linesLaunch))
90
+
91
+ return ingredientsModule, ingredientsFunction
92
+
93
+ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: IngredientsFunction, job: RecipeJobTheorem2Numba) -> IngredientsFunction:
94
+ """
95
+ Convert function parameters into initialized variables with concrete values.
96
+
97
+ This function implements a critical transformation that converts function parameters
98
+ into statically initialized variables in the function body. This enables several
99
+ optimizations:
100
+
101
+ 1. Eliminating parameter passing overhead.
102
+ 2. Embedding concrete values directly in the code.
103
+ 3. Allowing Numba to optimize based on known value characteristics.
104
+ 4. Simplifying function signatures for specialized use cases.
105
+
106
+ The function handles different data types (scalars, arrays, custom types) appropriately,
107
+ replacing abstract parameter references with concrete values from the computation state.
108
+ It also removes unused parameters and variables to eliminate dead code.
109
+
110
+ Parameters:
111
+ ingredientsFunction: The function to transform.
112
+ job: Recipe containing concrete values for parameters and field metadata.
113
+
114
+ Returns:
115
+ The modified function with parameters converted to initialized variables.
116
+ """
117
+ ingredientsFunction.imports.update(job.shatteredDataclass.imports)
118
+
119
+ list_argCuzMyBrainRefusesToThink = ingredientsFunction.astFunctionDef.args.args + ingredientsFunction.astFunctionDef.args.posonlyargs + ingredientsFunction.astFunctionDef.args.kwonlyargs
120
+ list_arg_arg: list[ast_Identifier] = [ast_arg.arg for ast_arg in list_argCuzMyBrainRefusesToThink]
121
+ listName: list[ast.Name] = []
122
+ NodeTourist(be.Name, Then.appendTo(listName)).visit(ingredientsFunction.astFunctionDef)
123
+ list_Identifiers: list[ast_Identifier] = [astName.id for astName in listName]
124
+ list_IdentifiersNotUsed: list[ast_Identifier] = list(set(list_arg_arg) - set(list_Identifiers))
125
+
126
+ for ast_arg in list_argCuzMyBrainRefusesToThink:
127
+ if ast_arg.arg in job.shatteredDataclass.field2AnnAssign:
128
+ if ast_arg.arg in list_IdentifiersNotUsed:
129
+ pass
130
+ else:
131
+ ImaAnnAssign, elementConstructor = job.shatteredDataclass.Z0Z_field2AnnAssign[ast_arg.arg]
132
+ match elementConstructor:
133
+ case 'scalar':
134
+ ImaAnnAssign.value.args[0].value = int(job.state.__dict__[ast_arg.arg]) # type: ignore
135
+ case 'array':
136
+ dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], True)
137
+ dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
138
+ ImaAnnAssign.value.args = [dataAs_astExpr] # type: ignore
139
+ case _:
140
+ list_exprDOTannotation: list[ast.expr] = []
141
+ list_exprDOTvalue: list[ast.expr] = []
142
+ for dimension in job.state.mapShape:
143
+ list_exprDOTannotation.append(Make.Name(elementConstructor))
144
+ list_exprDOTvalue.append(Make.Call(Make.Name(elementConstructor), [Make.Constant(dimension)]))
145
+ ImaAnnAssign.annotation.slice.elts = list_exprDOTannotation # type: ignore
146
+ ImaAnnAssign.value.elts = list_exprDOTvalue # type: ignore
147
+
148
+ ingredientsFunction.astFunctionDef.body.insert(0, ImaAnnAssign)
149
+
150
+ findThis = ifThis.is_arg_Identifier(ast_arg.arg)
151
+ remove_arg = NodeChanger(findThis, Then.removeIt)
152
+ remove_arg.visit(ingredientsFunction.astFunctionDef)
153
+
154
+ ast.fix_missing_locations(ingredientsFunction.astFunctionDef)
155
+ return ingredientsFunction
156
+
157
+ def makeJobNumba(job: RecipeJobTheorem2Numba, spices: SpicesJobNumba) -> None:
158
+
159
+ astFunctionDef = extractFunctionDef(job.source_astModule, job.countCallable)
160
+ if not astFunctionDef: raise raiseIfNoneGitHubIssueNumber3
161
+ ingredientsCount: IngredientsFunction = IngredientsFunction(astFunctionDef, LedgerOfImports())
162
+
163
+ # Remove `foldGroups` and any other unused statements, so you can dynamically determine which variables are not used
164
+ findThis = ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier('foldGroups'))
165
+ doThat = Then.removeIt
166
+ remove_foldGroups = NodeChanger(findThis, doThat)
167
+ remove_foldGroups.visit(ingredientsCount.astFunctionDef)
168
+
169
+ # replace identifiers with static values with their values, so you can dynamically determine which variables are not used
170
+ list_IdentifiersStaticValues = list_IdentifiersStaticValuesHARDCODED
171
+ for identifier in list_IdentifiersStaticValues:
172
+ findThis = ifThis.isName_Identifier(identifier)
173
+ doThat = Then.replaceWith(Make.Constant(int(job.state.__dict__[identifier])))
174
+ NodeChanger(findThis, doThat).visit(ingredientsCount.astFunctionDef)
175
+
176
+ ingredientsModule = IngredientsModule()
177
+ # This launcher eliminates the use of one identifier, so run it now and you can dynamically determine which variables are not used
178
+ if spices.useNumbaProgressBar:
179
+ ingredientsModule, ingredientsCount = addLauncherNumbaProgress(ingredientsModule, ingredientsCount, job, spices)
180
+ spices.parametersNumba['nogil'] = True
181
+ else:
182
+ linesLaunch: str = f"""
183
+ if __name__ == '__main__':
184
+ import time
185
+ timeStart = time.perf_counter()
186
+ foldsTotal = {job.countCallable}() * {job.state.leavesTotal}
187
+ print(time.perf_counter() - timeStart)
188
+ print('\\nmap {job.state.mapShape} =', foldsTotal)
189
+ writeStream = open('{job.pathFilenameFoldsTotal.as_posix()}', 'w')
190
+ writeStream.write(str(foldsTotal))
191
+ writeStream.close()
192
+ """
193
+ # from mapFolding.oeis import getFoldsTotalKnown
194
+ # print(foldsTotal == getFoldsTotalKnown({job.state.mapShape}))
195
+ ingredientsModule.appendLauncher(ast.parse(linesLaunch))
196
+ changeReturnParallelCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(job.shatteredDataclass.countingVariableName)))
197
+ changeReturnParallelCallable.visit(ingredientsCount.astFunctionDef)
198
+ ingredientsCount.astFunctionDef.returns = job.shatteredDataclass.countingVariableAnnotation
199
+
200
+ ingredientsCount = move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsCount, job)
201
+
202
+ class DatatypeConfig(NamedTuple):
203
+ Z0Z_module: str_nameDOTname
204
+ fml: ast_Identifier
205
+ Z0Z_type_name: ast_Identifier
206
+ Z0Z_asname: ast_Identifier | None = None
207
+
208
+ listDatatypeConfigs = [
209
+ DatatypeConfig(fml='DatatypeLeavesTotal', Z0Z_module='numba', Z0Z_type_name='uint8'),
210
+ DatatypeConfig(fml='DatatypeElephino', Z0Z_module='numba', Z0Z_type_name='uint16'),
211
+ DatatypeConfig(fml='DatatypeFoldsTotal', Z0Z_module='numba', Z0Z_type_name='uint64'),
212
+ ]
213
+
214
+ for datatypeConfig in listDatatypeConfigs:
215
+ ingredientsModule.imports.addImportFrom_asStr(datatypeConfig.Z0Z_module, datatypeConfig.Z0Z_type_name)
216
+ statement = Make.Assign(
217
+ [Make.Name(datatypeConfig.fml, ast.Store())],
218
+ Make.Name(datatypeConfig.Z0Z_type_name)
219
+ )
220
+ ingredientsModule.appendPrologue(statement=statement)
221
+
222
+ ingredientsCount.imports.removeImportFromModule('mapFolding.theSSOT')
223
+
224
+ listNumPyTypeConfigs = [
225
+ DatatypeConfig(fml='Array1DLeavesTotal', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array1DLeavesTotal'),
226
+ DatatypeConfig(fml='Array1DElephino', Z0Z_module='numpy', Z0Z_type_name='uint16', Z0Z_asname='Array1DElephino'),
227
+ DatatypeConfig(fml='Array3D', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array3D'),
228
+ ]
229
+
230
+ for typeConfig in listNumPyTypeConfigs:
231
+ ingredientsCount.imports.removeImportFrom(typeConfig.Z0Z_module, None, typeConfig.fml)
232
+ ingredientsCount.imports.addImportFrom_asStr(typeConfig.Z0Z_module, typeConfig.Z0Z_type_name, typeConfig.Z0Z_asname)
233
+
234
+ ingredientsCount.astFunctionDef.decorator_list = [] # TODO low-priority, handle this more elegantly
235
+ # TODO when I add the function signature in numba style back to the decorator, the logic needs to handle `ProgressBarType:`
236
+ ingredientsCount = decorateCallableWithNumba(ingredientsCount, spices.parametersNumba)
237
+
238
+ ingredientsModule.appendIngredientsFunction(ingredientsCount)
239
+ write_astModule(ingredientsModule, job.pathFilenameModule, job.packageIdentifier)
240
+
241
+ """
242
+ Overview
243
+ - the code starts life in theDao.py, which has many optimizations;
244
+ - `makeNumbaOptimizedFlow` increase optimization especially by using numba;
245
+ - `makeJobNumba` increases optimization especially by limiting its capabilities to just one set of parameters
246
+ - the synthesized module must run well as a standalone interpreted-Python script
247
+ - the next major optimization step will (probably) be to use the module synthesized by `makeJobNumba` to compile a standalone executable
248
+ - Nevertheless, at each major optimization step, the code is constantly being improved and optimized, so everything must be well organized (read: semantic) and able to handle a range of arbitrary upstream and not disrupt downstream transformations
249
+
250
+ Necessary
251
+ - Move the function's parameters to the function body,
252
+ - initialize identifiers with their state types and values,
253
+
254
+ Optimizations
255
+ - replace static-valued identifiers with their values
256
+ - narrowly focused imports
257
+
258
+ Minutia
259
+ - do not use `with` statement inside numba jitted code, except to use numba's obj mode
260
+ """
261
+
262
+ if __name__ == '__main__':
263
+ mapShape = (1,46)
264
+ state = MapFoldingState(mapShape)
265
+ state = initializeGroupsOfFolds(state)
266
+ # foldsTotalEstimated = getFoldsTotalKnown(state.mapShape) // state.leavesTotal
267
+ # foldsTotalEstimated = dictionaryEstimates[state.mapShape] // state.leavesTotal
268
+ foldsTotalEstimated = 0
269
+ pathModule = PurePosixPath(The.pathPackage, 'jobs')
270
+ pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
271
+ aJob = RecipeJobTheorem2Numba(state, foldsTotalEstimated, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
272
+ spices = SpicesJobNumba(useNumbaProgressBar=False, parametersNumba=parametersNumbaLight)
273
+ # spices = SpicesJobNumba()
274
+ makeJobNumba(aJob, spices)
@@ -22,6 +22,7 @@ from mapFolding import getPathFilenameFoldsTotal, raiseIfNoneGitHubIssueNumber3,
22
22
  from mapFolding.someAssemblyRequired import (
23
23
  ast_Identifier,
24
24
  be,
25
+ extractFunctionDef,
25
26
  ifThis,
26
27
  IngredientsFunction,
27
28
  IngredientsModule,
@@ -34,7 +35,7 @@ from mapFolding.someAssemblyRequired import (
34
35
  )
35
36
  from mapFolding.someAssemblyRequired.RecipeJob import RecipeJob
36
37
  from mapFolding.someAssemblyRequired.toolboxNumba import parametersNumbaLight, SpicesJobNumba, decorateCallableWithNumba
37
- from mapFolding.someAssemblyRequired.transformationTools import dictionaryEstimates, extractFunctionDef, write_astModule, makeInitializedComputationState
38
+ from mapFolding.someAssemblyRequired.transformationTools import dictionaryEstimates, write_astModule, makeInitializedComputationState
38
39
  from pathlib import PurePosixPath
39
40
  from typing import cast, NamedTuple
40
41
  from Z0Z_tools import autoDecodingRLE
@@ -131,7 +132,7 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
131
132
  Returns:
132
133
  The modified function with parameters converted to initialized variables.
133
134
  """
134
- ingredientsFunction.imports.update(job.shatteredDataclass.ledger)
135
+ ingredientsFunction.imports.update(job.shatteredDataclass.imports)
135
136
 
136
137
  list_argCuzMyBrainRefusesToThink = ingredientsFunction.astFunctionDef.args.args + ingredientsFunction.astFunctionDef.args.posonlyargs + ingredientsFunction.astFunctionDef.args.kwonlyargs
137
138
  list_arg_arg: list[ast_Identifier] = [ast_arg.arg for ast_arg in list_argCuzMyBrainRefusesToThink]
@@ -299,10 +300,11 @@ if __name__ == '__main__':
299
300
  """
300
301
 
301
302
  if __name__ == '__main__':
302
- mapShape = (2,21)
303
+ mapShape = (1,46)
303
304
  state = makeInitializedComputationState(mapShape)
304
305
  # foldsTotalEstimated = getFoldsTotalKnown(state.mapShape) // state.leavesTotal
305
- foldsTotalEstimated = dictionaryEstimates[state.mapShape] // state.leavesTotal
306
+ # foldsTotalEstimated = dictionaryEstimates[state.mapShape] // state.leavesTotal
307
+ foldsTotalEstimated = 0
306
308
  pathModule = PurePosixPath(The.pathPackage, 'jobs')
307
309
  pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
308
310
  aJob = RecipeJob(state, foldsTotalEstimated, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
@@ -16,23 +16,14 @@ performance improvements while preserving code semantics and correctness.
16
16
  """
17
17
 
18
18
  from collections.abc import Callable, Sequence
19
- from mapFolding.someAssemblyRequired import ast_Identifier, be, IngredientsFunction, Make, NodeTourist, RecipeSynthesizeFlow, str_nameDOTname, Then
19
+ from mapFolding import NotRequired, TypedDict
20
+ from mapFolding.someAssemblyRequired import ast_Identifier, IngredientsFunction, Make, RecipeSynthesizeFlow, str_nameDOTname
20
21
  from mapFolding.someAssemblyRequired.transformationTools import makeNewFlow, write_astModule
21
22
  from numba.core.compiler import CompilerBase as numbaCompilerBase
22
- from typing import Any, cast, Final, TYPE_CHECKING, TypeGuard
23
+ from typing import Any, cast, Final
23
24
  import ast
24
25
  import dataclasses
25
26
 
26
- try:
27
- from typing import NotRequired
28
- except Exception:
29
- from typing_extensions import NotRequired # pyright: ignore[reportShadowedImports]
30
-
31
- if TYPE_CHECKING:
32
- from typing import TypedDict
33
- else:
34
- TypedDict = dict[str,Any]
35
-
36
27
  # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
37
28
  theNumbaFlow: RecipeSynthesizeFlow = RecipeSynthesizeFlow()
38
29
 
@@ -60,17 +51,8 @@ class ParametersNumba(TypedDict):
60
51
  signature_or_function: NotRequired[Any | Callable[..., Any] | str | tuple[Any, ...]]
61
52
  target: NotRequired[str]
62
53
 
63
- parametersNumbaFailEarly: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': True, 'cache': True, 'error_model': 'python', 'fastmath': False, 'forceinline': True, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': True, 'parallel': False, }
64
- """For a production function: speed is irrelevant, error discovery is paramount, must be compatible with anything downstream."""
65
54
  parametersNumbaDefault: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': False, 'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': True, 'parallel': False, }
66
55
  """Middle of the road: fast, lean, but will talk to non-jitted functions."""
67
- parametersNumbaParallelDEFAULT: Final[ParametersNumba] = { **parametersNumbaDefault, '_nrt': True, 'parallel': True, }
68
- """Middle of the road: fast, lean, but will talk to non-jitted functions."""
69
- parametersNumbaSuperJit: Final[ParametersNumba] = { **parametersNumbaDefault, 'no_cfunc_wrapper': True, 'no_cpython_wrapper': True, }
70
- """Speed, no helmet, no talking to non-jitted functions."""
71
- parametersNumbaSuperJitParallel: Final[ParametersNumba] = { **parametersNumbaSuperJit, '_nrt': True, 'parallel': True, }
72
- """Speed, no helmet, concurrency, no talking to non-jitted functions."""
73
- parametersNumbaMinimum: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': True, 'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': False, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': False, 'forceobj': True, 'parallel': False, }
74
56
  parametersNumbaLight: Final[ParametersNumba] = {'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True}
75
57
 
76
58
  Z0Z_numbaDataTypeModule: str_nameDOTname = 'numba'
@@ -188,11 +170,5 @@ def makeNumbaFlow(numbaFlow: RecipeSynthesizeFlow) -> None:
188
170
 
189
171
  write_astModule(ingredientsModuleNumbaUnified, numbaFlow.pathFilenameDispatcher, numbaFlow.packageIdentifier)
190
172
 
191
- def getIt(astCallConcurrencyResult: list[ast.Call]) -> Callable[[ast.AST], ast.AST]:
192
- def workhorse(node: ast.AST) -> ast.AST:
193
- NodeTourist(be.Call, Then.appendTo(astCallConcurrencyResult)).visit(node)
194
- return node
195
- return workhorse
196
-
197
173
  if __name__ == '__main__':
198
174
  makeNumbaFlow(theNumbaFlow)