mapFolding 0.15.1__py3-none-any.whl → 0.15.3__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 (33) hide show
  1. mapFolding/_oeisFormulas/A000682.py +70 -2
  2. mapFolding/_oeisFormulas/A001010.py +11 -10
  3. mapFolding/_oeisFormulas/A001011.py +5 -0
  4. mapFolding/_oeisFormulas/Z0Z_aOFn.py +17 -4
  5. mapFolding/_oeisFormulas/Z0Z_notes.py +16 -0
  6. mapFolding/_oeisFormulas/Z0Z_oeisMeanders.py +35 -21
  7. mapFolding/_oeisFormulas/Z0Z_symmetry.py +131 -0
  8. mapFolding/_oeisFormulas/matrixMeanders.py +31 -23
  9. mapFolding/_oeisFormulas/matrixMeanders64.py +152 -0
  10. mapFolding/_oeisFormulas/matrixMeandersAnnex.py +1 -1
  11. mapFolding/_theSSOT.py +1 -1
  12. mapFolding/_theTypes.py +1 -1
  13. mapFolding/basecamp.py +52 -66
  14. mapFolding/reference/matrixMeandersBaselineV2.py +133 -0
  15. mapFolding/someAssemblyRequired/A007822rawMaterials.py +1 -1
  16. mapFolding/someAssemblyRequired/makeAllModules.py +4 -15
  17. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +5 -4
  18. mapFolding/syntheticModules/algorithmA007822.py +1 -1
  19. mapFolding/syntheticModules/algorithmA007822Numba.py +1 -1
  20. mapFolding/syntheticModules/dataPackingA007822.py +26 -0
  21. mapFolding/syntheticModules/initializeStateA007822.py +1 -1
  22. mapFolding/syntheticModules/theorem2A007822.py +1 -1
  23. mapFolding/syntheticModules/theorem2A007822Numba.py +3 -4
  24. mapFolding/syntheticModules/theorem2A007822Trimmed.py +1 -1
  25. mapFolding/syntheticModules/theorem2Numba.py +2 -3
  26. mapFolding/tests/conftest.py +2 -1
  27. mapFolding/tests/test_computations.py +48 -41
  28. {mapfolding-0.15.1.dist-info → mapfolding-0.15.3.dist-info}/METADATA +3 -2
  29. {mapfolding-0.15.1.dist-info → mapfolding-0.15.3.dist-info}/RECORD +33 -27
  30. {mapfolding-0.15.1.dist-info → mapfolding-0.15.3.dist-info}/WHEEL +0 -0
  31. {mapfolding-0.15.1.dist-info → mapfolding-0.15.3.dist-info}/entry_points.txt +0 -0
  32. {mapfolding-0.15.1.dist-info → mapfolding-0.15.3.dist-info}/licenses/LICENSE +0 -0
  33. {mapfolding-0.15.1.dist-info → mapfolding-0.15.3.dist-info}/top_level.txt +0 -0
@@ -35,7 +35,7 @@ curveMaximum: dict[int, limitLocators] = {
35
35
  25: limitLocators(0x55555555555555, 0xaaaaaaaaaaaaaa, 0x40000000000000),
36
36
  26: limitLocators(0x155555555555555, 0x2aaaaaaaaaaaaaa, 0x100000000000000),
37
37
  27: limitLocators(0x555555555555555, 0xaaaaaaaaaaaaaaa, 0x400000000000000),
38
- 28: limitLocators(0x1555555555555555, 0x2aaaaaaaaaaaaaaa, 0x1000000000000000), # 0x2aaaaaaaaaaaaaaa.bit_length() = 62
38
+ 28: limitLocators(0x1555555555555555, 0x2aaaaaaaaaaaaaaa, 0x1000000000000000),
39
39
  29: limitLocators(0x5555555555555555, 0xaaaaaaaaaaaaaaaa, 0x4000000000000000),
40
40
  30: limitLocators(0x15555555555555555, 0x2aaaaaaaaaaaaaaaa, 0x10000000000000000),
41
41
  31: limitLocators(0x55555555555555555, 0xaaaaaaaaaaaaaaaaa, 0x40000000000000000),
mapFolding/_theSSOT.py CHANGED
@@ -115,7 +115,7 @@ settingsOEISManuallySelected: dict[str, MetadataOEISidManuallySet] = {
115
115
  'getMapShape': lambda n: (1, 2 * n),
116
116
  'valuesBenchmark': [7],
117
117
  'valuesTestParallelization': [*range(2, 4)],
118
- 'valuesTestValidation': [random.randint(2, 4)], # noqa: S311
118
+ 'valuesTestValidation': [random.randint(2, 8)], # noqa: S311
119
119
  },
120
120
  }
121
121
 
mapFolding/_theTypes.py CHANGED
@@ -36,7 +36,7 @@ NumPyFoldsTotal: TypeAlias = numpy_uint64 # noqa: UP040 The TypeAlias may be us
36
36
 
