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,168 @@
|
|
|
1
|
+
from ...sage_helper import _within_sage, sage_method
|
|
2
|
+
from ...math_basics import prod
|
|
3
|
+
|
|
4
|
+
from ...geometric_structure.cusp_neighborhood.complex_cusp_cross_section import ComplexCuspCrossSection
|
|
5
|
+
from ...snap import peripheral
|
|
6
|
+
from ...snap.t3mlite import simplex
|
|
7
|
+
|
|
8
|
+
if _within_sage:
|
|
9
|
+
from sage.symbolic.constants import pi
|
|
10
|
+
from ...sage_helper import I, xgcd
|
|
11
|
+
|
|
12
|
+
from .. import hyperbolicity
|
|
13
|
+
|
|
14
|
+
from .adjust_torsion import *
|
|
15
|
+
from .compute_ptolemys import *
|
|
16
|
+
|
|
17
|
+
__all__ = ['verified_complex_volume_closed_torsion']
|
|
18
|
+
|
|
19
|
+
def _compute_holonomy(manifold, shapes):
|
|
20
|
+
"""
|
|
21
|
+
Computes the holonomy for the peripheral curves for the given 1-cusped
|
|
22
|
+
manifold and shape intervals.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Compute z', z''
|
|
26
|
+
zp = [ (1 / (1 - z)) for z in shapes ]
|
|
27
|
+
zpp = [ ((z - 1) / z) for z in shapes ]
|
|
28
|
+
|
|
29
|
+
# A list
|
|
30
|
+
# log(z_0) log(z'_0) log(z''_0) log(z_1) log(z'_1) log (z''_1) ...
|
|
31
|
+
cross_ratios = [ z for triple in zip(shapes, zp, zpp) for z in triple ]
|
|
32
|
+
|
|
33
|
+
# Unfill to get both the meridian and longitude gluing equation
|
|
34
|
+
trig = manifold.without_hyperbolic_structure()
|
|
35
|
+
trig.dehn_fill((0,0))
|
|
36
|
+
peripheral_eqns = trig.gluing_equations()[-2:]
|
|
37
|
+
|
|
38
|
+
return [ prod([l ** expo for l, expo in zip(cross_ratios, eqn)])
|
|
39
|
+
for eqn in peripheral_eqns ]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@sage_method
|
|
43
|
+
def zero_lifted_holonomy(manifold, m, l, f):
|
|
44
|
+
"""
|
|
45
|
+
Given a closed manifold and any log of the holonomy of the meridian and
|
|
46
|
+
longitude, adjust logs by multiplies of f pi i such that the peripheral
|
|
47
|
+
curves goes to 0.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
CIF = m.parent()
|
|
51
|
+
RIF = CIF.real_field()
|
|
52
|
+
multiple_of_pi = RIF(f*pi)
|
|
53
|
+
|
|
54
|
+
# (m_fill, l_fill) Dehn-filling
|
|
55
|
+
m_fill, l_fill = (int(x) for x in manifold.cusp_info()[0]['filling'])
|
|
56
|
+
|
|
57
|
+
# Compute what the peripheral curves goes to right now
|
|
58
|
+
p_interval = (m_fill * m + l_fill * l).imag() / multiple_of_pi
|
|
59
|
+
is_int, p = p_interval.is_int()
|
|
60
|
+
|
|
61
|
+
if not is_int:
|
|
62
|
+
raise Exception(
|
|
63
|
+
"Expected multiple of %d * pi * i (increase precision?)" % f)
|
|
64
|
+
|
|
65
|
+
if p == 0:
|
|
66
|
+
# Nothing to do
|
|
67
|
+
return m, l
|
|
68
|
+
|
|
69
|
+
# Compute by what multiple of 2 pi i to adjust
|
|
70
|
+
g, a, b = xgcd(m_fill, l_fill)
|
|
71
|
+
m -= p * a * multiple_of_pi * I
|
|
72
|
+
l -= p * b * multiple_of_pi * I
|
|
73
|
+
|
|
74
|
+
# For sanity, double check that we compute it right.
|
|
75
|
+
p_interval = (m_fill * m + l_fill * l).imag() / multiple_of_pi
|
|
76
|
+
is_int, p = p_interval.is_int()
|
|
77
|
+
|
|
78
|
+
if not is_int:
|
|
79
|
+
raise Exception(
|
|
80
|
+
"Expected multiple of %d * pi * i (increase precision?)" % f)
|
|
81
|
+
|
|
82
|
+
if p != 0:
|
|
83
|
+
# Nothing to do
|
|
84
|
+
raise Exception("Expected 0")
|
|
85
|
+
|
|
86
|
+
return m, l
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@sage_method
|
|
90
|
+
def verified_complex_volume_closed_torsion(manifold, bits_prec=None):
|
|
91
|
+
"""
|
|
92
|
+
Computes the verified complex volume (where the real part is the
|
|
93
|
+
volume and the imaginary part is the Chern-Simons) for a given
|
|
94
|
+
SnapPy.Manifold.
|
|
95
|
+
|
|
96
|
+
Note that the result is correct only up to two torsion, i.e.,
|
|
97
|
+
up to multiples of pi^2/2. The method expects an oriented manifold
|
|
98
|
+
with exactly one cusp which is filled, otherwise it raises an exception.
|
|
99
|
+
|
|
100
|
+
If bits_prec is unspecified, the default precision of
|
|
101
|
+
SnapPy.Manifold or SnapPy.ManifoldHP, respectively, will be used.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
if manifold.num_cusps() != 1:
|
|
105
|
+
raise ValueError(
|
|
106
|
+
"The method does not support the given manifold because "
|
|
107
|
+
"it does not have exactly one cusp.")
|
|
108
|
+
|
|
109
|
+
if manifold.cusp_info()[0]['complete?']:
|
|
110
|
+
raise ValueError(
|
|
111
|
+
"The method does not support the given manifold because "
|
|
112
|
+
"it is not a closed manifold.")
|
|
113
|
+
|
|
114
|
+
# Compute tetrahedra shapes to arbitrary precision.
|
|
115
|
+
shapes = manifold.tetrahedra_shapes(
|
|
116
|
+
'rect', bits_prec=bits_prec, intervals=True)
|
|
117
|
+
|
|
118
|
+
# Check it is a valid hyperbolic structure
|
|
119
|
+
hyperbolicity.check_logarithmic_gluing_equations_and_positively_oriented_tets(
|
|
120
|
+
manifold, shapes)
|
|
121
|
+
|
|
122
|
+
# Compute holonomy
|
|
123
|
+
m_holonomy, l_holonomy = _compute_holonomy(manifold, shapes)
|
|
124
|
+
|
|
125
|
+
# Compute 1-cocycle in H^1(boundary; Z)
|
|
126
|
+
m_star, l_star = peripheral.peripheral_cohomology_basis(manifold)
|
|
127
|
+
|
|
128
|
+
# Keys for the dual edges in cusp triangulation
|
|
129
|
+
cusp_dual_edges = [ (i, F, V)
|
|
130
|
+
for i in range(manifold.num_tetrahedra())
|
|
131
|
+
for F in simplex.TwoSubsimplices
|
|
132
|
+
for V in simplex.ZeroSubsimplices
|
|
133
|
+
if F & V ]
|
|
134
|
+
|
|
135
|
+
# Compute 1-cocycle in C^1(boundary; C^*) matching the holonomy
|
|
136
|
+
one_cocycle = {
|
|
137
|
+
k : 1 / (m_holonomy ** m_star[k] * l_holonomy ** l_star[k])
|
|
138
|
+
for k in cusp_dual_edges }
|
|
139
|
+
|
|
140
|
+
# Compute cusp cross section (for computation of complex volume,
|
|
141
|
+
# choices such as cusp size don't matter).
|
|
142
|
+
c = ComplexCuspCrossSection.fromManifoldAndShapes(
|
|
143
|
+
manifold, shapes, one_cocycle)
|
|
144
|
+
|
|
145
|
+
# Lift holonomy from C^* to C such that it is zero on the
|
|
146
|
+
# curve we fill along
|
|
147
|
+
m_lifted_holonomy, l_lifted_holonomy = zero_lifted_holonomy(
|
|
148
|
+
manifold, m_holonomy.log() / 2, l_holonomy.log() / 2, 1)
|
|
149
|
+
|
|
150
|
+
# Compute corresponding 1-cocycle in C^1(boundary; C)
|
|
151
|
+
lifted_one_cocycle = {
|
|
152
|
+
k: m_lifted_holonomy * m_star[k] + l_lifted_holonomy * l_star[k]
|
|
153
|
+
for k in cusp_dual_edges }
|
|
154
|
+
|
|
155
|
+
# Compute the lifted Ptolemy coordinates from cross section
|
|
156
|
+
lifted_ptolemys = lifted_ptolemys_from_cross_section(
|
|
157
|
+
c, lifted_one_cocycle)
|
|
158
|
+
|
|
159
|
+
# Compute the complex volume from the Ptolemy coordinates
|
|
160
|
+
complex_volume = verified_complex_volume_from_lifted_ptolemys(
|
|
161
|
+
c.mcomplex, lifted_ptolemys)
|
|
162
|
+
|
|
163
|
+
# When using the dilogarithm, the Chern-Simons is the real part.
|
|
164
|
+
# By SnapPy convention, the volume is the real part, so divide by
|
|
165
|
+
# I.
|
|
166
|
+
# Also add multiples of pi^2/2 to try to get the Chern-Simons part
|
|
167
|
+
# between -pi^2/4 and pi^2/4.
|
|
168
|
+
return normalize_by_pi_square_over_two(complex_volume) / I
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from ...snap import t3mlite as t3m
|
|
2
|
+
|
|
3
|
+
__all__ = ['lifted_ptolemys_from_cross_section']
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _ptolemy_coordinate_key(tet_index, edge):
|
|
7
|
+
return 'c_%d%d%d%d_%d' % (
|
|
8
|
+
(edge & 8) >> 3,
|
|
9
|
+
(edge & 4) >> 2,
|
|
10
|
+
(edge & 2) >> 1,
|
|
11
|
+
(edge & 1),
|
|
12
|
+
tet_index)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def lifted_ptolemys_from_cross_section(cusp_cross_section,
|
|
16
|
+
lifted_one_cocycle=None):
|
|
17
|
+
"""
|
|
18
|
+
Given a cusp cross section, compute lifted Ptolemy coordinates
|
|
19
|
+
(i.e., logarithms of the Ptolemy coordinates) returned as a dictionary
|
|
20
|
+
(e.g., the key for the Ptolemy coordinate for the edge from
|
|
21
|
+
vertex 0 to vertex 3 or simplex 4 is c_1001_4).
|
|
22
|
+
|
|
23
|
+
For complete cusp cross sections (where no lifted_one_cocycle is
|
|
24
|
+
necessary), we use Zickert's algorithm (Christian Zickert, The
|
|
25
|
+
volume and Chern-Simons invariant of a representation, Duke
|
|
26
|
+
Math. J. 150 no. 3 (2009) 489-532, math.GT/0710.2049). In this
|
|
27
|
+
case, all values for keys corresponding to the same edge in the
|
|
28
|
+
triangulation are guaranteed to be the same.
|
|
29
|
+
|
|
30
|
+
For the incomplete cusp cross sections, a lifted_one_cocycle
|
|
31
|
+
needs to be given. This cocycle is a lift of the cocycle one_cocycle
|
|
32
|
+
given to ComplexCuspCrossSection.fromManifoldAndShapes.
|
|
33
|
+
More precisely, lifted_one_cocycle is in C^1(boundary M; C) and
|
|
34
|
+
needs to map to one_cocycle in C^1(boundary M; C^*).
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
result = {}
|
|
38
|
+
|
|
39
|
+
some_tet = cusp_cross_section.mcomplex.Tetrahedra[0]
|
|
40
|
+
some_z = some_tet.ShapeParameters[t3m.E01]
|
|
41
|
+
CIF = some_z.parent()
|
|
42
|
+
|
|
43
|
+
# Compute the (lifted) Ptolemy coordinate for each edge of the
|
|
44
|
+
# triangulation only once
|
|
45
|
+
for edge in cusp_cross_section.mcomplex.Edges:
|
|
46
|
+
# Look at each way the triangulation's edge appears as edge
|
|
47
|
+
# of a tetrahedron
|
|
48
|
+
for i, (tet, perm) in enumerate(edge.embeddings()):
|
|
49
|
+
# The two vertices of the tetrahedron's edge
|
|
50
|
+
v0 = perm.image(t3m.V0)
|
|
51
|
+
v1 = perm.image(t3m.V1)
|
|
52
|
+
v2 = perm.image(t3m.V2)
|
|
53
|
+
# The edge in the tetrahedron
|
|
54
|
+
e = v0 | v1
|
|
55
|
+
# Face adjacent to the edge
|
|
56
|
+
face = e | v2
|
|
57
|
+
|
|
58
|
+
# Compute Ptolemy coordinate only once and use it
|
|
59
|
+
# for all other representatives of the triangulation's
|
|
60
|
+
# edge. Or use one_cocycle to transfer Ptolemy coordinate
|
|
61
|
+
# to other representatives.
|
|
62
|
+
if i == 0:
|
|
63
|
+
# Near one of the two ends of the edge of the tetrahedron
|
|
64
|
+
# the tetrahedron's face intersect the cusp neighborhood
|
|
65
|
+
# in an edge of the cusp cross section.
|
|
66
|
+
# Get the complex lengths of the two edges in the
|
|
67
|
+
# cusp cross section.
|
|
68
|
+
l1 = CIF(tet.horotriangles[v0].lengths[face])
|
|
69
|
+
l2 = CIF(tet.horotriangles[v1].lengths[face])
|
|
70
|
+
|
|
71
|
+
# Zickert's result: the Ptolemy coordinate is the
|
|
72
|
+
# inverse of the square root of the product of those two
|
|
73
|
+
# edge lengths.
|
|
74
|
+
#
|
|
75
|
+
# The choice of square root (and logarithm) does not
|
|
76
|
+
# matter as long as it is only done once per edge of
|
|
77
|
+
# the triangulation.
|
|
78
|
+
ptolemy = 1 / (l1 * l2).sqrt()
|
|
79
|
+
ptolemy = ptolemy.log()
|
|
80
|
+
|
|
81
|
+
elif lifted_one_cocycle:
|
|
82
|
+
# Use cocycle to compute for different representative
|
|
83
|
+
# edges
|
|
84
|
+
ptolemy -= lifted_one_cocycle[tet.Index, face, v0]
|
|
85
|
+
ptolemy -= lifted_one_cocycle[tet.Index, face, v1]
|
|
86
|
+
|
|
87
|
+
# Save Ptolemy coordinate in dictionary
|
|
88
|
+
result[_ptolemy_coordinate_key(tet.Index, e)] = ptolemy
|
|
89
|
+
|
|
90
|
+
return result
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from ...sage_helper import _within_sage, sage_method
|
|
2
|
+
|
|
3
|
+
if _within_sage:
|
|
4
|
+
from ...sage_helper import I
|
|
5
|
+
|
|
6
|
+
from .. import hyperbolicity
|
|
7
|
+
from ...geometric_structure.cusp_neighborhood.complex_cusp_cross_section import ComplexCuspCrossSection
|
|
8
|
+
|
|
9
|
+
from .adjust_torsion import *
|
|
10
|
+
from .compute_ptolemys import *
|
|
11
|
+
|
|
12
|
+
__all__ = ['verified_complex_volume_cusped_torsion']
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@sage_method
|
|
16
|
+
def verified_complex_volume_cusped_torsion(manifold, bits_prec=None):
|
|
17
|
+
"""
|
|
18
|
+
Computes the verified complex volume (where the real part is the
|
|
19
|
+
volume and the imaginary part is the Chern-Simons) for a given
|
|
20
|
+
SnapPy.Manifold.
|
|
21
|
+
|
|
22
|
+
Note that the result is correct only up to two torsion, i.e.,
|
|
23
|
+
up to multiples of pi^2/2. The method raises an exception if the
|
|
24
|
+
manifold is not oriented or has a filled cusp.
|
|
25
|
+
|
|
26
|
+
If bits_prec is unspecified, the default precision of
|
|
27
|
+
SnapPy.Manifold, respectively, SnapPy.ManifoldHP will be used.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
# Compute tetrahedra shapes to arbitrary precision.
|
|
31
|
+
shapes = manifold.tetrahedra_shapes(
|
|
32
|
+
'rect', bits_prec=bits_prec, intervals=True)
|
|
33
|
+
|
|
34
|
+
# Check it is a valid hyperbolic structure
|
|
35
|
+
hyperbolicity.check_logarithmic_gluing_equations_and_positively_oriented_tets(
|
|
36
|
+
manifold, shapes)
|
|
37
|
+
|
|
38
|
+
# Compute cusp cross section. For computation of complex volume,
|
|
39
|
+
# the size does not matter.
|
|
40
|
+
c = ComplexCuspCrossSection.fromManifoldAndShapes(manifold, shapes)
|
|
41
|
+
|
|
42
|
+
# Compute lifted Ptolemy coordinates: for each edge of the
|
|
43
|
+
# triangulation, a logarithm of the Ptolemy coordinate is computed
|
|
44
|
+
# once. Result is a dictionary.
|
|
45
|
+
lifted_ptolemys = lifted_ptolemys_from_cross_section(c)
|
|
46
|
+
|
|
47
|
+
# Compute the complex volume from the Ptolemy coordinates
|
|
48
|
+
complex_volume = verified_complex_volume_from_lifted_ptolemys(
|
|
49
|
+
c.mcomplex, lifted_ptolemys)
|
|
50
|
+
|
|
51
|
+
# When using the dilogarithm, the Chern-Simons is the real part.
|
|
52
|
+
# By SnapPy convention, the volume is the real part, so divide by
|
|
53
|
+
# I.
|
|
54
|
+
# Also add multiples of pi^2/2 to try to get the Chern-Simons part
|
|
55
|
+
# between -pi^2/4 and pi^2/4.
|
|
56
|
+
return normalize_by_pi_square_over_two(complex_volume) / I
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
from ...sage_helper import _within_sage, sage_method
|
|
2
|
+
|
|
3
|
+
if _within_sage:
|
|
4
|
+
from sage.symbolic.constants import pi
|
|
5
|
+
from ...sage_helper import I, Integer, RealField, ComplexBallField, exp
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@sage_method
|
|
9
|
+
def compute_z_and_parities_from_flattening_w0_w1(w0, w1):
|
|
10
|
+
"""
|
|
11
|
+
Given a pair (w0, w1) with +- exp(w0) +- exp(-w1) = 1, compute (z, p, q)
|
|
12
|
+
such that z = (-1)^p * exp(w0) and 1/(1-z) = (-1)^q exp(w1)
|
|
13
|
+
where p, q in {0,1}.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
e0 = exp( w0)
|
|
17
|
+
e1 = exp(-w1)
|
|
18
|
+
|
|
19
|
+
l = [ (((-1) ** p) * e0, p, q)
|
|
20
|
+
for p in [ 0, 1]
|
|
21
|
+
for q in [ 0, 1]
|
|
22
|
+
if Integer(1) in ((-1) ** p) * e0 + ((-1) ** q) * e1 ]
|
|
23
|
+
if not len(l) == 1:
|
|
24
|
+
raise Exception("Bad flattening %s %s %s" % (w0, w1, len(l)))
|
|
25
|
+
|
|
26
|
+
return l[0]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@sage_method
|
|
30
|
+
def compute_p_from_w_and_parity(w, parity):
|
|
31
|
+
"""
|
|
32
|
+
Compute p such that w - p * pi * i should have imaginary part between
|
|
33
|
+
-pi and pi and p has the same parity as the given value for parity
|
|
34
|
+
(the given value is supposed to be 0 or 1).
|
|
35
|
+
|
|
36
|
+
Note that this computation is not verified.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
RF = RealField(w.parent().precision())
|
|
40
|
+
real_part = (w.imag().center() / RF(pi) - parity) / 2
|
|
41
|
+
return 2 * Integer(real_part.round()) + parity
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@sage_method
|
|
45
|
+
def compute_z_p_q_from_flattening_w0_w1(w0, w1):
|
|
46
|
+
"""
|
|
47
|
+
Given w0 and w1 such that +- exp(w0) +- exp(-w1) = 1, compute
|
|
48
|
+
a triple [z; p, q] such that
|
|
49
|
+
w0 = log(z) + p * pi * i and w1 = -log(1-z) + q * pi * i.
|
|
50
|
+
|
|
51
|
+
While z is and the parities of p and q are verified, p and q are
|
|
52
|
+
not verified in the following sense:
|
|
53
|
+
w0 - p * pi * i and w1 + q * pi * i are likely to have imaginary
|
|
54
|
+
part between -pi and pi, but this is not verified.
|
|
55
|
+
"""
|
|
56
|
+
z, p_parity, q_parity = compute_z_and_parities_from_flattening_w0_w1(w0, w1)
|
|
57
|
+
|
|
58
|
+
return (z,
|
|
59
|
+
compute_p_from_w_and_parity(w0, p_parity),
|
|
60
|
+
compute_p_from_w_and_parity(w1, q_parity))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@sage_method
|
|
64
|
+
def my_dilog(z):
|
|
65
|
+
"""
|
|
66
|
+
Compute dilogarithm using complex ball field.
|
|
67
|
+
The dilogarithm isn't implemented for ComplexIntervalField itself, so
|
|
68
|
+
we use ComplexBallField. Note that ComplexBallField is conservative
|
|
69
|
+
about branch cuts. For Li_2(2+-i * epsilon), it returns the interval
|
|
70
|
+
containing both Li_2(2+i * epsilon) and Li_2(2-i * epsilon).
|
|
71
|
+
|
|
72
|
+
Thus, we need to avoid calling this function with a value near real numbers
|
|
73
|
+
greater 1.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
CIF = z.parent()
|
|
77
|
+
CBF = ComplexBallField(CIF.precision())
|
|
78
|
+
|
|
79
|
+
return CIF(CBF(z).polylog(2))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@sage_method
|
|
83
|
+
def is_imaginary_part_bounded(z, v):
|
|
84
|
+
"""
|
|
85
|
+
Check that the imaginary part of z is in (-v, v).
|
|
86
|
+
"""
|
|
87
|
+
imag = z.imag()
|
|
88
|
+
return -v < imag and imag < v
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@sage_method
|
|
92
|
+
def compute_Neumanns_Rogers_dilog_from_flattening_w0_w1(w0, w1):
|
|
93
|
+
"""
|
|
94
|
+
Given a flattening w0, w1 such that +- exp(w0) +- exp(-w1) = 1, compute
|
|
95
|
+
the complex volume given by R(z;p,q) (equation before Proposition 2.5 in
|
|
96
|
+
Neumann's Extended Bloch group and the Cheeger-Chern-Simons class).
|
|
97
|
+
"""
|
|
98
|
+
RIF = w0.parent().real_field()
|
|
99
|
+
my_pi = RIF(pi)
|
|
100
|
+
|
|
101
|
+
# Compute [z; p, q]
|
|
102
|
+
z, p, q = compute_z_p_q_from_flattening_w0_w1(w0, w1)
|
|
103
|
+
|
|
104
|
+
# Note that the values computed for log(z) and log(1-z)
|
|
105
|
+
# are not verified to have the imaginary part between -pi and pi.
|
|
106
|
+
logZ = w0 - my_pi * p * I
|
|
107
|
+
logOneMinusZ = - (w1 - my_pi * q * I)
|
|
108
|
+
|
|
109
|
+
# Neumann's formula for the complex volume is
|
|
110
|
+
#
|
|
111
|
+
# (1) R(z; p, q) = Li_2( z) + ( term1 + term2) / 2 - pi^2/6
|
|
112
|
+
#
|
|
113
|
+
# where
|
|
114
|
+
# term1 = log(z) * log(1-z)
|
|
115
|
+
# term2 = pi * i * (p * log(1-z) + q * log(z))
|
|
116
|
+
#
|
|
117
|
+
# Using Li_2(z) + Li_1(1-z) = pi^2/6 - log(z) * log(1-z), we also get
|
|
118
|
+
#
|
|
119
|
+
# (2) R(z; p, q) = - Li_2(1-z) + (-term1 + term2) / 2
|
|
120
|
+
#
|
|
121
|
+
# We use (1) when Re(z) < 1/2 and (2) otherwise.
|
|
122
|
+
#
|
|
123
|
+
# Note that if we use (1), we do not rely on the value computed for log(z)
|
|
124
|
+
# to have imaginary part between -pi and pi (because p was not computed
|
|
125
|
+
# such that we have this property). More precisely, if we add 2 to p, the
|
|
126
|
+
# value computed for log(z) changes by -2 * pi * i, so term1 changes by
|
|
127
|
+
# -2 * pi * i * log(1-z) but this is compensated by the change in term2.
|
|
128
|
+
# We do, however, need to check that the value of log(1-z) has imaginary
|
|
129
|
+
# part between -pi and pi. Since We have Re(z) < 1/2, we indeed expect that
|
|
130
|
+
# the imaginary part is between -pi/2 and pi/2 and can check the stronger
|
|
131
|
+
# condition that the imaginary part is between -2 and 2.
|
|
132
|
+
# We need to make sure that Li_2(z) is evaluated correctly. We always
|
|
133
|
+
# want to take the main branch. If z is close to the branch cut ([1,inf)),
|
|
134
|
+
# the choice is ambiguous but we are safe since my_dilog would
|
|
135
|
+
# conservatively return the large interval containing both branch choices.
|
|
136
|
+
# Note that we should always be able to avoid this by increasing bits_prec
|
|
137
|
+
# since we only use (1) if the interval for z is centered to the left of
|
|
138
|
+
# the line with real part 1/2.
|
|
139
|
+
#
|
|
140
|
+
# Similar considerations apply to (2) used when Re(z) > 1/2.
|
|
141
|
+
|
|
142
|
+
term1 = logZ * logOneMinusZ
|
|
143
|
+
term2 = my_pi * I * (p * logOneMinusZ + q * logZ)
|
|
144
|
+
|
|
145
|
+
if z.real().center() < 0.5:
|
|
146
|
+
# Check that we can apply equation (1)
|
|
147
|
+
if not is_imaginary_part_bounded(logOneMinusZ, 2):
|
|
148
|
+
raise Exception("Problem with computing Neumanns dilog using (1)",
|
|
149
|
+
z, logOneMinusZ)
|
|
150
|
+
|
|
151
|
+
return ( term1 + term2) / 2 + my_dilog(z) - my_pi * my_pi / 6
|
|
152
|
+
else:
|
|
153
|
+
# Check that we can apply equation (2)
|
|
154
|
+
if not is_imaginary_part_bounded(logZ, 2):
|
|
155
|
+
raise Exception("Problem with computing Neumanns dilog using (2)",
|
|
156
|
+
z, logZ)
|
|
157
|
+
|
|
158
|
+
return (-term1 + term2) / 2 - my_dilog(1 - z)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@sage_method
|
|
162
|
+
def compute_complex_volume_of_simplex_from_lifted_ptolemys(index, ptolemys):
|
|
163
|
+
"""
|
|
164
|
+
Given lifted Ptolemy coordinates for a triangulation (as dictionary),
|
|
165
|
+
compute the complex volume contribution by the simplex with given index.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
# The six Ptolemy coordinates for the given simplex
|
|
169
|
+
c_1100 = ptolemys['c_1100_%d' % index]
|
|
170
|
+
c_1010 = ptolemys['c_1010_%d' % index]
|
|
171
|
+
c_1001 = ptolemys['c_1001_%d' % index]
|
|
172
|
+
c_0110 = ptolemys['c_0110_%d' % index]
|
|
173
|
+
c_0101 = ptolemys['c_0101_%d' % index]
|
|
174
|
+
c_0011 = ptolemys['c_0011_%d' % index]
|
|
175
|
+
|
|
176
|
+
# Compute Neumann's flattening (w0, w1) from Ptolemy coordinates
|
|
177
|
+
w0 = c_1010 + c_0101 - c_1001 - c_0110
|
|
178
|
+
w1 = c_1001 + c_0110 - c_1100 - c_0011
|
|
179
|
+
|
|
180
|
+
# Compute Neumann's version of Roger's dilogarithm from flattening.
|
|
181
|
+
return compute_Neumanns_Rogers_dilog_from_flattening_w0_w1(w0, w1)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@sage_method
|
|
185
|
+
def compute_complex_volume_from_lifted_ptolemys_no_torsion_adjustment(
|
|
186
|
+
num_tetrahedra, ptolemys):
|
|
187
|
+
"""
|
|
188
|
+
Given lifted Ptolemy coordinates for a triangulation (as dictionary)
|
|
189
|
+
and the number of tetrahedra, compute the complex volume (where
|
|
190
|
+
the real part is the Chern-Simons and the imaginary part is the
|
|
191
|
+
volume).
|
|
192
|
+
|
|
193
|
+
This sums of the dilogs across tetrahedra without adjusting for the
|
|
194
|
+
fact that the triangulation might not be ordered.
|
|
195
|
+
Thus, the Chern-Simons is correct only up to multiples of pi^2/6.
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
return sum(
|
|
199
|
+
[ compute_complex_volume_of_simplex_from_lifted_ptolemys(
|
|
200
|
+
index, ptolemys)
|
|
201
|
+
for index in range(num_tetrahedra) ])
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from ..geometric_structure.cusp_neighborhood.complex_cusp_cross_section import ComplexCuspCrossSection
|
|
2
|
+
from .shapes import compute_hyperbolic_shapes
|
|
3
|
+
|
|
4
|
+
__all__ = ['cusp_translations_for_manifold',
|
|
5
|
+
'cusp_translations_for_neighborhood']
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def cusp_translations_for_manifold(manifold, verified, areas=None,
|
|
9
|
+
check_std_form=True,
|
|
10
|
+
bits_prec=None):
|
|
11
|
+
|
|
12
|
+
shapes = compute_hyperbolic_shapes(
|
|
13
|
+
manifold, verified=verified, bits_prec=bits_prec)
|
|
14
|
+
|
|
15
|
+
# Compute cusp cross section, the code is agnostic about whether
|
|
16
|
+
# the numbers are floating-point or intervals.
|
|
17
|
+
# Note that the constructed cusp cross section will always be too "large"
|
|
18
|
+
# and we need to scale them down (since during construction the
|
|
19
|
+
# cross-section of each cusp will have one edge of length 1, the
|
|
20
|
+
# corresponding tetrahedron does not intersect in "standard" form.)
|
|
21
|
+
c = ComplexCuspCrossSection.fromManifoldAndShapes(manifold, shapes)
|
|
22
|
+
|
|
23
|
+
if areas:
|
|
24
|
+
RF = shapes[0].real().parent()
|
|
25
|
+
# Convert given areas to elements in real (interval) field and then
|
|
26
|
+
# scale cusps to have that given area.
|
|
27
|
+
#
|
|
28
|
+
# These areas are just used as a hint to initialize the computation
|
|
29
|
+
# of cusp neighborhoods that are disjoint. ensure_disjoint will
|
|
30
|
+
# scale the cusps further down so that it is verified they are
|
|
31
|
+
# disjoint. In particular, it is ok that the given areas might be
|
|
32
|
+
# of a lower precision type or two use the number and turn it
|
|
33
|
+
# into an interval of length 0.
|
|
34
|
+
#
|
|
35
|
+
# Remark: If verified, RF(area) will result in intervals of
|
|
36
|
+
# length 0.
|
|
37
|
+
c.normalize_cusps([RF(area) for area in areas])
|
|
38
|
+
|
|
39
|
+
if check_std_form:
|
|
40
|
+
# If so desired, make neighborhoods a bit smaller if necessary
|
|
41
|
+
# so that they are "proven" to be in standard form.
|
|
42
|
+
c.ensure_std_form()
|
|
43
|
+
else:
|
|
44
|
+
# If no areas are given, scale (up or down) all the cusps so that
|
|
45
|
+
# they are in standard form.
|
|
46
|
+
c.ensure_std_form(allow_scaling_up=True)
|
|
47
|
+
|
|
48
|
+
# Note: the only code path avoiding ensure_std_form is through calling
|
|
49
|
+
# all_translations on a CuspNeighborhood with verified = False,
|
|
50
|
+
# see comment in cusp_translations_for_neighborhood
|
|
51
|
+
|
|
52
|
+
# Scale down cusps neighborhoods further to make sure that they are
|
|
53
|
+
# disjoint.
|
|
54
|
+
c.ensure_disjoint_on_edges()
|
|
55
|
+
|
|
56
|
+
# The result
|
|
57
|
+
return c.all_normalized_translations()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def cusp_translations_for_neighborhood(neighborhood,
|
|
61
|
+
verified=False, bits_prec=None):
|
|
62
|
+
|
|
63
|
+
# Use the proto-canonical triangulation corresponding to the given
|
|
64
|
+
# neighborhood and use Proposition 1 from cusp_neighborhoods.c to compute
|
|
65
|
+
# the cusp areas
|
|
66
|
+
|
|
67
|
+
manifold = neighborhood.manifold()
|
|
68
|
+
areas = [ neighborhood.volume(i) * 2 for i in range(manifold.num_cusps()) ]
|
|
69
|
+
|
|
70
|
+
# If we want verified results, do not rely on anything reported from
|
|
71
|
+
# the kernel, the areas are only used as hint. The cusps could be scaled
|
|
72
|
+
# down further to ensure the cusps neighborhoods are in standard form.
|
|
73
|
+
|
|
74
|
+
# If we don't want verified results, we set check_std_form to False to
|
|
75
|
+
# get high-precision results consistent with the translations reported
|
|
76
|
+
# by the kernel.
|
|
77
|
+
# This is safe under the assumption that the kernel has found a correct
|
|
78
|
+
# proto-canonical triangulation for the CuspNeighborhood. The kernel
|
|
79
|
+
# also should have given us areas corresponding to disjoint cusps to
|
|
80
|
+
# begin with.
|
|
81
|
+
|
|
82
|
+
return cusp_translations_for_manifold(manifold, areas=areas,
|
|
83
|
+
check_std_form=verified,
|
|
84
|
+
verified=verified,
|
|
85
|
+
bits_prec=bits_prec)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from .exceptions import *
|
|
2
|
+
|
|
3
|
+
from ..snap.t3mlite import simplex
|
|
4
|
+
|
|
5
|
+
def check_polynomial_edge_equations_exactly(mcomplex):
|
|
6
|
+
"""
|
|
7
|
+
Check that the polynomial edge equations are fulfilled exactly.
|
|
8
|
+
|
|
9
|
+
We use the conjugate inverse to support non-orientable manifolds.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# For each edge
|
|
13
|
+
for edge in mcomplex.Edges:
|
|
14
|
+
# The exact value when evaluating the edge equation
|
|
15
|
+
val = 1
|
|
16
|
+
|
|
17
|
+
# Iterate through edge embeddings
|
|
18
|
+
for tet, perm in edge.embeddings():
|
|
19
|
+
# Accumulate shapes of the edge exactly
|
|
20
|
+
val *= _shape_for_edge_embedding(tet, perm)
|
|
21
|
+
|
|
22
|
+
if not val == 1:
|
|
23
|
+
raise EdgeEquationExactVerifyError(val)
|
|
24
|
+
|
|
25
|
+
def check_logarithmic_edge_equations_and_positivity(mcomplex, NumericalField):
|
|
26
|
+
"""
|
|
27
|
+
Check that the shapes have positive imaginary part and that the
|
|
28
|
+
logarithmic gluing equations have small error.
|
|
29
|
+
|
|
30
|
+
The shapes are coerced into the field given as argument before the
|
|
31
|
+
logarithm is computed. It can be, e.g., a ComplexIntervalField.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
# For each edge
|
|
35
|
+
for edge in mcomplex.Edges:
|
|
36
|
+
|
|
37
|
+
# The complex interval arithmetic value of the logarithmic
|
|
38
|
+
# version of the edge equation.
|
|
39
|
+
log_sum = 0
|
|
40
|
+
|
|
41
|
+
# Iterate through edge embeddings
|
|
42
|
+
for tet, perm in edge.embeddings():
|
|
43
|
+
|
|
44
|
+
shape = _shape_for_edge_embedding(tet, perm)
|
|
45
|
+
|
|
46
|
+
numerical_shape = NumericalField(shape)
|
|
47
|
+
|
|
48
|
+
log_shape = numerical_shape.log()
|
|
49
|
+
|
|
50
|
+
# Note that this is true for z in R, R < 0 as well,
|
|
51
|
+
# but then it would fail for 1 - 1/z or 1 / (1-z)
|
|
52
|
+
|
|
53
|
+
if not (log_shape.imag() > 0):
|
|
54
|
+
raise ShapePositiveImaginaryPartNumericalVerifyError(
|
|
55
|
+
numerical_shape)
|
|
56
|
+
|
|
57
|
+
# Take logarithm and accumulate
|
|
58
|
+
log_sum += log_shape
|
|
59
|
+
|
|
60
|
+
twoPiI = NumericalField.pi() * NumericalField(2j)
|
|
61
|
+
|
|
62
|
+
if not abs(log_sum - twoPiI) < NumericalField(1e-7):
|
|
63
|
+
raise EdgeEquationLogLiftNumericalVerifyError(log_sum)
|
|
64
|
+
|
|
65
|
+
def _shape_for_edge_embedding(tet, perm):
|
|
66
|
+
"""
|
|
67
|
+
Given an edge embedding, find the shape assignment for it.
|
|
68
|
+
If the edge embedding flips orientation, apply conjugate inverse.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
# Get the shape for this edge embedding
|
|
72
|
+
subsimplex = perm.image(simplex.E01)
|
|
73
|
+
|
|
74
|
+
# Figure out the orientation of this tetrahedron
|
|
75
|
+
# with respect to the edge, apply conjugate inverse
|
|
76
|
+
# if differ
|
|
77
|
+
if perm.sign():
|
|
78
|
+
return 1 / tet.ShapeParameters[subsimplex].conjugate()
|
|
79
|
+
else:
|
|
80
|
+
return tet.ShapeParameters[subsimplex]
|