mapFolding 0.2.3__tar.gz → 0.2.5__tar.gz
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-0.2.3 → mapfolding-0.2.5}/PKG-INFO +8 -6
- {mapfolding-0.2.3 → mapfolding-0.2.5}/README.md +6 -1
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/__init__.py +1 -1
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/babbage.py +9 -4
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/beDRY.py +47 -6
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/benchmarks/benchmarking.py +3 -2
- mapfolding-0.2.5/mapFolding/importSelector.py +7 -0
- mapfolding-0.2.5/mapFolding/lovelace.py +213 -0
- mapfolding-0.2.3/mapFolding/JAX/lunnanJAX.py → mapfolding-0.2.5/mapFolding/reference/jax.py +2 -0
- mapfolding-0.2.5/mapFolding/someAssemblyRequired/inlineAfunction.py +152 -0
- mapfolding-0.2.5/mapFolding/someAssemblyRequired/jobsAndTasks.py +47 -0
- mapfolding-0.2.5/mapFolding/someAssemblyRequired/makeNuitkaSource.py +99 -0
- mapfolding-0.2.5/mapFolding/someAssemblyRequired/makeNumbaJob.py +121 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/startHere.py +8 -28
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/theSSOT.py +13 -5
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding.egg-info/PKG-INFO +8 -6
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding.egg-info/SOURCES.txt +6 -3
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding.egg-info/requires.txt +0 -4
- {mapfolding-0.2.3 → mapfolding-0.2.5}/pyproject.toml +4 -5
- {mapfolding-0.2.3 → mapfolding-0.2.5}/tests/conftest.py +8 -1
- {mapfolding-0.2.3 → mapfolding-0.2.5}/tests/test_other.py +158 -88
- mapfolding-0.2.3/mapFolding/JAX/taskJAX.py +0 -313
- mapfolding-0.2.3/mapFolding/benchmarks/test_benchmarks.py +0 -74
- mapfolding-0.2.3/mapFolding/lovelace.py +0 -217
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/oeis.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/reference/flattened.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/reference/hunterNumba.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/reference/irvineJavaPort.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/reference/lunnan.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/reference/lunnanNumpy.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/reference/lunnanWhile.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/reference/rotatedEntryPoint.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding/reference/total_countPlus1vsPlusN.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding.egg-info/dependency_links.txt +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding.egg-info/entry_points.txt +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/mapFolding.egg-info/top_level.txt +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/setup.cfg +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/tests/__init__.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/tests/pythons_idiotic_namespace.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/tests/test_oeis.py +0 -0
- {mapfolding-0.2.3 → mapfolding-0.2.5}/tests/test_tasks.py +0 -0
|
@@ -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,9 +14,6 @@ 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"
|
|
@@ -39,7 +36,7 @@ The directory [mapFolding/reference](https://github.com/hunterhogan/mapFolding/b
|
|
|
39
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
|
|
40
37
|
- miscellaneous notes.
|
|
41
38
|
|
|
42
|
-
[](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)   
|
|
43
40
|
|
|
44
41
|
## Simple, easy usage based on OEIS IDs
|
|
45
42
|
|
|
@@ -131,3 +128,8 @@ In [`foldings.txt`](https://github.com/hunterhogan/mapFolding/blob/main/mapFoldi
|
|
|
131
128
|
```sh
|
|
132
129
|
pip install mapFolding
|
|
133
130
|
```
|
|
131
|
+
|
|
132
|
+
## My recovery
|
|
133
|
+
|
|
134
|
+
[](https://HunterThinks.com/support)
|
|
135
|
+
[](https://www.youtube.com/@HunterHogan)
|
|
@@ -14,7 +14,7 @@ The directory [mapFolding/reference](https://github.com/hunterhogan/mapFolding/b
|
|
|
14
14
|
- [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
|
|
15
15
|
- miscellaneous notes.
|
|
16
16
|
|
|
17
|
-
[](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)   
|
|
18
18
|
|
|
19
19
|
## Simple, easy usage based on OEIS IDs
|
|
20
20
|
|
|
@@ -106,3 +106,8 @@ In [`foldings.txt`](https://github.com/hunterhogan/mapFolding/blob/main/mapFoldi
|
|
|
106
106
|
```sh
|
|
107
107
|
pip install mapFolding
|
|
108
108
|
```
|
|
109
|
+
|
|
110
|
+
## My recovery
|
|
111
|
+
|
|
112
|
+
[](https://HunterThinks.com/support)
|
|
113
|
+
[](https://www.youtube.com/@HunterHogan)
|
|
@@ -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
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from mapFolding.
|
|
1
|
+
from mapFolding.importSelector import countSequential, countParallel, countInitialize
|
|
2
|
+
from mapFolding import indexThe
|
|
2
3
|
from numpy import integer
|
|
3
4
|
from numpy.typing import NDArray
|
|
4
5
|
from typing import Any, Tuple
|
|
@@ -25,6 +26,10 @@ def _countFolds(connectionGraph: NDArray[integer[Any]], foldsSubTotals: NDArray[
|
|
|
25
26
|
- and just a few dozen-jillion other things.
|
|
26
27
|
|
|
27
28
|
"""
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
# print("babbage")
|
|
30
|
+
countInitialize(connectionGraph=connectionGraph, gapsWhere=gapsWhere, my=my, the=the, track=track)
|
|
31
|
+
|
|
32
|
+
if the[indexThe.taskDivisions.value] > 0:
|
|
33
|
+
countParallel(connectionGraph=connectionGraph, foldsSubTotals=foldsSubTotals, gapsWherePARALLEL=gapsWhere, myPARALLEL=my, the=the, trackPARALLEL=track)
|
|
34
|
+
else:
|
|
35
|
+
countSequential(connectionGraph=connectionGraph, foldsSubTotals=foldsSubTotals, gapsWhere=gapsWhere, my=my, the=the, track=track)
|
|
@@ -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
|
|
|
@@ -230,11 +240,42 @@ def parseDimensions(dimensions: Sequence[int], parameterName: str = 'unnamed par
|
|
|
230
240
|
raise ValueError(f"Dimension {dimension} must be non-negative")
|
|
231
241
|
listNonNegative.append(dimension)
|
|
232
242
|
|
|
233
|
-
if not listNonNegative:
|
|
234
|
-
raise ValueError("At least one dimension must be non-negative")
|
|
235
|
-
|
|
236
243
|
return listNonNegative
|
|
237
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
|
+
|
|
238
279
|
def setCPUlimit(CPUlimit: Union[bool, float, int, None]) -> int:
|
|
239
280
|
"""Sets CPU limit for Numba concurrent operations. Note that it can only affect Numba-jitted functions that have not yet been imported.
|
|
240
281
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
"""An incompetent benchmarking module for mapFolding."""
|
|
2
2
|
from typing import Callable
|
|
3
|
+
import multiprocessing
|
|
3
4
|
import numpy
|
|
4
5
|
import pathlib
|
|
5
6
|
import time
|
|
@@ -57,7 +58,7 @@ def runBenchmarks(benchmarkIterations: int = 30) -> None:
|
|
|
57
58
|
listCartesianProduct = list(itertools.product(listParametersOEIS, range(benchmarkIterations)))
|
|
58
59
|
with ProcessPoolExecutor(max_workers) as concurrencyManager:
|
|
59
60
|
listConcurrency = [concurrencyManager.submit(oeisIDfor_n, *parameters[0]) for parameters in listCartesianProduct]
|
|
60
|
-
for
|
|
61
|
+
for _complete in tqdm(as_completed(listConcurrency), total=len(listCartesianProduct)):
|
|
61
62
|
pass
|
|
62
63
|
|
|
63
64
|
if __name__ == '__main__':
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from mapFolding.lovelace import countSequential
|
|
2
|
+
from mapFolding.lovelace import countParallel
|
|
3
|
+
from mapFolding.lovelace import countInitialize
|
|
4
|
+
|
|
5
|
+
# from mapFolding.countSequential import countSequential
|
|
6
|
+
# from mapFolding.countParallel import countParallel
|
|
7
|
+
# from mapFolding.countInitialize import countInitialize
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
from mapFolding import indexMy, indexThe, indexTrack
|
|
2
|
+
import numba
|
|
3
|
+
|
|
4
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
5
|
+
def activeGapIncrement(my):
|
|
6
|
+
my[indexMy.gap1ndex.value] += 1
|
|
7
|
+
|
|
8
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
9
|
+
def activeLeafGreaterThan0Condition(my):
|
|
10
|
+
return my[indexMy.leaf1ndex.value] > 0
|
|
11
|
+
|
|
12
|
+
@numba.jit((numba.int64[::1],numba.int64[::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
13
|
+
def activeLeafGreaterThanLeavesTotalCondition(my, the):
|
|
14
|
+
return my[indexMy.leaf1ndex.value] > the[indexThe.leavesTotal.value]
|
|
15
|
+
|
|
16
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
17
|
+
def activeLeafIsTheFirstLeafCondition(my):
|
|
18
|
+
return my[indexMy.leaf1ndex.value] <= 1
|
|
19
|
+
|
|
20
|
+
@numba.jit((numba.int64[::1],numba.int64[::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
21
|
+
def allDimensionsAreUnconstrained(my, the):
|
|
22
|
+
return my[indexMy.dimensionsUnconstrained.value] == the[indexThe.dimensionsTotal.value]
|
|
23
|
+
|
|
24
|
+
@numba.jit((numba.int64[::1],numba.int64[:,::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
25
|
+
def backtrack(my, track):
|
|
26
|
+
my[indexMy.leaf1ndex.value] -= 1
|
|
27
|
+
track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]] = track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]
|
|
28
|
+
track[indexTrack.leafAbove.value, track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]] = track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]
|
|
29
|
+
|
|
30
|
+
@numba.jit((numba.int64[::1],numba.int64[:,::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
31
|
+
def backtrackCondition(my, track):
|
|
32
|
+
return my[indexMy.leaf1ndex.value] > 0 and my[indexMy.gap1ndex.value] == track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]
|
|
33
|
+
|
|
34
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
35
|
+
def gap1ndexCeilingIncrement(my):
|
|
36
|
+
my[indexMy.gap1ndexCeiling.value] += 1
|
|
37
|
+
|
|
38
|
+
@numba.jit((numba.int64[::1],numba.int64[::1],numba.int64[:,::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
39
|
+
def countGaps(gapsWhere, my, track):
|
|
40
|
+
gapsWhere[my[indexMy.gap1ndexCeiling.value]] = my[indexMy.leafConnectee.value]
|
|
41
|
+
if track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] == 0:
|
|
42
|
+
gap1ndexCeilingIncrement(my=my)
|
|
43
|
+
track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] += 1
|
|
44
|
+
|
|
45
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
46
|
+
def dimension1ndexIncrement(my):
|
|
47
|
+
my[indexMy.dimension1ndex.value] += 1
|
|
48
|
+
|
|
49
|
+
@numba.jit((numba.int64[:,:,::1], numba.int64[::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
50
|
+
def dimensionsUnconstrainedCondition(connectionGraph, my):
|
|
51
|
+
return connectionGraph[my[indexMy.dimension1ndex.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]] == my[indexMy.leaf1ndex.value]
|
|
52
|
+
|
|
53
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
54
|
+
def dimensionsUnconstrainedIncrement(my):
|
|
55
|
+
my[indexMy.dimensionsUnconstrained.value] += 1
|
|
56
|
+
|
|
57
|
+
@numba.jit((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)
|
|
58
|
+
def filterCommonGaps(gapsWhere, my, the, track):
|
|
59
|
+
gapsWhere[my[indexMy.gap1ndex.value]] = gapsWhere[my[indexMy.indexMiniGap.value]]
|
|
60
|
+
if track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] == the[indexThe.dimensionsTotal.value] - my[indexMy.dimensionsUnconstrained.value]:
|
|
61
|
+
activeGapIncrement(my=my)
|
|
62
|
+
track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] = 0
|
|
63
|
+
|
|
64
|
+
@numba.jit((numba.int64[::1],numba.int64[:,::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
65
|
+
def findGapsInitializeVariables(my, track):
|
|
66
|
+
my[indexMy.dimensionsUnconstrained.value] = 0
|
|
67
|
+
my[indexMy.gap1ndexCeiling.value] = track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]
|
|
68
|
+
my[indexMy.dimension1ndex.value] = 1
|
|
69
|
+
|
|
70
|
+
@numba.jit((numba.int64[::1],numba.int64[::1],numba.int64[::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
71
|
+
def foldsSubTotalIncrement(foldsSubTotals, my, the):
|
|
72
|
+
foldsSubTotals[my[indexMy.taskIndex.value]] += the[indexThe.leavesTotal.value]
|
|
73
|
+
|
|
74
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
75
|
+
def indexMiniGapIncrement(my):
|
|
76
|
+
my[indexMy.indexMiniGap.value] += 1
|
|
77
|
+
|
|
78
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
79
|
+
def indexMiniGapInitialization(my):
|
|
80
|
+
my[indexMy.indexMiniGap.value] = my[indexMy.gap1ndex.value]
|
|
81
|
+
|
|
82
|
+
@numba.jit((numba.int64[::1],numba.int64[::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
83
|
+
def insertUnconstrainedLeaf(gapsWhere, my):
|
|
84
|
+
my[indexMy.indexLeaf.value] = 0
|
|
85
|
+
while my[indexMy.indexLeaf.value] < my[indexMy.leaf1ndex.value]:
|
|
86
|
+
gapsWhere[my[indexMy.gap1ndexCeiling.value]] = my[indexMy.indexLeaf.value]
|
|
87
|
+
my[indexMy.gap1ndexCeiling.value] += 1
|
|
88
|
+
my[indexMy.indexLeaf.value] += 1
|
|
89
|
+
|
|
90
|
+
@numba.jit((numba.int64[:,::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
91
|
+
def leafBelowSentinelIs1Condition(track):
|
|
92
|
+
return track[indexTrack.leafBelow.value, 0] == 1
|
|
93
|
+
|
|
94
|
+
@numba.jit((numba.int64[:,:,::1], numba.int64[::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
95
|
+
def leafConnecteeInitialization(connectionGraph, my):
|
|
96
|
+
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.dimension1ndex.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]]
|
|
97
|
+
|
|
98
|
+
@numba.jit((numba.int64[:,:,::1], numba.int64[::1],numba.int64[:,::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
99
|
+
def leafConnecteeUpdate(connectionGraph, my, track):
|
|
100
|
+
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.dimension1ndex.value], my[indexMy.leaf1ndex.value], track[indexTrack.leafBelow.value, my[indexMy.leafConnectee.value]]]
|
|
101
|
+
|
|
102
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
103
|
+
def loopingLeavesConnectedToActiveLeaf(my):
|
|
104
|
+
return my[indexMy.leafConnectee.value] != my[indexMy.leaf1ndex.value]
|
|
105
|
+
|
|
106
|
+
@numba.jit((numba.int64[::1],numba.int64[::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
107
|
+
def loopingTheDimensions(my, the):
|
|
108
|
+
return my[indexMy.dimension1ndex.value] <= the[indexThe.dimensionsTotal.value]
|
|
109
|
+
|
|
110
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
111
|
+
def loopingToActiveGapCeiling(my):
|
|
112
|
+
return my[indexMy.indexMiniGap.value] < my[indexMy.gap1ndexCeiling.value]
|
|
113
|
+
|
|
114
|
+
@numba.jit((numba.int64[::1],numba.int64[::1],numba.int64[:,::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
115
|
+
def placeLeaf(gapsWhere, my, track):
|
|
116
|
+
my[indexMy.gap1ndex.value] -= 1
|
|
117
|
+
track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]] = gapsWhere[my[indexMy.gap1ndex.value]]
|
|
118
|
+
track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]] = track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]]
|
|
119
|
+
track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
|
|
120
|
+
track[indexTrack.leafAbove.value, track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
|
|
121
|
+
track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value]] = my[indexMy.gap1ndex.value]
|
|
122
|
+
my[indexMy.leaf1ndex.value] += 1
|
|
123
|
+
|
|
124
|
+
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
125
|
+
def placeLeafCondition(my):
|
|
126
|
+
return my[indexMy.leaf1ndex.value] > 0
|
|
127
|
+
|
|
128
|
+
@numba.jit((numba.int64[::1],numba.int64[::1]), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
129
|
+
def thereAreComputationDivisionsYouMightSkip(my, the):
|
|
130
|
+
return my[indexMy.leaf1ndex.value] != the[indexThe.taskDivisions.value] or my[indexMy.leafConnectee.value] % the[indexThe.taskDivisions.value] == my[indexMy.taskIndex.value]
|
|
131
|
+
|
|
132
|
+
@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)
|
|
133
|
+
def countInitialize(connectionGraph, gapsWhere, my, the, track):
|
|
134
|
+
while activeLeafGreaterThan0Condition(my=my):
|
|
135
|
+
if activeLeafIsTheFirstLeafCondition(my=my) or leafBelowSentinelIs1Condition(track=track):
|
|
136
|
+
findGapsInitializeVariables(my=my, track=track)
|
|
137
|
+
while loopingTheDimensions(my=my, the=the):
|
|
138
|
+
if dimensionsUnconstrainedCondition(connectionGraph=connectionGraph, my=my):
|
|
139
|
+
dimensionsUnconstrainedIncrement(my=my)
|
|
140
|
+
else:
|
|
141
|
+
leafConnecteeInitialization(connectionGraph=connectionGraph, my=my)
|
|
142
|
+
while loopingLeavesConnectedToActiveLeaf(my=my):
|
|
143
|
+
countGaps(gapsWhere=gapsWhere, my=my, track=track)
|
|
144
|
+
leafConnecteeUpdate(connectionGraph=connectionGraph, my=my, track=track)
|
|
145
|
+
dimension1ndexIncrement(my=my)
|
|
146
|
+
if allDimensionsAreUnconstrained(my=my, the=the):
|
|
147
|
+
insertUnconstrainedLeaf(gapsWhere=gapsWhere, my=my)
|
|
148
|
+
indexMiniGapInitialization(my=my)
|
|
149
|
+
while loopingToActiveGapCeiling(my=my):
|
|
150
|
+
filterCommonGaps(gapsWhere=gapsWhere, my=my, the=the, track=track)
|
|
151
|
+
indexMiniGapIncrement(my=my)
|
|
152
|
+
if placeLeafCondition(my=my):
|
|
153
|
+
placeLeaf(gapsWhere=gapsWhere, my=my, track=track)
|
|
154
|
+
if my[indexMy.gap1ndex.value] > 0:
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
@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)
|
|
158
|
+
def countSequential(connectionGraph, foldsSubTotals, gapsWhere, my, the, track):
|
|
159
|
+
while activeLeafGreaterThan0Condition(my=my):
|
|
160
|
+
if activeLeafIsTheFirstLeafCondition(my=my) or leafBelowSentinelIs1Condition(track=track):
|
|
161
|
+
if activeLeafGreaterThanLeavesTotalCondition(my=my, the=the):
|
|
162
|
+
foldsSubTotalIncrement(foldsSubTotals=foldsSubTotals, my=my, the=the)
|
|
163
|
+
else:
|
|
164
|
+
findGapsInitializeVariables(my=my, track=track)
|
|
165
|
+
while loopingTheDimensions(my=my, the=the):
|
|
166
|
+
if dimensionsUnconstrainedCondition(connectionGraph=connectionGraph, my=my):
|
|
167
|
+
dimensionsUnconstrainedIncrement(my=my)
|
|
168
|
+
else:
|
|
169
|
+
leafConnecteeInitialization(connectionGraph=connectionGraph, my=my)
|
|
170
|
+
while loopingLeavesConnectedToActiveLeaf(my=my):
|
|
171
|
+
countGaps(gapsWhere=gapsWhere, my=my, track=track)
|
|
172
|
+
leafConnecteeUpdate(connectionGraph=connectionGraph, my=my, track=track)
|
|
173
|
+
dimension1ndexIncrement(my=my)
|
|
174
|
+
indexMiniGapInitialization(my=my)
|
|
175
|
+
while loopingToActiveGapCeiling(my=my):
|
|
176
|
+
filterCommonGaps(gapsWhere=gapsWhere, my=my, the=the, track=track)
|
|
177
|
+
indexMiniGapIncrement(my=my)
|
|
178
|
+
while backtrackCondition(my=my, track=track):
|
|
179
|
+
backtrack(my=my, track=track)
|
|
180
|
+
if placeLeafCondition(my=my):
|
|
181
|
+
placeLeaf(gapsWhere=gapsWhere, my=my, track=track)
|
|
182
|
+
|
|
183
|
+
@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)
|
|
184
|
+
def countParallel(connectionGraph, foldsSubTotals, gapsWherePARALLEL, myPARALLEL, the, trackPARALLEL):
|
|
185
|
+
for indexSherpa in numba.prange(the[indexThe.taskDivisions.value]):
|
|
186
|
+
gapsWhere = gapsWherePARALLEL.copy()
|
|
187
|
+
my = myPARALLEL.copy()
|
|
188
|
+
my[indexMy.taskIndex.value] = indexSherpa
|
|
189
|
+
track = trackPARALLEL.copy()
|
|
190
|
+
while activeLeafGreaterThan0Condition(my=my):
|
|
191
|
+
if activeLeafIsTheFirstLeafCondition(my=my) or leafBelowSentinelIs1Condition(track=track):
|
|
192
|
+
if activeLeafGreaterThanLeavesTotalCondition(my=my, the=the):
|
|
193
|
+
foldsSubTotalIncrement(foldsSubTotals=foldsSubTotals, my=my, the=the)
|
|
194
|
+
else:
|
|
195
|
+
findGapsInitializeVariables(my=my, track=track)
|
|
196
|
+
while loopingTheDimensions(my=my, the=the):
|
|
197
|
+
if dimensionsUnconstrainedCondition(connectionGraph=connectionGraph, my=my):
|
|
198
|
+
dimensionsUnconstrainedIncrement(my=my)
|
|
199
|
+
else:
|
|
200
|
+
leafConnecteeInitialization(connectionGraph=connectionGraph, my=my)
|
|
201
|
+
while loopingLeavesConnectedToActiveLeaf(my=my):
|
|
202
|
+
if thereAreComputationDivisionsYouMightSkip(my=my, the=the):
|
|
203
|
+
countGaps(gapsWhere=gapsWhere, my=my, track=track)
|
|
204
|
+
leafConnecteeUpdate(connectionGraph=connectionGraph, my=my, track=track)
|
|
205
|
+
dimension1ndexIncrement(my=my)
|
|
206
|
+
indexMiniGapInitialization(my=my)
|
|
207
|
+
while loopingToActiveGapCeiling(my=my):
|
|
208
|
+
filterCommonGaps(gapsWhere=gapsWhere, my=my, the=the, track=track)
|
|
209
|
+
indexMiniGapIncrement(my=my)
|
|
210
|
+
while backtrackCondition(my=my, track=track):
|
|
211
|
+
backtrack(my=my, track=track)
|
|
212
|
+
if placeLeafCondition(my=my):
|
|
213
|
+
placeLeaf(gapsWhere=gapsWhere, my=my, track=track)
|
|
@@ -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
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from mapFolding import indexMy, indexThe, indexTrack
|
|
2
|
+
import ast
|
|
3
|
+
import copy
|
|
4
|
+
import pathlib
|
|
5
|
+
|
|
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
|
|
12
|
+
|
|
13
|
+
class RecursiveInlinerWithEnum(ast.NodeTransformer):
|
|
14
|
+
def __init__(self, dictionaryFunctions, dictionaryEnumValues):
|
|
15
|
+
self.dictionaryFunctions = dictionaryFunctions
|
|
16
|
+
self.dictionaryEnumValues = dictionaryEnumValues
|
|
17
|
+
self.processed = set() # Track processed functions to avoid infinite recursion
|
|
18
|
+
|
|
19
|
+
def inlineFunctionBody(self, functionName):
|
|
20
|
+
if functionName in self.processed:
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
self.processed.add(functionName)
|
|
24
|
+
inlineDefinition = self.dictionaryFunctions[functionName]
|
|
25
|
+
# Recursively process the function body
|
|
26
|
+
for node in ast.walk(inlineDefinition):
|
|
27
|
+
self.visit(node)
|
|
28
|
+
return inlineDefinition
|
|
29
|
+
|
|
30
|
+
def visit_Attribute(self, node):
|
|
31
|
+
# Substitute enum identifiers (e.g., indexMy.leaf1ndex.value)
|
|
32
|
+
if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name):
|
|
33
|
+
enumPath = f"{node.value.value.id}.{node.value.attr}.{node.attr}"
|
|
34
|
+
if enumPath in self.dictionaryEnumValues:
|
|
35
|
+
return ast.Constant(value=self.dictionaryEnumValues[enumPath])
|
|
36
|
+
return self.generic_visit(node)
|
|
37
|
+
|
|
38
|
+
def visit_Call(self, node):
|
|
39
|
+
callNode = self.generic_visit(node)
|
|
40
|
+
if isinstance(callNode, ast.Call) and isinstance(callNode.func, ast.Name) and callNode.func.id in self.dictionaryFunctions:
|
|
41
|
+
inlineDefinition = self.inlineFunctionBody(callNode.func.id)
|
|
42
|
+
if inlineDefinition and inlineDefinition.body:
|
|
43
|
+
lastStmt = inlineDefinition.body[-1]
|
|
44
|
+
if isinstance(lastStmt, ast.Return) and lastStmt.value is not None:
|
|
45
|
+
return self.visit(lastStmt.value)
|
|
46
|
+
elif isinstance(lastStmt, ast.Expr) and lastStmt.value is not None:
|
|
47
|
+
return self.visit(lastStmt.value)
|
|
48
|
+
return None
|
|
49
|
+
return callNode
|
|
50
|
+
|
|
51
|
+
def visit_Expr(self, node):
|
|
52
|
+
if isinstance(node.value, ast.Call):
|
|
53
|
+
if isinstance(node.value.func, ast.Name) and node.value.func.id in self.dictionaryFunctions:
|
|
54
|
+
inlineDefinition = self.inlineFunctionBody(node.value.func.id)
|
|
55
|
+
if inlineDefinition:
|
|
56
|
+
return [self.visit(stmt) for stmt in inlineDefinition.body]
|
|
57
|
+
return self.generic_visit(node)
|
|
58
|
+
|
|
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."""
|
|
62
|
+
requiredImports = set()
|
|
63
|
+
|
|
64
|
+
class ImportFinder(ast.NodeVisitor):
|
|
65
|
+
def visit_Name(self, node):
|
|
66
|
+
if node.id in {'numba'}:
|
|
67
|
+
requiredImports.add(node.id)
|
|
68
|
+
self.generic_visit(node)
|
|
69
|
+
|
|
70
|
+
def visitDecorator(self, node):
|
|
71
|
+
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
|
|
72
|
+
if node.func.id == 'jit':
|
|
73
|
+
requiredImports.add('numba')
|
|
74
|
+
self.generic_visit(node)
|
|
75
|
+
|
|
76
|
+
ImportFinder().visit(node)
|
|
77
|
+
return requiredImports
|
|
78
|
+
|
|
79
|
+
def generateImports(requiredImports):
|
|
80
|
+
"""Generate import statements based on required modules."""
|
|
81
|
+
importStatements = []
|
|
82
|
+
|
|
83
|
+
# Map of module names to their import statements
|
|
84
|
+
importMapping = {
|
|
85
|
+
'numba': 'import numba',
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
for moduleName in sorted(requiredImports):
|
|
89
|
+
if moduleName in importMapping:
|
|
90
|
+
importStatements.append(importMapping[moduleName])
|
|
91
|
+
|
|
92
|
+
return '\n'.join(importStatements)
|
|
93
|
+
|
|
94
|
+
def inlineFunctions(sourceCode, targetFunctionName, dictionaryEnumValues):
|
|
95
|
+
dictionaryParsed = ast.parse(sourceCode)
|
|
96
|
+
dictionaryFunctions = {
|
|
97
|
+
element.name: element
|
|
98
|
+
for element in dictionaryParsed.body
|
|
99
|
+
if isinstance(element, ast.FunctionDef)
|
|
100
|
+
}
|
|
101
|
+
nodeTarget = dictionaryFunctions[targetFunctionName]
|
|
102
|
+
nodeInliner = RecursiveInlinerWithEnum(dictionaryFunctions, dictionaryEnumValues)
|
|
103
|
+
nodeInlined = nodeInliner.visit(nodeTarget)
|
|
104
|
+
ast.fix_missing_locations(nodeInlined)
|
|
105
|
+
|
|
106
|
+
# Generate imports
|
|
107
|
+
requiredImports = findRequiredImports(nodeInlined)
|
|
108
|
+
importStatements = generateImports(requiredImports)
|
|
109
|
+
|
|
110
|
+
# Combine imports with inlined code
|
|
111
|
+
inlinedCode = importStatements + '\n\n' + ast.unparse(ast.Module(body=[nodeInlined], type_ignores=[]))
|
|
112
|
+
return inlinedCode
|
|
113
|
+
|
|
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)
|