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,717 @@
|
|
|
1
|
+
"""
|
|
2
|
+
We decorate Regina's triangulation isomorphism signature (isosig) to
|
|
3
|
+
record the peripheral structure of a cusped manifold M, that is, the
|
|
4
|
+
cusp labels and the peripheral curves on each cusp. The basic idea is
|
|
5
|
+
to store these relative to SnapPy's combinatorial defaults for the
|
|
6
|
+
triangulation created from the bare isosig.
|
|
7
|
+
|
|
8
|
+
Specifically, if M has n cusps, we append a permutation on {0,...,n-1}
|
|
9
|
+
as well as n change-of-basis matrices, represented as a sequence of 5n
|
|
10
|
+
integers and encoded as a string of isosig characters. This decoration
|
|
11
|
+
string is appended to the isosig string, after first appending a
|
|
12
|
+
separator character which is not a valid isosig character. To save
|
|
13
|
+
space, the permutation may be omitted when it is equal to the identity
|
|
14
|
+
permutation; this is indicated by the fact that the length of the
|
|
15
|
+
decoration is 4n rather than 5n.
|
|
16
|
+
|
|
17
|
+
A simple valid decorated isosig for a two-cusped manifold is::
|
|
18
|
+
|
|
19
|
+
eLPkbdcddhgggb_abBaaBBaaB
|
|
20
|
+
|
|
21
|
+
Here, the bare isosig is what precedes the underscore; what follows is
|
|
22
|
+
an encoded version of the 5n integers mentioned above. This decorated
|
|
23
|
+
isosig is equivalent to
|
|
24
|
+
|
|
25
|
+
eLPkbdcddhgggb_BaaBBaaB
|
|
26
|
+
|
|
27
|
+
where the permutation part has been elided since the permutation is
|
|
28
|
+
the identity.
|
|
29
|
+
|
|
30
|
+
In practice, one can extract the isosig and decorator from a decorated
|
|
31
|
+
isosig, say named di, as follows:
|
|
32
|
+
|
|
33
|
+
isosig, decorator = di.split('_')
|
|
34
|
+
|
|
35
|
+
Note: An isosig is an invariant of a triangulation of an *unoriented*
|
|
36
|
+
manifold. For an amphicheiral manifold M, it can happen that
|
|
37
|
+
Manifold(M.triangulation_isosig(decorated=False)) has the opposite
|
|
38
|
+
orientation from M itself.
|
|
39
|
+
The decoration implicitly embeds the preferred orientation of
|
|
40
|
+
M in the sign of the determinant of the change-of-basis matrices.
|
|
41
|
+
|
|
42
|
+
Note: If the triangulation has combinatorial symmetries, there can be
|
|
43
|
+
multiple change-of-basis matrices that yield combinatorially
|
|
44
|
+
isomorphic pairs (triangulation, peripheral curves). In such cases,
|
|
45
|
+
the decoration is the lexicographically first one.
|
|
46
|
+
|
|
47
|
+
Caveat: We pick the decoration with the lexicographically smallest
|
|
48
|
+
encoding with the following consequence: If we have more 26 cusps, the
|
|
49
|
+
lexicographically smallest permutation might not have the smallest encoding
|
|
50
|
+
and thus might not be the one picked.
|
|
51
|
+
|
|
52
|
+
Caveat: We drop the trivial permutation from the encoding. Pairs (a,b) of string
|
|
53
|
+
come with the lexicographic ordering. We also obtain a (partial) ordering by
|
|
54
|
+
ordering by a + b. These two orderings are not the same.
|
|
55
|
+
In particular, there is a combinatorial isomorphism from
|
|
56
|
+
Triangulation('L6n1') to
|
|
57
|
+
Triangulation(Triangulation('L6n1').triangulation_isosig(decorated = False))
|
|
58
|
+
that acts on the cusp by the identity perm and, thus, we would expect it to
|
|
59
|
+
be preferred. However,
|
|
60
|
+
Triangulation("L6n1(0,0)(0,0)(0,0)").triangulation_isosig() results in
|
|
61
|
+
'gLMzQbcdefffaelaaai_acbBaabCbbabbBC' which does not use the identity perm.
|
|
62
|
+
|
|
63
|
+
Caveat: There are de-facto two canonical choices of peripheral curves.
|
|
64
|
+
When calling
|
|
65
|
+
>>> T = Triangulation('ovLMvvPQQQccddlmnijklmnmnlgvfamtvfblhaumx'),
|
|
66
|
+
the SnapPea kernel picks peripheral curves and then orients the manifold
|
|
67
|
+
(see data_to_triangulation in kernel_code/kernel/triangulation.c)
|
|
68
|
+
>>> T.set_peripheral_curves('combinatorial')
|
|
69
|
+
is now calling the same SnapPea kernel code to pick peripheral curve but
|
|
70
|
+
on the oriented manifold. This can result in different peripheral curves.
|
|
71
|
+
|
|
72
|
+
Note that the encoding and decoding needs to use the same of the two
|
|
73
|
+
canonical choices of peripheral curves.
|
|
74
|
+
|
|
75
|
+
For the decoding, there is a difference based on whether the isosig is
|
|
76
|
+
decorated because set_peripheral_from_decoration calls
|
|
77
|
+
manifold.set_peripheral_curves('combinatorial').
|
|
78
|
+
|
|
79
|
+
We need to account for that in the encoding: we need to use
|
|
80
|
+
set_peripheral_curves('combinatorial') on the "target" triangulation if
|
|
81
|
+
we anticipate a decoration. And if we called
|
|
82
|
+
set_peripheral_curves('combinatorial'), we need to make sure we have a
|
|
83
|
+
decoration (see force_decoration).
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
import re
|
|
87
|
+
import string
|
|
88
|
+
|
|
89
|
+
from .matrix import make_vector
|
|
90
|
+
|
|
91
|
+
# Used between the base isosig and the decorated version.
|
|
92
|
+
separator = '_'
|
|
93
|
+
|
|
94
|
+
# Pattern matching decorated isosigs
|
|
95
|
+
|
|
96
|
+
base64_pat = r'([a-zA-Z0-9\+\-]+)'
|
|
97
|
+
separator_pat = '[%s]{1}' % separator
|
|
98
|
+
base64_opt_pat = r'([a-zA-Z0-9\+\-]*)'
|
|
99
|
+
isosig_pattern = re.compile(base64_pat + separator_pat + base64_opt_pat + '$')
|
|
100
|
+
|
|
101
|
+
# We store lists of integers as (non-RFC4648) base64 strings.
|
|
102
|
+
|
|
103
|
+
base64_letters = string.ascii_letters + '0123456789+-'
|
|
104
|
+
base64_lower = string.ascii_lowercase + '01234+'
|
|
105
|
+
base64_upper = string.ascii_uppercase + '56789-'
|
|
106
|
+
in_one = string.ascii_lowercase[:16] + string.ascii_lowercase[1:16].upper()
|
|
107
|
+
|
|
108
|
+
int_to_letter = dict(enumerate(base64_letters))
|
|
109
|
+
letter_to_int = {a: i for i, a in enumerate(base64_letters)}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def encode_nonnegative_int(x):
|
|
113
|
+
"""
|
|
114
|
+
Regina's base64 encoding scheme for nonnegative integers,
|
|
115
|
+
described in the appendix to http://arxiv.org/abs/1110.6080
|
|
116
|
+
"""
|
|
117
|
+
assert x >= 0
|
|
118
|
+
six_bits = []
|
|
119
|
+
while True:
|
|
120
|
+
low_six = x & 63
|
|
121
|
+
six_bits.append(low_six)
|
|
122
|
+
x = x >> 6
|
|
123
|
+
if x == 0:
|
|
124
|
+
break
|
|
125
|
+
return ''.join([int_to_letter[b] for b in six_bits])
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def decode_nonnegative_int(s):
|
|
129
|
+
return sum( letter_to_int[a] << 6*i for i, a in enumerate(s))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def encode_int(x):
|
|
133
|
+
"""
|
|
134
|
+
Encodes an integer in the range [-2**90 + 1, 2**90 - 1] with a "stop"
|
|
135
|
+
at the end so a concatenation of such encodings is easily decodable.
|
|
136
|
+
The basic format is:
|
|
137
|
+
|
|
138
|
+
If x in [0...15], encode as a single letter in [a...p].
|
|
139
|
+
If x in [-15...-1] encode as a single letter in [P...B].
|
|
140
|
+
|
|
141
|
+
Otherwise, the first letter specifies the length of
|
|
142
|
+
encode_nonnegative_int(abs(x)) as well as sign(x), followed by the
|
|
143
|
+
encoding of abs(x).
|
|
144
|
+
"""
|
|
145
|
+
if 0 <= x < 16:
|
|
146
|
+
return base64_letters[x]
|
|
147
|
+
if -15 <= x < 0:
|
|
148
|
+
return base64_letters[abs(x) + 26]
|
|
149
|
+
encoded_xabs = encode_nonnegative_int(abs(x))
|
|
150
|
+
L = len(encoded_xabs)
|
|
151
|
+
try:
|
|
152
|
+
if x > 0:
|
|
153
|
+
return base64_lower[16 + L] + encoded_xabs
|
|
154
|
+
if x < 0:
|
|
155
|
+
return base64_upper[16 + L] + encoded_xabs
|
|
156
|
+
except IndexError:
|
|
157
|
+
raise ValueError('The given integer is too large to encode')
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def encode_integer_list(L):
|
|
161
|
+
return ''.join(map(encode_int, L))
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def decode_integer_list(encoded):
|
|
165
|
+
ans = []
|
|
166
|
+
while len(encoded):
|
|
167
|
+
s = encoded[0]
|
|
168
|
+
sign = 1 if s in base64_lower else -1
|
|
169
|
+
if s in in_one:
|
|
170
|
+
ans.append(sign*letter_to_int[s.lower()])
|
|
171
|
+
encoded = encoded[1:]
|
|
172
|
+
else:
|
|
173
|
+
if sign == 1:
|
|
174
|
+
L = base64_lower.index(s) - 16
|
|
175
|
+
else:
|
|
176
|
+
L = base64_upper.index(s) - 16
|
|
177
|
+
current, encoded = encoded[1:L+1], encoded[L+1:]
|
|
178
|
+
ans.append(sign*decode_nonnegative_int(current))
|
|
179
|
+
return ans
|
|
180
|
+
|
|
181
|
+
###############################################################################
|
|
182
|
+
# Some helper functions
|
|
183
|
+
|
|
184
|
+
def det(A):
|
|
185
|
+
return A[0][0]*A[1][1] - A[0][1]*A[1][0]
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def inverse_perm(L):
|
|
189
|
+
ans = len(L)*[None]
|
|
190
|
+
for i, x in enumerate(L):
|
|
191
|
+
ans[x] = i
|
|
192
|
+
return ans
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def as_two_by_two_matrices(L):
|
|
196
|
+
assert len(L) % 4 == 0
|
|
197
|
+
return [[(L[i], L[i+1]), (L[i+2], L[i+3])] for i in range(0, len(L), 4)]
|
|
198
|
+
|
|
199
|
+
def first_non_zero_entry_in_column(matrix, col):
|
|
200
|
+
e = matrix[0, col]
|
|
201
|
+
if e != 0:
|
|
202
|
+
return e
|
|
203
|
+
return matrix[1, col]
|
|
204
|
+
|
|
205
|
+
def sgn_column(matrix, col):
|
|
206
|
+
"""
|
|
207
|
+
Returns +1 or -1 depending on the sign of the first non-zero entry
|
|
208
|
+
in the column of the given matrix.
|
|
209
|
+
"""
|
|
210
|
+
if first_non_zero_entry_in_column(matrix, col) > 0:
|
|
211
|
+
return +1
|
|
212
|
+
else:
|
|
213
|
+
return -1
|
|
214
|
+
|
|
215
|
+
def apply_peripheral_curve_flips(
|
|
216
|
+
matrix, slope, manifold_orientable, isomorphism_orientation):
|
|
217
|
+
"""
|
|
218
|
+
Flips peripheral curves (as encoded by matrix) to bring them into
|
|
219
|
+
canonical form and updates slope accordingly.
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
# Determine whether to flip meridian
|
|
223
|
+
f0 = sgn_column(matrix, 0)
|
|
224
|
+
|
|
225
|
+
# Determine whether to flip longitude
|
|
226
|
+
if manifold_orientable:
|
|
227
|
+
# We conform the matrix such that the first non-zero entry in the
|
|
228
|
+
# first column and the determinant are always positive
|
|
229
|
+
f1 = f0 * isomorphism_orientation
|
|
230
|
+
else:
|
|
231
|
+
# We conform the matrix such that the first non-zero entry in each
|
|
232
|
+
# column is always positive
|
|
233
|
+
f1 = sgn_column(matrix, 1)
|
|
234
|
+
|
|
235
|
+
flips = [ f0, f1 ]
|
|
236
|
+
|
|
237
|
+
for col, flip in enumerate(flips):
|
|
238
|
+
for row in range(2):
|
|
239
|
+
matrix[row,col] *= flip
|
|
240
|
+
slope[col] *= flip
|
|
241
|
+
|
|
242
|
+
def pack_matrices(matrices):
|
|
243
|
+
"""
|
|
244
|
+
Multiplies the columns of each matrix by the entries in flips and
|
|
245
|
+
packs all the matrices into one array, column-major.
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
return [ matrix[row,col]
|
|
249
|
+
for matrix in matrices
|
|
250
|
+
for col in range(2)
|
|
251
|
+
for row in range(2) ]
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def supress_minus_zero(x):
|
|
255
|
+
if x == 0:
|
|
256
|
+
return 0
|
|
257
|
+
else:
|
|
258
|
+
return x
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def is_trivial_perm(perm):
|
|
262
|
+
return all(i == p for i, p in enumerate(perm))
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def key_prefer_pos(x):
|
|
266
|
+
"""
|
|
267
|
+
Intended for key argument to min.
|
|
268
|
+
|
|
269
|
+
Prefers positive and then absolute value.
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
if x >= 0:
|
|
273
|
+
return (0, x)
|
|
274
|
+
else:
|
|
275
|
+
return (1, -x)
|
|
276
|
+
|
|
277
|
+
def key_slope(slope):
|
|
278
|
+
"""
|
|
279
|
+
Intended for key argument to min.
|
|
280
|
+
|
|
281
|
+
Prefers positive and small denominator.
|
|
282
|
+
"""
|
|
283
|
+
|
|
284
|
+
slope_m, slope_l = slope
|
|
285
|
+
return (key_prefer_pos(slope_l), key_prefer_pos(slope_m))
|
|
286
|
+
|
|
287
|
+
def key_decoration_info(info):
|
|
288
|
+
encoded, slopes = info
|
|
289
|
+
return [encoded, [key_slope(slope) for slope in slopes]]
|
|
290
|
+
|
|
291
|
+
def normalized_slope(slope):
|
|
292
|
+
"""
|
|
293
|
+
Returns slope or -slope preferring positive and small denominator.
|
|
294
|
+
|
|
295
|
+
Equivalent to min([slope, -slope], key=key_slope)
|
|
296
|
+
"""
|
|
297
|
+
|
|
298
|
+
slope_m, slope_l = slope
|
|
299
|
+
if slope_l < 0:
|
|
300
|
+
return -slope
|
|
301
|
+
if slope_l > 0:
|
|
302
|
+
return slope
|
|
303
|
+
if slope_m < 0:
|
|
304
|
+
return -slope
|
|
305
|
+
return slope
|
|
306
|
+
|
|
307
|
+
def candidate_decoration_info(
|
|
308
|
+
isomorphism,
|
|
309
|
+
slopes,
|
|
310
|
+
manifold_orientable,
|
|
311
|
+
ignore_cusp_ordering,
|
|
312
|
+
ignore_curves,
|
|
313
|
+
ignore_curve_orientations,
|
|
314
|
+
ignore_filling_orientations,
|
|
315
|
+
ignore_orientation):
|
|
316
|
+
|
|
317
|
+
matrices = isomorphism.cusp_maps()
|
|
318
|
+
isomorphism_orientation = matrices[0].det()
|
|
319
|
+
|
|
320
|
+
# Do not consider orientation-reversing isomorphisms if
|
|
321
|
+
# ignore_orientation isn't specified.
|
|
322
|
+
if manifold_orientable and not ignore_orientation:
|
|
323
|
+
if isomorphism_orientation < 0:
|
|
324
|
+
return None
|
|
325
|
+
|
|
326
|
+
# Make a copy as vectors so that we can modify in place and
|
|
327
|
+
# apply matrices.
|
|
328
|
+
# Outside of SnapPy, SimpleVector is not making a copy of the
|
|
329
|
+
# tuple and we need a list to modify things in place.
|
|
330
|
+
slopes = [ make_vector([slope_m, slope_l])
|
|
331
|
+
for slope_m, slope_l in slopes ]
|
|
332
|
+
|
|
333
|
+
# Permutation of cusps
|
|
334
|
+
perm = inverse_perm(isomorphism.cusp_images())
|
|
335
|
+
|
|
336
|
+
if ignore_cusp_ordering:
|
|
337
|
+
# If we do not include the permutation in the encoding,
|
|
338
|
+
# we need to apply it to the matrices
|
|
339
|
+
matrices = [ matrices[i] for i in perm ]
|
|
340
|
+
slopes = [ slopes[i] for i in perm ]
|
|
341
|
+
|
|
342
|
+
if ignore_curves:
|
|
343
|
+
slopes = [ matrix * slope
|
|
344
|
+
for matrix, slope in zip(matrices, slopes) ]
|
|
345
|
+
if manifold_orientable and isomorphism_orientation < 0:
|
|
346
|
+
# We want to preserve the direction of the core curve because it is
|
|
347
|
+
# relevant for preserving which way a geometric spun-triangulation
|
|
348
|
+
# goes.
|
|
349
|
+
# That means we need to reverse the direction of the filling if
|
|
350
|
+
# reversing the manifold orientaiton.
|
|
351
|
+
slopes = [ -slope for slope in slopes ]
|
|
352
|
+
else:
|
|
353
|
+
if ignore_curve_orientations:
|
|
354
|
+
for matrix, slope in zip(matrices, slopes):
|
|
355
|
+
apply_peripheral_curve_flips(
|
|
356
|
+
matrix, slope, manifold_orientable, isomorphism_orientation)
|
|
357
|
+
|
|
358
|
+
encoded = ''
|
|
359
|
+
|
|
360
|
+
if not ignore_cusp_ordering:
|
|
361
|
+
#
|
|
362
|
+
# Force decoration to fix a very subtle bug!
|
|
363
|
+
#
|
|
364
|
+
# Recall that we call N.set_peripheral_curves('combinatorial')
|
|
365
|
+
# in decorated_isosig below if either ignore_cusp_ordering or
|
|
366
|
+
# ignore_curves is False.
|
|
367
|
+
#
|
|
368
|
+
# On the decoding site, we thus also need to call
|
|
369
|
+
# manifold.set_peripheral_curves('combinatorial') in those cases.
|
|
370
|
+
# This happens in set_peripheral_from_decoration and thus only
|
|
371
|
+
# if the isosig returned here has a decoration, that is "encoded"
|
|
372
|
+
# is not empty.
|
|
373
|
+
#
|
|
374
|
+
# Assume that ignore_cusp_ordering is False and ignore_curves is
|
|
375
|
+
# True and the permutation happens to be the identity.
|
|
376
|
+
#
|
|
377
|
+
# We need to make sure not to have an empty "encoded" in this case.
|
|
378
|
+
force_decoration = ignore_curves
|
|
379
|
+
|
|
380
|
+
if force_decoration or not is_trivial_perm(perm):
|
|
381
|
+
# Encode permutation
|
|
382
|
+
encoded += encode_integer_list(perm)
|
|
383
|
+
|
|
384
|
+
if not ignore_curves:
|
|
385
|
+
# Encode the matrices
|
|
386
|
+
encoded += encode_integer_list(pack_matrices(matrices))
|
|
387
|
+
|
|
388
|
+
if ignore_filling_orientations:
|
|
389
|
+
slopes = [ normalized_slope(slope)
|
|
390
|
+
for slope in slopes ]
|
|
391
|
+
|
|
392
|
+
return encoded, slopes
|
|
393
|
+
|
|
394
|
+
# main two functions
|
|
395
|
+
|
|
396
|
+
def decorated_isosig(manifold, triangulation_class,
|
|
397
|
+
ignore_cusp_ordering=False,
|
|
398
|
+
ignore_curves=False,
|
|
399
|
+
ignore_curve_orientations=False,
|
|
400
|
+
ignore_filling_orientations=False,
|
|
401
|
+
ignore_orientation=True):
|
|
402
|
+
|
|
403
|
+
isosig = manifold._undecorated_triangulation_isosig(
|
|
404
|
+
ignore_orientation=ignore_orientation)
|
|
405
|
+
|
|
406
|
+
# Do not decorate if no cusps
|
|
407
|
+
if manifold.num_cusps() == 0:
|
|
408
|
+
return isosig
|
|
409
|
+
|
|
410
|
+
N = triangulation_class(isosig, remove_finite_vertices=False)
|
|
411
|
+
if not (ignore_cusp_ordering and ignore_curves):
|
|
412
|
+
# Note that data_to_triangulation determines the peripheral
|
|
413
|
+
# curves before orienting the manifold.
|
|
414
|
+
# Thus, we get different peripheral curves when calling
|
|
415
|
+
# N.set_peripheral_curves.
|
|
416
|
+
# For backwards compatibility (see set_peripheral_from_decoration),
|
|
417
|
+
# we need to keep calling N.set_peripheral_curves here unless there is
|
|
418
|
+
# no decoration.
|
|
419
|
+
N.set_peripheral_curves('combinatorial')
|
|
420
|
+
|
|
421
|
+
manifold_orientable = manifold.is_orientable()
|
|
422
|
+
slopes = manifold.cusp_info('filling')
|
|
423
|
+
|
|
424
|
+
# Try all combinatorial isomorphisms and pick
|
|
425
|
+
# lexicographically smallest info.
|
|
426
|
+
encoded, slopes = min(
|
|
427
|
+
(info
|
|
428
|
+
for isomorphism in manifold.isomorphisms_to(N)
|
|
429
|
+
if (
|
|
430
|
+
info := candidate_decoration_info(
|
|
431
|
+
isomorphism,
|
|
432
|
+
slopes,
|
|
433
|
+
manifold_orientable=manifold_orientable,
|
|
434
|
+
ignore_cusp_ordering=ignore_cusp_ordering,
|
|
435
|
+
ignore_curves=ignore_curves,
|
|
436
|
+
ignore_curve_orientations=ignore_curve_orientations,
|
|
437
|
+
ignore_filling_orientations=ignore_filling_orientations,
|
|
438
|
+
ignore_orientation=ignore_orientation)
|
|
439
|
+
) is not None),
|
|
440
|
+
key = key_decoration_info)
|
|
441
|
+
|
|
442
|
+
ans = isosig
|
|
443
|
+
|
|
444
|
+
if encoded:
|
|
445
|
+
ans += separator + encoded
|
|
446
|
+
|
|
447
|
+
if not all(manifold.cusp_info('complete?')):
|
|
448
|
+
for slope_m, slope_l in slopes:
|
|
449
|
+
ans += '(%g,%g)' % (supress_minus_zero(slope_m),
|
|
450
|
+
supress_minus_zero(slope_l))
|
|
451
|
+
|
|
452
|
+
return ans
|
|
453
|
+
|
|
454
|
+
def set_peripheral_from_decoration(manifold, decoration):
|
|
455
|
+
"""
|
|
456
|
+
The manifold is assumed to already have a triangulation created
|
|
457
|
+
from the "bare" isosig.
|
|
458
|
+
"""
|
|
459
|
+
dec = decode_integer_list(decoration)
|
|
460
|
+
manifold.set_peripheral_curves('combinatorial')
|
|
461
|
+
n = manifold.num_cusps()
|
|
462
|
+
k = len(dec)
|
|
463
|
+
|
|
464
|
+
if k not in [ n, 4 * n, 5 * n]:
|
|
465
|
+
raise ValueError("Decoration has unexpected length.")
|
|
466
|
+
|
|
467
|
+
if k == n or k == 5 * n:
|
|
468
|
+
if k == n:
|
|
469
|
+
manifold._reindex_cusps(dec)
|
|
470
|
+
else:
|
|
471
|
+
manifold._reindex_cusps(dec[:n])
|
|
472
|
+
if k == 4 * n or k == 5 * n:
|
|
473
|
+
if k == 4 * n:
|
|
474
|
+
cobs = as_two_by_two_matrices(dec)
|
|
475
|
+
else:
|
|
476
|
+
cobs = as_two_by_two_matrices(dec[n:])
|
|
477
|
+
if det(cobs[0]) < 0 and manifold.is_orientable():
|
|
478
|
+
manifold.reverse_orientation()
|
|
479
|
+
cobs = [[(-a, b), (-c, d)] for [(a, b), (c,d)] in cobs]
|
|
480
|
+
manifold.set_peripheral_curves(cobs)
|
|
481
|
+
|
|
482
|
+
# Testing code
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def is_identity(A):
|
|
486
|
+
return A[0, 0] == A[1, 1] == 1 and A[1, 0] == A[0, 1] == 0
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def preserves_peripheral_curves(h):
|
|
490
|
+
perm = h.cusp_images()
|
|
491
|
+
each_cusp = all(is_identity(A) for A in h.cusp_maps())
|
|
492
|
+
return perm == sorted(perm) and each_cusp
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
def same_peripheral_curves(M, N):
|
|
496
|
+
for h in M.isomorphisms_to(N):
|
|
497
|
+
if preserves_peripheral_curves(h):
|
|
498
|
+
return True
|
|
499
|
+
return False
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
asymmetric = ['v3372', 't10397', 't10448', 't11289', 't11581',
|
|
503
|
+
't11780', 't11824', 't12685', 'o9_34328', 'o9_35609', 'o9_35746',
|
|
504
|
+
'o9_36591', 'o9_37290', 'o9_37552', 'o9_38147', 'o9_38375',
|
|
505
|
+
'o9_38845', 'o9_39220', 'o9_41039', 'o9_41063', 'o9_41329',
|
|
506
|
+
'o9_43248']
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
def main_test():
|
|
510
|
+
import snappy
|
|
511
|
+
censuses = [snappy.OrientableClosedCensus[:100],
|
|
512
|
+
snappy.OrientableCuspedCensus(filter='tets<7'),
|
|
513
|
+
snappy.NonorientableClosedCensus,
|
|
514
|
+
snappy.NonorientableCuspedCensus,
|
|
515
|
+
snappy.CensusKnots(),
|
|
516
|
+
snappy.HTLinkExteriors(filter='cusps>3 and volume<14'),
|
|
517
|
+
[snappy.Manifold(name) for name in asymmetric]]
|
|
518
|
+
tests = 0
|
|
519
|
+
for census in censuses:
|
|
520
|
+
for M in census:
|
|
521
|
+
isosig = decorated_isosig(M, snappy.Triangulation)
|
|
522
|
+
N = snappy.Triangulation(isosig)
|
|
523
|
+
assert same_peripheral_curves(M, N), M
|
|
524
|
+
assert isosig == decorated_isosig(N, snappy.Triangulation), M
|
|
525
|
+
assert M.homology() == N.homology()
|
|
526
|
+
tests += 1
|
|
527
|
+
print('Tested decorated isosig encode/decode on %d triangulations' % tests)
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
def test_integer_list_encoder(tries=1000, length=100, max_entry=2**90):
|
|
531
|
+
import random
|
|
532
|
+
tests = 0
|
|
533
|
+
for i in range(tries):
|
|
534
|
+
entries = [random.randrange(-max_entry, max_entry) for i in range(length)]
|
|
535
|
+
entries += [random.randrange(-15, 16) for i in range(length)]
|
|
536
|
+
random.shuffle(entries)
|
|
537
|
+
assert decode_integer_list(encode_integer_list(entries)) == entries
|
|
538
|
+
tests += 1
|
|
539
|
+
print('Tested encode/decode on %d lists of integers' % tests)
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def test_link_invariant():
|
|
543
|
+
import snappy
|
|
544
|
+
|
|
545
|
+
# DT codes of the same link but with different orientations of the
|
|
546
|
+
# components
|
|
547
|
+
|
|
548
|
+
dt_codes = [
|
|
549
|
+
[(-14, -46, -40, -28, -60, -70), (-32, -34, -38, -4, -52, -50, -48), (-44, -42, -64, -2, -16, -58), (-56, -54, -8), (-36, -26, -24, -22, -20, -6, -18), (-10, -66), (-72, -30, -62), (-12, -68)],
|
|
550
|
+
[(-14, -46, -40, -28, -60, -70), (-36, -34, -30, -4, -52, -50, -48), (-42, -44, -58, -16, -2, -64), (-56, -54, -8), (-32, -26, -24, -22, -20, -6, -18), (-10, -66), (-72, -38, -62), (-12, -68)],
|
|
551
|
+
[(14, 70, 64, 50, 36, 24), (18, 2), (26, 16, 72), (46, 44, 22, 6, 48, 54), (52, 62, 60, 58, 56, 12, 34), (68, 66, 32, 10, 42, 40, 38), (28, 30, 8), (20, 4)],
|
|
552
|
+
[(-14, -46, -40, -28, -60, -70), (-32, -34, -38, -4, -52, -50, -48), (-44, -42, -64, -2, -16, -58), (-56, -54, -8), (-36, -26, -24, -22, -20, -6, -18), (-10, -68), (-30, -72, -62), (-12, -66)],
|
|
553
|
+
[(14, 70, 64, 50, 36, 24), (2, 18), (34, 16, 72), (42, 40, 54, 38, 6, 22), (62, 52, 26, 12, 56, 58, 60), (68, 66, 28, 10, 44, 46, 48), (32, 30, 8), (20, 4)],
|
|
554
|
+
[(-14, -46, -40, -28, -60, -70), (-34, -36, -58, -56, -54, -4, -30), (-42, -44, -48, -26, -2, -64), (-50, -52, -8), (-16, -32, -24, -6, -22, -20, -18), (-68, -10), (-38, -72, -62), (-66, -12)],
|
|
555
|
+
[(-14, -46, -40, -28, -60, -70), (-34, -36, -58, -56, -54, -4, -30), (-42, -44, -48, -26, -2, -64), (-50, -52, -8), (-16, -32, -24, -6, -22, -20, -18), (-10, -66), (-72, -38, -62), (-68, -12)],
|
|
556
|
+
[(14, 70, 64, 50, 36, 24), (2, 18), (16, 34, 72), (42, 40, 54, 38, 6, 20), (62, 52, 26, 12, 56, 58, 60), (68, 66, 28, 10, 44, 46, 48), (32, 30, 8), (4, 22)],
|
|
557
|
+
[(-14, -46, -40, -28, -60, -70), (-32, -34, -38, -4, -52, -50, -48), (-44, -42, -64, -2, -16, -58), (-56, -54, -8), (-36, -26, -24, -22, -20, -6, -18), (-66, -10), (-72, -30, -62), (-68, -12)]
|
|
558
|
+
]
|
|
559
|
+
|
|
560
|
+
# Get complement for each dt_code and complement with opposite orientation
|
|
561
|
+
# for each dt_code
|
|
562
|
+
mfds = [ snappy.Manifold('DT%s' % dt_code) for dt_code in (dt_codes + dt_codes) ]
|
|
563
|
+
for mfd in mfds[:len(dt_codes)]:
|
|
564
|
+
mfd.reverse_orientation()
|
|
565
|
+
|
|
566
|
+
isometry_signatures = [ mfd.isometry_signature(of_link=True)
|
|
567
|
+
for mfd in mfds ]
|
|
568
|
+
|
|
569
|
+
# All the links only differ in orientation of complement or components,
|
|
570
|
+
# should get the same isometry_signature
|
|
571
|
+
assert len(set(isometry_signatures)) == 1
|
|
572
|
+
|
|
573
|
+
M = snappy.Manifold(isometry_signatures[0])
|
|
574
|
+
N = snappy.Manifold(M.isometry_signature(of_link=True))
|
|
575
|
+
|
|
576
|
+
# Instantiating a manifold from its decorated isometry_signature should
|
|
577
|
+
# eventually yield to a fixed point
|
|
578
|
+
assert same_peripheral_curves(M, N)
|
|
579
|
+
|
|
580
|
+
# More sanity checks
|
|
581
|
+
assert isometry_signatures[0] == M.isometry_signature(of_link=True)
|
|
582
|
+
assert isometry_signatures[0] == N.isometry_signature(of_link=True)
|
|
583
|
+
|
|
584
|
+
for mfd in mfds:
|
|
585
|
+
assert mfd.is_isometric_to(M, True)[0].extends_to_link()
|
|
586
|
+
assert mfd.is_isometric_to(N, True)[0].extends_to_link()
|
|
587
|
+
|
|
588
|
+
print("Tested that decorated isometry_signature is a link invariant")
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
def helper_are_isometric(M, N):
|
|
592
|
+
for i in range(100):
|
|
593
|
+
try:
|
|
594
|
+
if M.is_isometric_to(N):
|
|
595
|
+
return
|
|
596
|
+
except:
|
|
597
|
+
pass
|
|
598
|
+
M.randomize()
|
|
599
|
+
N.randomize()
|
|
600
|
+
|
|
601
|
+
raise Exception("Could not find isometry")
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
def helper_test_by_dehn_filling(M):
|
|
605
|
+
from snappy import Manifold
|
|
606
|
+
|
|
607
|
+
M_filled = M.filled_triangulation()
|
|
608
|
+
|
|
609
|
+
for ignore_cusp_ordering in [ False, True]:
|
|
610
|
+
for ignore_curve_orientations in [ False, True]:
|
|
611
|
+
isosig = M.triangulation_isosig(
|
|
612
|
+
decorated=True,
|
|
613
|
+
ignore_cusp_ordering=ignore_cusp_ordering,
|
|
614
|
+
ignore_curve_orientations=ignore_curve_orientations)
|
|
615
|
+
N = Manifold(isosig)
|
|
616
|
+
N_filled = N.filled_triangulation()
|
|
617
|
+
|
|
618
|
+
helper_are_isometric(M, N)
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def test_by_dehn_filling():
|
|
622
|
+
import random
|
|
623
|
+
|
|
624
|
+
from snappy import OrientableCuspedCensus
|
|
625
|
+
|
|
626
|
+
count = 0
|
|
627
|
+
|
|
628
|
+
for M in OrientableCuspedCensus(cusps=3):
|
|
629
|
+
for i in range(20):
|
|
630
|
+
unfilled = random.randint(0, 2)
|
|
631
|
+
for c in range(3):
|
|
632
|
+
if c != unfilled:
|
|
633
|
+
fillings = [(1,0), (0,1), (11,12), (-13,16),
|
|
634
|
+
(9,-11), (8, 9), (1,7), (13, 14),
|
|
635
|
+
(14,-15), (17, -18)]
|
|
636
|
+
M.dehn_fill(fillings[random.randint(0, len(fillings) - 1)],
|
|
637
|
+
c)
|
|
638
|
+
|
|
639
|
+
if 'positive' in M.solution_type():
|
|
640
|
+
count += 1
|
|
641
|
+
helper_test_by_dehn_filling(M)
|
|
642
|
+
|
|
643
|
+
print("Tested %d randomly Dehn filled manifolds" % count)
|
|
644
|
+
|
|
645
|
+
def test_slope_transformations():
|
|
646
|
+
"""
|
|
647
|
+
Tests that slopes are transformed so that the filled
|
|
648
|
+
manifold is the same.
|
|
649
|
+
"""
|
|
650
|
+
|
|
651
|
+
import snappy
|
|
652
|
+
M = snappy.ManifoldHP("L14n63023(-5,1)(5,1)(10,1)")
|
|
653
|
+
oriented_isosig = M.triangulation_isosig(
|
|
654
|
+
decorated=False, ignore_orientation=False)
|
|
655
|
+
isosig = M.triangulation_isosig(
|
|
656
|
+
decorated=False)
|
|
657
|
+
Mop = M.copy()
|
|
658
|
+
Mop.reverse_orientation()
|
|
659
|
+
reverse_oriented_isosig = Mop.triangulation_isosig(
|
|
660
|
+
decorated=False, ignore_orientation=False)
|
|
661
|
+
|
|
662
|
+
if oriented_isosig != 'vLLvvLLMALQQzQQceillmnppqrlmrqtruututiivimllaelaqxrvdoxqltt':
|
|
663
|
+
raise AssertionError()
|
|
664
|
+
if isosig != 'vLLvLLPwPQLAMPQcefikkmnplkopqrsttutuuiixvimqlippawidlabavth':
|
|
665
|
+
raise AssertionError()
|
|
666
|
+
|
|
667
|
+
# The canonical orientation (used to compute the unoriented isosig)
|
|
668
|
+
# is the reverse of the actual orientation:
|
|
669
|
+
if reverse_oriented_isosig != isosig:
|
|
670
|
+
raise AssertionError()
|
|
671
|
+
if oriented_isosig == isosig:
|
|
672
|
+
raise ValueError()
|
|
673
|
+
|
|
674
|
+
isom_sig_pos = M.isometry_signature(ignore_orientation = False)
|
|
675
|
+
if isom_sig_pos != 'KLALvLwLLwMQLQPAMzMzMPzMPcbbeghnklntpqpqvrswtuvxyzABCDEFEGHIJJhhkofnaocnmrlsiaowxfcsaxhxhxhxhjhhhhs':
|
|
676
|
+
raise AssertionError()
|
|
677
|
+
isom_sig_neg = Mop.isometry_signature(ignore_orientation = False)
|
|
678
|
+
if isom_sig_neg != 'KLAMvMvvAwLvQPPPQMPzMPzMPcbbdegilopoouqtryvuxvwxzzBACDEFEGHIJJhhkhhohahrscaagwxkkgbvwpuxwqxqxwxxxxr':
|
|
679
|
+
raise AssertionError()
|
|
680
|
+
|
|
681
|
+
# It is not just the triangulation that is chiral, the manifold itself is:
|
|
682
|
+
if isom_sig_pos == isom_sig_neg:
|
|
683
|
+
raise ValueError()
|
|
684
|
+
|
|
685
|
+
# So we expect the oriented isometry signature to flip when neither the isomorphism
|
|
686
|
+
# signature nor its decoration capture the orientation.
|
|
687
|
+
for ignore_cusp_ordering in [False, True]:
|
|
688
|
+
for ignore_curves in [False, True]:
|
|
689
|
+
for ignore_curve_orientations in [False, True]:
|
|
690
|
+
for ignore_filling_orientations in [False, True]:
|
|
691
|
+
for ignore_orientation in [False, True]:
|
|
692
|
+
isosig = M.triangulation_isosig(
|
|
693
|
+
ignore_cusp_ordering = ignore_cusp_ordering,
|
|
694
|
+
ignore_curves = ignore_curves,
|
|
695
|
+
ignore_curve_orientations = ignore_curve_orientations,
|
|
696
|
+
ignore_filling_orientations = ignore_filling_orientations,
|
|
697
|
+
ignore_orientation = ignore_orientation)
|
|
698
|
+
isom_sig = (
|
|
699
|
+
snappy.ManifoldHP(isosig)
|
|
700
|
+
.isometry_signature(ignore_orientation = False))
|
|
701
|
+
does_ignore_orientation = (
|
|
702
|
+
ignore_orientation and
|
|
703
|
+
(ignore_curve_orientations or ignore_curves))
|
|
704
|
+
expected_isom_sig = (
|
|
705
|
+
isom_sig_neg
|
|
706
|
+
if does_ignore_orientation
|
|
707
|
+
else isom_sig_pos)
|
|
708
|
+
if isom_sig != expected_isom_sig:
|
|
709
|
+
raise AssertionError()
|
|
710
|
+
print("Tested slope transformations")
|
|
711
|
+
|
|
712
|
+
def run_tests():
|
|
713
|
+
test_integer_list_encoder()
|
|
714
|
+
main_test()
|
|
715
|
+
test_link_invariant()
|
|
716
|
+
test_by_dehn_filling()
|
|
717
|
+
test_slope_transformations()
|