mapFolding 0.15.0__py3-none-any.whl → 0.15.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 +1 -0
- mapFolding/_oeisFormulas/A001010.py +19 -0
- mapFolding/_oeisFormulas/A001011.py +5 -0
- mapFolding/_oeisFormulas/Z0Z_aOFn.py +15 -3
- mapFolding/_oeisFormulas/Z0Z_oeisMeanders.py +13 -16
- mapFolding/_theTypes.py +1 -1
- mapFolding/basecamp.py +89 -9
- mapFolding/daoOfMapFolding.py +2 -1
- mapFolding/oeis.py +1 -5
- mapFolding/reference/jaxCount.py +1 -1
- mapFolding/reference/rotatedEntryPoint.py +1 -1
- mapFolding/someAssemblyRequired/A007822rawMaterials.py +46 -0
- mapFolding/someAssemblyRequired/makeAllModules.py +185 -203
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +2 -2
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +2 -2
- mapFolding/syntheticModules/algorithmA007822.py +166 -0
- mapFolding/syntheticModules/algorithmA007822Numba.py +95 -0
- mapFolding/syntheticModules/{countParallel.py → countParallelNumba.py} +4 -6
- mapFolding/syntheticModules/{daoOfMapFolding.py → daoOfMapFoldingNumba.py} +4 -5
- mapFolding/syntheticModules/dataPacking.py +2 -1
- mapFolding/syntheticModules/dataPackingA007822.py +28 -0
- mapFolding/syntheticModules/{initializeCount.py → initializeState.py} +1 -1
- mapFolding/syntheticModules/initializeStateA007822.py +69 -0
- mapFolding/syntheticModules/theorem2.py +2 -1
- mapFolding/syntheticModules/theorem2A007822.py +70 -0
- mapFolding/syntheticModules/theorem2A007822Numba.py +66 -0
- mapFolding/syntheticModules/theorem2A007822Trimmed.py +64 -0
- mapFolding/syntheticModules/theorem2Numba.py +4 -4
- mapFolding/syntheticModules/theorem2Trimmed.py +2 -1
- mapFolding/tests/test_computations.py +29 -4
- {mapfolding-0.15.0.dist-info → mapfolding-0.15.2.dist-info}/METADATA +2 -2
- {mapfolding-0.15.0.dist-info → mapfolding-0.15.2.dist-info}/RECORD +36 -27
- mapFolding/_A007822.py +0 -181
- {mapfolding-0.15.0.dist-info → mapfolding-0.15.2.dist-info}/WHEEL +0 -0
- {mapfolding-0.15.0.dist-info → mapfolding-0.15.2.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.15.0.dist-info → mapfolding-0.15.2.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.15.0.dist-info → mapfolding-0.15.2.dist-info}/top_level.txt +0 -0
|
@@ -39,7 +39,10 @@ from astToolkit.transformationTools import inlineFunctionDef, removeUnusedParame
|
|
|
39
39
|
from hunterMakesPy import importLogicalPath2Identifier, raiseIfNone
|
|
40
40
|
from mapFolding import packageSettings
|
|
41
41
|
from mapFolding.someAssemblyRequired import (
|
|
42
|
-
DeReConstructField2ast, IfThis, ShatteredDataclass,
|
|
42
|
+
dataclassInstanceIdentifierDEFAULT, DeReConstructField2ast, IfThis, ShatteredDataclass,
|
|
43
|
+
sourceCallableDispatcherDEFAULT)
|
|
44
|
+
from mapFolding.someAssemblyRequired.A007822rawMaterials import (
|
|
45
|
+
FunctionDef_filterAsymmetricFolds, Z0Z_adjustFoldsTotal, Z0Z_incrementCount)
|
|
43
46
|
from mapFolding.someAssemblyRequired.infoBooth import (
|
|
44
47
|
algorithmSourceModuleDEFAULT, dataPackingModuleIdentifierDEFAULT, logicalPathInfixDEFAULT,
|
|
45
48
|
sourceCallableIdentifierDEFAULT, theCountingIdentifierDEFAULT)
|
|
@@ -98,69 +101,18 @@ def _findDataclass(ingredientsFunction: IngredientsFunction) -> tuple[str, str,
|
|
|
98
101
|
dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
99
102
|
return raiseIfNone(dataclassLogicalPathModule), dataclassIdentifier, dataclassInstanceIdentifier
|
|
100
103
|
|
|
101
|
-
def _getLogicalPath(
|
|
102
|
-
"""Construct logical module path by joining package and module components.
|
|
103
|
-
|
|
104
|
-
(AI generated docstring)
|
|
105
|
-
|
|
106
|
-
Builds a dot-separated logical path string from optional package name, infix path
|
|
107
|
-
components, and module identifiers. This standardizes module path construction
|
|
108
|
-
across the code generation system and ensures consistent naming conventions.
|
|
109
|
-
|
|
110
|
-
Parameters
|
|
111
|
-
----------
|
|
112
|
-
packageName : str | None = None
|
|
113
|
-
Root package name for the logical path.
|
|
114
|
-
logicalPathInfix : str | None = None
|
|
115
|
-
Middle path component (typically 'syntheticModules').
|
|
116
|
-
moduleIdentifier : str | None = None
|
|
117
|
-
Primary module identifier.
|
|
118
|
-
*modules : str
|
|
119
|
-
Additional module path components to append.
|
|
120
|
-
|
|
121
|
-
Returns
|
|
122
|
-
-------
|
|
123
|
-
logicalPath : identifierDotAttribute
|
|
124
|
-
Dot-separated logical path string suitable for module import operations.
|
|
125
|
-
|
|
126
|
-
"""
|
|
104
|
+
def _getLogicalPath(identifierPackage: str | None = None, logicalPathInfix: str | None = None, *moduleIdentifier: str | None) -> identifierDotAttribute:
|
|
127
105
|
listLogicalPathParts: list[str] = []
|
|
128
|
-
if
|
|
129
|
-
listLogicalPathParts.append(
|
|
106
|
+
if identifierPackage:
|
|
107
|
+
listLogicalPathParts.append(identifierPackage)
|
|
130
108
|
if logicalPathInfix:
|
|
131
109
|
listLogicalPathParts.append(logicalPathInfix)
|
|
132
110
|
if moduleIdentifier:
|
|
133
|
-
listLogicalPathParts.
|
|
134
|
-
if modules:
|
|
135
|
-
listLogicalPathParts.extend(modules)
|
|
111
|
+
listLogicalPathParts.extend([module for module in moduleIdentifier if module is not None])
|
|
136
112
|
return '.'.join(listLogicalPathParts)
|
|
137
113
|
|
|
138
|
-
def _getModule(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
(AI generated docstring)
|
|
142
|
-
|
|
143
|
-
Retrieves the specified module and parses it into an AST representation that can
|
|
144
|
-
be manipulated by the transformation tools. This provides the foundation for all
|
|
145
|
-
code generation operations by making the source algorithms available for analysis
|
|
146
|
-
and modification.
|
|
147
|
-
|
|
148
|
-
Parameters
|
|
149
|
-
----------
|
|
150
|
-
packageName : str | None = packageSettings.identifierPackage
|
|
151
|
-
Package containing the source module.
|
|
152
|
-
logicalPathInfix : str | None = logicalPathInfixDEFAULT
|
|
153
|
-
Path component within the package structure.
|
|
154
|
-
moduleIdentifier : str | None = algorithmSourceModuleDEFAULT
|
|
155
|
-
Specific module containing the algorithms.
|
|
156
|
-
|
|
157
|
-
Returns
|
|
158
|
-
-------
|
|
159
|
-
astModule : ast.Module
|
|
160
|
-
AST module representation ready for transformation operations.
|
|
161
|
-
|
|
162
|
-
"""
|
|
163
|
-
logicalPathSourceModule: identifierDotAttribute = _getLogicalPath(packageName, logicalPathInfix, moduleIdentifier)
|
|
114
|
+
def _getModule(identifierPackage: str | None = packageSettings.identifierPackage, logicalPathInfix: str | None = logicalPathInfixDEFAULT, moduleIdentifier: str | None = algorithmSourceModuleDEFAULT) -> ast.Module:
|
|
115
|
+
logicalPathSourceModule: identifierDotAttribute = _getLogicalPath(identifierPackage, logicalPathInfix, moduleIdentifier)
|
|
164
116
|
astModule: ast.Module = parseLogicalPath2astModule(logicalPathSourceModule)
|
|
165
117
|
return astModule
|
|
166
118
|
|
|
@@ -197,55 +149,43 @@ def _getPathFilename(pathRoot: PathLike[str] | PurePath | None = packageSettings
|
|
|
197
149
|
pathFilename = PurePath(pathRoot, pathFilename)
|
|
198
150
|
return pathFilename
|
|
199
151
|
|
|
200
|
-
|
|
201
|
-
"""Generate initialization module for counting variable setup.
|
|
152
|
+
# TODO Where is the generalized form of these functions?!
|
|
202
153
|
|
|
203
|
-
|
|
154
|
+
def addSymmetryCheck(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
|
|
155
|
+
"""Add logic to check for symmetric folds."""
|
|
156
|
+
imports=LedgerOfImports(astModule)
|
|
204
157
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
158
|
+
astFunctionDef_count: ast.FunctionDef = raiseIfNone(NodeTourist(
|
|
159
|
+
findThis = Be.FunctionDef.nameIs(IfThis.isIdentifier(sourceCallableIdentifierDEFAULT))
|
|
160
|
+
, doThat = Then.extractIt
|
|
161
|
+
).captureLastMatch(astModule))
|
|
209
162
|
|
|
210
|
-
|
|
211
|
-
|
|
163
|
+
# NOTE 2025 August 7. I am SHOCKED to discover that `astFunctionDef_count: ast.FunctionDef` returned by `NodeTourist` (subclass of
|
|
164
|
+
# `ast.NodeVisitor`) is a so-called mutable `object`!!!!!!
|
|
165
|
+
# !!!!!! Using the mutability of `ast.AST` subclasses, makes `astToolkit` SIGNIFICANTLY more powerful and solves "obstacles" I
|
|
166
|
+
# have been trying to overcome.
|
|
167
|
+
# (Side note: fuck you, Python, for your idiotic paradigms around mutability, its documentation, its identifiers, and its types.)
|
|
212
168
|
|
|
213
|
-
|
|
214
|
-
----------
|
|
215
|
-
astModule : ast.Module
|
|
216
|
-
Source module containing the base algorithm.
|
|
217
|
-
moduleIdentifier : str
|
|
218
|
-
Name for the generated initialization module.
|
|
219
|
-
callableIdentifier : str | None = None
|
|
220
|
-
Name for the initialization function.
|
|
221
|
-
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
222
|
-
Directory path for organizing the generated module.
|
|
223
|
-
sourceCallableDispatcher : str | None = None
|
|
224
|
-
Optional dispatcher function identifier.
|
|
169
|
+
NodeChanger(Be.Return, Then.insertThisAbove([Z0Z_adjustFoldsTotal])).visit(astFunctionDef_count)
|
|
225
170
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
171
|
+
NodeChanger(
|
|
172
|
+
findThis=Be.AugAssign.targetIs(IfThis.isAttributeNamespaceIdentifier(dataclassInstanceIdentifierDEFAULT, theCountingIdentifierDEFAULT))
|
|
173
|
+
, doThat=Then.replaceWith(Z0Z_incrementCount)
|
|
174
|
+
).visit(astFunctionDef_count)
|
|
230
175
|
|
|
231
|
-
|
|
232
|
-
sourceCallableIdentifier: identifierDotAttribute = sourceCallableIdentifierDEFAULT
|
|
233
|
-
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
234
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
|
|
176
|
+
ingredientsFunction=IngredientsFunction(FunctionDef_filterAsymmetricFolds)
|
|
235
177
|
|
|
236
|
-
|
|
237
|
-
theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
|
|
178
|
+
NodeChanger(Be.ImportFrom, Then.removeIt).visit(astModule)
|
|
238
179
|
|
|
239
|
-
|
|
240
|
-
doThat = Grab.testAttribute(Grab.andDoAllOf([Grab.opsAttribute(Then.replaceWith([ast.Eq()])), Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier)))]))
|
|
241
|
-
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef.body[0])
|
|
180
|
+
ingredientsModule = IngredientsModule(ingredientsFunction=ingredientsFunction, epilogue=astModule, imports=imports)
|
|
242
181
|
|
|
243
182
|
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
244
|
-
|
|
183
|
+
|
|
184
|
+
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
245
185
|
|
|
246
186
|
return pathFilename
|
|
247
187
|
|
|
248
|
-
def
|
|
188
|
+
def makeDaoOfMapFoldingNumba(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
249
189
|
"""Generate Numba-optimized sequential implementation of map folding algorithm.
|
|
250
190
|
|
|
251
191
|
(AI generated docstring)
|
|
@@ -318,19 +258,9 @@ def makeDaoOfMapFolding(astModule: ast.Module, moduleIdentifier: str, callableId
|
|
|
318
258
|
|
|
319
259
|
return pathFilename
|
|
320
260
|
|
|
321
|
-
def
|
|
261
|
+
def makeDaoOfMapFoldingParallelNumba(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
|
|
322
262
|
"""Generate parallel implementation with concurrent execution and task division.
|
|
323
263
|
|
|
324
|
-
This version of the algorithm: Creates a parallel processing version of the map folding algorithm that distributes
|
|
325
|
-
computational work across multiple processes using `ProcessPoolExecutor`. The implementation includes dataclass decomposition
|
|
326
|
-
for both base and parallel state fields, task division logic that partitions work based on leaf indices, concurrent execution
|
|
327
|
-
management with future objects, result aggregation from multiple parallel computations, and Numba optimization for the core
|
|
328
|
-
computational kernels.
|
|
329
|
-
|
|
330
|
-
The generated module contains multiple functions including core counting function with parallel-aware task filtering,
|
|
331
|
-
dataclass unpacking/repacking function for process communication, and main dispatcher function that manages the parallel
|
|
332
|
-
execution assembly line.
|
|
333
|
-
|
|
334
264
|
Parameters
|
|
335
265
|
----------
|
|
336
266
|
astModule : ast.Module
|
|
@@ -496,22 +426,56 @@ def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, ca
|
|
|
496
426
|
|
|
497
427
|
return pathFilename
|
|
498
428
|
|
|
499
|
-
def
|
|
500
|
-
"""Generate
|
|
429
|
+
def makeInitializeState(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
|
|
430
|
+
"""Generate initialization module for counting variable setup.
|
|
501
431
|
|
|
502
432
|
(AI generated docstring)
|
|
503
433
|
|
|
504
|
-
Creates a specialized
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
434
|
+
Creates a specialized module containing initialization logic for the counting variables
|
|
435
|
+
used in map folding computations. The generated function transforms the original
|
|
436
|
+
algorithm's loop conditions to use equality comparisons instead of greater-than
|
|
437
|
+
comparisons, optimizing the initialization phase.
|
|
438
|
+
|
|
439
|
+
This transformation is particularly important for ensuring that counting variables
|
|
440
|
+
are properly initialized before the main computational loops begin executing.
|
|
441
|
+
|
|
442
|
+
Parameters
|
|
443
|
+
----------
|
|
444
|
+
astModule : ast.Module
|
|
445
|
+
Source module containing the base algorithm.
|
|
446
|
+
moduleIdentifier : str
|
|
447
|
+
Name for the generated initialization module.
|
|
448
|
+
callableIdentifier : str | None = None
|
|
449
|
+
Name for the initialization function.
|
|
450
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
451
|
+
Directory path for organizing the generated module.
|
|
452
|
+
sourceCallableDispatcher : str | None = None
|
|
453
|
+
Optional dispatcher function identifier.
|
|
454
|
+
|
|
455
|
+
Returns
|
|
456
|
+
-------
|
|
457
|
+
pathFilename : PurePath
|
|
458
|
+
Filesystem path where the initialization module was written.
|
|
459
|
+
|
|
460
|
+
"""
|
|
461
|
+
sourceCallableIdentifier: identifierDotAttribute = sourceCallableIdentifierDEFAULT
|
|
462
|
+
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
463
|
+
ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
|
|
464
|
+
|
|
465
|
+
dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
466
|
+
theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
|
|
467
|
+
|
|
468
|
+
findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
469
|
+
doThat = Grab.testAttribute(Grab.andDoAllOf([Grab.opsAttribute(Then.replaceWith([ast.Eq()])), Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier)))]))
|
|
470
|
+
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef.body[0])
|
|
471
|
+
|
|
472
|
+
pathFilename: PurePath = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
|
|
473
|
+
write_astModule(IngredientsModule(ingredientsFunction), pathFilename, packageSettings.identifierPackage)
|
|
510
474
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
475
|
+
return pathFilename
|
|
476
|
+
|
|
477
|
+
def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
|
|
478
|
+
"""Generate module by applying optimization predicted by Theorem 2.
|
|
515
479
|
|
|
516
480
|
Parameters
|
|
517
481
|
----------
|
|
@@ -543,6 +507,14 @@ def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
|
|
|
543
507
|
|
|
544
508
|
dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
545
509
|
|
|
510
|
+
theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
|
|
511
|
+
doubleTheCount: ast.AugAssign = Make.AugAssign(Make.Attribute(Make.Name(dataclassInstanceIdentifier), theCountingIdentifier), Make.Mult(), Make.Constant(2))
|
|
512
|
+
|
|
513
|
+
NodeChanger(
|
|
514
|
+
findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
515
|
+
, doThat = Grab.orelseAttribute(Then.replaceWith([doubleTheCount]))
|
|
516
|
+
).visit(ingredientsFunction.astFunctionDef)
|
|
517
|
+
|
|
546
518
|
NodeChanger(
|
|
547
519
|
findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
|
|
548
520
|
, doThat = Grab.testAttribute(Grab.comparatorsAttribute(Then.replaceWith([Make.Constant(4)])))
|
|
@@ -567,13 +539,6 @@ def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
|
|
|
567
539
|
, doThat = Then.removeIt
|
|
568
540
|
).visit(ingredientsFunction.astFunctionDef)
|
|
569
541
|
|
|
570
|
-
theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
|
|
571
|
-
doubleTheCount: ast.AugAssign = Make.AugAssign(Make.Attribute(ast.Name(dataclassInstanceIdentifier), theCountingIdentifier), ast.Mult(), Make.Constant(2))
|
|
572
|
-
NodeChanger(
|
|
573
|
-
findThis = Be.Return
|
|
574
|
-
, doThat = Then.insertThisAbove([doubleTheCount])
|
|
575
|
-
).visit(ingredientsFunction.astFunctionDef)
|
|
576
|
-
|
|
577
542
|
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
578
543
|
|
|
579
544
|
if sourceCallableDispatcher is not None:
|
|
@@ -586,47 +551,47 @@ def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
|
|
|
586
551
|
|
|
587
552
|
return pathFilename
|
|
588
553
|
|
|
589
|
-
def
|
|
590
|
-
"""Generate
|
|
591
|
-
|
|
592
|
-
(AI generated docstring)
|
|
593
|
-
|
|
594
|
-
Creates a trimmed version of the Theorem 2 implementation by eliminating conditional logic that is not needed under specific
|
|
595
|
-
constraint assumptions. This transformation removes checks for unconstrained dimensions, simplifying the algorithm for cases
|
|
596
|
-
where dimensional constraints are guaranteed to be satisfied by external conditions.
|
|
597
|
-
|
|
598
|
-
The trimming operation is particularly valuable for generating lean implementations where the calling context ensures that
|
|
599
|
-
certain conditions will always be met, allowing the removal of defensive programming constructs that add computational
|
|
600
|
-
overhead without providing benefits in the constrained environment.
|
|
554
|
+
def makeUnRePackDataclass(astImportFrom: ast.ImportFrom, moduleIdentifier: identifierDotAttribute = dataPackingModuleIdentifierDEFAULT) -> None:
|
|
555
|
+
"""Generate interface module for dataclass unpacking and repacking operations.
|
|
601
556
|
|
|
602
557
|
Parameters
|
|
603
558
|
----------
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
moduleIdentifier : str
|
|
607
|
-
Name for the generated trimmed module.
|
|
608
|
-
callableIdentifier : str | None = None
|
|
609
|
-
Name for the trimmed computational function.
|
|
610
|
-
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
611
|
-
Directory path for organizing the generated module.
|
|
612
|
-
sourceCallableDispatcher : str | None = None
|
|
613
|
-
Optional dispatcher function identifier (unused).
|
|
559
|
+
astImportFrom : ast.ImportFrom
|
|
560
|
+
Import statement specifying the target optimized function to call.
|
|
614
561
|
|
|
615
562
|
Returns
|
|
616
563
|
-------
|
|
617
|
-
|
|
618
|
-
|
|
564
|
+
None
|
|
565
|
+
The generated module is written directly to the filesystem.
|
|
619
566
|
|
|
620
567
|
"""
|
|
621
|
-
|
|
622
|
-
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
623
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
|
|
568
|
+
callableIdentifierHARDCODED: str = 'sequential'
|
|
624
569
|
|
|
625
|
-
|
|
570
|
+
algorithmSourceModule: identifierDotAttribute = algorithmSourceModuleDEFAULT
|
|
571
|
+
sourceCallableIdentifier: identifierDotAttribute = sourceCallableDispatcherDEFAULT
|
|
572
|
+
logicalPathSourceModule: identifierDotAttribute = '.'.join([packageSettings.identifierPackage, algorithmSourceModule]) # noqa: FLY002
|
|
626
573
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
574
|
+
logicalPathInfix: identifierDotAttribute = logicalPathInfixDEFAULT
|
|
575
|
+
callableIdentifier: identifierDotAttribute = callableIdentifierHARDCODED
|
|
576
|
+
|
|
577
|
+
ingredientsFunction: IngredientsFunction = astModuleToIngredientsFunction(parseLogicalPath2astModule(logicalPathSourceModule), sourceCallableIdentifier)
|
|
578
|
+
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
579
|
+
|
|
580
|
+
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
|
|
581
|
+
|
|
582
|
+
ingredientsFunction.imports.update(shatteredDataclass.imports)
|
|
583
|
+
ingredientsFunction.imports.addAst(astImportFrom)
|
|
584
|
+
targetCallableIdentifier = astImportFrom.names[0].name
|
|
585
|
+
ingredientsFunction = raiseIfNone(unpackDataclassCallFunctionRepackDataclass(ingredientsFunction, targetCallableIdentifier, shatteredDataclass))
|
|
586
|
+
targetFunctionDef: ast.FunctionDef = raiseIfNone(extractFunctionDef(parseLogicalPath2astModule(raiseIfNone(astImportFrom.module)), targetCallableIdentifier))
|
|
587
|
+
astTuple: ast.Tuple = cast('ast.Tuple', raiseIfNone(NodeTourist(Be.Return.valueIs(Be.Tuple)
|
|
588
|
+
, doThat=Then.extractIt(DOT.value)).captureLastMatch(targetFunctionDef)))
|
|
589
|
+
astTuple.ctx = ast.Store()
|
|
590
|
+
|
|
591
|
+
changeAssignCallToTarget = NodeChanger(
|
|
592
|
+
findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
|
|
593
|
+
, doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts))))
|
|
594
|
+
changeAssignCallToTarget.visit(ingredientsFunction.astFunctionDef)
|
|
630
595
|
|
|
631
596
|
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
632
597
|
ingredientsModule.removeImportFromModule('numpy')
|
|
@@ -635,8 +600,6 @@ def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
|
|
|
635
600
|
|
|
636
601
|
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
637
602
|
|
|
638
|
-
return pathFilename
|
|
639
|
-
|
|
640
603
|
def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
|
|
641
604
|
"""Generate Numba-accelerated Theorem 2 implementation with dataclass decomposition.
|
|
642
605
|
|
|
@@ -696,61 +659,47 @@ def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdenti
|
|
|
696
659
|
|
|
697
660
|
return pathFilename
|
|
698
661
|
|
|
699
|
-
def
|
|
700
|
-
"""Generate
|
|
662
|
+
def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
|
|
663
|
+
"""Generate constrained Theorem 2 implementation by removing unnecessary logic.
|
|
701
664
|
|
|
702
665
|
(AI generated docstring)
|
|
703
666
|
|
|
704
|
-
Creates a
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
into individual primitive values, calls to the specified optimized target function
|
|
708
|
-
with decomposed parameters, repacking of results back into appropriate dataclass
|
|
709
|
-
instances, and import management for all required dependencies.
|
|
667
|
+
Creates a trimmed version of the Theorem 2 implementation by eliminating conditional logic that is not needed under specific
|
|
668
|
+
constraint assumptions. This transformation removes checks for unconstrained dimensions, simplifying the algorithm for cases
|
|
669
|
+
where dimensional constraints are guaranteed to be satisfied by external conditions.
|
|
710
670
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
671
|
+
The trimming operation is particularly valuable for generating lean implementations where the calling context ensures that
|
|
672
|
+
certain conditions will always be met, allowing the removal of defensive programming constructs that add computational
|
|
673
|
+
overhead without providing benefits in the constrained environment.
|
|
714
674
|
|
|
715
675
|
Parameters
|
|
716
676
|
----------
|
|
717
|
-
|
|
718
|
-
|
|
677
|
+
astModule : ast.Module
|
|
678
|
+
Source module containing the Theorem 2 implementation.
|
|
679
|
+
moduleIdentifier : str
|
|
680
|
+
Name for the generated trimmed module.
|
|
681
|
+
callableIdentifier : str | None = None
|
|
682
|
+
Name for the trimmed computational function.
|
|
683
|
+
logicalPathInfix : PathLike[str] | PurePath | str | None = None
|
|
684
|
+
Directory path for organizing the generated module.
|
|
685
|
+
sourceCallableDispatcher : str | None = None
|
|
686
|
+
Optional dispatcher function identifier (unused).
|
|
719
687
|
|
|
720
688
|
Returns
|
|
721
689
|
-------
|
|
722
|
-
|
|
723
|
-
|
|
690
|
+
pathFilename : PurePath
|
|
691
|
+
Filesystem path where the trimmed module was written.
|
|
724
692
|
|
|
725
693
|
"""
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
sourceCallableIdentifier: identifierDotAttribute = sourceCallableDispatcherDEFAULT
|
|
730
|
-
logicalPathSourceModule: identifierDotAttribute = '.'.join([packageSettings.identifierPackage, algorithmSourceModule]) # noqa: FLY002
|
|
731
|
-
|
|
732
|
-
logicalPathInfix: identifierDotAttribute = logicalPathInfixDEFAULT
|
|
733
|
-
moduleIdentifier: identifierDotAttribute = dataPackingModuleIdentifierDEFAULT
|
|
734
|
-
callableIdentifier: identifierDotAttribute = callableIdentifierHARDCODED
|
|
735
|
-
|
|
736
|
-
ingredientsFunction: IngredientsFunction = astModuleToIngredientsFunction(parseLogicalPath2astModule(logicalPathSourceModule), sourceCallableIdentifier)
|
|
737
|
-
ingredientsFunction.astFunctionDef.name = callableIdentifier
|
|
738
|
-
|
|
739
|
-
shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
|
|
694
|
+
sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
|
|
695
|
+
ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
|
|
696
|
+
ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
|
|
740
697
|
|
|
741
|
-
|
|
742
|
-
ingredientsFunction.imports.addAst(astImportFrom)
|
|
743
|
-
targetCallableIdentifier = astImportFrom.names[0].name
|
|
744
|
-
ingredientsFunction = raiseIfNone(unpackDataclassCallFunctionRepackDataclass(ingredientsFunction, targetCallableIdentifier, shatteredDataclass))
|
|
745
|
-
targetFunctionDef: ast.FunctionDef = raiseIfNone(extractFunctionDef(parseLogicalPath2astModule(raiseIfNone(astImportFrom.module)), targetCallableIdentifier))
|
|
746
|
-
astTuple: ast.Tuple = cast('ast.Tuple', raiseIfNone(NodeTourist(Be.Return.valueIs(Be.Tuple)
|
|
747
|
-
, doThat=Then.extractIt(DOT.value)).captureLastMatch(targetFunctionDef)))
|
|
748
|
-
astTuple.ctx = ast.Store()
|
|
698
|
+
dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
|
|
749
699
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
changeAssignCallToTarget.visit(ingredientsFunction.astFunctionDef)
|
|
700
|
+
findThis = IfThis.isIfUnaryNotAttributeNamespaceIdentifier(dataclassInstanceIdentifier, 'dimensionsUnconstrained')
|
|
701
|
+
doThat = Then.removeIt
|
|
702
|
+
NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
|
|
754
703
|
|
|
755
704
|
ingredientsModule = IngredientsModule(ingredientsFunction)
|
|
756
705
|
ingredientsModule.removeImportFromModule('numpy')
|
|
@@ -759,15 +708,17 @@ def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
|
|
|
759
708
|
|
|
760
709
|
write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
|
|
761
710
|
|
|
762
|
-
|
|
763
|
-
astModule: ast.Module = _getModule(logicalPathInfix=None)
|
|
764
|
-
makeInitializeGroupsOfFolds(astModule, 'initializeCount', 'initializeGroupsOfFolds', logicalPathInfixDEFAULT)
|
|
711
|
+
return pathFilename
|
|
765
712
|
|
|
713
|
+
if __name__ == '__main__':
|
|
766
714
|
astModule = _getModule(logicalPathInfix=None)
|
|
767
|
-
pathFilename: PurePath =
|
|
715
|
+
pathFilename: PurePath = makeDaoOfMapFoldingNumba(astModule, 'daoOfMapFoldingNumba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
|
|
768
716
|
|
|
769
717
|
astModule = _getModule(logicalPathInfix=None)
|
|
770
|
-
pathFilename =
|
|
718
|
+
pathFilename = makeDaoOfMapFoldingParallelNumba(astModule, 'countParallelNumba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
|
|
719
|
+
|
|
720
|
+
astModule: ast.Module = _getModule(logicalPathInfix=None)
|
|
721
|
+
makeInitializeState(astModule, 'initializeState', 'transitionOnGroupsOfFolds', logicalPathInfixDEFAULT)
|
|
771
722
|
|
|
772
723
|
astModule = _getModule(logicalPathInfix=None)
|
|
773
724
|
pathFilename = makeTheorem2(astModule, 'theorem2', None, logicalPathInfixDEFAULT, None)
|
|
@@ -780,3 +731,34 @@ if __name__ == '__main__':
|
|
|
780
731
|
|
|
781
732
|
astImportFrom: ast.ImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.identifierPackage, logicalPathInfixDEFAULT, 'theorem2Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
|
|
782
733
|
makeUnRePackDataclass(astImportFrom)
|
|
734
|
+
|
|
735
|
+
# A007822 -----------------------------------------------------------
|
|
736
|
+
astModule = _getModule(logicalPathInfix=None)
|
|
737
|
+
pathFilename = addSymmetryCheck(astModule, 'algorithmA007822', None, logicalPathInfixDEFAULT, None)
|
|
738
|
+
|
|
739
|
+
astModule = _getModule(moduleIdentifier='algorithmA007822')
|
|
740
|
+
pathFilename: PurePath = makeDaoOfMapFoldingNumba(astModule, 'algorithmA007822Numba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
|
|
741
|
+
|
|
742
|
+
# I can't handle parallel right now.
|
|
743
|
+
|
|
744
|
+
# TODO Implement logic that lets me amend modules instead of only overwriting them. "initializeState" could/should include state
|
|
745
|
+
# initialization for multiple algorithms.
|
|
746
|
+
astModule = _getModule(moduleIdentifier='algorithmA007822')
|
|
747
|
+
# NOTE `initializeState.transitionOnGroupsOfFolds` will collide with `initializeStateA007822.transitionOnGroupsOfFolds` if the
|
|
748
|
+
# modules are merged. This problem is a side effect of the problem with `MapFoldingState.groupsOfFolds` and
|
|
749
|
+
# `MapFoldingState.foldsTotal`. If I fix that issue, then the identifier `initializeStateA007822.transitionOnGroupsOfFolds` will
|
|
750
|
+
# naturally change to something more appropriate (and remove the collision).
|
|
751
|
+
makeInitializeState(astModule, 'initializeStateA007822', 'transitionOnGroupsOfFolds', logicalPathInfixDEFAULT)
|
|
752
|
+
|
|
753
|
+
astModule = _getModule(moduleIdentifier='algorithmA007822')
|
|
754
|
+
pathFilename = makeTheorem2(astModule, 'theorem2A007822', None, logicalPathInfixDEFAULT, None)
|
|
755
|
+
|
|
756
|
+
astModule = parsePathFilename2astModule(pathFilename)
|
|
757
|
+
pathFilename = trimTheorem2(astModule, 'theorem2A007822Trimmed', None, logicalPathInfixDEFAULT, None)
|
|
758
|
+
|
|
759
|
+
astModule = parsePathFilename2astModule(pathFilename)
|
|
760
|
+
pathFilename = numbaOnTheorem2(astModule, 'theorem2A007822Numba', None, logicalPathInfixDEFAULT, None)
|
|
761
|
+
|
|
762
|
+
astImportFrom: ast.ImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.identifierPackage, logicalPathInfixDEFAULT, 'theorem2A007822Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
|
|
763
|
+
makeUnRePackDataclass(astImportFrom, 'dataPackingA007822')
|
|
764
|
+
|
|
@@ -37,7 +37,7 @@ from mapFolding import getPathFilenameFoldsTotal, MapFoldingState, packageSettin
|
|
|
37
37
|
from mapFolding.someAssemblyRequired import IfThis
|
|
38
38
|
from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2
|
|
39
39
|
from mapFolding.someAssemblyRequired.toolkitNumba import decorateCallableWithNumba, parametersNumbaLight, SpicesJobNumba
|
|
40
|
-
from mapFolding.syntheticModules.
|
|
40
|
+
from mapFolding.syntheticModules.initializeState import transitionOnGroupsOfFolds
|
|
41
41
|
from pathlib import PurePosixPath
|
|
42
42
|
from typing import cast, NamedTuple, TYPE_CHECKING
|
|
43
43
|
from typing_extensions import TypeIs
|
|
@@ -326,7 +326,7 @@ if __name__ == '__main__':
|
|
|
326
326
|
"""
|
|
327
327
|
|
|
328
328
|
if __name__ == '__main__':
|
|
329
|
-
state =
|
|
329
|
+
state = transitionOnGroupsOfFolds(MapFoldingState((2,4)))
|
|
330
330
|
pathModule = PurePosixPath(packageSettings.pathPackage, 'jobs')
|
|
331
331
|
pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
|
|
332
332
|
aJob = RecipeJobTheorem2(state, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
|
|
@@ -11,7 +11,7 @@ from hunterMakesPy import autoDecodingRLE, raiseIfNone
|
|
|
11
11
|
from mapFolding import DatatypeLeavesTotal, getPathFilenameFoldsTotal, MapFoldingState
|
|
12
12
|
from mapFolding.someAssemblyRequired import IfThis
|
|
13
13
|
from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2
|
|
14
|
-
from mapFolding.syntheticModules.
|
|
14
|
+
from mapFolding.syntheticModules.initializeState import transitionOnGroupsOfFolds
|
|
15
15
|
from pathlib import Path, PurePosixPath
|
|
16
16
|
from typing import cast, NamedTuple, TYPE_CHECKING
|
|
17
17
|
import ast
|
|
@@ -212,7 +212,7 @@ def fromMapShape(mapShape: tuple[DatatypeLeavesTotal, ...]) -> None:
|
|
|
212
212
|
along one axis.
|
|
213
213
|
|
|
214
214
|
"""
|
|
215
|
-
state =
|
|
215
|
+
state = transitionOnGroupsOfFolds(MapFoldingState(mapShape))
|
|
216
216
|
pathModule = PurePosixPath(Path.home(), 'mapFolding', 'jobs')
|
|
217
217
|
pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
|
|
218
218
|
aJob = RecipeJobTheorem2(state, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
|