37
37
  Note well
38
38
  ---------
39
- If your elements might exceed 1.8 x 10^19, then you should take extra steps to ensure the integrity of the data in NumPy or use a
39
+ If your element values might exceed 1.8 x 10^19, then you should take extra steps to ensure the integrity of the data in NumPy or use a
40
40
  different data structure."""
41
41
 
42
42
  Array3DLeavesTotal: TypeAlias = ndarray[tuple[int, int, int], dtype[NumPyLeavesTotal]] # noqa: UP040 The TypeAlias may be used to construct ("cast") a value to the type. And the identifier may be changed to a different type.
mapFolding/basecamp.py CHANGED
@@ -1,27 +1,4 @@
1
- """
2
- Unified interface for map folding computation orchestration.
3
-
4
- (AI generated docstring)
5
-
6
- This module represents the culmination of the computational ecosystem, providing
7
- the primary entry point where users interact with the complete map folding analysis
8
- system. It orchestrates all preceding layers: the configuration foundation,
9
- type system, core utilities, state management, and persistent storage to deliver
10
- a seamless computational experience.
11
-
12
- The interface handles multiple computation flows including sequential algorithms,
13
- experimental task division strategies, and various mathematical theorem implementations.
14
- It provides flexible parameter validation, computation method selection, task
15
- division management, processor utilization control, and automatic result persistence.
16
- Integration with OEIS sequences enables research validation and mathematical
17
- verification of computed results.
18
-
19
- Through this unified interface, researchers and practitioners can access the full
20
- power of Lunnon's algorithm implementation while the underlying computational
21
- complexity remains elegantly abstracted. The interface ensures that whether
22
- solving simple 2D problems or complex multi-dimensional challenges, users receive
23
- consistent, reliable, and efficiently computed folding pattern counts.
24
- """
1
+ """Unified interface for map folding computation."""
25
2
 
26
3
  from collections.abc import Sequence
27
4
  from mapFolding import (
@@ -35,42 +12,62 @@ def countFolds(listDimensions: Sequence[int] | None = None
35
12
  , pathLikeWriteFoldsTotal: PathLike[str] | PurePath | None = None
36
13
  , computationDivisions: int | str | None = None
37
14
  # , * # TODO improve `standardizedEqualToCallableReturn` so it will work with keyword arguments
38
- , CPUlimit: int | float | bool | None = None # noqa: FBT001
15
+ , CPUlimit: bool | float | int | None = None # noqa: FBT001
39
16
  , mapShape: tuple[int, ...] | None = None
40
17
  , oeisID: str | None = None
41
18
  , oeis_n: int | None = None
42
19
  , flow: str | None = None
43
20
  ) -> int:
44
21
  """
45
- Count the total number of possible foldings for a given map dimensions.
22
+ Count the total number of distinct ways to fold a map.
46
23
 
47
- (AI generated docstring)
48
-
49
- This function serves as the main public interface to the map folding algorithm, handling all parameter validation,
50
- computation state management, and result persistence in a user-friendly way.
24
+ Mathematicians also describe this as folding a strip of stamps, and they usually call the total "number of distinct ways to
25
+ fold" a map the map's "foldings."
51
26
 
52
27
  Parameters
53
28
  ----------
54
- listDimensions
29
+ listDimensions : Sequence[int] | None = None
55
30
  List of integers representing the dimensions of the map to be folded.
56
- pathLikeWriteFoldsTotal: None
57
- Path, filename, or pathFilename to write the total fold count to. If a directory is provided, creates a file
58
- with a default name based on map dimensions.
59
- computationDivisions: None
31
+ pathLikeWriteFoldsTotal : PathLike[str] | PurePath | None = None
32
+ A filename, a path of only directories, or a path with directories and a filename to which `countFolds` will write the
33
+ value of `foldsTotal`. If `pathLikeWriteFoldsTotal` is a path of only directories, `countFolds` creates a filename based
34
+ on the map dimensions.
35
+ computationDivisions : int | str | None = None
60
36
  Whether and how to divide the computational work.
61
- - `None`: no division of the computation into tasks; sets task divisions to 0.
62
- - int: directly set the number of task divisions; cannot exceed the map's total leaves.
63
- - `'maximum'`: divides into `leavesTotal`-many `taskDivisions`.
64
- - `'cpu'`: limits the divisions to the number of available CPUs: i.e., `concurrencyLimit`.
65
- CPUlimit: None
66
- This is only relevant if there are `computationDivisions`: whether and how to limit the CPU usage.
37
+ - `None`: no division of the computation into tasks.
38
+ - `int`: into how many tasks `countFolds` will divide the computation. The values 0 or 1 are identical to `None`. It is
39
+ mathematically impossible to divide the computation into more tasks than the map's total leaves.
40
+ - 'maximum': divides the computation into `leavesTotal`-many tasks.
41
+ - 'cpu': divides the computation into the number of available CPUs.
42
+ CPUlimit : bool | float | int | None = None
43
+ If relevant, whether and how to limit the number of processors `countFolds` will use. `CPUlimit` is an irrelevant setting
44
+ unless the computation is divided into more than one task with the `computationDivisions` parameter.
67
45
  - `False`, `None`, or `0`: No limits on processor usage; uses all available processors. All other values will
