mapFolding 0.14.1__py3-none-any.whl → 0.15.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. mapFolding/__init__.py +2 -1
  2. mapFolding/_oeisFormulas/A000682.py +2 -2
  3. mapFolding/_oeisFormulas/A001010.py +18 -0
  4. mapFolding/_oeisFormulas/Z0Z_aOFn.py +7 -4
  5. mapFolding/_oeisFormulas/Z0Z_oeisMeanders.py +7 -0
  6. mapFolding/_oeisFormulas/matrixMeanders.py +122 -75
  7. mapFolding/_oeisFormulas/matrixMeandersAnnex.py +66 -66
  8. mapFolding/_theSSOT.py +9 -3
  9. mapFolding/_theTypes.py +34 -130
  10. mapFolding/basecamp.py +90 -10
  11. mapFolding/beDRY.py +5 -21
  12. mapFolding/daoOfMapFolding.py +2 -1
  13. mapFolding/dataBaskets.py +8 -3
  14. mapFolding/oeis.py +10 -16
  15. mapFolding/reference/A005316optimized128bit.py +19 -19
  16. mapFolding/reference/A005316primitiveOptimized.py +25 -25
  17. mapFolding/reference/A005316redis.py +19 -19
  18. mapFolding/reference/A005316write2disk.py +19 -19
  19. mapFolding/reference/jaxCount.py +1 -1
  20. mapFolding/reference/matrixMeandersBaseline.py +20 -20
  21. mapFolding/reference/matrixMeandersBaselineAnnex.py +4 -4
  22. mapFolding/reference/matrixMeandersSimpleQueue.py +90 -0
  23. mapFolding/reference/matrixMeandersSlicePop.py +104 -0
  24. mapFolding/reference/rotatedEntryPoint.py +1 -1
  25. mapFolding/someAssemblyRequired/A007822rawMaterials.py +46 -0
  26. mapFolding/someAssemblyRequired/_toolkitContainers.py +1 -1
  27. mapFolding/someAssemblyRequired/makeAllModules.py +192 -199
  28. mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +3 -3
  29. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +3 -3
  30. mapFolding/syntheticModules/algorithmA007822.py +166 -0
  31. mapFolding/syntheticModules/algorithmA007822Numba.py +95 -0
  32. mapFolding/syntheticModules/{countParallel.py → countParallelNumba.py} +5 -4
  33. mapFolding/syntheticModules/{daoOfMapFolding.py → daoOfMapFoldingNumba.py} +5 -4
  34. mapFolding/syntheticModules/dataPacking.py +4 -3
  35. mapFolding/syntheticModules/{initializeCount.py → initializeState.py} +1 -1
  36. mapFolding/syntheticModules/initializeStateA007822.py +69 -0
  37. mapFolding/syntheticModules/theorem2.py +2 -1
  38. mapFolding/syntheticModules/theorem2A007822.py +70 -0
  39. mapFolding/syntheticModules/theorem2A007822Numba.py +67 -0
  40. mapFolding/syntheticModules/theorem2A007822Trimmed.py +64 -0
  41. mapFolding/syntheticModules/theorem2Numba.py +6 -4
  42. mapFolding/syntheticModules/theorem2Trimmed.py +2 -1
  43. mapFolding/tests/test_computations.py +29 -4
  44. {mapfolding-0.14.1.dist-info → mapfolding-0.15.1.dist-info}/METADATA +2 -2
  45. mapfolding-0.15.1.dist-info/RECORD +86 -0
  46. mapfolding-0.14.1.dist-info/RECORD +0 -76
  47. {mapfolding-0.14.1.dist-info → mapfolding-0.15.1.dist-info}/WHEEL +0 -0
  48. {mapfolding-0.14.1.dist-info → mapfolding-0.15.1.dist-info}/entry_points.txt +0 -0
  49. {mapfolding-0.14.1.dist-info → mapfolding-0.15.1.dist-info}/licenses/LICENSE +0 -0
  50. {mapfolding-0.14.1.dist-info → mapfolding-0.15.1.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, sourceCallableDispatcherDEFAULT)
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(packageName: str | None = None, logicalPathInfix: str | None = None, moduleIdentifier: str | None = None, *modules: str) -> identifierDotAttribute:
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 packageName:
129
- listLogicalPathParts.append(packageName)
106
+ if identifierPackage:
107
+ listLogicalPathParts.append(identifierPackage)
130
108
  if logicalPathInfix:
