mapFolding 0.15.4__py3-none-any.whl → 0.16.0__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 (58) hide show
  1. mapFolding/__init__.py +7 -9
  2. mapFolding/_theSSOT.py +1 -0
  3. mapFolding/algorithms/daoOfMapFolding.py +1 -2
  4. mapFolding/algorithms/getBucketsTotal.py +137 -0
  5. mapFolding/algorithms/matrixMeanders.py +457 -286
  6. mapFolding/algorithms/oeisIDbyFormula.py +310 -76
  7. mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +84 -0
  8. mapFolding/basecamp.py +99 -14
  9. mapFolding/dataBaskets.py +74 -0
  10. mapFolding/oeis.py +3 -2
  11. mapFolding/reference/A000682facts.py +662 -0
  12. mapFolding/reference/A005316facts.py +62 -0
  13. mapFolding/reference/matrixMeandersAnalysis/__init__.py +1 -0
  14. mapFolding/reference/matrixMeandersAnalysis/evenEven.py +144 -0
  15. mapFolding/reference/matrixMeandersAnalysis/oddEven.py +54 -0
  16. mapFolding/someAssemblyRequired/A007822/A007822rawMaterials.py +55 -0
  17. mapFolding/someAssemblyRequired/A007822/__init__.py +0 -0
  18. mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +185 -0
  19. mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +71 -0
  20. mapFolding/someAssemblyRequired/RecipeJob.py +2 -2
  21. mapFolding/someAssemblyRequired/__init__.py +9 -2
  22. mapFolding/someAssemblyRequired/_toolIfThis.py +4 -3
  23. mapFolding/someAssemblyRequired/_toolkitContainers.py +8 -8
  24. mapFolding/someAssemblyRequired/infoBooth.py +27 -30
  25. mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +1 -1
  26. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +5 -2
  27. mapFolding/someAssemblyRequired/makingModules_count.py +301 -0
  28. mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +120 -0
  29. mapFolding/someAssemblyRequired/mapFolding/__init__.py +0 -0
  30. mapFolding/someAssemblyRequired/mapFolding/makeMapFoldingModules.py +220 -0
  31. mapFolding/someAssemblyRequired/toolkitMakeModules.py +152 -0
  32. mapFolding/someAssemblyRequired/toolkitNumba.py +1 -1
  33. mapFolding/someAssemblyRequired/transformationTools.py +1 -0
  34. mapFolding/syntheticModules/A007822/__init__.py +1 -0
  35. mapFolding/syntheticModules/{algorithmA007822Numba.py → A007822/algorithmNumba.py} +2 -4
  36. mapFolding/syntheticModules/A007822/asynchronous.py +148 -0
  37. mapFolding/syntheticModules/A007822/asynchronousAnnex.py +68 -0
  38. mapFolding/syntheticModules/A007822/asynchronousTheorem2.py +53 -0
  39. mapFolding/syntheticModules/A007822/asynchronousTrimmed.py +47 -0
  40. mapFolding/syntheticModules/dataPackingA007822.py +1 -1
  41. mapFolding/tests/test_computations.py +2 -2
  42. mapFolding/trim_memory.py +62 -0
  43. mapFolding/zCuzDocStoopid/__init__.py +1 -0
  44. mapFolding/zCuzDocStoopid/makeDocstrings.py +63 -0
  45. {mapfolding-0.15.4.dist-info → mapfolding-0.16.0.dist-info}/METADATA +9 -2
  46. mapfolding-0.16.0.dist-info/RECORD +100 -0
  47. mapFolding/someAssemblyRequired/A007822rawMaterials.py +0 -46
  48. mapFolding/someAssemblyRequired/makeAllModules.py +0 -764
  49. mapfolding-0.15.4.dist-info/RECORD +0 -78
  50. /mapFolding/syntheticModules/{algorithmA007822.py → A007822/algorithm.py} +0 -0
  51. /mapFolding/syntheticModules/{initializeStateA007822.py → A007822/initializeState.py} +0 -0
  52. /mapFolding/syntheticModules/{theorem2A007822.py → A007822/theorem2.py} +0 -0
  53. /mapFolding/syntheticModules/{theorem2A007822Numba.py → A007822/theorem2Numba.py} +0 -0
  54. /mapFolding/syntheticModules/{theorem2A007822Trimmed.py → A007822/theorem2Trimmed.py} +0 -0
  55. {mapfolding-0.15.4.dist-info → mapfolding-0.16.0.dist-info}/WHEEL +0 -0
  56. {mapfolding-0.15.4.dist-info → mapfolding-0.16.0.dist-info}/entry_points.txt +0 -0
  57. {mapfolding-0.15.4.dist-info → mapfolding-0.16.0.dist-info}/licenses/LICENSE +0 -0
  58. {mapfolding-0.15.4.dist-info → mapfolding-0.16.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,144 @@
1
+ """
2
+ Matrix Meanders Buckets Estimation Formula.
3
+
4
+ This module provides a function to estimate the number of buckets in matrix meanders
5
+ analysis based on parameters n and k. The formula was derived through regression
6
+ analysis on empirical data and achieves an R² score of 0.9978.
7
+
8
+ Author: Generated from Jupyter notebook analysis
9
+ Date: September 2025
10
+ """
11
+ import math
12
+
13
+ def estimateBucketsFromParametersNandK(parameterN: int, parameterK: int) -> float:
14
+ """
15
+ Estimate the number of buckets in matrix meanders analysis based on parameters n and k.
16
+
17
+ This function implements a log-polynomial regression model derived from empirical data analysis
18
+ of matrix meanders with even-even configurations. The model was trained on 34 data points
19
+ and achieved an R² score of 0.9978, indicating excellent predictive performance.
20
+
21
+ The underlying formula is:
22
+ buckets = exp(0.087760 + 0.447340*n - 0.058715*k - 0.014116*n² + 0.072333*n*k - 0.090631*k²) - 1
23
+
24
+ Parameters
25
+ ----------
26
+ parameterN : int
27
+ The n parameter (must be positive integer, typically even)
28
+ parameterK : int
29
+ The k parameter (must be positive integer, typically even)
30
+
31
+ Returns
32
+ -------
33
+ float
34
+ Estimated number of buckets
35
+
36
+ Raises
37
+ ------
38
+ ValueError
39
+ If parameterN or parameterK are not positive integers
40
+
41
+ Example:
42
+ --------
43
+ >>> estimateBucketsFromParametersNandK(20, 10)
44
+ 3656.4
45
+ >>> estimateBucketsFromParametersNandK(44, 22)
46
+ 32715318.1
47
+
48
+ Notes
49
+ -----
50
+ This formula is based on empirical data and is most accurate for values
51
+ within the training range (n: 4-44, k: 2-22). Extrapolation beyond this
52
+ range should be done with caution.
53
+
54
+ The underlying mathematical relationship shows that buckets grow exponentially
55
+ with both n and k, with complex polynomial interactions captured in the logarithmic space.
56
+
57
+ Performance Metrics:
58
+ - R² Score: 0.9978
59
+ - Mean Absolute Error: 4.02% across all training examples
60
+ - Median Error: 2.69%
61
+ - Maximum Error: 18.86% (on smallest values)
62
+ """
63
+ # Input validation
64
+ if not isinstance(parameterN, int) or parameterN <= 0:
65
+ raise ValueError(f"parameterN must be a positive integer, got {parameterN}")
66
+ if not isinstance(parameterK, int) or parameterK <= 0:
67
+ raise ValueError(f"parameterK must be a positive integer, got {parameterK}")
68
+
69
+ # Convert to float for calculations
70
+ n = float(parameterN)
71
+ k = float(parameterK)
72
+
73
+ # Log-polynomial formula coefficients (derived from regression analysis)
74
+ # Formula: log(buckets + 1) = intercept + c1*n + c2*k + c3*n² + c4*n*k + c5*k²
75
+ interceptValue = 0.087760
76
+ coefficientN = 0.447340
77
+ coefficientK = -0.058715
78
+ coefficientNSquared = -0.014116
79
+ coefficientNTimesK = 0.072333
80
+ coefficientKSquared = -0.090631
81
+
82
+ # Calculate log(buckets + 1)
83
+ logBucketsPlusOne = (interceptValue +
84
+ coefficientN * n +
85
+ coefficientK * k +
86
+ coefficientNSquared * (n * n) +
87
+ coefficientNTimesK * (n * k) +
88
+ coefficientKSquared * (k * k))
89
+
90
+ # Transform back to original scale: buckets = exp(log(buckets + 1)) - 1
91
+ estimatedBuckets = math.exp(logBucketsPlusOne) - 1.0
92
+
93
+ return max(0.0, estimatedBuckets) # Ensure non-negative result
94
+
95
+
96
+ def validateFormulaAccuracy() -> None:
97
+ """
98
+ Validate the formula against known test cases from the training data.
99
+
100
+ This function demonstrates the accuracy of the formula by testing it
101
+ against several known data points from the original dataset.
102
+ """
103
+ # Test cases from the original dataset (n, k, expected_buckets)
104
+ testCases = [
105
+ (4, 2, 4),
106
+ (20, 10, 3592),
107
+ (36, 18, 1666843),
108
+ (44, 22, 35674291)
109
+ ]
110
+
111
+ print("Formula Validation Results:")
112
+ print("-" * 50)
113
+ print(f"{'n':<4} {'k':<4} {'Expected':<12} {'Predicted':<12} {'Error %':<8}")
114
+ print("-" * 50)
115
+
116
+ totalError = 0.0
117
+ for n, k, expected in testCases:
118
+ predicted = estimateBucketsFromParametersNandK(n, k)
119
+ error = abs((expected - predicted) / expected) * 100
120
+ totalError += error
121
+
122
+ # Format large numbers appropriately
123
+ expectedStr = f"{expected:.0f}" if expected < 1e6 else f"{expected:.2e}"
124
+ predictedStr = f"{predicted:.1f}" if predicted < 1e6 else f"{predicted:.2e}"
125
+
126
+ print(f"{n:<4} {k:<4} {expectedStr:<12} {predictedStr:<12} {error:<8.1f}")
127
+
128
+ avgError = totalError / len(testCases)
129
+ print("-" * 50)
130
+ print(f"Average Error: {avgError:.2f}%")
131
+
132
+
133
+ if __name__ == "__main__":
134
+ # Run validation when script is executed directly
135
+ validateFormulaAccuracy()
136
+
137
+ # Demonstrate usage
138
+ print("\nUsage Examples:")
139
+ print("-" * 30)
140
+
141
+ examples = [(8, 4), (20, 10), (36, 18)]
142
+ for n, k in examples:
143
+ result = estimateBucketsFromParametersNandK(n, k)
144
+ print(f"estimateBucketsFromParametersNandK({n}, {k}) = {result:.1f}")
@@ -0,0 +1,54 @@
1
+ from math import exp as math_exp, log as math_log
2
+
3
+ def estimateBuckets(n: int, k: int) -> float:
4
+ """Estimate the number of buckets for given integers n and k.
5
+
6
+ Model form (log-space):
7
+ log(estimate) = a
8
+ + b * log(n)
9
+ + c * log(k)
10
+ + d * log(n)*log(k)
11
+ + e * (k / n)
12
+ + f * (n / k)
13
+
14
+ Coefficients were obtained via ordinary least squares fit on log(buckets)
15
+ using the dataset in df_oddEven.csv (38 observations). The regression achieved
16
+ R^2 ≈ {coefficient_determination:.5f} (log space) with MAPE ≈ {mean_absolute_percentage_error:.2f}% on training data.
17
+
18
+ NOTE: This is an empirical approximation; extrapolation outside the range
19
+ n ∈ [{min(n_values)}, {max(n_values)}], k ∈ [{min(k_values)}, {max(k_values)}] may be unreliable.
20
+
21
+ Parameters
22
+ ----------
23
+ n : int
24
+ Primary size parameter (must be > 0)
25
+ k : int
26
+ Secondary size parameter (must be > 0)
27
+
28
+ Returns
29
+ -------
30
+ float
31
+ Estimated bucket count (positive real number). Caller may round if an
32
+ integer is desired.
33
+ """
34
+ if not isinstance(n, int) or n <= 0:
35
+ raise ValueError(f'allegedInt n must be positive int, got {n!r}')
36
+ if not isinstance(k, int) or k <= 0:
37
+ raise ValueError(f'allegedInt k must be positive int, got {k!r}')
38
+
39
+ a = -679.088264366881
40
+ b = 864.829109159972
41
+ c = -873.871846814867
42
+ d = 3.487829177620
43
+ e = 943.512567960048
44
+ f = -193.640628682536
45
+
46
+ ln_n = math_log(n)
47
+ ln_k = math_log(k)
48
+ value_log = (a
49
+ + b * ln_n
50
+ + c * ln_k
51
+ + d * ln_n * ln_k
52
+ + e * (k / n)
53
+ + f * (n / k))
54
+ return math_exp(value_log)
@@ -0,0 +1,55 @@
1
+ from astToolkit import extractFunctionDef, Make # noqa: D100
2
+ from hunterMakesPy import raiseIfNone
3
+ from mapFolding.someAssemblyRequired import (
4
+ identifierCallableSourceDEFAULT, identifierCallableSourceDispatcherDEFAULT, identifierCountingDEFAULT,
5
+ identifierDataclassInstanceDEFAULT, logicalPathInfixDEFAULT)
6
+ import ast
7
+
8
+ identifierDataclass: str = identifierDataclassInstanceDEFAULT
9
+ identifierCounting: str = identifierCountingDEFAULT
10
+ logicalPathInfixA007822: str = logicalPathInfixDEFAULT + '.A007822'
11
+ sourceCallableDispatcherA007822: str = identifierCallableSourceDispatcherDEFAULT
12
+ sourceCallableIdentifierA007822: str = identifierCallableSourceDEFAULT
13
+
14
+ identifier_filterAsymmetricFolds = 'filterAsymmetricFolds'
15
+
16
+ ImaString = f"""
17
+ def {identifier_filterAsymmetricFolds}({identifierDataclass}: MapFoldingState) -> MapFoldingState:
18
+ {identifierDataclass}.indexLeaf = 0
19
+ leafConnectee = 0
20
+ while leafConnectee < {identifierDataclass}.leavesTotal + 1:
21
+ leafNumber = int({identifierDataclass}.leafBelow[{identifierDataclass}.indexLeaf])
22
+ {identifierDataclass}.leafComparison[leafConnectee] = (leafNumber - {identifierDataclass}.indexLeaf + {identifierDataclass}.leavesTotal) % {identifierDataclass}.leavesTotal
23
+ {identifierDataclass}.indexLeaf = leafNumber
24
+ leafConnectee += 1
25
+
26
+ indexInMiddle = {identifierDataclass}.leavesTotal // 2
27
+ {identifierDataclass}.indexMiniGap = 0
28
+ while {identifierDataclass}.indexMiniGap < {identifierDataclass}.leavesTotal + 1:
29
+ ImaSymmetricFold = True
30
+ leafConnectee = 0
31
+ while leafConnectee < indexInMiddle:
32
+ if {identifierDataclass}.leafComparison[({identifierDataclass}.indexMiniGap + leafConnectee) % ({identifierDataclass}.leavesTotal + 1)] != {identifierDataclass}.leafComparison[({identifierDataclass}.indexMiniGap + {identifierDataclass}.leavesTotal - 1 - leafConnectee) % ({identifierDataclass}.leavesTotal + 1)]:
33
+ ImaSymmetricFold = False
34
+ break
35
+ leafConnectee += 1
36
+ if ImaSymmetricFold:
37
+ {identifierDataclass}.{identifierCounting} += 1
38
+ {identifierDataclass}.indexMiniGap += 1
39
+
40
+ return {identifierDataclass}
41
+ """ # noqa: E501
42
+
43
+ FunctionDef_filterAsymmetricFolds: ast.FunctionDef = raiseIfNone(extractFunctionDef(ast.parse(ImaString), identifier_filterAsymmetricFolds))
44
+ del ImaString
45
+
46
+ ImaString = f"{identifierDataclass} = {identifier_filterAsymmetricFolds}({identifierDataclass})"
47
+ A007822incrementCount = ast.parse(ImaString).body[0]
48
+ del ImaString
49
+
50
+ ImaString = f'{identifierDataclass}.{identifierCounting} = ({identifierDataclass}.{identifierCounting} + 1) // 2'
51
+ A007822adjustFoldsTotal = ast.parse(ImaString).body[0]
52
+ del ImaString
53
+
54
+ astExprCall_filterAsymmetricFoldsDataclass: ast.Expr = Make.Expr(Make.Call(Make.Name(identifier_filterAsymmetricFolds), listParameters=[Make.Attribute(Make.Name(identifierDataclass), 'leafBelow')]))
55
+ astExprCall_filterAsymmetricFoldsLeafBelow: ast.Expr = Make.Expr(Make.Call(Make.Name(identifier_filterAsymmetricFolds), listParameters=[Make.Name('leafBelow')]))
File without changes
@@ -0,0 +1,185 @@
1
+ """addSymmetryCheckAsynchronous."""
2
+ from astToolkit import Be, extractFunctionDef, Grab, Make, NodeChanger, NodeTourist, parsePathFilename2astModule, Then
3
+ from hunterMakesPy import raiseIfNone
4
+ from mapFolding import packageSettings
5
+ from mapFolding.someAssemblyRequired import IfThis, logicalPathInfixAlgorithmDEFAULT
6
+ from mapFolding.someAssemblyRequired.A007822.A007822rawMaterials import (
7
+ A007822adjustFoldsTotal, astExprCall_filterAsymmetricFoldsDataclass, identifier_filterAsymmetricFolds,
8
+ identifierCounting, identifierDataclass, logicalPathInfixA007822, sourceCallableDispatcherA007822,
9
+ sourceCallableIdentifierA007822)
10
+ from mapFolding.someAssemblyRequired.makingModules_count import makeTheorem2, numbaOnTheorem2, trimTheorem2
11
+ from mapFolding.someAssemblyRequired.toolkitMakeModules import getModule, getPathFilename, write_astModule
12
+ from os import PathLike
13
+ from pathlib import PurePath
14
+ import ast
15
+
16
+ identifier_initializeConcurrencyManager = 'initializeConcurrencyManager'
17
+
18
+ astExprCall_initializeConcurrencyManager = Make.Expr(Make.Call(Make.Name(identifier_initializeConcurrencyManager)))
19
+ identifier_getAsymmetricFoldsTotal = 'getAsymmetricFoldsTotal'
20
+ AssignTotal2CountingIdentifier: ast.Assign = Make.Assign(
21
+ [Make.Attribute(Make.Name(identifierDataclass), identifierCounting, context=Make.Store())]
22
+ , value=Make.Call(Make.Name(identifier_getAsymmetricFoldsTotal))
23
+ )
24
+ identifier_processCompletedFutures = '_processCompletedFutures'
25
+
26
+ def addSymmetryCheckAsynchronous(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath: # noqa: ARG001
27
+ """Add symmetry check to the counting function."""
28
+ astFunctionDef_count: ast.FunctionDef = raiseIfNone(NodeTourist(
29
+ findThis = Be.FunctionDef.nameIs(IfThis.isIdentifier(sourceCallableIdentifierA007822))
30
+ , doThat = Then.extractIt
31
+ ).captureLastMatch(astModule))
32
+
33
+ NodeChanger(Be.Return, Then.insertThisAbove([A007822adjustFoldsTotal])).visit(astFunctionDef_count)
34
+
35
+ NodeChanger(
36
+ findThis=Be.AugAssign.targetIs(IfThis.isAttributeNamespaceIdentifier(identifierDataclass, identifierCounting))
37
+ , doThat=Then.replaceWith(astExprCall_filterAsymmetricFoldsDataclass)
38
+ ).visit(astFunctionDef_count)
39
+
40
+ NodeChanger(
41
+ findThis=Be.While.testIs(IfThis.isCallIdentifier('activeLeafGreaterThan0'))
42
+ , doThat=Grab.orelseAttribute(Then.replaceWith([AssignTotal2CountingIdentifier]))
43
+ ).visit(astFunctionDef_count)
44
+
45
+ NodeChanger(
46
+ findThis=Be.FunctionDef.nameIs(IfThis.isIdentifier(sourceCallableIdentifierA007822))
47
+ , doThat=Then.replaceWith(astFunctionDef_count)
48
+ ).visit(astModule)
49
+
50
+ astFunctionDef_doTheNeedful: ast.FunctionDef = raiseIfNone(NodeTourist(
51
+ findThis = Be.FunctionDef.nameIs(IfThis.isIdentifier(sourceCallableDispatcher))
52
+ , doThat = Then.extractIt
53
+ ).captureLastMatch(astModule))
54
+
55
+ astFunctionDef_doTheNeedful.body.insert(0, astExprCall_initializeConcurrencyManager)
56
+
57
+ NodeChanger(
58
+ findThis=Be.FunctionDef.nameIs(IfThis.isIdentifier(sourceCallableDispatcher))
59
+ , doThat=Then.replaceWith(astFunctionDef_doTheNeedful)
60
+ ).visit(astModule)
61
+
62
+ astImportFrom = ast.ImportFrom(f'{packageSettings.identifierPackage}.{logicalPathInfix}.{moduleIdentifier}Annex'
63
+ , [Make.alias(identifier_filterAsymmetricFolds), Make.alias(identifier_getAsymmetricFoldsTotal), Make.alias(identifier_initializeConcurrencyManager)], 0)
64
+
65
+ astModule.body.insert(0, astImportFrom)
66
+
67
+ pathFilename: PurePath = getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
68
+ pathFilenameAnnex: PurePath = getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier + 'Annex')
69
+
70
+ write_astModule(astModule, pathFilename, packageSettings.identifierPackage)
71
+ del astModule
72
+ # ----------------- Ingredients Module Annex ------------------------------------------------------------------------------
73
+ ImaString = """from concurrent.futures import Future as ConcurrentFuture, ProcessPoolExecutor
74
+ from hunterMakesPy import raiseIfNone
75
+ from mapFolding import Array1DLeavesTotal
76
+ from queue import Empty, Queue
77
+ from threading import Thread
78
+ import numpy"""
79
+
80
+ astModule = ast.parse(ImaString)
81
+ del ImaString
82
+
83
+ ImaString = f"""concurrencyManager = None
84
+ {identifierCounting}Total: int = 0
85
+ processingThread = None
86
+ queueFutures: Queue[ConcurrentFuture[int]] = Queue()
87
+ """
88
+ astModule.body.extend(ast.parse(ImaString).body)
89
+ del ImaString
90
+
91
+ ImaString = f"""def {identifier_initializeConcurrencyManager}(maxWorkers: int | None = None, {identifierCounting}: int = 0) -> None:
92
+ global concurrencyManager, queueFutures, {identifierCounting}Total, processingThread
93
+ concurrencyManager = ProcessPoolExecutor(max_workers=maxWorkers)
94
+ queueFutures = Queue()
95
+ {identifierCounting}Total = {identifierCounting}
96
+ processingThread = Thread(target={identifier_processCompletedFutures})
97
+ processingThread.start()
98
+ """
99
+ astModule.body.append(raiseIfNone(extractFunctionDef(ast.parse(ImaString), identifier_initializeConcurrencyManager)))
100
+ del ImaString
101
+
102
+ ImaString = f"""def {identifier_processCompletedFutures}() -> None:
103
+ global queueFutures, {identifierCounting}Total
104
+ while True:
105
+ try:
106
+ claimTicket: ConcurrentFuture[int] = queueFutures.get(timeout=1)
107
+ if claimTicket is None:
108
+ break
109
+ {identifierCounting}Total += claimTicket.result()
110
+ except Empty:
111
+ continue
112
+ """
113
+ astModule.body.append(raiseIfNone(extractFunctionDef(ast.parse(ImaString), identifier_processCompletedFutures)))
114
+ del ImaString
115
+
116
+ ImaString = f"""def _{identifier_filterAsymmetricFolds}(leafBelow: Array1DLeavesTotal) -> int:
117
+ {identifierCounting} = 0
118
+ leafComparison: Array1DLeavesTotal = numpy.zeros_like(leafBelow)
119
+ leavesTotal = leafBelow.size - 1
120
+
121
+ indexLeaf = 0
122
+ leafConnectee = 0
123
+ while leafConnectee < leavesTotal + 1:
124
+ leafNumber = int(leafBelow[indexLeaf])
125
+ leafComparison[leafConnectee] = (leafNumber - indexLeaf + leavesTotal) % leavesTotal
126
+ indexLeaf = leafNumber
127
+ leafConnectee += 1
128
+
129
+ indexInMiddle = leavesTotal // 2
130
+ indexDistance = 0
131
+ while indexDistance < leavesTotal + 1:
132
+ ImaSymmetricFold = True
133
+ leafConnectee = 0
134
+ while leafConnectee < indexInMiddle:
135
+ if leafComparison[(indexDistance + leafConnectee) % (leavesTotal + 1)] != leafComparison[(indexDistance + leavesTotal - 1 - leafConnectee) % (leavesTotal + 1)]:
136
+ ImaSymmetricFold = False
137
+ break
138
+ leafConnectee += 1
139
+ if ImaSymmetricFold:
140
+ {identifierCounting} += 1
141
+ indexDistance += 1
142
+ return {identifierCounting}
143
+ """
144
+ astModule.body.append(raiseIfNone(extractFunctionDef(ast.parse(ImaString), f'_{identifier_filterAsymmetricFolds}')))
145
+ del ImaString
146
+
147
+ ImaString = f"""
148
+ def {identifier_filterAsymmetricFolds}(leafBelow: Array1DLeavesTotal) -> None:
149
+ global concurrencyManager, queueFutures
150
+ queueFutures.put(raiseIfNone(concurrencyManager).submit(_{identifier_filterAsymmetricFolds}, leafBelow.copy()))
151
+ """
152
+ astModule.body.append(raiseIfNone(extractFunctionDef(ast.parse(ImaString), identifier_filterAsymmetricFolds)))
153
+ del ImaString
154
+
155
+ ImaString = f"""
156
+ def {identifier_getAsymmetricFoldsTotal}() -> int:
157
+ global concurrencyManager, queueFutures, processingThread
158
+ raiseIfNone(concurrencyManager).shutdown(wait=True)
159
+ queueFutures.put(None)
160
+ raiseIfNone(processingThread).join()
161
+ return {identifierCounting}Total
162
+ """
163
+ astModule.body.append(raiseIfNone(extractFunctionDef(ast.parse(ImaString), identifier_getAsymmetricFoldsTotal)))
164
+ del ImaString
165
+
166
+ write_astModule(astModule, pathFilenameAnnex, packageSettings.identifierPackage)
167
+
168
+ return pathFilename
169
+
170
+ def _makeA007822AsynchronousModules() -> None:
171
+
172
+ astModule = getModule(logicalPathInfix=logicalPathInfixAlgorithmDEFAULT)
173
+ pathFilename = addSymmetryCheckAsynchronous(astModule, 'asynchronous', None, logicalPathInfixA007822, sourceCallableDispatcherA007822)
174
+
175
+ astModule = getModule(logicalPathInfix=logicalPathInfixA007822, moduleIdentifier='asynchronous')
176
+ pathFilename = makeTheorem2(astModule, 'asynchronousTheorem2', None, logicalPathInfixA007822, None)
177
+
178
+ astModule = parsePathFilename2astModule(pathFilename)
179
+ pathFilename = trimTheorem2(astModule, 'asynchronousTrimmed', None, logicalPathInfixA007822, None)
180
+
181
+ # astModule = parsePathFilename2astModule(pathFilename)
182
+ # pathFilename = numbaOnTheorem2(astModule, 'asynchronousNumba', None, logicalPathInfixA007822, identifier_filterAsymmetricFolds)
183
+
184
+ if __name__ == '__main__':
185
+ _makeA007822AsynchronousModules()
@@ -0,0 +1,71 @@
1
+ """addSymmetryCheck."""
2
+ from astToolkit import Be, Make, NodeChanger, NodeTourist, parsePathFilename2astModule, Then
3
+ from hunterMakesPy import raiseIfNone
4
+ from mapFolding import packageSettings
5
+ from mapFolding.someAssemblyRequired import (
6
+ identifierCallableSourceDEFAULT, identifierCountingDEFAULT, identifierDataclassInstanceDEFAULT, IfThis)
7
+ from mapFolding.someAssemblyRequired.A007822.A007822rawMaterials import (
8
+ A007822adjustFoldsTotal, A007822incrementCount, FunctionDef_filterAsymmetricFolds, logicalPathInfixA007822,
9
+ sourceCallableDispatcherA007822, sourceCallableIdentifierA007822)
10
+ from mapFolding.someAssemblyRequired.makingModules_count import (
11
+ makeDaoOfMapFoldingNumba, makeTheorem2, numbaOnTheorem2, trimTheorem2)
12
+ from mapFolding.someAssemblyRequired.makingModules_doTheNeedful import makeInitializeState, makeUnRePackDataclass
13
+ from mapFolding.someAssemblyRequired.toolkitMakeModules import (
14
+ getLogicalPath, getModule, getPathFilename, write_astModule)
15
+ from os import PathLike
16
+ from pathlib import PurePath
17
+ import ast
18
+
19
+ 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
20
+ """Add logic to check for symmetric folds."""
21
+ # NOTE HEY HEY! Are you trying to figure out why there is more than one copy of `filterAsymmetricFolds`? See the TODO NOTE, below.
22
+
23
+ astFunctionDef_count: ast.FunctionDef = raiseIfNone(NodeTourist(
24
+ findThis = Be.FunctionDef.nameIs(IfThis.isIdentifier(identifierCallableSourceDEFAULT))
25
+ , doThat = Then.extractIt
26
+ ).captureLastMatch(astModule))
27
+ astFunctionDef_count.name = sourceCallableIdentifierA007822
28
+
29
+ NodeChanger(Be.Return, Then.insertThisAbove([A007822adjustFoldsTotal])).visit(astFunctionDef_count)
30
+
31
+ NodeChanger(
32
+ findThis=Be.AugAssign.targetIs(IfThis.isAttributeNamespaceIdentifier(identifierDataclassInstanceDEFAULT, identifierCountingDEFAULT))
33
+ , doThat=Then.replaceWith(A007822incrementCount)
34
+ ).visit(astFunctionDef_count)
35
+
36
+ # TODO NOTE This will insert a copy of `filterAsymmetricFolds` for each `ast.ImportFrom` in the source module. Find or make a
37
+ # system to replace the `Ingredients` paradigm.
38
+ NodeChanger(Be.ImportFrom, Then.insertThisBelow([FunctionDef_filterAsymmetricFolds])).visit(astModule)
39
+
40
+ pathFilename: PurePath = getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
41
+
42
+ write_astModule(astModule, pathFilename, packageSettings.identifierPackage)
43
+
44
+ return pathFilename
45
+
46
+ def _makeA007822Modules() -> None:
47
+ astModule = getModule(logicalPathInfix='algorithms')
48
+ pathFilename = addSymmetryCheck(astModule, 'algorithm', None, logicalPathInfixA007822, None)
49
+
50
+ astModule = getModule(logicalPathInfix=logicalPathInfixA007822, moduleIdentifier='algorithm')
51
+ pathFilename: PurePath = makeDaoOfMapFoldingNumba(astModule, 'algorithmNumba', None, logicalPathInfixA007822, sourceCallableDispatcherA007822)
52
+
53
+ # NOTE I can't handle parallel right now.
54
+
55
+ astModule = getModule(logicalPathInfix=logicalPathInfixA007822, moduleIdentifier='algorithm')
56
+ makeInitializeState(astModule, 'initializeState', 'transitionOnGroupsOfFolds', logicalPathInfixA007822)
57
+
58
+ astModule = getModule(logicalPathInfix=logicalPathInfixA007822, moduleIdentifier='algorithm')
59
+ pathFilename = makeTheorem2(astModule, 'theorem2', None, logicalPathInfixA007822, None)
60
+
61
+ astModule = parsePathFilename2astModule(pathFilename)
62
+ pathFilename = trimTheorem2(astModule, 'theorem2Trimmed', None, logicalPathInfixA007822, None)
63
+
64
+ astModule = parsePathFilename2astModule(pathFilename)
65
+ pathFilename = numbaOnTheorem2(astModule, 'theorem2Numba', None, logicalPathInfixA007822, None)
66
+
67
+ astImportFrom: ast.ImportFrom = Make.ImportFrom(getLogicalPath(packageSettings.identifierPackage, logicalPathInfixA007822, 'theorem2Numba'), list_alias=[Make.alias(sourceCallableIdentifierA007822)])
68
+ makeUnRePackDataclass(astImportFrom, 'dataPackingA007822')
69
+
70
+ if __name__ == '__main__':
71
+ _makeA007822Modules()
@@ -6,7 +6,7 @@ from mapFolding import (
6
6
  DatatypeElephino as TheDatatypeElephino, DatatypeFoldsTotal as TheDatatypeFoldsTotal,
7
7
  DatatypeLeavesTotal as TheDatatypeLeavesTotal, getPathFilenameFoldsTotal, getPathRootJobDEFAULT, MapFoldingState,
8
8
  packageSettings)
9
- from mapFolding.someAssemblyRequired import dataclassInstanceIdentifierDEFAULT, ShatteredDataclass
9
+ from mapFolding.someAssemblyRequired import identifierDataclassInstanceDEFAULT, ShatteredDataclass
10
10
  from mapFolding.someAssemblyRequired.transformationTools import shatter_dataclassesDOTdataclass
11
11
  from pathlib import Path, PurePosixPath
12
12
  import dataclasses
@@ -98,7 +98,7 @@ class RecipeJobTheorem2:
98
98
  """Logical path to the dataclass module."""
99
99
  sourceDataclassIdentifier: str = 'MapFoldingState'
100
100
  """Name of the source dataclass."""
101
- sourceDataclassInstance: str = dataclassInstanceIdentifierDEFAULT
101
+ sourceDataclassInstance: str = identifierDataclassInstanceDEFAULT
102
102
  """Instance identifier for the dataclass."""
103
103
 
104
104
  sourcePathPackage: PurePosixPath | None = PurePosixPath(packageSettings.pathPackage) # noqa: RUF009
@@ -73,8 +73,15 @@ calculations through the strategic application of compiler optimization techniqu
73
73
  """
74
74
 
75
75
  from mapFolding.someAssemblyRequired.infoBooth import (
76
- dataclassInstanceIdentifierDEFAULT as dataclassInstanceIdentifierDEFAULT,
77
- sourceCallableDispatcherDEFAULT as sourceCallableDispatcherDEFAULT,
76
+ dictionaryEstimatesMapFolding as dictionaryEstimatesMapFolding,
77
+ identifierCallableSourceDEFAULT as identifierCallableSourceDEFAULT,
78
+ identifierCallableSourceDispatcherDEFAULT as identifierCallableSourceDispatcherDEFAULT,
79
+ identifierCountingDEFAULT as identifierCountingDEFAULT,
80
+ identifierDataclassInstanceDEFAULT as identifierDataclassInstanceDEFAULT,
81
+ identifierModuleDataPackingDEFAULT as identifierModuleDataPackingDEFAULT,
82
+ identifierModuleSourceAlgorithmDEFAULT as identifierModuleSourceAlgorithmDEFAULT,
83
+ logicalPathInfixAlgorithmDEFAULT as logicalPathInfixAlgorithmDEFAULT,
84
+ logicalPathInfixDEFAULT as logicalPathInfixDEFAULT,
78
85
  )
79
86
 
80
87
  from mapFolding.someAssemblyRequired._toolIfThis import IfThis as IfThis
@@ -67,7 +67,7 @@ class IfThis(astToolkit_IfThis):
67
67
 
68
68
  """
69
69
  return lambda node: (Be.Compare.leftIs(IfThis.isAttributeNamespaceIdentifier(namespace, identifier))(node)
70
- and Be.Compare.opsIs(lambda at: Be.LtE(at[0]))(node)
70
+ and Be.Compare.opsIs(Be.at(0, Be.LtE))(node)
71
71
  )
72
72
 
73
73
  @staticmethod
@@ -94,8 +94,9 @@ class IfThis(astToolkit_IfThis):
94
94
 
95
95
  """
96
96
  return lambda node: (Be.Compare.leftIs(IfThis.isAttributeNamespaceIdentifier(namespace, identifier))(node)
97
- and Be.Gt(node.ops[0])
98
- and IfThis.isConstant_value(0)(node.comparators[0]))
97
+ and Be.Compare.opsIs(Be.at(0, Be.Gt))(node)
98
+ and Be.Compare.comparatorsIs(Be.at(0, IfThis.isConstant_value(0)))(node)
99
+ )
99
100
 
100
101
  @staticmethod
101
102
  def isIfAttributeNamespaceIdentifierGreaterThan0(namespace: str, identifier: str) -> Callable[[ast.AST], TypeIs[ast.If]]:
@@ -62,10 +62,10 @@ class ShatteredDataclass:
62
62
  countingVariableName: ast.Name
63
63
  """AST name node representing the counting variable identifier."""
64
64
 
65
- field2AnnAssign: dict[str, ast.AnnAssign | ast.Assign] = dataclasses.field(default_factory=lambda: dict[str, ast.AnnAssign | ast.Assign]())
65
+ field2AnnAssign: dict[str, ast.AnnAssign | ast.Assign] = dataclasses.field(default_factory=dict[str, ast.AnnAssign | ast.Assign])
66
66
  """Maps field names to their corresponding AST assignment expressions for initialization."""
67
67
 
68
- Z0Z_field2AnnAssign: dict[str, tuple[ast.AnnAssign | ast.Assign, str]] = dataclasses.field(default_factory=lambda: dict[str, tuple[ast.AnnAssign | ast.Assign, str]]())
68
+ Z0Z_field2AnnAssign: dict[str, tuple[ast.AnnAssign | ast.Assign, str]] = dataclasses.field(default_factory=dict[str, tuple[ast.AnnAssign | ast.Assign, str]])
69
69
  """Temporary mapping for field assignments with constructor type information."""
70
70
 
71
71
  fragments4AssignmentOrParameters: ast.Tuple = dummyTuple
@@ -74,22 +74,22 @@ class ShatteredDataclass:
74
74
  imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
75
75
  """Import records for the dataclass and its constituent field types."""
76
76
 
77
- list_argAnnotated4ArgumentsSpecification: list[ast.arg] = dataclasses.field(default_factory=lambda: list[ast.arg]())
77
+ list_argAnnotated4ArgumentsSpecification: list[ast.arg] = dataclasses.field(default_factory=list[ast.arg])
78
78
  """Function argument nodes with type annotations for parameter specification."""
79
79
 
80
- list_keyword_field__field4init: list[ast.keyword] = dataclasses.field(default_factory=lambda: list[ast.keyword]())
80
+ list_keyword_field__field4init: list[ast.keyword] = dataclasses.field(default_factory=list[ast.keyword])
81
81
  """Keyword arguments for dataclass initialization using field=field format."""
82
82
 
83
- listAnnotations: list[ast.expr] = dataclasses.field(default_factory=lambda: list[ast.expr]())
83
+ listAnnotations: list[ast.expr] = dataclasses.field(default_factory=list[ast.expr])
84
84
  """Type annotations for each dataclass field in declaration order."""
85
85
 
86
- listName4Parameters: list[ast.Name] = dataclasses.field(default_factory=lambda: list[ast.Name]())
86
+ listName4Parameters: list[ast.Name] = dataclasses.field(default_factory=list[ast.Name])
87
87
  """Name nodes for each dataclass field used as function parameters."""
88
88
 
89
- listUnpack: list[ast.AnnAssign] = dataclasses.field(default_factory=lambda: list[ast.AnnAssign]())
89
+ listUnpack: list[ast.AnnAssign] = dataclasses.field(default_factory=list[ast.AnnAssign])
90
90
  """Annotated assignment statements to extract individual fields from dataclass instances."""
91
91
 
92
- map_stateDOTfield2Name: dict[ast.AST, ast.Name] = dataclasses.field(default_factory=lambda: dict[ast.AST, ast.Name]())
92
+ map_stateDOTfield2Name: dict[ast.AST, ast.Name] = dataclasses.field(default_factory=dict[ast.AST, ast.Name])
93
93
  """Maps dataclass attribute access expressions to field name nodes for find-replace operations."""
94
94
 
95
95
  repack: ast.Assign = dummyAssign