mapFolding 0.2.4__py3-none-any.whl → 0.2.5__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/__init__.py +1 -1
- mapFolding/beDRY.py +47 -3
- mapFolding/importSelector.py +6 -11
- mapFolding/{JAX/lunnanJAX.py → reference/jax.py} +2 -0
- mapFolding/{inlineAfunction.py → someAssemblyRequired/inlineAfunction.py} +59 -31
- mapFolding/someAssemblyRequired/jobsAndTasks.py +47 -0
- mapFolding/someAssemblyRequired/makeNuitkaSource.py +99 -0
- mapFolding/someAssemblyRequired/makeNumbaJob.py +121 -0
- mapFolding/startHere.py +8 -17
- {mapFolding-0.2.4.dist-info → mapFolding-0.2.5.dist-info}/METADATA +8 -8
- {mapFolding-0.2.4.dist-info → mapFolding-0.2.5.dist-info}/RECORD +15 -17
- tests/test_other.py +28 -28
- mapFolding/JAX/taskJAX.py +0 -313
- mapFolding/countInitialize.py +0 -44
- mapFolding/countParallel.py +0 -49
- mapFolding/countSequential.py +0 -43
- tests/test_temporary.py +0 -25
- {mapFolding-0.2.4.dist-info → mapFolding-0.2.5.dist-info}/WHEEL +0 -0
- {mapFolding-0.2.4.dist-info → mapFolding-0.2.5.dist-info}/entry_points.txt +0 -0
- {mapFolding-0.2.4.dist-info → mapFolding-0.2.5.dist-info}/top_level.txt +0 -0
mapFolding/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from .theSSOT import *
|
|
2
2
|
from Z0Z_tools import defineConcurrencyLimit, intInnit, oopsieKwargsie
|
|
3
|
-
from .beDRY import getFilenameFoldsTotal, outfitCountFolds
|
|
3
|
+
from .beDRY import getFilenameFoldsTotal, getPathFilenameFoldsTotal, outfitCountFolds, saveFoldsTotal
|
|
4
4
|
from .startHere import countFolds
|
|
5
5
|
from .oeis import oeisIDfor_n, getOEISids, clearOEIScache
|
|
6
6
|
|
mapFolding/beDRY.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""A relatively stable API for oft-needed functionality."""
|
|
2
|
-
from mapFolding import dtypeDefault, dtypeLarge
|
|
2
|
+
from mapFolding import dtypeDefault, dtypeLarge, pathJobDEFAULT
|
|
3
3
|
from mapFolding import indexMy, indexThe, indexTrack, computationState
|
|
4
4
|
from mapFolding import intInnit, defineConcurrencyLimit, oopsieKwargsie
|
|
5
5
|
from numpy import integer
|
|
@@ -7,10 +7,12 @@ from numpy.typing import NDArray
|
|
|
7
7
|
from typing import Any, List, Optional, Sequence, Type, Union
|
|
8
8
|
import numba
|
|
9
9
|
import numpy
|
|
10
|
+
import os
|
|
11
|
+
import pathlib
|
|
10
12
|
import sys
|
|
11
13
|
|
|
12
14
|
def getFilenameFoldsTotal(listDimensions: Sequence[int]) -> str:
|
|
13
|
-
return str(sorted(listDimensions)).replace(' ', '') + '.foldsTotal'
|
|
15
|
+
return str(sorted(listDimensions)).replace(', ', 'x') + '.foldsTotal'
|
|
14
16
|
|
|
15
17
|
def getLeavesTotal(listDimensions: Sequence[int]) -> int:
|
|
16
18
|
"""
|
|
@@ -36,6 +38,14 @@ def getLeavesTotal(listDimensions: Sequence[int]) -> int:
|
|
|
36
38
|
|
|
37
39
|
return productDimensions
|
|
38
40
|
|
|
41
|
+
def getPathFilenameFoldsTotal(listDimensions: Sequence[int], pathishWriteFoldsTotal: Optional[Union[str, os.PathLike[str]]] = None) -> pathlib.Path:
|
|
42
|
+
pathFilenameFoldsTotal = pathlib.Path(pathishWriteFoldsTotal) if pathishWriteFoldsTotal is not None else pathJobDEFAULT
|
|
43
|
+
if pathFilenameFoldsTotal.is_dir():
|
|
44
|
+
filenameFoldsTotalDEFAULT = getFilenameFoldsTotal(listDimensions)
|
|
45
|
+
pathFilenameFoldsTotal = pathFilenameFoldsTotal / filenameFoldsTotalDEFAULT
|
|
46
|
+
pathFilenameFoldsTotal.parent.mkdir(parents=True, exist_ok=True)
|
|
47
|
+
return pathFilenameFoldsTotal
|
|
48
|
+
|
|
39
49
|
def getTaskDivisions(computationDivisions: Optional[Union[int, str]], concurrencyLimit: int, CPUlimit: Optional[Union[bool, float, int]], listDimensions: Sequence[int]):
|
|
40
50
|
"""
|
|
41
51
|
Determines whether or how to divide the computation into tasks.
|
|
@@ -148,7 +158,7 @@ def makeDataContainer(shape, datatype: Optional[Type] = None):
|
|
|
148
158
|
datatype = dtypeDefault
|
|
149
159
|
return numpy.zeros(shape, dtype=datatype)
|
|
150
160
|
|
|
151
|
-
def outfitCountFolds(listDimensions: Sequence[int], computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[bool, float, int]] = None, **keywordArguments: Optional[Type]) -> computationState:
|
|
161
|
+
def outfitCountFolds(listDimensions: Sequence[int], computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[bool, float, int]] = None, **keywordArguments: Optional[Type[Any]]) -> computationState:
|
|
152
162
|
"""
|
|
153
163
|
Initializes and configures the computation state for map folding computations.
|
|
154
164
|
|
|
@@ -232,6 +242,40 @@ def parseDimensions(dimensions: Sequence[int], parameterName: str = 'unnamed par
|
|
|
232
242
|
|
|
233
243
|
return listNonNegative
|
|
234
244
|
|
|
245
|
+
import tempfile
|
|
246
|
+
import shutil
|
|
247
|
+
import logging
|
|
248
|
+
import os
|
|
249
|
+
def saveFoldsTotal(pathFilename: Union[str, os.PathLike[str]], foldsTotal: int) -> None:
|
|
250
|
+
"""
|
|
251
|
+
Save foldsTotal with multiple fallback mechanisms.
|
|
252
|
+
|
|
253
|
+
Parameters:
|
|
254
|
+
pathFilename: Target save location
|
|
255
|
+
foldsTotal: Critical computed value to save
|
|
256
|
+
"""
|
|
257
|
+
"""Thoughts
|
|
258
|
+
Everything in a try block
|
|
259
|
+
Save it multiple times with multiple packages
|
|
260
|
+
no need for context managers, especially because they can cause errors"""
|
|
261
|
+
try:
|
|
262
|
+
pathFilenameFoldsTotal = pathlib.Path(pathFilename)
|
|
263
|
+
pathFilenameFoldsTotal.parent.mkdir(parents=True, exist_ok=True)
|
|
264
|
+
pathFilenameFoldsTotal.write_text(str(foldsTotal))
|
|
265
|
+
except Exception as ERRORmessage:
|
|
266
|
+
try:
|
|
267
|
+
print(f"\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n\n{foldsTotal=}\n\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n")
|
|
268
|
+
print(ERRORmessage)
|
|
269
|
+
print(f"\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n\n{foldsTotal=}\n\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n")
|
|
270
|
+
randomnessPlanB = (int(str(foldsTotal).strip()[-1]) + 1) * ['YO_']
|
|
271
|
+
filenameInfixUnique = ''.join(randomnessPlanB)
|
|
272
|
+
import os
|
|
273
|
+
pathFilenamePlanB = os.path.join(os.getcwd(), 'foldsTotal' + filenameInfixUnique + '.txt')
|
|
274
|
+
open(pathFilenamePlanB, 'w').write(str(foldsTotal))
|
|
275
|
+
print(str(pathFilenamePlanB))
|
|
276
|
+
except:
|
|
277
|
+
print(foldsTotal)
|
|
278
|
+
|
|
235
279
|
def setCPUlimit(CPUlimit: Union[bool, float, int, None]) -> int:
|
|
236
280
|
"""Sets CPU limit for Numba concurrent operations. Note that it can only affect Numba-jitted functions that have not yet been imported.
|
|
237
281
|
|
mapFolding/importSelector.py
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
from mapFolding.lovelace import countSequential
|
|
2
|
+
from mapFolding.lovelace import countParallel
|
|
3
|
+
from mapFolding.lovelace import countInitialize
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
from mapFolding.lovelace import countInitialize
|
|
8
|
-
|
|
9
|
-
else:
|
|
10
|
-
from mapFolding.countSequential import countSequential
|
|
11
|
-
from mapFolding.countParallel import countParallel
|
|
12
|
-
from mapFolding.countInitialize import countInitialize
|
|
5
|
+
# from mapFolding.countSequential import countSequential
|
|
6
|
+
# from mapFolding.countParallel import countParallel
|
|
7
|
+
# from mapFolding.countInitialize import countInitialize
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""I was able to implement the algorithm with JAX, but I didn't see an advantage and it's a pain in the ass.
|
|
2
|
+
I don't maintain this module."""
|
|
1
3
|
from mapFolding import validateListDimensions, getLeavesTotal, makeConnectionGraph
|
|
2
4
|
from typing import List, Tuple
|
|
3
5
|
import jax
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
from mapFolding import indexMy, indexThe, indexTrack
|
|
2
2
|
import ast
|
|
3
|
+
import copy
|
|
3
4
|
import pathlib
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
for
|
|
8
|
-
|
|
6
|
+
def getDictionaryEnumValues():
|
|
7
|
+
dictionaryEnumValues = {}
|
|
8
|
+
for enumIndex in [indexMy, indexThe, indexTrack]:
|
|
9
|
+
for memberName, memberValue in enumIndex._member_map_.items():
|
|
10
|
+
dictionaryEnumValues[f"{enumIndex.__name__}.{memberName}.value"] = memberValue.value
|
|
11
|
+
return dictionaryEnumValues
|
|
9
12
|
|
|
10
|
-
class
|
|
13
|
+
class RecursiveInlinerWithEnum(ast.NodeTransformer):
|
|
11
14
|
def __init__(self, dictionaryFunctions, dictionaryEnumValues):
|
|
12
15
|
self.dictionaryFunctions = dictionaryFunctions
|
|
13
16
|
self.dictionaryEnumValues = dictionaryEnumValues
|
|
14
17
|
self.processed = set() # Track processed functions to avoid infinite recursion
|
|
15
18
|
|
|
16
|
-
def
|
|
19
|
+
def inlineFunctionBody(self, functionName):
|
|
17
20
|
if functionName in self.processed:
|
|
18
21
|
return None
|
|
19
22
|
|
|
@@ -35,7 +38,7 @@ class RecursiveInliner(ast.NodeTransformer):
|
|
|
35
38
|
def visit_Call(self, node):
|
|
36
39
|
callNode = self.generic_visit(node)
|
|
37
40
|
if isinstance(callNode, ast.Call) and isinstance(callNode.func, ast.Name) and callNode.func.id in self.dictionaryFunctions:
|
|
38
|
-
inlineDefinition = self.
|
|
41
|
+
inlineDefinition = self.inlineFunctionBody(callNode.func.id)
|
|
39
42
|
if inlineDefinition and inlineDefinition.body:
|
|
40
43
|
lastStmt = inlineDefinition.body[-1]
|
|
41
44
|
if isinstance(lastStmt, ast.Return) and lastStmt.value is not None:
|
|
@@ -48,23 +51,23 @@ class RecursiveInliner(ast.NodeTransformer):
|
|
|
48
51
|
def visit_Expr(self, node):
|
|
49
52
|
if isinstance(node.value, ast.Call):
|
|
50
53
|
if isinstance(node.value.func, ast.Name) and node.value.func.id in self.dictionaryFunctions:
|
|
51
|
-
inlineDefinition = self.
|
|
54
|
+
inlineDefinition = self.inlineFunctionBody(node.value.func.id)
|
|
52
55
|
if inlineDefinition:
|
|
53
56
|
return [self.visit(stmt) for stmt in inlineDefinition.body]
|
|
54
57
|
return self.generic_visit(node)
|
|
55
58
|
|
|
56
|
-
def
|
|
57
|
-
"""Find all modules that need to be imported based on AST analysis.
|
|
59
|
+
def findRequiredImports(node):
|
|
60
|
+
"""Find all modules that need to be imported based on AST analysis.
|
|
61
|
+
NOTE: due to hardcoding, this is a glorified regex. No, wait, this is less versatile than regex."""
|
|
58
62
|
requiredImports = set()
|
|
59
63
|
|
|
60
64
|
class ImportFinder(ast.NodeVisitor):
|
|
61
65
|
def visit_Name(self, node):
|
|
62
|
-
# Common modules we might need
|
|
63
66
|
if node.id in {'numba'}:
|
|
64
67
|
requiredImports.add(node.id)
|
|
65
68
|
self.generic_visit(node)
|
|
66
69
|
|
|
67
|
-
def
|
|
70
|
+
def visitDecorator(self, node):
|
|
68
71
|
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
|
|
69
72
|
if node.func.id == 'jit':
|
|
70
73
|
requiredImports.add('numba')
|
|
@@ -73,7 +76,7 @@ def find_required_imports(node):
|
|
|
73
76
|
ImportFinder().visit(node)
|
|
74
77
|
return requiredImports
|
|
75
78
|
|
|
76
|
-
def
|
|
79
|
+
def generateImports(requiredImports):
|
|
77
80
|
"""Generate import statements based on required modules."""
|
|
78
81
|
importStatements = []
|
|
79
82
|
|
|
@@ -88,7 +91,7 @@ def generate_imports(requiredImports):
|
|
|
88
91
|
|
|
89
92
|
return '\n'.join(importStatements)
|
|
90
93
|
|
|
91
|
-
def
|
|
94
|
+
def inlineFunctions(sourceCode, targetFunctionName, dictionaryEnumValues):
|
|
92
95
|
dictionaryParsed = ast.parse(sourceCode)
|
|
93
96
|
dictionaryFunctions = {
|
|
94
97
|
element.name: element
|
|
@@ -96,29 +99,54 @@ def inline_functions(sourceCode, targetFunctionName, dictionaryEnumValues):
|
|
|
96
99
|
if isinstance(element, ast.FunctionDef)
|
|
97
100
|
}
|
|
98
101
|
nodeTarget = dictionaryFunctions[targetFunctionName]
|
|
99
|
-
nodeInliner =
|
|
102
|
+
nodeInliner = RecursiveInlinerWithEnum(dictionaryFunctions, dictionaryEnumValues)
|
|
100
103
|
nodeInlined = nodeInliner.visit(nodeTarget)
|
|
101
104
|
ast.fix_missing_locations(nodeInlined)
|
|
102
105
|
|
|
103
106
|
# Generate imports
|
|
104
|
-
requiredImports =
|
|
105
|
-
importStatements =
|
|
107
|
+
requiredImports = findRequiredImports(nodeInlined)
|
|
108
|
+
importStatements = generateImports(requiredImports)
|
|
106
109
|
|
|
107
110
|
# Combine imports with inlined code
|
|
108
111
|
inlinedCode = importStatements + '\n\n' + ast.unparse(ast.Module(body=[nodeInlined], type_ignores=[]))
|
|
109
112
|
return inlinedCode
|
|
110
113
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
114
|
+
def Z0Z_inlineMapFolding():
|
|
115
|
+
dictionaryEnumValues = getDictionaryEnumValues()
|
|
116
|
+
|
|
117
|
+
pathFilenameSource = pathlib.Path("/apps/mapFolding/mapFolding/lovelace.py")
|
|
118
|
+
codeSource = pathFilenameSource.read_text()
|
|
119
|
+
|
|
120
|
+
listCallables = [
|
|
121
|
+
'countInitialize',
|
|
122
|
+
'countParallel',
|
|
123
|
+
'countSequential',
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
listPathFilenamesDestination: list[pathlib.Path] = []
|
|
127
|
+
for callableTarget in listCallables:
|
|
128
|
+
pathFilenameDestination = pathFilenameSource.with_stem(callableTarget)
|
|
129
|
+
codeInlined = inlineFunctions(codeSource, callableTarget, dictionaryEnumValues)
|
|
130
|
+
pathFilenameDestination.write_text(codeInlined)
|
|
131
|
+
listPathFilenamesDestination.append(pathFilenameDestination)
|
|
132
|
+
|
|
133
|
+
listNoNumba = [
|
|
134
|
+
'countInitialize',
|
|
135
|
+
'countSequential',
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
listPathFilenamesNoNumba = []
|
|
139
|
+
for pathFilename in listPathFilenamesDestination:
|
|
140
|
+
if pathFilename.stem in listNoNumba:
|
|
141
|
+
pathFilenameNoNumba = pathFilename.with_name(pathFilename.stem + 'NoNumba' + pathFilename.suffix)
|
|
142
|
+
else:
|
|
143
|
+
continue
|
|
144
|
+
codeNoNumba = pathFilename.read_text()
|
|
145
|
+
for codeLine in copy.copy(codeNoNumba.splitlines()):
|
|
146
|
+
if 'numba' in codeLine:
|
|
147
|
+
codeNoNumba = codeNoNumba.replace(codeLine, '')
|
|
148
|
+
pathFilenameNoNumba.write_text(codeNoNumba)
|
|
149
|
+
listPathFilenamesNoNumba.append(pathFilenameNoNumba)
|
|
150
|
+
|
|
151
|
+
if __name__ == '__main__':
|
|
152
|
+
Z0Z_inlineMapFolding()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import Any, Optional, Sequence, Type, Union
|
|
2
|
+
|
|
3
|
+
def Z0Z_makeJob(listDimensions: Sequence[int], **keywordArguments: Optional[Type[Any]]):
|
|
4
|
+
from mapFolding import outfitCountFolds
|
|
5
|
+
stateUniversal = outfitCountFolds(listDimensions, computationDivisions=None, CPUlimit=None, **keywordArguments)
|
|
6
|
+
from mapFolding.countInitialize import countInitialize
|
|
7
|
+
countInitialize(stateUniversal['connectionGraph'], stateUniversal['gapsWhere'], stateUniversal['my'], stateUniversal['the'], stateUniversal['track'])
|
|
8
|
+
from mapFolding import getPathFilenameFoldsTotal
|
|
9
|
+
pathFilenameChopChop = getPathFilenameFoldsTotal(stateUniversal['mapShape'])
|
|
10
|
+
import pathlib
|
|
11
|
+
suffix = pathFilenameChopChop.suffix
|
|
12
|
+
pathJob = pathlib.Path(str(pathFilenameChopChop)[0:-len(suffix)])
|
|
13
|
+
pathJob.mkdir(parents=True, exist_ok=True)
|
|
14
|
+
pathFilenameJob = pathJob / 'stateJob.pkl'
|
|
15
|
+
|
|
16
|
+
pathFilenameFoldsTotal = getPathFilenameFoldsTotal(stateUniversal['mapShape'], pathFilenameJob.parent)
|
|
17
|
+
stateJob = {**stateUniversal, 'pathFilenameFoldsTotal': pathFilenameFoldsTotal}
|
|
18
|
+
|
|
19
|
+
del stateJob['mapShape']
|
|
20
|
+
|
|
21
|
+
import pickle
|
|
22
|
+
pathFilenameJob.write_bytes(pickle.dumps(stateJob))
|
|
23
|
+
return pathFilenameJob
|
|
24
|
+
|
|
25
|
+
def runJob(pathFilename):
|
|
26
|
+
from typing import Final
|
|
27
|
+
import numpy
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
pathFilenameJob = Path(pathFilename)
|
|
30
|
+
from pickle import loads
|
|
31
|
+
stateJob = loads(pathFilenameJob.read_bytes())
|
|
32
|
+
|
|
33
|
+
connectionGraph: numpy.ndarray = stateJob['connectionGraph']
|
|
34
|
+
foldsSubTotals: numpy.ndarray = stateJob['foldsSubTotals']
|
|
35
|
+
gapsWhere: numpy.ndarray = stateJob['gapsWhere']
|
|
36
|
+
my: numpy.ndarray = stateJob['my']
|
|
37
|
+
pathFilenameFoldsTotal: Final[Path] = stateJob['pathFilenameFoldsTotal']
|
|
38
|
+
the: Final[numpy.ndarray] = stateJob['the']
|
|
39
|
+
track: numpy.ndarray = stateJob['track']
|
|
40
|
+
|
|
41
|
+
from mapFolding.countSequentialNoNumba import countSequential
|
|
42
|
+
countSequential(connectionGraph, foldsSubTotals, gapsWhere, my, the, track)
|
|
43
|
+
|
|
44
|
+
print(foldsSubTotals.sum().item())
|
|
45
|
+
Path(pathFilenameFoldsTotal).parent.mkdir(parents=True, exist_ok=True)
|
|
46
|
+
Path(pathFilenameFoldsTotal).write_text(str(foldsSubTotals.sum().item()))
|
|
47
|
+
print(pathFilenameFoldsTotal)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""NOTE make a special venv for nuitka, then run nuitka from that venv"""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from pickle import loads
|
|
4
|
+
from typing import Final
|
|
5
|
+
import numpy
|
|
6
|
+
from mapFolding.someAssemblyRequired.jobsAndTasks import Z0Z_makeJob
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
Section: configure every time"""
|
|
10
|
+
|
|
11
|
+
# TODO configure this
|
|
12
|
+
mapShape = [3]*3
|
|
13
|
+
# NOTE ^^^^^^ pay attention
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
Section: settings"""
|
|
17
|
+
|
|
18
|
+
pathFilenameData = Z0Z_makeJob(mapShape)
|
|
19
|
+
|
|
20
|
+
pathJob = pathFilenameData.parent
|
|
21
|
+
|
|
22
|
+
pathFilenameAlgorithm = Path('/apps/mapFolding/mapFolding/countSequentialNoNumba.py')
|
|
23
|
+
pathFilenameDestination = Path(f"/apps/mapFolding/nn/{pathJob.name}.py")
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
Section: did you handle and include this stuff?"""
|
|
27
|
+
|
|
28
|
+
lineImportNumPy = "import numpy"
|
|
29
|
+
linePrintFoldsTotal = "print(foldsSubTotals.sum().item())"
|
|
30
|
+
linesAlgorithm = """"""
|
|
31
|
+
linesData = """"""
|
|
32
|
+
settingsNuitkaProject=f"""
|
|
33
|
+
# nuitka-project: --mode=onefile
|
|
34
|
+
# nuitka-project: --onefile-no-compression
|
|
35
|
+
# nuitka-project: --lto=yes
|
|
36
|
+
# nuitka-project: --clang
|
|
37
|
+
# nuitka-project: --output-dir={pathJob}
|
|
38
|
+
# nuitka-project: --output-filename={pathJob.name}.exe
|
|
39
|
+
"""
|
|
40
|
+
# nuitka-project:
|
|
41
|
+
"""
|
|
42
|
+
Section: do the work"""
|
|
43
|
+
|
|
44
|
+
WTFamIdoing = pathFilenameAlgorithm.read_text()
|
|
45
|
+
for lineSource in WTFamIdoing.splitlines():
|
|
46
|
+
ImaIndent = ' '
|
|
47
|
+
if lineSource.startswith(ImaIndent):
|
|
48
|
+
lineSource = lineSource[len(ImaIndent):None]
|
|
49
|
+
elif lineSource.startswith('#'):
|
|
50
|
+
continue
|
|
51
|
+
elif not lineSource:
|
|
52
|
+
continue
|
|
53
|
+
elif lineSource.startswith('def '):
|
|
54
|
+
continue
|
|
55
|
+
else:
|
|
56
|
+
raise NotImplementedError("You didn't anticipate this.")
|
|
57
|
+
linesAlgorithm = "\n".join([linesAlgorithm
|
|
58
|
+
, lineSource
|
|
59
|
+
])
|
|
60
|
+
|
|
61
|
+
stateJob = loads(pathFilenameData.read_bytes())
|
|
62
|
+
connectionGraph: Final[numpy.ndarray] = stateJob['connectionGraph']
|
|
63
|
+
foldsSubTotals: numpy.ndarray = stateJob['foldsSubTotals']
|
|
64
|
+
gapsWhere: numpy.ndarray = stateJob['gapsWhere']
|
|
65
|
+
my: numpy.ndarray = stateJob['my']
|
|
66
|
+
the: numpy.ndarray = stateJob['the']
|
|
67
|
+
track: numpy.ndarray = stateJob['track']
|
|
68
|
+
|
|
69
|
+
pathFilenameFoldsTotal = stateJob['pathFilenameFoldsTotal']
|
|
70
|
+
lineDataPathFilenameFoldsTotal = "pathFilenameFoldsTotal = r'" + str(pathFilenameFoldsTotal) + "'\n"
|
|
71
|
+
|
|
72
|
+
def archivistFormatsArrayToCode(arrayTarget: numpy.ndarray, identifierName: str) -> str:
|
|
73
|
+
"""Format numpy array into a code string that recreates the array."""
|
|
74
|
+
arrayAsTypeStr = numpy.array2string(
|
|
75
|
+
arrayTarget,
|
|
76
|
+
threshold=10000,
|
|
77
|
+
max_line_width=100,
|
|
78
|
+
separator=','
|
|
79
|
+
)
|
|
80
|
+
return f"{identifierName} = numpy.array({arrayAsTypeStr}, dtype=numpy.{arrayTarget.dtype})\n"
|
|
81
|
+
|
|
82
|
+
linesData = "\n".join([linesData
|
|
83
|
+
, lineDataPathFilenameFoldsTotal
|
|
84
|
+
, archivistFormatsArrayToCode(the, 'the')
|
|
85
|
+
, archivistFormatsArrayToCode(my, 'my')
|
|
86
|
+
, archivistFormatsArrayToCode(foldsSubTotals, 'foldsSubTotals')
|
|
87
|
+
, archivistFormatsArrayToCode(gapsWhere, 'gapsWhere')
|
|
88
|
+
, archivistFormatsArrayToCode(connectionGraph, 'connectionGraph')
|
|
89
|
+
, archivistFormatsArrayToCode(track, 'track')
|
|
90
|
+
])
|
|
91
|
+
|
|
92
|
+
linesAll = "\n".join([settingsNuitkaProject
|
|
93
|
+
, lineImportNumPy
|
|
94
|
+
, linesData
|
|
95
|
+
, linesAlgorithm
|
|
96
|
+
, linePrintFoldsTotal
|
|
97
|
+
])
|
|
98
|
+
|
|
99
|
+
pathFilenameDestination.write_text(linesAll)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Create a python module hardcoded to compute a map's foldsTotal.
|
|
2
|
+
NumPy ndarray.
|
|
3
|
+
Numba optimized.
|
|
4
|
+
Absolutely no other imports.
|
|
5
|
+
"""
|
|
6
|
+
from mapFolding import datatypeLarge, dtypeLarge, dtypeDefault
|
|
7
|
+
from mapFolding.someAssemblyRequired.inlineAfunction import Z0Z_inlineMapFolding
|
|
8
|
+
from mapFolding.someAssemblyRequired.jobsAndTasks import Z0Z_makeJob
|
|
9
|
+
import importlib
|
|
10
|
+
import llvmlite.binding
|
|
11
|
+
import numpy
|
|
12
|
+
import pathlib
|
|
13
|
+
import pickle
|
|
14
|
+
|
|
15
|
+
listDimensions = [3,7]
|
|
16
|
+
|
|
17
|
+
# NOTE this overwrites files
|
|
18
|
+
Z0Z_inlineMapFolding()
|
|
19
|
+
|
|
20
|
+
identifierCallableLaunch = "goGoGadgetAbsurdity"
|
|
21
|
+
|
|
22
|
+
def archivistFormatsArrayToCode(arrayTarget: numpy.ndarray, identifierName: str) -> str:
|
|
23
|
+
"""Format numpy array into a code string that recreates the array."""
|
|
24
|
+
arrayAsTypeStr = numpy.array2string(arrayTarget, threshold=10000, max_line_width=200, separator=',')
|
|
25
|
+
return f"{identifierName} = numpy.array({arrayAsTypeStr}, dtype=numpy.{arrayTarget.dtype})"
|
|
26
|
+
|
|
27
|
+
def writeModuleWithNumba(listDimensions):
|
|
28
|
+
numpy_dtypeLarge = dtypeLarge
|
|
29
|
+
numpy_dtypeDefault = dtypeDefault
|
|
30
|
+
|
|
31
|
+
parametersNumba = f"numba.types.{datatypeLarge}(), cache=True, parallel=False, boundscheck=False, \
|
|
32
|
+
error_model='numpy', fastmath=True, nogil=True, nopython=True, _nrt=True, forceinline=True, \
|
|
33
|
+
inline=True, looplift=True, no_cfunc_wrapper=False, no_cpython_wrapper=False"
|
|
34
|
+
|
|
35
|
+
pathFilenameData = Z0Z_makeJob(listDimensions, datatypeDefault=numpy_dtypeDefault, datatypeLarge=numpy_dtypeLarge)
|
|
36
|
+
|
|
37
|
+
pathFilenameAlgorithm = pathlib.Path('/apps/mapFolding/mapFolding/countSequentialNoNumba.py')
|
|
38
|
+
pathFilenameDestination = pathFilenameData.with_stem(pathFilenameData.parent.name).with_suffix(".py")
|
|
39
|
+
|
|
40
|
+
lineNumba = f"@numba.jit({parametersNumba})"
|
|
41
|
+
|
|
42
|
+
linesImport = "\n".join([
|
|
43
|
+
"import numpy"
|
|
44
|
+
, "import numba"
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
stateJob = pickle.loads(pathFilenameData.read_bytes())
|
|
48
|
+
|
|
49
|
+
ImaIndent = ' '
|
|
50
|
+
linesDataDynamic = """"""
|
|
51
|
+
linesDataDynamic = "\n".join([linesDataDynamic
|
|
52
|
+
, ImaIndent + archivistFormatsArrayToCode(stateJob['my'], 'my')
|
|
53
|
+
, ImaIndent + archivistFormatsArrayToCode(stateJob['foldsSubTotals'], 'foldsSubTotals')
|
|
54
|
+
, ImaIndent + archivistFormatsArrayToCode(stateJob['gapsWhere'], 'gapsWhere')
|
|
55
|
+
, ImaIndent + archivistFormatsArrayToCode(stateJob['track'], 'track')
|
|
56
|
+
])
|
|
57
|
+
|
|
58
|
+
linesDataStatic = """"""
|
|
59
|
+
linesDataStatic = "\n".join([linesDataStatic
|
|
60
|
+
, ImaIndent + archivistFormatsArrayToCode(stateJob['the'], 'the')
|
|
61
|
+
, ImaIndent + archivistFormatsArrayToCode(stateJob['connectionGraph'], 'connectionGraph')
|
|
62
|
+
])
|
|
63
|
+
|
|
64
|
+
pathFilenameFoldsTotal: pathlib.Path = stateJob['pathFilenameFoldsTotal']
|
|
65
|
+
|
|
66
|
+
linesAlgorithm = """"""
|
|
67
|
+
for lineSource in pathFilenameAlgorithm.read_text().splitlines():
|
|
68
|
+
if lineSource.startswith('#'):
|
|
69
|
+
continue
|
|
70
|
+
elif not lineSource:
|
|
71
|
+
continue
|
|
72
|
+
elif lineSource.startswith('def '):
|
|
73
|
+
lineSource = "\n".join([lineNumba
|
|
74
|
+
, f"def {identifierCallableLaunch}():"
|
|
75
|
+
, linesDataDynamic
|
|
76
|
+
, linesDataStatic
|
|
77
|
+
])
|
|
78
|
+
linesAlgorithm = "\n".join([linesAlgorithm
|
|
79
|
+
, lineSource
|
|
80
|
+
])
|
|
81
|
+
|
|
82
|
+
lineReturn = f"{ImaIndent}return foldsSubTotals.sum().item()"
|
|
83
|
+
|
|
84
|
+
linesLaunch = """"""
|
|
85
|
+
linesLaunch = linesLaunch + f"""
|
|
86
|
+
if __name__ == '__main__':
|
|
87
|
+
foldsTotal = {identifierCallableLaunch}()"""
|
|
88
|
+
|
|
89
|
+
linesWriteFoldsTotal = """"""
|
|
90
|
+
linesWriteFoldsTotal = "\n".join([linesWriteFoldsTotal
|
|
91
|
+
, " print(foldsTotal)"
|
|
92
|
+
, f" open('{pathFilenameFoldsTotal.as_posix()}', 'w').write(str(foldsTotal))"
|
|
93
|
+
])
|
|
94
|
+
|
|
95
|
+
linesAll = "\n".join([
|
|
96
|
+
linesImport
|
|
97
|
+
, linesAlgorithm
|
|
98
|
+
, f"{ImaIndent}print(foldsSubTotals.sum().item())"
|
|
99
|
+
, lineReturn
|
|
100
|
+
, linesLaunch
|
|
101
|
+
, linesWriteFoldsTotal
|
|
102
|
+
])
|
|
103
|
+
|
|
104
|
+
pathFilenameDestination.write_text(linesAll)
|
|
105
|
+
|
|
106
|
+
return pathFilenameDestination
|
|
107
|
+
|
|
108
|
+
def writeModuleLLVM(pathFilenamePythonFile: pathlib.Path) -> pathlib.Path:
|
|
109
|
+
pathRootPackage = pathlib.Path('c:/apps/mapFolding')
|
|
110
|
+
relativePathModule = pathFilenamePythonFile.relative_to(pathRootPackage)
|
|
111
|
+
moduleTarget = '.'.join(relativePathModule.parts)[0:-len(relativePathModule.suffix)]
|
|
112
|
+
moduleTargetImported = importlib.import_module(moduleTarget)
|
|
113
|
+
linesLLVM = moduleTargetImported.__dict__[identifierCallableLaunch].inspect_llvm()[()]
|
|
114
|
+
moduleLLVM = llvmlite.binding.module.parse_assembly(linesLLVM)
|
|
115
|
+
pathFilenameLLVM = pathFilenamePythonFile.with_suffix(".ll")
|
|
116
|
+
pathFilenameLLVM.write_text(str(moduleLLVM))
|
|
117
|
+
return pathFilenameLLVM
|
|
118
|
+
|
|
119
|
+
if __name__ == '__main__':
|
|
120
|
+
pathFilenamePythonFile = writeModuleWithNumba(listDimensions)
|
|
121
|
+
pathFilenameLLVM = writeModuleLLVM(pathFilenamePythonFile)
|
mapFolding/startHere.py
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
from mapFolding import outfitCountFolds,
|
|
2
|
-
from typing import Optional, Sequence, Type, Union
|
|
1
|
+
from mapFolding import outfitCountFolds, getPathFilenameFoldsTotal, saveFoldsTotal
|
|
2
|
+
from typing import Any, Optional, Sequence, Type, Union
|
|
3
3
|
import os
|
|
4
|
-
import pathlib
|
|
5
4
|
|
|
6
|
-
def countFolds(listDimensions: Sequence[int],
|
|
5
|
+
def countFolds(listDimensions: Sequence[int], pathishWriteFoldsTotal: Optional[Union[str, os.PathLike[str]]] = None, computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[int, float, bool]] = None, **keywordArguments: Optional[Type[Any]]) -> int:
|
|
7
6
|
"""Count the total number of possible foldings for a given map dimensions.
|
|
8
7
|
|
|
9
8
|
Parameters:
|
|
10
9
|
listDimensions: List of integers representing the dimensions of the map to be folded.
|
|
11
|
-
|
|
12
|
-
If a directory is provided, creates a file with default name based on map dimensions.
|
|
10
|
+
pathishWriteFoldsTotal (None): Path, filename, or pathFilename to write the total fold count to.
|
|
11
|
+
If a directory is provided, creates a file with a default name based on map dimensions.
|
|
13
12
|
computationDivisions (None):
|
|
14
13
|
Whether and how to divide the computational work. See notes for details.
|
|
15
14
|
CPUlimit (None): This is only relevant if there are `computationDivisions`: whether and how to limit the CPU usage. See notes for details.
|
|
@@ -37,12 +36,8 @@ def countFolds(listDimensions: Sequence[int], writeFoldsTotal: Optional[Union[st
|
|
|
37
36
|
stateUniversal = outfitCountFolds(listDimensions, computationDivisions=computationDivisions, CPUlimit=CPUlimit, **keywordArguments)
|
|
38
37
|
|
|
39
38
|
pathFilenameFoldsTotal = None
|
|
40
|
-
if
|
|
41
|
-
pathFilenameFoldsTotal =
|
|
42
|
-
if pathFilenameFoldsTotal.is_dir():
|
|
43
|
-
filenameFoldsTotalDEFAULT = getFilenameFoldsTotal(stateUniversal['mapShape'])
|
|
44
|
-
pathFilenameFoldsTotal = pathFilenameFoldsTotal / filenameFoldsTotalDEFAULT
|
|
45
|
-
pathFilenameFoldsTotal.parent.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
if pathishWriteFoldsTotal is not None:
|
|
40
|
+
pathFilenameFoldsTotal = getPathFilenameFoldsTotal(stateUniversal['mapShape'], pathishWriteFoldsTotal)
|
|
46
41
|
|
|
47
42
|
from mapFolding.babbage import _countFolds
|
|
48
43
|
_countFolds(**stateUniversal)
|
|
@@ -50,10 +45,6 @@ def countFolds(listDimensions: Sequence[int], writeFoldsTotal: Optional[Union[st
|
|
|
50
45
|
foldsTotal = stateUniversal['foldsSubTotals'].sum().item()
|
|
51
46
|
|
|
52
47
|
if pathFilenameFoldsTotal is not None:
|
|
53
|
-
|
|
54
|
-
pathFilenameFoldsTotal.write_text(str(foldsTotal))
|
|
55
|
-
except Exception as ERRORmessage:
|
|
56
|
-
print(ERRORmessage)
|
|
57
|
-
print(f"\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n\n{foldsTotal=}\n\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal")
|
|
48
|
+
saveFoldsTotal(pathFilenameFoldsTotal, foldsTotal)
|
|
58
49
|
|
|
59
50
|
return foldsTotal
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: mapFolding
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.2.5
|
|
4
|
+
Summary: Count distinct ways to fold a map (or a strip of stamps)
|
|
5
5
|
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
6
|
Project-URL: homepage, https://github.com/hunterhogan/mapFolding
|
|
7
7
|
Requires-Python: <3.13,>=3.10
|
|
@@ -14,16 +14,11 @@ Requires-Dist: pandas; extra == "benchmark"
|
|
|
14
14
|
Requires-Dist: jupyter; extra == "benchmark"
|
|
15
15
|
Requires-Dist: ipywidgets; extra == "benchmark"
|
|
16
16
|
Requires-Dist: tqdm; extra == "benchmark"
|
|
17
|
-
Provides-Extra: jax
|
|
18
|
-
Requires-Dist: jax; extra == "jax"
|
|
19
|
-
Requires-Dist: jaxtyping; extra == "jax"
|
|
20
17
|
Provides-Extra: testing
|
|
21
18
|
Requires-Dist: pytest; extra == "testing"
|
|
22
19
|
Requires-Dist: pytest-cov; extra == "testing"
|
|
23
20
|
Requires-Dist: pytest-env; extra == "testing"
|
|
24
21
|
Requires-Dist: pytest-xdist; extra == "testing"
|
|
25
|
-
Requires-Dist: pytest-order; extra == "testing"
|
|
26
|
-
Requires-Dist: pytest-dependency; extra == "testing"
|
|
27
22
|
|
|
28
23
|
# Algorithm(s) for counting distinct ways to fold a map (or a strip of stamps)
|
|
29
24
|
|
|
@@ -41,7 +36,7 @@ The directory [mapFolding/reference](https://github.com/hunterhogan/mapFolding/b
|
|
|
41
36
|
- [hunterNumba.py](https://github.com/hunterhogan/mapFolding/blob/main/mapFolding/reference), a one-size-fits-all, self-contained, reasonably fast, contemporary algorithm that is nevertheless infected by _noobaceae ignorancium_, and
|
|
42
37
|
- miscellaneous notes.
|
|
43
38
|
|
|
44
|
-
[](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml) [](https://pypi.org/project/mapFolding/) [](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml) [](https://youtu.be/g6f_miE91mk&t=4)   
|
|
45
40
|
|
|
46
41
|
## Simple, easy usage based on OEIS IDs
|
|
47
42
|
|
|
@@ -133,3 +128,8 @@ In [`foldings.txt`](https://github.com/hunterhogan/mapFolding/blob/main/mapFoldi
|
|
|
133
128
|
```sh
|
|
134
129
|
pip install mapFolding
|
|
135
130
|
```
|
|
131
|
+
|
|
132
|
+
## My recovery
|
|
133
|
+
|
|
134
|
+
[](https://HunterThinks.com/support)
|
|
135
|
+
[](https://www.youtube.com/@HunterHogan)
|
|
@@ -1,35 +1,33 @@
|
|
|
1
|
-
mapFolding/__init__.py,sha256=
|
|
1
|
+
mapFolding/__init__.py,sha256=yZ_rcMMCco346M62nKzp90GPp9OV1UkkWSxKzP3ISPA,380
|
|
2
2
|
mapFolding/babbage.py,sha256=51fO7lwcTsTvSMwzKW1G2nGslGoEQt19IgnqZi8znao,2222
|
|
3
|
-
mapFolding/beDRY.py,sha256=
|
|
4
|
-
mapFolding/
|
|
5
|
-
mapFolding/countParallel.py,sha256=1sLGIlMj_xZ4bFkG1srOPcDUCrSKc1q3x2QN_8l_sgY,2451
|
|
6
|
-
mapFolding/countSequential.py,sha256=QSXwK3o8YBcxNrir_wGMXgqp38hXYTJanYXFLxUPCPo,1993
|
|
7
|
-
mapFolding/importSelector.py,sha256=OY_LuUrLW5SFV6qM1tSgI2Rnfi5Bj3Fhdrkryo0WycE,392
|
|
8
|
-
mapFolding/inlineAfunction.py,sha256=KO2snTNSGX-4urRtTOYqAZBCsBCaMfr5bo6rNZR9MPA,5102
|
|
3
|
+
mapFolding/beDRY.py,sha256=IhBnlo-Lg8DBaebTDAyJ7OiGUce9OFbNUNHJmlB04L0,15835
|
|
4
|
+
mapFolding/importSelector.py,sha256=sc9IGk8CpCNerFbuYnrroBH-itqsxjeBc4VYjiesOQo,310
|
|
9
5
|
mapFolding/lovelace.py,sha256=iu7anbA_TacIAjc4EKkeBVxIJKAMdrYgvR4evzMZ1WY,15193
|
|
10
6
|
mapFolding/oeis.py,sha256=_-fLGc1ybZ2eFxoiBrSmojMexeg6ROxtrLaBF2BzMn4,12144
|
|
11
|
-
mapFolding/startHere.py,sha256=
|
|
7
|
+
mapFolding/startHere.py,sha256=Bu4boZnxlx66IU7RIsBRq00JScE0DWqKLAclUMPGOSM,3892
|
|
12
8
|
mapFolding/theSSOT.py,sha256=3Zty4rYWOqrwivuCaKA71R0HM4rjmvtkL_Bsn4ZhwFo,2318
|
|
13
|
-
mapFolding/JAX/lunnanJAX.py,sha256=xMZloN47q-MVfjdYOM1hi9qR4OnLq7qALmGLMraevQs,14819
|
|
14
|
-
mapFolding/JAX/taskJAX.py,sha256=yJNeH0rL6EhJ6ppnATHF0Zf81CDMC10bnPnimVxE1hc,20037
|
|
15
9
|
mapFolding/benchmarks/benchmarking.py,sha256=HD_0NSvuabblg94ftDre6LFnXShTe8MYj3hIodW-zV0,3076
|
|
16
10
|
mapFolding/reference/flattened.py,sha256=X9nvRzg7YDcpCtSDTL4YiidjshlX9rg2e6JVCY6i2u0,16547
|
|
17
11
|
mapFolding/reference/hunterNumba.py,sha256=0giUyqAFzP-XKcq3Kz8wIWCK0BVFhjABVJ1s-w4Jhu0,7109
|
|
18
12
|
mapFolding/reference/irvineJavaPort.py,sha256=Sj-63Z-OsGuDoEBXuxyjRrNmmyl0d7Yz_XuY7I47Oyg,4250
|
|
13
|
+
mapFolding/reference/jax.py,sha256=bB34dGdi3VSz4cRFbmCPn_erAmQ3FyrSED8uJ7CsES0,14961
|
|
19
14
|
mapFolding/reference/lunnan.py,sha256=XEcql_gxvCCghb6Or3qwmPbn4IZUbZTaSmw_fUjRxZE,5037
|
|
20
15
|
mapFolding/reference/lunnanNumpy.py,sha256=HqDgSwTOZA-G0oophOEfc4zs25Mv4yw2aoF1v8miOLk,4653
|
|
21
16
|
mapFolding/reference/lunnanWhile.py,sha256=7NY2IKO5XBgol0aWWF_Fi-7oTL9pvu_z6lB0TF1uVHk,4063
|
|
22
17
|
mapFolding/reference/rotatedEntryPoint.py,sha256=z0QyDQtnMvXNj5ntWzzJUQUMFm1-xHGLVhtYzwmczUI,11530
|
|
23
18
|
mapFolding/reference/total_countPlus1vsPlusN.py,sha256=usenM8Yn_G1dqlPl7NKKkcnbohBZVZBXTQRm2S3_EDA,8106
|
|
19
|
+
mapFolding/someAssemblyRequired/inlineAfunction.py,sha256=Hxytb9xgJV_Mnh8us0mA_oKwanEQWJSj3hJc25nI9Mk,6143
|
|
20
|
+
mapFolding/someAssemblyRequired/jobsAndTasks.py,sha256=u2ZtZ8xlQJALqQqQ8N7uBTNDbjG4OQ9nJsJZG5rLI8o,2189
|
|
21
|
+
mapFolding/someAssemblyRequired/makeNuitkaSource.py,sha256=jTK34OWzm6OsgFPd2mHwETxFo2X83io0M4YiEHRgk3U,3262
|
|
22
|
+
mapFolding/someAssemblyRequired/makeNumbaJob.py,sha256=YZ9JzzEieQH4sMqX84VGbpOJmdBatPanfmXFZ5V1Ex4,5109
|
|
24
23
|
tests/__init__.py,sha256=eg9smg-6VblOr0kisM40CpGnuDtU2JgEEWGDTFVOlW8,57
|
|
25
24
|
tests/conftest.py,sha256=AWB3m_jxMlkmOmGvk2ApJEk2ro5v8gmmJDcyLwN1oow,13761
|
|
26
25
|
tests/pythons_idiotic_namespace.py,sha256=oOLDBergQqqhGuRpsXUnFD-R_6AlJipNKYHw-kk_OKw,33
|
|
27
26
|
tests/test_oeis.py,sha256=vxnwO-cSR68htkyMh9QMVv-lvxBo6qlwPg1Rbx4JylY,7963
|
|
28
|
-
tests/test_other.py,sha256=
|
|
27
|
+
tests/test_other.py,sha256=1EtLe0te7qqdazFKvKIOHPYW_ENsqAu11nzJO0yAE_Q,12012
|
|
29
28
|
tests/test_tasks.py,sha256=Nwe4iuSjwGZvsw5CXCcic7tkBxgM5JX9mrGZMDYhAwE,1785
|
|
30
|
-
|
|
31
|
-
mapFolding-0.2.
|
|
32
|
-
mapFolding-0.2.
|
|
33
|
-
mapFolding-0.2.
|
|
34
|
-
mapFolding-0.2.
|
|
35
|
-
mapFolding-0.2.4.dist-info/RECORD,,
|
|
29
|
+
mapFolding-0.2.5.dist-info/METADATA,sha256=pKBorE-WQsa2LVETIUORCw-ae3cDPtUcLbE395-oVhs,6652
|
|
30
|
+
mapFolding-0.2.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
31
|
+
mapFolding-0.2.5.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
|
|
32
|
+
mapFolding-0.2.5.dist-info/top_level.txt,sha256=1gP2vFaqPwHujGwb3UjtMlLEGN-943VSYFR7V4gDqW8,17
|
|
33
|
+
mapFolding-0.2.5.dist-info/RECORD,,
|
tests/test_other.py
CHANGED
|
@@ -84,7 +84,7 @@ def test_countFolds_writeFoldsTotal(
|
|
|
84
84
|
mock_countFolds = mockFoldingFunction(foldsValue, listDimensionsTestFunctionality)
|
|
85
85
|
|
|
86
86
|
with unittest.mock.patch("mapFolding.babbage._countFolds", side_effect=mock_countFolds):
|
|
87
|
-
returned = countFolds(listDimensionsTestFunctionality,
|
|
87
|
+
returned = countFolds(listDimensionsTestFunctionality, pathishWriteFoldsTotal=pathWriteTarget)
|
|
88
88
|
|
|
89
89
|
standardComparison(foldsValue, lambda: returned) # Check return value
|
|
90
90
|
standardComparison(str(foldsValue), lambda: (pathTempTesting / filenameFoldsTotalExpected).read_text()) # Check file content
|
|
@@ -224,33 +224,33 @@ def parameterIterator():
|
|
|
224
224
|
yield dict(zip(parameterKeys, combination))
|
|
225
225
|
|
|
226
226
|
return generateCombinations
|
|
227
|
-
|
|
228
|
-
def test_outfitCountFolds_basic(listDimensionsTestFunctionality, parameterIterator):
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
227
|
+
# Must mock the set cpu count to avoid errors on GitHub
|
|
228
|
+
# def test_outfitCountFolds_basic(listDimensionsTestFunctionality, parameterIterator):
|
|
229
|
+
# """Basic validation of outfitCountFolds return value structure."""
|
|
230
|
+
# parameters = next(parameterIterator(listDimensionsTestFunctionality))
|
|
231
|
+
|
|
232
|
+
# stateInitialized = outfitCountFolds(
|
|
233
|
+
# listDimensionsTestFunctionality,
|
|
234
|
+
# **{k: v for k, v in parameters.items() if v is not None}
|
|
235
|
+
# )
|
|
236
|
+
|
|
237
|
+
# # Basic structure tests
|
|
238
|
+
# assert isinstance(stateInitialized, dict)
|
|
239
|
+
# assert len(stateInitialized) == 7 # 6 ndarray + 1 tuple
|
|
240
|
+
|
|
241
|
+
# # Check for specific keys
|
|
242
|
+
# requiredKeys = set(computationState.__annotations__.keys())
|
|
243
|
+
# assert set(stateInitialized.keys()) == requiredKeys
|
|
244
|
+
|
|
245
|
+
# # Check types more carefully
|
|
246
|
+
# for key, value in stateInitialized.items():
|
|
247
|
+
# if key == 'mapShape':
|
|
248
|
+
# assert isinstance(value, tuple)
|
|
249
|
+
# assert all(isinstance(dim, int) for dim in value)
|
|
250
|
+
# else:
|
|
251
|
+
# assert isinstance(value, numpy.ndarray), f"{key} should be ndarray but is {type(value)}"
|
|
252
|
+
# assert issubclass(value.dtype.type, numpy.integer), \
|
|
253
|
+
# f"{key} should have integer dtype but has {value.dtype}"
|
|
254
254
|
|
|
255
255
|
def test_pathJobDEFAULT_colab():
|
|
256
256
|
"""Test that pathJobDEFAULT is set correctly when running in Google Colab."""
|
mapFolding/JAX/taskJAX.py
DELETED
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
from mapFolding import validateListDimensions, getLeavesTotal
|
|
2
|
-
from typing import List, Tuple
|
|
3
|
-
import jax
|
|
4
|
-
import jaxtyping
|
|
5
|
-
|
|
6
|
-
dtypeDefault = jax.numpy.int32
|
|
7
|
-
dtypeMaximum = jax.numpy.int32
|
|
8
|
-
|
|
9
|
-
def countFolds(listDimensions: List[int]):
|
|
10
|
-
"""Calculate foldings across multiple devices using pmap"""
|
|
11
|
-
p = validateListDimensions(listDimensions)
|
|
12
|
-
n = getLeavesTotal(p)
|
|
13
|
-
|
|
14
|
-
# Get number of devices (GPUs/TPUs)
|
|
15
|
-
deviceCount = jax.device_count()
|
|
16
|
-
|
|
17
|
-
if deviceCount > 1:
|
|
18
|
-
# Split work across devices
|
|
19
|
-
tasksPerDevice = (n + deviceCount - 1) // deviceCount
|
|
20
|
-
paddedTaskCount = tasksPerDevice * deviceCount
|
|
21
|
-
|
|
22
|
-
# Create padded array of task indices
|
|
23
|
-
arrayTaskIndices = jax.numpy.arange(paddedTaskCount, dtype=dtypeDefault)
|
|
24
|
-
arrayTaskIndices = arrayTaskIndices.reshape((deviceCount, tasksPerDevice))
|
|
25
|
-
|
|
26
|
-
# Create pmapped function
|
|
27
|
-
parallelFoldingsTask = jax.pmap(lambda x: jax.vmap(lambda y: foldingsTask(tuple(p), y))(x))
|
|
28
|
-
|
|
29
|
-
# Run computation across devices
|
|
30
|
-
arrayResults = parallelFoldingsTask(arrayTaskIndices)
|
|
31
|
-
|
|
32
|
-
# Sum valid results (ignore padding)
|
|
33
|
-
return jax.numpy.sum(arrayResults[:, :min(tasksPerDevice, n - tasksPerDevice * (deviceCount-1))])
|
|
34
|
-
else:
|
|
35
|
-
# Fall back to sequential execution if no multiple devices available
|
|
36
|
-
arrayTaskIndices = jax.numpy.arange(n, dtype=dtypeDefault)
|
|
37
|
-
batchedFoldingsTask = jax.vmap(lambda x: foldingsTask(tuple(p), x))
|
|
38
|
-
return jax.numpy.sum(batchedFoldingsTask(arrayTaskIndices))
|
|
39
|
-
|
|
40
|
-
def foldingsTask(p, taskIndex) -> jaxtyping.UInt32:
|
|
41
|
-
arrayDimensions = jax.numpy.asarray(p, dtype=dtypeDefault)
|
|
42
|
-
leavesTotal = jax.numpy.prod(arrayDimensions)
|
|
43
|
-
dimensionsTotal = jax.numpy.size(arrayDimensions)
|
|
44
|
-
|
|
45
|
-
"""How to build a leaf connection graph, also called a "Cartesian Product Decomposition"
|
|
46
|
-
or a "Dimensional Product Mapping", with sentinels:
|
|
47
|
-
Step 1: find the cumulative product of the map's dimensions"""
|
|
48
|
-
cumulativeProduct = jax.numpy.ones(dimensionsTotal + 1, dtype=dtypeDefault)
|
|
49
|
-
cumulativeProduct = cumulativeProduct.at[1:].set(jax.numpy.cumprod(arrayDimensions))
|
|
50
|
-
|
|
51
|
-
"""Step 2: for each dimension, create a coordinate system """
|
|
52
|
-
"""coordinateSystem[dimension1ndex][leaf1ndex] holds the dimension1ndex-th coordinate of leaf leaf1ndex"""
|
|
53
|
-
coordinateSystem = jax.numpy.zeros((dimensionsTotal + 1, leavesTotal + 1), dtype=dtypeDefault)
|
|
54
|
-
|
|
55
|
-
# Create mesh of indices for vectorized computation
|
|
56
|
-
dimension1ndices, leaf1ndices = jax.numpy.meshgrid(
|
|
57
|
-
jax.numpy.arange(1, dimensionsTotal + 1),
|
|
58
|
-
jax.numpy.arange(1, leavesTotal + 1),
|
|
59
|
-
indexing='ij'
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
# Compute all coordinates at once using broadcasting
|
|
63
|
-
coordinateSystem = coordinateSystem.at[1:, 1:].set(
|
|
64
|
-
((leaf1ndices - 1) // cumulativeProduct.at[dimension1ndices - 1].get()) %
|
|
65
|
-
arrayDimensions.at[dimension1ndices - 1].get() + 1
|
|
66
|
-
)
|
|
67
|
-
del dimension1ndices, leaf1ndices
|
|
68
|
-
|
|
69
|
-
"""Step 3: create a huge empty connection graph"""
|
|
70
|
-
connectionGraph = jax.numpy.zeros((dimensionsTotal + 1, leavesTotal + 1, leavesTotal + 1), dtype=dtypeDefault)
|
|
71
|
-
|
|
72
|
-
# Create 3D mesh of indices for vectorized computation
|
|
73
|
-
dimension1ndices, activeLeaf1ndices, connectee1ndices = jax.numpy.meshgrid(
|
|
74
|
-
jax.numpy.arange(1, dimensionsTotal + 1),
|
|
75
|
-
jax.numpy.arange(1, leavesTotal + 1),
|
|
76
|
-
jax.numpy.arange(1, leavesTotal + 1),
|
|
77
|
-
indexing='ij'
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
# Create masks for valid indices
|
|
81
|
-
maskActiveConnectee = connectee1ndices <= activeLeaf1ndices
|
|
82
|
-
|
|
83
|
-
# Calculate coordinate parity comparison
|
|
84
|
-
coordsParity = (coordinateSystem.at[dimension1ndices, activeLeaf1ndices].get() & 1) == \
|
|
85
|
-
(coordinateSystem.at[dimension1ndices, connectee1ndices].get() & 1)
|
|
86
|
-
|
|
87
|
-
# Compute distance conditions
|
|
88
|
-
isFirstCoord = coordinateSystem.at[dimension1ndices, connectee1ndices].get() == 1
|
|
89
|
-
isLastCoord = coordinateSystem.at[dimension1ndices, connectee1ndices].get() == \
|
|
90
|
-
arrayDimensions.at[dimension1ndices - 1].get()
|
|
91
|
-
exceedsActive = connectee1ndices + cumulativeProduct.at[dimension1ndices - 1].get() > activeLeaf1ndices
|
|
92
|
-
|
|
93
|
-
# Compute connection values for even and odd parities
|
|
94
|
-
evenParityValues = jax.numpy.where(
|
|
95
|
-
isFirstCoord,
|
|
96
|
-
connectee1ndices,
|
|
97
|
-
connectee1ndices - cumulativeProduct.at[dimension1ndices - 1].get()
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
oddParityValues = jax.numpy.where(
|
|
101
|
-
jax.numpy.logical_or(isLastCoord, exceedsActive),
|
|
102
|
-
connectee1ndices,
|
|
103
|
-
connectee1ndices + cumulativeProduct.at[dimension1ndices - 1].get()
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
# Combine based on parity and valid indices
|
|
107
|
-
connectionValues = jax.numpy.where(
|
|
108
|
-
coordsParity,
|
|
109
|
-
evenParityValues,
|
|
110
|
-
oddParityValues
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
# Update only valid connections
|
|
114
|
-
connectionGraph = connectionGraph.at[dimension1ndices, activeLeaf1ndices, connectee1ndices].set(
|
|
115
|
-
jax.numpy.where(maskActiveConnectee, connectionValues, 0)
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
def doNothing(argument):
|
|
119
|
-
return argument
|
|
120
|
-
|
|
121
|
-
def while_activeLeaf1ndex_greaterThan_0(comparisonValues: Tuple):
|
|
122
|
-
comparand = comparisonValues[6]
|
|
123
|
-
return comparand > 0
|
|
124
|
-
|
|
125
|
-
def countFoldings(allValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
126
|
-
_0, leafBelow, _2, _3, _4, _5, activeLeaf1ndex, _7 = allValues
|
|
127
|
-
|
|
128
|
-
sentinel = leafBelow.at[0].get().astype(jax.numpy.int32)
|
|
129
|
-
|
|
130
|
-
allValues = jax.lax.cond(findGapsCondition(sentinel, activeLeaf1ndex),
|
|
131
|
-
lambda argumentX: dao(findGapsDo(argumentX)),
|
|
132
|
-
lambda argumentY: jax.lax.cond(incrementCondition(sentinel, activeLeaf1ndex), lambda argumentZ: dao(incrementDo(argumentZ)), dao, argumentY),
|
|
133
|
-
allValues)
|
|
134
|
-
|
|
135
|
-
return allValues
|
|
136
|
-
|
|
137
|
-
def findGapsCondition(leafBelowSentinel, activeLeafNumber):
|
|
138
|
-
return jax.numpy.logical_or(jax.numpy.logical_and(leafBelowSentinel == 1, activeLeafNumber <= leavesTotal), activeLeafNumber <= 1)
|
|
139
|
-
|
|
140
|
-
def findGapsDo(allValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
141
|
-
def for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1(comparisonValues: Tuple):
|
|
142
|
-
return comparisonValues[-1] <= dimensionsTotal
|
|
143
|
-
|
|
144
|
-
def for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1_do(for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1Values: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
145
|
-
def ifLeafIsUnconstrainedCondition(comparand):
|
|
146
|
-
return jax.numpy.equal(connectionGraph[comparand, activeLeaf1ndex, activeLeaf1ndex], activeLeaf1ndex)
|
|
147
|
-
|
|
148
|
-
def ifLeafIsUnconstrainedDo(unconstrainedValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
149
|
-
unconstrained_unconstrainedLeaf = unconstrainedValues[3]
|
|
150
|
-
unconstrained_unconstrainedLeaf = 1 + unconstrained_unconstrainedLeaf
|
|
151
|
-
return (unconstrainedValues[0], unconstrainedValues[1], unconstrainedValues[2], unconstrained_unconstrainedLeaf)
|
|
152
|
-
|
|
153
|
-
def ifLeafIsUnconstrainedElse(unconstrainedValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
154
|
-
def while_leaf1ndexConnectee_notEquals_activeLeaf1ndex(comparisonValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
155
|
-
return comparisonValues[-1] != activeLeaf1ndex
|
|
156
|
-
|
|
157
|
-
def countGaps(countGapsDoValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
158
|
-
# if taskDivisions == False or activeLeaf1ndex != leavesTotal or leaf1ndexConnectee % leavesTotal == taskIndex:
|
|
159
|
-
def taskDivisionComparison():
|
|
160
|
-
return jax.numpy.logical_or(activeLeaf1ndex != leavesTotal, jax.numpy.equal(countGapsLeaf1ndexConnectee % leavesTotal, taskIndex))
|
|
161
|
-
# return taskDivisions == False or jax.numpy.logical_or(activeLeaf1ndex != leavesTotal, jax.numpy.equal(countGapsLeaf1ndexConnectee % leavesTotal, taskIndex))
|
|
162
|
-
|
|
163
|
-
def taskDivisionDo(taskDivisionDoValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32]):
|
|
164
|
-
taskDivisionCountDimensionsGapped, taskDivisionPotentialGaps, taskDivisionGap1ndexLowerBound = taskDivisionDoValues
|
|
165
|
-
|
|
166
|
-
taskDivisionPotentialGaps = taskDivisionPotentialGaps.at[taskDivisionGap1ndexLowerBound].set(countGapsLeaf1ndexConnectee)
|
|
167
|
-
taskDivisionGap1ndexLowerBound = jax.numpy.where(
|
|
168
|
-
jax.numpy.equal(taskDivisionCountDimensionsGapped.at[countGapsLeaf1ndexConnectee].get(), 0), taskDivisionGap1ndexLowerBound + 1, taskDivisionGap1ndexLowerBound)
|
|
169
|
-
taskDivisionCountDimensionsGapped = taskDivisionCountDimensionsGapped.at[countGapsLeaf1ndexConnectee].add(1)
|
|
170
|
-
|
|
171
|
-
return (taskDivisionCountDimensionsGapped, taskDivisionPotentialGaps, taskDivisionGap1ndexLowerBound)
|
|
172
|
-
|
|
173
|
-
countGapsLeaf1ndexConnectee = countGapsDoValues[3]
|
|
174
|
-
taskDivisionValues = (countGapsDoValues[0], countGapsDoValues[1], countGapsDoValues[2])
|
|
175
|
-
taskDivisionValues = jax.lax.cond(taskDivisionComparison(), taskDivisionDo, doNothing, taskDivisionValues)
|
|
176
|
-
|
|
177
|
-
countGapsLeaf1ndexConnectee = connectionGraph.at[dimensionNumber, activeLeaf1ndex, leafBelow.at[countGapsLeaf1ndexConnectee].get()].get().astype(jax.numpy.int32)
|
|
178
|
-
|
|
179
|
-
return (taskDivisionValues[0], taskDivisionValues[1], taskDivisionValues[2], countGapsLeaf1ndexConnectee)
|
|
180
|
-
|
|
181
|
-
unconstrained_countDimensionsGapped, unconstrained_gapsWhere, unconstrained_gap1ndexCeiling, unconstrained_unconstrainedLeaf = unconstrainedValues
|
|
182
|
-
|
|
183
|
-
leaf1ndexConnectee = connectionGraph.at[dimensionNumber, activeLeaf1ndex, activeLeaf1ndex].get().astype(jax.numpy.int32)
|
|
184
|
-
|
|
185
|
-
countGapsValues = (unconstrained_countDimensionsGapped, unconstrained_gapsWhere, unconstrained_gap1ndexCeiling, leaf1ndexConnectee)
|
|
186
|
-
countGapsValues = jax.lax.while_loop(while_leaf1ndexConnectee_notEquals_activeLeaf1ndex, countGaps, countGapsValues)
|
|
187
|
-
unconstrained_countDimensionsGapped, unconstrained_gapsWhere, unconstrained_gap1ndexCeiling, leaf1ndexConnectee = countGapsValues
|
|
188
|
-
|
|
189
|
-
return (unconstrained_countDimensionsGapped, unconstrained_gapsWhere, unconstrained_gap1ndexCeiling, unconstrained_unconstrainedLeaf)
|
|
190
|
-
|
|
191
|
-
dimensions_countDimensionsGapped, dimensions_gapsWhere, dimensions_gap1ndexCeiling, dimensions_unconstrainedLeaf, dimensionNumber = for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1Values
|
|
192
|
-
|
|
193
|
-
ifLeafIsUnconstrainedValues = (dimensions_countDimensionsGapped, dimensions_gapsWhere, dimensions_gap1ndexCeiling, dimensions_unconstrainedLeaf)
|
|
194
|
-
ifLeafIsUnconstrainedValues = jax.lax.cond(ifLeafIsUnconstrainedCondition(dimensionNumber), ifLeafIsUnconstrainedDo, ifLeafIsUnconstrainedElse, ifLeafIsUnconstrainedValues)
|
|
195
|
-
dimensions_countDimensionsGapped, dimensions_gapsWhere, dimensions_gap1ndexCeiling, dimensions_unconstrainedLeaf = ifLeafIsUnconstrainedValues
|
|
196
|
-
|
|
197
|
-
dimensionNumber = 1 + dimensionNumber
|
|
198
|
-
return (dimensions_countDimensionsGapped, dimensions_gapsWhere, dimensions_gap1ndexCeiling, dimensions_unconstrainedLeaf, dimensionNumber)
|
|
199
|
-
|
|
200
|
-
def almostUselessCondition(comparand):
|
|
201
|
-
return comparand == dimensionsTotal
|
|
202
|
-
|
|
203
|
-
def almostUselessConditionDo(for_leaf1ndex_in_range_activeLeaf1ndexValues: Tuple[jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
204
|
-
def for_leaf1ndex_in_range_activeLeaf1ndex(comparisonValues):
|
|
205
|
-
return comparisonValues[-1] < activeLeaf1ndex
|
|
206
|
-
|
|
207
|
-
def for_leaf1ndex_in_range_activeLeaf1ndex_do(for_leaf1ndex_in_range_activeLeaf1ndexValues: Tuple[jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
208
|
-
leafInRangePotentialGaps, gapNumberLowerBound, leafNumber = for_leaf1ndex_in_range_activeLeaf1ndexValues
|
|
209
|
-
leafInRangePotentialGaps = leafInRangePotentialGaps.at[gapNumberLowerBound].set(leafNumber)
|
|
210
|
-
gapNumberLowerBound = 1 + gapNumberLowerBound
|
|
211
|
-
leafNumber = 1 + leafNumber
|
|
212
|
-
return (leafInRangePotentialGaps, gapNumberLowerBound, leafNumber)
|
|
213
|
-
return jax.lax.while_loop(for_leaf1ndex_in_range_activeLeaf1ndex, for_leaf1ndex_in_range_activeLeaf1ndex_do, for_leaf1ndex_in_range_activeLeaf1ndexValues)
|
|
214
|
-
|
|
215
|
-
def for_range_from_activeGap1ndex_to_gap1ndexCeiling(comparisonValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
216
|
-
return comparisonValues[-1] < gap1ndexCeiling
|
|
217
|
-
|
|
218
|
-
def miniGapDo(gapToGapValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
219
|
-
gapToGapCountDimensionsGapped, gapToGapPotentialGaps, activeGapNumber, index = gapToGapValues
|
|
220
|
-
gapToGapPotentialGaps = gapToGapPotentialGaps.at[activeGapNumber].set(gapToGapPotentialGaps.at[index].get())
|
|
221
|
-
activeGapNumber = jax.numpy.where(jax.numpy.equal(gapToGapCountDimensionsGapped.at[gapToGapPotentialGaps.at[index].get()].get(), dimensionsTotal - unconstrainedLeaf), activeGapNumber + 1, activeGapNumber).astype(jax.numpy.int32)
|
|
222
|
-
gapToGapCountDimensionsGapped = gapToGapCountDimensionsGapped.at[gapToGapPotentialGaps.at[index].get()].set(0)
|
|
223
|
-
index = 1 + index
|
|
224
|
-
return (gapToGapCountDimensionsGapped, gapToGapPotentialGaps, activeGapNumber, index)
|
|
225
|
-
|
|
226
|
-
_0, leafBelow, countDimensionsGapped, gapRangeStart, gapsWhere, _5, activeLeaf1ndex, activeGap1ndex = allValues
|
|
227
|
-
|
|
228
|
-
unconstrainedLeaf = jax.numpy.int32(0)
|
|
229
|
-
dimension1ndex = jax.numpy.int32(1)
|
|
230
|
-
gap1ndexCeiling = gapRangeStart.at[activeLeaf1ndex - 1].get().astype(jax.numpy.int32)
|
|
231
|
-
activeGap1ndex = gap1ndexCeiling
|
|
232
|
-
for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1Values = (countDimensionsGapped, gapsWhere, gap1ndexCeiling, unconstrainedLeaf, dimension1ndex)
|
|
233
|
-
for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1Values = jax.lax.while_loop(for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1, for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1_do, for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1Values)
|
|
234
|
-
countDimensionsGapped, gapsWhere, gap1ndexCeiling, unconstrainedLeaf, dimension1ndex = for_dimension1ndex_in_range_1_to_dimensionsTotalPlus1Values
|
|
235
|
-
del dimension1ndex
|
|
236
|
-
|
|
237
|
-
leaf1ndex = jax.numpy.int32(0)
|
|
238
|
-
for_leaf1ndex_in_range_activeLeaf1ndexValues = (gapsWhere, gap1ndexCeiling, leaf1ndex)
|
|
239
|
-
for_leaf1ndex_in_range_activeLeaf1ndexValues = jax.lax.cond(almostUselessCondition(unconstrainedLeaf), almostUselessConditionDo, doNothing, for_leaf1ndex_in_range_activeLeaf1ndexValues)
|
|
240
|
-
gapsWhere, gap1ndexCeiling, leaf1ndex = for_leaf1ndex_in_range_activeLeaf1ndexValues
|
|
241
|
-
del leaf1ndex
|
|
242
|
-
|
|
243
|
-
indexMiniGap = activeGap1ndex
|
|
244
|
-
miniGapValues = (countDimensionsGapped, gapsWhere, activeGap1ndex, indexMiniGap)
|
|
245
|
-
miniGapValues = jax.lax.while_loop(for_range_from_activeGap1ndex_to_gap1ndexCeiling, miniGapDo, miniGapValues)
|
|
246
|
-
countDimensionsGapped, gapsWhere, activeGap1ndex, indexMiniGap = miniGapValues
|
|
247
|
-
del indexMiniGap
|
|
248
|
-
|
|
249
|
-
return (allValues[0], leafBelow, countDimensionsGapped, gapRangeStart, gapsWhere, allValues[5], activeLeaf1ndex, activeGap1ndex)
|
|
250
|
-
|
|
251
|
-
def incrementCondition(leafBelowSentinel, activeLeafNumber):
|
|
252
|
-
return jax.numpy.logical_and(activeLeafNumber > leavesTotal, leafBelowSentinel == 1)
|
|
253
|
-
|
|
254
|
-
def incrementDo(allValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
255
|
-
foldingsSubTotal = allValues[5]
|
|
256
|
-
foldingsSubTotal = leavesTotal + foldingsSubTotal
|
|
257
|
-
return (allValues[0], allValues[1], allValues[2], allValues[3], allValues[4], foldingsSubTotal, allValues[6], allValues[7])
|
|
258
|
-
|
|
259
|
-
def dao(allValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
260
|
-
def whileBacktrackingCondition(backtrackingValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32]):
|
|
261
|
-
comparand = backtrackingValues[2]
|
|
262
|
-
return jax.numpy.logical_and(comparand > 0, jax.numpy.equal(activeGap1ndex, gapRangeStart.at[comparand - 1].get()))
|
|
263
|
-
|
|
264
|
-
def whileBacktrackingDo(backtrackingValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32]):
|
|
265
|
-
backtrackAbove, backtrackBelow, activeLeafNumber = backtrackingValues
|
|
266
|
-
|
|
267
|
-
activeLeafNumber = activeLeafNumber - 1
|
|
268
|
-
backtrackBelow = backtrackBelow.at[backtrackAbove.at[activeLeafNumber].get()].set(backtrackBelow.at[activeLeafNumber].get())
|
|
269
|
-
backtrackAbove = backtrackAbove.at[backtrackBelow.at[activeLeafNumber].get()].set(backtrackAbove.at[activeLeafNumber].get())
|
|
270
|
-
|
|
271
|
-
return (backtrackAbove, backtrackBelow, activeLeafNumber)
|
|
272
|
-
|
|
273
|
-
def if_activeLeaf1ndex_greaterThan_0(activeLeafNumber):
|
|
274
|
-
return activeLeafNumber > 0
|
|
275
|
-
|
|
276
|
-
def if_activeLeaf1ndex_greaterThan_0_do(leafPlacementValues: Tuple[jaxtyping.Array, jaxtyping.Array, jaxtyping.Array, jaxtyping.UInt32, jaxtyping.UInt32]):
|
|
277
|
-
placeLeafAbove, placeLeafBelow, placeGapRangeStart, activeLeafNumber, activeGapNumber = leafPlacementValues
|
|
278
|
-
activeGapNumber = activeGapNumber - 1
|
|
279
|
-
placeLeafAbove = placeLeafAbove.at[activeLeafNumber].set(gapsWhere.at[activeGapNumber].get())
|
|
280
|
-
placeLeafBelow = placeLeafBelow.at[activeLeafNumber].set(placeLeafBelow.at[placeLeafAbove.at[activeLeafNumber].get()].get())
|
|
281
|
-
placeLeafBelow = placeLeafBelow.at[placeLeafAbove.at[activeLeafNumber].get()].set(activeLeafNumber)
|
|
282
|
-
placeLeafAbove = placeLeafAbove.at[placeLeafBelow.at[activeLeafNumber].get()].set(activeLeafNumber)
|
|
283
|
-
placeGapRangeStart = placeGapRangeStart.at[activeLeafNumber].set(activeGapNumber)
|
|
284
|
-
|
|
285
|
-
activeLeafNumber = 1 + activeLeafNumber
|
|
286
|
-
return (placeLeafAbove, placeLeafBelow, placeGapRangeStart, activeLeafNumber, activeGapNumber)
|
|
287
|
-
|
|
288
|
-
leafAbove, leafBelow, _2, gapRangeStart, gapsWhere, _5, activeLeaf1ndex, activeGap1ndex = allValues
|
|
289
|
-
|
|
290
|
-
whileBacktrackingValues = (leafAbove, leafBelow, activeLeaf1ndex)
|
|
291
|
-
whileBacktrackingValues = jax.lax.while_loop(whileBacktrackingCondition, whileBacktrackingDo, whileBacktrackingValues)
|
|
292
|
-
leafAbove, leafBelow, activeLeaf1ndex = whileBacktrackingValues
|
|
293
|
-
|
|
294
|
-
if_activeLeaf1ndex_greaterThan_0_values = (leafAbove, leafBelow, gapRangeStart, activeLeaf1ndex, activeGap1ndex)
|
|
295
|
-
if_activeLeaf1ndex_greaterThan_0_values = jax.lax.cond(if_activeLeaf1ndex_greaterThan_0(activeLeaf1ndex), if_activeLeaf1ndex_greaterThan_0_do, doNothing, if_activeLeaf1ndex_greaterThan_0_values)
|
|
296
|
-
leafAbove, leafBelow, gapRangeStart, activeLeaf1ndex, activeGap1ndex = if_activeLeaf1ndex_greaterThan_0_values
|
|
297
|
-
|
|
298
|
-
return (leafAbove, leafBelow, allValues[2], gapRangeStart, gapsWhere, allValues[5], activeLeaf1ndex, activeGap1ndex)
|
|
299
|
-
|
|
300
|
-
# Dynamic values
|
|
301
|
-
A = jax.numpy.zeros(leavesTotal + 1, dtype=dtypeDefault)
|
|
302
|
-
B = jax.numpy.zeros(leavesTotal + 1, dtype=dtypeDefault)
|
|
303
|
-
count = jax.numpy.zeros(leavesTotal + 1, dtype=dtypeDefault)
|
|
304
|
-
gapter = jax.numpy.zeros(leavesTotal + 1, dtype=dtypeDefault)
|
|
305
|
-
gap = jax.numpy.zeros(leavesTotal * leavesTotal + 1, dtype=dtypeMaximum)
|
|
306
|
-
|
|
307
|
-
foldingsSubTotal = jax.numpy.int32(0)
|
|
308
|
-
l = jax.numpy.int32(1)
|
|
309
|
-
g = jax.numpy.int32(0)
|
|
310
|
-
|
|
311
|
-
foldingsValues = (A, B, count, gapter, gap, foldingsSubTotal, l, g)
|
|
312
|
-
foldingsValues = jax.lax.while_loop(while_activeLeaf1ndex_greaterThan_0, countFoldings, foldingsValues)
|
|
313
|
-
return foldingsValues[5]
|
mapFolding/countInitialize.py
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import numba
|
|
2
|
-
|
|
3
|
-
@numba.jit((numba.int64[:, :, ::1], numba.int64[::1], numba.int64[::1], numba.int64[::1], numba.int64[:, ::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
4
|
-
def countInitialize(connectionGraph, gapsWhere, my, the, track):
|
|
5
|
-
while my[6] > 0:
|
|
6
|
-
if my[6] <= 1 or track[1, 0] == 1:
|
|
7
|
-
my[1] = 0
|
|
8
|
-
my[3] = track[3, my[6] - 1]
|
|
9
|
-
my[0] = 1
|
|
10
|
-
while my[0] <= the[0]:
|
|
11
|
-
if connectionGraph[my[0], my[6], my[6]] == my[6]:
|
|
12
|
-
my[1] += 1
|
|
13
|
-
else:
|
|
14
|
-
my[7] = connectionGraph[my[0], my[6], my[6]]
|
|
15
|
-
while my[7] != my[6]:
|
|
16
|
-
gapsWhere[my[3]] = my[7]
|
|
17
|
-
if track[2, my[7]] == 0:
|
|
18
|
-
my[3] += 1
|
|
19
|
-
track[2, my[7]] += 1
|
|
20
|
-
my[7] = connectionGraph[my[0], my[6], track[1, my[7]]]
|
|
21
|
-
my[0] += 1
|
|
22
|
-
if my[1] == the[0]:
|
|
23
|
-
my[4] = 0
|
|
24
|
-
while my[4] < my[6]:
|
|
25
|
-
gapsWhere[my[3]] = my[4]
|
|
26
|
-
my[3] += 1
|
|
27
|
-
my[4] += 1
|
|
28
|
-
my[5] = my[2]
|
|
29
|
-
while my[5] < my[3]:
|
|
30
|
-
gapsWhere[my[2]] = gapsWhere[my[5]]
|
|
31
|
-
if track[2, gapsWhere[my[5]]] == the[0] - my[1]:
|
|
32
|
-
my[2] += 1
|
|
33
|
-
track[2, gapsWhere[my[5]]] = 0
|
|
34
|
-
my[5] += 1
|
|
35
|
-
if my[6] > 0:
|
|
36
|
-
my[2] -= 1
|
|
37
|
-
track[0, my[6]] = gapsWhere[my[2]]
|
|
38
|
-
track[1, my[6]] = track[1, track[0, my[6]]]
|
|
39
|
-
track[1, track[0, my[6]]] = my[6]
|
|
40
|
-
track[0, track[1, my[6]]] = my[6]
|
|
41
|
-
track[3, my[6]] = my[2]
|
|
42
|
-
my[6] += 1
|
|
43
|
-
if my[2] > 0:
|
|
44
|
-
return
|
mapFolding/countParallel.py
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import numba
|
|
2
|
-
|
|
3
|
-
@numba.jit((numba.int64[:, :, ::1], numba.int64[::1], numba.int64[::1], numba.int64[::1], numba.int64[::1], numba.int64[:, ::1]), parallel=True, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
4
|
-
def countParallel(connectionGraph, foldsSubTotals, gapsWherePARALLEL, myPARALLEL, the, trackPARALLEL):
|
|
5
|
-
for indexSherpa in numba.prange(the[2]):
|
|
6
|
-
gapsWhere = gapsWherePARALLEL.copy()
|
|
7
|
-
my = myPARALLEL.copy()
|
|
8
|
-
my[8] = indexSherpa
|
|
9
|
-
track = trackPARALLEL.copy()
|
|
10
|
-
while my[6] > 0:
|
|
11
|
-
if my[6] <= 1 or track[1, 0] == 1:
|
|
12
|
-
if my[6] > the[1]:
|
|
13
|
-
foldsSubTotals[my[8]] += the[1]
|
|
14
|
-
else:
|
|
15
|
-
my[1] = 0
|
|
16
|
-
my[3] = track[3, my[6] - 1]
|
|
17
|
-
my[0] = 1
|
|
18
|
-
while my[0] <= the[0]:
|
|
19
|
-
if connectionGraph[my[0], my[6], my[6]] == my[6]:
|
|
20
|
-
my[1] += 1
|
|
21
|
-
else:
|
|
22
|
-
my[7] = connectionGraph[my[0], my[6], my[6]]
|
|
23
|
-
while my[7] != my[6]:
|
|
24
|
-
if my[6] != the[2] or my[7] % the[2] == my[8]:
|
|
25
|
-
gapsWhere[my[3]] = my[7]
|
|
26
|
-
if track[2, my[7]] == 0:
|
|
27
|
-
my[3] += 1
|
|
28
|
-
track[2, my[7]] += 1
|
|
29
|
-
my[7] = connectionGraph[my[0], my[6], track[1, my[7]]]
|
|
30
|
-
my[0] += 1
|
|
31
|
-
my[5] = my[2]
|
|
32
|
-
while my[5] < my[3]:
|
|
33
|
-
gapsWhere[my[2]] = gapsWhere[my[5]]
|
|
34
|
-
if track[2, gapsWhere[my[5]]] == the[0] - my[1]:
|
|
35
|
-
my[2] += 1
|
|
36
|
-
track[2, gapsWhere[my[5]]] = 0
|
|
37
|
-
my[5] += 1
|
|
38
|
-
while my[6] > 0 and my[2] == track[3, my[6] - 1]:
|
|
39
|
-
my[6] -= 1
|
|
40
|
-
track[1, track[0, my[6]]] = track[1, my[6]]
|
|
41
|
-
track[0, track[1, my[6]]] = track[0, my[6]]
|
|
42
|
-
if my[6] > 0:
|
|
43
|
-
my[2] -= 1
|
|
44
|
-
track[0, my[6]] = gapsWhere[my[2]]
|
|
45
|
-
track[1, my[6]] = track[1, track[0, my[6]]]
|
|
46
|
-
track[1, track[0, my[6]]] = my[6]
|
|
47
|
-
track[0, track[1, my[6]]] = my[6]
|
|
48
|
-
track[3, my[6]] = my[2]
|
|
49
|
-
my[6] += 1
|
mapFolding/countSequential.py
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import numba
|
|
2
|
-
|
|
3
|
-
@numba.jit((numba.int64[:, :, ::1], numba.int64[::1], numba.int64[::1], numba.int64[::1], numba.int64[::1], numba.int64[:, ::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
4
|
-
def countSequential(connectionGraph, foldsSubTotals, gapsWhere, my, the, track):
|
|
5
|
-
while my[6] > 0:
|
|
6
|
-
if my[6] <= 1 or track[1, 0] == 1:
|
|
7
|
-
if my[6] > the[1]:
|
|
8
|
-
foldsSubTotals[my[8]] += the[1]
|
|
9
|
-
else:
|
|
10
|
-
my[1] = 0
|
|
11
|
-
my[3] = track[3, my[6] - 1]
|
|
12
|
-
my[0] = 1
|
|
13
|
-
while my[0] <= the[0]:
|
|
14
|
-
if connectionGraph[my[0], my[6], my[6]] == my[6]:
|
|
15
|
-
my[1] += 1
|
|
16
|
-
else:
|
|
17
|
-
my[7] = connectionGraph[my[0], my[6], my[6]]
|
|
18
|
-
while my[7] != my[6]:
|
|
19
|
-
gapsWhere[my[3]] = my[7]
|
|
20
|
-
if track[2, my[7]] == 0:
|
|
21
|
-
my[3] += 1
|
|
22
|
-
track[2, my[7]] += 1
|
|
23
|
-
my[7] = connectionGraph[my[0], my[6], track[1, my[7]]]
|
|
24
|
-
my[0] += 1
|
|
25
|
-
my[5] = my[2]
|
|
26
|
-
while my[5] < my[3]:
|
|
27
|
-
gapsWhere[my[2]] = gapsWhere[my[5]]
|
|
28
|
-
if track[2, gapsWhere[my[5]]] == the[0] - my[1]:
|
|
29
|
-
my[2] += 1
|
|
30
|
-
track[2, gapsWhere[my[5]]] = 0
|
|
31
|
-
my[5] += 1
|
|
32
|
-
while my[6] > 0 and my[2] == track[3, my[6] - 1]:
|
|
33
|
-
my[6] -= 1
|
|
34
|
-
track[1, track[0, my[6]]] = track[1, my[6]]
|
|
35
|
-
track[0, track[1, my[6]]] = track[0, my[6]]
|
|
36
|
-
if my[6] > 0:
|
|
37
|
-
my[2] -= 1
|
|
38
|
-
track[0, my[6]] = gapsWhere[my[2]]
|
|
39
|
-
track[1, my[6]] = track[1, track[0, my[6]]]
|
|
40
|
-
track[1, track[0, my[6]]] = my[6]
|
|
41
|
-
track[0, track[1, my[6]]] = my[6]
|
|
42
|
-
track[3, my[6]] = my[2]
|
|
43
|
-
my[6] += 1
|
tests/test_temporary.py
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from tests.conftest import *
|
|
2
|
-
from typing import Dict, List, Tuple
|
|
3
|
-
import importlib
|
|
4
|
-
import pytest
|
|
5
|
-
|
|
6
|
-
@pytest.fixture(scope="session", autouse=True)
|
|
7
|
-
def runSecondSetAfterAll(request: pytest.FixtureRequest):
|
|
8
|
-
"""Run after all other tests complete."""
|
|
9
|
-
def toggleAndRerun():
|
|
10
|
-
import mapFolding.importSelector
|
|
11
|
-
import mapFolding.babbage
|
|
12
|
-
mapFolding.importSelector.useLovelace = not mapFolding.importSelector.useLovelace
|
|
13
|
-
importlib.reload(mapFolding.importSelector)
|
|
14
|
-
importlib.reload(mapFolding.babbage)
|
|
15
|
-
|
|
16
|
-
request.addfinalizer(toggleAndRerun)
|
|
17
|
-
|
|
18
|
-
@pytest.mark.order(after="runSecondSetAfterAll")
|
|
19
|
-
def test_myabilitytodealwithbs(oeisID: str):
|
|
20
|
-
for n in settingsOEIS[oeisID]['valuesTestValidation']:
|
|
21
|
-
standardComparison(settingsOEIS[oeisID]['valuesKnown'][n], oeisIDfor_n, oeisID, n)
|
|
22
|
-
|
|
23
|
-
@pytest.mark.order(after="runSecondSetAfterAll")
|
|
24
|
-
def test_eff_em_el(listDimensionsTest_countFolds: List[int], foldsTotalKnown: Dict[Tuple[int, ...], int]) -> None:
|
|
25
|
-
standardComparison(foldsTotalKnown[tuple(listDimensionsTest_countFolds)], countFolds, listDimensionsTest_countFolds, None, 'maximum')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|