131
109
  listLogicalPathParts.append(logicalPathInfix)
132
110
  if moduleIdentifier:
133
- listLogicalPathParts.append(moduleIdentifier)
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(packageName: str | None = packageSettings.identifierPackage, logicalPathInfix: str | None = logicalPathInfixDEFAULT, moduleIdentifier: str | None = algorithmSourceModuleDEFAULT) -> ast.Module:
139
- """Load source algorithm module as AST for transformation operations.
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
- def makeInitializeGroupsOfFolds(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
201
- """Generate initialization module for counting variable setup.
152
+ # TODO Where is the generalized form of these functions?!
202
153
 
203
- (AI generated docstring)
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
- Creates a specialized module containing initialization logic for the counting variables
206
- used in map folding computations. The generated function transforms the original
207
- algorithm's loop conditions to use equality comparisons instead of greater-than
208
- comparisons, optimizing the initialization phase.
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
- This transformation is particularly important for ensuring that counting variables
211
- are properly initialized before the main computational loops begin executing.
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
- Parameters
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
- Returns
227
- -------
228
- pathFilename : PurePath
229
- Filesystem path where the initialization module was written.
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
- dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
237
- theCountingIdentifier: identifierDotAttribute = theCountingIdentifierDEFAULT
178
+ NodeChanger(Be.ImportFrom, Then.removeIt).visit(astModule)
238
179
 
239
- findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
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
- write_astModule(IngredientsModule(ingredientsFunction), pathFilename, packageSettings.identifierPackage)
183
+
184
+ write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
245
185
 
246
186
  return pathFilename
247
187
 
