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,372 @@
1
+ import itertools
2
+
3
+ from ..sage_helper import (cached_method, real_part, imag_part, round, ceil, floor, log,
4
+ ZZ, QQ, CDF, ComplexField, NumberField, PolynomialRing,
5
+ matrix, identity_matrix)
6
+
7
+
8
+ def error(poly, z, a=ZZ(0)):
9
+ """
10
+ The number of bits above 2^-(precision of z)
11
+ for which
12
+
13
+ poly(z) = a
14
+
15
+ fails to hold.
16
+ """
17
+ err = poly(z) - a
18
+ if err == 0:
19
+ return 0
20
+ return z.prec() + ceil(log(abs(poly(z) - a), 2))
21
+
22
+
23
+ def acceptable_error(poly, z, a, portion_bad):
24
+ """
25
+ A error is judged as acceptable if poly(z) = a to within
26
+ 2^-(portion_bad*z.prec())
27
+ """
28
+ return error(poly, z, a) <= floor(portion_bad*z.prec())
29
+
30
+
31
+ def best_algdep_factor(z, degree):
32
+ if hasattr(z, 'algebraic_dependency'): # Sage >= 8.0
33
+ return z.algebraic_dependency(degree)
34
+ else: # Sage < 8.0
35
+ P = z.algebraic_dependancy(degree)
36
+ return sorted( [p for p, e in P.factor()],
37
+ key=lambda p:abs(p(z)) )[0]
38
+
39
+
40
+ def complex_to_lattice(z, d, a, N=None):
41
+ """
42
+ Given an algebraic number z of degree d, set of up the
43
+ lattice which tries to express a in terms of powers of z,
44
+ where the last two columns are weighted by N.
45
+ """
46
+ if N is None:
47
+ N = ZZ(2)**(z.prec() - 10)
48
+ nums = [z**k for k in range(d)] + [a]
49
+ last_columns = [[round(N*real_part(x)) for x in nums], [round(N*imag_part(x)) for x in nums]]
50
+ A = matrix(identity_matrix(len(nums)).columns() + last_columns)
51
+ return A.transpose()
52
+
53
+
54
+ class ApproximateAlgebraicNumber():
55
+ """
56
+ An algebraic number which we can compute
57
+ to arbitrary precision. Specified by a function
58
+ where f(prec) is the number to 2^prec bits.
59
+ """
60
+ def __init__(self, defining_function):
61
+ if defining_function in QQ:
62
+ x = QQ(defining_function)
63
+ defining_function = lambda prec: ComplexField(prec)(x)
64
+ self.f = defining_function
65
+ self._min_poly = None
66
+
67
+ def __repr__(self):
68
+ return '<ApproxAN: %s>' % CDF(self(100))
69
+
70
+ @cached_method
71
+ def __call__(self, prec):
72
+ return self.f(prec)
73
+
74
+ def min_polynomial(self, prec=100, degree=10):
75
+ if self._min_poly is None:
76
+ self_prec = self(prec)
77
+ p = best_algdep_factor(self_prec, degree)
78
+ z = self(2*prec)
79
+ if acceptable_error(p, z, ZZ(0), 0.2):
80
+ self._min_poly = p
81
+ self._default_precision = prec
82
+ self._approx_root = self_prec
83
+
84
+ return self._min_poly
85
+
86
+ def express(self, a, prec=None):
87
+ 'Express the given number in terms of self'
88
+ if self._min_poly is None:
89
+ raise ValueError('Minimal polynomial is not known.')
90
+ if prec is None:
91
+ prec = self._default_precision
92
+ p = self._min_poly
93
+ z0, a0 = self(prec), a(prec)
94
+ A = complex_to_lattice(z0, p.degree(), a0)
95
+ v = A.LLL(delta=0.75)[0]
96
+ v = list(v)[:-2]
97
+ if v[-1] == 0:
98
+ return None
99
+ R = PolynomialRing(QQ, 'x')
100
+ q = -R(v[:-1])/v[-1]
101
+
102
+ # Now we double-check
103
+ z1, a1 = self(2*prec), a(2*prec)
104
+ if acceptable_error(q, z1, a1, 0.2):
105
+ return q
106
+
107
+ def express_several(self, elts, prec=None):
108
+ """
109
+ Return exact expressions every number elts, provided this is
110
+ possible.
111
+ """
112
+ ans = []
113
+ for a in elts:
114
+ exact = self.express(a, prec)
115
+ if exact is None:
116
+ return None
117
+ else:
118
+ ans.append(exact)
119
+ return ans
120
+
121
+ def can_express(self, a, prec=None):
122
+ return self.express(a, prec) is not None
123
+
124
+ def number_field(self):
125
+ p = self._min_poly
126
+ if p is None:
127
+ raise ValueError('Minimal polynomial is not known.')
128
+ q = p.change_ring(QQ)
129
+ q = (1/q.leading_coefficient())*q
130
+ return NumberField(q, 'z', embedding=self._approx_root)
131
+
132
+ def place(self, prec):
133
+ K = self.number_field()
134
+ z = self(prec)
135
+ CC = z.parent()
136
+ return K.hom(z, check=False, codomain=CC)
137
+
138
+ def __add__(self, other):
139
+ if not isinstance(other, ApproximateAlgebraicNumber):
140
+ raise ValueError
141
+
142
+ def f(prec):
143
+ return self(prec) + other(prec)
144
+ return ApproximateAlgebraicNumber(f)
145
+
146
+ def __mul__(self, other):
147
+ if not isinstance(other, ApproximateAlgebraicNumber):
148
+ raise ValueError
149
+
150
+ def f(prec):
151
+ return self(prec)*other(prec)
152
+ return ApproximateAlgebraicNumber(f)
153
+
154
+ def __div__(self, other):
155
+ if not isinstance(other, ApproximateAlgebraicNumber):
156
+ raise ValueError
157
+
158
+ def f(prec):
159
+ return self(prec)/other(prec)
160
+ return ApproximateAlgebraicNumber(f)
161
+
162
+ def __pow__(self, n):
163
+ def f(prec):
164
+ return self(prec)**n
165
+ return ApproximateAlgebraicNumber(f)
166
+
167
+ def __neg__(self):
168
+ def f(prec):
169
+ return -self(prec)
170
+ return ApproximateAlgebraicNumber(f)
171
+
172
+ def __sub__(self, other):
173
+ return self + other.__neg__()
174
+
175
+
176
+ class ExactAlgebraicNumber(ApproximateAlgebraicNumber):
177
+ """
178
+ An ApproximateAlgebraicNumber which is specified
179
+ explicitly by its minimal polynomial.
180
+ """
181
+ def __init__(self, poly, approx_root):
182
+ if not acceptable_error(poly, approx_root, ZZ(0), 0.2):
183
+ raise ValueError('Given number does not seem to be a root of this polynomial')
184
+ self._min_poly = poly
185
+ self._approx_root = approx_root
186
+
187
+ @cached_method
188
+ def __call__(self, prec):
189
+ roots = [r[0] for r in self._min_poly.roots(ComplexField(prec))]
190
+
191
+ def dist_to_defining_root(z):
192
+ return abs(z - self._approx_root)
193
+ return sorted(roots, key=dist_to_defining_root)[0]
194
+
195
+
196
+ def optimize_field_generator(z):
197
+ p = z.min_polynomial()
198
+ assert p.base_ring() == ZZ
199
+ a, n = p.leading_coefficient(), p.degree()
200
+ x = PolynomialRing(QQ, 'x').gen()
201
+ q = a**(n-1) * p(x/a)
202
+ root_of_q = a*z(1000)
203
+ K = NumberField(q, 'x')
204
+ F, F_to_K, K_to_F = K.optimized_representation()
205
+ w = F_to_K(F.gen()).polynomial()(root_of_q)
206
+ f = F.defining_polynomial()
207
+ f = f.denominator() * f
208
+ return ExactAlgebraicNumber(f.change_ring(ZZ), w)
209
+
210
+
211
+ class ListOfApproximateAlgebraicNumbers():
212
+ def __init__(self, defining_function):
213
+ self.f = defining_function
214
+ self.n = len(defining_function(100))
215
+ self._field = {True:None, False:None}
216
+
217
+ @cached_method
218
+ def __call__(self, prec):
219
+ return self.f(prec)
220
+
221
+ @cached_method
222
+ def __getitem__(self, index):
223
+ def f(n):
224
+ return self(n)[index]
225
+ return ApproximateAlgebraicNumber(f)
226
+
227
+ def list(self):
228
+ return [self[i] for i in range(self.n)]
229
+
230
+ def __repr__(self):
231
+ return '<SetOfAAN: %s>' % [CDF(z) for z in self.f(100)]
232
+
233
+ def __len__(self):
234
+ return self.n
235
+
236
+ def are_in_field_generated_by(self, z, prec=None):
237
+ ans = []
238
+ for i in range(self.n):
239
+ p = z.express(self[i], prec)
240
+ if p is None:
241
+ return None
242
+ ans.append(p)
243
+ return ans
244
+
245
+ def _find_field_uncached(self, prec, degree, verbosity=False):
246
+ # Works similar to snap's field::generated_by
247
+ #
248
+ # The input elts is a list of approximate algebraic numbers (i.e., high
249
+ # precisions of numbers known to be algebraic).
250
+ #
251
+ # We iteratively try to construct an approximate algebraic number z
252
+ # whose minimal polynomial can be computed such that all elements
253
+ # in the input considered up to that point are lying inside the field
254
+ # generated by z. z will be the sum over some subset of given elements.
255
+ #
256
+ # We return the number field (as sage number field) associated to
257
+ # z's minimal polynomial, the approximate value of z and exact
258
+ # expressions of all inputs as polynomials in the root of the
259
+ # minimal polynomial
260
+ #
261
+ # In each iteration, we check whether the newly considered element can
262
+ # be expressed as algebraic expression in z. If yes, we keep z and
263
+ # remember how the newly considered element can be expressed.
264
+ # If no, we consider the newly considered element itself and the sum
265
+ # of it and the old z as new candidate z.
266
+
267
+ # Helper functions
268
+ def min_poly(z):
269
+ return z.min_polynomial(prec, degree)
270
+
271
+ def min_poly_deg(z):
272
+ return z.min_polynomial().degree()
273
+
274
+ def message(*args):
275
+ if verbosity:
276
+ print(*args)
277
+ # assert False
278
+
279
+ # The input list
280
+ elts = self.list()
281
+
282
+ # Start with z = 1 in the number field Q
283
+ z = ApproximateAlgebraicNumber(1)
284
+ z.min_polynomial()
285
+
286
+ # The exact expressions for inputs
287
+ exact_elts = []
288
+
289
+ # Iterate
290
+ for i, elt in enumerate(elts):
291
+ # Can the newly considered element elt be expressed in the old z
292
+ exact_elt = z.express(elt, prec)
293
+ if exact_elt is not None:
294
+ # If yes, remember it as its exact representation
295
+ exact_elts.append(exact_elt)
296
+ else:
297
+ # If no, try to get a minimal polynomial for elt
298
+ if min_poly(elt) is None:
299
+ message("Bailing: no minimal polynomial found for "
300
+ "newly considered element", elt)
301
+ return None
302
+
303
+ # Search for a primitive element for the field generated by
304
+ # z and elt.
305
+ found = False
306
+ candidates = [elt, z + elt, z - elt, z*elt, elt + elt + z, z + z + elt,
307
+ elt + elt - z, z + z - elt, z + z*elt, elt + elt*z]
308
+ for w in candidates:
309
+ if min_poly(w) is None:
310
+ message("Skipping: no minimal polynomial found for "
311
+ "possible primitive element", elt)
312
+ else:
313
+ # If Q(w) contains both w and elt, then we've found
314
+ # the needed primitive element.
315
+ if (min_poly_deg(w) >= min_poly_deg(z)
316
+ and w.can_express(z, prec) and w.can_express(elt, prec)):
317
+ exact_elts = w.express_several(elts[:i+1], prec)
318
+ if exact_elts is None:
319
+ message("Bailing: Couldn't express everything"
320
+ "in terms of primitive element")
321
+ return None
322
+ found, z = True, w
323
+ break
324
+
325
+ if not found:
326
+ message("Bailing: Couldn't find primitive element for larger field")
327
+ return None
328
+
329
+ field = z.number_field()
330
+ exact_elts = [field(exact_elt) for exact_elt in exact_elts]
331
+ return field, z, exact_elts
332
+
333
+ def find_field(self, prec, degree, optimize=False, verbosity=False):
334
+
335
+ # Adding verbosity for now to debug potential problems
336
+
337
+ # We always need the unoptimized generator
338
+ if self._field[False] is None:
339
+ self._field[False] = self._find_field_uncached(prec, degree,
340
+ verbosity)
341
+
342
+ # If we need to optimize the generator
343
+ if optimize and self._field[True] is None:
344
+ if self._field[False] is None:
345
+ # Bail if no unoptimized generator
346
+ return None
347
+
348
+ K, z, exact_elts = self._field[False]
349
+ # Optimize generator
350
+ z = optimize_field_generator(z)
351
+ # Try to express elements in it
352
+ exact_elts = self.are_in_field_generated_by(z, prec)
353
+ if exact_elts is None:
354
+ if verbosity:
355
+ print("Bailing: Could not express elements in optimized "
356
+ "generator", z)
357
+ return None
358
+
359
+ field = z.number_field()
360
+ exact_elts = [ field(exact_elt) for exact_elt in exact_elts ]
361
+
362
+ self._field[True] = (field, z, exact_elts)
363
+
364
+ return self._field[optimize]
365
+
366
+ def _as_exact_matrices(self, optimize=None):
367
+ if optimize is None:
368
+ optimize = self._field[True] is not None
369
+ if len(self) % 4:
370
+ raise ValueError("Not right number of values to form 2x2 matrices")
371
+ K, z, ans = self._field[optimize]
372
+ return z, [matrix(K, 2, 2, ans[n:n+4]) for n in range(0, len(ans), 4)]
@@ -0,0 +1,271 @@
1
+ """
2
+ Implements the Fox-Milnor for test for Alexander polynomials which
3
+ gives an obstruction for a link being strongly slice.
4
+
5
+ Specifically, we is the basic Fox-Milnor test of Corollary 12.3.14 of
6
+ [Kawauchi, A survey of knot theory] and also Theorem 8.18 of
7
+ [Lickorish, Intro to knot theory].
8
+
9
+ The main function provided is `fox_milnor_test`.
10
+ """
11
+
12
+ from ..sage_helper import _within_sage, sage_method
13
+ from spherogram import Link
14
+ from .nsagetools import (join_lists,
15
+ minimum_exponents,
16
+ fox_derivative,
17
+ uniform_poly_exponents,
18
+ convert_laurent_to_poly,
19
+ alexander_polynomial_basic,
20
+ MapToFreeAbelianization,
21
+ MapToGroupRingOfFreeAbelianization)
22
+
23
+ if _within_sage:
24
+ from ..sage_helper import gcd, matrix, QQ, ZZ, PolynomialRing
25
+
26
+
27
+ def standard_map_to_group_ring_of_abelianization_for_link(manifold_group):
28
+ """
29
+ Assumes the given manifold group come from an n-cusped manifold
30
+ with H_1 = Z^n + torsion where a Z-basis for the Z^n part is given
31
+ by the meridians on each cusp::
32
+
33
+ sage: G = Link('L14a25429').exterior().fundamental_group()
34
+ sage: phi = standard_map_to_group_ring_of_abelianization_for_link(G)
35
+ sage: phi(''.join(m for m, l in G.peripheral_curves()))
36
+ a*b*c
37
+ """
38
+ G = manifold_group
39
+ phi = MapToGroupRingOfFreeAbelianization(G)
40
+ R = phi.range()
41
+ betti = R.ngens()
42
+ meridians = [m for m, l in G.peripheral_curves()]
43
+ A = matrix(ZZ, [MapToFreeAbelianization.__call__(phi, m) for m in meridians])
44
+ if not (len(meridians) == phi.U.nrows() == betti and A.is_invertible()):
45
+ raise ValueError('H_1 or meridians incompatible being the exterior of a link in S^3.')
46
+ A = A.transpose().inverse()
47
+ phi = MapToGroupRingOfFreeAbelianization(G)
48
+ phi.U = A * phi.U
49
+ assert all(phi(m) == g for m, g in zip(meridians, R.gens()))
50
+ return phi
51
+
52
+
53
+ def alexander_polynomial_of_link(manifold, d):
54
+ """
55
+ Compute the d-th Alexander polynomial, i.e. the gcd of the
56
+ (d + 1)-st elementrary ideal of A(M)::
57
+
58
+ sage: L = Link('L5a1')
59
+ sage: f = alexander_polynomial_of_link(L, 0)
60
+ sage: f == L.alexander_polynomial()(*f.parent().gens())
61
+ True
62
+ sage: U1 = Link(braid_closure=[1])
63
+ sage: alexander_polynomial_of_link(U1, 0)
64
+ 1
65
+ sage: U2 = Link(braid_closure=[1, -1])
66
+ sage: alexander_polynomial_of_link(U2, 0)
67
+ 0
68
+ sage: alexander_polynomial_of_link(U2, 1)
69
+ 1
70
+ sage: U4 = Link(braid_closure=[1, -1, 2, -2, 3, -3])
71
+ sage: [alexander_polynomial_of_link(U4, d) for d in range(4)]
72
+ [0, 0, 0, 1]
73
+ sage: M = Link('L12n1181') # Milnor's link, strongly slice.
74
+ sage: alexander_polynomial_of_link(M, 0)
75
+ 0
76
+ sage: alexander_polynomial_of_link(M, 1)
77
+ a^2*b + a*b^2 - a^2 - 3*a*b - b^2 + a + b
78
+ """
79
+ if isinstance(manifold, Link):
80
+ manifold = manifold.exterior()
81
+ G = manifold.fundamental_group()
82
+ phi = standard_map_to_group_ring_of_abelianization_for_link(G)
83
+ return alexander_polynomial_basic(G, phi, d, pos_leading_coeff=True)
84
+
85
+
86
+ def alexander_data(manifold):
87
+ """
88
+ Consider the Alexander module::
89
+
90
+ A(M) = H_1(univ abelian cover, p^{-1}(point)).
91
+
92
+ Returns the pair (d, p(t_1, ... , t_k)) where:
93
+
94
+ i) d is the Alexander nullity, that is, rank(A(M)) - 1, and
95
+
96
+ ii) p is the d^th Alexander polynomial, that is, the gcd of
97
+ the (d + 1)st elementrary ideal of A(M).
98
+
99
+ Some examples::
100
+
101
+ sage: U1 = Link(braid_closure=[1])
102
+ sage: alexander_data(U1)
103
+ (0, 1)
104
+ sage: U2 = Link(braid_closure=[1, -1])
105
+ sage: alexander_data(U2)
106
+ (1, 1)
107
+ sage: U4 = Link(braid_closure=[1, -1, 2, -2, 3, -3])
108
+ sage: alexander_data(U4)
109
+ (3, 1)
110
+ sage: M = Link('L12n1181')
111
+ sage: alexander_data(M)
112
+ (1, a^2*b + a*b^2 - a^2 - 3*a*b - b^2 + a + b)
113
+ """
114
+ if isinstance(manifold, Link):
115
+ manifold = manifold.exterior()
116
+ M = manifold
117
+ for d in range(M.num_cusps()):
118
+ alex = alexander_polynomial_of_link(M, d)
119
+ if alex != 0:
120
+ return (d, alex)
121
+
122
+ def normalize(poly):
123
+ """
124
+ Divide the polynomial by the largest mononomial that divides every
125
+ term::
126
+
127
+ sage: P = PolynomialRing(QQ, 'x')
128
+ sage: normalize(P('x^3 + 2*x^2 + 3*x'))
129
+ x^2 + 2*x + 3
130
+ sage: R = PolynomialRing(QQ, ['a', 'b'])
131
+ sage: normalize(R('2*a^3*b + a*b^2 + 3*a*b'))
132
+ 2*a^2 + b + 3
133
+ """
134
+ if poly.is_constant():
135
+ return poly
136
+
137
+ P = poly.parent()
138
+ if P.ngens() == 1:
139
+ m = min(poly.exponents())
140
+ return P({e - m:c for e, c in poly.dict().items()})
141
+ else:
142
+ n = P.ngens()
143
+ exps = poly.exponents()
144
+ mins = [min(e[i] for e in exps) for i in range(n)]
145
+ return P({tuple(e - m for e, m in zip(exps, mins)): c
146
+ for exps, c in poly.dict().items()})
147
+
148
+
149
+ def palindrome(poly):
150
+ """
151
+ For f in R[t_1, ... , t_n] compute f(1/t_1, ..., 1/t_n) and return
152
+ it times the minimal monomial that puts it in R[t_1, ... , t_n]::
153
+
154
+ sage: P = PolynomialRing(ZZ, 'x')
155
+ sage: palindrome(P(1))
156
+ 1
157
+ sage: palindrome(P('x^3 + 2*x^2 + 3*x'))
158
+ 3*x^2 + 2*x + 1
159
+ sage: R = PolynomialRing(ZZ, ['a', 'b'])
160
+ sage: palindrome(R(2))
161
+ 2
162
+ sage: palindrome(R('2*a^3*b + a*b^2 + 3*a*b'))
163
+ 3*a^2*b + a^2 + 2*b
164
+ """
165
+ if poly.is_constant():
166
+ return poly
167
+
168
+ P = poly.parent()
169
+ if P.ngens() == 1:
170
+ m = poly.degree()
171
+ return P({m - e:c for e, c in poly.dict().items()})
172
+ else:
173
+ n = P.ngens()
174
+ exps = poly.exponents()
175
+ maxes = [max(e[i] for e in exps) for i in range(n)]
176
+ return P({tuple(m - e for m, e in zip(maxes, exps)): c
177
+ for exps, c in poly.dict().items()})
178
+
179
+
180
+ def is_palindrome(poly):
181
+ return normalize(poly) == palindrome(poly)
182
+
183
+
184
+ def poly_is_a_norm(poly):
185
+ """
186
+ Given a poly in ZZ[t_1, ... , t_n], determines if the poly is of
187
+ the form f * palindrome(f) up to units where f(1, 1, ... , 1) is
188
+ +/-1.
189
+ """
190
+
191
+ if poly == 0:
192
+ return False
193
+ P = poly.parent()
194
+ assert P.base_ring() == ZZ
195
+ n = poly.parent().ngens()
196
+
197
+ ones = n*[1]
198
+ val_at_ones = poly(ones)
199
+ if val_at_ones < 0:
200
+ poly, val_at_ones = -poly, -val_at_ones
201
+
202
+
203
+ if val_at_ones != 1:
204
+ return False
205
+
206
+ facs = []
207
+ g = P(1)
208
+ for f, e in poly.factor():
209
+ assert abs(f(ones)) == 1
210
+ if f(ones) < 0:
211
+ f = -f
212
+ facs.append((f, e))
213
+ g = g * f**e
214
+
215
+ assert g == poly
216
+
217
+ for f, e in facs:
218
+ if is_palindrome(f):
219
+ if e % 2 != 0:
220
+ return False
221
+ else:
222
+ g = palindrome(f)
223
+ if not (g, e) in facs:
224
+ return False
225
+
226
+ return True
227
+
228
+ @sage_method
229
+ def fox_milnor_test(manifold_or_link):
230
+ """
231
+ Returns ``True`` when the Alexander polynomial data of the link is
232
+ compatible with it being topologically strongly slice (that is,
233
+ the link bounds a disjoint collection of locally-flat disks in the
234
+ 4-ball). More precisely, it checks if the Alexander nullity is as
235
+ expected and that the appropriate Alexander polynomial is a norm::
236
+
237
+ sage: mflds = [Manifold('L12n1181'), Manifold('L11n247'), Manifold('L10n107')]
238
+ sage: {M.alexander_polynomial() for M in mflds}
239
+ {0}
240
+ sage: [M.fox_milnor_test() for M in mflds]
241
+ [True, False, False]
242
+
243
+ Note: This method only requires that the homology (including the
244
+ meridians) is consistent being the complement of a link in S^3. It
245
+ does not check that the manifold is actually a link complement.
246
+
247
+ References: This test is Corollary 12.3.14 of `[Kawauchi]
248
+ <https://doi.org/10.1007/978-3-0348-9227-8>`_ and Theorem 8.18 of
249
+ `[Lickorish] <https://doi.org/10.1007/978-1-4612-0691-0>`_.
250
+ """
251
+
252
+ M = manifold_or_link
253
+ if isinstance(M, Link):
254
+ M = M.exterior()
255
+
256
+ if not all(M.cusp_info('is_complete')):
257
+ raise ValueError('All cusps must be unfilled.')
258
+
259
+ if M.homology().elementary_divisors() != M.num_cusps()*[0]:
260
+ raise ValueError('Homology is not Z^(number of cusps).')
261
+
262
+ nullity, alex = alexander_data(M)
263
+ if nullity != M.num_cusps() - 1:
264
+ return False
265
+ return poly_is_a_norm(alex)
266
+
267
+
268
+
269
+ if __name__ == '__main__':
270
+ import doctest
271
+ print(doctest.testmod())