mapFolding 0.9.0__py3-none-any.whl → 0.9.1__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.
@@ -16,13 +16,10 @@ performance improvements while preserving code semantics and correctness.
16
16
  """
17
17
 
18
18
  from collections.abc import Callable, Sequence
19
- from mapFolding.someAssemblyRequired import grab, IngredientsModule, LedgerOfImports, Make, NodeChanger, NodeTourist, RecipeSynthesizeFlow, Then, ast_Identifier, ifThis, parsePathFilename2astModule, str_nameDOTname, IngredientsFunction, ShatteredDataclass
20
- from mapFolding.someAssemblyRequired.transformationTools import inlineFunctionDef, Z0Z_lameFindReplace, astModuleToIngredientsFunction, shatter_dataclassesDOTdataclass, write_astModule
21
- from mapFolding.theSSOT import ComputationState, DatatypeFoldsTotal as TheDatatypeFoldsTotal, DatatypeElephino as TheDatatypeElephino, DatatypeLeavesTotal as TheDatatypeLeavesTotal
22
- from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal, getPathRootJobDEFAULT
19
+ from mapFolding.someAssemblyRequired import Make, NodeTourist, RecipeSynthesizeFlow, Then, ast_Identifier, str_nameDOTname, IngredientsFunction
20
+ from mapFolding.someAssemblyRequired.transformationTools import ( makeNewFlow, write_astModule, )
23
21
  from numba.core.compiler import CompilerBase as numbaCompilerBase
24
- from pathlib import Path, PurePosixPath
25
- from typing import Any, cast, Final, TYPE_CHECKING, TypeAlias, TypeGuard
22
+ from typing import Any, cast, Final, TYPE_CHECKING, TypeGuard
26
23
  import ast
27
24
  import dataclasses
28
25
 
@@ -48,17 +45,17 @@ class ParametersNumba(TypedDict):
48
45
  debug: NotRequired[bool]
49
46
  error_model: str
50
47
  fastmath: bool
51
- forceinline: bool
48
+ forceinline: NotRequired[bool]
52
49
  forceobj: NotRequired[bool]
53
- inline: str
50
+ inline: NotRequired[str]
54
51
  locals: NotRequired[dict[str, Any]]
55
- looplift: bool
56
- no_cfunc_wrapper: bool
57
- no_cpython_wrapper: bool
52
+ looplift: NotRequired[bool]
53
+ no_cfunc_wrapper: NotRequired[bool]
54
+ no_cpython_wrapper: NotRequired[bool]
58
55
  no_rewrites: NotRequired[bool]
59
56
  nogil: NotRequired[bool]
60
- nopython: bool
61
- parallel: bool
57
+ nopython: NotRequired[bool]
58
+ parallel: NotRequired[bool]
62
59
  pipeline_class: NotRequired[type[numbaCompilerBase]]
63
60
  signature_or_function: NotRequired[Any | Callable[..., Any] | str | tuple[Any, ...]]
64
61
  target: NotRequired[str]
@@ -74,6 +71,7 @@ parametersNumbaSuperJit: Final[ParametersNumba] = { **parametersNumbaDefault, 'n
74
71
  parametersNumbaSuperJitParallel: Final[ParametersNumba] = { **parametersNumbaSuperJit, '_nrt': True, 'parallel': True, }
75
72
  """Speed, no helmet, concurrency, no talking to non-jitted functions."""
76
73
  parametersNumbaMinimum: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': True, 'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': False, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': False, 'forceobj': True, 'parallel': False, }
74
+ parametersNumbaLight: Final[ParametersNumba] = {'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True}
77
75
 
78
76
  Z0Z_numbaDataTypeModule: str_nameDOTname = 'numba'
79
77
  Z0Z_decoratorCallable: ast_Identifier = 'jit'
@@ -121,10 +119,10 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
121
119
  list_arg4signature_or_function: list[ast.expr] = []
122
120
  for parameter in ingredientsFunction.astFunctionDef.args.args:
123
121
  # For now, let Numba infer them.
122
+ signatureElement: ast.Subscript | ast.Name | None = makeSpecialSignatureForNumba(parameter)
123
+ if signatureElement:
124
+ list_arg4signature_or_function.append(signatureElement)
124
125
  continue
125
- # signatureElement: ast.Subscript | ast.Name | None = makeSpecialSignatureForNumba(parameter)
126
- # if signatureElement:
127
- # list_arg4signature_or_function.append(signatureElement)
128
126
 
129
127
  if ingredientsFunction.astFunctionDef.returns and isinstance(ingredientsFunction.astFunctionDef.returns, ast.Name):
130
128
  theReturn: ast.Name = ingredientsFunction.astFunctionDef.returns
@@ -153,103 +151,9 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
153
151
  class SpicesJobNumba:
154
152
  useNumbaProgressBar: bool = True
155
153
  numbaProgressBarIdentifier: ast_Identifier = 'ProgressBarGroupsOfFolds'
156
- parametersNumba = parametersNumbaDefault
154
+ parametersNumba: ParametersNumba = dataclasses.field(default_factory=ParametersNumba) # type: ignore
157
155
 
158
156
  # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
159
- @dataclasses.dataclass
160
- class RecipeJob:
161
- state: ComputationState
162
- # TODO create function to calculate `foldsTotalEstimated`
163
- foldsTotalEstimated: int = 0
164
- shatteredDataclass: ShatteredDataclass = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
165
-
166
- # ========================================
167
- # Source
168
- source_astModule = parsePathFilename2astModule(theNumbaFlow.pathFilenameSequential)
169
- sourceCountCallable: ast_Identifier = theNumbaFlow.callableSequential
170
-
171
- sourceLogicalPathModuleDataclass: str_nameDOTname = theNumbaFlow.logicalPathModuleDataclass
172
- sourceDataclassIdentifier: ast_Identifier = theNumbaFlow.dataclassIdentifier
173
- sourceDataclassInstance: ast_Identifier = theNumbaFlow.dataclassInstance
174
-
175
- sourcePathPackage: PurePosixPath | None = theNumbaFlow.pathPackage
176
- sourcePackageIdentifier: ast_Identifier | None = theNumbaFlow.packageIdentifier
177
-
178
- # ========================================
179
- # Filesystem (names of physical objects)
180
- pathPackage: PurePosixPath | None = None
181
- pathModule: PurePosixPath | None = PurePosixPath(getPathRootJobDEFAULT())
182
- """ `pathModule` will override `pathPackage` and `logicalPathRoot`."""
183
- fileExtension: str = theNumbaFlow.fileExtension
184
- pathFilenameFoldsTotal: PurePosixPath = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
185
-
186
- # ========================================
187
- # Logical identifiers (as opposed to physical identifiers)
188
- packageIdentifier: ast_Identifier | None = None
189
- logicalPathRoot: str_nameDOTname | None = None
190
- """ `logicalPathRoot` likely corresponds to a physical filesystem directory."""
191
- moduleIdentifier: ast_Identifier = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
192
- countCallable: ast_Identifier = sourceCountCallable
193
- dataclassIdentifier: ast_Identifier | None = sourceDataclassIdentifier
194
- dataclassInstance: ast_Identifier | None = sourceDataclassInstance
195
- logicalPathModuleDataclass: str_nameDOTname | None = sourceLogicalPathModuleDataclass
196
-
197
- # ========================================
198
- # Datatypes
199
- DatatypeFoldsTotal: TypeAlias = TheDatatypeFoldsTotal
200
- DatatypeElephino: TypeAlias = TheDatatypeElephino
201
- DatatypeLeavesTotal: TypeAlias = TheDatatypeLeavesTotal
202
-
203
- def _makePathFilename(self,
204
- pathRoot: PurePosixPath | None = None,
205
- logicalPathINFIX: str_nameDOTname | None = None,
206
- filenameStem: str | None = None,
207
- fileExtension: str | None = None,
208
- ) -> PurePosixPath:
209
- if pathRoot is None:
210
- pathRoot = self.pathPackage or PurePosixPath(Path.cwd())
211
- if logicalPathINFIX:
212
- whyIsThisStillAThing: list[str] = logicalPathINFIX.split('.')
213
- pathRoot = pathRoot.joinpath(*whyIsThisStillAThing)
214
- if filenameStem is None:
215
- filenameStem = self.moduleIdentifier
216
- if fileExtension is None:
217
- fileExtension = self.fileExtension
218
- filename: str = filenameStem + fileExtension
219
- return pathRoot.joinpath(filename)
220
-
221
- @property
222
- def pathFilenameModule(self) -> PurePosixPath:
223
- if self.pathModule is None:
224
- return self._makePathFilename()
225
- else:
226
- return self._makePathFilename(pathRoot=self.pathModule, logicalPathINFIX=None)
227
-
228
- def __post_init__(self):
229
- pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(self.state.mapShape))
230
-
231
- if self.moduleIdentifier is None: # pyright: ignore[reportUnnecessaryComparison]
232
- self.moduleIdentifier = pathFilenameFoldsTotal.stem
233
-
234
- if self.pathFilenameFoldsTotal is None: # pyright: ignore[reportUnnecessaryComparison]
235
- self.pathFilenameFoldsTotal = pathFilenameFoldsTotal
236
-
237
- if self.shatteredDataclass is None and self.logicalPathModuleDataclass and self.dataclassIdentifier and self.dataclassInstance: # pyright: ignore[reportUnnecessaryComparison]
238
- self.shatteredDataclass = shatter_dataclassesDOTdataclass(self.logicalPathModuleDataclass, self.dataclassIdentifier, self.dataclassInstance)
239
-
240
- # ========================================
241
- # Fields you probably don't need =================================
242
- # Dispatcher =================================
243
- sourceDispatcherCallable: ast_Identifier = theNumbaFlow.callableDispatcher
244
- dispatcherCallable: ast_Identifier = sourceDispatcherCallable
245
- # Parallel counting =================================
246
- sourceDataclassInstanceTaskDistribution: ast_Identifier = theNumbaFlow.dataclassInstanceTaskDistribution
247
- sourceConcurrencyManagerNamespace: ast_Identifier = theNumbaFlow.concurrencyManagerNamespace
248
- sourceConcurrencyManagerIdentifier: ast_Identifier = theNumbaFlow.concurrencyManagerIdentifier
249
- dataclassInstanceTaskDistribution: ast_Identifier = sourceDataclassInstanceTaskDistribution
250
- concurrencyManagerNamespace: ast_Identifier = sourceConcurrencyManagerNamespace
251
- concurrencyManagerIdentifier: ast_Identifier = sourceConcurrencyManagerIdentifier
252
-
253
157
  class be:
254
158
  @staticmethod
255
159
  def Call(node: ast.AST) -> TypeGuard[ast.Call]:
@@ -283,109 +187,12 @@ def makeNumbaFlow(numbaFlow: RecipeSynthesizeFlow) -> None:
283
187
  transformation process, including source and target locations,
284
188
  function and variable names, and output paths.
285
189
  """