248
- def makeDaoOfMapFolding(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
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 makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001, PLR0915
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 makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
500
- """Generate optimized implementation applying Theorem 2 mathematical optimizations.
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 version of the map folding algorithm that applies Theorem 2
505
- optimizations for improved computational efficiency. The transformation includes
506
- modifying loop termination conditions from general cases to Theorem 2 specifics,
507
- restructuring conditional logic to eliminate unnecessary branch evaluations,
508
- adding count doubling operations to leverage mathematical properties, and
509
- removing redundant computations that are not needed under Theorem 2 constraints.
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
- Theorem 2 provides mathematical guarantees that allow certain computational
512
- shortcuts and optimizations that would not be valid in the general case. This
513
- implementation capitalizes on those properties to achieve significant performance
514
- improvements for maps that satisfy Theorem 2 conditions.
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,61 @@ def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
586
551
 
587
552
  return pathFilename
588
553
 
589
- 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
590
- """Generate constrained Theorem 2 implementation by removing unnecessary logic.
554
+ def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
555
+ """Generate interface module for dataclass unpacking and repacking operations.
591
556
 
592
557
  (AI generated docstring)
593
558
 
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.
559
+ Creates a specialized module that serves as an interface between dataclass-based
560
+ calling code and optimized implementations that operate on decomposed primitive
561
+ values. The generated module includes a function that unpacks dataclass instances
562
+ into individual primitive values, calls to the specified optimized target function
563
+ with decomposed parameters, repacking of results back into appropriate dataclass
564
+ instances, and import management for all required dependencies.
597
565
 
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.
566
+ This bridge module enables seamless integration between high-level dataclass-based
567
+ APIs and low-level optimized implementations, maintaining type safety and usability
568
+ while leveraging performance optimizations that require primitive value operations.
601
569
 
602
570
  Parameters
603
571
  ----------
604
- astModule : ast.Module
605
- Source module containing the Theorem 2 implementation.
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).
572
+ astImportFrom : ast.ImportFrom
573
+ Import statement specifying the target optimized function to call.
614
574
 
615
575
  Returns
616
576
  -------
617
- pathFilename : PurePath
618
- Filesystem path where the trimmed module was written.
577
+ None
578
+ The generated module is written directly to the filesystem.
619
579
 
620
580
  """
621
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
622
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
623
- ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
581
+ callableIdentifierHARDCODED: str = 'sequential'
624
582
 
625
- dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
583
+ algorithmSourceModule: identifierDotAttribute = algorithmSourceModuleDEFAULT
584
+ sourceCallableIdentifier: identifierDotAttribute = sourceCallableDispatcherDEFAULT
585
+ logicalPathSourceModule: identifierDotAttribute = '.'.join([packageSettings.identifierPackage, algorithmSourceModule]) # noqa: FLY002
626
586
 
627
- findThis = IfThis.isIfUnaryNotAttributeNamespaceIdentifier(dataclassInstanceIdentifier, 'dimensionsUnconstrained')
628
- doThat = Then.removeIt
629
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
587
+ logicalPathInfix: identifierDotAttribute = logicalPathInfixDEFAULT
588
+ moduleIdentifier: identifierDotAttribute = dataPackingModuleIdentifierDEFAULT
589
+ callableIdentifier: identifierDotAttribute = callableIdentifierHARDCODED
590
+
591
+ ingredientsFunction: IngredientsFunction = astModuleToIngredientsFunction(parseLogicalPath2astModule(logicalPathSourceModule), sourceCallableIdentifier)
592
+ ingredientsFunction.astFunctionDef.name = callableIdentifier
593
+
594
+ shatteredDataclass: ShatteredDataclass = shatter_dataclassesDOTdataclass(*_findDataclass(ingredientsFunction))
595
+
596
+ ingredientsFunction.imports.update(shatteredDataclass.imports)
597
+ ingredientsFunction.imports.addAst(astImportFrom)
598
+ targetCallableIdentifier = astImportFrom.names[0].name
599
+ ingredientsFunction = raiseIfNone(unpackDataclassCallFunctionRepackDataclass(ingredientsFunction, targetCallableIdentifier, shatteredDataclass))
600
+ targetFunctionDef: ast.FunctionDef = raiseIfNone(extractFunctionDef(parseLogicalPath2astModule(raiseIfNone(astImportFrom.module)), targetCallableIdentifier))
601
+ astTuple: ast.Tuple = cast('ast.Tuple', raiseIfNone(NodeTourist(Be.Return.valueIs(Be.Tuple)
602
+ , doThat=Then.extractIt(DOT.value)).captureLastMatch(targetFunctionDef)))
603
+ astTuple.ctx = ast.Store()
604
+
605
+ changeAssignCallToTarget = NodeChanger(
606
+ findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
607
+ , doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts))))
608
+ changeAssignCallToTarget.visit(ingredientsFunction.astFunctionDef)
630
609
 
631
610
  ingredientsModule = IngredientsModule(ingredientsFunction)
632
611
  ingredientsModule.removeImportFromModule('numpy')
@@ -635,8 +614,6 @@ def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
635
614
 
636
615
  write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
637
616
 
638
- return pathFilename
639
-
640
617
  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
618
  """Generate Numba-accelerated Theorem 2 implementation with dataclass decomposition.
642
619
 
@@ -696,61 +673,47 @@ def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdenti
696
673
 
697
674
  return pathFilename
698
675
 
699
- def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
700
- """Generate interface module for dataclass unpacking and repacking operations.
676
+ 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
677
+ """Generate constrained Theorem 2 implementation by removing unnecessary logic.
701
678
 
702
679
  (AI generated docstring)
703
680
 
704
- Creates a specialized module that serves as an interface between dataclass-based
705
- calling code and optimized implementations that operate on decomposed primitive
706
- values. The generated module includes a function that unpacks dataclass instances
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.
681
+ Creates a trimmed version of the Theorem 2 implementation by eliminating conditional logic that is not needed under specific
682
+ constraint assumptions. This transformation removes checks for unconstrained dimensions, simplifying the algorithm for cases
683
+ where dimensional constraints are guaranteed to be satisfied by external conditions.
710
684
 
711
- This bridge module enables seamless integration between high-level dataclass-based
712
- APIs and low-level optimized implementations, maintaining type safety and usability
713
- while leveraging performance optimizations that require primitive value operations.
685
+ The trimming operation is particularly valuable for generating lean implementations where the calling context ensures that
686
+ certain conditions will always be met, allowing the removal of defensive programming constructs that add computational
687
+ overhead without providing benefits in the constrained environment.
714
688
 
715
689
  Parameters
716
690
  ----------
717
- astImportFrom : ast.ImportFrom
718
- Import statement specifying the target optimized function to call.
691
+ astModule : ast.Module
692
+ Source module containing the Theorem 2 implementation.
693
+ moduleIdentifier : str
694
+ Name for the generated trimmed module.
695
+ callableIdentifier : str | None = None
696
+ Name for the trimmed computational function.
697
+ logicalPathInfix : PathLike[str] | PurePath | str | None = None
698
+ Directory path for organizing the generated module.
699
+ sourceCallableDispatcher : str | None = None
700
+ Optional dispatcher function identifier (unused).
719
701
 
720
702
  Returns
721
703
  -------
722
- None
723
- The generated module is written directly to the filesystem.
704
+ pathFilename : PurePath
705
+ Filesystem path where the trimmed module was written.
724
706
 
725
707
  """
