snappy 3.3__cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.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 (541) hide show
  1. snappy/CyOpenGL.cpython-310-aarch64-linux-gnu.so +0 -0
  2. snappy/SnapPy.cpython-310-aarch64-linux-gnu.so +0 -0
  3. snappy/SnapPy.ico +0 -0
  4. snappy/SnapPy.png +0 -0
  5. snappy/SnapPyHP.cpython-310-aarch64-linux-gnu.so +0 -0
  6. snappy/__init__.py +534 -0
  7. snappy/app.py +604 -0
  8. snappy/app_menus.py +372 -0
  9. snappy/browser.py +998 -0
  10. snappy/cache.py +25 -0
  11. snappy/canonical.py +249 -0
  12. snappy/cusps/__init__.py +280 -0
  13. snappy/cusps/cusp_area_matrix.py +98 -0
  14. snappy/cusps/cusp_areas_from_matrix.py +96 -0
  15. snappy/cusps/maximal_cusp_area_matrix.py +136 -0
  16. snappy/cusps/short_slopes_for_cusp.py +217 -0
  17. snappy/cusps/test.py +22 -0
  18. snappy/cusps/trig_cusp_area_matrix.py +63 -0
  19. snappy/database.py +454 -0
  20. snappy/db_utilities.py +79 -0
  21. snappy/decorated_isosig.py +717 -0
  22. snappy/dev/__init__.py +0 -0
  23. snappy/dev/extended_ptolemy/__init__.py +8 -0
  24. snappy/dev/extended_ptolemy/closed.py +106 -0
  25. snappy/dev/extended_ptolemy/complexVolumesClosed.py +149 -0
  26. snappy/dev/extended_ptolemy/direct.py +42 -0
  27. snappy/dev/extended_ptolemy/extended.py +406 -0
  28. snappy/dev/extended_ptolemy/giac_helper.py +43 -0
  29. snappy/dev/extended_ptolemy/giac_rur.py +129 -0
  30. snappy/dev/extended_ptolemy/gluing.py +46 -0
  31. snappy/dev/extended_ptolemy/phc_wrapper.py +220 -0
  32. snappy/dev/extended_ptolemy/printMatrices.py +70 -0
  33. snappy/dev/vericlosed/__init__.py +1 -0
  34. snappy/dev/vericlosed/computeApproxHyperbolicStructureNew.py +159 -0
  35. snappy/dev/vericlosed/computeApproxHyperbolicStructureOrb.py +90 -0
  36. snappy/dev/vericlosed/computeVerifiedHyperbolicStructure.py +111 -0
  37. snappy/dev/vericlosed/gimbalLoopFinder.py +130 -0
  38. snappy/dev/vericlosed/hyperbolicStructure.py +313 -0
  39. snappy/dev/vericlosed/krawczykCertifiedEdgeLengthsEngine.py +165 -0
  40. snappy/dev/vericlosed/oneVertexTruncatedComplex.py +122 -0
  41. snappy/dev/vericlosed/orb/__init__.py +1 -0
  42. snappy/dev/vericlosed/orb/orb_solution_for_snappea_finite_triangulation_mac +0 -0
  43. snappy/dev/vericlosed/parseVertexGramMatrixFile.py +47 -0
  44. snappy/dev/vericlosed/polishApproxHyperbolicStructure.py +61 -0
  45. snappy/dev/vericlosed/test.py +54 -0
  46. snappy/dev/vericlosed/truncatedComplex.py +176 -0
  47. snappy/dev/vericlosed/verificationError.py +58 -0
  48. snappy/dev/vericlosed/verifyHyperbolicStructureEngine.py +177 -0
  49. snappy/doc/_images/SnapPy-196.png +0 -0
  50. snappy/doc/_images/m004_paper_plane_on_systole.jpg +0 -0
  51. snappy/doc/_images/m125_paper_plane.jpg +0 -0
  52. snappy/doc/_images/mac.png +0 -0
  53. snappy/doc/_images/o9_00000_systole_paper_plane.jpg +0 -0
  54. snappy/doc/_images/o9_00000_systole_paper_plane_closer.jpg +0 -0
  55. snappy/doc/_images/plink-action.png +0 -0
  56. snappy/doc/_images/ubuntu.png +0 -0
  57. snappy/doc/_images/win7.png +0 -0
  58. snappy/doc/_sources/additional_classes.rst.txt +40 -0
  59. snappy/doc/_sources/bugs.rst.txt +14 -0
  60. snappy/doc/_sources/censuses.rst.txt +52 -0
  61. snappy/doc/_sources/credits.rst.txt +81 -0
  62. snappy/doc/_sources/development.rst.txt +261 -0
  63. snappy/doc/_sources/index.rst.txt +215 -0
  64. snappy/doc/_sources/installing.rst.txt +249 -0
  65. snappy/doc/_sources/manifold.rst.txt +6 -0
  66. snappy/doc/_sources/manifoldhp.rst.txt +46 -0
  67. snappy/doc/_sources/news.rst.txt +425 -0
  68. snappy/doc/_sources/other.rst.txt +25 -0
  69. snappy/doc/_sources/platonic_census.rst.txt +20 -0
  70. snappy/doc/_sources/plink.rst.txt +102 -0
  71. snappy/doc/_sources/ptolemy.rst.txt +66 -0
  72. snappy/doc/_sources/ptolemy_classes.rst.txt +42 -0
  73. snappy/doc/_sources/ptolemy_examples1.rst.txt +298 -0
  74. snappy/doc/_sources/ptolemy_examples2.rst.txt +363 -0
  75. snappy/doc/_sources/ptolemy_examples3.rst.txt +301 -0
  76. snappy/doc/_sources/ptolemy_examples4.rst.txt +61 -0
  77. snappy/doc/_sources/ptolemy_prelim.rst.txt +105 -0
  78. snappy/doc/_sources/screenshots.rst.txt +21 -0
  79. snappy/doc/_sources/snap.rst.txt +87 -0
  80. snappy/doc/_sources/snappy.rst.txt +28 -0
  81. snappy/doc/_sources/spherogram.rst.txt +103 -0
  82. snappy/doc/_sources/todo.rst.txt +47 -0
  83. snappy/doc/_sources/triangulation.rst.txt +11 -0
  84. snappy/doc/_sources/tutorial.rst.txt +49 -0
  85. snappy/doc/_sources/verify.rst.txt +210 -0
  86. snappy/doc/_sources/verify_internals.rst.txt +79 -0
  87. snappy/doc/_static/SnapPy-horizontal-128.png +0 -0
  88. snappy/doc/_static/SnapPy.ico +0 -0
  89. snappy/doc/_static/_sphinx_javascript_frameworks_compat.js +123 -0
  90. snappy/doc/_static/basic.css +906 -0
  91. snappy/doc/_static/css/badge_only.css +1 -0
  92. snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
  93. snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
  94. snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
  95. snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
  96. snappy/doc/_static/css/fonts/fontawesome-webfont.eot +0 -0
  97. snappy/doc/_static/css/fonts/fontawesome-webfont.svg +2671 -0
  98. snappy/doc/_static/css/fonts/fontawesome-webfont.ttf +0 -0
  99. snappy/doc/_static/css/fonts/fontawesome-webfont.woff +0 -0
  100. snappy/doc/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
  101. snappy/doc/_static/css/fonts/lato-bold-italic.woff +0 -0
  102. snappy/doc/_static/css/fonts/lato-bold-italic.woff2 +0 -0
  103. snappy/doc/_static/css/fonts/lato-bold.woff +0 -0
  104. snappy/doc/_static/css/fonts/lato-bold.woff2 +0 -0
  105. snappy/doc/_static/css/fonts/lato-normal-italic.woff +0 -0
  106. snappy/doc/_static/css/fonts/lato-normal-italic.woff2 +0 -0
  107. snappy/doc/_static/css/fonts/lato-normal.woff +0 -0
  108. snappy/doc/_static/css/fonts/lato-normal.woff2 +0 -0
  109. snappy/doc/_static/css/theme.css +4 -0
  110. snappy/doc/_static/doctools.js +149 -0
  111. snappy/doc/_static/documentation_options.js +13 -0
  112. snappy/doc/_static/file.png +0 -0
  113. snappy/doc/_static/fonts/Lato/lato-bold.eot +0 -0
  114. snappy/doc/_static/fonts/Lato/lato-bold.ttf +0 -0
  115. snappy/doc/_static/fonts/Lato/lato-bold.woff +0 -0
  116. snappy/doc/_static/fonts/Lato/lato-bold.woff2 +0 -0
  117. snappy/doc/_static/fonts/Lato/lato-bolditalic.eot +0 -0
  118. snappy/doc/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
  119. snappy/doc/_static/fonts/Lato/lato-bolditalic.woff +0 -0
  120. snappy/doc/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
  121. snappy/doc/_static/fonts/Lato/lato-italic.eot +0 -0
  122. snappy/doc/_static/fonts/Lato/lato-italic.ttf +0 -0
  123. snappy/doc/_static/fonts/Lato/lato-italic.woff +0 -0
  124. snappy/doc/_static/fonts/Lato/lato-italic.woff2 +0 -0
  125. snappy/doc/_static/fonts/Lato/lato-regular.eot +0 -0
  126. snappy/doc/_static/fonts/Lato/lato-regular.ttf +0 -0
  127. snappy/doc/_static/fonts/Lato/lato-regular.woff +0 -0
  128. snappy/doc/_static/fonts/Lato/lato-regular.woff2 +0 -0
  129. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
  130. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
  131. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
  132. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
  133. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
  134. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
  135. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
  136. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
  137. snappy/doc/_static/jquery.js +2 -0
  138. snappy/doc/_static/js/badge_only.js +1 -0
  139. snappy/doc/_static/js/theme.js +1 -0
  140. snappy/doc/_static/js/versions.js +228 -0
  141. snappy/doc/_static/language_data.js +192 -0
  142. snappy/doc/_static/minus.png +0 -0
  143. snappy/doc/_static/plus.png +0 -0
  144. snappy/doc/_static/pygments.css +75 -0
  145. snappy/doc/_static/searchtools.js +635 -0
  146. snappy/doc/_static/snappy_furo.css +33 -0
  147. snappy/doc/_static/snappy_sphinx_rtd_theme.css +42 -0
  148. snappy/doc/_static/sphinx_highlight.js +154 -0
  149. snappy/doc/additional_classes.html +1500 -0
  150. snappy/doc/bugs.html +132 -0
  151. snappy/doc/censuses.html +453 -0
  152. snappy/doc/credits.html +184 -0
  153. snappy/doc/development.html +385 -0
  154. snappy/doc/doc-latest/additional_classes.html +1500 -0
  155. snappy/doc/doc-latest/bugs.html +132 -0
  156. snappy/doc/doc-latest/censuses.html +453 -0
  157. snappy/doc/doc-latest/credits.html +184 -0
  158. snappy/doc/doc-latest/development.html +385 -0
  159. snappy/doc/doc-latest/genindex.html +1349 -0
  160. snappy/doc/doc-latest/index.html +287 -0
  161. snappy/doc/doc-latest/installing.html +346 -0
  162. snappy/doc/doc-latest/manifold.html +3632 -0
  163. snappy/doc/doc-latest/manifoldhp.html +180 -0
  164. snappy/doc/doc-latest/news.html +438 -0
  165. snappy/doc/doc-latest/objects.inv +0 -0
  166. snappy/doc/doc-latest/other.html +160 -0
  167. snappy/doc/doc-latest/platonic_census.html +376 -0
  168. snappy/doc/doc-latest/plink.html +210 -0
  169. snappy/doc/doc-latest/ptolemy.html +253 -0
  170. snappy/doc/doc-latest/ptolemy_classes.html +1144 -0
  171. snappy/doc/doc-latest/ptolemy_examples1.html +409 -0
  172. snappy/doc/doc-latest/ptolemy_examples2.html +471 -0
  173. snappy/doc/doc-latest/ptolemy_examples3.html +414 -0
  174. snappy/doc/doc-latest/ptolemy_examples4.html +195 -0
  175. snappy/doc/doc-latest/ptolemy_prelim.html +248 -0
  176. snappy/doc/doc-latest/py-modindex.html +165 -0
  177. snappy/doc/doc-latest/screenshots.html +141 -0
  178. snappy/doc/doc-latest/search.html +135 -0
  179. snappy/doc/doc-latest/searchindex.js +1 -0
  180. snappy/doc/doc-latest/snap.html +202 -0
  181. snappy/doc/doc-latest/snappy.html +181 -0
  182. snappy/doc/doc-latest/spherogram.html +1346 -0
  183. snappy/doc/doc-latest/todo.html +166 -0
  184. snappy/doc/doc-latest/triangulation.html +1676 -0
  185. snappy/doc/doc-latest/tutorial.html +159 -0
  186. snappy/doc/doc-latest/verify.html +330 -0
  187. snappy/doc/doc-latest/verify_internals.html +1235 -0
  188. snappy/doc/genindex.html +1349 -0
  189. snappy/doc/index.html +287 -0
  190. snappy/doc/installing.html +346 -0
  191. snappy/doc/manifold.html +3632 -0
  192. snappy/doc/manifoldhp.html +180 -0
  193. snappy/doc/news.html +438 -0
  194. snappy/doc/objects.inv +0 -0
  195. snappy/doc/other.html +160 -0
  196. snappy/doc/platonic_census.html +376 -0
  197. snappy/doc/plink.html +210 -0
  198. snappy/doc/ptolemy.html +253 -0
  199. snappy/doc/ptolemy_classes.html +1144 -0
  200. snappy/doc/ptolemy_examples1.html +409 -0
  201. snappy/doc/ptolemy_examples2.html +471 -0
  202. snappy/doc/ptolemy_examples3.html +414 -0
  203. snappy/doc/ptolemy_examples4.html +195 -0
  204. snappy/doc/ptolemy_prelim.html +248 -0
  205. snappy/doc/py-modindex.html +165 -0
  206. snappy/doc/screenshots.html +141 -0
  207. snappy/doc/search.html +135 -0
  208. snappy/doc/searchindex.js +1 -0
  209. snappy/doc/snap.html +202 -0
  210. snappy/doc/snappy.html +181 -0
  211. snappy/doc/spherogram.html +1346 -0
  212. snappy/doc/todo.html +166 -0
  213. snappy/doc/triangulation.html +1676 -0
  214. snappy/doc/tutorial.html +159 -0
  215. snappy/doc/verify.html +330 -0
  216. snappy/doc/verify_internals.html +1235 -0
  217. snappy/drilling/__init__.py +456 -0
  218. snappy/drilling/barycentric.py +103 -0
  219. snappy/drilling/constants.py +5 -0
  220. snappy/drilling/crush.py +270 -0
  221. snappy/drilling/cusps.py +125 -0
  222. snappy/drilling/debug.py +242 -0
  223. snappy/drilling/epsilons.py +6 -0
  224. snappy/drilling/exceptions.py +55 -0
  225. snappy/drilling/moves.py +620 -0
  226. snappy/drilling/peripheral_curves.py +210 -0
  227. snappy/drilling/perturb.py +188 -0
  228. snappy/drilling/shorten.py +36 -0
  229. snappy/drilling/subdivide.py +274 -0
  230. snappy/drilling/test.py +23 -0
  231. snappy/drilling/test_cases.py +132 -0
  232. snappy/drilling/tracing.py +351 -0
  233. snappy/exceptions.py +26 -0
  234. snappy/export_stl.py +120 -0
  235. snappy/exterior_to_link/__init__.py +2 -0
  236. snappy/exterior_to_link/barycentric_geometry.py +463 -0
  237. snappy/exterior_to_link/exceptions.py +6 -0
  238. snappy/exterior_to_link/geodesic_map.json +14408 -0
  239. snappy/exterior_to_link/hyp_utils.py +112 -0
  240. snappy/exterior_to_link/link_projection.py +323 -0
  241. snappy/exterior_to_link/main.py +198 -0
  242. snappy/exterior_to_link/mcomplex_with_expansion.py +261 -0
  243. snappy/exterior_to_link/mcomplex_with_link.py +687 -0
  244. snappy/exterior_to_link/mcomplex_with_memory.py +162 -0
  245. snappy/exterior_to_link/pl_utils.py +491 -0
  246. snappy/exterior_to_link/put_in_S3.py +156 -0
  247. snappy/exterior_to_link/rational_linear_algebra.py +130 -0
  248. snappy/exterior_to_link/rational_linear_algebra_wrapped.py +135 -0
  249. snappy/exterior_to_link/simplify_to_base_tri.py +114 -0
  250. snappy/exterior_to_link/stored_moves.py +475 -0
  251. snappy/exterior_to_link/test.py +31 -0
  252. snappy/filedialog.py +28 -0
  253. snappy/geometric_structure/__init__.py +212 -0
  254. snappy/geometric_structure/cusp_neighborhood/__init__.py +3 -0
  255. snappy/geometric_structure/cusp_neighborhood/complex_cusp_cross_section.py +691 -0
  256. snappy/geometric_structure/cusp_neighborhood/cusp_cross_section_base.py +480 -0
  257. snappy/geometric_structure/cusp_neighborhood/exceptions.py +41 -0
  258. snappy/geometric_structure/cusp_neighborhood/real_cusp_cross_section.py +294 -0
  259. snappy/geometric_structure/cusp_neighborhood/tiles_for_cusp_neighborhood.py +156 -0
  260. snappy/geometric_structure/cusp_neighborhood/vertices.py +35 -0
  261. snappy/geometric_structure/geodesic/__init__.py +0 -0
  262. snappy/geometric_structure/geodesic/add_core_curves.py +152 -0
  263. snappy/geometric_structure/geodesic/avoid_core_curves.py +369 -0
  264. snappy/geometric_structure/geodesic/canonical_representatives.py +52 -0
  265. snappy/geometric_structure/geodesic/check_away_from_core_curve.py +60 -0
  266. snappy/geometric_structure/geodesic/constants.py +6 -0
  267. snappy/geometric_structure/geodesic/exceptions.py +22 -0
  268. snappy/geometric_structure/geodesic/fixed_points.py +106 -0
  269. snappy/geometric_structure/geodesic/geodesic_start_point_info.py +435 -0
  270. snappy/geometric_structure/geodesic/graph_trace_helper.py +67 -0
  271. snappy/geometric_structure/geodesic/line.py +30 -0
  272. snappy/geometric_structure/geodesic/multiplicity.py +127 -0
  273. snappy/geometric_structure/geodesic/tiles_for_geodesic.py +128 -0
  274. snappy/geometric_structure/test.py +22 -0
  275. snappy/gui.py +121 -0
  276. snappy/horoviewer.py +443 -0
  277. snappy/hyperboloid/__init__.py +212 -0
  278. snappy/hyperboloid/distances.py +259 -0
  279. snappy/hyperboloid/horoball.py +19 -0
  280. snappy/hyperboloid/line.py +35 -0
  281. snappy/hyperboloid/point.py +9 -0
  282. snappy/hyperboloid/triangle.py +29 -0
  283. snappy/info_icon.gif +0 -0
  284. snappy/infowindow.py +65 -0
  285. snappy/isometry_signature.py +389 -0
  286. snappy/len_spec/__init__.py +609 -0
  287. snappy/len_spec/geodesic_info.py +129 -0
  288. snappy/len_spec/geodesic_key_info_dict.py +116 -0
  289. snappy/len_spec/geodesic_piece.py +146 -0
  290. snappy/len_spec/geometric_structure.py +182 -0
  291. snappy/len_spec/geometry.py +136 -0
  292. snappy/len_spec/length_spectrum_geodesic_info.py +185 -0
  293. snappy/len_spec/spine.py +128 -0
  294. snappy/len_spec/test.py +24 -0
  295. snappy/len_spec/test_cases.py +69 -0
  296. snappy/len_spec/tile.py +276 -0
  297. snappy/len_spec/word.py +86 -0
  298. snappy/manifolds/HTWKnots/alternating.gz +0 -0
  299. snappy/manifolds/HTWKnots/nonalternating.gz +0 -0
  300. snappy/manifolds/__init__.py +3 -0
  301. snappy/margulis/__init__.py +332 -0
  302. snappy/margulis/cusp_neighborhood_neighborhood.py +66 -0
  303. snappy/margulis/geodesic_neighborhood.py +152 -0
  304. snappy/margulis/margulis_info.py +21 -0
  305. snappy/margulis/mu_from_neighborhood_pair.py +175 -0
  306. snappy/margulis/neighborhood.py +29 -0
  307. snappy/margulis/test.py +22 -0
  308. snappy/math_basics.py +187 -0
  309. snappy/matrix.py +525 -0
  310. snappy/number.py +657 -0
  311. snappy/numeric_output_checker.py +345 -0
  312. snappy/pari.py +41 -0
  313. snappy/phone_home.py +57 -0
  314. snappy/polyviewer.py +259 -0
  315. snappy/ptolemy/__init__.py +17 -0
  316. snappy/ptolemy/component.py +103 -0
  317. snappy/ptolemy/coordinates.py +2290 -0
  318. snappy/ptolemy/fieldExtensions.py +153 -0
  319. snappy/ptolemy/findLoops.py +473 -0
  320. snappy/ptolemy/geometricRep.py +59 -0
  321. snappy/ptolemy/homology.py +165 -0
  322. snappy/ptolemy/magma/default.magma_template +229 -0
  323. snappy/ptolemy/magma/radicalsOfPrimaryDecomposition.magma_template +79 -0
  324. snappy/ptolemy/manifoldMethods.py +395 -0
  325. snappy/ptolemy/matrix.py +350 -0
  326. snappy/ptolemy/numericalSolutionsToGroebnerBasis.py +113 -0
  327. snappy/ptolemy/polynomial.py +856 -0
  328. snappy/ptolemy/processComponents.py +173 -0
  329. snappy/ptolemy/processFileBase.py +247 -0
  330. snappy/ptolemy/processFileDispatch.py +46 -0
  331. snappy/ptolemy/processMagmaFile.py +392 -0
  332. snappy/ptolemy/processRurFile.py +150 -0
  333. snappy/ptolemy/ptolemyGeneralizedObstructionClass.py +102 -0
  334. snappy/ptolemy/ptolemyObstructionClass.py +64 -0
  335. snappy/ptolemy/ptolemyVariety.py +995 -0
  336. snappy/ptolemy/ptolemyVarietyPrimeIdealGroebnerBasis.py +140 -0
  337. snappy/ptolemy/reginaWrapper.py +698 -0
  338. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
  339. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
  340. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
  341. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
  342. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
  343. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
  344. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
  345. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
  346. snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
  347. snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
  348. snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c0.magma_out.bz2 +0 -0
  349. snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
  350. snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
  351. snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c1.magma_out.bz2 +0 -0
  352. snappy/ptolemy/rur.py +545 -0
  353. snappy/ptolemy/solutionsToPrimeIdealGroebnerBasis.py +277 -0
  354. snappy/ptolemy/test.py +1126 -0
  355. snappy/ptolemy/testing_files/3_1__sl2_c0.magma_out.bz2 +0 -0
  356. snappy/ptolemy/testing_files/3_1__sl2_c1.magma_out.bz2 +0 -0
  357. snappy/ptolemy/testing_files/4_1__sl2_c0.magma_out.bz2 +0 -0
  358. snappy/ptolemy/testing_files/4_1__sl2_c1.magma_out.bz2 +0 -0
  359. snappy/ptolemy/testing_files/4_1__sl3_c0.magma_out.bz2 +0 -0
  360. snappy/ptolemy/testing_files/4_1__sl4_c0.magma_out.bz2 +0 -0
  361. snappy/ptolemy/testing_files/4_1__sl4_c1.magma_out.bz2 +0 -0
  362. snappy/ptolemy/testing_files/5_2__sl2_c0.magma_out.bz2 +0 -0
  363. snappy/ptolemy/testing_files/5_2__sl2_c1.magma_out.bz2 +0 -0
  364. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
  365. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
  366. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
  367. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
  368. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
  369. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
  370. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
  371. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
  372. snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c0.magma_out +95 -0
  373. snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c1.magma_out +95 -0
  374. snappy/ptolemy/testing_files/m015__sl3_c0.magma_out.bz2 +0 -0
  375. snappy/ptolemy/testing_files/m135__sl2_c0.magma_out.bz2 +0 -0
  376. snappy/ptolemy/testing_files/m135__sl2_c1.magma_out.bz2 +0 -0
  377. snappy/ptolemy/testing_files/m135__sl2_c2.magma_out.bz2 +0 -0
  378. snappy/ptolemy/testing_files/m135__sl2_c3.magma_out.bz2 +0 -0
  379. snappy/ptolemy/testing_files/m135__sl2_c4.magma_out.bz2 +0 -0
  380. snappy/ptolemy/testing_files/m135__sl2_c5.magma_out.bz2 +0 -0
  381. snappy/ptolemy/testing_files/m135__sl2_c6.magma_out.bz2 +0 -0
  382. snappy/ptolemy/testing_files/m135__sl2_c7.magma_out.bz2 +0 -0
  383. snappy/ptolemy/testing_files/s000__sl2_c0.magma_out.bz2 +0 -0
  384. snappy/ptolemy/testing_files/s000__sl2_c1.magma_out.bz2 +0 -0
  385. snappy/ptolemy/testing_files/t00000__sl2_c0.magma_out.bz2 +0 -0
  386. snappy/ptolemy/testing_files/t00000__sl2_c1.magma_out.bz2 +0 -0
  387. snappy/ptolemy/testing_files/v0000__sl2_c0.magma_out.bz2 +0 -0
  388. snappy/ptolemy/testing_files/v0000__sl2_c1.magma_out.bz2 +0 -0
  389. snappy/ptolemy/testing_files/v0000__sl2_c2.magma_out.bz2 +0 -0
  390. snappy/ptolemy/testing_files/v0000__sl2_c3.magma_out.bz2 +0 -0
  391. snappy/ptolemy/testing_files_generalized/m003__sl2_c0.magma_out.bz2 +0 -0
  392. snappy/ptolemy/testing_files_generalized/m003__sl2_c1.magma_out.bz2 +0 -0
  393. snappy/ptolemy/testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
  394. snappy/ptolemy/testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
  395. snappy/ptolemy/testing_files_generalized/m004__sl2_c0.magma_out.bz2 +0 -0
  396. snappy/ptolemy/testing_files_generalized/m004__sl2_c1.magma_out.bz2 +0 -0
  397. snappy/ptolemy/testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
  398. snappy/ptolemy/testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
  399. snappy/ptolemy/testing_files_rur/m052__sl3_c0.rur.bz2 +0 -0
  400. snappy/ptolemy/utilities.py +236 -0
  401. snappy/raytracing/__init__.py +64 -0
  402. snappy/raytracing/additional_horospheres.py +64 -0
  403. snappy/raytracing/additional_len_spec_choices.py +63 -0
  404. snappy/raytracing/cohomology_fractal.py +197 -0
  405. snappy/raytracing/eyeball.py +124 -0
  406. snappy/raytracing/finite_raytracing_data.py +237 -0
  407. snappy/raytracing/finite_viewer.py +590 -0
  408. snappy/raytracing/geodesic_tube_info.py +174 -0
  409. snappy/raytracing/geodesics.py +246 -0
  410. snappy/raytracing/geodesics_window.py +258 -0
  411. snappy/raytracing/gui_utilities.py +293 -0
  412. snappy/raytracing/hyperboloid_navigation.py +556 -0
  413. snappy/raytracing/hyperboloid_utilities.py +234 -0
  414. snappy/raytracing/ideal_raytracing_data.py +592 -0
  415. snappy/raytracing/inside_viewer.py +974 -0
  416. snappy/raytracing/pack.py +22 -0
  417. snappy/raytracing/raytracing_data.py +126 -0
  418. snappy/raytracing/raytracing_view.py +454 -0
  419. snappy/raytracing/shaders/Eye.png +0 -0
  420. snappy/raytracing/shaders/NonGeometric.png +0 -0
  421. snappy/raytracing/shaders/__init__.py +101 -0
  422. snappy/raytracing/shaders/fragment.glsl +1744 -0
  423. snappy/raytracing/test.py +29 -0
  424. snappy/raytracing/tooltip.py +146 -0
  425. snappy/raytracing/upper_halfspace_utilities.py +98 -0
  426. snappy/raytracing/view_scale_controller.py +98 -0
  427. snappy/raytracing/zoom_slider/__init__.py +263 -0
  428. snappy/raytracing/zoom_slider/inward.png +0 -0
  429. snappy/raytracing/zoom_slider/inward18.png +0 -0
  430. snappy/raytracing/zoom_slider/outward.png +0 -0
  431. snappy/raytracing/zoom_slider/outward18.png +0 -0
  432. snappy/raytracing/zoom_slider/test.py +20 -0
  433. snappy/sage_helper.py +119 -0
  434. snappy/settings.py +407 -0
  435. snappy/shell.py +53 -0
  436. snappy/snap/__init__.py +117 -0
  437. snappy/snap/character_varieties.py +375 -0
  438. snappy/snap/find_field.py +372 -0
  439. snappy/snap/fox_milnor.py +271 -0
  440. snappy/snap/fundamental_polyhedron.py +569 -0
  441. snappy/snap/generators.py +39 -0
  442. snappy/snap/interval_reps.py +81 -0
  443. snappy/snap/kernel_structures.py +128 -0
  444. snappy/snap/mcomplex_base.py +18 -0
  445. snappy/snap/nsagetools.py +716 -0
  446. snappy/snap/peripheral/__init__.py +1 -0
  447. snappy/snap/peripheral/dual_cellulation.py +219 -0
  448. snappy/snap/peripheral/link.py +127 -0
  449. snappy/snap/peripheral/peripheral.py +159 -0
  450. snappy/snap/peripheral/surface.py +522 -0
  451. snappy/snap/peripheral/test.py +35 -0
  452. snappy/snap/polished_reps.py +335 -0
  453. snappy/snap/shapes.py +152 -0
  454. snappy/snap/slice_obs_HKL/__init__.py +194 -0
  455. snappy/snap/slice_obs_HKL/basics.py +236 -0
  456. snappy/snap/slice_obs_HKL/direct.py +217 -0
  457. snappy/snap/slice_obs_HKL/poly_norm.py +212 -0
  458. snappy/snap/slice_obs_HKL/rep_theory.py +424 -0
  459. snappy/snap/t3mlite/__init__.py +2 -0
  460. snappy/snap/t3mlite/arrow.py +243 -0
  461. snappy/snap/t3mlite/corner.py +22 -0
  462. snappy/snap/t3mlite/edge.py +172 -0
  463. snappy/snap/t3mlite/face.py +37 -0
  464. snappy/snap/t3mlite/files.py +211 -0
  465. snappy/snap/t3mlite/homology.py +53 -0
  466. snappy/snap/t3mlite/linalg.py +419 -0
  467. snappy/snap/t3mlite/mcomplex.py +1499 -0
  468. snappy/snap/t3mlite/perm4.py +320 -0
  469. snappy/snap/t3mlite/setup.py +12 -0
  470. snappy/snap/t3mlite/simplex.py +199 -0
  471. snappy/snap/t3mlite/spun.py +297 -0
  472. snappy/snap/t3mlite/surface.py +519 -0
  473. snappy/snap/t3mlite/test.py +20 -0
  474. snappy/snap/t3mlite/test_vs_regina.py +86 -0
  475. snappy/snap/t3mlite/tetrahedron.py +109 -0
  476. snappy/snap/t3mlite/vertex.py +42 -0
  477. snappy/snap/test.py +139 -0
  478. snappy/snap/utilities.py +288 -0
  479. snappy/test.py +213 -0
  480. snappy/test_cases.py +263 -0
  481. snappy/testing.py +131 -0
  482. snappy/tiling/__init__.py +2 -0
  483. snappy/tiling/dict_based_set.py +79 -0
  484. snappy/tiling/floor.py +49 -0
  485. snappy/tiling/hyperboloid_dict.py +54 -0
  486. snappy/tiling/iter_utils.py +78 -0
  487. snappy/tiling/lifted_tetrahedron.py +22 -0
  488. snappy/tiling/lifted_tetrahedron_set.py +54 -0
  489. snappy/tiling/quotient_dict.py +70 -0
  490. snappy/tiling/real_hash_dict.py +164 -0
  491. snappy/tiling/test.py +23 -0
  492. snappy/tiling/tile.py +224 -0
  493. snappy/tiling/triangle.py +33 -0
  494. snappy/tkterminal.py +920 -0
  495. snappy/twister/__init__.py +20 -0
  496. snappy/twister/main.py +646 -0
  497. snappy/twister/surfaces/S_0_1 +3 -0
  498. snappy/twister/surfaces/S_0_2 +3 -0
  499. snappy/twister/surfaces/S_0_4 +7 -0
  500. snappy/twister/surfaces/S_0_4_Lantern +8 -0
  501. snappy/twister/surfaces/S_1 +3 -0
  502. snappy/twister/surfaces/S_1_1 +4 -0
  503. snappy/twister/surfaces/S_1_2 +5 -0
  504. snappy/twister/surfaces/S_1_2_5 +6 -0
  505. snappy/twister/surfaces/S_2 +6 -0
  506. snappy/twister/surfaces/S_2_1 +8 -0
  507. snappy/twister/surfaces/S_2_heeg +10 -0
  508. snappy/twister/surfaces/S_3 +8 -0
  509. snappy/twister/surfaces/S_3_1 +10 -0
  510. snappy/twister/surfaces/S_4_1 +12 -0
  511. snappy/twister/surfaces/S_5_1 +14 -0
  512. snappy/twister/surfaces/heeg_fig8 +9 -0
  513. snappy/twister/twister_core.cpython-310-aarch64-linux-gnu.so +0 -0
  514. snappy/upper_halfspace/__init__.py +146 -0
  515. snappy/upper_halfspace/ideal_point.py +29 -0
  516. snappy/verify/__init__.py +13 -0
  517. snappy/verify/canonical.py +542 -0
  518. snappy/verify/complex_volume/__init__.py +18 -0
  519. snappy/verify/complex_volume/adjust_torsion.py +86 -0
  520. snappy/verify/complex_volume/closed.py +168 -0
  521. snappy/verify/complex_volume/compute_ptolemys.py +90 -0
  522. snappy/verify/complex_volume/cusped.py +56 -0
  523. snappy/verify/complex_volume/extended_bloch.py +201 -0
  524. snappy/verify/cusp_translations.py +85 -0
  525. snappy/verify/edge_equations.py +80 -0
  526. snappy/verify/exceptions.py +254 -0
  527. snappy/verify/hyperbolicity.py +224 -0
  528. snappy/verify/interval_newton_shapes_engine.py +523 -0
  529. snappy/verify/interval_tree.py +400 -0
  530. snappy/verify/krawczyk_shapes_engine.py +518 -0
  531. snappy/verify/real_algebra.py +286 -0
  532. snappy/verify/shapes.py +25 -0
  533. snappy/verify/square_extensions.py +1005 -0
  534. snappy/verify/test.py +72 -0
  535. snappy/verify/volume.py +128 -0
  536. snappy/version.py +2 -0
  537. snappy-3.3.dist-info/METADATA +58 -0
  538. snappy-3.3.dist-info/RECORD +541 -0
  539. snappy-3.3.dist-info/WHEEL +6 -0
  540. snappy-3.3.dist-info/entry_points.txt +2 -0
  541. snappy-3.3.dist-info/top_level.txt +28 -0