286
- # TODO a tool to automatically remove unused variables from the ArgumentsSpecification (return, and returns) _might_ be nice.
287
- # Figure out dynamic flow control to synthesized modules https://github.com/hunterhogan/mapFolding/issues/4
288
-
289
- listAllIngredientsFunctions = [
290
- (ingredientsInitialize := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableInitialize)),
291
- (ingredientsParallel := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableParallel)),
292
- (ingredientsSequential := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableSequential)),
293
- (ingredientsDispatcher := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableDispatcher)),
294
- ]
295
-
296
- # Inline functions ========================================================
297
- # NOTE Replacements statements are based on the identifiers in the _source_, so operate on the source identifiers.
298
- ingredientsInitialize.astFunctionDef = inlineFunctionDef(numbaFlow.sourceCallableInitialize, numbaFlow.source_astModule)
299
- ingredientsParallel.astFunctionDef = inlineFunctionDef(numbaFlow.sourceCallableParallel, numbaFlow.source_astModule)
300
- ingredientsSequential.astFunctionDef = inlineFunctionDef(numbaFlow.sourceCallableSequential, numbaFlow.source_astModule)
301
-
302
- # assignRecipeIdentifiersToCallable. =============================
303
- # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
304
- # How can I use dataclass settings as the SSOT for specific actions? https://github.com/hunterhogan/mapFolding/issues/16
305
- # NOTE reminder: you are updating these `ast.Name` here (and not in a more general search) because this is a
306
- # narrow search for `ast.Call` so you won't accidentally replace unrelated `ast.Name`.
307
- listFindReplace = [(numbaFlow.sourceCallableDispatcher, numbaFlow.callableDispatcher),
308
- (numbaFlow.sourceCallableInitialize, numbaFlow.callableInitialize),
309
- (numbaFlow.sourceCallableParallel, numbaFlow.callableParallel),
310
- (numbaFlow.sourceCallableSequential, numbaFlow.callableSequential),]
311
- for ingredients in listAllIngredientsFunctions:
312
- for source_Identifier, recipe_Identifier in listFindReplace:
313
- updateCallName = NodeChanger(ifThis.isCall_Identifier(source_Identifier), grab.funcAttribute(Then.replaceWith(Make.Name(recipe_Identifier))))
314
- updateCallName.visit(ingredients.astFunctionDef)
315
-
316
- ingredientsDispatcher.astFunctionDef.name = numbaFlow.callableDispatcher
317
- ingredientsInitialize.astFunctionDef.name = numbaFlow.callableInitialize
318
- ingredientsParallel.astFunctionDef.name = numbaFlow.callableParallel
319
- ingredientsSequential.astFunctionDef.name = numbaFlow.callableSequential
320
-
321
- # Assign identifiers per the recipe. ==============================
322
- listFindReplace = [(numbaFlow.sourceDataclassInstance, numbaFlow.dataclassInstance),
323
- (numbaFlow.sourceDataclassInstanceTaskDistribution, numbaFlow.dataclassInstanceTaskDistribution),
324
- (numbaFlow.sourceConcurrencyManagerNamespace, numbaFlow.concurrencyManagerNamespace),]
325
- for ingredients in listAllIngredientsFunctions:
326
- for source_Identifier, recipe_Identifier in listFindReplace:
327
- updateName = NodeChanger(ifThis.isName_Identifier(source_Identifier) , grab.idAttribute(Then.replaceWith(recipe_Identifier)))
328
- update_arg = NodeChanger(ifThis.isArgument_Identifier(source_Identifier), grab.argAttribute(Then.replaceWith(recipe_Identifier)))
329
- updateName.visit(ingredients.astFunctionDef)
330
- update_arg.visit(ingredients.astFunctionDef)
331
-
332
- updateConcurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(numbaFlow.sourceConcurrencyManagerNamespace, numbaFlow.sourceConcurrencyManagerIdentifier)
333
- , grab.funcAttribute(Then.replaceWith(Make.Attribute(Make.Name(numbaFlow.concurrencyManagerNamespace), numbaFlow.concurrencyManagerIdentifier))))
334
- updateConcurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
335
-
336
- # shatter Dataclass =======================================================
337
- instance_Identifier = numbaFlow.dataclassInstance
338
- getTheOtherRecord_damn = numbaFlow.dataclassInstanceTaskDistribution
339
- shatteredDataclass = shatter_dataclassesDOTdataclass(numbaFlow.logicalPathModuleDataclass, numbaFlow.sourceDataclassIdentifier, instance_Identifier)
340
- ingredientsDispatcher.imports.update(shatteredDataclass.ledger)
341
-
342
- # How can I use dataclass settings as the SSOT for specific actions? https://github.com/hunterhogan/mapFolding/issues/16
343
- # Change callable parameters and Call to the callable at the same time ====
344
- # sequentialCallable =========================================================
345
- ingredientsSequential.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
346
- astCallSequentialCallable = Make.Call(Make.Name(numbaFlow.callableSequential), shatteredDataclass.listName4Parameters)
347
- changeReturnSequentialCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.fragments4AssignmentOrParameters)))
348
- ingredientsSequential.astFunctionDef.returns = shatteredDataclass.signatureReturnAnnotation
349
- replaceAssignSequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(numbaFlow.callableSequential)), Then.replaceWith(Make.Assign(listTargets=[shatteredDataclass.fragments4AssignmentOrParameters], value=astCallSequentialCallable)))
350
-
351
- unpack4sequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(numbaFlow.callableSequential)), Then.insertThisAbove(shatteredDataclass.listUnpack))
352
- repack4sequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(numbaFlow.callableSequential)), Then.insertThisBelow([shatteredDataclass.repack]))
353
-
354
- changeReturnSequentialCallable.visit(ingredientsSequential.astFunctionDef)
355
- replaceAssignSequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
356
- unpack4sequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
357
- repack4sequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
358
-
359
- ingredientsSequential.astFunctionDef = Z0Z_lameFindReplace(ingredientsSequential.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
360
-
361
- # parallelCallable =========================================================
362
- ingredientsParallel.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
363
- replaceCall2concurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(numbaFlow.concurrencyManagerNamespace, numbaFlow.concurrencyManagerIdentifier), Then.replaceWith(Make.Call(Make.Attribute(Make.Name(numbaFlow.concurrencyManagerNamespace), numbaFlow.concurrencyManagerIdentifier), listArguments=[Make.Name(numbaFlow.callableParallel)] + shatteredDataclass.listName4Parameters)))
364
-
365
- # NOTE I am dissatisfied with this logic for many reasons, including that it requires separate NodeCollector and NodeReplacer instances.
366
- astCallConcurrencyResult: list[ast.Call] = []
367
- get_astCallConcurrencyResult = NodeTourist(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), getIt(astCallConcurrencyResult))
368
- get_astCallConcurrencyResult.visit(ingredientsDispatcher.astFunctionDef)
369
- replaceAssignParallelCallable = NodeChanger(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), grab.valueAttribute(Then.replaceWith(astCallConcurrencyResult[0])))
370
- replaceAssignParallelCallable.visit(ingredientsDispatcher.astFunctionDef)
371
- changeReturnParallelCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.countingVariableName)))
372
- ingredientsParallel.astFunctionDef.returns = shatteredDataclass.countingVariableAnnotation
373
-
374
- unpack4parallelCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCallAttributeNamespace_Identifier(numbaFlow.concurrencyManagerNamespace, numbaFlow.concurrencyManagerIdentifier)), Then.insertThisAbove(shatteredDataclass.listUnpack))
375
-
376
- unpack4parallelCallable.visit(ingredientsDispatcher.astFunctionDef)
377
- replaceCall2concurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
378
- changeReturnParallelCallable.visit(ingredientsParallel.astFunctionDef)
379
-
380
- ingredientsParallel.astFunctionDef = Z0Z_lameFindReplace(ingredientsParallel.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
381
190
 
382
- # numba decorators =========================================
383
- ingredientsParallel = decorateCallableWithNumba(ingredientsParallel)
384
- ingredientsSequential = decorateCallableWithNumba(ingredientsSequential)
191
+ ingredientsModuleNumbaUnified = makeNewFlow(numbaFlow)
385
192
 
386
- # Module-level transformations ===========================================================
387
- ingredientsModuleNumbaUnified = IngredientsModule(ingredientsFunction=listAllIngredientsFunctions, imports=LedgerOfImports(numbaFlow.source_astModule))
388
- ingredientsModuleNumbaUnified.removeImportFromModule('numpy')
193
+ # numba decorators =========================================
194
+ ingredientsModuleNumbaUnified.listIngredientsFunctions[1] = decorateCallableWithNumba(ingredientsModuleNumbaUnified.listIngredientsFunctions[1])
195
+ ingredientsModuleNumbaUnified.listIngredientsFunctions[2] = decorateCallableWithNumba(ingredientsModuleNumbaUnified.listIngredientsFunctions[2])
389
196
 
390
197
  write_astModule(ingredientsModuleNumbaUnified, numbaFlow.pathFilenameDispatcher, numbaFlow.packageIdentifier)
391
198
 
@@ -25,7 +25,9 @@ from mapFolding.beDRY import outfitCountFolds
25
25
  from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal, writeStringToHere
26
26
  from mapFolding.someAssemblyRequired import (
27
27
  ast_Identifier,
28
+ be,
28
29
  DOT,
30
+ grab,
29
31
  ifThis,
30
32
  importLogicalPath2Callable,
31
33
  IngredientsFunction,
@@ -35,6 +37,7 @@ from mapFolding.someAssemblyRequired import (
35
37
  NodeChanger,
36
38
  NodeTourist,
37
39
  parseLogicalPath2astModule,
40
+ RecipeSynthesizeFlow,
38
41
  ShatteredDataclass,
39
42
  str_nameDOTname,
40
43
  Then,
@@ -47,6 +50,7 @@ from typing import Any, Literal, overload
47
50
  import ast
48
51
  import dataclasses
49
52
  import pickle
53
+ import python_minifier
50
54
 
51
55
  def astModuleToIngredientsFunction(astModule: ast.AST, identifierFunctionDef: ast_Identifier) -> IngredientsFunction:
52
56
  """
@@ -97,7 +101,7 @@ def extractFunctionDef(module: ast.AST, identifier: ast_Identifier) -> ast.Funct
97
101
  identifier: The name of the function to find.
98
102
 
99
103
  Returns:
100
- The matching function definition AST node, or None if not found.
104
+ astFunctionDef: The matching function definition AST node, or None if not found.
101
105
  """
102
106
  return NodeTourist(ifThis.isFunctionDef_Identifier(identifier), Then.extractIt).captureLastMatch(module)
103
107
 
@@ -263,8 +267,8 @@ class DeReConstructField2ast:
263
267
  ast_nameDOTname: ast.Attribute = dataclasses.field(init=False)
264
268
  astAnnotation: ast.expr = dataclasses.field(init=False)
265
269
  ast_argAnnotated: ast.arg = dataclasses.field(init=False)
266
- astAnnAssignConstructor: ast.AnnAssign = dataclasses.field(init=False)
267
- Z0Z_hack: tuple[ast.AnnAssign, str] = dataclasses.field(init=False)
270
+ astAnnAssignConstructor: ast.AnnAssign|ast.Assign = dataclasses.field(init=False)
271
+ Z0Z_hack: tuple[ast.AnnAssign|ast.Assign, str] = dataclasses.field(init=False)
268
272
 
269
273
  def __post_init__(self, dataclassesDOTdataclassLogicalPathModule: str_nameDOTname, dataclassClassDef: ast.ClassDef, dataclassesDOTdataclassInstance_Identifier: ast_Identifier, field: dataclasses.Field[Any]) -> None:
270
274
  self.compare = field.compare
@@ -287,18 +291,42 @@ class DeReConstructField2ast:
287
291
  else: self.astAnnotation = sherpa
288
292
 
289
293
  self.ast_argAnnotated = Make.arg(self.name, self.astAnnotation)
294
+ """
295
+ from ast import Module, Expr, Subscript, Name, Tuple, Load
296
+ Subscript(
297
+ value=Name(id='ndarray', ctx=Load()),
298
+ slice=Tuple(
299
+ elts=[
300
+ Subscript(
301
+ value=Name(id='tuple', ctx=Load()),
302
+ slice=Name(id='int', ctx=Load()),
303
+ ctx=Load()),
304
+ Subscript(
305
+ value=Name(id='dtype', ctx=Load()),
306
+ slice=Name(id='NumPyLeavesTotal', ctx=Load()),
307
+ ctx=Load())],
308
+ ctx=Load()),
309
+ ctx=Load()
310
+ )
290
311
 
312
+ """
291
313
  dtype = self.metadata.get('dtype', None)
292
314
  if dtype:
293
315
  moduleWithLogicalPath: str_nameDOTname = 'numpy'
294
- annotation = 'ndarray'
295
- self.ledger.addImportFrom_asStr(moduleWithLogicalPath, annotation)
316
+ annotationType = 'ndarray'
317
+ self.ledger.addImportFrom_asStr(moduleWithLogicalPath, annotationType)
318
+ self.ledger.addImportFrom_asStr(moduleWithLogicalPath, 'dtype')
319
+ axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Name('uint8'))
320
+ dtype_asnameName: ast.Name = self.astAnnotation # type: ignore
321
+ if dtype_asnameName.id == 'Array3D':
322
+ axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Tuple([Make.Name('uint8'), Make.Name('uint8'), Make.Name('uint8')]))
323
+ ast_expr = Make.Subscript(Make.Name(annotationType), Make.Tuple([axesSubscript, Make.Subscript(Make.Name('dtype'), dtype_asnameName)]))
296
324
  constructor = 'array'
297
325
  self.ledger.addImportFrom_asStr(moduleWithLogicalPath, constructor)
298
326
  dtypeIdentifier: ast_Identifier = dtype.__name__
299
- dtype_asnameName: ast.Name = self.astAnnotation # type: ignore
300
327
  self.ledger.addImportFrom_asStr(moduleWithLogicalPath, dtypeIdentifier, dtype_asnameName.id)
301
- self.astAnnAssignConstructor = Make.AnnAssign(self.astName, Make.Name(annotation), Make.Call(Make.Name(constructor), list_astKeywords=[Make.keyword('dtype', dtype_asnameName)]))
328
+ self.astAnnAssignConstructor = Make.AnnAssign(self.astName, ast_expr, Make.Call(Make.Name(constructor), list_astKeywords=[Make.keyword('dtype', dtype_asnameName)]))
329
+ self.astAnnAssignConstructor = Make.Assign([self.astName], Make.Call(Make.Name(constructor), list_astKeywords=[Make.keyword('dtype', dtype_asnameName)]))
302
330
  self.Z0Z_hack = (self.astAnnAssignConstructor, 'array')
303
331
  elif isinstance(self.astAnnotation, ast.Name):
304
332
  self.astAnnAssignConstructor = Make.AnnAssign(self.astName, self.astAnnotation, Make.Call(self.astAnnotation, [Make.Constant(-1)]))
@@ -413,9 +441,18 @@ def write_astModule(ingredients: IngredientsModule, pathFilename: PathLike[Any]
413
441
  if packageName:
414
442
  autoflake_additional_imports.append(packageName)
415
443
  pythonSource = autoflake_fix_code(pythonSource, autoflake_additional_imports, expand_star_imports=False, remove_all_unused_imports=True, remove_duplicate_keys = False, remove_unused_variables = False)
444
+ # pythonSource = python_minifier.minify(pythonSource)
416
445
  writeStringToHere(pythonSource, pathFilename)
417
446
 
418
447
  # END of acceptable classes and functions ======================================================
448
+ def removeUnusedParameters(ingredientsFunction: IngredientsFunction):
449
+ list_argCuzMyBrainRefusesToThink = ingredientsFunction.astFunctionDef.args.args + ingredientsFunction.astFunctionDef.args.posonlyargs + ingredientsFunction.astFunctionDef.args.kwonlyargs
450
+ list_arg_arg: list[ast_Identifier] = [ast_arg.arg for ast_arg in list_argCuzMyBrainRefusesToThink]
451
+ listName: list[ast.Name] = []
452
+ NodeTourist(be.Name, Then.appendTo(listName)).visit(ingredientsFunction.astFunctionDef)
453
+ list_Identifiers: list[ast_Identifier] = [astName.id for astName in listName]
454
+ list_IdentifiersNotUsed: list[ast_Identifier] = list(set(list_arg_arg) - set(list_Identifiers))
455
+
419
456
  dictionaryEstimates: dict[tuple[int, ...], int] = {
420
457
  (2,2,2,2,2,2,2,2): 798148657152000,
421
458
  (2,21): 776374224866624,
@@ -457,3 +494,113 @@ def Z0Z_lameFindReplace(astTree: 个, mappingFindReplaceNodes: Mapping[ast.AST,
457
494
  else:
458
495
  astTree = deepcopy(newTree)
459
496
  return newTree
497
+
498
+ def makeNewFlow(recipeFlow: RecipeSynthesizeFlow) -> IngredientsModule:
499
+ # TODO a tool to automatically remove unused variables from the ArgumentsSpecification (return, and returns) _might_ be nice.
500
+ # Figure out dynamic flow control to synthesized modules https://github.com/hunterhogan/mapFolding/issues/4
501
+ listAllIngredientsFunctions = [
502
+ (ingredientsInitialize := astModuleToIngredientsFunction(recipeFlow.source_astModule, recipeFlow.sourceCallableInitialize)),
503
+ (ingredientsParallel := astModuleToIngredientsFunction(recipeFlow.source_astModule, recipeFlow.sourceCallableParallel)),
504
+ (ingredientsSequential := astModuleToIngredientsFunction(recipeFlow.source_astModule, recipeFlow.sourceCallableSequential)),
505
+ (ingredientsDispatcher := astModuleToIngredientsFunction(recipeFlow.source_astModule, recipeFlow.sourceCallableDispatcher)),
506
+ ]
507
+
508
+ # Inline functions ========================================================
509
+ # NOTE Replacements statements are based on the identifiers in the _source_, so operate on the source identifiers.
510
+ ingredientsInitialize.astFunctionDef = inlineFunctionDef(recipeFlow.sourceCallableInitialize, recipeFlow.source_astModule)
511
+ ingredientsParallel.astFunctionDef = inlineFunctionDef(recipeFlow.sourceCallableParallel, recipeFlow.source_astModule)
512
+ ingredientsSequential.astFunctionDef = inlineFunctionDef(recipeFlow.sourceCallableSequential, recipeFlow.source_astModule)
513
+
514
+ # assignRecipeIdentifiersToCallable. =============================
515
+ # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
516
+ # How can I use dataclass settings as the SSOT for specific actions? https://github.com/hunterhogan/mapFolding/issues/16
517
+ # NOTE reminder: you are updating these `ast.Name` here (and not in a more general search) because this is a
518
+ # narrow search for `ast.Call` so you won't accidentally replace unrelated `ast.Name`.
519
+ listFindReplace = [(recipeFlow.sourceCallableDispatcher, recipeFlow.callableDispatcher),
520
+ (recipeFlow.sourceCallableInitialize, recipeFlow.callableInitialize),
521
+ (recipeFlow.sourceCallableParallel, recipeFlow.callableParallel),
522
+ (recipeFlow.sourceCallableSequential, recipeFlow.callableSequential),]
523
+ for ingredients in listAllIngredientsFunctions:
524
+ for source_Identifier, recipe_Identifier in listFindReplace:
525
+ updateCallName = NodeChanger(ifThis.isCall_Identifier(source_Identifier), grab.funcAttribute(Then.replaceWith(Make.Name(recipe_Identifier))))
526
+ updateCallName.visit(ingredients.astFunctionDef)
527
+
528
+ ingredientsDispatcher.astFunctionDef.name = recipeFlow.callableDispatcher
529
+ ingredientsInitialize.astFunctionDef.name = recipeFlow.callableInitialize
530
+ ingredientsParallel.astFunctionDef.name = recipeFlow.callableParallel
531
+ ingredientsSequential.astFunctionDef.name = recipeFlow.callableSequential
532
+
533
+ # Assign identifiers per the recipe. ==============================
534
+ listFindReplace = [(recipeFlow.sourceDataclassInstance, recipeFlow.dataclassInstance),
535
+ (recipeFlow.sourceDataclassInstanceTaskDistribution, recipeFlow.dataclassInstanceTaskDistribution),
536
+ (recipeFlow.sourceConcurrencyManagerNamespace, recipeFlow.concurrencyManagerNamespace),]
537
+ for ingredients in listAllIngredientsFunctions:
538
+ for source_Identifier, recipe_Identifier in listFindReplace:
539
+ updateName = NodeChanger(ifThis.isName_Identifier(source_Identifier) , grab.idAttribute(Then.replaceWith(recipe_Identifier)))
540
+ update_arg = NodeChanger(ifThis.isArgument_Identifier(source_Identifier), grab.argAttribute(Then.replaceWith(recipe_Identifier)))
541
+ updateName.visit(ingredients.astFunctionDef)
542
+ update_arg.visit(ingredients.astFunctionDef)
543
+
544
+ updateConcurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(recipeFlow.sourceConcurrencyManagerNamespace, recipeFlow.sourceConcurrencyManagerIdentifier)
545
+ , grab.funcAttribute(Then.replaceWith(Make.Attribute(Make.Name(recipeFlow.concurrencyManagerNamespace), recipeFlow.concurrencyManagerIdentifier))))
546
+ updateConcurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
547
+
548
+ # shatter Dataclass =======================================================
549
+ instance_Identifier = recipeFlow.dataclassInstance
550
+ getTheOtherRecord_damn = recipeFlow.dataclassInstanceTaskDistribution
551
+ shatteredDataclass = shatter_dataclassesDOTdataclass(recipeFlow.logicalPathModuleDataclass, recipeFlow.sourceDataclassIdentifier, instance_Identifier)
552
+ ingredientsDispatcher.imports.update(shatteredDataclass.ledger)
553
+
554
+ # How can I use dataclass settings as the SSOT for specific actions? https://github.com/hunterhogan/mapFolding/issues/16
555
+ # Change callable parameters and Call to the callable at the same time ====
556
+ # sequentialCallable =========================================================
557
+ if recipeFlow.removeDataclassSequential:
558
+ ingredientsSequential.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
559
+ astCallSequentialCallable = Make.Call(Make.Name(recipeFlow.callableSequential), shatteredDataclass.listName4Parameters)
560
+ changeReturnSequentialCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.fragments4AssignmentOrParameters)))
561
+ ingredientsSequential.astFunctionDef.returns = shatteredDataclass.signatureReturnAnnotation
562
+ replaceAssignSequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(recipeFlow.callableSequential)), Then.replaceWith(Make.Assign(listTargets=[shatteredDataclass.fragments4AssignmentOrParameters], value=astCallSequentialCallable)))
563
+
564
+ unpack4sequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(recipeFlow.callableSequential)), Then.insertThisAbove(shatteredDataclass.listUnpack))
565
+ repack4sequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(recipeFlow.callableSequential)), Then.insertThisBelow([shatteredDataclass.repack]))
566
+
567
+ changeReturnSequentialCallable.visit(ingredientsSequential.astFunctionDef)
568
+ replaceAssignSequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
569
+ unpack4sequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
570
+ repack4sequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
571
+
572
+ ingredientsSequential.astFunctionDef = Z0Z_lameFindReplace(ingredientsSequential.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
573
+
574
+ # parallelCallable =========================================================
575
+ if recipeFlow.removeDataclassParallel:
576
+ ingredientsParallel.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
577
+ replaceCall2concurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(recipeFlow.concurrencyManagerNamespace, recipeFlow.concurrencyManagerIdentifier), Then.replaceWith(Make.Call(Make.Attribute(Make.Name(recipeFlow.concurrencyManagerNamespace), recipeFlow.concurrencyManagerIdentifier), listArguments=[Make.Name(recipeFlow.callableParallel)] + shatteredDataclass.listName4Parameters)))
578
+
579
+ # NOTE I am dissatisfied with this logic for many reasons, including that it requires separate NodeCollector and NodeReplacer instances.
580
+ astCallConcurrencyResult: list[ast.Call] = []
581
+ get_astCallConcurrencyResult = NodeTourist(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), getIt(astCallConcurrencyResult))
582
+ get_astCallConcurrencyResult.visit(ingredientsDispatcher.astFunctionDef)
583
+ replaceAssignParallelCallable = NodeChanger(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), grab.valueAttribute(Then.replaceWith(astCallConcurrencyResult[0])))
584
+ replaceAssignParallelCallable.visit(ingredientsDispatcher.astFunctionDef)
585
+ changeReturnParallelCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.countingVariableName)))
586
+ ingredientsParallel.astFunctionDef.returns = shatteredDataclass.countingVariableAnnotation
587
+
588
+ unpack4parallelCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCallAttributeNamespace_Identifier(recipeFlow.concurrencyManagerNamespace, recipeFlow.concurrencyManagerIdentifier)), Then.insertThisAbove(shatteredDataclass.listUnpack))
589
+
590
+ unpack4parallelCallable.visit(ingredientsDispatcher.astFunctionDef)
591
+ replaceCall2concurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
592
+ changeReturnParallelCallable.visit(ingredientsParallel.astFunctionDef)
593
+
594
+ ingredientsParallel.astFunctionDef = Z0Z_lameFindReplace(ingredientsParallel.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
595
+
596
+ # Module-level transformations ===========================================================
597
+ ingredientsModuleNumbaUnified = IngredientsModule(ingredientsFunction=listAllIngredientsFunctions, imports=LedgerOfImports(recipeFlow.source_astModule))
598
+ ingredientsModuleNumbaUnified.removeImportFromModule('numpy')
599
+
600
+ return ingredientsModuleNumbaUnified
601
+
602
+ def getIt(astCallConcurrencyResult: list[ast.Call]) -> Callable[[ast.AST], ast.AST]:
603
+ def workhorse(node: ast.AST) -> ast.AST:
604
+ NodeTourist(be.Call, Then.appendTo(astCallConcurrencyResult)).visit(node)
605
+ return node
606
+ return workhorse
@@ -47,7 +47,7 @@ def countInitialize(state: ComputationState) -> ComputationState:
47
47
  return state
48
48
 
49
49
  @jit(_nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=False, no_cpython_wrapper=False, nopython=True, parallel=False)
50
- def countParallel(mapShape: tuple[DatatypeLeavesTotal, ...], leavesTotal: DatatypeLeavesTotal, taskDivisions: DatatypeLeavesTotal, concurrencyLimit: DatatypeElephino, connectionGraph: Array3D, dimensionsTotal: DatatypeLeavesTotal, countDimensionsGapped: Array1DLeavesTotal, dimensionsUnconstrained: DatatypeLeavesTotal, gapRangeStart: Array1DElephino, gapsWhere: Array1DLeavesTotal, leafAbove: Array1DLeavesTotal, leafBelow: Array1DLeavesTotal, foldGroups: Array1DFoldsTotal, foldsTotal: DatatypeFoldsTotal, gap1ndex: DatatypeLeavesTotal, gap1ndexCeiling: DatatypeElephino, groupsOfFolds: DatatypeFoldsTotal, indexDimension: DatatypeLeavesTotal, indexLeaf: DatatypeLeavesTotal, indexMiniGap: DatatypeElephino, leaf1ndex: DatatypeElephino, leafConnectee: DatatypeElephino, taskIndex: DatatypeLeavesTotal) -> DatatypeFoldsTotal:
50
+ def countParallel(mapShape: tuple[DatatypeLeavesTotal, ...], leavesTotal: DatatypeLeavesTotal, taskDivisions: DatatypeLeavesTotal, concurrencyLimit: DatatypeElephino, connectionGraph: Array3D, dimensionsTotal: DatatypeLeavesTotal, countDimensionsGapped: Array1DLeavesTotal, dimensionsUnconstrained: DatatypeLeavesTotal, gapRangeStart: Array1DElephino, gapsWhere: Array1DLeavesTotal, leafAbove: Array1DLeavesTotal, leafBelow: Array1DLeavesTotal, foldGroups: Array1DFoldsTotal, foldsTotal: DatatypeFoldsTotal, gap1ndex: DatatypeLeavesTotal, gap1ndexCeiling: DatatypeElephino, groupsOfFolds: DatatypeFoldsTotal, indexDimension: DatatypeLeavesTotal, indexLeaf: DatatypeLeavesTotal, indexMiniGap: DatatypeElephino, leaf1ndex: DatatypeLeavesTotal, leafConnectee: DatatypeElephino, taskIndex: DatatypeLeavesTotal) -> DatatypeFoldsTotal:
51
51
  while leaf1ndex > 0:
52
52
  if leaf1ndex <= 1 or leafBelow[0] == 1:
53
53
  if leaf1ndex > leavesTotal:
@@ -92,7 +92,7 @@ def countParallel(mapShape: tuple[DatatypeLeavesTotal, ...], leavesTotal: Dataty
92
92
  return groupsOfFolds
93
93
 
94
94
  @jit(_nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=False, no_cpython_wrapper=False, nopython=True, parallel=False)
95
- def countSequential(mapShape: tuple[DatatypeLeavesTotal, ...], leavesTotal: DatatypeLeavesTotal, taskDivisions: DatatypeLeavesTotal, concurrencyLimit: DatatypeElephino, connectionGraph: Array3D, dimensionsTotal: DatatypeLeavesTotal, countDimensionsGapped: Array1DLeavesTotal, dimensionsUnconstrained: DatatypeLeavesTotal, gapRangeStart: Array1DElephino, gapsWhere: Array1DLeavesTotal, leafAbove: Array1DLeavesTotal, leafBelow: Array1DLeavesTotal, foldGroups: Array1DFoldsTotal, foldsTotal: DatatypeFoldsTotal, gap1ndex: DatatypeLeavesTotal, gap1ndexCeiling: DatatypeElephino, groupsOfFolds: DatatypeFoldsTotal, indexDimension: DatatypeLeavesTotal, indexLeaf: DatatypeLeavesTotal, indexMiniGap: DatatypeElephino, leaf1ndex: DatatypeElephino, leafConnectee: DatatypeElephino, taskIndex: DatatypeLeavesTotal) -> tuple[tuple[DatatypeLeavesTotal, ...], DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeElephino, Array3D, DatatypeLeavesTotal, Array1DLeavesTotal, DatatypeLeavesTotal, Array1DElephino, Array1DLeavesTotal, Array1DLeavesTotal, Array1DLeavesTotal, Array1DFoldsTotal, DatatypeFoldsTotal, DatatypeLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeElephino, DatatypeElephino, DatatypeElephino, DatatypeLeavesTotal]:
95
+ def countSequential(mapShape: tuple[DatatypeLeavesTotal, ...], leavesTotal: DatatypeLeavesTotal, taskDivisions: DatatypeLeavesTotal, concurrencyLimit: DatatypeElephino, connectionGraph: Array3D, dimensionsTotal: DatatypeLeavesTotal, countDimensionsGapped: Array1DLeavesTotal, dimensionsUnconstrained: DatatypeLeavesTotal, gapRangeStart: Array1DElephino, gapsWhere: Array1DLeavesTotal, leafAbove: Array1DLeavesTotal, leafBelow: Array1DLeavesTotal, foldGroups: Array1DFoldsTotal, foldsTotal: DatatypeFoldsTotal, gap1ndex: DatatypeLeavesTotal, gap1ndexCeiling: DatatypeElephino, groupsOfFolds: DatatypeFoldsTotal, indexDimension: DatatypeLeavesTotal, indexLeaf: DatatypeLeavesTotal, indexMiniGap: DatatypeElephino, leaf1ndex: DatatypeLeavesTotal, leafConnectee: DatatypeElephino, taskIndex: DatatypeLeavesTotal) -> tuple[tuple[DatatypeLeavesTotal, ...], DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeElephino, Array3D, DatatypeLeavesTotal, Array1DLeavesTotal, DatatypeLeavesTotal, Array1DElephino, Array1DLeavesTotal, Array1DLeavesTotal, Array1DLeavesTotal, Array1DFoldsTotal, DatatypeFoldsTotal, DatatypeLeavesTotal, DatatypeElephino, DatatypeFoldsTotal, DatatypeLeavesTotal, DatatypeLeavesTotal, DatatypeElephino, DatatypeLeavesTotal, DatatypeElephino, DatatypeLeavesTotal]:
96
96
  while leaf1ndex > 0:
97
97
  if leaf1ndex <= 1 or leafBelow[0] == 1:
98
98
  if leaf1ndex > leavesTotal:
@@ -124,6 +124,9 @@ def countSequential(mapShape: tuple[DatatypeLeavesTotal, ...], leavesTotal: Data
124
124
  leaf1ndex -= 1
125
125
  leafBelow[leafAbove[leaf1ndex]] = leafBelow[leaf1ndex]
126
126
  leafAbove[leafBelow[leaf1ndex]] = leafAbove[leaf1ndex]
127
+ if groupsOfFolds and leaf1ndex == 3:
128
+ groupsOfFolds *= 2
129
+ break
127
130
  if leaf1ndex > 0:
128
131
  gap1ndex -= 1
129
132
  leafAbove[leaf1ndex] = gapsWhere[gap1ndex]
@@ -164,7 +167,7 @@ def doTheNeedful(state: ComputationState) -> ComputationState:
164
167
  indexDimension: DatatypeLeavesTotal = state.indexDimension
165
168
  indexLeaf: DatatypeLeavesTotal = state.indexLeaf
166
169
  indexMiniGap: DatatypeElephino = state.indexMiniGap
167
- leaf1ndex: DatatypeElephino = state.leaf1ndex
170
+ leaf1ndex: DatatypeLeavesTotal = state.leaf1ndex
168
171
  leafConnectee: DatatypeElephino = state.leafConnectee
169
172
  taskIndex: DatatypeLeavesTotal = state.taskIndex
170
173
  dictionaryConcurrency[indexSherpa] = concurrencyManager.submit(countParallel, mapShape, leavesTotal, taskDivisions, concurrencyLimit, connectionGraph, dimensionsTotal, countDimensionsGapped, dimensionsUnconstrained, gapRangeStart, gapsWhere, leafAbove, leafBelow, foldGroups, foldsTotal, gap1ndex, gap1ndexCeiling, groupsOfFolds, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, taskIndex)
@@ -192,7 +195,7 @@ def doTheNeedful(state: ComputationState) -> ComputationState:
192
195
  indexDimension: DatatypeLeavesTotal = state.indexDimension
193
196
  indexLeaf: DatatypeLeavesTotal = state.indexLeaf
194
197
  indexMiniGap: DatatypeElephino = state.indexMiniGap
195
- leaf1ndex: DatatypeElephino = state.leaf1ndex
198
+ leaf1ndex: DatatypeLeavesTotal = state.leaf1ndex
196
199
  leafConnectee: DatatypeElephino = state.leafConnectee
197
200
  taskIndex: DatatypeLeavesTotal = state.taskIndex
198
201
  mapShape, leavesTotal, taskDivisions, concurrencyLimit, connectionGraph, dimensionsTotal, countDimensionsGapped, dimensionsUnconstrained, gapRangeStart, gapsWhere, leafAbove, leafBelow, foldGroups, foldsTotal, gap1ndex, gap1ndexCeiling, groupsOfFolds, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, taskIndex = countSequential(mapShape, leavesTotal, taskDivisions, concurrencyLimit, connectionGraph, dimensionsTotal, countDimensionsGapped, dimensionsUnconstrained, gapRangeStart, gapsWhere, leafAbove, leafBelow, foldGroups, foldsTotal, gap1ndex, gap1ndexCeiling, groupsOfFolds, indexDimension, indexLeaf, indexMiniGap, leaf1ndex, leafConnectee, taskIndex)
mapFolding/theDao.py CHANGED
@@ -43,12 +43,6 @@ def activeLeafIsTheFirstLeaf(state: ComputationState) -> bool:
43
43
  def allDimensionsAreUnconstrained(state: ComputationState) -> bool:
44
44
  return not state.dimensionsUnconstrained
45
45
 
46
- def undoLastLeafPlacement(state: ComputationState) -> ComputationState:
47
- state.leaf1ndex -= 1
48
- state.leafBelow[state.leafAbove[state.leaf1ndex]] = state.leafBelow[state.leaf1ndex]
49
- state.leafAbove[state.leafBelow[state.leaf1ndex]] = state.leafAbove[state.leaf1ndex]
50
- return state
51
-
52
46
  def countGaps(state: ComputationState) -> ComputationState:
53
47
  state.gapsWhere[state.gap1ndexCeiling] = state.leafConnectee
54
48
  if state.countDimensionsGapped[state.leafConnectee] == 0:
@@ -100,6 +94,16 @@ def initializeVariablesToFindGaps(state: ComputationState) -> ComputationState:
100
94
  state.indexDimension = 0
101
95
  return state
102
96
 
97
+ def insertLeafAtGap(state: ComputationState) -> ComputationState:
98
+ state.gap1ndex -= 1
99
+ state.leafAbove[state.leaf1ndex] = state.gapsWhere[state.gap1ndex]
100
+ state.leafBelow[state.leaf1ndex] = state.leafBelow[state.leafAbove[state.leaf1ndex]]
101
+ state.leafBelow[state.leafAbove[state.leaf1ndex]] = state.leaf1ndex
102
+ state.leafAbove[state.leafBelow[state.leaf1ndex]] = state.leaf1ndex
103
+ state.gapRangeStart[state.leaf1ndex] = state.gap1ndex
104
+ state.leaf1ndex += 1
105
+ return state
106
+
103
107
  def insertUnconstrainedLeaf(state: ComputationState) -> ComputationState:
104
108
  state.indexLeaf = 0
105
109
  while state.indexLeaf < state.leaf1ndex:
@@ -123,22 +127,18 @@ def loopUpToDimensionsTotal(state: ComputationState) -> bool:
123
127
  def noGapsHere(state: ComputationState) -> bool:
124
128
  return (state.leaf1ndex > 0) and (state.gap1ndex == state.gapRangeStart[state.leaf1ndex - 1])
125
129
 
126
- def insertLeafAtGap(state: ComputationState) -> ComputationState:
127
- state.gap1ndex -= 1
128
- state.leafAbove[state.leaf1ndex] = state.gapsWhere[state.gap1ndex]
129
- state.leafBelow[state.leaf1ndex] = state.leafBelow[state.leafAbove[state.leaf1ndex]]
130
- state.leafBelow[state.leafAbove[state.leaf1ndex]] = state.leaf1ndex
131
- state.leafAbove[state.leafBelow[state.leaf1ndex]] = state.leaf1ndex
132
- state.gapRangeStart[state.leaf1ndex] = state.gap1ndex
133
- state.leaf1ndex += 1
134
- return state
135
-
136
130
  def thereIsAnActiveLeaf(state: ComputationState) -> bool:
137
131
  return state.leaf1ndex > 0
138
132
 
139
133
  def thisIsMyTaskIndex(state: ComputationState) -> bool:
140
134
  return (state.leaf1ndex != state.taskDivisions) or (state.leafConnectee % state.taskDivisions == state.taskIndex)
141
135
 
136
+ def undoLastLeafPlacement(state: ComputationState) -> ComputationState:
137
+ state.leaf1ndex -= 1
138
+ state.leafBelow[state.leafAbove[state.leaf1ndex]] = state.leafBelow[state.leaf1ndex]
139
+ state.leafAbove[state.leafBelow[state.leaf1ndex]] = state.leafAbove[state.leaf1ndex]
140
+ return state
141
+
142
142
  def updateLeafConnectee(state: ComputationState) -> ComputationState:
143
143
  state.leafConnectee = state.connectionGraph[state.indexDimension, state.leaf1ndex, state.leafBelow[state.leafConnectee]]
144
144
  return state
@@ -218,6 +218,9 @@ def countSequential(state: ComputationState) -> ComputationState:
218
218
  state = incrementIndexMiniGap(state)
219
219
  while noGapsHere(state):
220
220
  state = undoLastLeafPlacement(state)
221
+ if state.groupsOfFolds and state.leaf1ndex == 3:
222
+ state.groupsOfFolds *= 2
223
+ break
221
224
  if thereIsAnActiveLeaf(state):
222
225
  state = insertLeafAtGap(state)
223
226
  state.foldGroups[state.taskIndex] = state.groupsOfFolds