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,112 @@
|
|
|
1
|
+
def pos_tets(manifold):
|
|
2
|
+
return manifold.solution_type() == 'all tetrahedra positively oriented'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def basic_improve_tri(manifold, tries=10):
|
|
6
|
+
M = manifold.copy()
|
|
7
|
+
for i in range(tries):
|
|
8
|
+
if pos_tets(M):
|
|
9
|
+
return M
|
|
10
|
+
M.randomize()
|
|
11
|
+
return manifold.copy()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def improved_triangulation(manifold, tries=10):
|
|
15
|
+
M = basic_improve_tri(manifold, tries=tries)
|
|
16
|
+
if pos_tets(M):
|
|
17
|
+
return M
|
|
18
|
+
|
|
19
|
+
curves = M.dual_curves()
|
|
20
|
+
for i, c in zip(range(tries), curves):
|
|
21
|
+
D = M.drill(c)
|
|
22
|
+
D.dehn_fill((1, 0), M.num_cusps())
|
|
23
|
+
F = D.filled_triangulation()
|
|
24
|
+
if pos_tets(F):
|
|
25
|
+
return F
|
|
26
|
+
|
|
27
|
+
return manifold.copy()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def is_isometric_to_with_effort(A, B, return_isometries=False, tries=10):
|
|
31
|
+
A = improved_triangulation(A, tries=tries)
|
|
32
|
+
B = improved_triangulation(B, tries=tries)
|
|
33
|
+
try:
|
|
34
|
+
return A.is_isometric_to(B, return_isometries=return_isometries)
|
|
35
|
+
except RuntimeError: # SnapPea kernel failed
|
|
36
|
+
return []
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def orient_pres(isometry):
|
|
40
|
+
"""
|
|
41
|
+
>>> M = Manifold('K4a1')
|
|
42
|
+
>>> kinds = {orient_pres(iso) for iso in M.is_isometric_to(M, True)}
|
|
43
|
+
>>> sorted(kinds)
|
|
44
|
+
[False, True]
|
|
45
|
+
"""
|
|
46
|
+
return isometry.cusp_maps()[0].det() > 0
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def are_orient_pres_isometric_as_ordered_links(A, B):
|
|
50
|
+
"""
|
|
51
|
+
All of the following manifolds isometric, but not as ordered links
|
|
52
|
+
|
|
53
|
+
>>> A = Manifold('L10n1')
|
|
54
|
+
>>> B = Manifold('L7a2')
|
|
55
|
+
>>> C = Manifold('L10n1')
|
|
56
|
+
>>> C._reindex_cusps([1, 0])
|
|
57
|
+
>>> are_orient_pres_isometric_as_ordered_links(A, B)
|
|
58
|
+
False
|
|
59
|
+
>>> are_orient_pres_isometric_as_ordered_links(A, C)
|
|
60
|
+
False
|
|
61
|
+
>>> are_orient_pres_isometric_as_ordered_links(C, C)
|
|
62
|
+
True
|
|
63
|
+
"""
|
|
64
|
+
isos = is_isometric_to_with_effort(A, B, return_isometries=True)
|
|
65
|
+
isos = [iso for iso in isos if iso.extends_to_link() and orient_pres(iso)]
|
|
66
|
+
ident = list(range(A.num_cusps()))
|
|
67
|
+
return any(iso.cusp_images() == ident for iso in isos)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def orientation_preserving_link_isometries(A, B, tries=100):
|
|
71
|
+
isos = is_isometric_to_with_effort(A, B, return_isometries=True, tries=tries)
|
|
72
|
+
ans = any(iso.extends_to_link() for iso in isos)
|
|
73
|
+
if not ans:
|
|
74
|
+
A, B = A.high_precision(), B.high_precision()
|
|
75
|
+
isos = is_isometric_to_with_effort(A, B, return_isometries=True, tries=tries)
|
|
76
|
+
good_isos = [iso for iso in isos if iso.extends_to_link() and orient_pres(iso)]
|
|
77
|
+
if good_isos:
|
|
78
|
+
return good_isos[0]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def reorder_link_components(link, perm):
|
|
82
|
+
"""
|
|
83
|
+
This link has three components, which are in order a trefoil, the
|
|
84
|
+
figure 8, and an unknot.
|
|
85
|
+
|
|
86
|
+
>>> L0 = Manifold('DT[uciicOFRTIQKUDsMpgBelAnjCH.000001011100110110010]').link()
|
|
87
|
+
>>> [len(L0.sublink([i]).crossings) for i in range(3)]
|
|
88
|
+
[3, 4, 0]
|
|
89
|
+
|
|
90
|
+
perm is the permutation of {0, 1, ... , num_comps - 1} where
|
|
91
|
+
perm[old_comp_index] = new_comp_index.
|
|
92
|
+
|
|
93
|
+
>>> L1 = reorder_link_components(L0, [1, 2, 0])
|
|
94
|
+
>>> [len(L1.sublink([i]).crossings) for i in range(3)]
|
|
95
|
+
[0, 3, 4]
|
|
96
|
+
>>> L2 = reorder_link_components(L0, [2, 0, 1])
|
|
97
|
+
>>> [len(L2.sublink([i]).crossings) for i in range(3)]
|
|
98
|
+
[4, 0, 3]
|
|
99
|
+
"""
|
|
100
|
+
n = len(link.link_components)
|
|
101
|
+
assert len(perm) == n and link.unlinked_unknot_components == 0
|
|
102
|
+
L = link.copy()
|
|
103
|
+
component_starts = n * [None]
|
|
104
|
+
for a, b in enumerate(perm):
|
|
105
|
+
component_starts[b] = L.link_components[a][0]
|
|
106
|
+
L._build_components(component_starts)
|
|
107
|
+
return L
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
if __name__ == '__main__':
|
|
111
|
+
import doctest
|
|
112
|
+
doctest.testmod()
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"""
|
|
2
|
+
For a PL link in R^3, produce a link diagram by projecting it onto a
|
|
3
|
+
plane (by default a randomly chosen one). Also includes code for
|
|
4
|
+
simplifying a PL link by basic straightening moves.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import spherogram
|
|
8
|
+
import random
|
|
9
|
+
import itertools
|
|
10
|
+
from . import pl_utils
|
|
11
|
+
from .rational_linear_algebra import QQ, Matrix, Vector3
|
|
12
|
+
from .exceptions import GeneralPositionError
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def fig8_points():
|
|
16
|
+
# Extracted from put_in_S3.example10, used for testing.
|
|
17
|
+
pts = [(1564, 148, 0, 1117), (765, 1137, 786, 1117), (1117, 1882, 1490, 1117),
|
|
18
|
+
(1469, 1137, 786, 1117), (698, 280, 0, 1117), (1166, 372, -744, 1117),
|
|
19
|
+
(1862, 372, -1440, 1117), (1514, 1068, -744, 1117), (380, 198, 0, 279),
|
|
20
|
+
(564, 604, 604, 559), (701, 219, 438, 1117), (-679, -241, 0, 1117),
|
|
21
|
+
(460, 679, -482, 1117)]
|
|
22
|
+
return [[Vector3([a, b, c])/d for a, b, c, d in pts]]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def twist_knot_points():
|
|
26
|
+
"""
|
|
27
|
+
The knot 5_2 = K5a1
|
|
28
|
+
"""
|
|
29
|
+
pts = [(25, 36, 5), (14, 36, -3), (14, 14, 0), (47, 14, 0), (47, 25, 0),
|
|
30
|
+
(3, 25, 0), (3, 47, 0), (36, 47, -6), (36, 3, 4), (25, 3, -5)]
|
|
31
|
+
return [[Vector3(pt) for pt in pts]]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def proj(point): # projection onto z = 0
|
|
35
|
+
return Vector3([point[i] for i in [0,1]]+[0])
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def random_transform(steps=5):
|
|
39
|
+
"""
|
|
40
|
+
Generators of SL(3, Z) from
|
|
41
|
+
|
|
42
|
+
https://doi.org/10.1090/S0002-9939-1992-1079696-5
|
|
43
|
+
|
|
44
|
+
>>> random_transform(5).det()
|
|
45
|
+
1
|
|
46
|
+
"""
|
|
47
|
+
I = Matrix([[1, 0, 0], [0, 1, 0], [ 0, 0, 1]])
|
|
48
|
+
X = Matrix([[0, 1, 0], [0, 0, 1], [ 1, 0, 0]])
|
|
49
|
+
Y = Matrix([[1, 0, 1], [0, -1, -1], [ 0, 1, 0]])
|
|
50
|
+
Z = Matrix([[0, 1, 0], [1, 0, 0], [-1, -1, -1]])
|
|
51
|
+
# X and Y have order two and Z order three, so there are
|
|
52
|
+
# symmetric gens:
|
|
53
|
+
gens = [I, X, X*X, Y, Y*Y, Z, Z]
|
|
54
|
+
ans = I
|
|
55
|
+
for s in range(steps):
|
|
56
|
+
ans = ans * random.choice(gens)
|
|
57
|
+
return ans
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def norm_sq(v):
|
|
61
|
+
return sum(x**2 for x in v)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def min_dist_sq(points):
|
|
65
|
+
pairs = itertools.combinations(points, 2)
|
|
66
|
+
return min(norm_sq(p - q) for p, q in pairs)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def straightenable_tri(points, extra_arcs=None):
|
|
70
|
+
if extra_arcs is None:
|
|
71
|
+
extra_arcs = []
|
|
72
|
+
n = len(points)
|
|
73
|
+
for i in range(n):
|
|
74
|
+
indices = i, (i + 1) % n, (i + 2) % n
|
|
75
|
+
tri = [points[k] for k in indices]
|
|
76
|
+
other_arcs = [(points[k], points[(k+1) % n])
|
|
77
|
+
for k in range(n) if k not in indices[:2]]
|
|
78
|
+
if pl_utils.colinear(*tri):
|
|
79
|
+
return indices
|
|
80
|
+
M = pl_utils.standardize_bend_matrix(*tri)
|
|
81
|
+
if all(pl_utils.can_straighten_bend(a, tri, False, M)
|
|
82
|
+
for a in other_arcs + extra_arcs):
|
|
83
|
+
return indices
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def arcs_from_points(points_list):
|
|
87
|
+
arcs = []
|
|
88
|
+
for p in points_list:
|
|
89
|
+
n = len(p)
|
|
90
|
+
arcs += [(p[k], p[(k+1) % n]) for k in range(n)]
|
|
91
|
+
return arcs
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def straighten_knot(points):
|
|
95
|
+
while True:
|
|
96
|
+
tri = straightenable_tri(points)
|
|
97
|
+
if tri:
|
|
98
|
+
a, b, c = tri
|
|
99
|
+
# We shuffle is so that we look for next triangle in less examined location
|
|
100
|
+
if a < b < c:
|
|
101
|
+
points = points[c:] + points[:b]
|
|
102
|
+
else:
|
|
103
|
+
points = points[:b] + points[b + 1:]
|
|
104
|
+
else:
|
|
105
|
+
break
|
|
106
|
+
return points
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def straighten_link(points_list):
|
|
110
|
+
for i in range(len(points_list)):
|
|
111
|
+
other_points = points_list.copy()
|
|
112
|
+
del other_points[i]
|
|
113
|
+
other_arcs = arcs_from_points(other_points)
|
|
114
|
+
while True:
|
|
115
|
+
points = points_list[i]
|
|
116
|
+
tri = straightenable_tri(points, other_arcs)
|
|
117
|
+
if tri:
|
|
118
|
+
a, b, c = tri
|
|
119
|
+
if a < b < c:
|
|
120
|
+
points = points[c:] + points[:b]
|
|
121
|
+
else:
|
|
122
|
+
points = points[:b] + points[b + 1:]
|
|
123
|
+
else:
|
|
124
|
+
break
|
|
125
|
+
points_list[i] = points
|
|
126
|
+
return points_list
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class Arc():
|
|
130
|
+
"""
|
|
131
|
+
An arc from point a to point b where a and b are labeled by i and j.
|
|
132
|
+
"""
|
|
133
|
+
def __init__(self, a, i, b, j, label):
|
|
134
|
+
self.a, self.i, self.b, self.j, self.label = a, i, b, j, label
|
|
135
|
+
self.proj = a[:2], b[:2]
|
|
136
|
+
self.crossings = []
|
|
137
|
+
|
|
138
|
+
def __getitem__(self, index):
|
|
139
|
+
return [self.a, self.b][index]
|
|
140
|
+
|
|
141
|
+
def add_crossing(self, crossing, t):
|
|
142
|
+
self.crossings.append((t, crossing))
|
|
143
|
+
try:
|
|
144
|
+
self.crossings.sort()
|
|
145
|
+
except TypeError:
|
|
146
|
+
raise GeneralPositionError('Two crossings on top of one another')
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class Crossing():
|
|
150
|
+
def __init__(self, over_arc, under_arc, s, t, label):
|
|
151
|
+
self.over, self.under, self.label = over_arc, under_arc, label
|
|
152
|
+
self.s, self.t = s, t
|
|
153
|
+
a, b = over_arc.proj
|
|
154
|
+
u, v = under_arc.proj
|
|
155
|
+
M = Matrix([b - a, v - u])
|
|
156
|
+
self.sign = 1 if M.det() > 0 else -1
|
|
157
|
+
e = 1e-12
|
|
158
|
+
assert (1 - s)*a + s*b == (1 - t)*u + t*v
|
|
159
|
+
assert ((e < s < 1 - e) and (e < t < 1 - e))
|
|
160
|
+
over_arc.add_crossing(self, s)
|
|
161
|
+
under_arc.add_crossing(self, t)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class LinkProjection():
|
|
165
|
+
"""
|
|
166
|
+
The idea is to apply a unimodular matrix and to project the knot
|
|
167
|
+
onto the z=0 plane. We then recover the crossing data by finding
|
|
168
|
+
points that intersect after projecting then taking the over
|
|
169
|
+
crossing to be the lift with larger z coord.
|
|
170
|
+
|
|
171
|
+
>>> pts = fig8_points()
|
|
172
|
+
>>> kp = LinkProjection(pts)
|
|
173
|
+
>>> K = kp.link()
|
|
174
|
+
>>> K.exterior().identify()
|
|
175
|
+
[m004(0,0), 4_1(0,0), K2_1(0,0), K4a1(0,0), otet02_00001(0,0)]
|
|
176
|
+
|
|
177
|
+
>>> M = Matrix([[0,1,1],[1,1,0],[0,0,2]])
|
|
178
|
+
>>> kp = LinkProjection(pts, M)
|
|
179
|
+
>>> K = kp.link()
|
|
180
|
+
>>> K.exterior().identify()
|
|
181
|
+
[m004(0,0), 4_1(0,0), K2_1(0,0), K4a1(0,0), otet02_00001(0,0)]
|
|
182
|
+
|
|
183
|
+
>>> kp = LinkProjection(twist_knot_points())
|
|
184
|
+
>>> K = kp.link()
|
|
185
|
+
>>> M = Manifold('K5a1')
|
|
186
|
+
>>> isos = M.is_isometric_to(K.exterior(), True)
|
|
187
|
+
>>> {iso.cusp_maps()[0].det() for iso in isos}
|
|
188
|
+
{1}
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
def __init__(self, points_by_component, mat=None):
|
|
192
|
+
# mat is a matrix, we transform the points by mat then project
|
|
193
|
+
# onto z = 0 plane, plane is point and vector
|
|
194
|
+
if mat is None:
|
|
195
|
+
mat = Matrix([[0, -2, -1], [1, 2, 2], [-1, 1, 0]])
|
|
196
|
+
self.mat = mat
|
|
197
|
+
|
|
198
|
+
components = []
|
|
199
|
+
for component_points in points_by_component:
|
|
200
|
+
start = sum(len(C) for C in components)
|
|
201
|
+
comp_len = len(component_points)
|
|
202
|
+
components.append(list(range(start, start + comp_len)))
|
|
203
|
+
|
|
204
|
+
self.components = components
|
|
205
|
+
all_points = sum(points_by_component, [])
|
|
206
|
+
self.points = [mat*p for p in all_points]
|
|
207
|
+
self.projected_points = [proj(p) for p in self.points]
|
|
208
|
+
|
|
209
|
+
# Check that nothing is too degenerate:
|
|
210
|
+
assert min_dist_sq(self.points) > 1e-15
|
|
211
|
+
if min_dist_sq(self.projected_points) < 1e-16:
|
|
212
|
+
raise GeneralPositionError('Projection is nearly degenerate')
|
|
213
|
+
|
|
214
|
+
self._setup_crossings()
|
|
215
|
+
|
|
216
|
+
def _setup_crossings(self):
|
|
217
|
+
# compute the over and under crossings of the link projection
|
|
218
|
+
|
|
219
|
+
pts = self.points
|
|
220
|
+
crossings, arcs = [], []
|
|
221
|
+
for component in self.components:
|
|
222
|
+
successive_pairs = [(c, component[(i + 1) % len(component)]) for
|
|
223
|
+
i, c in enumerate(component)]
|
|
224
|
+
arcs += [Arc(pts[i], i, pts[j], j, i) for i, j in successive_pairs]
|
|
225
|
+
|
|
226
|
+
for A, B in itertools.combinations(arcs, 2):
|
|
227
|
+
a = proj(A[0]), proj(A[1])
|
|
228
|
+
b = proj(B[0]), proj(B[1])
|
|
229
|
+
|
|
230
|
+
# When A and B are successive arcs, we just need to test
|
|
231
|
+
# things are sufficiently generic.
|
|
232
|
+
|
|
233
|
+
if A.j == B.i:
|
|
234
|
+
# assert not near_reverse(a[0], a[1], b[1])
|
|
235
|
+
continue
|
|
236
|
+
elif B.j == A.i:
|
|
237
|
+
# assert not near_reverse(b[0], b[1], a[1])
|
|
238
|
+
continue
|
|
239
|
+
elif pl_utils.segments_meet_not_at_endpoint(a, b):
|
|
240
|
+
# There is a crossing and now we figure out which arc
|
|
241
|
+
# crosses over the other.
|
|
242
|
+
|
|
243
|
+
# find the intersection point
|
|
244
|
+
M = Matrix([a[1]-a[0], b[0]-b[1]]).transpose()
|
|
245
|
+
if M.rank() != 2:
|
|
246
|
+
raise GeneralPositionError('Segments overlap on their interiors')
|
|
247
|
+
s, t = M.solve_right(b[0]-a[0])
|
|
248
|
+
e = 1e-12
|
|
249
|
+
if not ((e < s < 1 - e) and (e < t < 1 - e)):
|
|
250
|
+
raise GeneralPositionError('Intersection too near the end of one segment')
|
|
251
|
+
|
|
252
|
+
x_a = (1-s)*A[0] + s*A[1] # lift of intersection to A
|
|
253
|
+
x_b = (1-t)*B[0] + t*B[1] # lift of intersection to B
|
|
254
|
+
|
|
255
|
+
# make sure our lifts project to same point in plane
|
|
256
|
+
assert norm_sq(proj(x_a - x_b)) < 1e-5
|
|
257
|
+
|
|
258
|
+
# whichever arc contains the higher intersection
|
|
259
|
+
# lifted point is the over crossing arc
|
|
260
|
+
height_a = x_a[2]
|
|
261
|
+
height_b = x_b[2]
|
|
262
|
+
|
|
263
|
+
assert abs(height_a - height_b) > 1e-14
|
|
264
|
+
if height_a > height_b:
|
|
265
|
+
crossings.append(Crossing(A, B, s, t, len(crossings)))
|
|
266
|
+
else:
|
|
267
|
+
crossings.append(Crossing(B, A, t, s, len(crossings)))
|
|
268
|
+
|
|
269
|
+
self.crossings, self.arcs = crossings, arcs
|
|
270
|
+
|
|
271
|
+
def link(self):
|
|
272
|
+
# For bookkeeping, we use a Strand for each point the
|
|
273
|
+
# projection, together with the obviously needed crossings.
|
|
274
|
+
|
|
275
|
+
strands = [spherogram.Strand(label='S%d' % i)
|
|
276
|
+
for i, p in enumerate(self.points)]
|
|
277
|
+
crossings = [spherogram.Crossing(label='C%d' % i)
|
|
278
|
+
for i, c in enumerate(self.crossings)]
|
|
279
|
+
|
|
280
|
+
for arc in self.arcs:
|
|
281
|
+
A, a = strands[arc.i], 1
|
|
282
|
+
for t, C in arc.crossings:
|
|
283
|
+
B = crossings[C.label]
|
|
284
|
+
if arc == C.over:
|
|
285
|
+
b = 3 if C.sign == 1 else 1
|
|
286
|
+
else:
|
|
287
|
+
b = 0
|
|
288
|
+
# glue up
|
|
289
|
+
A[a] = B[b]
|
|
290
|
+
A, a = B, (b + 2) % 4
|
|
291
|
+
|
|
292
|
+
# glue to Strand corresponding to the endpoint of the arc.
|
|
293
|
+
B, b = strands[arc.j], 0
|
|
294
|
+
A[a] = B[b]
|
|
295
|
+
|
|
296
|
+
L = spherogram.Link(strands + crossings)
|
|
297
|
+
return L
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def project_to_diagram(link_in_R3):
|
|
301
|
+
"""
|
|
302
|
+
>>> project_to_diagram(fig8_points())
|
|
303
|
+
<Link: 1 comp; 4 cross>
|
|
304
|
+
"""
|
|
305
|
+
diagram = None
|
|
306
|
+
for mat_size in [None, 15, 25, 15, 25, 15, 25, 100, 250, 100, 250, 500, 500]:
|
|
307
|
+
if mat_size is None:
|
|
308
|
+
proj_mat = Matrix([[3, 1, 0], [1, -1, 5], [0, 0, -1]])
|
|
309
|
+
else:
|
|
310
|
+
proj_mat = random_transform(mat_size)
|
|
311
|
+
try:
|
|
312
|
+
projection = LinkProjection(link_in_R3, proj_mat)
|
|
313
|
+
diagram = projection.link()
|
|
314
|
+
break
|
|
315
|
+
except GeneralPositionError as e:
|
|
316
|
+
pass
|
|
317
|
+
|
|
318
|
+
return diagram
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
if __name__ == '__main__':
|
|
322
|
+
import doctest
|
|
323
|
+
print(doctest.testmod())
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Defines the main function `exterior_to_link`.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import random
|
|
6
|
+
import typing
|
|
7
|
+
from .exceptions import ExteriorToLinkError
|
|
8
|
+
from .simplify_to_base_tri import good_simplification
|
|
9
|
+
from . import put_in_S3
|
|
10
|
+
from . import link_projection
|
|
11
|
+
from .rational_linear_algebra import Matrix
|
|
12
|
+
from . import hyp_utils
|
|
13
|
+
from ..SnapPy import set_rand_seed
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def filled_is_3sphere(manifold):
|
|
17
|
+
"""
|
|
18
|
+
>>> isosig = 'nLvLLLPQQkcfejimhklkmlkmuphkvuoupilhhv_Bbba(1, 0)'
|
|
19
|
+
>>> filled_is_3sphere(Manifold(isosig))
|
|
20
|
+
True
|
|
21
|
+
>>> filled_is_3sphere(Triangulation('m004(1, 2)'))
|
|
22
|
+
False
|
|
23
|
+
"""
|
|
24
|
+
if hasattr(manifold, 'without_hyperbolic_structure'):
|
|
25
|
+
T = manifold.without_hyperbolic_structure()
|
|
26
|
+
else:
|
|
27
|
+
T = manifold.copy()
|
|
28
|
+
for i in range(T.num_cusps()):
|
|
29
|
+
if T.cusp_info(i).is_complete:
|
|
30
|
+
T.dehn_fill((1, 0), i)
|
|
31
|
+
|
|
32
|
+
for i in range(10):
|
|
33
|
+
if T.fundamental_group().num_generators() == 0:
|
|
34
|
+
return True
|
|
35
|
+
F = T.filled_triangulation()
|
|
36
|
+
if F.fundamental_group().num_generators() == 0:
|
|
37
|
+
return True
|
|
38
|
+
T.randomize()
|
|
39
|
+
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def exterior_to_link(manifold,
|
|
44
|
+
verbose : bool = False,
|
|
45
|
+
check_input : bool = True,
|
|
46
|
+
check_answer : bool = True,
|
|
47
|
+
careful_perturbation : bool = True,
|
|
48
|
+
simplify_link : bool = True,
|
|
49
|
+
pachner_search_tries :int = 10,
|
|
50
|
+
seed : typing.Optional[int] = None) -> 'Link':
|
|
51
|
+
"""
|
|
52
|
+
For a triangulation of the exterior of a link in the 3-sphere,
|
|
53
|
+
return a planar diagram for the link. The peripheral curves whose
|
|
54
|
+
Dehn filling is the 3-sphere are **part of the input**, specified
|
|
55
|
+
by either:
|
|
56
|
+
|
|
57
|
+
a. If no cusp is filled, then they are the meridians of the
|
|
58
|
+
current peripheral curves.
|
|
59
|
+
|
|
60
|
+
b. If every cusp is filled, then they are the current Dehn filling
|
|
61
|
+
curves.
|
|
62
|
+
|
|
63
|
+
In particular, it does **not** try to determine whether there exist
|
|
64
|
+
fillings on the input which give the 3-sphere. Example usage:
|
|
65
|
+
|
|
66
|
+
>>> M = Manifold('m016')
|
|
67
|
+
>>> L = exterior_to_link(M)
|
|
68
|
+
>>> L.exterior().is_isometric_to(M)
|
|
69
|
+
True
|
|
70
|
+
|
|
71
|
+
The algorithm used is that of `Dunfield, Obeidin, and Rudd
|
|
72
|
+
<https://arxiv.org/abs/2112.03251>`_. The optional arguments are
|
|
73
|
+
as follows.
|
|
74
|
+
|
|
75
|
+
* ``verbose``: When ``True``, prints progress updates as the algorithm
|
|
76
|
+
goes along.
|
|
77
|
+
|
|
78
|
+
* ``check_input``: When ``True`` (the default), first checks that the
|
|
79
|
+
fundamental group of the specified Dehn filling is trivial. As
|
|
80
|
+
it doesn't try too hard to simplify the group presentation, it
|
|
81
|
+
can happen that this check fails but the algorithm still finds a
|
|
82
|
+
diagram if you pass ``check_input=False``.
|
|
83
|
+
|
|
84
|
+
* ``check_answer``: When ``True`` (the default), take the exterior of
|
|
85
|
+
the final link diagram and use ``Manifold.is_isometric_to`` to
|
|
86
|
+
confirm that it is homeomorphic to the input. If the input is
|
|
87
|
+
not hyperbolic or is very large, this check may fail even though
|
|
88
|
+
the diagram is correct.
|
|
89
|
+
|
|
90
|
+
* ``careful_perturbation``: The rational coordinates of the
|
|
91
|
+
intermediate PL links are periodically rounded to control the
|
|
92
|
+
size of their denominators. When ``careful_perturbation=True``
|
|
93
|
+
(the default), computations are performed to ensure this
|
|
94
|
+
rounding does not change the isotopy class of the link.
|
|
95
|
+
|
|
96
|
+
* ``simplify_link``: When ``True`` (the default), uses
|
|
97
|
+
``Link.simplify('global')`` to minimize the size of the final
|
|
98
|
+
diagram; otherwise, it just does ``basic`` simplifications, which
|
|
99
|
+
can be much faster if the initial link is complicated.
|
|
100
|
+
|
|
101
|
+
* ``pachner_search_tries``: Controls how hard to search for a
|
|
102
|
+
suitable sequence of Pachner moves from the filled input
|
|
103
|
+
triangulation to a standard triangulation of the 3-sphere.
|
|
104
|
+
|
|
105
|
+
* ``seed``: The algorithm involves many random choices, and hence
|
|
106
|
+
each run typically produces a different diagram of the
|
|
107
|
+
underlying link. If you need the same output each time, you can
|
|
108
|
+
specify a fixed seed for the various pseudo-random number
|
|
109
|
+
generators.
|
|
110
|
+
|
|
111
|
+
Note on rigor: Provided at least one of ``check_answer`` and
|
|
112
|
+
``careful_perturbation`` is ``True``, the exterior of the output
|
|
113
|
+
link is guaranteed to match the input (including the choice of
|
|
114
|
+
meridians).
|
|
115
|
+
|
|
116
|
+
**Warning:** The order of the link components and the cusps of the
|
|
117
|
+
input manifold is only guaranteed to match when
|
|
118
|
+
``check_answer=True``. Even then, the implicit orientation along
|
|
119
|
+
each component of the link may not be preserved.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
unfilled = set(manifold.cusp_info('is_complete'))
|
|
123
|
+
if unfilled == {True, False}:
|
|
124
|
+
raise ValueError('Cusps should either be all filled or all unfilled')
|
|
125
|
+
|
|
126
|
+
if check_input and not filled_is_3sphere(manifold):
|
|
127
|
+
raise ValueError('Filling in the meridians does not obviously give S^3')
|
|
128
|
+
|
|
129
|
+
def print_status(*args, **kwargs):
|
|
130
|
+
if verbose:
|
|
131
|
+
print(*args, **kwargs, flush=True)
|
|
132
|
+
|
|
133
|
+
print_status(f'Finding link for {manifold.name()}')
|
|
134
|
+
if seed is not None:
|
|
135
|
+
seed = int(seed)
|
|
136
|
+
random.seed(seed)
|
|
137
|
+
set_rand_seed(seed)
|
|
138
|
+
print_status(' Seed:', seed)
|
|
139
|
+
|
|
140
|
+
print_status(' Finding moves to base triangulation of S^3...')
|
|
141
|
+
tris_with_moves = good_simplification(manifold,
|
|
142
|
+
max_tries=pachner_search_tries)
|
|
143
|
+
if tris_with_moves:
|
|
144
|
+
M, moves, expanded_moves = tris_with_moves
|
|
145
|
+
else:
|
|
146
|
+
raise ExteriorToLinkError('Could not simplify to standard triangulation of S^3')
|
|
147
|
+
|
|
148
|
+
print_status(f' Starting with {len(M)} tets, to do {len(moves)} simple Pachner moves.')
|
|
149
|
+
M.perform_moves(moves, push=True, straighten=True, round=True, careful=careful_perturbation)
|
|
150
|
+
M.rebuild()
|
|
151
|
+
M.connect_arcs()
|
|
152
|
+
print_status(' Moves resulted in', sum(len(tet.arcs) for tet in M),
|
|
153
|
+
f'PL segments; max denom of coor is {M._curr_max_denom()}.')
|
|
154
|
+
print_status(' Embedding in S3...', end='')
|
|
155
|
+
link_in_R3 = put_in_S3.embed_link_in_S3(M)
|
|
156
|
+
link_in_R3 = link_projection.straighten_link(link_in_R3)
|
|
157
|
+
num_seg = sum(len(component) + 1 for component in link_in_R3)
|
|
158
|
+
print_status('got PL link of', num_seg ,'segments.')
|
|
159
|
+
print_status(' Projecting...', end='')
|
|
160
|
+
|
|
161
|
+
L = link_projection.project_to_diagram(link_in_R3)
|
|
162
|
+
if L is None:
|
|
163
|
+
raise ExteriorToLinkError('Was unable to project link')
|
|
164
|
+
|
|
165
|
+
L.simplify('basic')
|
|
166
|
+
print_status(f'got diagram with {len(L.crossings)} crossings.')
|
|
167
|
+
|
|
168
|
+
if simplify_link:
|
|
169
|
+
print_status(' Simplifying diagram...', end='')
|
|
170
|
+
L.simplify('pickup')
|
|
171
|
+
print_status(f'{len(L.crossings)} crossings...', end='')
|
|
172
|
+
L.simplify('global')
|
|
173
|
+
print_status(f'{len(L.crossings)} crossings.')
|
|
174
|
+
|
|
175
|
+
if check_answer:
|
|
176
|
+
E = L.exterior()
|
|
177
|
+
if unfilled == {True}:
|
|
178
|
+
F = manifold
|
|
179
|
+
else:
|
|
180
|
+
F = manifold.copy()
|
|
181
|
+
F.set_peripheral_curves('fillings')
|
|
182
|
+
F.dehn_fill(F.num_cusps()*[(0, 0)])
|
|
183
|
+
F.randomize()
|
|
184
|
+
if hasattr(F, 'with_hyperbolic_structure'):
|
|
185
|
+
F = F.with_hyperbolic_structure()
|
|
186
|
+
|
|
187
|
+
iso = hyp_utils.orientation_preserving_link_isometries(E, F, tries=1000)
|
|
188
|
+
if iso is not None:
|
|
189
|
+
L = hyp_utils.reorder_link_components(L, iso.cusp_images())
|
|
190
|
+
E = L.exterior()
|
|
191
|
+
if hyp_utils.are_orient_pres_isometric_as_ordered_links(E, F):
|
|
192
|
+
print_status(' Exterior of final link checks!\n')
|
|
193
|
+
else:
|
|
194
|
+
ExteriorToLinkError('Could not correctly order link components')
|
|
195
|
+
else:
|
|
196
|
+
raise ExteriorToLinkError('Could not confirm topology of link exterior')
|
|
197
|
+
|
|
198
|
+
return L
|