mapFolding 0.7.1__py3-none-any.whl → 0.8.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.
Files changed (48) hide show
  1. mapFolding/__init__.py +33 -4
  2. mapFolding/basecamp.py +14 -0
  3. mapFolding/beDRY.py +93 -82
  4. mapFolding/filesystem.py +124 -90
  5. mapFolding/noHomeYet.py +14 -2
  6. mapFolding/oeis.py +18 -3
  7. mapFolding/reference/flattened.py +46 -45
  8. mapFolding/reference/hunterNumba.py +4 -4
  9. mapFolding/reference/irvineJavaPort.py +1 -1
  10. mapFolding/reference/lunnanNumpy.py +3 -4
  11. mapFolding/reference/lunnanWhile.py +5 -7
  12. mapFolding/reference/rotatedEntryPoint.py +2 -3
  13. mapFolding/someAssemblyRequired/__init__.py +33 -3
  14. mapFolding/someAssemblyRequired/getLLVMforNoReason.py +32 -15
  15. mapFolding/someAssemblyRequired/ingredientsNumba.py +108 -2
  16. mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +196 -0
  17. mapFolding/someAssemblyRequired/{synthesizeNumbaJob.py → synthesizeNumbaJobVESTIGIAL.py} +19 -23
  18. mapFolding/someAssemblyRequired/transformDataStructures.py +162 -0
  19. mapFolding/someAssemblyRequired/transformationTools.py +607 -252
  20. mapFolding/syntheticModules/numbaCount_doTheNeedful.py +197 -12
  21. mapFolding/theDao.py +37 -16
  22. mapFolding/theSSOT.py +47 -44
  23. {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info}/METADATA +51 -46
  24. mapfolding-0.8.1.dist-info/RECORD +39 -0
  25. {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info}/WHEEL +1 -1
  26. tests/conftest.py +2 -3
  27. tests/test_filesystem.py +0 -2
  28. tests/test_other.py +2 -3
  29. tests/test_tasks.py +0 -4
  30. mapFolding/reference/lunnan.py +0 -153
  31. mapFolding/someAssemblyRequired/Z0Z_workbench.py +0 -33
  32. mapFolding/someAssemblyRequired/synthesizeCountingFunctions.py +0 -7
  33. mapFolding/someAssemblyRequired/synthesizeDataConverters.py +0 -135
  34. mapFolding/someAssemblyRequired/synthesizeNumba.py +0 -91
  35. mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +0 -91
  36. mapFolding/someAssemblyRequired/whatWillBe.py +0 -357
  37. mapFolding/syntheticModules/dataNamespaceFlattened.py +0 -30
  38. mapFolding/syntheticModules/multiprocessingCount_doTheNeedful.py +0 -216
  39. mapFolding/syntheticModules/numbaCount.py +0 -90
  40. mapFolding/syntheticModules/numbaCountExample.py +0 -158
  41. mapFolding/syntheticModules/numbaCountSequential.py +0 -111
  42. mapFolding/syntheticModules/numba_doTheNeedful.py +0 -12
  43. mapFolding/syntheticModules/numba_doTheNeedfulExample.py +0 -13
  44. mapfolding-0.7.1.dist-info/RECORD +0 -51
  45. /mapFolding/{syntheticModules → reference}/__init__.py +0 -0
  46. {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info}/entry_points.txt +0 -0
  47. {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info/licenses}/LICENSE +0 -0
  48. {mapfolding-0.7.1.dist-info → mapfolding-0.8.1.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,17 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: mapFolding
3
- Version: 0.7.1
4
- Summary: Count distinct ways to fold a map (or a strip of stamps)
3
+ Version: 0.8.1
4
+ Summary: Map folding algorithm with code transformation framework for optimizing numerical computations
5
5
  Author-email: Hunter Hogan <HunterHogan@pm.me>
6
6
  License: CC-BY-NC-4.0
7
7
  Project-URL: Donate, https://www.patreon.com/integrated
8
8
  Project-URL: Homepage, https://github.com/hunterhogan/mapFolding
9
9
  Project-URL: Repository, https://github.com/hunterhogan/mapFolding.git
10
- Keywords: A001415,A001416,A001417,A001418,A195646,combinatorics,folding,map folding,OEIS,optimization,stamp folding
10
+ Keywords: A001415,A001416,A001417,A001418,A195646,algorithmic optimization,AST manipulation,code generation,code transformation,combinatorics,computational geometry,dataclass transformation,folding pattern enumeration,just-in-time compilation,map folding,Numba optimization,OEIS,performance optimization,source code analysis,stamp folding
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
13
14
  Classifier: Intended Audience :: Education
14
- Classifier: Intended Audience :: End Users/Desktop
15
- Classifier: Intended Audience :: Other Audience
16
15
  Classifier: Intended Audience :: Science/Research
17
16
  Classifier: Natural Language :: English
18
17
  Classifier: Operating System :: OS Independent
@@ -23,7 +22,10 @@ Classifier: Programming Language :: Python :: 3.11
23
22
  Classifier: Programming Language :: Python :: 3.12
24
23
  Classifier: Programming Language :: Python :: 3.13
25
24
  Classifier: Topic :: Scientific/Engineering :: Mathematics
25
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
26
+ Classifier: Topic :: Software Development :: Code Generators
26
27
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
28
+ Classifier: Topic :: Software Development :: Compilers
27
29
  Classifier: Typing :: Typed
28
30
  Requires-Python: >=3.10
29
31
  Description-Content-Type: text/markdown
@@ -38,12 +40,12 @@ Requires-Dist: tomli
38
40
  Requires-Dist: Z0Z_tools
39
41
  Provides-Extra: testing
40
42
  Requires-Dist: mypy; extra == "testing"
43
+ Requires-Dist: pytest; extra == "testing"
41
44
  Requires-Dist: pytest-cov; extra == "testing"
42
45
  Requires-Dist: pytest-env; extra == "testing"
43
46
  Requires-Dist: pytest-xdist; extra == "testing"
44
- Requires-Dist: pytest; extra == "testing"
45
47
  Requires-Dist: pyupgrade; extra == "testing"
46
- Requires-Dist: updateCitation; extra == "testing"
48
+ Dynamic: license-file
47
49
 
48
50
  # mapFolding: Algorithms for enumerating distinct map/stamp folding patterns 🗺️
49
51
 
@@ -52,8 +54,6 @@ Requires-Dist: updateCitation; extra == "testing"
52
54
  [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml)
53
55
  ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen)