@@ -0,0 +1,717 @@
1
+ """
2
+ We decorate Regina's triangulation isomorphism signature (isosig) to
3
+ record the peripheral structure of a cusped manifold M, that is, the
4
+ cusp labels and the peripheral curves on each cusp. The basic idea is
5
+ to store these relative to SnapPy's combinatorial defaults for the
6
+ triangulation created from the bare isosig.
7
+
8
+ Specifically, if M has n cusps, we append a permutation on {0,...,n-1}
9
+ as well as n change-of-basis matrices, represented as a sequence of 5n
10
+ integers and encoded as a string of isosig characters. This decoration
11
+ string is appended to the isosig string, after first appending a
12
+ separator character which is not a valid isosig character. To save
13
+ space, the permutation may be omitted when it is equal to the identity
14
+ permutation; this is indicated by the fact that the length of the
15
+ decoration is 4n rather than 5n.
16
+
17
+ A simple valid decorated isosig for a two-cusped manifold is::
18
+
19
+ eLPkbdcddhgggb_abBaaBBaaB
20
+
21
+ Here, the bare isosig is what precedes the underscore; what follows is
22
+ an encoded version of the 5n integers mentioned above. This decorated
23
+ isosig is equivalent to
24
+
25
+ eLPkbdcddhgggb_BaaBBaaB
26
+
27
+ where the permutation part has been elided since the permutation is
28
+ the identity.
29
+
30
+ In practice, one can extract the isosig and decorator from a decorated
31
+ isosig, say named di, as follows:
32
+
33
+ isosig, decorator = di.split('_')
34
+
35
+ Note: An isosig is an invariant of a triangulation of an *unoriented*
36
+ manifold. For an amphicheiral manifold M, it can happen that
37
+ Manifold(M.triangulation_isosig(decorated=False)) has the opposite
38
+ orientation from M itself.
39
+ The decoration implicitly embeds the preferred orientation of
40
+ M in the sign of the determinant of the change-of-basis matrices.
41
+
42
+ Note: If the triangulation has combinatorial symmetries, there can be
43
+ multiple change-of-basis matrices that yield combinatorially
44
+ isomorphic pairs (triangulation, peripheral curves). In such cases,
45
+ the decoration is the lexicographically first one.
46
+
47
+ Caveat: We pick the decoration with the lexicographically smallest
48
+ encoding with the following consequence: If we have more 26 cusps, the
49
+ lexicographically smallest permutation might not have the smallest encoding
50
+ and thus might not be the one picked.
51
+
52
+ Caveat: We drop the trivial permutation from the encoding. Pairs (a,b) of string
53
+ come with the lexicographic ordering. We also obtain a (partial) ordering by
54
+ ordering by a + b. These two orderings are not the same.
55
+ In particular, there is a combinatorial isomorphism from
56
+ Triangulation('L6n1') to
57
+ Triangulation(Triangulation('L6n1').triangulation_isosig(decorated = False))
58
+ that acts on the cusp by the identity perm and, thus, we would expect it to
59
+ be preferred. However,
60
+ Triangulation("L6n1(0,0)(0,0)(0,0)").triangulation_isosig() results in
61
+ 'gLMzQbcdefffaelaaai_acbBaabCbbabbBC' which does not use the identity perm.
62
+
63
+ Caveat: There are de-facto two canonical choices of peripheral curves.
64
+ When calling
65
+ >>> T = Triangulation('ovLMvvPQQQccddlmnijklmnmnlgvfamtvfblhaumx'),
66
+ the SnapPea kernel picks peripheral curves and then orients the manifold
67
+ (see data_to_triangulation in kernel_code/kernel/triangulation.c)
68
+ >>> T.set_peripheral_curves('combinatorial')
69
+ is now calling the same SnapPea kernel code to pick peripheral curve but
70
+ on the oriented manifold. This can result in different peripheral curves.
71
+
72
+ Note that the encoding and decoding needs to use the same of the two
73
+ canonical choices of peripheral curves.
74
+
75
+ For the decoding, there is a difference based on whether the isosig is
76
+ decorated because set_peripheral_from_decoration calls
77
+ manifold.set_peripheral_curves('combinatorial').
78
+
79
+ We need to account for that in the encoding: we need to use
80
+ set_peripheral_curves('combinatorial') on the "target" triangulation if
81
+ we anticipate a decoration. And if we called
82
+ set_peripheral_curves('combinatorial'), we need to make sure we have a
83
+ decoration (see force_decoration).
84
+ """
85
+
86
+ import re
87
+ import string
88
+
89
+ from .matrix import make_vector
90
+
91
+ # Used between the base isosig and the decorated version.
92
+ separator = '_'
93
+
94
+ # Pattern matching decorated isosigs
95
+
96
+ base64_pat = r'([a-zA-Z0-9\+\-]+)'
97
+ separator_pat = '[%s]{1}' % separator
98
+ base64_opt_pat = r'([a-zA-Z0-9\+\-]*)'
99
+ isosig_pattern = re.compile(base64_pat + separator_pat + base64_opt_pat + '$')
100
+
101
+ # We store lists of integers as (non-RFC4648) base64 strings.
102
+
103
+ base64_letters = string.ascii_letters + '0123456789+-'
104
+ base64_lower = string.ascii_lowercase + '01234+'
105
+ base64_upper = string.ascii_uppercase + '56789-'
106
+ in_one = string.ascii_lowercase[:16] + string.ascii_lowercase[1:16].upper()
107
+
108
+ int_to_letter = dict(enumerate(base64_letters))
109
+ letter_to_int = {a: i for i, a in enumerate(base64_letters)}
110
+
111
+
112
+ def encode_nonnegative_int(x):
113
+ """
114
+ Regina's base64 encoding scheme for nonnegative integers,
115
+ described in the appendix to http://arxiv.org/abs/1110.6080
116
+ """
117
+ assert x >= 0
118
+ six_bits = []
119
+ while True:
120
+ low_six = x & 63
121
+ six_bits.append(low_six)
122
+ x = x >> 6
123
+ if x == 0:
124
+ break
125
+ return ''.join([int_to_letter[b] for b in six_bits])
126
+
127
+
128
+ def decode_nonnegative_int(s):
129
+ return sum( letter_to_int[a] << 6*i for i, a in enumerate(s))
130
+
131
+
132
+ def encode_int(x):
133
+ """
134
+ Encodes an integer in the range [-2**90 + 1, 2**90 - 1] with a "stop"
135
+ at the end so a concatenation of such encodings is easily decodable.
136
+ The basic format is:
137
+
138
+ If x in [0...15], encode as a single letter in [a...p].
139
+ If x in [-15...-1] encode as a single letter in [P...B].
140
+
141
+ Otherwise, the first letter specifies the length of
142
+ encode_nonnegative_int(abs(x)) as well as sign(x), followed by the
143
+ encoding of abs(x).
144
+ """
145
+ if 0 <= x < 16:
146
+ return base64_letters[x]
147
+ if -15 <= x < 0:
148
+ return base64_letters[abs(x) + 26]
149
+ encoded_xabs = encode_nonnegative_int(abs(x))
150
+ L = len(encoded_xabs)
151
+ try:
152
+ if x > 0:
153
+ return base64_lower[16 + L] + encoded_xabs
154
+ if x < 0:
155
+ return base64_upper[16 + L] + encoded_xabs
156
+ except IndexError:
157
+ raise ValueError('The given integer is too large to encode')
158
+
159
+
160
+ def encode_integer_list(L):
161
+ return ''.join(map(encode_int, L))
162
+
163
+
164
+ def decode_integer_list(encoded):
165
+ ans = []
166
+ while len(encoded):
167
+ s = encoded[0]
168
+ sign = 1 if s in base64_lower else -1
169
+ if s in in_one:
170
+ ans.append(sign*letter_to_int[s.lower()])
171
+ encoded = encoded[1:]
172
+ else:
173
+ if sign == 1:
174
+ L = base64_lower.index(s) - 16
175
+ else:
176
+ L = base64_upper.index(s) - 16
177
+ current, encoded = encoded[1:L+1], encoded[L+1:]
178
+ ans.append(sign*decode_nonnegative_int(current))
179
+ return ans
180
+
181
+ ###############################################################################
182
+ # Some helper functions
183
+
184
+ def det(A):
185
+ return A[0][0]*A[1][1] - A[0][1]*A[1][0]
186
+
187
+
188
+ def inverse_perm(L):
189
+ ans = len(L)*[None]
190
+ for i, x in enumerate(L):
191
+ ans[x] = i
192
+ return ans
193
+
194
+
195
+ def as_two_by_two_matrices(L):
196
+ assert len(L) % 4 == 0
197
+ return [[(L[i], L[i+1]), (L[i+2], L[i+3])] for i in range(0, len(L), 4)]
198
+
199
+ def first_non_zero_entry_in_column(matrix, col):
200
+ e = matrix[0, col]
201
+ if e != 0:
202
+ return e
203
+ return matrix[1, col]
204
+
205
+ def sgn_column(matrix, col):
206
+ """
207
+ Returns +1 or -1 depending on the sign of the first non-zero entry
208
+ in the column of the given matrix.
209
+ """
210
+ if first_non_zero_entry_in_column(matrix, col) > 0:
211
+ return +1
212
+ else:
213
+ return -1
214
+
215
+ def apply_peripheral_curve_flips(
216
+ matrix, slope, manifold_orientable, isomorphism_orientation):
217
+ """
218
+ Flips peripheral curves (as encoded by matrix) to bring them into
219
+ canonical form and updates slope accordingly.
220
+ """
221
+
222
+ # Determine whether to flip meridian
223
+ f0 = sgn_column(matrix, 0)
224
+
225
+ # Determine whether to flip longitude
226
+ if manifold_orientable:
227
+ # We conform the matrix such that the first non-zero entry in the
228
+ # first column and the determinant are always positive
229
+ f1 = f0 * isomorphism_orientation
230
+ else:
231
+ # We conform the matrix such that the first non-zero entry in each
232
+ # column is always positive
233
+ f1 = sgn_column(matrix, 1)
234
+
235
+ flips = [ f0, f1 ]
236
+
237
+ for col, flip in enumerate(flips):
238
+ for row in range(2):
239
+ matrix[row,col] *= flip
240
+ slope[col] *= flip
241
+
242
+ def pack_matrices(matrices):
243
+ """
244
+ Multiplies the columns of each matrix by the entries in flips and
245
+ packs all the matrices into one array, column-major.
246
+ """
247
+
248
+ return [ matrix[row,col]
249
+ for matrix in matrices
250
+ for col in range(2)
251
+ for row in range(2) ]
252
+
253
+
254
+ def supress_minus_zero(x):
255
+ if x == 0:
256
+ return 0
257
+ else:
258
+ return x
259
+
260
+
261
+ def is_trivial_perm(perm):
262
+ return all(i == p for i, p in enumerate(perm))
263
+
264
+
265
+ def key_prefer_pos(x):
266
+ """
267
+ Intended for key argument to min.
268
+
269
+ Prefers positive and then absolute value.
270
+ """
271
+
272
+ if x >= 0:
273
+ return (0, x)
274
+ else:
275
+ return (1, -x)
276
+
277
+ def key_slope(slope):
278
+ """
279
+ Intended for key argument to min.
280
+
281
+ Prefers positive and small denominator.
282
+ """
283
+
284
+ slope_m, slope_l = slope
285
+ return (key_prefer_pos(slope_l), key_prefer_pos(slope_m))
286
+
287
+ def key_decoration_info(info):
288
+ encoded, slopes = info
289
+ return [encoded, [key_slope(slope) for slope in slopes]]
290
+
291
+ def normalized_slope(slope):
292
+ """
293
+ Returns slope or -slope preferring positive and small denominator.
294
+
295
+ Equivalent to min([slope, -slope], key=key_slope)
296
+ """
297
+
298
+ slope_m, slope_l = slope
299
+ if slope_l < 0:
300
+ return -slope
301
+ if slope_l > 0:
302
+ return slope
303
+ if slope_m < 0:
304
+ return -slope
305
+ return slope
306
+
307
+ def candidate_decoration_info(
308
+ isomorphism,
309
+ slopes,
310
+ manifold_orientable,
311
+ ignore_cusp_ordering,
312
+ ignore_curves,
313
+ ignore_curve_orientations,
314
+ ignore_filling_orientations,
315
+ ignore_orientation):
316
+
317
+ matrices = isomorphism.cusp_maps()
318
+ isomorphism_orientation = matrices[0].det()
319
+
320
+ # Do not consider orientation-reversing isomorphisms if
321
+ # ignore_orientation isn't specified.
322
+ if manifold_orientable and not ignore_orientation:
323
+ if isomorphism_orientation < 0:
324
+ return None
325
+
326
+ # Make a copy as vectors so that we can modify in place and
327
+ # apply matrices.
328
+ # Outside of SnapPy, SimpleVector is not making a copy of the
329
+ # tuple and we need a list to modify things in place.
330
+ slopes = [ make_vector([slope_m, slope_l])
331
+ for slope_m, slope_l in slopes ]
332
+
333
+ # Permutation of cusps
334
+ perm = inverse_perm(isomorphism.cusp_images())
335
+
336
+ if ignore_cusp_ordering:
337
+ # If we do not include the permutation in the encoding,
338
+ # we need to apply it to the matrices
339
+ matrices = [ matrices[i] for i in perm ]
340
+ slopes = [ slopes[i] for i in perm ]
341
+
342
+ if ignore_curves:
343
+ slopes = [ matrix * slope
344
+ for matrix, slope in zip(matrices, slopes) ]
345
+ if manifold_orientable and isomorphism_orientation < 0:
346
+ # We want to preserve the direction of the core curve because it is
347
+ # relevant for preserving which way a geometric spun-triangulation
348
+ # goes.
349
+ # That means we need to reverse the direction of the filling if
350
+ # reversing the manifold orientaiton.
351
+ slopes = [ -slope for slope in slopes ]
352
+ else:
353
+ if ignore_curve_orientations:
354
+ for matrix, slope in zip(matrices, slopes):
355
+ apply_peripheral_curve_flips(
356
+ matrix, slope, manifold_orientable, isomorphism_orientation)
357
+
358
+ encoded = ''
359
+
360
+ if not ignore_cusp_ordering:
361
+ #
362
+ # Force decoration to fix a very subtle bug!
363
+ #
364
+ # Recall that we call N.set_peripheral_curves('combinatorial')
365
+ # in decorated_isosig below if either ignore_cusp_ordering or
366
+ # ignore_curves is False.
367
+ #
368
+ # On the decoding site, we thus also need to call
369
+ # manifold.set_peripheral_curves('combinatorial') in those cases.
370
+ # This happens in set_peripheral_from_decoration and thus only
371
+ # if the isosig returned here has a decoration, that is "encoded"
372
+ # is not empty.
373
+ #
374
+ # Assume that ignore_cusp_ordering is False and ignore_curves is
375
+ # True and the permutation happens to be the identity.
376
+ #
377
+ # We need to make sure not to have an empty "encoded" in this case.
378
+ force_decoration = ignore_curves
379
+
380
+ if force_decoration or not is_trivial_perm(perm):
381
+ # Encode permutation
382
+ encoded += encode_integer_list(perm)
383
+
384
+ if not ignore_curves:
385
+ # Encode the matrices
386
+ encoded += encode_integer_list(pack_matrices(matrices))
387
+
388
+ if ignore_filling_orientations:
389
+ slopes = [ normalized_slope(slope)
390
+ for slope in slopes ]
391
+
392
+ return encoded, slopes
393
+
394
+ # main two functions
395
+
396
+ def decorated_isosig(manifold, triangulation_class,
397
+ ignore_cusp_ordering=False,
398
+ ignore_curves=False,
399
+ ignore_curve_orientations=False,
400
+ ignore_filling_orientations=False,
401
+ ignore_orientation=True):
402
+
403
+ isosig = manifold._undecorated_triangulation_isosig(
404
+ ignore_orientation=ignore_orientation)
405
+
406
+ # Do not decorate if no cusps
407
+ if manifold.num_cusps() == 0:
408
+ return isosig
409
+
410
+ N = triangulation_class(isosig, remove_finite_vertices=False)
411
+ if not (ignore_cusp_ordering and ignore_curves):
412
+ # Note that data_to_triangulation determines the peripheral
413
+ # curves before orienting the manifold.
414
+ # Thus, we get different peripheral curves when calling
415
+ # N.set_peripheral_curves.
416
+ # For backwards compatibility (see set_peripheral_from_decoration),
417
+ # we need to keep calling N.set_peripheral_curves here unless there is
418
+ # no decoration.
419
+ N.set_peripheral_curves('combinatorial')
420
+
421
+ manifold_orientable = manifold.is_orientable()
422
+ slopes = manifold.cusp_info('filling')
423
+
424
+ # Try all combinatorial isomorphisms and pick
425
+ # lexicographically smallest info.
426
+ encoded, slopes = min(
427
+ (info
428
+ for isomorphism in manifold.isomorphisms_to(N)
429
+ if (
430
+ info := candidate_decoration_info(
431
+ isomorphism,
432
+ slopes,
433
+ manifold_orientable=manifold_orientable,
434
+ ignore_cusp_ordering=ignore_cusp_ordering,
435
+ ignore_curves=ignore_curves,
436
+ ignore_curve_orientations=ignore_curve_orientations,
437
+ ignore_filling_orientations=ignore_filling_orientations,
438
+ ignore_orientation=ignore_orientation)
439
+ ) is not None),
440
+ key = key_decoration_info)
441
+
442
+ ans = isosig
443
+
444
+ if encoded:
445
+ ans += separator + encoded
446
+
447
+ if not all(manifold.cusp_info('complete?')):
448
+ for slope_m, slope_l in slopes:
449
+ ans += '(%g,%g)' % (supress_minus_zero(slope_m),
450
+ supress_minus_zero(slope_l))
451
+
452
+ return ans
453
+
454
+ def set_peripheral_from_decoration(manifold, decoration):
455
+ """
456
+ The manifold is assumed to already have a triangulation created
457
+ from the "bare" isosig.
458
+ """
459
+ dec = decode_integer_list(decoration)
460
+ manifold.set_peripheral_curves('combinatorial')
461
+ n = manifold.num_cusps()
462
+ k = len(dec)
463
+
464
+ if k not in [ n, 4 * n, 5 * n]:
465
+ raise ValueError("Decoration has unexpected length.")
466
+
467
+ if k == n or k == 5 * n:
468
+ if k == n:
469
+ manifold._reindex_cusps(dec)
470
+ else:
471
+ manifold._reindex_cusps(dec[:n])
472
+ if k == 4 * n or k == 5 * n:
473
+ if k == 4 * n:
474
+ cobs = as_two_by_two_matrices(dec)
475
+ else:
476
+ cobs = as_two_by_two_matrices(dec[n:])
477
+ if det(cobs[0]) < 0 and manifold.is_orientable():
478
+ manifold.reverse_orientation()
479
+ cobs = [[(-a, b), (-c, d)] for [(a, b), (c,d)] in cobs]
480
+ manifold.set_peripheral_curves(cobs)
481
+
482
+ # Testing code
483
+
484
+
485
+ def is_identity(A):
486
+ return A[0, 0] == A[1, 1] == 1 and A[1, 0] == A[0, 1] == 0
487
+
488
+
489
+ def preserves_peripheral_curves(h):
490
+ perm = h.cusp_images()
491
+ each_cusp = all(is_identity(A) for A in h.cusp_maps())
492
+ return perm == sorted(perm) and each_cusp
493
+
494
+
495
+ def same_peripheral_curves(M, N):
496
+ for h in M.isomorphisms_to(N):
497
+ if preserves_peripheral_curves(h):
498
+ return True
499
+ return False
500
+
501
+
502
+ asymmetric = ['v3372', 't10397', 't10448', 't11289', 't11581',
503
+ 't11780', 't11824', 't12685', 'o9_34328', 'o9_35609', 'o9_35746',
504
+ 'o9_36591', 'o9_37290', 'o9_37552', 'o9_38147', 'o9_38375',
505
+ 'o9_38845', 'o9_39220', 'o9_41039', 'o9_41063', 'o9_41329',
506
+ 'o9_43248']
507
+
508
+
509
+ def main_test():
510
+ import snappy
511
+ censuses = [snappy.OrientableClosedCensus[:100],
512
+ snappy.OrientableCuspedCensus(filter='tets<7'),
513
+ snappy.NonorientableClosedCensus,
514
+ snappy.NonorientableCuspedCensus,
515
+ snappy.CensusKnots(),
516
+ snappy.HTLinkExteriors(filter='cusps>3 and volume<14'),
517
+ [snappy.Manifold(name) for name in asymmetric]]
518
+ tests = 0
519
+ for census in censuses:
520
+ for M in census:
521
+ isosig = decorated_isosig(M, snappy.Triangulation)
522
+ N = snappy.Triangulation(isosig)
523
+ assert same_peripheral_curves(M, N), M
524
+ assert isosig == decorated_isosig(N, snappy.Triangulation), M
525
+ assert M.homology() == N.homology()
526
+ tests += 1
527
+ print('Tested decorated isosig encode/decode on %d triangulations' % tests)
528
+
529
+
530
+ def test_integer_list_encoder(tries=1000, length=100, max_entry=2**90):
531
+ import random
532
+ tests = 0
533
+ for i in range(tries):
534
+ entries = [random.randrange(-max_entry, max_entry) for i in range(length)]
535
+ entries += [random.randrange(-15, 16) for i in range(length)]
536
+ random.shuffle(entries)
537
+ assert decode_integer_list(encode_integer_list(entries)) == entries
538
+ tests += 1
539
+ print('Tested encode/decode on %d lists of integers' % tests)
540
+
541
+
542
+ def test_link_invariant():
543
+ import snappy
544
+
545
+ # DT codes of the same link but with different orientations of the
546
+ # components
547
+
548
+ dt_codes = [
549
+ [(-14, -46, -40, -28, -60, -70), (-32, -34, -38, -4, -52, -50, -48), (-44, -42, -64, -2, -16, -58), (-56, -54, -8), (-36, -26, -24, -22, -20, -6, -18), (-10, -66), (-72, -30, -62), (-12, -68)],
550
+ [(-14, -46, -40, -28, -60, -70), (-36, -34, -30, -4, -52, -50, -48), (-42, -44, -58, -16, -2, -64), (-56, -54, -8), (-32, -26, -24, -22, -20, -6, -18), (-10, -66), (-72, -38, -62), (-12, -68)],
551
+ [(14, 70, 64, 50, 36, 24), (18, 2), (26, 16, 72), (46, 44, 22, 6, 48, 54), (52, 62, 60, 58, 56, 12, 34), (68, 66, 32, 10, 42, 40, 38), (28, 30, 8), (20, 4)],
552
+ [(-14, -46, -40, -28, -60, -70), (-32, -34, -38, -4, -52, -50, -48), (-44, -42, -64, -2, -16, -58), (-56, -54, -8), (-36, -26, -24, -22, -20, -6, -18), (-10, -68), (-30, -72, -62), (-12, -66)],
553
+ [(14, 70, 64, 50, 36, 24), (2, 18), (34, 16, 72), (42, 40, 54, 38, 6, 22), (62, 52, 26, 12, 56, 58, 60), (68, 66, 28, 10, 44, 46, 48), (32, 30, 8), (20, 4)],
554
+ [(-14, -46, -40, -28, -60, -70), (-34, -36, -58, -56, -54, -4, -30), (-42, -44, -48, -26, -2, -64), (-50, -52, -8), (-16, -32, -24, -6, -22, -20, -18), (-68, -10), (-38, -72, -62), (-66, -12)],
555
+ [(-14, -46, -40, -28, -60, -70), (-34, -36, -58, -56, -54, -4, -30), (-42, -44, -48, -26, -2, -64), (-50, -52, -8), (-16, -32, -24, -6, -22, -20, -18), (-10, -66), (-72, -38, -62), (-68, -12)],
556
+ [(14, 70, 64, 50, 36, 24), (2, 18), (16, 34, 72), (42, 40, 54, 38, 6, 20), (62, 52, 26, 12, 56, 58, 60), (68, 66, 28, 10, 44, 46, 48), (32, 30, 8), (4, 22)],
557
+ [(-14, -46, -40, -28, -60, -70), (-32, -34, -38, -4, -52, -50, -48), (-44, -42, -64, -2, -16, -58), (-56, -54, -8), (-36, -26, -24, -22, -20, -6, -18), (-66, -10), (-72, -30, -62), (-68, -12)]
558
+ ]
559
+
560
+ # Get complement for each dt_code and complement with opposite orientation
561
+ # for each dt_code
562
+ mfds = [ snappy.Manifold('DT%s' % dt_code) for dt_code in (dt_codes + dt_codes) ]
563
+ for mfd in mfds[:len(dt_codes)]:
564
+ mfd.reverse_orientation()
565
+
566
+ isometry_signatures = [ mfd.isometry_signature(of_link=True)
567
+ for mfd in mfds ]
568
+
569
+ # All the links only differ in orientation of complement or components,
570
+ # should get the same isometry_signature
571
+ assert len(set(isometry_signatures)) == 1
572
+
573
+ M = snappy.Manifold(isometry_signatures[0])
574
+ N = snappy.Manifold(M.isometry_signature(of_link=True))
575
+
576
+ # Instantiating a manifold from its decorated isometry_signature should
577
+ # eventually yield to a fixed point
578
+ assert same_peripheral_curves(M, N)
579
+
580
+ # More sanity checks
581
+ assert isometry_signatures[0] == M.isometry_signature(of_link=True)
582
+ assert isometry_signatures[0] == N.isometry_signature(of_link=True)
583
+
584
+ for mfd in mfds:
585
+ assert mfd.is_isometric_to(M, True)[0].extends_to_link()
586
+ assert mfd.is_isometric_to(N, True)[0].extends_to_link()
587
+
588
+ print("Tested that decorated isometry_signature is a link invariant")
589
+
590
+
591
+ def helper_are_isometric(M, N):
592
+ for i in range(100):
593
+ try:
594
+ if M.is_isometric_to(N):
595
+ return
596
+ except:
597
+ pass
598
+ M.randomize()
599
+ N.randomize()
600
+
601
+ raise Exception("Could not find isometry")
602
+
603
+
604
+ def helper_test_by_dehn_filling(M):
605
+ from snappy import Manifold
606
+
607
+ M_filled = M.filled_triangulation()
608
+
609
+ for ignore_cusp_ordering in [ False, True]:
610
+ for ignore_curve_orientations in [ False, True]:
611
+ isosig = M.triangulation_isosig(
612
+ decorated=True,
613
+ ignore_cusp_ordering=ignore_cusp_ordering,
614
+ ignore_curve_orientations=ignore_curve_orientations)
615
+ N = Manifold(isosig)
616
+ N_filled = N.filled_triangulation()
617
+
618
+ helper_are_isometric(M, N)
619
+
620
+
621
+ def test_by_dehn_filling():
622
+ import random
623
+
624
+ from snappy import OrientableCuspedCensus
625
+
626
+ count = 0
627
+
628
+ for M in OrientableCuspedCensus(cusps=3):
629
+ for i in range(20):
630
+ unfilled = random.randint(0, 2)
631
+ for c in range(3):
632
+ if c != unfilled:
633
+ fillings = [(1,0), (0,1), (11,12), (-13,16),
634
+ (9,-11), (8, 9), (1,7), (13, 14),
635
+ (14,-15), (17, -18)]
636
+ M.dehn_fill(fillings[random.randint(0, len(fillings) - 1)],
637
+ c)
638
+
639
+ if 'positive' in M.solution_type():
640
+ count += 1
641
+ helper_test_by_dehn_filling(M)
642
+
643
+ print("Tested %d randomly Dehn filled manifolds" % count)
644
+
645
+ def test_slope_transformations():
646
+ """
647
+ Tests that slopes are transformed so that the filled
648
+ manifold is the same.
649
+ """
650
+
651
+ import snappy
652
+ M = snappy.ManifoldHP("L14n63023(-5,1)(5,1)(10,1)")
653
+ oriented_isosig = M.triangulation_isosig(
654
+ decorated=False, ignore_orientation=False)
655
+ isosig = M.triangulation_isosig(
656
+ decorated=False)
657
+ Mop = M.copy()
658
+ Mop.reverse_orientation()
659
+ reverse_oriented_isosig = Mop.triangulation_isosig(
660
+ decorated=False, ignore_orientation=False)
661
+
662
+ if oriented_isosig != 'vLLvvLLMALQQzQQceillmnppqrlmrqtruututiivimllaelaqxrvdoxqltt':
663
+ raise AssertionError()
664
+ if isosig != 'vLLvLLPwPQLAMPQcefikkmnplkopqrsttutuuiixvimqlippawidlabavth':
665
+ raise AssertionError()
666
+
667
+ # The canonical orientation (used to compute the unoriented isosig)
668
+ # is the reverse of the actual orientation:
669
+ if reverse_oriented_isosig != isosig:
670
+ raise AssertionError()
671
+ if oriented_isosig == isosig:
672
+ raise ValueError()
673
+
674
+ isom_sig_pos = M.isometry_signature(ignore_orientation = False)
675
+ if isom_sig_pos != 'KLALvLwLLwMQLQPAMzMzMPzMPcbbeghnklntpqpqvrswtuvxyzABCDEFEGHIJJhhkofnaocnmrlsiaowxfcsaxhxhxhxhjhhhhs':
676
+ raise AssertionError()
677
+ isom_sig_neg = Mop.isometry_signature(ignore_orientation = False)
678
+ if isom_sig_neg != 'KLAMvMvvAwLvQPPPQMPzMPzMPcbbdegilopoouqtryvuxvwxzzBACDEFEGHIJJhhkhhohahrscaagwxkkgbvwpuxwqxqxwxxxxr':
679
+ raise AssertionError()
680
+
681
+ # It is not just the triangulation that is chiral, the manifold itself is:
682
+ if isom_sig_pos == isom_sig_neg:
683
+ raise ValueError()
684
+
685
+ # So we expect the oriented isometry signature to flip when neither the isomorphism
686
+ # signature nor its decoration capture the orientation.
687
+ for ignore_cusp_ordering in [False, True]:
688
+ for ignore_curves in [False, True]:
689
+ for ignore_curve_orientations in [False, True]:
690
+ for ignore_filling_orientations in [False, True]:
691
+ for ignore_orientation in [False, True]:
692
+ isosig = M.triangulation_isosig(
693
+ ignore_cusp_ordering = ignore_cusp_ordering,
694
+ ignore_curves = ignore_curves,
695
+ ignore_curve_orientations = ignore_curve_orientations,
696
+ ignore_filling_orientations = ignore_filling_orientations,
697
+ ignore_orientation = ignore_orientation)
698
+ isom_sig = (
699
+ snappy.ManifoldHP(isosig)
700
+ .isometry_signature(ignore_orientation = False))
701
+ does_ignore_orientation = (
702
+ ignore_orientation and
703
+ (ignore_curve_orientations or ignore_curves))
704
+ expected_isom_sig = (
705
+ isom_sig_neg
706
+ if does_ignore_orientation
707
+ else isom_sig_pos)
708
+ if isom_sig != expected_isom_sig:
709
+ raise AssertionError()
710
+ print("Tested slope transformations")
711
+
712
+ def run_tests():
713
+ test_integer_list_encoder()
714
+ main_test()
715
+ test_link_invariant()
716
+ test_by_dehn_filling()
717
+ test_slope_transformations()