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.
- snappy/CyOpenGL.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/SnapPy.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/SnapPy.ico +0 -0
- snappy/SnapPy.png +0 -0
- snappy/SnapPyHP.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/__init__.py +534 -0
- snappy/app.py +604 -0
- snappy/app_menus.py +372 -0
- snappy/browser.py +998 -0
- snappy/cache.py +25 -0
- snappy/canonical.py +249 -0
- snappy/cusps/__init__.py +280 -0
- snappy/cusps/cusp_area_matrix.py +98 -0
- snappy/cusps/cusp_areas_from_matrix.py +96 -0
- snappy/cusps/maximal_cusp_area_matrix.py +136 -0
- snappy/cusps/short_slopes_for_cusp.py +217 -0
- snappy/cusps/test.py +22 -0
- snappy/cusps/trig_cusp_area_matrix.py +63 -0
- snappy/database.py +454 -0
- snappy/db_utilities.py +79 -0
- snappy/decorated_isosig.py +717 -0
- snappy/dev/__init__.py +0 -0
- snappy/dev/extended_ptolemy/__init__.py +8 -0
- snappy/dev/extended_ptolemy/closed.py +106 -0
- snappy/dev/extended_ptolemy/complexVolumesClosed.py +149 -0
- snappy/dev/extended_ptolemy/direct.py +42 -0
- snappy/dev/extended_ptolemy/extended.py +406 -0
- snappy/dev/extended_ptolemy/giac_helper.py +43 -0
- snappy/dev/extended_ptolemy/giac_rur.py +129 -0
- snappy/dev/extended_ptolemy/gluing.py +46 -0
- snappy/dev/extended_ptolemy/phc_wrapper.py +220 -0
- snappy/dev/extended_ptolemy/printMatrices.py +70 -0
- snappy/dev/vericlosed/__init__.py +1 -0
- snappy/dev/vericlosed/computeApproxHyperbolicStructureNew.py +159 -0
- snappy/dev/vericlosed/computeApproxHyperbolicStructureOrb.py +90 -0
- snappy/dev/vericlosed/computeVerifiedHyperbolicStructure.py +111 -0
- snappy/dev/vericlosed/gimbalLoopFinder.py +130 -0
- snappy/dev/vericlosed/hyperbolicStructure.py +313 -0
- snappy/dev/vericlosed/krawczykCertifiedEdgeLengthsEngine.py +165 -0
- snappy/dev/vericlosed/oneVertexTruncatedComplex.py +122 -0
- snappy/dev/vericlosed/orb/__init__.py +1 -0
- snappy/dev/vericlosed/orb/orb_solution_for_snappea_finite_triangulation_mac +0 -0
- snappy/dev/vericlosed/parseVertexGramMatrixFile.py +47 -0
- snappy/dev/vericlosed/polishApproxHyperbolicStructure.py +61 -0
- snappy/dev/vericlosed/test.py +54 -0
- snappy/dev/vericlosed/truncatedComplex.py +176 -0
- snappy/dev/vericlosed/verificationError.py +58 -0
- snappy/dev/vericlosed/verifyHyperbolicStructureEngine.py +177 -0
- snappy/doc/_images/SnapPy-196.png +0 -0
- snappy/doc/_images/m004_paper_plane_on_systole.jpg +0 -0
- snappy/doc/_images/m125_paper_plane.jpg +0 -0
- snappy/doc/_images/mac.png +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane.jpg +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane_closer.jpg +0 -0
- snappy/doc/_images/plink-action.png +0 -0
- snappy/doc/_images/ubuntu.png +0 -0
- snappy/doc/_images/win7.png +0 -0
- snappy/doc/_sources/additional_classes.rst.txt +40 -0
- snappy/doc/_sources/bugs.rst.txt +14 -0
- snappy/doc/_sources/censuses.rst.txt +52 -0
- snappy/doc/_sources/credits.rst.txt +81 -0
- snappy/doc/_sources/development.rst.txt +261 -0
- snappy/doc/_sources/index.rst.txt +215 -0
- snappy/doc/_sources/installing.rst.txt +249 -0
- snappy/doc/_sources/manifold.rst.txt +6 -0
- snappy/doc/_sources/manifoldhp.rst.txt +46 -0
- snappy/doc/_sources/news.rst.txt +425 -0
- snappy/doc/_sources/other.rst.txt +25 -0
- snappy/doc/_sources/platonic_census.rst.txt +20 -0
- snappy/doc/_sources/plink.rst.txt +102 -0
- snappy/doc/_sources/ptolemy.rst.txt +66 -0
- snappy/doc/_sources/ptolemy_classes.rst.txt +42 -0
- snappy/doc/_sources/ptolemy_examples1.rst.txt +298 -0
- snappy/doc/_sources/ptolemy_examples2.rst.txt +363 -0
- snappy/doc/_sources/ptolemy_examples3.rst.txt +301 -0
- snappy/doc/_sources/ptolemy_examples4.rst.txt +61 -0
- snappy/doc/_sources/ptolemy_prelim.rst.txt +105 -0
- snappy/doc/_sources/screenshots.rst.txt +21 -0
- snappy/doc/_sources/snap.rst.txt +87 -0
- snappy/doc/_sources/snappy.rst.txt +28 -0
- snappy/doc/_sources/spherogram.rst.txt +103 -0
- snappy/doc/_sources/todo.rst.txt +47 -0
- snappy/doc/_sources/triangulation.rst.txt +11 -0
- snappy/doc/_sources/tutorial.rst.txt +49 -0
- snappy/doc/_sources/verify.rst.txt +210 -0
- snappy/doc/_sources/verify_internals.rst.txt +79 -0
- snappy/doc/_static/SnapPy-horizontal-128.png +0 -0
- snappy/doc/_static/SnapPy.ico +0 -0
- snappy/doc/_static/_sphinx_javascript_frameworks_compat.js +123 -0
- snappy/doc/_static/basic.css +906 -0
- snappy/doc/_static/css/badge_only.css +1 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.eot +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.svg +2671 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.ttf +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff2 +0 -0
- snappy/doc/_static/css/theme.css +4 -0
- snappy/doc/_static/doctools.js +149 -0
- snappy/doc/_static/documentation_options.js +13 -0
- snappy/doc/_static/file.png +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
- snappy/doc/_static/jquery.js +2 -0
- snappy/doc/_static/js/badge_only.js +1 -0
- snappy/doc/_static/js/theme.js +1 -0
- snappy/doc/_static/js/versions.js +228 -0
- snappy/doc/_static/language_data.js +192 -0
- snappy/doc/_static/minus.png +0 -0
- snappy/doc/_static/plus.png +0 -0
- snappy/doc/_static/pygments.css +75 -0
- snappy/doc/_static/searchtools.js +635 -0
- snappy/doc/_static/snappy_furo.css +33 -0
- snappy/doc/_static/snappy_sphinx_rtd_theme.css +42 -0
- snappy/doc/_static/sphinx_highlight.js +154 -0
- snappy/doc/additional_classes.html +1500 -0
- snappy/doc/bugs.html +132 -0
- snappy/doc/censuses.html +453 -0
- snappy/doc/credits.html +184 -0
- snappy/doc/development.html +385 -0
- snappy/doc/doc-latest/additional_classes.html +1500 -0
- snappy/doc/doc-latest/bugs.html +132 -0
- snappy/doc/doc-latest/censuses.html +453 -0
- snappy/doc/doc-latest/credits.html +184 -0
- snappy/doc/doc-latest/development.html +385 -0
- snappy/doc/doc-latest/genindex.html +1349 -0
- snappy/doc/doc-latest/index.html +287 -0
- snappy/doc/doc-latest/installing.html +346 -0
- snappy/doc/doc-latest/manifold.html +3632 -0
- snappy/doc/doc-latest/manifoldhp.html +180 -0
- snappy/doc/doc-latest/news.html +438 -0
- snappy/doc/doc-latest/objects.inv +0 -0
- snappy/doc/doc-latest/other.html +160 -0
- snappy/doc/doc-latest/platonic_census.html +376 -0
- snappy/doc/doc-latest/plink.html +210 -0
- snappy/doc/doc-latest/ptolemy.html +253 -0
- snappy/doc/doc-latest/ptolemy_classes.html +1144 -0
- snappy/doc/doc-latest/ptolemy_examples1.html +409 -0
- snappy/doc/doc-latest/ptolemy_examples2.html +471 -0
- snappy/doc/doc-latest/ptolemy_examples3.html +414 -0
- snappy/doc/doc-latest/ptolemy_examples4.html +195 -0
- snappy/doc/doc-latest/ptolemy_prelim.html +248 -0
- snappy/doc/doc-latest/py-modindex.html +165 -0
- snappy/doc/doc-latest/screenshots.html +141 -0
- snappy/doc/doc-latest/search.html +135 -0
- snappy/doc/doc-latest/searchindex.js +1 -0
- snappy/doc/doc-latest/snap.html +202 -0
- snappy/doc/doc-latest/snappy.html +181 -0
- snappy/doc/doc-latest/spherogram.html +1346 -0
- snappy/doc/doc-latest/todo.html +166 -0
- snappy/doc/doc-latest/triangulation.html +1676 -0
- snappy/doc/doc-latest/tutorial.html +159 -0
- snappy/doc/doc-latest/verify.html +330 -0
- snappy/doc/doc-latest/verify_internals.html +1235 -0
- snappy/doc/genindex.html +1349 -0
- snappy/doc/index.html +287 -0
- snappy/doc/installing.html +346 -0
- snappy/doc/manifold.html +3632 -0
- snappy/doc/manifoldhp.html +180 -0
- snappy/doc/news.html +438 -0
- snappy/doc/objects.inv +0 -0
- snappy/doc/other.html +160 -0
- snappy/doc/platonic_census.html +376 -0
- snappy/doc/plink.html +210 -0
- snappy/doc/ptolemy.html +253 -0
- snappy/doc/ptolemy_classes.html +1144 -0
- snappy/doc/ptolemy_examples1.html +409 -0
- snappy/doc/ptolemy_examples2.html +471 -0
- snappy/doc/ptolemy_examples3.html +414 -0
- snappy/doc/ptolemy_examples4.html +195 -0
- snappy/doc/ptolemy_prelim.html +248 -0
- snappy/doc/py-modindex.html +165 -0
- snappy/doc/screenshots.html +141 -0
- snappy/doc/search.html +135 -0
- snappy/doc/searchindex.js +1 -0
- snappy/doc/snap.html +202 -0
- snappy/doc/snappy.html +181 -0
- snappy/doc/spherogram.html +1346 -0
- snappy/doc/todo.html +166 -0
- snappy/doc/triangulation.html +1676 -0
- snappy/doc/tutorial.html +159 -0
- snappy/doc/verify.html +330 -0
- snappy/doc/verify_internals.html +1235 -0
- snappy/drilling/__init__.py +456 -0
- snappy/drilling/barycentric.py +103 -0
- snappy/drilling/constants.py +5 -0
- snappy/drilling/crush.py +270 -0
- snappy/drilling/cusps.py +125 -0
- snappy/drilling/debug.py +242 -0
- snappy/drilling/epsilons.py +6 -0
- snappy/drilling/exceptions.py +55 -0
- snappy/drilling/moves.py +620 -0
- snappy/drilling/peripheral_curves.py +210 -0
- snappy/drilling/perturb.py +188 -0
- snappy/drilling/shorten.py +36 -0
- snappy/drilling/subdivide.py +274 -0
- snappy/drilling/test.py +23 -0
- snappy/drilling/test_cases.py +132 -0
- snappy/drilling/tracing.py +351 -0
- snappy/exceptions.py +26 -0
- snappy/export_stl.py +120 -0
- snappy/exterior_to_link/__init__.py +2 -0
- snappy/exterior_to_link/barycentric_geometry.py +463 -0
- snappy/exterior_to_link/exceptions.py +6 -0
- snappy/exterior_to_link/geodesic_map.json +14408 -0
- snappy/exterior_to_link/hyp_utils.py +112 -0
- snappy/exterior_to_link/link_projection.py +323 -0
- snappy/exterior_to_link/main.py +198 -0
- snappy/exterior_to_link/mcomplex_with_expansion.py +261 -0
- snappy/exterior_to_link/mcomplex_with_link.py +687 -0
- snappy/exterior_to_link/mcomplex_with_memory.py +162 -0
- snappy/exterior_to_link/pl_utils.py +491 -0
- snappy/exterior_to_link/put_in_S3.py +156 -0
- snappy/exterior_to_link/rational_linear_algebra.py +130 -0
- snappy/exterior_to_link/rational_linear_algebra_wrapped.py +135 -0
- snappy/exterior_to_link/simplify_to_base_tri.py +114 -0
- snappy/exterior_to_link/stored_moves.py +475 -0
- snappy/exterior_to_link/test.py +31 -0
- snappy/filedialog.py +28 -0
- snappy/geometric_structure/__init__.py +212 -0
- snappy/geometric_structure/cusp_neighborhood/__init__.py +3 -0
- snappy/geometric_structure/cusp_neighborhood/complex_cusp_cross_section.py +691 -0
- snappy/geometric_structure/cusp_neighborhood/cusp_cross_section_base.py +480 -0
- snappy/geometric_structure/cusp_neighborhood/exceptions.py +41 -0
- snappy/geometric_structure/cusp_neighborhood/real_cusp_cross_section.py +294 -0
- snappy/geometric_structure/cusp_neighborhood/tiles_for_cusp_neighborhood.py +156 -0
- snappy/geometric_structure/cusp_neighborhood/vertices.py +35 -0
- snappy/geometric_structure/geodesic/__init__.py +0 -0
- snappy/geometric_structure/geodesic/add_core_curves.py +152 -0
- snappy/geometric_structure/geodesic/avoid_core_curves.py +369 -0
- snappy/geometric_structure/geodesic/canonical_representatives.py +52 -0
- snappy/geometric_structure/geodesic/check_away_from_core_curve.py +60 -0
- snappy/geometric_structure/geodesic/constants.py +6 -0
- snappy/geometric_structure/geodesic/exceptions.py +22 -0
- snappy/geometric_structure/geodesic/fixed_points.py +106 -0
- snappy/geometric_structure/geodesic/geodesic_start_point_info.py +435 -0
- snappy/geometric_structure/geodesic/graph_trace_helper.py +67 -0
- snappy/geometric_structure/geodesic/line.py +30 -0
- snappy/geometric_structure/geodesic/multiplicity.py +127 -0
- snappy/geometric_structure/geodesic/tiles_for_geodesic.py +128 -0
- snappy/geometric_structure/test.py +22 -0
- snappy/gui.py +121 -0
- snappy/horoviewer.py +443 -0
- snappy/hyperboloid/__init__.py +212 -0
- snappy/hyperboloid/distances.py +259 -0
- snappy/hyperboloid/horoball.py +19 -0
- snappy/hyperboloid/line.py +35 -0
- snappy/hyperboloid/point.py +9 -0
- snappy/hyperboloid/triangle.py +29 -0
- snappy/info_icon.gif +0 -0
- snappy/infowindow.py +65 -0
- snappy/isometry_signature.py +389 -0
- snappy/len_spec/__init__.py +609 -0
- snappy/len_spec/geodesic_info.py +129 -0
- snappy/len_spec/geodesic_key_info_dict.py +116 -0
- snappy/len_spec/geodesic_piece.py +146 -0
- snappy/len_spec/geometric_structure.py +182 -0
- snappy/len_spec/geometry.py +136 -0
- snappy/len_spec/length_spectrum_geodesic_info.py +185 -0
- snappy/len_spec/spine.py +128 -0
- snappy/len_spec/test.py +24 -0
- snappy/len_spec/test_cases.py +69 -0
- snappy/len_spec/tile.py +276 -0
- snappy/len_spec/word.py +86 -0
- snappy/manifolds/HTWKnots/alternating.gz +0 -0
- snappy/manifolds/HTWKnots/nonalternating.gz +0 -0
- snappy/manifolds/__init__.py +3 -0
- snappy/margulis/__init__.py +332 -0
- snappy/margulis/cusp_neighborhood_neighborhood.py +66 -0
- snappy/margulis/geodesic_neighborhood.py +152 -0
- snappy/margulis/margulis_info.py +21 -0
- snappy/margulis/mu_from_neighborhood_pair.py +175 -0
- snappy/margulis/neighborhood.py +29 -0
- snappy/margulis/test.py +22 -0
- snappy/math_basics.py +187 -0
- snappy/matrix.py +525 -0
- snappy/number.py +657 -0
- snappy/numeric_output_checker.py +345 -0
- snappy/pari.py +41 -0
- snappy/phone_home.py +57 -0
- snappy/polyviewer.py +259 -0
- snappy/ptolemy/__init__.py +17 -0
- snappy/ptolemy/component.py +103 -0
- snappy/ptolemy/coordinates.py +2290 -0
- snappy/ptolemy/fieldExtensions.py +153 -0
- snappy/ptolemy/findLoops.py +473 -0
- snappy/ptolemy/geometricRep.py +59 -0
- snappy/ptolemy/homology.py +165 -0
- snappy/ptolemy/magma/default.magma_template +229 -0
- snappy/ptolemy/magma/radicalsOfPrimaryDecomposition.magma_template +79 -0
- snappy/ptolemy/manifoldMethods.py +395 -0
- snappy/ptolemy/matrix.py +350 -0
- snappy/ptolemy/numericalSolutionsToGroebnerBasis.py +113 -0
- snappy/ptolemy/polynomial.py +856 -0
- snappy/ptolemy/processComponents.py +173 -0
- snappy/ptolemy/processFileBase.py +247 -0
- snappy/ptolemy/processFileDispatch.py +46 -0
- snappy/ptolemy/processMagmaFile.py +392 -0
- snappy/ptolemy/processRurFile.py +150 -0
- snappy/ptolemy/ptolemyGeneralizedObstructionClass.py +102 -0
- snappy/ptolemy/ptolemyObstructionClass.py +64 -0
- snappy/ptolemy/ptolemyVariety.py +995 -0
- snappy/ptolemy/ptolemyVarietyPrimeIdealGroebnerBasis.py +140 -0
- snappy/ptolemy/reginaWrapper.py +698 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/rur.py +545 -0
- snappy/ptolemy/solutionsToPrimeIdealGroebnerBasis.py +277 -0
- snappy/ptolemy/test.py +1126 -0
- snappy/ptolemy/testing_files/3_1__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/3_1__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl4_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl4_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/5_2__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/5_2__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c0.magma_out +95 -0
- snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c1.magma_out +95 -0
- snappy/ptolemy/testing_files/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/s000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/s000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/t00000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/t00000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m004__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m004__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_rur/m052__sl3_c0.rur.bz2 +0 -0
- snappy/ptolemy/utilities.py +236 -0
- snappy/raytracing/__init__.py +64 -0
- snappy/raytracing/additional_horospheres.py +64 -0
- snappy/raytracing/additional_len_spec_choices.py +63 -0
- snappy/raytracing/cohomology_fractal.py +197 -0
- snappy/raytracing/eyeball.py +124 -0
- snappy/raytracing/finite_raytracing_data.py +237 -0
- snappy/raytracing/finite_viewer.py +590 -0
- snappy/raytracing/geodesic_tube_info.py +174 -0
- snappy/raytracing/geodesics.py +246 -0
- snappy/raytracing/geodesics_window.py +258 -0
- snappy/raytracing/gui_utilities.py +293 -0
- snappy/raytracing/hyperboloid_navigation.py +556 -0
- snappy/raytracing/hyperboloid_utilities.py +234 -0
- snappy/raytracing/ideal_raytracing_data.py +592 -0
- snappy/raytracing/inside_viewer.py +974 -0
- snappy/raytracing/pack.py +22 -0
- snappy/raytracing/raytracing_data.py +126 -0
- snappy/raytracing/raytracing_view.py +454 -0
- snappy/raytracing/shaders/Eye.png +0 -0
- snappy/raytracing/shaders/NonGeometric.png +0 -0
- snappy/raytracing/shaders/__init__.py +101 -0
- snappy/raytracing/shaders/fragment.glsl +1744 -0
- snappy/raytracing/test.py +29 -0
- snappy/raytracing/tooltip.py +146 -0
- snappy/raytracing/upper_halfspace_utilities.py +98 -0
- snappy/raytracing/view_scale_controller.py +98 -0
- snappy/raytracing/zoom_slider/__init__.py +263 -0
- snappy/raytracing/zoom_slider/inward.png +0 -0
- snappy/raytracing/zoom_slider/inward18.png +0 -0
- snappy/raytracing/zoom_slider/outward.png +0 -0
- snappy/raytracing/zoom_slider/outward18.png +0 -0
- snappy/raytracing/zoom_slider/test.py +20 -0
- snappy/sage_helper.py +119 -0
- snappy/settings.py +407 -0
- snappy/shell.py +53 -0
- snappy/snap/__init__.py +117 -0
- snappy/snap/character_varieties.py +375 -0
- snappy/snap/find_field.py +372 -0
- snappy/snap/fox_milnor.py +271 -0
- snappy/snap/fundamental_polyhedron.py +569 -0
- snappy/snap/generators.py +39 -0
- snappy/snap/interval_reps.py +81 -0
- snappy/snap/kernel_structures.py +128 -0
- snappy/snap/mcomplex_base.py +18 -0
- snappy/snap/nsagetools.py +716 -0
- snappy/snap/peripheral/__init__.py +1 -0
- snappy/snap/peripheral/dual_cellulation.py +219 -0
- snappy/snap/peripheral/link.py +127 -0
- snappy/snap/peripheral/peripheral.py +159 -0
- snappy/snap/peripheral/surface.py +522 -0
- snappy/snap/peripheral/test.py +35 -0
- snappy/snap/polished_reps.py +335 -0
- snappy/snap/shapes.py +152 -0
- snappy/snap/slice_obs_HKL/__init__.py +194 -0
- snappy/snap/slice_obs_HKL/basics.py +236 -0
- snappy/snap/slice_obs_HKL/direct.py +217 -0
- snappy/snap/slice_obs_HKL/poly_norm.py +212 -0
- snappy/snap/slice_obs_HKL/rep_theory.py +424 -0
- snappy/snap/t3mlite/__init__.py +2 -0
- snappy/snap/t3mlite/arrow.py +243 -0
- snappy/snap/t3mlite/corner.py +22 -0
- snappy/snap/t3mlite/edge.py +172 -0
- snappy/snap/t3mlite/face.py +37 -0
- snappy/snap/t3mlite/files.py +211 -0
- snappy/snap/t3mlite/homology.py +53 -0
- snappy/snap/t3mlite/linalg.py +419 -0
- snappy/snap/t3mlite/mcomplex.py +1499 -0
- snappy/snap/t3mlite/perm4.py +320 -0
- snappy/snap/t3mlite/setup.py +12 -0
- snappy/snap/t3mlite/simplex.py +199 -0
- snappy/snap/t3mlite/spun.py +297 -0
- snappy/snap/t3mlite/surface.py +519 -0
- snappy/snap/t3mlite/test.py +20 -0
- snappy/snap/t3mlite/test_vs_regina.py +86 -0
- snappy/snap/t3mlite/tetrahedron.py +109 -0
- snappy/snap/t3mlite/vertex.py +42 -0
- snappy/snap/test.py +139 -0
- snappy/snap/utilities.py +288 -0
- snappy/test.py +213 -0
- snappy/test_cases.py +263 -0
- snappy/testing.py +131 -0
- snappy/tiling/__init__.py +2 -0
- snappy/tiling/dict_based_set.py +79 -0
- snappy/tiling/floor.py +49 -0
- snappy/tiling/hyperboloid_dict.py +54 -0
- snappy/tiling/iter_utils.py +78 -0
- snappy/tiling/lifted_tetrahedron.py +22 -0
- snappy/tiling/lifted_tetrahedron_set.py +54 -0
- snappy/tiling/quotient_dict.py +70 -0
- snappy/tiling/real_hash_dict.py +164 -0
- snappy/tiling/test.py +23 -0
- snappy/tiling/tile.py +224 -0
- snappy/tiling/triangle.py +33 -0
- snappy/tkterminal.py +920 -0
- snappy/twister/__init__.py +20 -0
- snappy/twister/main.py +646 -0
- snappy/twister/surfaces/S_0_1 +3 -0
- snappy/twister/surfaces/S_0_2 +3 -0
- snappy/twister/surfaces/S_0_4 +7 -0
- snappy/twister/surfaces/S_0_4_Lantern +8 -0
- snappy/twister/surfaces/S_1 +3 -0
- snappy/twister/surfaces/S_1_1 +4 -0
- snappy/twister/surfaces/S_1_2 +5 -0
- snappy/twister/surfaces/S_1_2_5 +6 -0
- snappy/twister/surfaces/S_2 +6 -0
- snappy/twister/surfaces/S_2_1 +8 -0
- snappy/twister/surfaces/S_2_heeg +10 -0
- snappy/twister/surfaces/S_3 +8 -0
- snappy/twister/surfaces/S_3_1 +10 -0
- snappy/twister/surfaces/S_4_1 +12 -0
- snappy/twister/surfaces/S_5_1 +14 -0
- snappy/twister/surfaces/heeg_fig8 +9 -0
- snappy/twister/twister_core.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/upper_halfspace/__init__.py +146 -0
- snappy/upper_halfspace/ideal_point.py +29 -0
- snappy/verify/__init__.py +13 -0
- snappy/verify/canonical.py +542 -0
- snappy/verify/complex_volume/__init__.py +18 -0
- snappy/verify/complex_volume/adjust_torsion.py +86 -0
- snappy/verify/complex_volume/closed.py +168 -0
- snappy/verify/complex_volume/compute_ptolemys.py +90 -0
- snappy/verify/complex_volume/cusped.py +56 -0
- snappy/verify/complex_volume/extended_bloch.py +201 -0
- snappy/verify/cusp_translations.py +85 -0
- snappy/verify/edge_equations.py +80 -0
- snappy/verify/exceptions.py +254 -0
- snappy/verify/hyperbolicity.py +224 -0
- snappy/verify/interval_newton_shapes_engine.py +523 -0
- snappy/verify/interval_tree.py +400 -0
- snappy/verify/krawczyk_shapes_engine.py +518 -0
- snappy/verify/real_algebra.py +286 -0
- snappy/verify/shapes.py +25 -0
- snappy/verify/square_extensions.py +1005 -0
- snappy/verify/test.py +72 -0
- snappy/verify/volume.py +128 -0
- snappy/version.py +2 -0
- snappy-3.3.dist-info/METADATA +58 -0
- snappy-3.3.dist-info/RECORD +541 -0
- snappy-3.3.dist-info/WHEEL +6 -0
- snappy-3.3.dist-info/entry_points.txt +2 -0
- snappy-3.3.dist-info/top_level.txt +28 -0
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tools for use in Sage.
|
|
3
|
+
"""
|
|
4
|
+
import string
|
|
5
|
+
from ..sage_helper import _within_sage, sage_method
|
|
6
|
+
|
|
7
|
+
if _within_sage:
|
|
8
|
+
from ..sage_helper import ZZ, vector, matrix, block_matrix, identity_matrix, gcd, prod, det
|
|
9
|
+
from ..sage_helper import MatrixSpace, PolynomialRing, LaurentPolynomialRing
|
|
10
|
+
from ..sage_helper import SageObject, AbelianGroup, GroupAlgebra
|
|
11
|
+
from .polished_reps import polished_holonomy, MatrixRepresentation
|
|
12
|
+
Id2 = MatrixSpace(ZZ, 2)(1)
|
|
13
|
+
else:
|
|
14
|
+
SageObject = object
|
|
15
|
+
ZZ, Id2 = None, None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def search_for_low_rank_triangulation(M, tries=100, target_lower_bound=0):
|
|
19
|
+
rank_lower_bound = max(M.homology().rank(), target_lower_bound)
|
|
20
|
+
|
|
21
|
+
rank_upper_bound = M.fundamental_group().num_generators()
|
|
22
|
+
N = M.copy()
|
|
23
|
+
curr_best_tri = N.copy()
|
|
24
|
+
for i in range(tries):
|
|
25
|
+
if rank_upper_bound == rank_lower_bound:
|
|
26
|
+
break
|
|
27
|
+
N.randomize()
|
|
28
|
+
new_rank = N.fundamental_group().num_generators()
|
|
29
|
+
if new_rank < rank_upper_bound:
|
|
30
|
+
rank_upper_bound = new_rank
|
|
31
|
+
curr_best_tri = N.copy()
|
|
32
|
+
|
|
33
|
+
return rank_upper_bound, rank_lower_bound, curr_best_tri
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# ----------------------------------------------------------------
|
|
37
|
+
#
|
|
38
|
+
# Abelianization of the fundamental group
|
|
39
|
+
#
|
|
40
|
+
# ----------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
def abelianize_word(word, gens):
|
|
43
|
+
return vector(ZZ, [ word.count(g) - word.count(g.swapcase()) for g in gens])
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class MapToAbelianization(SageObject):
|
|
47
|
+
"""
|
|
48
|
+
sage: M = Manifold('v2037')
|
|
49
|
+
sage: ab = MapToAbelianization(M.fundamental_group())
|
|
50
|
+
sage: ab.range()
|
|
51
|
+
Multiplicative Abelian group isomorphic to C2 x C4 x Z
|
|
52
|
+
sage: ab('ab').order()
|
|
53
|
+
4
|
|
54
|
+
sage: ab('abc').order()
|
|
55
|
+
+Infinity
|
|
56
|
+
|
|
57
|
+
sage: U = Manifold('dLQbcbchecv')
|
|
58
|
+
sage: ab = MapToAbelianization(U.fundamental_group())
|
|
59
|
+
sage: ab.range()
|
|
60
|
+
Multiplicative Abelian group isomorphic to Z
|
|
61
|
+
sage: ab('aaa')
|
|
62
|
+
t^3
|
|
63
|
+
"""
|
|
64
|
+
def __init__(self, fund_group):
|
|
65
|
+
self.domain_gens = fund_group.generators()
|
|
66
|
+
ab_words = [abelianize_word(R, self.domain_gens) for R in fund_group.relators()]
|
|
67
|
+
if not ab_words:
|
|
68
|
+
n = fund_group.num_generators()
|
|
69
|
+
self.elementary_divisors = n*[0,]
|
|
70
|
+
self.U = identity_matrix(n)
|
|
71
|
+
else:
|
|
72
|
+
R = matrix(ZZ, ab_words).transpose()
|
|
73
|
+
D, U, V = R.smith_form()
|
|
74
|
+
m = U.nrows()
|
|
75
|
+
assert m == D.nrows()
|
|
76
|
+
d = min(D.nrows(), D.ncols())
|
|
77
|
+
diag = D.diagonal()
|
|
78
|
+
num_ones = diag.count(1)
|
|
79
|
+
self.elementary_divisors = diag[num_ones:] + [0,]*(m - d)
|
|
80
|
+
self.U = U[num_ones:]
|
|
81
|
+
|
|
82
|
+
tor = [d for d in self.elementary_divisors if d != 0]
|
|
83
|
+
free = [d for d in self.elementary_divisors if d == 0]
|
|
84
|
+
names = []
|
|
85
|
+
if len(tor) == 1:
|
|
86
|
+
names.append('u')
|
|
87
|
+
else:
|
|
88
|
+
names += ['u%d' % i for i in range(len(tor))]
|
|
89
|
+
if len(free) == 1:
|
|
90
|
+
names.append('t')
|
|
91
|
+
else:
|
|
92
|
+
names += ['t%d' % i for i in range(len(free))]
|
|
93
|
+
self._range = AbelianGroup(self.elementary_divisors, names=names)
|
|
94
|
+
|
|
95
|
+
def range(self):
|
|
96
|
+
return self._range
|
|
97
|
+
|
|
98
|
+
def _normalize_exponents(self, exponents):
|
|
99
|
+
D = self.elementary_divisors
|
|
100
|
+
return [v % d if d > 0 else v for (v, d) in zip(exponents, D)]
|
|
101
|
+
|
|
102
|
+
def _exponents_of_word(self, word):
|
|
103
|
+
exponents = self.U*abelianize_word(word, self.domain_gens)
|
|
104
|
+
return self._normalize_exponents(exponents)
|
|
105
|
+
|
|
106
|
+
def __call__(self, word):
|
|
107
|
+
return self._range(self._exponents_of_word(word))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class MapToFreeAbelianization(MapToAbelianization):
|
|
111
|
+
def range(self):
|
|
112
|
+
return ZZ**self.elementary_divisors.count(0)
|
|
113
|
+
|
|
114
|
+
def __call__(self, word):
|
|
115
|
+
D = self.elementary_divisors
|
|
116
|
+
v = self.U*abelianize_word(word, self.domain_gens)
|
|
117
|
+
return vector(ZZ, [v[i] for i in range(len(D)) if D[i] == 0])
|
|
118
|
+
|
|
119
|
+
# Finding the longitude
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@sage_method
|
|
123
|
+
def homological_longitude(manifold, cusp=None):
|
|
124
|
+
"""
|
|
125
|
+
Returns the peripheral curve in the given cusp, if any, which is
|
|
126
|
+
homologically trivial (with rational coefficients) in the manifold::
|
|
127
|
+
|
|
128
|
+
sage: M = Manifold('m015')
|
|
129
|
+
sage: M.homological_longitude()
|
|
130
|
+
(2, -1)
|
|
131
|
+
|
|
132
|
+
If no cusp is specified, the default is the first unfilled cusp;
|
|
133
|
+
if all cusps are filled, the default is the first cusp::
|
|
134
|
+
|
|
135
|
+
sage: M = Manifold('L5a1(3,4)(0,0)')
|
|
136
|
+
sage: M.homological_longitude()
|
|
137
|
+
(0, 1)
|
|
138
|
+
|
|
139
|
+
The components of the next link have nontrivial linking number
|
|
140
|
+
so there is no such curve::
|
|
141
|
+
|
|
142
|
+
sage: W = Manifold('L7a2')
|
|
143
|
+
sage: W.homological_longitude(cusp=1) is None
|
|
144
|
+
True
|
|
145
|
+
|
|
146
|
+
If every curve in the given cusp is trivial in the rational homology of
|
|
147
|
+
the manifold, an exception is raised::
|
|
148
|
+
|
|
149
|
+
sage: M = Manifold('4_1(1,0)')
|
|
150
|
+
sage: M.homological_longitude()
|
|
151
|
+
Traceback (most recent call last):
|
|
152
|
+
...
|
|
153
|
+
ValueError: Every curve on cusp is homologically trivial
|
|
154
|
+
"""
|
|
155
|
+
if cusp is None:
|
|
156
|
+
unfilled = [i for i, status in
|
|
157
|
+
enumerate(manifold.cusp_info('complete?')) if status]
|
|
158
|
+
if len(unfilled):
|
|
159
|
+
cusp = unfilled[0]
|
|
160
|
+
else:
|
|
161
|
+
cusp = 0
|
|
162
|
+
G = manifold.fundamental_group()
|
|
163
|
+
f = MapToFreeAbelianization(G)
|
|
164
|
+
m, l = G.peripheral_curves()[cusp]
|
|
165
|
+
kernel_basis = matrix(ZZ, [f(m), f(l)]).left_kernel().basis()
|
|
166
|
+
if len(kernel_basis) >= 2:
|
|
167
|
+
raise ValueError('Every curve on cusp is homologically trivial')
|
|
168
|
+
if len(kernel_basis) == 0:
|
|
169
|
+
return None
|
|
170
|
+
return kernel_basis[0]
|
|
171
|
+
|
|
172
|
+
# --------------------------------------------------------------
|
|
173
|
+
#
|
|
174
|
+
# Computing the Alexander polynomial
|
|
175
|
+
#
|
|
176
|
+
# --------------------------------------------------------------
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class MapToGroupRingOfAbelianization(MapToAbelianization):
|
|
180
|
+
"""
|
|
181
|
+
sage: M = Manifold('m003')
|
|
182
|
+
sage: G = M.fundamental_group()
|
|
183
|
+
sage: psi = MapToGroupRingOfAbelianization(G)
|
|
184
|
+
sage: psi('ab') + psi('AAAAB')
|
|
185
|
+
u*t + u^4*t^-4
|
|
186
|
+
"""
|
|
187
|
+
def __init__(self, fund_group, base_ring=ZZ):
|
|
188
|
+
MapToAbelianization.__init__(self, fund_group)
|
|
189
|
+
self.H = H = self._range # The abelian group
|
|
190
|
+
self.R = GroupAlgebra(H, base_ring)
|
|
191
|
+
|
|
192
|
+
def range(self):
|
|
193
|
+
return self.R
|
|
194
|
+
|
|
195
|
+
def __call__(self, word):
|
|
196
|
+
v = MapToAbelianization.__call__(self, word)
|
|
197
|
+
return self.R.monomial(v)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class MapToGroupRingOfFreeAbelianization(MapToFreeAbelianization):
|
|
201
|
+
def __init__(self, fund_group, base_ring=ZZ):
|
|
202
|
+
MapToFreeAbelianization.__init__(self, fund_group)
|
|
203
|
+
n = self.elementary_divisors.count(0)
|
|
204
|
+
self.R = LaurentPolynomialRing(base_ring, list(string.ascii_lowercase[:n]))
|
|
205
|
+
|
|
206
|
+
def range(self):
|
|
207
|
+
return self.R
|
|
208
|
+
|
|
209
|
+
def __call__(self, word):
|
|
210
|
+
v = MapToFreeAbelianization.__call__(self, word)
|
|
211
|
+
return prod([ g**v[i] for i, g in enumerate(self.R.gens())])
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def setup_fox_derivative(word, phi, var, involute=False):
|
|
215
|
+
R = phi.range()
|
|
216
|
+
if len(word) == 0:
|
|
217
|
+
return R.zero()
|
|
218
|
+
|
|
219
|
+
# Cache things for speed
|
|
220
|
+
|
|
221
|
+
gens = list(set( (var + word).lower() ))
|
|
222
|
+
gens += [g.upper() for g in gens]
|
|
223
|
+
|
|
224
|
+
phi_ims = {}
|
|
225
|
+
fox_ders = {}
|
|
226
|
+
for g in gens:
|
|
227
|
+
phi_ims[g] = phi(g) if not involute else phi(g.swapcase())
|
|
228
|
+
if g == g.lower():
|
|
229
|
+
fox_ders[g] = R.zero() if g != var else R.one()
|
|
230
|
+
else:
|
|
231
|
+
fox_ders[g] = R.zero() if g.lower() != var else -phi_ims[var.upper()]
|
|
232
|
+
|
|
233
|
+
return R, phi_ims, fox_ders
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def fox_derivative(word, phi, var):
|
|
237
|
+
"""
|
|
238
|
+
Given a homorphism phi of a group pi, computes
|
|
239
|
+
phi( d word / d var), i.e. the image of the fox derivative
|
|
240
|
+
of the word with respect to var.
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
R, phi_ims, fox_ders = setup_fox_derivative(word, phi, var)
|
|
244
|
+
D = 0
|
|
245
|
+
for w in reverse_word(word):
|
|
246
|
+
D = fox_ders[w] + phi_ims[w] * D
|
|
247
|
+
return D
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def fox_derivative_with_involution(word, phi, var):
|
|
251
|
+
"""
|
|
252
|
+
The group ring Z[pi] has a natural involution iota sends
|
|
253
|
+
g in pi to g^-1 and respects addition. This function
|
|
254
|
+
computes
|
|
255
|
+
|
|
256
|
+
phi( iota( d word / d var) )
|
|
257
|
+
"""
|
|
258
|
+
R, phi_ims, fox_ders = setup_fox_derivative(word, phi, var, involute=True)
|
|
259
|
+
D = 0
|
|
260
|
+
for w in reverse_word(word):
|
|
261
|
+
D = fox_ders[w] + D * phi_ims[w]
|
|
262
|
+
return D
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
# It's best to deal with matrices of polynomials rather than Laurent
|
|
266
|
+
# polynomials, so we need to be able to clear denominators. This add
|
|
267
|
+
# to the complexity of the code.
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def join_lists(list_of_lists):
|
|
271
|
+
for L in list_of_lists:
|
|
272
|
+
yield from L
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def uniform_poly_exponents(poly):
|
|
276
|
+
if poly.parent().ngens() == 1:
|
|
277
|
+
return [(e,) for e in poly.exponents()]
|
|
278
|
+
return poly.exponents()
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def minimum_exponents(elts):
|
|
282
|
+
exps = iter(join_lists(uniform_poly_exponents(p) for p in elts))
|
|
283
|
+
mins = list(next(exps))
|
|
284
|
+
n = len(mins)
|
|
285
|
+
for e in exps:
|
|
286
|
+
for i in range(n):
|
|
287
|
+
if e[i] < mins[i]:
|
|
288
|
+
mins[i] = e[i]
|
|
289
|
+
return mins
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def convert_laurent_to_poly(elt, minexp, P):
|
|
293
|
+
if P.ngens() == 1:
|
|
294
|
+
f = minexp[0]
|
|
295
|
+
return P({e - f: c for e, c in elt.dict().items()})
|
|
296
|
+
return P({tuple(e - f for e, f in zip(exps, minexp)): c
|
|
297
|
+
for exps, c in elt.dict().items()})
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def alexander_polynomial_basic(G, phi, d=0, pos_leading_coeff=False):
|
|
301
|
+
"""
|
|
302
|
+
Compute the d-th Alexander polynomial, i.e. the gcd of the
|
|
303
|
+
(d + 1)-st elementrary ideal of A(M).
|
|
304
|
+
"""
|
|
305
|
+
R = phi.range()
|
|
306
|
+
P = R.polynomial_ring()
|
|
307
|
+
if G.num_relators() == 0:
|
|
308
|
+
return 1 if G.num_generators() <= d + 1 else 0
|
|
309
|
+
M = [[fox_derivative(rel, phi, var) for rel in G.relators()]
|
|
310
|
+
for var in G.generators()]
|
|
311
|
+
entries = sum(M, [])
|
|
312
|
+
if all(e == 0 for e in entries):
|
|
313
|
+
M = matrix(P, M)
|
|
314
|
+
else:
|
|
315
|
+
minexp = minimum_exponents(entries)
|
|
316
|
+
M = matrix(P, [[ convert_laurent_to_poly(p, minexp, P) for p in row]
|
|
317
|
+
for row in M])
|
|
318
|
+
alex_poly = gcd(M.minors(G.num_generators() - d - 1))
|
|
319
|
+
if alex_poly == 0:
|
|
320
|
+
return alex_poly
|
|
321
|
+
|
|
322
|
+
# Normalize it
|
|
323
|
+
alex_poly = convert_laurent_to_poly(alex_poly, minimum_exponents([alex_poly]), P)
|
|
324
|
+
if pos_leading_coeff:
|
|
325
|
+
e = max(alex_poly.exponents())
|
|
326
|
+
if alex_poly[e] < 0:
|
|
327
|
+
alex_poly = -alex_poly
|
|
328
|
+
|
|
329
|
+
return alex_poly
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def alexander_polynomial_group(G):
|
|
333
|
+
phi = MapToGroupRingOfFreeAbelianization(G)
|
|
334
|
+
return alexander_polynomial_basic(G, phi, d=0, pos_leading_coeff=True)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
@sage_method
|
|
338
|
+
def alexander_polynomial(manifold, **kwargs):
|
|
339
|
+
"""
|
|
340
|
+
Computes the multivariable Alexander polynomial of the manifold::
|
|
341
|
+
|
|
342
|
+
sage: M = Manifold('K12n123')
|
|
343
|
+
sage: M.alexander_polynomial()
|
|
344
|
+
2*a^6 - 14*a^5 + 34*a^4 - 45*a^3 + 34*a^2 - 14*a + 2
|
|
345
|
+
|
|
346
|
+
sage: N = Triangulation('v1539(5,1)')
|
|
347
|
+
sage: N.alexander_polynomial()
|
|
348
|
+
a^2*b + a*b^2 + a*b + a + b
|
|
349
|
+
|
|
350
|
+
Any provided keyword arguments are passed to
|
|
351
|
+
:meth:`fundamental_group <snappy.Triangulation.fundamental_group>` and
|
|
352
|
+
so affect the group presentation used in the computation.
|
|
353
|
+
"""
|
|
354
|
+
if manifold.homology().order() != 'infinite':
|
|
355
|
+
raise ValueError(
|
|
356
|
+
"Alexander polynomial only defined for manifolds with "
|
|
357
|
+
"infinite homology.")
|
|
358
|
+
|
|
359
|
+
return alexander_polynomial_group(manifold.fundamental_group(**kwargs))
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
# --------------------------------------------------------------
|
|
363
|
+
#
|
|
364
|
+
# Computing the twisted torsion polynomials
|
|
365
|
+
# for deficiency one presentations.
|
|
366
|
+
#
|
|
367
|
+
# --------------------------------------------------------------
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
class PhiAlpha():
|
|
371
|
+
def __init__(self, phi, alpha):
|
|
372
|
+
self.base_ring = phi.range()
|
|
373
|
+
self.image_ring = MatrixSpace(self.base_ring, 2)
|
|
374
|
+
self.phi, self.alpha = phi, alpha
|
|
375
|
+
|
|
376
|
+
def range(self):
|
|
377
|
+
return self.image_ring
|
|
378
|
+
|
|
379
|
+
def __call__(self, word):
|
|
380
|
+
a = self.phi(word)
|
|
381
|
+
A = self.alpha(word)
|
|
382
|
+
M = self.image_ring(0)
|
|
383
|
+
M[0,0], M[0,1], M[1,0], M[1,1] = a*A[0,0], a*A[0,1], a*A[1,0], a*A[1,1]
|
|
384
|
+
return M
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def free_monoid_elt_to_string(elt):
|
|
388
|
+
vars = elt.parent().variable_names()
|
|
389
|
+
return "".join([e*vars[v] for v, e in elt._element_list])
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def inverse_word(word):
|
|
393
|
+
L = list(word.swapcase())
|
|
394
|
+
L.reverse()
|
|
395
|
+
return "".join(L)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def reverse_word(word):
|
|
399
|
+
L = list(word)
|
|
400
|
+
L.reverse()
|
|
401
|
+
return "".join(L)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def clean_RR(r, error):
|
|
405
|
+
return 0 if abs(r) < error else r
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def clean_CC(z, error):
|
|
409
|
+
CC = z.parent()
|
|
410
|
+
return CC( clean_RR(z.real(),error), clean_RR(z.imag(), error) ) if not CC.is_exact() else z
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def univ_exponents(p):
|
|
414
|
+
try:
|
|
415
|
+
return [a[0] for a in p.exponents()]
|
|
416
|
+
except TypeError:
|
|
417
|
+
return p.exponents()
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
def clean_laurent(p, error):
|
|
421
|
+
R = p.parent()
|
|
422
|
+
t = R.gen()
|
|
423
|
+
new_coeffs = [clean_CC(z, error) for z in p.coefficients()]
|
|
424
|
+
return sum( [a*t**n for a , n in zip(new_coeffs, univ_exponents(p))], R.zero())
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def clean_laurent_to_poly(p, error=10**-8):
|
|
428
|
+
R = p.parent()
|
|
429
|
+
P = PolynomialRing(R.base_ring(), R.variable_names())
|
|
430
|
+
t = P.gen()
|
|
431
|
+
cp = clean_laurent(p,error)
|
|
432
|
+
exponents = univ_exponents(cp)
|
|
433
|
+
if len(exponents) == 0:
|
|
434
|
+
return P(0)
|
|
435
|
+
m = min(exponents)
|
|
436
|
+
return sum( [a*t**(n-m) for a,n in zip(cp.coefficients(), exponents)], P(0))
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def univ_abs(z):
|
|
440
|
+
"""
|
|
441
|
+
Compute a reasonable choice for the absolute value of z.
|
|
442
|
+
"""
|
|
443
|
+
try:
|
|
444
|
+
return z.abs()
|
|
445
|
+
except (TypeError, AttributeError):
|
|
446
|
+
if hasattr(z, 'coefficients'):
|
|
447
|
+
return max([0,] + [univ_abs(c) for c in z.coefficients()])
|
|
448
|
+
else:
|
|
449
|
+
return 0 if z == 0 else Infinity
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def univ_matrix_norm(A):
|
|
453
|
+
return max([0] + [univ_abs(a) for a in A.list()])
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
def matrix_has_small_entries(A, bound):
|
|
457
|
+
if A.base_ring().is_exact():
|
|
458
|
+
return A == 0
|
|
459
|
+
else:
|
|
460
|
+
return univ_matrix_norm(A) < bound
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
def last_square_submatrix(A):
|
|
464
|
+
r, c = A.nrows(), A.ncols()
|
|
465
|
+
if r <= c:
|
|
466
|
+
return A.matrix_from_columns( range(c - r, c) )
|
|
467
|
+
else:
|
|
468
|
+
return A.matrix_from_rows( range( r - c, r) )
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def first_square_submatrix(A):
|
|
472
|
+
r, c = A.nrows(), A.ncols()
|
|
473
|
+
if r <= c:
|
|
474
|
+
return A.matrix_from_columns( range(r) )
|
|
475
|
+
else:
|
|
476
|
+
return A.matrix_from_rows( range(c) )
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
class TorsionComputationError(Exception):
|
|
480
|
+
pass
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def fast_determinant_of_laurent_poly_matrix(A):
|
|
484
|
+
"""
|
|
485
|
+
Return the determinant of the given matrix up to
|
|
486
|
+
a power of t^n, using the faster algorithm for
|
|
487
|
+
polynomial entries.
|
|
488
|
+
"""
|
|
489
|
+
R = A.base_ring()
|
|
490
|
+
P = R.polynomial_ring()
|
|
491
|
+
if A == 0:
|
|
492
|
+
return P(0)
|
|
493
|
+
minexp = minimum_exponents(A.list())
|
|
494
|
+
MS = A.parent().change_ring(P)
|
|
495
|
+
Ap = MS([convert_laurent_to_poly(p, minexp, P) for p in A.list()])
|
|
496
|
+
return Ap.det()
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def compute_torsion(G, bits_prec, alpha=None, phi=None, phialpha=None,
|
|
500
|
+
return_parts=False, return_as_poly=True,
|
|
501
|
+
wada_conventions=False, symmetry_test=True):
|
|
502
|
+
if alpha:
|
|
503
|
+
F = alpha('a').base_ring()
|
|
504
|
+
elif phialpha:
|
|
505
|
+
F = phialpha('a').base_ring().base_ring()
|
|
506
|
+
epsilon = ZZ(2)**(-bits_prec//3) if not F.is_exact() else None
|
|
507
|
+
big_epsilon = ZZ(2)**(-bits_prec//5) if not F.is_exact() else None
|
|
508
|
+
gens, rels = G.generators(), G.relators()
|
|
509
|
+
|
|
510
|
+
if len(rels) != len(gens) - 1:
|
|
511
|
+
raise ValueError(
|
|
512
|
+
"Algorithm to compute torsion requires a group presentation "
|
|
513
|
+
"with deficiency one")
|
|
514
|
+
|
|
515
|
+
k = len(gens)
|
|
516
|
+
if phi is None:
|
|
517
|
+
phi = MapToGroupRingOfFreeAbelianization(G, F)
|
|
518
|
+
|
|
519
|
+
if len(phi.range().gens()) != 1:
|
|
520
|
+
raise ValueError(
|
|
521
|
+
"Algorithm to compute torsion requires betti number 1")
|
|
522
|
+
|
|
523
|
+
# Want the first variable to be homologically nontrivial
|
|
524
|
+
i0 = [i for i, g in enumerate(gens) if phi(g) != 1][0]
|
|
525
|
+
gens = gens[i0:] + gens[:i0]
|
|
526
|
+
if phialpha is None:
|
|
527
|
+
phialpha = PhiAlpha(phi, alpha)
|
|
528
|
+
|
|
529
|
+
# Boundary maps for chain complex
|
|
530
|
+
|
|
531
|
+
if not wada_conventions: # Using the conventions of our paper.
|
|
532
|
+
d2 = [ [fox_derivative_with_involution(R, phialpha, g) for R in rels] for g in gens]
|
|
533
|
+
d2 = block_matrix(d2, nrows=k, ncols=k-1)
|
|
534
|
+
d1 = [phialpha(g.swapcase()) - 1 for g in gens]
|
|
535
|
+
d1 = block_matrix(d1, nrows=1, ncols=k)
|
|
536
|
+
dsquared = d1 * d2
|
|
537
|
+
|
|
538
|
+
else: # Using those implicit in Wada's paper.
|
|
539
|
+
d2 = [ [fox_derivative(R, phialpha, g) for g in gens] for R in rels]
|
|
540
|
+
d2 = block_matrix(sum(d2, []), nrows=k-1, ncols=k)
|
|
541
|
+
d1 = [phialpha(g) - 1 for g in gens]
|
|
542
|
+
d1 = block_matrix(d1, nrows=k, ncols=1)
|
|
543
|
+
dsquared = d2 * d1
|
|
544
|
+
|
|
545
|
+
if not matrix_has_small_entries( dsquared, epsilon ):
|
|
546
|
+
raise TorsionComputationError("(boundary)^2 != 0")
|
|
547
|
+
|
|
548
|
+
T = last_square_submatrix(d2)
|
|
549
|
+
if return_as_poly:
|
|
550
|
+
T = fast_determinant_of_laurent_poly_matrix(T)
|
|
551
|
+
else:
|
|
552
|
+
T = det(T)
|
|
553
|
+
B = first_square_submatrix(d1)
|
|
554
|
+
B = det(B)
|
|
555
|
+
if return_as_poly:
|
|
556
|
+
T = clean_laurent_to_poly(T, epsilon)
|
|
557
|
+
B = clean_laurent_to_poly(B, epsilon)
|
|
558
|
+
else:
|
|
559
|
+
T = clean_laurent(T, epsilon)
|
|
560
|
+
B = clean_laurent(B, epsilon)
|
|
561
|
+
|
|
562
|
+
if return_parts:
|
|
563
|
+
return (T, B)
|
|
564
|
+
|
|
565
|
+
q, r = T.quo_rem(B)
|
|
566
|
+
ans = clean_laurent_to_poly(q, epsilon)
|
|
567
|
+
if (not F.is_exact() and univ_abs(r) > epsilon) or (F.is_exact() and r != 0):
|
|
568
|
+
raise TorsionComputationError("Division failed")
|
|
569
|
+
|
|
570
|
+
# Now do a quick sanity check
|
|
571
|
+
|
|
572
|
+
if symmetry_test:
|
|
573
|
+
coeffs = ans.coefficients()
|
|
574
|
+
error = max([univ_abs(a-b) for a,b in zip(coeffs, reversed(coeffs))], default=0)
|
|
575
|
+
if (not F.is_exact() and error > epsilon) or (F.is_exact() and error != 0):
|
|
576
|
+
raise TorsionComputationError("Torsion polynomial doesn't seem symmetric")
|
|
577
|
+
|
|
578
|
+
return ans
|
|
579
|
+
|
|
580
|
+
# --------------------------------------------------------------
|
|
581
|
+
#
|
|
582
|
+
# Computing the torsion polynomials
|
|
583
|
+
# for the *adjoint* representation
|
|
584
|
+
# i.e. the poly of Dubois-Yamaguichi
|
|
585
|
+
# --------------------------------------------------------------
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
def adjoint_action(A):
|
|
589
|
+
a, b, c, d = A.list()
|
|
590
|
+
return matrix( [[a**2, 2*a*b, b**2],[a*c,b*c+a*d,b*d],[c**2,2*c*d,d**2]] )
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
def SL2_to_SLN(A, N):
|
|
594
|
+
F = A.base_ring()
|
|
595
|
+
R = PolynomialRing(F, ['x', 'y'])
|
|
596
|
+
x, y = R.gens()
|
|
597
|
+
X, Y = A * vector(R, (x, y))
|
|
598
|
+
monomials = [x**(N - 1 - i) * y**i for i in range(N)]
|
|
599
|
+
image_vectors = [m(X, Y) for m in monomials]
|
|
600
|
+
return matrix(F, [[v.monomial_coefficient(m) for m in monomials] for v in image_vectors])
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
class PhiAlpha3():
|
|
604
|
+
def __init__(self, phi, alpha):
|
|
605
|
+
self.base_ring = phi.range()
|
|
606
|
+
self.image_ring = MatrixSpace(self.base_ring, 3)
|
|
607
|
+
self.phi, self.alpha = phi, alpha
|
|
608
|
+
|
|
609
|
+
def range(self):
|
|
610
|
+
return self.image_ring
|
|
611
|
+
|
|
612
|
+
def __call__(self, word):
|
|
613
|
+
a = self.phi(word)
|
|
614
|
+
A = adjoint_action(self.alpha(word))
|
|
615
|
+
M = self.image_ring(0)
|
|
616
|
+
for i in range(3):
|
|
617
|
+
for j in range(3):
|
|
618
|
+
M[i,j] = a*A[i,j]
|
|
619
|
+
|
|
620
|
+
return M
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
class PhiAlphaN():
|
|
624
|
+
def __init__(self, phi, alpha, N):
|
|
625
|
+
self.base_ring = phi.range()
|
|
626
|
+
self.image_ring = MatrixSpace(self.base_ring, N)
|
|
627
|
+
self.phi, self.alpha, self.N = phi, alpha, N
|
|
628
|
+
|
|
629
|
+
def range(self):
|
|
630
|
+
return self.image_ring
|
|
631
|
+
|
|
632
|
+
def __call__(self, word):
|
|
633
|
+
a = self.phi(word)
|
|
634
|
+
A = SL2_to_SLN(self.alpha(word), self.N)
|
|
635
|
+
M = self.image_ring(0)
|
|
636
|
+
for i in range(self.N):
|
|
637
|
+
for j in range(self.N):
|
|
638
|
+
M[i,j] = a*A[i,j]
|
|
639
|
+
|
|
640
|
+
return M
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
def test_rep(G, phialpha):
|
|
644
|
+
def manually_apply_word(w):
|
|
645
|
+
return prod(phialpha(x) for x in w)
|
|
646
|
+
return max([univ_matrix_norm(manually_apply_word(R) - 1) for R in G.relators()])
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
@sage_method
|
|
650
|
+
def hyperbolic_torsion(manifold, bits_prec=100, all_lifts=False, wada_conventions=False, phi=None):
|
|
651
|
+
"""
|
|
652
|
+
Computes the hyperbolic torsion polynomial as defined in
|
|
653
|
+
`[DFJ] <http://arxiv.org/abs/1108.3045>`_::
|
|
654
|
+
|
|
655
|
+
sage: M = Manifold('K11n42')
|
|
656
|
+
sage: M.alexander_polynomial()
|
|
657
|
+
1
|
|
658
|
+
sage: tau = M.hyperbolic_torsion(bits_prec=200)
|
|
659
|
+
sage: tau.degree()
|
|
660
|
+
6
|
|
661
|
+
"""
|
|
662
|
+
if manifold.homology().betti_number() != 1:
|
|
663
|
+
raise ValueError('Algorithm needs H^1(M; Z) = Z to be able to compute torsion')
|
|
664
|
+
H = manifold.fundamental_group()
|
|
665
|
+
if H.num_generators() != H.num_relators() + 1:
|
|
666
|
+
raise ValueError('Algorithm to compute torsion requires a group presentation '
|
|
667
|
+
'with deficiency one')
|
|
668
|
+
G = alpha = polished_holonomy(manifold, bits_prec=bits_prec, lift_to_SL2=True)
|
|
669
|
+
if not all_lifts:
|
|
670
|
+
return compute_torsion(G, bits_prec, alpha, phi, wada_conventions=wada_conventions)
|
|
671
|
+
else:
|
|
672
|
+
return [compute_torsion(G, bits_prec, beta, phi, wada_conventions=wada_conventions)
|
|
673
|
+
for beta in alpha.all_lifts_to_SL2C()]
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
@sage_method
|
|
677
|
+
def hyperbolic_SLN_torsion(manifold, N, bits_prec=100):
|
|
678
|
+
"""
|
|
679
|
+
Compute the torsion polynomial of the holonomy representation lifted
|
|
680
|
+
to SL(2, C) and then followed by the irreducible representation
|
|
681
|
+
from SL(2, C) -> SL(N, C)::
|
|
682
|
+
|
|
683
|
+
sage: M = Manifold('m016')
|
|
684
|
+
sage: [M.hyperbolic_SLN_torsion(N).degree() for N in [2, 3, 4]]
|
|
685
|
+
[18, 27, 36]
|
|
686
|
+
"""
|
|
687
|
+
if manifold.homology().betti_number() != 1:
|
|
688
|
+
raise ValueError('Algorithm needs H^1(M; Z) = Z to be able to compute torsion')
|
|
689
|
+
H = manifold.fundamental_group()
|
|
690
|
+
if H.num_generators() != H.num_relators() + 1:
|
|
691
|
+
raise ValueError('Algorithm to compute torsion requires a group presentation '
|
|
692
|
+
'with deficiency one')
|
|
693
|
+
G = alpha = polished_holonomy(manifold, bits_prec)
|
|
694
|
+
phi = MapToGroupRingOfFreeAbelianization(G, alpha('a').base_ring())
|
|
695
|
+
phialpha = PhiAlphaN(phi, alpha, N)
|
|
696
|
+
if not test_rep(G, phialpha) < ZZ(2)**(bits_prec // 2):
|
|
697
|
+
raise RuntimeError("Invalid representation")
|
|
698
|
+
return compute_torsion(G, bits_prec, phialpha=phialpha, symmetry_test=False)
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
@sage_method
|
|
702
|
+
def hyperbolic_adjoint_torsion(manifold, bits_prec=100):
|
|
703
|
+
"""
|
|
704
|
+
Computes the torsion polynomial of the adjoint representation
|
|
705
|
+
a la Dubois-Yamaguichi. This is not a sign-refined computation
|
|
706
|
+
so the result is only defined up to sign, not to mention a power
|
|
707
|
+
of the variable 'a'::
|
|
708
|
+
|
|
709
|
+
sage: M = Manifold('K11n42')
|
|
710
|
+
sage: tau = M.hyperbolic_adjoint_torsion()
|
|
711
|
+
sage: tau.parent()
|
|
712
|
+
Univariate Polynomial Ring in a over Complex Field with 100 bits of precision
|
|
713
|
+
sage: tau.degree()
|
|
714
|
+
7
|
|
715
|
+
"""
|
|
716
|
+
return hyperbolic_SLN_torsion(manifold, 3, bits_prec)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .peripheral import peripheral_cohomology_basis
|