mapFolding 0.2.1__py3-none-any.whl → 0.2.2__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 CHANGED
@@ -1,4 +1,5 @@
1
1
  from .theSSOT import *
2
+ from Z0Z_tools import defineConcurrencyLimit, intInnit, oopsieKwargsie
2
3
  from .beDRY import getTaskDivisions, makeConnectionGraph, outfitFoldings, setCPUlimit
3
4
  from .beDRY import getLeavesTotal, parseDimensions, validateListDimensions
4
5
  from .startHere import countFolds
mapFolding/beDRY.py CHANGED
@@ -1,12 +1,14 @@
1
1
  """A relatively stable API for oft-needed functionality."""
2
- from mapFolding.importPackages import intInnit, defineConcurrencyLimit, oopsieKwargsie
2
+ from mapFolding import intInnit, defineConcurrencyLimit, oopsieKwargsie
3
3
  from mapFolding import indexMy, indexThe, indexTrack, computationState
4
+ from mapFolding import dtypeDefault, dtypeLarge, dtypeSmall
4
5
  from typing import Any, List, Optional, Sequence, Type, Union
5
6
  import numpy
6
7
  import numba
7
8
  from numpy.typing import NDArray
8
9
  from numpy import integer
9
10
  import sys
11
+ import operator
10
12
 
11
13
  def getLeavesTotal(listDimensions: Sequence[int]) -> int:
12
14
  """
@@ -32,7 +34,7 @@ def getLeavesTotal(listDimensions: Sequence[int]) -> int:
32
34
 
33
35
  return productDimensions
34
36
 
35
- def getTaskDivisions(computationDivisions: Optional[Union[int, str]], concurrencyLimit: int, the: NDArray[integer[Any]], CPUlimit: Optional[Union[bool, float, int]], listDimensions: Sequence[int]):
37
+ def getTaskDivisions(computationDivisions: Optional[Union[int, str]], concurrencyLimit: int, CPUlimit: Optional[Union[bool, float, int]], listDimensions: Sequence[int]):
36
38
  """
37
39
  Determines whether or how to divide the computation into tasks.
38
40
 
