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.
Files changed (245) hide show
  1. easyRun/NOTcountingFolds.py +16 -10
  2. easyRun/__init__.py +1 -0
  3. easyRun/countFolds.py +17 -9
  4. easyRun/meanders.py +6 -8
  5. mapFolding/__init__.py +24 -35
  6. mapFolding/_e/Z0Z_analysisPython/SORTZ0Z_hypothesis.py +189 -0
  7. mapFolding/_e/Z0Z_analysisPython/SORTZ0Z_p2d6.py +143 -0
  8. mapFolding/_e/Z0Z_analysisPython/__init__.py +4 -0
  9. mapFolding/_e/Z0Z_analysisPython/exclusionData/__init__.py +0 -0
  10. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200.py +369 -0
  11. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/2001.py +694 -0
  12. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/270/211.py +514 -0
  13. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/270/2111.py +480 -0
  14. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214.py +511 -0
  15. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/2141.py +515 -0
  16. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214/344/270/211.py +485 -0
  17. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214/344/270/2111.py +442 -0
  18. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/211.py +313 -0
  19. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/2111.py +343 -0
  20. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214.py +400 -0
  21. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/2141.py +497 -0
  22. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214/344/270/211.py +463 -0
  23. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214/344/270/2111.py +441 -0
  24. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266.py +35 -0
  25. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/2661.py +35 -0
  26. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200.py +382 -0
  27. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/2001.py +630 -0
  28. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/270/211.py +488 -0
  29. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/270/2111.py +475 -0
  30. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214.py +473 -0
  31. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/2141.py +500 -0
  32. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +465 -0
  33. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +439 -0
  34. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/211.py +599 -0
  35. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/2111.py +536 -0
  36. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214.py +506 -0
  37. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/2141.py +533 -0
  38. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214/344/270/211.py +489 -0
  39. mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214/344/270/2111.py +474 -0
  40. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200.py +1186 -0
  41. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2001.py +2158 -0
  42. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2001Negative.py +2158 -0
  43. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200Negative.py +1186 -0
  44. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/211.py +1397 -0
  45. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/2111.py +1291 -0
  46. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/2111Negative.py +1291 -0
  47. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/211Negative.py +1397 -0
  48. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214.py +1240 -0
  49. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/2141.py +1420 -0
  50. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/2141Negative.py +1420 -0
  51. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214Negative.py +1240 -0
  52. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/211.py +1366 -0
  53. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/2111.py +1274 -0
  54. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/2111Negative.py +1274 -0
  55. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/211Negative.py +1366 -0
  56. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/211.py +1186 -0
  57. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2111.py +1186 -0
  58. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2111Negative.py +1186 -0
  59. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/211Negative.py +1186 -0
  60. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214.py +1102 -0
  61. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/2141.py +1422 -0
  62. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/2141Negative.py +1422 -0
  63. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214Negative.py +1102 -0
  64. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/211.py +1240 -0
  65. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/2111.py +1228 -0
  66. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/2111Negative.py +1228 -0
  67. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/211Negative.py +1240 -0
  68. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266.py +32 -0
  69. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/2661.py +1162 -0
  70. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/2661Negative.py +1162 -0
  71. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266Negative.py +32 -0
  72. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200.py +1186 -0
  73. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2001.py +1926 -0
  74. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2001Negative.py +1926 -0
  75. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200Negative.py +1186 -0
  76. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/211.py +1291 -0
  77. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/2111.py +1176 -0
  78. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/2111Negative.py +1176 -0
  79. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/211Negative.py +1291 -0
  80. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214.py +1228 -0
  81. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/2141.py +1324 -0
  82. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/2141Negative.py +1324 -0
  83. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214Negative.py +1228 -0
  84. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +1274 -0
  85. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +1038 -0
  86. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111Negative.py +1038 -0
  87. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211Negative.py +1274 -0
  88. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/211.py +2158 -0
  89. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2111.py +1926 -0
  90. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2111Negative.py +1926 -0
  91. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/211Negative.py +2158 -0
  92. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214.py +1422 -0
  93. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/2141.py +1364 -0
  94. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/2141Negative.py +1364 -0
  95. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214Negative.py +1422 -0
  96. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/211.py +1420 -0
  97. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/2111.py +1324 -0
  98. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/2111Negative.py +1324 -0
  99. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/211Negative.py +1420 -0
  100. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200.py +3133 -0
  101. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2001.py +6039 -0
  102. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2001Negative.py +6039 -0
  103. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200Negative.py +3133 -0
  104. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/211.py +3527 -0
  105. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/2111.py +2300 -0
  106. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/2111Negative.py +2300 -0
  107. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/211Negative.py +3527 -0
  108. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214.py +3597 -0
  109. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/2141.py +3317 -0
  110. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/2141Negative.py +3317 -0
  111. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214Negative.py +3597 -0
  112. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/211.py +3161 -0
  113. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/2111.py +2877 -0
  114. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/2111Negative.py +2877 -0
  115. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/211Negative.py +3161 -0
  116. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/211.py +2981 -0
  117. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2111.py +3055 -0
  118. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2111Negative.py +3055 -0
  119. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/211Negative.py +2981 -0
  120. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214.py +3221 -0
  121. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/2141.py +3988 -0
  122. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/2141Negative.py +3988 -0
  123. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214Negative.py +3221 -0
  124. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/211.py +3652 -0
  125. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/2111.py +2863 -0
  126. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/2111Negative.py +2863 -0
  127. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/211Negative.py +3652 -0
  128. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200.py +2485 -0
  129. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2001.py +4566 -0
  130. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2001Negative.py +4566 -0
  131. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200Negative.py +2485 -0
  132. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/211.py +3006 -0
  133. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/2111.py +2485 -0
  134. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/2111Negative.py +2485 -0
  135. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/211Negative.py +3006 -0
  136. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214.py +3304 -0
  137. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/2141.py +3015 -0
  138. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/2141Negative.py +3015 -0
  139. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214Negative.py +3304 -0
  140. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +2939 -0
  141. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +2589 -0
  142. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111Negative.py +2589 -0
  143. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211Negative.py +2939 -0
  144. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/211.py +3899 -0
  145. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2111.py +2996 -0
  146. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2111Negative.py +2996 -0
  147. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/211Negative.py +3899 -0
  148. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214.py +3223 -0
  149. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/2141.py +3020 -0
  150. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/2141Negative.py +3020 -0
  151. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214Negative.py +3223 -0
  152. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/211.py +3250 -0
  153. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/2111.py +2667 -0
  154. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/2111Negative.py +2667 -0
  155. mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/211Negative.py +3250 -0
  156. mapFolding/_e/Z0Z_analysisPython/measure.py +162 -0
  157. mapFolding/_e/Z0Z_analysisPython/positionAnalysis.py +403 -0
  158. mapFolding/_e/Z0Z_analysisPython/positionAnalysisPileRanges2d6.py +110 -0
  159. mapFolding/_e/Z0Z_analysisPython/theExcluderBeast.py +640 -0
  160. mapFolding/_e/Z0Z_analysisPython/toolkit.py +166 -0
  161. mapFolding/_e/Z0Z_analysisPython/toolkitCSVsequences.py +188 -0
  162. mapFolding/_e/Z0Z_analysisPython/workBenchPatternFinder.py +284 -0
  163. mapFolding/_e/Z0Z_notes/__init__.py +0 -0
  164. mapFolding/_e/Z0Z_notes/knowledgeDump.py +214 -0
  165. mapFolding/_e/__init__.py +45 -0
  166. mapFolding/_e/_beDRY.py +547 -0
  167. mapFolding/_e/_dataDynamic.py +1164 -0
  168. mapFolding/_e/_measure.py +579 -0
  169. mapFolding/_e/_semiotics.py +363 -0
  170. mapFolding/_e/_theTypes.py +31 -0
  171. mapFolding/_e/algorithms/__init__.py +1 -0
  172. mapFolding/_e/algorithms/constraintPropagation.py +158 -0
  173. mapFolding/_e/algorithms/elimination.py +118 -0
  174. mapFolding/_e/algorithms/eliminationCrease.py +66 -0
  175. mapFolding/_e/algorithms/iff.py +584 -0
  176. mapFolding/_e/basecamp.py +89 -0
  177. mapFolding/_e/dataBaskets.py +123 -0
  178. mapFolding/_e/dataRaw/__init__.py +0 -0
  179. mapFolding/_e/easyRun/__init__.py +0 -0
  180. mapFolding/_e/easyRun/eliminateFolds.py +72 -0
  181. mapFolding/_e/easyRun/pinning.py +62 -0
  182. mapFolding/_e/filters.py +384 -0
  183. mapFolding/_e/pin2/344/270/212nDimensions.py +882 -0
  184. mapFolding/_e/pin2/344/270/212nDimensionsAnnex.py +551 -0
  185. mapFolding/_e/pin2/344/270/212nDimensionsByCrease.py +190 -0
  186. mapFolding/_e/pin2/344/270/212nDimensionsByDomain.py +459 -0
  187. mapFolding/_e/pinIt.py +436 -0
  188. mapFolding/_semiotics.py +42 -0
  189. mapFolding/_theSSOT.py +11 -56
  190. mapFolding/_theTypes.py +52 -68
  191. mapFolding/algorithms/A086345.py +8 -3
  192. mapFolding/algorithms/__init__.py +1 -1
  193. mapFolding/algorithms/matrixMeandersNumPyndas.py +18 -18
  194. mapFolding/algorithms/oeisIDbyFormula.py +4 -4
  195. mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +3 -3
  196. mapFolding/basecamp.py +13 -28
  197. mapFolding/beDRY.py +108 -99
  198. mapFolding/filesystemToolkit.py +15 -11
  199. mapFolding/oeis.py +17 -16
  200. mapFolding/reference/matrixMeandersAnalysis/prefixNotationNotes.py +2 -2
  201. mapFolding/reference/meandersDumpingGround/matrixMeandersBaselineV2.py +0 -1
  202. mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +8 -10
  203. mapFolding/someAssemblyRequired/RecipeJob.py +5 -5
  204. mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +5 -2
  205. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +9 -11
  206. mapFolding/someAssemblyRequired/mapFoldingModules/makeMapFoldingModules.py +2 -1
  207. mapFolding/someAssemblyRequired/transformationTools.py +2 -2
  208. mapFolding/tests/Z0Z_test_e_excluder.py +155 -0
  209. mapFolding/tests/conftest.py +193 -314
  210. mapFolding/tests/dataSamples/A001417.py +455 -0
  211. mapFolding/tests/dataSamples/__init__.py +1 -0
  212. mapFolding/tests/dataSamples/measurementData.py +1818 -0
  213. mapFolding/tests/dataSamples/p2DnDomain3_2_/351/246/226/344/270/200_/351/246/226/351/233/266/344/270/200.py +17 -0
  214. mapFolding/tests/dataSamples/p2DnDomain3_/351/246/226/344/270/200.py +17 -0
  215. mapFolding/tests/dataSamples/p2DnDomain5_4.py +17 -0
  216. mapFolding/tests/dataSamples/p2DnDomain6_5.py +17 -0
  217. mapFolding/tests/dataSamples/p2DnDomain6_7_5_4.py +17 -0
  218. mapFolding/tests/dataSamples/p2DnDomain7_6.py +17 -0
  219. 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
  220. 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
  221. 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
  222. mapFolding/tests/dataSamples/p2DnDomain/351/246/226/351/233/266/344/272/214_/351/246/226/344/272/214.py +15 -0
  223. mapFolding/tests/dataSamples/semioticsData.py +135 -0
  224. mapFolding/tests/test_computations.py +133 -88
  225. mapFolding/tests/test_e_computations.py +42 -0
  226. mapFolding/tests/test_e_dataDynamic.py +189 -0
  227. mapFolding/tests/test_e_measurements.py +257 -0
  228. mapFolding/tests/test_e_pinning.py +61 -0
  229. mapFolding/tests/test_e_semiotics.py +128 -0
  230. mapFolding/tests/test_filesystem.py +39 -17
  231. mapFolding/tests/{test_other.py → test_parameterValidation.py} +3 -3
  232. mapFolding/tests/{test_tasks.py → test_taskDivisions.py} +42 -23
  233. mapFolding/zCuzDocStoopid/makeDocstrings.py +3 -2
  234. {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/METADATA +15 -9
  235. mapfolding-0.18.0.dist-info/RECORD +305 -0
  236. {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/WHEEL +1 -1
  237. easyRun/A000682.py +0 -25
  238. easyRun/A005316.py +0 -20
  239. mapFolding/algorithms/A000136constraintPropagation.py +0 -95
  240. mapFolding/algorithms/A000136elimination.py +0 -163
  241. mapFolding/algorithms/A000136eliminationParallel.py +0 -77
  242. mapfolding-0.17.0.dist-info/RECORD +0 -107
  243. {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/entry_points.txt +0 -0
  244. {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/licenses/LICENSE +0 -0
  245. {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,162 @@
1
+ # ruff: noqa: T201
2
+ """Analyze entropy of leaves in folding sequences to understand their distributional properties."""
3
+ from hunterMakesPy import raiseIfNone
4
+ from mapFolding._e import dimensionNearestTail, getLeafDomain, pileOrigin, 零
5
+ from mapFolding._e._dataDynamic import getDataFrameFoldings
6
+ from mapFolding._e.dataBaskets import EliminationState
7
+ from typing import Any, TYPE_CHECKING
8
+ import numpy
9
+ import pandas
10
+
11
+ if TYPE_CHECKING:
12
+ from pandas import DataFrame, Series
13
+
14
+ def measureEntropy(state: EliminationState, listLeavesAnalyzed: list[int] | None = None) -> pandas.DataFrame:
15
+ """Measure the relative entropy and distributional properties of leaves across folding sequences.
16
+
17
+ This function analyzes how leaves are distributed across their mathematical domains by comparing
18
+ empirical distributions from actual folding sequences against uniform distributions. The analysis
19
+ uses Shannon entropy normalized by maximum possible entropy to produce comparable measures across
20
+ leaves with different domain sizes.
21
+
22
+ Parameters
23
+ ----------
24
+ state : EliminationState
25
+ The elimination state containing the map shape and dimension information.
26
+ listLeavesAnalyzed : list[int] | None = None
27
+ Specific leaves to analyze. If None, analyzes all leaves except the trivial ones
28
+ (0, 1, and leavesTotal-1) which always occupy the same pile.
29
+
30
+ Returns
31
+ -------
32
+ dataframeEntropy : pandas.DataFrame
33
+ DataFrame with columns:
34
+ - 'leaf': The leaf value being analyzed
35
+ - 'domainSize': Number of possible piles where this leaf can appear
36
+ - 'entropyActual': Shannon entropy of the empirical distribution
37
+ - 'entropyMaximum': Maximum possible entropy (uniform distribution)
38
+ - 'entropyRelative': entropyActual / entropyMaximum (0 to 1)
39
+ - 'concentrationMaximum': Maximum frequency / mean frequency
40
+ - 'bitPattern': Binary representation for easy identification of patterns
41
+ - 'bitCount': Number of 1s in binary representation
42
+ - 'trailingZeros': Number of trailing zeros (power of 2 factor)
43
+ Sorted by entropyRelative descending to show most uniform distributions first.
44
+
45
+ Notes
46
+ -----
47
+ The relative entropy metric allows fair comparison between leaves with vastly different domain
48
+ sizes. A value near 1.0 indicates nearly uniform distribution (high entropy, unpredictable),
49
+ while values near 0.0 indicate highly concentrated distribution (low entropy, predictable).
50
+
51
+ The concentration metric shows how peaked the distribution is by comparing the most frequent
52
+ position to the mean frequency. Higher values indicate more predictable placement.
53
+
54
+ """
55
+ dataframeFoldings: pandas.DataFrame = raiseIfNone(getDataFrameFoldings(state))
56
+
57
+ if listLeavesAnalyzed is None:
58
+ leavesExcluded: set[int] = {pileOrigin, 零, state.leavesTotal - 零}
59
+ listLeavesAnalyzed = [leaf for leaf in range(state.leavesTotal) if leaf not in leavesExcluded]
60
+
61
+ listEntropyRecords: list[dict[str, Any]] = []
62
+
63
+ for leaf in listLeavesAnalyzed:
64
+ domainLeaf: range = getLeafDomain(state, leaf)
65
+ domainSize: int = len(domainLeaf)
66
+
67
+ if domainSize == 0:
68
+ continue
69
+
70
+ dataframeMelted: pandas.DataFrame = dataframeFoldings[dataframeFoldings == leaf].melt(ignore_index=False)
71
+ dataframeMelted = dataframeMelted.dropna()
72
+ if dataframeMelted.empty:
73
+ continue
74
+
75
+ arrayPileCounts: numpy.ndarray = numpy.bincount(dataframeMelted['variable'].astype(int), minlength=state.leavesTotal)
76
+ arrayPileCountsInDomain: numpy.ndarray = arrayPileCounts[list(domainLeaf)]
77
+ arrayFrequencies: numpy.ndarray = arrayPileCountsInDomain / arrayPileCountsInDomain.sum()
78
+
79
+ maskNonzero: numpy.ndarray = arrayFrequencies > 0
80
+ entropyActual: float = float(-numpy.sum(arrayFrequencies[maskNonzero] * numpy.log2(arrayFrequencies[maskNonzero])))
81
+ entropyMaximum: float = float(numpy.log2(domainSize))
82
+ entropyRelative: float = entropyActual / entropyMaximum if entropyMaximum > 0 else 0.0
83
+
84
+ frequencyMaximum: float = float(arrayFrequencies.max())
85
+ frequencyMean: float = 1.0 / domainSize
86
+ concentrationMaximum: float = frequencyMaximum / frequencyMean if frequencyMean > 0 else 0.0
87
+
88
+ listEntropyRecords.append({
89
+ 'leaf': leaf,
90
+ 'domainSize': domainSize,
91
+ 'entropyActual': entropyActual,
92
+ 'entropyMaximum': entropyMaximum,
93
+ 'entropyRelative': entropyRelative,
94
+ 'concentrationMaximum': concentrationMaximum,
95
+ 'bitPattern': leaf.__format__('06b'),
96
+ 'bitCount': leaf.bit_count(),
97
+ 'trailingZeros': dimensionNearestTail(leaf),
98
+ })
99
+
100
+ return pandas.DataFrame(listEntropyRecords).sort_values('entropyRelative', ascending=False).reset_index(drop=True)
101
+
102
+ def analyzeEntropyForDimension(dimensionsTotal: int = 6) -> None:
103
+ """Analyze entropy for all non-trivial leaves in a given dimension configuration."""
104
+ mapShape: tuple[int, ...] = (2,) * dimensionsTotal
105
+ state: EliminationState = EliminationState(mapShape)
106
+
107
+ print(f"\n{'=' * 80}")
108
+ print(f"Entropy Analysis for 2^{dimensionsTotal} (mapShape={mapShape})")
109
+ print(f"{'=' * 80}\n")
110
+
111
+ dataframeEntropy = measureEntropy(state)
112
+
113
+ print("\nTop 20 leaves by relative entropy (most uniform distributions):")
114
+ print(dataframeEntropy.head(20).to_string(index=False))
115
+
116
+ print("\n\nBottom 20 leaves by relative entropy (most concentrated distributions):")
117
+ print(dataframeEntropy.tail(20).to_string(index=False))
118
+
119
+ leaf63: int = 63
120
+ if leaf63 in dataframeEntropy['leaf'].to_numpy():
121
+ row63: Series = dataframeEntropy[dataframeEntropy['leaf'] == leaf63].iloc[0]
122
+ rankOf63: int = int(dataframeEntropy[dataframeEntropy['leaf'] == leaf63].index[0])
123
+ totalLeaves: int = len(dataframeEntropy)
124
+
125
+ print(f"\n\n{'=' * 80}")
126
+ print(f"Analysis of Leaf 63 ({bin(leaf63)} = 2^6 - 1, all dimensions have value 1)")
127
+ print(f"{'=' * 80}")
128
+ print(f"Rank: {rankOf63 + 1} / {totalLeaves}")
129
+ print(f"Domain Size: {row63['domainSize']}")
130
+ print(f"Entropy (actual): {row63['entropyActual']:.4f}")
131
+ print(f"Entropy (maximum): {row63['entropyMaximum']:.4f}")
132
+ print(f"Relative Entropy: {row63['entropyRelative']:.4f} (1.0 = uniform, 0.0 = concentrated)")
133
+ print(f"Concentration: {row63['concentrationMaximum']:.4f}x mean frequency")
134
+ print(f"Bit Count: {row63['bitCount']}")
135
+ print(f"Trailing Zeros: {row63['trailingZeros']}")
136
+
137
+ print("\n\nComparing leaf 63 to leaves with similar properties:")
138
+
139
+ bitCount: int = int(row63['bitCount'])
140
+ leavesWithSameBitCount: DataFrame = dataframeEntropy[dataframeEntropy['bitCount'] == bitCount]
141
+ print(f"\nLeaves with same bit_count ({bitCount}):")
142
+ subsetBitCount: DataFrame = leavesWithSameBitCount[['leaf', 'bitPattern', 'entropyRelative', 'concentrationMaximum']]
143
+ print(subsetBitCount.head(10).to_string(index=False))
144
+
145
+ trailingZeros: int = int(row63['trailingZeros'])
146
+ leavesWithSameTrailingZeros: DataFrame = dataframeEntropy[dataframeEntropy['trailingZeros'] == trailingZeros]
147
+ print(f"\nLeaves with same trailing zeros ({trailingZeros}):")
148
+ subsetTrailing: DataFrame = leavesWithSameTrailingZeros[['leaf', 'bitPattern', 'entropyRelative', 'concentrationMaximum']]
149
+ print(subsetTrailing.head(10).to_string(index=False))
150
+
151
+ powersOf2: DataFrame = dataframeEntropy[dataframeEntropy['bitCount'] == 1]
152
+ print("\nPowers of 2 (bitCount == 1):")
153
+ subsetPowers: DataFrame = powersOf2[['leaf', 'bitPattern', 'entropyRelative', 'concentrationMaximum']]
154
+ print(subsetPowers.to_string(index=False))
155
+
156
+ print(f"\n{'=' * 80}")
157
+ print("Summary Statistics")
158
+ print(f"{'=' * 80}")
159
+ print(dataframeEntropy[['entropyRelative', 'concentrationMaximum']].describe())
160
+
161
+ if __name__ == '__main__':
162
+ analyzeEntropyForDimension(6)
@@ -0,0 +1,403 @@
1
+ # ruff: noqa: ERA001 T201 T203 # noqa: RUF100
2
+ # 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.
3
+ from gmpy2 import bit_mask
4
+ from hunterMakesPy import raiseIfNone
5
+ from mapFolding import ansiColorReset, ansiColors
6
+ from mapFolding._e import (
7
+ dimensionNearestTail, dimensionNearest首, getDictionaryConditionalLeafPredecessors,
8
+ getDictionaryConditionalLeafSuccessors, getLeafDomain, howManyDimensionsHaveOddParity, Leaf, Pile, pileOrigin, 零)
9
+ from mapFolding._e._dataDynamic import getDataFrameFoldings
10
+ from mapFolding._e.dataBaskets import EliminationState
11
+ from pprint import pprint
12
+ from typing import Any
13
+ import numpy
14
+ import pandas
15
+
16
+ def getLeafUnconditionalPrecedence(state: EliminationState) -> pandas.DataFrame:
17
+ """Identify leaves that always precede other leaves across all folding sequences.
18
+
19
+ (AI generated docstring)
20
+
21
+ Analyzes all valid folding sequences for a given elimination state to find pairs
22
+ of leaves (Earlier, Later) where the Earlier leaf appears at a smaller column
23
+ index than the Later leaf in every single folding sequence without exception.
24
+
25
+ The analysis proceeds as follows.
26
+ 1. Load sequence data where each row is a folding and columns represent positions.
27
+ 2. Build a positions matrix mapping each leaf value to its column index per row.
28
+ 3. Construct a comparison cube testing whether each leaf precedes every other leaf.
29
+ 4. Reduce across all rows to find pairs where precedence holds universally.
30
+
31
+ Parameters
32
+ ----------
33
+ state : EliminationState
34
+ The elimination state containing the map shape and dimension information.
35
+
36
+ Returns
37
+ -------
38
+ dataframePrecedence : pandas.DataFrame
39
+ A two-column DataFrame with 'Earlier' and 'Later' indicating leaf values
40
+ where the Earlier leaf unconditionally precedes the Later leaf.
41
+
42
+ """
43
+ dataframeSequences: pandas.DataFrame = raiseIfNone(getDataFrameFoldings(state))
44
+ arraySequences: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = dataframeSequences.to_numpy(dtype=numpy.int16)
45
+
46
+ rowsCount: int
47
+ positionsCount: int
48
+ rowsCount, positionsCount = arraySequences.shape
49
+ valueMaximum: int = int(arraySequences.max())
50
+ positionsMatrix: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.full((rowsCount, valueMaximum + 1), -1, dtype=numpy.int16)
51
+
52
+ rowIndices: numpy.ndarray[Any, numpy.dtype[numpy.int32]] = numpy.arange(rowsCount, dtype=numpy.int32)[:, None]
53
+ columnIndices: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.broadcast_to(numpy.arange(positionsCount, dtype=numpy.int16), (rowsCount, positionsCount))
54
+ positionsMatrix[rowIndices, arraySequences] = columnIndices
55
+
56
+ valuesPresentEveryRow: numpy.ndarray[Any, numpy.dtype[numpy.intp]] = numpy.where((positionsMatrix >= 0).all(axis=0))[0]
57
+ positionsAnalyzed: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = positionsMatrix[:, valuesPresentEveryRow]
58
+
59
+ comparisonCube: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] = positionsAnalyzed[:, :, None] < positionsAnalyzed[:, None, :]
60
+ alwaysEarlierMatrix: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] = comparisonCube.all(axis=0) # pyright: ignore[reportAssignmentType]
61
+ numpy.fill_diagonal(alwaysEarlierMatrix, val=False)
62
+
63
+ indicesEarlier: numpy.ndarray[Any, numpy.dtype[numpy.intp]]
64
+ indicesLater: numpy.ndarray[Any, numpy.dtype[numpy.intp]]
65
+ indicesEarlier, indicesLater = numpy.where(alwaysEarlierMatrix)
66
+ dataframePrecedence: pandas.DataFrame = pandas.DataFrame(
67
+ {
68
+ 'Earlier': valuesPresentEveryRow[indicesEarlier],
69
+ 'Later': valuesPresentEveryRow[indicesLater],
70
+ }
71
+ ).sort_values(['Earlier', 'Later']).reset_index(drop=True)
72
+
73
+ return dataframePrecedence
74
+
75
+ def getLeafConditionalPrecedence(state: EliminationState) -> pandas.DataFrame:
76
+ """Identify precedence relationships that emerge only when a leaf is at its earliest column.
77
+
78
+ (AI generated docstring)
79
+
80
+ For each leaf, determines the earliest possible column it can occupy based on
81
+ bit structure properties (`bit_count` and `howMany0coordinatesAtTail`). Then
82
+ finds leaves that always precede it in the subset of foldings where that leaf
83
+ is at its earliest column. Excludes relationships already captured by the
84
+ unconditional precedence analysis.
85
+
86
+ The formula for the earliest column of a leaf is.
87
+ columnEarliest = leaf.bit_count() + (2^(howMany0coordinatesAtTail(leaf) + 1) - 2)
88
+
89
+ Parameters
90
+ ----------
91
+ state : EliminationState
92
+ The elimination state containing the map shape and dimension information.
93
+ columnsToExclude : list[int] | None = None
94
+ Column indices (as integers) to exclude from analysis. Pass [0, 1, leavesTotal-1]
95
+ to exclude the trivially-pinned positions.
96
+
97
+ Returns
98
+ -------
99
+ dataframeConditionalPrecedence : pandas.DataFrame
100
+ A three-column DataFrame with 'Earlier', 'Later', and 'AtColumn' indicating
101
+ that when 'Later' is at column 'AtColumn', 'Earlier' always precedes it.
102
+ Only includes relationships not already present in unconditional precedence.
103
+
104
+ """
105
+ dataframeSequences: pandas.DataFrame = raiseIfNone(getDataFrameFoldings(state))
106
+ columnsToExclude: list[int] | None = [pileOrigin, 零, state.pileLast]
107
+ if columnsToExclude is not None: # pyright: ignore[reportUnnecessaryComparison]
108
+ dataframeSequences = dataframeSequences.drop(columns=columnsToExclude)
109
+ arraySequences: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = dataframeSequences.to_numpy(dtype=numpy.int16)
110
+
111
+ rowsCount: int
112
+ positionsCount: int
113
+ rowsCount, positionsCount = arraySequences.shape
114
+ valueMaximum: int = int(arraySequences.max())
115
+ positionsMatrix: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.full((rowsCount, valueMaximum + 1), -1, dtype=numpy.int16)
116
+
117
+ rowIndices: numpy.ndarray[Any, numpy.dtype[numpy.int32]] = numpy.arange(rowsCount, dtype=numpy.int32)[:, None]
118
+ columnIndices: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.broadcast_to(numpy.arange(positionsCount, dtype=numpy.int16), (rowsCount, positionsCount))
119
+ positionsMatrix[rowIndices, arraySequences] = columnIndices
120
+
121
+ columnOffset: int = 2 if columnsToExclude is not None and 0 in columnsToExclude and 1 in columnsToExclude else 0 # pyright: ignore[reportUnnecessaryComparison]
122
+
123
+ dataframeUnconditional: pandas.DataFrame = getLeafUnconditionalPrecedence(state)
124
+ setUnconditional: set[tuple[Any, Any]] = set(zip(dataframeUnconditional['Earlier'], dataframeUnconditional['Later'], strict=True))
125
+
126
+ listConditionalRelationships: list[dict[str, int]] = []
127
+
128
+ for leafLater in range(state.leavesTotal):
129
+ columnEarliestOriginal: int = leafLater.bit_count() + (2 ** (dimensionNearestTail(leafLater) + 1) - 2)
130
+ columnEarliestIndex: int = columnEarliestOriginal - columnOffset
131
+
132
+ if columnEarliestIndex < 0:
133
+ continue
134
+
135
+ maskRowsAtEarliestColumn: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] = (positionsMatrix[:, leafLater] == columnEarliestIndex)
136
+
137
+ if not numpy.any(maskRowsAtEarliestColumn):
138
+ continue
139
+
140
+ positionsSubset: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = positionsMatrix[maskRowsAtEarliestColumn]
141
+
142
+ for leafEarlier in range(state.leavesTotal):
143
+ if leafEarlier == leafLater:
144
+ continue
145
+
146
+ positionsOfEarlier: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = positionsSubset[:, leafEarlier]
147
+
148
+ isEarlierAlwaysPresentAndPrecedes: bool = bool(numpy.all((positionsOfEarlier >= 0) & (positionsOfEarlier < columnEarliestIndex)))
149
+ if isEarlierAlwaysPresentAndPrecedes and (leafEarlier, leafLater) not in setUnconditional:
150
+ listConditionalRelationships.append({
151
+ 'Earlier': leafEarlier,
152
+ 'Later': leafLater,
153
+ 'AtColumn': columnEarliestOriginal
154
+ })
155
+
156
+ dataframeConditionalPrecedence: pandas.DataFrame = pandas.DataFrame(listConditionalRelationships).sort_values(['Later', 'Earlier']).reset_index(drop=True)
157
+
158
+ return dataframeConditionalPrecedence
159
+
160
+ def getLeafConditionalPrecedenceAtLastPileOfLeafDomain(state: EliminationState) -> pandas.DataFrame:
161
+ """Identify precedence relationships that emerge only when a leaf is at the last pile in its domain.
162
+
163
+ (AI generated docstring)
164
+
165
+ For each leaf, determines the last pile it can occupy within its mathematical
166
+ domain, then finds leaves that always precede it in the subset of foldings
167
+ where that leaf is observed at that last-in-domain pile. Excludes relationships
168
+ already captured by the unconditional precedence analysis.
169
+
170
+ The formula for the last pile *in* the domain of a leaf is.
171
+ pileLastOfLeaf = int(bit_mask(dimensionsTotal) ^ bit_mask(dimensionsTotal - dimensionNearest首(leaf))) - howManyDimensionsHaveOddParity(leaf) + 1
172
+
173
+ Parameters
174
+ ----------
175
+ state : EliminationState
176
+ The elimination state containing the map shape and dimension information.
177
+ columnsToExclude : list[int] | None = None
178
+ Column indices (as integers) to exclude from analysis. Pass [0, 1, leavesTotal-1]
179
+ to exclude the trivially-pinned positions.
180
+
181
+ Returns
182
+ -------
183
+ dataframeConditionalPrecedenceAtLastPile : pandas.DataFrame
184
+ A three-column DataFrame with 'Earlier', 'Later', and 'AtColumn' indicating
185
+ that when 'Later' is at column 'AtColumn' (its last-in-domain pile),
186
+ 'Earlier' always precedes it. Only includes relationships not already
187
+ present in unconditional precedence.
188
+
189
+ """
190
+ dataframeSequences: pandas.DataFrame = raiseIfNone(getDataFrameFoldings(state))
191
+ columnsToExclude: list[int] | None = [pileOrigin, 零, state.pileLast]
192
+ if columnsToExclude is not None: # pyright: ignore[reportUnnecessaryComparison]
193
+ dataframeSequences = dataframeSequences.drop(columns=columnsToExclude)
194
+ arraySequences: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = dataframeSequences.to_numpy(dtype=numpy.int16)
195
+
196
+ rowsCount: int
197
+ positionsCount: int
198
+ rowsCount, positionsCount = arraySequences.shape
199
+ valueMaximum: int = int(arraySequences.max())
200
+ positionsMatrix: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.full((rowsCount, valueMaximum + 1), -1, dtype=numpy.int16)
201
+
202
+ rowIndices: numpy.ndarray[Any, numpy.dtype[numpy.int32]] = numpy.arange(rowsCount, dtype=numpy.int32)[:, None]
203
+ columnIndices: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.broadcast_to(numpy.arange(positionsCount, dtype=numpy.int16), (rowsCount, positionsCount))
204
+ positionsMatrix[rowIndices, arraySequences] = columnIndices
205
+
206
+ columnOffset: int = 2 if columnsToExclude is not None and 0 in columnsToExclude and 1 in columnsToExclude else 0 # pyright: ignore[reportUnnecessaryComparison]
207
+
208
+ dataframeUnconditional: pandas.DataFrame = getLeafUnconditionalPrecedence(state)
209
+ setUnconditional: set[tuple[Any, Any]] = set(zip(dataframeUnconditional['Earlier'], dataframeUnconditional['Later'], strict=True))
210
+
211
+ listConditionalRelationships: list[dict[str, int]] = []
212
+
213
+ for leafLater in range(state.leavesTotal):
214
+ pileLastOfLeafOriginal: int = int(bit_mask(state.dimensionsTotal) ^ bit_mask(state.dimensionsTotal - dimensionNearest首(leafLater))) - howManyDimensionsHaveOddParity(leafLater) + 1
215
+ pileLastOfLeafIndex: int = pileLastOfLeafOriginal - columnOffset
216
+
217
+ if pileLastOfLeafIndex < 0:
218
+ continue
219
+
220
+ maskRowsAtLastPileOfLeaf: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] = (positionsMatrix[:, leafLater] == pileLastOfLeafIndex)
221
+
222
+ if not numpy.any(maskRowsAtLastPileOfLeaf):
223
+ continue
224
+
225
+ positionsSubset: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = positionsMatrix[maskRowsAtLastPileOfLeaf]
226
+
227
+ for leafEarlier in range(state.leavesTotal):
228
+ if leafEarlier == leafLater:
229
+ continue
230
+
231
+ positionsOfEarlier: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = positionsSubset[:, leafEarlier]
232
+
233
+ isEarlierAlwaysPresentAndPrecedes: bool = bool(numpy.all((positionsOfEarlier >= 0) & (positionsOfEarlier < pileLastOfLeafIndex)))
234
+ if isEarlierAlwaysPresentAndPrecedes and (leafEarlier, leafLater) not in setUnconditional:
235
+ listConditionalRelationships.append({
236
+ 'Earlier': leafEarlier,
237
+ 'Later': leafLater,
238
+ 'AtColumn': pileLastOfLeafOriginal
239
+ })
240
+
241
+ dataframeConditionalPrecedenceAtLastPile: pandas.DataFrame = pandas.DataFrame(listConditionalRelationships).sort_values(['Later', 'Earlier']).reset_index(drop=True)
242
+
243
+ return dataframeConditionalPrecedenceAtLastPile
244
+
245
+ def getLeafConditionalSuccession(state: EliminationState) -> pandas.DataFrame:
246
+ """When a leaf is at the last pile in its domain, identify leaves that must come after it."""
247
+ dataframeSequences: pandas.DataFrame = raiseIfNone(getDataFrameFoldings(state))
248
+ columnsToExclude: list[int] | None = [pileOrigin, 零, state.pileLast]
249
+ if columnsToExclude is not None: # pyright: ignore[reportUnnecessaryComparison]
250
+ dataframeSequences = dataframeSequences.drop(columns=columnsToExclude)
251
+ arraySequences: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = dataframeSequences.to_numpy(dtype=numpy.int16)
252
+
253
+ rowsCount: int
254
+ positionsCount: int
255
+ rowsCount, positionsCount = arraySequences.shape
256
+ valueMaximum: int = int(arraySequences.max())
257
+ positionsMatrix: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.full((rowsCount, valueMaximum + 1), -1, dtype=numpy.int16)
258
+
259
+ rowIndices: numpy.ndarray[Any, numpy.dtype[numpy.int32]] = numpy.arange(rowsCount, dtype=numpy.int32)[:, None]
260
+ columnIndices: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.broadcast_to(numpy.arange(positionsCount, dtype=numpy.int16), (rowsCount, positionsCount))
261
+ positionsMatrix[rowIndices, arraySequences] = columnIndices
262
+
263
+ columnOffset: int = 2 if columnsToExclude is not None and 0 in columnsToExclude and 1 in columnsToExclude else 0 # pyright: ignore[reportUnnecessaryComparison]
264
+
265
+ dataframeUnconditional: pandas.DataFrame = getLeafUnconditionalPrecedence(state)
266
+ setUnconditional: set[tuple[Any, Any]] = set(zip(dataframeUnconditional['Earlier'], dataframeUnconditional['Later'], strict=True))
267
+
268
+ listConditionalRelationships: list[dict[str, int]] = []
269
+
270
+ for leafEarlier in range(state.leavesTotal):
271
+ pileLastOfLeafOriginal: int = int(bit_mask(state.dimensionsTotal) ^ bit_mask(state.dimensionsTotal - dimensionNearest首(leafEarlier))) - howManyDimensionsHaveOddParity(leafEarlier) + 1
272
+ pileLastOfLeafIndex: int = pileLastOfLeafOriginal - columnOffset
273
+
274
+ if pileLastOfLeafIndex < 0:
275
+ continue
276
+
277
+ maskRowsAtLastPileOfLeaf: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] = (positionsMatrix[:, leafEarlier] == pileLastOfLeafIndex)
278
+
279
+ if not numpy.any(maskRowsAtLastPileOfLeaf):
280
+ continue
281
+
282
+ positionsSubset: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = positionsMatrix[maskRowsAtLastPileOfLeaf]
283
+
284
+ for leafLater in range(state.leavesTotal):
285
+ if leafLater == leafEarlier:
286
+ continue
287
+
288
+ positionsOfLater: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = positionsSubset[:, leafLater]
289
+ isLaterAlwaysPresentAndFollows: bool = bool(numpy.all((positionsOfLater >= 0) & (pileLastOfLeafIndex < positionsOfLater)))
290
+ if isLaterAlwaysPresentAndFollows and (leafEarlier, leafLater) not in setUnconditional:
291
+ listConditionalRelationships.append({
292
+ 'Earlier': leafEarlier,
293
+ 'Later': leafLater,
294
+ 'AtColumn': pileLastOfLeafOriginal,
295
+ })
296
+
297
+ dataframeConditionalSuccession: pandas.DataFrame = pandas.DataFrame(listConditionalRelationships, columns=['Earlier', 'Later', 'AtColumn']).sort_values(['Earlier', 'Later']).reset_index(drop=True)
298
+
299
+ return dataframeConditionalSuccession
300
+
301
+ def getLeafConditionalPrecedenceAcrossLeafDomain(state: EliminationState, leafLater: Leaf) -> pandas.DataFrame:
302
+ dataframeSequences: pandas.DataFrame = raiseIfNone(getDataFrameFoldings(state))
303
+ columnsToExclude: list[Pile] | None = [pileOrigin, 零, state.pileLast]
304
+ if columnsToExclude is not None: # pyright: ignore[reportUnnecessaryComparison]
305
+ dataframeSequences = dataframeSequences.drop(columns=columnsToExclude)
306
+ arraySequences: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = dataframeSequences.to_numpy(dtype=numpy.int16)
307
+
308
+ rowsCount: int
309
+ positionsCount: int
310
+ rowsCount, positionsCount = arraySequences.shape
311
+ valueMaximum: int = int(arraySequences.max())
312
+ positionsMatrix: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.full((rowsCount, valueMaximum + 1), -1, dtype=numpy.int16)
313
+
314
+ rowIndices: numpy.ndarray[Any, numpy.dtype[numpy.int32]] = numpy.arange(rowsCount, dtype=numpy.int32)[:, None]
315
+ columnIndices: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = numpy.broadcast_to(numpy.arange(positionsCount, dtype=numpy.int16), (rowsCount, positionsCount))
316
+ positionsMatrix[rowIndices, arraySequences] = columnIndices
317
+
318
+ columnOffset: int = 2 if columnsToExclude is not None and 0 in columnsToExclude and 1 in columnsToExclude else 0 # pyright: ignore[reportUnnecessaryComparison]
319
+
320
+ dataframeUnconditional: pandas.DataFrame = getLeafUnconditionalPrecedence(state)
321
+ setUnconditional: set[tuple[Any, Any]] = set(zip(dataframeUnconditional['Earlier'], dataframeUnconditional['Later'], strict=True))
322
+
323
+ leafDomain: range = getLeafDomain(state, leafLater)
324
+
325
+ listConditionalRelationships: list[dict[str, int]] = []
326
+ for pileOfLeafOriginal in leafDomain:
327
+ if pileOfLeafOriginal <= 1:
328
+ continue
329
+ if pileOfLeafOriginal >= state.pileLast:
330
+ continue
331
+
332
+ pileOfLeafIndex: int = pileOfLeafOriginal - columnOffset
333
+ if pileOfLeafIndex < 0:
334
+ continue
335
+
336
+ maskRowsAtPileOfLeaf: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] = (positionsMatrix[:, leafLater] == pileOfLeafIndex)
337
+ if not numpy.any(maskRowsAtPileOfLeaf):
338
+ continue
339
+
340
+ positionsSubset: numpy.ndarray[Any, numpy.dtype[numpy.int16]] = positionsMatrix[maskRowsAtPileOfLeaf]
341
+ maskAlwaysEarlier: numpy.ndarray[Any, numpy.dtype[numpy.bool_]] = numpy.all((positionsSubset >= 0) & (positionsSubset < pileOfLeafIndex), axis=0)
342
+ maskAlwaysEarlier[leafLater] = False
343
+ indicesEarlier: numpy.ndarray[Any, numpy.dtype[numpy.intp]] = numpy.flatnonzero(maskAlwaysEarlier)
344
+
345
+ for leafEarlierCandidate in indicesEarlier.tolist():
346
+ leafEarlier: Leaf = int(leafEarlierCandidate)
347
+ if (leafEarlier, leafLater) in setUnconditional:
348
+ continue
349
+ listConditionalRelationships.append({
350
+ 'Earlier': leafEarlier,
351
+ 'Later': leafLater,
352
+ 'AtColumn': pileOfLeafOriginal,
353
+ })
354
+
355
+ dataframeConditionalPrecedenceAcrossDomain: pandas.DataFrame = pandas.DataFrame(listConditionalRelationships, columns=['Earlier', 'Later', 'AtColumn']).sort_values(['AtColumn', 'Earlier']).reset_index(drop=True)
356
+ return dataframeConditionalPrecedenceAcrossDomain
357
+
358
+ def getLeafConditionalPrecedenceAcrossLeafDomainPileGroups(state: EliminationState, leafLater: Leaf) -> list[list[Pile]]:
359
+ dataframeConditional: pandas.DataFrame = getLeafConditionalPrecedenceAcrossLeafDomain(state, leafLater)
360
+ pilesSortedUnique: list[Pile]
361
+ if dataframeConditional.empty:
362
+ pilesSortedUnique = []
363
+ else:
364
+ pilesSortedUnique = sorted({int(pile) for pile in dataframeConditional['AtColumn'].tolist()})
365
+
366
+ listPileGroups: list[list[Pile]] = []
367
+ for pile in pilesSortedUnique:
368
+ if not listPileGroups:
369
+ listPileGroups.append([pile])
370
+ elif pile == listPileGroups[-1][-1] + 2:
371
+ listPileGroups[-1].append(pile)
372
+ else:
373
+ listPileGroups.append([pile])
374
+ return listPileGroups
375
+
376
+ def getLeafPilesAtDomainEndFromConditionalPrecedenceAcrossLeafDomain(state: EliminationState, leaf: Leaf) -> list[Pile]:
377
+ listPileGroups: list[list[Pile]] = getLeafConditionalPrecedenceAcrossLeafDomainPileGroups(state, leaf)
378
+ listPilesAtEnd: list[Pile] = []
379
+ if listPileGroups:
380
+ listPilesAtEnd = listPileGroups[-1]
381
+ return listPilesAtEnd
382
+
383
+ def getDictionaryPilesAtDomainEndsFromConditionalPrecedenceAcrossLeafDomain(state: EliminationState, listLeavesAnalyzed: list[Leaf] | None = None) -> dict[Leaf, list[Pile]]:
384
+ if listLeavesAnalyzed is None:
385
+ leavesExcluded: set[Leaf] = {pileOrigin, 零, state.leavesTotal - 零}
386
+ listLeavesAnalyzed = [leaf for leaf in range(state.leavesTotal) if leaf not in leavesExcluded]
387
+
388
+ dictionaryPilesAtDomainEnds: dict[Leaf, list[Pile]] = {}
389
+ for leaf in listLeavesAnalyzed:
390
+ listPilesAtEnd: list[Pile] = getLeafPilesAtDomainEndFromConditionalPrecedenceAcrossLeafDomain(state, leaf)
391
+ if listPilesAtEnd:
392
+ dictionaryPilesAtDomainEnds[leaf] = listPilesAtEnd
393
+ return dictionaryPilesAtDomainEnds
394
+
395
+ if __name__ == '__main__':
396
+ state = EliminationState((2,) * 6)
397
+ # leaf33 is wrong because of step = 4.
398
+ # leaf33 and leaf49 are already known from prior analysis.
399
+ dictionaryPilesAtDomainEnds = getDictionaryPilesAtDomainEndsFromConditionalPrecedenceAcrossLeafDomain(state)
400
+ print(ansiColors.BlackOnCyan + 'dictionaryPilesAtDomainEnds' + ansiColorReset)
401
+ pprint(dictionaryPilesAtDomainEnds, width=140)
402
+ pprint(getDictionaryConditionalLeafPredecessors(state), width=380, compact=True)
403
+ pprint(getDictionaryConditionalLeafSuccessors(state), width=380, compact=True)