68
46
  potentially limit processor usage.
69
47
  - `True`: Yes, limit the processor usage; limits to 1 processor.
70
- - Integer `>= 1`: Limits usage to the specified number of processors.
71
- - Decimal value (`float`) between 0 and 1: Fraction of total processors to use.
72
- - Decimal value (`float`) between -1 and 0: Fraction of processors to _not_ use.
73
- - Integer `<= -1`: Subtract the absolute value from total processors.
48
+ - `int >= 1`: The maximum number of available processors to use.
49
+ - `0 < float < 1`: The maximum number of processors to use expressed as a fraction of available processors.
50
+ - `-1 < float < 0`: The number of processors to *not* use expressed as a fraction of available processors.
51
+ - `int <= -1`: The number of available processors to *not* use.
52
+ - If the value of `CPUlimit` is a `float` greater than 1 or less than -1, `countFolds` truncates the value to an `int`
53
+ with the same sign as the `float`.
54
+ mapShape : tuple[int, ...] | None = None
55
+ Tuple of integers representing the dimensions of the map to be folded. Mathematicians almost always use the term
56
+ "dimensions", such as in the seminal paper, "Multi-dimensional map-folding". Nevertheless, in contemporary Python
57
+ programming, in the context of these algorithms, the term "shape" makes it much easier to align the mathematics with the
58
+ syntax of the programming language.
59
+ oeisID : str | None = None
60
+ The On-Line Encyclopedia of Integer Sequences (OEIS) ID for which to compute a(n) for value of 'n' set in `oeis_n`.
61
+ oeis_n : int | None = None
62
+ The 'n' value for the `oeisID`.
63
+ flow : str | None = None
64
+ My stupid way of selecting the version of the algorithm to use in the computation. There are certainly better ways to do
65
+ this, but I have not yet solved this issue. As of 2025 Aug 14, these values will work:
66
+ - 'daoOfMapFolding'
67
+ - 'numba'
68
+ - 'theorem2'
69
+ - 'theorem2Numba'
70
+ - 'theorem2Trimmed'
74
71
 
75
72
  Returns
76
73
  -------
