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,400 @@
|
|
|
1
|
+
__all__ = ['IntervalTree']
|
|
2
|
+
|
|
3
|
+
LEFT = 0
|
|
4
|
+
RIGHT = 1
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class IntervalTree():
|
|
8
|
+
"""
|
|
9
|
+
A data structure that can store (interval, value) pairs and quickly
|
|
10
|
+
retrieve all values for which the interval overlaps with a given
|
|
11
|
+
interval.
|
|
12
|
+
|
|
13
|
+
Create an interval tree and add pairs to it::
|
|
14
|
+
|
|
15
|
+
sage: from sage.all import RIF
|
|
16
|
+
sage: t = IntervalTree()
|
|
17
|
+
sage: t.insert(RIF(1.01,1.02),'1')
|
|
18
|
+
sage: t.insert(RIF(3.01,3.02),'3')
|
|
19
|
+
sage: t.insert(RIF(2.01,2.02),'2')
|
|
20
|
+
sage: t.insert(RIF(0.99, 3.0),'big')
|
|
21
|
+
|
|
22
|
+
Retrieve all values for intervals overlapping [1.5, 2.5]::
|
|
23
|
+
|
|
24
|
+
sage: t.find(RIF(1.5, 2.5))
|
|
25
|
+
['big', '2']
|
|
26
|
+
|
|
27
|
+
Calls to insert :py:meth:`insert` and :py:meth:`find` can be mixed::
|
|
28
|
+
|
|
29
|
+
sage: t.insert(RIF(4.01,4.02),'4')
|
|
30
|
+
sage: t.find(RIF(1,10))
|
|
31
|
+
['big', '1', '2', '3', '4']
|
|
32
|
+
sage: t.find(RIF(16, 17))
|
|
33
|
+
[]
|
|
34
|
+
|
|
35
|
+
This is implemented as interval tree, i.e., as a red-black tree keyed by
|
|
36
|
+
the left endpoint of an interval with each node *N* storing the max of all
|
|
37
|
+
right endpoints of all intervals of the subtree under *N*.
|
|
38
|
+
|
|
39
|
+
A demo of red-black trees is at https://www.youtube.com/watch?v=gme8e_6Fnug
|
|
40
|
+
and explanation at http://unhyperbolic.org/rbtree.pdf .
|
|
41
|
+
Also see wikipedia or Cormen et al, *Introduction to Algorithms*.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
class _Node():
|
|
45
|
+
def __init__(self, interval, value):
|
|
46
|
+
# The interval and value of the inserted pair this node corresponds
|
|
47
|
+
# to. The left endpoint of the interval is used as key for the
|
|
48
|
+
# binary search tree.
|
|
49
|
+
self.interval = interval
|
|
50
|
+
self.value = value
|
|
51
|
+
# The maximum of all right endpoints of all intervals of the
|
|
52
|
+
# subtree under this node, including the node itself.
|
|
53
|
+
self.max_value = interval.upper()
|
|
54
|
+
# Left and right child
|
|
55
|
+
self.children = [None, None]
|
|
56
|
+
# Is this node red or black?
|
|
57
|
+
self.isRed = True
|
|
58
|
+
|
|
59
|
+
def update_max_value(self):
|
|
60
|
+
# Assuming that the children store the correct max_value, update
|
|
61
|
+
# this node's max_value
|
|
62
|
+
self.max_value = self.interval.upper()
|
|
63
|
+
for child in self.children:
|
|
64
|
+
if child:
|
|
65
|
+
self.max_value = max(self.max_value, child.max_value)
|
|
66
|
+
|
|
67
|
+
def __init__(self):
|
|
68
|
+
self._root = None
|
|
69
|
+
|
|
70
|
+
def find(self, interval):
|
|
71
|
+
"""
|
|
72
|
+
Finds all values that have been inserted with intervals overlapping the
|
|
73
|
+
given interval which is an element in SageMath's ``RealIntervalField``.
|
|
74
|
+
|
|
75
|
+
The runtime of this call is O(log (n) + m) where n is the number of
|
|
76
|
+
intervals in the tree and m the number of the returned intervals.
|
|
77
|
+
|
|
78
|
+
The order of the returned values is ascending in the left endpoint of
|
|
79
|
+
the associated intervals. If several intervals have the same left
|
|
80
|
+
endpoint, the order of the returned values depends on the insertion
|
|
81
|
+
order but is still deterministic.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
result = []
|
|
85
|
+
# Recurse the tree
|
|
86
|
+
IntervalTree._fill_recursive(self._root, interval, result)
|
|
87
|
+
return result
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def _fill_recursive(node, interval, result):
|
|
91
|
+
if not node:
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
# The max_value is the maximum over the entire subtree. If it is
|
|
95
|
+
# strictly lower than the queried interval, we can stop recursing.
|
|
96
|
+
if node.max_value < interval.lower():
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
# Recurse down to the left
|
|
100
|
+
IntervalTree._fill_recursive(node.children[LEFT], interval, result)
|
|
101
|
+
|
|
102
|
+
# The left endpoint of the interval is used as key. If it is strictly
|
|
103
|
+
# greater than the queried interval, we do not need to consider this
|
|
104
|
+
# node or the subtree to the right.
|
|
105
|
+
if node.interval.lower() > interval.upper():
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
# Add to result if overlapping
|
|
109
|
+
if node.interval.overlaps(interval):
|
|
110
|
+
result.append(node.value)
|
|
111
|
+
|
|
112
|
+
# Recurse down to the right
|
|
113
|
+
IntervalTree._fill_recursive(node.children[RIGHT], interval, result)
|
|
114
|
+
|
|
115
|
+
def insert(self, interval, value):
|
|
116
|
+
"""
|
|
117
|
+
Inserts (interval, value) where interval is an element in
|
|
118
|
+
SageMath's ``RealIntervalField`` and value can be anything.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
# Create node
|
|
122
|
+
node = IntervalTree._Node(interval, value)
|
|
123
|
+
|
|
124
|
+
if self._root:
|
|
125
|
+
# Recurse down the tree to insert node, fix the red-black
|
|
126
|
+
# property and update max field when unwinding the stack.
|
|
127
|
+
#
|
|
128
|
+
# The root of the tree might change, so update self._root.
|
|
129
|
+
violation, self._root = IntervalTree._insert_fix_and_update_max(
|
|
130
|
+
self._root, node)
|
|
131
|
+
else:
|
|
132
|
+
# If empty tree, node becomes root
|
|
133
|
+
self._root = node
|
|
134
|
+
|
|
135
|
+
# Root is always black
|
|
136
|
+
self._root.isRed = False
|
|
137
|
+
|
|
138
|
+
@staticmethod
|
|
139
|
+
def _if_red(node):
|
|
140
|
+
# Does node exist and is red
|
|
141
|
+
if node and node.isRed:
|
|
142
|
+
return node
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
@staticmethod
|
|
146
|
+
def _insert_fix_and_update_max(node, leaf):
|
|
147
|
+
# We actually recurse down the tree to figure out where to insert a
|
|
148
|
+
# node and then use the unwinding of the stack to fix the red-black
|
|
149
|
+
# tree and update the max_value field.
|
|
150
|
+
#
|
|
151
|
+
# This functions does this in three steps:
|
|
152
|
+
# Step 1: figure out whether to follow the left or right child and
|
|
153
|
+
# call yourself to recurse down the tree to insert the new
|
|
154
|
+
# node.
|
|
155
|
+
# Step 2: fix any potential violation where a black node has a red
|
|
156
|
+
# child and a red grand child.
|
|
157
|
+
# Step 3: update the max_value field of the node.
|
|
158
|
+
#
|
|
159
|
+
# The result of this function is a pair (violation, node) used by step
|
|
160
|
+
# 2 of the calling function is:
|
|
161
|
+
# * violation is
|
|
162
|
+
# - 'VIOLATION' if there is definitively a violation where a red
|
|
163
|
+
# node has a red child
|
|
164
|
+
# - 'POTENTIAL' indicating that the node has became red and there
|
|
165
|
+
# is a violation if and only if the parent is red
|
|
166
|
+
# - 'OK' meaning there is no violation
|
|
167
|
+
# * node is the new root of the subtree - the root of the subtree might
|
|
168
|
+
# have changed due to rotations so we need to update the respective
|
|
169
|
+
# child field of the parent to point to the new root.
|
|
170
|
+
|
|
171
|
+
# Step 1 and 2
|
|
172
|
+
violation, node = IntervalTree._insert_and_fix(node, leaf)
|
|
173
|
+
|
|
174
|
+
# Step 3
|
|
175
|
+
node.update_max_value()
|
|
176
|
+
|
|
177
|
+
return violation, node
|
|
178
|
+
|
|
179
|
+
@staticmethod
|
|
180
|
+
def _insert_and_fix(node, leaf):
|
|
181
|
+
# Step 1: find whether to follow left or right child
|
|
182
|
+
|
|
183
|
+
branch = LEFT if leaf.interval.lower() <= node.interval.lower() else RIGHT
|
|
184
|
+
|
|
185
|
+
# If we recursed down and have no more child, ...
|
|
186
|
+
if not node.children[branch]:
|
|
187
|
+
# ... add this as leaf node. The new leaf node is always red, ...
|
|
188
|
+
node.children[branch] = leaf
|
|
189
|
+
# ... so there is something to fix if and only if this node is also
|
|
190
|
+
# red.
|
|
191
|
+
return ('VIOLATION' if node.isRed else 'OK', node)
|
|
192
|
+
|
|
193
|
+
# Otherwise, recurse further down the tree
|
|
194
|
+
violation, node.children[branch] = IntervalTree._insert_fix_and_update_max(
|
|
195
|
+
node.children[branch], leaf)
|
|
196
|
+
|
|
197
|
+
# We are unwinding the stack:
|
|
198
|
+
|
|
199
|
+
# Check whether we have a violation. Skip step 2 if not.
|
|
200
|
+
if violation == 'OK' or (violation == 'POTENTIAL' and not node.isRed):
|
|
201
|
+
return ('OK', node)
|
|
202
|
+
|
|
203
|
+
# Step 2: fix the violation where a red node has a red child.
|
|
204
|
+
return IntervalTree._fix(node)
|
|
205
|
+
|
|
206
|
+
@staticmethod
|
|
207
|
+
def _fix(node):
|
|
208
|
+
# Step 2: fix the violation where a red node has a red child.
|
|
209
|
+
|
|
210
|
+
# If this node is red, we leave it to our parent to fix the violation.
|
|
211
|
+
if node.isRed:
|
|
212
|
+
return ('VIOLATION', node)
|
|
213
|
+
|
|
214
|
+
# This node is black. Get all our red children to analyze the different
|
|
215
|
+
# cases.
|
|
216
|
+
redChildren = [
|
|
217
|
+
(branch, child) for branch, child in enumerate(node.children)
|
|
218
|
+
if IntervalTree._if_red(child) ]
|
|
219
|
+
|
|
220
|
+
# We have to distinguish three cases:
|
|
221
|
+
# Case 1 and 2: this node has one red child which has one red child.
|
|
222
|
+
# Caes 3: this node has two red children (and one red grandchild).
|
|
223
|
+
|
|
224
|
+
if len(redChildren) == 2:
|
|
225
|
+
# We are in case 3. We change the color of this node and its two
|
|
226
|
+
# children.
|
|
227
|
+
for child in node.children:
|
|
228
|
+
child.isRed = False
|
|
229
|
+
node.isRed = True
|
|
230
|
+
# This will fix the violation for the children, but might introduce
|
|
231
|
+
# a violation where this node and its parent are both red.
|
|
232
|
+
return ('POTENTIAL', node)
|
|
233
|
+
|
|
234
|
+
# We are left with case 1 or 2. Get the one red child.
|
|
235
|
+
branch, child = redChildren[0]
|
|
236
|
+
|
|
237
|
+
# And look at one if its children to distinguish between case 1 and 2.
|
|
238
|
+
# If our left child is red, get its right child.
|
|
239
|
+
# If our right child is red, get its left child.
|
|
240
|
+
grandChild = IntervalTree._if_red(child.children[1 - branch])
|
|
241
|
+
if grandChild:
|
|
242
|
+
# If that grand child is red, we are in case 2 which
|
|
243
|
+
# requires an extra rotation to reduce to case 1.
|
|
244
|
+
child.children[1 - branch] = grandChild.children[branch]
|
|
245
|
+
child.update_max_value()
|
|
246
|
+
grandChild.children[branch] = child
|
|
247
|
+
node.children[branch] = grandChild
|
|
248
|
+
child = grandChild
|
|
249
|
+
# Case 1: perform rotation.
|
|
250
|
+
node.children[branch] = child.children[1 - branch]
|
|
251
|
+
node.update_max_value()
|
|
252
|
+
node.isRed = True
|
|
253
|
+
child.children[1 - branch] = node
|
|
254
|
+
child.isRed = False
|
|
255
|
+
|
|
256
|
+
# Case 1 and 2 have the violation resolved, no more fixing
|
|
257
|
+
# required.
|
|
258
|
+
return ('OK', child)
|
|
259
|
+
|
|
260
|
+
################################################################################
|
|
261
|
+
#
|
|
262
|
+
# TESTING
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class _IntervalTreeTester(IntervalTree):
|
|
266
|
+
"""
|
|
267
|
+
A test rig for IntervalTree. It will keep a separate plain list of all
|
|
268
|
+
entries added by :py:meth:`insert`. It offers methods to compare the result
|
|
269
|
+
of a brute force search in the plain list against an interval tree search.
|
|
270
|
+
It also offers methods to do many consistency checks on the red black tree.
|
|
271
|
+
|
|
272
|
+
Run the test rig::
|
|
273
|
+
|
|
274
|
+
sage: _IntervalTreeTester.run_test()
|
|
275
|
+
|
|
276
|
+
"""
|
|
277
|
+
|
|
278
|
+
def __init__(self):
|
|
279
|
+
self._entries = []
|
|
280
|
+
super().__init__()
|
|
281
|
+
|
|
282
|
+
def insert(self, interval, value):
|
|
283
|
+
# Insert in plain list for reference
|
|
284
|
+
self._entries.append((interval, value))
|
|
285
|
+
# Insert into red black tree
|
|
286
|
+
super().insert(interval, value)
|
|
287
|
+
|
|
288
|
+
def brute_force_find(self, interval):
|
|
289
|
+
"""
|
|
290
|
+
Search plain list as ground truth to compare against.
|
|
291
|
+
"""
|
|
292
|
+
return [ entry[1]
|
|
293
|
+
for entry in self._entries
|
|
294
|
+
if entry[0].overlaps(interval) ]
|
|
295
|
+
|
|
296
|
+
def check_find_result(self, interval):
|
|
297
|
+
if set(self.find(interval)) != set(self.brute_force_find(interval)):
|
|
298
|
+
raise Exception("Different results: %r %r" % (
|
|
299
|
+
self.find(interval),
|
|
300
|
+
self.brute_force_find(interval)))
|
|
301
|
+
|
|
302
|
+
def check_consistency(self):
|
|
303
|
+
from ..sage_helper import Infinity
|
|
304
|
+
if self._root.isRed:
|
|
305
|
+
raise Exception("Red root")
|
|
306
|
+
_IntervalTreeTester._recursively_check_consistency(
|
|
307
|
+
self._root, -Infinity, +Infinity)
|
|
308
|
+
|
|
309
|
+
@staticmethod
|
|
310
|
+
def _recursively_check_consistency(node, l, r):
|
|
311
|
+
from ..sage_helper import Infinity
|
|
312
|
+
|
|
313
|
+
if not node:
|
|
314
|
+
return -Infinity, 0
|
|
315
|
+
|
|
316
|
+
if not (node.interval.lower() >= l):
|
|
317
|
+
raise Exception("Node left lower %r %r", node.interval.lower(), l)
|
|
318
|
+
if not (node.interval.lower() <= r):
|
|
319
|
+
raise Exception("Node right lower %r %r", node.interval.lower(), r)
|
|
320
|
+
|
|
321
|
+
left_max, left_depth = (
|
|
322
|
+
_IntervalTreeTester._recursively_check_consistency(
|
|
323
|
+
node.children[LEFT], l, node.interval.lower()))
|
|
324
|
+
|
|
325
|
+
right_max, right_depth = (
|
|
326
|
+
_IntervalTreeTester._recursively_check_consistency(
|
|
327
|
+
node.children[RIGHT], node.interval.lower(), r))
|
|
328
|
+
|
|
329
|
+
if not max(left_max, right_max, node.interval.upper()) == node.max_value:
|
|
330
|
+
raise Exception("Maximum incorrect")
|
|
331
|
+
|
|
332
|
+
if left_depth != right_depth:
|
|
333
|
+
raise Exception("Inconsistent black depths")
|
|
334
|
+
|
|
335
|
+
if node.isRed:
|
|
336
|
+
for child in node.children:
|
|
337
|
+
if child and child.isRed:
|
|
338
|
+
raise Exception("Red node has red child")
|
|
339
|
+
else:
|
|
340
|
+
left_depth += 1
|
|
341
|
+
|
|
342
|
+
return node.max_value, left_depth
|
|
343
|
+
|
|
344
|
+
def print_tree(self):
|
|
345
|
+
self.print_tree_recursively(self._root, 0)
|
|
346
|
+
|
|
347
|
+
@staticmethod
|
|
348
|
+
def print_tree_recursively(node, depth):
|
|
349
|
+
if not node:
|
|
350
|
+
return
|
|
351
|
+
|
|
352
|
+
if not node.isRed:
|
|
353
|
+
depth += 1
|
|
354
|
+
|
|
355
|
+
_IntervalTreeTester.print_tree_recursively(node.children[0], depth)
|
|
356
|
+
|
|
357
|
+
align = 6 * depth
|
|
358
|
+
if node.isRed:
|
|
359
|
+
align += 3
|
|
360
|
+
|
|
361
|
+
print(align * " ", end=" ")
|
|
362
|
+
if node.isRed:
|
|
363
|
+
print("R", end=" ")
|
|
364
|
+
else:
|
|
365
|
+
print("B", end=" ")
|
|
366
|
+
|
|
367
|
+
print(node.interval.lower())
|
|
368
|
+
|
|
369
|
+
_IntervalTreeTester.print_tree_recursively(node.children[1], depth)
|
|
370
|
+
|
|
371
|
+
@staticmethod
|
|
372
|
+
def run_test():
|
|
373
|
+
from ..sage_helper import RIF, Infinity, sin
|
|
374
|
+
|
|
375
|
+
intervals = [
|
|
376
|
+
RIF(sin(1.2 * i), sin(1.2 * i) + sin(1.43 * i) ** 2)
|
|
377
|
+
for i in range(200) ]
|
|
378
|
+
|
|
379
|
+
t = _IntervalTreeTester()
|
|
380
|
+
for i, interval in enumerate(intervals):
|
|
381
|
+
t.insert(interval, i)
|
|
382
|
+
if i % 50 == 0:
|
|
383
|
+
for j in intervals:
|
|
384
|
+
t.check_find_result(j)
|
|
385
|
+
t.check_consistency()
|
|
386
|
+
|
|
387
|
+
num_true = len(intervals)
|
|
388
|
+
num_have = len(t.find(RIF(-Infinity, Infinity)))
|
|
389
|
+
if num_true != num_have:
|
|
390
|
+
raise Exception("Inconsistent number of intervals: %d %d" % (
|
|
391
|
+
num_true, num_have))
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def _doctest():
|
|
395
|
+
import doctest
|
|
396
|
+
doctest.testmod()
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
if __name__ == '__main__':
|
|
400
|
+
_doctest()
|