54
56
  [![License: CC-BY-NC-4.0](https://img.shields.io/badge/License-CC_BY--NC_4.0-3b434b)](https://creativecommons.org/licenses/by-nc/4.0/)
55
- ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding)
56
- ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
57
57
 
58
58
  ---
59
59
 
@@ -101,44 +101,49 @@ Available OEIS sequences:
101
101
 
102
102
  ### 2. **Algorithm Zoo** 🦒
103
103
 
104
- - **Lunnons 1971 Algorithm**: A painstakingly debugged version of [the original typo-riddled code](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt)
104
+ - **Lunnon's 1971 Algorithm**: A painstakingly debugged version of [the original typo-riddled code](https://github.com/hunterhogan/mapFolding/blob/mapFolding/reference/foldings.txt)
105
105
  - The /reference directory.
106
106
  - **Numba-JIT Accelerated**: Up to 1000× faster than pure Python ([benchmarks](https://github.com/hunterhogan/mapFolding/blob/mapFolding/notes/Speed%20highlights.md))
107
107
 
108
- ### 3. **For Researchers** 🔬
109
-
110
- - Change multiple minute settings, such as the bit width of the data types.
111
- - Transform the algorithm using AST
112
- - Create hyper-optimized modules to compute a specific map.
113
-
114
- ### 4. **Customizing your algorithm**
115
-
116
- - mapFolding\someAssemblyRequired\synthesizeNumbaJob.py (and/or synthesizeNumba____.py, as applicable)
117
- - Synthesize a Numba-optimized module for a specific mapShape
118
- - Synthesize _from_ a module in mapFolding\syntheticModules or from any source you select
119
- - Use the existing transformation options
120
- - Or create new ways of transforming the algorithm from its source to a specific job
121
- - mapFolding\someAssemblyRequired\makeJob.py
122
- - Initialize data for a specific mapShape
123
- - mapFolding\someAssemblyRequired\synthesizeNumbaModules.py (and/or synthesizeNumba____.py, as applicable)
124
- - Synthesize one or more Numba-optimized modules for parallel or sequential computation
125
- - Overwrite the modules in mapFolding\syntheticModules or save the module(s) to a custom path
126
- - Synthesize _from_ the algorithm(s) in mapFolding\theDao.py or from any source you select
127
- - Use the existing transformation options
128
- - Or create new ways of transforming the algorithm from its source to a new module
129
- - Use your new module in synthesizeNumbaJob.py, above, as the source to create a mapShape-specific job module
130
- - mapFolding\theDao.py
131
- - Modify the algorithms for initializing values, parallel computation, and/or sequential computation
132
- - Use the modified algorithm(s) in synthesizeNumbaModules.py, above, to create Numba-optimized version(s)
133
- - Then use a Numba-optimized version in synthesizeNumbaJob.py, above, to create a hyper-optimized version for a specific mapShape
134
- - mapFolding\theSSOT.py (and/or theSSOTnumba.py and/ or theSSOT____.py, if they exist)
135
- - Modify broad settings or find functions to modify broad settings, such as data structures and their data types
136
- - Create new settings or groups of settings
137
- - mapFolding\beDRY.py
138
- - Functions to handle common tasks, such as parsing parameters or creating the `connectionGraph` for a mapShape (a Cartesian product decomposition)
139
- - mapFolding\someAssemblyRequired
140
- - Create new transformations to optimize the algorithm, such as for JAX, CuPy, or CUDA
141
- - (mapFolding\reference\jax.py has a once-functional JAX implementation, and synthesizeModuleJAX.py might be a useful starting point)
108
+ ### 3. **For Researchers and Power Users** 🔬
109
+
110
+ This package provides a sophisticated code transformation framework that can turn readable algorithm implementations into highly-optimized computational engines:
111
+
112
+ - **Algorithmic Exploration**: Study the core algorithm in `theDao.py`, which uses a functional state-transformation approach with clear, isolated functions
113
+ - **Performance Optimization**: Generate specialized implementations with the `someAssemblyRequired` transformation pipeline:
114
+ - AST-based code analysis and manipulation
115
+ - Dataclass "shattering" to decompose complex state objects into primitive components
116
+ - Just-in-time compilation with Numba and various optimization profiles
117
+ - LLVM IR extraction for low-level algorithmic analysis
118
+
119
+ - **Extensible Design**: The transformation framework is abstract and generic, enabling:
120
+ - Creation of new optimization targets beyond the included Numba implementation
121
+ - Customization of compilation parameters and optimization levels
122
+ - Development of specialized algorithms for specific map dimensions
123
+
124
+ ### 4. **Customization and Extension Guide**
125
+
126
+ The package architecture supports multiple levels of customization:
127
+
128
+ - **Basic Usage**: Work with the high-level API in `basecamp.py` for standard computations
129
+ - **Algorithm Modification**:
130
+ - Modify the core algorithm in `theDao.py` while preserving its functional approach
131
+ - Configure system-wide settings in `theSSOT.py` to adjust data types and performance characteristics
132
+ - Use utility functions in `beDRY.py` for common operations
133
+
134
+ - **Advanced Transformation**:
135
+ - The `someAssemblyRequired` package provides tools to transform code at the AST level:
136
+ - `transformationTools.py` contains utilities for AST manipulation and code generation
137
+ - `transformDataStructures.py` handles complex data structure transformations
138
+ - `ingredientsNumba.py` provides Numba-specific configuration profiles
139
+ - `synthesizeNumbaFlow.py` orchestrates the transformation process
140
+
141
+ - **Custom Deployment**:
142
+ - Generate specialized implementations for specific dimensions
143
+ - Create optimized modules that can be executed as standalone scripts
144
+ - Extract LLVM IR for further analysis or optimization
145
+
146
+ The package's multi-level design allows you to start with simple API calls and progressively delve deeper into optimization as your computational needs grow.
142
147
 
143
148
  ## Map-folding Video
144
149
 
@@ -155,4 +160,4 @@ Available OEIS sequences:
155
160
  [![Static Badge](https://img.shields.io/badge/2011_August-Homeless_since-blue?style=flat)](https://HunterThinks.com/support)
156
161
  [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC3Gx7kz61009NbhpRtPP7tw)](https://www.youtube.com/@HunterHogan)
157
162
 
158
- [![CC-BY-NC-4.0](https://github.com/hunterhogan/mapFolding/blob/main/CC-BY-NC-4.0.png)](https://creativecommons.org/licenses/by-nc/4.0/)
163
+ [![CC-BY-NC-4.0](https://github.com/hunterhogan/mapFolding/blob/main/CC-BY-NC-4.0.svg)](https://creativecommons.org/licenses/by-nc/4.0/)
@@ -0,0 +1,39 @@
1
+ mapFolding/__init__.py,sha256=hYxPUBU6A1_XCbKEseSDamooTsb1mzN_XHqaRLPvpGk,1701
2
+ mapFolding/basecamp.py,sha256=7ghnbEcgMaGJYCy08GpOg0O28gY5P36ZibJkjs_r-Rg,4481
3
+ mapFolding/beDRY.py,sha256=WRbvissfUGAmYbj1o0ZpGvq_9hwllDqpNwuC2_yxFyM,9785
4
+ mapFolding/filesystem.py,sha256=-pYpWugd0p3TrAz7xf9YIJW-pn1X-iRCGtJgEAF9Rns,5923
5
+ mapFolding/noHomeYet.py,sha256=UKZeWlyn0SKlF9dhYoud7E6gWXpiSEekZOOoJp88WeI,1362
6
+ mapFolding/oeis.py,sha256=xArJ8X3HqzopKIKYdKwxk7Y62vtXZFxvZ0jEqv-8GO0,12625
7
+ mapFolding/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ mapFolding/theDao.py,sha256=Blzm5j24x1BE2nvgXjdzHEeuc2na6kAH9b_eP6PcwlI,9836
9
+ mapFolding/theSSOT.py,sha256=pyetKz_Yuofm_z2XhNaQT_CWTatuAykZO2bxEPy9wS4,13670
10
+ mapFolding/reference/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ mapFolding/reference/flattened.py,sha256=KEIR8hhOW0NHDX52LHJrrTUY5QaCzexZF0S6P2wvogY,15209
12
+ mapFolding/reference/hunterNumba.py,sha256=9MEy2szRSENZc9l1_VnRqBnnd71z4KjoPwOWnOwb9Pw,6105
13
+ mapFolding/reference/irvineJavaPort.py,sha256=UkOSX0_dkKR84hp8aqHPuf7KLz_nVnji9M0IF_hRVm8,3418
14
+ mapFolding/reference/jax.py,sha256=7ji9YWia6Kof0cjcNdiS1GG1rMbC5SBjcyVr_07AeUk,13845
15
+ mapFolding/reference/lunnanNumpy.py,sha256=isI0dOYZM1CZi1P4NEojl9L2Kh45mOYtc2C8yXUit8E,3731
16
+ mapFolding/reference/lunnanWhile.py,sha256=z1hcE6SeK0CFJSS4LggmzzsLNjU3dU26LsL5y_ZGBxM,3231
17
+ mapFolding/reference/rotatedEntryPoint.py,sha256=S3y5hSUTYOR_lKBnd5SwufvjNvg3UP-Je4wpYRB-_78,9328
18
+ mapFolding/reference/total_countPlus1vsPlusN.py,sha256=wpgay-uqPOBd64Z4Pg6tg40j7-4pzWHGMM6v0bnmjhE,6288
19
+ mapFolding/someAssemblyRequired/__init__.py,sha256=xA5a-nZjXIwcqEOig5PEZSxde4_m3JJ5Pb0CN4aiRjw,2488
20
+ mapFolding/someAssemblyRequired/getLLVMforNoReason.py,sha256=bGI8RZY-RnyR9TNF0r0OXwA6fm4TYH2cHy7WzhsnddQ,1895
21
+ mapFolding/someAssemblyRequired/ingredientsNumba.py,sha256=g6Z7t35NpoDskzm0OLwTQhHw5CYiYktVYxI2NhCQHww,8435
22
+ mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py,sha256=EtzULVeivQ_4G2E2UKqXoZLx6XwRcbBDzhtzwCTOEfs,10627
23
+ mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py,sha256=RBSrtr7US2P7mkY-EA-b2WIOxjs2b0WJaCln1ERxOcI,22314
24
+ mapFolding/someAssemblyRequired/transformDataStructures.py,sha256=0qtILOuH8I4CWFog64SPAyOWTylCa2Yh7L_hILrQY9Q,8279
25
+ mapFolding/someAssemblyRequired/transformationTools.py,sha256=vLRKAtaXa9RmoISUbFvQIWHDHor6CYctm7NEgU11T_E,40743
26
+ mapFolding/syntheticModules/numbaCount_doTheNeedful.py,sha256=52RuwJVH2fROvWU2dT8wYcQvLgRuvkNZPq01kujCC_U,15725
27
+ mapfolding-0.8.1.dist-info/licenses/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
28
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ tests/conftest.py,sha256=rRlXOhihwheHyQ8ggjRBbmgPVERxWjupajguVBzBkVE,10783
30
+ tests/test_computations.py,sha256=YhadlskBh_r5RiefHRy0FlrYQ0FelYbqcSNNSkSJMIY,3368
31
+ tests/test_filesystem.py,sha256=Kou0gj5T72oISao6umYfU6L_W5Hi7QS9_IxTv2hU0Pw,3147
32
+ tests/test_oeis.py,sha256=uxvwmgbnylSDdsVJfuAT0LuYLbIVFwSgdLxHm-xUGBM,5043
33
+ tests/test_other.py,sha256=1uuApByNWPiTf0zaro2dETkvyWQFfMweU_ge4aJuVgM,4244
34
+ tests/test_tasks.py,sha256=hkZygihT8bCEO2zc-2VcxReQrZJBwgLNbYx0YP4lTDg,2853
35
+ mapfolding-0.8.1.dist-info/METADATA,sha256=Upa7kSAeKLeSk33CiII-W08xLugqgnqwIBVQu4VLEQg,7892
36
+ mapfolding-0.8.1.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
37
+ mapfolding-0.8.1.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
38
+ mapfolding-0.8.1.dist-info/top_level.txt,sha256=1gP2vFaqPwHujGwb3UjtMlLEGN-943VSYFR7V4gDqW8,17
39
+ mapfolding-0.8.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (77.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
tests/conftest.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from collections.abc import Callable, Generator, Sequence
2
- from mapFolding.theSSOT import getAlgorithmDispatcher, getSourceAlgorithm, getPackageDispatcher, theModuleOfSyntheticModules, FREAKOUT
2
+ from mapFolding.theSSOT import getAlgorithmDispatcher, getSourceAlgorithm, getPackageDispatcher, theModuleOfSyntheticModules, raiseIfNoneGitHubIssueNumber3
3
3
  from mapFolding.beDRY import getLeavesTotal, validateListDimensions, makeDataContainer
4
4
  from mapFolding.oeis import oeisIDsImplemented, settingsOEIS
5
5
  from pathlib import Path
@@ -10,7 +10,6 @@ import random
10
10
  import shutil
11
11
  import unittest.mock
12
12
  import uuid
13
- # TODO learn how to run tests and coverage analysis without `env = ["NUMBA_DISABLE_JIT=1"]`
14
13
 
15
14
  # SSOT for test data paths and filenames
16
15
  pathDataSamples = Path("tests/dataSamples")
@@ -215,7 +214,7 @@ def syntheticDispatcherFixture(useThisDispatcher: Callable[..., Any]) -> Callabl
215
214
  dispatcherSynthetic = stuff
216
215
 
217
216
  if dispatcherSynthetic is None:
218
- raise FREAKOUT
217
+ raise raiseIfNoneGitHubIssueNumber3
219
218
 
220
219
  dispatcherSpec = importlib.util.spec_from_file_location(dispatcherSynthetic.callableSynthesized, dispatcherSynthetic.pathFilenameForMe)
221
220
  if dispatcherSpec is None:
tests/test_filesystem.py CHANGED
@@ -3,9 +3,7 @@ from mapFolding.filesystem import getFilenameFoldsTotal, getPathFilenameFoldsTot
3
3
  from mapFolding.beDRY import validateListDimensions
4
4
  from mapFolding.theSSOT import getPathJobRootDEFAULT
5
5
  from pathlib import Path
6
- from typing import Any
7
6
  import io
8
- import numpy
9
7
  import pytest
10
8
  import unittest.mock
11
9
 
tests/test_other.py CHANGED
@@ -42,8 +42,8 @@ import sys
42
42
  (tuple([3, 5, 7]), [3, 5, 7], (3, 5, 7)), # tuple sequence type
43
43
  ])
44
44
  def test_listDimensionsAsParameter(listDimensions: None | list[str] | list[int] | list[float] | list[None] | list[bool] | list[list[int]] | list[complex] | range | tuple[int, ...],
45
- expected_intInnit: type[ValueError] | list[int] | type[TypeError],
46
- expected_validateListDimensions: type[ValueError] | type[NotImplementedError] | tuple[int, ...] | type[TypeError]) -> None:
45
+ expected_intInnit: type[ValueError] | list[int] | type[TypeError],
46
+ expected_validateListDimensions: type[ValueError] | type[NotImplementedError] | tuple[int, ...] | type[TypeError]) -> None:
47
47
  """Test both validateListDimensions and getLeavesTotal with the same inputs."""
48
48
  standardizedEqualToCallableReturn(expected_intInnit, intInnit, listDimensions)
49
49
  standardizedEqualToCallableReturn(expected_validateListDimensions, validateListDimensions, listDimensions)
@@ -56,7 +56,6 @@ def test_getLeavesTotal_edge_cases() -> None:
56
56
  # Input preservation
57
57
  mapShape = (2, 3)
58
58
  standardizedEqualToCallableReturn(6, getLeavesTotal, mapShape)
59
- # Remove the lambda entirely for a simpler approach
60
59
  assert mapShape == (2, 3), "Input tuple was modified"
61
60
 
62
61
  @pytest.mark.parametrize("nameOfTest,callablePytest", PytestFor_intInnit())
tests/test_tasks.py CHANGED
@@ -12,10 +12,6 @@ import pytest
12
12
  if __name__ == '__main__':
13
13
  multiprocessing.set_start_method('spawn')
14
14
 
15
-
16
- # TODO add a test. `C` = number of logical cores available. `n = C + 1`. Ensure that `[2,n]` is computed correctly.
17
- # Or, probably smarter: limit the number of cores, then run a test with C+1.
18
-
19
15
  def test_countFoldsComputationDivisionsInvalid(mapShapeTestFunctionality: tuple[int, ...]) -> None:
20
16
  standardizedEqualToCallableReturn(ValueError, countFolds, mapShapeTestFunctionality, None, {"wrong": "value"})
21
17
 
@@ -1,153 +0,0 @@
1
- """
2
- An unnecessarily literal translation of the original Atlas Autocode code by W. F. Lunnon to Python.
3
- W. F. Lunnon, Multi-dimensional map-folding, The Computer Journal, Volume 14, Issue 1, 1971, Pages 75-80, https://doi.org/10.1093/comjnl/14.1.75
4
- """# NOTE not functional yet
5
- def foldings(p, job=None):
6
- """An unnecessarily literal translation of the original Atlas Autocode code."""
7
- p = list(p)
8
- p.append(None) # NOTE mimics Atlas `array` type
9
- p.insert(0, None) # NOTE mimics Atlas `array` type
10
-
11
- if job is None:
12
- global G
13
- G = 0
14
- def job(A, B):
15
- global G
16
- G = G + 1
17
- return foldings(p, job)
18
- # perform job (A, B) on each folding of a p[1] x ... x p[d] map,
19
- # where A and B are the above and below vectors. p[d + 1] < 0 terminates p;
20
-
21
- d: int
22
- n: int
23
- j: int
24
- i: int
25
- m: int
26
- l: int
27
- g: int
28
- gg: int
29
- dd: int
30
-
31
- n = 1
32
- i, d = 0, 0
33
-
34
- while (i := i + 1) and p[i] is not None:
35
- d = i
36
- n = n * p[i]
37
-
38
- # d dimensions and n leaves;
39
-
40
- # A: list[int] = [None] * (n + 1) # type: ignore
41
- # B: list[int] = [None] * (n + 1) # type: ignore
42
- # count: list[int] = [None] * (n + 1) # type: ignore
43
- # gapter: list[int] = [None] * (n + 1) # type: ignore
44
- # gap: list[int] = [None] * (n * n + 1) # type: ignore
45
- A: list[int] = [0] * (n + 1) # type: ignore
46
- B: list[int] = [0] * (n + 1) # type: ignore
47
- count: list[int] = [0] * (n + 1) # type: ignore
48
- gapter: list[int] = [0] * (n + 1) # type: ignore
49
- gap: list[int] = [0] * (n * n + 1) # type: ignore
50
-
51
- # B[m] is the leaf below leaf m in the current folding,
52
- # A[m] the leaf above. count[m] is the no. of sections in which
53
- # there is a gap for the new leaf l below leaf m,
54
- # gap[gapter[l - 1] + j] is the j-th (possible or actual) gap for leaf l,
55
- # and later gap[gapter[l]] is the gap where leaf l is currently inserted;
56
-
57
- P: list[int] = [0] * (d + 1) # type: ignore
58
- C: list[list[int]] = [[0] * (n + 1) for dimension1 in range(d + 1)] # type: ignore
59
- # D: list[list[list[int]]] = [[[None] * (n + 1) for dimension2 in range(n + 1)] for dimension1 in range(d + 1)] # type: ignore
60
- D: list[list[list[int]]] = [[[0] * (n + 1) for dimension2 in range(n + 1)] for dimension1 in range(d + 1)]
61
-
62
- P[0] = 1
63
- for i in range(1, d + 1):
64
- P[i] = P[i - 1] * p[i]
65
-
66
- for i in range(1, d + 1):
67
- for m in range(1, n + 1):
68
- C[i][m] = ((m - 1) // P[i - 1]) - ((m - 1) // P[i]) * p[i] + 1
69
-
70
- for i in range(1, d + 1):
71
- for l in range(1, n + 1):
72
- for m in range(1, l + 1):
73
- D[i][l][m] = (0 if m == 0
74
- else
75
- ((m if C[i][m] == 1
76
- else m - P[i - 1])
77
- if C[i][l] - C[i][m] == (C[i][l] - C[i][m]) // 2 * 2
78
- else
79
- (m if C[i][m] == p[i] or m + P[i - 1] > l
80
- else m + P[i - 1])))
81
- # P[i] = p[1] x ... x p[i], C[i][m] = i-th co-ordinate of leaf m,
82
- # D[i][l][m] = leaf connected to m in section i when inserting l;
83
-
84
- for m in range(n + 1):
85
- count[m] = 0
86
-
87
- A[0], B[0], g, l = 0, 0, 0, 0
88
-
89
- state = 'entry'
90
- while True:
91
- if state == 'entry':
92
- gapter[l] = g
93
- l = l + 1
94
- if l <= n:
95
- state = 'down'
96
- continue
97
- else:
98
- job(A, B)
99
- state = 'up'
100
- continue
101
-
102
- elif state == 'down':
103
- dd = 0
104
- gg = gapter[l - 1]
105
- g = gg
106
- for i in range(1, d + 1):
107
- if D[i][l][l] == l:
108
- dd = dd + 1
109
- else:
110
- m = D[i][l][l]
111
- while m != l:
112
- gap[gg] = m
113
- if count[m] == 0:
114
- gg = gg + 1
115
- count[m] = count[m] + 1
116
- m = D[i][l][B[m]]
117
-
118
- if dd == d:
119
- for m in range(l):
120
- gap[gg] = m
121
- gg = gg + 1
122
-
123
- for j in range(g, gg):
124
- gap[g] = gap[j]
125
- if count[gap[j]] == d - dd:
126
- g = g + 1
127
- count[gap[j]] = 0
128
- state = 'along'
129
- continue
130
-
131
- elif state == 'along':
132
- if g == gapter[l - 1]:
133
- state = 'up'
134
- continue
135
- g = g - 1
136
- A[l] = gap[g]
137
- B[l] = B[A[l]]
138
- B[A[l]] = l
139
- A[B[l]] = l
140
- state = 'entry'
141
- continue
142
-
143
- elif state == 'up':
144
- l = l - 1
145
- B[A[l]] = B[l]
146
- A[B[l]] = A[l]
147
- if l > 0:
148
- state = 'along'
149
- continue
150
- else:
151
- break
152
-
153
- return G #if job.__closure__ else None
@@ -1,33 +0,0 @@
1
- from mapFolding.someAssemblyRequired.synthesizeDataConverters import makeDataclassConverter
2
- from mapFolding.someAssemblyRequired.whatWillBe import IngredientsFunction, IngredientsModule, numbaFlow
3
- from mapFolding.someAssemblyRequired.synthesizeCountingFunctions import Z0Z_makeCountingFunction
4
- import ast
5
-
6
- if __name__ == '__main__':
7
- ingredientsFunctionDataConverter = makeDataclassConverter(
8
- dataclassIdentifier=numbaFlow.sourceDataclassIdentifier
9
- , logicalPathModuleDataclass=numbaFlow.logicalPathModuleDataclass
10
- , dataclassInstance=numbaFlow.dataclassInstance
11
-
12
- , dispatcherCallable=numbaFlow.dispatcherCallable
13
- , logicalPathModuleDispatcher=numbaFlow.logicalPathModuleDispatcher
14
- , dataConverterCallable=numbaFlow.dataConverterCallable
15
- )
16
-
17
- # initialize with theDao
18
- dataInitializationHack = "state=makeStateJob(state.mapShape,writeJob=False)"
19
- ingredientsFunctionDataConverter.FunctionDef.body.insert(0, ast.parse(dataInitializationHack).body[0])
20
- ingredientsFunctionDataConverter.imports.addImportFromStr('mapFolding.someAssemblyRequired', 'makeStateJob')
21
-
22
- ingredientsSequential = Z0Z_makeCountingFunction(numbaFlow.sequentialCallable
23
- , numbaFlow.sourceAlgorithm
24
- , inline=True
25
- , dataclass=False)
26
-
27
- ingredientsModuleDataConverter = IngredientsModule(
28
- name=numbaFlow.dataConverterModule,
29
- ingredientsFunction=ingredientsFunctionDataConverter,
30
- logicalPathINFIX=numbaFlow.Z0Z_flowLogicalPathRoot,
31
- )
32
-
33
- ingredientsModuleDataConverter.writeModule()
@@ -1,7 +0,0 @@
1
- from mapFolding.someAssemblyRequired import IngredientsFunction, Make
2
- from typing import cast
3
- from types import ModuleType
4
- import ast
5
-
6
- def Z0Z_makeCountingFunction(callableTarget: str, sourceAlgorithm: ModuleType, inline: bool, dataclass: bool):
7
- pass
@@ -1,135 +0,0 @@
1
- from collections.abc import Sequence
2
- from importlib import import_module
3
- from inspect import getsource as inspect_getsource
4
- from pathlib import Path
5
- from types import ModuleType
6
- from typing import Any, cast, overload, Literal
7
- import ast
8
- import pickle
9
- from mapFolding.beDRY import ComputationState, outfitCountFolds, validateListDimensions
10
- from mapFolding.filesystem import getPathFilenameFoldsTotal
11
- from mapFolding.someAssemblyRequired import (
12
- ast_Identifier,
13
- executeActionUnlessDescendantMatches,
14
- extractClassDef,
15
- ifThis,
16
- IngredientsFunction,
17
- LedgerOfImports,
18
- Make,
19
- NodeCollector,
20
- strDotStrCuzPyStoopid,
21
- Then,
22
- )
23
- from mapFolding.theSSOT import getSourceAlgorithm
24
-
25
- def shatter_dataclassesDOTdataclass(logicalPathModule: strDotStrCuzPyStoopid, dataclass_Identifier: ast_Identifier, instance_Identifier: ast_Identifier
26
- ) -> tuple[ast.Name, LedgerOfImports, list[ast.AnnAssign], list[ast.Name], list[ast.keyword], ast.Tuple]:
27
- """
28
- Parameters:
29
- logicalPathModule: gimme string cuz python is stoopid
30
- dataclass_Identifier: The identifier of the dataclass to be dismantled.
31
- instance_Identifier: In the synthesized module/function/scope, the identifier that will be used for the instance.
32
- """
33
- module: ast.Module = ast.parse(inspect_getsource(import_module(logicalPathModule)))
34
-
35
- dataclass = extractClassDef(dataclass_Identifier, module)
36
-
37
- if not isinstance(dataclass, ast.ClassDef):
38
- raise ValueError(f"I could not find {dataclass_Identifier=} in {logicalPathModule=}.")
39
-
40
- list_astAnnAssign: list[ast.AnnAssign] = []
41
- listKeywordForDataclassInitialization: list[ast.keyword] = []
42
- list_astNameDataclassFragments: list[ast.Name] = []
43
- ledgerDataclassAndFragments = LedgerOfImports()
44
-
45
- addToLedgerPredicate = ifThis.isAnnAssignAndAnnotationIsName
46
- addToLedgerAction = Then.Z0Z_ledger(logicalPathModule, ledgerDataclassAndFragments)
47
- addToLedger = NodeCollector(addToLedgerPredicate, [addToLedgerAction])
48
-
49
- exclusionPredicate = ifThis.is_keyword_IdentifierEqualsConstantValue('init', False)
50
- appendKeywordAction = Then.Z0Z_appendKeywordMirroredTo(listKeywordForDataclassInitialization)
51
- filteredAppendKeywordAction = executeActionUnlessDescendantMatches(exclusionPredicate, appendKeywordAction)
52
-
53
- collector = NodeCollector(
54
- ifThis.isAnnAssignAndTargetIsName,
55
- [Then.Z0Z_appendAnnAssignOfNameDOTnameTo(instance_Identifier, list_astAnnAssign)
56
- , Then.append_targetTo(list_astNameDataclassFragments)
57
- , lambda node: addToLedger.visit(node)
58
- , filteredAppendKeywordAction
59
- ]
60
- )
61
-
62
- collector.visit(dataclass)
63
-
64
- ledgerDataclassAndFragments.addImportFromStr(logicalPathModule, dataclass_Identifier)
65
-
66
- astNameDataclass = Make.astName(dataclass_Identifier)
67
- astTupleForAssignTargetsToFragments: ast.Tuple = Make.astTuple(list_astNameDataclassFragments, ast.Store())
68
- return astNameDataclass, ledgerDataclassAndFragments, list_astAnnAssign, list_astNameDataclassFragments, listKeywordForDataclassInitialization, astTupleForAssignTargetsToFragments
69
-
70
- def makeDataclassConverter(dataclassIdentifier: str,
71
- logicalPathModuleDataclass: str,
72
- dataclassInstance: str,
73
- dispatcherCallable: str,
74
- logicalPathModuleDispatcher: str,
75
- dataConverterCallable: str,
76
- ) -> IngredientsFunction:
77
-
78
- astNameDataclass, ledgerDataclassAndFragments, list_astAnnAssign, list_astNameDataclassFragments, list_astKeywordDataclassFragments, astTupleForAssignTargetsToFragments = shatter_dataclassesDOTdataclass(logicalPathModuleDataclass, dataclassIdentifier, dataclassInstance)
79
-
80
- ingredientsFunction = IngredientsFunction(
81
- FunctionDef = Make.astFunctionDef(name=dataConverterCallable
82
- , argumentsSpecification=Make.astArgumentsSpecification(args=[Make.astArg(dataclassInstance, astNameDataclass)])
83
- , body = cast(list[ast.stmt], list_astAnnAssign)
84
- , returns = astNameDataclass
85
- )
86
- , imports = ledgerDataclassAndFragments
87
- )
88
-
89
- callToDispatcher = Make.astAssign(listTargets=[astTupleForAssignTargetsToFragments]
90
- , value=Make.astCall(Make.astName(dispatcherCallable), args=list_astNameDataclassFragments))
91
- ingredientsFunction.FunctionDef.body.append(callToDispatcher)
92
- ingredientsFunction.imports.addImportFromStr(logicalPathModuleDispatcher, dispatcherCallable)
93
-
94
- ingredientsFunction.FunctionDef.body.append(Make.astReturn(Make.astCall(astNameDataclass, list_astKeywords=list_astKeywordDataclassFragments)))
95
-
96
- return ingredientsFunction
97
-
98
- @overload
99
- def makeStateJob(listDimensions: Sequence[int], *, writeJob: Literal[True], **keywordArguments: Any) -> Path: ...
100
- @overload
101
- def makeStateJob(listDimensions: Sequence[int], *, writeJob: Literal[False], **keywordArguments: Any) -> ComputationState: ...
102
- def makeStateJob(listDimensions: Sequence[int], *, writeJob: bool = True, **keywordArguments: Any) -> ComputationState | Path:
103
- """
104
- Creates a computation state job for map folding calculations and optionally saves it to disk.
105
-
106
- This function initializes a computation state for map folding calculations based on the given dimensions,
107
- sets up the initial counting configuration, and can optionally save the state to a pickle file.
108
-
109
- Parameters:
110
- listDimensions: List of integers representing the dimensions of the map to be folded.
111
- writeJob (True): Whether to save the state to disk.
112
- **keywordArguments: Additional keyword arguments to pass to the computation state initialization.
113
-
114
- Returns:
115
- stateUniversal|pathFilenameJob: The computation state for the map folding calculations, or
116
- the path to the saved state file if writeJob is True.
117
- """
118
- mapShape = validateListDimensions(listDimensions)
119
- stateUniversal = outfitCountFolds(mapShape, **keywordArguments)
120
-
121
- moduleSource: ModuleType = getSourceAlgorithm()
122
- # TODO `countInitialize` is hardcoded
123
- stateUniversal: ComputationState = moduleSource.countInitialize(stateUniversal)
124
-
125
- if not writeJob:
126
- return stateUniversal
127
-
128
- pathFilenameChopChop = getPathFilenameFoldsTotal(stateUniversal.mapShape, None)
129
- suffix = pathFilenameChopChop.suffix
130
- pathJob = Path(str(pathFilenameChopChop)[0:-len(suffix)])
131
- pathJob.mkdir(parents=True, exist_ok=True)
132
- pathFilenameJob = pathJob / 'stateJob.pkl'
133
-
134
- pathFilenameJob.write_bytes(pickle.dumps(stateUniversal))
135
- return pathFilenameJob