726
- callableIdentifierHARDCODED: str = 'sequential'
727
-
728
- algorithmSourceModule: identifierDotAttribute = algorithmSourceModuleDEFAULT
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))
708
+ sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
709
+ ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
710
+ ingredientsFunction.astFunctionDef.name = callableIdentifier or sourceCallableIdentifier
740
711
 
741
- ingredientsFunction.imports.update(shatteredDataclass.imports)
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()
712
+ dataclassInstanceIdentifier: identifierDotAttribute = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
749
713
 
750
- changeAssignCallToTarget = NodeChanger(
751
- findThis = Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier))
752
- , doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), astTuple.elts))))
753
- changeAssignCallToTarget.visit(ingredientsFunction.astFunctionDef)
714
+ findThis = IfThis.isIfUnaryNotAttributeNamespaceIdentifier(dataclassInstanceIdentifier, 'dimensionsUnconstrained')
715
+ doThat = Then.removeIt
716
+ NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
754
717
 
755
718
  ingredientsModule = IngredientsModule(ingredientsFunction)
756
719
  ingredientsModule.removeImportFromModule('numpy')
@@ -759,15 +722,17 @@ def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
759
722
 
760
723
  write_astModule(ingredientsModule, pathFilename, packageSettings.identifierPackage)
761
724
 
762
- if __name__ == '__main__':
763
- astModule: ast.Module = _getModule(logicalPathInfix=None)
764
- makeInitializeGroupsOfFolds(astModule, 'initializeCount', 'initializeGroupsOfFolds', logicalPathInfixDEFAULT)
725
+ return pathFilename
765
726
 
727
+ if __name__ == '__main__':
766
728
  astModule = _getModule(logicalPathInfix=None)
