mapFolding 0.11.2__py3-none-any.whl → 0.11.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.
- mapFolding/__init__.py +0 -13
- mapFolding/basecamp.py +2 -3
- mapFolding/beDRY.py +2 -145
- mapFolding/datatypes.py +0 -3
- mapFolding/oeis.py +0 -3
- mapFolding/someAssemblyRequired/RecipeJob.py +14 -121
- mapFolding/someAssemblyRequired/{Z0Z_makeSomeModules.py → Z0Z_makeAllModules.py} +109 -114
- mapFolding/someAssemblyRequired/__init__.py +4 -30
- mapFolding/someAssemblyRequired/_toolIfThis.py +7 -8
- mapFolding/someAssemblyRequired/_toolkitContainers.py +9 -129
- mapFolding/someAssemblyRequired/infoBooth.py +20 -0
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +17 -18
- mapFolding/someAssemblyRequired/toolkitNumba.py +4 -46
- mapFolding/someAssemblyRequired/transformationTools.py +11 -181
- mapFolding/theSSOT.py +9 -4
- {mapfolding-0.11.2.dist-info → mapfolding-0.11.4.dist-info}/METADATA +1 -4
- {mapfolding-0.11.2.dist-info → mapfolding-0.11.4.dist-info}/RECORD +24 -27
- {mapfolding-0.11.2.dist-info → mapfolding-0.11.4.dist-info}/WHEEL +1 -1
- tests/conftest.py +2 -77
- tests/test_computations.py +11 -18
- tests/test_tasks.py +2 -1
- mapFolding/infoBooth.py +0 -96
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +0 -315
- mapFolding/syntheticModules/numbaCount.py +0 -202
- mapFolding/theDao.py +0 -243
- {mapfolding-0.11.2.dist-info → mapfolding-0.11.4.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.11.2.dist-info → mapfolding-0.11.4.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.11.2.dist-info → mapfolding-0.11.4.dist-info}/top_level.txt +0 -0
|
@@ -1,315 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Job-specific Numba Code Generation for Map Folding Calculations
|
|
3
|
-
|
|
4
|
-
This module specializes in generating highly-optimized, single-purpose Numba modules
|
|
5
|
-
for specific map folding calculation jobs. Unlike the general-purpose transformation
|
|
6
|
-
in toolboxNumba.py, this module creates standalone Python modules optimized for a
|
|
7
|
-
single map shape with statically-encoded parameters.
|
|
8
|
-
|
|
9
|
-
The code generation assembly line focuses on:
|
|
10
|
-
|
|
11
|
-
1. Converting function parameters to initialized variables with concrete values.
|
|
12
|
-
2. Replacing dynamic computations with statically-known values.
|
|
13
|
-
3. Eliminating unused code paths and variables.
|
|
14
|
-
4. Adding progress tracking for long-running calculations.
|
|
15
|
-
5. Applying appropriate Numba optimizations for the specific calculation.
|
|
16
|
-
|
|
17
|
-
This creates extremely fast, specialized implementations that can be run directly
|
|
18
|
-
as Python scripts or further compiled into standalone executables.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
from astToolkit import ClassIsAndAttribute
|
|
22
|
-
from mapFolding import getPathFilenameFoldsTotal, raiseIfNoneGitHubIssueNumber3, The
|
|
23
|
-
from mapFolding.someAssemblyRequired import (
|
|
24
|
-
ast_Identifier,
|
|
25
|
-
Be,
|
|
26
|
-
extractFunctionDef,
|
|
27
|
-
IfThis,
|
|
28
|
-
IngredientsFunction,
|
|
29
|
-
IngredientsModule,
|
|
30
|
-
LedgerOfImports,
|
|
31
|
-
Make,
|
|
32
|
-
NodeChanger,
|
|
33
|
-
NodeTourist,
|
|
34
|
-
str_nameDOTname,
|
|
35
|
-
Then,
|
|
36
|
-
write_astModule,
|
|
37
|
-
)
|
|
38
|
-
from mapFolding.someAssemblyRequired.RecipeJob import RecipeJob
|
|
39
|
-
from mapFolding.someAssemblyRequired.toolkitNumba import parametersNumbaLight, SpicesJobNumba, decorateCallableWithNumba
|
|
40
|
-
from mapFolding.someAssemblyRequired.transformationTools import dictionaryEstimates, makeInitializedComputationState
|
|
41
|
-
from pathlib import PurePosixPath
|
|
42
|
-
from typing import cast, NamedTuple
|
|
43
|
-
from Z0Z_tools import autoDecodingRLE
|
|
44
|
-
import ast
|
|
45
|
-
"""Synthesize one file to compute `foldsTotal` of `mapShape`."""
|
|
46
|
-
|
|
47
|
-
list_IdentifiersNotUsedAllHARDCODED = ['concurrencyLimit', 'foldsTotal', 'mapShape',]
|
|
48
|
-
list_IdentifiersNotUsedParallelSequentialHARDCODED = ['indexLeaf']
|
|
49
|
-
list_IdentifiersNotUsedSequentialHARDCODED = ['foldGroups', 'taskDivisions', 'taskIndex',]
|
|
50
|
-
|
|
51
|
-
list_IdentifiersReplacedHARDCODED = ['groupsOfFolds',]
|
|
52
|
-
|
|
53
|
-
list_IdentifiersStaticValuesHARDCODED = ['dimensionsTotal', 'leavesTotal',]
|
|
54
|
-
|
|
55
|
-
list_IdentifiersNotUsedHARDCODED = list_IdentifiersStaticValuesHARDCODED + list_IdentifiersReplacedHARDCODED + list_IdentifiersNotUsedAllHARDCODED + list_IdentifiersNotUsedParallelSequentialHARDCODED + list_IdentifiersNotUsedSequentialHARDCODED
|
|
56
|
-
|
|
57
|
-
def addLauncherNumbaProgress(ingredientsModule: IngredientsModule, ingredientsFunction: IngredientsFunction, job: RecipeJob, spices: SpicesJobNumba) -> tuple[IngredientsModule, IngredientsFunction]:
|
|
58
|
-
"""
|
|
59
|
-
Add progress tracking capabilities to a Numba-optimized function.
|
|
60
|
-
|
|
61
|
-
This function modifies both the module and the function to integrate Numba-compatible
|
|
62
|
-
progress tracking for long-running calculations. It performs several key transformations:
|
|
63
|
-
|
|
64
|
-
1. Adds a progress bar parameter to the function signature
|
|
65
|
-
2. Replaces counting increments with progress bar updates
|
|
66
|
-
3. Creates a launcher section that displays and updates progress
|
|
67
|
-
4. Configures file output to save results upon completion
|
|
68
|
-
|
|
69
|
-
The progress tracking is particularly important for map folding calculations
|
|
70
|
-
which can take hours or days to complete, providing visual feedback and
|
|
71
|
-
estimated completion times.
|
|
72
|
-
|
|
73
|
-
Parameters:
|
|
74
|
-
ingredientsModule: The module where the function is defined.
|
|
75
|
-
ingredientsFunction: The function to modify with progress tracking.
|
|
76
|
-
job: Configuration specifying shape details and output paths.
|
|
77
|
-
spices: Configuration specifying progress bar details.
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
A tuple containing the modified module and function with progress tracking.
|
|
81
|
-
"""
|
|
82
|
-
linesLaunch: str = f"""
|
|
83
|
-
if __name__ == '__main__':
|
|
84
|
-
with ProgressBar(total={job.foldsTotalEstimated}, update_interval=2) as statusUpdate:
|
|
85
|
-
{job.countCallable}(statusUpdate)
|
|
86
|
-
foldsTotal = statusUpdate.n * {job.state.leavesTotal}
|
|
87
|
-
print('\\nmap {job.state.mapShape} =', foldsTotal)
|
|
88
|
-
writeStream = open('{job.pathFilenameFoldsTotal.as_posix()}', 'w')
|
|
89
|
-
writeStream.write(str(foldsTotal))
|
|
90
|
-
writeStream.close()
|
|
91
|
-
"""
|
|
92
|
-
numba_progressPythonClass: ast_Identifier = 'ProgressBar'
|
|
93
|
-
numba_progressNumbaType: ast_Identifier = 'ProgressBarType'
|
|
94
|
-
ingredientsModule.imports.addImportFrom_asStr('numba_progress', numba_progressPythonClass)
|
|
95
|
-
ingredientsModule.imports.addImportFrom_asStr('numba_progress', numba_progressNumbaType)
|
|
96
|
-
|
|
97
|
-
ast_argNumbaProgress = ast.arg(arg=spices.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
|
|
98
|
-
ingredientsFunction.astFunctionDef.args.args.append(ast_argNumbaProgress)
|
|
99
|
-
|
|
100
|
-
findThis = ClassIsAndAttribute.targetIs(ast.AugAssign, IfThis.isName_Identifier(job.shatteredDataclass.countingVariableName.id)) # type: ignore
|
|
101
|
-
doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(spices.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
|
|
102
|
-
countWithProgressBar = NodeChanger(findThis, doThat)
|
|
103
|
-
countWithProgressBar.visit(ingredientsFunction.astFunctionDef)
|
|
104
|
-
|
|
105
|
-
removeReturnStatement = NodeChanger(Be.Return, Then.removeIt)
|
|
106
|
-
removeReturnStatement.visit(ingredientsFunction.astFunctionDef)
|
|
107
|
-
ingredientsFunction.astFunctionDef.returns = Make.Constant(value=None)
|
|
108
|
-
|
|
109
|
-
ingredientsModule.appendLauncher(ast.parse(linesLaunch))
|
|
110
|
-
|
|
111
|
-
return ingredientsModule, ingredientsFunction
|
|
112
|
-
|
|
113
|
-
def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: IngredientsFunction, job: RecipeJob) -> IngredientsFunction:
|
|
114
|
-
"""
|
|
115
|
-
Convert function parameters into initialized variables with concrete values.
|
|
116
|
-
|
|
117
|
-
This function implements a critical transformation that converts function parameters
|
|
118
|
-
into statically initialized variables in the function body. This enables several
|
|
119
|
-
optimizations:
|
|
120
|
-
|
|
121
|
-
1. Eliminating parameter passing overhead.
|
|
122
|
-
2. Embedding concrete values directly in the code.
|
|
123
|
-
3. Allowing Numba to optimize based on known value characteristics.
|
|
124
|
-
4. Simplifying function signatures for specialized use cases.
|
|
125
|
-
|
|
126
|
-
The function handles different data types (scalars, arrays, custom types) appropriately,
|
|
127
|
-
replacing abstract parameter references with concrete values from the computation state.
|
|
128
|
-
It also removes unused parameters and variables to eliminate dead code.
|
|
129
|
-
|
|
130
|
-
Parameters:
|
|
131
|
-
ingredientsFunction: The function to transform.
|
|
132
|
-
job: Recipe containing concrete values for parameters and field metadata.
|
|
133
|
-
|
|
134
|
-
Returns:
|
|
135
|
-
The modified function with parameters converted to initialized variables.
|
|
136
|
-
"""
|
|
137
|
-
ingredientsFunction.imports.update(job.shatteredDataclass.imports)
|
|
138
|
-
|
|
139
|
-
list_argCuzMyBrainRefusesToThink = ingredientsFunction.astFunctionDef.args.args + ingredientsFunction.astFunctionDef.args.posonlyargs + ingredientsFunction.astFunctionDef.args.kwonlyargs
|
|
140
|
-
list_arg_arg: list[ast_Identifier] = [ast_arg.arg for ast_arg in list_argCuzMyBrainRefusesToThink]
|
|
141
|
-
listName: list[ast.Name] = []
|
|
142
|
-
NodeTourist(Be.Name, Then.appendTo(listName)).visit(ingredientsFunction.astFunctionDef)
|
|
143
|
-
list_Identifiers: list[ast_Identifier] = [astName.id for astName in listName]
|
|
144
|
-
list_IdentifiersNotUsed: list[ast_Identifier] = list(set(list_arg_arg) - set(list_Identifiers))
|
|
145
|
-
|
|
146
|
-
for ast_arg in list_argCuzMyBrainRefusesToThink:
|
|
147
|
-
if ast_arg.arg in job.shatteredDataclass.field2AnnAssign:
|
|
148
|
-
if ast_arg.arg in list_IdentifiersNotUsed:
|
|
149
|
-
pass
|
|
150
|
-
else:
|
|
151
|
-
ImaAnnAssign, elementConstructor = job.shatteredDataclass.Z0Z_field2AnnAssign[ast_arg.arg]
|
|
152
|
-
match elementConstructor:
|
|
153
|
-
case 'scalar':
|
|
154
|
-
cast(ast.Constant, cast(ast.Call, ImaAnnAssign.value).args[0]).value = int(job.state.__dict__[ast_arg.arg])
|
|
155
|
-
case 'array':
|
|
156
|
-
dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], True)
|
|
157
|
-
dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
|
|
158
|
-
cast(ast.Call, ImaAnnAssign.value).args = [dataAs_astExpr]
|
|
159
|
-
case _:
|
|
160
|
-
list_exprDOTannotation: list[ast.expr] = []
|
|
161
|
-
list_exprDOTvalue: list[ast.expr] = []
|
|
162
|
-
for dimension in job.state.mapShape:
|
|
163
|
-
list_exprDOTannotation.append(Make.Name(elementConstructor))
|
|
164
|
-
list_exprDOTvalue.append(Make.Call(Make.Name(elementConstructor), [Make.Constant(dimension)]))
|
|
165
|
-
cast(ast.Tuple, cast(ast.Subscript, cast(ast.AnnAssign, ImaAnnAssign).annotation).slice).elts = list_exprDOTannotation
|
|
166
|
-
cast(ast.Tuple, ImaAnnAssign.value).elts = list_exprDOTvalue
|
|
167
|
-
|
|
168
|
-
ingredientsFunction.astFunctionDef.body.insert(0, ImaAnnAssign)
|
|
169
|
-
|
|
170
|
-
findThis = IfThis.is_arg_Identifier(ast_arg.arg)
|
|
171
|
-
remove_arg = NodeChanger(findThis, Then.removeIt)
|
|
172
|
-
remove_arg.visit(ingredientsFunction.astFunctionDef)
|
|
173
|
-
|
|
174
|
-
ast.fix_missing_locations(ingredientsFunction.astFunctionDef)
|
|
175
|
-
return ingredientsFunction
|
|
176
|
-
|
|
177
|
-
def makeJobNumba(job: RecipeJob, spices: SpicesJobNumba) -> None:
|
|
178
|
-
"""
|
|
179
|
-
Generate a highly-optimized, single-purpose Numba module for a specific map shape.
|
|
180
|
-
|
|
181
|
-
This function implements the complete transformation assembly line for creating a
|
|
182
|
-
standalone, specialized implementation for calculating map folding solutions for
|
|
183
|
-
a specific shape. The process includes:
|
|
184
|
-
|
|
185
|
-
1. Extracting the counting function from the source module
|
|
186
|
-
2. Removing unused code paths based on static analysis
|
|
187
|
-
3. Replacing dynamic variables with concrete values
|
|
188
|
-
4. Converting parameters to initialized variables
|
|
189
|
-
5. Adding progress tracking if requested
|
|
190
|
-
6. Applying Numba optimizations and type specifications
|
|
191
|
-
7. Writing the final module to the filesystem
|
|
192
|
-
|
|
193
|
-
The resulting Python module is both human-readable and extraordinarily efficient,
|
|
194
|
-
with all shape-specific optimizations statically encoded. This creates specialized
|
|
195
|
-
implementations that can be orders of magnitude faster than general-purpose code.
|
|
196
|
-
|
|
197
|
-
Parameters:
|
|
198
|
-
job: Configuration specifying the target shape, paths, and computation state.
|
|
199
|
-
spices: Configuration specifying Numba and progress tracking options.
|
|
200
|
-
"""
|
|
201
|
-
astFunctionDef = extractFunctionDef(job.source_astModule, job.countCallable)
|
|
202
|
-
if not astFunctionDef: raise raiseIfNoneGitHubIssueNumber3
|
|
203
|
-
ingredientsCount: IngredientsFunction = IngredientsFunction(astFunctionDef, LedgerOfImports())
|
|
204
|
-
|
|
205
|
-
# Remove `foldGroups` and any other unused statements, so you can dynamically determine which variables are not used
|
|
206
|
-
findThis = IfThis.isAssignAndTargets0Is(IfThis.isSubscript_Identifier('foldGroups'))
|
|
207
|
-
doThat = Then.removeIt
|
|
208
|
-
remove_foldGroups = NodeChanger(findThis, doThat)
|
|
209
|
-
remove_foldGroups.visit(ingredientsCount.astFunctionDef)
|
|
210
|
-
|
|
211
|
-
# replace identifiers with static values with their values, so you can dynamically determine which variables are not used
|
|
212
|
-
list_IdentifiersStaticValues = list_IdentifiersStaticValuesHARDCODED
|
|
213
|
-
for identifier in list_IdentifiersStaticValues:
|
|
214
|
-
findThis = IfThis.isName_Identifier(identifier)
|
|
215
|
-
doThat = Then.replaceWith(Make.Constant(int(job.state.__dict__[identifier])))
|
|
216
|
-
NodeChanger(findThis, doThat).visit(ingredientsCount.astFunctionDef)
|
|
217
|
-
|
|
218
|
-
ingredientsModule = IngredientsModule()
|
|
219
|
-
# This launcher eliminates the use of one identifier, so run it now and you can dynamically determine which variables are not used
|
|
220
|
-
if spices.useNumbaProgressBar:
|
|
221
|
-
ingredientsModule, ingredientsCount = addLauncherNumbaProgress(ingredientsModule, ingredientsCount, job, spices)
|
|
222
|
-
spices.parametersNumba['nogil'] = True
|
|
223
|
-
else:
|
|
224
|
-
linesLaunch: str = f"""
|
|
225
|
-
if __name__ == '__main__':
|
|
226
|
-
import time
|
|
227
|
-
timeStart = time.perf_counter()
|
|
228
|
-
foldsTotal = {job.countCallable}() * {job.state.leavesTotal}
|
|
229
|
-
print(time.perf_counter() - timeStart)
|
|
230
|
-
print('\\nmap {job.state.mapShape} =', foldsTotal)
|
|
231
|
-
writeStream = open('{job.pathFilenameFoldsTotal.as_posix()}', 'w')
|
|
232
|
-
writeStream.write(str(foldsTotal))
|
|
233
|
-
writeStream.close()
|
|
234
|
-
"""
|
|
235
|
-
# from mapFolding.oeis import getFoldsTotalKnown
|
|
236
|
-
# print(foldsTotal == getFoldsTotalKnown({job.state.mapShape}))
|
|
237
|
-
ingredientsModule.appendLauncher(ast.parse(linesLaunch))
|
|
238
|
-
changeReturnParallelCallable = NodeChanger(Be.Return, Then.replaceWith(Make.Return(job.shatteredDataclass.countingVariableName)))
|
|
239
|
-
changeReturnParallelCallable.visit(ingredientsCount.astFunctionDef)
|
|
240
|
-
ingredientsCount.astFunctionDef.returns = job.shatteredDataclass.countingVariableAnnotation
|
|
241
|
-
|
|
242
|
-
ingredientsCount = move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsCount, job)
|
|
243
|
-
|
|
244
|
-
class DatatypeConfig(NamedTuple):
|
|
245
|
-
Z0Z_module: str_nameDOTname
|
|
246
|
-
fml: ast_Identifier
|
|
247
|
-
Z0Z_type_name: ast_Identifier
|
|
248
|
-
Z0Z_asname: ast_Identifier | None = None
|
|
249
|
-
|
|
250
|
-
listDatatypeConfigs = [
|
|
251
|
-
DatatypeConfig(fml='DatatypeLeavesTotal', Z0Z_module='numba', Z0Z_type_name='uint8'),
|
|
252
|
-
DatatypeConfig(fml='DatatypeElephino', Z0Z_module='numba', Z0Z_type_name='uint16'),
|
|
253
|
-
DatatypeConfig(fml='DatatypeFoldsTotal', Z0Z_module='numba', Z0Z_type_name='uint64'),
|
|
254
|
-
]
|
|
255
|
-
|
|
256
|
-
for datatypeConfig in listDatatypeConfigs:
|
|
257
|
-
ingredientsModule.imports.addImportFrom_asStr(datatypeConfig.Z0Z_module, datatypeConfig.Z0Z_type_name)
|
|
258
|
-
statement = Make.Assign(
|
|
259
|
-
[Make.Name(datatypeConfig.fml, ast.Store())],
|
|
260
|
-
Make.Name(datatypeConfig.Z0Z_type_name)
|
|
261
|
-
)
|
|
262
|
-
ingredientsModule.appendPrologue(statement=statement)
|
|
263
|
-
|
|
264
|
-
ingredientsCount.imports.removeImportFromModule('mapFolding.theSSOT')
|
|
265
|
-
|
|
266
|
-
listNumPyTypeConfigs = [
|
|
267
|
-
DatatypeConfig(fml='Array1DLeavesTotal', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array1DLeavesTotal'),
|
|
268
|
-
DatatypeConfig(fml='Array1DElephino', Z0Z_module='numpy', Z0Z_type_name='uint16', Z0Z_asname='Array1DElephino'),
|
|
269
|
-
DatatypeConfig(fml='Array3D', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array3D'),
|
|
270
|
-
]
|
|
271
|
-
|
|
272
|
-
for typeConfig in listNumPyTypeConfigs:
|
|
273
|
-
ingredientsCount.imports.removeImportFrom(typeConfig.Z0Z_module, None, typeConfig.fml)
|
|
274
|
-
ingredientsCount.imports.addImportFrom_asStr(typeConfig.Z0Z_module, typeConfig.Z0Z_type_name, typeConfig.Z0Z_asname)
|
|
275
|
-
|
|
276
|
-
ingredientsCount.astFunctionDef.decorator_list = [] # TODO low-priority, handle this more elegantly
|
|
277
|
-
# TODO when I add the function signature in numba style back to the decorator, the logic needs to handle `ProgressBarType:`
|
|
278
|
-
ingredientsCount = decorateCallableWithNumba(ingredientsCount, spices.parametersNumba)
|
|
279
|
-
|
|
280
|
-
ingredientsModule.appendIngredientsFunction(ingredientsCount)
|
|
281
|
-
write_astModule(ingredientsModule, job.pathFilenameModule, job.packageIdentifier)
|
|
282
|
-
|
|
283
|
-
"""
|
|
284
|
-
Overview
|
|
285
|
-
- the code starts life in theDao.py, which has many optimizations;
|
|
286
|
-
- `makeNumbaOptimizedFlow` increase optimization especially by using numba;
|
|
287
|
-
- `makeJobNumba` increases optimization especially by limiting its capabilities to just one set of parameters
|
|
288
|
-
- the synthesized module must run well as a standalone interpreted-Python script
|
|
289
|
-
- the next major optimization step will (probably) be to use the module synthesized by `makeJobNumba` to compile a standalone executable
|
|
290
|
-
- 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
|
|
291
|
-
|
|
292
|
-
Necessary
|
|
293
|
-
- Move the function's parameters to the function body,
|
|
294
|
-
- initialize identifiers with their state types and values,
|
|
295
|
-
|
|
296
|
-
Optimizations
|
|
297
|
-
- replace static-valued identifiers with their values
|
|
298
|
-
- narrowly focused imports
|
|
299
|
-
|
|
300
|
-
Minutia
|
|
301
|
-
- do not use `with` statement inside numba jitted code, except to use numba's obj mode
|
|
302
|
-
"""
|
|
303
|
-
|
|
304
|
-
if __name__ == '__main__':
|
|
305
|
-
mapShape = (1,46)
|
|
306
|
-
state = makeInitializedComputationState(mapShape)
|
|
307
|
-
# foldsTotalEstimated = getFoldsTotalKnown(state.mapShape) // state.leavesTotal
|
|
308
|
-
# foldsTotalEstimated = dictionaryEstimates[state.mapShape] // state.leavesTotal
|
|
309
|
-
foldsTotalEstimated = 0
|
|
310
|
-
pathModule = PurePosixPath(The.pathPackage, 'jobs')
|
|
311
|
-
pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
|
|
312
|
-
aJob = RecipeJob(state, foldsTotalEstimated, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
|
|
313
|
-
spices = SpicesJobNumba(useNumbaProgressBar=False, parametersNumba=parametersNumbaLight)
|
|
314
|
-
# spices = SpicesJobNumba()
|
|
315
|
-
makeJobNumba(aJob, spices)
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
from concurrent.futures import Future as ConcurrentFuture, ProcessPoolExecutor
|
|
2
|
-
from copy import deepcopy
|
|
3
|
-
from mapFolding import ComputationState
|
|
4
|
-
from mapFolding import Array1DElephino, Array1DFoldsTotal, Array1DLeavesTotal, Array3D, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal
|
|
5
|
-
from numba import jit
|
|
6
|
-
|
|
7
|
-
def countInitialize(state: ComputationState) -> ComputationState:
|
|
8
|
-
while state.gap1ndex == 0:
|
|
9
|
-
if state.leaf1ndex <= 1 or state.leafBelow[0] == 1:
|
|
10
|
-
state.dimensionsUnconstrained = state.dimensionsTotal
|
|
11
|
-
state.gap1ndexCeiling = state.gapRangeStart[state.leaf1ndex - 1]
|
|
12
|
-
state.indexDimension = 0
|
|
13
|
-
while state.indexDimension < state.dimensionsTotal:
|
|
14
|
-
state.leafConnectee = state.connectionGraph[state.indexDimension, state.leaf1ndex, state.leaf1ndex]
|
|
15
|
-
if state.leafConnectee == state.leaf1ndex:
|
|
16
|
-
state.dimensionsUnconstrained -= 1
|
|
17
|
-
else:
|
|
18
|
-
while state.leafConnectee != state.leaf1ndex:
|
|
19
|
-
state.gapsWhere[state.gap1ndexCeiling] = state.leafConnectee
|
|
20
|
-
if state.countDimensionsGapped[state.leafConnectee] == 0:
|
|
21
|
-
state.gap1ndexCeiling += 1
|
|
22
|
-
state.countDimensionsGapped[state.leafConnectee] += 1
|
|
23
|
-
state.leafConnectee = state.connectionGraph[state.indexDimension, state.leaf1ndex, state.leafBelow[state.leafConnectee]]
|
|
24
|
-
state.indexDimension += 1
|
|
25
|
-
if not state.dimensionsUnconstrained:
|
|
26
|
-
state.indexLeaf = 0
|
|
27
|
-
while state.indexLeaf < state.leaf1ndex:
|
|
28
|
-
state.gapsWhere[state.gap1ndexCeiling] = state.indexLeaf
|
|
29
|
-
state.gap1ndexCeiling += 1
|
|
30
|
-
state.indexLeaf += 1
|
|
31
|
-
state.indexMiniGap = state.gap1ndex
|
|
32
|
-
while state.indexMiniGap < state.gap1ndexCeiling:
|
|
33
|
-
state.gapsWhere[state.gap1ndex] = state.gapsWhere[state.indexMiniGap]
|
|
34
|
-
if state.countDimensionsGapped[state.gapsWhere[state.indexMiniGap]] == state.dimensionsUnconstrained:
|
|
35
|
-
state.gap1ndex += 1
|
|
36
|
-
state.countDimensionsGapped[state.gapsWhere[state.indexMiniGap]] = 0
|
|
37
|
-
state.indexMiniGap += 1
|
|
38
|
-
if state.leaf1ndex > 0:
|
|
39
|
-
state.gap1ndex -= 1
|
|
40
|
-
state.leafAbove[state.leaf1ndex] = state.gapsWhere[state.gap1ndex]
|
|
41
|
-
state.leafBelow[state.leaf1ndex] = state.leafBelow[state.leafAbove[state.leaf1ndex]]
|
|
42
|
-
state.leafBelow[state.leafAbove[state.leaf1ndex]] = state.leaf1ndex
|
|
43
|
-
state.leafAbove[state.leafBelow[state.leaf1ndex]] = state.leaf1ndex
|
|
44
|
-
state.gapRangeStart[state.leaf1ndex] = state.gap1ndex
|
|
45
|
-
state.leaf1ndex += 1
|
|
46
|
-
return state
|
|
47
|
-
|
|
48
|
-
@jit(_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)
|
|
49
|
-
def countParallel(leavesTotal: DatatypeLeavesTotal, taskDivisions: DatatypeLeavesTotal, connectionGraph: Array3D, dimensionsTotal: DatatypeLeavesTotal, countDimensionsGapped: Array1DLeavesTotal, dimensionsUnconstrained: DatatypeLeavesTotal, gapRangeStart: Array1DElephino, gapsWhere: Array1DLeavesTotal, leafAbove: Array1DLeavesTotal, leafBelow: Array1DLeavesTotal, foldGroups: Array1DFoldsTotal, gap1ndex: DatatypeElephino, gap1ndexCeiling: DatatypeElephino, groupsOfFolds: DatatypeFoldsTotal, indexDimension: DatatypeLeavesTotal, indexMiniGap: DatatypeElephino, leaf1ndex: DatatypeLeavesTotal, leafConnectee: DatatypeLeavesTotal, taskIndex: DatatypeLeavesTotal) -> DatatypeFoldsTotal:
|
|
50
|
-
while leaf1ndex > 0:
|
|
51
|
-
if leaf1ndex <= 1 or leafBelow[0] == 1:
|
|
52
|
-
if leaf1ndex > leavesTotal:
|
|
53
|
-
groupsOfFolds += 1
|
|
54
|
-
else:
|
|
55
|
-
dimensionsUnconstrained = dimensionsTotal
|
|
56
|
-
gap1ndexCeiling = gapRangeStart[leaf1ndex - 1]
|
|
57
|
-
indexDimension = 0
|
|
58
|
-
while indexDimension < dimensionsTotal:
|
|
59
|
-
if connectionGraph[indexDimension, leaf1ndex, leaf1ndex] == leaf1ndex:
|
|
60
|
-
dimensionsUnconstrained -= 1
|
|
61
|
-
else:
|
|
62
|
-
leafConnectee = connectionGraph[indexDimension, leaf1ndex, leaf1ndex]
|
|
63
|
-
while leafConnectee != leaf1ndex:
|
|
64
|
-
if leaf1ndex != taskDivisions or leafConnectee % taskDivisions == taskIndex:
|
|
65
|
-
gapsWhere[gap1ndexCeiling] = leafConnectee
|
|
66
|
-
if countDimensionsGapped[leafConnectee] == 0:
|
|
67
|
-
gap1ndexCeiling += 1
|
|
68
|
-
countDimensionsGapped[leafConnectee] += 1
|
|
69
|
-
leafConnectee = connectionGraph[indexDimension, leaf1ndex, leafBelow[leafConnectee]]
|
|
70
|
-
indexDimension += 1
|
|
71
|
-
indexMiniGap = gap1ndex
|
|
72
|
-
while indexMiniGap < gap1ndexCeiling:
|
|
73
|
-
gapsWhere[gap1ndex] = gapsWhere[indexMiniGap]
|
|
74
|
-
if countDimensionsGapped[gapsWhere[indexMiniGap]] == dimensionsUnconstrained:
|
|
75
|
-
gap1ndex += 1
|
|
76
|
-
countDimensionsGapped[gapsWhere[indexMiniGap]] = 0
|
|
77
|
-
indexMiniGap += 1
|
|
78
|
-
while leaf1ndex > 0 and gap1ndex == gapRangeStart[leaf1ndex - 1]:
|
|
79
|
-
leaf1ndex -= 1
|
|
80
|
-
leafBelow[leafAbove[leaf1ndex]] = leafBelow[leaf1ndex]
|
|
81
|
-
leafAbove[leafBelow[leaf1ndex]] = leafAbove[leaf1ndex]
|
|
82
|
-
if leaf1ndex > 0:
|
|
83
|
-
gap1ndex -= 1
|
|
84
|
-
leafAbove[leaf1ndex] = gapsWhere[gap1ndex]
|
|
85
|
-
leafBelow[leaf1ndex] = leafBelow[leafAbove[leaf1ndex]]
|
|
86
|
-
leafBelow[leafAbove[leaf1ndex]] = leaf1ndex
|
|
87
|
-
leafAbove[leafBelow[leaf1ndex]] = leaf1ndex
|
|
88
|
-
gapRangeStart[leaf1ndex] = gap1ndex
|
|
89
|
-
leaf1ndex += 1
|
|
90
|
-
foldGroups[taskIndex] = groupsOfFolds
|
|
91
|
-
return groupsOfFolds
|
|
92
|
-
|
|
93
|
-
@jit(_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)
|
|
94
|
-
def countSequential(mapShape: tuple[DatatypeLeavesTotal, ...], leavesTotal: DatatypeLeavesTotal, taskDivisions: DatatypeLeavesTotal, concurrencyLimit: DatatypeElephino, connectionGraph: Array3D, dimensionsTotal: DatatypeLeavesTotal, countDimensionsGapped: Array1DLeavesTotal, dimensionsUnconstrained: DatatypeLeavesTotal, gapRangeStart: Array1DElephino, gapsWhere: Array1DLeavesTotal, leafAbove: Array1DLeavesTotal, leafBelow: Array1DLeavesTotal, foldGroups: Array1DFoldsTotal, foldsTotal: DatatypeFoldsTotal, gap1ndex: DatatypeElephino, gap1ndexCeiling: DatatypeElephino, groupsOfFolds: DatatypeFoldsTotal, indexDimension: DatatypeLeavesTotal, indexLeaf: DatatypeLeavesTotal, indexMiniGap: DatatypeElephino, leaf1ndex: DatatypeLeavesTotal, leafConnectee: DatatypeLeavesTotal, taskIndex: DatatypeLeavesTotal) -> tuple[tuple[DatatypeLeavesTotal, ...], DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeElephino, Array3D, DatatypeLeavesTotal, Array1DLeavesTotal, DatatypeLeavesTotal, Array1DElephino, Array1DLeavesTotal, Array1DLeavesTotal, Array1DLeavesTotal, Array1DFoldsTotal, DatatypeFoldsTotal, DatatypeElephino, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeElephino, DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeLeavesTotal]:
|
|
95
|
-
while leaf1ndex > 0:
|
|
96
|
-
if leaf1ndex <= 1 or leafBelow[0] == 1:
|
|
97
|
-
if leaf1ndex > leavesTotal:
|
|
98
|
-
groupsOfFolds += 1
|
|
99
|
-
else:
|
|
100
|
-
dimensionsUnconstrained = dimensionsTotal
|
|
101
|
-
gap1ndexCeiling = gapRangeStart[leaf1ndex - 1]
|
|
102
|
-
indexDimension = 0
|
|
103
|
-
while indexDimension < dimensionsTotal:
|
|
104
|
-
leafConnectee = connectionGraph[indexDimension, leaf1ndex, leaf1ndex]
|
|
105
|
-
if leafConnectee == leaf1ndex:
|
|
106
|
-
dimensionsUnconstrained -= 1
|
|
107
|
-
else:
|
|
108
|
-
while leafConnectee != leaf1ndex:
|
|
109
|
-
gapsWhere[gap1ndexCeiling] = leafConnectee
|
|
110
|
-
if countDimensionsGapped[leafConnectee] == 0:
|
|
111
|
-
gap1ndexCeiling += 1
|
|
112
|
-
countDimensionsGapped[leafConnectee] += 1
|
|
113
|
-
leafConnectee = connectionGraph[indexDimension, leaf1ndex, leafBelow[leafConnectee]]
|
|
114
|
-
indexDimension += 1
|
|
115
|
-
indexMiniGap = gap1ndex
|
|
116
|
-
while indexMiniGap < gap1ndexCeiling:
|
|
117
|
-
gapsWhere[gap1ndex] = gapsWhere[indexMiniGap]
|
|
118
|
-
if countDimensionsGapped[gapsWhere[indexMiniGap]] == dimensionsUnconstrained:
|
|
119
|
-
gap1ndex += 1
|
|
120
|
-
countDimensionsGapped[gapsWhere[indexMiniGap]] = 0
|
|
121
|
-
indexMiniGap += 1
|
|
122
|
-
while leaf1ndex > 0 and gap1ndex == gapRangeStart[leaf1ndex - 1]:
|
|
123
|
-
leaf1ndex -= 1
|
|
124
|
-
leafBelow[leafAbove[leaf1ndex]] = leafBelow[leaf1ndex]
|
|
125
|
-
leafAbove[leafBelow[leaf1ndex]] = leafAbove[leaf1ndex]
|
|
126
|
-
if leaf1ndex == 3 and groupsOfFolds:
|
|
127
|
-
groupsOfFolds *= 2
|
|
128
|
-
break
|
|
129
|
-
if leaf1ndex > 0:
|
|
130
|
-
gap1ndex -= 1
|
|
131
|
-
leafAbove[leaf1ndex] = gapsWhere[gap1ndex]
|
|
132
|
-
leafBelow[leaf1ndex] = leafBelow[leafAbove[leaf1ndex]]
|
|
133
|
-
leafBelow[leafAbove[leaf1ndex]] = leaf1ndex
|
|
134
|
-
leafAbove[leafBelow[leaf1ndex]] = leaf1ndex
|
|
135
|
-
gapRangeStart[leaf1ndex] = gap1ndex
|
|
136
|
-
leaf1ndex += 1
|
|
137
|
-
foldGroups[taskIndex] = groupsOfFolds
|
|
138
|
-
return (mapShape, leavesTotal, taskDivisions, concurrencyLimit, connectionGraph, dimensionsTotal, countDimensionsGapped, dimensionsUnconstrained, gapRangeStart, gapsWhere, leafAbove, leafBelow, foldGroups, foldsTotal, gap1ndex, gap1ndexCeiling, groupsOfFolds, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, taskIndex)
|
|
139
|
-
|
|
140
|
-
def doTheNeedful(state: ComputationState) -> ComputationState:
|
|
141
|
-
state = countInitialize(state)
|
|
142
|
-
if state.taskDivisions > 0:
|
|
143
|
-
dictionaryConcurrency: dict[int, ConcurrentFuture[ComputationState]] = {}
|
|
144
|
-
stateParallel = deepcopy(state)
|
|
145
|
-
with ProcessPoolExecutor(stateParallel.concurrencyLimit) as concurrencyManager:
|
|
146
|
-
for indexSherpa in range(stateParallel.taskDivisions):
|
|
147
|
-
state = deepcopy(stateParallel)
|
|
148
|
-
state.taskIndex = indexSherpa
|
|
149
|
-
mapShape: tuple[DatatypeLeavesTotal, ...] = state.mapShape
|
|
150
|
-
leavesTotal: DatatypeLeavesTotal = state.leavesTotal
|
|
151
|
-
taskDivisions: DatatypeLeavesTotal = state.taskDivisions
|
|
152
|
-
concurrencyLimit: DatatypeElephino = state.concurrencyLimit
|
|
153
|
-
connectionGraph: Array3D = state.connectionGraph
|
|
154
|
-
dimensionsTotal: DatatypeLeavesTotal = state.dimensionsTotal
|
|
155
|
-
countDimensionsGapped: Array1DLeavesTotal = state.countDimensionsGapped
|
|
156
|
-
dimensionsUnconstrained: DatatypeLeavesTotal = state.dimensionsUnconstrained
|
|
157
|
-
gapRangeStart: Array1DElephino = state.gapRangeStart
|
|
158
|
-
gapsWhere: Array1DLeavesTotal = state.gapsWhere
|
|
159
|
-
leafAbove: Array1DLeavesTotal = state.leafAbove
|
|
160
|
-
leafBelow: Array1DLeavesTotal = state.leafBelow
|
|
161
|
-
foldGroups: Array1DFoldsTotal = state.foldGroups
|
|
162
|
-
foldsTotal: DatatypeFoldsTotal = state.foldsTotal
|
|
163
|
-
gap1ndex: DatatypeElephino = state.gap1ndex
|
|
164
|
-
gap1ndexCeiling: DatatypeElephino = state.gap1ndexCeiling
|
|
165
|
-
groupsOfFolds: DatatypeFoldsTotal = state.groupsOfFolds
|
|
166
|
-
indexDimension: DatatypeLeavesTotal = state.indexDimension
|
|
167
|
-
indexLeaf: DatatypeLeavesTotal = state.indexLeaf
|
|
168
|
-
indexMiniGap: DatatypeElephino = state.indexMiniGap
|
|
169
|
-
leaf1ndex: DatatypeLeavesTotal = state.leaf1ndex
|
|
170
|
-
leafConnectee: DatatypeLeavesTotal = state.leafConnectee
|
|
171
|
-
taskIndex: DatatypeLeavesTotal = state.taskIndex
|
|
172
|
-
dictionaryConcurrency[indexSherpa] = concurrencyManager.submit(countParallel, leavesTotal, taskDivisions, connectionGraph, dimensionsTotal, countDimensionsGapped, dimensionsUnconstrained, gapRangeStart, gapsWhere, leafAbove, leafBelow, foldGroups, gap1ndex, gap1ndexCeiling, groupsOfFolds, indexDimension, indexMiniGap, leaf1ndex, leafConnectee, taskIndex)
|
|
173
|
-
for indexSherpa in range(stateParallel.taskDivisions):
|
|
174
|
-
stateParallel.foldGroups[indexSherpa] = dictionaryConcurrency[indexSherpa].result()
|
|
175
|
-
state = stateParallel
|
|
176
|
-
else:
|
|
177
|
-
mapShape: tuple[DatatypeLeavesTotal, ...] = state.mapShape
|
|
178
|
-
leavesTotal: DatatypeLeavesTotal = state.leavesTotal
|
|
179
|
-
taskDivisions: DatatypeLeavesTotal = state.taskDivisions
|
|
180
|
-
concurrencyLimit: DatatypeElephino = state.concurrencyLimit
|
|
181
|
-
connectionGraph: Array3D = state.connectionGraph
|
|
182
|
-
dimensionsTotal: DatatypeLeavesTotal = state.dimensionsTotal
|
|
183
|
-
countDimensionsGapped: Array1DLeavesTotal = state.countDimensionsGapped
|
|
184
|
-
dimensionsUnconstrained: DatatypeLeavesTotal = state.dimensionsUnconstrained
|
|
185
|
-
gapRangeStart: Array1DElephino = state.gapRangeStart
|
|
186
|
-
gapsWhere: Array1DLeavesTotal = state.gapsWhere
|
|
187
|
-
leafAbove: Array1DLeavesTotal = state.leafAbove
|
|
188
|
-
leafBelow: Array1DLeavesTotal = state.leafBelow
|
|
189
|
-
foldGroups: Array1DFoldsTotal = state.foldGroups
|
|
190
|
-
foldsTotal: DatatypeFoldsTotal = state.foldsTotal
|
|
191
|
-
gap1ndex: DatatypeElephino = state.gap1ndex
|
|
192
|
-
gap1ndexCeiling: DatatypeElephino = state.gap1ndexCeiling
|
|
193
|
-
groupsOfFolds: DatatypeFoldsTotal = state.groupsOfFolds
|
|
194
|
-
indexDimension: DatatypeLeavesTotal = state.indexDimension
|
|
195
|
-
indexLeaf: DatatypeLeavesTotal = state.indexLeaf
|
|
196
|
-
indexMiniGap: DatatypeElephino = state.indexMiniGap
|
|
197
|
-
leaf1ndex: DatatypeLeavesTotal = state.leaf1ndex
|
|
198
|
-
leafConnectee: DatatypeLeavesTotal = state.leafConnectee
|
|
199
|
-
taskIndex: DatatypeLeavesTotal = state.taskIndex
|
|
200
|
-
mapShape, leavesTotal, taskDivisions, concurrencyLimit, connectionGraph, dimensionsTotal, countDimensionsGapped, dimensionsUnconstrained, gapRangeStart, gapsWhere, leafAbove, leafBelow, foldGroups, foldsTotal, gap1ndex, gap1ndexCeiling, groupsOfFolds, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, taskIndex = countSequential(mapShape, leavesTotal, taskDivisions, concurrencyLimit, connectionGraph, dimensionsTotal, countDimensionsGapped, dimensionsUnconstrained, gapRangeStart, gapsWhere, leafAbove, leafBelow, foldGroups, foldsTotal, gap1ndex, gap1ndexCeiling, groupsOfFolds, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, taskIndex)
|
|
201
|
-
state = ComputationState(mapShape=mapShape, leavesTotal=leavesTotal, taskDivisions=taskDivisions, concurrencyLimit=concurrencyLimit, countDimensionsGapped=countDimensionsGapped, dimensionsUnconstrained=dimensionsUnconstrained, gapRangeStart=gapRangeStart, gapsWhere=gapsWhere, leafAbove=leafAbove, leafBelow=leafBelow, foldGroups=foldGroups, foldsTotal=foldsTotal, gap1ndex=gap1ndex, gap1ndexCeiling=gap1ndexCeiling, groupsOfFolds=groupsOfFolds, indexDimension=indexDimension, indexLeaf=indexLeaf, indexMiniGap=indexMiniGap, leaf1ndex=leaf1ndex, leafConnectee=leafConnectee, taskIndex=taskIndex)
|
|
202
|
-
return state
|