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,569 @@
|
|
|
1
|
+
from .mcomplex_base import *
|
|
2
|
+
from .kernel_structures import *
|
|
3
|
+
from . import t3mlite as t3m
|
|
4
|
+
from .t3mlite import ZeroSubsimplices, simplex
|
|
5
|
+
from .t3mlite import Corner, Perm4
|
|
6
|
+
from .t3mlite import V0, V1, V2, V3
|
|
7
|
+
from ..math_basics import prod
|
|
8
|
+
from functools import reduce
|
|
9
|
+
|
|
10
|
+
__all__ = ['FundamentalPolyhedronEngine']
|
|
11
|
+
|
|
12
|
+
from ..sage_helper import _within_sage
|
|
13
|
+
if _within_sage:
|
|
14
|
+
from ..sage_helper import matrix
|
|
15
|
+
else:
|
|
16
|
+
from .utilities import Matrix2x2 as matrix
|
|
17
|
+
|
|
18
|
+
_VerticesInFace = {
|
|
19
|
+
F: [V for V in simplex.ZeroSubsimplices if t3m.is_subset(V, F)]
|
|
20
|
+
for F in simplex.TwoSubsimplices }
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class FundamentalPolyhedronEngine(McomplexEngine):
|
|
24
|
+
@staticmethod
|
|
25
|
+
def from_manifold_and_shapes(
|
|
26
|
+
manifold, shapes, normalize_matrices=False, match_kernel=True):
|
|
27
|
+
"""
|
|
28
|
+
Given a SnapPy.Manifold and shapes (which can be numbers or intervals),
|
|
29
|
+
create a t3mlite.Mcomplex for the fundamental polyhedron that the
|
|
30
|
+
SnapPea kernel computed, assign each vertex of it to a point on the
|
|
31
|
+
boundary of upper half space H^3, and compute the matrices pairing the
|
|
32
|
+
faces of the fundamental polyhedron. The matrices will have determinant
|
|
33
|
+
one if normalize_matrices is True.
|
|
34
|
+
|
|
35
|
+
Some notes about the vertices: We use the one-point
|
|
36
|
+
compactification to represent the boundary of H^3, i.e., we
|
|
37
|
+
either assign a complex number (or interval) to a vertex or
|
|
38
|
+
Infinity (a sentinel in kernel_structures). If match_kernel is True,
|
|
39
|
+
the vertices are at the same positions than in the SnapPea kernel.
|
|
40
|
+
This has the disadvantage that the matrices computed that way no longer
|
|
41
|
+
have entries in the trace field. Use match_kernel is False for matrices
|
|
42
|
+
over the trace field (e.g., obtain the quaternion algebra).
|
|
43
|
+
|
|
44
|
+
Some notes about the matrices: If normalize_matrices is False, the
|
|
45
|
+
product of a matrix for a generator and its inverse is not necessarily
|
|
46
|
+
the identity, but a multiple of the identity.
|
|
47
|
+
Even if normalize_matrices is True, the product of matrices
|
|
48
|
+
corresponding to the letters in a relation might still yield minus the
|
|
49
|
+
identity (i.e., we do not lift to SL(2,C)).
|
|
50
|
+
|
|
51
|
+
>>> M = Manifold("m004")
|
|
52
|
+
>>> F = FundamentalPolyhedronEngine.from_manifold_and_shapes(
|
|
53
|
+
... M, M.tetrahedra_shapes('rect'))
|
|
54
|
+
|
|
55
|
+
The above code adds the given shapes to each edge (here 01) of each
|
|
56
|
+
tetrahedron::
|
|
57
|
+
|
|
58
|
+
>>> from snappy.snap.t3mlite import simplex
|
|
59
|
+
>>> F.mcomplex.Tetrahedra[0].ShapeParameters[simplex.E01] # doctest: +NUMERIC6
|
|
60
|
+
0.500000000000000 + 0.866025403784438*I
|
|
61
|
+
|
|
62
|
+
And annotates each face (here 1) of each tetrahedron with the
|
|
63
|
+
corresponding generator (here, the inverse of the second generator)
|
|
64
|
+
or 0 if the face is internal to the fundamental polyhedron::
|
|
65
|
+
|
|
66
|
+
>>> F.mcomplex.Tetrahedra[0].GeneratorsInfo[simplex.F1]
|
|
67
|
+
-2
|
|
68
|
+
|
|
69
|
+
This information is also available in a dict keyed by generator.
|
|
70
|
+
For each generator, it gives a list of the corresponding face pairing
|
|
71
|
+
data (there might be multiple face pairings corresponding to the same
|
|
72
|
+
generator). The face pairing data consists of a pair of t3mlite.Corner's
|
|
73
|
+
indicating the paired faces as well as the permutation to take one
|
|
74
|
+
face to the other.
|
|
75
|
+
Here, for example, the generator corresponds to exactly one face
|
|
76
|
+
pairing of face 2 of tet 1 to face 1 of tet0 such that face 2 is
|
|
77
|
+
taken to face 1 by the permutation (3, 0, 1, 2)::
|
|
78
|
+
|
|
79
|
+
>>> F.mcomplex.Generators[2]
|
|
80
|
+
[((<F2 of tet1>, <F1 of tet0>), (3, 0, 1, 2))]
|
|
81
|
+
|
|
82
|
+
The four vertices of tetrahedron 1::
|
|
83
|
+
|
|
84
|
+
>>> for v in simplex.ZeroSubsimplices: # doctest: +NUMERIC6
|
|
85
|
+
... F.mcomplex.Tetrahedra[1].Class[v].IdealPoint
|
|
86
|
+
'Infinity'
|
|
87
|
+
0.000000000000000
|
|
88
|
+
0.866025403784439 - 0.500000000000000*I
|
|
89
|
+
0.866025403784439 + 0.500000000000000*I
|
|
90
|
+
|
|
91
|
+
The matrix for generator 1 (of the unsimplified presentation)::
|
|
92
|
+
|
|
93
|
+
>>> F.mcomplex.GeneratorMatrices[1] # doctest: +NUMERIC6 +ELLIPSIS
|
|
94
|
+
[ -0.577350269189626 - 1.00000000000000*I 0.500000000000000 + 0.288675134594813*I...]
|
|
95
|
+
[ -0.500000000000000 - 0.288675134594813*I 0.577350269189626 + 2.22044604925031e-16*I...]
|
|
96
|
+
|
|
97
|
+
Get the cusp that a vertex of the fundamental polyhedron corresponds
|
|
98
|
+
to::
|
|
99
|
+
|
|
100
|
+
>>> F.mcomplex.Tetrahedra[1].Class[simplex.V0].SubsimplexIndexInManifold
|
|
101
|
+
0
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
m = t3m.Mcomplex(manifold)
|
|
106
|
+
|
|
107
|
+
f = FundamentalPolyhedronEngine(m)
|
|
108
|
+
t = TransferKernelStructuresEngine(m, manifold)
|
|
109
|
+
|
|
110
|
+
t.add_shapes(shapes)
|
|
111
|
+
t.choose_and_transfer_generators(
|
|
112
|
+
compute_corners=True, centroid_at_origin=False)
|
|
113
|
+
|
|
114
|
+
f.unglue()
|
|
115
|
+
|
|
116
|
+
if match_kernel:
|
|
117
|
+
init_verts = f.init_vertices_kernel()
|
|
118
|
+
else:
|
|
119
|
+
init_verts = f.init_vertices()
|
|
120
|
+
|
|
121
|
+
f.visit_tetrahedra_to_compute_vertices(
|
|
122
|
+
m.ChooseGenInitialTet, init_verts)
|
|
123
|
+
f.compute_matrices(normalize_matrices=normalize_matrices)
|
|
124
|
+
|
|
125
|
+
return f
|
|
126
|
+
|
|
127
|
+
def unglue(self):
|
|
128
|
+
"""
|
|
129
|
+
It will unglue all face-pairings corresponding to generators.
|
|
130
|
+
What is left is a fundamental polyhedron.
|
|
131
|
+
|
|
132
|
+
It assumes that GeneratorsInfo has been set (by the
|
|
133
|
+
TranferKernelStructuresEngine).
|
|
134
|
+
|
|
135
|
+
Besides ungluing, it will add the field Generators to the Mcomplex
|
|
136
|
+
and SubsimplexIndexInManifold to each Vertex, Edge, Face, see
|
|
137
|
+
examples in from_manifold_and_shapes.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
originalSubsimplexIndices = [
|
|
141
|
+
[ tet.Class[subsimplex].Index for subsimplex in range(1, 15) ]
|
|
142
|
+
for tet in self.mcomplex.Tetrahedra ]
|
|
143
|
+
|
|
144
|
+
self.mcomplex.Generators = {}
|
|
145
|
+
|
|
146
|
+
# Record for each generators what faces need to be unglued as well as
|
|
147
|
+
# the permutations.
|
|
148
|
+
for tet in self.mcomplex.Tetrahedra:
|
|
149
|
+
for face in simplex.TwoSubsimplices:
|
|
150
|
+
# Index of generator
|
|
151
|
+
g = tet.GeneratorsInfo[face]
|
|
152
|
+
# g == 0 does not correspond to a generator
|
|
153
|
+
if g != 0:
|
|
154
|
+
# Add to dictionary value
|
|
155
|
+
l = self.mcomplex.Generators.setdefault(g, [])
|
|
156
|
+
l.append(
|
|
157
|
+
( (
|
|
158
|
+
# Inbound face
|
|
159
|
+
Corner(tet, face),
|
|
160
|
+
# Outbound face
|
|
161
|
+
Corner(tet.Neighbor[face], tet.Gluing[face].image(face))),
|
|
162
|
+
# Permutation
|
|
163
|
+
tet.Gluing[face]))
|
|
164
|
+
|
|
165
|
+
# Unglue
|
|
166
|
+
for g, pairings in self.mcomplex.Generators.items():
|
|
167
|
+
# Unglue only once, ignore inverse
|
|
168
|
+
if g > 0:
|
|
169
|
+
for corners, perm in pairings:
|
|
170
|
+
for corner in corners:
|
|
171
|
+
corner.Tetrahedron.attach(corner.Subsimplex, None, None)
|
|
172
|
+
|
|
173
|
+
# Rebuild the vertex classes, edge classes, ...
|
|
174
|
+
self.mcomplex.rebuild()
|
|
175
|
+
|
|
176
|
+
# Use the saved data to populate SubsimplexIndexInManifold
|
|
177
|
+
for tet, o in zip(self.mcomplex.Tetrahedra, originalSubsimplexIndices):
|
|
178
|
+
for subsimplex, index in enumerate(o):
|
|
179
|
+
tet.Class[subsimplex + 1].SubsimplexIndexInManifold = index
|
|
180
|
+
|
|
181
|
+
def visit_tetrahedra_to_compute_vertices(self, init_tet, init_vertices):
|
|
182
|
+
"""
|
|
183
|
+
Computes the positions of the vertices of fundamental polyhedron in
|
|
184
|
+
the boundary of H^3, assuming the Mcomplex has been unglued and
|
|
185
|
+
ShapeParameters were assigned to the tetrahedra.
|
|
186
|
+
|
|
187
|
+
It starts by assigning the vertices of the given init_tet using
|
|
188
|
+
init_vertices.
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
for vertex in self.mcomplex.Vertices:
|
|
192
|
+
vertex.IdealPoint = None
|
|
193
|
+
for tet in self.mcomplex.Tetrahedra:
|
|
194
|
+
tet.visited = False
|
|
195
|
+
|
|
196
|
+
self.mcomplex.InitialTet = init_tet
|
|
197
|
+
|
|
198
|
+
for v, idealPoint in init_vertices.items():
|
|
199
|
+
init_tet.Class[v].IdealPoint = idealPoint
|
|
200
|
+
init_tet.visited = True
|
|
201
|
+
|
|
202
|
+
queue = [ init_tet ]
|
|
203
|
+
while len(queue) > 0:
|
|
204
|
+
tet = queue.pop(0)
|
|
205
|
+
for F in simplex.TwoSubsimplices:
|
|
206
|
+
if bool(tet.Neighbor[F]) != bool(tet.GeneratorsInfo[F] == 0):
|
|
207
|
+
raise Exception(
|
|
208
|
+
"Improper fundamental domain, "
|
|
209
|
+
"probably a bug in unglue code")
|
|
210
|
+
|
|
211
|
+
S = tet.Neighbor[F]
|
|
212
|
+
if S and not S.visited:
|
|
213
|
+
perm = tet.Gluing[F]
|
|
214
|
+
for V in _VerticesInFace[F]:
|
|
215
|
+
vertex_class = S.Class[perm.image(V)]
|
|
216
|
+
if vertex_class.IdealPoint is None:
|
|
217
|
+
vertex_class.IdealPoint = tet.Class[V].IdealPoint
|
|
218
|
+
_compute_fourth_corner(S)
|
|
219
|
+
S.visited = True
|
|
220
|
+
queue.append(S)
|
|
221
|
+
|
|
222
|
+
def init_vertices(self):
|
|
223
|
+
"""
|
|
224
|
+
Computes vertices for the initial tetrahedron such that vertex 0, 1
|
|
225
|
+
and 2 are at Infinity, 0 and z.
|
|
226
|
+
"""
|
|
227
|
+
|
|
228
|
+
tet = self.mcomplex.ChooseGenInitialTet
|
|
229
|
+
|
|
230
|
+
z = tet.ShapeParameters[simplex.E01]
|
|
231
|
+
CF = z.parent()
|
|
232
|
+
|
|
233
|
+
return { simplex.V0 : Infinity,
|
|
234
|
+
simplex.V1 : CF(0),
|
|
235
|
+
simplex.V2 : CF(1),
|
|
236
|
+
simplex.V3 : z }
|
|
237
|
+
|
|
238
|
+
def init_vertices_kernel(self):
|
|
239
|
+
"""
|
|
240
|
+
Computes vertices for the initial tetrahedron matching the choices
|
|
241
|
+
made by the SnapPea kernel.
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
# Note that initial_tetrahedron in choose_generators.c picks
|
|
245
|
+
# the initial tetrahedron and best edge in a purely combinatorial way -
|
|
246
|
+
# and doesn't use shapes to assign 0 and Infinity to the ends of
|
|
247
|
+
# the edges.
|
|
248
|
+
#
|
|
249
|
+
# Hence, the code below can't be tricked into picking a different
|
|
250
|
+
# permutation by setting the unverified shapes stored in the
|
|
251
|
+
# kernel Triangulation (to some non-sensical values). It would fail
|
|
252
|
+
# instead.
|
|
253
|
+
|
|
254
|
+
tet = self.mcomplex.ChooseGenInitialTet
|
|
255
|
+
|
|
256
|
+
candidates = []
|
|
257
|
+
|
|
258
|
+
for perm in Perm4.A4():
|
|
259
|
+
z = tet.ShapeParameters[perm.image(simplex.E01)]
|
|
260
|
+
# Complex field
|
|
261
|
+
CF = z.parent()
|
|
262
|
+
sqrt_z = z.sqrt()
|
|
263
|
+
sqrt_z_inv = CF(1) / sqrt_z
|
|
264
|
+
|
|
265
|
+
candidate = {
|
|
266
|
+
perm.image(simplex.V0) : Infinity,
|
|
267
|
+
perm.image(simplex.V1) : CF(0),
|
|
268
|
+
perm.image(simplex.V2) : sqrt_z_inv,
|
|
269
|
+
perm.image(simplex.V3) : sqrt_z
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if _are_vertices_close_to_kernel(
|
|
273
|
+
candidate, tet.SnapPeaIdealVertices):
|
|
274
|
+
candidates.append(candidate)
|
|
275
|
+
|
|
276
|
+
if len(candidates) == 1:
|
|
277
|
+
return candidates[0]
|
|
278
|
+
|
|
279
|
+
raise Exception(
|
|
280
|
+
"Could not match vertices to vertices from SnapPea kernel")
|
|
281
|
+
|
|
282
|
+
def compute_matrices(self, normalize_matrices=False):
|
|
283
|
+
"""
|
|
284
|
+
Assuming positions were assigned to the vertices, adds
|
|
285
|
+
GeneratorMatrices to the Mcomplex which assigns a matrix to each
|
|
286
|
+
generator.
|
|
287
|
+
|
|
288
|
+
Compute generator matrices:
|
|
289
|
+
|
|
290
|
+
>>> M = Manifold("s776")
|
|
291
|
+
>>> F = FundamentalPolyhedronEngine.from_manifold_and_shapes(
|
|
292
|
+
... M, M.tetrahedra_shapes('rect'), normalize_matrices = True)
|
|
293
|
+
>>> generatorMatrices = F.mcomplex.GeneratorMatrices
|
|
294
|
+
|
|
295
|
+
Given a letter such as 'a' or 'A', return matrix for corresponding
|
|
296
|
+
generator:
|
|
297
|
+
|
|
298
|
+
>>> def letterToMatrix(l, generatorMatrices):
|
|
299
|
+
... g = ord(l.lower()) - ord('a') + 1
|
|
300
|
+
... if l.isupper():
|
|
301
|
+
... g = -g
|
|
302
|
+
... return generatorMatrices[g]
|
|
303
|
+
|
|
304
|
+
Check that relations are fulfilled up to sign:
|
|
305
|
+
|
|
306
|
+
>>> def p(L): return reduce(lambda x, y: x * y, L)
|
|
307
|
+
>>> def close_to_identity(m, epsilon = 1e-12):
|
|
308
|
+
... return abs(m[(0,0)] - 1) < epsilon and abs(m[(1,1)] - 1) < epsilon and abs(m[(0,1)]) < epsilon and abs(m[(1,0)]) < epsilon
|
|
309
|
+
>>> def close_to_pm_identity(m, epsilon = 1e-12):
|
|
310
|
+
... return close_to_identity(m, epsilon) or close_to_identity(-m, epsilon)
|
|
311
|
+
>>> G = M.fundamental_group(simplify_presentation = False)
|
|
312
|
+
>>> for rel in G.relators():
|
|
313
|
+
... close_to_pm_identity(p([letterToMatrix(l, generatorMatrices) for l in rel]))
|
|
314
|
+
True
|
|
315
|
+
True
|
|
316
|
+
True
|
|
317
|
+
True
|
|
318
|
+
|
|
319
|
+
"""
|
|
320
|
+
|
|
321
|
+
z = self.mcomplex.Tetrahedra[0].ShapeParameters[simplex.E01]
|
|
322
|
+
CF = z.parent()
|
|
323
|
+
|
|
324
|
+
self.mcomplex.GeneratorMatrices = { 0 : matrix([[CF(1), CF(0)],
|
|
325
|
+
[CF(0), CF(1)]]) }
|
|
326
|
+
|
|
327
|
+
for g, pairings in self.mcomplex.Generators.items():
|
|
328
|
+
# We compute the matrix for the generator and its inverse at the
|
|
329
|
+
# same time, so ignore inverses.
|
|
330
|
+
if g > 0:
|
|
331
|
+
m = _compute_pairing_matrix(pairings[0])
|
|
332
|
+
if normalize_matrices:
|
|
333
|
+
m = m / m.det().sqrt()
|
|
334
|
+
self.mcomplex.GeneratorMatrices[ g] = m
|
|
335
|
+
self.mcomplex.GeneratorMatrices[-g] = _adjoint2(m)
|
|
336
|
+
|
|
337
|
+
def matrices_for_presentation(self, G, match_kernel=False):
|
|
338
|
+
"""
|
|
339
|
+
Given the result of M.fundamental_group(...) where M is the
|
|
340
|
+
corresponding SnapPy.Manifold, return the matrices for that
|
|
341
|
+
presentation of the fundamental polyhedron.
|
|
342
|
+
|
|
343
|
+
The GeneratorMatrices computed here are for the face-pairing
|
|
344
|
+
presentation with respect to the fundamental polyhedron.
|
|
345
|
+
That presentation can be simplified by M.fundamental_group(...)
|
|
346
|
+
and this function will compute the matrices for the simplified
|
|
347
|
+
presentation from the GeneratorMatrices.
|
|
348
|
+
|
|
349
|
+
If match_kernel is True, it will flip the signs of some of
|
|
350
|
+
the matrices to match the ones in the given G (which were determined
|
|
351
|
+
by the SnapPea kernel).
|
|
352
|
+
|
|
353
|
+
This makes the result stable when changing precision (when normalizing
|
|
354
|
+
matrices with determinant -1, sqrt(-1) might jump between i and -i when
|
|
355
|
+
increasing precision).
|
|
356
|
+
"""
|
|
357
|
+
|
|
358
|
+
num_generators = len(self.mcomplex.GeneratorMatrices) // 2
|
|
359
|
+
matrices = [ self.mcomplex.GeneratorMatrices[g + 1]
|
|
360
|
+
for g in range(num_generators) ]
|
|
361
|
+
|
|
362
|
+
result = _perform_word_moves(matrices, G)
|
|
363
|
+
if match_kernel:
|
|
364
|
+
return _negate_matrices_to_match_kernel(result, G)
|
|
365
|
+
else:
|
|
366
|
+
return result
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _diff_to_kernel(value, snappeaValue):
|
|
370
|
+
"""
|
|
371
|
+
The SnapPea kernel will always give us a number, but we might deal
|
|
372
|
+
with a number or an interval.
|
|
373
|
+
|
|
374
|
+
Cast to our numeric type so that we can compare.
|
|
375
|
+
"""
|
|
376
|
+
CF = value.parent()
|
|
377
|
+
return value - CF(snappeaValue)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def _is_number_close_to_kernel(value, snappeaValue, error=10**-6):
|
|
381
|
+
CF = value.parent()
|
|
382
|
+
return abs(_diff_to_kernel(value, snappeaValue)) < CF(error)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def _is_vertex_close_to_kernel(vertex, snappeaVertex):
|
|
386
|
+
if vertex == Infinity or snappeaVertex == Infinity:
|
|
387
|
+
return vertex == snappeaVertex
|
|
388
|
+
return _is_number_close_to_kernel(vertex, snappeaVertex)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def _are_vertices_close_to_kernel(verts, snappeaVerts):
|
|
392
|
+
for key, vert in verts.items():
|
|
393
|
+
snappeaVert = snappeaVerts[key]
|
|
394
|
+
if not _is_vertex_close_to_kernel(vert, snappeaVert):
|
|
395
|
+
return False
|
|
396
|
+
return True
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
_RemainingFace = { (V0, V1): V3, (V0, V2): V1, (V0, V3): V2,
|
|
400
|
+
(V1, V0): V2, (V1, V2): V3, (V1, V3): V0,
|
|
401
|
+
(V2, V0): V3, (V2, V1): V0, (V2, V3): V1,
|
|
402
|
+
(V3, V0): V1, (V3, V1): V2, (V3, V2): V0}
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def _compute_fourth_corner(T):
|
|
406
|
+
v = 4 * [ None ]
|
|
407
|
+
missing_corners = [V for V in ZeroSubsimplices if T.Class[V].IdealPoint is None]
|
|
408
|
+
if not missing_corners:
|
|
409
|
+
return
|
|
410
|
+
missing_corner = missing_corners[0]
|
|
411
|
+
|
|
412
|
+
v[3] = missing_corner
|
|
413
|
+
v[0] = ( [V for V in ZeroSubsimplices if T.Class[V].IdealPoint == Infinity] +
|
|
414
|
+
[V for V in ZeroSubsimplices if V != missing_corner])[0]
|
|
415
|
+
v[1], v[2] = _RemainingFace[ (v[3], v[0]) ], _RemainingFace[ (v[0], v[3]) ]
|
|
416
|
+
z = [T.Class[V].IdealPoint for V in v]
|
|
417
|
+
|
|
418
|
+
cross_ratio = T.ShapeParameters[ v[0] | v[1] ]
|
|
419
|
+
if z[0] == Infinity:
|
|
420
|
+
z[3] = z[1] + cross_ratio * (z[2] - z[1])
|
|
421
|
+
else:
|
|
422
|
+
diff20 = z[2] - z[0]
|
|
423
|
+
diff21 = z[2] - z[1]
|
|
424
|
+
numerator = (z[1]*diff20 - cross_ratio*(z[0]*diff21))
|
|
425
|
+
denominator = (diff20 - cross_ratio*diff21)
|
|
426
|
+
if abs(denominator) == 0 and abs(numerator) > 0:
|
|
427
|
+
z[3] = Infinity
|
|
428
|
+
else:
|
|
429
|
+
z[3] = numerator/denominator
|
|
430
|
+
|
|
431
|
+
T.Class[missing_corner].IdealPoint = z[3]
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def _normalize_points(a, b):
|
|
435
|
+
"""
|
|
436
|
+
Reduce the number of cases involving infinity that we need to
|
|
437
|
+
consider.
|
|
438
|
+
|
|
439
|
+
In particular (assuming no degeneracy), a[0], a[1] and b[0] are
|
|
440
|
+
never infinite.
|
|
441
|
+
"""
|
|
442
|
+
a_infinities = [i for i, z in enumerate(a) if z == Infinity]
|
|
443
|
+
if len(a_infinities) > 0:
|
|
444
|
+
i = a_infinities[0]
|
|
445
|
+
a, b = a[i : ] + a[ : i], b[i : ] + b[ : i]
|
|
446
|
+
|
|
447
|
+
b_infinities = [i for i, z in enumerate(b) if z == Infinity]
|
|
448
|
+
if len(b_infinities) > 0:
|
|
449
|
+
i = b_infinities[0]
|
|
450
|
+
if a[0] != Infinity:
|
|
451
|
+
a, b = a[i : ] + a[ : i], b[i : ] + b[ : i]
|
|
452
|
+
else:
|
|
453
|
+
if i == 2:
|
|
454
|
+
a, b = [a[0], a[2], a[1]], [b[0], b[2], b[1]]
|
|
455
|
+
|
|
456
|
+
a.reverse(), b.reverse()
|
|
457
|
+
return a, b
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def _matrix_taking_triple_to_triple(a, b):
|
|
461
|
+
"""
|
|
462
|
+
To quote Jeff:
|
|
463
|
+
|
|
464
|
+
The formula for the Moebius transformation taking the a[] to the b[]
|
|
465
|
+
is simple enough:
|
|
466
|
+
|
|
467
|
+
f(z) = [ (b1*k - b0) * z + (b0*a1 - b1*a0*k)] /
|
|
468
|
+
[ (k - 1) * z + (a1 - k*a0) ]
|
|
469
|
+
|
|
470
|
+
where
|
|
471
|
+
|
|
472
|
+
k = [(b2-b0)/(b2-b1)] * [(a2-a1)/(a2-a0)]
|
|
473
|
+
"""
|
|
474
|
+
# Let's make it so that a[0], a[1], and b[0] are never infinite
|
|
475
|
+
|
|
476
|
+
(a0, a1, a2), (b0, b1, b2) = _normalize_points(a,b)
|
|
477
|
+
|
|
478
|
+
ka = (a2 - a1)/(a2 - a0) if a2 != Infinity else 1
|
|
479
|
+
|
|
480
|
+
if b1 == Infinity:
|
|
481
|
+
kb, b1kb = 0, -(b2 - b0)
|
|
482
|
+
else:
|
|
483
|
+
kb = (b2 - b0)/(b2 - b1) if b2 != Infinity else 1
|
|
484
|
+
b1kb = b1 * kb
|
|
485
|
+
|
|
486
|
+
k = kb * ka
|
|
487
|
+
|
|
488
|
+
return matrix([(b1kb * ka - b0, b0 * a1 - a0 * b1kb * ka),
|
|
489
|
+
(k - 1, a1 - k * a0)])
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
def _adjoint2(m):
|
|
493
|
+
"""
|
|
494
|
+
Sage matrix.adjoint() produces an unnecessary large interval for
|
|
495
|
+
ComplexIntervalField entries.
|
|
496
|
+
"""
|
|
497
|
+
return matrix([[m[1, 1], -m[0, 1]], [-m[1, 0], m[0, 0]]])
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def _perform_word_moves(matrices, G):
|
|
501
|
+
mats = [ None ] + matrices
|
|
502
|
+
moves = G._word_moves()
|
|
503
|
+
while moves:
|
|
504
|
+
a = moves.pop(0)
|
|
505
|
+
if a >= len(mats): # new generator added
|
|
506
|
+
n = moves.index(a) # end symbol location
|
|
507
|
+
word, moves = moves[:n], moves[n+1:]
|
|
508
|
+
mats.append( prod( [mats[g] if g > 0 else _adjoint2(mats[-g]) for g in word] ) )
|
|
509
|
+
else:
|
|
510
|
+
b = moves.pop(0)
|
|
511
|
+
if a == b: # generator removed
|
|
512
|
+
mats[a] = mats[-1]
|
|
513
|
+
mats = mats[:-1]
|
|
514
|
+
elif a == -b: # invert generator
|
|
515
|
+
mats[a] = _adjoint2(mats[a])
|
|
516
|
+
else: # handle slide
|
|
517
|
+
A, B = mats[abs(a)], mats[abs(b)]
|
|
518
|
+
if a*b < 0:
|
|
519
|
+
B = _adjoint2(B)
|
|
520
|
+
mats[abs(a)] = A*B if a > 0 else B*A
|
|
521
|
+
|
|
522
|
+
return mats[1 : G.num_generators() + 1]
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def _matrix_L1_distance_to_kernel(m, snappeaM):
|
|
526
|
+
return sum([ abs(_diff_to_kernel(m[i,j], snappeaM[i,j]))
|
|
527
|
+
for i in range(2)
|
|
528
|
+
for j in range(2)])
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def _negate_matrix_to_match_kernel(m, snappeaM):
|
|
532
|
+
diff_plus = _matrix_L1_distance_to_kernel(m, snappeaM)
|
|
533
|
+
|
|
534
|
+
diff_minus = _matrix_L1_distance_to_kernel(m, -snappeaM)
|
|
535
|
+
|
|
536
|
+
# Note that from an interval perspective, (not diff_plus < diff_minus)
|
|
537
|
+
# is not implying that diff_plus >= diff_minus and that "-m" is the
|
|
538
|
+
# "correct" answer.
|
|
539
|
+
# But both +m and -m are valid, we just try to heuristically match the
|
|
540
|
+
# choice that the SnapPea kernel made.
|
|
541
|
+
|
|
542
|
+
if diff_plus < diff_minus:
|
|
543
|
+
return m
|
|
544
|
+
else:
|
|
545
|
+
return -m
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def _negate_matrices_to_match_kernel(matrices, G):
|
|
549
|
+
"""
|
|
550
|
+
Normalize things so the signs of the matices match SnapPy's default
|
|
551
|
+
This makes the representations stay close as one increases the precision.
|
|
552
|
+
"""
|
|
553
|
+
|
|
554
|
+
return [ _negate_matrix_to_match_kernel(m, matrix(G.SL2C(g)))
|
|
555
|
+
for m, g in zip(matrices, G.generators()) ]
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
def _compute_pairing_matrix(pairing):
|
|
559
|
+
(inCorner, outCorner), perm = pairing
|
|
560
|
+
|
|
561
|
+
inTriple = []
|
|
562
|
+
outTriple = []
|
|
563
|
+
|
|
564
|
+
for v in simplex.ZeroSubsimplices:
|
|
565
|
+
if simplex.is_subset(v, inCorner.Subsimplex):
|
|
566
|
+
inTriple.append(inCorner.Tetrahedron.Class[v].IdealPoint)
|
|
567
|
+
outTriple.append(outCorner.Tetrahedron.Class[perm.image(v)].IdealPoint)
|
|
568
|
+
|
|
569
|
+
return _matrix_taking_triple_to_triple(outTriple, inTriple)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This has been moved to FundamentalPolyhedronEngine.
|
|
3
|
+
Only the testing code was left here.
|
|
4
|
+
|
|
5
|
+
Replicating how SnapPea finds the matrices of the geometric generators,
|
|
6
|
+
so that this can replicated using e.g. extended precision.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .fundamental_polyhedron import *
|
|
10
|
+
from . import t3mlite as t3m
|
|
11
|
+
from .t3mlite import ZeroSubsimplices
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Testing code
|
|
15
|
+
|
|
16
|
+
def matrix_norm(A):
|
|
17
|
+
return max(map(abs, A.list()))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def check_example(M, shapes=None):
|
|
21
|
+
e = fromManifoldAndShapes(M, shapes)
|
|
22
|
+
|
|
23
|
+
MM = e.mcomplex
|
|
24
|
+
max_error = 0
|
|
25
|
+
for T in MM:
|
|
26
|
+
for V in ZeroSubsimplices:
|
|
27
|
+
vs, vn = T.SnapPeaIdealVertices[V], T.IdealVertices[V]
|
|
28
|
+
if vn != vs:
|
|
29
|
+
max_error = max(max_error, abs(vs-vn))
|
|
30
|
+
|
|
31
|
+
G = M.fundamental_group(False, False, False)
|
|
32
|
+
mats = compute_matrices(MM)
|
|
33
|
+
for i in range(1, G.num_generators() + 1):
|
|
34
|
+
A = mats[i]
|
|
35
|
+
B = G.SL2C(G.generators()[i - 1])
|
|
36
|
+
error = min(matrix_norm(A - B), matrix_norm(A + B))
|
|
37
|
+
max_error = max(max_error, error)
|
|
38
|
+
|
|
39
|
+
return max_error
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Creating a group representation from shape *intervals*,
|
|
3
|
+
specifically elements of Sage's ComplexIntervalField. Also contains
|
|
4
|
+
some utility functions for dealing with such representations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .polished_reps import ManifoldGroup
|
|
8
|
+
from .fundamental_polyhedron import *
|
|
9
|
+
|
|
10
|
+
# Most of the below small functions are not used in SnapPy proper, but
|
|
11
|
+
# published code (https://doi.org/10.7910/DVN/LCYXPO) depends on them,
|
|
12
|
+
# so they should not be removed.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def matrix_difference_norm(A, B):
|
|
16
|
+
B = B.change_ring(A.base_ring())
|
|
17
|
+
return max([abs(a - b) for a,b in zip(A.list(), B.list())])
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def diameter(A):
|
|
21
|
+
return max(x.diameter() for x in A.list())
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def contains_zero(A):
|
|
25
|
+
return all(x.contains_zero() for x in A.list())
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def contains_one(A):
|
|
29
|
+
return contains_zero(A - 1)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def contains_plus_minus_one(A):
|
|
33
|
+
return contains_one(A) or contains_one(-A)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def could_be_equal_numbers(x, y):
|
|
37
|
+
return (x - y).contains_zero()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def could_be_equal(A, B):
|
|
41
|
+
return contains_zero(A - B)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def holonomy_from_shape_intervals(manifold, shape_intervals,
|
|
45
|
+
fundamental_group_args=[], lift_to_SL2=True):
|
|
46
|
+
"""
|
|
47
|
+
Returns the representation
|
|
48
|
+
|
|
49
|
+
rho: pi_1(manifold) -> (P)SL(2, ComplexIntervalField)
|
|
50
|
+
|
|
51
|
+
determined by the given shape_intervals. If shape_intervals
|
|
52
|
+
contains an exact solution z0 to the gluing equations with
|
|
53
|
+
corresponding holonomy representation rho0, then for all g the
|
|
54
|
+
ComplexIntervalField matrix rho(g) contains rho0(g)::
|
|
55
|
+
|
|
56
|
+
sage: M = Manifold('m004(1,2)')
|
|
57
|
+
sage: success, shapes = M.verify_hyperbolicity(bits_prec=53)
|
|
58
|
+
sage: success
|
|
59
|
+
True
|
|
60
|
+
sage: rho = holonomy_from_shape_intervals(M, shapes)
|
|
61
|
+
sage: (rho('a').det() - 1).contains_zero()
|
|
62
|
+
True
|
|
63
|
+
|
|
64
|
+
Of course, for long words the matrix entries will smear out::
|
|
65
|
+
|
|
66
|
+
sage: diameter(rho('a')).log10() # doctest: +NUMERIC0
|
|
67
|
+
-10.9576580520835
|
|
68
|
+
sage: diameter(rho(10*'abAB')).log10() # doctest: +NUMERIC0
|
|
69
|
+
-8.39987365046327
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
M = manifold
|
|
73
|
+
G = M.fundamental_group(*fundamental_group_args)
|
|
74
|
+
f = FundamentalPolyhedronEngine.from_manifold_and_shapes(
|
|
75
|
+
M, shape_intervals, normalize_matrices=True)
|
|
76
|
+
mats = f.matrices_for_presentation(G, match_kernel=True)
|
|
77
|
+
PG = ManifoldGroup(G.generators(), G.relators(),
|
|
78
|
+
G.peripheral_curves(), mats)
|
|
79
|
+
if lift_to_SL2:
|
|
80
|
+
PG.lift_to_SL2C()
|
|
81
|
+
return PG
|