@@ -83,7 +80,7 @@ def countFolds(listDimensions: Sequence[int] | None = None
83
80
  If you want to compute a large `foldsTotal`, dividing the computation into tasks is usually a bad idea. Dividing the
84
81
  algorithm into tasks is inherently inefficient: efficient division into tasks means there would be no overlap in the
85
82
  work performed by each task. When dividing this algorithm, the amount of overlap is between 50% and 90% by all
86
- tasks: at least 50% of the work done by every task must be done by _all_ tasks. If you improve the computation time,
83
+ tasks: at least 50% of the work done by every task must be done by each task. If you improve the computation time,
87
84
  it will only change by -10 to -50% depending on (at the very least) the ratio of the map dimensions and the number
88
85
  of leaves. If an undivided computation would take 10 hours on your computer, for example, the computation will still
89
86
  take at least 5 hours but you might reduce the time to 9 hours. Most of the time, however, you will increase the
@@ -136,27 +133,16 @@ def countFolds(listDimensions: Sequence[int] | None = None
136
133
 
137
134
  # A007822 flow control until I can figure out a good way ---------------------------------
138
135
  if oeisID == 'A007822':
139
- """Temporary notes.
140
-
141
- The REAL motivation for integrating into basecamp is to integrate into the test modules. No, wait: to stop having to work
142
- around the test modules.
143
-
144
- I put `if oeisID == 'A007822'` in the `elif flow ==` cascade, before the `flow` checks because I want to remove A007822
145
- from those flow paths. It is fundamentally incompatible and it will cause `Exception` or incorrect computations.
136
+ """To use A007822, oeisID is mandatory.
146
137
 
147
- To use A007822, oeisID is mandatory.
148
-
149
- Parameters:
150
- listDimensions should work. mapShape should work. oeis_n should work. `pathLikeWriteFoldsTotal` should work!!! I
151
- didn't think about that, and I like it.
138
+ `if oeisID == 'A007822'` precedes the `elif flow ==` cascade because A007822 is fundamentally incompatible with those flow
139
+ paths and it will cause `Exception` or incorrect computations.
152
140
 
153
141
  Parallel version:
154
- idk. The computation division logic will try to execute. As of 2025 Aug 6 at 7 PM, I haven't tried or thought about a
155
- parallel version. TODO Watch out for errors.
156
-
157
- `flow`:
158
- It looks like I will need to make decisions tree just for A007822. That's probably not a big deal since all of the
159
- possible routes are predictable.
142
+ idk. The computation division logic will try to execute. As of 2025 Aug 13 at 11 PM, I haven't tried or thought about
143
+ a parallel version. And I don't really care. Potential parallelism is certainly present in `filterAsymmetricFolds`.
144
+ But, if I want to implement that, I should almost certainly replace `filterAsymmetricFolds` with a non-blocking
145
+ function to which `count` can pass the necessary values to. TODO Watch out for errors.
160
146
 
161
147
  """
162
148
  match flow:
@@ -184,8 +170,8 @@ def countFolds(listDimensions: Sequence[int] | None = None
184
170
  from mapFolding.syntheticModules.initializeStateA007822 import transitionOnGroupsOfFolds # noqa: PLC0415
185
171
  mapFoldingState = transitionOnGroupsOfFolds(mapFoldingState)
186
172
 
187
- from mapFolding.syntheticModules.theorem2A007822Numba import count # noqa: PLC0415
188
- mapFoldingState = count(mapFoldingState)
173
+ from mapFolding.syntheticModules.dataPackingA007822 import sequential # noqa: PLC0415
174
+ mapFoldingState = sequential(mapFoldingState)
189
175
 
190
176
  case 'theorem2Trimmed':
191
177
  from mapFolding.dataBaskets import MapFoldingState # noqa: PLC0415
@@ -0,0 +1,133 @@
1
+ def count(bridges: int, startingCurveLocations: dict[int, int]) -> int:
2
+ listCurveMaximums: list[tuple[int, int, int]] = [
3
+ (0x15, 0x2a, 0x10),
4
+ (0x55, 0xaa, 0x40),
5
+ (0x155, 0x2aa, 0x100),
6
+ (0x555, 0xaaa, 0x400),
7
+ (0x1555, 0x2aaa, 0x1000),
8
+ (0x5555, 0xaaaa, 0x4000),
9
+ (0x15555, 0x2aaaa, 0x10000),
10
+ (0x55555, 0xaaaaa, 0x40000),
11
+ (0x155555, 0x2aaaaa, 0x100000),
12
+ (0x555555, 0xaaaaaa, 0x400000),
13
+ (0x1555555, 0x2aaaaaa, 0x1000000),
14
+ (0x5555555, 0xaaaaaaa, 0x4000000),
15
+ (0x15555555, 0x2aaaaaaa, 0x10000000),
16
+ (0x55555555, 0xaaaaaaaa, 0x40000000), # `bridges = 13`, 0xaaaaaaaa.bit_length() = 32
17
+ (0x155555555, 0x2aaaaaaaa, 0x100000000),
18
+ (0x555555555, 0xaaaaaaaaa, 0x400000000),
19
+ (0x1555555555, 0x2aaaaaaaaa, 0x1000000000),
20
+ (0x5555555555, 0xaaaaaaaaaa, 0x4000000000),
21
+ (0x15555555555, 0x2aaaaaaaaaa, 0x10000000000),
22
+ (0x55555555555, 0xaaaaaaaaaaa, 0x40000000000),
23
+ (0x155555555555, 0x2aaaaaaaaaaa, 0x100000000000),
24
+ (0x555555555555, 0xaaaaaaaaaaaa, 0x400000000000),
25
+ (0x1555555555555, 0x2aaaaaaaaaaaa, 0x1000000000000),
26
+ (0x5555555555555, 0xaaaaaaaaaaaaa, 0x4000000000000),
27
+ (0x15555555555555, 0x2aaaaaaaaaaaaa, 0x10000000000000),
28
+ (0x55555555555555, 0xaaaaaaaaaaaaaa, 0x40000000000000),
29
+ (0x155555555555555, 0x2aaaaaaaaaaaaaa, 0x100000000000000),
30
+ (0x555555555555555, 0xaaaaaaaaaaaaaaa, 0x400000000000000),
31
+ (0x1555555555555555, 0x2aaaaaaaaaaaaaaa, 0x1000000000000000),
32
+ (0x5555555555555555, 0xaaaaaaaaaaaaaaaa, 0x4000000000000000), # 0x5000000000000000.bit_length() = 63; 0xaaaaaaaaaaaaaaaa.bit_length() = 64; 0x5555555555555555.bit_length() = 63
33
+ (0x15555555555555555, 0x2aaaaaaaaaaaaaaaa, 0x10000000000000000),
34
+ (0x55555555555555555, 0xaaaaaaaaaaaaaaaaa, 0x40000000000000000),
35
+ (0x155555555555555555, 0x2aaaaaaaaaaaaaaaaa, 0x100000000000000000),
36
+ (0x555555555555555555, 0xaaaaaaaaaaaaaaaaaa, 0x400000000000000000),
37
+ (0x1555555555555555555, 0x2aaaaaaaaaaaaaaaaaa, 0x1000000000000000000),
38
+ (0x5555555555555555555, 0xaaaaaaaaaaaaaaaaaaa, 0x4000000000000000000),
39
+ (0x15555555555555555555, 0x2aaaaaaaaaaaaaaaaaaa, 0x10000000000000000000),
40
+ (0x55555555555555555555, 0xaaaaaaaaaaaaaaaaaaaa, 0x40000000000000000000),
41
+ (0x155555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaa, 0x100000000000000000000),
42
+ (0x555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaa, 0x400000000000000000000),
43
+ (0x1555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaa, 0x1000000000000000000000),
44
+ (0x5555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaa, 0x4000000000000000000000),
45
+ (0x15555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaa, 0x10000000000000000000000),
46
+ (0x55555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaa, 0x40000000000000000000000),
47
+ (0x155555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaa, 0x100000000000000000000000),
48
+ (0x555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaa, 0x400000000000000000000000),
49
+ (0x1555555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaaa, 0x1000000000000000000000000),
50
+ (0x5555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaaa, 0x4000000000000000000000000),
51
+ (0x15555555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaaaa, 0x10000000000000000000000000),
52
+ (0x55555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x40000000000000000000000000),
53
+ (0x155555555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaa, 0x100000000000000000000000000),
54
+ (0x555555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x400000000000000000000000000),
55
+ (0x1555555555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x1000000000000000000000000000),
56
+ (0x5555555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x4000000000000000000000000000),
57
+ (0x15555555555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x10000000000000000000000000000),
58
+ (0x55555555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x40000000000000000000000000000),
59
+ (0x155555555555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x100000000000000000000000000000),
60
+ (0x555555555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x400000000000000000000000000000),
61
+ (0x1555555555555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x1000000000000000000000000000000),
62
+ (0x5555555555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x4000000000000000000000000000000),
63
+ (0x15555555555555555555555555555555, 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x10000000000000000000000000000000),
64
+ (0x55555555555555555555555555555555, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0x40000000000000000000000000000000),
65
+ ]
66
+ """`bridges = 29`
67
+ 0x5000000000000000.bit_length() = 63;
68
+ 0xaaaaaaaaaaaaaaaa.bit_length() = 64;
69
+ 0x5555555555555555.bit_length() = 63"""
70
+
71
+ listCurveMaximums = listCurveMaximums[0:bridges]
72
+
73
+ dictionaryCurveLocations: dict[int, int] = {}
74
+ while bridges > 0:
75
+ bridges -= 1
76
+
77
+ bifurcationAlphaLocator, bifurcationZuluLocator, curveLocationsMAXIMUM = listCurveMaximums[bridges]
78
+
79
+ for curveLocations, distinctCrossings in startingCurveLocations.items():
80
+ bifurcationAlpha = (curveLocations & bifurcationAlphaLocator)
81
+ bifurcationZulu = (curveLocations & bifurcationZuluLocator) >> 1
82
+
83
+ bifurcationAlphaHasCurves = bifurcationAlpha != 1
84
+ bifurcationZuluHasCurves = bifurcationZulu != 1
85
+
86
+ # Z0Z_simpleBridges
87
+ curveLocationAnalysis = ((bifurcationAlpha | (bifurcationZulu << 1)) << 2) | 3
88
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
89
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
90
+
91
+ # bifurcationAlphaCurves
92
+ if bifurcationAlphaHasCurves:
93
+ curveLocationAnalysis = (bifurcationAlphaShiftRight2 := bifurcationAlpha >> 2) | (bifurcationZulu << 3) | ((bifurcationAlphaIsEven := 1 - (bifurcationAlpha & 0b1)) << 1)
94
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
95
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
96
+
97
+ # bifurcationZuluCurves
98
+ if bifurcationZuluHasCurves:
99
+ curveLocationAnalysis = (bifurcationZulu >> 1) | (bifurcationAlpha << 2) | (bifurcationZuluIsEven := 1 - (bifurcationZulu & 1))
100
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
101
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
102
+
103
+ # Z0Z_alignedBridges
104
+ if bifurcationZuluHasCurves and bifurcationAlphaHasCurves:
105
+ # One Truth-check to select a code path
106
+ bifurcationsCanBePairedTogether = (bifurcationZuluIsEven << 1) | bifurcationAlphaIsEven # pyright: ignore[reportPossiblyUnboundVariable]
107
+
108
+ if bifurcationsCanBePairedTogether != 0: # Case 0 (False, False)
109
+ XOrHere2makePair = 0b1
110
+ findUnpaired_0b1 = 0
111
+
112
+ if bifurcationsCanBePairedTogether == 1: # Case 1: (False, True)
113
+ while findUnpaired_0b1 >= 0:
114
+ XOrHere2makePair <<= 2
115
+ findUnpaired_0b1 += 1 if (bifurcationAlpha & XOrHere2makePair) == 0 else -1
116
+ bifurcationAlphaShiftRight2 = (bifurcationAlpha ^ XOrHere2makePair) >> 2
117
+ elif bifurcationsCanBePairedTogether == 2: # Case 2: (True, False)
118
+ while findUnpaired_0b1 >= 0:
119
+ XOrHere2makePair <<= 2
120
+ findUnpaired_0b1 += 1 if (bifurcationZulu & XOrHere2makePair) == 0 else -1
121
+ bifurcationZulu ^= XOrHere2makePair
122
+
123
+ # Cases 1, 2, and 3 all compute curveLocationAnalysis
124
+ # TODO https://github.com/hunterhogan/mapFolding/issues/19
125
+ curveLocationAnalysis = ((bifurcationZulu >> 2) << 1) | bifurcationAlphaShiftRight2 # pyright: ignore[reportPossiblyUnboundVariable]
126
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
127
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
128
+
129
+ startingCurveLocations.clear()
130
+ startingCurveLocations, dictionaryCurveLocations = dictionaryCurveLocations, startingCurveLocations
131
+
132
+ return sum(startingCurveLocations.values())
133
+
@@ -21,7 +21,7 @@ def {Z0Z_identifier}(state: MapFoldingState) -> MapFoldingState:
21
21
  ImaSymmetricFold = True
22
22
  leafConnectee = 0
23
23
  while leafConnectee < indexInMiddle:
24
- if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal + 1 - 2 - leafConnectee) % (state.leavesTotal + 1)]:
24
+ if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal - 1 - leafConnectee) % (state.leavesTotal + 1)]:
25
25
  ImaSymmetricFold = False
26
26
  break
27
27
  leafConnectee += 1
@@ -551,22 +551,9 @@ def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifie
551
551
 
552
552
  return pathFilename
553
553
 
554
- def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
554
+ def makeUnRePackDataclass(astImportFrom: ast.ImportFrom, moduleIdentifier: identifierDotAttribute = dataPackingModuleIdentifierDEFAULT) -> None:
555
555
  """Generate interface module for dataclass unpacking and repacking operations.
556
556
 
557
- (AI generated docstring)
558
-
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.
565
-
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.
569
-
570
557
  Parameters
571
558
  ----------
572
559
  astImportFrom : ast.ImportFrom
@@ -585,7 +572,6 @@ def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
585
572
  logicalPathSourceModule: identifierDotAttribute = '.'.join([packageSettings.identifierPackage, algorithmSourceModule]) # noqa: FLY002
586
573
 
587
574
  logicalPathInfix: identifierDotAttribute = logicalPathInfixDEFAULT
588
- moduleIdentifier: identifierDotAttribute = dataPackingModuleIdentifierDEFAULT
589
575
  callableIdentifier: identifierDotAttribute = callableIdentifierHARDCODED
590
576
 
591
577
  ingredientsFunction: IngredientsFunction = astModuleToIngredientsFunction(parseLogicalPath2astModule(logicalPathSourceModule), sourceCallableIdentifier)
@@ -773,3 +759,6 @@ if __name__ == '__main__':
773
759
  astModule = parsePathFilename2astModule(pathFilename)
774
760
  pathFilename = numbaOnTheorem2(astModule, 'theorem2A007822Numba', None, logicalPathInfixDEFAULT, None)
775
761
 
762
+ astImportFrom: ast.ImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.identifierPackage, logicalPathInfixDEFAULT, 'theorem2A007822Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
763
+ makeUnRePackDataclass(astImportFrom, 'dataPackingA007822')
764
+
@@ -5,13 +5,13 @@ https://docs.exaloop.io/start/install/
5
5
 
6
6
  from astToolkit import (
7
7
  Be, DOT, extractFunctionDef, Grab, identifierDotAttribute, IngredientsFunction, IngredientsModule, Make, NodeChanger,
8
- NodeTourist, Then)
8
+ NodeTourist, parseLogicalPath2astModule, Then)
9
9
  from astToolkit.transformationTools import removeUnusedParameters, write_astModule
10
10
  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.initializeState import transitionOnGroupsOfFolds
14
+ from mapFolding.syntheticModules.initializeStateA007822 import transitionOnGroupsOfFolds
15
15
  from pathlib import Path, PurePosixPath
16
16
  from typing import cast, NamedTuple, TYPE_CHECKING
17
17
  import ast
@@ -214,11 +214,12 @@ def fromMapShape(mapShape: tuple[DatatypeLeavesTotal, ...]) -> None:
214
214
  """
215
215
  state = transitionOnGroupsOfFolds(MapFoldingState(mapShape))
216
216
  pathModule = PurePosixPath(Path.home(), 'mapFolding', 'jobs')
217
+ source_astModule = parseLogicalPath2astModule('mapFolding.syntheticModules.theorem2A007822Numba')
217
218
  pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
218
- aJob = RecipeJobTheorem2(state, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
219
+ aJob = RecipeJobTheorem2(state, source_astModule=source_astModule, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
219
220
  makeJob(aJob)
220
221
 
221
222
  if __name__ == '__main__':
222
- mapShape = (2, 21)
223
+ mapShape = (1, 15)
223
224
  fromMapShape(mapShape)
224
225
 
@@ -14,7 +14,7 @@ def filterAsymmetricFolds(state: MapFoldingState) -> MapFoldingState:
14
14
  ImaSymmetricFold = True
15
15
  leafConnectee = 0
16
16
  while leafConnectee < indexInMiddle:
17
- if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal + 1 - 2 - leafConnectee) % (state.leavesTotal + 1)]:
17
+ if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal - 1 - leafConnectee) % (state.leavesTotal + 1)]:
18
18
  ImaSymmetricFold = False
19
19
  break
20
20
  leafConnectee += 1
@@ -19,7 +19,7 @@ def count(groupsOfFolds: DatatypeFoldsTotal, gap1ndex: DatatypeElephino, gap1nde
19
19
  ImaSymmetricFold = True
20
20
  leafConnectee = 0
21
21
  while leafConnectee < indexInMiddle:
22
- if leafComparison[(indexMiniGap + leafConnectee) % (leavesTotal + 1)] != leafComparison[(indexMiniGap + leavesTotal + 1 - 2 - leafConnectee) % (leavesTotal + 1)]:
22
+ if leafComparison[(indexMiniGap + leafConnectee) % (leavesTotal + 1)] != leafComparison[(indexMiniGap + leavesTotal - 1 - leafConnectee) % (leavesTotal + 1)]:
23
23
  ImaSymmetricFold = False
24
24
  break
25
25
  leafConnectee += 1
@@ -0,0 +1,26 @@
1
+ from mapFolding.dataBaskets import Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal, MapFoldingState
2
+ from mapFolding.syntheticModules.theorem2A007822Numba import count
3
+
4
+ def sequential(state: MapFoldingState) -> MapFoldingState:
5
+ mapShape: tuple[DatatypeLeavesTotal, ...] = state.mapShape
6
+ groupsOfFolds: DatatypeFoldsTotal = state.groupsOfFolds
7
+ gap1ndex: DatatypeElephino = state.gap1ndex
8
+ gap1ndexCeiling: DatatypeElephino = state.gap1ndexCeiling
9
+ indexDimension: DatatypeLeavesTotal = state.indexDimension
10
+ indexLeaf: DatatypeLeavesTotal = state.indexLeaf
11
+ indexMiniGap: DatatypeElephino = state.indexMiniGap
12
+ leaf1ndex: DatatypeLeavesTotal = state.leaf1ndex
13
+ leafConnectee: DatatypeLeavesTotal = state.leafConnectee
14
+ dimensionsUnconstrained: DatatypeLeavesTotal = state.dimensionsUnconstrained
15
+ countDimensionsGapped: Array1DLeavesTotal = state.countDimensionsGapped
16
+ gapRangeStart: Array1DElephino = state.gapRangeStart
17
+ gapsWhere: Array1DLeavesTotal = state.gapsWhere
18
+ leafAbove: Array1DLeavesTotal = state.leafAbove
19
+ leafBelow: Array1DLeavesTotal = state.leafBelow
20
+ leafComparison: Array1DLeavesTotal = state.leafComparison
21
+ connectionGraph: Array3DLeavesTotal = state.connectionGraph
22
+ dimensionsTotal: DatatypeLeavesTotal = state.dimensionsTotal
23
+ leavesTotal: DatatypeLeavesTotal = state.leavesTotal
24
+ groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, leavesTotal = count(groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, leavesTotal)
25
+ state = MapFoldingState(mapShape=mapShape, groupsOfFolds=groupsOfFolds, gap1ndex=gap1ndex, gap1ndexCeiling=gap1ndexCeiling, indexDimension=indexDimension, indexLeaf=indexLeaf, indexMiniGap=indexMiniGap, leaf1ndex=leaf1ndex, leafConnectee=leafConnectee, dimensionsUnconstrained=dimensionsUnconstrained, countDimensionsGapped=countDimensionsGapped, gapRangeStart=gapRangeStart, gapsWhere=gapsWhere, leafAbove=leafAbove, leafBelow=leafBelow, leafComparison=leafComparison)
26
+ return state
@@ -17,7 +17,7 @@ def transitionOnGroupsOfFolds(state: MapFoldingState) -> MapFoldingState:
17
17
  ImaSymmetricFold = True
18
18
  leafConnectee = 0
19
19
  while leafConnectee < indexInMiddle:
20
- if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal + 1 - 2 - leafConnectee) % (state.leavesTotal + 1)]:
20
+ if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal - 1 - leafConnectee) % (state.leavesTotal + 1)]:
21
21
  ImaSymmetricFold = False
22
22
  break
23
23
  leafConnectee += 1
@@ -17,7 +17,7 @@ def count(state: MapFoldingState) -> MapFoldingState:
17
17
  ImaSymmetricFold = True
18
18
  leafConnectee = 0
19
19
  while leafConnectee < indexInMiddle:
20
- if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal + 1 - 2 - leafConnectee) % (state.leavesTotal + 1)]:
20
+ if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal - 1 - leafConnectee) % (state.leavesTotal + 1)]:
21
21
  ImaSymmetricFold = False
22
22
  break
23
23
  leafConnectee += 1
@@ -1,5 +1,4 @@
1
- from mapFolding.dataBaskets import (
2
- Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal)
1
+ from mapFolding.dataBaskets import Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal
3
2
  from numba import jit
4
3
 
5
4
  @jit(cache=True, error_model='numpy', fastmath=True, forceinline=True)
@@ -20,7 +19,7 @@ def count(groupsOfFolds: DatatypeFoldsTotal, gap1ndex: DatatypeElephino, gap1nde
20
19
  ImaSymmetricFold = True
21
20
  leafConnectee = 0
22
21
  while leafConnectee < indexInMiddle:
23
- if leafComparison[(indexMiniGap + leafConnectee) % (leavesTotal + 1)] != leafComparison[(indexMiniGap + leavesTotal + 1 - 2 - leafConnectee) % (leavesTotal + 1)]:
22
+ if leafComparison[(indexMiniGap + leafConnectee) % (leavesTotal + 1)] != leafComparison[(indexMiniGap + leavesTotal - 1 - leafConnectee) % (leavesTotal + 1)]:
24
23
  ImaSymmetricFold = False
25
24
  break
26
25
  leafConnectee += 1
@@ -64,4 +63,4 @@ def count(groupsOfFolds: DatatypeFoldsTotal, gap1ndex: DatatypeElephino, gap1nde
64
63
  else:
65
64
  groupsOfFolds *= 2
66
65
  groupsOfFolds = (groupsOfFolds + 1) // 2
67
- return (groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, leavesTotal)
66
+ return (groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, leafComparison, connectionGraph, dimensionsTotal, leavesTotal)
@@ -17,7 +17,7 @@ def count(state: MapFoldingState) -> MapFoldingState:
17
17
  ImaSymmetricFold = True
18
18
  leafConnectee = 0
19
19
  while leafConnectee < indexInMiddle:
20
- if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal + 1 - 2 - leafConnectee) % (state.leavesTotal + 1)]:
20
+ if state.leafComparison[(state.indexMiniGap + leafConnectee) % (state.leavesTotal + 1)] != state.leafComparison[(state.indexMiniGap + state.leavesTotal - 1 - leafConnectee) % (state.leavesTotal + 1)]:
21
21
  ImaSymmetricFold = False
22
22
  break
23
23
  leafConnectee += 1
@@ -1,5 +1,4 @@
1
- from mapFolding.dataBaskets import (
2
- Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal)
1
+ from mapFolding.dataBaskets import Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal
3
2
  from numba import jit
4
3
 
5
4
  @jit(cache=True, error_model='numpy', fastmath=True, forceinline=True)
@@ -44,4 +43,4 @@ def count(groupsOfFolds: DatatypeFoldsTotal, gap1ndex: DatatypeElephino, gap1nde
44
43
  leaf1ndex += 1
45
44
  else:
46
45
  groupsOfFolds *= 2
47
- return (groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, connectionGraph, dimensionsTotal, leavesTotal)
46
+ return (groupsOfFolds, gap1ndex, gap1ndexCeiling, indexDimension, indexMiniGap, leaf1ndex, leafConnectee, dimensionsUnconstrained, countDimensionsGapped, gapRangeStart, gapsWhere, leafAbove, leafBelow, connectionGraph, dimensionsTotal, leavesTotal)
@@ -224,7 +224,8 @@ def oneTestCuzTestsOverwritingTests(oeisID_1random: str) -> tuple[int, ...]:
224
224
 
225
225
  @pytest.fixture
226
226
  def mapShapeTestCountFolds(oeisID: str) -> tuple[int, ...]:
227
- """For each `oeisID` from the `pytest.fixture`, returns `listDimensions` from `valuesTestValidation` if `validateListDimensions` approves. Each `listDimensions` is suitable for testing counts.
227
+ """For each `oeisID` from the `pytest.fixture`, returns `listDimensions` from `valuesTestValidation` if
228
+ `validateListDimensions` approves. Each `listDimensions` is suitable for testing counts.
228
229
 
229
230
  Parameters
230
231
  ----------