@@ -46,15 +48,12 @@ def getTaskDivisions(computationDivisions: Optional[Union[int, str]], concurrenc
46
48
  - "cpu": limits the divisions to the number of available CPUs, i.e. `concurrencyLimit`
47
49
  concurrencyLimit:
48
50
  Maximum number of concurrent tasks allowed
49
- the:
50
- Array of settings, including `leavesTotal`
51
- CPUlimit: for error reporting
52
51
  listDimensions: for error reporting
52
+ CPUlimit: for error reporting
53
53
 
54
54
  Returns
55
55
  -------
56
- the
57
- Updated settings, including for `taskDivisions`
56
+ taskDivisions:
58
57
 
59
58
  Raises
60
59
  ------
@@ -65,26 +64,27 @@ def getTaskDivisions(computationDivisions: Optional[Union[int, str]], concurrenc
65
64
  -----
66
65
  Task divisions cannot exceed total leaves to prevent duplicate counting of folds.
67
66
  """
68
-
69
67
  if not computationDivisions:
70
- the[indexThe.taskDivisions] = 0
71
- elif isinstance(computationDivisions, int):
72
- the[indexThe.taskDivisions] = computationDivisions
68
+ return 0
69
+ else:
70
+ leavesTotal = getLeavesTotal(listDimensions)
71
+ if isinstance(computationDivisions, int):
72
+ taskDivisions = computationDivisions
73
73
  elif isinstance(computationDivisions, str):
74
74
  computationDivisions = computationDivisions.lower()
75
75
  if computationDivisions == "maximum":
76
- the[indexThe.taskDivisions] = the[indexThe.leavesTotal]
76
+ taskDivisions = leavesTotal
77
77
  elif computationDivisions == "cpu":
78
- the[indexThe.taskDivisions] = min(concurrencyLimit, the[indexThe.leavesTotal])
78
+ taskDivisions = min(concurrencyLimit, leavesTotal)
79
79
  else:
80
80
  raise ValueError(f"I received {computationDivisions} for the parameter, `computationDivisions`, but the so-called programmer didn't implement code for that.")
81
81
 
82
- if the[indexThe.taskDivisions] > the[indexThe.leavesTotal]:
83
- raise ValueError(f"Problem: `taskDivisions`, ({the[indexThe.taskDivisions]}), is greater than `leavesTotal`, ({the[indexThe.leavesTotal]}), which will cause duplicate counting of the folds.\n\nChallenge: you cannot directly set `taskDivisions` or `leavesTotal`. They are derived from parameters that may or may not still be named `computationDivisions`, `CPUlimit` , and `listDimensions` and from dubious-quality Python code.\n\nFor those parameters, I received {computationDivisions=}, {CPUlimit=}, and {listDimensions=}.\n\nPotential solutions: get a different hobby or set `computationDivisions` to a different value.")
82
+ if taskDivisions > leavesTotal:
83
+ raise ValueError(f"Problem: `taskDivisions`, ({taskDivisions}), is greater than `leavesTotal`, ({leavesTotal}), which will cause duplicate counting of the folds.\n\nChallenge: you cannot directly set `taskDivisions` or `leavesTotal`. They are derived from parameters that may or may not still be named `computationDivisions`, `CPUlimit` , and `listDimensions` and from dubious-quality Python code.\n\nFor those parameters, I received {computationDivisions=}, {CPUlimit=}, and {listDimensions=}.\n\nPotential solutions: get a different hobby or set `computationDivisions` to a different value.")
84
84
 
85
- return the
85
+ return taskDivisions
86
86
 
87
- def makeConnectionGraph(listDimensions: Sequence[int], dtype: Optional[Type] = numpy.int64) -> NDArray[integer[Any]]:
87
+ def makeConnectionGraph(listDimensions: Sequence[int], **keywordArguments: Optional[Type]) -> NDArray[integer[Any]]:
88
88
  """
89
89
  Constructs a multi-dimensional connection graph representing the connections between the leaves of a map with the given dimensions.
90
90
  Also called a Cartesian product decomposition or dimensional product mapping.
@@ -94,16 +94,17 @@ def makeConnectionGraph(listDimensions: Sequence[int], dtype: Optional[Type] = n
94
94
  Returns:
95
95
  connectionGraph: A 3D numpy array with shape of (dimensionsTotal + 1, leavesTotal + 1, leavesTotal + 1).
96
96
  """
97
+ datatype = keywordArguments.get('datatype', dtypeDefault)
97
98
  mapShape = validateListDimensions(listDimensions)
98
99
  leavesTotal = getLeavesTotal(mapShape)
99
- arrayDimensions = numpy.array(mapShape, dtype=dtype)
100
+ arrayDimensions = numpy.array(mapShape, dtype=datatype)
100
101
  dimensionsTotal = len(arrayDimensions)
101
102
 
102
103
  # Step 1: find the cumulative product of the map's dimensions
103
- cumulativeProduct = numpy.multiply.accumulate([1] + mapShape, dtype=dtype)
104
+ cumulativeProduct = numpy.multiply.accumulate([1] + mapShape, dtype=datatype)
104
105
 
105
106
  # Step 2: create a coordinate system
106
- coordinateSystem = numpy.zeros((dimensionsTotal + 1, leavesTotal + 1), dtype=dtype)
107
+ coordinateSystem = numpy.zeros((dimensionsTotal + 1, leavesTotal + 1), dtype=datatype)
107
108
 
108
109
  for dimension1ndex in range(1, dimensionsTotal + 1):
109
110
  for leaf1ndex in range(1, leavesTotal + 1):
@@ -113,7 +114,7 @@ def makeConnectionGraph(listDimensions: Sequence[int], dtype: Optional[Type] = n
113
114
  )
114
115
 
115
116
  # Step 3: create and fill the connection graph
116
- connectionGraph = numpy.zeros((dimensionsTotal + 1, leavesTotal + 1, leavesTotal + 1), dtype=dtype)
117
+ connectionGraph = numpy.zeros((dimensionsTotal + 1, leavesTotal + 1, leavesTotal + 1), dtype=datatype)
117
118
 
118
119
  for dimension1ndex in range(1, dimensionsTotal + 1):
119
120
  for activeLeaf1ndex in range(1, leavesTotal + 1):
@@ -139,7 +140,13 @@ def makeConnectionGraph(listDimensions: Sequence[int], dtype: Optional[Type] = n
139
140
 
140
141
  return connectionGraph
141
142
 
142
- def outfitFoldings(listDimensions: Sequence[int], computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[bool, float, int]] = None, dtypeDefault: Optional[Type] = numpy.int64, dtypeLarge: Optional[Type] = numpy.int64, ) -> computationState:
143
+ def makeDataContainer(shape, datatype: Optional[Type] = None):
144
+ """Create a container, probably numpy.ndarray, with the given shape and datatype."""
145
+ if datatype is None:
146
+ datatype = dtypeDefault
147
+ return numpy.zeros(shape, dtype=datatype)
148
+
149
+ def outfitFoldings(listDimensions: Sequence[int], computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[bool, float, int]] = None, **keywordArguments: Optional[Type]) -> computationState:
143
150
  """
144
151
  Initializes and configures the computation state for map folding computations.
145
152
 
@@ -151,10 +158,6 @@ def outfitFoldings(listDimensions: Sequence[int], computationDivisions: Optional
151
158
  Specifies how to divide the computation tasks
152
159
  CPUlimit (None):
153
160
  Limits the CPU usage for computations
154
- dtypeDefault (numpy.int64):
155
- The default numpy dtype to use for arrays
156
- dtypeLarge (numpy.int64):
157
- The numpy dtype to use for larger arrays
158
161
 
159
162
  Returns
160
163
  -------
@@ -165,25 +168,28 @@ def outfitFoldings(listDimensions: Sequence[int], computationDivisions: Optional
165
168
  - mapShape: Validated and sorted dimensions of the map
166
169
  - my: Array for internal state tracking
167
170
  - gapsWhere: Array tracking gap positions
168
- - the: Configured task divisions
171
+ - the: Static settings and metadata
169
172
  - track: Array for tracking computation progress
170
173
  """
174
+ datatypeDefault = keywordArguments.get('datatypeDefault', dtypeDefault)
175
+ datatypeLarge = keywordArguments.get('datatypeLarge', dtypeLarge)
171
176
 
172
- the = numpy.zeros(len(indexThe), dtype=dtypeDefault)
177
+ the = makeDataContainer(len(indexThe), datatypeDefault)
173
178
 
174
179
  mapShape = tuple(sorted(validateListDimensions(listDimensions)))
175
180
  the[indexThe.leavesTotal] = getLeavesTotal(mapShape)
176
181
  the[indexThe.dimensionsTotal] = len(mapShape)
177
182
  concurrencyLimit = setCPUlimit(CPUlimit)
178
-
183
+ the[indexThe.taskDivisions] = getTaskDivisions(computationDivisions, concurrencyLimit, CPUlimit, listDimensions)
184
+
179
185
  stateInitialized = computationState(
180
- connectionGraph = makeConnectionGraph(mapShape, dtype=dtypeDefault),
181
- foldsTotal = numpy.zeros(the[indexThe.leavesTotal], dtype=numpy.int64),
186
+ connectionGraph = makeConnectionGraph(mapShape, datatype=datatypeDefault),
187
+ foldsTotal = makeDataContainer(the[indexThe.leavesTotal], datatypeLarge),
182
188
  mapShape = mapShape,
183
- my = numpy.zeros(len(indexMy), dtype=dtypeLarge),
184
- gapsWhere = numpy.zeros(int(the[indexThe.leavesTotal]) * int(the[indexThe.leavesTotal]) + 1, dtype=dtypeDefault),
185
- the = getTaskDivisions(computationDivisions, concurrencyLimit, the, CPUlimit, listDimensions),
186
- track = numpy.zeros((len(indexTrack), the[indexThe.leavesTotal] + 1), dtype=dtypeLarge)
189
+ my = makeDataContainer(len(indexMy), datatypeLarge),
190
+ gapsWhere = makeDataContainer(int(the[indexThe.leavesTotal]) * int(the[indexThe.leavesTotal]) + 1, datatypeDefault),
191
+ the = the,
192
+ track = makeDataContainer((len(indexTrack), the[indexThe.leavesTotal] + 1), datatypeLarge)
187
193
  )
188
194
 
189
195
  stateInitialized['my'][indexMy.leaf1ndex.value] = 1
mapFolding/oeis.py CHANGED
@@ -65,6 +65,40 @@ settingsOEIShardcodedValues = {
65
65
  oeisIDsImplemented: Final[List[str]] = sorted([oeisID.upper().strip() for oeisID in settingsOEIShardcodedValues.keys()])
66
66
  """Directly implemented OEIS IDs; standardized, e.g., 'A001415'."""
67
67
 
68
+ def _validateOEISid(oeisIDcandidate: str):
69
+ """
70
+ Validates an OEIS sequence ID against implemented sequences.
71
+
72
+ If the provided ID is recognized within the application's implemented
73
+ OEIS sequences, the function returns the verified ID in uppercase.
74
+ Otherwise, a KeyError is raised indicating that the sequence is not
75
+ directly supported.
76
+
77
+ Parameters:
78
+ oeisIDcandidate: The OEIS sequence identifier to validate.
79
+
80
+ Returns:
81
+ oeisID: The validated and possibly modified OEIS sequence ID, if recognized.
82
+
83
+ Raises:
84
+ KeyError: If the provided sequence ID is not directly implemented.
85
+ """
86
+ if oeisIDcandidate in oeisIDsImplemented:
87
+ return oeisIDcandidate
88
+ else:
89
+ oeisIDcleaned = str(oeisIDcandidate).upper().strip()
90
+ if oeisIDcleaned in oeisIDsImplemented:
91
+ return oeisIDcleaned
92
+ else:
93
+ raise KeyError(
94
+ f"OEIS ID {oeisIDcandidate} is not directly implemented.\n"
95
+ f"Available sequences:\n{_formatOEISsequenceInfo()}"
96
+ )
97
+
98
+ def _getFilenameOEISbFile(oeisID: str) -> str:
99
+ oeisID = _validateOEISid(oeisID)
100
+ return f"b{oeisID[1:]}.txt"
101
+
68
102
  def _parseBFileOEIS(OEISbFile: str, oeisID: str) -> Dict[int, int]:
69
103
  """
70
104
  Parses the content of an OEIS b-file for a given sequence ID.
@@ -101,8 +135,6 @@ try:
101
135
  except NameError:
102
136
  _pathCache = pathlib.Path.home() / ".mapFoldingCache"
103
137
 
104
- _formatFilenameCache = "{oeisID}.txt"
105
-
106
138
  def _getOEISidValues(oeisID: str) -> Dict[int, int]:
107
139
  """
108
140
  Retrieves the specified OEIS sequence as a dictionary mapping integer indices
@@ -122,7 +154,7 @@ def _getOEISidValues(oeisID: str) -> Dict[int, int]:
122
154
  IOError: If there is an error reading from or writing to the local cache.
123
155
  """
124
156
 
125
- pathFilenameCache = _pathCache / _formatFilenameCache.format(oeisID=oeisID)
157
+ pathFilenameCache = _pathCache / _getFilenameOEISbFile(oeisID)
126
158
  cacheDays = 7
127
159
 
128
160
  tryCache = False
@@ -137,7 +169,7 @@ def _getOEISidValues(oeisID: str) -> Dict[int, int]:
137
169
  except (ValueError, IOError):
138
170
  tryCache = False
139
171
 
140
- urlOEISbFile = f"https://oeis.org/{oeisID}/b{oeisID[1:]}.txt"
172
+ urlOEISbFile = f"https://oeis.org/{oeisID}/{_getFilenameOEISbFile(oeisID)}"
141
173
  httpResponse: urllib.response.addinfourl = urllib.request.urlopen(urlOEISbFile)
142
174
  OEISbFile = httpResponse.read().decode('utf-8')
143
175
 
@@ -212,36 +244,6 @@ def _formatOEISsequenceInfo() -> str:
212
244
  for oeisID in oeisIDsImplemented
213
245
  )
214
246
 
215
- def _validateOEISid(oeisIDcandidate: str):
216
- """
217
- Validates an OEIS sequence ID against implemented sequences.
218
-
219
- If the provided ID is recognized within the application's implemented
220
- OEIS sequences, the function returns the verified ID in uppercase.
221
- Otherwise, a KeyError is raised indicating that the sequence is not
222
- directly supported.
223
-
224
- Parameters:
225
- oeisIDcandidate: The OEIS sequence identifier to validate.
226
-
227
- Returns:
228
- oeisID: The validated and possibly modified OEIS sequence ID, if recognized.
229
-
230
- Raises:
231
- KeyError: If the provided sequence ID is not directly implemented.
232
- """
233
- if oeisIDcandidate in oeisIDsImplemented:
234
- return oeisIDcandidate
235
- else:
236
- oeisIDcleaned = str(oeisIDcandidate).upper().strip()
237
- if oeisIDcleaned in oeisIDsImplemented:
238
- return oeisIDcleaned
239
- else:
240
- raise KeyError(
241
- f"OEIS ID {oeisIDcandidate} is not directly implemented.\n"
242
- f"Available sequences:\n{_formatOEISsequenceInfo()}"
243
- )
244
-
245
247
  """
246
248
  Section: public functions"""
247
249
 
@@ -308,7 +310,7 @@ def clearOEIScache() -> None:
308
310
  return
309
311
  else:
310
312
  for oeisID in settingsOEIS:
311
- pathFilenameCache = _pathCache / _formatFilenameCache.format(oeisID=oeisID)
313
+ pathFilenameCache = _pathCache / _getFilenameOEISbFile(oeisID)
312
314
  pathFilenameCache.unlink(missing_ok=True)
313
315
 
314
316
  print(f"Cache cleared from {_pathCache}")
@@ -46,15 +46,15 @@ def countFolds(listDimensions: List[int]) -> int:
46
46
 
47
47
  """Step for... for... for...: fill the connection graph"""
48
48
  for dimension1ndex in range(1, dimensionsTotal + 1):
49
- for activeLeaf1ndex in range(1, leavesTotal + 1):
50
- for leaf1ndexConnectee in range(1, activeLeaf1ndex + 1):
51
- connectionGraph[dimension1ndex, activeLeaf1ndex, leaf1ndexConnectee] = (0 if leaf1ndexConnectee == 0
52
- else ((leaf1ndexConnectee if coordinateSystem[dimension1ndex, leaf1ndexConnectee] == 1
53
- else leaf1ndexConnectee - cumulativeProduct[dimension1ndex - 1])
54
- if (coordinateSystem[dimension1ndex, activeLeaf1ndex] & 1) == (coordinateSystem[dimension1ndex, leaf1ndexConnectee] & 1)
55
- else (leaf1ndexConnectee if coordinateSystem[dimension1ndex, leaf1ndexConnectee] == listDimensions[dimension1ndex-1]
56
- or leaf1ndexConnectee + cumulativeProduct[dimension1ndex - 1] > activeLeaf1ndex
57
- else leaf1ndexConnectee + cumulativeProduct[dimension1ndex - 1])))
49
+ for leaf1ndex in range(1, leavesTotal + 1):
50
+ for leafConnectee in range(1, leaf1ndex + 1):
51
+ connectionGraph[dimension1ndex, leaf1ndex, leafConnectee] = (0 if leafConnectee == 0
52
+ else ((leafConnectee if coordinateSystem[dimension1ndex, leafConnectee] == 1
53
+ else leafConnectee - cumulativeProduct[dimension1ndex - 1])
54
+ if (coordinateSystem[dimension1ndex, leaf1ndex] & 1) == (coordinateSystem[dimension1ndex, leafConnectee] & 1)
55
+ else (leafConnectee if coordinateSystem[dimension1ndex, leafConnectee] == listDimensions[dimension1ndex-1]
56
+ or leafConnectee + cumulativeProduct[dimension1ndex - 1] > leaf1ndex
57
+ else leafConnectee + cumulativeProduct[dimension1ndex - 1])))
58
58
 
59
59
  """Indices of array `track` (to "track" the execution state), which is a collection of one-dimensional arrays each of length `leavesTotal + 1`."""
60
60
  leafAbove = numba.literally(0)
@@ -66,67 +66,67 @@ def countFolds(listDimensions: List[int]) -> int:
66
66
  gapsWhere = numpy.zeros(integerLarge(integerLarge(leavesTotal) * integerLarge(leavesTotal) + 1), dtype=dtypeMaximum)
67
67
 
68
68
  foldsTotal = integerLarge(0)
69
- activeLeaf1ndex = integerSmall(1)
70
- activeGap1ndex = integerSmall(0)
69
+ leaf1ndex = integerSmall(1)
70
+ gap1ndex = integerSmall(0)
71
71
 
72
- while activeLeaf1ndex > 0:
73
- if activeLeaf1ndex <= 1 or track[leafBelow, 0] == 1:
74
- if activeLeaf1ndex > leavesTotal:
72
+ while leaf1ndex > 0:
73
+ if leaf1ndex <= 1 or track[leafBelow, 0] == 1:
74
+ if leaf1ndex > leavesTotal:
75
75
  foldsTotal += leavesTotal
76
76
  else:
77
77
  dimensionsUnconstrained = integerSmall(0)
78
- """Track possible gaps for activeLeaf1ndex in each section"""
79
- gap1ndexCeiling = track[gapRangeStart, activeLeaf1ndex - 1]
78
+ """Track possible gaps for leaf1ndex in each section"""
79
+ gap1ndexCeiling = track[gapRangeStart, leaf1ndex - 1]
80
80
 
81
- """Count possible gaps for activeLeaf1ndex in each section"""
81
+ """Count possible gaps for leaf1ndex in each section"""
82
82
  dimension1ndex = integerSmall(1)
83
83
  while dimension1ndex <= dimensionsTotal:
84
- if connectionGraph[dimension1ndex, activeLeaf1ndex, activeLeaf1ndex] == activeLeaf1ndex:
84
+ if connectionGraph[dimension1ndex, leaf1ndex, leaf1ndex] == leaf1ndex:
85
85
  dimensionsUnconstrained += 1
86
86
  else:
87
- leaf1ndexConnectee = connectionGraph[dimension1ndex, activeLeaf1ndex, activeLeaf1ndex]
88
- while leaf1ndexConnectee != activeLeaf1ndex:
89
- gapsWhere[gap1ndexCeiling] = leaf1ndexConnectee
90
- if track[countDimensionsGapped, leaf1ndexConnectee] == 0:
87
+ leafConnectee = connectionGraph[dimension1ndex, leaf1ndex, leaf1ndex]
88
+ while leafConnectee != leaf1ndex:
89
+ gapsWhere[gap1ndexCeiling] = leafConnectee
90
+ if track[countDimensionsGapped, leafConnectee] == 0:
91
91
  gap1ndexCeiling += 1
92
- track[countDimensionsGapped, leaf1ndexConnectee] += 1
93
- leaf1ndexConnectee = connectionGraph[dimension1ndex, activeLeaf1ndex, track[leafBelow, leaf1ndexConnectee]]
92
+ track[countDimensionsGapped, leafConnectee] += 1
93
+ leafConnectee = connectionGraph[dimension1ndex, leaf1ndex, track[leafBelow, leafConnectee]]
94
94
  dimension1ndex += 1
95
95
 
96
- """If activeLeaf1ndex is unconstrained in all sections, it can be inserted anywhere"""
96
+ """If leaf1ndex is unconstrained in all sections, it can be inserted anywhere"""
97
97
  if dimensionsUnconstrained == dimensionsTotal:
98
- leaf1ndex = integerSmall(0)
99
- while leaf1ndex < activeLeaf1ndex:
100
- gapsWhere[gap1ndexCeiling] = leaf1ndex
98
+ indexLeaf = integerSmall(0)
99
+ while indexLeaf < leaf1ndex:
100
+ gapsWhere[gap1ndexCeiling] = indexLeaf
101
101
  gap1ndexCeiling += 1
102
- leaf1ndex += 1
102
+ indexLeaf += 1
103
103
 
104
104
  """Filter gaps that are common to all sections"""
105
- indexMiniGap = activeGap1ndex
105
+ indexMiniGap = gap1ndex
106
106
  while indexMiniGap < gap1ndexCeiling:
107
- gapsWhere[activeGap1ndex] = gapsWhere[indexMiniGap]
107
+ gapsWhere[gap1ndex] = gapsWhere[indexMiniGap]
108
108
  if track[countDimensionsGapped, gapsWhere[indexMiniGap]] == dimensionsTotal - dimensionsUnconstrained:
109
- activeGap1ndex += 1
109
+ gap1ndex += 1
110
110
  """Reset track[countDimensionsGapped] for next iteration"""
111
111
  track[countDimensionsGapped, gapsWhere[indexMiniGap]] = 0
112
112
  indexMiniGap += 1
113
113
 
114
114
  """Recursive backtracking steps"""
115
- while activeLeaf1ndex > 0 and activeGap1ndex == track[gapRangeStart, activeLeaf1ndex - 1]:
116
- activeLeaf1ndex -= 1
117
- track[leafBelow, track[leafAbove, activeLeaf1ndex]] = track[leafBelow, activeLeaf1ndex]
118
- track[leafAbove, track[leafBelow, activeLeaf1ndex]] = track[leafAbove, activeLeaf1ndex]
115
+ while leaf1ndex > 0 and gap1ndex == track[gapRangeStart, leaf1ndex - 1]:
116
+ leaf1ndex -= 1
117
+ track[leafBelow, track[leafAbove, leaf1ndex]] = track[leafBelow, leaf1ndex]
118
+ track[leafAbove, track[leafBelow, leaf1ndex]] = track[leafAbove, leaf1ndex]
119
119
 
120
120
  """Place leaf in valid position"""
121
- if activeLeaf1ndex > 0:
122
- activeGap1ndex -= 1
123
- track[leafAbove, activeLeaf1ndex] = gapsWhere[activeGap1ndex]
124
- track[leafBelow, activeLeaf1ndex] = track[leafBelow, track[leafAbove, activeLeaf1ndex]]
125
- track[leafBelow, track[leafAbove, activeLeaf1ndex]] = activeLeaf1ndex
126
- track[leafAbove, track[leafBelow, activeLeaf1ndex]] = activeLeaf1ndex
121
+ if leaf1ndex > 0:
122
+ gap1ndex -= 1
123
+ track[leafAbove, leaf1ndex] = gapsWhere[gap1ndex]
124
+ track[leafBelow, leaf1ndex] = track[leafBelow, track[leafAbove, leaf1ndex]]
125
+ track[leafBelow, track[leafAbove, leaf1ndex]] = leaf1ndex
126
+ track[leafAbove, track[leafBelow, leaf1ndex]] = leaf1ndex
127
127
  """Save current gap index"""
128
- track[gapRangeStart, activeLeaf1ndex] = activeGap1ndex
128
+ track[gapRangeStart, leaf1ndex] = gap1ndex
129
129
  """Move to next leaf"""
130
- activeLeaf1ndex += 1
130
+ leaf1ndex += 1
131
131
 
132
132
  return int(foldsTotal)
@@ -9,11 +9,11 @@ def foldings(p, job=None):
9
9
  p.insert(0, None) # NOTE mimics Atlas `array` type
10
10
 
11
11
  if job is None:
12
- global f
13
- f = 0
12
+ global G
13
+ G = 0
14
14
  def job(A, B):
15
- global f
16
- f = f + 1
15
+ global G
16
+ G = G + 1
17
17
  return foldings(p, job)
18
18
  # perform job (A, B) on each folding of a p[1] x ... x p[d] map,
19
19
  # where A and B are the above and below vectors. p[d + 1] < 0 terminates p;
@@ -150,4 +150,4 @@ def foldings(p, job=None):
150
150
  else:
151
151
  break
152
152
 
153
- return f #if job.__closure__ else None
153
+ return G #if job.__closure__ else None
@@ -13,7 +13,7 @@ def foldings(p: List[int]) -> int:
13
13
  p: A list of integers representing the dimensions of the map.
14
14
 
15
15
  Returns:
16
- f: The number of distinct foldings for the given map dimensions.
16
+ G: The number of distinct foldings for the given map dimensions.
17
17
 
18
18
  NOTE If there are fewer than two dimensions, any dimensions are not positive, or any dimensions are not integers, the output will be unreliable.
19
19
  """
@@ -65,14 +65,14 @@ def foldings(p: List[int]) -> int:
65
65
  # P[i] = p[1] x ... x p[i], C[i][m] = i-th co-ordinate of leaf m,
66
66
  # D[i][l][m] = leaf connected to m in section i when inserting l;
67
67
 
68
- f: int = 0
68
+ G: int = 0
69
69
  l: int = 1
70
70
 
71
71
  # kick off with null folding
72
72
  while l > 0:
73
73
  if l <= 1 or B[0] == 1: # NOTE This statement is part of a significant divergence from the 1971 paper. As a result, this version is greater than one order of magnitude faster.
74
74
  if l > n:
75
- f = f + n # NOTE Due to `B[0] == 1`, this implementation increments the counted foldings in batches of `n`-many foldings, rather than immediately incrementing when a folding is found, i.e. `f = f + 1`
75
+ G = G + n # NOTE Due to `B[0] == 1`, this implementation increments the counted foldings in batches of `n`-many foldings, rather than immediately incrementing when a folding is found, i.e. `G = G + 1`
76
76
  else:
77
77
  dd: int = 0
78
78
  gg: int = gapter[l - 1]
@@ -120,4 +120,4 @@ def foldings(p: List[int]) -> int:
120
120
  A[B[l]] = l
121
121
  gapter[l] = g
122
122
  l = l + 1
123
- return f
123
+ return G
@@ -12,7 +12,7 @@ def foldings(p: Sequence[int]) -> int:
12
12
  p: An array of integers representing the dimensions of the map.
13
13
 
14
14
  Returns:
15
- f: The number of distinct foldings for the given map dimensions.
15
+ G: The number of distinct foldings for the given map dimensions.
16
16
 
17
17
  NOTE If there are fewer than two dimensions, any dimensions are not positive, or any dimensions are not integers, the output will be unreliable.
18
18
  """
@@ -29,7 +29,7 @@ def foldings(p: Sequence[int]) -> int:
29
29
  B = [0] * (n + 1)
30
30
  count = [0] * (n + 1)
31
31
  gapter = [0] * (n + 1)
32
- gap = [0] * (n * n + 1)
32
+ gap = [0] * (n * n + 1)
33
33
 
34
34
  # B[m] is the leaf below leaf m in the current folding,
35
35
  # A[m] the leaf above. count[m] is the no. of sections in which
@@ -64,13 +64,13 @@ def foldings(p: Sequence[int]) -> int:
64
64
  # P[i] = p[1] x ... x p[i], C[i][m] = i-th co-ordinate of leaf m,
65
65
  # D[i][l][m] = leaf connected to m in section i when inserting l;
66
66
 
67
- f: int = 0
67
+ G: int = 0
68
68
  l: int = 1
69
69
 
70
70
  # kick off with null folding
71
71
  while l > 0:
72
72
  if l > n:
73
- f = f + 1
73
+ G = G + 1
74
74
  else:
75
75
  dd: int = 0
76
76
  gg: int = gapter[l - 1]
@@ -118,4 +118,4 @@ def foldings(p: Sequence[int]) -> int:
118
118
  A[B[l]] = l
119
119
  gapter[l] = g
120
120
  l = l + 1
121
- return f
121
+ return G