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,640 @@
|
|
|
1
|
+
# NOTE to AI assistants: this module is not representative of my coding style. Most of it is AI generated, but because it's temporary code, I didn't strictly enforce my usual standards. Do not emulate it.
|
|
2
|
+
from collections.abc import Sequence
|
|
3
|
+
from fractions import Fraction
|
|
4
|
+
from functools import cache, reduce
|
|
5
|
+
from gmpy2 import bit_flip
|
|
6
|
+
from hunterMakesPy import CallableFunction, raiseIfNone
|
|
7
|
+
from hunterMakesPy.dataStructures import updateExtendPolishDictionaryLists
|
|
8
|
+
from hunterMakesPy.filesystemToolkit import importPathFilename2Identifier, writePython
|
|
9
|
+
from itertools import product as CartesianProduct, repeat
|
|
10
|
+
from mapFolding import ansiColorReset, ansiColors, inclusive, packageSettings
|
|
11
|
+
from mapFolding._e import (
|
|
12
|
+
getDictionaryLeafDomains, getLeafDomain, getPileRange, PermutationSpace, 首一, 首一三, 首一二, 首一二三, 首三, 首二, 首二三, 首零, 首零一,
|
|
13
|
+
首零一三, 首零一二, 首零一二三, 首零三, 首零二, 首零二三)
|
|
14
|
+
from mapFolding._e._dataDynamic import getDataFrameFoldings
|
|
15
|
+
from mapFolding._e.dataBaskets import EliminationState
|
|
16
|
+
from mapFolding._e.filters import between, exclude
|
|
17
|
+
from mapFolding._e.pin2上nDimensions import pinPilesAtEnds
|
|
18
|
+
from mapFolding._e.pinIt import deconstructPermutationSpaceAtPile, deconstructPermutationSpaceByDomainOfLeaf
|
|
19
|
+
from mapFolding._e.Z0Z_analysisPython.toolkit import detectPermutationSpaceErrors, PermutationSpaceStatus
|
|
20
|
+
from more_itertools import consecutive_groups
|
|
21
|
+
from operator import indexOf, neg, pos
|
|
22
|
+
from pathlib import Path, PurePath
|
|
23
|
+
from pprint import pformat
|
|
24
|
+
from typing import TYPE_CHECKING
|
|
25
|
+
import numpy
|
|
26
|
+
import sys
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
import pandas
|
|
30
|
+
|
|
31
|
+
def 首一1(dd: int, /) -> int: return 首一(dd) + 1
|
|
32
|
+
def 首一三1(dd: int, /) -> int: return 首一三(dd) + 1
|
|
33
|
+
def 首一二1(dd: int, /) -> int: return 首一二(dd) + 1
|
|
34
|
+
def 首一二三1(dd: int, /) -> int: return 首一二三(dd) + 1
|
|
35
|
+
def 首三1(dd: int, /) -> int: return 首三(dd) + 1
|
|
36
|
+
def 首二1(dd: int, /) -> int: return 首二(dd) + 1
|
|
37
|
+
def 首二三1(dd: int, /) -> int: return 首二三(dd) + 1
|
|
38
|
+
def 首零1(dd: int, /) -> int: return 首零(dd) + 1
|
|
39
|
+
def 首零一1(dd: int, /) -> int: return 首零一(dd) + 1
|
|
40
|
+
def 首零一三1(dd: int, /) -> int: return 首零一三(dd) + 1
|
|
41
|
+
def 首零一二1(dd: int, /) -> int: return 首零一二(dd) + 1
|
|
42
|
+
def 首零一二三1(dd: int, /) -> int: return 首零一二三(dd) + 1
|
|
43
|
+
def 首零三1(dd: int, /) -> int: return 首零三(dd) + 1
|
|
44
|
+
def 首零二1(dd: int, /) -> int: return 首零二(dd) + 1
|
|
45
|
+
def 首零二三1(dd: int, /) -> int: return 首零二三(dd) + 1
|
|
46
|
+
|
|
47
|
+
type Addend = int
|
|
48
|
+
type FractionAddend = tuple[Fraction, Addend]
|
|
49
|
+
type IndexPilesTotal = int
|
|
50
|
+
type Leaf = int
|
|
51
|
+
type MapKind = str
|
|
52
|
+
type Pile = int
|
|
53
|
+
type strLeafExcluded = str
|
|
54
|
+
type strLeafExcluder = str
|
|
55
|
+
type strPileExcluded = str
|
|
56
|
+
type strPileExcluder = str
|
|
57
|
+
type ExclusionData = dict[MapKind, dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]]
|
|
58
|
+
|
|
59
|
+
pathExclusionData: Path = Path(f"{packageSettings.pathPackage}/_e/Z0Z_analysisPython/exclusionData")
|
|
60
|
+
pathExclusionData.mkdir(parents=True, exist_ok=True)
|
|
61
|
+
|
|
62
|
+
functionsHeadDimensions: list[CallableFunction[[int], int]] = [
|
|
63
|
+
首一, 首一三, 首一二, 首一二三, 首三, 首二, 首二三, 首零, 首零一, 首零一三, 首零一二, 首零一二三, 首零三, 首零二, 首零二三,
|
|
64
|
+
首一1, 首一三1, 首一二1, 首一二三1, 首三1, 首二1, 首二三1, 首零1, 首零一1, 首零一三1, 首零一二1, 首零一二三1, 首零三1, 首零二1, 首零二三1]
|
|
65
|
+
dictionaryFunctionsByName: dict[str, CallableFunction[[int], int]] = {function.__name__: function for function in functionsHeadDimensions}
|
|
66
|
+
|
|
67
|
+
#======== Collate exclusion data =======
|
|
68
|
+
|
|
69
|
+
def writeExclusionDataCollated(listDimensions: Sequence[int] = (5, 6)) -> list[PurePath]:
|
|
70
|
+
"""{mapShape: {leafExcluder: {pileExcluder: {leafExcluded: listIndicesExcluded}}}}."""
|
|
71
|
+
dictionaryIndices: dict[MapKind, dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]] = {}
|
|
72
|
+
dictionaryIndicesNegative: dict[MapKind, dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]] = {}
|
|
73
|
+
|
|
74
|
+
# TODO Use the docstring to explain this computation, and change the computation to a simpler statement.
|
|
75
|
+
listsAreAlwaysLessThanHalfLeavesTotal = 1
|
|
76
|
+
integerDivisionIsSillyIfTheNumeratorIsLessThanTwiceTheDenominator = 1
|
|
77
|
+
qq = min(listDimensions) - listsAreAlwaysLessThanHalfLeavesTotal - integerDivisionIsSillyIfTheNumeratorIsLessThanTwiceTheDenominator
|
|
78
|
+
denominatorsValid: tuple[int, ...] = tuple(int(bit_flip(0, ww)) for ww in range(1, qq))
|
|
79
|
+
|
|
80
|
+
for dimensionsTotal in listDimensions:
|
|
81
|
+
state: EliminationState = EliminationState((2,) * dimensionsTotal)
|
|
82
|
+
dataframeFoldings: pandas.DataFrame = raiseIfNone(getDataFrameFoldings(state))
|
|
83
|
+
|
|
84
|
+
dictionaryLeafDomains: dict[Leaf, range] = getDictionaryLeafDomains(state)
|
|
85
|
+
|
|
86
|
+
mapKind: MapKind = f"p2d{dimensionsTotal}"
|
|
87
|
+
dictionaryIndices[mapKind] = {}
|
|
88
|
+
dictionaryIndicesNegative[mapKind] = {}
|
|
89
|
+
|
|
90
|
+
for leafExcluder, pileExcluder, leafExcluded in CartesianProduct(functionsHeadDimensions, functionsHeadDimensions, functionsHeadDimensions):
|
|
91
|
+
if pileExcluder(dimensionsTotal) not in dictionaryLeafDomains.get(leafExcluder(dimensionsTotal), []):
|
|
92
|
+
continue
|
|
93
|
+
pilesInTheDataframe: pandas.Series = dataframeFoldings.loc[dataframeFoldings[pileExcluder(dimensionsTotal)] == leafExcluder(dimensionsTotal)].eq(leafExcluded(dimensionsTotal)).any()
|
|
94
|
+
leafExcludedValue = leafExcluded(dimensionsTotal)
|
|
95
|
+
if leafExcludedValue not in dictionaryLeafDomains:
|
|
96
|
+
continue
|
|
97
|
+
listOfPiles: list[Pile] = list(dictionaryLeafDomains[leafExcludedValue])
|
|
98
|
+
listPilesExcluded: set[Pile] = set(listOfPiles).difference(pilesInTheDataframe[pilesInTheDataframe].index.tolist())
|
|
99
|
+
listIndicesExcluded: list[IndexPilesTotal] = sorted(map(indexOf, repeat(listOfPiles), listPilesExcluded))
|
|
100
|
+
|
|
101
|
+
pilesTotal = len(listOfPiles)
|
|
102
|
+
denominators: list[int] = list(filter(between(0, pilesTotal), denominatorsValid))
|
|
103
|
+
dictionaryIndices[mapKind].setdefault(leafExcluder.__name__, {}).setdefault(pileExcluder.__name__, {})[leafExcluded.__name__] = [
|
|
104
|
+
expressIndexAsFractionAddend(index, pilesTotal, tuple(denominators)) for index in listIndicesExcluded]
|
|
105
|
+
dictionaryIndicesNegative[mapKind].setdefault(leafExcluder.__name__, {}).setdefault(pileExcluder.__name__, {})[leafExcluded.__name__] = [
|
|
106
|
+
expressIndexAsFractionAddend(index - pilesTotal, pilesTotal, tuple(denominators)) for index in listIndicesExcluded]
|
|
107
|
+
|
|
108
|
+
listPathFilenames: list[PurePath] = []
|
|
109
|
+
|
|
110
|
+
for mapKind in dictionaryIndices:
|
|
111
|
+
for leafExcluderName, dictionary in dictionaryIndices[mapKind].items():
|
|
112
|
+
pythonSource: str = f"from fractions import Fraction\n\nleafExcluderData: dict[str, dict[str, list[tuple[Fraction, int]]]] = {pformat(dictionary, indent=0, width=160)}"
|
|
113
|
+
pathFilename: Path = pathExclusionData / f"collated{mapKind}{leafExcluderName}.py"
|
|
114
|
+
writePython(pythonSource, pathFilename)
|
|
115
|
+
listPathFilenames.append(PurePath(pathFilename))
|
|
116
|
+
|
|
117
|
+
for mapKind in dictionaryIndicesNegative:
|
|
118
|
+
for leafExcluderName, dictionary in dictionaryIndicesNegative[mapKind].items():
|
|
119
|
+
pythonSource: str = f"from fractions import Fraction\n\nleafExcluderData: dict[str, dict[str, list[tuple[Fraction, int]]]] = {pformat(dictionary, indent=0, width=160)}"
|
|
120
|
+
pathFilename: Path = pathExclusionData / f"collated{mapKind}{leafExcluderName}Negative.py"
|
|
121
|
+
writePython(pythonSource, pathFilename)
|
|
122
|
+
listPathFilenames.append(PurePath(pathFilename))
|
|
123
|
+
|
|
124
|
+
return listPathFilenames
|
|
125
|
+
|
|
126
|
+
@cache
|
|
127
|
+
def expressIndexAsFractionAddend(index: IndexPilesTotal, pilesTotal: int, denominators: tuple[int, ...]) -> FractionAddend:
|
|
128
|
+
indexAsFractionAndAddend: FractionAddend = (Fraction(0, 1), index)
|
|
129
|
+
direction = pos if index >= 0 else neg
|
|
130
|
+
|
|
131
|
+
if denominators:
|
|
132
|
+
addendsMagnitude: int = pilesTotal // max(denominators)
|
|
133
|
+
distanceBest: float = 9000.1
|
|
134
|
+
|
|
135
|
+
for denominator, addend in CartesianProduct(denominators, range(-(addendsMagnitude), addendsMagnitude + inclusive)):
|
|
136
|
+
for numerator in range(1, denominator):
|
|
137
|
+
if ((numerator / denominator).is_integer()) and (numerator // denominator in denominators):
|
|
138
|
+
continue
|
|
139
|
+
numerator = direction(numerator)
|
|
140
|
+
if index == (((numerator * pilesTotal) // denominator) + addend):
|
|
141
|
+
distance: float = abs(index - (((numerator * pilesTotal) / denominator) + addend))
|
|
142
|
+
if distance < distanceBest:
|
|
143
|
+
indexAsFractionAndAddend = (Fraction(numerator, denominator), addend)
|
|
144
|
+
distanceBest = distance
|
|
145
|
+
|
|
146
|
+
return indexAsFractionAndAddend
|
|
147
|
+
|
|
148
|
+
#======== Analyze exclusion data =======
|
|
149
|
+
|
|
150
|
+
def loadCollatedIndices(*, negative: bool = False) -> ExclusionData:
|
|
151
|
+
collatedIndices: ExclusionData = {}
|
|
152
|
+
stringGlob: str = 'collated*'
|
|
153
|
+
stringGlob += 'Negative' if negative else ''
|
|
154
|
+
for pathFilename in pathExclusionData.glob(stringGlob + ".py"):
|
|
155
|
+
stem: str = pathFilename.stem.removeprefix("collated").removesuffix("Negative")
|
|
156
|
+
mapKind, leafExcluderName = stem[0:4], stem[4:]
|
|
157
|
+
collatedIndices.setdefault(mapKind, {})[leafExcluderName] = importPathFilename2Identifier(pathFilename, "leafExcluderData")
|
|
158
|
+
return collatedIndices
|
|
159
|
+
|
|
160
|
+
@cache
|
|
161
|
+
def _dictionaryLeafDomainsByMapKind(mapKind: MapKind) -> dict[Leaf, range]:
|
|
162
|
+
return getDictionaryLeafDomains(EliminationState((2,) * _dimensionsTotalFromMapKind(mapKind)))
|
|
163
|
+
|
|
164
|
+
def _dimensionsTotalFromMapKind(mapKind: MapKind) -> int:
|
|
165
|
+
return int(mapKind.removeprefix("p2d"))
|
|
166
|
+
|
|
167
|
+
@cache
|
|
168
|
+
def _fractionAddendToIndex(fractionAddend: FractionAddend, pilesTotal: int) -> int:
|
|
169
|
+
fraction, addend = fractionAddend
|
|
170
|
+
index: int = ((fraction.numerator * pilesTotal) // fraction.denominator) + addend
|
|
171
|
+
if index < 0:
|
|
172
|
+
return pilesTotal + index
|
|
173
|
+
return index
|
|
174
|
+
|
|
175
|
+
def _listFractionAddendsToIndices(mapKind: MapKind, leafExcludedName: strLeafExcluded, listFractionAddends: list[FractionAddend]) -> list[int]:
|
|
176
|
+
pilesTotal: int = _pilesTotalOfLeafExcluded(mapKind, leafExcludedName)
|
|
177
|
+
return [_fractionAddendToIndex(fractionAddend, pilesTotal) for fractionAddend in listFractionAddends]
|
|
178
|
+
|
|
179
|
+
@cache
|
|
180
|
+
def _pilesTotalOfLeafExcluded(mapKind: MapKind, leafExcludedName: strLeafExcluded) -> int:
|
|
181
|
+
leaf: Leaf = dictionaryFunctionsByName[leafExcludedName](_dimensionsTotalFromMapKind(mapKind))
|
|
182
|
+
return len(_dictionaryLeafDomainsByMapKind(mapKind)[leaf])
|
|
183
|
+
|
|
184
|
+
def _fractionAddendsForIndexSubset(listFractionAddends: list[FractionAddend], listResolvedIndices: list[int], indicesSubset: list[int]) -> set[FractionAddend]:
|
|
185
|
+
if not indicesSubset:
|
|
186
|
+
return set()
|
|
187
|
+
indicesSet: set[int] = set(indicesSubset)
|
|
188
|
+
return {fractionAddend for fractionAddend, resolvedIndex in zip(listFractionAddends, listResolvedIndices, strict=True) if resolvedIndex in indicesSet}
|
|
189
|
+
|
|
190
|
+
def _fractionAddendFromIndex(index: IndexPilesTotal) -> FractionAddend:
|
|
191
|
+
return (Fraction(0, 1), index)
|
|
192
|
+
|
|
193
|
+
def _getContiguousFromStart(listIndices: list[IndexPilesTotal]) -> list[IndexPilesTotal]:
|
|
194
|
+
"""Return the first contiguous group starting at index 0, if it has at least 2 elements."""
|
|
195
|
+
listContiguous: list[IndexPilesTotal] = []
|
|
196
|
+
if listIndices and listIndices[0] == 0:
|
|
197
|
+
listContiguous = list(next(consecutive_groups(listIndices)))
|
|
198
|
+
if len(listContiguous) < 2:
|
|
199
|
+
listContiguous = []
|
|
200
|
+
return listContiguous
|
|
201
|
+
|
|
202
|
+
def _getContiguousEndingAtNegativeOne(listRelativeIndices: list[int]) -> list[int]:
|
|
203
|
+
"""Return the last contiguous group ending at -1, if it has at least 2 elements."""
|
|
204
|
+
listContiguous: list[int] = []
|
|
205
|
+
listRelativeIndicesSorted: list[int] = sorted(listRelativeIndices)
|
|
206
|
+
if listRelativeIndicesSorted and listRelativeIndicesSorted[-1] == -1:
|
|
207
|
+
for group in consecutive_groups(listRelativeIndicesSorted):
|
|
208
|
+
listContiguous = list(group)
|
|
209
|
+
if (len(listContiguous) < 2) or (listContiguous[-1] != -1):
|
|
210
|
+
listContiguous = []
|
|
211
|
+
return listContiguous
|
|
212
|
+
|
|
213
|
+
def analyzeContiguousStartAbsolute(dataset: ExclusionData) -> dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]:
|
|
214
|
+
"""Find common contiguous indices starting from 0 across all map shapes, expressed as absolute indices."""
|
|
215
|
+
aggregatedExclusions: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]] = {}
|
|
216
|
+
listMapKinds: list[MapKind] = list(dataset.keys())
|
|
217
|
+
mapKind0: MapKind = listMapKinds[0]
|
|
218
|
+
|
|
219
|
+
for leafExcluderName in dataset[mapKind0]:
|
|
220
|
+
if any(leafExcluderName not in dataset[mapKind] for mapKind in listMapKinds):
|
|
221
|
+
continue
|
|
222
|
+
aggregatedExclusions[leafExcluderName] = {}
|
|
223
|
+
|
|
224
|
+
for pileExcluderName in dataset[mapKind0][leafExcluderName]:
|
|
225
|
+
if any(pileExcluderName not in dataset[mapKind][leafExcluderName] for mapKind in listMapKinds):
|
|
226
|
+
continue
|
|
227
|
+
aggregatedExclusions[leafExcluderName][pileExcluderName] = {}
|
|
228
|
+
|
|
229
|
+
for leafExcludedName in dataset[mapKind0][leafExcluderName][pileExcluderName]:
|
|
230
|
+
if any(leafExcludedName not in dataset[mapKind][leafExcluderName][pileExcluderName] for mapKind in listMapKinds):
|
|
231
|
+
continue
|
|
232
|
+
|
|
233
|
+
listContiguousLengths: list[int] = []
|
|
234
|
+
|
|
235
|
+
for mapKind in listMapKinds:
|
|
236
|
+
listFractionAddends: list[FractionAddend] = dataset[mapKind][leafExcluderName][pileExcluderName][leafExcludedName]
|
|
237
|
+
resolvedIndices: list[int] = _listFractionAddendsToIndices(mapKind, leafExcludedName, listFractionAddends)
|
|
238
|
+
listContiguousLengths.append(len(_getContiguousFromStart(resolvedIndices)))
|
|
239
|
+
|
|
240
|
+
commonLength: int = min(listContiguousLengths) if listContiguousLengths else 0
|
|
241
|
+
listFractionAddendsCommon: list[FractionAddend] = [_fractionAddendFromIndex(indexValue) for indexValue in range(commonLength)] if commonLength >= 2 else []
|
|
242
|
+
aggregatedExclusions[leafExcluderName][pileExcluderName][leafExcludedName] = listFractionAddendsCommon
|
|
243
|
+
|
|
244
|
+
return aggregatedExclusions
|
|
245
|
+
|
|
246
|
+
def analyzeContiguousEndAbsolute(dataset: ExclusionData) -> dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]:
|
|
247
|
+
"""Find common contiguous indices ending at pilesTotal-1 across all map shapes, expressed as negative absolute indices."""
|
|
248
|
+
aggregatedExclusions: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]] = {}
|
|
249
|
+
listMapKinds: list[MapKind] = list(dataset.keys())
|
|
250
|
+
mapKind0: MapKind = listMapKinds[0]
|
|
251
|
+
|
|
252
|
+
for leafExcluderName in dataset[mapKind0]:
|
|
253
|
+
if any(leafExcluderName not in dataset[mapKind] for mapKind in listMapKinds):
|
|
254
|
+
continue
|
|
255
|
+
aggregatedExclusions[leafExcluderName] = {}
|
|
256
|
+
|
|
257
|
+
for pileExcluderName in dataset[mapKind0][leafExcluderName]:
|
|
258
|
+
if any(pileExcluderName not in dataset[mapKind][leafExcluderName] for mapKind in listMapKinds):
|
|
259
|
+
continue
|
|
260
|
+
aggregatedExclusions[leafExcluderName][pileExcluderName] = {}
|
|
261
|
+
|
|
262
|
+
for leafExcludedName in dataset[mapKind0][leafExcluderName][pileExcluderName]:
|
|
263
|
+
if any(leafExcludedName not in dataset[mapKind][leafExcluderName][pileExcluderName] for mapKind in listMapKinds):
|
|
264
|
+
continue
|
|
265
|
+
|
|
266
|
+
listContiguousLengths: list[int] = []
|
|
267
|
+
|
|
268
|
+
for mapKind in listMapKinds:
|
|
269
|
+
listFractionAddends: list[FractionAddend] = dataset[mapKind][leafExcluderName][pileExcluderName][leafExcludedName]
|
|
270
|
+
listRelativeIndices: list[int] = _listFractionAddendsToIndices(mapKind, leafExcludedName, listFractionAddends)
|
|
271
|
+
listContiguousLengths.append(len(_getContiguousEndingAtNegativeOne(listRelativeIndices)))
|
|
272
|
+
|
|
273
|
+
commonLength: int = min(listContiguousLengths) if listContiguousLengths else 0
|
|
274
|
+
rangeIndices: range = range(-commonLength, 0) if commonLength >= 2 else range(0)
|
|
275
|
+
aggregatedExclusions[leafExcluderName][pileExcluderName][leafExcludedName] = [_fractionAddendFromIndex(indexValue) for indexValue in rangeIndices]
|
|
276
|
+
|
|
277
|
+
return aggregatedExclusions
|
|
278
|
+
|
|
279
|
+
def analyzeContiguousStartRelative(dataset: ExclusionData) -> dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]:
|
|
280
|
+
"""Find common contiguous indices starting from 0 across all map shapes, expressed as fractions of pilesTotal."""
|
|
281
|
+
aggregatedExclusions: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]] = {}
|
|
282
|
+
listMapKinds: list[MapKind] = list(dataset.keys())
|
|
283
|
+
mapKind0: MapKind = listMapKinds[0]
|
|
284
|
+
|
|
285
|
+
for leafExcluderName in dataset[mapKind0]:
|
|
286
|
+
if any(leafExcluderName not in dataset[mapKind] for mapKind in listMapKinds):
|
|
287
|
+
continue
|
|
288
|
+
aggregatedExclusions[leafExcluderName] = {}
|
|
289
|
+
|
|
290
|
+
for pileExcluderName in dataset[mapKind0][leafExcluderName]:
|
|
291
|
+
if any(pileExcluderName not in dataset[mapKind][leafExcluderName] for mapKind in listMapKinds):
|
|
292
|
+
continue
|
|
293
|
+
aggregatedExclusions[leafExcluderName][pileExcluderName] = {}
|
|
294
|
+
|
|
295
|
+
for leafExcludedName in dataset[mapKind0][leafExcluderName][pileExcluderName]:
|
|
296
|
+
if any(leafExcludedName not in dataset[mapKind][leafExcluderName][pileExcluderName] for mapKind in listMapKinds):
|
|
297
|
+
continue
|
|
298
|
+
|
|
299
|
+
listSetsFractionAddends: list[set[FractionAddend]] = []
|
|
300
|
+
|
|
301
|
+
for mapKind in listMapKinds:
|
|
302
|
+
listFractionAddends: list[FractionAddend] = dataset[mapKind][leafExcluderName][pileExcluderName][leafExcludedName]
|
|
303
|
+
resolvedIndices: list[int] = _listFractionAddendsToIndices(mapKind, leafExcludedName, listFractionAddends)
|
|
304
|
+
contiguousIndices: list[int] = _getContiguousFromStart(resolvedIndices)
|
|
305
|
+
setFractionAddends: set[FractionAddend] = _fractionAddendsForIndexSubset(listFractionAddends, resolvedIndices, contiguousIndices)
|
|
306
|
+
listSetsFractionAddends.append(setFractionAddends)
|
|
307
|
+
|
|
308
|
+
commonFractionAddends: set[FractionAddend] = reduce(set[FractionAddend].intersection, listSetsFractionAddends)
|
|
309
|
+
aggregatedExclusions[leafExcluderName][pileExcluderName][leafExcludedName] = list(commonFractionAddends)
|
|
310
|
+
|
|
311
|
+
return aggregatedExclusions
|
|
312
|
+
|
|
313
|
+
def analyzeContiguousEndRelative(dataset: ExclusionData) -> dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]:
|
|
314
|
+
"""Find common contiguous indices ending at pilesTotal-1 across all map shapes, expressed as fractions of pilesTotal."""
|
|
315
|
+
aggregatedExclusions: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]] = {}
|
|
316
|
+
listMapKinds: list[MapKind] = list(dataset.keys())
|
|
317
|
+
mapKind0: MapKind = listMapKinds[0]
|
|
318
|
+
|
|
319
|
+
for leafExcluderName in dataset[mapKind0]:
|
|
320
|
+
if any(leafExcluderName not in dataset[mapKind] for mapKind in listMapKinds):
|
|
321
|
+
continue
|
|
322
|
+
aggregatedExclusions[leafExcluderName] = {}
|
|
323
|
+
|
|
324
|
+
for pileExcluderName in dataset[mapKind0][leafExcluderName]:
|
|
325
|
+
if any(pileExcluderName not in dataset[mapKind][leafExcluderName] for mapKind in listMapKinds):
|
|
326
|
+
continue
|
|
327
|
+
aggregatedExclusions[leafExcluderName][pileExcluderName] = {}
|
|
328
|
+
|
|
329
|
+
for leafExcludedName in dataset[mapKind0][leafExcluderName][pileExcluderName]:
|
|
330
|
+
if any(leafExcludedName not in dataset[mapKind][leafExcluderName][pileExcluderName] for mapKind in listMapKinds):
|
|
331
|
+
continue
|
|
332
|
+
|
|
333
|
+
listSetsFractionAddends: list[set[FractionAddend]] = []
|
|
334
|
+
|
|
335
|
+
for mapKind in listMapKinds:
|
|
336
|
+
listFractionAddends: list[FractionAddend] = dataset[mapKind][leafExcluderName][pileExcluderName][leafExcludedName]
|
|
337
|
+
listRelativeIndices: list[int] = _listFractionAddendsToIndices(mapKind, leafExcludedName, listFractionAddends)
|
|
338
|
+
contiguousRelativeIndices: list[int] = _getContiguousEndingAtNegativeOne(listRelativeIndices)
|
|
339
|
+
setFractionAddends: set[FractionAddend] = _fractionAddendsForIndexSubset(listFractionAddends, listRelativeIndices, contiguousRelativeIndices)
|
|
340
|
+
listSetsFractionAddends.append(setFractionAddends)
|
|
341
|
+
|
|
342
|
+
commonFractionAddends: set[FractionAddend] = reduce(set[FractionAddend].intersection, listSetsFractionAddends)
|
|
343
|
+
aggregatedExclusions[leafExcluderName][pileExcluderName][leafExcludedName] = list(commonFractionAddends)
|
|
344
|
+
|
|
345
|
+
return aggregatedExclusions
|
|
346
|
+
|
|
347
|
+
def analyzeNonContiguousIndicesRelative(dataset: ExclusionData) -> dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]:
|
|
348
|
+
"""Find common indices across all map shapes (contiguous or not), expressed as fractions of pilesTotal."""
|
|
349
|
+
aggregatedExclusions: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]] = {}
|
|
350
|
+
listMapKinds: list[MapKind] = list(dataset.keys())
|
|
351
|
+
mapKind0: MapKind = listMapKinds[0]
|
|
352
|
+
|
|
353
|
+
for leafExcluderName in dataset[mapKind0]:
|
|
354
|
+
if any(leafExcluderName not in dataset[mapKind] for mapKind in listMapKinds):
|
|
355
|
+
continue
|
|
356
|
+
|
|
357
|
+
for pileExcluderName in dataset[mapKind0][leafExcluderName]:
|
|
358
|
+
if any(pileExcluderName not in dataset[mapKind][leafExcluderName] for mapKind in listMapKinds):
|
|
359
|
+
continue
|
|
360
|
+
|
|
361
|
+
for leafExcludedName in dataset[mapKind0][leafExcluderName][pileExcluderName]:
|
|
362
|
+
if any(leafExcludedName not in dataset[mapKind][leafExcluderName][pileExcluderName] for mapKind in listMapKinds):
|
|
363
|
+
continue
|
|
364
|
+
|
|
365
|
+
listSetsFractionAddends: list[set[FractionAddend]] = []
|
|
366
|
+
|
|
367
|
+
for mapKind in listMapKinds:
|
|
368
|
+
listFractionAddends: list[FractionAddend] = dataset[mapKind][leafExcluderName][pileExcluderName][leafExcludedName]
|
|
369
|
+
setFractionAddends: set[FractionAddend] = set(listFractionAddends)
|
|
370
|
+
listSetsFractionAddends.append(setFractionAddends)
|
|
371
|
+
|
|
372
|
+
aggregatedExclusions.setdefault(leafExcluderName, {}).setdefault(pileExcluderName, {})[leafExcludedName] = list(reduce(set[FractionAddend].intersection, listSetsFractionAddends))
|
|
373
|
+
|
|
374
|
+
return aggregatedExclusions
|
|
375
|
+
|
|
376
|
+
#======== Aggregate exclusion data =======
|
|
377
|
+
|
|
378
|
+
def writeAggregatedExclusions(pathWrite: Path | None = None) -> list[PurePath]:
|
|
379
|
+
"""{leafExcluder: {pileExcluder: {leafExcluded: listIndicesAsFractionAddends}}}."""
|
|
380
|
+
if pathWrite is None:
|
|
381
|
+
pathWrite = pathExclusionData
|
|
382
|
+
listPathFilenames: list[PurePath] = []
|
|
383
|
+
collatedIndices: ExclusionData = loadCollatedIndices()
|
|
384
|
+
collatedIndicesNegative: ExclusionData = loadCollatedIndices(negative=True)
|
|
385
|
+
|
|
386
|
+
listExclusions: list[dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]] = [
|
|
387
|
+
analyzeContiguousEndAbsolute(collatedIndicesNegative),
|
|
388
|
+
analyzeContiguousEndRelative(collatedIndicesNegative),
|
|
389
|
+
analyzeContiguousStartAbsolute(collatedIndices),
|
|
390
|
+
analyzeContiguousStartRelative(collatedIndices),
|
|
391
|
+
analyzeNonContiguousIndicesRelative(collatedIndices),
|
|
392
|
+
analyzeNonContiguousIndicesRelative(collatedIndicesNegative),
|
|
393
|
+
]
|
|
394
|
+
|
|
395
|
+
aggregatedExclusions: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]] = {}
|
|
396
|
+
|
|
397
|
+
for leafExcluder, pileExcluder in CartesianProduct(functionsHeadDimensions, functionsHeadDimensions):
|
|
398
|
+
dictionaryMerged: dict[strLeafExcluded, list[FractionAddend]] = updateExtendPolishDictionaryLists(
|
|
399
|
+
*[dictionaryExclusions.get(leafExcluder.__name__, {}).get(pileExcluder.__name__, {}) for dictionaryExclusions in listExclusions]
|
|
400
|
+
, destroyDuplicates=True, reorderLists=True)
|
|
401
|
+
aggregatedExclusions.setdefault(leafExcluder.__name__, {})[pileExcluder.__name__] = dictionaryMerged
|
|
402
|
+
|
|
403
|
+
for leafExcluderName, pileExcluderData in aggregatedExclusions.items():
|
|
404
|
+
pythonSource: str = "from fractions import Fraction\n\n"
|
|
405
|
+
pythonSource += "type FractionAddend = tuple[Fraction, int]\n\n"
|
|
406
|
+
dataFormatted: str = pformat(pileExcluderData, indent=0, width=160, compact=True)
|
|
407
|
+
pythonSource += f"dictionaryExclusions: dict[str, dict[str, list[FractionAddend]]] = {dataFormatted}\n"
|
|
408
|
+
pathFilename: Path = pathWrite / f"aggregated{leafExcluderName}.py"
|
|
409
|
+
writePython(pythonSource, pathFilename)
|
|
410
|
+
listPathFilenames.append(PurePath(pathFilename))
|
|
411
|
+
|
|
412
|
+
return listPathFilenames
|
|
413
|
+
|
|
414
|
+
#======== Create exclusion dictionaries for elimination tools =======
|
|
415
|
+
|
|
416
|
+
def loadAggregatedExclusions() -> dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]:
|
|
417
|
+
aggregatedExclusions: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]] = {}
|
|
418
|
+
for pathFilename in pathExclusionData.glob("aggregated*.py"):
|
|
419
|
+
leafExcluderName: str = pathFilename.stem.removeprefix("aggregated")
|
|
420
|
+
aggregatedExclusions[leafExcluderName] = importPathFilename2Identifier(pathFilename, "dictionaryExclusions")
|
|
421
|
+
return aggregatedExclusions
|
|
422
|
+
|
|
423
|
+
def restructureAggregatedExclusionsForMapShape(dimensionsTotal: int, aggregatedExclusions: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]) -> tuple[dict[Leaf, dict[Pile, dict[Pile, list[Leaf]]]], dict[Pile, dict[Leaf, dict[Pile, list[Leaf]]]]]:
|
|
424
|
+
leafDomains: dict[Leaf, range] = getDictionaryLeafDomains(EliminationState(mapShape=(2,) * dimensionsTotal))
|
|
425
|
+
|
|
426
|
+
dictionaryLeafExcludedAtPileByPile: dict[Leaf, dict[Pile, dict[Pile, list[Leaf]]]] = {}
|
|
427
|
+
dictionaryAtPileLeafExcludedByPile: dict[Pile, dict[Leaf, dict[Pile, list[Leaf]]]] = {}
|
|
428
|
+
|
|
429
|
+
for leafExcluderName, pileExcluderData in aggregatedExclusions.items():
|
|
430
|
+
for pileExcluderName, leafExcludedData in pileExcluderData.items():
|
|
431
|
+
for leafExcludedName, listFractionAddends in leafExcludedData.items():
|
|
432
|
+
leafExcluded: Leaf = dictionaryFunctionsByName[leafExcludedName](dimensionsTotal)
|
|
433
|
+
leafExcluderValue: Leaf = dictionaryFunctionsByName[leafExcluderName](dimensionsTotal)
|
|
434
|
+
pileExcluderValue: Pile = dictionaryFunctionsByName[pileExcluderName](dimensionsTotal)
|
|
435
|
+
|
|
436
|
+
domainOfLeafExcluded: list[Pile] = list(leafDomains[leafExcluded])
|
|
437
|
+
pilesTotal: int = len(domainOfLeafExcluded)
|
|
438
|
+
|
|
439
|
+
for fractionAddend in listFractionAddends:
|
|
440
|
+
indexResolved: int = _fractionAddendToIndex(fractionAddend, pilesTotal)
|
|
441
|
+
pileExcluded: Pile = domainOfLeafExcluded[indexResolved]
|
|
442
|
+
|
|
443
|
+
dictionaryLeafExcludedAtPileByPile.setdefault(leafExcluded, {}
|
|
444
|
+
).setdefault(pileExcluded, {}
|
|
445
|
+
).setdefault(pileExcluderValue, []
|
|
446
|
+
).append(leafExcluderValue)
|
|
447
|
+
dictionaryAtPileLeafExcludedByPile.setdefault(pileExcluded, {}
|
|
448
|
+
).setdefault(leafExcluded, {}
|
|
449
|
+
).setdefault(pileExcluderValue, []
|
|
450
|
+
).append(leafExcluderValue)
|
|
451
|
+
|
|
452
|
+
for leafExcluded in dictionaryLeafExcludedAtPileByPile:
|
|
453
|
+
for pileExcluded in dictionaryLeafExcludedAtPileByPile[leafExcluded]:
|
|
454
|
+
for pileExcluder in dictionaryLeafExcludedAtPileByPile[leafExcluded][pileExcluded]:
|
|
455
|
+
dictionaryLeafExcludedAtPileByPile[leafExcluded][pileExcluded][pileExcluder] = sorted(set(dictionaryLeafExcludedAtPileByPile[leafExcluded][pileExcluded][pileExcluder]))
|
|
456
|
+
|
|
457
|
+
for pileExcluded in dictionaryAtPileLeafExcludedByPile:
|
|
458
|
+
for leafExcluded in dictionaryAtPileLeafExcludedByPile[pileExcluded]:
|
|
459
|
+
for pileExcluder in dictionaryAtPileLeafExcludedByPile[pileExcluded][leafExcluded]:
|
|
460
|
+
dictionaryAtPileLeafExcludedByPile[pileExcluded][leafExcluded][pileExcluder] = sorted(set(dictionaryAtPileLeafExcludedByPile[pileExcluded][leafExcluded][pileExcluder]))
|
|
461
|
+
|
|
462
|
+
return (dictionaryLeafExcludedAtPileByPile, dictionaryAtPileLeafExcludedByPile)
|
|
463
|
+
|
|
464
|
+
def writeExclusionDictionaries(pathExclusionsFile: PurePath | None = None) -> PurePath:
|
|
465
|
+
listDimensions: list[int] = [5, 6]
|
|
466
|
+
listLines: list[str] = ['"""Static exclusion dictionaries for elimination tools."""', ""]
|
|
467
|
+
|
|
468
|
+
for dimensionsTotal in listDimensions:
|
|
469
|
+
dictionaryLeafExcludedAtPileByPile, dictionaryAtPileLeafExcludedByPile = restructureAggregatedExclusionsForMapShape(dimensionsTotal, loadAggregatedExclusions())
|
|
470
|
+
|
|
471
|
+
mapKind: MapKind = f"2d{dimensionsTotal}"
|
|
472
|
+
|
|
473
|
+
listLines.append(f"dictionary{mapKind}LeafExcludedAtPileByPile: dict[int, dict[int, dict[int, list[int]]]] = {pformat(dictionaryLeafExcludedAtPileByPile, indent=4, width=160, compact=True)}")
|
|
474
|
+
listLines.append("")
|
|
475
|
+
listLines.append(f"dictionary{mapKind}AtPileLeafExcludedByPile: dict[int, dict[int, dict[int, list[int]]]] = {pformat(dictionaryAtPileLeafExcludedByPile, indent=4, width=160, compact=True)}")
|
|
476
|
+
listLines.append("")
|
|
477
|
+
|
|
478
|
+
pathFilename: Path = Path(pathExclusionsFile) if pathExclusionsFile is not None else Path(f"{packageSettings.pathPackage}/_e/_exclusions.py")
|
|
479
|
+
pythonSource: str = "\n".join(listLines)
|
|
480
|
+
writePython(pythonSource, pathFilename)
|
|
481
|
+
|
|
482
|
+
return PurePath(pathFilename)
|
|
483
|
+
|
|
484
|
+
#======== Validation functions =======
|
|
485
|
+
|
|
486
|
+
@cache
|
|
487
|
+
def _getArrayFoldingsByDimensions(dimensionsTotal: int) -> numpy.ndarray:
|
|
488
|
+
return raiseIfNone(getDataFrameFoldings(EliminationState((2,) * dimensionsTotal))).to_numpy(dtype=numpy.uint8, copy=False)
|
|
489
|
+
|
|
490
|
+
def validateExclusionDictionaries(dictionaryLeafExcludedAtPileByPile: dict[Leaf, dict[Pile, dict[Pile, list[Leaf]]]], dictionaryAtPileLeafExcludedByPile: dict[Pile, dict[Leaf, dict[Pile, list[Leaf]]]], mapKind: MapKind) -> tuple[bool, list[str]]:
|
|
491
|
+
dimensions: int = int(mapKind[3:])
|
|
492
|
+
listValidationErrors: list[str] = []
|
|
493
|
+
arrayFoldings = _getArrayFoldingsByDimensions(dimensions)
|
|
494
|
+
|
|
495
|
+
for pileExcluded, leafExcludedData in dictionaryAtPileLeafExcludedByPile.items():
|
|
496
|
+
for leafExcluded, pileExcluderData in leafExcludedData.items():
|
|
497
|
+
for pileExcluder, listLeafExcluders in pileExcluderData.items():
|
|
498
|
+
for leafExcluder in listLeafExcluders:
|
|
499
|
+
mask = (arrayFoldings[:, pileExcluder] == leafExcluder)
|
|
500
|
+
if (arrayFoldings[mask, pileExcluded] == leafExcluded).any():
|
|
501
|
+
listValidationErrors.append(
|
|
502
|
+
f"Invalid exclusion in dictionaryAtPile...: If pile {pileExcluder} has leaf {leafExcluder}, "
|
|
503
|
+
f"pile {pileExcluded} cannot have leaf {leafExcluded}. Found counter-example."
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
for leafExcluded, pileExcludedData in dictionaryLeafExcludedAtPileByPile.items():
|
|
507
|
+
for pileExcluded, pileExcluderData in pileExcludedData.items():
|
|
508
|
+
for pileExcluder, listLeafExcluders in pileExcluderData.items():
|
|
509
|
+
for leafExcluder in listLeafExcluders:
|
|
510
|
+
mask = (arrayFoldings[:, pileExcluder] == leafExcluder)
|
|
511
|
+
if (arrayFoldings[mask, pileExcluded] == leafExcluded).any():
|
|
512
|
+
listValidationErrors.append(
|
|
513
|
+
f"Invalid exclusion in dictionaryLeaf...: If pile {pileExcluder} has leaf {leafExcluder}, "
|
|
514
|
+
f"pile {pileExcluded} cannot have leaf {leafExcluded}. Found counter-example."
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
return len(listValidationErrors) == 0, listValidationErrors
|
|
518
|
+
|
|
519
|
+
def validateAnalysisMethodForMapShape(exclusionsFromAnalysisMethod: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]], mapKind: MapKind) -> tuple[bool, list[str]]:
|
|
520
|
+
dimensions: int = int(mapKind[3:])
|
|
521
|
+
listValidationErrors: list[str] = []
|
|
522
|
+
arrayFoldings = _getArrayFoldingsByDimensions(dimensions)
|
|
523
|
+
rowsTotal: int = int(arrayFoldings.shape[0])
|
|
524
|
+
|
|
525
|
+
for leafExcluderName in exclusionsFromAnalysisMethod:
|
|
526
|
+
leafExcluderFunction: CallableFunction[[int], int] = dictionaryFunctionsByName[leafExcluderName]
|
|
527
|
+
leafExcluder: int = leafExcluderFunction(dimensions)
|
|
528
|
+
|
|
529
|
+
for pileExcluderName in exclusionsFromAnalysisMethod[leafExcluderName]:
|
|
530
|
+
pileExcluderFunction: CallableFunction[[int], int] = dictionaryFunctionsByName[pileExcluderName]
|
|
531
|
+
pileExcluder: int = pileExcluderFunction(dimensions)
|
|
532
|
+
|
|
533
|
+
for leafExcludedName in exclusionsFromAnalysisMethod[leafExcluderName][pileExcluderName]:
|
|
534
|
+
leafExcludedFunction: CallableFunction[[int], int] = dictionaryFunctionsByName[leafExcludedName]
|
|
535
|
+
leafExcluded: int = leafExcludedFunction(dimensions)
|
|
536
|
+
|
|
537
|
+
listFractionAddends: list[FractionAddend] = exclusionsFromAnalysisMethod[leafExcluderName][pileExcluderName][leafExcludedName]
|
|
538
|
+
|
|
539
|
+
if not listFractionAddends:
|
|
540
|
+
continue
|
|
541
|
+
|
|
542
|
+
stateValidation: EliminationState = EliminationState(mapShape=(2,) * dimensions)
|
|
543
|
+
pilesTotalCurrent: int = len(list(getLeafDomain(stateValidation, dictionaryFunctionsByName[leafExcludedName](dimensions))))
|
|
544
|
+
|
|
545
|
+
listIndicesExcluded: list[int] = []
|
|
546
|
+
for fractionAddend in listFractionAddends:
|
|
547
|
+
indexComputed: int = _fractionAddendToIndex(fractionAddend, pilesTotalCurrent)
|
|
548
|
+
listIndicesExcluded.append(indexComputed)
|
|
549
|
+
|
|
550
|
+
if not listIndicesExcluded:
|
|
551
|
+
continue
|
|
552
|
+
|
|
553
|
+
stateValidation = pinPilesAtEnds(stateValidation, 1)
|
|
554
|
+
|
|
555
|
+
pileRange: list[int] = list(getPileRange(stateValidation, pileExcluder))
|
|
556
|
+
dictionaryDeconstructed: dict[int, PermutationSpace] = deconstructPermutationSpaceAtPile(stateValidation.listPermutationSpace[0], pileExcluder, pileRange)
|
|
557
|
+
|
|
558
|
+
permutationSpaceWithExcluder: PermutationSpace | None = dictionaryDeconstructed.get(leafExcluder)
|
|
559
|
+
if permutationSpaceWithExcluder is None:
|
|
560
|
+
continue
|
|
561
|
+
|
|
562
|
+
listPermutationSpaceOther: list[PermutationSpace] = [permutationSpace for leaf, permutationSpace in dictionaryDeconstructed.items() if leaf != leafExcluder]
|
|
563
|
+
|
|
564
|
+
domainOfLeafExcluded: list[int] = list(getLeafDomain(stateValidation, leafExcluded))
|
|
565
|
+
domainReduced: list[int] = list(exclude(domainOfLeafExcluded, listIndicesExcluded))
|
|
566
|
+
|
|
567
|
+
listPermutationSpaceFromExcluder: list[PermutationSpace] = deconstructPermutationSpaceByDomainOfLeaf(permutationSpaceWithExcluder, leafExcluded, domainReduced)
|
|
568
|
+
|
|
569
|
+
stateValidation.listPermutationSpace = listPermutationSpaceOther + listPermutationSpaceFromExcluder
|
|
570
|
+
|
|
571
|
+
pinningCoverage: PermutationSpaceStatus = detectPermutationSpaceErrors(arrayFoldings, stateValidation.listPermutationSpace)
|
|
572
|
+
|
|
573
|
+
if pinningCoverage.rowsRequired < rowsTotal:
|
|
574
|
+
listValidationErrors.append(
|
|
575
|
+
f"{mapKind} {leafExcluderName}->{pileExcluderName}->{leafExcludedName}: {pinningCoverage.rowsRequired = }/{rowsTotal}")
|
|
576
|
+
|
|
577
|
+
overlappingRowCount: int = int(pinningCoverage.indicesOverlappingRows.size)
|
|
578
|
+
if overlappingRowCount > 0:
|
|
579
|
+
listValidationErrors.append(
|
|
580
|
+
f"{mapKind} {leafExcluderName}->{pileExcluderName}->{leafExcludedName}: {overlappingRowCount} overlapping rows")
|
|
581
|
+
|
|
582
|
+
isValid: bool = len(listValidationErrors) == 0
|
|
583
|
+
return (isValid, listValidationErrors)
|
|
584
|
+
|
|
585
|
+
def validateAnalysisMethod(analysisMethodCallable: CallableFunction[[ExclusionData], dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]]) -> dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]]:
|
|
586
|
+
collatedIndices: ExclusionData = loadCollatedIndices()
|
|
587
|
+
listMapShapeNames: list[str] = list(collatedIndices.keys())
|
|
588
|
+
exclusionsFromMethod: dict[strLeafExcluder, dict[strPileExcluder, dict[strLeafExcluded, list[FractionAddend]]]] = analysisMethodCallable(collatedIndices)
|
|
589
|
+
errorsByMapShape: dict[str, list[str]] = {}
|
|
590
|
+
|
|
591
|
+
for mapShapeName in listMapShapeNames:
|
|
592
|
+
isValid, listValidationErrors = validateAnalysisMethodForMapShape(exclusionsFromMethod, mapShapeName)
|
|
593
|
+
if not isValid:
|
|
594
|
+
errorsByMapShape.setdefault(mapShapeName, []).extend(listValidationErrors)
|
|
595
|
+
|
|
596
|
+
dimensions: int = int(mapShapeName[3:])
|
|
597
|
+
dictionaryLeafExcludedAtPileByPile, dictionaryAtPileLeafExcludedByPile = restructureAggregatedExclusionsForMapShape(dimensions, exclusionsFromMethod)
|
|
598
|
+
isValidDictionaries, listDictionaryErrors = validateExclusionDictionaries(dictionaryLeafExcludedAtPileByPile, dictionaryAtPileLeafExcludedByPile, mapShapeName)
|
|
599
|
+
if not isValidDictionaries:
|
|
600
|
+
errorsByMapShape.setdefault(mapShapeName, []).extend(listDictionaryErrors)
|
|
601
|
+
|
|
602
|
+
if not errorsByMapShape:
|
|
603
|
+
colorSuccess = ansiColors.BlackOnCyan
|
|
604
|
+
sys.stdout.write(f"{colorSuccess}{analysisMethodCallable.__name__} validated across {len(listMapShapeNames)} mapShapes{ansiColorReset}\n")
|
|
605
|
+
else:
|
|
606
|
+
colorFailure = ansiColors.WhiteOnMagenta
|
|
607
|
+
sys.stdout.write(f"{colorFailure}{analysisMethodCallable.__name__} validation failed for {len(errorsByMapShape)} mapShapes{ansiColorReset}\n")
|
|
608
|
+
for mapShapeName, listErrors in errorsByMapShape.items():
|
|
609
|
+
sys.stdout.write(f"{colorFailure}{mapShapeName}: {len(listErrors)} issues{ansiColorReset}\n")
|
|
610
|
+
for error in listErrors[0:3]:
|
|
611
|
+
sys.stdout.write(f"{colorFailure} {error}{ansiColorReset}\n")
|
|
612
|
+
|
|
613
|
+
return exclusionsFromMethod
|
|
614
|
+
|
|
615
|
+
def runGenerators() -> None:
|
|
616
|
+
sys.stdout.write(f"{writeExclusionDataCollated() = }\n")
|
|
617
|
+
sys.stdout.write(f"{writeAggregatedExclusions() = }\n")
|
|
618
|
+
sys.stdout.write(f"{writeExclusionDictionaries() = }\n")
|
|
619
|
+
|
|
620
|
+
def runValidators() -> None:
|
|
621
|
+
collatedIndices: ExclusionData = loadCollatedIndices()
|
|
622
|
+
if not collatedIndices:
|
|
623
|
+
sys.stdout.write("No collated indices found. Run 'generate' mode first to create exclusion data.\\n")
|
|
624
|
+
return
|
|
625
|
+
|
|
626
|
+
listAnalysisMethods = [
|
|
627
|
+
analyzeNonContiguousIndicesRelative,
|
|
628
|
+
analyzeContiguousStartAbsolute,
|
|
629
|
+
analyzeContiguousEndAbsolute,
|
|
630
|
+
analyzeContiguousStartRelative,
|
|
631
|
+
analyzeContiguousEndRelative,
|
|
632
|
+
]
|
|
633
|
+
|
|
634
|
+
for analysisMethod in listAnalysisMethods:
|
|
635
|
+
validateAnalysisMethod(analysisMethod)
|
|
636
|
+
|
|
637
|
+
if __name__ == '__main__':
|
|
638
|
+
runGenerators()
|
|
639
|
+
runValidators()
|
|
640
|
+
|