mapFolding 0.2.4__tar.gz → 0.2.6__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.4 → mapfolding-0.2.6}/PKG-INFO +8 -8
- {mapfolding-0.2.4 → mapfolding-0.2.6}/README.md +6 -1
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/__init__.py +1 -1
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/babbage.py +6 -6
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/beDRY.py +75 -37
- mapfolding-0.2.6/mapFolding/importSelector.py +7 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/lovelace.py +37 -37
- mapfolding-0.2.4/mapFolding/JAX/lunnanJAX.py → mapfolding-0.2.6/mapFolding/reference/jax.py +2 -0
- {mapfolding-0.2.4/mapFolding → mapfolding-0.2.6/mapFolding/someAssemblyRequired}/inlineAfunction.py +59 -31
- mapfolding-0.2.6/mapFolding/someAssemblyRequired/jobsAndTasks.py +47 -0
- mapfolding-0.2.6/mapFolding/someAssemblyRequired/makeNuitkaSource.py +99 -0
- mapfolding-0.2.6/mapFolding/someAssemblyRequired/makeNumbaJob.py +144 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/startHere.py +9 -18
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/theSSOT.py +9 -8
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding.egg-info/PKG-INFO +8 -8
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding.egg-info/SOURCES.txt +6 -8
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding.egg-info/requires.txt +0 -6
- {mapfolding-0.2.4 → mapfolding-0.2.6}/pyproject.toml +4 -5
- {mapfolding-0.2.4 → mapfolding-0.2.6}/tests/conftest.py +7 -9
- {mapfolding-0.2.4 → mapfolding-0.2.6}/tests/test_other.py +45 -31
- mapfolding-0.2.4/mapFolding/JAX/taskJAX.py +0 -313
- mapfolding-0.2.4/mapFolding/countInitialize.py +0 -44
- mapfolding-0.2.4/mapFolding/countParallel.py +0 -49
- mapfolding-0.2.4/mapFolding/countSequential.py +0 -43
- mapfolding-0.2.4/mapFolding/importSelector.py +0 -12
- mapfolding-0.2.4/tests/test_temporary.py +0 -25
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/benchmarks/benchmarking.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/oeis.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/reference/flattened.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/reference/hunterNumba.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/reference/irvineJavaPort.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/reference/lunnan.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/reference/lunnanNumpy.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/reference/lunnanWhile.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/reference/rotatedEntryPoint.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding/reference/total_countPlus1vsPlusN.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding.egg-info/dependency_links.txt +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding.egg-info/entry_points.txt +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/mapFolding.egg-info/top_level.txt +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/setup.cfg +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/tests/__init__.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/tests/pythons_idiotic_namespace.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/tests/test_oeis.py +0 -0
- {mapfolding-0.2.4 → mapfolding-0.2.6}/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.6
|
|
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)
|
|
@@ -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,5 +1,5 @@
|
|
|
1
1
|
from mapFolding.importSelector import countSequential, countParallel, countInitialize
|
|
2
|
-
from mapFolding import
|
|
2
|
+
from mapFolding import indexMy
|
|
3
3
|
from numpy import integer
|
|
4
4
|
from numpy.typing import NDArray
|
|
5
5
|
from typing import Any, Tuple
|
|
@@ -7,7 +7,7 @@ import numba
|
|
|
7
7
|
import numpy
|
|
8
8
|
|
|
9
9
|
@numba.jit(cache=True)
|
|
10
|
-
def _countFolds(connectionGraph: NDArray[integer[Any]],
|
|
10
|
+
def _countFolds(connectionGraph: NDArray[integer[Any]], foldGroups: NDArray[integer[Any]], gapsWhere: NDArray[integer[Any]], mapShape: Tuple[int, ...], my: NDArray[integer[Any]], track: NDArray[integer[Any]]):
|
|
11
11
|
"""
|
|
12
12
|
What in tarnation is this stupid module and function?
|
|
13
13
|
|
|
@@ -27,9 +27,9 @@ def _countFolds(connectionGraph: NDArray[integer[Any]], foldsSubTotals: NDArray[
|
|
|
27
27
|
|
|
28
28
|
"""
|
|
29
29
|
# print("babbage")
|
|
30
|
-
countInitialize(connectionGraph=connectionGraph, gapsWhere=gapsWhere, my=my,
|
|
30
|
+
countInitialize(connectionGraph=connectionGraph, gapsWhere=gapsWhere, my=my, track=track)
|
|
31
31
|
|
|
32
|
-
if
|
|
33
|
-
countParallel(connectionGraph=connectionGraph,
|
|
32
|
+
if my[indexMy.taskDivisions.value] > 0:
|
|
33
|
+
countParallel(connectionGraph=connectionGraph, foldGroups=foldGroups, gapsWherePARALLEL=gapsWhere, myPARALLEL=my, trackPARALLEL=track)
|
|
34
34
|
else:
|
|
35
|
-
countSequential(connectionGraph=connectionGraph,
|
|
35
|
+
countSequential(connectionGraph=connectionGraph, foldGroups=foldGroups, gapsWhere=gapsWhere, my=my, track=track)
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
"""A relatively stable API for oft-needed functionality."""
|
|
2
|
-
from mapFolding import dtypeDefault, dtypeLarge
|
|
3
|
-
from mapFolding import indexMy,
|
|
2
|
+
from mapFolding import dtypeDefault, dtypeLarge, dtypeSmall, pathJobDEFAULT
|
|
3
|
+
from mapFolding import indexMy, indexTrack, computationState
|
|
4
4
|
from mapFolding import intInnit, defineConcurrencyLimit, oopsieKwargsie
|
|
5
5
|
from numpy import integer
|
|
6
6
|
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').replace('[', 'p').replace(']', '') + '.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.
|
|
@@ -91,10 +101,11 @@ def makeConnectionGraph(listDimensions: Sequence[int], **keywordArguments: Optio
|
|
|
91
101
|
Constructs a multi-dimensional connection graph representing the connections between the leaves of a map with the given dimensions.
|
|
92
102
|
Also called a Cartesian product decomposition or dimensional product mapping.
|
|
93
103
|
|
|
94
|
-
Parameters
|
|
104
|
+
Parameters
|
|
95
105
|
listDimensions: A sequence of integers representing the dimensions of the map.
|
|
96
|
-
|
|
97
|
-
|
|
106
|
+
|
|
107
|
+
Returns
|
|
108
|
+
connectionGraph: A 3D numpy array with shape of (dimensionsTotal, leavesTotal + 1, leavesTotal + 1).
|
|
98
109
|
"""
|
|
99
110
|
datatype = keywordArguments.get('datatype', dtypeDefault)
|
|
100
111
|
mapShape = validateListDimensions(listDimensions)
|
|
@@ -106,39 +117,37 @@ def makeConnectionGraph(listDimensions: Sequence[int], **keywordArguments: Optio
|
|
|
106
117
|
cumulativeProduct = numpy.multiply.accumulate([1] + mapShape, dtype=datatype)
|
|
107
118
|
|
|
108
119
|
# Step 2: create a coordinate system
|
|
109
|
-
coordinateSystem = numpy.zeros((dimensionsTotal
|
|
120
|
+
coordinateSystem = numpy.zeros((dimensionsTotal, leavesTotal + 1), dtype=datatype)
|
|
110
121
|
|
|
111
|
-
for
|
|
122
|
+
for indexDimension in range(dimensionsTotal):
|
|
112
123
|
for leaf1ndex in range(1, leavesTotal + 1):
|
|
113
|
-
coordinateSystem[
|
|
114
|
-
((leaf1ndex - 1) // cumulativeProduct[
|
|
115
|
-
arrayDimensions[
|
|
124
|
+
coordinateSystem[indexDimension, leaf1ndex] = (
|
|
125
|
+
((leaf1ndex - 1) // cumulativeProduct[indexDimension]) %
|
|
126
|
+
arrayDimensions[indexDimension] + 1
|
|
116
127
|
)
|
|
117
128
|
|
|
118
129
|
# Step 3: create and fill the connection graph
|
|
119
|
-
connectionGraph = numpy.zeros((dimensionsTotal
|
|
130
|
+
connectionGraph = numpy.zeros((dimensionsTotal, leavesTotal + 1, leavesTotal + 1), dtype=datatype)
|
|
120
131
|
|
|
121
|
-
for
|
|
132
|
+
for indexDimension in range(dimensionsTotal):
|
|
122
133
|
for activeLeaf1ndex in range(1, leavesTotal + 1):
|
|
123
134
|
for connectee1ndex in range(1, activeLeaf1ndex + 1):
|
|
124
135
|
# Base coordinate conditions
|
|
125
|
-
isFirstCoord = coordinateSystem[
|
|
126
|
-
isLastCoord = coordinateSystem[
|
|
127
|
-
exceedsActive = connectee1ndex + cumulativeProduct[
|
|
136
|
+
isFirstCoord = coordinateSystem[indexDimension, connectee1ndex] == 1
|
|
137
|
+
isLastCoord = coordinateSystem[indexDimension, connectee1ndex] == arrayDimensions[indexDimension]
|
|
138
|
+
exceedsActive = connectee1ndex + cumulativeProduct[indexDimension] > activeLeaf1ndex
|
|
128
139
|
|
|
129
140
|
# Parity check
|
|
130
|
-
isEvenParity = (coordinateSystem[
|
|
131
|
-
(coordinateSystem[
|
|
141
|
+
isEvenParity = (coordinateSystem[indexDimension, activeLeaf1ndex] & 1) == \
|
|
142
|
+
(coordinateSystem[indexDimension, connectee1ndex] & 1)
|
|
132
143
|
|
|
133
144
|
# Determine connection value
|
|
134
145
|
if (isEvenParity and isFirstCoord) or (not isEvenParity and (isLastCoord or exceedsActive)):
|
|
135
|
-
connectionGraph[
|
|
146
|
+
connectionGraph[indexDimension, activeLeaf1ndex, connectee1ndex] = connectee1ndex
|
|
136
147
|
elif isEvenParity and not isFirstCoord:
|
|
137
|
-
connectionGraph[
|
|
148
|
+
connectionGraph[indexDimension, activeLeaf1ndex, connectee1ndex] = connectee1ndex - cumulativeProduct[indexDimension]
|
|
138
149
|
elif not isEvenParity and not (isLastCoord or exceedsActive):
|
|
139
|
-
connectionGraph[
|
|
140
|
-
else:
|
|
141
|
-
connectionGraph[dimension1ndex, activeLeaf1ndex, connectee1ndex] = connectee1ndex
|
|
150
|
+
connectionGraph[indexDimension, activeLeaf1ndex, connectee1ndex] = connectee1ndex + cumulativeProduct[indexDimension]
|
|
142
151
|
|
|
143
152
|
return connectionGraph
|
|
144
153
|
|
|
@@ -148,7 +157,7 @@ def makeDataContainer(shape, datatype: Optional[Type] = None):
|
|
|
148
157
|
datatype = dtypeDefault
|
|
149
158
|
return numpy.zeros(shape, dtype=datatype)
|
|
150
159
|
|
|
151
|
-
def outfitCountFolds(listDimensions: Sequence[int], computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[bool, float, int]] = None, **keywordArguments: Optional[Type]) -> computationState:
|
|
160
|
+
def outfitCountFolds(listDimensions: Sequence[int], computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[bool, float, int]] = None, **keywordArguments: Optional[Type[Any]]) -> computationState:
|
|
152
161
|
"""
|
|
153
162
|
Initializes and configures the computation state for map folding computations.
|
|
154
163
|
|
|
@@ -187,36 +196,38 @@ def outfitCountFolds(listDimensions: Sequence[int], computationDivisions: Option
|
|
|
187
196
|
"""
|
|
188
197
|
datatypeDefault = keywordArguments.get('datatypeDefault', dtypeDefault)
|
|
189
198
|
datatypeLarge = keywordArguments.get('datatypeLarge', dtypeLarge)
|
|
199
|
+
datatypeSmall = keywordArguments.get('datatypeSmall', dtypeSmall)
|
|
190
200
|
|
|
191
|
-
|
|
201
|
+
my = makeDataContainer(len(indexMy), datatypeDefault)
|
|
192
202
|
|
|
193
203
|
mapShape = tuple(sorted(validateListDimensions(listDimensions)))
|
|
194
|
-
the[indexThe.leavesTotal] = getLeavesTotal(mapShape)
|
|
195
|
-
the[indexThe.dimensionsTotal] = len(mapShape)
|
|
196
204
|
concurrencyLimit = setCPUlimit(CPUlimit)
|
|
197
|
-
|
|
205
|
+
my[indexMy.taskDivisions] = getTaskDivisions(computationDivisions, concurrencyLimit, CPUlimit, mapShape)
|
|
198
206
|
|
|
207
|
+
foldGroups = makeDataContainer(max(my[indexMy.taskDivisions] + 1, 2), datatypeLarge)
|
|
208
|
+
foldGroups[-1] = leavesTotal = getLeavesTotal(mapShape)
|
|
209
|
+
|
|
210
|
+
my[indexMy.dimensionsTotal] = len(mapShape)
|
|
211
|
+
my[indexMy.leaf1ndex] = 1
|
|
199
212
|
stateInitialized = computationState(
|
|
200
|
-
connectionGraph = makeConnectionGraph(mapShape, datatype=
|
|
201
|
-
|
|
213
|
+
connectionGraph = makeConnectionGraph(mapShape, datatype=datatypeSmall),
|
|
214
|
+
foldGroups = foldGroups,
|
|
202
215
|
mapShape = mapShape,
|
|
203
|
-
my =
|
|
204
|
-
gapsWhere = makeDataContainer(int(
|
|
205
|
-
|
|
206
|
-
track = makeDataContainer((len(indexTrack), the[indexThe.leavesTotal] + 1), datatypeLarge)
|
|
216
|
+
my = my,
|
|
217
|
+
gapsWhere = makeDataContainer(int(leavesTotal) * int(leavesTotal) + 1, datatypeSmall),
|
|
218
|
+
track = makeDataContainer((len(indexTrack), leavesTotal + 1), datatypeDefault)
|
|
207
219
|
)
|
|
208
220
|
|
|
209
|
-
stateInitialized['my'][indexMy.leaf1ndex.value] = 1
|
|
210
221
|
|
|
211
222
|
return stateInitialized
|
|
212
223
|
|
|
213
|
-
def parseDimensions(dimensions: Sequence[int], parameterName: str = '
|
|
224
|
+
def parseDimensions(dimensions: Sequence[int], parameterName: str = 'listDimensions') -> List[int]:
|
|
214
225
|
"""
|
|
215
226
|
Parse and validate dimensions are non-negative integers.
|
|
216
227
|
|
|
217
228
|
Parameters:
|
|
218
229
|
dimensions: Sequence of integers representing dimensions
|
|
219
|
-
parameterName ('
|
|
230
|
+
parameterName ('listDimensions'): Name of the parameter for error messages. Defaults to 'listDimensions'
|
|
220
231
|
Returns:
|
|
221
232
|
listNonNegative: List of validated non-negative integers
|
|
222
233
|
Raises:
|
|
@@ -232,6 +243,33 @@ def parseDimensions(dimensions: Sequence[int], parameterName: str = 'unnamed par
|
|
|
232
243
|
|
|
233
244
|
return listNonNegative
|
|
234
245
|
|
|
246
|
+
def saveFoldsTotal(pathFilename: Union[str, os.PathLike[str]], foldsTotal: int) -> None:
|
|
247
|
+
"""
|
|
248
|
+
Save foldsTotal with multiple fallback mechanisms.
|
|
249
|
+
|
|
250
|
+
Parameters:
|
|
251
|
+
pathFilename: Target save location
|
|
252
|
+
foldsTotal: Critical computed value to save
|
|
253
|
+
"""
|
|
254
|
+
try:
|
|
255
|
+
pathFilenameFoldsTotal = pathlib.Path(pathFilename)
|
|
256
|
+
pathFilenameFoldsTotal.parent.mkdir(parents=True, exist_ok=True)
|
|
257
|
+
pathFilenameFoldsTotal.write_text(str(foldsTotal))
|
|
258
|
+
except Exception as ERRORmessage:
|
|
259
|
+
try:
|
|
260
|
+
print(f"\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n\n{foldsTotal=}\n\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n")
|
|
261
|
+
print(ERRORmessage)
|
|
262
|
+
print(f"\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n\n{foldsTotal=}\n\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n")
|
|
263
|
+
randomnessPlanB = (int(str(foldsTotal).strip()[-1]) + 1) * ['YO_']
|
|
264
|
+
filenameInfixUnique = ''.join(randomnessPlanB)
|
|
265
|
+
pathFilenamePlanB = os.path.join(os.getcwd(), 'foldsTotal' + filenameInfixUnique + '.txt')
|
|
266
|
+
writeStreamFallback = open(pathFilenamePlanB, 'w')
|
|
267
|
+
writeStreamFallback.write(str(foldsTotal))
|
|
268
|
+
writeStreamFallback.close()
|
|
269
|
+
print(str(pathFilenamePlanB))
|
|
270
|
+
except:
|
|
271
|
+
print(foldsTotal)
|
|
272
|
+
|
|
235
273
|
def setCPUlimit(CPUlimit: Union[bool, float, int, None]) -> int:
|
|
236
274
|
"""Sets CPU limit for Numba concurrent operations. Note that it can only affect Numba-jitted functions that have not yet been imported.
|
|
237
275
|
|
|
@@ -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.someAssemblyRequired.countSequential import countSequential
|
|
6
|
+
# from mapFolding.someAssemblyRequired.countParallel import countParallel
|
|
7
|
+
# from mapFolding.someAssemblyRequired.countInitialize import countInitialize
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from mapFolding import indexMy,
|
|
1
|
+
from mapFolding import indexMy, indexTrack
|
|
2
2
|
import numba
|
|
3
3
|
|
|
4
4
|
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
@@ -10,16 +10,16 @@ def activeLeafGreaterThan0Condition(my):
|
|
|
10
10
|
return my[indexMy.leaf1ndex.value] > 0
|
|
11
11
|
|
|
12
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(
|
|
14
|
-
return my[indexMy.leaf1ndex.value] >
|
|
13
|
+
def activeLeafGreaterThanLeavesTotalCondition(foldGroups, my):
|
|
14
|
+
return my[indexMy.leaf1ndex.value] > foldGroups[-1] # leavesTotal
|
|
15
15
|
|
|
16
16
|
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
17
17
|
def activeLeafIsTheFirstLeafCondition(my):
|
|
18
18
|
return my[indexMy.leaf1ndex.value] <= 1
|
|
19
19
|
|
|
20
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
|
|
22
|
-
return my[indexMy.dimensionsUnconstrained.value] ==
|
|
21
|
+
def allDimensionsAreUnconstrained(my):
|
|
22
|
+
return my[indexMy.dimensionsUnconstrained.value] == my[indexMy.dimensionsTotal.value]
|
|
23
23
|
|
|
24
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
25
|
def backtrack(my, track):
|
|
@@ -44,20 +44,20 @@ def countGaps(gapsWhere, my, track):
|
|
|
44
44
|
|
|
45
45
|
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
46
46
|
def dimension1ndexIncrement(my):
|
|
47
|
-
my[indexMy.
|
|
47
|
+
my[indexMy.indexDimension.value] += 1
|
|
48
48
|
|
|
49
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
50
|
def dimensionsUnconstrainedCondition(connectionGraph, my):
|
|
51
|
-
return connectionGraph[my[indexMy.
|
|
51
|
+
return connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]] == my[indexMy.leaf1ndex.value]
|
|
52
52
|
|
|
53
53
|
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
54
54
|
def dimensionsUnconstrainedIncrement(my):
|
|
55
55
|
my[indexMy.dimensionsUnconstrained.value] += 1
|
|
56
56
|
|
|
57
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,
|
|
58
|
+
def filterCommonGaps(gapsWhere, my, track):
|
|
59
59
|
gapsWhere[my[indexMy.gap1ndex.value]] = gapsWhere[my[indexMy.indexMiniGap.value]]
|
|
60
|
-
if track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] ==
|
|
60
|
+
if track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] == my[indexMy.dimensionsTotal.value] - my[indexMy.dimensionsUnconstrained.value]:
|
|
61
61
|
activeGapIncrement(my=my)
|
|
62
62
|
track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] = 0
|
|
63
63
|
|
|
@@ -65,11 +65,11 @@ def filterCommonGaps(gapsWhere, my, the, track):
|
|
|
65
65
|
def findGapsInitializeVariables(my, track):
|
|
66
66
|
my[indexMy.dimensionsUnconstrained.value] = 0
|
|
67
67
|
my[indexMy.gap1ndexCeiling.value] = track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]
|
|
68
|
-
my[indexMy.
|
|
68
|
+
my[indexMy.indexDimension.value] = 0
|
|
69
69
|
|
|
70
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(
|
|
72
|
-
|
|
71
|
+
def foldsSubTotalIncrement(foldGroups, my):
|
|
72
|
+
foldGroups[my[indexMy.taskIndex.value]] += 1
|
|
73
73
|
|
|
74
74
|
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
75
75
|
def indexMiniGapIncrement(my):
|
|
@@ -93,19 +93,19 @@ def leafBelowSentinelIs1Condition(track):
|
|
|
93
93
|
|
|
94
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
95
|
def leafConnecteeInitialization(connectionGraph, my):
|
|
96
|
-
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.
|
|
96
|
+
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]]
|
|
97
97
|
|
|
98
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
99
|
def leafConnecteeUpdate(connectionGraph, my, track):
|
|
100
|
-
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.
|
|
100
|
+
my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], track[indexTrack.leafBelow.value, my[indexMy.leafConnectee.value]]]
|
|
101
101
|
|
|
102
102
|
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
103
103
|
def loopingLeavesConnectedToActiveLeaf(my):
|
|
104
104
|
return my[indexMy.leafConnectee.value] != my[indexMy.leaf1ndex.value]
|
|
105
105
|
|
|
106
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
|
|
108
|
-
return my[indexMy.
|
|
107
|
+
def loopingTheDimensions(my):
|
|
108
|
+
return my[indexMy.indexDimension.value] < my[indexMy.dimensionsTotal.value]
|
|
109
109
|
|
|
110
110
|
@numba.jit((numba.int64[::1],), parallel=False, boundscheck=False, error_model='numpy', fastmath=True, looplift=False, nogil=True, nopython=True)
|
|
111
111
|
def loopingToActiveGapCeiling(my):
|
|
@@ -126,15 +126,15 @@ def placeLeafCondition(my):
|
|
|
126
126
|
return my[indexMy.leaf1ndex.value] > 0
|
|
127
127
|
|
|
128
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
|
|
130
|
-
return my[indexMy.leaf1ndex.value] !=
|
|
129
|
+
def thereAreComputationDivisionsYouMightSkip(my):
|
|
130
|
+
return my[indexMy.leaf1ndex.value] != my[indexMy.taskDivisions.value] or my[indexMy.leafConnectee.value] % my[indexMy.taskDivisions.value] == my[indexMy.taskIndex.value]
|
|
131
131
|
|
|
132
|
-
@numba.jit((numba.int64[:,:,::1], numba.int64[::1], numba.int64[::1], numba.int64[
|
|
133
|
-
def countInitialize(connectionGraph, gapsWhere, my,
|
|
132
|
+
@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)
|
|
133
|
+
def countInitialize(connectionGraph, gapsWhere, my, track):
|
|
134
134
|
while activeLeafGreaterThan0Condition(my=my):
|
|
135
135
|
if activeLeafIsTheFirstLeafCondition(my=my) or leafBelowSentinelIs1Condition(track=track):
|
|
136
136
|
findGapsInitializeVariables(my=my, track=track)
|
|
137
|
-
while loopingTheDimensions(my=my
|
|
137
|
+
while loopingTheDimensions(my=my):
|
|
138
138
|
if dimensionsUnconstrainedCondition(connectionGraph=connectionGraph, my=my):
|
|
139
139
|
dimensionsUnconstrainedIncrement(my=my)
|
|
140
140
|
else:
|
|
@@ -143,26 +143,26 @@ def countInitialize(connectionGraph, gapsWhere, my, the, track):
|
|
|
143
143
|
countGaps(gapsWhere=gapsWhere, my=my, track=track)
|
|
144
144
|
leafConnecteeUpdate(connectionGraph=connectionGraph, my=my, track=track)
|
|
145
145
|
dimension1ndexIncrement(my=my)
|
|
146
|
-
if allDimensionsAreUnconstrained(my=my
|
|
146
|
+
if allDimensionsAreUnconstrained(my=my):
|
|
147
147
|
insertUnconstrainedLeaf(gapsWhere=gapsWhere, my=my)
|
|
148
148
|
indexMiniGapInitialization(my=my)
|
|
149
149
|
while loopingToActiveGapCeiling(my=my):
|
|
150
|
-
filterCommonGaps(gapsWhere=gapsWhere, my=my,
|
|
150
|
+
filterCommonGaps(gapsWhere=gapsWhere, my=my, track=track)
|
|
151
151
|
indexMiniGapIncrement(my=my)
|
|
152
152
|
if placeLeafCondition(my=my):
|
|
153
153
|
placeLeaf(gapsWhere=gapsWhere, my=my, track=track)
|
|
154
154
|
if my[indexMy.gap1ndex.value] > 0:
|
|
155
155
|
return
|
|
156
156
|
|
|
157
|
-
@numba.jit((numba.int64[:,:,::1], numba.int64[::1], numba.int64[::1], numba.int64[::1], numba.int64[
|
|
158
|
-
def countSequential(connectionGraph,
|
|
157
|
+
@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)
|
|
158
|
+
def countSequential(connectionGraph, foldGroups, gapsWhere, my, track):
|
|
159
159
|
while activeLeafGreaterThan0Condition(my=my):
|
|
160
160
|
if activeLeafIsTheFirstLeafCondition(my=my) or leafBelowSentinelIs1Condition(track=track):
|
|
161
|
-
if activeLeafGreaterThanLeavesTotalCondition(
|
|
162
|
-
foldsSubTotalIncrement(
|
|
161
|
+
if activeLeafGreaterThanLeavesTotalCondition(foldGroups=foldGroups, my=my):
|
|
162
|
+
foldsSubTotalIncrement(foldGroups=foldGroups, my=my)
|
|
163
163
|
else:
|
|
164
164
|
findGapsInitializeVariables(my=my, track=track)
|
|
165
|
-
while loopingTheDimensions(my=my
|
|
165
|
+
while loopingTheDimensions(my=my):
|
|
166
166
|
if dimensionsUnconstrainedCondition(connectionGraph=connectionGraph, my=my):
|
|
167
167
|
dimensionsUnconstrainedIncrement(my=my)
|
|
168
168
|
else:
|
|
@@ -173,39 +173,39 @@ def countSequential(connectionGraph, foldsSubTotals, gapsWhere, my, the, track):
|
|
|
173
173
|
dimension1ndexIncrement(my=my)
|
|
174
174
|
indexMiniGapInitialization(my=my)
|
|
175
175
|
while loopingToActiveGapCeiling(my=my):
|
|
176
|
-
filterCommonGaps(gapsWhere=gapsWhere, my=my,
|
|
176
|
+
filterCommonGaps(gapsWhere=gapsWhere, my=my, track=track)
|
|
177
177
|
indexMiniGapIncrement(my=my)
|
|
178
178
|
while backtrackCondition(my=my, track=track):
|
|
179
179
|
backtrack(my=my, track=track)
|
|
180
180
|
if placeLeafCondition(my=my):
|
|
181
181
|
placeLeaf(gapsWhere=gapsWhere, my=my, track=track)
|
|
182
182
|
|
|
183
|
-
@numba.jit((numba.int64[:,:,::1], numba.int64[::1], numba.int64[::1],numba.int64[::1],numba.int64[
|
|
184
|
-
def countParallel(connectionGraph,
|
|
185
|
-
for indexSherpa in numba.prange(
|
|
183
|
+
@numba.jit((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, foldGroups, gapsWherePARALLEL, myPARALLEL, trackPARALLEL):
|
|
185
|
+
for indexSherpa in numba.prange(myPARALLEL[indexMy.taskDivisions.value]):
|
|
186
186
|
gapsWhere = gapsWherePARALLEL.copy()
|
|
187
187
|
my = myPARALLEL.copy()
|
|
188
188
|
my[indexMy.taskIndex.value] = indexSherpa
|
|
189
189
|
track = trackPARALLEL.copy()
|
|
190
190
|
while activeLeafGreaterThan0Condition(my=my):
|
|
191
191
|
if activeLeafIsTheFirstLeafCondition(my=my) or leafBelowSentinelIs1Condition(track=track):
|
|
192
|
-
if activeLeafGreaterThanLeavesTotalCondition(
|
|
193
|
-
foldsSubTotalIncrement(
|
|
192
|
+
if activeLeafGreaterThanLeavesTotalCondition(foldGroups=foldGroups, my=my):
|
|
193
|
+
foldsSubTotalIncrement(foldGroups=foldGroups, my=my)
|
|
194
194
|
else:
|
|
195
195
|
findGapsInitializeVariables(my=my, track=track)
|
|
196
|
-
while loopingTheDimensions(my=my
|
|
196
|
+
while loopingTheDimensions(my=my):
|
|
197
197
|
if dimensionsUnconstrainedCondition(connectionGraph=connectionGraph, my=my):
|
|
198
198
|
dimensionsUnconstrainedIncrement(my=my)
|
|
199
199
|
else:
|
|
200
200
|
leafConnecteeInitialization(connectionGraph=connectionGraph, my=my)
|
|
201
201
|
while loopingLeavesConnectedToActiveLeaf(my=my):
|
|
202
|
-
if thereAreComputationDivisionsYouMightSkip(my=my
|
|
202
|
+
if thereAreComputationDivisionsYouMightSkip(my=my):
|
|
203
203
|
countGaps(gapsWhere=gapsWhere, my=my, track=track)
|
|
204
204
|
leafConnecteeUpdate(connectionGraph=connectionGraph, my=my, track=track)
|
|
205
205
|
dimension1ndexIncrement(my=my)
|
|
206
206
|
indexMiniGapInitialization(my=my)
|
|
207
207
|
while loopingToActiveGapCeiling(my=my):
|
|
208
|
-
filterCommonGaps(gapsWhere=gapsWhere, my=my,
|
|
208
|
+
filterCommonGaps(gapsWhere=gapsWhere, my=my, track=track)
|
|
209
209
|
indexMiniGapIncrement(my=my)
|
|
210
210
|
while backtrackCondition(my=my, track=track):
|
|
211
211
|
backtrack(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
|