mapFolding 0.12.0__py3-none-any.whl → 0.12.2__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 +42 -18
- mapFolding/_theSSOT.py +137 -0
- mapFolding/basecamp.py +28 -18
- mapFolding/beDRY.py +21 -19
- mapFolding/dataBaskets.py +170 -18
- mapFolding/datatypes.py +109 -1
- mapFolding/filesystemToolkit.py +38 -33
- mapFolding/oeis.py +209 -93
- mapFolding/someAssemblyRequired/RecipeJob.py +120 -9
- mapFolding/someAssemblyRequired/__init__.py +35 -38
- mapFolding/someAssemblyRequired/_toolIfThis.py +80 -18
- mapFolding/someAssemblyRequired/_toolkitContainers.py +123 -45
- mapFolding/someAssemblyRequired/infoBooth.py +37 -2
- mapFolding/someAssemblyRequired/makeAllModules.py +712 -0
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +111 -48
- mapFolding/someAssemblyRequired/toolkitNumba.py +171 -19
- mapFolding/someAssemblyRequired/transformationTools.py +93 -49
- mapfolding-0.12.2.dist-info/METADATA +167 -0
- mapfolding-0.12.2.dist-info/RECORD +53 -0
- {mapfolding-0.12.0.dist-info → mapfolding-0.12.2.dist-info}/WHEEL +1 -1
- tests/__init__.py +28 -44
- tests/conftest.py +66 -61
- tests/test_computations.py +39 -82
- tests/test_filesystem.py +25 -1
- tests/test_oeis.py +30 -1
- tests/test_other.py +27 -0
- tests/test_tasks.py +31 -1
- mapFolding/someAssemblyRequired/Z0Z_makeAllModules.py +0 -433
- mapFolding/theSSOT.py +0 -34
- mapfolding-0.12.0.dist-info/METADATA +0 -184
- mapfolding-0.12.0.dist-info/RECORD +0 -53
- {mapfolding-0.12.0.dist-info → mapfolding-0.12.2.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.12.0.dist-info → mapfolding-0.12.2.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.12.0.dist-info → mapfolding-0.12.2.dist-info}/top_level.txt +0 -0
|
@@ -1,433 +0,0 @@
|
|
|
1
|
-
from astToolkit import (
|
|
2
|
-
astModuleToIngredientsFunction,
|
|
3
|
-
Be,
|
|
4
|
-
ClassIsAndAttribute,
|
|
5
|
-
DOT,
|
|
6
|
-
extractClassDef,
|
|
7
|
-
extractFunctionDef,
|
|
8
|
-
Grab,
|
|
9
|
-
IngredientsFunction,
|
|
10
|
-
IngredientsModule,
|
|
11
|
-
LedgerOfImports,
|
|
12
|
-
Make,
|
|
13
|
-
NodeChanger,
|
|
14
|
-
NodeTourist,
|
|
15
|
-
parseLogicalPath2astModule,
|
|
16
|
-
parsePathFilename2astModule,
|
|
17
|
-
str_nameDOTname,
|
|
18
|
-
Then,
|
|
19
|
-
)
|
|
20
|
-
from astToolkit.transformationTools import inlineFunctionDef, removeUnusedParameters, write_astModule
|
|
21
|
-
from collections.abc import Sequence
|
|
22
|
-
from mapFolding import packageSettings
|
|
23
|
-
from mapFolding.someAssemblyRequired import (
|
|
24
|
-
DeReConstructField2ast,
|
|
25
|
-
IfThis,
|
|
26
|
-
raiseIfNone,
|
|
27
|
-
ShatteredDataclass,
|
|
28
|
-
sourceCallableDispatcherDEFAULT,
|
|
29
|
-
)
|
|
30
|
-
from mapFolding.someAssemblyRequired.infoBooth import algorithmSourceModuleDEFAULT, dataPackingModuleIdentifierDEFAULT, logicalPathInfixDEFAULT, sourceCallableIdentifierDEFAULT, theCountingIdentifierDEFAULT
|
|
31
|
-
from mapFolding.someAssemblyRequired.toolkitNumba import decorateCallableWithNumba, parametersNumbaLight
|
|
32
|
-
from mapFolding.someAssemblyRequired.transformationTools import (
|
|
33
|
-
removeDataclassFromFunction,
|
|
34
|
-
shatter_dataclassesDOTdataclass,
|
|
35
|
-
unpackDataclassCallFunctionRepackDataclass,
|
|
36
|
-
)
|
|
37
|
-
from os import PathLike
|
|
38
|
-
from pathlib import PurePath
|
|
39
|
-
from typing import cast
|
|
40
|
-
from Z0Z_tools import importLogicalPath2Callable
|
|
41
|
-
import ast
|
|
42
|
-
import dataclasses
|
|
43
|
-
|
|
44
|
-
def findDataclass(ingredientsFunction: IngredientsFunction) -> tuple[str, str, str]:
|
|
45
|
-
dataclassName: ast.expr = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.annotation)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
46
|
-
dataclass_Identifier: str = raiseIfNone(NodeTourist(Be.Name, Then.extractIt(DOT.id)).captureLastMatch(dataclassName))
|
|
47
|
-
dataclassLogicalPathModule = None
|
|
48
|
-
for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports.dictionaryImportFrom.items():
|
|
49
|
-
for nameTuple in listNameTuples:
|
|
50
|
-
if nameTuple[0] == dataclass_Identifier:
|
|
51
|
-
dataclassLogicalPathModule = moduleWithLogicalPath
|
|
52
|
-
break
|
|
53
|
-
if dataclassLogicalPathModule:
|
|
54
|
-
break
|
|
55
|
-
dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
56
|
-
return raiseIfNone(dataclassLogicalPathModule), dataclass_Identifier, dataclassInstanceIdentifier
|
|
57
|
-
|
|
58
|
-
def _getLogicalPath(packageName: str | None = None, logicalPathInfix: str | None = None, moduleIdentifier: str | None = None, *modules: str) -> str_nameDOTname:
|
|
59
|
-
listLogicalPathParts: list[str] = []
|
|
60
|
-
if packageName:
|
|
61
|
-
listLogicalPathParts.append(packageName)
|
|
62
|
-
if logicalPathInfix:
|
|
63
|
-
listLogicalPathParts.append(logicalPathInfix)
|
|
64
|
-
if moduleIdentifier:
|
|
65
|
-
listLogicalPathParts.append(moduleIdentifier)
|
|
66
|
-
if modules:
|
|
67
|
-
listLogicalPathParts.extend(modules)
|
|
68
|
-
logicalPath = '.'.join(listLogicalPathParts)
|
|
69
|
-
return logicalPath
|
|
70
|
-
|
|
71
|
-
def getModule(packageName: str | None = packageSettings.packageName, logicalPathInfix: str | None = logicalPathInfixDEFAULT, moduleIdentifier: str | None = algorithmSourceModuleDEFAULT) -> ast.Module:
|
|
72
|
-
logicalPathSourceModule = _getLogicalPath(packageName, logicalPathInfix, moduleIdentifier)
|
|
73
|
-
astModule = parseLogicalPath2astModule(logicalPathSourceModule)
|
|
74
|
-
return astModule
|
|
75
|
-
|
|
76
|
-
def _getPathFilename(pathRoot: PathLike[str] | PurePath | None = packageSettings.pathPackage, logicalPathInfix: PathLike[str] | PurePath | str | None = None, moduleIdentifier: str = '', fileExtension: str = packageSettings.fileExtension) -> PurePath:
|
|
77
|
-
pathFilename = PurePath(moduleIdentifier + fileExtension)
|
|
78
|
-
if logicalPathInfix:
|
|
79
|
-
pathFilename = PurePath(logicalPathInfix, pathFilename)
|
|
80
|
-
if pathRoot:
|
|
81
|
-
pathFilename = PurePath(pathRoot, pathFilename)
|
|
82
|
-
return pathFilename
|
|
83
|
-
|
|
84
|
-
def makeInitializeGroupsOfFolds(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
85
|
-
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
86
|
-
if callableIdentifier is None:
|
|
87
|
-
callableIdentifier = sourceCallableIdentifier
|
|
88
|
-
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
89
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
90
|
-
|
|
91
|
-
dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
92
|
-
theCountingIdentifier = theCountingIdentifierDEFAULT
|
|
93
|
-
|
|
94
|
-
findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
95
|
-
doThat = Grab.testAttribute(Grab.andDoAllOf([Grab.opsAttribute(Then.replaceWith([ast.Eq()])), Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier)))])) # pyright: ignore[reportArgumentType]
|
|
96
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef.body[0])
|
|
97
|
-
|
|
98
|
-
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
99
|
-
pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
100
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
|
|
101
|
-
|
|
102
|
-
return pathFilename
|
|
103
|
-
|
|
104
|
-
def makeDaoOfMapFolding(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
105
|
-
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
106
|
-
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
107
|
-
|
|
108
|
-
if callableIdentifier is None:
|
|
109
|
-
callableIdentifier = sourceCallableIdentifier
|
|
110
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
111
|
-
|
|
112
|
-
shatteredDataclass = shatter_dataclassesDOTdataclass(*findDataclass(ingredientsFunction))
|
|
113
|
-
|
|
114
|
-
ingredientsFunction.imports.update(shatteredDataclass.imports)
|
|
115
|
-
ingredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
|
|
116
|
-
ingredientsFunction = removeUnusedParameters(ingredientsFunction)
|
|
117
|
-
ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
|
|
118
|
-
|
|
119
|
-
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
120
|
-
|
|
121
|
-
if sourceCallableDispatcher is not None:
|
|
122
|
-
|
|
123
|
-
ingredientsFunctionDispatcher: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableDispatcher)
|
|
124
|
-
ingredientsFunctionDispatcher.imports.update(shatteredDataclass.imports)
|
|
125
|
-
targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
|
|
126
|
-
ingredientsFunctionDispatcher = unpackDataclassCallFunctionRepackDataclass(ingredientsFunctionDispatcher, targetCallableIdentifier, shatteredDataclass)
|
|
127
|
-
astTuple = raiseIfNone(NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
128
|
-
cast(ast.Tuple, astTuple).ctx = ast.Store()
|
|
129
|
-
|
|
130
|
-
findThis = ClassIsAndAttribute.valueIs(ast.Assign, IfThis.isCall_Identifier(targetCallableIdentifier))
|
|
131
|
-
doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), cast(ast.Tuple, astTuple).elts)))
|
|
132
|
-
changeAssignCallToTarget = NodeChanger(findThis, doThat)
|
|
133
|
-
changeAssignCallToTarget.visit(ingredientsFunctionDispatcher.astFunctionDef)
|
|
134
|
-
|
|
135
|
-
ingredientsModule.appendIngredientsFunction(ingredientsFunctionDispatcher)
|
|
136
|
-
|
|
137
|
-
ingredientsModule.removeImportFromModule('numpy')
|
|
138
|
-
|
|
139
|
-
pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
140
|
-
|
|
141
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
|
|
142
|
-
|
|
143
|
-
return pathFilename
|
|
144
|
-
|
|
145
|
-
def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
146
|
-
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
147
|
-
if callableIdentifier is None:
|
|
148
|
-
callableIdentifier = sourceCallableIdentifier
|
|
149
|
-
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
150
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
151
|
-
|
|
152
|
-
dataclassName: ast.expr = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.annotation)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
153
|
-
dataclass_Identifier: str = raiseIfNone(NodeTourist(Be.Name, Then.extractIt(DOT.id)).captureLastMatch(dataclassName))
|
|
154
|
-
|
|
155
|
-
dataclassLogicalPathModule = None
|
|
156
|
-
for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports.dictionaryImportFrom.items():
|
|
157
|
-
for nameTuple in listNameTuples:
|
|
158
|
-
if nameTuple[0] == dataclass_Identifier:
|
|
159
|
-
dataclassLogicalPathModule = moduleWithLogicalPath
|
|
160
|
-
break
|
|
161
|
-
if dataclassLogicalPathModule:
|
|
162
|
-
break
|
|
163
|
-
if dataclassLogicalPathModule is None: raise Exception
|
|
164
|
-
dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
165
|
-
shatteredDataclass = shatter_dataclassesDOTdataclass(dataclassLogicalPathModule, dataclass_Identifier, dataclassInstanceIdentifier)
|
|
166
|
-
|
|
167
|
-
# Start add the parallel state fields to the count function ================================================
|
|
168
|
-
dataclassBaseFields = dataclasses.fields(importLogicalPath2Callable(dataclassLogicalPathModule, dataclass_Identifier)) # pyright: ignore [reportArgumentType]
|
|
169
|
-
dataclass_IdentifierParallel = 'Parallel' + dataclass_Identifier
|
|
170
|
-
dataclassFieldsParallel = dataclasses.fields(importLogicalPath2Callable(dataclassLogicalPathModule, dataclass_IdentifierParallel)) # pyright: ignore [reportArgumentType]
|
|
171
|
-
onlyParallelFields = [field for field in dataclassFieldsParallel if field.name not in [fieldBase.name for fieldBase in dataclassBaseFields]]
|
|
172
|
-
|
|
173
|
-
Official_fieldOrder: list[str] = []
|
|
174
|
-
dictionaryDeReConstruction: dict[str, DeReConstructField2ast] = {}
|
|
175
|
-
|
|
176
|
-
dataclassClassDef = extractClassDef(parseLogicalPath2astModule(dataclassLogicalPathModule), dataclass_IdentifierParallel)
|
|
177
|
-
if not isinstance(dataclassClassDef, ast.ClassDef): raise ValueError(f"I could not find `{dataclass_IdentifierParallel = }` in `{dataclassLogicalPathModule = }`.")
|
|
178
|
-
|
|
179
|
-
for aField in onlyParallelFields:
|
|
180
|
-
Official_fieldOrder.append(aField.name)
|
|
181
|
-
dictionaryDeReConstruction[aField.name] = DeReConstructField2ast(dataclassLogicalPathModule, dataclassClassDef, dataclassInstanceIdentifier, aField)
|
|
182
|
-
|
|
183
|
-
shatteredDataclassParallel = ShatteredDataclass(
|
|
184
|
-
countingVariableAnnotation=shatteredDataclass.countingVariableAnnotation,
|
|
185
|
-
countingVariableName=shatteredDataclass.countingVariableName,
|
|
186
|
-
field2AnnAssign={**shatteredDataclass.field2AnnAssign, **{dictionaryDeReConstruction[field].name: dictionaryDeReConstruction[field].astAnnAssignConstructor for field in Official_fieldOrder}},
|
|
187
|
-
Z0Z_field2AnnAssign={**shatteredDataclass.Z0Z_field2AnnAssign, **{dictionaryDeReConstruction[field].name: dictionaryDeReConstruction[field].Z0Z_hack for field in Official_fieldOrder}},
|
|
188
|
-
list_argAnnotated4ArgumentsSpecification=shatteredDataclass.list_argAnnotated4ArgumentsSpecification + [dictionaryDeReConstruction[field].ast_argAnnotated for field in Official_fieldOrder],
|
|
189
|
-
list_keyword_field__field4init=shatteredDataclass.list_keyword_field__field4init + [dictionaryDeReConstruction[field].ast_keyword_field__field for field in Official_fieldOrder if dictionaryDeReConstruction[field].init],
|
|
190
|
-
listAnnotations=shatteredDataclass.listAnnotations + [dictionaryDeReConstruction[field].astAnnotation for field in Official_fieldOrder],
|
|
191
|
-
listName4Parameters=shatteredDataclass.listName4Parameters + [dictionaryDeReConstruction[field].astName for field in Official_fieldOrder],
|
|
192
|
-
listUnpack=shatteredDataclass.listUnpack + [Make.AnnAssign(dictionaryDeReConstruction[field].astName, dictionaryDeReConstruction[field].astAnnotation, dictionaryDeReConstruction[field].ast_nameDOTname) for field in Official_fieldOrder],
|
|
193
|
-
map_stateDOTfield2Name={**shatteredDataclass.map_stateDOTfield2Name, **{dictionaryDeReConstruction[field].ast_nameDOTname: dictionaryDeReConstruction[field].astName for field in Official_fieldOrder}},
|
|
194
|
-
)
|
|
195
|
-
shatteredDataclassParallel.fragments4AssignmentOrParameters = Make.Tuple(shatteredDataclassParallel.listName4Parameters, ast.Store())
|
|
196
|
-
shatteredDataclassParallel.repack = Make.Assign([Make.Name(dataclassInstanceIdentifier)], value=Make.Call(Make.Name(dataclass_IdentifierParallel), list_keyword=shatteredDataclassParallel.list_keyword_field__field4init))
|
|
197
|
-
shatteredDataclassParallel.signatureReturnAnnotation = Make.Subscript(Make.Name('tuple'), Make.Tuple(shatteredDataclassParallel.listAnnotations))
|
|
198
|
-
|
|
199
|
-
shatteredDataclassParallel.imports.update(*(dictionaryDeReConstruction[field].ledger for field in Official_fieldOrder))
|
|
200
|
-
shatteredDataclassParallel.imports.addImportFrom_asStr(dataclassLogicalPathModule, dataclass_IdentifierParallel)
|
|
201
|
-
shatteredDataclassParallel.imports.update(shatteredDataclass.imports)
|
|
202
|
-
shatteredDataclassParallel.imports.removeImportFrom(dataclassLogicalPathModule, dataclass_Identifier)
|
|
203
|
-
|
|
204
|
-
# End add the parallel state fields to the count function ================================================
|
|
205
|
-
|
|
206
|
-
ingredientsFunction.imports.update(shatteredDataclassParallel.imports)
|
|
207
|
-
ingredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclassParallel)
|
|
208
|
-
|
|
209
|
-
# Start add the parallel logic to the count function ================================================
|
|
210
|
-
|
|
211
|
-
findThis = ClassIsAndAttribute.testIs(ast.While, ClassIsAndAttribute.leftIs(ast.Compare, IfThis.isName_Identifier('leafConnectee')))
|
|
212
|
-
doThat = Then.extractIt(DOT.body)
|
|
213
|
-
captureCountGapsCodeBlock: NodeTourist[ast.While, Sequence[ast.stmt]] = NodeTourist(findThis, doThat)
|
|
214
|
-
countGapsCodeBlock = raiseIfNone(captureCountGapsCodeBlock.captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
215
|
-
|
|
216
|
-
thisIsMyTaskIndexCodeBlock = ast.If(ast.BoolOp(ast.Or()
|
|
217
|
-
, values=[ast.Compare(ast.Name('leaf1ndex'), ops=[ast.NotEq()], comparators=[ast.Name('taskDivisions')])
|
|
218
|
-
, ast.Compare(ast.BinOp(ast.Name('leafConnectee'), op=ast.Mod(), right=ast.Name('taskDivisions')), ops=[ast.Eq()], comparators=[ast.Name('taskIndex')])])
|
|
219
|
-
, body=list(countGapsCodeBlock[0:-1]))
|
|
220
|
-
|
|
221
|
-
countGapsCodeBlockNew: list[ast.stmt] = [thisIsMyTaskIndexCodeBlock, countGapsCodeBlock[-1]]
|
|
222
|
-
|
|
223
|
-
doThat = Grab.bodyAttribute(Then.replaceWith(countGapsCodeBlockNew))
|
|
224
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
225
|
-
|
|
226
|
-
# End add the parallel logic to the count function ================================================
|
|
227
|
-
|
|
228
|
-
ingredientsFunction = removeUnusedParameters(ingredientsFunction)
|
|
229
|
-
|
|
230
|
-
ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
|
|
231
|
-
|
|
232
|
-
# Start unpack/repack the dataclass function ================================================
|
|
233
|
-
sourceCallableIdentifier = sourceCallableDispatcherDEFAULT
|
|
234
|
-
|
|
235
|
-
unRepackDataclass: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableIdentifier)
|
|
236
|
-
unRepackDataclass.astFunctionDef.name = 'unRepack' + dataclass_IdentifierParallel
|
|
237
|
-
unRepackDataclass.imports.update(shatteredDataclassParallel.imports)
|
|
238
|
-
findThis = ClassIsAndAttribute.annotationIs(ast.arg, IfThis.isName_Identifier(dataclass_Identifier)) # pyright: ignore[reportArgumentType, reportUnknownVariableType, reportCallIssue]
|
|
239
|
-
doThat = Grab.annotationAttribute(Grab.idAttribute(Then.replaceWith(dataclass_IdentifierParallel))) # pyright: ignore[reportArgumentType]
|
|
240
|
-
NodeChanger(findThis, doThat).visit(unRepackDataclass.astFunctionDef) # pyright: ignore[reportUnknownArgumentType]
|
|
241
|
-
unRepackDataclass.astFunctionDef.returns = Make.Name(dataclass_IdentifierParallel)
|
|
242
|
-
targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
|
|
243
|
-
unRepackDataclass = unpackDataclassCallFunctionRepackDataclass(unRepackDataclass, targetCallableIdentifier, shatteredDataclassParallel)
|
|
244
|
-
|
|
245
|
-
astTuple = raiseIfNone(NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
246
|
-
cast(ast.Tuple, astTuple).ctx = ast.Store()
|
|
247
|
-
findThis = ClassIsAndAttribute.valueIs(ast.Assign, IfThis.isCall_Identifier(targetCallableIdentifier))
|
|
248
|
-
doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), cast(ast.Tuple, astTuple).elts)))
|
|
249
|
-
changeAssignCallToTarget = NodeChanger(findThis, doThat)
|
|
250
|
-
changeAssignCallToTarget.visit(unRepackDataclass.astFunctionDef)
|
|
251
|
-
|
|
252
|
-
ingredientsDoTheNeedful: IngredientsFunction = IngredientsFunction(
|
|
253
|
-
astFunctionDef = ast.FunctionDef(name='doTheNeedful'
|
|
254
|
-
, args=ast.arguments(args=[ast.arg('state', annotation=ast.Name(dataclass_IdentifierParallel)), ast.arg('concurrencyLimit', annotation=ast.Name('int'))])
|
|
255
|
-
, body=[ast.Assign(targets=[ast.Name('stateParallel', ctx=ast.Store())], value=ast.Call(func=ast.Name('deepcopy'), args=[ast.Name('state')]))
|
|
256
|
-
, ast.AnnAssign(target=ast.Name('listStatesParallel', ctx=ast.Store()), annotation=ast.Subscript(value=ast.Name('list'), slice=ast.Name(dataclass_IdentifierParallel)), value=ast.BinOp(left=ast.List(elts=[ast.Name('stateParallel')]), op=ast.Mult(), right=ast.Attribute(value=ast.Name('stateParallel'), attr='taskDivisions')), simple=1)
|
|
257
|
-
, ast.AnnAssign(target=ast.Name('groupsOfFoldsTotal', ctx=ast.Store()), annotation=ast.Name('int'), value=ast.Constant(value=0), simple=1)
|
|
258
|
-
|
|
259
|
-
, ast.AnnAssign(target=ast.Name('dictionaryConcurrency', ctx=ast.Store()), annotation=ast.Subscript(value=ast.Name('dict'), slice=ast.Tuple(elts=[ast.Name('int'), ast.Subscript(value=ast.Name('ConcurrentFuture'), slice=ast.Name(dataclass_IdentifierParallel))])), value=ast.Dict(), simple=1)
|
|
260
|
-
, ast.With(items=[ast.withitem(context_expr=ast.Call(func=ast.Name('ProcessPoolExecutor'), args=[ast.Name('concurrencyLimit')]), optional_vars=ast.Name('concurrencyManager', ctx=ast.Store()))]
|
|
261
|
-
, body=[ast.For(target=ast.Name('indexSherpa', ctx=ast.Store()), iter=ast.Call(func=ast.Name('range'), args=[ast.Attribute(value=ast.Name('stateParallel'), attr='taskDivisions')])
|
|
262
|
-
, body=[ast.Assign(targets=[ast.Name('state', ctx=ast.Store())], value=ast.Call(func=ast.Name('deepcopy'), args=[ast.Name('stateParallel')]))
|
|
263
|
-
, ast.Assign(targets=[ast.Attribute(value=ast.Name('state'), attr='taskIndex', ctx=ast.Store())], value=ast.Name('indexSherpa'))
|
|
264
|
-
, ast.Assign(targets=[ast.Subscript(value=ast.Name('dictionaryConcurrency'), slice=ast.Name('indexSherpa'), ctx=ast.Store())], value=ast.Call(func=ast.Attribute(value=ast.Name('concurrencyManager'), attr='submit'), args=[ast.Name(unRepackDataclass.astFunctionDef.name), ast.Name('state')]))])
|
|
265
|
-
, ast.For(target=ast.Name('indexSherpa', ctx=ast.Store()), iter=ast.Call(func=ast.Name('range'), args=[ast.Attribute(value=ast.Name('stateParallel'), attr='taskDivisions')])
|
|
266
|
-
, body=[ast.Assign(targets=[ast.Subscript(value=ast.Name('listStatesParallel'), slice=ast.Name('indexSherpa'), ctx=ast.Store())], value=ast.Call(func=ast.Attribute(value=ast.Subscript(value=ast.Name('dictionaryConcurrency'), slice=ast.Name('indexSherpa')), attr='result')))
|
|
267
|
-
, ast.AugAssign(target=ast.Name('groupsOfFoldsTotal', ctx=ast.Store()), op=ast.Add(), value=ast.Attribute(value=ast.Subscript(value=ast.Name('listStatesParallel'), slice=ast.Name('indexSherpa')), attr='groupsOfFolds'))])])
|
|
268
|
-
|
|
269
|
-
, ast.AnnAssign(target=ast.Name('foldsTotal', ctx=ast.Store()), annotation=ast.Name('int'), value=ast.BinOp(left=ast.Name('groupsOfFoldsTotal'), op=ast.Mult(), right=ast.Attribute(value=ast.Name('stateParallel'), attr='leavesTotal')), simple=1)
|
|
270
|
-
, ast.Return(value=ast.Tuple(elts=[ast.Name('foldsTotal'), ast.Name('listStatesParallel')]))]
|
|
271
|
-
, returns=ast.Subscript(value=ast.Name('tuple'), slice=ast.Tuple(elts=[ast.Name('int'), ast.Subscript(value=ast.Name('list'), slice=ast.Name(dataclass_IdentifierParallel))])))
|
|
272
|
-
, imports = LedgerOfImports(Make.Module([ast.ImportFrom(module='concurrent.futures', names=[ast.alias(name='Future', asname='ConcurrentFuture'), ast.alias(name='ProcessPoolExecutor')], level=0),
|
|
273
|
-
ast.ImportFrom(module='copy', names=[ast.alias(name='deepcopy')], level=0),
|
|
274
|
-
ast.ImportFrom(module='multiprocessing', names=[ast.alias(name='set_start_method', asname='multiprocessing_set_start_method')], level=0),])
|
|
275
|
-
)
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
ingredientsModule = IngredientsModule([ingredientsFunction, unRepackDataclass, ingredientsDoTheNeedful]
|
|
279
|
-
, prologue = Make.Module([ast.If(test=ast.Compare(left=ast.Name('__name__'), ops=[ast.Eq()], comparators=[ast.Constant(value='__main__')]), body=[ast.Expr(value=ast.Call(func=ast.Name('multiprocessing_set_start_method'), args=[ast.Constant(value='spawn')]))])])
|
|
280
|
-
)
|
|
281
|
-
ingredientsModule.removeImportFromModule('numpy')
|
|
282
|
-
|
|
283
|
-
pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
284
|
-
|
|
285
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
|
|
286
|
-
return pathFilename
|
|
287
|
-
|
|
288
|
-
def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
289
|
-
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
290
|
-
if callableIdentifier is None:
|
|
291
|
-
callableIdentifier = sourceCallableIdentifier
|
|
292
|
-
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
293
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
294
|
-
|
|
295
|
-
dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
296
|
-
|
|
297
|
-
findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
298
|
-
doThat = Grab.testAttribute(Grab.comparatorsAttribute(Then.replaceWith([Make.Constant(4)]))) # pyright: ignore[reportArgumentType]
|
|
299
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
300
|
-
|
|
301
|
-
findThis = IfThis.isIfAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
302
|
-
doThat = Then.extractIt(DOT.body)
|
|
303
|
-
insertLeaf = NodeTourist(findThis, doThat).captureLastMatch(ingredientsFunction.astFunctionDef)
|
|
304
|
-
findThis = IfThis.isIfAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
305
|
-
doThat = Then.replaceWith(insertLeaf)
|
|
306
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
307
|
-
|
|
308
|
-
findThis = IfThis.isAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
309
|
-
doThat = Then.removeIt
|
|
310
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
311
|
-
|
|
312
|
-
findThis = IfThis.isAttributeNamespaceIdentifierLessThanOrEqual0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
313
|
-
doThat = Then.removeIt
|
|
314
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
315
|
-
|
|
316
|
-
theCountingIdentifier = theCountingIdentifierDEFAULT
|
|
317
|
-
doubleTheCount = Make.AugAssign(Make.Attribute(ast.Name(dataclassInstanceIdentifier), theCountingIdentifier), ast.Mult(), Make.Constant(2))
|
|
318
|
-
findThis = Be.Return
|
|
319
|
-
doThat = Then.insertThisAbove([doubleTheCount])
|
|
320
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
321
|
-
|
|
322
|
-
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
323
|
-
|
|
324
|
-
if sourceCallableDispatcher is not None:
|
|
325
|
-
raise NotImplementedError('sourceCallableDispatcher is not implemented yet')
|
|
326
|
-
|
|
327
|
-
pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
328
|
-
|
|
329
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
|
|
330
|
-
|
|
331
|
-
return pathFilename
|
|
332
|
-
|
|
333
|
-
def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
334
|
-
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
335
|
-
if callableIdentifier is None:
|
|
336
|
-
callableIdentifier = sourceCallableIdentifier
|
|
337
|
-
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
338
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
339
|
-
|
|
340
|
-
dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
341
|
-
|
|
342
|
-
findThis = IfThis.isIfUnaryNotAttributeNamespace_Identifier(dataclassInstanceIdentifier, 'dimensionsUnconstrained')
|
|
343
|
-
doThat = Then.removeIt
|
|
344
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
345
|
-
|
|
346
|
-
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
347
|
-
ingredientsModule.removeImportFromModule('numpy')
|
|
348
|
-
|
|
349
|
-
pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
350
|
-
|
|
351
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
|
|
352
|
-
|
|
353
|
-
return pathFilename
|
|
354
|
-
|
|
355
|
-
def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
356
|
-
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
357
|
-
if callableIdentifier is None:
|
|
358
|
-
callableIdentifier = sourceCallableIdentifier
|
|
359
|
-
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
360
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
361
|
-
|
|
362
|
-
shatteredDataclass = shatter_dataclassesDOTdataclass(*findDataclass(ingredientsFunction))
|
|
363
|
-
|
|
364
|
-
ingredientsFunction.imports.update(shatteredDataclass.imports)
|
|
365
|
-
ingredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
|
|
366
|
-
ingredientsFunction = removeUnusedParameters(ingredientsFunction)
|
|
367
|
-
ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
|
|
368
|
-
|
|
369
|
-
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
370
|
-
ingredientsModule.removeImportFromModule('numpy')
|
|
371
|
-
|
|
372
|
-
pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
373
|
-
|
|
374
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
|
|
375
|
-
|
|
376
|
-
return pathFilename
|
|
377
|
-
|
|
378
|
-
def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
|
|
379
|
-
callableIdentifierHARDCODED: str = 'sequential'
|
|
380
|
-
|
|
381
|
-
algorithmSourceModule = algorithmSourceModuleDEFAULT
|
|
382
|
-
sourceCallableIdentifier = sourceCallableDispatcherDEFAULT
|
|
383
|
-
logicalPathSourceModule = '.'.join([packageSettings.packageName, algorithmSourceModule])
|
|
384
|
-
|
|
385
|
-
logicalPathInfix = logicalPathInfixDEFAULT
|
|
386
|
-
moduleIdentifier = dataPackingModuleIdentifierDEFAULT
|
|
387
|
-
callableIdentifier = callableIdentifierHARDCODED
|
|
388
|
-
|
|
389
|
-
ingredientsFunction: IngredientsFunction = astModuleToIngredientsFunction(parseLogicalPath2astModule(logicalPathSourceModule), sourceCallableIdentifier)
|
|
390
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
391
|
-
|
|
392
|
-
shatteredDataclass = shatter_dataclassesDOTdataclass(*findDataclass(ingredientsFunction))
|
|
393
|
-
|
|
394
|
-
ingredientsFunction.imports.update(shatteredDataclass.imports)
|
|
395
|
-
ingredientsFunction.imports.addAst(astImportFrom)
|
|
396
|
-
targetCallableIdentifier = astImportFrom.names[0].name
|
|
397
|
-
ingredientsFunction = raiseIfNone(unpackDataclassCallFunctionRepackDataclass(ingredientsFunction, targetCallableIdentifier, shatteredDataclass))
|
|
398
|
-
targetFunctionDef = raiseIfNone(extractFunctionDef(parseLogicalPath2astModule(raiseIfNone(astImportFrom.module)), targetCallableIdentifier))
|
|
399
|
-
astTuple = raiseIfNone(NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(targetFunctionDef))
|
|
400
|
-
cast(ast.Tuple, astTuple).ctx = ast.Store()
|
|
401
|
-
|
|
402
|
-
findThis = ClassIsAndAttribute.valueIs(ast.Assign, IfThis.isCall_Identifier(targetCallableIdentifier))
|
|
403
|
-
doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), cast(ast.Tuple, astTuple).elts)))
|
|
404
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
405
|
-
|
|
406
|
-
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
407
|
-
ingredientsModule.removeImportFromModule('numpy')
|
|
408
|
-
|
|
409
|
-
pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
410
|
-
|
|
411
|
-
write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
|
|
412
|
-
|
|
413
|
-
if __name__ == '__main__':
|
|
414
|
-
astModule = getModule(logicalPathInfix=None)
|
|
415
|
-
makeInitializeGroupsOfFolds(astModule, 'initializeCount', 'initializeGroupsOfFolds', logicalPathInfixDEFAULT)
|
|
416
|
-
|
|
417
|
-
astModule = getModule(logicalPathInfix=None)
|
|
418
|
-
pathFilename = makeDaoOfMapFolding(astModule, 'daoOfMapFolding', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
|
|
419
|
-
|
|
420
|
-
astModule = getModule(logicalPathInfix=None)
|
|
421
|
-
pathFilename = makeDaoOfMapFoldingParallel(astModule, 'countParallel', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
|
|
422
|
-
|
|
423
|
-
astModule = getModule(logicalPathInfix=None)
|
|
424
|
-
pathFilename = makeTheorem2(astModule, 'theorem2', None, logicalPathInfixDEFAULT, None)
|
|
425
|
-
|
|
426
|
-
astModule = parsePathFilename2astModule(pathFilename)
|
|
427
|
-
pathFilename = trimTheorem2(astModule, 'theorem2Trimmed', None, logicalPathInfixDEFAULT, None)
|
|
428
|
-
|
|
429
|
-
astModule = parsePathFilename2astModule(pathFilename)
|
|
430
|
-
pathFilename = numbaOnTheorem2(astModule, 'theorem2Numba', None, logicalPathInfixDEFAULT, None)
|
|
431
|
-
|
|
432
|
-
astImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.packageName, logicalPathInfixDEFAULT, 'theorem2Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
|
|
433
|
-
makeUnRePackDataclass(astImportFrom)
|
mapFolding/theSSOT.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
from importlib import import_module as importlib_import_module
|
|
2
|
-
from inspect import getfile as inspect_getfile
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from tomli import load as tomli_load
|
|
5
|
-
import dataclasses
|
|
6
|
-
|
|
7
|
-
packageNamePACKAGING_HARDCODED = "mapFolding"
|
|
8
|
-
concurrencyPackageHARDCODED = 'multiprocessing'
|
|
9
|
-
|
|
10
|
-
# Evaluate When Packaging
|
|
11
|
-
# https://github.com/hunterhogan/mapFolding/issues/18
|
|
12
|
-
try:
|
|
13
|
-
packageNamePACKAGING: str = tomli_load(Path("../pyproject.toml").open('rb'))["project"]["name"]
|
|
14
|
-
except Exception:
|
|
15
|
-
packageNamePACKAGING = packageNamePACKAGING_HARDCODED
|
|
16
|
-
|
|
17
|
-
# Evaluate When Installing
|
|
18
|
-
# https://github.com/hunterhogan/mapFolding/issues/18
|
|
19
|
-
def getPathPackageINSTALLING() -> Path:
|
|
20
|
-
pathPackage: Path = Path(inspect_getfile(importlib_import_module(packageNamePACKAGING)))
|
|
21
|
-
if pathPackage.is_file():
|
|
22
|
-
pathPackage = pathPackage.parent
|
|
23
|
-
return pathPackage
|
|
24
|
-
|
|
25
|
-
@dataclasses.dataclass
|
|
26
|
-
class PackageSettings:
|
|
27
|
-
fileExtension: str = dataclasses.field(default='.py', metadata={'evaluateWhen': 'installing'})
|
|
28
|
-
packageName: str = dataclasses.field(default = packageNamePACKAGING, metadata={'evaluateWhen': 'packaging'})
|
|
29
|
-
pathPackage: Path = dataclasses.field(default_factory=getPathPackageINSTALLING, metadata={'evaluateWhen': 'installing'})
|
|
30
|
-
concurrencyPackage: str | None = None
|
|
31
|
-
"""Package to use for concurrent execution (e.g., 'multiprocessing', 'numba')."""
|
|
32
|
-
|
|
33
|
-
concurrencyPackage = concurrencyPackageHARDCODED
|
|
34
|
-
packageSettings = PackageSettings(concurrencyPackage=concurrencyPackage)
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: mapFolding
|
|
3
|
-
Version: 0.12.0
|
|
4
|
-
Summary: Map folding algorithm with code transformation framework for optimizing numerical computations
|
|
5
|
-
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
|
-
License: CC-BY-NC-4.0
|
|
7
|
-
Project-URL: Donate, https://www.patreon.com/integrated
|
|
8
|
-
Project-URL: Homepage, https://github.com/hunterhogan/mapFolding
|
|
9
|
-
Project-URL: Repository, https://github.com/hunterhogan/mapFolding.git
|
|
10
|
-
Project-URL: Issues, https://github.com/hunterhogan/mapFolding/issues
|
|
11
|
-
Keywords: A000136,A001415,A001416,A001417,A001418,A195646,algorithmic optimization,AST manipulation,code generation,code transformation,combinatorics,computational geometry,dataclass transformation,folding pattern enumeration,just-in-time compilation,map folding,Numba optimization,OEIS,performance optimization,source code analysis,stamp folding
|
|
12
|
-
Classifier: Development Status :: 4 - Beta
|
|
13
|
-
Classifier: Environment :: Console
|
|
14
|
-
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: Intended Audience :: Education
|
|
16
|
-
Classifier: Intended Audience :: Science/Research
|
|
17
|
-
Classifier: Natural Language :: English
|
|
18
|
-
Classifier: Operating System :: OS Independent
|
|
19
|
-
Classifier: Programming Language :: Python
|
|
20
|
-
Classifier: Programming Language :: Python :: 3
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
-
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
24
|
-
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
25
|
-
Classifier: Topic :: Software Development :: Code Generators
|
|
26
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
-
Classifier: Topic :: Software Development :: Compilers
|
|
28
|
-
Classifier: Typing :: Typed
|
|
29
|
-
Requires-Python: >=3.12
|
|
30
|
-
Description-Content-Type: text/markdown
|
|
31
|
-
License-File: LICENSE
|
|
32
|
-
Requires-Dist: astToolkit
|
|
33
|
-
Requires-Dist: autoflake
|
|
34
|
-
Requires-Dist: numba_progress
|
|
35
|
-
Requires-Dist: numba
|
|
36
|
-
Requires-Dist: numpy
|
|
37
|
-
Requires-Dist: platformdirs
|
|
38
|
-
Requires-Dist: python_minifier
|
|
39
|
-
Requires-Dist: sympy
|
|
40
|
-
Requires-Dist: tomli
|
|
41
|
-
Requires-Dist: Z0Z_tools
|
|
42
|
-
Provides-Extra: testing
|
|
43
|
-
Requires-Dist: mypy; extra == "testing"
|
|
44
|
-
Requires-Dist: pytest; extra == "testing"
|
|
45
|
-
Requires-Dist: pytest-cov; extra == "testing"
|
|
46
|
-
Requires-Dist: pytest-env; extra == "testing"
|
|
47
|
-
Requires-Dist: pytest-xdist; extra == "testing"
|
|
48
|
-
Requires-Dist: pyupgrade; extra == "testing"
|
|
49
|
-
Requires-Dist: ruff; extra == "testing"
|
|
50
|
-
Dynamic: license-file
|
|
51
|
-
|
|
52
|
-
# mapFolding: High-Performance Algorithm Playground for Computational Enthusiasts 🗺️
|
|
53
|
-
|
|
54
|
-
[](https://pypi.org/project/mapFolding/)
|
|
55
|
-
[](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
|
|
56
|
-
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
|
57
|
-
|
|
58
|
-
**This package is for you if:**
|
|
59
|
-
|
|
60
|
-
- You're fascinated by computational algorithms and their optimization
|
|
61
|
-
- You want to explore AST transformation techniques for Python performance tuning
|
|
62
|
-
- You're interested in solving mathematical puzzles through code
|
|
63
|
-
- You're learning about Numba and advanced Python optimization
|
|
64
|
-
|
|
65
|
-
## What Does This Package Actually Do?
|
|
66
|
-
|
|
67
|
-
`mapFolding` solves a specific mathematical problem: counting the number of distinct ways to fold a rectangular map. While this may sound niche, it's a fascinating computational challenge that demonstrates:
|
|
68
|
-
|
|
69
|
-
1. How to transform readable algorithms into blazingly fast implementations
|
|
70
|
-
2. Advanced techniques for Python optimization using AST manipulation
|
|
71
|
-
3. Numba acceleration with specialized compilation strategies
|
|
72
|
-
4. Algorithms for problems that grow combinatorially
|
|
73
|
-
|
|
74
|
-
The package has achieved new computational records, including first-ever calculations for large maps that were previously infeasible.
|
|
75
|
-
|
|
76
|
-
```python
|
|
77
|
-
# Compute the number of ways to fold a 5×5 grid:
|
|
78
|
-
from mapFolding import oeisIDfor_n
|
|
79
|
-
foldsTotal = oeisIDfor_n('A001418', 5)
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Key Benefits for Computational Enthusiasts
|
|
83
|
-
|
|
84
|
-
### 1. Algorithm Transformation Laboratory
|
|
85
|
-
|
|
86
|
-
See how the same algorithm evolves from readable Python to highly-optimized implementations:
|
|
87
|
-
|
|
88
|
-
```python
|
|
89
|
-
# The intuitive, readable version:
|
|
90
|
-
def countFolds(mapShape):
|
|
91
|
-
# ...implement readable algorithm...
|
|
92
|
-
|
|
93
|
-
# The transformed, optimized version (auto-generated):
|
|
94
|
-
@numba.jit(nopython=True, parallel=True, fastmath=True)
|
|
95
|
-
def countFolds_optimized(shape_param):
|
|
96
|
-
# ...blazingly fast implementation...
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### 2. Code Generation Framework
|
|
100
|
-
|
|
101
|
-
Study and extend a complete Python code transformation assembly line:
|
|
102
|
-
|
|
103
|
-
- AST analysis and manipulation
|
|
104
|
-
- Dataclass decomposition ("shattering")
|
|
105
|
-
- Automatic import management
|
|
106
|
-
- Type specialization for numerical computing
|
|
107
|
-
|
|
108
|
-
### 3. Exhaustive Test Framework
|
|
109
|
-
|
|
110
|
-
Leverage a sophisticated test suite for validating your own optimizations:
|
|
111
|
-
|
|
112
|
-
```python
|
|
113
|
-
# Test your own recipe implementation with just a few lines:
|
|
114
|
-
@pytest.fixture
|
|
115
|
-
def myCustomRecipeFixture(useThisDispatcher, pathTmpTesting):
|
|
116
|
-
myRecipe = RecipeSynthesizeFlow(
|
|
117
|
-
# Your custom configuration here
|
|
118
|
-
)
|
|
119
|
-
# ...transformation code...
|
|
120
|
-
return customDispatcher
|
|
121
|
-
|
|
122
|
-
def test_myCustomImplementation(myCustomRecipeFixture):
|
|
123
|
-
# Automatic validation against known values
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Installation and Getting Started
|
|
127
|
-
|
|
128
|
-
```sh
|
|
129
|
-
pip install mapFolding
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Try a quick calculation:
|
|
133
|
-
|
|
134
|
-
```python
|
|
135
|
-
from mapFolding import oeisIDfor_n
|
|
136
|
-
|
|
137
|
-
# Calculate ways to fold a 2×4 map
|
|
138
|
-
result = oeisIDfor_n('A001415', 4) # Returns 8
|
|
139
|
-
print(f"A 2×4 map can be folded {result} different ways")
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
## Mathematical Background (For the Curious)
|
|
143
|
-
|
|
144
|
-
The map folding problem was introduced by Lunnon in 1971 and connects to combinatorial geometry, computational complexity, and integer sequence analysis. The calculations provide entries to the Online Encyclopedia of Integer Sequences (OEIS).
|
|
145
|
-
|
|
146
|
-
This package implements several OEIS sequences, including:
|
|
147
|
-
|
|
148
|
-
- A001415: Number of ways to fold a 2×n strip (now calculated up to n=20!)
|
|
149
|
-
- A001418: Number of ways to fold an n×n square grid
|
|
150
|
-
|
|
151
|
-
## Explore the Repository
|
|
152
|
-
|
|
153
|
-
The repository structure reveals the package's educational value:
|
|
154
|
-
|
|
155
|
-
- `reference/`: Historical implementations and algorithm evolution
|
|
156
|
-
- `someAssemblyRequired/`: Code transformation framework
|
|
157
|
-
- `tests/`: Comprehensive test suite with fixtures for your own implementations
|
|
158
|
-
|
|
159
|
-
## Who Is This For, Really?
|
|
160
|
-
|
|
161
|
-
If you've read this far and are intrigued by computational puzzles, algorithm optimization, or Python performance techniques, this package offers a playground for exploration. It's particularly valuable for:
|
|
162
|
-
|
|
163
|
-
- Computer science students studying algorithm optimization
|
|
164
|
-
- Python developers exploring Numba and AST manipulation
|
|
165
|
-
- Computational mathematicians interested in combinatorial problems
|
|
166
|
-
- Anyone fascinated by the intersection of mathematics and computing
|
|
167
|
-
|
|
168
|
-
Whether you use it to solve map folding problems or to study its optimization techniques, `mapFolding` offers a unique window into advanced Python programming approaches.
|
|
169
|
-
|
|
170
|
-
## My recovery
|
|
171
|
-
|
|
172
|
-
[](https://HunterThinks.com/support)
|
|
173
|
-
[](https://www.youtube.com/@HunterHogan)
|
|
174
|
-
|
|
175
|
-
## How to code
|
|
176
|
-
|
|
177
|
-
Coding One Step at a Time:
|
|
178
|
-
|
|
179
|
-
0. WRITE CODE.
|
|
180
|
-
1. Don't write stupid code that's hard to revise.
|
|
181
|
-
2. Write good code.
|
|
182
|
-
3. When revising, write better code.
|
|
183
|
-
|
|
184
|
-
[](https://creativecommons.org/licenses/by-nc/4.0/)
|