mapFolding 0.2.4__tar.gz → 0.2.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {mapfolding-0.2.4 → mapfolding-0.2.5}/PKG-INFO +8 -8
  2. {mapfolding-0.2.4 → mapfolding-0.2.5}/README.md +6 -1
  3. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/__init__.py +1 -1
  4. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/beDRY.py +47 -3
  5. mapfolding-0.2.5/mapFolding/importSelector.py +7 -0
  6. mapfolding-0.2.4/mapFolding/JAX/lunnanJAX.py → mapfolding-0.2.5/mapFolding/reference/jax.py +2 -0
  7. {mapfolding-0.2.4/mapFolding → mapfolding-0.2.5/mapFolding/someAssemblyRequired}/inlineAfunction.py +59 -31
  8. mapfolding-0.2.5/mapFolding/someAssemblyRequired/jobsAndTasks.py +47 -0
  9. mapfolding-0.2.5/mapFolding/someAssemblyRequired/makeNuitkaSource.py +99 -0
  10. mapfolding-0.2.5/mapFolding/someAssemblyRequired/makeNumbaJob.py +121 -0
  11. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/startHere.py +8 -17
  12. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding.egg-info/PKG-INFO +8 -8
  13. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding.egg-info/SOURCES.txt +6 -8
  14. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding.egg-info/requires.txt +0 -6
  15. {mapfolding-0.2.4 → mapfolding-0.2.5}/pyproject.toml +5 -6
  16. {mapfolding-0.2.4 → mapfolding-0.2.5}/tests/test_other.py +28 -28
  17. mapfolding-0.2.4/mapFolding/JAX/taskJAX.py +0 -313
  18. mapfolding-0.2.4/mapFolding/countInitialize.py +0 -44
  19. mapfolding-0.2.4/mapFolding/countParallel.py +0 -49
  20. mapfolding-0.2.4/mapFolding/countSequential.py +0 -43
  21. mapfolding-0.2.4/mapFolding/importSelector.py +0 -12
  22. mapfolding-0.2.4/tests/test_temporary.py +0 -25
  23. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/babbage.py +0 -0
  24. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/benchmarks/benchmarking.py +0 -0
  25. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/lovelace.py +0 -0
  26. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/oeis.py +0 -0
  27. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/reference/flattened.py +0 -0
  28. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/reference/hunterNumba.py +0 -0
  29. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/reference/irvineJavaPort.py +0 -0
  30. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/reference/lunnan.py +0 -0
  31. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/reference/lunnanNumpy.py +0 -0
  32. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/reference/lunnanWhile.py +0 -0
  33. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/reference/rotatedEntryPoint.py +0 -0
  34. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/reference/total_countPlus1vsPlusN.py +0 -0
  35. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding/theSSOT.py +0 -0
  36. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding.egg-info/dependency_links.txt +0 -0
  37. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding.egg-info/entry_points.txt +0 -0
  38. {mapfolding-0.2.4 → mapfolding-0.2.5}/mapFolding.egg-info/top_level.txt +0 -0
  39. {mapfolding-0.2.4 → mapfolding-0.2.5}/setup.cfg +0 -0
  40. {mapfolding-0.2.4 → mapfolding-0.2.5}/tests/__init__.py +0 -0
  41. {mapfolding-0.2.4 → mapfolding-0.2.5}/tests/conftest.py +0 -0
  42. {mapfolding-0.2.4 → mapfolding-0.2.5}/tests/pythons_idiotic_namespace.py +0 -0
  43. {mapfolding-0.2.4 → mapfolding-0.2.5}/tests/test_oeis.py +0 -0
  44. {mapfolding-0.2.4 → mapfolding-0.2.5}/tests/test_tasks.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mapFolding
3
- Version: 0.2.4
4
- Summary: Algorithm(s) for counting distinct ways to fold a map (or a strip of stamps)
3
+ Version: 0.2.5
4
+ Summary: Count distinct ways to fold a map (or a strip of stamps)
5
5
  Author-email: Hunter Hogan <HunterHogan@pm.me>
6
6
  Project-URL: homepage, https://github.com/hunterhogan/mapFolding
7
7
  Requires-Python: <3.13,>=3.10
