mapFolding 0.14.1__py3-none-any.whl → 0.15.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.
- mapFolding/_A007822.py +181 -0
- mapFolding/__init__.py +1 -1
- mapFolding/_oeisFormulas/A000682.py +2 -2
- mapFolding/_oeisFormulas/Z0Z_aOFn.py +7 -4
- mapFolding/_oeisFormulas/Z0Z_oeisMeanders.py +2 -0
- mapFolding/_oeisFormulas/matrixMeanders.py +122 -75
- mapFolding/_oeisFormulas/matrixMeandersAnnex.py +66 -66
- mapFolding/_theSSOT.py +9 -3
- mapFolding/_theTypes.py +34 -130
- mapFolding/basecamp.py +1 -1
- mapFolding/beDRY.py +5 -21
- mapFolding/dataBaskets.py +8 -3
- mapFolding/oeis.py +13 -15
- mapFolding/reference/A005316optimized128bit.py +19 -19
- mapFolding/reference/A005316primitiveOptimized.py +25 -25
- mapFolding/reference/A005316redis.py +19 -19
- mapFolding/reference/A005316write2disk.py +19 -19
- mapFolding/reference/matrixMeandersBaseline.py +20 -20
- mapFolding/reference/matrixMeandersBaselineAnnex.py +4 -4
- mapFolding/reference/matrixMeandersSimpleQueue.py +90 -0
- mapFolding/reference/matrixMeandersSlicePop.py +104 -0
- mapFolding/someAssemblyRequired/_toolkitContainers.py +1 -1
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +1 -1
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +1 -1
- mapFolding/syntheticModules/countParallel.py +7 -4
- mapFolding/syntheticModules/daoOfMapFolding.py +6 -4
- mapFolding/syntheticModules/dataPacking.py +5 -3
- mapFolding/syntheticModules/theorem2Numba.py +4 -3
- {mapfolding-0.14.1.dist-info → mapfolding-0.15.0.dist-info}/METADATA +2 -2
- {mapfolding-0.14.1.dist-info → mapfolding-0.15.0.dist-info}/RECORD +34 -31
- {mapfolding-0.14.1.dist-info → mapfolding-0.15.0.dist-info}/WHEEL +0 -0
- {mapfolding-0.14.1.dist-info → mapfolding-0.15.0.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.14.1.dist-info → mapfolding-0.15.0.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.14.1.dist-info → mapfolding-0.15.0.dist-info}/top_level.txt +0 -0
mapFolding/_theTypes.py
CHANGED
|
@@ -1,148 +1,52 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
(AI generated docstring)
|
|
5
|
-
|
|
6
|
-
Building upon the configuration foundation, this module defines the complete type
|
|
7
|
-
hierarchy that ensures type safety and semantic clarity throughout the map folding
|
|
8
|
-
computational framework. The type system recognizes three distinct computational
|
|
9
|
-
domains, each with specific data characteristics and performance requirements
|
|
10
|
-
that emerge from Lunnon's algorithm implementation.
|
|
11
|
-
|
|
12
|
-
The Leaves domain handles map sections, their indices, and dimensional parameters.
|
|
13
|
-
The Elephino domain manages internal computational state, gap calculations, and
|
|
14
|
-
temporary indices used during the recursive folding analysis. The Folds domain
|
|
15
|
-
represents final pattern counts and computation results. Each domain employs both
|
|
16
|
-
Python types for general computation and NumPy types for performance-critical
|
|
17
|
-
array operations.
|
|
18
|
-
|
|
19
|
-
This dual-type strategy enables the core utility functions to operate with type
|
|
20
|
-
safety while maintaining the computational efficiency required for analyzing
|
|
21
|
-
complex multi-dimensional folding patterns. The array types built from these
|
|
22
|
-
base types provide the structured data containers that computational state
|
|
23
|
-
management depends upon.
|
|
24
|
-
"""
|
|
25
|
-
from numpy import dtype, integer, ndarray, uint8 as numpy_uint8, uint16 as numpy_uint16, uint64 as numpy_uint64
|
|
1
|
+
"""Types for defensive coding and for computation optimization."""
|
|
2
|
+
|
|
3
|
+
from numpy import dtype, int_ as numpy_int, integer, ndarray, uint64 as numpy_uint64
|
|
26
4
|
from typing import Any, TypeAlias, TypeVar
|
|
27
5
|
|
|
28
6
|
NumPyIntegerType = TypeVar('NumPyIntegerType', bound=integer[Any], covariant=True)
|
|
29
|
-
"""
|
|
30
|
-
Generic type variable for NumPy integer types used in computational operations.
|
|
31
|
-
|
|
32
|
-
(AI generated docstring)
|
|
33
|
-
|
|
34
|
-
This type variable enables generic programming with NumPy integer types while
|
|
35
|
-
maintaining type safety. It supports covariant relationships between different
|
|
36
|
-
NumPy integer types and their array containers.
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
DatatypeLeavesTotal: TypeAlias = int
|
|
40
|
-
"""
|
|
41
|
-
Python type for leaf-related counts and indices in map folding computations.
|
|
42
|
-
|
|
43
|
-
(AI generated docstring)
|
|
44
|
-
|
|
45
|
-
Represents quantities related to individual map sections (leaves), including
|
|
46
|
-
total leaf counts, leaf indices, and dimensional parameters. Uses standard
|
|
47
|
-
Python integers for compatibility with general computations while enabling
|
|
48
|
-
conversion to NumPy types when performance optimization is needed.
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
NumPyLeavesTotal: TypeAlias = numpy_uint8
|
|
52
|
-
"""
|
|
53
|
-
NumPy type for efficient leaf-related computations and array operations.
|
|
54
|
-
|
|
55
|
-
(AI generated docstring)
|
|
56
|
-
|
|
57
|
-
Corresponds to `DatatypeLeavesTotal` but optimized for NumPy operations.
|
|
58
|
-
Uses 8-bit unsigned integers since leaf counts in practical map folding
|
|
59
|
-
scenarios typically remain small (under 256).
|
|
60
|
-
"""
|
|
61
|
-
|
|
62
|
-
DatatypeElephino: TypeAlias = int
|
|
63
|
-
"""
|
|
64
|
-
Python type for internal computational indices and intermediate values.
|
|
65
|
-
|
|
66
|
-
(AI generated docstring)
|
|
67
|
-
|
|
68
|
-
Used for temporary variables, gap indices, and other internal computational
|
|
69
|
-
state that doesn't directly correspond to leaves or final fold counts. The
|
|
70
|
-
name follows the package convention for internal computational domains.
|
|
71
|
-
"""
|
|
7
|
+
"""Any NumPy integer type, which is usually between 8-bit signed and 64-bit unsigned."""
|
|
72
8
|
|
|
73
|
-
|
|
74
|
-
"""
|
|
75
|
-
NumPy type for internal computational operations requiring moderate value ranges.
|
|
9
|
+
DatatypeLeavesTotal: TypeAlias = int # 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.
|
|
10
|
+
"""Use on unsigned integers that will never exceed the magnitude of `leavesTotal`."""
|
|
76
11
|
|
|
77
|
-
(
|
|
12
|
+
NumPyLeavesTotal: TypeAlias = numpy_int # 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.
|
|
13
|
+
"""Use in NumPy data structures whose elements are unsigned integers that will never exceed the magnitude of `leavesTotal`."""
|
|
78
14
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
memory efficiency in array operations.
|
|
82
|
-
"""
|
|
15
|
+
DatatypeElephino: TypeAlias = int # 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.
|
|
16
|
+
"""Use on unsigned integers that will exceed the magnitude of `leavesTotal` but that are not "colossal."
|
|
83
17
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
18
|
+
Note well
|
|
19
|
+
---------
|
|
20
|
+
Colossal values are found with the cross humpy inequality:
|
|
87
21
|
|
|
88
|
-
|
|
22
|
+
⎡ el ⎤ ⎡ ⎤
|
|
23
|
+
⎢ eph ⎥ X ⎢ rhi ⎥ <= elephino
|
|
24
|
+
⎣ ant ⎦ ⎣ no ⎦
|
|
89
25
|
|
|
90
|
-
Represents the ultimate results of map folding computations - the total number
|
|
91
|
-
of distinct folding patterns possible for a given map configuration. These
|
|
92
|
-
values can grow exponentially with map size, requiring flexible integer types.
|
|
93
26
|
"""
|
|
94
27
|
|
|
95
|
-
|
|
96
|
-
"""
|
|
97
|
-
NumPy type for large fold count computations and high-precision results.
|
|
28
|
+
NumPyElephino: TypeAlias = numpy_int # 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.
|
|
29
|
+
"""Use in NumPy data structures whose elements are unsigned integers that might exceed the magnitude of `leavesTotal` but that are not 'colossal.'"""
|
|
98
30
|
|
|
99
|
-
(
|
|
31
|
+
DatatypeFoldsTotal: TypeAlias = int # 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.
|
|
32
|
+
"""Use on unsigned integers that might have colossal magnitudes similar to `foldsTotal`."""
|
|
100
33
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
computations on even moderately-sized maps.
|
|
104
|
-
"""
|
|
34
|
+
NumPyFoldsTotal: TypeAlias = numpy_uint64 # 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.
|
|
35
|
+
"""Use in NumPy data structures whose elements are unsigned integers that might have colossal magnitudes similar to `foldsTotal`.
|
|
105
36
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
37
|
+
Note well
|
|
38
|
+
---------
|
|
39
|
+
If your elements might exceed 1.8 × 10^19, then you should take extra steps to ensure the integrity of the data in NumPy or use a
|
|
40
|
+
different data structure."""
|
|
109
41
|
|
|
110
|
-
(
|
|
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.
|
|
43
|
+
"""A `numpy.ndarray` with three axes and elements of type `NumPyLeavesTotal`."""
|
|
111
44
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
the stored values represent leaf indices and connection states.
|
|
115
|
-
"""
|
|
45
|
+
Array1DLeavesTotal: TypeAlias = ndarray[tuple[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.
|
|
46
|
+
"""A `numpy.ndarray` with one axis and elements of type `NumPyLeavesTotal`."""
|
|
116
47
|
|
|
117
|
-
|
|
118
|
-
"""
|
|
119
|
-
One-dimensional NumPy array type for leaf-related data sequences.
|
|
48
|
+
Array1DElephino: TypeAlias = ndarray[tuple[int], dtype[NumPyElephino]] # 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.
|
|
49
|
+
"""A `numpy.ndarray` with one axis and elements of type `NumPyElephino`."""
|
|
120
50
|
|
|
121
|
-
(
|
|
122
|
-
|
|
123
|
-
Stores sequences of leaf counts, indices, or related values in efficient
|
|
124
|
-
array format. Common uses include leaf sequences, gap locations, and
|
|
125
|
-
dimensional data where each element relates to the leaves domain.
|
|
126
|
-
"""
|
|
127
|
-
|
|
128
|
-
Array1DElephino: TypeAlias = ndarray[tuple[int], dtype[NumPyElephino]]
|
|
129
|
-
"""
|
|
130
|
-
One-dimensional NumPy array type for internal computational sequences.
|
|
131
|
-
|
|
132
|
-
(AI generated docstring)
|
|
133
|
-
|
|
134
|
-
Used for storing sequences of internal computational values such as
|
|
135
|
-
gap range starts, temporary indices, and other intermediate results
|
|
136
|
-
that require the elephino computational domain's value range.
|
|
137
|
-
"""
|
|
138
|
-
|
|
139
|
-
Array1DFoldsTotal: TypeAlias = ndarray[tuple[int], dtype[NumPyFoldsTotal]]
|
|
140
|
-
"""
|
|
141
|
-
One-dimensional NumPy array type for sequences of fold count results.
|
|
142
|
-
|
|
143
|
-
(AI generated docstring)
|
|
144
|
-
|
|
145
|
-
Stores sequences of fold totals and pattern counts, using the large
|
|
146
|
-
integer type to accommodate the potentially enormous values that
|
|
147
|
-
result from complex map folding computations.
|
|
148
|
-
"""
|
|
51
|
+
Array1DFoldsTotal: TypeAlias = ndarray[tuple[int], dtype[NumPyFoldsTotal]] # 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.
|
|
52
|
+
"""A `numpy.ndarray` with one axis and elements of type `NumPyFoldsTotal`."""
|
mapFolding/basecamp.py
CHANGED
|
@@ -31,7 +31,7 @@ from os import PathLike
|
|
|
31
31
|
from pathlib import PurePath
|
|
32
32
|
import contextlib
|
|
33
33
|
|
|
34
|
-
def countFolds(listDimensions: Sequence[int] | None = None
|
|
34
|
+
def countFolds(listDimensions: Sequence[int] | None = None
|
|
35
35
|
, pathLikeWriteFoldsTotal: PathLike[str] | PurePath | None = None
|
|
36
36
|
, computationDivisions: int | str | None = None
|
|
37
37
|
# , * # TODO improve `standardizedEqualToCallableReturn` so it will work with keyword arguments
|
mapFolding/beDRY.py
CHANGED
|
@@ -121,12 +121,6 @@ def getTaskDivisions(computationDivisions: int | str | None, concurrencyLimit: i
|
|
|
121
121
|
def _makeConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int) -> ndarray[tuple[int, int, int], numpy_dtype[numpy_int64]]:
|
|
122
122
|
"""Implement connection graph generation for map folding.
|
|
123
123
|
|
|
124
|
-
(AI generated docstring)
|
|
125
|
-
|
|
126
|
-
This is the internal implementation that calculates all possible connections between leaves in a map folding problem
|
|
127
|
-
based on Lunnon's algorithm. The function constructs a three-dimensional array representing which leaves can be
|
|
128
|
-
connected to each other for each dimension of the map.
|
|
129
|
-
|
|
130
124
|
Parameters
|
|
131
125
|
----------
|
|
132
126
|
mapShape : tuple[int, ...]
|
|
@@ -177,12 +171,6 @@ def _makeConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int) -> ndarray
|
|
|
177
171
|
def getConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int, datatype: type[NumPyIntegerType]) -> ndarray[tuple[int, int, int], numpy_dtype[NumPyIntegerType]]:
|
|
178
172
|
"""Create a properly typed connection graph for the map folding algorithm.
|
|
179
173
|
|
|
180
|
-
(AI generated docstring)
|
|
181
|
-
|
|
182
|
-
This function serves as a typed wrapper around the internal implementation that generates connection graphs. It
|
|
183
|
-
provides the correct type information for the returned array, ensuring consistency throughout the computation
|
|
184
|
-
assembly-line.
|
|
185
|
-
|
|
186
174
|
Parameters
|
|
187
175
|
----------
|
|
188
176
|
mapShape : tuple[int, ...]
|
|
@@ -204,25 +192,21 @@ def getConnectionGraph(mapShape: tuple[int, ...], leavesTotal: int, datatype: ty
|
|
|
204
192
|
return connectionGraph.astype(datatype)
|
|
205
193
|
|
|
206
194
|
def makeDataContainer(shape: int | tuple[int, ...], datatype: type[NumPyIntegerType]) -> ndarray[Any, numpy_dtype[NumPyIntegerType]]:
|
|
207
|
-
"""Create a
|
|
208
|
-
|
|
209
|
-
(AI generated docstring)
|
|
195
|
+
"""Create any data container as long as it is a `numpy.ndarray` full of zeroes of type `numpy.integer`.
|
|
210
196
|
|
|
211
|
-
|
|
212
|
-
easy switching between different container types or implementation strategies if needed in the future.
|
|
197
|
+
By centralizing data container creation, you can more easily make global changes.
|
|
213
198
|
|
|
214
199
|
Parameters
|
|
215
200
|
----------
|
|
216
201
|
shape : int | tuple[int, ...]
|
|
217
|
-
|
|
218
|
-
dimensions of the array.
|
|
202
|
+
The array shape, either as a single axis length or a tuple of axes lengths.
|
|
219
203
|
datatype : type[NumPyIntegerType]
|
|
220
|
-
The
|
|
204
|
+
The `numpy.integer` type for the array elements.
|
|
221
205
|
|
|
222
206
|
Returns
|
|
223
207
|
-------
|
|
224
208
|
container : ndarray[Any, numpy_dtype[NumPyIntegerType]]
|
|
225
|
-
A
|
|
209
|
+
A zero-filled `ndarray` with the specified `shape` and `datatype`.
|
|
226
210
|
|
|
227
211
|
"""
|
|
228
212
|
return numpy.zeros(shape, dtype=datatype)
|
mapFolding/dataBaskets.py
CHANGED
|
@@ -21,7 +21,7 @@ integrity throughout the recursive analysis while providing the structured data
|
|
|
21
21
|
access patterns that enable efficient result persistence and retrieval.
|
|
22
22
|
"""
|
|
23
23
|
from mapFolding import (
|
|
24
|
-
Array1DElephino, Array1DLeavesTotal,
|
|
24
|
+
Array1DElephino, Array1DLeavesTotal, Array3DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal,
|
|
25
25
|
getConnectionGraph, getLeavesTotal, makeDataContainer)
|
|
26
26
|
import dataclasses
|
|
27
27
|
|
|
@@ -63,7 +63,9 @@ class MapFoldingState:
|
|
|
63
63
|
Array tracking the leaves above to the current leaf, `leaf1ndex`, during computation.
|
|
64
64
|
leafBelow : Array1DLeavesTotal = None
|
|
65
65
|
Array tracking the leaves below to the current leaf, `leaf1ndex`, during computation.
|
|
66
|
-
|
|
66
|
+
leafComparison : Array1DLeavesTotal = None
|
|
67
|
+
Array for finding symmetric folds.
|
|
68
|
+
connectionGraph : Array3DLeavesTotal
|
|
67
69
|
Unchanging array representing connections between all leaves.
|
|
68
70
|
dimensionsTotal : DatatypeLeavesTotal
|
|
69
71
|
Unchanging total number of dimensions in the map.
|
|
@@ -106,8 +108,10 @@ class MapFoldingState:
|
|
|
106
108
|
"""Array tracking the leaves above to the current leaf, `leaf1ndex`, during computation."""
|
|
107
109
|
leafBelow: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
108
110
|
"""Array tracking the leaves below to the current leaf, `leaf1ndex`, during computation."""
|
|
111
|
+
leafComparison: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
112
|
+
"""Array for finding symmetric folds."""
|
|
109
113
|
|
|
110
|
-
connectionGraph:
|
|
114
|
+
connectionGraph: Array3DLeavesTotal = dataclasses.field(init=False, metadata={'dtype': Array3DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
|
|
111
115
|
"""Unchanging array representing connections between all leaves."""
|
|
112
116
|
dimensionsTotal: DatatypeLeavesTotal = dataclasses.field(init=False)
|
|
113
117
|
"""Unchanging total number of dimensions in the map."""
|
|
@@ -147,6 +151,7 @@ class MapFoldingState:
|
|
|
147
151
|
if self.gapRangeStart is None: self.gapRangeStart = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['gapRangeStart'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
148
152
|
if self.leafAbove is None: self.leafAbove = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafAbove'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
149
153
|
if self.leafBelow is None: self.leafBelow = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafBelow'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
154
|
+
if self.leafComparison is None: self.leafComparison = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafComparison'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison] # noqa: E701
|
|
150
155
|
|
|
151
156
|
@dataclasses.dataclass
|
|
152
157
|
class ParallelMapFoldingState(MapFoldingState):
|
mapFolding/oeis.py
CHANGED
|
@@ -31,7 +31,7 @@ from itertools import chain
|
|
|
31
31
|
from mapFolding import countFolds
|
|
32
32
|
from mapFolding._theSSOT import cacheDays, pathCache, settingsOEISManuallySelected
|
|
33
33
|
from pathlib import Path
|
|
34
|
-
from typing import
|
|
34
|
+
from typing import Final, TypedDict
|
|
35
35
|
from urllib.request import urlopen
|
|
36
36
|
import argparse
|
|
37
37
|
import sys
|
|
@@ -331,8 +331,8 @@ def makeDictionaryFoldsTotalKnown() -> dict[tuple[int, ...], int]:
|
|
|
331
331
|
of distinct folding patterns for those shapes.
|
|
332
332
|
|
|
333
333
|
"""
|
|
334
|
-
return dict(chain.from_iterable(zip(map(
|
|
335
|
-
,
|
|
334
|
+
return dict(chain.from_iterable(zip(map(oeisIDmetadata['getMapShape'], oeisIDmetadata['valuesKnown'].keys())
|
|
335
|
+
, oeisIDmetadata['valuesKnown'].values(), strict=True) for oeisID, oeisIDmetadata in dictionaryOEIS.items() if oeisID != 'A007822'))
|
|
336
336
|
|
|
337
337
|
def getFoldsTotalKnown(mapShape: tuple[int, ...]) -> int:
|
|
338
338
|
"""Retrieve the known total number of distinct folding patterns for a given map shape.
|
|
@@ -410,26 +410,19 @@ def _formatOEISsequenceInfo() -> str:
|
|
|
410
410
|
for oeisID in oeisIDsImplemented
|
|
411
411
|
)
|
|
412
412
|
|
|
413
|
-
def oeisIDfor_n(oeisID: str, n: int
|
|
414
|
-
"""Calculate the value a(n) for a specified OEIS
|
|
415
|
-
|
|
416
|
-
(AI generated docstring)
|
|
417
|
-
|
|
418
|
-
This function serves as the primary interface for computing OEIS sequence values within the map folding
|
|
419
|
-
context. For small values or values within the known range, it returns cached OEIS data. For larger
|
|
420
|
-
values, it computes the result using the map folding algorithm with the appropriate map shape derived
|
|
421
|
-
from the sequence definition.
|
|
413
|
+
def oeisIDfor_n(oeisID: str, n: int) -> int:
|
|
414
|
+
"""Calculate the value a(n) for a specified OEIS ID and index.
|
|
422
415
|
|
|
423
416
|
Parameters
|
|
424
417
|
----------
|
|
425
418
|
oeisID : str
|
|
426
419
|
The identifier of the OEIS sequence to evaluate.
|
|
427
|
-
n : int
|
|
420
|
+
n : int
|
|
428
421
|
A non-negative integer index for which to calculate the sequence value.
|
|
429
422
|
|
|
430
423
|
Returns
|
|
431
424
|
-------
|
|
432
|
-
int
|
|
425
|
+
a(n) : int
|
|
433
426
|
The value a(n) of the specified OEIS sequence.
|
|
434
427
|
|
|
435
428
|
Raises
|
|
@@ -448,7 +441,7 @@ def oeisIDfor_n(oeisID: str, n: int | Any) -> int:
|
|
|
448
441
|
message = f"I received `{n = }` in the form of `{type(n) = }`, but it must be non-negative integer in the form of `{int}`."
|
|
449
442
|
raise ValueError(message)
|
|
450
443
|
|
|
451
|
-
mapShape
|
|
444
|
+
mapShape = dictionaryOEIS[oeisID]['getMapShape'](n)
|
|
452
445
|
|
|
453
446
|
if n <= 1 or len(mapShape) < 2:
|
|
454
447
|
offset: int = dictionaryOEIS[oeisID]['offset']
|
|
@@ -457,6 +450,11 @@ def oeisIDfor_n(oeisID: str, n: int | Any) -> int:
|
|
|
457
450
|
raise ArithmeticError(message)
|
|
458
451
|
foldsTotal: int = dictionaryOEIS[oeisID]['valuesKnown'][n]
|
|
459
452
|
return foldsTotal
|
|
453
|
+
|
|
454
|
+
if oeisID == 'A007822':
|
|
455
|
+
from mapFolding._A007822 import Z0Z_flowNeedsFixing # noqa: PLC0415
|
|
456
|
+
return Z0Z_flowNeedsFixing(mapShape)
|
|
457
|
+
|
|
460
458
|
return countFolds(mapShape)
|
|
461
459
|
|
|
462
460
|
def OEIS_for_n() -> None:
|
|
@@ -5,44 +5,44 @@ def count(bridges: int, dictionaryCurveLocationsKnown: dict[int, int]) -> int:
|
|
|
5
5
|
dictionaryCurveLocationsDiscovered: dict[int, int] = {}
|
|
6
6
|
|
|
7
7
|
for curveLocations, distinctCrossings in dictionaryCurveLocationsKnown.items():
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
bifurcationAlpha = curveLocations & 0x5555555555555555555555555555555555555555555555555555555555555555
|
|
9
|
+
bifurcationZulu = (curveLocations ^ bifurcationAlpha) >> 1
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
bifurcationAlphaHasCurves = bifurcationAlpha != 1
|
|
12
|
+
bifurcationZuluHasCurves = bifurcationZulu != 1
|
|
13
|
+
bifurcationAlphaFinalZero = not bifurcationAlpha & 1
|
|
14
|
+
bifurcationZuluFinalZero = not bifurcationZulu & 1
|
|
15
15
|
|
|
16
|
-
if
|
|
17
|
-
curveLocationAnalysis = (
|
|
16
|
+
if bifurcationAlphaHasCurves:
|
|
17
|
+
curveLocationAnalysis = (bifurcationAlpha >> 2) | (bifurcationZulu << 3) | (bifurcationAlphaFinalZero << 1)
|
|
18
18
|
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
19
19
|
dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
20
20
|
|
|
21
|
-
if
|
|
22
|
-
curveLocationAnalysis = (
|
|
21
|
+
if bifurcationZuluHasCurves:
|
|
22
|
+
curveLocationAnalysis = (bifurcationZulu >> 1) | (bifurcationAlpha << 2) | bifurcationZuluFinalZero
|
|
23
23
|
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
24
24
|
dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
25
25
|
|
|
26
|
-
curveLocationAnalysis = ((
|
|
26
|
+
curveLocationAnalysis = ((bifurcationAlpha | (bifurcationZulu << 1)) << 2) | 3
|
|
27
27
|
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
28
28
|
dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
29
29
|
|
|
30
|
-
if
|
|
30
|
+
if bifurcationAlphaHasCurves and bifurcationZuluHasCurves and (bifurcationAlphaFinalZero or bifurcationZuluFinalZero):
|
|
31
31
|
XOrHere2makePair = 0b1
|
|
32
32
|
findUnpairedBinary1 = 0
|
|
33
|
-
if
|
|
33
|
+
if bifurcationAlphaFinalZero and not bifurcationZuluFinalZero:
|
|
34
34
|
while findUnpairedBinary1 >= 0:
|
|
35
35
|
XOrHere2makePair <<= 2
|
|
36
|
-
findUnpairedBinary1 += 1 if (
|
|
37
|
-
|
|
36
|
+
findUnpairedBinary1 += 1 if (bifurcationAlpha & XOrHere2makePair) == 0 else -1
|
|
37
|
+
bifurcationAlpha ^= XOrHere2makePair
|
|
38
38
|
|
|
39
|
-
elif
|
|
39
|
+
elif bifurcationZuluFinalZero and not bifurcationAlphaFinalZero:
|
|
40
40
|
while findUnpairedBinary1 >= 0:
|
|
41
41
|
XOrHere2makePair <<= 2
|
|
42
|
-
findUnpairedBinary1 += 1 if (
|
|
43
|
-
|
|
42
|
+
findUnpairedBinary1 += 1 if (bifurcationZulu & XOrHere2makePair) == 0 else -1
|
|
43
|
+
bifurcationZulu ^= XOrHere2makePair
|
|
44
44
|
|
|
45
|
-
curveLocationAnalysis = (
|
|
45
|
+
curveLocationAnalysis = (bifurcationAlpha >> 2) | ((bifurcationZulu >> 2) << 1)
|
|
46
46
|
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
47
47
|
dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
48
48
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
bitWidth = 1 << (
|
|
1
|
+
bifurcationAlphaLocator = 0x55555555555555555555555555555555
|
|
2
|
+
bitWidth = 1 << (bifurcationAlphaLocator.bit_length() - 1).bit_length()
|
|
3
3
|
|
|
4
4
|
def count(bridges: int, dictionaryCurveLocationsKnown: dict[int, int]) -> int:
|
|
5
5
|
while bridges > 0:
|
|
@@ -9,53 +9,53 @@ def count(bridges: int, dictionaryCurveLocationsKnown: dict[int, int]) -> int:
|
|
|
9
9
|
dictionaryCurveLocationsDiscovered: dict[int, int] = {}
|
|
10
10
|
|
|
11
11
|
for curveLocations, distinctCrossings in dictionaryCurveLocationsKnown.items():
|
|
12
|
-
global
|
|
12
|
+
global bifurcationAlphaLocator, bitWidth # noqa: PLW0603
|
|
13
13
|
|
|
14
|
-
if curveLocations >
|
|
15
|
-
while curveLocations >
|
|
16
|
-
|
|
14
|
+
if curveLocations > bifurcationAlphaLocator:
|
|
15
|
+
while curveLocations > bifurcationAlphaLocator:
|
|
16
|
+
bifurcationAlphaLocator |= bifurcationAlphaLocator << bitWidth
|
|
17
17
|
bitWidth <<= 1
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
bifurcationAlpha = curveLocations & bifurcationAlphaLocator
|
|
20
|
+
bifurcationZulu = (curveLocations ^ bifurcationAlpha) >> 1
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
bifurcationAlphaHasCurves = bifurcationAlpha != 1
|
|
23
|
+
bifurcationZuluHasCurves = bifurcationZulu != 1
|
|
24
|
+
bifurcationAlphaFinalZero = (bifurcationAlpha & 1) == 0
|
|
25
|
+
bifurcationZuluFinalZero = (bifurcationZulu & 1) == 0
|
|
26
26
|
|
|
27
|
-
if
|
|
28
|
-
curveLocationAnalysis = (
|
|
27
|
+
if bifurcationAlphaHasCurves:
|
|
28
|
+
curveLocationAnalysis = (bifurcationAlpha >> 2) | (bifurcationZulu << 3) | (bifurcationAlphaFinalZero << 1)
|
|
29
29
|
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
30
30
|
dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
31
31
|
|
|
32
|
-
if
|
|
33
|
-
curveLocationAnalysis = (
|
|
32
|
+
if bifurcationZuluHasCurves:
|
|
33
|
+
curveLocationAnalysis = (bifurcationZulu >> 1) | ((bifurcationAlpha << 2) | bifurcationZuluFinalZero)
|
|
34
34
|
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
35
35
|
dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
36
36
|
|
|
37
|
-
curveLocationAnalysis = ((
|
|
37
|
+
curveLocationAnalysis = ((bifurcationAlpha | (bifurcationZulu << 1)) << 2) | 3
|
|
38
38
|
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
39
39
|
dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
40
40
|
|
|
41
|
-
if
|
|
42
|
-
if
|
|
41
|
+
if bifurcationAlphaHasCurves and bifurcationZuluHasCurves and (bifurcationAlphaFinalZero or bifurcationZuluFinalZero):
|
|
42
|
+
if bifurcationAlphaFinalZero and not bifurcationZuluFinalZero:
|
|
43
43
|
Z0Z_idk = 0
|
|
44
44
|
Z0Z_indexIDK = 1
|
|
45
45
|
while Z0Z_idk >= 0:
|
|
46
46
|
Z0Z_indexIDK <<= 2
|
|
47
|
-
Z0Z_idk += 1 if (
|
|
48
|
-
|
|
47
|
+
Z0Z_idk += 1 if (bifurcationAlpha & Z0Z_indexIDK) == 0 else -1
|
|
48
|
+
bifurcationAlpha ^= Z0Z_indexIDK
|
|
49
49
|
|
|
50
|
-
if
|
|
50
|
+
if bifurcationZuluFinalZero and not bifurcationAlphaFinalZero:
|
|
51
51
|
Z0Z_idk = 0
|
|
52
52
|
Z0Z_indexIDK = 1
|
|
53
53
|
while Z0Z_idk >= 0:
|
|
54
54
|
Z0Z_indexIDK <<= 2
|
|
55
|
-
Z0Z_idk += 1 if (
|
|
56
|
-
|
|
55
|
+
Z0Z_idk += 1 if (bifurcationZulu & Z0Z_indexIDK) == 0 else -1
|
|
56
|
+
bifurcationZulu ^= Z0Z_indexIDK
|
|
57
57
|
|
|
58
|
-
curveLocationAnalysis = (
|
|
58
|
+
curveLocationAnalysis = (bifurcationAlpha >> 2) | ((bifurcationZulu >> 2) << 1)
|
|
59
59
|
if curveLocationAnalysis < curveLocationsMAXIMUM:
|
|
60
60
|
dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
|
|
61
61
|
|
|
@@ -34,41 +34,41 @@ def count(bridges: int, curveLocationsKnown: dict[int, int]) -> int:
|
|
|
34
34
|
curveLocations = int(str(keyName).split(":")[1])
|
|
35
35
|
distinctCrossings = int(str(redisClient.get(keyName)))
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
bifurcationAlpha = curveLocations & 0x5555555555555555555555555555555555555555555555555555555555555555
|
|
38
|
+
bifurcationZulu = (curveLocations ^ bifurcationAlpha) >> 1
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
bifurcationAlphaHasCurves = bifurcationAlpha != 1
|
|
41
|
+
bifurcationZuluHasCurves = bifurcationZulu != 1
|
|
42
|
+
bifurcationAlphaFinalZero = not bifurcationAlpha & 1
|
|
43
|
+
bifurcationZuluFinalZero = not bifurcationZulu & 1
|
|
44
44
|
|
|
45
|
-
if
|
|
46
|
-
curveLocationAnalysis = (
|
|
45
|
+
if bifurcationAlphaHasCurves:
|
|
46
|
+
curveLocationAnalysis = (bifurcationAlpha >> 2) | (bifurcationZulu << 3) | (bifurcationAlphaFinalZero << 1)
|
|
47
47
|
storeCurveLocations(curveLocationAnalysis, distinctCrossings)
|
|
48
48
|
|
|
49
|
-
if
|
|
50
|
-
curveLocationAnalysis = (
|
|
49
|
+
if bifurcationZuluHasCurves:
|
|
50
|
+
curveLocationAnalysis = (bifurcationZulu >> 1) | (bifurcationAlpha << 2) | bifurcationZuluFinalZero
|
|
51
51
|
storeCurveLocations(curveLocationAnalysis, distinctCrossings)
|
|
52
52
|
|
|
53
|
-
curveLocationAnalysis = ((
|
|
53
|
+
curveLocationAnalysis = ((bifurcationAlpha | (bifurcationZulu << 1)) << 2) | 3
|
|
54
54
|
storeCurveLocations(curveLocationAnalysis, distinctCrossings)
|
|
55
55
|
|
|
56
|
-
if
|
|
56
|
+
if bifurcationAlphaHasCurves and bifurcationZuluHasCurves and (bifurcationAlphaFinalZero or bifurcationZuluFinalZero):
|
|
57
57
|
XOrHere2makePair = 0b1
|
|
58
58
|
findUnpairedBinary1 = 0
|
|
59
|
-
if
|
|
59
|
+
if bifurcationAlphaFinalZero and not bifurcationZuluFinalZero:
|
|
60
60
|
while findUnpairedBinary1 >= 0:
|
|
61
61
|
XOrHere2makePair <<= 2
|
|
62
|
-
findUnpairedBinary1 += 1 if (
|
|
63
|
-
|
|
62
|
+
findUnpairedBinary1 += 1 if (bifurcationAlpha & XOrHere2makePair) == 0 else -1
|
|
63
|
+
bifurcationAlpha ^= XOrHere2makePair
|
|
64
64
|
|
|
65
|
-
elif
|
|
65
|
+
elif bifurcationZuluFinalZero and not bifurcationAlphaFinalZero:
|
|
66
66
|
while findUnpairedBinary1 >= 0:
|
|
67
67
|
XOrHere2makePair <<= 2
|
|
68
|
-
findUnpairedBinary1 += 1 if (
|
|
69
|
-
|
|
68
|
+
findUnpairedBinary1 += 1 if (bifurcationZulu & XOrHere2makePair) == 0 else -1
|
|
69
|
+
bifurcationZulu ^= XOrHere2makePair
|
|
70
70
|
|
|
71
|
-
curveLocationAnalysis = (
|
|
71
|
+
curveLocationAnalysis = (bifurcationAlpha >> 2) | ((bifurcationZulu >> 2) << 1)
|
|
72
72
|
storeCurveLocations(curveLocationAnalysis, distinctCrossings)
|
|
73
73
|
|
|
74
74
|
# Move discovered data to known for next iteration
|