767
- pathFilename: PurePath = makeDaoOfMapFolding(astModule, 'daoOfMapFolding', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
729
+ pathFilename: PurePath = makeDaoOfMapFoldingNumba(astModule, 'daoOfMapFoldingNumba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
768
730
 
769
731
  astModule = _getModule(logicalPathInfix=None)
770
- pathFilename = makeDaoOfMapFoldingParallel(astModule, 'countParallel', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
732
+ pathFilename = makeDaoOfMapFoldingParallelNumba(astModule, 'countParallelNumba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
733
+
734
+ astModule: ast.Module = _getModule(logicalPathInfix=None)
735
+ makeInitializeState(astModule, 'initializeState', 'transitionOnGroupsOfFolds', logicalPathInfixDEFAULT)
771
736
 
772
737
  astModule = _getModule(logicalPathInfix=None)
773
738
  pathFilename = makeTheorem2(astModule, 'theorem2', None, logicalPathInfixDEFAULT, None)
@@ -780,3 +745,31 @@ if __name__ == '__main__':
780
745
 
781
746
  astImportFrom: ast.ImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.identifierPackage, logicalPathInfixDEFAULT, 'theorem2Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
782
747
  makeUnRePackDataclass(astImportFrom)
748
+
749
+ # A007822 -----------------------------------------------------------
750
+ astModule = _getModule(logicalPathInfix=None)
751
+ pathFilename = addSymmetryCheck(astModule, 'algorithmA007822', None, logicalPathInfixDEFAULT, None)
752
+
753
+ astModule = _getModule(moduleIdentifier='algorithmA007822')
754
+ pathFilename: PurePath = makeDaoOfMapFoldingNumba(astModule, 'algorithmA007822Numba', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
755
+
756
+ # I can't handle parallel right now.
757
+
758
+ # TODO Implement logic that lets me amend modules instead of only overwriting them. "initializeState" could/should include state
759
+ # initialization for multiple algorithms.
760
+ astModule = _getModule(moduleIdentifier='algorithmA007822')
761
+ # NOTE `initializeState.transitionOnGroupsOfFolds` will collide with `initializeStateA007822.transitionOnGroupsOfFolds` if the
762
+ # modules are merged. This problem is a side effect of the problem with `MapFoldingState.groupsOfFolds` and
763
+ # `MapFoldingState.foldsTotal`. If I fix that issue, then the identifier `initializeStateA007822.transitionOnGroupsOfFolds` will
764
+ # naturally change to something more appropriate (and remove the collision).
765
+ makeInitializeState(astModule, 'initializeStateA007822', 'transitionOnGroupsOfFolds', logicalPathInfixDEFAULT)
766
+
767
+ astModule = _getModule(moduleIdentifier='algorithmA007822')
768
+ pathFilename = makeTheorem2(astModule, 'theorem2A007822', None, logicalPathInfixDEFAULT, None)
769
+
770
+ astModule = parsePathFilename2astModule(pathFilename)
771
+ pathFilename = trimTheorem2(astModule, 'theorem2A007822Trimmed', None, logicalPathInfixDEFAULT, None)
772
+
773
+ astModule = parsePathFilename2astModule(pathFilename)
774
+ pathFilename = numbaOnTheorem2(astModule, 'theorem2A007822Numba', None, logicalPathInfixDEFAULT, None)
775
+
@@ -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.initializeCount import initializeGroupsOfFolds
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
@@ -292,7 +292,7 @@ if __name__ == '__main__':
292
292
  listNumPyTypeConfigs = [
293
293
  DatatypeConfig(fml='Array1DLeavesTotal', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array1DLeavesTotal'),
294
294
  DatatypeConfig(fml='Array1DElephino', Z0Z_module='numpy', Z0Z_type_name='uint16', Z0Z_asname='Array1DElephino'),
295
- DatatypeConfig(fml='Array3D', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array3D'),
295
+ DatatypeConfig(fml='Array3DLeavesTotal', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array3DLeavesTotal'),
296
296
  ]
297
297
 
298
298
  for typeConfig in listNumPyTypeConfigs:
@@ -326,7 +326,7 @@ if __name__ == '__main__':
326
326
  """
327
327
 
328
328
  if __name__ == '__main__':
329
- state = initializeGroupsOfFolds(MapFoldingState((2,4)))
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.initializeCount import initializeGroupsOfFolds
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
@@ -58,7 +58,7 @@ listDatatypeConfigurations: list[DatatypeConfiguration] = [
58
58
  listNumPy_dtype: list[DatatypeConfiguration] = [
59
59
  DatatypeConfiguration(datatypeIdentifier='Array1DLeavesTotal', typeModule='numpy', typeIdentifier='uint8', type_asname='Array1DLeavesTotal'),
60
60
  DatatypeConfiguration(datatypeIdentifier='Array1DElephino', typeModule='numpy', typeIdentifier='uint8', type_asname='Array1DElephino'),
61
- DatatypeConfiguration(datatypeIdentifier='Array3D', typeModule='numpy', typeIdentifier='uint8', type_asname='Array3D'),
61
+ DatatypeConfiguration(datatypeIdentifier='Array3DLeavesTotal', typeModule='numpy', typeIdentifier='uint8', type_asname='Array3DLeavesTotal'),
62
62
  ]
63
63
 
64
64
  def _addWriteFoldsTotal(ingredientsFunction: IngredientsFunction, job: RecipeJobTheorem2) -> IngredientsFunction:
@@ -212,7 +212,7 @@ def fromMapShape(mapShape: tuple[DatatypeLeavesTotal, ...]) -> None:
212
212
  along one axis.
213
213
 
214
214
  """
215
- state = initializeGroupsOfFolds(MapFoldingState(mapShape))
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)