@@ -14,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
- [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml) [![pip install mapFolding](https://img.shields.io/badge/pip%20install-mapFolding-gray.svg?colorB=3b434b)](https://pypi.org/project/mapFolding/) ![Static Badge](https://img.shields.io/badge/stinkin'%20badges-don't%20need-b98e5e) ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding) ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen) ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
39
+ [![pip install mapFolding](https://img.shields.io/badge/pip%20install-mapFolding-gray.svg?colorB=3b434b)](https://pypi.org/project/mapFolding/) [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml) [![Static Badge](https://img.shields.io/badge/stinkin'%20badges-don't%20need-b98e5e)](https://youtu.be/g6f_miE91mk&t=4) ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding) ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen) ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
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
+ [![Static Badge](https://img.shields.io/badge/2011_August-Homeless_since-blue?style=flat)](https://HunterThinks.com/support)
135
+ [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC3Gx7kz61009NbhpRtPP7tw)](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
- [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml) [![pip install mapFolding](https://img.shields.io/badge/pip%20install-mapFolding-gray.svg?colorB=3b434b)](https://pypi.org/project/mapFolding/) ![Static Badge](https://img.shields.io/badge/stinkin'%20badges-don't%20need-b98e5e) ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding) ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen) ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
17
+ [![pip install mapFolding](https://img.shields.io/badge/pip%20install-mapFolding-gray.svg?colorB=3b434b)](https://pypi.org/project/mapFolding/) [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml) [![Static Badge](https://img.shields.io/badge/stinkin'%20badges-don't%20need-b98e5e)](https://youtu.be/g6f_miE91mk&t=4) ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding) ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen) ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
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
+ [![Static Badge](https://img.shields.io/badge/2011_August-Homeless_since-blue?style=flat)](https://HunterThinks.com/support)
113
+ [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC3Gx7kz61009NbhpRtPP7tw)](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
  """A relatively stable API for oft-needed functionality."""
2
- from mapFolding import dtypeDefault, dtypeLarge
2
+ from mapFolding import dtypeDefault, dtypeLarge, pathJobDEFAULT
3
3
  from mapFolding import indexMy, indexThe, indexTrack, computationState
4
4
  from mapFolding import intInnit, defineConcurrencyLimit, oopsieKwargsie
5
5
  from numpy import integer
@@ -7,10 +7,12 @@ from numpy.typing import NDArray
7
7
  from typing import Any, List, Optional, Sequence, Type, Union
8
8
  import numba
9
9
  import numpy
10
+ import os
11
+ import pathlib
10
12
  import sys
11
13
 
12
14
  def getFilenameFoldsTotal(listDimensions: Sequence[int]) -> str:
13
- return str(sorted(listDimensions)).replace(' ', '') + '.foldsTotal'
15
+ return str(sorted(listDimensions)).replace(', ', 'x') + '.foldsTotal'
14
16
 
15
17
  def getLeavesTotal(listDimensions: Sequence[int]) -> int:
16
18
  """
@@ -36,6 +38,14 @@ def getLeavesTotal(listDimensions: Sequence[int]) -> int:
36
38
 
37
39
  return productDimensions
38
40
 
41
+ def getPathFilenameFoldsTotal(listDimensions: Sequence[int], pathishWriteFoldsTotal: Optional[Union[str, os.PathLike[str]]] = None) -> pathlib.Path:
42
+ pathFilenameFoldsTotal = pathlib.Path(pathishWriteFoldsTotal) if pathishWriteFoldsTotal is not None else pathJobDEFAULT
43
+ if pathFilenameFoldsTotal.is_dir():
44
+ filenameFoldsTotalDEFAULT = getFilenameFoldsTotal(listDimensions)
45
+ pathFilenameFoldsTotal = pathFilenameFoldsTotal / filenameFoldsTotalDEFAULT
46
+ pathFilenameFoldsTotal.parent.mkdir(parents=True, exist_ok=True)
47
+ return pathFilenameFoldsTotal
48
+
39
49
  def getTaskDivisions(computationDivisions: Optional[Union[int, str]], concurrencyLimit: int, CPUlimit: Optional[Union[bool, float, int]], listDimensions: Sequence[int]):
40
50
  """
41
51
  Determines whether or how to divide the computation into tasks.
@@ -148,7 +158,7 @@ def makeDataContainer(shape, datatype: Optional[Type] = None):
148
158
  datatype = dtypeDefault
149
159
  return numpy.zeros(shape, dtype=datatype)
150
160
 
151
- def outfitCountFolds(listDimensions: Sequence[int], computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[bool, float, int]] = None, **keywordArguments: Optional[Type]) -> computationState:
161
+ def outfitCountFolds(listDimensions: Sequence[int], computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[bool, float, int]] = None, **keywordArguments: Optional[Type[Any]]) -> computationState:
152
162
  """
153
163
  Initializes and configures the computation state for map folding computations.
154
164
 
@@ -232,6 +242,40 @@ def parseDimensions(dimensions: Sequence[int], parameterName: str = 'unnamed par
232
242
 
233
243
  return listNonNegative
234
244
 
245
+ import tempfile
246
+ import shutil
247
+ import logging
248
+ import os
249
+ def saveFoldsTotal(pathFilename: Union[str, os.PathLike[str]], foldsTotal: int) -> None:
250
+ """
251
+ Save foldsTotal with multiple fallback mechanisms.
252
+
253
+ Parameters:
254
+ pathFilename: Target save location
255
+ foldsTotal: Critical computed value to save
256
+ """
257
+ """Thoughts
258
+ Everything in a try block
259
+ Save it multiple times with multiple packages
260
+ no need for context managers, especially because they can cause errors"""
261
+ try:
262
+ pathFilenameFoldsTotal = pathlib.Path(pathFilename)
263
+ pathFilenameFoldsTotal.parent.mkdir(parents=True, exist_ok=True)
264
+ pathFilenameFoldsTotal.write_text(str(foldsTotal))
265
+ except Exception as ERRORmessage:
266
+ try:
267
+ print(f"\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n\n{foldsTotal=}\n\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n")
268
+ print(ERRORmessage)
269
+ print(f"\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n\n{foldsTotal=}\n\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n")
270
+ randomnessPlanB = (int(str(foldsTotal).strip()[-1]) + 1) * ['YO_']
271
+ filenameInfixUnique = ''.join(randomnessPlanB)
272
+ import os
273
+ pathFilenamePlanB = os.path.join(os.getcwd(), 'foldsTotal' + filenameInfixUnique + '.txt')
274
+ open(pathFilenamePlanB, 'w').write(str(foldsTotal))
275
+ print(str(pathFilenamePlanB))
276
+ except:
277
+ print(foldsTotal)
278
+
235
279
  def setCPUlimit(CPUlimit: Union[bool, float, int, None]) -> int:
236
280
  """Sets CPU limit for Numba concurrent operations. Note that it can only affect Numba-jitted functions that have not yet been imported.
237
281
 
@@ -0,0 +1,7 @@
1
+ from mapFolding.lovelace import countSequential
2
+ from mapFolding.lovelace import countParallel
3
+ from mapFolding.lovelace import countInitialize
4
+
5
+ # from mapFolding.countSequential import countSequential
6
+ # from mapFolding.countParallel import countParallel
7
+ # from mapFolding.countInitialize import countInitialize
@@ -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
@@ -1,19 +1,22 @@
1
1
  from mapFolding import indexMy, indexThe, indexTrack
2
2
  import ast
3
+ import copy
3
4
  import pathlib
4
5
 
5
- dictionaryEnumValues = {}
6
- for enumIndex in [indexMy, indexThe, indexTrack]:
7
- for memberName, memberValue in enumIndex._member_map_.items():
8
- dictionaryEnumValues[f"{enumIndex.__name__}.{memberName}.value"] = memberValue.value
6
+ def getDictionaryEnumValues():
7
+ dictionaryEnumValues = {}
8
+ for enumIndex in [indexMy, indexThe, indexTrack]:
9
+ for memberName, memberValue in enumIndex._member_map_.items():
10
+ dictionaryEnumValues[f"{enumIndex.__name__}.{memberName}.value"] = memberValue.value
11
+ return dictionaryEnumValues
9
12
 
10
- class RecursiveInliner(ast.NodeTransformer):
13
+ class RecursiveInlinerWithEnum(ast.NodeTransformer):
11
14
  def __init__(self, dictionaryFunctions, dictionaryEnumValues):
12
15
  self.dictionaryFunctions = dictionaryFunctions
13
16
  self.dictionaryEnumValues = dictionaryEnumValues
14
17
  self.processed = set() # Track processed functions to avoid infinite recursion
15
18
 
16
- def inline_function_body(self, functionName):
19
+ def inlineFunctionBody(self, functionName):
17
20
  if functionName in self.processed:
18
21
  return None
19
22
 
@@ -35,7 +38,7 @@ class RecursiveInliner(ast.NodeTransformer):
35
38
  def visit_Call(self, node):
36
39
  callNode = self.generic_visit(node)
37
40
  if isinstance(callNode, ast.Call) and isinstance(callNode.func, ast.Name) and callNode.func.id in self.dictionaryFunctions:
38
- inlineDefinition = self.inline_function_body(callNode.func.id)
41
+ inlineDefinition = self.inlineFunctionBody(callNode.func.id)
39
42
  if inlineDefinition and inlineDefinition.body:
40
43
  lastStmt = inlineDefinition.body[-1]
41
44
  if isinstance(lastStmt, ast.Return) and lastStmt.value is not None:
@@ -48,23 +51,23 @@ class RecursiveInliner(ast.NodeTransformer):
48
51
  def visit_Expr(self, node):
49
52
  if isinstance(node.value, ast.Call):
50
53
  if isinstance(node.value.func, ast.Name) and node.value.func.id in self.dictionaryFunctions:
51
- inlineDefinition = self.inline_function_body(node.value.func.id)
54
+ inlineDefinition = self.inlineFunctionBody(node.value.func.id)
52
55
  if inlineDefinition:
53
56
  return [self.visit(stmt) for stmt in inlineDefinition.body]
54
57
  return self.generic_visit(node)
55
58
 
56
- def find_required_imports(node):
57
- """Find all modules that need to be imported based on AST analysis."""
59
+ def findRequiredImports(node):
60
+ """Find all modules that need to be imported based on AST analysis.
61
+ NOTE: due to hardcoding, this is a glorified regex. No, wait, this is less versatile than regex."""
58
62
  requiredImports = set()
59
63
 
60
64
  class ImportFinder(ast.NodeVisitor):
61
65
  def visit_Name(self, node):
62
- # Common modules we might need
63
66
  if node.id in {'numba'}:
64
67
  requiredImports.add(node.id)
65
68
  self.generic_visit(node)
66
69
 
67
- def visit_Decorator(self, node):
70
+ def visitDecorator(self, node):
68
71
  if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
69
72
  if node.func.id == 'jit':
70
73
  requiredImports.add('numba')
@@ -73,7 +76,7 @@ def find_required_imports(node):
73
76
  ImportFinder().visit(node)
74
77
  return requiredImports
75
78
 
76
- def generate_imports(requiredImports):
79
+ def generateImports(requiredImports):
77
80
  """Generate import statements based on required modules."""
78
81
  importStatements = []
79
82
 
@@ -88,7 +91,7 @@ def generate_imports(requiredImports):
88
91
 
89
92
  return '\n'.join(importStatements)
90
93
 
91
- def inline_functions(sourceCode, targetFunctionName, dictionaryEnumValues):
94
+ def inlineFunctions(sourceCode, targetFunctionName, dictionaryEnumValues):
92
95
  dictionaryParsed = ast.parse(sourceCode)
93
96
  dictionaryFunctions = {
94
97
  element.name: element
@@ -96,29 +99,54 @@ def inline_functions(sourceCode, targetFunctionName, dictionaryEnumValues):
96
99
  if isinstance(element, ast.FunctionDef)
97
100
  }
98
101
  nodeTarget = dictionaryFunctions[targetFunctionName]
99
- nodeInliner = RecursiveInliner(dictionaryFunctions, dictionaryEnumValues)
102
+ nodeInliner = RecursiveInlinerWithEnum(dictionaryFunctions, dictionaryEnumValues)
100
103
  nodeInlined = nodeInliner.visit(nodeTarget)
101
104
  ast.fix_missing_locations(nodeInlined)
102
105
 
103
106
  # Generate imports
104
- requiredImports = find_required_imports(nodeInlined)
105
- importStatements = generate_imports(requiredImports)
107
+ requiredImports = findRequiredImports(nodeInlined)
108
+ importStatements = generateImports(requiredImports)
106
109
 
107
110
  # Combine imports with inlined code
108
111
  inlinedCode = importStatements + '\n\n' + ast.unparse(ast.Module(body=[nodeInlined], type_ignores=[]))
109
112
  return inlinedCode
110
113
 
111
- pathFilenameSource = pathlib.Path("/apps/mapFolding/mapFolding/lovelace.py")
112
- codeSource = pathFilenameSource.read_text()
113
-
114
- listCallables = [
115
- 'countSequential',
116
- 'countParallel',
117
- 'countInitialize',
118
- ]
119
- listPathFilenamesDestination = []
120
- for callableTarget in listCallables:
121
- pathFilenameDestination = pathFilenameSource.with_stem(callableTarget)
122
- codeInlined = inline_functions(codeSource, callableTarget, dictionaryEnumValues)
123
- pathFilenameDestination.write_text(codeInlined)
124
- listPathFilenamesDestination.append(pathFilenameDestination)
114
+ def Z0Z_inlineMapFolding():
115
+ dictionaryEnumValues = getDictionaryEnumValues()
116
+
117
+ pathFilenameSource = pathlib.Path("/apps/mapFolding/mapFolding/lovelace.py")
118
+ codeSource = pathFilenameSource.read_text()
119
+
120
+ listCallables = [
121
+ 'countInitialize',
122
+ 'countParallel',
123
+ 'countSequential',
124
+ ]
125
+
126
+ listPathFilenamesDestination: list[pathlib.Path] = []
127
+ for callableTarget in listCallables:
128
+ pathFilenameDestination = pathFilenameSource.with_stem(callableTarget)
129
+ codeInlined = inlineFunctions(codeSource, callableTarget, dictionaryEnumValues)
130
+ pathFilenameDestination.write_text(codeInlined)
131
+ listPathFilenamesDestination.append(pathFilenameDestination)
132
+
133
+ listNoNumba = [
134
+ 'countInitialize',
135
+ 'countSequential',
136
+ ]
137
+
138
+ listPathFilenamesNoNumba = []
139
+ for pathFilename in listPathFilenamesDestination:
140
+ if pathFilename.stem in listNoNumba:
141
+ pathFilenameNoNumba = pathFilename.with_name(pathFilename.stem + 'NoNumba' + pathFilename.suffix)
142
+ else:
143
+ continue
144
+ codeNoNumba = pathFilename.read_text()
145
+ for codeLine in copy.copy(codeNoNumba.splitlines()):
146
+ if 'numba' in codeLine:
147
+ codeNoNumba = codeNoNumba.replace(codeLine, '')
148
+ pathFilenameNoNumba.write_text(codeNoNumba)
149
+ listPathFilenamesNoNumba.append(pathFilenameNoNumba)
150
+
151
+ if __name__ == '__main__':
152
+ Z0Z_inlineMapFolding()
@@ -0,0 +1,47 @@
1
+ from typing import Any, Optional, Sequence, Type, Union
2
+
3
+ def Z0Z_makeJob(listDimensions: Sequence[int], **keywordArguments: Optional[Type[Any]]):
4
+ from mapFolding import outfitCountFolds
5
+ stateUniversal = outfitCountFolds(listDimensions, computationDivisions=None, CPUlimit=None, **keywordArguments)
6
+ from mapFolding.countInitialize import countInitialize
7
+ countInitialize(stateUniversal['connectionGraph'], stateUniversal['gapsWhere'], stateUniversal['my'], stateUniversal['the'], stateUniversal['track'])
8
+ from mapFolding import getPathFilenameFoldsTotal
9
+ pathFilenameChopChop = getPathFilenameFoldsTotal(stateUniversal['mapShape'])
10
+ import pathlib
11
+ suffix = pathFilenameChopChop.suffix
12
+ pathJob = pathlib.Path(str(pathFilenameChopChop)[0:-len(suffix)])
13
+ pathJob.mkdir(parents=True, exist_ok=True)
14
+ pathFilenameJob = pathJob / 'stateJob.pkl'
15
+
16
+ pathFilenameFoldsTotal = getPathFilenameFoldsTotal(stateUniversal['mapShape'], pathFilenameJob.parent)
17
+ stateJob = {**stateUniversal, 'pathFilenameFoldsTotal': pathFilenameFoldsTotal}
18
+
19
+ del stateJob['mapShape']
20
+
21
+ import pickle
22
+ pathFilenameJob.write_bytes(pickle.dumps(stateJob))
23
+ return pathFilenameJob
24
+
25
+ def runJob(pathFilename):
26
+ from typing import Final
27
+ import numpy
28
+ from pathlib import Path
29
+ pathFilenameJob = Path(pathFilename)
30
+ from pickle import loads
31
+ stateJob = loads(pathFilenameJob.read_bytes())
32
+
33
+ connectionGraph: numpy.ndarray = stateJob['connectionGraph']
34
+ foldsSubTotals: numpy.ndarray = stateJob['foldsSubTotals']
35
+ gapsWhere: numpy.ndarray = stateJob['gapsWhere']
36
+ my: numpy.ndarray = stateJob['my']
37
+ pathFilenameFoldsTotal: Final[Path] = stateJob['pathFilenameFoldsTotal']
38
+ the: Final[numpy.ndarray] = stateJob['the']
39
+ track: numpy.ndarray = stateJob['track']
40
+
41
+ from mapFolding.countSequentialNoNumba import countSequential
42
+ countSequential(connectionGraph, foldsSubTotals, gapsWhere, my, the, track)
43
+
44
+ print(foldsSubTotals.sum().item())
45
+ Path(pathFilenameFoldsTotal).parent.mkdir(parents=True, exist_ok=True)
46
+ Path(pathFilenameFoldsTotal).write_text(str(foldsSubTotals.sum().item()))
47
+ print(pathFilenameFoldsTotal)
@@ -0,0 +1,99 @@
1
+ """NOTE make a special venv for nuitka, then run nuitka from that venv"""
2
+ from pathlib import Path
3
+ from pickle import loads
4
+ from typing import Final
5
+ import numpy
6
+ from mapFolding.someAssemblyRequired.jobsAndTasks import Z0Z_makeJob
7
+
8
+ """
9
+ Section: configure every time"""
10
+
11
+ # TODO configure this
12
+ mapShape = [3]*3
13
+ # NOTE ^^^^^^ pay attention
14
+
15
+ """
16
+ Section: settings"""
17
+
18
+ pathFilenameData = Z0Z_makeJob(mapShape)
19
+
20
+ pathJob = pathFilenameData.parent
21
+
22
+ pathFilenameAlgorithm = Path('/apps/mapFolding/mapFolding/countSequentialNoNumba.py')
23
+ pathFilenameDestination = Path(f"/apps/mapFolding/nn/{pathJob.name}.py")
24
+
25
+ """
26
+ Section: did you handle and include this stuff?"""
27
+
28
+ lineImportNumPy = "import numpy"
29
+ linePrintFoldsTotal = "print(foldsSubTotals.sum().item())"
30
+ linesAlgorithm = """"""
31
+ linesData = """"""
32
+ settingsNuitkaProject=f"""
33
+ # nuitka-project: --mode=onefile
34
+ # nuitka-project: --onefile-no-compression
35
+ # nuitka-project: --lto=yes
36
+ # nuitka-project: --clang
37
+ # nuitka-project: --output-dir={pathJob}
38
+ # nuitka-project: --output-filename={pathJob.name}.exe
39
+ """
40
+ # nuitka-project:
41
+ """
42
+ Section: do the work"""
43
+
44
+ WTFamIdoing = pathFilenameAlgorithm.read_text()
45
+ for lineSource in WTFamIdoing.splitlines():
46
+ ImaIndent = ' '
47
+ if lineSource.startswith(ImaIndent):
48
+ lineSource = lineSource[len(ImaIndent):None]
49
+ elif lineSource.startswith('#'):
50
+ continue
51
+ elif not lineSource:
52
+ continue
53
+ elif lineSource.startswith('def '):
54
+ continue
55
+ else:
56
+ raise NotImplementedError("You didn't anticipate this.")
57
+ linesAlgorithm = "\n".join([linesAlgorithm
58
+ , lineSource
59
+ ])
60
+
61
+ stateJob = loads(pathFilenameData.read_bytes())
62
+ connectionGraph: Final[numpy.ndarray] = stateJob['connectionGraph']
63
+ foldsSubTotals: numpy.ndarray = stateJob['foldsSubTotals']
64
+ gapsWhere: numpy.ndarray = stateJob['gapsWhere']
65
+ my: numpy.ndarray = stateJob['my']
66
+ the: numpy.ndarray = stateJob['the']
67
+ track: numpy.ndarray = stateJob['track']
68
+
69
+ pathFilenameFoldsTotal = stateJob['pathFilenameFoldsTotal']
70
+ lineDataPathFilenameFoldsTotal = "pathFilenameFoldsTotal = r'" + str(pathFilenameFoldsTotal) + "'\n"
71
+
72
+ def archivistFormatsArrayToCode(arrayTarget: numpy.ndarray, identifierName: str) -> str:
73
+ """Format numpy array into a code string that recreates the array."""
74
+ arrayAsTypeStr = numpy.array2string(
75
+ arrayTarget,
76
+ threshold=10000,
77
+ max_line_width=100,
78
+ separator=','
79
+ )
80
+ return f"{identifierName} = numpy.array({arrayAsTypeStr}, dtype=numpy.{arrayTarget.dtype})\n"
81
+
82
+ linesData = "\n".join([linesData
83
+ , lineDataPathFilenameFoldsTotal
84
+ , archivistFormatsArrayToCode(the, 'the')
85
+ , archivistFormatsArrayToCode(my, 'my')
86
+ , archivistFormatsArrayToCode(foldsSubTotals, 'foldsSubTotals')
87
+ , archivistFormatsArrayToCode(gapsWhere, 'gapsWhere')
88
+ , archivistFormatsArrayToCode(connectionGraph, 'connectionGraph')
89
+ , archivistFormatsArrayToCode(track, 'track')
90
+ ])
91
+
92
+ linesAll = "\n".join([settingsNuitkaProject
93
+ , lineImportNumPy
94
+ , linesData
95
+ , linesAlgorithm
96
+ , linePrintFoldsTotal
97
+ ])
98
+
99
+ pathFilenameDestination.write_text(linesAll)
@@ -0,0 +1,121 @@
1
+ """Create a python module hardcoded to compute a map's foldsTotal.
2
+ NumPy ndarray.
3
+ Numba optimized.
4
+ Absolutely no other imports.
5
+ """
6
+ from mapFolding import datatypeLarge, dtypeLarge, dtypeDefault
7
+ from mapFolding.someAssemblyRequired.inlineAfunction import Z0Z_inlineMapFolding
8
+ from mapFolding.someAssemblyRequired.jobsAndTasks import Z0Z_makeJob
9
+ import importlib
10
+ import llvmlite.binding
11
+ import numpy
12
+ import pathlib
13
+ import pickle
14
+
15
+ listDimensions = [3,7]
16
+
17
+ # NOTE this overwrites files
18
+ Z0Z_inlineMapFolding()
19
+
20
+ identifierCallableLaunch = "goGoGadgetAbsurdity"
21
+
22
+ def archivistFormatsArrayToCode(arrayTarget: numpy.ndarray, identifierName: str) -> str:
23
+ """Format numpy array into a code string that recreates the array."""
24
+ arrayAsTypeStr = numpy.array2string(arrayTarget, threshold=10000, max_line_width=200, separator=',')
25
+ return f"{identifierName} = numpy.array({arrayAsTypeStr}, dtype=numpy.{arrayTarget.dtype})"
26
+
27
+ def writeModuleWithNumba(listDimensions):
28
+ numpy_dtypeLarge = dtypeLarge
29
+ numpy_dtypeDefault = dtypeDefault
30
+
31
+ parametersNumba = f"numba.types.{datatypeLarge}(), cache=True, parallel=False, boundscheck=False, \
32
+ error_model='numpy', fastmath=True, nogil=True, nopython=True, _nrt=True, forceinline=True, \
33
+ inline=True, looplift=True, no_cfunc_wrapper=False, no_cpython_wrapper=False"
34
+
35
+ pathFilenameData = Z0Z_makeJob(listDimensions, datatypeDefault=numpy_dtypeDefault, datatypeLarge=numpy_dtypeLarge)
36
+
37
+ pathFilenameAlgorithm = pathlib.Path('/apps/mapFolding/mapFolding/countSequentialNoNumba.py')
38
+ pathFilenameDestination = pathFilenameData.with_stem(pathFilenameData.parent.name).with_suffix(".py")
39
+
40
+ lineNumba = f"@numba.jit({parametersNumba})"
41
+
42
+ linesImport = "\n".join([
43
+ "import numpy"
44
+ , "import numba"
45
+ ])
46
+
47
+ stateJob = pickle.loads(pathFilenameData.read_bytes())
48
+
49
+ ImaIndent = ' '
50
+ linesDataDynamic = """"""
51
+ linesDataDynamic = "\n".join([linesDataDynamic
52
+ , ImaIndent + archivistFormatsArrayToCode(stateJob['my'], 'my')
53
+ , ImaIndent + archivistFormatsArrayToCode(stateJob['foldsSubTotals'], 'foldsSubTotals')
54
+ , ImaIndent + archivistFormatsArrayToCode(stateJob['gapsWhere'], 'gapsWhere')
55
+ , ImaIndent + archivistFormatsArrayToCode(stateJob['track'], 'track')
56
+ ])
57
+
58
+ linesDataStatic = """"""
59
+ linesDataStatic = "\n".join([linesDataStatic
60
+ , ImaIndent + archivistFormatsArrayToCode(stateJob['the'], 'the')
61
+ , ImaIndent + archivistFormatsArrayToCode(stateJob['connectionGraph'], 'connectionGraph')
62
+ ])
63
+
64
+ pathFilenameFoldsTotal: pathlib.Path = stateJob['pathFilenameFoldsTotal']
65
+
66
+ linesAlgorithm = """"""
67
+ for lineSource in pathFilenameAlgorithm.read_text().splitlines():
68
+ if lineSource.startswith('#'):
69
+ continue
70
+ elif not lineSource:
71
+ continue
72
+ elif lineSource.startswith('def '):
73
+ lineSource = "\n".join([lineNumba
74
+ , f"def {identifierCallableLaunch}():"
75
+ , linesDataDynamic
76
+ , linesDataStatic
77
+ ])
78
+ linesAlgorithm = "\n".join([linesAlgorithm
79
+ , lineSource
80
+ ])
81
+
82
+ lineReturn = f"{ImaIndent}return foldsSubTotals.sum().item()"
83
+
84
+ linesLaunch = """"""
85
+ linesLaunch = linesLaunch + f"""
86
+ if __name__ == '__main__':
87
+ foldsTotal = {identifierCallableLaunch}()"""
88
+
89
+ linesWriteFoldsTotal = """"""
90
+ linesWriteFoldsTotal = "\n".join([linesWriteFoldsTotal
91
+ , " print(foldsTotal)"
92
+ , f" open('{pathFilenameFoldsTotal.as_posix()}', 'w').write(str(foldsTotal))"
93
+ ])
94
+
95
+ linesAll = "\n".join([
96
+ linesImport
97
+ , linesAlgorithm
98
+ , f"{ImaIndent}print(foldsSubTotals.sum().item())"
99
+ , lineReturn
100
+ , linesLaunch
101
+ , linesWriteFoldsTotal
102
+ ])
103
+
104
+ pathFilenameDestination.write_text(linesAll)
105
+
106
+ return pathFilenameDestination
107
+
108
+ def writeModuleLLVM(pathFilenamePythonFile: pathlib.Path) -> pathlib.Path:
109
+ pathRootPackage = pathlib.Path('c:/apps/mapFolding')
110
+ relativePathModule = pathFilenamePythonFile.relative_to(pathRootPackage)
111
+ moduleTarget = '.'.join(relativePathModule.parts)[0:-len(relativePathModule.suffix)]
112
+ moduleTargetImported = importlib.import_module(moduleTarget)
113
+ linesLLVM = moduleTargetImported.__dict__[identifierCallableLaunch].inspect_llvm()[()]
114
+ moduleLLVM = llvmlite.binding.module.parse_assembly(linesLLVM)
115
+ pathFilenameLLVM = pathFilenamePythonFile.with_suffix(".ll")
116
+ pathFilenameLLVM.write_text(str(moduleLLVM))
117
+ return pathFilenameLLVM
118
+
119
+ if __name__ == '__main__':
120
+ pathFilenamePythonFile = writeModuleWithNumba(listDimensions)
121
+ pathFilenameLLVM = writeModuleLLVM(pathFilenamePythonFile)
@@ -1,15 +1,14 @@
1
- from mapFolding import outfitCountFolds, getFilenameFoldsTotal
2
- from typing import Optional, Sequence, Type, Union
1
+ from mapFolding import outfitCountFolds, getPathFilenameFoldsTotal, saveFoldsTotal
2
+ from typing import Any, Optional, Sequence, Type, Union
3
3
  import os
4
- import pathlib
5
4
 
6
- def countFolds(listDimensions: Sequence[int], writeFoldsTotal: Optional[Union[str, os.PathLike[str]]] = None, computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[int, float, bool]] = None, **keywordArguments: Optional[Type]) -> int:
5
+ def countFolds(listDimensions: Sequence[int], pathishWriteFoldsTotal: Optional[Union[str, os.PathLike[str]]] = None, computationDivisions: Optional[Union[int, str]] = None, CPUlimit: Optional[Union[int, float, bool]] = None, **keywordArguments: Optional[Type[Any]]) -> int:
7
6
  """Count the total number of possible foldings for a given map dimensions.
8
7
 
9
8
  Parameters:
10
9
  listDimensions: List of integers representing the dimensions of the map to be folded.
11
- writeFoldsTotal (None): Path or filename to write the total fold count.
12
- If a directory is provided, creates a file with default name based on map dimensions.
10
+ pathishWriteFoldsTotal (None): Path, filename, or pathFilename to write the total fold count to.
11
+ If a directory is provided, creates a file with a default name based on map dimensions.
13
12
  computationDivisions (None):
14
13
  Whether and how to divide the computational work. See notes for details.
15
14
  CPUlimit (None): This is only relevant if there are `computationDivisions`: whether and how to limit the CPU usage. See notes for details.
@@ -37,12 +36,8 @@ def countFolds(listDimensions: Sequence[int], writeFoldsTotal: Optional[Union[st
37
36
  stateUniversal = outfitCountFolds(listDimensions, computationDivisions=computationDivisions, CPUlimit=CPUlimit, **keywordArguments)
38
37
 
39
38
  pathFilenameFoldsTotal = None
40
- if writeFoldsTotal is not None:
41
- pathFilenameFoldsTotal = pathlib.Path(writeFoldsTotal)
42
- if pathFilenameFoldsTotal.is_dir():
43
- filenameFoldsTotalDEFAULT = getFilenameFoldsTotal(stateUniversal['mapShape'])
44
- pathFilenameFoldsTotal = pathFilenameFoldsTotal / filenameFoldsTotalDEFAULT
45
- pathFilenameFoldsTotal.parent.mkdir(parents=True, exist_ok=True)
39
+ if pathishWriteFoldsTotal is not None:
40
+ pathFilenameFoldsTotal = getPathFilenameFoldsTotal(stateUniversal['mapShape'], pathishWriteFoldsTotal)
46
41
 
47
42
  from mapFolding.babbage import _countFolds
48
43
  _countFolds(**stateUniversal)
@@ -50,10 +45,6 @@ def countFolds(listDimensions: Sequence[int], writeFoldsTotal: Optional[Union[st
50
45
  foldsTotal = stateUniversal['foldsSubTotals'].sum().item()
51
46
 
52
47
  if pathFilenameFoldsTotal is not None:
53
- try:
54
- pathFilenameFoldsTotal.write_text(str(foldsTotal))
55
- except Exception as ERRORmessage:
56
- print(ERRORmessage)
57
- print(f"\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal\n\n{foldsTotal=}\n\nfoldsTotal foldsTotal foldsTotal foldsTotal foldsTotal")
48
+ saveFoldsTotal(pathFilenameFoldsTotal, foldsTotal)
58
49
 
59
50
  return foldsTotal