mapFolding 0.17.0__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 +16 -10
- easyRun/__init__.py +1 -0
- easyRun/countFolds.py +17 -9
- easyRun/meanders.py +6 -8
- mapFolding/__init__.py +24 -35
- 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 -68
- mapFolding/algorithms/A086345.py +8 -3
- mapFolding/algorithms/__init__.py +1 -1
- mapFolding/algorithms/matrixMeandersNumPyndas.py +18 -18
- mapFolding/algorithms/oeisIDbyFormula.py +4 -4
- mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +3 -3
- mapFolding/basecamp.py +13 -28
- mapFolding/beDRY.py +108 -99
- 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 +2 -2
- 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 +133 -88
- 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.0.dist-info → mapfolding-0.18.0.dist-info}/METADATA +15 -9
- mapfolding-0.18.0.dist-info/RECORD +305 -0
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/WHEEL +1 -1
- easyRun/A000682.py +0 -25
- easyRun/A005316.py +0 -20
- mapFolding/algorithms/A000136constraintPropagation.py +0 -95
- mapFolding/algorithms/A000136elimination.py +0 -163
- mapFolding/algorithms/A000136eliminationParallel.py +0 -77
- mapfolding-0.17.0.dist-info/RECORD +0 -107
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
# ruff: noqa: ERA001
|
|
2
|
+
from collections import Counter, deque
|
|
3
|
+
from cytoolz.dicttoolz import get_in, keyfilter, valfilter
|
|
4
|
+
from cytoolz.functoolz import complement, curry as syntacticCurry
|
|
5
|
+
from functools import cache
|
|
6
|
+
from gmpy2 import bit_flip, bit_test as isBit1吗
|
|
7
|
+
from hunterMakesPy import raiseIfNone
|
|
8
|
+
from itertools import chain, combinations, product as CartesianProduct
|
|
9
|
+
from mapFolding import inclusive
|
|
10
|
+
from mapFolding._e import (
|
|
11
|
+
bifurcatePermutationSpace, DimensionIndex, dimensionNearestTail, dimensionNearest首, DOTitems, DOTkeys, DOTvalues,
|
|
12
|
+
getAntiPileRangeOfLeaves, getDictionaryConditionalLeafPredecessors, getIteratorOfLeaves, getLeafDomain,
|
|
13
|
+
getLeavesCreaseAnte, getLeavesCreasePost, JeanValjean, Leaf, LeafOrPileRangeOfLeaves, mapShapeIs2上nDimensions,
|
|
14
|
+
PermutationSpace, Pile, PileRangeOfLeaves, pileRangeOfLeavesAND, PinnedLeaves, reverseLookup, 一, 零, 首一, 首零一)
|
|
15
|
+
from mapFolding._e.algorithms.iff import thisIsAViolation
|
|
16
|
+
from mapFolding._e.dataBaskets import EliminationState
|
|
17
|
+
from mapFolding._e.filters import (
|
|
18
|
+
between, extractPilesWithPileRangeOfLeaves, extractPinnedLeaves, leafIsInPileRange, leafIsPinned, mappingHasKey,
|
|
19
|
+
notLeafOriginOrLeaf零, notPileLast, thisHasThat, thisIsALeaf, thisIsAPileRangeOfLeaves)
|
|
20
|
+
from mapFolding._e.pinIt import atPilePinLeaf, disqualifyAppendingLeafAtPile
|
|
21
|
+
from more_itertools import (
|
|
22
|
+
filter_map, ilen as lenIterator, one, pairwise, partition as more_itertools_partition, split_at, triplewise)
|
|
23
|
+
from typing import TYPE_CHECKING
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from collections.abc import Iterable, Iterator
|
|
27
|
+
|
|
28
|
+
#======== Boolean filters ======================================
|
|
29
|
+
|
|
30
|
+
@syntacticCurry
|
|
31
|
+
def leafIsOddInDimension(leaf: Leaf, dimension: int) -> bool:
|
|
32
|
+
return isBit1吗(leaf, dimension)
|
|
33
|
+
|
|
34
|
+
#======== Reducing `PileRangeOfLeaves` =======
|
|
35
|
+
|
|
36
|
+
# TODO implement - The signs of the magnitudes alternate: if the difference between two leaves is 2, for example, then before there can be another difference of 2, there must be a difference of -2.
|
|
37
|
+
# TODO implement - Because `state.leavesTotal // 2` always has one more than `- state.leavesTotal // 2`, the first and last differences with magnitude `state.leavesTotal // 2` are positive.
|
|
38
|
+
# TODO implement The running total of the differences does not repeat in a Folding.
|
|
39
|
+
def reduceAllPermutationSpaceInEliminationState(state: EliminationState) -> EliminationState:
|
|
40
|
+
"""Flow control to apply per-`PermutationSpace` functions to all of `state.listPermutationSpace`."""
|
|
41
|
+
listPermutationSpace: list[PermutationSpace] = state.listPermutationSpace
|
|
42
|
+
state.listPermutationSpace = []
|
|
43
|
+
state.listPermutationSpace.extend(filter_map(_reducePermutationSpace_byCrease(state), listPermutationSpace))
|
|
44
|
+
|
|
45
|
+
listPermutationSpace: list[PermutationSpace] = state.listPermutationSpace
|
|
46
|
+
state.listPermutationSpace = []
|
|
47
|
+
state.listPermutationSpace.extend(filter_map(_reducePermutationSpace_LeafIsPinned(state), listPermutationSpace))
|
|
48
|
+
|
|
49
|
+
listPermutationSpace: list[PermutationSpace] = state.listPermutationSpace
|
|
50
|
+
state.listPermutationSpace = []
|
|
51
|
+
state.listPermutationSpace.extend(filter_map(_reducePermutationSpace_HeadsBeforeTails(state), listPermutationSpace))
|
|
52
|
+
|
|
53
|
+
listPermutationSpace: list[PermutationSpace] = state.listPermutationSpace
|
|
54
|
+
state.listPermutationSpace = []
|
|
55
|
+
state.listPermutationSpace.extend(filter_map(_reducePermutationSpace_ConditionalPredecessors(state), listPermutationSpace))
|
|
56
|
+
|
|
57
|
+
listPermutationSpace: list[PermutationSpace] = state.listPermutationSpace
|
|
58
|
+
state.listPermutationSpace = []
|
|
59
|
+
state.listPermutationSpace.extend(filter_map(_reducePermutationSpace_CrossedCreases(state), listPermutationSpace))
|
|
60
|
+
|
|
61
|
+
listPermutationSpace: list[PermutationSpace] = state.listPermutationSpace
|
|
62
|
+
state.listPermutationSpace = []
|
|
63
|
+
state.listPermutationSpace.extend(filter_map(_reducePermutationSpace_noConsecutiveDimensions(state), listPermutationSpace))
|
|
64
|
+
|
|
65
|
+
listPermutationSpace: list[PermutationSpace] = state.listPermutationSpace
|
|
66
|
+
state.listPermutationSpace = []
|
|
67
|
+
state.listPermutationSpace.extend(filter_map(_reducePermutationSpace_leafDomainIs1(state), listPermutationSpace))
|
|
68
|
+
|
|
69
|
+
return state
|
|
70
|
+
|
|
71
|
+
#-------- Shared logic -----------------------------------------
|
|
72
|
+
def _reducePileRangesOfLeaves(state: EliminationState, permutationSpace: PermutationSpace, pilesToUpdate: deque[tuple[Pile, PileRangeOfLeaves]], antiPileRangeOfLeaves: PileRangeOfLeaves) -> PermutationSpace:
|
|
73
|
+
"""You can use this function to reduce `PileRangeOfLeaves` values in `permutationSpace` and propagate newly pinned `Leaf`.
|
|
74
|
+
|
|
75
|
+
(AI generated docstring)
|
|
76
|
+
|
|
77
|
+
This function updates each `pile: pileRangeOfLeaves` pair from `pilesToUpdate` by intersecting
|
|
78
|
+
`pileRangeOfLeaves` with `antiPileRangeOfLeaves` using `pileRangeOfLeavesAND`.
|
|
79
|
+
|
|
80
|
+
This function converts an updated `PileRangeOfLeaves` to a `Leaf` using `JeanValjean` when the
|
|
81
|
+
intersection contains exactly one `leaf`. If the intersection is empty, `JeanValjean` returns `None`,
|
|
82
|
+
and this function returns `{}` to signal that `permutationSpace` is invalid.
|
|
83
|
+
|
|
84
|
+
When a new `Leaf` becomes pinned, this function applies the "beans without cornbread" rule by
|
|
85
|
+
pinning the complementary adjacent `Leaf` via a local subroutine. This function then calls
|
|
86
|
+
`_reducePermutationSpace_LeafIsPinned` to propagate the new `Leaf` to all other piles.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
state : EliminationState
|
|
91
|
+
A data basket that provides `state.mapShape` for constructing follow-on `EliminationState` values.
|
|
92
|
+
permutationSpace : PermutationSpace
|
|
93
|
+
A dictionary of `pile: leaf` and/or `pile: pileRangeOfLeaves`.
|
|
94
|
+
pilesToUpdate : deque[tuple[Pile, PileRangeOfLeaves]]
|
|
95
|
+
A LIFO work list of `pile` and `pileRangeOfLeaves` pairs that must be reduced.
|
|
96
|
+
antiPileRangeOfLeaves : PileRangeOfLeaves
|
|
97
|
+
A `PileRangeOfLeaves` mask applied to each `pileRangeOfLeaves` using `pileRangeOfLeavesAND`.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
updatedPermutationSpace : PermutationSpace
|
|
102
|
+
An updated `permutationSpace` when reduction succeeds.
|
|
103
|
+
An empty dictionary `{}` when reduction invalidates `permutationSpace`.
|
|
104
|
+
|
|
105
|
+
References
|
|
106
|
+
----------
|
|
107
|
+
[1] mapFolding._e.pileRangeOfLeavesAND
|
|
108
|
+
Internal package reference.
|
|
109
|
+
[2] mapFolding._e.JeanValjean
|
|
110
|
+
Internal package reference.
|
|
111
|
+
[3] mapFolding._e.filters.thisIsALeaf
|
|
112
|
+
Internal package reference.
|
|
113
|
+
[4] mapFolding._e.pin2上nDimensionsAnnex._reducePermutationSpace_LeafIsPinned
|
|
114
|
+
Internal package reference.
|
|
115
|
+
|
|
116
|
+
"""
|
|
117
|
+
def pinLeafCornbread(state: EliminationState) -> EliminationState:
|
|
118
|
+
leafBeans: Leaf | None = None
|
|
119
|
+
for beans, cornbread in ((一+零, 一), (首一(state.dimensionsTotal), 首零一(state.dimensionsTotal))):
|
|
120
|
+
beansPinned: bool = leafIsPinned(state.permutationSpace, beans)
|
|
121
|
+
cornbreadPinned: bool = leafIsPinned(state.permutationSpace, cornbread)
|
|
122
|
+
if beansPinned ^ cornbreadPinned:
|
|
123
|
+
leafBeans = beans if beansPinned else cornbread
|
|
124
|
+
break
|
|
125
|
+
|
|
126
|
+
if leafBeans is None:
|
|
127
|
+
return state
|
|
128
|
+
|
|
129
|
+
state.pile = raiseIfNone(reverseLookup(state.permutationSpace, leafBeans))
|
|
130
|
+
if leafBeans in [一+零, 首一(state.dimensionsTotal)]:
|
|
131
|
+
state.pile += 1
|
|
132
|
+
leafCornbread = one(getLeavesCreasePost(state, leafBeans))
|
|
133
|
+
else:
|
|
134
|
+
state.pile -= 1
|
|
135
|
+
leafCornbread = one(getLeavesCreaseAnte(state, leafBeans))
|
|
136
|
+
|
|
137
|
+
if disqualifyAppendingLeafAtPile(state, leafCornbread):
|
|
138
|
+
state.permutationSpace = {}
|
|
139
|
+
else:
|
|
140
|
+
state.permutationSpace = atPilePinLeaf(state.permutationSpace, state.pile, leafCornbread)
|
|
141
|
+
|
|
142
|
+
return state
|
|
143
|
+
|
|
144
|
+
permutationSpaceHasNewLeaf: bool = False
|
|
145
|
+
while pilesToUpdate and not permutationSpaceHasNewLeaf:
|
|
146
|
+
pile, pileRangeOfLeaves = pilesToUpdate.pop()
|
|
147
|
+
if (ImaLeafOrPileRangeOfLeavesNotAWalrusSubscript := JeanValjean(pileRangeOfLeavesAND(antiPileRangeOfLeaves, pileRangeOfLeaves))) is None:
|
|
148
|
+
return {}
|
|
149
|
+
# TODO These statements are syntactically necessary because I'm using subscripts AND walrus operators. Does that suggest there is
|
|
150
|
+
# a "better" flow paradigm, or is this merely a limitation of Python syntax?
|
|
151
|
+
permutationSpace[pile] = ImaLeafOrPileRangeOfLeavesNotAWalrusSubscript
|
|
152
|
+
if thisIsALeaf(permutationSpace[pile]):
|
|
153
|
+
stateCornbread = EliminationState(state.mapShape, pile=pile, permutationSpace=permutationSpace)
|
|
154
|
+
if not (permutationSpace := pinLeafCornbread(stateCornbread).permutationSpace):
|
|
155
|
+
return {}
|
|
156
|
+
permutationSpaceHasNewLeaf = True
|
|
157
|
+
if permutationSpaceHasNewLeaf:
|
|
158
|
+
sherpa: PermutationSpace | None = _reducePermutationSpace_LeafIsPinned(state, permutationSpace)
|
|
159
|
+
if not sherpa:
|
|
160
|
+
return {}
|
|
161
|
+
else:
|
|
162
|
+
permutationSpace = sherpa
|
|
163
|
+
return permutationSpace
|
|
164
|
+
|
|
165
|
+
@syntacticCurry
|
|
166
|
+
def _reducePermutationSpace_byCrease(state: EliminationState, permutationSpace: PermutationSpace) -> PermutationSpace | None:
|
|
167
|
+
permutationSpaceHasNewLeaf = True
|
|
168
|
+
while permutationSpaceHasNewLeaf:
|
|
169
|
+
permutationSpaceHasNewLeaf = False
|
|
170
|
+
|
|
171
|
+
dequePileLeafOrPileRangeOfLeavesPileLeafOrPileRangeOfLeaves: deque[tuple[tuple[Pile, LeafOrPileRangeOfLeaves], tuple[Pile, LeafOrPileRangeOfLeaves]]] = deque(pairwise(sorted(permutationSpace.items())))
|
|
172
|
+
while dequePileLeafOrPileRangeOfLeavesPileLeafOrPileRangeOfLeaves and not permutationSpaceHasNewLeaf:
|
|
173
|
+
(pile_k, leafOrPileRangeOfLeaves_k), (pile_r, leafOrPileRangeOfLeaves_r) = dequePileLeafOrPileRangeOfLeavesPileLeafOrPileRangeOfLeaves.pop()
|
|
174
|
+
|
|
175
|
+
antiPileRangeOfLeaves: PileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, frozenset())
|
|
176
|
+
leavesCrease: Iterator[Leaf] = iter(())
|
|
177
|
+
pilesToUpdate: deque[tuple[Pile, PileRangeOfLeaves]] = deque()
|
|
178
|
+
|
|
179
|
+
if thisIsALeaf(leafOrPileRangeOfLeaves_k) and thisIsAPileRangeOfLeaves(leafOrPileRangeOfLeaves_r):
|
|
180
|
+
pilesToUpdate = deque([(pile_r, leafOrPileRangeOfLeaves_r)])
|
|
181
|
+
leavesCrease = getLeavesCreasePost(state, leafOrPileRangeOfLeaves_k)
|
|
182
|
+
elif thisIsAPileRangeOfLeaves(leafOrPileRangeOfLeaves_k) and thisIsALeaf(leafOrPileRangeOfLeaves_r):
|
|
183
|
+
pilesToUpdate = deque([(pile_k, leafOrPileRangeOfLeaves_k)])
|
|
184
|
+
leavesCrease = getLeavesCreaseAnte(state, leafOrPileRangeOfLeaves_r)
|
|
185
|
+
else:
|
|
186
|
+
continue
|
|
187
|
+
|
|
188
|
+
antiPileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, set(range(state.leavesTotal)).difference(leavesCrease))
|
|
189
|
+
|
|
190
|
+
sumChecksForNewLeaves: int = sum(map(dimensionNearest首, permutationSpace.values()))
|
|
191
|
+
if not (permutationSpace := _reducePileRangesOfLeaves(state, permutationSpace, pilesToUpdate, antiPileRangeOfLeaves)):
|
|
192
|
+
return None
|
|
193
|
+
if sum(map(dimensionNearest首, permutationSpace.values())) < sumChecksForNewLeaves:
|
|
194
|
+
permutationSpaceHasNewLeaf = True
|
|
195
|
+
|
|
196
|
+
return permutationSpace
|
|
197
|
+
|
|
198
|
+
@syntacticCurry
|
|
199
|
+
def _reducePermutationSpace_ConditionalPredecessors(state: EliminationState, permutationSpace: PermutationSpace) -> PermutationSpace | None:
|
|
200
|
+
if not mapShapeIs2上nDimensions(state.mapShape, youMustBeDimensionsTallToPinThis=6):
|
|
201
|
+
return permutationSpace
|
|
202
|
+
|
|
203
|
+
dictionaryConditionalLeafPredecessors: dict[Leaf, dict[Pile, list[Leaf]]] = getDictionaryConditionalLeafPredecessors(state)
|
|
204
|
+
|
|
205
|
+
permutationSpaceHasNewLeaf: bool = True
|
|
206
|
+
while permutationSpaceHasNewLeaf:
|
|
207
|
+
permutationSpaceHasNewLeaf = False
|
|
208
|
+
|
|
209
|
+
dequePileLeaf: deque[tuple[Pile, Leaf]] = deque(sorted(DOTitems(valfilter(mappingHasKey(dictionaryConditionalLeafPredecessors),
|
|
210
|
+
keyfilter(notPileLast(state.pileLast), valfilter(notLeafOriginOrLeaf零, extractPinnedLeaves(permutationSpace)))))))
|
|
211
|
+
|
|
212
|
+
while dequePileLeaf and not permutationSpaceHasNewLeaf:
|
|
213
|
+
pile, leaf = dequePileLeaf.pop()
|
|
214
|
+
|
|
215
|
+
if mappingHasKey(dictionaryConditionalLeafPredecessors[leaf], pile):
|
|
216
|
+
# For this `pile:leaf` in `permutationSpace`, `dictionaryConditionalLeafPredecessors` has a `list` of at least one
|
|
217
|
+
# `leaf` that must precede this `pile:leaf`, so the `list` cannot follow this `pile:leaf`, so remove the `list`
|
|
218
|
+
# from the `PileRangeOfLeaves` at piles after `pile`.
|
|
219
|
+
antiPileRangeOfLeaves: PileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, dictionaryConditionalLeafPredecessors[leaf][pile])
|
|
220
|
+
|
|
221
|
+
pilesToUpdate: deque[tuple[Pile, PileRangeOfLeaves]] = deque(DOTitems(extractPilesWithPileRangeOfLeaves(keyfilter(between(pile + inclusive, state.pileLast), permutationSpace))))
|
|
222
|
+
|
|
223
|
+
sumChecksForNewLeaves: int = sum(map(dimensionNearest首, permutationSpace.values()))
|
|
224
|
+
if not (permutationSpace := _reducePileRangesOfLeaves(state, permutationSpace, pilesToUpdate, antiPileRangeOfLeaves)):
|
|
225
|
+
return None
|
|
226
|
+
if sum(map(dimensionNearest首, permutationSpace.values())) < sumChecksForNewLeaves:
|
|
227
|
+
permutationSpaceHasNewLeaf = True
|
|
228
|
+
|
|
229
|
+
return permutationSpace
|
|
230
|
+
|
|
231
|
+
@syntacticCurry
|
|
232
|
+
def _reducePermutationSpace_CrossedCreases(state: EliminationState, permutationSpace: PermutationSpace) -> PermutationSpace | None:
|
|
233
|
+
permutationSpaceHasNewLeaf = True
|
|
234
|
+
while permutationSpaceHasNewLeaf:
|
|
235
|
+
permutationSpaceHasNewLeaf = False
|
|
236
|
+
for dimension in range(state.dimensionsTotal):
|
|
237
|
+
|
|
238
|
+
dictionaryLeafToPile: dict[Leaf, Pile] = {leafValue: pileKey for pileKey, leafValue in extractPinnedLeaves(permutationSpace).items()}
|
|
239
|
+
|
|
240
|
+
# For efficiency, I wish I could create the two dictionaries with one operation and without the intermediate `leavesPinned`.
|
|
241
|
+
leavesPinned: PinnedLeaves = extractPinnedLeaves(permutationSpace)
|
|
242
|
+
leavesPinnedEvenInDimension: PinnedLeaves = valfilter(complement(leafIsOddInDimension(dimension=dimension)), leavesPinned)
|
|
243
|
+
leavesPinnedOddInDimension: PinnedLeaves = valfilter(leafIsOddInDimension(dimension=dimension), leavesPinned)
|
|
244
|
+
|
|
245
|
+
dequePileLeafPileLeaf: deque[tuple[PinnedLeaves, tuple[tuple[Pile, Leaf], tuple[Pile, Leaf]]]] = deque(
|
|
246
|
+
CartesianProduct((leavesPinnedOddInDimension,), combinations(leavesPinnedEvenInDimension.items(), 2)))
|
|
247
|
+
dequePileLeafPileLeaf.extend(deque(CartesianProduct((leavesPinnedEvenInDimension,), combinations(leavesPinnedOddInDimension.items(), 2))))
|
|
248
|
+
|
|
249
|
+
while dequePileLeafPileLeaf and not permutationSpaceHasNewLeaf:
|
|
250
|
+
leavesPinnedParityOpposite, ((pileOf_k, leaf_k), (pileOf_r, leaf_r)) = dequePileLeafPileLeaf.pop()
|
|
251
|
+
leaf_kCrease: Leaf = int(bit_flip(leaf_k, dimension))
|
|
252
|
+
leaf_rCrease: Leaf = int(bit_flip(leaf_r, dimension))
|
|
253
|
+
pileOf_kCrease: Pile = 31212012
|
|
254
|
+
pileOf_rCrease: Pile = 31212012
|
|
255
|
+
|
|
256
|
+
if (leaf_kCreaseIsPinned := leafIsPinned(leavesPinnedParityOpposite, leaf_kCrease)):
|
|
257
|
+
pileOf_kCrease = dictionaryLeafToPile[leaf_kCrease]
|
|
258
|
+
if (leaf_rCreaseIsPinned := leafIsPinned(leavesPinnedParityOpposite, leaf_rCrease)):
|
|
259
|
+
pileOf_rCrease = dictionaryLeafToPile[leaf_rCrease]
|
|
260
|
+
|
|
261
|
+
pilesForbidden: Iterable[Pile] = []
|
|
262
|
+
antiPileRangeOfLeaves: PileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, frozenset())
|
|
263
|
+
|
|
264
|
+
if leaf_kCreaseIsPinned and not leaf_rCreaseIsPinned:
|
|
265
|
+
antiPileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, (leaf_rCrease,))
|
|
266
|
+
|
|
267
|
+
if pileOf_k < pileOf_r < pileOf_kCrease:
|
|
268
|
+
pilesForbidden = frozenset([*range(pileOf_k), *range(pileOf_kCrease + 1, state.pileLast + inclusive)])
|
|
269
|
+
elif pileOf_kCrease < pileOf_r < pileOf_k:
|
|
270
|
+
pilesForbidden = frozenset([*range(pileOf_kCrease), *range(pileOf_k + 1, state.pileLast + inclusive)])
|
|
271
|
+
elif (pileOf_r < pileOf_kCrease < pileOf_k) or (pileOf_kCrease < pileOf_k < pileOf_r):
|
|
272
|
+
pilesForbidden = frozenset(range(pileOf_kCrease + 1, pileOf_k))
|
|
273
|
+
elif (pileOf_r < pileOf_k < pileOf_kCrease) or (pileOf_k < pileOf_kCrease < pileOf_r):
|
|
274
|
+
pilesForbidden = frozenset(range(pileOf_k + 1, pileOf_kCrease))
|
|
275
|
+
|
|
276
|
+
elif not leaf_kCreaseIsPinned and leaf_rCreaseIsPinned:
|
|
277
|
+
antiPileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, (leaf_kCrease,))
|
|
278
|
+
|
|
279
|
+
if pileOf_rCrease < pileOf_k < pileOf_r:
|
|
280
|
+
pilesForbidden = frozenset([*range(pileOf_rCrease), *range(pileOf_r + 1, state.pileLast + inclusive)])
|
|
281
|
+
elif pileOf_r < pileOf_k < pileOf_rCrease:
|
|
282
|
+
pilesForbidden = frozenset([*range(pileOf_r), *range(pileOf_rCrease + 1, state.pileLast + inclusive)])
|
|
283
|
+
elif (pileOf_k < pileOf_r < pileOf_rCrease) or (pileOf_r < pileOf_rCrease < pileOf_k):
|
|
284
|
+
pilesForbidden = frozenset(range(pileOf_r + 1, pileOf_rCrease))
|
|
285
|
+
elif (pileOf_k < pileOf_rCrease < pileOf_r) or (pileOf_rCrease < pileOf_r < pileOf_k):
|
|
286
|
+
pilesForbidden = frozenset(range(pileOf_rCrease + 1, pileOf_r))
|
|
287
|
+
|
|
288
|
+
elif leaf_kCreaseIsPinned and leaf_rCreaseIsPinned:
|
|
289
|
+
if thisIsAViolation(pileOf_k, pileOf_r, pileOf_kCrease, pileOf_rCrease):
|
|
290
|
+
return None
|
|
291
|
+
|
|
292
|
+
elif not leaf_kCreaseIsPinned and not leaf_rCreaseIsPinned:
|
|
293
|
+
# case leaves: leaf_k, leaf_r
|
|
294
|
+
# I don't think I have enough information to do anything.
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
pilesToUpdate: deque[tuple[Pile, PileRangeOfLeaves]] = deque(DOTitems(keyfilter(thisHasThat(pilesForbidden), extractPilesWithPileRangeOfLeaves(permutationSpace))))
|
|
298
|
+
|
|
299
|
+
sumChecksForNewLeaves: int = sum(map(dimensionNearest首, permutationSpace.values()))
|
|
300
|
+
if not (permutationSpace := _reducePileRangesOfLeaves(state, permutationSpace, pilesToUpdate, antiPileRangeOfLeaves)):
|
|
301
|
+
return None
|
|
302
|
+
if sum(map(dimensionNearest首, permutationSpace.values())) < sumChecksForNewLeaves:
|
|
303
|
+
permutationSpaceHasNewLeaf = True
|
|
304
|
+
|
|
305
|
+
return permutationSpace
|
|
306
|
+
|
|
307
|
+
@syntacticCurry
|
|
308
|
+
def _reducePermutationSpace_HeadsBeforeTails(state: EliminationState, permutationSpace: PermutationSpace) -> PermutationSpace | None:
|
|
309
|
+
permutationSpaceHasNewLeaf: bool = True
|
|
310
|
+
while permutationSpaceHasNewLeaf:
|
|
311
|
+
permutationSpaceHasNewLeaf = False
|
|
312
|
+
dequePileLeaf: deque[tuple[Pile, Leaf]] = deque(sorted(DOTitems(keyfilter(notPileLast(state.pileLast), valfilter(notLeafOriginOrLeaf零, extractPinnedLeaves(permutationSpace))))))
|
|
313
|
+
while dequePileLeaf and not permutationSpaceHasNewLeaf:
|
|
314
|
+
pile, leaf = dequePileLeaf.pop()
|
|
315
|
+
dimensionTail: int = dimensionNearestTail(leaf)
|
|
316
|
+
dimensionHead: int = dimensionNearest首(leaf)
|
|
317
|
+
if 0 < dimensionHead:
|
|
318
|
+
leavesForbidden = range(state.productsOfDimensions[dimensionHead], state.leavesTotal, state.productsOfDimensions[dimensionHead])
|
|
319
|
+
floor: Pile = 2
|
|
320
|
+
ceiling: Pile = pile - inclusive
|
|
321
|
+
|
|
322
|
+
antiPileRangeOfLeaves: PileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, leavesForbidden)
|
|
323
|
+
pilesToUpdate: deque[tuple[Pile, PileRangeOfLeaves]] = deque(extractPilesWithPileRangeOfLeaves(keyfilter(between(floor, ceiling), permutationSpace)).items())
|
|
324
|
+
|
|
325
|
+
sumChecksForNewLeaves: int = sum(map(dimensionNearest首, permutationSpace.values()))
|
|
326
|
+
if not (permutationSpace := _reducePileRangesOfLeaves(state, permutationSpace, pilesToUpdate, antiPileRangeOfLeaves)):
|
|
327
|
+
return None
|
|
328
|
+
if sum(map(dimensionNearest首, permutationSpace.values())) < sumChecksForNewLeaves:
|
|
329
|
+
permutationSpaceHasNewLeaf = True
|
|
330
|
+
|
|
331
|
+
if 0 < dimensionTail:
|
|
332
|
+
leavesForbidden = range(0, state.sumsOfProductsOfDimensions[dimensionTail], 1)
|
|
333
|
+
floor: Pile = pile + inclusive
|
|
334
|
+
ceiling: Pile = state.pileLast
|
|
335
|
+
|
|
336
|
+
antiPileRangeOfLeaves: PileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, leavesForbidden)
|
|
337
|
+
pilesToUpdate: deque[tuple[Pile, PileRangeOfLeaves]] = deque(extractPilesWithPileRangeOfLeaves(keyfilter(between(floor, ceiling), permutationSpace)).items())
|
|
338
|
+
|
|
339
|
+
sumChecksForNewLeaves = sum(map(dimensionNearest首, permutationSpace.values()))
|
|
340
|
+
if not (permutationSpace := _reducePileRangesOfLeaves(state, permutationSpace, pilesToUpdate, antiPileRangeOfLeaves)):
|
|
341
|
+
return None
|
|
342
|
+
if sum(map(dimensionNearest首, permutationSpace.values())) < sumChecksForNewLeaves:
|
|
343
|
+
permutationSpaceHasNewLeaf = True
|
|
344
|
+
|
|
345
|
+
return permutationSpace
|
|
346
|
+
|
|
347
|
+
@syntacticCurry
|
|
348
|
+
def _reducePermutationSpace_leafDomainIs1(state: EliminationState, permutationSpace: PermutationSpace) -> PermutationSpace | None:
|
|
349
|
+
permutationSpaceHasNewLeaf: bool = True
|
|
350
|
+
while permutationSpaceHasNewLeaf:
|
|
351
|
+
permutationSpaceHasNewLeaf = False
|
|
352
|
+
|
|
353
|
+
leavesPinned, pilesWithPileRangeOfLeaves = bifurcatePermutationSpace(permutationSpace)
|
|
354
|
+
|
|
355
|
+
leafAndItsDomainSize: Counter[Leaf] = Counter(chain(
|
|
356
|
+
chain.from_iterable(map(getIteratorOfLeaves, DOTvalues(pilesWithPileRangeOfLeaves))),
|
|
357
|
+
DOTvalues(leavesPinned)
|
|
358
|
+
))
|
|
359
|
+
|
|
360
|
+
if set(range(state.leavesTotal)).difference(leafAndItsDomainSize.keys()):
|
|
361
|
+
return None
|
|
362
|
+
|
|
363
|
+
leavesWithDomainOf1: set[Leaf] = set(DOTkeys(valfilter((1).__eq__, leafAndItsDomainSize))).difference(leavesPinned.values()).difference([state.leavesTotal])
|
|
364
|
+
if leavesWithDomainOf1:
|
|
365
|
+
permutationSpaceHasNewLeaf = True
|
|
366
|
+
leaf: Leaf = leavesWithDomainOf1.pop()
|
|
367
|
+
pile: Pile = one(DOTkeys(valfilter(leafIsInPileRange(leaf), pilesWithPileRangeOfLeaves)))
|
|
368
|
+
sherpa: PermutationSpace | None = _reducePermutationSpace_LeafIsPinned(state, atPilePinLeaf(permutationSpace, pile, leaf))
|
|
369
|
+
if (sherpa is None) or (not sherpa):
|
|
370
|
+
return None
|
|
371
|
+
else:
|
|
372
|
+
permutationSpace = sherpa
|
|
373
|
+
return permutationSpace
|
|
374
|
+
|
|
375
|
+
@syntacticCurry
|
|
376
|
+
def _reducePermutationSpace_LeafIsPinned(state: EliminationState, permutationSpace: PermutationSpace) -> PermutationSpace | None:
|
|
377
|
+
"""Update or invalidate `permutationSpace`: for every `leaf` pinned at a `pile`, remove `leaf` from `PileRangeOfLeaves` from every other `pile`; or return `None` if the updated `permutationSpace` is invalid.
|
|
378
|
+
|
|
379
|
+
If the `PileRangeOfLeaves` for a `pile` is reduced to one `leaf`, then convert from `pile: pileRangeOfLeaves` to `pile: leaf`.
|
|
380
|
+
If that results in "beans without cornbread", then pin the complementary "cornbread" `leaf` at the appropriate adjacent
|
|
381
|
+
`pile`.
|
|
382
|
+
|
|
383
|
+
Parameters
|
|
384
|
+
----------
|
|
385
|
+
state : EliminationState
|
|
386
|
+
A data basket to facilitate computations and actions.
|
|
387
|
+
permutationSpace : PermutationSpace
|
|
388
|
+
A dictionary of `pile: leaf` and/or `pile: pileRangeOfLeaves`.
|
|
389
|
+
|
|
390
|
+
Returns
|
|
391
|
+
-------
|
|
392
|
+
updatedPermutationSpace : PermutationSpace | None
|
|
393
|
+
An updated `permutationSpace` if valid; otherwise `None`.
|
|
394
|
+
|
|
395
|
+
"""
|
|
396
|
+
permutationSpaceHasNewLeaf: bool = True
|
|
397
|
+
|
|
398
|
+
while permutationSpaceHasNewLeaf:
|
|
399
|
+
permutationSpaceHasNewLeaf = False
|
|
400
|
+
|
|
401
|
+
leavesPinned, pilesWithPileRangeOfLeaves = bifurcatePermutationSpace(permutationSpace)
|
|
402
|
+
|
|
403
|
+
antiPileRangeOfLeaves: PileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, DOTvalues(leavesPinned))
|
|
404
|
+
|
|
405
|
+
pilesToUpdate: deque[tuple[Pile, PileRangeOfLeaves]] = deque(pilesWithPileRangeOfLeaves.items())
|
|
406
|
+
|
|
407
|
+
sumChecksForNewLeaves: int = sum(map(dimensionNearest首, permutationSpace.values()))
|
|
408
|
+
if not (permutationSpace := _reducePileRangesOfLeaves(state, permutationSpace, pilesToUpdate, antiPileRangeOfLeaves)):
|
|
409
|
+
return None
|
|
410
|
+
if sum(map(dimensionNearest首, permutationSpace.values())) < sumChecksForNewLeaves:
|
|
411
|
+
permutationSpaceHasNewLeaf = True
|
|
412
|
+
|
|
413
|
+
return permutationSpace
|
|
414
|
+
|
|
415
|
+
@syntacticCurry
|
|
416
|
+
def _reducePermutationSpace_noConsecutiveDimensions(state: EliminationState, permutationSpace: PermutationSpace) -> PermutationSpace | None:
|
|
417
|
+
# TODO Figure out a way to measure how often this function (or the other functions) actually reduces `permutationSpace`.
|
|
418
|
+
permutationSpaceHasNewLeaf = True
|
|
419
|
+
while permutationSpaceHasNewLeaf:
|
|
420
|
+
permutationSpaceHasNewLeaf = False
|
|
421
|
+
|
|
422
|
+
Z0Z_triple = deque(triplewise(sorted(permutationSpace.items())))
|
|
423
|
+
while Z0Z_triple and not permutationSpaceHasNewLeaf:
|
|
424
|
+
(pile_k, leafOrPileRangeOfLeaves_k), (pile_r, leafOrPileRangeOfLeaves_r), (pile_z, leafOrPileRangeOfLeaves_z) = Z0Z_triple.pop()
|
|
425
|
+
|
|
426
|
+
antiPileRangeOfLeaves: PileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, frozenset())
|
|
427
|
+
leafForbidden: Leaf = 0
|
|
428
|
+
pilesToUpdate: deque[tuple[Pile, PileRangeOfLeaves]] = deque()
|
|
429
|
+
|
|
430
|
+
if thisIsALeaf(leafOrPileRangeOfLeaves_k) and thisIsALeaf(leafOrPileRangeOfLeaves_r) and thisIsAPileRangeOfLeaves(leafOrPileRangeOfLeaves_z):
|
|
431
|
+
pilesToUpdate = deque([(pile_z, leafOrPileRangeOfLeaves_z)])
|
|
432
|
+
differenceOfLeaves: int = leafOrPileRangeOfLeaves_k - leafOrPileRangeOfLeaves_r
|
|
433
|
+
leafForbidden = leafOrPileRangeOfLeaves_r + differenceOfLeaves
|
|
434
|
+
elif thisIsALeaf(leafOrPileRangeOfLeaves_k) and thisIsAPileRangeOfLeaves(leafOrPileRangeOfLeaves_r) and thisIsALeaf(leafOrPileRangeOfLeaves_z):
|
|
435
|
+
pilesToUpdate = deque([(pile_r, leafOrPileRangeOfLeaves_r)])
|
|
436
|
+
leafForbidden = (leafOrPileRangeOfLeaves_k + leafOrPileRangeOfLeaves_z) // 2
|
|
437
|
+
elif thisIsAPileRangeOfLeaves(leafOrPileRangeOfLeaves_k) and thisIsALeaf(leafOrPileRangeOfLeaves_r) and thisIsALeaf(leafOrPileRangeOfLeaves_z):
|
|
438
|
+
pilesToUpdate = deque([(pile_k, leafOrPileRangeOfLeaves_k)])
|
|
439
|
+
differenceOfLeaves: int = leafOrPileRangeOfLeaves_r - leafOrPileRangeOfLeaves_z
|
|
440
|
+
leafForbidden = leafOrPileRangeOfLeaves_r - differenceOfLeaves
|
|
441
|
+
else:
|
|
442
|
+
continue
|
|
443
|
+
|
|
444
|
+
antiPileRangeOfLeaves = getAntiPileRangeOfLeaves(state.leavesTotal, [leafForbidden])
|
|
445
|
+
|
|
446
|
+
sumChecksForNewLeaves: int = sum(map(dimensionNearest首, permutationSpace.values()))
|
|
447
|
+
if not (permutationSpace := _reducePileRangesOfLeaves(state, permutationSpace, pilesToUpdate, antiPileRangeOfLeaves)):
|
|
448
|
+
return None
|
|
449
|
+
if sum(map(dimensionNearest首, permutationSpace.values())) < sumChecksForNewLeaves:
|
|
450
|
+
permutationSpaceHasNewLeaf = True
|
|
451
|
+
|
|
452
|
+
return permutationSpace
|
|
453
|
+
|
|
454
|
+
@syntacticCurry
|
|
455
|
+
# TODO Implement `sudoku` reduction: borrow ideas from `notEnoughOpenPiles`.
|
|
456
|
+
def sudoku(state: EliminationState, permutationSpace: PermutationSpace) -> PermutationSpace | None: # noqa: ARG001
|
|
457
|
+
"""My implementation broke `eliminationCrease` and possibly other things.
|
|
458
|
+
|
|
459
|
+
Sudoku trick:
|
|
460
|
+
in a restricted space (square, row, or column), if two numbers have the same domain of two cells, then all other numbers are excluded from those two cells.
|
|
461
|
+
^^^ generalizes to if n numbers have the same domain of n cells, all other numbers are excluded from that domain of n cells.
|
|
462
|
+
"""
|
|
463
|
+
return permutationSpace
|
|
464
|
+
def notEnoughOpenPiles(state: EliminationState) -> bool:
|
|
465
|
+
"""Decommissioned: implement with the sudoku trick.
|
|
466
|
+
|
|
467
|
+
Check `state.permutationSpace` for enough open piles for required leaves.
|
|
468
|
+
|
|
469
|
+
Some leaves must be before or after other leaves, such as the dimension origin leaves. For each pinned leaf, get all of the
|
|
470
|
+
required leaves for before and after, and check if there are enough open piles for all of them. If the set of open piles does
|
|
471
|
+
not intersect with the domain of a required leaf, return True. If a required leaf can only be pinned in one pile of the open
|
|
472
|
+
piles, pin it at that pile in stateOfOpenPiles. Use the real pinning functions with the disposable stateOfOpenPiles. With the required
|
|
473
|
+
leaves that are not pinned, check if there are enough open piles for them.
|
|
474
|
+
"""
|
|
475
|
+
stateWorkbench = EliminationState(state.mapShape, pile=state.pile, permutationSpace=state.permutationSpace.copy())
|
|
476
|
+
|
|
477
|
+
dictionaryConditionalLeafPredecessors: dict[Leaf, dict[Pile, list[Leaf]]] = getDictionaryConditionalLeafPredecessors(state)
|
|
478
|
+
|
|
479
|
+
# DEVELOPMENT Reminder: I designed this function before `updateListPermutationSpace` AND BEFORE `PileRangeOfLeaves`. I'm not using
|
|
480
|
+
# `PileRangeOfLeaves` anywhere in this function, which seems odd. I should rethink the entire function. Actually, I should
|
|
481
|
+
# translate the broader concept--allocating limited piles to the leaves that must have them--into a subroutine of
|
|
482
|
+
# `updateListPermutationSpace`. And then eliminate this function.
|
|
483
|
+
|
|
484
|
+
# This general concept is the sudoku trick, right?
|
|
485
|
+
|
|
486
|
+
# DEVELOPMENT Flow control
|
|
487
|
+
permutationSpaceHasNewLeaf: bool = True
|
|
488
|
+
while permutationSpaceHasNewLeaf:
|
|
489
|
+
permutationSpaceHasNewLeaf = False
|
|
490
|
+
|
|
491
|
+
# DEVELOPMENT Too many intermediate variables. And/or the wrong variables. And/or the wrong functions.
|
|
492
|
+
leavesPinned, _pilesWithPileRangeOfLeaves = bifurcatePermutationSpace(stateWorkbench.permutationSpace)
|
|
493
|
+
leavesFixed: tuple[Leaf, ...] = tuple(DOTvalues(leavesPinned))
|
|
494
|
+
leavesNotPinned: frozenset[Leaf] = frozenset(range(stateWorkbench.leavesTotal)).difference(leavesFixed)
|
|
495
|
+
pilesOpen: frozenset[Pile] = frozenset(range(stateWorkbench.pileLast + inclusive)).difference(leavesPinned.keys())
|
|
496
|
+
|
|
497
|
+
dequePileLeaf: deque[tuple[Pile, Leaf]] = deque(sorted(DOTitems(keyfilter(notPileLast(state.pileLast), valfilter(notLeafOriginOrLeaf零, leavesPinned)))))
|
|
498
|
+
|
|
499
|
+
while dequePileLeaf and not permutationSpaceHasNewLeaf:
|
|
500
|
+
# DEVELOPMENT Iteration data
|
|
501
|
+
pile, leaf = dequePileLeaf.pop()
|
|
502
|
+
leavesFixedBeforePile, leavesFixedAfterPile = split_at(leavesFixed, leaf.__eq__, maxsplit=1)
|
|
503
|
+
pilesOpenAfterLeaf, pilesOpenBeforeLeaf = more_itertools_partition(pile.__lt__, pilesOpen)
|
|
504
|
+
|
|
505
|
+
@cache
|
|
506
|
+
def leaf_kMustPrecede_leaf吗(leaf_k: Leaf, leaf: Leaf = leaf, pile: Pile = pile) -> bool:
|
|
507
|
+
if dimensionNearest首(leaf_k) <= dimensionNearestTail(leaf):
|
|
508
|
+
return True
|
|
509
|
+
return leaf_k in get_in([leaf, pile], dictionaryConditionalLeafPredecessors, default=list[Leaf]())
|
|
510
|
+
|
|
511
|
+
dimensionHead: DimensionIndex = dimensionNearest首(leaf)
|
|
512
|
+
@cache
|
|
513
|
+
def leafMustPrecede_leaf_r吗(leaf_r: Leaf, dimensionHead: DimensionIndex = dimensionHead) -> bool:
|
|
514
|
+
return dimensionHead <= dimensionNearestTail(leaf_r)
|
|
515
|
+
|
|
516
|
+
if any(map(leaf_kMustPrecede_leaf吗, leavesFixedAfterPile)) or any(map(leafMustPrecede_leaf_r吗, leavesFixedBeforePile)):
|
|
517
|
+
return True
|
|
518
|
+
|
|
519
|
+
leavesMustPrecede_leaf: deque[Leaf] = deque(filter(leaf_kMustPrecede_leaf吗, leavesNotPinned))
|
|
520
|
+
leafMustPrecedeLeaves: deque[Leaf] = deque(filter(leafMustPrecede_leaf_r吗, leavesNotPinned))
|
|
521
|
+
|
|
522
|
+
if (lenIterator(pilesOpenBeforeLeaf) < lenIterator(leavesMustPrecede_leaf)) or (lenIterator(pilesOpenAfterLeaf) < lenIterator(leafMustPrecedeLeaves)):
|
|
523
|
+
return True
|
|
524
|
+
|
|
525
|
+
while leavesMustPrecede_leaf and not permutationSpaceHasNewLeaf:
|
|
526
|
+
# DEVELOPMENT Iteration data, nested
|
|
527
|
+
leaf_k: Leaf = leavesMustPrecede_leaf.pop()
|
|
528
|
+
|
|
529
|
+
domain_k = getLeafDomain(stateWorkbench, leaf_k)
|
|
530
|
+
pilesOpenFor_k: set[Pile] = set(pilesOpenBeforeLeaf).intersection(domain_k)
|
|
531
|
+
|
|
532
|
+
if len(pilesOpenFor_k) == 0:
|
|
533
|
+
return True
|
|
534
|
+
if len(pilesOpenFor_k) == 1:
|
|
535
|
+
stateWorkbench.permutationSpace = atPilePinLeaf(stateWorkbench.permutationSpace, pilesOpenFor_k.pop(), leaf_k)
|
|
536
|
+
permutationSpaceHasNewLeaf = True
|
|
537
|
+
|
|
538
|
+
while leafMustPrecedeLeaves and not permutationSpaceHasNewLeaf:
|
|
539
|
+
# DEVELOPMENT Iteration data, nested
|
|
540
|
+
leaf_r: Leaf = leafMustPrecedeLeaves.pop()
|
|
541
|
+
|
|
542
|
+
domain_r = getLeafDomain(stateWorkbench, leaf_r)
|
|
543
|
+
pilesOpenFor_r: set[int] = set(pilesOpenAfterLeaf).intersection(domain_r)
|
|
544
|
+
|
|
545
|
+
if len(pilesOpenFor_r) == 0:
|
|
546
|
+
return True
|
|
547
|
+
if len(pilesOpenFor_r) == 1:
|
|
548
|
+
stateWorkbench.permutationSpace = atPilePinLeaf(stateWorkbench.permutationSpace, pilesOpenFor_r.pop(), leaf_r)
|
|
549
|
+
permutationSpaceHasNewLeaf = True
|
|
550
|
+
|
|
551
|
+
return False
|