mapFolding 0.9.1__py3-none-any.whl → 0.9.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.
- mapFolding/Z0Z_flowControl.py +99 -0
- mapFolding/__init__.py +63 -60
- mapFolding/basecamp.py +40 -35
- mapFolding/beDRY.py +72 -66
- mapFolding/dataBaskets.py +49 -0
- mapFolding/datatypes.py +21 -0
- mapFolding/oeis.py +57 -75
- mapFolding/reference/__init__.py +2 -2
- mapFolding/someAssemblyRequired/__init__.py +6 -4
- mapFolding/someAssemblyRequired/_theTypes.py +9 -1
- mapFolding/someAssemblyRequired/_tool_Make.py +0 -1
- mapFolding/someAssemblyRequired/_tool_Then.py +16 -8
- mapFolding/someAssemblyRequired/_toolboxAntecedents.py +111 -35
- mapFolding/someAssemblyRequired/_toolboxContainers.py +58 -49
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +42 -42
- mapFolding/someAssemblyRequired/toolboxNumba.py +3 -11
- mapFolding/someAssemblyRequired/transformationTools.py +94 -70
- mapFolding/syntheticModules/numbaCount.py +9 -11
- mapFolding/theDao.py +19 -21
- mapFolding/theDaoOfMapFolding.py +142 -0
- mapFolding/theSSOT.py +36 -58
- mapFolding/toolboxFilesystem.py +29 -38
- {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/METADATA +4 -3
- mapfolding-0.9.3.dist-info/RECORD +51 -0
- {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/WHEEL +1 -1
- tests/__init__.py +2 -2
- tests/conftest.py +7 -7
- tests/test_computations.py +15 -13
- tests/test_other.py +0 -7
- tests/test_tasks.py +2 -2
- mapfolding-0.9.1.dist-info/RECORD +0 -47
- /mapFolding/reference/{lunnanNumpy.py → lunnonNumpy.py} +0 -0
- /mapFolding/reference/{lunnanWhile.py → lunnonWhile.py} +0 -0
- {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from mapFolding.beDRY import getConnectionGraph, getLeavesTotal, makeDataContainer
|
|
2
|
+
from mapFolding.datatypes import Array3D, Array1DElephino, Array1DLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal
|
|
3
|
+
import dataclasses
|
|
4
|
+
|
|
5
|
+
@dataclasses.dataclass
|
|
6
|
+
class MapFoldingState:
|
|
7
|
+
mapShape: tuple[DatatypeLeavesTotal, ...] = dataclasses.field(init=True, metadata={'elementConstructor': 'DatatypeLeavesTotal'})
|
|
8
|
+
|
|
9
|
+
groupsOfFolds: DatatypeFoldsTotal = dataclasses.field(default=DatatypeFoldsTotal(0), metadata={'theCountingIdentifier': True})
|
|
10
|
+
|
|
11
|
+
gap1ndex: DatatypeElephino = DatatypeElephino(0)
|
|
12
|
+
gap1ndexCeiling: DatatypeElephino = DatatypeElephino(0)
|
|
13
|
+
indexDimension: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
14
|
+
indexLeaf: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
15
|
+
indexMiniGap: DatatypeElephino = DatatypeElephino(0)
|
|
16
|
+
leaf1ndex: DatatypeLeavesTotal = DatatypeLeavesTotal(1)
|
|
17
|
+
leafConnectee: DatatypeLeavesTotal = DatatypeLeavesTotal(0)
|
|
18
|
+
|
|
19
|
+
dimensionsUnconstrained: DatatypeLeavesTotal = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
20
|
+
|
|
21
|
+
countDimensionsGapped: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
22
|
+
gapRangeStart: Array1DElephino = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DElephino.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
23
|
+
gapsWhere: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
24
|
+
leafAbove: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
25
|
+
leafBelow: Array1DLeavesTotal = dataclasses.field(default=None, init=True, metadata={'dtype': Array1DLeavesTotal.__args__[1].__args__[0]}) # pyright: ignore[reportAssignmentType, reportAttributeAccessIssue, reportUnknownMemberType]
|
|
26
|
+
|
|
27
|
+
connectionGraph: Array3D = dataclasses.field(init=False, metadata={'dtype': Array3D.__args__[1].__args__[0]}) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
|
|
28
|
+
dimensionsTotal: DatatypeLeavesTotal = dataclasses.field(init=False)
|
|
29
|
+
leavesTotal: DatatypeLeavesTotal = dataclasses.field(init=False)
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def foldsTotal(self) -> DatatypeFoldsTotal:
|
|
33
|
+
_foldsTotal = DatatypeFoldsTotal(self.leavesTotal) * self.groupsOfFolds
|
|
34
|
+
return _foldsTotal
|
|
35
|
+
|
|
36
|
+
def __post_init__(self) -> None:
|
|
37
|
+
self.dimensionsTotal = DatatypeLeavesTotal(len(self.mapShape))
|
|
38
|
+
self.leavesTotal = DatatypeLeavesTotal(getLeavesTotal(self.mapShape))
|
|
39
|
+
|
|
40
|
+
leavesTotalAsInt = int(self.leavesTotal)
|
|
41
|
+
|
|
42
|
+
self.connectionGraph = getConnectionGraph(self.mapShape, leavesTotalAsInt, self.__dataclass_fields__['connectionGraph'].metadata['dtype'])
|
|
43
|
+
|
|
44
|
+
if self.dimensionsUnconstrained is None: self.dimensionsUnconstrained = DatatypeLeavesTotal(int(self.dimensionsTotal)) # pyright: ignore[reportUnnecessaryComparison]
|
|
45
|
+
if self.gapsWhere is None: self.gapsWhere = makeDataContainer(leavesTotalAsInt * leavesTotalAsInt + 1, self.__dataclass_fields__['gapsWhere'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
46
|
+
if self.countDimensionsGapped is None: self.countDimensionsGapped = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['countDimensionsGapped'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
47
|
+
if self.gapRangeStart is None: self.gapRangeStart = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['gapRangeStart'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
48
|
+
if self.leafAbove is None: self.leafAbove = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafAbove'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
|
49
|
+
if self.leafBelow is None: self.leafBelow = makeDataContainer(leavesTotalAsInt + 1, self.__dataclass_fields__['leafBelow'].metadata['dtype']) # pyright: ignore[reportUnnecessaryComparison]
|
mapFolding/datatypes.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from numpy import dtype, int64 as numpy_int64, integer, ndarray
|
|
2
|
+
from typing import Any, TypeAlias, TypeVar
|
|
3
|
+
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Flexible Data Structure System Needs Enhanced Paradigm https://github.com/hunterhogan/mapFolding/issues/9
|
|
6
|
+
|
|
7
|
+
NumPyIntegerType = TypeVar('NumPyIntegerType', bound=integer[Any], covariant=True)
|
|
8
|
+
|
|
9
|
+
DatatypeLeavesTotal: TypeAlias = int
|
|
10
|
+
NumPyLeavesTotal: TypeAlias = numpy_int64
|
|
11
|
+
|
|
12
|
+
DatatypeElephino: TypeAlias = int
|
|
13
|
+
NumPyElephino: TypeAlias = numpy_int64
|
|
14
|
+
|
|
15
|
+
DatatypeFoldsTotal: TypeAlias = int
|
|
16
|
+
NumPyFoldsTotal: TypeAlias = numpy_int64
|
|
17
|
+
|
|
18
|
+
Array3D: TypeAlias = ndarray[tuple[int, int, int], dtype[NumPyLeavesTotal]]
|
|
19
|
+
Array1DLeavesTotal: TypeAlias = ndarray[tuple[int], dtype[NumPyLeavesTotal]]
|
|
20
|
+
Array1DElephino: TypeAlias = ndarray[tuple[int], dtype[NumPyElephino]]
|
|
21
|
+
Array1DFoldsTotal: TypeAlias = ndarray[tuple[int], dtype[NumPyFoldsTotal]]
|
mapFolding/oeis.py
CHANGED
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Interface to The Online Encyclopedia of Integer Sequences (OEIS) for map folding sequences.
|
|
3
3
|
|
|
4
|
-
This module provides a comprehensive interface for accessing and utilizing integer sequences
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
This module provides a comprehensive interface for accessing and utilizing integer sequences from the OEIS that relate
|
|
5
|
+
to map folding problems. It serves as the bridge between mathematical sequence definitions and the computational
|
|
6
|
+
algorithm, implementing:
|
|
7
7
|
|
|
8
8
|
1. Retrieval of sequence data from OEIS with local caching for performance optimization.
|
|
9
9
|
2. Mapping of sequence indices to corresponding map shapes based on sequence definitions.
|
|
10
10
|
3. Command-line and programmatic interfaces for sequence lookups and validation.
|
|
11
11
|
4. Computation of sequence terms not available in the OEIS database.
|
|
12
12
|
|
|
13
|
-
The module maintains a registry of implemented OEIS sequences (A001415-A001418, A195646)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
literature while also extending sequences beyond their currently known terms.
|
|
13
|
+
The module maintains a registry of implemented OEIS sequences (A001415-A001418, A195646) with their metadata, known
|
|
14
|
+
values, and conversion functions between sequence indices and map dimensions. This allows the package to validate
|
|
15
|
+
results against established mathematical literature while also extending sequences beyond their currently known terms.
|
|
17
16
|
|
|
18
|
-
Each sequence is carefully mapped to its corresponding map folding problem, enabling
|
|
19
|
-
|
|
20
|
-
implementation in the package.
|
|
17
|
+
Each sequence is carefully mapped to its corresponding map folding problem, enabling seamless integration between the
|
|
18
|
+
mathematical definition in OEIS and the computational implementation in the package.
|
|
21
19
|
"""
|
|
22
20
|
from collections.abc import Callable
|
|
23
21
|
from datetime import datetime, timedelta
|
|
24
22
|
from functools import cache
|
|
25
|
-
from mapFolding import
|
|
23
|
+
from mapFolding import countFolds, The, writeStringToHere
|
|
26
24
|
from pathlib import Path
|
|
27
25
|
from typing import Any, Final, TYPE_CHECKING
|
|
28
26
|
import argparse
|
|
@@ -104,10 +102,8 @@ def validateOEISid(oeisIDcandidate: str) -> str:
|
|
|
104
102
|
"""
|
|
105
103
|
Validates an OEIS sequence ID against implemented sequences.
|
|
106
104
|
|
|
107
|
-
If the provided ID is recognized within the application's implemented
|
|
108
|
-
|
|
109
|
-
Otherwise, a KeyError is raised indicating that the sequence is not
|
|
110
|
-
directly supported.
|
|
105
|
+
If the provided ID is recognized within the application's implemented OEIS sequences, the function returns the
|
|
106
|
+
verified ID in uppercase. Otherwise, a KeyError is raised indicating that the sequence is not directly supported.
|
|
111
107
|
|
|
112
108
|
Parameters:
|
|
113
109
|
oeisIDcandidate: The OEIS sequence identifier to validate.
|
|
@@ -138,20 +134,18 @@ def _parseBFileOEIS(OEISbFile: str, oeisID: str) -> dict[int, int]:
|
|
|
138
134
|
"""
|
|
139
135
|
Parses the content of an OEIS b-file for a given sequence ID.
|
|
140
136
|
|
|
141
|
-
This function processes a multiline string representing an OEIS b-file and
|
|
142
|
-
|
|
143
|
-
values. The first line of the b-file is expected to contain a comment that
|
|
137
|
+
This function processes a multiline string representing an OEIS b-file and creates a dictionary mapping integer
|
|
138
|
+
indices to their corresponding sequence values. The first line of the b-file is expected to contain a comment that
|
|
144
139
|
matches the given sequence ID. If it does not match, a ValueError is raised.
|
|
145
140
|
|
|
146
141
|
Parameters:
|
|
147
|
-
OEISbFile: A multiline string representing an OEIS b-file.
|
|
148
|
-
oeisID: The expected OEIS sequence identifier.
|
|
142
|
+
OEISbFile: A multiline string representing an OEIS b-file. oeisID: The expected OEIS sequence identifier.
|
|
149
143
|
Returns:
|
|
150
|
-
OEISsequence: A dictionary where each key is an integer index `n` and
|
|
151
|
-
|
|
144
|
+
OEISsequence: A dictionary where each key is an integer index `n` and each value is the sequence value `a(n)`
|
|
145
|
+
corresponding to that index.
|
|
152
146
|
Raises:
|
|
153
|
-
ValueError: If the first line of the file does not indicate the expected
|
|
154
|
-
|
|
147
|
+
ValueError: If the first line of the file does not indicate the expected sequence ID or if the content format is
|
|
148
|
+
invalid.
|
|
155
149
|
"""
|
|
156
150
|
bFileLines: list[str] = OEISbFile.strip().splitlines()
|
|
157
151
|
# if not bFileLines.pop(0).startswith(f"# {oeisID}"):
|
|
@@ -170,23 +164,21 @@ def getOEISofficial(pathFilenameCache: Path, url: str) -> None | str:
|
|
|
170
164
|
"""
|
|
171
165
|
Retrieve OEIS sequence data from cache or online source.
|
|
172
166
|
|
|
173
|
-
This function implements a caching strategy for OEIS sequence data, first checking
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
writes it to the cache for future use.
|
|
167
|
+
This function implements a caching strategy for OEIS sequence data, first checking if a local cached copy exists and
|
|
168
|
+
is not expired. If a valid cache exists, it returns the cached content; otherwise, it fetches the data from the OEIS
|
|
169
|
+
website and writes it to the cache for future use.
|
|
177
170
|
|
|
178
171
|
Parameters:
|
|
179
|
-
pathFilenameCache: Path to the local cache file.
|
|
180
|
-
|
|
172
|
+
pathFilenameCache: Path to the local cache file. url: URL to retrieve the OEIS sequence data from if cache is
|
|
173
|
+
invalid or missing.
|
|
181
174
|
|
|
182
175
|
Returns:
|
|
183
|
-
oeisInformation: The retrieved OEIS sequence information as a string, or None if
|
|
184
|
-
|
|
176
|
+
oeisInformation: The retrieved OEIS sequence information as a string, or None if the information could not be
|
|
177
|
+
retrieved.
|
|
185
178
|
|
|
186
179
|
Notes:
|
|
187
|
-
The cache expiration period is controlled by the global `cacheDays` variable.
|
|
188
|
-
|
|
189
|
-
it will return None and issue a warning.
|
|
180
|
+
The cache expiration period is controlled by the global `cacheDays` variable. If the function fails to retrieve
|
|
181
|
+
data from both cache and online source, it will return None and issue a warning.
|
|
190
182
|
"""
|
|
191
183
|
tryCache: bool = False
|
|
192
184
|
if pathFilenameCache.exists():
|
|
@@ -213,22 +205,20 @@ def getOEISofficial(pathFilenameCache: Path, url: str) -> None | str:
|
|
|
213
205
|
|
|
214
206
|
def getOEISidValues(oeisID: str) -> dict[int, int]:
|
|
215
207
|
"""
|
|
216
|
-
Retrieves the specified OEIS sequence as a dictionary mapping integer indices
|
|
217
|
-
to their corresponding values.
|
|
208
|
+
Retrieves the specified OEIS sequence as a dictionary mapping integer indices to their corresponding values.
|
|
218
209
|
|
|
219
|
-
This function checks for a cached local copy of the sequence data, using it if
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
mapping each index to its sequence value.
|
|
210
|
+
This function checks for a cached local copy of the sequence data, using it if it has not expired. Otherwise, it
|
|
211
|
+
fetches the sequence data from the OEIS website and writes it to the cache. The parsed data is returned as a
|
|
212
|
+
dictionary mapping each index to its sequence value.
|
|
223
213
|
|
|
224
214
|
Parameters:
|
|
225
215
|
oeisID: The identifier of the OEIS sequence to retrieve.
|
|
226
216
|
Returns:
|
|
227
|
-
OEISsequence: A dictionary where each key is an integer index, `n`, and each
|
|
228
|
-
|
|
217
|
+
OEISsequence: A dictionary where each key is an integer index, `n`, and each value is the corresponding `a(n)`
|
|
218
|
+
from the OEIS entry.
|
|
229
219
|
Raises:
|
|
230
|
-
ValueError: If the cached or downloaded file format is invalid.
|
|
231
|
-
|
|
220
|
+
ValueError: If the cached or downloaded file format is invalid. IOError: If there is an error reading from or
|
|
221
|
+
writing to the local cache.
|
|
232
222
|
"""
|
|
233
223
|
|
|
234
224
|
pathFilenameCache: Path = pathCache / getFilenameOEISbFile(oeisID)
|
|
@@ -244,23 +234,19 @@ def getOEISidInformation(oeisID: str) -> tuple[str, int]:
|
|
|
244
234
|
"""
|
|
245
235
|
Retrieve the description and offset for an OEIS sequence.
|
|
246
236
|
|
|
247
|
-
This function fetches the metadata for a given OEIS sequence ID, including
|
|
248
|
-
|
|
249
|
-
to avoid redundant network requests while ensuring data freshness.
|
|
237
|
+
This function fetches the metadata for a given OEIS sequence ID, including its textual description and index offset
|
|
238
|
+
value. It uses a caching mechanism to avoid redundant network requests while ensuring data freshness.
|
|
250
239
|
|
|
251
240
|
Parameters:
|
|
252
241
|
oeisID: The OEIS sequence identifier to retrieve information for.
|
|
253
242
|
|
|
254
243
|
Returns:
|
|
255
|
-
A tuple containing:
|
|
256
|
-
|
|
257
|
-
- offset: An integer representing the starting index of the sequence.
|
|
258
|
-
Usually 0 or 1, depending on the mathematical context.
|
|
244
|
+
A tuple containing: - description: A string describing the sequence's mathematical meaning. - offset: An integer
|
|
245
|
+
representing the starting index of the sequence. Usually 0 or 1, depending on the mathematical context.
|
|
259
246
|
|
|
260
247
|
Notes:
|
|
261
|
-
Sequence descriptions are parsed from the machine-readable format of OEIS.
|
|
262
|
-
|
|
263
|
-
fallback values are returned.
|
|
248
|
+
Sequence descriptions are parsed from the machine-readable format of OEIS. If information cannot be retrieved,
|
|
249
|
+
warning messages are issued and fallback values are returned.
|
|
264
250
|
"""
|
|
265
251
|
oeisID = validateOEISid(oeisID)
|
|
266
252
|
pathFilenameCache: Path = pathCache / f"{oeisID}.txt"
|
|
@@ -294,22 +280,22 @@ def makeSettingsOEIS() -> dict[str, SettingsOEIS]:
|
|
|
294
280
|
"""
|
|
295
281
|
Construct the comprehensive settings dictionary for all implemented OEIS sequences.
|
|
296
282
|
|
|
297
|
-
This function builds a complete configuration dictionary for all supported OEIS
|
|
298
|
-
|
|
283
|
+
This function builds a complete configuration dictionary for all supported OEIS sequences by retrieving and
|
|
284
|
+
combining:
|
|
299
285
|
1. Sequence values from OEIS b-files
|
|
300
286
|
2. Sequence metadata (descriptions and offsets)
|
|
301
287
|
3. Hardcoded mapping functions and test values
|
|
302
288
|
|
|
303
|
-
The resulting dictionary provides a single authoritative source for all OEIS-related
|
|
304
|
-
|
|
289
|
+
The resulting dictionary provides a single authoritative source for all OEIS-related configurations used throughout
|
|
290
|
+
the package, including:
|
|
305
291
|
- Mathematical descriptions of each sequence
|
|
306
292
|
- Functions to convert between sequence indices and map dimensions
|
|
307
293
|
- Known sequence values retrieved from OEIS
|
|
308
294
|
- Testing and benchmarking reference values
|
|
309
295
|
|
|
310
296
|
Returns:
|
|
311
|
-
A dictionary mapping OEIS sequence IDs to their complete settings objects,
|
|
312
|
-
|
|
297
|
+
A dictionary mapping OEIS sequence IDs to their complete settings objects, containing all metadata and known
|
|
298
|
+
values needed for computation and validation.
|
|
313
299
|
"""
|
|
314
300
|
settingsTarget: dict[str, SettingsOEIS] = {}
|
|
315
301
|
for oeisID in oeisIDsImplemented:
|
|
@@ -340,7 +326,7 @@ def makeDictionaryFoldsTotalKnown() -> dict[tuple[int, ...], int]:
|
|
|
340
326
|
|
|
341
327
|
for n, foldingsTotal in sequence.items():
|
|
342
328
|
mapShape = settings['getMapShape'](n)
|
|
343
|
-
mapShape = tuple(
|
|
329
|
+
mapShape = tuple(mapShape)
|
|
344
330
|
dictionaryMapDimensionsToFoldsTotalKnown[mapShape] = foldingsTotal
|
|
345
331
|
return dictionaryMapDimensionsToFoldsTotalKnown
|
|
346
332
|
|
|
@@ -348,21 +334,20 @@ def getFoldsTotalKnown(mapShape: tuple[int, ...]) -> int:
|
|
|
348
334
|
"""
|
|
349
335
|
Retrieve the known total number of foldings for a given map shape.
|
|
350
336
|
|
|
351
|
-
This function looks up precalculated folding totals for specific map dimensions
|
|
352
|
-
|
|
353
|
-
requiring computation, and can be used to validate algorithm results.
|
|
337
|
+
This function looks up precalculated folding totals for specific map dimensions from OEIS sequences. It serves as a
|
|
338
|
+
rapid reference for known values without requiring computation, and can be used to validate algorithm results.
|
|
354
339
|
|
|
355
340
|
Parameters:
|
|
356
341
|
mapShape: A tuple of integers representing the dimensions of the map.
|
|
357
342
|
|
|
358
343
|
Returns:
|
|
359
|
-
foldingsTotal: The known total number of foldings for the given map shape,
|
|
360
|
-
|
|
344
|
+
foldingsTotal: The known total number of foldings for the given map shape, or -1 if the map shape doesn't match
|
|
345
|
+
any known values in the OEIS sequences.
|
|
361
346
|
|
|
362
347
|
Notes:
|
|
363
|
-
The function uses a cached dictionary (via makeDictionaryFoldsTotalKnown) to
|
|
364
|
-
|
|
365
|
-
|
|
348
|
+
The function uses a cached dictionary (via makeDictionaryFoldsTotalKnown) to efficiently retrieve values without
|
|
349
|
+
repeatedly parsing OEIS data. Map shape tuples are sorted internally to ensure consistent lookup regardless of
|
|
350
|
+
dimension order.
|
|
366
351
|
"""
|
|
367
352
|
lookupFoldsTotal = makeDictionaryFoldsTotalKnown()
|
|
368
353
|
return lookupFoldsTotal.get(tuple(mapShape), -1)
|
|
@@ -395,15 +380,13 @@ def oeisIDfor_n(oeisID: str, n: int | Any) -> int:
|
|
|
395
380
|
Calculate `a(n)` of a sequence from "The On-Line Encyclopedia of Integer Sequences" (OEIS).
|
|
396
381
|
|
|
397
382
|
Parameters:
|
|
398
|
-
oeisID: The ID of the OEIS sequence.
|
|
399
|
-
n: A non-negative integer for which to calculate the sequence value.
|
|
383
|
+
oeisID: The ID of the OEIS sequence. n: A non-negative integer for which to calculate the sequence value.
|
|
400
384
|
|
|
401
385
|
Returns:
|
|
402
386
|
sequenceValue: `a(n)` of the OEIS sequence.
|
|
403
387
|
|
|
404
388
|
Raises:
|
|
405
|
-
ValueError: If `n` is negative.
|
|
406
|
-
KeyError: If the OEIS sequence ID is not directly implemented.
|
|
389
|
+
ValueError: If `n` is negative. KeyError: If the OEIS sequence ID is not directly implemented.
|
|
407
390
|
"""
|
|
408
391
|
oeisID = validateOEISid(oeisID)
|
|
409
392
|
|
|
@@ -418,7 +401,6 @@ def oeisIDfor_n(oeisID: str, n: int | Any) -> int:
|
|
|
418
401
|
raise ArithmeticError(f"OEIS sequence {oeisID} is not defined at {n = }.")
|
|
419
402
|
foldsTotal: int = settingsOEIS[oeisID]['valuesKnown'][n]
|
|
420
403
|
return foldsTotal
|
|
421
|
-
from mapFolding.basecamp import countFolds
|
|
422
404
|
return countFolds(mapShape)
|
|
423
405
|
|
|
424
406
|
def OEIS_for_n() -> None:
|
mapFolding/reference/__init__.py
CHANGED
|
@@ -13,8 +13,8 @@ Categories of reference implementations:
|
|
|
13
13
|
- foldings.AA - Reconstructed Atlas Autocode version with corrections
|
|
14
14
|
|
|
15
15
|
2. Direct translations:
|
|
16
|
-
-
|
|
17
|
-
-
|
|
16
|
+
- lunnonWhile.py - Python translation using while loops
|
|
17
|
+
- lunnonNumpy.py - NumPy-based translation with array operations
|
|
18
18
|
|
|
19
19
|
3. Alternative implementations:
|
|
20
20
|
- irvineJavaPort.py - Port from Sean A. Irvine's Java implementation
|
|
@@ -22,7 +22,7 @@ functional implementations into highly-optimized variants with verified correctn
|
|
|
22
22
|
- Recipe configuration for generating optimized code (RecipeSynthesizeFlow)
|
|
23
23
|
- Dataclass decomposition for compatibility (ShatteredDataclass)
|
|
24
24
|
|
|
25
|
-
3. **Optimization
|
|
25
|
+
3. **Optimization assembly lines**
|
|
26
26
|
- General-purpose Numba acceleration (makeNumbaFlow)
|
|
27
27
|
- Job-specific optimization for concrete parameters (makeJobNumba)
|
|
28
28
|
- Specialized component transformation (decorateCallableWithNumba)
|
|
@@ -52,15 +52,17 @@ from mapFolding.someAssemblyRequired._theTypes import (
|
|
|
52
52
|
ast_Identifier as ast_Identifier,
|
|
53
53
|
astClassHasDOTnameNotName as astClassHasDOTnameNotName,
|
|
54
54
|
astClassHasDOTtarget as astClassHasDOTtarget,
|
|
55
|
-
astClassHasDOTvalue_expr as astClassHasDOTvalue_expr,
|
|
56
|
-
astClassHasDOTvalue_exprNone as astClassHasDOTvalue_exprNone,
|
|
57
|
-
astClassHasDOTtargetAttributeNameSubscript as astClassHasDOTtargetAttributeNameSubscript,
|
|
58
55
|
astClassHasDOTtarget_expr as astClassHasDOTtarget_expr,
|
|
56
|
+
astClassHasDOTtargetAttributeNameSubscript as astClassHasDOTtargetAttributeNameSubscript,
|
|
59
57
|
astClassHasDOTvalue as astClassHasDOTvalue,
|
|
58
|
+
astClassHasDOTvalue_expr as astClassHasDOTvalue_expr,
|
|
59
|
+
astClassHasDOTvalue_exprNone as astClassHasDOTvalue_exprNone,
|
|
60
60
|
astClassOptionallyHasDOTnameNotName as astClassOptionallyHasDOTnameNotName,
|
|
61
|
+
ImaCallToName as ImaCallToName,
|
|
61
62
|
intORlist_ast_type_paramORstr_orNone as intORlist_ast_type_paramORstr_orNone,
|
|
62
63
|
intORstr_orNone as intORstr_orNone,
|
|
63
64
|
list_ast_type_paramORstr_orNone as list_ast_type_paramORstr_orNone,
|
|
65
|
+
NodeORattribute as NodeORattribute,
|
|
64
66
|
str_nameDOTname as str_nameDOTname,
|
|
65
67
|
个 as 个,
|
|
66
68
|
)
|
|
@@ -13,10 +13,17 @@ else:
|
|
|
13
13
|
astClassHasDOTnameNotName = stuPyd
|
|
14
14
|
astClassHasDOTvalue_expr = stuPyd
|
|
15
15
|
|
|
16
|
+
class ImaCallToName(ast.Call):
|
|
17
|
+
func: ast.Name # pyright: ignore[reportIncompatibleVariableOverride]
|
|
18
|
+
# assert isinstance(ast.Call.func, ast.Name), "brinkmanship"
|
|
19
|
+
# func: ast.Name
|
|
20
|
+
|
|
16
21
|
astClassHasDOTtargetAttributeNameSubscript: typing_TypeAlias = ast.AnnAssign | ast.AugAssign
|
|
17
22
|
astClassHasDOTtarget_expr: typing_TypeAlias = ast.AsyncFor | ast.comprehension | ast.For
|
|
18
23
|
astClassHasDOTtarget: typing_TypeAlias = ast.NamedExpr | astClassHasDOTtarget_expr | astClassHasDOTtargetAttributeNameSubscript
|
|
24
|
+
|
|
19
25
|
astClassOptionallyHasDOTnameNotName: typing_TypeAlias = ast.ExceptHandler | ast.MatchAs | ast.MatchStar
|
|
26
|
+
|
|
20
27
|
astClassHasDOTvalue_exprNone: typing_TypeAlias = ast.AnnAssign | ast.Return | ast.Yield
|
|
21
28
|
astClassHasDOTvalue: typing_TypeAlias = ast.Constant | ast.MatchSingleton | astClassHasDOTvalue_expr | astClassHasDOTvalue_exprNone
|
|
22
29
|
|
|
@@ -27,7 +34,8 @@ intORstr_orNone: typing_TypeAlias = Any
|
|
|
27
34
|
list_ast_type_paramORstr_orNone: typing_TypeAlias = Any
|
|
28
35
|
str_nameDOTname: typing_TypeAlias = stuPyd
|
|
29
36
|
|
|
30
|
-
个 = typing_TypeVar('个', bound= ast.AST, covariant=True)
|
|
37
|
+
个 = typing_TypeVar('个', bound = ast.AST, covariant = True)
|
|
38
|
+
NodeORattribute = typing_TypeVar('NodeORattribute', bound = ast.AST | ast_expr_Slice | ast_Identifier | str_nameDOTname | bool | Any | None, covariant = True)
|
|
31
39
|
|
|
32
40
|
# All ast classes by subgroup:
|
|
33
41
|
Ima_ast_boolop: typing_TypeAlias = ast.boolop | ast.And | ast.Or
|
|
@@ -83,7 +83,6 @@ class Make:
|
|
|
83
83
|
|
|
84
84
|
@staticmethod
|
|
85
85
|
def Constant(value: Any, **keywordArguments: intORstr_orNone) -> ast.Constant:
|
|
86
|
-
"""value: str|int|float|bool|None|bytes|bytearray|memoryview|complex|list|tuple|dict|set, or any other type that can be represented as a constant in Python."""
|
|
87
86
|
return ast.Constant(value, **keywordArguments)
|
|
88
87
|
|
|
89
88
|
@staticmethod
|
|
@@ -15,7 +15,7 @@ once they have been identified using predicate functions from ifThis.
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
from collections.abc import Callable, Sequence
|
|
18
|
-
from mapFolding.someAssemblyRequired import ast_Identifier, astClassHasDOTvalue
|
|
18
|
+
from mapFolding.someAssemblyRequired import ast_Identifier, astClassHasDOTvalue, ImaCallToName, NodeORattribute
|
|
19
19
|
from typing import Any
|
|
20
20
|
import ast
|
|
21
21
|
|
|
@@ -46,6 +46,13 @@ class grab:
|
|
|
46
46
|
return node
|
|
47
47
|
return workhorse
|
|
48
48
|
|
|
49
|
+
@staticmethod
|
|
50
|
+
def funcDOTidAttribute(action: Callable[[ast_Identifier], Any]) -> Callable[[ImaCallToName], ImaCallToName]:
|
|
51
|
+
def workhorse(node: ImaCallToName) -> ImaCallToName:
|
|
52
|
+
node.func = grab.idAttribute(action)(node.func)
|
|
53
|
+
return node
|
|
54
|
+
return workhorse
|
|
55
|
+
|
|
49
56
|
@staticmethod
|
|
50
57
|
def idAttribute(action: Callable[[ast_Identifier], ast_Identifier]) -> Callable[[ast.Name], ast.Name]:
|
|
51
58
|
def workhorse(node: ast.Name) -> ast.Name:
|
|
@@ -54,7 +61,7 @@ class grab:
|
|
|
54
61
|
return workhorse
|
|
55
62
|
|
|
56
63
|
@staticmethod
|
|
57
|
-
def valueAttribute(action: Callable[[Any
|
|
64
|
+
def valueAttribute(action: Callable[[Any], Any]) -> Callable[[astClassHasDOTvalue], astClassHasDOTvalue]:
|
|
58
65
|
def workhorse(node: astClassHasDOTvalue) -> astClassHasDOTvalue:
|
|
59
66
|
node.value = action(node.value)
|
|
60
67
|
return node
|
|
@@ -73,14 +80,14 @@ class Then:
|
|
|
73
80
|
pattern-matching-and-action workflow for AST manipulation.
|
|
74
81
|
"""
|
|
75
82
|
@staticmethod
|
|
76
|
-
def appendTo(listOfAny: list[Any]) -> Callable[[ast.AST | ast_Identifier],
|
|
77
|
-
def workhorse(node: ast.AST | ast_Identifier) ->
|
|
83
|
+
def appendTo(listOfAny: list[Any]) -> Callable[[ast.AST | ast_Identifier], ast.AST | ast_Identifier]:
|
|
84
|
+
def workhorse(node: ast.AST | ast_Identifier) -> ast.AST | ast_Identifier:
|
|
78
85
|
listOfAny.append(node)
|
|
79
|
-
return
|
|
86
|
+
return node
|
|
80
87
|
return workhorse
|
|
81
88
|
|
|
82
89
|
@staticmethod
|
|
83
|
-
def extractIt(node:
|
|
90
|
+
def extractIt(node: NodeORattribute) -> NodeORattribute:
|
|
84
91
|
return node
|
|
85
92
|
|
|
86
93
|
@staticmethod
|
|
@@ -92,10 +99,11 @@ class Then:
|
|
|
92
99
|
return lambda belowMe: [belowMe, *list_astAST]
|
|
93
100
|
|
|
94
101
|
@staticmethod
|
|
95
|
-
def removeIt(
|
|
102
|
+
def removeIt(_removeMe: ast.AST) -> None:
|
|
103
|
+
return None
|
|
96
104
|
|
|
97
105
|
@staticmethod
|
|
98
|
-
def replaceWith(astAST:
|
|
106
|
+
def replaceWith(astAST: NodeORattribute) -> Callable[[NodeORattribute], NodeORattribute]:
|
|
99
107
|
return lambda _replaceMe: astAST
|
|
100
108
|
|
|
101
109
|
@staticmethod
|