mapFolding 0.11.2__py3-none-any.whl → 0.11.4__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/theDao.py DELETED
@@ -1,243 +0,0 @@
1
- """
2
- Core computational algorithm for map folding counting and enumeration.
3
-
4
- This module implements the core algorithms for enumerating and counting the various ways a rectangular map can be
5
- folded. It uses a functional state-transformation approach, where each function performs a specific state mutation and
6
- returns the updated state. The module provides three main counting algorithms:
7
-
8
- 1. `countInitialize`: Sets up the initial state for computation.
9
- 2. `countSequential`: Processes the folding computation sequentially.
10
- 3. `countParallel`: Distributes the computation across multiple processes.
11
-
12
- All algorithms operate on a `ComputationState` object that tracks the folding process, including:
13
- - A "leaf" is a unit square in the map.
14
- - A "gap" is a potential position where a new leaf can be folded.
15
- - Connections track how leaves can connect above/below each other.
16
- - Leaves are enumerated starting from 1, not 0; hence, `leaf1ndex` not `leafIndex`.
17
-
18
- The `doTheNeedful` function is the main entry point that orchestrates the computation strategy based on task divisions and
19
- concurrency parameters.
20
- """
21
- from concurrent.futures import Future as ConcurrentFuture, ProcessPoolExecutor
22
- from copy import deepcopy
23
- from mapFolding.beDRY import ComputationState
24
- from multiprocessing import set_start_method as multiprocessing_set_start_method
25
-
26
- # When to use multiprocessing.set_start_method https://github.com/hunterhogan/mapFolding/issues/6
27
- if __name__ == '__main__':
28
- multiprocessing_set_start_method('spawn')
29
-
30
- def activeLeafConnectedToItself(state: ComputationState) -> bool:
31
- return state.leafConnectee == state.leaf1ndex
32
-
33
- def activeLeafGreaterThan0(state: ComputationState) -> bool:
34
- return state.leaf1ndex > 0
35
-
36
- def activeLeafGreaterThanLeavesTotal(state: ComputationState) -> bool:
37
- return state.leaf1ndex > state.leavesTotal
38
-
39
- def activeLeafIsTheFirstLeaf(state: ComputationState) -> bool:
40
- return state.leaf1ndex <= 1
41
-
42
- def allDimensionsAreUnconstrained(state: ComputationState) -> bool:
43
- return not state.dimensionsUnconstrained
44
-
45
- def countGaps(state: ComputationState) -> ComputationState:
46
- state.gapsWhere[state.gap1ndexCeiling] = state.leafConnectee
47
- if state.countDimensionsGapped[state.leafConnectee] == 0:
48
- state = incrementGap1ndexCeiling(state)
49
- state.countDimensionsGapped[state.leafConnectee] += 1
50
- return state
51
-
52
- def decrementDimensionsUnconstrained(state: ComputationState) -> ComputationState:
53
- state.dimensionsUnconstrained -= 1
54
- return state
55
-
56
- def dimensionsUnconstrainedCondition(state: ComputationState) -> bool:
57
- return state.connectionGraph[state.indexDimension, state.leaf1ndex, state.leaf1ndex] == state.leaf1ndex
58
-
59
- def filterCommonGaps(state: ComputationState) -> ComputationState:
60
- state.gapsWhere[state.gap1ndex] = state.gapsWhere[state.indexMiniGap]
61
- if state.countDimensionsGapped[state.gapsWhere[state.indexMiniGap]] == state.dimensionsUnconstrained:
62
- state = incrementActiveGap(state)
63
- state.countDimensionsGapped[state.gapsWhere[state.indexMiniGap]] = 0
64
- return state
65
-
66
- def incrementActiveGap(state: ComputationState) -> ComputationState:
67
- state.gap1ndex += 1
68
- return state
69
-
70
- def incrementGap1ndexCeiling(state: ComputationState) -> ComputationState:
71
- state.gap1ndexCeiling += 1
72
- return state
73
-
74
- def incrementIndexDimension(state: ComputationState) -> ComputationState:
75
- state.indexDimension += 1
76
- return state
77
-
78
- def incrementIndexMiniGap(state: ComputationState) -> ComputationState:
79
- state.indexMiniGap += 1
80
- return state
81
-
82
- def initializeIndexMiniGap(state: ComputationState) -> ComputationState:
83
- state.indexMiniGap = state.gap1ndex
84
- return state
85
-
86
- def initializeLeafConnectee(state: ComputationState) -> ComputationState:
87
- state.leafConnectee = state.connectionGraph[state.indexDimension, state.leaf1ndex, state.leaf1ndex]
88
- return state
89
-
90
- def initializeVariablesToFindGaps(state: ComputationState) -> ComputationState:
91
- state.dimensionsUnconstrained = state.dimensionsTotal
92
- state.gap1ndexCeiling = state.gapRangeStart[state.leaf1ndex - 1]
93
- state.indexDimension = 0
94
- return state
95
-
96
- def insertLeafAtGap(state: ComputationState) -> ComputationState:
97
- state.gap1ndex -= 1
98
- state.leafAbove[state.leaf1ndex] = state.gapsWhere[state.gap1ndex]
99
- state.leafBelow[state.leaf1ndex] = state.leafBelow[state.leafAbove[state.leaf1ndex]]
100
- state.leafBelow[state.leafAbove[state.leaf1ndex]] = state.leaf1ndex
101
- state.leafAbove[state.leafBelow[state.leaf1ndex]] = state.leaf1ndex
102
- state.gapRangeStart[state.leaf1ndex] = state.gap1ndex
103
- state.leaf1ndex += 1
104
- return state
105
-
106
- def insertUnconstrainedLeaf(state: ComputationState) -> ComputationState:
107
- state.indexLeaf = 0
108
- while state.indexLeaf < state.leaf1ndex:
109
- state.gapsWhere[state.gap1ndexCeiling] = state.indexLeaf
110
- state.gap1ndexCeiling += 1
111
- state.indexLeaf += 1
112
- return state
113
-
114
- def leafBelowSentinelIs1(state: ComputationState) -> bool:
115
- return state.leafBelow[0] == 1
116
-
117
- def loopingLeavesConnectedToActiveLeaf(state: ComputationState) -> bool:
118
- return state.leafConnectee != state.leaf1ndex
119
-
120
- def loopingToActiveGapCeiling(state: ComputationState) -> bool:
121
- return state.indexMiniGap < state.gap1ndexCeiling
122
-
123
- def loopUpToDimensionsTotal(state: ComputationState) -> bool:
124
- return state.indexDimension < state.dimensionsTotal
125
-
126
- def noGapsHere(state: ComputationState) -> bool:
127
- return (state.leaf1ndex > 0) and (state.gap1ndex == state.gapRangeStart[state.leaf1ndex - 1])
128
-
129
- def thereIsAnActiveLeaf(state: ComputationState) -> bool:
130
- return state.leaf1ndex > 0
131
-
132
- def thisIsMyTaskIndex(state: ComputationState) -> bool:
133
- return (state.leaf1ndex != state.taskDivisions) or (state.leafConnectee % state.taskDivisions == state.taskIndex)
134
-
135
- def undoLastLeafPlacement(state: ComputationState) -> ComputationState:
136
- state.leaf1ndex -= 1
137
- state.leafBelow[state.leafAbove[state.leaf1ndex]] = state.leafBelow[state.leaf1ndex]
138
- state.leafAbove[state.leafBelow[state.leaf1ndex]] = state.leafAbove[state.leaf1ndex]
139
- return state
140
-
141
- def updateLeafConnectee(state: ComputationState) -> ComputationState:
142
- state.leafConnectee = state.connectionGraph[state.indexDimension, state.leaf1ndex, state.leafBelow[state.leafConnectee]]
143
- return state
144
-
145
- def countInitialize(state: ComputationState) -> ComputationState:
146
- while state.gap1ndex == 0:
147
- if activeLeafIsTheFirstLeaf(state) or leafBelowSentinelIs1(state):
148
- state = initializeVariablesToFindGaps(state)
149
- while loopUpToDimensionsTotal(state):
150
- state = initializeLeafConnectee(state)
151
- if activeLeafConnectedToItself(state):
152
- state = decrementDimensionsUnconstrained(state)
153
- else:
154
- while loopingLeavesConnectedToActiveLeaf(state):
155
- state = countGaps(state)
156
- state = updateLeafConnectee(state)
157
- state = incrementIndexDimension(state)
158
- if allDimensionsAreUnconstrained(state):
159
- state = insertUnconstrainedLeaf(state)
160
- state = initializeIndexMiniGap(state)
161
- while loopingToActiveGapCeiling(state):
162
- state = filterCommonGaps(state)
163
- state = incrementIndexMiniGap(state)
164
- if thereIsAnActiveLeaf(state):
165
- state = insertLeafAtGap(state)
166
- return state
167
-
168
- def countParallel(state: ComputationState) -> ComputationState:
169
- while activeLeafGreaterThan0(state):
170
- if activeLeafIsTheFirstLeaf(state) or leafBelowSentinelIs1(state):
171
- if activeLeafGreaterThanLeavesTotal(state):
172
- state.groupsOfFolds += 1
173
- else:
174
- state = initializeVariablesToFindGaps(state)
175
- while loopUpToDimensionsTotal(state):
176
- if dimensionsUnconstrainedCondition(state):
177
- state = decrementDimensionsUnconstrained(state)
178
- else:
179
- state = initializeLeafConnectee(state)
180
- while loopingLeavesConnectedToActiveLeaf(state):
181
- if thisIsMyTaskIndex(state):
182
- state = countGaps(state)
183
- state = updateLeafConnectee(state)
184
- state = incrementIndexDimension(state)
185
- state = initializeIndexMiniGap(state)
186
- while loopingToActiveGapCeiling(state):
187
- state = filterCommonGaps(state)
188
- state = incrementIndexMiniGap(state)
189
- while noGapsHere(state):
190
- state = undoLastLeafPlacement(state)
191
- if thereIsAnActiveLeaf(state):
192
- state = insertLeafAtGap(state)
193
- state.foldGroups[state.taskIndex] = state.groupsOfFolds
194
- return state
195
-
196
- def countSequential(state: ComputationState) -> ComputationState:
197
- while activeLeafGreaterThan0(state):
198
- if activeLeafIsTheFirstLeaf(state) or leafBelowSentinelIs1(state):
199
- if activeLeafGreaterThanLeavesTotal(state):
200
- state.groupsOfFolds += 1
201
- else:
202
- state = initializeVariablesToFindGaps(state)
203
- while loopUpToDimensionsTotal(state):
204
- state = initializeLeafConnectee(state)
205
- if activeLeafConnectedToItself(state):
206
- state = decrementDimensionsUnconstrained(state)
207
- else:
208
- while loopingLeavesConnectedToActiveLeaf(state):
209
- state = countGaps(state)
210
- state = updateLeafConnectee(state)
211
- state = incrementIndexDimension(state)
212
- state = initializeIndexMiniGap(state)
213
- while loopingToActiveGapCeiling(state):
214
- state = filterCommonGaps(state)
215
- state = incrementIndexMiniGap(state)
216
- while noGapsHere(state):
217
- state = undoLastLeafPlacement(state)
218
- if state.leaf1ndex == 3 and state.groupsOfFolds:
219
- state.groupsOfFolds *= 2
220
- # print('break')
221
- break
222
- if thereIsAnActiveLeaf(state):
223
- state = insertLeafAtGap(state)
224
- state.foldGroups[state.taskIndex] = state.groupsOfFolds
225
- return state
226
-
227
- def doTheNeedful(state: ComputationState) -> ComputationState:
228
- state = countInitialize(state)
229
- if state.taskDivisions > 0:
230
- dictionaryConcurrency: dict[int, ConcurrentFuture[ComputationState]] = {}
231
- stateParallel = deepcopy(state)
232
- with ProcessPoolExecutor(stateParallel.concurrencyLimit) as concurrencyManager:
233
- for indexSherpa in range(stateParallel.taskDivisions):
234
- state = deepcopy(stateParallel)
235
- state.taskIndex = indexSherpa
236
- dictionaryConcurrency[indexSherpa] = concurrencyManager.submit(countParallel, state)
237
- for indexSherpa in range(stateParallel.taskDivisions):
238
- stateParallel.foldGroups[indexSherpa] = dictionaryConcurrency[indexSherpa].result().foldGroups[indexSherpa]
239
- state = stateParallel
240
- else:
241
- state = countSequential(state)
242
-
243
- return state