mapFolding 0.17.1__py3-none-any.whl → 0.18.0__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.
- easyRun/NOTcountingFolds.py +7 -11
- easyRun/countFolds.py +11 -10
- easyRun/meanders.py +6 -8
- mapFolding/__init__.py +24 -36
- mapFolding/_e/Z0Z_analysisPython/SORTZ0Z_hypothesis.py +189 -0
- mapFolding/_e/Z0Z_analysisPython/SORTZ0Z_p2d6.py +143 -0
- mapFolding/_e/Z0Z_analysisPython/__init__.py +4 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/__init__.py +0 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200.py +369 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/2001.py +694 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/270/211.py +514 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/270/2111.py +480 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214.py +511 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/2141.py +515 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214/344/270/211.py +485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214/344/270/2111.py +442 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/211.py +313 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/2111.py +343 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214.py +400 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/2141.py +497 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214/344/270/211.py +463 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214/344/270/2111.py +441 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266.py +35 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/2661.py +35 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200.py +382 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/2001.py +630 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/270/211.py +488 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/270/2111.py +475 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214.py +473 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/2141.py +500 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +465 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +439 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/211.py +599 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/2111.py +536 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214.py +506 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/2141.py +533 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214/344/270/211.py +489 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214/344/270/2111.py +474 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2001.py +2158 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2001Negative.py +2158 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200Negative.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/211.py +1397 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/2111.py +1291 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/2111Negative.py +1291 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/211Negative.py +1397 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214.py +1240 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/2141.py +1420 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/2141Negative.py +1420 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214Negative.py +1240 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/211.py +1366 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/2111.py +1274 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/2111Negative.py +1274 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/211Negative.py +1366 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/211.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2111.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2111Negative.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/211Negative.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214.py +1102 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/2141.py +1422 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/2141Negative.py +1422 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214Negative.py +1102 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/211.py +1240 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/2111.py +1228 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/2111Negative.py +1228 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/211Negative.py +1240 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266.py +32 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/2661.py +1162 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/2661Negative.py +1162 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266Negative.py +32 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2001.py +1926 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2001Negative.py +1926 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200Negative.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/211.py +1291 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/2111.py +1176 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/2111Negative.py +1176 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/211Negative.py +1291 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214.py +1228 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/2141.py +1324 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/2141Negative.py +1324 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214Negative.py +1228 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +1274 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +1038 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111Negative.py +1038 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211Negative.py +1274 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/211.py +2158 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2111.py +1926 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2111Negative.py +1926 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/211Negative.py +2158 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214.py +1422 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/2141.py +1364 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/2141Negative.py +1364 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214Negative.py +1422 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/211.py +1420 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/2111.py +1324 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/2111Negative.py +1324 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/211Negative.py +1420 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200.py +3133 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2001.py +6039 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2001Negative.py +6039 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200Negative.py +3133 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/211.py +3527 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/2111.py +2300 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/2111Negative.py +2300 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/211Negative.py +3527 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214.py +3597 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/2141.py +3317 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/2141Negative.py +3317 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214Negative.py +3597 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/211.py +3161 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/2111.py +2877 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/2111Negative.py +2877 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/211Negative.py +3161 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/211.py +2981 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2111.py +3055 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2111Negative.py +3055 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/211Negative.py +2981 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214.py +3221 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/2141.py +3988 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/2141Negative.py +3988 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214Negative.py +3221 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/211.py +3652 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/2111.py +2863 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/2111Negative.py +2863 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/211Negative.py +3652 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200.py +2485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2001.py +4566 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2001Negative.py +4566 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200Negative.py +2485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/211.py +3006 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/2111.py +2485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/2111Negative.py +2485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/211Negative.py +3006 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214.py +3304 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/2141.py +3015 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/2141Negative.py +3015 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214Negative.py +3304 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +2939 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +2589 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111Negative.py +2589 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211Negative.py +2939 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/211.py +3899 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2111.py +2996 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2111Negative.py +2996 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/211Negative.py +3899 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214.py +3223 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/2141.py +3020 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/2141Negative.py +3020 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214Negative.py +3223 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/211.py +3250 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/2111.py +2667 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/2111Negative.py +2667 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/211Negative.py +3250 -0
- mapFolding/_e/Z0Z_analysisPython/measure.py +162 -0
- mapFolding/_e/Z0Z_analysisPython/positionAnalysis.py +403 -0
- mapFolding/_e/Z0Z_analysisPython/positionAnalysisPileRanges2d6.py +110 -0
- mapFolding/_e/Z0Z_analysisPython/theExcluderBeast.py +640 -0
- mapFolding/_e/Z0Z_analysisPython/toolkit.py +166 -0
- mapFolding/_e/Z0Z_analysisPython/toolkitCSVsequences.py +188 -0
- mapFolding/_e/Z0Z_analysisPython/workBenchPatternFinder.py +284 -0
- mapFolding/_e/Z0Z_notes/__init__.py +0 -0
- mapFolding/_e/Z0Z_notes/knowledgeDump.py +214 -0
- mapFolding/_e/__init__.py +45 -0
- mapFolding/_e/_beDRY.py +547 -0
- mapFolding/_e/_dataDynamic.py +1164 -0
- mapFolding/_e/_measure.py +579 -0
- mapFolding/_e/_semiotics.py +363 -0
- mapFolding/_e/_theTypes.py +31 -0
- mapFolding/_e/algorithms/__init__.py +1 -0
- mapFolding/_e/algorithms/constraintPropagation.py +158 -0
- mapFolding/_e/algorithms/elimination.py +118 -0
- mapFolding/_e/algorithms/eliminationCrease.py +66 -0
- mapFolding/_e/algorithms/iff.py +584 -0
- mapFolding/_e/basecamp.py +89 -0
- mapFolding/_e/dataBaskets.py +123 -0
- mapFolding/_e/dataRaw/__init__.py +0 -0
- mapFolding/_e/easyRun/__init__.py +0 -0
- mapFolding/_e/easyRun/eliminateFolds.py +72 -0
- mapFolding/_e/easyRun/pinning.py +62 -0
- mapFolding/_e/filters.py +384 -0
- mapFolding/_e/pin2/344/270/212nDimensions.py +882 -0
- mapFolding/_e/pin2/344/270/212nDimensionsAnnex.py +551 -0
- mapFolding/_e/pin2/344/270/212nDimensionsByCrease.py +190 -0
- mapFolding/_e/pin2/344/270/212nDimensionsByDomain.py +459 -0
- mapFolding/_e/pinIt.py +436 -0
- mapFolding/_semiotics.py +42 -0
- mapFolding/_theSSOT.py +11 -56
- mapFolding/_theTypes.py +52 -67
- mapFolding/algorithms/matrixMeandersNumPyndas.py +18 -18
- mapFolding/algorithms/oeisIDbyFormula.py +4 -4
- mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +3 -3
- mapFolding/basecamp.py +11 -80
- mapFolding/beDRY.py +107 -111
- mapFolding/dataBaskets.py +0 -56
- mapFolding/filesystemToolkit.py +15 -11
- mapFolding/oeis.py +17 -16
- mapFolding/reference/matrixMeandersAnalysis/prefixNotationNotes.py +2 -2
- mapFolding/reference/meandersDumpingGround/matrixMeandersBaselineV2.py +0 -1
- mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +8 -10
- mapFolding/someAssemblyRequired/RecipeJob.py +5 -5
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +5 -2
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +9 -11
- mapFolding/someAssemblyRequired/mapFoldingModules/makeMapFoldingModules.py +2 -1
- mapFolding/someAssemblyRequired/transformationTools.py +1 -1
- mapFolding/tests/Z0Z_test_e_excluder.py +155 -0
- mapFolding/tests/conftest.py +193 -314
- mapFolding/tests/dataSamples/A001417.py +455 -0
- mapFolding/tests/dataSamples/__init__.py +1 -0
- mapFolding/tests/dataSamples/measurementData.py +1818 -0
- mapFolding/tests/dataSamples/p2DnDomain3_2_/351/246/226/344/270/200_/351/246/226/351/233/266/344/270/200.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain3_/351/246/226/344/270/200.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain5_4.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain6_5.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain6_7_5_4.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain7_6.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain/351/246/226/344/272/214_/351/246/226/351/233/266/344/270/200/344/272/214.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain/351/246/226/344/272/214_/351/246/226/351/233/266/344/272/214_/351/246/226/351/233/266/344/270/200/344/272/214_/351/246/226/344/270/200/344/272/214.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain/351/246/226/351/233/266/344/270/200/344/272/214_/351/246/226/344/270/200/344/272/214.py +15 -0
- mapFolding/tests/dataSamples/p2DnDomain/351/246/226/351/233/266/344/272/214_/351/246/226/344/272/214.py +15 -0
- mapFolding/tests/dataSamples/semioticsData.py +135 -0
- mapFolding/tests/test_computations.py +134 -80
- mapFolding/tests/test_e_computations.py +42 -0
- mapFolding/tests/test_e_dataDynamic.py +189 -0
- mapFolding/tests/test_e_measurements.py +257 -0
- mapFolding/tests/test_e_pinning.py +61 -0
- mapFolding/tests/test_e_semiotics.py +128 -0
- mapFolding/tests/test_filesystem.py +39 -17
- mapFolding/tests/{test_other.py → test_parameterValidation.py} +3 -3
- mapFolding/tests/{test_tasks.py → test_taskDivisions.py} +42 -23
- mapFolding/zCuzDocStoopid/makeDocstrings.py +3 -2
- {mapfolding-0.17.1.dist-info → mapfolding-0.18.0.dist-info}/METADATA +11 -8
- mapfolding-0.18.0.dist-info/RECORD +305 -0
- {mapfolding-0.17.1.dist-info → mapfolding-0.18.0.dist-info}/WHEEL +1 -1
- easyRun/eliminateFolds.py +0 -60
- mapFolding/algorithms/constraintPropagation.py +0 -184
- mapFolding/algorithms/elimination.py +0 -131
- mapFolding/algorithms/eliminationCount.py +0 -26
- mapFolding/algorithms/eliminationPinned.py +0 -35
- mapFolding/algorithms/iff.py +0 -206
- mapFolding/algorithms/patternFinder.py +0 -280
- mapFolding/algorithms/pinning2Dn.py +0 -345
- mapFolding/algorithms/pinning2DnAnnex.py +0 -43
- mapFolding/tests/verify.py +0 -323
- mapfolding-0.17.1.dist-info/RECORD +0 -112
- {mapfolding-0.17.1.dist-info → mapfolding-0.18.0.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.17.1.dist-info → mapfolding-0.18.0.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.17.1.dist-info → mapfolding-0.18.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
from functools import cache
|
|
2
|
+
from hunterMakesPy.parseParameters import intInnit
|
|
3
|
+
from mapFolding._e import DimensionIndex
|
|
4
|
+
from math import log
|
|
5
|
+
from operator import getitem
|
|
6
|
+
|
|
7
|
+
#======== Using a single-base positional-numeral system as a proxy for Cartesian coordinates =======
|
|
8
|
+
# https://en.wikipedia.org/wiki/Positional_notation
|
|
9
|
+
|
|
10
|
+
# Ideogram pronunciation references:
|
|
11
|
+
# https://en.wikipedia.org/wiki/Chinese_numerals
|
|
12
|
+
# https://en.wikipedia.org/wiki/Japanese_numerals
|
|
13
|
+
# https://en.wikipedia.org/wiki/Korean_numerals
|
|
14
|
+
# https://en.wikipedia.org/wiki/Vietnamese_numerals
|
|
15
|
+
|
|
16
|
+
"""NOTE Do you hate my system of ideographs for powers of 2?
|
|
17
|
+
|
|
18
|
+
With relatively little effort you could use `astToolkit` (pip install astToolkit) to replace all of the ideographs with
|
|
19
|
+
`state.productsOfDimensions[dimensionIndex]`. With `astToolkit`, you create a transformation that you can apply after any update.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
_dimensionLength: int = 2 # Hypothetically, change to 3 for 3^d-dimensional maps.
|
|
23
|
+
_dimensionIndex: DimensionIndex = 0 # == 0
|
|
24
|
+
|
|
25
|
+
零: int = _dimensionLength ** _dimensionIndex
|
|
26
|
+
"""dimensionIndex = 0: assign `1` to `dimensionIndex = 0`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
27
|
+
- index zero
|
|
28
|
+
- líng
|
|
29
|
+
- ling4
|
|
30
|
+
- rei
|
|
31
|
+
- yeong
|
|
32
|
+
- linh
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
# 一
|
|
36
|
+
_base: int = _dimensionLength
|
|
37
|
+
_dimensionIndex += 1 # == 1
|
|
38
|
+
_power: int = _dimensionIndex
|
|
39
|
+
一: int = _base ** _power # == _dimensionLength ** _dimensionIndex
|
|
40
|
+
"""dimensionIndex = 1: assign `1` to `dimensionIndex = 1`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
41
|
+
- index one
|
|
42
|
+
- yī
|
|
43
|
+
- jat1
|
|
44
|
+
- ichi
|
|
45
|
+
- il
|
|
46
|
+
- nhất
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# 二
|
|
50
|
+
_radix: int = _dimensionLength
|
|
51
|
+
_dimensionIndex += 1 # == 2
|
|
52
|
+
_place_ValueIndex: int = _dimensionIndex
|
|
53
|
+
二: int = _radix ** _place_ValueIndex # == _dimensionLength ** _dimensionIndex
|
|
54
|
+
"""dimensionIndex = 2: assign `1` to `dimensionIndex = 2`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
55
|
+
- index two
|
|
56
|
+
- èr
|
|
57
|
+
- ji6
|
|
58
|
+
- ni
|
|
59
|
+
- i
|
|
60
|
+
- nhị
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
# etc.
|
|
64
|
+
三: int = _dimensionLength ** 3
|
|
65
|
+
"""dimensionIndex = 3: assign `1` to `dimensionIndex = 3`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
66
|
+
- index three
|
|
67
|
+
- sān
|
|
68
|
+
- saam1
|
|
69
|
+
- san
|
|
70
|
+
- sam
|
|
71
|
+
- tam
|
|
72
|
+
"""
|
|
73
|
+
四: int = _dimensionLength ** 4
|
|
74
|
+
"""dimensionIndex = 4: assign `1` to `dimensionIndex = 4`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
75
|
+
- index four
|
|
76
|
+
- sì
|
|
77
|
+
- sei3
|
|
78
|
+
- shi
|
|
79
|
+
- sa
|
|
80
|
+
- tứ
|
|
81
|
+
"""
|
|
82
|
+
五: int = _dimensionLength ** 5
|
|
83
|
+
"""dimensionIndex = 5: assign `1` to `dimensionIndex = 5`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
84
|
+
- index five
|
|
85
|
+
- wǔ
|
|
86
|
+
- ng5
|
|
87
|
+
- go
|
|
88
|
+
- o
|
|
89
|
+
- ngũ
|
|
90
|
+
"""
|
|
91
|
+
六: int = _dimensionLength ** 6
|
|
92
|
+
"""dimensionIndex = 6: assign `1` to `dimensionIndex = 6`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
93
|
+
- index six
|
|
94
|
+
- liù
|
|
95
|
+
- luk6
|
|
96
|
+
- roku
|
|
97
|
+
- yuk
|
|
98
|
+
- lục
|
|
99
|
+
"""
|
|
100
|
+
七: int = _dimensionLength ** 7
|
|
101
|
+
"""dimensionIndex = 7: assign `1` to `dimensionIndex = 7`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
102
|
+
- index seven
|
|
103
|
+
- qī
|
|
104
|
+
- cat1
|
|
105
|
+
- shichi
|
|
106
|
+
- chil
|
|
107
|
+
- thất
|
|
108
|
+
"""
|
|
109
|
+
八: int = _dimensionLength ** 8
|
|
110
|
+
"""dimensionIndex = 8: assign `1` to `dimensionIndex = 8`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
111
|
+
- index eight
|
|
112
|
+
- bā
|
|
113
|
+
- baat3
|
|
114
|
+
- hachi
|
|
115
|
+
- pal
|
|
116
|
+
- bát
|
|
117
|
+
"""
|
|
118
|
+
九: int = _dimensionLength ** 9
|
|
119
|
+
"""dimensionIndex = 9: assign `1` to `dimensionIndex = 9`, and assign `0` to each other `DimensionIndex`. Read as (any of):
|
|
120
|
+
- index nine
|
|
121
|
+
- jiǔ
|
|
122
|
+
- gau2
|
|
123
|
+
- kyū
|
|
124
|
+
- gu
|
|
125
|
+
- cửu
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
@cache
|
|
129
|
+
def dimensionIndex(dimensionAsNonnegativeInteger: int, /, *, dimensionLength: int = _dimensionLength) -> int:
|
|
130
|
+
"""Convert the integer value of a single dimension into its corresponding `DimensionIndex`."""
|
|
131
|
+
dimension: int = getitem(intInnit([dimensionAsNonnegativeInteger], 'dimensionNonnegative', int), 0)
|
|
132
|
+
if dimension < 0:
|
|
133
|
+
message: str = f"I received `{dimensionAsNonnegativeInteger = }`, but I need a value greater than or equal to 0."
|
|
134
|
+
raise ValueError(message)
|
|
135
|
+
base: int = getitem(intInnit([dimensionLength], 'dimensionLength', int), 0)
|
|
136
|
+
if base < 1:
|
|
137
|
+
message: str = f"I received `{dimensionLength = }`, but I need an integer value greater than 1."
|
|
138
|
+
raise ValueError(message)
|
|
139
|
+
place_ValueIndex: float = log(dimension, base)
|
|
140
|
+
if not place_ValueIndex.is_integer():
|
|
141
|
+
message: str = f"I received `{dimensionAsNonnegativeInteger = }`, but I need a value that is an integer power of `{dimensionLength = }`."
|
|
142
|
+
raise ValueError(message)
|
|
143
|
+
return int(place_ValueIndex)
|
|
144
|
+
|
|
145
|
+
#-------- Access the dimension coordinates encoded in a number relative to the number's most significant digit -------
|
|
146
|
+
|
|
147
|
+
@cache
|
|
148
|
+
def 首零(dimensionsTotal: int, /) -> int:
|
|
149
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `零` (`dimensionIndex = 0`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
150
|
+
|
|
151
|
+
Read as (any of):
|
|
152
|
+
- from the head, index zero
|
|
153
|
+
- shǒu líng
|
|
154
|
+
- sau2 ling4
|
|
155
|
+
- shu rei
|
|
156
|
+
- su yeong
|
|
157
|
+
- thủ linh
|
|
158
|
+
"""
|
|
159
|
+
return int('1' + '0' * (dimensionsTotal - 1), _dimensionLength)
|
|
160
|
+
|
|
161
|
+
@cache
|
|
162
|
+
def 首零一(dimensionsTotal: int, /) -> int:
|
|
163
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `零` and `一` (`dimensionIndex = 0` and `dimensionIndex = 1`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
164
|
+
|
|
165
|
+
Read as (any of):
|
|
166
|
+
- from the head, indices zero-one
|
|
167
|
+
- shǒu líng yī
|
|
168
|
+
- sau2 ling4 jat1
|
|
169
|
+
- shu rei ichi
|
|
170
|
+
- su yeong il
|
|
171
|
+
- thủ linh nhất
|
|
172
|
+
"""
|
|
173
|
+
return int('11' + '0' * (dimensionsTotal - 2), _dimensionLength)
|
|
174
|
+
|
|
175
|
+
@cache
|
|
176
|
+
def 首零一二(dimensionsTotal: int, /) -> int:
|
|
177
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `零`, `一`, and `二` (`dimensionIndex = 0`, `dimensionIndex = 1`, and `dimensionIndex = 2`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
178
|
+
|
|
179
|
+
Read as (any of):
|
|
180
|
+
- from the head, indices zero-one-two
|
|
181
|
+
- shǒu líng yī èr
|
|
182
|
+
- sau2 ling4 jat1 ji6
|
|
183
|
+
- shu rei ichi ni
|
|
184
|
+
- su yeong il i
|
|
185
|
+
- thủ linh nhất nhị
|
|
186
|
+
"""
|
|
187
|
+
return int('111' + '0' * (dimensionsTotal - 3), _dimensionLength)
|
|
188
|
+
|
|
189
|
+
@cache
|
|
190
|
+
def 首零二(dimensionsTotal: int, /) -> int:
|
|
191
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `零` and `二` (`dimensionIndex = 0` and `dimensionIndex = 2`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
192
|
+
|
|
193
|
+
Read as (any of):
|
|
194
|
+
- from the head, indices zero-two
|
|
195
|
+
- shǒu líng èr
|
|
196
|
+
- sau2 ling4 ji6
|
|
197
|
+
- shu rei ni
|
|
198
|
+
- su yeong i
|
|
199
|
+
- thủ linh nhị
|
|
200
|
+
"""
|
|
201
|
+
return int('101' + '0' * (dimensionsTotal - 3), _dimensionLength)
|
|
202
|
+
|
|
203
|
+
@cache
|
|
204
|
+
def 首一(dimensionsTotal: int, /) -> int:
|
|
205
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `一` (`dimensionIndex = 1`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
206
|
+
|
|
207
|
+
Read as (any of):
|
|
208
|
+
- from the head, index one
|
|
209
|
+
- shǒu yī
|
|
210
|
+
- sau2 jat1
|
|
211
|
+
- shu ichi
|
|
212
|
+
- su il
|
|
213
|
+
- thủ nhất
|
|
214
|
+
"""
|
|
215
|
+
return int('01' + '0' * (dimensionsTotal - 2), _dimensionLength)
|
|
216
|
+
|
|
217
|
+
@cache
|
|
218
|
+
def 首一二(dimensionsTotal: int, /) -> int:
|
|
219
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `一` and `二` (`dimensionIndex = 1` and `dimensionIndex = 2`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
220
|
+
|
|
221
|
+
Read as (any of):
|
|
222
|
+
- from the head, indices one-two
|
|
223
|
+
- shǒu yī èr
|
|
224
|
+
- sau2 jat1 ji6
|
|
225
|
+
- shu ichi ni
|
|
226
|
+
- su il i
|
|
227
|
+
- thủ nhất nhị
|
|
228
|
+
"""
|
|
229
|
+
return int('011' + '0' * (dimensionsTotal - 3), _dimensionLength)
|
|
230
|
+
|
|
231
|
+
@cache
|
|
232
|
+
def 首二(dimensionsTotal: int, /) -> int:
|
|
233
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `二` (`dimensionIndex = 2`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
234
|
+
|
|
235
|
+
Read as (any of):
|
|
236
|
+
- from the head, index two
|
|
237
|
+
- shǒu èr
|
|
238
|
+
- sau2 ji6
|
|
239
|
+
- shu ni
|
|
240
|
+
- su i
|
|
241
|
+
- thủ nhị
|
|
242
|
+
"""
|
|
243
|
+
return int('001' + '0' * (dimensionsTotal - 3), _dimensionLength)
|
|
244
|
+
|
|
245
|
+
@cache
|
|
246
|
+
def 首三(dimensionsTotal: int, /) -> int:
|
|
247
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `三` (`dimensionIndex = 3`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
248
|
+
|
|
249
|
+
Read as (any of):
|
|
250
|
+
- from the head, index three
|
|
251
|
+
- shǒu sān
|
|
252
|
+
- sau2 saam1
|
|
253
|
+
- shu san
|
|
254
|
+
- su sam
|
|
255
|
+
- thủ tam
|
|
256
|
+
"""
|
|
257
|
+
return int('0001' + '0' * (dimensionsTotal - 4), _dimensionLength)
|
|
258
|
+
|
|
259
|
+
@cache
|
|
260
|
+
def 首零一二三(dimensionsTotal: int, /) -> int:
|
|
261
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `零`, `一`, `二`, and `三` (`dimensionIndex = 0`, `dimensionIndex = 1`, `dimensionIndex = 2`, and `dimensionIndex = 3`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
262
|
+
|
|
263
|
+
Read as (any of):
|
|
264
|
+
- from the head, indices zero-one-two-three
|
|
265
|
+
- shǒu líng yī èr sān
|
|
266
|
+
- sau2 ling4 jat1 ji6 saam1
|
|
267
|
+
- shu rei ichi ni san
|
|
268
|
+
- su yeong il i sam
|
|
269
|
+
- thủ linh nhất nhị tam
|
|
270
|
+
"""
|
|
271
|
+
return int('1111' + '0' * (dimensionsTotal - 4), _dimensionLength)
|
|
272
|
+
|
|
273
|
+
@cache
|
|
274
|
+
def 首零一三(dimensionsTotal: int, /) -> int:
|
|
275
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `零`, `一`, and `三` (`dimensionIndex = 0`, `dimensionIndex = 1`, and `dimensionIndex = 3`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
276
|
+
|
|
277
|
+
Read as (any of):
|
|
278
|
+
- from the head, indices zero-one-three
|
|
279
|
+
- shǒu líng yī sān
|
|
280
|
+
- sau2 ling4 jat1 saam1
|
|
281
|
+
- shu rei ichi san
|
|
282
|
+
- su yeong il sam
|
|
283
|
+
- thủ linh nhất tam
|
|
284
|
+
"""
|
|
285
|
+
return int('1101' + '0' * (dimensionsTotal - 4), _dimensionLength)
|
|
286
|
+
|
|
287
|
+
@cache
|
|
288
|
+
def 首零二三(dimensionsTotal: int, /) -> int:
|
|
289
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `零`, `二`, and `三` (`dimensionIndex = 0`, `dimensionIndex = 2`, and `dimensionIndex = 3`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
290
|
+
|
|
291
|
+
Read as (any of):
|
|
292
|
+
- from the head, indices zero-two-three
|
|
293
|
+
- shǒu líng èr sān
|
|
294
|
+
- sau2 ling4 ji6 saam1
|
|
295
|
+
- shu rei ni san
|
|
296
|
+
- su yeong i sam
|
|
297
|
+
- thủ linh nhị tam
|
|
298
|
+
"""
|
|
299
|
+
return int('1011' + '0' * (dimensionsTotal - 4), _dimensionLength)
|
|
300
|
+
|
|
301
|
+
@cache
|
|
302
|
+
def 首零三(dimensionsTotal: int, /) -> int:
|
|
303
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `零` and `三` (`dimensionIndex = 0` and `dimensionIndex = 3`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
304
|
+
|
|
305
|
+
Read as (any of):
|
|
306
|
+
- from the head, indices zero-three
|
|
307
|
+
- shǒu líng sān
|
|
308
|
+
- sau2 ling4 saam1
|
|
309
|
+
- shu rei san
|
|
310
|
+
- su yeong sam
|
|
311
|
+
- thủ linh tam
|
|
312
|
+
"""
|
|
313
|
+
return int('1001' + '0' * (dimensionsTotal - 4), _dimensionLength)
|
|
314
|
+
|
|
315
|
+
@cache
|
|
316
|
+
def 首一二三(dimensionsTotal: int, /) -> int:
|
|
317
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `一`, `二`, and `三` (`dimensionIndex = 1`, `dimensionIndex = 2`, and `dimensionIndex = 3`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
318
|
+
|
|
319
|
+
Read as (any of):
|
|
320
|
+
- from the head, indices one-two-three
|
|
321
|
+
- shǒu yī èr sān
|
|
322
|
+
- sau2 jat1 ji6 saam1
|
|
323
|
+
- shu ichi ni san
|
|
324
|
+
- su il i sam
|
|
325
|
+
- thủ nhất nhị tam
|
|
326
|
+
"""
|
|
327
|
+
return int('0111' + '0' * (dimensionsTotal - 4), _dimensionLength)
|
|
328
|
+
|
|
329
|
+
@cache
|
|
330
|
+
def 首一三(dimensionsTotal: int, /) -> int:
|
|
331
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `一` and `三` (`dimensionIndex = 1` and `dimensionIndex = 3`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
332
|
+
|
|
333
|
+
Read as (any of):
|
|
334
|
+
- from the head, indices one-three
|
|
335
|
+
- shǒu yī sān
|
|
336
|
+
- sau2 jat1 saam1
|
|
337
|
+
- shu ichi san
|
|
338
|
+
- su il sam
|
|
339
|
+
- thủ nhất tam
|
|
340
|
+
"""
|
|
341
|
+
return int('0101' + '0' * (dimensionsTotal - 4), _dimensionLength)
|
|
342
|
+
|
|
343
|
+
@cache
|
|
344
|
+
def 首二三(dimensionsTotal: int, /) -> int:
|
|
345
|
+
"""Enumerate each `DimensionIndex` starting from the head `首`, assign `1` to `二` and `三` (`dimensionIndex = 2` and `dimensionIndex = 3`), and assign `0` to each other `DimensionIndex` in `dimensionsTotal`.
|
|
346
|
+
|
|
347
|
+
Read as (any of):
|
|
348
|
+
- from the head, indices two-three
|
|
349
|
+
- shǒu èr sān
|
|
350
|
+
- sau2 ji6 saam1
|
|
351
|
+
- shu ni san
|
|
352
|
+
- su i sam
|
|
353
|
+
- thủ nhị tam
|
|
354
|
+
"""
|
|
355
|
+
return int('0011' + '0' * (dimensionsTotal - 4), _dimensionLength)
|
|
356
|
+
|
|
357
|
+
#======== Semantic replacements for ambiguous values =======
|
|
358
|
+
|
|
359
|
+
leafOrigin: int = (0 * 九) + (0 * 八) + (0 * 七) + (0 * 六) + (0 * 五) + (0 * 四) + (0 * 三) + (0 * 二) + (0 * 一) + (0 * 零)
|
|
360
|
+
"""The `leaf` at the origin of all dimensions, with `0` in every `DimensionIndex`."""
|
|
361
|
+
pileOrigin: int = (0 * 九) + (0 * 八) + (0 * 七) + (0 * 六) + (0 * 五) + (0 * 四) + (0 * 三) + (0 * 二) + (0 * 一) + (0 * 零)
|
|
362
|
+
"""The `pile` at the origin of all dimensions, with `0` in every `DimensionIndex`."""
|
|
363
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from gmpy2 import mpz
|
|
2
|
+
|
|
3
|
+
# NOTE HEY!!! Are you -> RENAMING <- a type alias? Pylance will NOT do a global update unless you delete `type `. You can add it back afterwards.
|
|
4
|
+
|
|
5
|
+
#======== Scalars ================================
|
|
6
|
+
|
|
7
|
+
type DimensionIndex = int
|
|
8
|
+
"""Zero-based index of a dimension."""
|
|
9
|
+
type Leaf = int
|
|
10
|
+
type Pile = int
|
|
11
|
+
|
|
12
|
+
type PileRangeOfLeaves = mpz
|
|
13
|
+
"""But I am le tired."""
|
|
14
|
+
|
|
15
|
+
type LeafOrPileRangeOfLeaves = Leaf | PileRangeOfLeaves
|
|
16
|
+
"""Zen take a nap, and then fire the missiles!"""
|
|
17
|
+
|
|
18
|
+
#======== Containers ============================
|
|
19
|
+
|
|
20
|
+
type Folding = tuple[Leaf, ...]
|
|
21
|
+
"""`leaf` indexed to `pile`; length must be `leavesTotal`."""
|
|
22
|
+
|
|
23
|
+
type PermutationSpace = dict[Pile, LeafOrPileRangeOfLeaves]
|
|
24
|
+
"""`pile: leaf` or `pile: pileRangeOfLeaves`; length must be `leavesTotal`."""
|
|
25
|
+
|
|
26
|
+
type PilesWithPileRangeOfLeaves = dict[Pile, PileRangeOfLeaves]
|
|
27
|
+
"""`pile: pileRangeOfLeaves`; length less than or equal to `leavesTotal`."""
|
|
28
|
+
|
|
29
|
+
type PinnedLeaves = dict[Pile, Leaf]
|
|
30
|
+
"""`pile: leaf`; length ought to be less than `leavesTotal`: when length equals `leavesTotal`, ought to convert to `Folding`."""
|
|
31
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Hand-made algorithms and formulas."""
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
from pprint import pprint
|
|
2
|
+
from concurrent.futures import as_completed, Future, ProcessPoolExecutor
|
|
3
|
+
from cytoolz.itertoolz import last
|
|
4
|
+
from itertools import pairwise, product as CartesianProduct
|
|
5
|
+
from mapFolding import packageSettings
|
|
6
|
+
from mapFolding._e import (
|
|
7
|
+
getIteratorOfLeaves, indicesMapShapeDimensionLengthsAreEqual, Leaf, leafOrigin, mapShapeIs2上nDimensions, pileOrigin,
|
|
8
|
+
PilesWithPileRangeOfLeaves, PinnedLeaves)
|
|
9
|
+
from mapFolding._e.dataBaskets import EliminationState
|
|
10
|
+
from mapFolding._e.filters import between, extractPilesWithPileRangeOfLeaves, extractPinnedLeaves
|
|
11
|
+
from math import factorial, prod
|
|
12
|
+
from ortools.sat.python import cp_model
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from tqdm import tqdm
|
|
15
|
+
import csv
|
|
16
|
+
import uuid
|
|
17
|
+
|
|
18
|
+
def count(state: EliminationState) -> EliminationState:
|
|
19
|
+
model = cp_model.CpModel()
|
|
20
|
+
|
|
21
|
+
listLeavesInPileOrder: list[cp_model.IntVar] = [model.new_int_var(pileOrigin, state.pileLast, f"leafInPile[{pile}]") for pile in range(state.leavesTotal)]
|
|
22
|
+
listPilingsInLeafOrder: list[cp_model.IntVar] = [model.new_int_var(leafOrigin, state.leafLast, f"pileOfLeaf[{leaf}]") for leaf in range(state.leavesTotal)]
|
|
23
|
+
model.add_inverse(listLeavesInPileOrder, listPilingsInLeafOrder)
|
|
24
|
+
|
|
25
|
+
#======== Manual concurrency and targeted constraints ============================
|
|
26
|
+
dictionaryOfPileLeaf: PinnedLeaves = extractPinnedLeaves(state.permutationSpace)
|
|
27
|
+
for aPile, aLeaf in dictionaryOfPileLeaf.items():
|
|
28
|
+
model.add(listLeavesInPileOrder[aPile] == aLeaf)
|
|
29
|
+
|
|
30
|
+
pilesWithPileRangeOfLeaves: PilesWithPileRangeOfLeaves = extractPilesWithPileRangeOfLeaves(state.permutationSpace)
|
|
31
|
+
for aPile, aLeaf in pilesWithPileRangeOfLeaves.items():
|
|
32
|
+
model.add_allowed_assignments([listLeavesInPileOrder[aPile]], list(zip(getIteratorOfLeaves(aLeaf))))
|
|
33
|
+
|
|
34
|
+
#======== Lunnon Theorem 2(a): foldsTotal is divisible by leavesTotal ============================
|
|
35
|
+
model.add(listLeavesInPileOrder[pileOrigin] == leafOrigin)
|
|
36
|
+
|
|
37
|
+
#======== Lunnon Theorem 4: "G(p^d) is divisible by d!p^d." ============================
|
|
38
|
+
if 2 < max(state.mapShape):
|
|
39
|
+
for indicesSameDimensionLength in indicesMapShapeDimensionLengthsAreEqual(state.mapShape):
|
|
40
|
+
state.Theorem4Multiplier *= factorial(len(indicesSameDimensionLength))
|
|
41
|
+
for index_k, index_r in pairwise(indicesSameDimensionLength):
|
|
42
|
+
model.add(listPilingsInLeafOrder[state.productsOfDimensions[index_k]] < listPilingsInLeafOrder[state.productsOfDimensions[index_r]])
|
|
43
|
+
|
|
44
|
+
#======== Rules for 2^n-dimensional maps ============================
|
|
45
|
+
|
|
46
|
+
if mapShapeIs2上nDimensions(state.mapShape):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
#======== Lunnon Theorem 2(b): "If some [dimensionLength in state.mapShape] > 2, [foldsTotal] is divisible by 2 * [leavesTotal]." ============================
|
|
50
|
+
if (state.Theorem4Multiplier == 1) and (2 < max(state.mapShape)):
|
|
51
|
+
state.Theorem2Multiplier = 2
|
|
52
|
+
leafOrigin下_aDimension: int = last(filter(between(0, state.leafLast // 2), state.productsOfDimensions))
|
|
53
|
+
model.add(listPilingsInLeafOrder[leafOrigin下_aDimension] < listPilingsInLeafOrder[2 * leafOrigin下_aDimension])
|
|
54
|
+
|
|
55
|
+
#======== Forbidden inequalities ============================
|
|
56
|
+
def addLessThan(comparatorLeft: Leaf, comparatorRight: Leaf) -> cp_model.IntVar:
|
|
57
|
+
ruleΩ: cp_model.IntVar = model.new_bool_var(f"this_{comparatorLeft}_lessThan_{comparatorRight}")
|
|
58
|
+
model.add(listPilingsInLeafOrder[comparatorLeft] < listPilingsInLeafOrder[comparatorRight]).only_enforce_if(ruleΩ)
|
|
59
|
+
model.add(listPilingsInLeafOrder[comparatorRight] <= listPilingsInLeafOrder[comparatorLeft]).only_enforce_if(ruleΩ.Not())
|
|
60
|
+
return ruleΩ
|
|
61
|
+
|
|
62
|
+
def addForbiddenInequalityCycle(leaf_k: Leaf, leaf_r: Leaf, leaf_kCrease: Leaf, leaf_rCrease: Leaf) -> None:
|
|
63
|
+
k__小于_r: cp_model.IntVar = addLessThan(leaf_k, leaf_r) # 小, xiǎo: small, less; as in 李小龍, Lǐ Xiǎolóng, Lǐ little dragon, aka Bruce Lee
|
|
64
|
+
r1_小于_k: cp_model.IntVar = addLessThan(leaf_rCrease, leaf_k)
|
|
65
|
+
k1_小于_r1: cp_model.IntVar = addLessThan(leaf_kCrease, leaf_rCrease)
|
|
66
|
+
model.add_bool_or([k1_小于_r1.Not(), r1_小于_k.Not(), k__小于_r.Not()]) # [k+1 < r+1 < k < r]
|
|
67
|
+
|
|
68
|
+
r__小于_k1: cp_model.IntVar = addLessThan(leaf_r, leaf_kCrease)
|
|
69
|
+
model.add_bool_or([r1_小于_k.Not(), k__小于_r.Not(), r__小于_k1.Not()]) # [r+1 < k < r < k+1]
|
|
70
|
+
|
|
71
|
+
model.add_bool_or([k__小于_r.Not(), r__小于_k1.Not(), k1_小于_r1.Not()]) # [k < r < k+1 < r+1]
|
|
72
|
+
|
|
73
|
+
k__小于_r1: cp_model.IntVar = addLessThan(leaf_k, leaf_rCrease)
|
|
74
|
+
r1_小于_k1: cp_model.IntVar = addLessThan(leaf_rCrease, leaf_kCrease)
|
|
75
|
+
k1_小于_r: cp_model.IntVar = addLessThan(leaf_kCrease, leaf_r)
|
|
76
|
+
model.add_bool_or([k__小于_r1.Not(), r1_小于_k1.Not(), k1_小于_r.Not()]) # [k < r+1 < k+1 < r]
|
|
77
|
+
|
|
78
|
+
def leaf2IndicesCartesian(leaf: Leaf) -> tuple[int, ...]:
|
|
79
|
+
return tuple((leaf // prod(state.mapShape[0:dimension])) % state.mapShape[dimension] for dimension in range(state.dimensionsTotal))
|
|
80
|
+
|
|
81
|
+
def leafCreasePost(leaf: Leaf, dimension: int) -> Leaf | None:
|
|
82
|
+
leafCrease: Leaf | None = None
|
|
83
|
+
if leaf2IndicesCartesian(leaf)[dimension] + 1 < state.mapShape[dimension]:
|
|
84
|
+
leafCrease = leaf + prod(state.mapShape[0:dimension])
|
|
85
|
+
return leafCrease
|
|
86
|
+
|
|
87
|
+
for leaf_k, leaf_r in CartesianProduct(range(state.leafLast), range(1, state.leafLast)):
|
|
88
|
+
if leaf_k == leaf_r:
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
k下_indicesCartesian: tuple[int, ...] = leaf2IndicesCartesian(leaf_k) # 下, xià: below, subscript
|
|
92
|
+
r下_indicesCartesian: tuple[int, ...] = leaf2IndicesCartesian(leaf_r)
|
|
93
|
+
|
|
94
|
+
for aDimension in range(state.dimensionsTotal):
|
|
95
|
+
k1下_aDimension: Leaf | None = leafCreasePost(leaf_k, aDimension)
|
|
96
|
+
r1下_aDimension: Leaf | None = leafCreasePost(leaf_r, aDimension)
|
|
97
|
+
|
|
98
|
+
if k1下_aDimension and r1下_aDimension and ((k下_indicesCartesian[aDimension] - r下_indicesCartesian[aDimension]) % 2 == 0):
|
|
99
|
+
addForbiddenInequalityCycle(leaf_k, leaf_r, k1下_aDimension, r1下_aDimension)
|
|
100
|
+
|
|
101
|
+
#======== Solver ================================
|
|
102
|
+
solver = cp_model.CpSolver()
|
|
103
|
+
solver.parameters.enumerate_all_solutions = True
|
|
104
|
+
|
|
105
|
+
solver.parameters.log_search_progress = False
|
|
106
|
+
|
|
107
|
+
class FoldingCollector(cp_model.CpSolverSolutionCallback):
|
|
108
|
+
def __init__(self, _listOfIndicesLeafInPilingsOrder: list[cp_model.IntVar]) -> None:
|
|
109
|
+
super().__init__()
|
|
110
|
+
self._listOfIndicesLeafInPilingsOrder: list[cp_model.IntVar] = _listOfIndicesLeafInPilingsOrder
|
|
111
|
+
self.listFolding: list[list[Leaf]] = []
|
|
112
|
+
|
|
113
|
+
def on_solution_callback(self) -> None:
|
|
114
|
+
self.listFolding.append([self.value(leaf) for leaf in self._listOfIndicesLeafInPilingsOrder])
|
|
115
|
+
|
|
116
|
+
foldingCollector = FoldingCollector(listLeavesInPileOrder)
|
|
117
|
+
solver.solve(model, foldingCollector)
|
|
118
|
+
|
|
119
|
+
state.listFolding = list(map(tuple, foldingCollector.listFolding))
|
|
120
|
+
|
|
121
|
+
return state
|
|
122
|
+
|
|
123
|
+
def doTheNeedful(state: EliminationState, workersMaximum: int) -> EliminationState:
|
|
124
|
+
"""Do the things necessary so that `count` operates efficiently."""
|
|
125
|
+
if state.listPermutationSpace or (workersMaximum > 1):
|
|
126
|
+
|
|
127
|
+
with ProcessPoolExecutor(workersMaximum) as concurrencyManager:
|
|
128
|
+
|
|
129
|
+
if not state.listPermutationSpace:
|
|
130
|
+
pileForConcurrency: int = state.pileLast // 2
|
|
131
|
+
state.listPermutationSpace = [{pileForConcurrency: leaf} for leaf in range(state.leavesTotal)]
|
|
132
|
+
|
|
133
|
+
listClaimTickets: list[Future[EliminationState]] = [
|
|
134
|
+
concurrencyManager.submit(count, EliminationState(state.mapShape, permutationSpace=permutationSpace))
|
|
135
|
+
for permutationSpace in state.listPermutationSpace
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
for claimTicket in tqdm(as_completed(listClaimTickets), total=len(listClaimTickets), disable=False):
|
|
139
|
+
sherpa: EliminationState = claimTicket.result()
|
|
140
|
+
|
|
141
|
+
# TODO NOTE temporary data collection for p2d7
|
|
142
|
+
if (sherpa.dimensionsTotal == 7) and (sherpa.listFolding):
|
|
143
|
+
pathFilename: Path = packageSettings.pathPackage / "_e" / "dataRaw" / f"p2d7_{uuid.uuid4()}.csv"
|
|
144
|
+
with Path.open(pathFilename, mode="w", newline="") as fileCSV:
|
|
145
|
+
csvWriter = csv.writer(fileCSV)
|
|
146
|
+
csvWriter.writerows(sherpa.listFolding)
|
|
147
|
+
|
|
148
|
+
state.groupsOfFolds += len(sherpa.listFolding)
|
|
149
|
+
state.Theorem2aMultiplier = sherpa.Theorem2aMultiplier
|
|
150
|
+
state.Theorem2Multiplier = sherpa.Theorem2Multiplier
|
|
151
|
+
state.Theorem3Multiplier = sherpa.Theorem3Multiplier
|
|
152
|
+
state.Theorem4Multiplier = sherpa.Theorem4Multiplier
|
|
153
|
+
|
|
154
|
+
else:
|
|
155
|
+
state = count(state)
|
|
156
|
+
state.groupsOfFolds = len(state.listFolding)
|
|
157
|
+
|
|
158
|
+
return state
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from itertools import pairwise, permutations, repeat
|
|
3
|
+
from mapFolding._e import indicesMapShapeDimensionLengthsAreEqual, leafOrigin, PermutationSpace, pileOrigin
|
|
4
|
+
from mapFolding._e.algorithms.iff import thisLeafFoldingIsValid
|
|
5
|
+
from mapFolding._e.dataBaskets import EliminationState
|
|
6
|
+
from mapFolding._e.pinIt import excludeLeaf_rBeforeLeaf_k, makeFolding
|
|
7
|
+
from math import factorial
|
|
8
|
+
|
|
9
|
+
# TODO make sure all permutationSpace have pile-ranges and update their pile-ranges
|
|
10
|
+
|
|
11
|
+
def count(state: EliminationState) -> EliminationState:
|
|
12
|
+
state.groupsOfFolds += sum(map(countPermutationSpace, state.listPermutationSpace, repeat(state.mapShape), repeat(range(state.leavesTotal))))
|
|
13
|
+
return state
|
|
14
|
+
|
|
15
|
+
def countPermutationSpace(permutationSpace: PermutationSpace, mapShape: tuple[int, ...], leavesToInsert: Iterable[int]) -> int:
|
|
16
|
+
"""# TODO Replace `permutations` with the `noDuplicates` filter on `CartesianProduct` of the domains of each leaf.
|
|
17
|
+
|
|
18
|
+
permutationSpace must be in order by `pile`.
|
|
19
|
+
filter with `oop`.
|
|
20
|
+
pileRangeOfLeaves.iter_set() returns an iterator of int corresponding to the leaves in the pile's range.
|
|
21
|
+
https://gmpy2.readthedocs.io/en/latest/advmpz.html#gmpy2.xmpz.iter_set
|
|
22
|
+
filter out "leaf" = state.leavesTotal
|
|
23
|
+
CartesianProduct over these iterators.
|
|
24
|
+
filter via noDuplicates.
|
|
25
|
+
each product tuple is a `leavesToInsert` argument to makeFolding.
|
|
26
|
+
return sum(
|
|
27
|
+
map(thisLeafFoldingIsValid
|
|
28
|
+
, map(makeFolding
|
|
29
|
+
, repeat(permutationSpace)
|
|
30
|
+
, CartesianProduct(*map(getIteratorOfLeaves, extractPilesWithPileRangeOfLeaves(permutationSpace).values()))
|
|
31
|
+
)
|
|
32
|
+
, repeat(mapShape)
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
"""
|
|
36
|
+
return sum(map(thisLeafFoldingIsValid, map(makeFolding, repeat(permutationSpace), permutations(tuple(set(leavesToInsert).difference(permutationSpace.values())))), repeat(mapShape)))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def theorem2b(state: EliminationState) -> EliminationState:
|
|
40
|
+
"""Implement Lunnon Theorem 2(b): If some dimension pᵢ > 2 (with Theorem 4 inactive), G is divisible by 2·n.
|
|
41
|
+
|
|
42
|
+
Conditions
|
|
43
|
+
----------
|
|
44
|
+
Executed only when:
|
|
45
|
+
- `state.Theorem4Multiplier == 1` (Theorem 4 did not apply),
|
|
46
|
+
- `max(mapShape) > 2` (at least one dimension exceeds 2),
|
|
47
|
+
- `leavesTotal > 4` (non-trivial folding size).
|
|
48
|
+
|
|
49
|
+
Mechanism
|
|
50
|
+
---------
|
|
51
|
+
Select the maximal dimension, compute `k = productOfDimensions(mapShape, dimension)` and `r = 2 * k`, then eliminate
|
|
52
|
+
configurations where r precedes k (via `excludeLeafRBeforeLeafK`). This enforces the structural constraint underpinning
|
|
53
|
+
the `2·n` divisibility and sets `state.Theorem2Multiplier = 2`.
|
|
54
|
+
|
|
55
|
+
Side Effects
|
|
56
|
+
------------
|
|
57
|
+
Mutates `state.listPermutationSpace` and `state.Theorem2Multiplier` when applicable.
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
EliminationState
|
|
62
|
+
Same state instance after potential exclusion.
|
|
63
|
+
|
|
64
|
+
See Also
|
|
65
|
+
--------
|
|
66
|
+
theorem4, excludeLeafRBeforeLeafK
|
|
67
|
+
"""
|
|
68
|
+
if state.Theorem4Multiplier == 1 and (2 < max(state.mapShape)) and (4 < state.leavesTotal):
|
|
69
|
+
state.Theorem2Multiplier = 2
|
|
70
|
+
dimension: int = state.mapShape.index(max(state.mapShape))
|
|
71
|
+
leaf_k: int = state.productsOfDimensions[dimension]
|
|
72
|
+
leaf_r: int = 2 * leaf_k
|
|
73
|
+
state = excludeLeaf_rBeforeLeaf_k(state, leaf_k, leaf_r)
|
|
74
|
+
return state
|
|
75
|
+
|
|
76
|
+
def theorem4(state: EliminationState) -> EliminationState:
|
|
77
|
+
"""***Bluntly*** implement Lunnon Theorem 4 (divisibility by d! · p^d) via systematic leaf exclusions.
|
|
78
|
+
|
|
79
|
+
This function is ignorant of the actual domains of the dimension-origin leaves, so it creates `PermutationSpace` dictionaries to
|
|
80
|
+
exclude at every `pile`. The permutation space is still valid. However, for each `PermutationSpace` dictionary, for each `pile`
|
|
81
|
+
*not* in the domain of a dimension-origin leaf, the function creates approximately `leavesTotal - 1` unnecessary
|
|
82
|
+
`PermutationSpace` dictionaries. They are "unnecessary" because we didn't need to exclude the leaf from a pile in which it could
|
|
83
|
+
never appear. The net result is that the number of unnecessary dictionaries grows exponentially with the number of repeated
|
|
84
|
+
dimension magnitudes.
|
|
85
|
+
|
|
86
|
+
For a map whose shape has repeated dimension magnitudes (say a size `p` occurring `d` times), the total number of foldings
|
|
87
|
+
`G(p^d)` is divisible by `d! · p^d`. This routine encodes the constructive elimination implied by that divisibility.
|
|
88
|
+
|
|
89
|
+
Returns
|
|
90
|
+
-------
|
|
91
|
+
EliminationState
|
|
92
|
+
Same state instance after applying all required exclusions.
|
|
93
|
+
|
|
94
|
+
See Also
|
|
95
|
+
--------
|
|
96
|
+
theorem2b : Applies the complementary 2(b) divisibility if theorem4 does not apply.
|
|
97
|
+
excludeLeafRBeforeLeafK : Performs the actual leaf ordering elimination.
|
|
98
|
+
"""
|
|
99
|
+
if 2 < max(state.mapShape):
|
|
100
|
+
for indicesSameDimensionLength in indicesMapShapeDimensionLengthsAreEqual(state.mapShape):
|
|
101
|
+
state.Theorem4Multiplier *= factorial(len(indicesSameDimensionLength))
|
|
102
|
+
for index_k, index_r in pairwise(indicesSameDimensionLength):
|
|
103
|
+
state = excludeLeaf_rBeforeLeaf_k(state, state.productsOfDimensions[index_k], state.productsOfDimensions[index_r])
|
|
104
|
+
return state
|
|
105
|
+
|
|
106
|
+
def doTheNeedful(state: EliminationState, workersMaximum: int) -> EliminationState: # noqa: ARG001
|
|
107
|
+
"""Count the number of valid foldings for a given number of leaves."""
|
|
108
|
+
if state.leavesTotal == 0:
|
|
109
|
+
state.groupsOfFolds = 1
|
|
110
|
+
return state
|
|
111
|
+
if not state.listPermutationSpace:
|
|
112
|
+
"""Lunnon Theorem 2(a): `foldsTotal` is divisible by `leavesTotal`; pin `leafOrigin` at `pileOrigin`, which eliminates other leaves at `pileOrigin`."""
|
|
113
|
+
state.listPermutationSpace = [{pileOrigin: leafOrigin}]
|
|
114
|
+
state = theorem4(state)
|
|
115
|
+
state = theorem2b(state)
|
|
116
|
+
|
|
117
|
+
return count(state)
|
|
118
|
+
|