diff --git a/CITATION.cff b/CITATION.cff index 8e536719607..effa2901c0c 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ title: SageMath abstract: SageMath is a free open-source mathematics software system. authors: - name: "The SageMath Developers" -version: 10.1.beta9 +version: 10.1.rc0 doi: 10.5281/zenodo.593563 -date-released: 2023-08-05 +date-released: 2023-08-13 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/VERSION.txt b/VERSION.txt index 3a158e5f21f..a62521f032f 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.1.beta9, Release Date: 2023-08-05 +SageMath version 10.1.rc0, Release Date: 2023-08-13 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index ba8597088cd..ba26592020a 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=0c03cb79520ba7f484e811aeb10ce528b3ea97d5 -md5=499635417f054c55dc90c9aca9494d61 -cksum=3916950255 +sha1=139bcabc03fbf74d05379ff27713c7e3496fc362 +md5=2631cd73e85221b77dea105e30f6165d +cksum=2003135383 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 1d722817b70..b18e430562c 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -ffdd9f8e55c138555338187b059d80ceecc2abaf +50208b761995b49bf6f0702f4b9d36da24fae1a0 diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index 76fd774f5f4..69a6f60f50b 100644 --- a/build/pkgs/sage_conf/install-requires.txt +++ b/build/pkgs/sage_conf/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.1b9 +sage-conf ~= 10.1rc0 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index 49a89420880..76cee94895b 100644 --- a/build/pkgs/sage_docbuild/install-requires.txt +++ b/build/pkgs/sage_docbuild/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.1b9 +sage-docbuild ~= 10.1rc0 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index c222b9cdd2f..ec6e85e090c 100644 --- a/build/pkgs/sage_setup/install-requires.txt +++ b/build/pkgs/sage_setup/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.1b9 +sage-setup ~= 10.1rc0 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index 4486a67ed75..440d25adb32 100644 --- a/build/pkgs/sage_sws2rst/install-requires.txt +++ b/build/pkgs/sage_sws2rst/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.1b9 +sage-sws2rst ~= 10.1rc0 diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index 74089ecdd65..cb3d1c3382f 100644 --- a/build/pkgs/sagelib/install-requires.txt +++ b/build/pkgs/sagelib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.1b9 +sagemath-standard ~= 10.1rc0 diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt index 7e7c708066a..8a64ef0c0b1 100644 --- a/build/pkgs/sagemath_bliss/install-requires.txt +++ b/build/pkgs/sagemath_bliss/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.1b9 +sagemath-bliss ~= 10.1rc0 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index 21f5efa6dd8..c9666be341e 100644 --- a/build/pkgs/sagemath_categories/install-requires.txt +++ b/build/pkgs/sagemath_categories/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.1b9 +sagemath-categories ~= 10.1rc0 diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt index 174264f9c2d..8db0a45278c 100644 --- a/build/pkgs/sagemath_coxeter3/install-requires.txt +++ b/build/pkgs/sagemath_coxeter3/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.1b9 +sagemath-coxeter3 ~= 10.1rc0 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index 3a2a2e06ca5..1bf65f70706 100644 --- a/build/pkgs/sagemath_environment/install-requires.txt +++ b/build/pkgs/sagemath_environment/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.1b9 +sagemath-environment ~= 10.1rc0 diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt index 5012bc30606..ad1d463c994 100644 --- a/build/pkgs/sagemath_mcqd/install-requires.txt +++ b/build/pkgs/sagemath_mcqd/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.1b9 +sagemath-mcqd ~= 10.1rc0 diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt index d9c67ecdcb4..0fbda8ca0a9 100644 --- a/build/pkgs/sagemath_meataxe/install-requires.txt +++ b/build/pkgs/sagemath_meataxe/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.1b9 +sagemath-meataxe ~= 10.1rc0 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index cdaa97d1f23..47b1fbbe689 100644 --- a/build/pkgs/sagemath_objects/install-requires.txt +++ b/build/pkgs/sagemath_objects/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.1b9 +sagemath-objects ~= 10.1rc0 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index d8fa592fcc2..dc870d02cfd 100644 --- a/build/pkgs/sagemath_repl/install-requires.txt +++ b/build/pkgs/sagemath_repl/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.1b9 +sagemath-repl ~= 10.1rc0 diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt index 743cd19995b..03021ff49a6 100644 --- a/build/pkgs/sagemath_sirocco/install-requires.txt +++ b/build/pkgs/sagemath_sirocco/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.1b9 +sagemath-sirocco ~= 10.1rc0 diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt index 40c4589d4b3..57437e13652 100644 --- a/build/pkgs/sagemath_tdlib/install-requires.txt +++ b/build/pkgs/sagemath_tdlib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.1b9 +sagemath-tdlib ~= 10.1rc0 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/src/.relint.yml b/src/.relint.yml index d0eafb0d8fc..97bf2ac1dbc 100644 --- a/src/.relint.yml +++ b/src/.relint.yml @@ -51,7 +51,18 @@ # Keep in sync with SAGE_ROOT/src/sage/misc/replace_dot_all.py pattern: 'from\s+sage(|[.](arith|categories|combinat|crypto|databases|data_structures|dynamics|ext|game_theory|games|geometry|graphs|groups|interfaces|manifolds|matrix|matroids|misc|modules|monoids|numerical|probability|quadratic_forms|quivers|rings|sat|schemes|sets|stats|symbolic|tensor)[a-z0-9_.]*|[.]libs)[.]all\s+import' # imports from .all are allowed in all.py; also allow in some modules that need sage.all - filePattern: '(.*/|)(?!(all|benchmark|dev_tools|parsing|sage_eval))[^/.]*[.](py|pyx|pxi)$' + filePattern: '(.*/|)(?!(all|benchmark|dev_tools|parsing|sage_eval|explain_pickle|.*_test))[^/.]*[.](py|pyx|pxi)$' + +- name: 'namespace_pkg_all_import_2: Module-level import of .all of a namespace package' + hint: | + Sage library code should not import sage.PAC.KAGE.all when sage.PAC.KAGE is an implicit + namespace package. Type import_statements("SOME_IDENTIFIER") to find a more specific import, + and rewrite the import statement as "from sage.PAC.KAGE.MODULE import ..." + or "lazy_import('sage.PAC.KAGE.MODULE', '...')". + # Keep in sync with above; but for now we ignore sage.{arith,categories} + pattern: '^import\s+sage(|[.](combinat|crypto|databases|data_structures|dynamics|ext|game_theory|games|geometry|graphs|groups|interfaces|manifolds|matrix|matroids|misc|modules|monoids|numerical|probability|quadratic_forms|quivers|rings|sat|schemes|sets|stats|symbolic|tensor)[a-z0-9_.]*|[.]libs)[.]all' + # imports from .all are allowed in all.py; also allow in some modules that need sage.all + filePattern: '(.*/|)(?!(all|benchmark|dev_tools|parsing|sage_eval|explain_pickle|.*_test))[^/.]*[.](py|pyx|pxi)$' # Magic doctest comments diff --git a/src/VERSION.txt b/src/VERSION.txt index 6730b33848c..72237f23c26 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.1.beta9 +10.1.rc0 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 8c1a833ccb2..5cbb47685ea 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.1.beta9' -SAGE_RELEASE_DATE='2023-08-05' -SAGE_VERSION_BANNER='SageMath version 10.1.beta9, Release Date: 2023-08-05' +SAGE_VERSION='10.1.rc0' +SAGE_RELEASE_DATE='2023-08-13' +SAGE_VERSION_BANNER='SageMath version 10.1.rc0, Release Date: 2023-08-13' diff --git a/src/doc/en/website/root_index.html b/src/doc/en/website/root_index.html index 3ae4d4cd272..21a6086ed72 100644 --- a/src/doc/en/website/root_index.html +++ b/src/doc/en/website/root_index.html @@ -113,7 +113,7 @@
= CyclotomicField(9) # optional - sage.rings.number_field - sage: L.= NumberField((q + q**(-1)).minpoly(), # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = CyclotomicField(9) + sage: L.= NumberField((q + q**(-1)).minpoly(), ....: embedding=AA(q + q**-1)) - sage: norms = [[1, 1/3*(-2*r9**2-r9+1), 0], # optional - sage.rings.number_field + sage: norms = [[1, 1/3*(-2*r9**2-r9+1), 0], ....: [1, -r9**2 - r9, 0], ....: [1, -r9**2 + 1, 0], ....: [1, -r9**2, 0], ....: [1, r9**2 - 4, -r9**2+3]] - sage: H. = HyperplaneArrangements(L) # optional - sage.rings.number_field - sage: A = H(backend='normaliz') # optional - sage.rings.number_field - sage: for v in norms: # optional - sage.rings.number_field + sage: H. = HyperplaneArrangements(L) + sage: A = H(backend='normaliz') + sage: for v in norms: ....: a,b,c = v ....: A = A.add_hyperplane(a*x + b*y + c*z) - sage: R = A.regions() # optional - pynormaliz sage.rings.number_field - sage: R[0].backend() # optional - pynormaliz sage.rings.number_field + sage: R = A.regions() # optional - pynormaliz + sage: R[0].backend() # optional - pynormaliz 'normaliz' TESTS:: @@ -1987,23 +2003,24 @@ def poset_of_regions(self, B=None, numbered_labels=True): sage: H. = HyperplaneArrangements(QQ) sage: A = H([[0,1,1,1], [0,1,2,3]]) - sage: A.poset_of_regions() # optional - sage.combinat + sage: A.poset_of_regions() # needs sage.combinat Finite poset containing 4 elements - sage: A = hyperplane_arrangements.braid(3) # optional - sage.combinat sage.graphs - sage: A.poset_of_regions() # optional - sage.combinat sage.graphs + sage: # needs sage.combinat sage.graphs + sage: A = hyperplane_arrangements.braid(3) + sage: A.poset_of_regions() Finite poset containing 6 elements - sage: A.poset_of_regions(numbered_labels=False) # optional - sage.combinat sage.graphs + sage: A.poset_of_regions(numbered_labels=False) Finite poset containing 6 elements - sage: A = hyperplane_arrangements.braid(4) # optional - sage.combinat sage.graphs - sage: A.poset_of_regions() # optional - sage.combinat sage.graphs + sage: A = hyperplane_arrangements.braid(4) + sage: A.poset_of_regions() Finite poset containing 24 elements sage: H. = HyperplaneArrangements(QQ) sage: A = H([[0,1,1,1], [0,1,2,3], [0,1,3,2], [0,2,1,3]]) - sage: R = A.regions() # optional - sage.combinat - sage: base_region = R[3] # optional - sage.combinat - sage: A.poset_of_regions(B=base_region) # optional - sage.combinat + sage: R = A.regions() + sage: base_region = R[3] + sage: A.poset_of_regions(B=base_region) # needs sage.combinat Finite poset containing 14 elements """ from sage.combinat.posets.posets import Poset @@ -2108,24 +2125,25 @@ def closed_faces(self, labelled=True): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(2) # optional - sage.graphs - sage: a.hyperplanes() # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(2) + sage: a.hyperplanes() (Hyperplane t0 - t1 + 0,) - sage: a.closed_faces() # optional - sage.graphs + sage: a.closed_faces() (((0,), A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line), ((1,), A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line), ((-1,), A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line)) - sage: a.closed_faces(labelled=False) # optional - sage.graphs + sage: a.closed_faces(labelled=False) (A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line, A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line, A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line) - sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] # optional - sage.graphs + sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] [((0,), A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line, (0, 0)), ((1,), A 2-dimensional polyhedron in QQ^2 defined @@ -2157,12 +2175,12 @@ def closed_faces(self, labelled=True): ((-1, -1), A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, (-1, -2))] - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: a.hyperplanes() # optional - sage.graphs + sage: a = hyperplane_arrangements.braid(3) # needs sage.graphs + sage: a.hyperplanes() # needs sage.graphs (Hyperplane 0*t0 + t1 - t2 + 0, Hyperplane t0 - t1 + 0*t2 + 0, Hyperplane t0 + 0*t1 - t2 + 0) - sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] # optional - sage.graphs + sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] # needs sage.graphs [((0, 0, 0), A 1-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line, (0, 0, 0)), ((0, 1, 1), A 2-dimensional polyhedron in QQ^3 defined @@ -2200,10 +2218,10 @@ def closed_faces(self, labelled=True): ....: LHS = Qx.sum(x ** F[1].dim() for F in a.closed_faces()) ....: return LHS == RHS sage: a = hyperplane_arrangements.Catalan(2) - sage: test_number(a) # optional - sage.combinat + sage: test_number(a) # needs sage.combinat True - sage: a = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: test_number(a) # long time # optional - sage.combinat + sage: a = hyperplane_arrangements.Shi(3) + sage: test_number(a) # long time # needs sage.combinat True TESTS: @@ -2338,27 +2356,28 @@ def face_product(self, F, G, normalize=True): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: a.hyperplanes() # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: a.hyperplanes() (Hyperplane 0*t0 + t1 - t2 + 0, Hyperplane t0 - t1 + 0*t2 + 0, Hyperplane t0 + 0*t1 - t2 + 0) - sage: faces = {F0: F1 for F0, F1 in a.closed_faces()} # optional - sage.graphs - sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z # optional - sage.graphs - sage: xGyEz.representative_point() # optional - sage.graphs + sage: faces = {F0: F1 for F0, F1 in a.closed_faces()} + sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z + sage: xGyEz.representative_point() (0, -1, -1) - sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z # optional - sage.graphs - sage: xGyEz.representative_point() # optional - sage.graphs + sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z + sage: xGyEz.representative_point() (0, -1, -1) - sage: yGxGz = faces[(1, -1, 1)] # closed face y >= x >= z # optional - sage.graphs - sage: xGyGz = faces[(1, 1, 1)] # closed face x >= y >= z # optional - sage.graphs - sage: a.face_product(xGyEz, yGxGz) == xGyGz # optional - sage.graphs + sage: yGxGz = faces[(1, -1, 1)] # closed face y >= x >= z + sage: xGyGz = faces[(1, 1, 1)] # closed face x >= y >= z + sage: a.face_product(xGyEz, yGxGz) == xGyGz True - sage: a.face_product(yGxGz, xGyEz) == yGxGz # optional - sage.graphs + sage: a.face_product(yGxGz, xGyEz) == yGxGz True - sage: xEzGy = faces[(-1, 1, 0)] # closed face x = z >= y # optional - sage.graphs - sage: xGzGy = faces[(-1, 1, 1)] # closed face x >= z >= y # optional - sage.graphs - sage: a.face_product(xEzGy, yGxGz) == xGzGy # optional - sage.graphs + sage: xEzGy = faces[(-1, 1, 0)] # closed face x = z >= y + sage: xGzGy = faces[(-1, 1, 1)] # closed face x >= z >= y + sage: a.face_product(xEzGy, yGxGz) == xGzGy True """ f = F.representative_point() @@ -2433,8 +2452,9 @@ def face_semigroup_algebra(self, field=None, names='e'): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: [(i, F[0]) for i, F in enumerate(a.closed_faces())] # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: [(i, F[0]) for i, F in enumerate(a.closed_faces())] [(0, (0, 0, 0)), (1, (0, 1, 1)), (2, (0, -1, -1)), @@ -2448,44 +2468,45 @@ def face_semigroup_algebra(self, field=None, names='e'): (10, (-1, 1, 1)), (11, (-1, 1, -1)), (12, (-1, -1, -1))] - sage: U = a.face_semigroup_algebra(); U # optional - sage.graphs + sage: U = a.face_semigroup_algebra(); U Finite-dimensional algebra of degree 13 over Rational Field - sage: e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = U.basis() # optional - sage.graphs - sage: e0 * e1 # optional - sage.graphs + sage: e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = U.basis() + sage: e0 * e1 e1 - sage: e0 * e5 # optional - sage.graphs + sage: e0 * e5 e5 - sage: e5 * e0 # optional - sage.graphs + sage: e5 * e0 e5 - sage: e3 * e2 # optional - sage.graphs + sage: e3 * e2 e6 - sage: e7 * e12 # optional - sage.graphs + sage: e7 * e12 e7 - sage: e3 * e12 # optional - sage.graphs + sage: e3 * e12 e6 - sage: e4 * e8 # optional - sage.graphs + sage: e4 * e8 e4 - sage: e8 * e4 # optional - sage.graphs + sage: e8 * e4 e11 - sage: e8 * e1 # optional - sage.graphs + sage: e8 * e1 e11 - sage: e5 * e12 # optional - sage.graphs + sage: e5 * e12 e7 - sage: (e3 + 2*e4) * (e1 - e7) # optional - sage.graphs + sage: (e3 + 2*e4) * (e1 - e7) e4 - e6 - sage: U3 = a.face_semigroup_algebra(field=GF(3)); U3 # optional - sage.graphs sage.rings.finite_rings + sage: U3 = a.face_semigroup_algebra(field=GF(3)); U3 # needs sage.graphs sage.rings.finite_rings Finite-dimensional algebra of degree 13 over Finite Field of size 3 TESTS: The ``names`` keyword works:: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: U = a.face_semigroup_algebra(names='x'); U # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: U = a.face_semigroup_algebra(names='x'); U Finite-dimensional algebra of degree 13 over Rational Field - sage: e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = U.basis() # optional - sage.graphs - sage: e0 * e1 # optional - sage.graphs + sage: e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = U.basis() + sage: e0 * e1 x1 """ if field is None: @@ -2545,8 +2566,8 @@ def region_containing_point(self, p): TESTS:: sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3]) - sage: B = A.change_ring(FiniteField(7)) # optional - sage.rings.finite_rings - sage: B.region_containing_point((1,2)) # optional - sage.rings.finite_rings + sage: B = A.change_ring(FiniteField(7)) + sage: B.region_containing_point((1,2)) Traceback (most recent call last): ... ValueError: base field must have characteristic zero @@ -2584,8 +2605,8 @@ def _bounded_region_indices(self): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: a._bounded_region_indices() # optional - sage.combinat + sage: a = hyperplane_arrangements.semiorder(3) + sage: a._bounded_region_indices() (2, 7, 8, 9, 10, 11, 16) """ from sage.geometry.polyhedron.constructor import Polyhedron @@ -2620,8 +2641,9 @@ def bounded_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: A.bounded_regions() # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.semiorder(3) + sage: A.bounded_regions() (A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line, A 3-dimensional polyhedron in QQ^3 defined @@ -2636,9 +2658,9 @@ def bounded_regions(self): as the convex hull of 3 vertices and 1 line, A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line) - sage: A.bounded_regions()[0].is_compact() # the regions are only *relatively* bounded # optional - sage.combinat + sage: A.bounded_regions()[0].is_compact() # the regions are only *relatively* bounded False - sage: A.is_essential() # optional - sage.combinat + sage: A.is_essential() False """ return tuple(self.regions()[i] for i in self._bounded_region_indices()) @@ -2659,11 +2681,12 @@ def unbounded_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: B = A.essentialization() # optional - sage.combinat - sage: B.n_regions() - B.n_bounded_regions() # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.semiorder(3) + sage: B = A.essentialization() + sage: B.n_regions() - B.n_bounded_regions() 12 - sage: B.unbounded_regions() # optional - sage.combinat + sage: B.unbounded_regions() (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray, A 2-dimensional polyhedron in QQ^2 defined @@ -2711,8 +2734,8 @@ def whitney_data(self): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: A.whitney_data() # optional - sage.combinat + sage: A = hyperplane_arrangements.Shi(3) + sage: A.whitney_data() # needs sage.combinat ( [ 1 -6 9] [ 1 6 6] [ 0 6 -15] [ 0 6 15] @@ -2761,12 +2784,13 @@ def doubly_indexed_whitney_number(self, i, j, kind=1): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: A.doubly_indexed_whitney_number(0, 2) # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.Shi(3) + sage: A.doubly_indexed_whitney_number(0, 2) 9 - sage: A.whitney_number(2) # optional - sage.combinat + sage: A.whitney_number(2) 9 - sage: A.doubly_indexed_whitney_number(1, 2) # optional - sage.combinat + sage: A.doubly_indexed_whitney_number(1, 2) -15 REFERENCES: @@ -2811,20 +2835,21 @@ def whitney_number(self, k, kind=1): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: A.whitney_number(0) # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.Shi(3) + sage: A.whitney_number(0) 1 - sage: A.whitney_number(1) # optional - sage.combinat + sage: A.whitney_number(1) -6 - sage: A.whitney_number(2) # optional - sage.combinat + sage: A.whitney_number(2) 9 - sage: A.characteristic_polynomial() # optional - sage.combinat + sage: A.characteristic_polynomial() x^3 - 6*x^2 + 9*x - sage: A.whitney_number(1, kind=2) # optional - sage.combinat + sage: A.whitney_number(1, kind=2) 6 - sage: p = A.intersection_poset() # optional - sage.combinat - sage: r = p.rank_function() # optional - sage.combinat - sage: len([i for i in p if r(i) == 1]) # optional - sage.combinat + sage: p = A.intersection_poset() + sage: r = p.rank_function() + sage: len([i for i in p if r(i) == 1]) 6 """ if k >= 0 and k <= self.dimension(): @@ -3005,8 +3030,8 @@ def matroid(self): intersection lattice:: sage: f = sum([list(M.flats(i)) for i in range(M.rank() + 1)], []) - sage: PF = Poset([f, lambda x, y: x < y]) # optional - sage.combinat - sage: PF.is_isomorphic(A.intersection_poset()) # optional - sage.combinat + sage: PF = Poset([f, lambda x, y: x < y]) # needs sage.combinat + sage: PF.is_isomorphic(A.intersection_poset()) # needs sage.combinat True """ if not self.is_central(): @@ -3096,13 +3121,14 @@ def minimal_generated_number(self): Check that :trac:`26705` is fixed:: - sage: w = WeylGroup(['A', 4]).from_reduced_word([3, 4, 2, 1]) # optional - sage.combinat sage.groups - sage: I = w.inversion_arrangement() # optional - sage.combinat sage.groups - sage: I # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: w = WeylGroup(['A', 4]).from_reduced_word([3, 4, 2, 1]) + sage: I = w.inversion_arrangement() + sage: I Arrangement - sage: I.minimal_generated_number() # optional - sage.combinat sage.groups + sage: I.minimal_generated_number() 0 - sage: I.is_formal() # optional - sage.combinat sage.groups + sage: I.is_formal() True """ V = VectorSpace(self.base_ring(), self.dimension()) @@ -3184,9 +3210,9 @@ def derivation_module_free_chain(self): EXAMPLES:: - sage: W = WeylGroup(['A',3], prefix='s') # optional - sage.combinat sage.groups - sage: A = W.long_element().inversion_arrangement() # optional - sage.combinat sage.groups - sage: for M in A.derivation_module_free_chain(): print("%s\n"%M) # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A',3], prefix='s') # needs sage.combinat sage.groups + sage: A = W.long_element().inversion_arrangement() # needs sage.combinat sage.groups + sage: for M in A.derivation_module_free_chain(): print("%s\n"%M) # needs sage.combinat sage.groups [ 1 0 0] [ 0 1 0] [ 0 0 a3] @@ -3260,8 +3286,8 @@ def is_free(self, algorithm="singular"): For type `A` arrangements, chordality is equivalent to freeness. We verify that in type `A_3`:: - sage: W = WeylGroup(['A', 3], prefix='s') # optional - sage.combinat sage.groups - sage: for x in W: # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3], prefix='s') # needs sage.combinat sage.groups + sage: for x in W: # needs sage.combinat sage.groups ....: A = x.inversion_arrangement() ....: assert A.matroid().is_chordal() == A.is_free() @@ -3269,8 +3295,8 @@ def is_free(self, algorithm="singular"): We check that the algorithms agree:: - sage: W = WeylGroup(['B', 3], prefix='s') # optional - sage.combinat sage.groups - sage: for x in W: # long time # optional - sage.combinat sage.groups + sage: W = WeylGroup(['B', 3], prefix='s') # needs sage.combinat sage.groups + sage: for x in W: # long time # needs sage.combinat sage.groups ....: A = x.inversion_arrangement() ....: assert (A.is_free(algorithm="BC") ....: == A.is_free(algorithm="singular")) @@ -3329,19 +3355,19 @@ def derivation_module_basis(self, algorithm="singular"): EXAMPLES:: - sage: W = WeylGroup(['A', 2], prefix='s') # optional - sage.combinat sage.groups - sage: A = W.long_element().inversion_arrangement() # optional - sage.combinat sage.groups - sage: A.derivation_module_basis() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 2], prefix='s') # needs sage.combinat sage.groups + sage: A = W.long_element().inversion_arrangement() # needs sage.combinat sage.groups + sage: A.derivation_module_basis() # needs sage.combinat sage.groups [(a1, a2), (0, a1*a2 + a2^2)] TESTS: We check the algorithms produce a basis with the same exponents:: - sage: W = WeylGroup(['A', 2], prefix='s') # optional - sage.combinat sage.groups - sage: def exponents(B): # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 2], prefix='s') # needs sage.combinat sage.groups + sage: def exponents(B): ....: return sorted([max(x.degree() for x in b) for b in B]) - sage: for x in W: # long time # optional - sage.combinat sage.groups + sage: for x in W: # long time # needs sage.combinat sage.groups ....: A = x.inversion_arrangement() ....: B = A.derivation_module_basis(algorithm="singular") ....: Bp = A.derivation_module_basis(algorithm="BC") @@ -3633,7 +3659,8 @@ def ngens(self): EXAMPLES:: sage: L. = HyperplaneArrangements(QQ); L - Hyperplane arrangements in 3-dimensional linear space over Rational Field with coordinates x, y, z + Hyperplane arrangements in 3-dimensional linear space + over Rational Field with coordinates x, y, z sage: L.ngens() 3 """ diff --git a/src/sage/geometry/hyperplane_arrangement/hyperplane.py b/src/sage/geometry/hyperplane_arrangement/hyperplane.py index 8284022d3d8..8d4b301f8d8 100644 --- a/src/sage/geometry/hyperplane_arrangement/hyperplane.py +++ b/src/sage/geometry/hyperplane_arrangement/hyperplane.py @@ -26,7 +26,7 @@ (3, 2, -5) sage: h.constant_term() -7 - sage: h.change_ring(GF(3)) # optional - sage.rings.finite_rings + sage: h.change_ring(GF(3)) Hyperplane 0*x + 2*y + z + 2 sage: h.point() (21/38, 7/19, -35/38) @@ -238,9 +238,9 @@ def _normal_pivot(self): sage: (x + 3/2*y - 2*z)._normal_pivot() 2 - sage: H. = HyperplaneArrangements(GF(5)) # optional - sage.rings.finite_rings - sage: V = H.ambient_space() # optional - sage.rings.finite_rings - sage: (x + 3*y - 4*z)._normal_pivot() # optional - sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(5)) + sage: V = H.ambient_space() + sage: (x + 3*y - 4*z)._normal_pivot() 1 """ try: @@ -397,16 +397,17 @@ def point(self): sage: h.point() in h True - sage: H. = HyperplaneArrangements(GF(3)) # optional - sage.rings.finite_rings - sage: h = 2*x + y + z + 1 # optional - sage.rings.finite_rings - sage: h.point() # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(3)) + sage: h = 2*x + y + z + 1 + sage: h.point() (1, 0, 0) - sage: h.point().base_ring() # optional - sage.rings.finite_rings + sage: h.point().base_ring() Finite Field of size 3 - sage: H. = HyperplaneArrangements(GF(3)) # optional - sage.rings.finite_rings - sage: h = x + y + z + 1 # optional - sage.rings.finite_rings - sage: h.point() # optional - sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(3)) + sage: h = x + y + z + 1 + sage: h.point() (2, 0, 0) """ P = self.parent() @@ -552,21 +553,23 @@ def primitive(self, signed=True): Check that :trac:`30078` is fixed:: - sage: R. = QuadraticField(2) # optional - sage.rings.number_field - sage: H. = HyperplaneArrangements(base_ring=R) # optional - sage.rings.number_field - sage: B = H([1,1,0], [2,2,0], [sqrt2,sqrt2,0]) # optional - sage.rings.number_field - sage: B # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: R. = QuadraticField(2) + sage: H. = HyperplaneArrangements(base_ring=R) + sage: B = H([1,1,0], [2,2,0], [sqrt2,sqrt2,0]) + sage: B Arrangement Check that :trac:`30749` is fixed:: - sage: tau = (1+AA(5).sqrt()) / 2 # optional - sage.rings.number_field - sage: ncn = [[2*tau+1,2*tau,tau],[2*tau+2,2*tau+1,tau+1]] # optional - sage.rings.number_field - sage: ncn += [[tau+1,tau+1,tau],[2*tau,2*tau,tau],[tau+1,tau+1,1]] # optional - sage.rings.number_field - sage: ncn += [[1,1,1],[1,1,0],[0,1,0],[1,0,0],[tau+1,tau,tau]] # optional - sage.rings.number_field - sage: H = HyperplaneArrangements(AA,names='xyz') # optional - sage.rings.number_field - sage: A = H([[0]+v for v in ncn]) # optional - sage.rings.number_field - sage: A.n_regions() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: tau = (1+AA(5).sqrt()) / 2 + sage: ncn = [[2*tau+1,2*tau,tau],[2*tau+2,2*tau+1,tau+1]] + sage: ncn += [[tau+1,tau+1,tau],[2*tau,2*tau,tau],[tau+1,tau+1,1]] + sage: ncn += [[1,1,1],[1,1,0],[0,1,0],[1,0,0],[tau+1,tau,tau]] + sage: H = HyperplaneArrangements(AA,names='xyz') + sage: A = H([[0]+v for v in ncn]) + sage: A.n_regions() 60 """ from sage.rings.rational_field import QQ @@ -638,7 +641,7 @@ def plot(self, **kwds): EXAMPLES:: sage: L. = HyperplaneArrangements(QQ) - sage: (x + y - 2).plot() # optional - sage.plot + sage: (x + y - 2).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives """ from sage.geometry.hyperplane_arrangement.plot import plot_hyperplane diff --git a/src/sage/geometry/hyperplane_arrangement/library.py b/src/sage/geometry/hyperplane_arrangement/library.py index 5d0b4aae4d7..83c4f80c325 100644 --- a/src/sage/geometry/hyperplane_arrangement/library.py +++ b/src/sage/geometry/hyperplane_arrangement/library.py @@ -90,7 +90,7 @@ def braid(self, n, K=QQ, names=None): EXAMPLES:: - sage: hyperplane_arrangements.braid(4) # optional - sage.graphs + sage: hyperplane_arrangements.braid(4) # needs sage.graphs Arrangement of 6 hyperplanes of dimension 4 and rank 3 """ x = polygen(QQ, 'x') @@ -124,18 +124,19 @@ def bigraphical(self, G, A=None, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CycleGraph(4) # optional - sage.graphs - sage: G.edges(sort=True) # optional - sage.graphs + sage: # needs sage.graphs + sage: G = graphs.CycleGraph(4) + sage: G.edges(sort=True) [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)] - sage: G.edges(sort=True, labels=False) # optional - sage.graphs + sage: G.edges(sort=True, labels=False) [(0, 1), (0, 3), (1, 2), (2, 3)] - sage: A = {0:{1:1, 3:2}, 1:{0:3, 2:0}, 2:{1:2, 3:1}, 3:{2:0, 0:2}} # optional - sage.graphs - sage: HA = hyperplane_arrangements.bigraphical(G, A) # optional - sage.graphs - sage: HA.n_regions() # optional - sage.graphs + sage: A = {0:{1:1, 3:2}, 1:{0:3, 2:0}, 2:{1:2, 3:1}, 3:{2:0, 0:2}} + sage: HA = hyperplane_arrangements.bigraphical(G, A) + sage: HA.n_regions() 63 - sage: hyperplane_arrangements.bigraphical(G, 'generic').n_regions() # optional - sage.graphs + sage: hyperplane_arrangements.bigraphical(G, 'generic').n_regions() 65 - sage: hyperplane_arrangements.bigraphical(G).n_regions() # optional - sage.graphs + sage: hyperplane_arrangements.bigraphical(G).n_regions() 59 REFERENCES: @@ -253,11 +254,12 @@ def G_semiorder(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) # optional - sage.graphs - sage: hyperplane_arrangements.G_semiorder(G) # optional - sage.graphs + sage: # needs sage.graphs + sage: G = graphs.CompleteGraph(5) + sage: hyperplane_arrangements.G_semiorder(G) Arrangement of 20 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() # optional - sage.graphs - sage: hyperplane_arrangements.G_semiorder(g) # optional - sage.graphs + sage: g = graphs.HouseGraph() + sage: hyperplane_arrangements.G_semiorder(g) Arrangement of 12 hyperplanes of dimension 5 and rank 4 """ n = G.num_verts() @@ -291,13 +293,14 @@ def G_Shi(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) # optional - sage.graphs - sage: hyperplane_arrangements.G_Shi(G) # optional - sage.graphs + sage: # needs sage.graphs + sage: G = graphs.CompleteGraph(5) + sage: hyperplane_arrangements.G_Shi(G) Arrangement of 20 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() # optional - sage.graphs - sage: hyperplane_arrangements.G_Shi(g) # optional - sage.graphs + sage: g = graphs.HouseGraph() + sage: hyperplane_arrangements.G_Shi(g) Arrangement of 12 hyperplanes of dimension 5 and rank 4 - sage: a = hyperplane_arrangements.G_Shi(graphs.WheelGraph(4)); a # optional - sage.graphs + sage: a = hyperplane_arrangements.G_Shi(graphs.WheelGraph(4)); a Arrangement of 12 hyperplanes of dimension 4 and rank 3 """ n = G.num_verts() @@ -333,20 +336,22 @@ def graphical(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) # optional - sage.graphs - sage: hyperplane_arrangements.graphical(G) # optional - sage.graphs + sage: # needs sage.graphs + sage: G = graphs.CompleteGraph(5) + sage: hyperplane_arrangements.graphical(G) Arrangement of 10 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() # optional - sage.graphs - sage: hyperplane_arrangements.graphical(g) # optional - sage.graphs + sage: g = graphs.HouseGraph() + sage: hyperplane_arrangements.graphical(g) Arrangement of 6 hyperplanes of dimension 5 and rank 4 TESTS:: - sage: h = hyperplane_arrangements.graphical(g) # optional - sage.graphs - sage: h.characteristic_polynomial() # optional - sage.graphs + sage: # needs sage.graphs + sage: h = hyperplane_arrangements.graphical(g) + sage: h.characteristic_polynomial() x^5 - 6*x^4 + 14*x^3 - 15*x^2 + 6*x - sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.graphs - sage: h.characteristic_polynomial() # long time # optional - sage.graphs + sage: h.characteristic_polynomial.clear_cache() # long time + sage: h.characteristic_polynomial() # long time x^5 - 6*x^4 + 14*x^3 - 15*x^2 + 6*x """ n = G.num_verts() @@ -388,18 +393,19 @@ def Ish(self, n, K=QQ, names=None): EXAMPLES:: - sage: a = hyperplane_arrangements.Ish(3); a # optional - sage.combinat + sage: # needs sage.combinat + sage: a = hyperplane_arrangements.Ish(3); a Arrangement of 6 hyperplanes of dimension 3 and rank 2 - sage: a.characteristic_polynomial() # optional - sage.combinat + sage: a.characteristic_polynomial() x^3 - 6*x^2 + 9*x - sage: b = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: b.characteristic_polynomial() # optional - sage.combinat + sage: b = hyperplane_arrangements.Shi(3) + sage: b.characteristic_polynomial() x^3 - 6*x^2 + 9*x TESTS:: - sage: a.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat - sage: a.characteristic_polynomial() # long time # optional - sage.combinat + sage: a.characteristic_polynomial.clear_cache() # long time # needs sage.combinat + sage: a.characteristic_polynomial() # long time # needs sage.combinat x^3 - 6*x^2 + 9*x REFERENCES: @@ -565,16 +571,17 @@ def semiorder(self, n, K=QQ, names=None): EXAMPLES:: - sage: hyperplane_arrangements.semiorder(4) # optional - sage.combinat + sage: hyperplane_arrangements.semiorder(4) Arrangement of 12 hyperplanes of dimension 4 and rank 3 TESTS:: - sage: h = hyperplane_arrangements.semiorder(5) # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: # needs sage.combinat + sage: h = hyperplane_arrangements.semiorder(5) + sage: h.characteristic_polynomial() x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x - sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat - sage: h.characteristic_polynomial() # long time # optional - sage.combinat + sage: h.characteristic_polynomial.clear_cache() # long time + sage: h.characteristic_polynomial() # long time x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x """ H = make_parent(K, n, names) @@ -626,29 +633,30 @@ def Shi(self, data, K=QQ, names=None, m=1): EXAMPLES:: - sage: hyperplane_arrangements.Shi(4) # optional - sage.combinat + sage: # needs sage.combinat + sage: hyperplane_arrangements.Shi(4) Arrangement of 12 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("A3") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("A3") Arrangement of 12 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("A3", m=2) # optional - sage.combinat + sage: hyperplane_arrangements.Shi("A3", m=2) Arrangement of 24 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("B4") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("B4") Arrangement of 32 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("B4", m=3) # optional - sage.combinat + sage: hyperplane_arrangements.Shi("B4", m=3) Arrangement of 96 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("C3") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("C3") Arrangement of 18 hyperplanes of dimension 3 and rank 3 - sage: hyperplane_arrangements.Shi("D4", m=3) # optional - sage.combinat + sage: hyperplane_arrangements.Shi("D4", m=3) Arrangement of 72 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("E6") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("E6") Arrangement of 72 hyperplanes of dimension 8 and rank 6 - sage: hyperplane_arrangements.Shi("E6", m=2) # optional - sage.combinat + sage: hyperplane_arrangements.Shi("E6", m=2) Arrangement of 144 hyperplanes of dimension 8 and rank 6 If the Cartan type is not crystallographic, the Shi arrangement is not defined:: - sage: hyperplane_arrangements.Shi("H4") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("H4") Traceback (most recent call last): ... NotImplementedError: Shi arrangements are not defined for non crystallographic Cartan types @@ -656,36 +664,38 @@ def Shi(self, data, K=QQ, names=None, m=1): The characteristic polynomial is pre-computed using the results of [Ath1996]_:: - sage: hyperplane_arrangements.Shi("A3").characteristic_polynomial() # optional - sage.combinat + sage: # needs sage.combinat + sage: hyperplane_arrangements.Shi("A3").characteristic_polynomial() x^4 - 12*x^3 + 48*x^2 - 64*x - sage: hyperplane_arrangements.Shi("A3", m=2).characteristic_polynomial() # optional - sage.combinat + sage: hyperplane_arrangements.Shi("A3", m=2).characteristic_polynomial() x^4 - 24*x^3 + 192*x^2 - 512*x - sage: hyperplane_arrangements.Shi("C3").characteristic_polynomial() # optional - sage.combinat + sage: hyperplane_arrangements.Shi("C3").characteristic_polynomial() x^3 - 18*x^2 + 108*x - 216 - sage: hyperplane_arrangements.Shi("E6").characteristic_polynomial() # optional - sage.combinat + sage: hyperplane_arrangements.Shi("E6").characteristic_polynomial() x^8 - 72*x^7 + 2160*x^6 - 34560*x^5 + 311040*x^4 - 1492992*x^3 + 2985984*x^2 - sage: hyperplane_arrangements.Shi("B4", m=3).characteristic_polynomial() # optional - sage.combinat + sage: hyperplane_arrangements.Shi("B4", m=3).characteristic_polynomial() x^4 - 96*x^3 + 3456*x^2 - 55296*x + 331776 TESTS:: - sage: h = hyperplane_arrangements.Shi(4) # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: # needs sage.combinat + sage: h = hyperplane_arrangements.Shi(4) + sage: h.characteristic_polynomial() x^4 - 12*x^3 + 48*x^2 - 64*x - sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat - sage: h.characteristic_polynomial() # long time # optional - sage.combinat + sage: h.characteristic_polynomial.clear_cache() # long time + sage: h.characteristic_polynomial() # long time x^4 - 12*x^3 + 48*x^2 - 64*x - sage: h = hyperplane_arrangements.Shi("A3", m=2) # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: h = hyperplane_arrangements.Shi("A3", m=2) + sage: h.characteristic_polynomial() x^4 - 24*x^3 + 192*x^2 - 512*x - sage: h.characteristic_polynomial.clear_cache() # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: h.characteristic_polynomial.clear_cache() + sage: h.characteristic_polynomial() x^4 - 24*x^3 + 192*x^2 - 512*x - sage: h = hyperplane_arrangements.Shi("B3", m=3) # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: h = hyperplane_arrangements.Shi("B3", m=3) + sage: h.characteristic_polynomial() x^3 - 54*x^2 + 972*x - 5832 - sage: h.characteristic_polynomial.clear_cache() # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: h.characteristic_polynomial.clear_cache() + sage: h.characteristic_polynomial() x^3 - 54*x^2 + 972*x - 5832 """ if data in NN: diff --git a/src/sage/geometry/hyperplane_arrangement/plot.py b/src/sage/geometry/hyperplane_arrangement/plot.py index d2c62f2d547..be468c111bc 100644 --- a/src/sage/geometry/hyperplane_arrangement/plot.py +++ b/src/sage/geometry/hyperplane_arrangement/plot.py @@ -56,26 +56,26 @@ sage: H3. = HyperplaneArrangements(QQ) sage: A = H3([(1,0,0), 0], [(0,0,1), 5]) - sage: A.plot(hyperplane_opacities=0.5, hyperplane_labels=True, # optional - sage.plot + sage: A.plot(hyperplane_opacities=0.5, hyperplane_labels=True, # needs sage.plot ....: hyperplane_legend=False) Graphics3d Object sage: c = H3([(1,0,0),0], [(0,0,1),5]) - sage: c.plot(ranges=10) # optional - sage.plot + sage: c.plot(ranges=10) # needs sage.plot Graphics3d Object - sage: c.plot(ranges=[[9.5,10], [-3,3]]) # optional - sage.plot + sage: c.plot(ranges=[[9.5,10], [-3,3]]) # needs sage.plot Graphics3d Object - sage: c.plot(ranges=[[[9.5,10], [-3,3]], [[-6,6], [-5,5]]]) # optional - sage.plot + sage: c.plot(ranges=[[[9.5,10], [-3,3]], [[-6,6], [-5,5]]]) # needs sage.plot Graphics3d Object sage: H2. = HyperplaneArrangements(QQ) sage: h = H2([(1,1),0], [(1,-1),0], [(0,1),2]) - sage: h.plot(ranges=20) # optional - sage.plot + sage: h.plot(ranges=20) # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: h.plot(ranges=[-1, 10]) # optional - sage.plot + sage: h.plot(ranges=[-1, 10]) # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: h.plot(ranges=[[-1, 1], [-5, 5], [-1, 10]]) # optional - sage.plot + sage: h.plot(ranges=[[-1, 1], [-5, 5], [-1, 10]]) # needs sage.plot Graphics object consisting of 3 graphics primitives sage: a = hyperplane_arrangements.coordinate(3) @@ -84,24 +84,24 @@ sage: opts['label_offsets'] = [(0,2,2), (2,0,2), (2,2,0)] sage: opts['hyperplane_legend'] = False sage: opts['hyperplane_opacities'] = 0.7 - sage: a.plot(**opts) # optional - sage.plot + sage: a.plot(**opts) # needs sage.plot Graphics3d Object sage: opts['hyperplane_labels'] = 'short' - sage: a.plot(**opts) # optional - sage.plot + sage: a.plot(**opts) # needs sage.plot Graphics3d Object sage: H. = HyperplaneArrangements(QQ) sage: pts = H(3*u+4, 2*u+5, 7*u+1) - sage: pts.plot(hyperplane_colors=['yellow','black','blue']) # optional - sage.plot + sage: pts.plot(hyperplane_colors=['yellow','black','blue']) # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: pts.plot(point_sizes=[50,100,200], hyperplane_colors='blue') # optional - sage.plot + sage: pts.plot(point_sizes=[50,100,200], hyperplane_colors='blue') # needs sage.plot Graphics object consisting of 3 graphics primitives sage: H.= HyperplaneArrangements(QQ) sage: a = H(x, y+1, y+2) - sage: a.plot(hyperplane_labels=True, label_colors='blue', label_fontsize=18) # optional - sage.plot + sage: a.plot(hyperplane_labels=True, label_colors='blue', label_fontsize=18) # needs sage.plot Graphics3d Object - sage: a.plot(hyperplane_labels=True, label_colors=['red','green','black']) # optional - sage.plot + sage: a.plot(hyperplane_labels=True, label_colors=['red','green','black']) # needs sage.plot Graphics3d Object """ from copy import copy @@ -145,8 +145,8 @@ def plot(hyperplane_arrangement, **kwds): EXAMPLES:: - sage: B = hyperplane_arrangements.semiorder(4) # optional - sage.combinat - sage: B.plot() # optional - sage.combinat sage.plot + sage: B = hyperplane_arrangements.semiorder(4) + sage: B.plot() # needs sage.combinat sage.plot Displaying the essentialization. Graphics3d Object """ @@ -331,34 +331,35 @@ def plot_hyperplane(hyperplane, **kwds): sage: H1. = HyperplaneArrangements(QQ) sage: a = 3*x + 4 - sage: a.plot() # indirect doctest # optional - sage.plot + sage: a.plot() # indirect doctest # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: a.plot(point_size=100, hyperplane_label='hello') # optional - sage.plot + sage: a.plot(point_size=100, hyperplane_label='hello') # needs sage.plot Graphics object consisting of 3 graphics primitives sage: H2. = HyperplaneArrangements(QQ) sage: b = 3*x + 4*y + 5 - sage: b.plot() # optional - sage.plot + sage: b.plot() # needs sage.plot Graphics object consisting of 2 graphics primitives - sage: b.plot(ranges=(1,5), label_offset=(2,-1)) # optional - sage.plot + sage: b.plot(ranges=(1,5), label_offset=(2,-1)) # needs sage.plot Graphics object consisting of 2 graphics primitives sage: opts = {'hyperplane_label': True, 'label_color': 'green', ....: 'label_fontsize': 24, 'label_offset': (0,1.5)} - sage: b.plot(**opts) # optional - sage.plot + sage: b.plot(**opts) # needs sage.plot Graphics object consisting of 2 graphics primitives + sage: # needs sage.plot sage: H3. = HyperplaneArrangements(QQ) sage: c = 2*x + 3*y + 4*z + 5 - sage: c.plot() # optional - sage.plot + sage: c.plot() Graphics3d Object - sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', # optional - sage.plot + sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', ....: frame=False) Graphics3d Object sage: d = -3*x + 2*y + 2*z + 3 - sage: d.plot(opacity=0.8) # optional - sage.plot + sage: d.plot(opacity=0.8) Graphics3d Object sage: e = 4*x + 2*z + 3 - sage: e.plot(ranges=[[-1,1],[0,8]], label_offset=(2,2,1), aspect_ratio=1) # optional - sage.plot + sage: e.plot(ranges=[[-1,1],[0,8]], label_offset=(2,2,1), aspect_ratio=1) Graphics3d Object """ if hyperplane.base_ring().characteristic(): @@ -486,22 +487,22 @@ def legend_3d(hyperplane_arrangement, hyperplane_colors, length): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: a = hyperplane_arrangements.semiorder(3) sage: from sage.geometry.hyperplane_arrangement.plot import legend_3d - sage: legend_3d(a, list(colors.values())[:6], length='long') # optional - sage.combinat sage.plot + sage: legend_3d(a, list(colors.values())[:6], length='long') # needs sage.combinat sage.plot Graphics object consisting of 6 graphics primitives - sage: b = hyperplane_arrangements.semiorder(4) # optional - sage.combinat - sage: c = b.essentialization() # optional - sage.combinat - sage: legend_3d(c, list(colors.values())[:12], length='long') # optional - sage.combinat sage.plot + sage: b = hyperplane_arrangements.semiorder(4) + sage: c = b.essentialization() + sage: legend_3d(c, list(colors.values())[:12], length='long') # needs sage.combinat sage.plot Graphics object consisting of 12 graphics primitives - sage: legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.combinat sage.plot + sage: legend_3d(c, list(colors.values())[:12], length='short') # needs sage.combinat sage.plot Graphics object consisting of 12 graphics primitives - sage: p = legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.combinat sage.plot - sage: p.set_legend_options(ncol=4) # optional - sage.combinat sage.plot - sage: type(p) # optional - sage.combinat sage.plot + sage: p = legend_3d(c, list(colors.values())[:12], length='short') # needs sage.combinat sage.plot + sage: p.set_legend_options(ncol=4) # needs sage.combinat sage.plot + sage: type(p) # needs sage.combinat sage.plot """ if hyperplane_arrangement.dimension() != 3: diff --git a/src/sage/geometry/integral_points.pxi b/src/sage/geometry/integral_points.pxi index dae34bc99af..c45f7f1cb2e 100644 --- a/src/sage/geometry/integral_points.pxi +++ b/src/sage/geometry/integral_points.pxi @@ -474,8 +474,8 @@ cpdef rectangular_box_points(list box_min, list box_max, Long ints and non-integral polyhedra are explicitly allowed:: - sage: polytope = Polyhedron([[1], [10*pi.n()]], base_ring=RDF) # optional - sage.symbolic - sage: len(rectangular_box_points([-100], [100], polytope)) # optional - sage.symbolic + sage: polytope = Polyhedron([[1], [10*pi.n()]], base_ring=RDF) # needs sage.symbolic + sage: len(rectangular_box_points([-100], [100], polytope)) # needs sage.symbolic 31 sage: halfplane = Polyhedron(ieqs=[(-1,1,0)]) @@ -488,15 +488,16 @@ cpdef rectangular_box_points(list box_min, list box_max, Using a PPL polyhedron:: - sage: from ppl import Variable, Generator_System, C_Polyhedron, point # optional - pplpy - sage: gs = Generator_System() # optional - pplpy - sage: x = Variable(0); y = Variable(1); z = Variable(2) # optional - pplpy - sage: gs.insert(point(0*x + 1*y + 0*z)) # optional - pplpy - sage: gs.insert(point(0*x + 1*y + 3*z)) # optional - pplpy - sage: gs.insert(point(3*x + 1*y + 0*z)) # optional - pplpy - sage: gs.insert(point(3*x + 1*y + 3*z)) # optional - pplpy - sage: poly = C_Polyhedron(gs) # optional - pplpy - sage: rectangular_box_points([0]*3, [3]*3, poly) # optional - pplpy + sage: # needs pplpy + sage: from ppl import Variable, Generator_System, C_Polyhedron, point + sage: gs = Generator_System() + sage: x = Variable(0); y = Variable(1); z = Variable(2) + sage: gs.insert(point(0*x + 1*y + 0*z)) + sage: gs.insert(point(0*x + 1*y + 3*z)) + sage: gs.insert(point(3*x + 1*y + 0*z)) + sage: gs.insert(point(3*x + 1*y + 3*z)) + sage: poly = C_Polyhedron(gs) + sage: rectangular_box_points([0]*3, [3]*3, poly) ((0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 1, 3), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 1, 3)) @@ -739,7 +740,7 @@ cdef class Inequality_generic: EXAMPLES:: sage: from sage.geometry.integral_points import Inequality_generic - sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # optional - sage.symbolic + sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # needs sage.symbolic generic: (2*pi, sqrt(3), 7/2) x + -5.50000000000000 >= 0 """ @@ -761,7 +762,7 @@ cdef class Inequality_generic: EXAMPLES:: sage: from sage.geometry.integral_points import Inequality_generic - sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # optional - sage.symbolic + sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # needs sage.symbolic generic: (2*pi, sqrt(3), 7/2) x + -5.50000000000000 >= 0 """ self.A = A @@ -1131,16 +1132,17 @@ cdef class InequalityCollection: EXAMPLES:: - sage: from ppl import Variable, Generator_System, C_Polyhedron, point # optional - pplpy - sage: gs = Generator_System() # optional - pplpy - sage: x = Variable(0); y = Variable(1); z = Variable(2) # optional - pplpy - sage: gs.insert(point(0*x + 0*y + 1*z)) # optional - pplpy - sage: gs.insert(point(0*x + 3*y + 1*z)) # optional - pplpy - sage: gs.insert(point(3*x + 0*y + 1*z)) # optional - pplpy - sage: gs.insert(point(3*x + 3*y + 1*z)) # optional - pplpy - sage: poly = C_Polyhedron(gs) # optional - pplpy - sage: from sage.geometry.integral_points import InequalityCollection # optional - pplpy - sage: InequalityCollection(poly, [0,2,1], [0]*3, [3]*3 ) # optional - pplpy + sage: # needs pplpy + sage: from ppl import Variable, Generator_System, C_Polyhedron, point + sage: gs = Generator_System() + sage: x = Variable(0); y = Variable(1); z = Variable(2) + sage: gs.insert(point(0*x + 0*y + 1*z)) + sage: gs.insert(point(0*x + 3*y + 1*z)) + sage: gs.insert(point(3*x + 0*y + 1*z)) + sage: gs.insert(point(3*x + 3*y + 1*z)) + sage: poly = C_Polyhedron(gs) + sage: from sage.geometry.integral_points import InequalityCollection + sage: InequalityCollection(poly, [0,2,1], [0]*3, [3]*3 ) The collection of inequalities integer: (0, 1, 0) x + -1 >= 0 integer: (0, -1, 0) x + 1 >= 0 @@ -1191,8 +1193,8 @@ cdef class InequalityCollection: Check that :trac:`21037` is fixed:: sage: P = Polyhedron(vertices=((0, 0), (17,3))) - sage: P += 1/1000*polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: P.integral_points() # optional - sage.rings.number_field + sage: P += 1/1000*polytopes.regular_polygon(5) # needs sage.rings.number_field + sage: P.integral_points() # needs sage.rings.number_field ((0, 0), (17, 3)) """ cdef list A diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index eab90bd12d2..701b8e43ee8 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -239,7 +239,7 @@ def LatticePolytope(data, compute_vertices=True, n=0, lattice=None): We draw a pretty picture of the polytope in 3-dimensional space:: - sage: p.plot3d().show() # optional - palp sage.plot + sage: p.plot3d().show() # needs palp sage.plot Now we add an extra point, which is in the interior of the polytope... @@ -295,7 +295,7 @@ def LatticePolytope(data, compute_vertices=True, n=0, lattice=None): sage: p.points() Empty collection in 3-d lattice M - sage: p.faces() # optional - sage.graphs + sage: p.faces() # needs sage.graphs ((-1-d lattice polytope in 3-d lattice M,),) """ if isinstance(data, LatticePolytopeClass): @@ -464,7 +464,7 @@ def is_LatticePolytope(x): sage: is_LatticePolytope(1) False sage: p = LatticePolytope([(1,0), (0,1), (-1,-1)]) - sage: p # optional - palp + sage: p # needs palp 2-d reflexive polytope #0 in 2-d lattice M sage: is_LatticePolytope(p) True @@ -763,17 +763,18 @@ def _compute_facets(self): Check that :trac:`28741` is fixed:: + sage: # needs sage.graphs sage: p = LatticePolytope([], lattice=ToricLattice(3).dual()); p -1-d lattice polytope in 3-d lattice M - sage: a = p.faces()[0][0] # optional - sage.graphs + sage: a = p.faces()[0][0] sage: p = LatticePolytope([], lattice=ToricLattice(3).dual()); p -1-d lattice polytope in 3-d lattice M - sage: a = p.faces()[0][0]; a # optional - sage.graphs + sage: a = p.faces()[0][0]; a -1-d lattice polytope in 3-d lattice M - sage: a.facet_normals() # optional - sage.graphs + sage: a.facet_normals() Empty collection in 3-d lattice N - sage: a # optional - sage.graphs + sage: a -1-d lattice polytope in 3-d lattice M """ assert not hasattr(self, "_facet_normals") @@ -966,9 +967,9 @@ def _palp(self, command, reduce_dimension=False): TESTS:: sage: o = lattice_polytope.cross_polytope(3) - sage: o._palp("poly.x -f") # optional - palp + sage: o._palp("poly.x -f") # needs palp 'M:7 6 N:27 8 Pic:17 Cor:0\n' - sage: print(o._palp("nef.x -f -N -p")) # random time information # optional - palp + sage: print(o._palp("nef.x -f -N -p")) # random time information # needs palp M:27 8 N:7 6 codim=2 #part=5 H:[0] P:0 V:2 4 5 0sec 0cpu H:[0] P:2 V:3 4 5 0sec 0cpu @@ -976,18 +977,18 @@ def _palp(self, command, reduce_dimension=False): np=3 d:1 p:1 0sec 0cpu sage: p = LatticePolytope([[1]]) - sage: p._palp("poly.x -f") # optional - palp + sage: p._palp("poly.x -f") # needs palp Traceback (most recent call last): ... ValueError: Cannot run "poly.x -f" for the zero-dimensional polytope! Polytope: 0-d lattice polytope in 1-d lattice M sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: p._palp("poly.x -f") # optional - palp + sage: p._palp("poly.x -f") # needs palp Traceback (most recent call last): ... ValueError: Cannot run PALP for a 2-dimensional polytope in a 3-dimensional space! - sage: p._palp("poly.x -f", reduce_dimension=True) # optional - palp + sage: p._palp("poly.x -f", reduce_dimension=True) # needs palp 'M:5 4 F:4\n' """ if self.dim() <= 0: @@ -1098,22 +1099,23 @@ def _read_equations(self, data): For a reflexive polytope construct the polar polytope:: + sage: # needs palp sage: p = LatticePolytope([(1,0), (0,1), (-1,-1)]) sage: p.vertices() M( 1, 0), M( 0, 1), M(-1, -1) in 2-d lattice M - sage: s = p.poly_x("e") # optional - palp - sage: print(s) # optional - palp + sage: s = p.poly_x("e") + sage: print(s) 3 2 Vertices of P-dual <-> Equations of P 2 -1 -1 2 -1 -1 - sage: "_polar" in p.__dict__ # optional - palp + sage: "_polar" in p.__dict__ False - sage: p._read_equations(s) # optional - palp - sage: p._polar._vertices # optional - palp + sage: p._read_equations(s) + sage: p._polar._vertices N( 2, -1), N(-1, 2), N(-1, -1) @@ -1121,6 +1123,7 @@ def _read_equations(self, data): For a non-reflexive polytope cache facet equations:: + sage: # needs palp sage: p = LatticePolytope([(1,0), (0,2), (-1,-3 )]) sage: p.vertices() M( 1, 0), @@ -1131,19 +1134,19 @@ def _read_equations(self, data): False sage: "_facet_constants" in p.__dict__ False - sage: s = p.poly_x("e") # optional - palp - sage: print(s) # optional - palp + sage: s = p.poly_x("e") + sage: print(s) 3 2 Equations of P 5 -1 2 -2 -1 2 -3 2 3 - sage: p._read_equations(s) # optional - palp - sage: p._facet_normals # optional - palp + sage: p._read_equations(s) + sage: p._facet_normals N( 5, -1), N(-2, -1), N(-3, 2) in 2-d lattice N - sage: p._facet_constants # optional - palp + sage: p._facet_constants (2, 2, 3) """ if isinstance(data, str): @@ -1210,8 +1213,8 @@ def _read_nef_partitions(self, data): TESTS:: sage: o = lattice_polytope.cross_polytope(3) - sage: s = o.nef_x("-p -N -Lv") # optional - palp - sage: print(s) # random time values # optional - palp + sage: s = o.nef_x("-p -N -Lv") # needs palp + sage: print(s) # random time values # needs palp M:27 8 N:7 6 codim=2 #part=5 3 6 Vertices in N-lattice: 1 0 0 -1 0 0 @@ -1232,8 +1235,8 @@ def _read_nef_partitions(self, data): sage: o_copy = LatticePolytope(o.vertices()) sage: "_nef_partitions" in o_copy.__dict__ False - sage: o_copy._read_nef_partitions(s) # optional - palp - sage: o_copy._nef_partitions # optional - palp + sage: o_copy._read_nef_partitions(s) # needs palp + sage: o_copy._nef_partitions # needs palp [ Nef-partition {0, 1, 3} ⊔ {2, 4, 5}, Nef-partition {0, 1, 2} ⊔ {3, 4, 5}, @@ -1335,7 +1338,7 @@ def _sort_faces(self, faces): sage: o = lattice_polytope.cross_polytope(3) sage: # indirect doctest - sage: for i, face in enumerate(o.faces(0)): # optional - sage.graphs + sage: for i, face in enumerate(o.faces(0)): # needs sage.graphs ....: if face.vertex(0) != o.vertex(i): ....: print("Wrong order!") """ @@ -1380,10 +1383,10 @@ def adjacent(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.adjacent() # optional - sage.graphs + sage: o.adjacent() # needs sage.graphs () - sage: face = o.faces(1)[0] # optional - sage.graphs - sage: face.adjacent() # optional - sage.graphs + sage: face = o.faces(1)[0] # needs sage.graphs + sage: face.adjacent() # needs sage.graphs (1-d face of 3-d reflexive polytope in 3-d lattice M, 1-d face of 3-d reflexive polytope in 3-d lattice M, 1-d face of 3-d reflexive polytope in 3-d lattice M, @@ -1505,12 +1508,14 @@ def ambient(self): 3-d reflexive polytope in 3-d lattice M sage: o.ambient() is o True - sage: face = o.faces(1)[0] # optional - sage.graphs - sage: face # optional - sage.graphs + + sage: # needs sage.graphs + sage: face = o.faces(1)[0] + sage: face 1-d face of 3-d reflexive polytope in 3-d lattice M - sage: face.ambient() # optional - sage.graphs + sage: face.ambient() 3-d reflexive polytope in 3-d lattice M - sage: face.ambient() is o # optional - sage.graphs + sage: face.ambient() is o True """ return self._ambient @@ -1533,14 +1538,15 @@ def ambient_facet_indices(self): But each of its other faces is contained in one or more facets:: - sage: face = o.faces(1)[0] # optional - sage.graphs - sage: face.ambient_facet_indices() # optional - sage.graphs + sage: # needs sage.graphs + sage: face = o.faces(1)[0] + sage: face.ambient_facet_indices() (4, 5) - sage: face.vertices() # optional - sage.graphs + sage: face.vertices() M(1, 0, 0), M(0, 1, 0) in 3-d lattice M - sage: o.facets()[face.ambient_facet_indices()[0]].vertices() # optional - sage.graphs + sage: o.facets()[face.ambient_facet_indices()[0]].vertices() M(1, 0, 0), M(0, 1, 0), M(0, 0, -1) @@ -1561,10 +1567,10 @@ def ambient_point_indices(self): EXAMPLES:: sage: cube = lattice_polytope.cross_polytope(3).polar() - sage: face = cube.facets()[0] # optional - sage.graphs - sage: face.ambient_point_indices() # optional - palp sage.graphs + sage: face = cube.facets()[0] # needs sage.graphs + sage: face.ambient_point_indices() # needs palp sage.graphs (4, 5, 6, 7, 8, 9, 10, 11, 12) - sage: cube.points(face.ambient_point_indices()) == face.points() # optional - palp sage.graphs + sage: cube.points(face.ambient_point_indices()) == face.points() # needs palp sage.graphs True """ if self._ambient is self: @@ -1587,10 +1593,10 @@ def ambient_ordered_point_indices(self): EXAMPLES:: sage: cube = lattice_polytope.cross_polytope(3).polar() - sage: face = cube.facets()[0] # optional - sage.graphs - sage: face.ambient_ordered_point_indices() # optional - palp sage.graphs + sage: face = cube.facets()[0] # needs sage.graphs + sage: face.ambient_ordered_point_indices() # needs palp sage.graphs (5, 8, 4, 9, 10, 11, 6, 12, 7) - sage: cube.points(face.ambient_ordered_point_indices()) # optional - palp sage.graphs + sage: cube.points(face.ambient_ordered_point_indices()) # needs palp sage.graphs N(-1, -1, -1), N(-1, -1, 0), N(-1, -1, 1), @@ -1621,8 +1627,8 @@ def ambient_vertex_indices(self): sage: o = lattice_polytope.cross_polytope(3) sage: o.ambient_vertex_indices() (0, 1, 2, 3, 4, 5) - sage: face = o.faces(1)[0] # optional - sage.graphs - sage: face.ambient_vertex_indices() # optional - sage.graphs + sage: face = o.faces(1)[0] # needs sage.graphs + sage: face.ambient_vertex_indices() # needs sage.graphs (0, 1) """ return self._ambient_vertex_indices @@ -1641,7 +1647,7 @@ def boundary_point_indices(self): All points but the origin are on the boundary of this square:: sage: square = lattice_polytope.cross_polytope(2).polar() - sage: square.points() # optional - palp + sage: square.points() # needs palp N( 1, 1), N( 1, -1), N(-1, -1), @@ -1652,18 +1658,18 @@ def boundary_point_indices(self): N( 0, 1), N( 1, 0) in 2-d lattice N - sage: square.boundary_point_indices() # optional - palp + sage: square.boundary_point_indices() # needs palp (0, 1, 2, 3, 4, 5, 7, 8) For an edge the boundary is formed by the end points:: - sage: face = square.edges()[0] # optional - sage.graphs - sage: face.points() # optional - sage.graphs + sage: face = square.edges()[0] # needs sage.graphs + sage: face.points() # needs sage.graphs N(-1, -1), N(-1, 1), N(-1, 0) in 2-d lattice N - sage: face.boundary_point_indices() # optional - sage.graphs + sage: face.boundary_point_indices() # needs sage.graphs (0, 1) """ return tuple(i @@ -1683,7 +1689,7 @@ def boundary_points(self): All points but the origin are on the boundary of this square:: sage: square = lattice_polytope.cross_polytope(2).polar() - sage: square.boundary_points() # optional - palp + sage: square.boundary_points() # needs palp N( 1, 1), N( 1, -1), N(-1, -1), @@ -1696,8 +1702,8 @@ def boundary_points(self): For an edge the boundary is formed by the end points:: - sage: face = square.edges()[0] # optional - sage.graphs - sage: face.boundary_points() # optional - sage.graphs + sage: face = square.edges()[0] # needs sage.graphs + sage: face.boundary_points() # needs sage.graphs N(-1, -1), N(-1, 1) in 2-d lattice N @@ -1775,7 +1781,7 @@ def distances(self, point=None): EXAMPLES: The matrix of distances for a 3-dimensional octahedron:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.distances() # optional - palp + sage: o.distances() # needs palp [2 0 0 0 2 2 1] [2 2 0 0 0 2 1] [2 2 2 0 0 0 1] @@ -1794,7 +1800,7 @@ def distances(self, point=None): sage: o.distances([1,2,3/2]) (-3/2, 5/2, 11/2, 3/2, -1/2, -7/2, 1/2, 7/2) - sage: o.distances([1,2,sqrt(2)]) # optional - sage.symbolic + sage: o.distances([1,2,sqrt(2)]) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert sqrt(2) to an element of Rational Field @@ -1802,17 +1808,17 @@ def distances(self, point=None): Now we create a non-spanning polytope:: sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: p.distances() # optional - palp + sage: p.distances() # needs palp [2 2 0 0 1] [2 0 0 2 1] [0 0 2 2 1] [0 2 2 0 1] - sage: p.distances((1/2, 3, 0)) # optional - palp + sage: p.distances((1/2, 3, 0)) # needs palp (9/2, -3/2, -5/2, 7/2) This point is not even in the affine subspace of the polytope:: - sage: p.distances((1, 1, 1)) # optional - palp + sage: p.distances((1, 1, 1)) # needs palp (3, 1, -1, 1) """ if point is not None: @@ -1841,16 +1847,17 @@ def dual(self): EXAMPLES:: + sage: # needs sage.graphs sage: o = lattice_polytope.cross_polytope(4) - sage: e = o.edges()[0]; e # optional - sage.graphs + sage: e = o.edges()[0]; e 1-d face of 4-d reflexive polytope in 4-d lattice M - sage: ed = e.dual(); ed # optional - sage.graphs + sage: ed = e.dual(); ed 2-d face of 4-d reflexive polytope in 4-d lattice N - sage: ed.ambient() is e.ambient().polar() # optional - sage.graphs + sage: ed.ambient() is e.ambient().polar() True - sage: e.ambient_vertex_indices() == ed.ambient_facet_indices() # optional - sage.graphs + sage: e.ambient_vertex_indices() == ed.ambient_facet_indices() True - sage: e.ambient_facet_indices() == ed.ambient_vertex_indices() # optional - sage.graphs + sage: e.ambient_facet_indices() == ed.ambient_vertex_indices() True """ for f in self._ambient.polar().faces(codim=self.dim() + 1): @@ -1893,11 +1900,11 @@ def edges(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.edges() # optional - sage.graphs + sage: o.edges() # needs sage.graphs (1-d face of 3-d reflexive polytope in 3-d lattice M, ... 1-d face of 3-d reflexive polytope in 3-d lattice M) - sage: len(o.edges()) # optional - sage.graphs + sage: len(o.edges()) # needs sage.graphs 12 """ return self.faces(dim=1) @@ -1920,12 +1927,12 @@ def face_lattice(self): Let's take a look at the face lattice of a square:: sage: square = LatticePolytope([(0,0), (1,0), (1,1), (0,1)]) - sage: L = square.face_lattice(); L # optional - sage.graphs + sage: L = square.face_lattice(); L # needs sage.graphs Finite lattice containing 10 elements with distinguished linear extension To see all faces arranged by dimension, you can do this:: - sage: for level in L.level_sets(): print(level) # optional - sage.graphs + sage: for level in L.level_sets(): print(level) # needs sage.graphs [-1-d face of 2-d lattice polytope in 2-d lattice M] [0-d face of 2-d lattice polytope in 2-d lattice M, 0-d face of 2-d lattice polytope in 2-d lattice M, @@ -1939,31 +1946,31 @@ def face_lattice(self): For a particular face you can look at its actual vertices... :: - sage: face = L.level_sets()[1][0] # optional - sage.graphs - sage: face.vertices() # optional - sage.graphs + sage: face = L.level_sets()[1][0] # needs sage.graphs + sage: face.vertices() # needs sage.graphs M(0, 0) in 2-d lattice M ... or you can see the index of the vertex of the original polytope that corresponds to the above one:: - sage: face.ambient_vertex_indices() # optional - sage.graphs + sage: face.ambient_vertex_indices() # needs sage.graphs (0,) - sage: square.vertex(0) # optional - sage.graphs + sage: square.vertex(0) M(0, 0) An alternative to extracting faces from the face lattice is to use :meth:`faces` method:: - sage: face is square.faces(dim=0)[0] # optional - sage.graphs + sage: face is square.faces(dim=0)[0] # needs sage.graphs True The advantage of working with the face lattice directly is that you can (relatively easily) get faces that are related to the given one:: - sage: face = L.level_sets()[1][0] # optional - sage.graphs - sage: D = L.hasse_diagram() # optional - sage.graphs - sage: sorted(D.neighbors(face)) # optional - sage.graphs + sage: face = L.level_sets()[1][0] # needs sage.graphs + sage: D = L.hasse_diagram() # needs sage.graphs + sage: sorted(D.neighbors(face)) # needs sage.graphs [-1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M] @@ -1971,43 +1978,45 @@ def face_lattice(self): However, you can achieve some of this functionality using :meth:`facets`, :meth:`facet_of`, and :meth:`adjacent` methods:: - sage: face = square.faces(0)[0] # optional - sage.graphs - sage: face # optional - sage.graphs + sage: # needs sage.graphs + sage: face = square.faces(0)[0] + sage: face 0-d face of 2-d lattice polytope in 2-d lattice M - sage: face.vertices() # optional - sage.graphs + sage: face.vertices() M(0, 0) in 2-d lattice M - sage: face.facets() # optional - sage.graphs + sage: face.facets() (-1-d face of 2-d lattice polytope in 2-d lattice M,) - sage: face.facet_of() # optional - sage.graphs + sage: face.facet_of() (1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M) - sage: face.adjacent() # optional - sage.graphs + sage: face.adjacent() (0-d face of 2-d lattice polytope in 2-d lattice M, 0-d face of 2-d lattice polytope in 2-d lattice M) - sage: face.adjacent()[0].vertices() # optional - sage.graphs + sage: face.adjacent()[0].vertices() M(1, 0) in 2-d lattice M Note that if ``p`` is a face of ``superp``, then the face lattice of ``p`` consists of (appropriate) faces of ``superp``:: + sage: # needs sage.graphs sage: superp = LatticePolytope([(1,2,3,4), (5,6,7,8), ....: (1,2,4,8), (1,3,9,7)]) - sage: superp.face_lattice() # optional - sage.graphs + sage: superp.face_lattice() Finite lattice containing 16 elements with distinguished linear extension - sage: superp.face_lattice().top() # optional - sage.graphs + sage: superp.face_lattice().top() 3-d lattice polytope in 4-d lattice M - sage: p = superp.facets()[0] # optional - sage.graphs - sage: p # optional - sage.graphs + sage: p = superp.facets()[0] + sage: p 2-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice() # optional - sage.graphs + sage: p.face_lattice() Finite poset containing 8 elements with distinguished linear extension - sage: p.face_lattice().bottom() # optional - sage.graphs + sage: p.face_lattice().bottom() -1-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice().top() # optional - sage.graphs + sage: p.face_lattice().top() 2-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice().top() is p # optional - sage.graphs + sage: p.face_lattice().top() is p True """ if self._ambient is self: @@ -2097,7 +2106,7 @@ def faces(self, dim=None, codim=None): Let's take a look at the faces of a square:: sage: square = LatticePolytope([(0,0), (1,0), (1,1), (0,1)]) - sage: square.faces() # optional - sage.graphs + sage: square.faces() # needs sage.graphs ((-1-d face of 2-d lattice polytope in 2-d lattice M,), (0-d face of 2-d lattice polytope in 2-d lattice M, 0-d face of 2-d lattice polytope in 2-d lattice M, @@ -2111,7 +2120,7 @@ def faces(self, dim=None, codim=None): Its faces of dimension one (i.e., edges):: - sage: square.faces(dim=1) # optional - sage.graphs + sage: square.faces(dim=1) # needs sage.graphs (1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M, @@ -2119,16 +2128,16 @@ def faces(self, dim=None, codim=None): Its faces of codimension one are the same (also edges):: - sage: square.faces(codim=1) is square.faces(dim=1) # optional - sage.graphs + sage: square.faces(codim=1) is square.faces(dim=1) # needs sage.graphs True Let's pick a particular face:: - sage: face = square.faces(dim=1)[0] # optional - sage.graphs + sage: face = square.faces(dim=1)[0] # needs sage.graphs Now you can look at the actual vertices of this face... :: - sage: face.vertices() # optional - sage.graphs + sage: face.vertices() # needs sage.graphs M(0, 0), M(0, 1) in 2-d lattice M @@ -2136,9 +2145,9 @@ def faces(self, dim=None, codim=None): ... or you can see indices of the vertices of the original polytope that correspond to the above ones:: - sage: face.ambient_vertex_indices() # optional - sage.graphs + sage: face.ambient_vertex_indices() # needs sage.graphs (0, 3) - sage: square.vertices(face.ambient_vertex_indices()) # optional - sage.graphs + sage: square.vertices(face.ambient_vertex_indices()) # needs sage.graphs M(0, 0), M(0, 1) in 2-d lattice M @@ -2363,13 +2372,14 @@ def facet_of(self): EXAMPLES:: + sage: # needs sage.graphs sage: square = LatticePolytope([(0,0), (1,0), (1,1), (0,1)]) - sage: square.facet_of() # optional - sage.graphs + sage: square.facet_of() () - sage: face = square.faces(0)[0] # optional - sage.graphs - sage: len(face.facet_of()) # optional - sage.graphs + sage: face = square.faces(0)[0] + sage: len(face.facet_of()) 2 - sage: face.facet_of()[1] # optional - sage.graphs + sage: face.facet_of()[1] 1-d face of 2-d lattice polytope in 2-d lattice M """ L = self._ambient.face_lattice() @@ -2387,11 +2397,11 @@ def facets(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.facets() # optional - sage.graphs + sage: o.facets() # needs sage.graphs (2-d face of 3-d reflexive polytope in 3-d lattice M, ... 2-d face of 3-d reflexive polytope in 3-d lattice M) - sage: len(o.facets()) # optional - sage.graphs + sage: len(o.facets()) # needs sage.graphs 8 """ return self.faces(codim=1) @@ -2419,14 +2429,14 @@ def incidence_matrix(self): [0 1 1 0] [1 1 0 0] [1 0 0 1] - sage: o.faces(1)[0].incidence_matrix() # optional - sage.graphs + sage: o.faces(1)[0].incidence_matrix() # needs sage.graphs [1 0] [0 1] sage: o = lattice_polytope.cross_polytope(4) sage: o.incidence_matrix().column(3).nonzero_positions() [3, 4, 5, 6] - sage: o.facets()[3].ambient_vertex_indices() # optional - sage.graphs + sage: o.facets()[3].ambient_vertex_indices() # needs sage.graphs (3, 4, 5, 6) TESTS:: @@ -2470,7 +2480,7 @@ def index(self): database:: sage: d = lattice_polytope.cross_polytope(2) - sage: d.index() # optional - palp + sage: d.index() # needs palp 3 Note that polytopes with the same index are not necessarily the @@ -2492,7 +2502,7 @@ def index(self): But they are in the same `GL(Z^n)` orbit and have the same normal form:: - sage: d.normal_form() # optional - palp + sage: d.normal_form() # needs palp M( 1, 0), M( 0, 1), M( 0, -1), @@ -2531,7 +2541,7 @@ def interior_point_indices(self): The origin is the only interior point of this square:: sage: square = lattice_polytope.cross_polytope(2).polar() - sage: square.points() # optional - palp + sage: square.points() # needs palp N( 1, 1), N( 1, -1), N(-1, -1), @@ -2542,18 +2552,18 @@ def interior_point_indices(self): N( 0, 1), N( 1, 0) in 2-d lattice N - sage: square.interior_point_indices() # optional - palp + sage: square.interior_point_indices() # needs palp (6,) Its edges also have a single interior point each:: - sage: face = square.edges()[0] # optional - sage.graphs - sage: face.points() # optional - sage.graphs + sage: face = square.edges()[0] # needs sage.graphs + sage: face.points() # needs sage.graphs N(-1, -1), N(-1, 1), N(-1, 0) in 2-d lattice N - sage: face.interior_point_indices() # optional - sage.graphs + sage: face.interior_point_indices() # needs sage.graphs (2,) """ return tuple(i @@ -2573,14 +2583,14 @@ def interior_points(self): The origin is the only interior point of this square:: sage: square = lattice_polytope.cross_polytope(2).polar() - sage: square.interior_points() # optional - palp + sage: square.interior_points() # needs palp N(0, 0) in 2-d lattice N Its edges also have a single interior point each:: - sage: face = square.edges()[0] # optional - sage.graphs - sage: face.interior_points() # optional - sage.graphs + sage: face = square.edges()[0] # needs sage.graphs + sage: face.interior_points() # needs sage.graphs N(-1, 0) in 2-d lattice N """ @@ -2666,7 +2676,7 @@ def ambient_vector_space(self, base_field=None): sage: p = LatticePolytope([(1,0)]) sage: p.ambient_vector_space() Vector space of dimension 2 over Rational Field - sage: p.ambient_vector_space(AA) # optional - sage.rings.number_field + sage: p.ambient_vector_space(AA) # needs sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field """ return self.lattice().vector_space(base_field=base_field) @@ -2727,7 +2737,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, Nef-partitions of the 4-dimensional cross-polytope:: sage: p = lattice_polytope.cross_polytope(4) - sage: p.nef_partitions() # optional - palp + sage: p.nef_partitions() # needs palp [ Nef-partition {0, 1, 4, 5} ⊔ {2, 3, 6, 7} (direct product), Nef-partition {0, 1, 2, 4} ⊔ {3, 5, 6, 7}, @@ -2741,7 +2751,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, Now we omit projections:: - sage: p.nef_partitions(keep_projections=False) # optional - palp + sage: p.nef_partitions(keep_projections=False) # needs palp [ Nef-partition {0, 1, 4, 5} ⊔ {2, 3, 6, 7} (direct product), Nef-partition {0, 1, 2, 4} ⊔ {3, 5, 6, 7}, @@ -2754,7 +2764,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, Currently Hodge numbers cannot be computed for a given nef-partition:: - sage: p.nef_partitions()[1].hodge_numbers() # optional - palp + sage: p.nef_partitions()[1].hodge_numbers() # needs palp Traceback (most recent call last): ... NotImplementedError: use nef_partitions(hodge_numbers=True)! @@ -2762,7 +2772,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, But they can be obtained from ``nef.x`` for all nef-partitions at once. Partitions will be exactly the same:: - sage: p.nef_partitions(hodge_numbers=True) # long time (2s on sage.math, 2011) # optional - palp + sage: p.nef_partitions(hodge_numbers=True) # long time (2s on sage.math, 2011), needs palp [ Nef-partition {0, 1, 4, 5} ⊔ {2, 3, 6, 7} (direct product), Nef-partition {0, 1, 2, 4} ⊔ {3, 5, 6, 7}, @@ -2776,26 +2786,26 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, Now it is possible to get Hodge numbers:: - sage: p.nef_partitions(hodge_numbers=True)[1].hodge_numbers() # optional - palp + sage: p.nef_partitions(hodge_numbers=True)[1].hodge_numbers() # needs palp (20,) Since nef-partitions are cached, their Hodge numbers are accessible after the first request, even if you do not specify ``hodge_numbers=True`` anymore:: - sage: p.nef_partitions()[1].hodge_numbers() # optional - palp + sage: p.nef_partitions()[1].hodge_numbers() # needs palp (20,) We illustrate removal of symmetric partitions on a diamond:: sage: p = lattice_polytope.cross_polytope(2) - sage: p.nef_partitions() # optional - palp + sage: p.nef_partitions() # needs palp [ Nef-partition {0, 2} ⊔ {1, 3} (direct product), Nef-partition {0, 1} ⊔ {2, 3}, Nef-partition {0, 1, 2} ⊔ {3} (projection) ] - sage: p.nef_partitions(keep_symmetric=True) # optional - palp + sage: p.nef_partitions(keep_symmetric=True) # needs palp [ Nef-partition {0, 1, 3} ⊔ {2} (projection), Nef-partition {0, 2, 3} ⊔ {1} (projection), @@ -2810,7 +2820,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, sage: p = LatticePolytope([(1,0,0), (0,1,0), (0,0,2), ....: (-1,0,0), (0,-1,0), (0,0,-1)]) - sage: p.nef_partitions() # optional - palp + sage: p.nef_partitions() # needs palp Traceback (most recent call last): ... ValueError: The given polytope is not reflexive! @@ -2864,8 +2874,8 @@ def nef_x(self, keys): nef-partitions:: sage: o = lattice_polytope.cross_polytope(3) - sage: s = o.nef_x("-N -V -p") # optional - palp - sage: s # output contains random time # optional - palp + sage: s = o.nef_x("-N -V -p") # needs palp + sage: s # output contains random time # needs palp M:27 8 N:7 6 codim=2 #part=5 3 6 Vertices of P: 1 0 0 -1 0 0 @@ -2952,7 +2962,7 @@ def normal_form(self, algorithm="palp", permutation=False): M(-1, 0), M( 0, -1) in 2-d lattice M - sage: d.normal_form() # optional - palp + sage: d.normal_form() # needs palp M( 1, 0), M( 0, 1), M( 0, -1), @@ -2961,9 +2971,9 @@ def normal_form(self, algorithm="palp", permutation=False): The diamond is the 3rd polytope in the internal database:: - sage: d.index() # optional - palp + sage: d.index() # needs palp 3 - sage: d # optional - palp + sage: d # needs palp 2-d reflexive polytope #3 in 2-d lattice M You can get it in its normal form (in the default lattice) as :: @@ -2988,7 +2998,7 @@ def normal_form(self, algorithm="palp", permutation=False): We can perform the same examples using other algorithms:: sage: o = lattice_polytope.cross_polytope(2) - sage: o.normal_form(algorithm="palp_native") + sage: o.normal_form(algorithm="palp_native") # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), @@ -2996,7 +3006,7 @@ def normal_form(self, algorithm="palp", permutation=False): in 2-d lattice M sage: o = lattice_polytope.cross_polytope(2) - sage: o.normal_form(algorithm="palp_modified") + sage: o.normal_form(algorithm="palp_modified") # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), @@ -3054,13 +3064,13 @@ def _palp_modified_normal_form(self, permutation=False): M(-1, 0), M( 0, -1) in 2-d lattice M - sage: o._palp_modified_normal_form() # optional - sage.graphs + sage: o._palp_modified_normal_form() # needs sage.graphs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), M(-1, 0) in 2-d lattice M - sage: o._palp_modified_normal_form(permutation=True) # optional - sage.graphs + sage: o._palp_modified_normal_form(permutation=True) # needs sage.graphs sage.groups (M( 1, 0), M( 0, 1), M( 0, -1), @@ -3107,13 +3117,13 @@ def _palp_native_normal_form(self, permutation=False): M(-1, 0), M( 0, -1) in 2-d lattice M - sage: o._palp_native_normal_form() # optional - sage.groups + sage: o._palp_native_normal_form() # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), M(-1, 0) in 2-d lattice M - sage: o._palp_native_normal_form(permutation=True) # optional - sage.groups + sage: o._palp_native_normal_form(permutation=True) # needs sage.groups (M( 1, 0), M( 0, 1), M( 0, -1), @@ -3158,23 +3168,23 @@ def _palp_PM_max(self, check=False): sage: o = lattice_polytope.cross_polytope(2) sage: PM = o.vertex_facet_pairing_matrix() - sage: PM_max = PM.permutation_normal_form() # optional - sage.graphs - sage: PM_max == o._palp_PM_max() # optional - sage.graphs + sage: PM_max = PM.permutation_normal_form() # needs sage.graphs + sage: PM_max == o._palp_PM_max() # needs sage.graphs sage.groups True sage: P2 = ReflexivePolytope(2, 0) - sage: PM_max, permutations = P2._palp_PM_max(check=True) - sage: PM_max + sage: PM_max, permutations = P2._palp_PM_max(check=True) # needs sage.groups + sage: PM_max # needs sage.graphs [3 0 0] [0 3 0] [0 0 3] - sage: list(permutations.values()) + sage: list(permutations.values()) # needs sage.groups [[(1,2,3), (1,2,3)], [(1,3,2), (1,3,2)], [(1,3), (1,3)], [(1,2), (1,2)], [(), ()], [(2,3), (2,3)]] - sage: PM_max.automorphisms_of_rows_and_columns() + sage: PM_max.automorphisms_of_rows_and_columns() # needs sage.graphs [((), ()), ((1,2,3), (1,2,3)), ((1,3,2), (1,3,2)), @@ -3396,10 +3406,10 @@ def npoints(self): octahedron and its polar cube:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.npoints() # optional - palp + sage: o.npoints() # needs palp 7 sage: cube = o.polar() - sage: cube.npoints() # optional - palp + sage: cube.npoints() # needs palp 27 """ try: @@ -3435,9 +3445,9 @@ def origin(self): EXAMPLES:: sage: p = lattice_polytope.cross_polytope(2) - sage: p.origin() # optional - palp + sage: p.origin() # needs palp 4 - sage: p.point(p.origin()) # optional - palp + sage: p.point(p.origin()) # needs palp M(0, 0) sage: p = LatticePolytope(([1],[2])) @@ -3550,30 +3560,30 @@ def plot3d(self, EXAMPLES: The default plot of a cube:: sage: c = lattice_polytope.cross_polytope(3).polar() - sage: c.plot3d() # optional - palp sage.plot + sage: c.plot3d() # needs palp sage.plot Graphics3d Object Plot without facets and points, shown without the frame:: - sage: c.plot3d(show_facets=false, # optional - palp sage.plot + sage: c.plot3d(show_facets=false, # needs palp sage.plot ....: show_points=false).show(frame=False) Plot with facets of different colors:: - sage: c.plot3d(facet_colors=rainbow(c.nfacets(), 'rgbtuple')) # optional - palp sage.plot + sage: c.plot3d(facet_colors=rainbow(c.nfacets(), 'rgbtuple')) # needs palp sage.plot Graphics3d Object It is also possible to plot lower dimensional polytops in 3D (let's also change labels of vertices):: sage: c2 = lattice_polytope.cross_polytope(2) - sage: c2.plot3d(vlabels=["A", "B", "C", "D"]) # optional - palp sage.plot + sage: c2.plot3d(vlabels=["A", "B", "C", "D"]) # needs palp sage.plot Graphics3d Object TESTS:: sage: p = LatticePolytope([[0,0,0],[0,1,1],[1,0,1],[1,1,0]]) - sage: p.plot3d() # optional - palp sage.plot + sage: p.plot3d() # needs palp sage.plot Graphics3d Object """ dim = self.dim() @@ -3664,7 +3674,7 @@ def show3d(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.show3d() # optional - palp sage.plot + sage: o.show3d() # needs palp sage.plot """ self.plot3d().show(axis=False, frame=False) @@ -3684,14 +3694,14 @@ def point(self, i): M( 0, -1, 0), M( 0, 0, -1) in 3-d lattice M - sage: o.point(1) # optional - palp + sage: o.point(1) # needs palp M(0, 1, 0) The only other point in the octahedron is the origin:: - sage: o.point(6) # optional - palp + sage: o.point(6) # needs palp M(0, 0, 0) - sage: o.points() # optional - palp + sage: o.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M( 0, 0, 1), @@ -3720,7 +3730,7 @@ def points(self, *args, **kwds): Lattice points of the octahedron and its polar cube:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.points() # optional - palp + sage: o.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M( 0, 0, 1), @@ -3730,7 +3740,7 @@ def points(self, *args, **kwds): M( 0, 0, 0) in 3-d lattice M sage: cube = o.polar() - sage: cube.points() # optional - palp + sage: cube.points() # needs palp N( 1, -1, -1), N( 1, 1, -1), N( 1, 1, 1), @@ -3763,7 +3773,7 @@ def points(self, *args, **kwds): Lattice points of a 2-dimensional diamond in a 3-dimensional space:: sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: p.points() # optional - palp + sage: p.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M(-1, 0, 0), @@ -3773,7 +3783,7 @@ def points(self, *args, **kwds): Only two of the above points:: - sage: p.points(1, 3) # optional - palp + sage: p.points(1, 3) # needs palp M(0, 1, 0), M(0, -1, 0) in 3-d lattice M @@ -3904,7 +3914,7 @@ def poly_x(self, keys, reduce_dimension=False): reflexive or not:: sage: o = lattice_polytope.cross_polytope(3) - sage: print(o.poly_x("e")) # optional - palp + sage: print(o.poly_x("e")) # needs palp 8 3 Vertices of P-dual <-> Equations of P -1 -1 1 1 -1 1 @@ -3922,7 +3932,7 @@ def poly_x(self, keys, reduce_dimension=False): sage: BIG = lattice_polytope.cross_polytope(7) sage: BIG 7-d reflexive polytope in 7-d lattice M - sage: BIG.poly_x("e") # optional - palp + sage: BIG.poly_x("e") # needs palp Traceback (most recent call last): ... ValueError: Error executing 'poly.x -fe' for the given polytope! @@ -3933,7 +3943,7 @@ def poly_x(self, keys, reduce_dimension=False): could, it would crush anyway):: sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: p.poly_x("e") # optional - palp + sage: p.poly_x("e") # needs palp Traceback (most recent call last): ... ValueError: Cannot run PALP for a 2-dimensional polytope in a 3-dimensional space! @@ -3941,7 +3951,7 @@ def poly_x(self, keys, reduce_dimension=False): But if you know what you are doing, you can call it for the polytope in some basis of the spanned space:: - sage: print(p.poly_x("e", reduce_dimension=True)) # optional - palp + sage: print(p.poly_x("e", reduce_dimension=True)) # needs palp 4 2 Equations of P -1 1 0 1 1 2 @@ -3958,9 +3968,9 @@ def skeleton(self): EXAMPLES:: sage: d = lattice_polytope.cross_polytope(2) - sage: g = d.skeleton(); g # optional - palp sage.graphs + sage: g = d.skeleton(); g # needs palp sage.graphs Graph on 4 vertices - sage: g.edges(sort=True) # optional - palp sage.graphs + sage: g.edges(sort=True) # needs palp sage.graphs [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)] """ skeleton = Graph() @@ -3980,35 +3990,35 @@ def skeleton_points(self, k=1): sage: o = lattice_polytope.cross_polytope(3) sage: c = o.polar() - sage: c.skeleton_points() # optional - palp sage.graphs + sage: c.skeleton_points() # needs palp sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 19, 21, 22, 23, 25, 26] The default was 1-skeleton:: - sage: c.skeleton_points(k=1) # optional - palp sage.graphs + sage: c.skeleton_points(k=1) # needs palp sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 19, 21, 22, 23, 25, 26] 0-skeleton just lists all vertices:: - sage: c.skeleton_points(k=0) # optional - palp sage.graphs + sage: c.skeleton_points(k=0) # needs palp sage.graphs [0, 1, 2, 3, 4, 5, 6, 7] 2-skeleton lists all points except for the origin (point #17):: - sage: c.skeleton_points(k=2) # optional - palp sage.graphs + sage: c.skeleton_points(k=2) # needs palp sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26] 3-skeleton includes all points:: - sage: c.skeleton_points(k=3) # optional - palp sage.graphs + sage: c.skeleton_points(k=3) # needs palp [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] It is OK to compute higher dimensional skeletons - you will get the list of all points:: - sage: c.skeleton_points(k=100) # optional - palp sage.graphs + sage: c.skeleton_points(k=100) # needs palp [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] """ @@ -4036,7 +4046,7 @@ def skeleton_show(self, normal=None): EXAMPLES: Show a pretty picture of the octahedron:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.skeleton_show([1,2,4]) # optional - palp sage.plot + sage: o.skeleton_show([1,2,4]) # needs palp sage.plot Does not work for a diamond at the moment:: @@ -4064,7 +4074,7 @@ def traverse_boundary(self): EXAMPLES:: sage: p = lattice_polytope.cross_polytope(2).polar() - sage: p.traverse_boundary() # optional - sage.graphs + sage: p.traverse_boundary() # needs sage.graphs [3, 0, 1, 2] """ if self.dim() != 2: @@ -4193,9 +4203,9 @@ def is_NefPartition(x): sage: is_NefPartition(1) False sage: o = lattice_polytope.cross_polytope(3) - sage: np = o.nef_partitions()[0]; np # optional - palp + sage: np = o.nef_partitions()[0]; np # needs palp Nef-partition {0, 1, 3} ⊔ {2, 4, 5} - sage: is_NefPartition(np) # optional - palp + sage: is_NefPartition(np) # needs palp True """ return isinstance(x, NefPartition) @@ -4333,7 +4343,7 @@ class NefPartition(SageObject, Hashable): nef-partitions of a given reflexive polytope (they will be computed using ``nef.x`` program from PALP):: - sage: o.nef_partitions() # optional - palp + sage: o.nef_partitions() # needs palp [ Nef-partition {0, 1, 3} ⊔ {2, 4, 5}, Nef-partition {0, 1, 3, 4} ⊔ {2, 5} (direct product), @@ -4350,8 +4360,8 @@ def __init__(self, data, Delta_polar, check=True): TESTS:: sage: o = lattice_polytope.cross_polytope(3) - sage: np = o.nef_partitions()[0] # optional - palp - sage: TestSuite(np).run() # optional - palp + sage: np = o.nef_partitions()[0] # needs palp + sage: TestSuite(np).run() # needs palp """ if check and not Delta_polar.is_reflexive(): raise ValueError("nef-partitions can be constructed for reflexive " @@ -4386,9 +4396,9 @@ def __eq__(self, other): sage: np = NefPartition([0, 0, 1, 0, 1, 1], o) sage: np == np True - sage: np == o.nef_partitions()[0] # optional - palp + sage: np == o.nef_partitions()[0] # needs palp True - sage: np == o.nef_partitions()[1] # optional - palp + sage: np == o.nef_partitions()[1] # needs palp False sage: np2 = NefPartition(np._vertex_to_part, o) sage: np2 is np @@ -4447,9 +4457,9 @@ def __ne__(self, other): sage: np = NefPartition([0, 0, 1, 0, 1, 1], o) sage: np != np False - sage: np != o.nef_partitions()[0] # optional - palp + sage: np != o.nef_partitions()[0] # needs palp False - sage: np != o.nef_partitions()[1] # optional - palp + sage: np != o.nef_partitions()[1] # needs palp True sage: np2 = NefPartition(np._vertex_to_part, o) sage: np2 is np @@ -4729,14 +4739,15 @@ def hodge_numbers(self): Currently, you need to request Hodge numbers when you compute nef-partitions:: + sage: # long time, needs palp sage: p = lattice_polytope.cross_polytope(5) - sage: np = p.nef_partitions()[0] # long time (4s on sage.math, 2011) # optional - palp - sage: np.hodge_numbers() # long time # optional - palp + sage: np = p.nef_partitions()[0] # 4s on sage.math, 2011 + sage: np.hodge_numbers() Traceback (most recent call last): ... NotImplementedError: use nef_partitions(hodge_numbers=True)! - sage: np = p.nef_partitions(hodge_numbers=True)[0] # long time (13s on sage.math, 2011) # optional - palp - sage: np.hodge_numbers() # long time # optional - palp + sage: np = p.nef_partitions(hodge_numbers=True)[0] # 13s on sage.math, 2011 + sage: np.hodge_numbers() (19, 19) """ try: @@ -4914,11 +4925,11 @@ def part(self, i, all_points=False): Nef-partition {0, 1, 3} ⊔ {2, 4, 5} sage: np.part(0) (0, 1, 3) - sage: np.part(0, all_points=True) # optional - palp + sage: np.part(0, all_points=True) # needs palp (0, 1, 3) sage: np.dual().part(0) (0, 1, 2, 3) - sage: np.dual().part(0, all_points=True) # optional - palp + sage: np.dual().part(0, all_points=True) # needs palp (0, 1, 2, 3, 8) """ return self.parts(all_points)[i] @@ -4948,11 +4959,11 @@ def parts(self, all_points=False): Nef-partition {0, 1, 3} ⊔ {2, 4, 5} sage: np.parts() ((0, 1, 3), (2, 4, 5)) - sage: np.parts(all_points=True) # optional - palp + sage: np.parts(all_points=True) # needs palp ((0, 1, 3), (2, 4, 5)) sage: np.dual().parts() ((0, 1, 2, 3), (4, 5, 6, 7)) - sage: np.dual().parts(all_points=True) # optional - palp + sage: np.dual().parts(all_points=True) # needs palp ((0, 1, 2, 3, 8), (4, 5, 6, 7, 10)) """ parts = [[] for _ in range(self._nparts)] @@ -5026,29 +5037,29 @@ def part_of_point(self, i): sage: p = LatticePolytope([(1,0,0), (0,1,0), (0,0,1), (0,1,-1), ....: (0,-1,1), (-1,1,0), (0,-1,-1), (-1,-1,0), (-1,-1,2)]) - sage: np = p.nef_partitions()[0]; np # optional - palp + sage: np = p.nef_partitions()[0]; np # needs palp Nef-partition {1, 2, 5, 7, 8} ⊔ {0, 3, 4, 6} sage: p.nvertices() 9 - sage: p.npoints() # optional - palp + sage: p.npoints() # needs palp 15 We see that the polytope has 6 more points in addition to vertices. One of them is the origin:: - sage: p.origin() # optional - palp + sage: p.origin() # needs palp 14 - sage: np.part_of_point(14) # optional - palp + sage: np.part_of_point(14) # needs palp Traceback (most recent call last): ... ValueError: the origin belongs to all parts! But the remaining 5 are partitioned by ``np``:: - sage: [n for n in range(p.npoints()) # optional - palp + sage: [n for n in range(p.npoints()) # needs palp ....: if p.origin() != n and np.part_of_point(n) == 0] [1, 2, 5, 7, 8, 9, 11, 13] - sage: [n for n in range(p.npoints()) # optional - palp + sage: [n for n in range(p.npoints()) # needs palp ....: if p.origin() != n and np.part_of_point(n) == 1] [0, 3, 4, 6, 10, 12] """ @@ -5081,27 +5092,29 @@ def _palp(command, polytopes, reduce_dimension=False): TESTS:: + sage: # needs palp sage: o = lattice_polytope.cross_polytope(3) - sage: result_name = lattice_polytope._palp("poly.x -f", [o]) # optional - palp - sage: f = open(result_name) # optional - palp - sage: f.readlines() # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -f", [o]) + sage: f = open(result_name) + sage: f.readlines() ['M:7 6 N:27 8 Pic:17 Cor:0\n'] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() + sage: os.remove(result_name) sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: lattice_polytope._palp("poly.x -f", [p]) # optional - palp + sage: lattice_polytope._palp("poly.x -f", [p]) # needs palp Traceback (most recent call last): ... ValueError: Cannot run PALP for a 2-dimensional polytope in a 3-dimensional space! - sage: result_name = lattice_polytope._palp("poly.x -f", [p], # optional - palp + sage: # needs palp + sage: result_name = lattice_polytope._palp("poly.x -f", [p], ....: reduce_dimension=True) - sage: f = open(result_name) # optional - palp - sage: f.readlines() # optional - palp + sage: f = open(result_name) + sage: f.readlines() ['M:5 4 F:4\n'] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() + sage: os.remove(result_name) """ if _palp_dimension is not None: dot = command.find(".") @@ -5172,9 +5185,9 @@ def _palp_canonical_order(V, PM_max, permutations): sage: L = lattice_polytope.cross_polytope(2) sage: V = L.vertices() - sage: PM_max, permutations = L._palp_PM_max(check=True) # optional - sage.groups + sage: PM_max, permutations = L._palp_PM_max(check=True) # needs sage.groups sage: from sage.geometry.lattice_polytope import _palp_canonical_order - sage: _palp_canonical_order(V, PM_max, permutations) # optional - sage.groups + sage: _palp_canonical_order(V, PM_max, permutations) # needs sage.groups (M( 1, 0), M( 0, 1), M( 0, -1), @@ -5228,9 +5241,9 @@ def _palp_convert_permutation(permutation): EXAMPLES:: sage: from sage.geometry.lattice_polytope import _palp_convert_permutation - sage: _palp_convert_permutation('1023') # optional - sage.groups + sage: _palp_convert_permutation('1023') # needs sage.groups (1,2) - sage: _palp_convert_permutation('0123456789bac') # optional - sage.groups + sage: _palp_convert_permutation('0123456789bac') # needs sage.groups (11,12) """ def from_palp_index(i): @@ -5271,14 +5284,14 @@ def _read_nef_x_partitions(data): TESTS:: sage: o = lattice_polytope.cross_polytope(3) - sage: s = o.nef_x("-N -p") # optional - palp - sage: print(s) # random # optional - palp + sage: s = o.nef_x("-N -p") # needs palp + sage: print(s) # random # needs palp M:27 8 N:7 6 codim=2 #part=5 P:0 V:2 4 5 0sec 0cpu P:2 V:3 4 5 0sec 0cpu P:3 V:4 5 0sec 0cpu np=3 d:1 p:1 0sec 0cpu - sage: lattice_polytope._read_nef_x_partitions(s) # optional - palp + sage: lattice_polytope._read_nef_x_partitions(s) # needs palp [[2, 4, 5], [3, 4, 5], [4, 5]] """ if isinstance(data, str): @@ -5333,9 +5346,10 @@ def _read_poly_x_incidences(data, dim): TESTS:: + sage: # needs palp sage: p = lattice_polytope.cross_polytope(2) - sage: result_name = lattice_polytope._palp("poly.x -fi", [p]) # optional - palp - sage: with open(result_name) as f: # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -fi", [p]) + sage: with open(result_name) as f: ....: print(f.read()) Incidences as binary numbers [F-vector=(4 4)]: v[d][i]: sum_j Incidence(i'th dim-d-face, j-th vertex) x 2^j @@ -5344,12 +5358,12 @@ def _read_poly_x_incidences(data, dim): f[d][i]: sum_j Incidence(i'th dim-d-face, j-th facet) x 2^j f[0]: 0011 0101 1010 1100 f[1]: 0001 0010 0100 1000 - sage: f = open(result_name) # optional - palp - sage: l = f.readline() # optional - palp - sage: lattice_polytope._read_poly_x_incidences(f, 2) # optional - palp + sage: f = open(result_name) + sage: l = f.readline() + sage: lattice_polytope._read_poly_x_incidences(f, 2) [[[3], [0], [2], [1]], [[0, 3], [2, 3], [0, 1], [1, 2]]] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() + sage: os.remove(result_name) """ data.readline() lines = [data.readline().split() for i in range(dim)] @@ -5387,7 +5401,7 @@ def all_cached_data(polytopes): sequences as well:: sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.all_cached_data([o]) # optional - palp + sage: lattice_polytope.all_cached_data([o]) # needs palp """ all_polars(polytopes) all_points(polytopes) @@ -5418,8 +5432,8 @@ def all_nef_partitions(polytopes, keep_symmetric=False): sequences as well:: sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.all_nef_partitions([o]) # optional - palp - sage: o.nef_partitions() # optional - palp + sage: lattice_polytope.all_nef_partitions([o]) # needs palp + sage: o.nef_partitions() # needs palp [ Nef-partition {0, 1, 3} ⊔ {2, 4, 5}, Nef-partition {0, 1, 3, 4} ⊔ {2, 5} (direct product), @@ -5432,7 +5446,7 @@ def all_nef_partitions(polytopes, keep_symmetric=False): sage: p = LatticePolytope([(1,0,0), (0,1,0), (0,0,2), ....: (-1,0,0), (0,-1,0), (0,0,-1)]) - sage: lattice_polytope.all_nef_partitions([o, p]) # optional - palp + sage: lattice_polytope.all_nef_partitions([o, p]) # needs palp Traceback (most recent call last): ... ValueError: nef-partitions can be computed for reflexive polytopes only @@ -5467,8 +5481,8 @@ def all_points(polytopes): sequences as well:: sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.all_points([o]) # optional - palp - sage: o.points() # optional - palp + sage: lattice_polytope.all_points([o]) # needs palp + sage: o.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M( 0, 0, 1), @@ -5520,8 +5534,8 @@ def all_polars(polytopes): sequences as well:: sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.all_polars([o]) # optional - palp - sage: o.polar() # optional - palp + sage: lattice_polytope.all_polars([o]) # needs palp + sage: o.polar() # needs palp 3-d reflexive polytope in 3-d lattice N """ result_name = _palp("poly.x -fe", polytopes) @@ -5663,7 +5677,7 @@ def positive_integer_relations(points): sage: p = LatticePolytope([(1,0,0), (0,1,0), ....: (-1,-1,0), (0,0,1), (-1,0,-1)]) - sage: p.points() # optional - palp + sage: p.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M(-1, -1, 0), @@ -5675,7 +5689,7 @@ def positive_integer_relations(points): We can compute linear relations between its points in the following way:: - sage: p.points().matrix().kernel().echelonized_basis_matrix() # optional - palp + sage: p.points().matrix().kernel().echelonized_basis_matrix() # needs palp [ 1 0 0 1 1 0] [ 0 1 1 -1 -1 0] [ 0 0 0 0 0 1] @@ -5685,7 +5699,7 @@ def positive_integer_relations(points): coefficients are non-negative integers:: sage: points = p.points().column_matrix() - sage: lattice_polytope.positive_integer_relations(points) # optional - palp + sage: lattice_polytope.positive_integer_relations(points) # needs palp [1 0 0 1 1 0] [1 1 1 0 0 0] [0 0 0 0 0 1] @@ -5751,10 +5765,11 @@ def read_all_polytopes(file_name): We use poly.x to compute two polar polytopes and read them:: + sage: # needs palp sage: d = lattice_polytope.cross_polytope(2) sage: o = lattice_polytope.cross_polytope(3) - sage: result_name = lattice_polytope._palp("poly.x -fe", [d, o]) # optional - palp - sage: with open(result_name) as f: # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -fe", [d, o]) + sage: with open(result_name) as f: ....: print(f.read()) 4 2 Vertices of P-dual <-> Equations of P -1 1 @@ -5770,10 +5785,10 @@ def read_all_polytopes(file_name): 1 -1 -1 -1 1 -1 1 1 -1 - sage: lattice_polytope.read_all_polytopes(result_name) # optional - palp + sage: lattice_polytope.read_all_polytopes(result_name) [2-d reflexive polytope #14 in 2-d lattice M, 3-d reflexive polytope in 3-d lattice M] - sage: os.remove(result_name) # optional - palp + sage: os.remove(result_name) """ polytopes = [] with open(file_name) as f: @@ -5873,7 +5888,7 @@ def set_palp_dimension(d): Let's try to work with a 7-dimensional polytope:: sage: p = lattice_polytope.cross_polytope(7) - sage: p._palp("poly.x -fv") # optional - palp + sage: p._palp("poly.x -fv") # needs palp Traceback (most recent call last): ... ValueError: Error executing 'poly.x -fv' for the given polytope! @@ -5883,7 +5898,7 @@ def set_palp_dimension(d): However, we can work with this polytope by changing PALP dimension to 11:: sage: lattice_polytope.set_palp_dimension(11) - sage: p._palp("poly.x -fv") # optional - palp + sage: p._palp("poly.x -fv") # needs palp '7 14 Vertices of P...' Let's go back to default settings:: @@ -5914,10 +5929,11 @@ def skip_palp_matrix(data, n=1): EXAMPLES: We create a file with vertices of the square and the cube, but read only the second set:: + sage: # needs palp sage: d = lattice_polytope.cross_polytope(2) sage: o = lattice_polytope.cross_polytope(3) - sage: result_name = lattice_polytope._palp("poly.x -fe", [d, o]) # optional - palp - sage: with open(result_name) as f: # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -fe", [d, o]) + sage: with open(result_name) as f: ....: print(f.read()) 4 2 Vertices of P-dual <-> Equations of P -1 1 @@ -5933,14 +5949,14 @@ def skip_palp_matrix(data, n=1): 1 -1 -1 -1 1 -1 1 1 -1 - sage: f = open(result_name) # optional - palp - sage: lattice_polytope.skip_palp_matrix(f) # optional - palp - sage: lattice_polytope.read_palp_matrix(f) # optional - palp + sage: f = open(result_name) + sage: lattice_polytope.skip_palp_matrix(f) + sage: lattice_polytope.read_palp_matrix(f) [-1 1 -1 1 -1 1 -1 1] [-1 -1 1 1 -1 -1 1 1] [ 1 1 1 1 -1 -1 -1 -1] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() + sage: os.remove(result_name) """ for i in range(n): line = data.readline() diff --git a/src/sage/geometry/linear_expression.py b/src/sage/geometry/linear_expression.py index b62e17193a3..0bc15952746 100644 --- a/src/sage/geometry/linear_expression.py +++ b/src/sage/geometry/linear_expression.py @@ -440,7 +440,7 @@ def evaluate(self, point): 9 sage: ex([1,1]) # syntactic sugar 9 - sage: ex([pi, e]) # optional - sage.symbolic + sage: ex([pi, e]) # needs sage.symbolic 2*pi + 3*e + 4 """ try: diff --git a/src/sage/geometry/newton_polygon.py b/src/sage/geometry/newton_polygon.py index 7eae994c6e3..28101e70646 100644 --- a/src/sage/geometry/newton_polygon.py +++ b/src/sage/geometry/newton_polygon.py @@ -464,7 +464,7 @@ def plot(self, **kwargs): sage: from sage.geometry.newton_polygon import NewtonPolygon sage: NP = NewtonPolygon([ (0,0), (1,1), (2,6) ]) - sage: polygon = NP.plot() # optional - sage.plot + sage: polygon = NP.plot() # needs sage.plot """ vertices = self.vertices() if len(vertices) == 0: diff --git a/src/sage/geometry/polyhedral_complex.py b/src/sage/geometry/polyhedral_complex.py index bec18228aca..2e20e508057 100644 --- a/src/sage/geometry/polyhedral_complex.py +++ b/src/sage/geometry/polyhedral_complex.py @@ -203,7 +203,7 @@ class PolyhedralComplex(GenericCellComplex): (A vertex at (0, 1/4),), (A vertex at (1/7, 2/7),), (A vertex at (1/3, 1/3),)] - sage: pc.plot() # optional - sage.plot + sage: pc.plot() # needs sage.plot Graphics object consisting of 10 graphics primitives sage: pc.is_pure() True @@ -752,17 +752,17 @@ def plot(self, **kwds): sage: p3 = Polyhedron(vertices=[(0, 0), (0, 2), (-1, 1)]) sage: pc1 = PolyhedralComplex([p1, p2, p3, -p1, -p2, -p3]) sage: bb = dict(xmin=-2, xmax=2, ymin=-3, ymax=3, axes=False) - sage: g0 = pc1.plot(color='rainbow', **bb) # optional - sage.plot - sage: g1 = pc1.plot(explosion_factor=0.5, **bb) # optional - sage.plot - sage: g2 = pc1.plot(explosion_factor=1, color='rainbow', alpha=0.5, **bb) # optional - sage.plot + sage: g0 = pc1.plot(color='rainbow', **bb) # needs sage.plot + sage: g1 = pc1.plot(explosion_factor=0.5, **bb) # needs sage.plot + sage: g2 = pc1.plot(explosion_factor=1, color='rainbow', alpha=0.5, **bb) # needs sage.plot sage: graphics_array([g0, g1, g2]).show(axes=False) # not tested sage: pc2 = PolyhedralComplex([polytopes.hypercube(3)]) sage: pc3 = pc2.subdivide(new_vertices=[(0, 0, 0)]) - sage: g3 = pc3.plot(explosion_factor=1, color='rainbow', # optional - sage.plot + sage: g3 = pc3.plot(explosion_factor=1, color='rainbow', # needs sage.plot ....: alpha=0.5, axes=False, online=True) sage: pc4 = pc2.subdivide(make_simplicial=True) - sage: g4 = pc4.plot(explosion_factor=1, center=(1, -1, 1), fill='blue', # optional - sage.plot + sage: g4 = pc4.plot(explosion_factor=1, center=(1, -1, 1), fill='blue', # needs sage.plot ....: wireframe='white', point={'color':'red', 'size':10}, ....: alpha=0.6, online=True) sage: pc5 = PolyhedralComplex([ @@ -773,7 +773,7 @@ def plot(self, **kwds): ....: Polyhedron(rays=[[-1,0,0], [0,-1,0], [0,0,1]]), ....: Polyhedron(rays=[[-1,0,0], [0,1,0], [0,0,-1]]), ....: Polyhedron(rays=[[-1,0,0], [0,1,0], [0,0,1]])]) - sage: g5 = pc5.plot(explosion_factor=0.3, color='rainbow', alpha=0.8, # optional - sage.plot + sage: g5 = pc5.plot(explosion_factor=0.3, color='rainbow', alpha=0.8, # needs sage.plot ....: point={'size': 20}, axes=False, online=True) """ @@ -1001,7 +1001,7 @@ def face_poset(self): sage: poset Finite poset containing 11 elements sage: d = {i: i.vertices_matrix() for i in poset} - sage: poset.plot(element_labels=d) # optional - sage.plot + sage: poset.plot(element_labels=d) # needs sage.plot Graphics object consisting of 28 graphics primitives For a nonbounded polyhedral complex:: @@ -2532,11 +2532,11 @@ def exploded_plot(polyhedra, *, sage: p1 = Polyhedron(vertices=[(1, 1), (0, 0), (1, 2)]) sage: p2 = Polyhedron(vertices=[(1, 2), (0, 0), (0, 2)]) sage: p3 = Polyhedron(vertices=[(0, 0), (1, 1), (2, 0)]) - sage: exploded_plot([p1, p2, p3]) # optional - sage.plot + sage: exploded_plot([p1, p2, p3]) # needs sage.plot Graphics object consisting of 20 graphics primitives - sage: exploded_plot([p1, p2, p3], center=(1, 1)) # optional - sage.plot + sage: exploded_plot([p1, p2, p3], center=(1, 1)) # needs sage.plot Graphics object consisting of 19 graphics primitives - sage: exploded_plot([p1, p2, p3], center=(1, 1), sticky_vertices=True) # optional - sage.plot + sage: exploded_plot([p1, p2, p3], center=(1, 1), sticky_vertices=True) # needs sage.plot Graphics object consisting of 23 graphics primitives """ from sage.plot.colors import rainbow diff --git a/src/sage/geometry/polyhedron/backend_cdd_rdf.py b/src/sage/geometry/polyhedron/backend_cdd_rdf.py index ed3f6cac169..a39ad446a80 100644 --- a/src/sage/geometry/polyhedron/backend_cdd_rdf.py +++ b/src/sage/geometry/polyhedron/backend_cdd_rdf.py @@ -134,6 +134,7 @@ def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep, verbose=Fal Test that :trac:`29568` is fixed:: + sage: # needs sage.groups sage: P = polytopes.buckyball(exact=False) sage: Q = P + P.center() sage: P.is_combinatorially_isomorphic(Q) diff --git a/src/sage/geometry/polyhedron/backend_field.py b/src/sage/geometry/polyhedron/backend_field.py index 4e190c09cda..77d83c4a381 100644 --- a/src/sage/geometry/polyhedron/backend_field.py +++ b/src/sage/geometry/polyhedron/backend_field.py @@ -7,15 +7,16 @@ EXAMPLES:: + sage: # needs sage.rings.number_field sage: p0 = (0, 0) sage: p1 = (1, 0) - sage: p2 = (1/2, AA(3).sqrt()/2) # optional - sage.rings.number_field - sage: equilateral_triangle = Polyhedron([p0, p1, p2]) # optional - sage.rings.number_field - sage: equilateral_triangle.vertices() # optional - sage.rings.number_field + sage: p2 = (1/2, AA(3).sqrt()/2) + sage: equilateral_triangle = Polyhedron([p0, p1, p2]) + sage: equilateral_triangle.vertices() (A vertex at (0, 0), A vertex at (1, 0), A vertex at (0.500000000000000?, 0.866025403784439?)) - sage: equilateral_triangle.inequalities() # optional - sage.rings.number_field + sage: equilateral_triangle.inequalities() (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) @@ -46,23 +47,24 @@ class Polyhedron_field(Polyhedron_base): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # needs sage.rings.number_field ....: rays=[(1,1)], lines=[], backend='field', base_ring=AA) - sage: TestSuite(p).run() # optional - sage.rings.number_field + sage: TestSuite(p).run() # needs sage.rings.number_field TESTS:: - sage: K. = QuadraticField(3) # optional - sage.rings.number_field - sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # optional - sage.rings.number_field - sage: TestSuite(p).run() # optional - sage.rings.number_field + sage: K. = QuadraticField(3) # needs sage.rings.number_field + sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # needs sage.rings.number_field + sage: TestSuite(p).run() # needs sage.rings.number_field Check that :trac:`19013` is fixed:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2-x-1, embedding=1.618) # optional - sage.rings.number_field - sage: P1 = Polyhedron([[0,1],[1,1],[1,-phi+1]]) # optional - sage.rings.number_field - sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]]) # optional - sage.rings.number_field - sage: P1.intersection(P2) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - x - 1, embedding=1.618) + sage: P1 = Polyhedron([[0,1], [1,1], [1,-phi+1]]) + sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]]) + sage: P1.intersection(P2) The empty polyhedron in (Number Field in phi with defining polynomial x^2 - x - 1 with phi = 1.618033988749895?)^2 @@ -85,10 +87,10 @@ def _is_zero(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field - sage: p._is_zero(0) # optional - sage.rings.number_field + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_zero(0) # needs sage.rings.number_field sage.symbolic True - sage: p._is_zero(1/100000) # optional - sage.rings.number_field + sage: p._is_zero(1/100000) # needs sage.rings.number_fiedl False """ return x == 0 @@ -107,10 +109,10 @@ def _is_nonneg(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field - sage: p._is_nonneg(1) # optional - sage.rings.number_field + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_nonneg(1) # needs sage.rings.number_field sage.symbolic True - sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field + sage: p._is_nonneg(-1/100000) # needs sage.rings.number_field sage.symbolic False """ return x >= 0 @@ -129,10 +131,10 @@ def _is_positive(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field - sage: p._is_positive(1) # optional - sage.rings.number_field + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_positive(1) # needs sage.rings.number_field sage.symbolic True - sage: p._is_positive(0) # optional - sage.rings.number_field + sage: p._is_positive(0) # needs sage.rings.number_field sage.symbolic False """ return x > 0 @@ -152,12 +154,12 @@ def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field + sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # needs sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) - sage: p # optional - sage.rings.number_field + sage: p # needs sage.rings.number_field A 1-dimensional polyhedron in AA^1 defined as the convex hull of 2 vertices """ self._init_Vrepresentation(*Vrep) @@ -246,13 +248,13 @@ def _init_Vrepresentation(self, vertices, rays, lines): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field + sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # needs sage.rings.number_field ....: Vrep_minimal=True, ....: Hrep_minimal=True) - sage: p.vertices_list() # optional - sage.rings.number_field + sage: p.vertices_list() # needs sage.rings.number_field [[0], [1]] """ self._Vrepresentation = [] @@ -271,15 +273,15 @@ def _init_Vrepresentation_backend(self, Vrep): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0, 1/sqrt(2)), # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0, 1/sqrt(2)), # indirect doctest # needs sage.rings.number_field sage.symbolic ....: (sqrt(2), 0), ....: (4, sqrt(5)/6)], ....: base_ring=AA, backend='field') - sage: p.Hrepresentation() # optional - sage.rings.number_field + sage: p.Hrepresentation() # needs sage.rings.number_field sage.symbolic (An inequality (-0.1582178750233332?, 1.097777812326429?) x + 0.2237538646678492? >= 0, An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) - sage: p.Vrepresentation() # optional - sage.rings.number_field + sage: p.Vrepresentation() # needs sage.rings.number_field sage.symbolic (A vertex at (0.?e-16, 0.7071067811865475?), A vertex at (1.414213562373095?, 0), A vertex at (4.000000000000000?, 0.372677996249965?)) @@ -294,12 +296,12 @@ def _init_Hrepresentation(self, inequalities, equations): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field + sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # needs sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) - sage: p.inequalities_list() # optional - sage.rings.number_field + sage: p.inequalities_list() # needs sage.rings.number_field [[0, 1], [1, -1]] """ self._Hrepresentation = [] @@ -316,15 +318,15 @@ def _init_Hrepresentation_backend(self, Hrep): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0, 1/sqrt(2)), # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0, 1/sqrt(2)), # indirect doctest # needs sage.rings.number_field sage.symbolic ....: (sqrt(2), 0), ....: (4, sqrt(5)/6)], ....: base_ring=AA, backend='field') - sage: p.Hrepresentation() # optional - sage.rings.number_field + sage: p.Hrepresentation() # needs sage.rings.number_field sage.symbolic (An inequality (-0.1582178750233332?, 1.097777812326429?) x + 0.2237538646678492? >= 0, An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) - sage: p.Vrepresentation() # optional - sage.rings.number_field + sage: p.Vrepresentation() # needs sage.rings.number_field sage.symbolic (A vertex at (0.?e-16, 0.7071067811865475?), A vertex at (1.414213562373095?, 0), A vertex at (4.000000000000000?, 0.372677996249965?)) @@ -337,11 +339,11 @@ def _init_empty_polyhedron(self): TESTS:: - sage: empty = Polyhedron(backend='field', base_ring=AA); empty # optional - sage.rings.number_field + sage: empty = Polyhedron(backend='field', base_ring=AA); empty # needs sage.rings.number_field The empty polyhedron in AA^0 - sage: empty.Vrepresentation() # optional - sage.rings.number_field + sage: empty.Vrepresentation() # needs sage.rings.number_field () - sage: empty.Hrepresentation() # optional - sage.rings.number_field + sage: empty.Hrepresentation() # needs sage.rings.number_field (An equation -1 == 0,) sage: Polyhedron(vertices=[], backend='field') The empty polyhedron in QQ^0 diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index ce389f090a2..19da8cce5e5 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -156,7 +156,7 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): Algebraic polyhedra:: - sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], # optional - sage.rings.number_field sage.symbolic + sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], # needs sage.rings.number_field sage.symbolic ....: backend='normaliz', verbose=True) # ----8<---- Equivalent Normaliz input file ----8<---- amb_space 1 @@ -168,13 +168,13 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): (a) 1 # ----8<-------------------8<-------------------8<---- # Calling PyNormaliz.NmzCone(cone=[], number_field=['a^2 - 2', 'a', '[1.414213562373095 +/- 2.99e-16]'], subspace=[], vertices=[[1, 1], [[[0, 1], [1, 1]], 1]]) - sage: P # optional - sage.rings.number_field sage.symbolic + sage: P # needs sage.rings.number_field sage.symbolic A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field sage.symbolic + sage: P.vertices() # needs sage.rings.number_field sage.symbolic (A vertex at (1), A vertex at (sqrt(2))) - sage: P = polytopes.icosahedron(exact=True, # optional - sage.rings.number_field + sage: P = polytopes.icosahedron(exact=True, # needs sage.rings.number_field ....: backend='normaliz'); P A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 @@ -182,7 +182,7 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): defined as the convex hull of 12 vertices sage: x = polygen(ZZ) - sage: P = Polyhedron(vertices=[[sqrt(2)], # optional - sage.rings.number_field sage.symbolic + sage: P = Polyhedron(vertices=[[sqrt(2)], # needs sage.rings.number_field sage.symbolic ....: [AA.polynomial_root(x^3 - 2, RIF(0,3))]], ....: backend='normaliz', verbose=True) # ----8<---- Equivalent Normaliz input file ----8<---- @@ -195,10 +195,10 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): (a^2) 1 # ----8<-------------------8<-------------------8<---- # Calling PyNormaliz.NmzCone(cone=[], number_field=['a^6 - 2', 'a', '[1.122462048309373 +/- 5.38e-16]'], subspace=[], vertices=[[[[0, 1], [0, 1], [0, 1], [1, 1], [0, 1], [0, 1]], 1], [[[0, 1], [0, 1], [1, 1], [0, 1], [0, 1], [0, 1]], 1]]) - sage: P # optional - sage.rings.number_field sage.symbolic + sage: P # needs sage.rings.number_field sage.symbolic A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field sage.symbolic + sage: P.vertices() # needs sage.rings.number_field sage.symbolic (A vertex at (2^(1/3)), A vertex at (sqrt(2))) """ @@ -248,23 +248,24 @@ def _nmz_result(self, normaliz_cone, property): ... NormalizError: Some error in the normaliz input data detected: Unknown ConeProperty... - sage: x = polygen(QQ, 'x') # optional - sage.rings.number_field - sage: K. = NumberField(x^3 - 3, embedding=AA(3)**(1/3)) # optional - sage.rings.number_field - sage: p = Polyhedron(vertices=[(0, 0), (1, 1), (a, 3), (-1, a**2)], # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: x = polygen(QQ, 'x') + sage: K. = NumberField(x^3 - 3, embedding=AA(3)**(1/3)) + sage: p = Polyhedron(vertices=[(0, 0), (1, 1), (a, 3), (-1, a**2)], ....: rays=[(-1,-a)], backend='normaliz') - sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) # optional - sage.rings.number_field + sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) [[-1, a^2, 1], [1, 1, 1], [a, 3, 1]] - sage: triangulation_generators = p._nmz_result(p._normaliz_cone, # optional - sage.rings.number_field + sage: triangulation_generators = p._nmz_result(p._normaliz_cone, ....: 'Triangulation')[1] - sage: sorted(triangulation_generators) # optional - sage.rings.number_field + sage: sorted(triangulation_generators) [[-a^2, -3, 0], [-1, a^2, 1], [0, 0, 1], [1, 1, 1], [a, 3, 1]] - sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 True - sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 True - sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') [[-1/3*a^2, -1, 0]] - sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') [] """ def rational_handler(list): @@ -309,7 +310,7 @@ def _convert_to_pynormaliz(x): TESTS:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: K. = QuadraticField(2) # needs sage.rings.number_field sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._convert_to_pynormaliz(17) 17 @@ -321,9 +322,9 @@ def _convert_to_pynormaliz(x): [[28, 5]] sage: Pn._convert_to_pynormaliz(28901824309821093821093812093810928309183091832091/5234573685674784567853456543456456786543456765) [[28901824309821093821093812093810928309183091832091, 5234573685674784567853456543456456786543456765]] - sage: Pn._convert_to_pynormaliz(7 + sqrt2) # optional - sage.rings.number_field + sage: Pn._convert_to_pynormaliz(7 + sqrt2) # needs sage.rings.number_field [[7, 1], [1, 1]] - sage: Pn._convert_to_pynormaliz(7/2 + sqrt2) # optional - sage.rings.number_field + sage: Pn._convert_to_pynormaliz(7/2 + sqrt2) # needs sage.rings.number_field [[7, 2], [1, 1]] sage: Pn._convert_to_pynormaliz([[1, 2], (3, 4)]) [[1, 2], [3, 4]] @@ -331,8 +332,8 @@ def _convert_to_pynormaliz(x): Check that :trac:`29836` is fixed:: sage: P = polytopes.simplex(backend='normaliz') - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: P.dilation(sqrt2) # optional - sage.rings.number_field + sage: K. = QuadraticField(2) # needs sage.rings.number_field + sage: P.dilation(sqrt2) # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.41...)^4 defined as the convex hull of 4 vertices @@ -367,17 +368,17 @@ def _init_from_normaliz_data(self, data, internal_base_ring=None, verbose=False) [[0, -1, 2], [0, 2, -1]] sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz - sage: from sage.rings.qqbar import AA # optional - sage.rings.number_field - sage: from sage.rings.number_field.number_field import QuadraticField # optional - sage.rings.number_field + sage: from sage.rings.qqbar import AA # needs sage.rings.number_field + sage: from sage.rings.number_field.number_field import QuadraticField # needs sage.rings.number_field sage: data = {'number_field': ['a^2 - 2', 'a', '[1.4 +/- 0.1]'], ....: 'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} sage: from sage.geometry.polyhedron.parent import Polyhedra_normaliz - sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # optional - sage.rings.number_field - sage: Polyhedron_normaliz(parent, None, None, # indirect doctest, optional - sage.rings.number_field + sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # needs sage.rings.number_field + sage: Polyhedron_normaliz(parent, None, None, # needs sage.rings.number_field ....: normaliz_data=data, ....: internal_base_ring=QuadraticField(2)) A 2-dimensional polyhedron in AA^2 defined as the convex hull of 1 vertex and 2 rays - sage: _.inequalities_list() # optional - sage.rings.number_field + sage: _.inequalities_list() # needs sage.rings.number_field [[0, -1/2, 1], [0, 2, -1]] """ if internal_base_ring is None: @@ -432,10 +433,10 @@ def _is_zero(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field sage.symbolic - sage: p._is_zero(0) # optional - sage.rings.number_field sage.symbolic + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_zero(0) # needs sage.rings.number_field sage.symbolic True - sage: p._is_zero(1/100000) # optional - sage.rings.number_field sage.symbolic + sage: p._is_zero(1/100000) # needs sage.rings.number_field sage.symbolic False """ return x == 0 @@ -454,10 +455,10 @@ def _is_nonneg(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field sage.symbolic - sage: p._is_nonneg(1) # optional - sage.rings.number_field sage.symbolic + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_nonneg(1) # needs sage.rings.number_field sage.symbolic True - sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field sage.symbolic + sage: p._is_nonneg(-1/100000) # needs sage.rings.number_field sage.symbolic False """ return x >= 0 @@ -476,10 +477,10 @@ def _is_positive(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field sage.symbolic - sage: p._is_positive(1) # optional - sage.rings.number_field sage.symbolic + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_positive(1) # needs sage.rings.number_field sage.symbolic True - sage: p._is_positive(0) # optional - sage.rings.number_field sage.symbolic + sage: p._is_positive(0) # needs sage.rings.number_field sage.symbolic False """ return x > 0 @@ -586,24 +587,25 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): TESTS:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: p = Polyhedron(ieqs=[(1, a, 0)], backend='normaliz') # optional - sage.rings.number_field - sage: p & p == p # optional - sage.rings.number_field + sage: K. = QuadraticField(2) # needs sage.rings.number_field + sage: p = Polyhedron(ieqs=[(1, a, 0)], backend='normaliz') # needs sage.rings.number_field + sage: p & p == p # needs sage.rings.number_field True Check that :trac:`30248` is fixed, that maps as input works:: - sage: q = Polyhedron(backend='normaliz', base_ring=AA, # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: q = Polyhedron(backend='normaliz', base_ring=AA, ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]) sage: def make_new_Hrep(h): ....: return tuple(x if i == 0 else -1*x ....: for i, x in enumerate(h._vector)) - sage: new_inequalities = map(make_new_Hrep, q.inequality_generator()) # optional - sage.rings.number_field - sage: new_equations = map(make_new_Hrep, q.equation_generator()) # optional - sage.rings.number_field - sage: parent = q.parent() # optional - sage.rings.number_field - sage: new_q = parent.element_class(parent, None, # optional - sage.rings.number_field + sage: new_inequalities = map(make_new_Hrep, q.inequality_generator()) + sage: new_equations = map(make_new_Hrep, q.equation_generator()) + sage: parent = q.parent() + sage: new_q = parent.element_class(parent, None, ....: [new_inequalities, new_equations]) - sage: new_q # optional - sage.rings.number_field + sage: new_q A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ @@ -736,7 +738,7 @@ def _cone_from_Vrepresentation_and_Hrepresentation(self, vertices, rays, lines, ....: for arg in args) sage: test_poly(polytopes.simplex(backend='normaliz')) True - sage: test_poly(polytopes.dodecahedron(backend='normaliz')) # optional - sage.rings.number_field + sage: test_poly(polytopes.dodecahedron(backend='normaliz')) # needs sage.rings.number_field True sage: test_poly(Polyhedron(vertices=[[1,0], [0,1]], rays=[[1,1]], ....: backend='normaliz')) @@ -1022,7 +1024,7 @@ def _number_field_triple(internal_base_ring): sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._number_field_triple(QQ) is None True - sage: Pn._number_field_triple(QuadraticField(5)) # optional - sage.rings.number_field + sage: Pn._number_field_triple(QuadraticField(5)) # needs sage.rings.number_field ['a^2 - 5', 'a', '[2.236067977499789 +/- 8.06e-16]'] """ R = internal_base_ring @@ -1271,11 +1273,12 @@ def __setstate__(self, state): sage: P2 == P True - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - sage.rings.number_field - sage: P1 = loads(dumps(P)) # optional - sage.rings.number_field - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron(backend='normaliz') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, ....: internal_base_ring=P1._internal_base_ring) - sage: P == P2 # optional - sage.rings.number_field + sage: P == P2 True Test that :trac:`31820` is fixed:: @@ -1325,7 +1328,7 @@ def integral_hull(self): sage: P = Polyhedron(ieqs=[[1, 0, 2], [3, 0, -2], [3, 2, -2]], ....: backend='normaliz') sage: PI = P.integral_hull() - sage: P.plot(color='yellow') + PI.plot(color='green') # optional - sage.plot + sage: P.plot(color='yellow') + PI.plot(color='green') # needs sage.plot Graphics object consisting of 10 graphics primitives sage: PI.Vrepresentation() (A vertex at (-1, 0), @@ -1453,8 +1456,8 @@ def _volume_normaliz(self, measure='euclidean'): Check that :trac:`28872` is fixed:: - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - sage.rings.number_field - sage: P.volume(measure='induced_lattice') # optional - sage.rings.number_field + sage: P = polytopes.dodecahedron(backend='normaliz') # needs sage.rings.number_field + sage: P.volume(measure='induced_lattice') # needs sage.rings.number_field -1056*sqrt5 + 2400 Some sanity checks that the ambient volume works correctly:: @@ -1466,12 +1469,12 @@ def _volume_normaliz(self, measure='euclidean'): sage: s._volume_normaliz(measure='ambient') 0 - sage: P = polytopes.regular_polygon(3, backend='normaliz') # optional - sage.rings.number_field - sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # optional - sage.rings.number_field + sage: P = polytopes.regular_polygon(3, backend='normaliz') # needs sage.rings.number_field + sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # needs sage.rings.number_field True - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - sage.rings.number_field - sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # optional - sage.rings.number_field + sage: P = polytopes.dodecahedron(backend='normaliz') # needs sage.rings.number_field + sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # needs sage.rings.number_field True sage: P = Polyhedron(rays=[[1]], backend='normaliz') @@ -1976,9 +1979,9 @@ def integral_points(self, threshold=10000): sage: pts1 = P.integral_points() sage: all(P.contains(p) for p in pts1) True - sage: pts2 = LatticePolytope(v).points() # optional - palp + sage: pts2 = LatticePolytope(v).points() # needs palp sage: for p in pts1: p.set_immutable() - sage: set(pts1) == set(pts2) # optional - palp + sage: set(pts1) == set(pts2) # needs palp True sage: timeit('Polyhedron(v, backend='normaliz').integral_points()') # not tested - random @@ -2238,16 +2241,17 @@ class functions. is equal to 1 = `\chi_{trivial}` (Prop 6.1 [Stap2011]_). Here is the computation for the 3-dimensional standard simplex:: + sage: # needs sage.groups sage: S = polytopes.simplex(3, backend='normaliz'); S A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices - sage: G = S.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: G.is_isomorphic(SymmetricGroup(4)) # optional - sage.groups + sage: G = S.restricted_automorphism_group(output='permutation') + sage: G.is_isomorphic(SymmetricGroup(4)) True - sage: len(G) # optional - sage.groups + sage: len(G) 24 - sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - sage.groups + sage: Hstar = S._Hstar_function_normaliz(G); Hstar chi_4 - sage: G.character_table() # optional - sage.groups + sage: G.character_table() [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -2259,29 +2263,30 @@ class functions. `\pm(0,0,1),\pm(1,0,1), \pm(0,1,1), \pm(1,1,1)` and let G = `\Zmod{2}` act on P as follows:: + sage: # needs sage.groups sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], [-1,0,-1], ....: [0,1,1], [0,-1,-1], [1,1,1], [-1,-1,-1]], ....: backend='normaliz') - sage: K = P.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: G = K.subgroup(gens=[K([(0,2),(1,3),(4,6),(5,7)])]) # optional - sage.groups - sage: conj_reps = G.conjugacy_classes_representatives() # optional - sage.groups - sage: Dict = P.permutations_to_matrices(conj_reps, acting_group=G) # optional - sage.groups - sage: list(Dict.keys())[0] # optional - sage.groups + sage: K = P.restricted_automorphism_group(output='permutation') + sage: G = K.subgroup(gens=[K([(0,2),(1,3),(4,6),(5,7)])]) + sage: conj_reps = G.conjugacy_classes_representatives() + sage: Dict = P.permutations_to_matrices(conj_reps, acting_group=G) + sage: list(Dict.keys())[0] (0,2)(1,3)(4,6)(5,7) - sage: list(Dict.values())[0] # optional - sage.groups + sage: list(Dict.values())[0] [-1 0 1 0] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] - sage: len(G) # optional - sage.groups + sage: len(G) 2 - sage: G.character_table() # optional - sage.groups + sage: G.character_table() [ 1 1] [ 1 -1] Then we calculate the rational function `H^*(t)`:: - sage: Hst = P._Hstar_function_normaliz(G); Hst # optional - sage.groups + sage: Hst = P._Hstar_function_normaliz(G); Hst # needs sage.groups (chi_0*t^4 + (3*chi_0 + 3*chi_1)*t^3 + (8*chi_0 + 2*chi_1)*t^2 + (3*chi_0 + 3*chi_1)*t + chi_0)/(t + 1) @@ -2289,7 +2294,7 @@ class functions. ``'Hstar_as_lin_comb'``. The first coordinate is the coefficient of the trivial character; the second is the coefficient of the sign character:: - sage: lin = P._Hstar_function_normaliz(G, output='Hstar_as_lin_comb'); lin # optional - sage.groups + sage: lin = P._Hstar_function_normaliz(G, output='Hstar_as_lin_comb'); lin # needs sage.groups ((t^4 + 3*t^3 + 8*t^2 + 3*t + 1)/(t + 1), (3*t^3 + 2*t^2 + 3*t)/(t + 1)) """ from sage.groups.conjugacy_classes import ConjugacyClassGAP @@ -2400,14 +2405,14 @@ def _Hstar_as_rat_fct(self, initial_Hstar): sage: simplex = Polyhedron(vertices=[[0,0,0], [1,0,0], ....: [0,1,0], [0,0,1]], backend='normaliz') - sage: Hstar = simplex.Hstar_function(); Hstar # indirect doctest # optional - sage.rings.number_field + sage: Hstar = simplex.Hstar_function(); Hstar # indirect doctest # needs sage.rings.number_field chi_4 The polynomial is `\chi_4 \cdot t^0`. We can see which irreducible representation `\chi_4` corresponds to by looking at the character table:: - sage: G = simplex.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: char = G.character_table(); char # optional - sage.groups + sage: G = simplex.restricted_automorphism_group(output='permutation') # needs sage.groups + sage: char = G.character_table(); char # needs sage.groups [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -2421,14 +2426,14 @@ def _Hstar_as_rat_fct(self, initial_Hstar): sage: square = Polyhedron(vertices=[[1,1], [-1,1], [-1,-1], [1,-1]], ....: backend='normaliz') - sage: Hstar = square.Hstar_function(); Hstar # optional - sage.rings.number_field + sage: Hstar = square.Hstar_function(); Hstar # needs sage.rings.number_field chi_0*t^2 + (2*chi_0 + chi_2 + chi_3 + chi_4)*t + chi_0 Plugging in the values from the first column of the character table below yields the `h^*`-polynomial of the square, `t^2+6t+1`:: - sage: G = square.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: G.character_table() # optional - sage.groups + sage: G = square.restricted_automorphism_group(output='permutation') # needs sage.groups + sage: G.character_table() # needs sage.groups [ 1 1 1 1 1] [ 1 -1 -1 1 1] [ 1 -1 1 -1 1] @@ -2475,30 +2480,32 @@ class functions of the acting group. A character `\rho` is effective if The `H^*` series of the two-dimensional permutahedron under the action of the symmetric group is effective:: + sage: # needs sage.groups sage: p3 = polytopes.permutahedron(3, backend='normaliz') - sage: G = p3.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: reflection12 = G([(0,2),(1,4),(3,5)]) # optional - sage.groups - sage: reflection23 = G([(0,1),(2,3),(4,5)]) # optional - sage.groups - sage: S3 = G.subgroup(gens=[reflection12, reflection23]) # optional - sage.groups - sage: S3.is_isomorphic(SymmetricGroup(3)) # optional - sage.groups + sage: G = p3.restricted_automorphism_group(output='permutation') + sage: reflection12 = G([(0,2),(1,4),(3,5)]) + sage: reflection23 = G([(0,1),(2,3),(4,5)]) + sage: S3 = G.subgroup(gens=[reflection12, reflection23]) + sage: S3.is_isomorphic(SymmetricGroup(3)) True - sage: Hstar = p3.Hstar_function(S3) # optional - sage.groups sage.rings.number_field - sage: Hlin = p3.Hstar_function(S3, output='Hstar_as_lin_comb') # optional - sage.groups sage.rings.number_field - sage: p3._is_effective_normaliz(Hstar, Hlin) # optional - sage.groups sage.rings.number_field + sage: Hstar = p3.Hstar_function(S3) # needs sage.rings.number_field + sage: Hlin = p3.Hstar_function(S3, output='Hstar_as_lin_comb') # needs sage.rings.number_field + sage: p3._is_effective_normaliz(Hstar, Hlin) # needs sage.rings.number_field True If the `H^*`-series is not polynomial, then it is not effective:: + sage: # needs sage.groups sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], [-1,0,-1], ....: [0,1,1], [0,-1,-1], [1,1,1], [-1,-1,-1]], ....: backend='normaliz') - sage: G = P.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: H = G.subgroup(gens = [G([(0,2),(1,3),(4,6),(5,7)])]) # optional - sage.groups - sage: Hstar = P.Hstar_function(H); Hstar # optional - sage.groups sage.rings.number_field + sage: G = P.restricted_automorphism_group(output='permutation') + sage: H = G.subgroup(gens = [G([(0,2),(1,3),(4,6),(5,7)])]) + sage: Hstar = P.Hstar_function(H); Hstar # needs sage.rings.number_field (chi_0*t^4 + (3*chi_0 + 3*chi_1)*t^3 + (8*chi_0 + 2*chi_1)*t^2 + (3*chi_0 + 3*chi_1)*t + chi_0)/(t + 1) - sage: Hstar_lin = P.Hstar_function(H, output='Hstar_as_lin_comb') # optional - sage.groups sage.rings.number_field - sage: P._is_effective_normaliz(Hstar, Hstar_lin) # optional - sage.groups sage.rings.number_field + sage: Hstar_lin = P.Hstar_function(H, output='Hstar_as_lin_comb') # needs sage.rings.number_field + sage: P._is_effective_normaliz(Hstar, Hstar_lin) # needs sage.rings.number_field False """ if not Hstar.denominator().is_unit(): diff --git a/src/sage/geometry/polyhedron/backend_number_field.py b/src/sage/geometry/polyhedron/backend_number_field.py index 650c41f1e36..e79688bea5f 100644 --- a/src/sage/geometry/polyhedron/backend_number_field.py +++ b/src/sage/geometry/polyhedron/backend_number_field.py @@ -39,27 +39,26 @@ class Polyhedron_number_field(Polyhedron_field, Polyhedron_base_number_field): EXAMPLES:: - sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='number_field') # optional - sage.rings.number_field - sage: P # optional - sage.rings.number_field + sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='number_field'); P # needs sage.rings.number_field sage.symbolic A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() # needs sage.rings.number_field sage.symbolic (A vertex at (1), A vertex at (sqrt(2))) - sage: P = polytopes.icosahedron(exact=True, backend='number_field') # optional - sage.rings.number_field - sage: P # optional - sage.rings.number_field + sage: P = polytopes.icosahedron(exact=True, backend='number_field') # needs sage.rings.number_field + sage: P # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 defined as the convex hull of 12 vertices - sage: x = polygen(ZZ); P = Polyhedron( # optional - sage.rings.number_field sage.symbolic + sage: x = polygen(ZZ); P = Polyhedron( # needs sage.rings.number_field sage.symbolic ....: vertices=[[sqrt(2)], [AA.polynomial_root(x^3-2, RIF(0,3))]], ....: backend='number_field') - sage: P # optional - sage.rings.number_field + sage: P # needs sage.rings.number_field sage.symbolic A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() # needs sage.rings.number_field sage.symbolic (A vertex at (sqrt(2)), A vertex at (2^(1/3))) TESTS: @@ -67,19 +66,21 @@ class Polyhedron_number_field(Polyhedron_field, Polyhedron_base_number_field): Tests from :class:`~sage.geometry.polyhedron.backend_field.Polyhedron_field` -- here the data are already either in a number field or in ``AA``:: - sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # optional - sage.rings.number_field - ....: rays=[(1,1)], lines=[], backend='number_field', base_ring=AA) - sage: TestSuite(p).run() # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # needs sage.rings.number_field + ....: rays=[(1,1)], lines=[], backend='number_field', + ....: base_ring=AA) + sage: TestSuite(p).run() # needs sage.rings.number_field - sage: K. = QuadraticField(3) # optional - sage.rings.number_field - sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)], backend='number_field') # optional - sage.rings.number_field - sage: TestSuite(p).run() # optional - sage.rings.number_field + sage: K. = QuadraticField(3) # needs sage.rings.number_field + sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)], backend='number_field') # needs sage.rings.number_field + sage: TestSuite(p).run() # needs sage.rings.number_field + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - x - 1, embedding=1.618) # optional - sage.rings.number_field - sage: P1 = Polyhedron([[0,1], [1,1], [1,-phi+1]], backend='number_field') # optional - sage.rings.number_field - sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]], backend='number_field') # optional - sage.rings.number_field - sage: P1.intersection(P2) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - x - 1, embedding=1.618) + sage: P1 = Polyhedron([[0,1], [1,1], [1,-phi+1]], backend='number_field') + sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]], backend='number_field') + sage: P1.intersection(P2) The empty polyhedron in (Number Field in phi with defining polynomial x^2 - x - 1 with phi = 1.618033988749895?)^2 @@ -120,11 +121,11 @@ def _init_from_Vrepresentation(self, vertices, rays, lines, Check that the coordinates of a vertex get simplified in the Symbolic Ring:: - sage: p = Polyhedron(ambient_dim=2, base_ring=SR, backend='number_field') # optional - sage.symbolic + sage: p = Polyhedron(ambient_dim=2, base_ring=SR, backend='number_field') # needs sage.symbolic sage: from sage.geometry.polyhedron.backend_number_field import Polyhedron_number_field - sage: Polyhedron_number_field._init_from_Vrepresentation(p, [(0,1/2),(sqrt(2),0),(4,5/6)], [], []); p # optional - sage.symbolic + sage: Polyhedron_number_field._init_from_Vrepresentation(p, [(0,1/2),(sqrt(2),0),(4,5/6)], [], []); p # needs sage.symbolic A 2-dimensional polyhedron in (Symbolic Ring)^2 defined as the convex hull of 3 vertices - sage: p.vertices()[0][0] # optional - sage.symbolic + sage: p.vertices()[0][0] 0 """ (vertices, rays, lines), internal_base_ring \ diff --git a/src/sage/geometry/polyhedron/backend_polymake.py b/src/sage/geometry/polyhedron/backend_polymake.py index 52aaeb2743b..624ae2f6340 100644 --- a/src/sage/geometry/polyhedron/backend_polymake.py +++ b/src/sage/geometry/polyhedron/backend_polymake.py @@ -77,13 +77,14 @@ class Polyhedron_polymake(Polyhedron_base): It can also be obtained differently:: - sage: P=Polyhedron(ieqs=[[-2, 1, 1], [-3, -1, -1], [-4, 1, -2]], # optional - jupymake + sage: # optional - jupymake + sage: P=Polyhedron(ieqs=[[-2, 1, 1], [-3, -1, -1], [-4, 1, -2]], ....: backend='polymake') - sage: P # optional - jupymake + sage: P The empty polyhedron in QQ^2 - sage: P.Vrepresentation() # optional - jupymake + sage: P.Vrepresentation() () - sage: P.Hrepresentation() # optional - jupymake + sage: P.Hrepresentation() (An equation -1 == 0,) The full polyhedron:: @@ -96,8 +97,8 @@ class Polyhedron_polymake(Polyhedron_base): Quadratic fields work:: - sage: V = polytopes.dodecahedron().vertices_list() # optional - sage.rings.number_field - sage: Polyhedron(vertices=V, backend='polymake') # optional - jupymake # optional - sage.rings.number_field + sage: V = polytopes.dodecahedron().vertices_list() # needs sage.rings.number_field + sage: Polyhedron(vertices=V, backend='polymake') # optional - jupymake, needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 @@ -211,11 +212,12 @@ def __init__(self, parent, Vrep, Hrep, polymake_polytope=None, **kwds): TESTS: - sage: p = Polyhedron(backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake - sage: p = Polyhedron(vertices=[(1, 1)], rays=[(0, 1)], # optional - jupymake + sage: # optional - jupymake + sage: p = Polyhedron(backend='polymake') + sage: TestSuite(p).run() + sage: p = Polyhedron(vertices=[(1, 1)], rays=[(0, 1)], ....: backend='polymake') - sage: TestSuite(p).run() # optional - jupymake + sage: TestSuite(p).run() We skip the Lawrence test because it involves numerically unstable floating point arithmetic:: @@ -226,14 +228,15 @@ def __init__(self, parent, Vrep, Hrep, polymake_polytope=None, **kwds): :: - sage: p = Polyhedron(rays=[[1,1]], backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake - sage: p = Polyhedron(rays=[[1]], backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake - sage: p = Polyhedron(rays=[[1,1,1]], lines=[[1,0,0]], backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake - sage: p = Polyhedron(vertices=[[]], backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake + sage: # optional - jupymake + sage: p = Polyhedron(rays=[[1,1]], backend='polymake') + sage: TestSuite(p).run() + sage: p = Polyhedron(rays=[[1]], backend='polymake') + sage: TestSuite(p).run() + sage: p = Polyhedron(rays=[[1,1,1]], lines=[[1,0,0]], backend='polymake') + sage: TestSuite(p).run() + sage: p = Polyhedron(vertices=[[]], backend='polymake') + sage: TestSuite(p).run() """ if polymake_polytope is not None: if Hrep is not None or Vrep is not None: @@ -250,7 +253,7 @@ def _init_from_polymake_polytope(self, polymake_polytope): TESTS:: sage: p = Polyhedron(backend='polymake') # optional - jupymake - sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - jupymake + sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake sage: Polyhedron_polymake._init_from_Hrepresentation(p, [], []) # indirect doctest # optional - jupymake """ self._polymake_polytope = polymake_polytope @@ -281,7 +284,7 @@ def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbo EXAMPLES:: sage: p = Polyhedron(backend='polymake') # optional - jupymake - sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - jupymake + sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake sage: Polyhedron_polymake._init_from_Vrepresentation(p, [], [], []) # optional - jupymake """ from sage.interfaces.polymake import polymake @@ -348,7 +351,7 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): EXAMPLES:: sage: p = Polyhedron(backend='polymake') # optional - jupymake - sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - jupymake + sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake sage: Polyhedron_polymake._init_from_Hrepresentation(p, [], []) # optional - jupymake """ from sage.interfaces.polymake import polymake @@ -644,31 +647,35 @@ def __setstate__(self, state): Test that the obtained cone is valid:: - sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - jupymake - sage: P = polytopes.permutahedron(4, backend='polymake') # optional - jupymake - sage: P1 = loads(dumps(P)) # optional - jupymake - sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) # optional - jupymake - sage: P._test_polymake_pickling(other=P2) # optional - jupymake + sage: # optional - jupymake + sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake + sage: P = polytopes.permutahedron(4, backend='polymake') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) + sage: P._test_polymake_pickling(other=P2) - sage: P = Polyhedron(lines=[[1,0], [0,1]], backend='polymake') # optional - jupymake - sage: P1 = loads(dumps(P)) # optional - jupymake - sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) # optional - jupymake - sage: P._test_polymake_pickling(other=P2) # optional - jupymake + sage: # optional - jupymake + sage: P = Polyhedron(lines=[[1,0], [0,1]], backend='polymake') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) + sage: P._test_polymake_pickling(other=P2) sage: P = Polyhedron(backend='polymake') # optional - jupymake sage: P1 = loads(dumps(P)) # optional - jupymake sage: P._test_polymake_pickling(other=P1) # optional - jupymake - sage: P = polytopes.permutahedron(4, backend='polymake') * Polyhedron(lines=[[1]], backend='polymake') # optional - jupymake - sage: P1 = loads(dumps(P)) # optional - jupymake - sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) # optional - jupymake - sage: P._test_polymake_pickling(other=P2) # optional - jupymake + sage: # optional - jupymake + sage: P = polytopes.permutahedron(4, backend='polymake') * Polyhedron(lines=[[1]], backend='polymake') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) + sage: P._test_polymake_pickling(other=P2) - sage: print("Possible output"); P = polytopes.dodecahedron(backend='polymake') # optional - jupymake # optional - sage.rings.number_field + sage: # optional - jupymake, needs sage.rings.number_field + sage: print("Possible output"); P = polytopes.dodecahedron(backend='polymake') Possible output... - sage: P1 = loads(dumps(P)) # optional - jupymake # optional - sage.rings.number_field - sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) # optional - jupymake # optional - sage.rings.number_field - sage: P._test_polymake_pickling(other=P2) # optional - jupymake # optional - sage.rings.number_field + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) + sage: P._test_polymake_pickling(other=P2) """ if "_pickle_vertices" in state[1]: vertices = state[1].pop("_pickle_vertices") diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index ff5be490df5..ec26e49075c 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -124,8 +124,8 @@ class Polyhedron_base(Polyhedron_base7): :: - sage: p = polytopes.flow_polytope(digraphs.DeBruijn(3,2)) # optional - sage.graphs - sage: TestSuite(p).run() # optional - sage.graphs + sage: p = polytopes.flow_polytope(digraphs.DeBruijn(3,2)) # needs sage.combinat sage.graphs + sage: TestSuite(p).run() :: @@ -136,13 +136,13 @@ class Polyhedron_base(Polyhedron_base7): :: sage: P3 = polytopes.permutahedron(3) - sage: P = P3 * Polyhedron(rays=[[0,0,1], [0,1,1], [1,2,3]]) # optional - sage.combinat - sage: TestSuite(P).run() # optional - sage.combinat + sage: P = P3 * Polyhedron(rays=[[0,0,1], [0,1,1], [1,2,3]]) + sage: TestSuite(P).run() :: - sage: P = P3 * Polyhedron(rays=[[0,0,1], [0,1,1]], lines=[[1,0,0]]) # optional - sage.combinat - sage: TestSuite(P).run() # optional - sage.combinat + sage: P = P3 * Polyhedron(rays=[[0,0,1], [0,1,1]], lines=[[1,0,0]]) + sage: TestSuite(P).run() :: @@ -234,44 +234,46 @@ def to_linear_program(self, solver=None, return_variable=False, base_ring=None): Irrational algebraic linear program over an embedded number field:: - sage: p = polytopes.icosahedron() # optional - sage.rings.number_field - sage: lp, x = p.to_linear_program(return_variable=True) # optional - sage.rings.number_field - sage: lp.set_objective(x[0] + x[1] + x[2]) # optional - sage.rings.number_field - sage: lp.solve() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: p = polytopes.icosahedron() + sage: lp, x = p.to_linear_program(return_variable=True) + sage: lp.set_objective(x[0] + x[1] + x[2]) + sage: lp.solve() 1/4*sqrt5 + 3/4 Same example with floating point:: - sage: lp, x = p.to_linear_program(return_variable=True, base_ring=RDF) # optional - sage.rings.number_field - sage: lp.set_objective(x[0] + x[1] + x[2]) # optional - sage.rings.number_field - sage: lp.solve() # tol 1e-5 # optional - sage.rings.number_field + sage: lp, x = p.to_linear_program(return_variable=True, base_ring=RDF) + sage: lp.set_objective(x[0] + x[1] + x[2]) + sage: lp.solve() # tol 1e-5 # needs sage.rings.number_field 1.3090169943749475 Same example with a specific floating point solver:: - sage: lp, x = p.to_linear_program(return_variable=True, solver='GLPK') # optional - sage.rings.number_field - sage: lp.set_objective(x[0] + x[1] + x[2]) # optional - sage.rings.number_field - sage: lp.solve() # tol 1e-8 # optional - sage.rings.number_field + sage: lp, x = p.to_linear_program(return_variable=True, solver='GLPK') + sage: lp.set_objective(x[0] + x[1] + x[2]) + sage: lp.solve() # tol 1e-8 # needs sage.rings.number_field 1.3090169943749475 Irrational algebraic linear program over `AA`:: - sage: p = polytopes.icosahedron(base_ring=AA) # optional - sage.rings.number_field - sage: lp, x = p.to_linear_program(return_variable=True) # optional - sage.rings.number_field - sage: lp.set_objective(x[0] + x[1] + x[2]) # optional - sage.rings.number_field - sage: lp.solve() # long time # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: p = polytopes.icosahedron(base_ring=AA) + sage: lp, x = p.to_linear_program(return_variable=True) + sage: lp.set_objective(x[0] + x[1] + x[2]) + sage: lp.solve() # long time 1.309016994374948? TESTS:: - sage: p = polytopes.flow_polytope(digraphs.DeBruijn(3,2)); p # optional - sage.graphs + sage: p = polytopes.flow_polytope(digraphs.DeBruijn(3,2)); p # needs sage.combinat sage.graphs A 19-dimensional polyhedron in QQ^27 defined as the convex hull of 1 vertex and 148 rays - sage: p.to_linear_program().polyhedron() == p # optional - sage.graphs + sage: p.to_linear_program().polyhedron() == p True - sage: p = polytopes.icosahedron() # optional - sage.rings.number_field - sage: p.to_linear_program(solver='PPL') # optional - sage.rings.number_field + sage: p = polytopes.icosahedron() # needs sage.rings.number_field + sage: p.to_linear_program(solver='PPL') # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: The PPL backend only supports rational data. @@ -317,17 +319,18 @@ def boundary_complex(self): The boundary complex of the octahedron:: + sage: # needs sage.graphs sage: oc = polytopes.octahedron() - sage: sc_oc = oc.boundary_complex() # optional - sage.graphs - sage: fl_oc = oc.face_lattice() # optional - sage.combinat sage.graphs - sage: fl_sc = sc_oc.face_poset() # optional - sage.combinat sage.graphs - sage: [len(x) for x in fl_oc.level_sets()] # optional - sage.combinat sage.graphs + sage: sc_oc = oc.boundary_complex() + sage: fl_oc = oc.face_lattice() # needs sage.combinat + sage: fl_sc = sc_oc.face_poset() # needs sage.combinat + sage: [len(x) for x in fl_oc.level_sets()] # needs sage.combinat [1, 6, 12, 8, 1] - sage: [len(x) for x in fl_sc.level_sets()] # optional - sage.combinat sage.graphs + sage: [len(x) for x in fl_sc.level_sets()] # needs sage.combinat [6, 12, 8] - sage: sc_oc.euler_characteristic() # optional - sage.graphs + sage: sc_oc.euler_characteristic() 2 - sage: sc_oc.homology() # optional - sage.graphs + sage: sc_oc.homology() {0: 0, 1: 0, 2: Z} The polyhedron should be simplicial:: @@ -556,7 +559,7 @@ def is_inscribed(self, certificate=False): sage: V = P.Vrepresentation() sage: H = P.Hrepresentation() sage: parent = P.parent() - sage: for V1 in Permutations(V): # optional - sage.combinat + sage: for V1 in Permutations(V): ....: P1 = parent._element_constructor_( ....: [V1, [], []], [H, []], Vrep_minimal=True, Hrep_minimal=True) ....: assert P1.is_inscribed() @@ -624,7 +627,7 @@ def hyperplane_arrangement(self): EXAMPLES:: sage: p = polytopes.hypercube(2) - sage: p.hyperplane_arrangement() # optional - sage.combinat + sage: p.hyperplane_arrangement() Arrangement <-t0 + 1 | -t1 + 1 | t1 + 1 | t0 + 1> """ names = tuple('t' + str(i) for i in range(self.ambient_dim())) @@ -680,10 +683,10 @@ def normal_fan(self, direction='inner'): ... ValueError: the normal fan is only defined for full-dimensional polytopes - sage: R = Polyhedron(vertices=[[0, 0], # optional - sage.rings.number_field sage.symbolic + sage: R = Polyhedron(vertices=[[0, 0], # needs sage.rings.number_field sage.symbolic ....: [AA(sqrt(2)), 0], ....: [0, AA(sqrt(2))]]) - sage: R.normal_fan() # optional - sage.rings.number_field sage.symbolic + sage: R.normal_fan() # needs sage.rings.number_field sage.symbolic Traceback (most recent call last): ... NotImplementedError: normal fan handles only polytopes over the rationals @@ -764,8 +767,8 @@ def face_fan(self): The polytope has to have rational coordinates:: - sage: S = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: S.face_fan() # optional - sage.rings.number_field + sage: S = polytopes.dodecahedron() # needs sage.rings.number_field + sage: S.face_fan() # needs sage.rings.number_field Traceback (most recent call last): ... NotImplementedError: face fan handles only polytopes over the rationals @@ -856,8 +859,8 @@ def barycentric_subdivision(self, subdivision_frac=None): sage: P.barycentric_subdivision() A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices - sage: P = polytopes.regular_polygon(4, base_ring=QQ) # optional - sage.rings.number_field - sage: P.barycentric_subdivision() # optional - sage.rings.number_field + sage: P = polytopes.regular_polygon(4, base_ring=QQ) # needs sage.rings.number_field + sage: P.barycentric_subdivision() # needs sage.rings.number_field A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 8 vertices @@ -969,19 +972,20 @@ def permutations_to_matrices(self, conj_class_reps, acting_group=None, additiona `\pm 1` 2-dimensional square. The permutations are written in terms of the vertices of the square:: - sage: square = Polyhedron(vertices=[[1,1], [-1,1], # optional - pynormaliz + sage: # optional - pynormaliz, needs sage.groups + sage: square = Polyhedron(vertices=[[1,1], [-1,1], ....: [-1,-1], [1,-1]], ....: backend='normaliz') - sage: square.vertices() # optional - pynormaliz + sage: square.vertices() (A vertex at (-1, -1), A vertex at (-1, 1), A vertex at (1, -1), A vertex at (1, 1)) - sage: aut_square = square.restricted_automorphism_group(output='permutation') # optional - pynormaliz sage.groups - sage: conj_reps = aut_square.conjugacy_classes_representatives() # optional - pynormaliz sage.groups - sage: gens_dict = square.permutations_to_matrices(conj_reps) # optional - pynormaliz sage.groups - sage: rotation_180 = aut_square([(0,3),(1,2)]) # optional - pynormaliz sage.groups - sage: rotation_180, gens_dict[rotation_180] # optional - pynormaliz sage.groups + sage: aut_square = square.restricted_automorphism_group(output='permutation') + sage: conj_reps = aut_square.conjugacy_classes_representatives() + sage: gens_dict = square.permutations_to_matrices(conj_reps) + sage: rotation_180 = aut_square([(0,3),(1,2)]) + sage: rotation_180, gens_dict[rotation_180] ( [-1 0 0] [ 0 -1 0] @@ -990,13 +994,14 @@ def permutations_to_matrices(self, conj_class_reps, acting_group=None, additiona This example tests the functionality for additional elements:: + sage: # needs sage.groups sage.rings.real_mpfr sage: C = polytopes.cross_polytope(2) - sage: G = C.restricted_automorphism_group(output='permutation') # optional - sage.groups sage.rings.real_mpfr - sage: conj_reps = G.conjugacy_classes_representatives() # optional - sage.groups sage.rings.real_mpfr - sage: add_elt = G([(0, 2, 3, 1)]) # optional - sage.groups sage.rings.real_mpfr - sage: dict = C.permutations_to_matrices(conj_reps, # optional - sage.groups sage.rings.real_mpfr + sage: G = C.restricted_automorphism_group(output='permutation') + sage: conj_reps = G.conjugacy_classes_representatives() + sage: add_elt = G([(0, 2, 3, 1)]) + sage: dict = C.permutations_to_matrices(conj_reps, ....: additional_elts=[add_elt]) - sage: dict[add_elt] # optional - sage.groups sage.rings.real_mpfr + sage: dict[add_elt] [ 0 1 0] [-1 0 0] [ 0 0 1] @@ -1063,7 +1068,7 @@ def bounding_box(self, integral=False, integral_hull=False): (None, None) sage: Polyhedron([(1/3,2/3), (3/3, 4/3)]).bounding_box(integral_hull=True) ((1, 1), (1, 1)) - sage: polytopes.buckyball(exact=False).bounding_box() # optional - sage.groups + sage: polytopes.buckyball(exact=False).bounding_box() # needs sage.groups ((-0.8090169944, -0.8090169944, -0.8090169944), (0.8090169944, 0.8090169944, 0.8090169944)) @@ -1143,38 +1148,39 @@ def _polymake_init_(self): Non-pointed polyhedron:: + sage: # optional - jupymake sage: P = Polyhedron(vertices=[[1, 0], [0, 1]], lines=[[1, 0]]) - sage: PP = polymake(P) # optional - jupymake - sage: PP.VERTICES # optional - jupymake + sage: PP = polymake(P) + sage: PP.VERTICES 1 0 1 1 0 0 - sage: PP.FACETS # optional - jupymake + sage: PP.FACETS 1 0 -1 0 0 1 - sage: PP.LINEALITY_SPACE # optional - jupymake + sage: PP.LINEALITY_SPACE 0 1 0 Algebraic polyhedron:: - sage: P = polytopes.dodecahedron(); P # optional - sage.rings.number_field + sage: P = polytopes.dodecahedron(); P # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 defined as the convex hull of 20 vertices - sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake sage.rings.number_field + sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake, needs sage.rings.number_field Maybe recompile warning... Polytope >[...] - sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake sage.rings.number_field + sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake, needs sage.rings.number_field 1 -1+1r5 -4+2r5 0 Floating-point polyhedron:: - sage: P = polytopes.dodecahedron(exact=False); P # optional - sage.groups + sage: P = polytopes.dodecahedron(exact=False); P # needs sage.groups A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 20 vertices - sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake sage.groups + sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake, needs sage.groups There may be a recompilation warning... Polytope [...] - sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake sage.groups + sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake, needs sage.groups 1 -0.472135955 0 -1.236067978 """ diff --git a/src/sage/geometry/polyhedron/base0.py b/src/sage/geometry/polyhedron/base0.py index 3f6f9d31f7a..556eefc5148 100644 --- a/src/sage/geometry/polyhedron/base0.py +++ b/src/sage/geometry/polyhedron/base0.py @@ -83,10 +83,10 @@ def __init__(self, parent, Vrep, Hrep, Vrep_minimal=None, Hrep_minimal=None, pre sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field sage: from sage.geometry.polyhedron.parent import Polyhedra_field - sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field + sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field sage: Vrep = [[[0], [1/2], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # optional - sage.rings.number_field + sage: p = Polyhedron_field(parent, Vrep, Hrep, # needs sage.rings.number_field ....: Vrep_minimal=False, Hrep_minimal=True) Traceback (most recent call last): ... @@ -406,13 +406,13 @@ def change_ring(self, base_ring, backend=None): ... TypeError: cannot change the base ring to the Integer Ring - sage: P = polytopes.regular_polygon(3); P # optional - sage.rings.number_field + sage: P = polytopes.regular_polygon(3); P # needs sage.rings.number_field A 2-dimensional polyhedron in AA^2 defined as the convex hull of 3 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() # needs sage.rings.number_field (A vertex at (0.?e-16, 1.000000000000000?), A vertex at (0.866025403784439?, -0.500000000000000?), A vertex at (-0.866025403784439?, -0.500000000000000?)) - sage: P.change_ring(QQ) # optional - sage.rings.number_field + sage: P.change_ring(QQ) # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: cannot change the base ring to the Rational Field @@ -425,11 +425,11 @@ def change_ring(self, base_ring, backend=None): base ring from an exact ring into ``RDF`` may cause a loss of data:: - sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P # optional - sage.rings.number_field + sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P # needs sage.rings.number_field A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: Q = P.change_ring(RDF); Q # optional - sage.rings.number_field + sage: Q = P.change_ring(RDF); Q # needs sage.rings.number_field A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex - sage: P.n_vertices() == Q.n_vertices() # optional - sage.rings.number_field + sage: P.n_vertices() == Q.n_vertices() # needs sage.rings.number_field False """ from sage.categories.rings import Rings @@ -577,8 +577,8 @@ def is_compact(self): EXAMPLES:: - sage: p = polytopes.icosahedron() # optional - sage.rings.number_field - sage: p.is_compact() # optional - sage.rings.number_field + sage: p = polytopes.icosahedron() # needs sage.rings.number_field + sage: p.is_compact() # needs sage.rings.number_field True sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0],[0,0,0,1],[1,-1,0,0]]) sage: p.is_compact() @@ -890,11 +890,12 @@ def inequalities(self): An inequality (0, 1, 0) x + 0 >= 0, An inequality (0, 0, 1) x + 0 >= 0) - sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4])) # optional - sage.combinat - sage: ieqs = p3.inequalities() # optional - sage.combinat - sage: ieqs[0] # optional - sage.combinat + sage: # needs sage.combinat + sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4])) + sage: ieqs = p3.inequalities() + sage: ieqs[0] An inequality (0, 1, 1, 1) x - 6 >= 0 - sage: list(_) # optional - sage.combinat + sage: list(_) [-6, 0, 1, 1, 1] """ return tuple(self.inequality_generator()) @@ -915,13 +916,14 @@ def inequalities_list(self): sage: p.inequalities_list()[0:3] [[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] - sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4])) # optional - sage.combinat - sage: ieqs = p3.inequalities_list() # optional - sage.combinat - sage: ieqs[0] # optional - sage.combinat + sage: # needs sage.combinat + sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4])) + sage: ieqs = p3.inequalities_list() + sage: ieqs[0] [-6, 0, 1, 1, 1] - sage: ieqs[-1] # optional - sage.combinat + sage: ieqs[-1] [-3, 0, 1, 0, 1] - sage: ieqs == [list(x) for x in p3.inequality_generator()] # optional - sage.combinat + sage: ieqs == [list(x) for x in p3.inequality_generator()] True """ return [list(x) for x in self.inequality_generator()] @@ -1317,8 +1319,8 @@ def backend(self): sage: triangle = Polyhedron(vertices = [[1, 0], [0, 1], [1, 1]]) sage: triangle.backend() 'ppl' - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: D.backend() # optional - sage.rings.number_field + sage: D = polytopes.dodecahedron() # needs sage.rings.number_field + sage: D.backend() # needs sage.rings.number_field 'field' sage: P = Polyhedron([[1.23]]) sage: P.backend() @@ -1352,10 +1354,10 @@ def cdd_Hrepresentation(self): end - sage: triangle = Polyhedron(vertices=[[1,0], [0,1], [1,1]], base_ring=AA) # optional - sage.rings.number_field - sage: triangle.base_ring() # optional - sage.rings.number_field + sage: triangle = Polyhedron(vertices=[[1,0], [0,1], [1,1]], base_ring=AA) # needs sage.rings.number_field + sage: triangle.base_ring() # needs sage.rings.number_field Algebraic Real Field - sage: triangle.cdd_Hrepresentation() # optional - sage.rings.number_field + sage: triangle.cdd_Hrepresentation() # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: the base ring must be ZZ, QQ, or RDF diff --git a/src/sage/geometry/polyhedron/base1.py b/src/sage/geometry/polyhedron/base1.py index 9236996fb0a..77b7bf4427e 100644 --- a/src/sage/geometry/polyhedron/base1.py +++ b/src/sage/geometry/polyhedron/base1.py @@ -95,14 +95,15 @@ def __hash__(self): r""" TESTS:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: p = Polyhedron(vertices=[(0, 1, a), (3, a, 5)], # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(2) + sage: p = Polyhedron(vertices=[(0, 1, a), (3, a, 5)], ....: rays=[(a, 2, 3), (0, 0, 1)], ....: base_ring=K) - sage: q = Polyhedron(vertices=[(3, a, 5), (0, 1, a)], # optional - sage.rings.number_field + sage: q = Polyhedron(vertices=[(3, a, 5), (0, 1, a)], ....: rays=[(0, 0, 1), (a, 2, 3)], ....: base_ring=K) - sage: hash(p) == hash(q) # optional - sage.rings.number_field + sage: hash(p) == hash(q) True """ # TODO: find something better *but* fast @@ -401,11 +402,11 @@ def ambient_vector_space(self, base_field=None): sage: poly_test.ambient_vector_space() is poly_test.ambient() True - sage: poly_test.ambient_vector_space(AA) # optional - sage.rings.number_field + sage: poly_test.ambient_vector_space(AA) # needs sage.rings.number_field Vector space of dimension 4 over Algebraic Real Field sage: poly_test.ambient_vector_space(RDF) Vector space of dimension 4 over Real Double Field - sage: poly_test.ambient_vector_space(SR) # optional - sage.symbolic + sage: poly_test.ambient_vector_space(SR) # needs sage.symbolic Vector space of dimension 4 over Symbolic Ring """ return self.Vrepresentation_space().vector_space(base_field=base_field) @@ -620,14 +621,15 @@ def contains(self, point): The point need not have coordinates in the same field as the polyhedron:: + sage: # needs sage.symbolic sage: ray = Polyhedron(vertices=[(0,0)], rays=[(1,0)], base_ring=QQ) - sage: ray.contains([sqrt(2)/3,0]) # irrational coordinates are ok # optional - sage.symbolic + sage: ray.contains([sqrt(2)/3,0]) # irrational coordinates are ok True - sage: a = var('a') # optional - sage.symbolic - sage: ray.contains([a,0]) # a might be negative! # optional - sage.symbolic + sage: a = var('a') + sage: ray.contains([a,0]) # a might be negative! False - sage: assume(a>0) # optional - sage.symbolic - sage: ray.contains([a,0]) # optional - sage.symbolic + sage: assume(a>0) + sage: ray.contains([a,0]) True sage: ray.contains(['hello', 'kitty']) # no common ring for coordinates False diff --git a/src/sage/geometry/polyhedron/base2.py b/src/sage/geometry/polyhedron/base2.py index 41ec3ad203d..0594d0c6708 100644 --- a/src/sage/geometry/polyhedron/base2.py +++ b/src/sage/geometry/polyhedron/base2.py @@ -95,7 +95,7 @@ def is_lattice_polytope(self): sage: polytopes.cross_polytope(3).is_lattice_polytope() True - sage: polytopes.regular_polygon(5).is_lattice_polytope() # optional - sage.rings.number_field + sage: polytopes.regular_polygon(5).is_lattice_polytope() # needs sage.rings.number_field False """ if not self.is_compact(): @@ -145,7 +145,7 @@ def lattice_polytope(self, envelope=False): sage: P = Polyhedron(vertices=[(1, 0), (0, 1), (-1, 0), (0, -1)]) sage: lp = P.lattice_polytope(); lp 2-d reflexive polytope... in 2-d lattice M - sage: lp # optional - palp polytopes_db + sage: lp # optional - polytopes_db, needs palp 2-d reflexive polytope #3 in 2-d lattice M sage: lp.vertices() M(-1, 0), @@ -164,7 +164,7 @@ def lattice_polytope(self, envelope=False): to add the argument "envelope=True" to compute an enveloping lattice polytope. sage: lp = P.lattice_polytope(True) - sage: lp # optional - palp polytopes_db + sage: lp # optional - polytopes_db, needs palp 2-d reflexive polytope #5 in 2-d lattice M sage: lp.vertices() M(-1, 0), @@ -208,9 +208,9 @@ def _integral_points_PALP(self): EXAMPLES:: - sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)])._integral_points_PALP() # optional - palp + sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)])._integral_points_PALP() # needs palp [M(-1, -1), M(0, 1), M(1, 0), M(1, 1), M(0, 0)] - sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)]).lattice_polytope(True).points() # optional - palp + sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)]).lattice_polytope(True).points() # needs palp M(-1, -1), M(-1, 0), M( 0, -1), @@ -219,7 +219,7 @@ def _integral_points_PALP(self): M( 1, 0), M( 0, 0) in 2-d lattice M - sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)])._integral_points_PALP() # optional - palp + sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)])._integral_points_PALP() # needs palp [M(1, 1), M(0, 1), M(1, 0), M(0, 0)] """ if not self.is_compact(): @@ -263,10 +263,11 @@ def h_star_vector(self): volume = `\frac{1}{dim(S)!}`) is always 1. Here we test this on simplices up to dimension 3:: - sage: s1 = polytopes.simplex(1,backend='normaliz') # optional - pynormaliz - sage: s2 = polytopes.simplex(2,backend='normaliz') # optional - pynormaliz - sage: s3 = polytopes.simplex(3,backend='normaliz') # optional - pynormaliz - sage: [s1.h_star_vector(), s2.h_star_vector(), s3.h_star_vector()] # optional - pynormaliz + sage: # optional - pynormaliz + sage: s1 = polytopes.simplex(1,backend='normaliz') + sage: s2 = polytopes.simplex(2,backend='normaliz') + sage: s3 = polytopes.simplex(3,backend='normaliz') + sage: [s1.h_star_vector(), s2.h_star_vector(), s3.h_star_vector()] [[1], [1], [1]] For a less trivial example, we compute the `h^*`-vector of the @@ -276,8 +277,8 @@ def h_star_vector(self): sage: cube = polytopes.cube(intervals='zero_one', backend='normaliz') # optional - pynormaliz sage: cube.h_star_vector() # optional - pynormaliz [1, 4, 1] - sage: from sage.combinat.combinat import eulerian_number # optional - sage.combinat - sage: [eulerian_number(3,i) for i in range(3)] # optional - sage.combinat + sage: from sage.combinat.combinat import eulerian_number + sage: [eulerian_number(3,i) for i in range(3)] [1, 4, 1] TESTS:: @@ -294,8 +295,8 @@ def h_star_vector(self): ... TypeError: The h_star vector is only defined for lattice polytopes - sage: t2 = Polyhedron(vertices=[[AA(sqrt(2))], [1/2]]) # optional - sage.rings.number_field - sage: t2.h_star_vector() # optional - sage.rings.number_field + sage: t2 = Polyhedron(vertices=[[AA(sqrt(2))], [1/2]]) # needs sage.rings.number_field sage.symbolic + sage: t2.h_star_vector() # needs sage.rings.number_field sage.symbolic Traceback (most recent call last): ... TypeError: The h_star vector is only defined for lattice polytopes @@ -446,9 +447,9 @@ def integral_points(self, threshold=100000): sage: pts1 = P.integral_points() # Sage's own code sage: all(P.contains(p) for p in pts1) True - sage: pts2 = LatticePolytope(v).points() # optional - palp + sage: pts2 = LatticePolytope(v).points() # needs palp sage: for p in pts1: p.set_immutable() - sage: set(pts1) == set(pts2) # optional - palp + sage: set(pts1) == set(pts2) # needs palp True sage: timeit('Polyhedron(v).integral_points()') # not tested - random @@ -642,13 +643,15 @@ def random_integral_point(self, **kwds): EXAMPLES:: sage: P = Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)]) - sage: P.random_integral_point() # random + sage: P.random_integral_point() # random (0, 0) sage: P.random_integral_point() in P.integral_points() True - sage: P.random_integral_point(explicit_enumeration_threshold=0, triangulation='cddlib') # random, optional - latte_int + sage: P.random_integral_point(explicit_enumeration_threshold=0, # random, optional - latte_int + ....: triangulation='cddlib') (1, 1) - sage: P.random_integral_point(explicit_enumeration_threshold=0, triangulation='cddlib', foo=7) # optional - latte_int + sage: P.random_integral_point(explicit_enumeration_threshold=0, # optional - latte_int + ....: triangulation='cddlib', foo=7) Traceback (most recent call last): ... RuntimeError: ... @@ -765,36 +768,37 @@ def generating_function_of_integral_points(self, **kwds): EXAMPLES:: - sage: P2 = ( - ....: Polyhedron(ieqs=[(0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, -1)]), - ....: Polyhedron(ieqs=[(0, -1, 0, 1), (0, 1, 0, 0), (0, 0, 1, 0)])) - sage: P2[0].generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat + sage: # needs sage.combinat + sage: P2 = (Polyhedron(ieqs=[(0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, -1)]), + ....: Polyhedron(ieqs=[(0, -1, 0, 1), (0, 1, 0, 0), (0, 0, 1, 0)])) + sage: P2[0].generating_function_of_integral_points(sort_factors=True) 1 * (-y0 + 1)^-1 * (-y1 + 1)^-1 * (-y0*y2 + 1)^-1 - sage: P2[1].generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat + sage: P2[1].generating_function_of_integral_points(sort_factors=True) 1 * (-y1 + 1)^-1 * (-y2 + 1)^-1 * (-y0*y2 + 1)^-1 sage: (P2[0] & P2[1]).Hrepresentation() (An equation (1, 0, -1) x + 0 == 0, An inequality (1, 0, 0) x + 0 >= 0, An inequality (0, 1, 0) x + 0 >= 0) - sage: (P2[0] & P2[1]).generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat + sage: (P2[0] & P2[1]).generating_function_of_integral_points(sort_factors=True) 1 * (-y1 + 1)^-1 * (-y0*y2 + 1)^-1 The number of integer partitions `1 \leq r_0 \leq r_1 \leq r_2 \leq r_3 \leq r_4`:: + sage: # needs sage.combinat sage: P = Polyhedron(ieqs=[(-1, 1, 0, 0, 0, 0), (0, -1, 1, 0, 0, 0), ....: (0, 0, -1, 1, 0, 0), (0, 0, 0, -1, 1, 0), ....: (0, 0, 0, 0, -1, 1)]) - sage: f = P.generating_function_of_integral_points(sort_factors=True); f # optional - sage.combinat + sage: f = P.generating_function_of_integral_points(sort_factors=True); f y0*y1*y2*y3*y4 * (-y4 + 1)^-1 * (-y3*y4 + 1)^-1 * (-y2*y3*y4 + 1)^-1 * (-y1*y2*y3*y4 + 1)^-1 * (-y0*y1*y2*y3*y4 + 1)^-1 - sage: f = f.value() # optional - sage.combinat - sage: P. = PowerSeriesRing(ZZ) # optional - sage.combinat - sage: c = f.subs({y: z for y in f.parent().gens()}); c # optional - sage.combinat + sage: f = f.value() + sage: P. = PowerSeriesRing(ZZ) + sage: c = f.subs({y: z for y in f.parent().gens()}); c z^5 + z^6 + 2*z^7 + 3*z^8 + 5*z^9 + 7*z^10 + 10*z^11 + 13*z^12 + 18*z^13 + 23*z^14 + 30*z^15 + 37*z^16 + 47*z^17 + 57*z^18 + 70*z^19 + 84*z^20 + 101*z^21 + 119*z^22 + 141*z^23 + 164*z^24 + O(z^25) - sage: ([Partitions(k, length=5).cardinality() for k in range(5,20)] == # optional - sage.combinat + sage: ([Partitions(k, length=5).cardinality() for k in range(5,20)] == ....: c.truncate().coefficients(sparse=False)[5:20]) True diff --git a/src/sage/geometry/polyhedron/base3.py b/src/sage/geometry/polyhedron/base3.py index 807714afde3..8904d9fac82 100644 --- a/src/sage/geometry/polyhedron/base3.py +++ b/src/sage/geometry/polyhedron/base3.py @@ -135,8 +135,9 @@ def slack_matrix(self): [1 0 1 0 0 1] [1 0 0 0 1 1] - sage: P = polytopes.dodecahedron().faces(2)[0].as_polyhedron() # optional - sage.rings.number_field - sage: P.slack_matrix() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron().faces(2)[0].as_polyhedron() + sage: P.slack_matrix() [1/2*sqrt5 - 1/2 0 0 1 1/2*sqrt5 - 1/2 0] [ 0 0 1/2*sqrt5 - 1/2 1/2*sqrt5 - 1/2 1 0] [ 0 1/2*sqrt5 - 1/2 1 0 1/2*sqrt5 - 1/2 0] @@ -153,7 +154,7 @@ def slack_matrix(self): sage: Polyhedron().slack_matrix() [] - sage: Polyhedron(base_ring=QuadraticField(2)).slack_matrix().base_ring() # optional - sage.rings.number_field + sage: Polyhedron(base_ring=QuadraticField(2)).slack_matrix().base_ring() # needs sage.rings.number_field Number Field in a with defining polynomial x^2 - 2 with a = 1.41... """ if not self.n_Vrepresentation() or not self.n_Hrepresentation(): @@ -274,7 +275,7 @@ def incidence_matrix(self): sage: P = polytopes.twenty_four_cell() sage: M = P.incidence_matrix() - sage: sum(sum(x) for x in M) == P.flag_f_vector(0, 3) # optional - sage.combinat + sage: sum(sum(x) for x in M) == P.flag_f_vector(0, 3) # needs sage.combinat True TESTS: @@ -287,10 +288,11 @@ def incidence_matrix(self): Test that this method works for inexact base ring (``cdd`` sets the cache already):: - sage: P = polytopes.dodecahedron(exact=False) # optional - sage.groups - sage: M = P.incidence_matrix.cache # optional - sage.groups - sage: P.incidence_matrix.clear_cache() # optional - sage.groups - sage: M == P.incidence_matrix() # optional - sage.groups + sage: # needs sage.groups + sage: P = polytopes.dodecahedron(exact=False) + sage: M = P.incidence_matrix.cache + sage: P.incidence_matrix.clear_cache() + sage: M == P.incidence_matrix() True """ if self.base_ring() in (ZZ, QQ): @@ -1008,8 +1010,8 @@ def vertex_adjacency_matrix(self, algorithm=None): sage: M = Q.vertex_adjacency_matrix() sage: sum(M) (4, 4, 3, 3, 4, 4, 4, 3, 3) - sage: G = Q.vertex_graph() # optional - sage.graphs - sage: G.degree() # optional - sage.graphs + sage: G = Q.vertex_graph() # needs sage.graphs + sage: G.degree() # needs sage.graphs [4, 4, 3, 3, 4, 4, 4, 3, 3] TESTS: @@ -1154,11 +1156,11 @@ def simplicity(self): EXAMPLES:: - sage: polytopes.hypersimplex(4,2).simplicity() # optional - sage.combinat + sage: polytopes.hypersimplex(4,2).simplicity() 1 - sage: polytopes.hypersimplex(5,2).simplicity() # optional - sage.combinat + sage: polytopes.hypersimplex(5,2).simplicity() 2 - sage: polytopes.hypersimplex(6,2).simplicity() # optional - sage.combinat + sage: polytopes.hypersimplex(6,2).simplicity() 3 sage: polytopes.simplex(3).simplicity() 3 @@ -1207,7 +1209,7 @@ def simpliciality(self): sage: polytopes.cyclic_polytope(10,4).simpliciality() 3 - sage: polytopes.hypersimplex(5,2).simpliciality() # optional - sage.combinat + sage: polytopes.hypersimplex(5,2).simpliciality() 2 sage: polytopes.cross_polytope(4).simpliciality() 3 @@ -1293,8 +1295,8 @@ def is_pyramid(self, certificate=False): True sage: P.is_pyramid(certificate=True) (True, A vertex at (1, 0, 0, 0)) - sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field - sage: egyptian_pyramid.is_pyramid() # optional - sage.rings.number_field + sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # needs sage.rings.number_field + sage: egyptian_pyramid.is_pyramid() # needs sage.rings.number_field True sage: Q = polytopes.octahedron() sage: Q.is_pyramid() @@ -1463,13 +1465,13 @@ def is_lawrence_polytope(self): EXAMPLES:: - sage: P = polytopes.hypersimplex(5,2) # optional - sage.combinat - sage: L = P.lawrence_polytope() # optional - sage.combinat - sage: L.is_lattice_polytope() # optional - sage.combinat + sage: P = polytopes.hypersimplex(5,2) + sage: L = P.lawrence_polytope() + sage: L.is_lattice_polytope() True - sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # optional - sage.number_field - sage: egyptian_pyramid.is_lawrence_polytope() # optional - sage.number_field + sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # needs sage.number_field + sage: egyptian_pyramid.is_lawrence_polytope() # needs sage.number_field True sage: polytopes.octahedron().is_lawrence_polytope() diff --git a/src/sage/geometry/polyhedron/base4.py b/src/sage/geometry/polyhedron/base4.py index ae092615ac5..5313d64b357 100644 --- a/src/sage/geometry/polyhedron/base4.py +++ b/src/sage/geometry/polyhedron/base4.py @@ -95,7 +95,7 @@ def vertex_facet_graph(self, labels=True): sage: P = polytopes.cube() sage: G = P.vertex_facet_graph(); G Digraph on 14 vertices - sage: G.vertices(key = lambda v: str(v)) + sage: G.vertices(sort=True, key=lambda v: str(v)) [A vertex at (-1, -1, -1), A vertex at (-1, -1, 1), A vertex at (-1, 1, -1), diff --git a/src/sage/geometry/polyhedron/base5.py b/src/sage/geometry/polyhedron/base5.py index 906334eda3d..89feb2d7b0f 100644 --- a/src/sage/geometry/polyhedron/base5.py +++ b/src/sage/geometry/polyhedron/base5.py @@ -324,7 +324,7 @@ def _test_pyramid(self, tester=None, **options): TESTS: - sage: polytopes.regular_polygon(4)._test_pyramid() # optional - sage.rings.number_field + sage: polytopes.regular_polygon(4)._test_pyramid() # needs sage.rings.number_field """ if tester is None: tester = self._tester(**options) @@ -1057,7 +1057,7 @@ def join(self, other): sage: C = polytopes.hypercube(5) sage: S = Polyhedron([[1]]) - sage: C.join(S).is_combinatorially_isomorphic(C.pyramid()) # optional - sage.graphs + sage: C.join(S).is_combinatorially_isomorphic(C.pyramid()) # needs sage.graphs True sage: P = polytopes.simplex(backend='cdd') @@ -1355,10 +1355,11 @@ def intersection(self, other): Check that :trac:`19012` is fixed:: - sage: K. = QuadraticField(5) # optional - sage.rings.number_field - sage: P = Polyhedron([[0, 0], [0, a], [1, 1]]) # optional - sage.rings.number_field - sage: Q = Polyhedron(ieqs=[[-1, a, 1]]) # optional - sage.rings.number_field - sage: P.intersection(Q) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(5) + sage: P = Polyhedron([[0, 0], [0, a], [1, 1]]) + sage: Q = Polyhedron(ieqs=[[-1, a, 1]]) + sage: P.intersection(Q) A 2-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?)^2 defined as the convex hull of 4 vertices @@ -1712,23 +1713,25 @@ def linear_transformation(self, linear_transf, new_base_ring=None): sage: b3_proj = proj_mat * b3; b3_proj A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices - sage: square = polytopes.regular_polygon(4) # optional - sage.rings.number_field - sage: square.vertices_list() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: square = polytopes.regular_polygon(4) + sage: square.vertices_list() [[0, -1], [1, 0], [-1, 0], [0, 1]] - sage: transf = matrix([[1,1], [0,1]]) # optional - sage.rings.number_field - sage: sheared = transf * square # optional - sage.rings.number_field - sage: sheared.vertices_list() # optional - sage.rings.number_field + sage: transf = matrix([[1,1], [0,1]]) + sage: sheared = transf * square + sage: sheared.vertices_list() [[-1, -1], [1, 0], [-1, 0], [1, 1]] - sage: sheared == square.linear_transformation(transf) # optional - sage.rings.number_field + sage: sheared == square.linear_transformation(transf) True Specifying the new base ring may avoid coercion failure:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: L. = QuadraticField(3) # optional - sage.rings.number_field - sage: P = polytopes.cube()*sqrt2 # optional - sage.rings.number_field - sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]]) # optional - sage.rings.number_field - sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0]) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(2) + sage: L. = QuadraticField(3) + sage: P = polytopes.cube()*sqrt2 + sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]]) + sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0]) A 3-dimensional polyhedron in (Number Field in sqrt2sqrt3 with defining polynomial x^4 - 10*x^2 + 1 with sqrt2sqrt3 = 0.3178372451957823?)^3 @@ -1736,7 +1739,7 @@ def linear_transformation(self, linear_transf, new_base_ring=None): Linear transformation without specified new base ring fails in this case:: - sage: M*P # optional - sage.rings.number_field + sage: M*P # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: @@ -1760,7 +1763,7 @@ def linear_transformation(self, linear_transf, new_base_ring=None): A 3-dimensional polyhedron in RDF^4 defined as the convex hull of 5 vertices sage: (1/1 * proj_mat) * b3 A 3-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices - sage: (AA(2).sqrt() * proj_mat) * b3 # optional - sage.rings.number_field + sage: (AA(2).sqrt() * proj_mat) * b3 # needs sage.rings.number_field A 3-dimensional polyhedron in AA^4 defined as the convex hull of 5 vertices Check that zero-matrices act correctly:: @@ -2014,7 +2017,7 @@ def face_truncation(self, face, linear_coefficients=None, cut_frac=None): A vertex at (-1/3, 1, 1), A vertex at (-1/3, 1, -1), A vertex at (-1/3, -1, -1)) - sage: face_trunc.face_lattice().is_isomorphic(Cube.face_lattice()) # optional - sage.combinat sage.graphs + sage: face_trunc.face_lattice().is_isomorphic(Cube.face_lattice()) # needs sage.combinat sage.graphs True TESTS: @@ -2113,15 +2116,16 @@ def stack(self, face, position=None): (1, 9, 16, 9, 1) sage: stacked_square_large = cube.stack(square_face, position=10) - sage: hexaprism = polytopes.regular_polygon(6).prism() # optional - sage.rings.number_field - sage: hexaprism.f_vector() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: hexaprism = polytopes.regular_polygon(6).prism() + sage: hexaprism.f_vector() (1, 12, 18, 8, 1) - sage: square_face = hexaprism.faces(2)[2] # optional - sage.rings.number_field - sage: stacked_hexaprism = hexaprism.stack(square_face) # optional - sage.rings.number_field - sage: stacked_hexaprism.f_vector() # optional - sage.rings.number_field + sage: square_face = hexaprism.faces(2)[2] + sage: stacked_hexaprism = hexaprism.stack(square_face) + sage: stacked_hexaprism.f_vector() (1, 13, 22, 11, 1) - sage: hexaprism.stack(square_face, position=4) # optional - sage.rings.number_field + sage: hexaprism.stack(square_face, position=4) # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: the chosen position is too large @@ -2241,17 +2245,18 @@ def wedge(self, face, width=1): EXAMPLES:: - sage: P_4 = polytopes.regular_polygon(4) # optional - sage.rings.number_field - sage: W1 = P_4.wedge(P_4.faces(1)[0]); W1 # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P_4 = polytopes.regular_polygon(4) + sage: W1 = P_4.wedge(P_4.faces(1)[0]); W1 A 3-dimensional polyhedron in AA^3 defined as the convex hull of 6 vertices - sage: triangular_prism = polytopes.regular_polygon(3).prism() # optional - sage.rings.number_field - sage: W1.is_combinatorially_isomorphic(triangular_prism) # optional - sage.graphs sage.rings.number_field + sage: triangular_prism = polytopes.regular_polygon(3).prism() + sage: W1.is_combinatorially_isomorphic(triangular_prism) # needs sage.graphs True - sage: Q = polytopes.hypersimplex(4,2) # optional - sage.combinat - sage: W2 = Q.wedge(Q.faces(2)[7]); W2 # optional - sage.combinat + sage: Q = polytopes.hypersimplex(4,2) + sage: W2 = Q.wedge(Q.faces(2)[7]); W2 A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 9 vertices - sage: W2.vertices() # optional - sage.combinat + sage: W2.vertices() (A vertex at (1, 1, 0, 0, 1), A vertex at (1, 1, 0, 0, -1), A vertex at (1, 0, 1, 0, 1), @@ -2262,9 +2267,9 @@ def wedge(self, face, width=1): A vertex at (0, 1, 1, 0, 0), A vertex at (0, 1, 0, 1, 0)) - sage: W3 = Q.wedge(Q.faces(1)[11]); W3 # optional - sage.combinat + sage: W3 = Q.wedge(Q.faces(1)[11]); W3 A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 10 vertices - sage: W3.vertices() # optional - sage.combinat + sage: W3.vertices() (A vertex at (1, 1, 0, 0, -2), A vertex at (1, 1, 0, 0, 2), A vertex at (1, 0, 1, 0, -2), @@ -2277,9 +2282,9 @@ def wedge(self, face, width=1): A vertex at (0, 1, 1, 0, -1)) sage: C_3_7 = polytopes.cyclic_polytope(3,7) - sage: P_6 = polytopes.regular_polygon(6) # optional - sage.rings.number_field - sage: W4 = P_6.wedge(P_6.faces(1)[0]) # optional - sage.rings.number_field - sage: W4.is_combinatorially_isomorphic(C_3_7.polar()) # optional - sage.graphs sage.rings.number_field + sage: P_6 = polytopes.regular_polygon(6) # needs sage.rings.number_field + sage: W4 = P_6.wedge(P_6.faces(1)[0]) # needs sage.rings.number_field + sage: W4.is_combinatorially_isomorphic(C_3_7.polar()) # needs sage.graphs sage.rings.number_field True REFERENCES: @@ -2363,10 +2368,11 @@ def face_split(self, face): EXAMPLES:: - sage: pentagon = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: f = pentagon.faces(1)[0] # optional - sage.rings.number_field - sage: fsplit_pentagon = pentagon.face_split(f) # optional - sage.rings.number_field - sage: fsplit_pentagon.f_vector() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: pentagon = polytopes.regular_polygon(5) + sage: f = pentagon.faces(1)[0] + sage: fsplit_pentagon = pentagon.face_split(f) + sage: fsplit_pentagon.f_vector() (1, 7, 14, 9, 1) TESTS: @@ -2450,7 +2456,7 @@ def _test_lawrence(self, tester=None, **options): Check that :trac:`28725` is fixed:: - sage: polytopes.regular_polygon(3)._test_lawrence() # optional - sage.rings.number_field + sage: polytopes.regular_polygon(3)._test_lawrence() # needs sage.rings.number_field Check that :trac:`30293` is fixed:: @@ -2559,10 +2565,11 @@ def one_point_suspension(self, vertex): sage: ops_cube.f_vector() (1, 9, 24, 24, 9, 1) - sage: pentagon = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: v = pentagon.vertices()[0] # optional - sage.rings.number_field - sage: ops_pentagon = pentagon.one_point_suspension(v) # optional - sage.rings.number_field - sage: ops_pentagon.f_vector() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: pentagon = polytopes.regular_polygon(5) + sage: v = pentagon.vertices()[0] + sage: ops_pentagon = pentagon.one_point_suspension(v) + sage: ops_pentagon.f_vector() (1, 6, 12, 8, 1) It works with a polyhedral face as well:: diff --git a/src/sage/geometry/polyhedron/base6.py b/src/sage/geometry/polyhedron/base6.py index e125b5228a0..b9d23daefa1 100644 --- a/src/sage/geometry/polyhedron/base6.py +++ b/src/sage/geometry/polyhedron/base6.py @@ -45,9 +45,9 @@ class Polyhedron_base6(Polyhedron_base5): sage: from sage.geometry.polyhedron.base6 import Polyhedron_base6 sage: P = polytopes.cube() - sage: Polyhedron_base6.plot(P) # optional - sage.plot + sage: Polyhedron_base6.plot(P) # needs sage.plot Graphics3d Object - sage: print(Polyhedron_base6.tikz(P, output_type='TikzPicture')) # optional - sage.plot + sage: print(Polyhedron_base6.tikz(P, output_type='TikzPicture')) # needs sage.plot \RequirePackage{luatex85} \documentclass[tikz]{standalone} \begin{document} @@ -130,7 +130,7 @@ class Polyhedron_base6(Polyhedron_base5): \end{document} sage: Q = polytopes.hypercube(4) - sage: Polyhedron_base6.show(Q) # optional - sage.plot + sage: Polyhedron_base6.show(Q) # needs sage.plot sage: Polyhedron_base6.schlegel_projection(Q) The projection of a polyhedron into 3 dimensions @@ -194,55 +194,59 @@ def plot(self, By default, the wireframe is rendered in blue and the fill in green:: - sage: square.plot() # optional - sage.plot + sage: # needs sage.plot + sage: square.plot() Graphics object consisting of 6 graphics primitives - sage: point.plot() # optional - sage.plot + sage: point.plot() Graphics object consisting of 1 graphics primitive - sage: line.plot() # optional - sage.plot + sage: line.plot() Graphics object consisting of 2 graphics primitives - sage: cube.plot() # optional - sage.plot + sage: cube.plot() Graphics3d Object - sage: hypercube.plot() # optional - sage.plot + sage: hypercube.plot() Graphics3d Object Draw the lines in red and nothing else:: - sage: square.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: # needs sage.plot + sage: square.plot(point=False, line='red', polygon=False) Graphics object consisting of 4 graphics primitives - sage: point.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: point.plot(point=False, line='red', polygon=False) Graphics object consisting of 0 graphics primitives - sage: line.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: line.plot(point=False, line='red', polygon=False) Graphics object consisting of 1 graphics primitive - sage: cube.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: cube.plot(point=False, line='red', polygon=False) Graphics3d Object - sage: hypercube.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: hypercube.plot(point=False, line='red', polygon=False) Graphics3d Object Draw points in red, no lines, and a blue polygon:: - sage: square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: # needs sage.plot + sage: square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics object consisting of 2 graphics primitives - sage: point.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: point.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics object consisting of 1 graphics primitive - sage: line.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: line.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics object consisting of 1 graphics primitive - sage: cube.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: cube.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics3d Object - sage: hypercube.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: hypercube.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics3d Object If we instead use the ``fill`` and ``wireframe`` options, the coloring depends on the dimension of the object:: - sage: square.plot(fill='green', wireframe='red') # optional - sage.plot + sage: # needs sage.plot + sage: square.plot(fill='green', wireframe='red') Graphics object consisting of 6 graphics primitives - sage: point.plot(fill='green', wireframe='red') # optional - sage.plot + sage: point.plot(fill='green', wireframe='red') Graphics object consisting of 1 graphics primitive - sage: line.plot(fill='green', wireframe='red') # optional - sage.plot + sage: line.plot(fill='green', wireframe='red') Graphics object consisting of 2 graphics primitives - sage: cube.plot(fill='green', wireframe='red') # optional - sage.plot + sage: cube.plot(fill='green', wireframe='red') Graphics3d Object - sage: hypercube.plot(fill='green', wireframe='red') # optional - sage.plot + sage: hypercube.plot(fill='green', wireframe='red') Graphics3d Object It is possible to draw polyhedra up to dimension 4, no matter what the @@ -251,32 +255,32 @@ def plot(self, sage: hcube = polytopes.hypercube(5) sage: facet = hcube.facets()[0].as_polyhedron(); facet A 4-dimensional polyhedron in ZZ^5 defined as the convex hull of 16 vertices - sage: facet.plot() # optional - sage.plot + sage: facet.plot() # needs sage.plot Graphics3d Object For a 3d plot, we may draw the polygons with rainbow colors, using any of the following ways:: - sage: cube.plot(polygon='rainbow') # optional - sage.plot + sage: cube.plot(polygon='rainbow') # needs sage.plot Graphics3d Object - sage: cube.plot(polygon={'color':'rainbow'}) # optional - sage.plot + sage: cube.plot(polygon={'color':'rainbow'}) # needs sage.plot Graphics3d Object - sage: cube.plot(fill='rainbow') # optional - sage.plot + sage: cube.plot(fill='rainbow') # needs sage.plot Graphics3d Object For a 3d plot, the size of a point, the thickness of a line and the width of an arrow are controlled by the respective parameters:: sage: prism = Polyhedron(vertices=[[0,0,0],[1,0,0],[0,1,0]], rays=[[0,0,1]]) - sage: prism.plot(size=20, thickness=30, width=1) # optional - sage.plot + sage: prism.plot(size=20, thickness=30, width=1) # needs sage.plot Graphics3d Object - sage: prism.plot(point={'size':20, 'color':'black'}, # optional - sage.plot + sage: prism.plot(point={'size':20, 'color':'black'}, # needs sage.plot ....: line={'thickness':30, 'width':1, 'color':'black'}, ....: polygon='rainbow') Graphics3d Object TESTS:: - sage: for p in square.plot(): # optional - sage.plot + sage: for p in square.plot(): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) blue Point set defined by 4 point(s) blue Line defined by 2 points @@ -285,18 +289,18 @@ def plot(self, blue Line defined by 2 points green Polygon defined by 4 points - sage: for p in line.plot(): # optional - sage.plot + sage: for p in line.plot(): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) blue Point set defined by 2 point(s) green Line defined by 2 points - sage: for p in point.plot(): # optional - sage.plot + sage: for p in point.plot(): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) green Point set defined by 1 point(s) Draw the lines in red and nothing else:: - sage: for p in square.plot(point=False, line='red', polygon=False): # optional - sage.plot + sage: for p in square.plot(point=False, line='red', polygon=False): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Line defined by 2 points red Line defined by 2 points @@ -305,66 +309,68 @@ def plot(self, Draw vertices in red, no lines, and a blue polygon:: - sage: for p in square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # optional - sage.plot + sage: for p in square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Point set defined by 4 point(s) (0, 0, 1) Polygon defined by 4 points - sage: for p in line.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # optional - sage.plot + sage: for p in line.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Point set defined by 2 point(s) - sage: for p in point.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # optional - sage.plot + sage: for p in point.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Point set defined by 1 point(s) Draw in red without wireframe:: - sage: for p in square.plot(wireframe=False, fill="red"): # optional - sage.plot + sage: for p in square.plot(wireframe=False, fill="red"): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Polygon defined by 4 points - sage: for p in line.plot(wireframe=False, fill="red"): # optional - sage.plot + sage: for p in line.plot(wireframe=False, fill="red"): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Line defined by 2 points - sage: for p in point.plot(wireframe=False, fill="red"): # optional - sage.plot + sage: for p in point.plot(wireframe=False, fill="red"): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Point set defined by 1 point(s) We try to draw the polytope in 2 or 3 dimensions:: - sage: type(Polyhedron(ieqs=[(1,)]).plot()) # optional - sage.plot + sage: # needs sage.plot + sage: type(Polyhedron(ieqs=[(1,)]).plot()) - sage: type(polytopes.hypercube(1).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(1).plot()) - sage: type(polytopes.hypercube(2).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(2).plot()) - sage: type(polytopes.hypercube(3).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(3).plot()) In 4d a projection to 3d is used:: - sage: type(polytopes.hypercube(4).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(4).plot()) # needs sage.plot - sage: type(polytopes.hypercube(5).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(5).plot()) Traceback (most recent call last): ... NotImplementedError: plotting of 5-dimensional polyhedra not implemented If the polyhedron is not full-dimensional, the :meth:`affine_hull_projection` is used if necessary:: - sage: type(Polyhedron([(0,), (1,)]).plot()) # optional - sage.plot + sage: # needs sage.plot + sage: type(Polyhedron([(0,), (1,)]).plot()) - sage: type(Polyhedron([(0,0), (1,1)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0), (1,1)]).plot()) - sage: type(Polyhedron([(0,0,0), (1,1,1)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0,0), (1,1,1)]).plot()) - sage: type(Polyhedron([(0,0,0,0), (1,1,1,1)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0,0,0), (1,1,1,1)]).plot()) - sage: type(Polyhedron([(0,0,0,0,0), (1,1,1,1,1)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0,0,0,0), (1,1,1,1,1)]).plot()) - sage: type(Polyhedron([(0,0,0,0), (1,1,1,1), (1,0,0,0)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0,0,0), (1,1,1,1), (1,0,0,0)]).plot()) TESTS: @@ -382,28 +388,29 @@ def plot(self, Check that :trac:`31802` is fixed:: + sage: # needs sage.plot sage: halfspace = Polyhedron(rays=[(0, 0, 1)], lines=[(1, 0, 0), (0, 1, 0)]) sage: len(halfspace.projection().arrows) 5 - sage: halfspace.plot(fill=(0, 1, 0)) # optional - sage.plot + sage: halfspace.plot(fill=(0, 1, 0)) Graphics3d Object sage: fullspace = Polyhedron(lines=[(1, 0, 0), (0, 1, 0), (0, 0, 1)]) sage: len(fullspace.projection().arrows) 6 - sage: fullspace.plot(color=(1, 0, 0), alpha=0.5) # optional - sage.plot + sage: fullspace.plot(color=(1, 0, 0), alpha=0.5) Graphics3d Object sage: cone = Polyhedron(rays=[(1, 0, 0), (0, 1, 0), (0, 0, 1)]) - sage: cone.plot(fill='rainbow', alpha=0.6) # optional - sage.plot + sage: cone.plot(fill='rainbow', alpha=0.6) Graphics3d Object sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0)], rays=[(-1, 1, 0), (1, 1, 0), (0, 0, 1)]) - sage: p.plot(fill='mediumspringgreen', point='red', size=30, width=2) # optional - sage.plot + sage: p.plot(fill='mediumspringgreen', point='red', size=30, width=2) Graphics3d Object sage: cylinder = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0)], lines=[(0, 0, 1)]) - sage: cylinder.plot(fill='red') # check it is not all black # optional - sage.plot + sage: cylinder.plot(fill='red') # check it is not all black # needs sage.plot Graphics3d Object sage: quarter = Polyhedron(rays=[(-1, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)]) - sage: quarter.plot(fill='rainbow') # check it is not all black nor with too many colors # optional - sage.plot + sage: quarter.plot(fill='rainbow') # check it is not all black nor with too many colors # needs sage.plot Graphics3d Object """ def merge_options(*opts): @@ -472,7 +479,7 @@ def show(self, **kwds): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: square.show(point='red') # optional - sage.plot + sage: square.show(point='red') # needs sage.plot """ self.plot(**kwds).show() @@ -546,9 +553,10 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, EXAMPLES:: + sage: # needs sage.plot sage: co = polytopes.cuboctahedron() - sage: Img = co.tikz([0, 0, 1], 0, output_type='TikzPicture') # optional - sage.plot - sage: Img # optional - sage.plot + sage: Img = co.tikz([0, 0, 1], 0, output_type='TikzPicture') + sage: Img \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -565,7 +573,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: print('\n'.join(Img.content().splitlines()[12:21])) # optional - sage.plot + sage: print('\n'.join(Img.content().splitlines()[12:21])) %% with the command: ._tikz_3d_in_3d and parameters: %% view = [0, 0, 1] %% angle = 0 @@ -575,7 +583,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% opacity = 0.8 %% vertex_color = green %% axis = False - sage: print('\n'.join(Img.content().splitlines()[22:26])) # optional - sage.plot + sage: print('\n'.join(Img.content().splitlines()[22:26])) %% Coordinate of the vertices: %% \coordinate (-1.00000, -1.00000, 0.00000) at (-1.00000, -1.00000, 0.00000); @@ -583,9 +591,9 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, When output type is a :class:`sage.misc.latex_standalone.TikzPicture`:: + sage: # needs sage.plot sage: co = polytopes.cuboctahedron() - sage: t = co.tikz([674, 108, -731], 112, output_type='TikzPicture') # optional - sage.plot - sage: t # optional - sage.plot + sage: t = co.tikz([674, 108, -731], 112, output_type='TikzPicture'); t \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -602,7 +610,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: path_to_file = t.pdf() # not tested # optional - sage.plot + sage: path_to_file = t.pdf() # not tested """ return self.projection().tikz(view, angle, scale, @@ -694,8 +702,8 @@ def gale_transform(self): Check that :trac:`29073` is fixed:: - sage: P = polytopes.icosahedron(exact=False) # optional - sage.groups - sage: sum(P.gale_transform()).norm() < 1e-15 # optional - sage.groups + sage: P = polytopes.icosahedron(exact=False) # needs sage.groups + sage: sum(P.gale_transform()).norm() < 1e-15 # needs sage.groups True """ if not self.is_compact(): @@ -786,8 +794,8 @@ def render_solid(self, **kwds): EXAMPLES:: sage: p = polytopes.hypercube(3) - sage: p_solid = p.render_solid(opacity=.7) # optional - sage.plot - sage: type(p_solid) # optional - sage.plot + sage: p_solid = p.render_solid(opacity=.7) # needs sage.plot + sage: type(p_solid) # needs sage.plot """ proj = self.projection() @@ -805,8 +813,8 @@ def render_wireframe(self, **kwds): EXAMPLES:: sage: p = Polyhedron([[1,2,],[1,1],[0,0]]) - sage: p_wireframe = p.render_wireframe() # optional - sage.plot - sage: p_wireframe._objects # optional - sage.plot + sage: p_wireframe = p.render_wireframe() # needs sage.plot + sage: p_wireframe._objects # needs sage.plot [Line defined by 2 points, Line defined by 2 points, Line defined by 2 points] """ proj = self.projection() @@ -855,24 +863,25 @@ def schlegel_projection(self, facet=None, position=None): sage: tfcube.facets()[-1] A 3-dimensional face of a Polyhedron in QQ^4 defined as the convex hull of 8 vertices sage: sp = tfcube.schlegel_projection(tfcube.facets()[-1]) - sage: sp.plot() # optional - sage.plot + sage: sp.plot() # needs sage.plot Graphics3d Object The same truncated cube but see inside the tetrahedral facet:: sage: tfcube.facets()[4] A 3-dimensional face of a Polyhedron in QQ^4 defined as the convex hull of 4 vertices - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4]) # optional - sage.symbolic - sage: sp.plot() # optional - sage.plot sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4]) # needs sage.symbolic + sage: sp.plot() # needs sage.plot sage.symbolic Graphics3d Object A different values of ``position`` changes the projection:: - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 1/2) # optional - sage.symbolic - sage: sp.plot() # optional - sage.plot sage.symbolic + sage: # needs sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 1/2) + sage: sp.plot() # needs sage.plot Graphics3d Object - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 4) # optional - sage.symbolic - sage: sp.plot() # optional - sage.plot sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 4) + sage: sp.plot() # needs sage.plot Graphics3d Object A value which is too large give a projection point that sees more than @@ -941,7 +950,7 @@ def _affine_hull_projection(self, *, sage: P1 = Polyhedron(vertices=[[-1, 1], [0, -1], [0, 0], [-1, -1]]) sage: P2 = Polyhedron(vertices=[[1, 1], [1, -1], [0, -1], [0, 0]]) sage: P = P1.intersection(P2) - sage: A, b = P.affine_hull_projection(as_affine_map=True, # optional - sage.rings.number_field + sage: A, b = P.affine_hull_projection(as_affine_map=True, ....: orthonormal=True, extend=True) sage: Polyhedron([(2,3,4)]).affine_hull_projection() @@ -953,7 +962,7 @@ def _affine_hull_projection(self, *, 'field' sage: P = Polyhedron(vertices=[[0,0], [1,0]], backend='field') - sage: P.affine_hull_projection(orthogonal=True, orthonormal=True, # optional - sage.rings.number_field + sage: P.affine_hull_projection(orthogonal=True, orthonormal=True, ....: extend=True).backend() 'field' @@ -968,11 +977,11 @@ def _affine_hull_projection(self, *, sage: P = Polyhedron(V) sage: P.affine_hull_projection() A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 6 vertices - sage: P.affine_hull_projection(orthonormal=True) # optional - sage.symbolic + sage: P.affine_hull_projection(orthonormal=True) # needs sage.symbolic Traceback (most recent call last): ... ValueError: the base ring needs to be extended; try with "extend=True" - sage: P.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.rings.number_field + sage: P.affine_hull_projection(orthonormal=True, extend=True) # needs sage.rings.number_field A 4-dimensional polyhedron in AA^4 defined as the convex hull of 6 vertices """ result = AffineHullProjectionData() @@ -1188,13 +1197,13 @@ def affine_hull_projection(self, A 1-dimensional polyhedron in QQ^1 defined as the convex hull of 2 vertices sage: A.vertices() (A vertex at (0), A vertex at (2)) - sage: A = L.affine_hull_projection(orthonormal=True) # optional - sage.rings.number_field + sage: A = L.affine_hull_projection(orthonormal=True) # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: the base ring needs to be extended; try with "extend=True" - sage: A = L.affine_hull_projection(orthonormal=True, extend=True); A # optional - sage.rings.number_field + sage: A = L.affine_hull_projection(orthonormal=True, extend=True); A # needs sage.rings.number_field A 1-dimensional polyhedron in AA^1 defined as the convex hull of 2 vertices - sage: A.vertices() # optional - sage.rings.number_field + sage: A.vertices() # needs sage.rings.number_field (A vertex at (1.414213562373095?), A vertex at (0.?e-18)) More generally:: @@ -1220,9 +1229,9 @@ def affine_hull_projection(self, A vertex at (2, 0, 0), A vertex at (1, 3/2, 0), A vertex at (1, 1/2, 4/3)) - sage: A = S.affine_hull_projection(orthonormal=True, extend=True); A # optional - sage.rings.number_field + sage: A = S.affine_hull_projection(orthonormal=True, extend=True); A # needs sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 4 vertices - sage: A.vertices() # optional - sage.rings.number_field + sage: A.vertices() # needs sage.rings.number_field (A vertex at (0.7071067811865475?, 0.4082482904638630?, 1.154700538379252?), A vertex at (0.7071067811865475?, 1.224744871391589?, 0.?e-18), A vertex at (1.414213562373095?, 0.?e-18, 0.?e-18), @@ -1230,103 +1239,108 @@ def affine_hull_projection(self, With the parameter ``minimal`` one can get a minimal base ring:: + sage: # needs sage.rings.number_field sage: s = polytopes.simplex(3) - sage: s_AA = s.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.rings.number_field - sage: s_AA.base_ring() # optional - sage.rings.number_field + sage: s_AA = s.affine_hull_projection(orthonormal=True, extend=True) + sage: s_AA.base_ring() Algebraic Real Field - sage: s_full = s.affine_hull_projection(orthonormal=True, extend=True, # optional - sage.rings.number_field + sage: s_full = s.affine_hull_projection(orthonormal=True, extend=True, ....: minimal=True) - sage: s_full.base_ring() # optional - sage.rings.number_field + sage: s_full.base_ring() Number Field in a with defining polynomial y^4 - 4*y^2 + 1 with a = 0.5176380902050415? More examples with the ``orthonormal`` parameter:: - sage: P = polytopes.permutahedron(3); P # optional - sage.combinat sage.rings.number_field + sage: P = polytopes.permutahedron(3); P A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices - sage: set([F.as_polyhedron().affine_hull_projection( # optional - sage.combinat sage.rings.number_field + sage: set([F.as_polyhedron().affine_hull_projection( # needs sage.combinat sage.rings.number_field ....: orthonormal=True, extend=True).volume() ....: for F in P.affine_hull_projection().faces(1)]) == {1, sqrt(AA(2))} True - sage: set([F.as_polyhedron().affine_hull_projection( # optional - sage.combinat sage.rings.number_field + sage: set([F.as_polyhedron().affine_hull_projection( # needs sage.combinat sage.rings.number_field ....: orthonormal=True, extend=True).volume() ....: for F in P.affine_hull_projection( ....: orthonormal=True, extend=True).faces(1)]) == {sqrt(AA(2))} True - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: F = D.faces(2)[0].as_polyhedron() # optional - sage.rings.number_field - sage: F.affine_hull_projection(orthogonal=True) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: D = polytopes.dodecahedron() + sage: F = D.faces(2)[0].as_polyhedron() + sage: F.affine_hull_projection(orthogonal=True) A 2-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^2 defined as the convex hull of 5 vertices - sage: F.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.rings.number_field + sage: F.affine_hull_projection(orthonormal=True, extend=True) A 2-dimensional polyhedron in AA^2 defined as the convex hull of 5 vertices - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: P = Polyhedron([2*[K.zero()],2*[sqrt2]]); P # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(2) + sage: P = Polyhedron([2*[K.zero()],2*[sqrt2]]); P A 1-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?)^2 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() (A vertex at (0, 0), A vertex at (sqrt2, sqrt2)) - sage: A = P.affine_hull_projection(orthonormal=True); A # optional - sage.rings.number_field + sage: A = P.affine_hull_projection(orthonormal=True); A A 1-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?)^1 defined as the convex hull of 2 vertices - sage: A.vertices() # optional - sage.rings.number_field + sage: A.vertices() (A vertex at (0), A vertex at (2)) - sage: K. = QuadraticField(3) # optional - sage.rings.number_field - sage: P = Polyhedron([2*[K.zero()], 2*[sqrt3]]); P # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(3) + sage: P = Polyhedron([2*[K.zero()], 2*[sqrt3]]); P A 1-dimensional polyhedron in (Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^2 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() (A vertex at (0, 0), A vertex at (sqrt3, sqrt3)) - sage: A = P.affine_hull_projection(orthonormal=True) # optional - sage.rings.number_field + sage: A = P.affine_hull_projection(orthonormal=True) Traceback (most recent call last): ... ValueError: the base ring needs to be extended; try with "extend=True" - sage: A = P.affine_hull_projection(orthonormal=True, extend=True); A # optional - sage.rings.number_field + sage: A = P.affine_hull_projection(orthonormal=True, extend=True); A A 1-dimensional polyhedron in AA^1 defined as the convex hull of 2 vertices - sage: A.vertices() # optional - sage.rings.number_field + sage: A.vertices() (A vertex at (0), A vertex at (2.449489742783178?)) - sage: sqrt(6).n() # optional - sage.rings.number_field + sage: sqrt(6).n() 2.44948974278318 The affine hull is combinatorially equivalent to the input:: - sage: P.is_combinatorially_isomorphic(P.affine_hull_projection()) # optional - sage.rings.number_field + sage: P.is_combinatorially_isomorphic(P.affine_hull_projection()) # needs sage.rings.number_field True - sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # optional - sage.rings.number_field + sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # needs sage.rings.number_field ....: orthogonal=True)) True - sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # optional - sage.rings.number_field + sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # needs sage.rings.number_field ....: orthonormal=True, extend=True)) True The ``orthonormal=True`` parameter preserves volumes; it provides an isometric copy of the polyhedron:: - sage: Pentagon = polytopes.dodecahedron().faces(2)[0].as_polyhedron() # optional - sage.rings.number_field - sage: P = Pentagon.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.rings.number_field - sage: _, c= P.is_inscribed(certificate=True) # optional - sage.rings.number_field - sage: c # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: Pentagon = polytopes.dodecahedron().faces(2)[0].as_polyhedron() + sage: P = Pentagon.affine_hull_projection(orthonormal=True, extend=True) + sage: _, c= P.is_inscribed(certificate=True) + sage: c (0.4721359549995794?, 0.6498393924658126?) - sage: circumradius = (c - vector(P.vertices()[0])).norm() # optional - sage.rings.number_field - sage: p = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: p.volume() # optional - sage.rings.number_field + sage: circumradius = (c - vector(P.vertices()[0])).norm() + sage: p = polytopes.regular_polygon(5) + sage: p.volume() 2.377641290737884? - sage: P.volume() # optional - sage.rings.number_field + sage: P.volume() 1.53406271079097? - sage: p.volume()*circumradius^2 # optional - sage.rings.number_field + sage: p.volume()*circumradius^2 1.534062710790965? - sage: P.volume() == p.volume()*circumradius^2 # optional - sage.rings.number_field + sage: P.volume() == p.volume()*circumradius^2 True One can also use ``orthogonal`` parameter to calculate volumes; @@ -1334,31 +1348,33 @@ def affine_hull_projection(self, by the square root of the determinant of the linear part of the affine transformation times its transpose:: - sage: Pentagon = polytopes.dodecahedron().faces(2)[0].as_polyhedron() # optional - sage.rings.number_field - sage: Pnormal = Pentagon.affine_hull_projection(orthonormal=True, # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: Pentagon = polytopes.dodecahedron().faces(2)[0].as_polyhedron() + sage: Pnormal = Pentagon.affine_hull_projection(orthonormal=True, ....: extend=True) - sage: Pgonal = Pentagon.affine_hull_projection(orthogonal=True) # optional - sage.rings.number_field - sage: A, b = Pentagon.affine_hull_projection(orthogonal=True, # optional - sage.rings.number_field + sage: Pgonal = Pentagon.affine_hull_projection(orthogonal=True) + sage: A, b = Pentagon.affine_hull_projection(orthogonal=True, ....: as_affine_map=True) - sage: Adet = (A.matrix().transpose()*A.matrix()).det() # optional - sage.rings.number_field - sage: Pnormal.volume() # optional - sage.rings.number_field + sage: Adet = (A.matrix().transpose()*A.matrix()).det() + sage: Pnormal.volume() 1.53406271079097? - sage: Pgonal.volume()/Adet.sqrt(extend=True) # optional - sage.rings.number_field + sage: Pgonal.volume()/Adet.sqrt(extend=True) -80*(55*sqrt(5) - 123)/sqrt(-6368*sqrt(5) + 14240) - sage: Pgonal.volume()/AA(Adet).sqrt().n(digits=20) # optional - sage.rings.number_field + sage: Pgonal.volume()/AA(Adet).sqrt().n(digits=20) 1.5340627107909646813 - sage: AA(Pgonal.volume()^2) == (Pnormal.volume()^2)*AA(Adet) # optional - sage.rings.number_field + sage: AA(Pgonal.volume()^2) == (Pnormal.volume()^2)*AA(Adet) True Another example with ``as_affine_map=True``:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat sage.rings.number_field - sage: Q = P.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.combinat sage.rings.number_field - sage: A, b = P.affine_hull_projection(orthonormal=True, extend=True, # optional - sage.combinat sage.rings.number_field + sage: # needs sage.combinat sage.rings.number_field + sage: P = polytopes.permutahedron(4) + sage: Q = P.affine_hull_projection(orthonormal=True, extend=True) + sage: A, b = P.affine_hull_projection(orthonormal=True, extend=True, ....: as_affine_map=True) - sage: Q.center() # optional - sage.combinat sage.rings.number_field + sage: Q.center() (0.7071067811865475?, 1.224744871391589?, 1.732050807568878?) - sage: A(P.center()) + b == Q.center() # optional - sage.combinat sage.rings.number_field + sage: A(P.center()) + b == Q.center() True For unbounded, non full-dimensional polyhedra, the ``orthogonal=True`` and ``orthonormal=True`` @@ -1506,8 +1522,8 @@ def _test_affine_hull_projection(self, tester=None, verbose=False, **options): TESTS:: - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: D.facets()[0].as_polyhedron()._test_affine_hull_projection() # optional - sage.rings.number_field + sage: D = polytopes.dodecahedron() # needs sage.rings.number_field + sage: D.facets()[0].as_polyhedron()._test_affine_hull_projection() # needs sage.rings.number_field """ if tester is None: tester = self._tester(**options) @@ -1595,48 +1611,50 @@ def affine_hull_manifold(self, name=None, latex_name=None, start_index=0, ambien EXAMPLES:: + sage: # needs sage.symbolic sage: triangle = Polyhedron([(1, 0, 0), (0, 1, 0), (0, 0, 1)]); triangle A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices - sage: A = triangle.affine_hull_manifold(name='A'); A # optional - sage.symbolic + sage: A = triangle.affine_hull_manifold(name='A'); A 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 - sage: A.embedding().display() # optional - sage.symbolic + sage: A.embedding().display() A → E^3 (x0, x1) ↦ (x, y, z) = (t0 + x0, t0 + x1, t0 - x0 - x1 + 1) - sage: A.embedding().inverse().display() # optional - sage.symbolic + sage: A.embedding().inverse().display() E^3 → A (x, y, z) ↦ (x0, x1) = (x, y) - sage: A.adapted_chart() # optional - sage.symbolic + sage: A.adapted_chart() [Chart (E^3, (x0_E3, x1_E3, t0_E3))] - sage: A.normal().display() # optional - sage.symbolic + sage: A.normal().display() n = 1/3*sqrt(3) e_x + 1/3*sqrt(3) e_y + 1/3*sqrt(3) e_z - sage: A.induced_metric() # Need to call this before volume_form # optional - sage.symbolic + sage: A.induced_metric() # Need to call this before volume_form Riemannian metric gamma on the 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 - sage: A.volume_form() # optional - sage.symbolic + sage: A.volume_form() 2-form eps_gamma on the 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 Orthogonal version:: - sage: A = triangle.affine_hull_manifold(name='A', orthogonal=True); A # optional - sage.symbolic + sage: A = triangle.affine_hull_manifold(name='A', orthogonal=True); A # needs sage.symbolic 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 - sage: A.embedding().display() # optional - sage.symbolic + sage: A.embedding().display() # needs sage.symbolic A → E^3 (x0, x1) ↦ (x, y, z) = (t0 - 1/2*x0 - 1/3*x1 + 1, t0 + 1/2*x0 - 1/3*x1, t0 + 2/3*x1) - sage: A.embedding().inverse().display() # optional - sage.symbolic + sage: A.embedding().inverse().display() # needs sage.symbolic E^3 → A (x, y, z) ↦ (x0, x1) = (-x + y + 1, -1/2*x - 1/2*y + z + 1/2) Arrangement of affine hull of facets:: - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: E3 = EuclideanSpace(3) # optional - sage.rings.number_field sage.symbolic - sage: submanifolds = [ # long time # optional - sage.rings.number_field sage.symbolic + sage: # needs sage.rings.number_field sage.symbolic + sage: D = polytopes.dodecahedron() + sage: E3 = EuclideanSpace(3) + sage: submanifolds = [ # long time ....: F.as_polyhedron().affine_hull_manifold(name=f'F{i}', ....: orthogonal=True, ambient_space=E3) ....: for i, F in enumerate(D.facets())] - sage: sum(FM.plot({}, # not tested # long time # optional - sage.symbolic sage.plot sage.rings.number_field + sage: sum(FM.plot({}, # long time, not tested # needs sage.plot ....: srange(-2, 2, 0.1), srange(-2, 2, 0.1), ....: opacity=0.2) ....: for FM in submanifolds) + D.plot() @@ -1646,7 +1664,7 @@ def affine_hull_manifold(self, name=None, latex_name=None, start_index=0, ambien sage: cube = polytopes.cube(); cube A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices - sage: cube.affine_hull_manifold() # optional - sage.symbolic + sage: cube.affine_hull_manifold() # needs sage.symbolic Euclidean space E^3 """ diff --git a/src/sage/geometry/polyhedron/base7.py b/src/sage/geometry/polyhedron/base7.py index ce632e1655d..c1c06b90a28 100644 --- a/src/sage/geometry/polyhedron/base7.py +++ b/src/sage/geometry/polyhedron/base7.py @@ -43,16 +43,17 @@ class Polyhedron_base7(Polyhedron_base6): TESTS:: + sage: # needs sage.combinat sage: from sage.geometry.polyhedron.base7 import Polyhedron_base7 - sage: P = polytopes.associahedron(['A', 3]) # optional - sage.combinat - sage: Polyhedron_base7.centroid(P) # optional - sage.combinat + sage: P = polytopes.associahedron(['A', 3]) + sage: Polyhedron_base7.centroid(P) (81/632, 36/79, 81/632) - sage: Polyhedron_base7.triangulate(P) # optional - sage.combinat + sage: Polyhedron_base7.triangulate(P) (<0,1,2,13>, <0,1,7,13>, <0,2,5,13>, <0,6,7,12>, <0,6,8,13>, <0,6,12,13>, <0,7,12,13>, <1,2,7,12>, <1,2,12,13>, <1,7,12,13>, <2,3,7,12>, <2,3,12,13>, <3,4,7,12>, <3,11,12,13>, <6,8,9,12>, <6,8,12,13>, <6,9,10,12>, <8,9,12,13>) - sage: Polyhedron_base7.volume(P, measure='induced') # optional - sage.combinat + sage: Polyhedron_base7.volume(P, measure='induced') 79/3 """ @cached_method(do_pickle=True) @@ -91,8 +92,8 @@ def centroid(self, engine='auto', **kwds): sage: P.centroid() (1/4, 0, 0) - sage: P = polytopes.associahedron(['A', 2]) # optional - sage.combinat - sage: P.centroid() # optional - sage.combinat + sage: P = polytopes.associahedron(['A', 2]) # needs sage.combinat + sage: P.centroid() # needs sage.combinat (2/21, 2/21) sage: P = polytopes.permutahedron(4, backend='normaliz') # optional - pynormaliz @@ -258,15 +259,16 @@ def triangulate(self, engine='auto', connected=True, fine=False, regular=None, s The normaliz engine can triangulate pointed cones:: - sage: C1 = Polyhedron(rays=[[0,0,1], [1,0,1], # optional - pynormaliz + sage: # optional - pynormaliz + sage: C1 = Polyhedron(rays=[[0,0,1], [1,0,1], ....: [0,1,1], [1,1,1]], ....: backend='normaliz') - sage: C1.triangulate(engine='normaliz') # optional - pynormaliz + sage: C1.triangulate(engine='normaliz') (<0,1,2>, <1,2,3>) - sage: C2 = Polyhedron(rays=[[1,0,1], [0,0,1], # optional - pynormaliz + sage: C2 = Polyhedron(rays=[[1,0,1], [0,0,1], ....: [0,1,1], [1,1,10/9]], ....: backend='normaliz') - sage: C2.triangulate(engine='normaliz') # optional - pynormaliz + sage: C2.triangulate(engine='normaliz') (<0,1,2>, <1,2,3>) They can also be affine cones:: @@ -389,13 +391,14 @@ def _volume_latte(self, verbose=False, algorithm='triangulate', **kwargs): EXAMPLES:: - sage: polytopes.hypercube(3)._volume_latte() # optional - latte_int + sage: # optional - latte_int + sage: polytopes.hypercube(3)._volume_latte() 8 - sage: (polytopes.hypercube(3)*2)._volume_latte() # optional - latte_int + sage: (polytopes.hypercube(3)*2)._volume_latte() 64 - sage: polytopes.twenty_four_cell()._volume_latte() # optional - latte_int + sage: polytopes.twenty_four_cell()._volume_latte() 2 - sage: polytopes.cuboctahedron()._volume_latte() # optional - latte_int + sage: polytopes.cuboctahedron()._volume_latte() 20/3 TESTS: @@ -514,13 +517,13 @@ def volume(self, measure='ambient', engine='auto', **kwds): If the base ring is exact, the answer is exact:: - sage: P5 = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: P5.volume() # optional - sage.rings.number_field + sage: P5 = polytopes.regular_polygon(5) # needs sage.rings.number_field + sage: P5.volume() # needs sage.rings.number_field 2.377641290737884? - sage: polytopes.icosahedron().volume() # optional - sage.rings.number_field + sage: polytopes.icosahedron().volume() # needs sage.rings.number_field 5/12*sqrt5 + 5/4 - sage: numerical_approx(_) # abs tol 1e9 # optional - sage.rings.number_field + sage: numerical_approx(_) # abs tol 1e9 # needs sage.rings.number_field 2.18169499062491 When considering lower-dimensional polytopes, we can ask for the @@ -533,36 +536,38 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P = Polyhedron([[0, 0], [1, 1]]) sage: P.volume() 0 - sage: P.volume(measure='induced') # optional - sage.rings.number_field + sage: P.volume(measure='induced') # needs sage.rings.number_field 1.414213562373095? sage: P.volume(measure='induced_rational') # optional - latte_int 1 - sage: S = polytopes.regular_polygon(6); S # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: S = polytopes.regular_polygon(6); S A 2-dimensional polyhedron in AA^2 defined as the convex hull of 6 vertices - sage: edge = S.faces(1)[4].as_polyhedron() # optional - sage.rings.number_field - sage: edge.vertices() # optional - sage.rings.number_field + sage: edge = S.faces(1)[4].as_polyhedron() + sage: edge.vertices() (A vertex at (0.866025403784439?, 1/2), A vertex at (0, 1)) - sage: edge.volume() # optional - sage.rings.number_field + sage: edge.volume() 0 - sage: edge.volume(measure='induced') # optional - sage.rings.number_field + sage: edge.volume(measure='induced') 1 - sage: P = Polyhedron(backend='normaliz', # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz', ....: vertices=[[1,0,0], [0,0,1], ....: [-1,1,1], [-1,2,0]]) - sage: P.volume() # optional - pynormaliz + sage: P.volume() 0 - sage: P.volume(measure='induced') # optional - pynormaliz sage.rings.number_field + sage: P.volume(measure='induced') # needs sage.rings.number_field 2.598076211353316? - sage: P.volume(measure='induced', engine='normaliz') # optional - pynormaliz + sage: P.volume(measure='induced', engine='normaliz') 2.598076211353316 - sage: P.volume(measure='induced_rational') # optional - pynormaliz latte_int + sage: P.volume(measure='induced_rational') # optional - latte_int 3/2 - sage: P.volume(measure='induced_rational', # optional - pynormaliz + sage: P.volume(measure='induced_rational', ....: engine='normaliz') 3/2 - sage: P.volume(measure='induced_lattice') # optional - pynormaliz + sage: P.volume(measure='induced_lattice') 3 The same polytope without normaliz backend:: @@ -571,35 +576,37 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P.volume(measure='induced_lattice', engine='latte') # optional - latte_int 3 - sage: Dexact = polytopes.dodecahedron() # optional - sage.rings.number_field sage.groups + sage: # needs sage.groups sage.rings.number_field + sage: Dexact = polytopes.dodecahedron() sage: F0 = Dexact.faces(2)[0].as_polyhedron() - sage: v = F0.volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field sage.groups + sage: v = F0.volume(measure='induced', engine='internal'); v 1.53406271079097? sage: F4 = Dexact.faces(2)[4].as_polyhedron() - sage: v = F4.volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field sage.groups + sage: v = F4.volume(measure='induced', engine='internal'); v 1.53406271079097? - sage: RDF(v) # abs tol 1e-9 # optional - sage.rings.number_field sage.groups + sage: RDF(v) # abs tol 1e-9 1.53406271079044 - sage: Dinexact = polytopes.dodecahedron(exact=False) # optional - sage.groups + sage: # needs sage.groups + sage: Dinexact = polytopes.dodecahedron(exact=False) sage: F2 = Dinexact.faces(2)[2].as_polyhedron() - sage: w = F2.volume(measure='induced', engine='internal') # optional - sage.groups + sage: w = F2.volume(measure='induced', engine='internal') sage: RDF(w) # abs tol 1e-9 1.5340627082974878 - sage: all(polytopes.simplex(d).volume(measure='induced') # optional - sage.rings.number_field sage.symbolic + sage: all(polytopes.simplex(d).volume(measure='induced') # needs sage.rings.number_field sage.symbolic ....: == sqrt(d+1)/factorial(d) ....: for d in range(1,5)) True sage: I = Polyhedron([[-3, 0], [0, 9]]) - sage: I.volume(measure='induced') # optional - sage.rings.number_field + sage: I.volume(measure='induced') # needs sage.rings.number_field 9.48683298050514? sage: I.volume(measure='induced_rational') # optional - latte_int 3 sage: T = Polyhedron([[3, 0, 0], [0, 4, 0], [0, 0, 5]]) - sage: T.volume(measure='induced') # optional - sage.rings.number_field + sage: T.volume(measure='induced') # needs sage.rings.number_field 13.86542462386205? sage: T.volume(measure='induced_rational') # optional - latte_int 1/2 @@ -628,7 +635,7 @@ def volume(self, measure='ambient', engine='auto', **kwds): 0 sage: P.volume(measure='induced_rational') # optional - pynormaliz +Infinity - sage: P.volume(measure='induced_rational',engine='latte') # optional - latte_int + sage: P.volume(measure='induced_rational',engine='latte') +Infinity The volume in `0`-dimensional space is taken by counting measure:: @@ -809,7 +816,7 @@ def integrate(self, function, measure='ambient', **kwds): sage: x, y = polygens(QQ, 'x, y') sage: P = Polyhedron(vertices=[[0,0], [1,1]]) - sage: P.integrate(x*y) # optional - latte_int + sage: P.integrate(x*y) 0 sage: ixy = P.integrate(x*y, measure='induced'); ixy # optional - latte_int 0.4714045207910317? @@ -825,21 +832,21 @@ def integrate(self, function, measure='ambient', **kwds): sage: R. = QQ[] sage: P = polytopes.simplex(2) - sage: V = AA(P.volume(measure='induced')) # optional - sage.rings.number_field - sage: V.radical_expression() # optional - sage.rings.number_field sage.symbolic + sage: V = AA(P.volume(measure='induced')) # needs sage.rings.number_field + sage: V.radical_expression() # needs sage.rings.number_field sage.symbolic 1/2*sqrt(3) - sage: P.integrate(R(1), measure='induced') == V # optional - latte_int sage.rings.number_field sage.symbolic + sage: P.integrate(R(1), measure='induced') == V # optional - latte_int, needs sage.rings.number_field sage.symbolic True Computing the mass center:: - sage: (P.integrate(x, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + sage: (P.integrate(x, measure='induced') # optional - latte_int, needs sage.rings.number_field sage.symbolic ....: / V).radical_expression() 1/3 - sage: (P.integrate(y, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + sage: (P.integrate(y, measure='induced') # optional - latte_int, needs sage.rings.number_field sage.symbolic ....: / V).radical_expression() 1/3 - sage: (P.integrate(z, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + sage: (P.integrate(z, measure='induced') # optional - latte_int, needs sage.rings.number_field sage.symbolic ....: / V).radical_expression() 1/3 @@ -854,8 +861,8 @@ def integrate(self, function, measure='ambient', **kwds): Testing a polytope with non-rational vertices:: - sage: P = polytopes.icosahedron() # optional - sage.rings.number_field - sage: P.integrate(x^2*y^2*z^2) # optional - latte_int sage.rings.number_field + sage: P = polytopes.icosahedron() # needs sage.rings.number_field + sage: P.integrate(x^2*y^2*z^2) # optional - latte_int, needs sage.rings.number_field Traceback (most recent call last): ... TypeError: the base ring must be ZZ, QQ, or RDF @@ -870,7 +877,7 @@ def integrate(self, function, measure='ambient', **kwds): Testing a polytope with floating point coordinates:: sage: P = Polyhedron(vertices=[[0, 0], [1, 0], [1.1, 1.1], [0, 1]]) - sage: P.integrate('[[1,[2,2]]]') # optional - latte_int + sage: P.integrate('[[1,[2,2]]]') Traceback (most recent call last): ... TypeError: LattE integrale cannot be applied over inexact rings diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index 7aa1c568480..007f000eb56 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -132,7 +132,7 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, sage: Q = P*(8/9) sage: Q.integral_points_count() 1 - sage: Q.integral_points_count(explicit_enumeration_threshold=0) # optional - latte_int + sage: Q.integral_points_count(explicit_enumeration_threshold=0) 1 Unbounded polyhedra (with or without lattice points) are not supported:: @@ -150,12 +150,12 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, "Fibonacci" knapsacks (preprocessing helps a lot):: - sage: def fibonacci_knapsack(d, b, backend=None): # optional - sage.combinat + sage: def fibonacci_knapsack(d, b, backend=None): ....: lp = MixedIntegerLinearProgram(base_ring=QQ) ....: x = lp.new_variable(nonnegative=True) ....: lp.add_constraint(lp.sum(fibonacci(i+3)*x[i] for i in range(d)) <= b) ....: return lp.polyhedron(backend=backend) - sage: fibonacci_knapsack(20, 12).integral_points_count() # does not finish with preprocess=False # optional - sage.combinat + sage: fibonacci_knapsack(20, 12).integral_points_count() # does not finish with preprocess=False # needs sage.combinat 33 TESTS: @@ -163,10 +163,10 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, We check that :trac:`21491` is fixed:: sage: P = Polyhedron(ieqs=[], eqns=[[-10,0,1],[-10,1,0]]) - sage: P.integral_points_count() # optional - latte_int + sage: P.integral_points_count() 1 sage: P = Polyhedron(ieqs=[], eqns=[[-11,0,2],[-10,1,0]]) - sage: P.integral_points_count() # optional - latte_int + sage: P.integral_points_count() 0 """ if self.is_empty(): @@ -296,23 +296,24 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: poly(1) # optional - latte_int 6 - sage: len(simplex.integral_points()) # optional - latte_int + sage: len(simplex.integral_points()) 6 sage: poly(2) # optional - latte_int 36 - sage: len((2*simplex).integral_points()) # optional - latte_int + sage: len((2*simplex).integral_points()) 36 Now we find the same Ehrhart polynomial, this time using ``engine='normaliz'``. To use the Normaliz engine, the ``simplex`` must be defined with ``backend='normaliz'``:: - sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), # optional - pynormaliz + sage: # optional - pynormaliz + sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), ....: (-3,2,1), (1,-1,-2)], ....: backend='normaliz') - sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz - sage: poly = simplex.ehrhart_polynomial(engine='normaliz') # optional - pynormaliz - sage: poly # optional - pynormaliz + sage: simplex = simplex.change_ring(QQ) + sage: poly = simplex.ehrhart_polynomial(engine='normaliz') + sage: poly 7/2*t^3 + 2*t^2 - 1/2*t + 1 If the ``engine='normaliz'``, the backend should be ``'normaliz'``, otherwise @@ -321,7 +322,7 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), ....: (-3,2,1), (1,-1,-2)]) sage: simplex = simplex.change_ring(QQ) - sage: simplex.ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: simplex.ehrhart_polynomial(engine='normaliz') Traceback (most recent call last): ... TypeError: The backend of the polyhedron should be 'normaliz' @@ -348,11 +349,12 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, The cache of the Ehrhart polynomial is being pickled:: - sage: P = polytopes.cube().change_ring(QQ) # optional - latte_int - sage: P.ehrhart_polynomial() # optional - latte_int + sage: # optional - latte_int + sage: P = polytopes.cube().change_ring(QQ) + sage: P.ehrhart_polynomial() 8*t^3 + 12*t^2 + 6*t + 1 - sage: Q = loads(dumps(P)) # optional - latte_int - sage: Q.ehrhart_polynomial.is_in_cache() # optional - latte_int + sage: Q = loads(dumps(P)) + sage: Q.ehrhart_polynomial.is_in_cache() True """ # check if ``self`` is compact and has vertices in ZZ @@ -525,32 +527,35 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, If the polytope happens to be a lattice polytope, the Ehrhart polynomial is returned:: - sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), # optional - pynormaliz + sage: # optional - pynormaliz + sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), ....: (-3,2,1), (1,-1,-2)], ....: backend='normaliz') - sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz - sage: poly = simplex.ehrhart_quasipolynomial( # optional - pynormaliz + sage: simplex = simplex.change_ring(QQ) + sage: poly = simplex.ehrhart_quasipolynomial( ....: engine='normaliz'); poly 7/2*t^3 + 2*t^2 - 1/2*t + 1 - sage: simplex.ehrhart_polynomial() # optional - pynormaliz latte_int + sage: simplex.ehrhart_polynomial() # optional - latte_int 7/2*t^3 + 2*t^2 - 1/2*t + 1 TESTS: The cache of the Ehrhart quasipolynomial is being pickled:: - sage: P = polytopes.cuboctahedron(backend='normaliz')/2 # optional - pynormaliz - sage: P.ehrhart_quasipolynomial() # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = polytopes.cuboctahedron(backend='normaliz')/2 + sage: P.ehrhart_quasipolynomial() (5/6*t^3 + 2*t^2 + 5/3*t + 1, 5/6*t^3 + 1/2*t^2 + 1/6*t - 1/2) - sage: Q = loads(dumps(P)) # optional - pynormaliz - sage: Q.ehrhart_quasipolynomial.is_in_cache() # optional - pynormaliz + sage: Q = loads(dumps(P)) + sage: Q.ehrhart_quasipolynomial.is_in_cache() True - sage: P = polytopes.cuboctahedron().change_ring(QQ) # optional - latte_int - sage: P.ehrhart_quasipolynomial(engine='latte') # optional - latte_int + sage: # optional - latte_int + sage: P = polytopes.cuboctahedron().change_ring(QQ) + sage: P.ehrhart_quasipolynomial(engine='latte') 20/3*t^3 + 8*t^2 + 10/3*t + 1 - sage: Q = loads(dumps(P)) # optional - latte_int - sage: Q.ehrhart_quasipolynomial.is_in_cache(engine='latte') # optional - latte_int + sage: Q = loads(dumps(P)) + sage: Q.ehrhart_quasipolynomial.is_in_cache(engine='latte') True """ if self.is_empty(): @@ -626,7 +631,7 @@ def _ehrhart_quasipolynomial_normaliz(self, variable='t'): TESTS:: sage: line_seg = Polyhedron(vertices=[[0],[1/2]]) - sage: line_seg._ehrhart_quasipolynomial_normaliz() # optional - pynormaliz + sage: line_seg._ehrhart_quasipolynomial_normaliz() Traceback (most recent call last): ... TypeError: The backend of the polyhedron should be 'normaliz' @@ -709,25 +714,26 @@ def _ehrhart_polynomial_latte(self, verbose=False, dual=None, 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: p(1) # optional - latte_int 6 - sage: len(P.integral_points()) # optional - latte_int + sage: len(P.integral_points()) 6 sage: p(2) # optional - latte_int 36 - sage: len((2*P).integral_points()) # optional - latte_int + sage: len((2*P).integral_points()) 36 The unit hypercubes:: + sage: # optional - latte_int sage: from itertools import product sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1], repeat=d))) - sage: hypercube(3)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(3)._ehrhart_polynomial_latte() t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(4)._ehrhart_polynomial_latte() t^4 + 4*t^3 + 6*t^2 + 4*t + 1 - sage: hypercube(5)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(5)._ehrhart_polynomial_latte() t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1 - sage: hypercube(6)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(6)._ehrhart_polynomial_latte() t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 TESTS: @@ -863,19 +869,20 @@ def fixed_subpolytope(self, vertex_permutation): The next example shows that :meth:`fixed_subpolytope` works for rational polytopes:: - sage: P = Polyhedron(vertices=[[0], [1/2]], # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0], [1/2]], ....: backend='normaliz') - sage: P.vertices() # optional - pynormaliz + sage: P.vertices() (A vertex at (0), A vertex at (1/2)) - sage: G = P.restricted_automorphism_group( # optional - pynormaliz + sage: G = P.restricted_automorphism_group( ....: output='permutation'); G Permutation Group with generators [(0,1)] - sage: len(G) # optional - pynormaliz + sage: len(G) 2 - sage: fixed_set = P.fixed_subpolytope(G.gens()[0]) # optional - pynormaliz - sage: fixed_set # optional - pynormaliz + sage: fixed_set = P.fixed_subpolytope(G.gens()[0]) + sage: fixed_set A 0-dimensional polyhedron in QQ^1 defined as the convex hull of 1 vertex - sage: fixed_set.vertices_list() # optional - pynormaliz + sage: fixed_set.vertices_list() [[1/4]] """ if self.is_empty(): @@ -939,23 +946,24 @@ def fixed_subpolytopes(self, conj_class_reps): Here is an example for the square:: - sage: p = polytopes.hypercube(2, backend='normaliz'); p # optional - pynormaliz + sage: # optional - pynormaliz, needs sage.groups + sage: p = polytopes.hypercube(2, backend='normaliz'); p A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices - sage: aut_p = p.restricted_automorphism_group( # optional - pynormaliz sage.groups + sage: aut_p = p.restricted_automorphism_group( ....: output='permutation') - sage: aut_p.order() # optional - pynormaliz sage.groups + sage: aut_p.order() 8 - sage: conj_list = aut_p.conjugacy_classes_representatives() # optional - pynormaliz sage.groups - sage: fixedpolytopes_dict = p.fixed_subpolytopes(conj_list) # optional - pynormaliz sage.groups - sage: fixedpolytopes_dict[aut_p([(0,3),(1,2)])] # optional - pynormaliz sage.groups + sage: conj_list = aut_p.conjugacy_classes_representatives() + sage: fixedpolytopes_dict = p.fixed_subpolytopes(conj_list) + sage: fixedpolytopes_dict[aut_p([(0,3),(1,2)])] A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex TESTS:: sage: P = Polyhedron(vertices=[[1, 1]], rays=[[1, 1]]) - sage: aut_P = P.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: conj_list = aut_P.conjugacy_classes_representatives() # optional - sage.groups - sage: P.fixed_subpolytopes(conj_list) # optional - sage.groups + sage: aut_P = P.restricted_automorphism_group(output='permutation') # needs sage.groups + sage: conj_list = aut_P.conjugacy_classes_representatives() # needs sage.groups + sage: P.fixed_subpolytopes(conj_list) # needs sage.groups Traceback (most recent call last): ... NotImplementedError: unbounded polyhedra are not supported @@ -1021,15 +1029,16 @@ class functions. is equal to 1 = `\chi_{trivial}` (Prop 6.1 [Stap2011]_). Here is the computation for the 3-dimensional standard simplex:: - sage: S = polytopes.simplex(3, backend='normaliz'); S # optional - pynormaliz + sage: # optional - pynormaliz + sage: S = polytopes.simplex(3, backend='normaliz'); S A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices - sage: G = S.restricted_automorphism_group( # optional - pynormaliz + sage: G = S.restricted_automorphism_group( ....: output='permutation') - sage: G.is_isomorphic(SymmetricGroup(4)) # optional - pynormaliz + sage: G.is_isomorphic(SymmetricGroup(4)) True - sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - pynormaliz + sage: Hstar = S._Hstar_function_normaliz(G); Hstar chi_4 - sage: G.character_table() # optional - pynormaliz + sage: G.character_table() [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -1041,26 +1050,27 @@ class functions. `\pm(0,0,1),\pm(1,0,1), \pm(0,1,1), \pm(1,1,1)` and let G = `\Zmod{2}` act on P as follows:: - sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], ....: [-1,0,-1], [0,1,1], ....: [0,-1,-1], [1,1,1], [-1,-1,-1]], ....: backend='normaliz') - sage: K = P.restricted_automorphism_group( # optional - pynormaliz + sage: K = P.restricted_automorphism_group( ....: output='permutation') - sage: G = K.subgroup(gens=[K([(0,2),(1,3),(4,6),(5,7)])]) # optional - pynormaliz - sage: conj_reps = G.conjugacy_classes_representatives() # optional - pynormaliz - sage: Dict = P.permutations_to_matrices(conj_reps, # optional - pynormaliz + sage: G = K.subgroup(gens=[K([(0,2),(1,3),(4,6),(5,7)])]) + sage: conj_reps = G.conjugacy_classes_representatives() + sage: Dict = P.permutations_to_matrices(conj_reps, ....: acting_group=G) - sage: list(Dict.keys())[0] # optional - pynormaliz + sage: list(Dict.keys())[0] (0,2)(1,3)(4,6)(5,7) - sage: list(Dict.values())[0] # optional - pynormaliz + sage: list(Dict.values())[0] [-1 0 1 0] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] - sage: len(G) # optional - pynormaliz + sage: len(G) 2 - sage: G.character_table() # optional - pynormaliz + sage: G.character_table() [ 1 1] [ 1 -1] @@ -1170,35 +1180,37 @@ class functions of the acting group. A character `\rho` is effective if The `H^*` series of the two-dimensional permutahedron under the action of the symmetric group is effective:: - sage: p3 = polytopes.permutahedron(3, backend='normaliz') # optional - pynormaliz - sage: G = p3.restricted_automorphism_group( # optional - pynormaliz + sage: # optional - pynormaliz + sage: p3 = polytopes.permutahedron(3, backend='normaliz') + sage: G = p3.restricted_automorphism_group( ....: output='permutation') - sage: reflection12 = G([(0,2),(1,4),(3,5)]) # optional - pynormaliz - sage: reflection23 = G([(0,1),(2,3),(4,5)]) # optional - pynormaliz - sage: S3 = G.subgroup(gens=[reflection12, reflection23]) # optional - pynormaliz - sage: S3.is_isomorphic(SymmetricGroup(3)) # optional - pynormaliz + sage: reflection12 = G([(0,2),(1,4),(3,5)]) + sage: reflection23 = G([(0,1),(2,3),(4,5)]) + sage: S3 = G.subgroup(gens=[reflection12, reflection23]) + sage: S3.is_isomorphic(SymmetricGroup(3)) True - sage: Hstar = p3.Hstar_function(S3) # optional - pynormaliz - sage: Hlin = p3.Hstar_function(S3, # optional - pynormaliz + sage: Hstar = p3.Hstar_function(S3) + sage: Hlin = p3.Hstar_function(S3, ....: output='Hstar_as_lin_comb') - sage: p3.is_effective(Hstar, Hlin) # optional - pynormaliz + sage: p3.is_effective(Hstar, Hlin) True If the `H^*`-series is not polynomial, then it is not effective:: - sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], ....: [-1,0,-1], [0,1,1], ....: [0,-1,-1], [1,1,1], [-1,-1,-1]], ....: backend='normaliz') - sage: G = P.restricted_automorphism_group( # optional - pynormaliz + sage: G = P.restricted_automorphism_group( ....: output='permutation') - sage: H = G.subgroup(gens=[G([(0,2),(1,3),(4,6),(5,7)])]) # optional - pynormaliz - sage: Hstar = P.Hstar_function(H); Hstar # optional - pynormaliz + sage: H = G.subgroup(gens=[G([(0,2),(1,3),(4,6),(5,7)])]) + sage: Hstar = P.Hstar_function(H); Hstar (chi_0*t^4 + (3*chi_0 + 3*chi_1)*t^3 + (8*chi_0 + 2*chi_1)*t^2 + (3*chi_0 + 3*chi_1)*t + chi_0)/(t + 1) - sage: Hstar_lin = P.Hstar_function(H, # optional - pynormaliz + sage: Hstar_lin = P.Hstar_function(H, ....: output='Hstar_as_lin_comb') - sage: P.is_effective(Hstar, Hstar_lin) # optional - pynormaliz + sage: P.is_effective(Hstar, Hstar_lin) False """ if self.is_empty(): diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index b9b36bd6a48..7e360658341 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -79,7 +79,7 @@ def is_lattice_polytope(self): sage: polytopes.cross_polytope(3).is_lattice_polytope() True - sage: polytopes.regular_polygon(5).is_lattice_polytope() # optional - sage.rings.number_field + sage: polytopes.regular_polygon(5).is_lattice_polytope() # needs sage.rings.number_field False TESTS: @@ -163,25 +163,26 @@ def _ehrhart_polynomial_latte(self, verbose=False, dual=None, 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: p(1) # optional - latte_int 6 - sage: len(P.integral_points()) # optional - latte_int + sage: len(P.integral_points()) 6 sage: p(2) # optional - latte_int 36 - sage: len((2*P).integral_points()) # optional - latte_int + sage: len((2*P).integral_points()) 36 The unit hypercubes:: + sage: # optional - latte_int sage: from itertools import product sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1],repeat=d))) - sage: hypercube(3)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(3)._ehrhart_polynomial_latte() t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(4)._ehrhart_polynomial_latte() t^4 + 4*t^3 + 6*t^2 + 4*t + 1 - sage: hypercube(5)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(5)._ehrhart_polynomial_latte() t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1 - sage: hypercube(6)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(6)._ehrhart_polynomial_latte() t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 TESTS: @@ -281,7 +282,7 @@ def _ehrhart_polynomial_normaliz(self, variable='t'): Receive a type error if the backend is not normaliz:: sage: c = Polyhedron(vertices = [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]) - sage: c._ehrhart_polynomial_normaliz() # optional - pynormaliz + sage: c._ehrhart_polynomial_normaliz() Traceback (most recent call last): ... TypeError: The polyhedron's backend should be 'normaliz' @@ -367,11 +368,11 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: poly(1) # optional - latte_int 6 - sage: len(simplex.integral_points()) # optional - latte_int + sage: len(simplex.integral_points()) 6 sage: poly(2) # optional - latte_int 36 - sage: len((2*simplex).integral_points()) # optional - latte_int + sage: len((2*simplex).integral_points()) 36 Now we find the same Ehrhart polynomial, this time using @@ -387,7 +388,7 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None it returns an error:: sage: simplex = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)]) - sage: simplex.ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: simplex.ehrhart_polynomial(engine='normaliz') Traceback (most recent call last): ... TypeError: The polyhedron's backend should be 'normaliz' @@ -399,27 +400,29 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None hypercube, and the coefficient of the leading monomial equals the volume of the unit hypercube:: + sage: # optional - latte_int sage: from itertools import product sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1],repeat=d))) - sage: hypercube(3).ehrhart_polynomial() # optional - latte_int + sage: hypercube(3).ehrhart_polynomial() t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4).ehrhart_polynomial() # optional - latte_int + sage: hypercube(4).ehrhart_polynomial() t^4 + 4*t^3 + 6*t^2 + 4*t + 1 - sage: hypercube(5).ehrhart_polynomial() # optional - latte_int + sage: hypercube(5).ehrhart_polynomial() t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1 - sage: hypercube(6).ehrhart_polynomial() # optional - latte_int + sage: hypercube(6).ehrhart_polynomial() t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 + sage: # optional - pynormaliz sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1],repeat=d)),backend='normaliz') - sage: hypercube(3).ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: hypercube(3).ehrhart_polynomial(engine='normaliz') t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4).ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: hypercube(4).ehrhart_polynomial(engine='normaliz') t^4 + 4*t^3 + 6*t^2 + 4*t + 1 - sage: hypercube(5).ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: hypercube(5).ehrhart_polynomial(engine='normaliz') t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1 - sage: hypercube(6).ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: hypercube(6).ehrhart_polynomial(engine='normaliz') t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 An empty polyhedron:: @@ -626,8 +629,8 @@ def fibration_generator(self, dim): EXAMPLES:: - sage: P = Polyhedron(toric_varieties.P4_11169().fan().rays(), base_ring=ZZ) # optional - palp - sage: list(P.fibration_generator(2)) # optional - palp + sage: P = Polyhedron(toric_varieties.P4_11169().fan().rays(), base_ring=ZZ) # needs palp sage.graphs + sage: list(P.fibration_generator(2)) # needs palp sage.graphs [A 2-dimensional polyhedron in ZZ^4 defined as the convex hull of 3 vertices] """ from sage.combinat.combination import Combinations diff --git a/src/sage/geometry/polyhedron/base_number_field.py b/src/sage/geometry/polyhedron/base_number_field.py index 40b9017dc53..9491fce4e75 100644 --- a/src/sage/geometry/polyhedron/base_number_field.py +++ b/src/sage/geometry/polyhedron/base_number_field.py @@ -32,12 +32,12 @@ def _number_field_elements_from_algebraics_list_of_lists_of_lists(listss, **kwds EXAMPLES:: - sage: rt2 = AA(sqrt(2)); rt2 # optional - sage.rings.number_field + sage: rt2 = AA(sqrt(2)); rt2 # needs sage.rings.number_field sage.symbolic 1.414213562373095? - sage: rt3 = AA(sqrt(3)); rt3 # optional - sage.rings.number_field + sage: rt3 = AA(sqrt(3)); rt3 # needs sage.rings.number_field sage.symbolic 1.732050807568878? sage: from sage.geometry.polyhedron.base_number_field import _number_field_elements_from_algebraics_list_of_lists_of_lists - sage: K, results, hom = _number_field_elements_from_algebraics_list_of_lists_of_lists([[[rt2], [1]], [[rt3]], [[1], []]]); results # optional - sage.rings.number_field + sage: K, results, hom = _number_field_elements_from_algebraics_list_of_lists_of_lists([[[rt2], [1]], [[rt3]], [[1], []]]); results # needs sage.rings.number_field sage.symbolic [[[-a^3 + 3*a], [1]], [[a^2 - 2]], [[1], []]] """ from sage.rings.qqbar import number_field_elements_from_algebraics @@ -58,28 +58,29 @@ def _compute_data_lists_and_internal_base_ring(self, data_lists, convert_QQ, con EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,1/2), (2,0), (4,5/6)], # optional - pynormaliz + sage: # optional - pynormaliz, needs sage.rings.number_field + sage: p = Polyhedron(vertices=[(0,1/2), (2,0), (4,5/6)], ....: base_ring=AA, backend='normaliz') - sage: def convert_QQ(ieqs, eqs): # optional - pynormaliz + sage: def convert_QQ(ieqs, eqs): ....: return [[1000*x for x in ieq] for ieq in ieqs], \ ....: [[1000*x for x in eq] for eq in eqs] - sage: def convert_NF(ieqs, eqs): # optional - pynormaliz + sage: def convert_NF(ieqs, eqs): ....: return ieqs, eqs - sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz + sage: p._compute_data_lists_and_internal_base_ring( ....: [[[1]], [[1/2]]], convert_QQ, convert_NF) (([[1000]], [[500]]), Rational Field) - sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz + sage: p._compute_data_lists_and_internal_base_ring( ....: [[[AA(1)]], [[1/2]]], convert_QQ, convert_NF) (([[1000]], [[500]]), Rational Field) - sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz sage.rings.number_field + sage: p._compute_data_lists_and_internal_base_ring( ....: [[[AA(sqrt(2))]], [[1/2]]], convert_QQ, convert_NF) ([[[a]], [[1/2]]], Number Field in a with defining polynomial y^2 - 2 with a = 1.414213562373095?) TESTS:: - sage: K. = QuadraticField(-5) # optional - sage.rings.number_field - sage: p = Polyhedron(base_ring=K, # indirect doctest # optional - pynormaliz sage.rings.number_field + sage: K. = QuadraticField(-5) # needs sage.rings.number_field + sage: p = Polyhedron(base_ring=K, # indirect doctest # optional - pynormaliz, needs sage.rings.number_field ....: backend='normaliz', ....: vertices=[(a,1/2), (2,0), (4,5/6)]) Traceback (most recent call last): @@ -88,11 +89,11 @@ def _compute_data_lists_and_internal_base_ring(self, data_lists, convert_QQ, con Checks that :trac:`30248` is fixed:: - sage: q = Polyhedron(base_ring=AA, # indirect doctest # optional - pynormaliz sage.rings.number_field + sage: q = Polyhedron(base_ring=AA, # indirect doctest # optional - pynormaliz, needs sage.rings.number_field ....: backend='normaliz', ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]); q A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays - sage: -q # optional - pynormaliz sage.rings.number_field + sage: -q # optional - pynormaliz, needs sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ from sage.categories.number_fields import NumberFields diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index d25ca1ceebf..5a07abb2408 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -49,14 +49,14 @@ Obtaining edges and ridges:: Vertex-graph and facet-graph:: - sage: C.vertex_graph() # optional - sage.graphs + sage: C.vertex_graph() # needs sage.graphs Graph on 16 vertices - sage: C.facet_graph() # optional - sage.graphs + sage: C.facet_graph() # needs sage.graphs Graph on 8 vertices Face lattice:: - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 82 elements Face iterator:: @@ -328,7 +328,7 @@ cdef class CombinatorialPolyhedron(SageObject): Traceback (most recent call last): ... ValueError: the combinatorial polyhedron was not initialized - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Traceback (most recent call last): ... ValueError: the combinatorial polyhedron was not initialized @@ -640,16 +640,17 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C1 = loads(C.dumps()) # optional - sage.combinat - sage: it = C.face_generator() # optional - sage.combinat - sage: it1 = C1.face_generator() # optional - sage.combinat - sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: C1 = loads(C.dumps()) + sage: it = C.face_generator() + sage: it1 = C1.face_generator() + sage: tup = tuple((face.ambient_Vrepresentation(), ....: face.ambient_Hrepresentation()) for face in it) - sage: tup1 = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + sage: tup1 = tuple((face.ambient_Vrepresentation(), ....: face.ambient_Hrepresentation()) for face in it1) - sage: tup == tup1 # optional - sage.combinat + sage: tup == tup1 True sage: P = polytopes.cyclic_polytope(4,10) @@ -747,9 +748,9 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(3) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.Hrepresentation() # optional - sage.combinat + sage: P = polytopes.permutahedron(3) + sage: C = CombinatorialPolyhedron(P) + sage: C.Hrepresentation() (An inequality (1, 1, 0) x - 3 >= 0, An inequality (-1, -1, 0) x + 5 >= 0, An inequality (0, 1, 0) x - 1 >= 0, @@ -1104,10 +1105,11 @@ cdef class CombinatorialPolyhedron(SageObject): :: - sage: P = polytopes.permutahedron(5, backend='field') # optional - sage.combinat - sage: C = P.combinatorial_polyhedron() # optional - sage.combinat - sage: C.incidence_matrix.clear_cache() # optional - sage.combinat - sage: C.incidence_matrix() == P.incidence_matrix() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5, backend='field') + sage: C = P.combinatorial_polyhedron() + sage: C.incidence_matrix.clear_cache() + sage: C.incidence_matrix() == P.incidence_matrix() True The incidence matrix is consistent with @@ -1284,14 +1286,14 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cyclic_polytope(3,5) sage: C = CombinatorialPolyhedron(P) - sage: G = C.vertex_graph(); G # optional - sage.graphs + sage: G = C.vertex_graph(); G # needs sage.graphs Graph on 5 vertices - sage: sorted(G.degree()) # optional - sage.graphs + sage: sorted(G.degree()) # needs sage.graphs [3, 3, 4, 4, 4] sage: P = Polyhedron(rays=[[1]]) sage: C = CombinatorialPolyhedron(P) - sage: C.graph() # optional - sage.graphs + sage: C.graph() # needs sage.graphs Graph on 1 vertex """ vertices = self.vertices(names=names) @@ -1392,11 +1394,12 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(2) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.ridges() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(2) + sage: C = CombinatorialPolyhedron(P) + sage: C.ridges() ((An inequality (1, 0) x - 1 >= 0, An inequality (-1, 0) x + 2 >= 0),) - sage: C.ridges(add_equations=True) # optional - sage.combinat + sage: C.ridges(add_equations=True) (((An inequality (1, 0) x - 1 >= 0, An equation (1, 1) x - 3 == 0), (An inequality (-1, 0) x + 2 >= 0, An equation (1, 1) x - 3 == 0)),) @@ -1565,25 +1568,25 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cyclic_polytope(4,6) sage: C = CombinatorialPolyhedron(P) - sage: C.facet_graph() # optional - sage.graphs + sage: C.facet_graph() # needs sage.graphs Graph on 9 vertices TESTS:: sage: P = Polyhedron(ieqs=[[1,-1,0],[1,1,0]]) - sage: CombinatorialPolyhedron(P).facet_graph() # optional - sage.graphs + sage: CombinatorialPolyhedron(P).facet_graph() # needs sage.graphs Graph on 2 vertices Checking that :trac:`28604` is fixed:: sage: C = CombinatorialPolyhedron(polytopes.cube()); C A 3-dimensional combinatorial polyhedron with 6 facets - sage: C.facet_graph(names=False) # optional - sage.graphs + sage: C.facet_graph(names=False) # needs sage.graphs Graph on 6 vertices - sage: C = CombinatorialPolyhedron(polytopes.hypersimplex(5,2)); C # optional - sage.combinat + sage: C = CombinatorialPolyhedron(polytopes.hypersimplex(5,2)); C A 4-dimensional combinatorial polyhedron with 10 facets - sage: C.facet_graph() # optional - sage.graphs sage.combinat + sage: C.facet_graph() # needs sage.combinat sage.graphs Graph on 10 vertices """ face_iter = self.face_iter(self.dimension() - 1, algorithm='primal') @@ -1621,7 +1624,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.hypercube(2).pyramid() sage: C = CombinatorialPolyhedron(P) - sage: G = C.vertex_facet_graph(); G # optional - sage.graphs + sage: G = C.vertex_facet_graph(); G # needs sage.graphs Digraph on 10 vertices sage: C.Vrepresentation() (A vertex at (0, -1, -1), @@ -1629,7 +1632,7 @@ cdef class CombinatorialPolyhedron(SageObject): A vertex at (0, 1, -1), A vertex at (0, 1, 1), A vertex at (1, 0, 0)) - sage: sorted(G.neighbors_out(C.Vrepresentation()[4])) # optional - sage.graphs + sage: sorted(G.neighbors_out(C.Vrepresentation()[4])) # needs sage.graphs [An inequality (-1, -1, 0) x + 1 >= 0, An inequality (-1, 0, -1) x + 1 >= 0, An inequality (-1, 0, 1) x + 1 >= 0, @@ -1642,7 +1645,7 @@ cdef class CombinatorialPolyhedron(SageObject): with a string 'H' or 'V':: sage: C = CombinatorialPolyhedron(P.incidence_matrix()) - sage: C.vertex_facet_graph().vertices(sort=True) # optional - sage.graphs + sage: C.vertex_facet_graph().vertices(sort=True) # needs sage.graphs [('H', 0), ('H', 1), ('H', 2), @@ -1656,18 +1659,18 @@ cdef class CombinatorialPolyhedron(SageObject): If ``names`` is ``False`` then the vertices of the graph are given by integers:: - sage: C.vertex_facet_graph(names=False).vertices(sort=True) # optional - sage.graphs + sage: C.vertex_facet_graph(names=False).vertices(sort=True) # needs sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] TESTS: Test that :trac:`29898` is fixed:: - sage: Polyhedron().vertex_facet_graph() # optional - sage.graphs + sage: Polyhedron().vertex_facet_graph() # needs sage.graphs Digraph on 0 vertices - sage: Polyhedron([[0]]).vertex_facet_graph() # optional - sage.graphs + sage: Polyhedron([[0]]).vertex_facet_graph() # needs sage.graphs Digraph on 1 vertex - sage: Polyhedron([[0]]).vertex_facet_graph(False) # optional - sage.graphs + sage: Polyhedron([[0]]).vertex_facet_graph(False) # needs sage.graphs Digraph on 1 vertex """ from sage.graphs.digraph import DiGraph @@ -1736,9 +1739,9 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.f_vector() # optional - sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: C.f_vector() (1, 120, 240, 150, 30, 1) sage: P = polytopes.cyclic_polytope(6,10) @@ -1748,9 +1751,9 @@ cdef class CombinatorialPolyhedron(SageObject): Using two threads:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.f_vector(num_threads=2) # optional - sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: C.f_vector(num_threads=2) (1, 120, 240, 150, 30, 1) TESTS:: @@ -1808,7 +1811,7 @@ cdef class CombinatorialPolyhedron(SageObject): Obtain the entire flag-f-vector:: sage: C = polytopes.hypercube(4).combinatorial_polyhedron() - sage: C.flag_f_vector() # optional - sage.combinat + sage: C.flag_f_vector() # needs sage.combinat {(-1,): 1, (0,): 16, (0, 1): 64, @@ -1829,38 +1832,38 @@ cdef class CombinatorialPolyhedron(SageObject): Specify an entry:: - sage: C.flag_f_vector(0,3) # optional - sage.combinat + sage: C.flag_f_vector(0,3) # needs sage.combinat 64 - sage: C.flag_f_vector(2) # optional - sage.combinat + sage: C.flag_f_vector(2) # needs sage.combinat 24 Leading ``-1`` and trailing entry of dimension are allowed:: - sage: C.flag_f_vector(-1,0,3) # optional - sage.combinat + sage: C.flag_f_vector(-1,0,3) # needs sage.combinat 64 - sage: C.flag_f_vector(-1,0,3,4) # optional - sage.combinat + sage: C.flag_f_vector(-1,0,3,4) # needs sage.combinat 64 One can get the number of trivial faces:: - sage: C.flag_f_vector(-1) # optional - sage.combinat + sage: C.flag_f_vector(-1) # needs sage.combinat 1 - sage: C.flag_f_vector(4) # optional - sage.combinat + sage: C.flag_f_vector(4) # needs sage.combinat 1 Polyhedra with lines, have ``0`` entries accordingly:: sage: C = (Polyhedron(lines=[[1]]) * polytopes.hypercube(2)).combinatorial_polyhedron() - sage: C.flag_f_vector() # optional - sage.combinat + sage: C.flag_f_vector() # needs sage.combinat {(-1,): 1, (0, 1): 0, (0, 2): 0, (0,): 0, (1, 2): 8, (1,): 4, (2,): 4, 3: 1} If the arguments are not stricly increasing or out of range, a key error is raised:: - sage: C.flag_f_vector(-1,0,3,5) # optional - sage.combinat + sage: C.flag_f_vector(-1,0,3,5) # needs sage.combinat Traceback (most recent call last): ... KeyError: (0, 3, 5) - sage: C.flag_f_vector(-1,3,0) # optional - sage.combinat + sage: C.flag_f_vector(-1,3,0) # needs sage.combinat Traceback (most recent call last): ... KeyError: (3, 0) @@ -1888,7 +1891,7 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: sage: C = CombinatorialPolyhedron(3) - sage: C._flag_f_vector() # optional - sage.combinat + sage: C._flag_f_vector() # needs sage.combinat {(-1,): 1, (0, 1): 0, (0, 2): 0, (0,): 0, (1, 2): 0, (1,): 0, (2,): 0, 3: 1} """ poly = self.face_lattice().flag_f_polynomial() @@ -2086,8 +2089,8 @@ cdef class CombinatorialPolyhedron(SageObject): sage: CombinatorialPolyhedron(cyclic).simpliciality() 3 - sage: hypersimplex = polytopes.hypersimplex(5,2) # optional - sage.combinat - sage: CombinatorialPolyhedron(hypersimplex).simpliciality() # optional - sage.combinat + sage: hypersimplex = polytopes.hypersimplex(5,2) + sage: CombinatorialPolyhedron(hypersimplex).simpliciality() 2 sage: cross = polytopes.cross_polytope(4) @@ -2194,16 +2197,16 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: hyper4 = polytopes.hypersimplex(4,2) # optional - sage.combinat - sage: CombinatorialPolyhedron(hyper4).simplicity() # optional - sage.combinat + sage: hyper4 = polytopes.hypersimplex(4,2) + sage: CombinatorialPolyhedron(hyper4).simplicity() 1 - sage: hyper5 = polytopes.hypersimplex(5,2) # optional - sage.combinat - sage: CombinatorialPolyhedron(hyper5).simplicity() # optional - sage.combinat + sage: hyper5 = polytopes.hypersimplex(5,2) + sage: CombinatorialPolyhedron(hyper5).simplicity() 2 - sage: hyper6 = polytopes.hypersimplex(6,2) # optional - sage.combinat - sage: CombinatorialPolyhedron(hyper6).simplicity() # optional - sage.combinat + sage: hyper6 = polytopes.hypersimplex(6,2) + sage: CombinatorialPolyhedron(hyper6).simplicity() 3 sage: P = polytopes.simplex(3) @@ -2631,15 +2634,16 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.join_of_Vrep(0,1) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: C.join_of_Vrep(0,1) A 1-dimensional face of a 3-dimensional combinatorial polyhedron - sage: C.join_of_Vrep(0,11).ambient_V_indices() # optional - sage.combinat + sage: C.join_of_Vrep(0,11).ambient_V_indices() (0, 1, 10, 11, 12, 13) - sage: C.join_of_Vrep(8).ambient_V_indices() # optional - sage.combinat + sage: C.join_of_Vrep(8).ambient_V_indices() (8,) - sage: C.join_of_Vrep().ambient_V_indices() # optional - sage.combinat + sage: C.join_of_Vrep().ambient_V_indices() () """ return self.face_generator().join_of_Vrep(*indices) @@ -2654,19 +2658,20 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: C = CombinatorialPolyhedron(P) # optional - sage.rings.number_field - sage: C.meet_of_Hrep(0) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: C = CombinatorialPolyhedron(P) + sage: C.meet_of_Hrep(0) A 2-dimensional face of a 3-dimensional combinatorial polyhedron - sage: C.meet_of_Hrep(0).ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0).ambient_H_indices() (0,) - sage: C.meet_of_Hrep(0,1).ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0,1).ambient_H_indices() (0, 1) - sage: C.meet_of_Hrep(0,2).ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0,2).ambient_H_indices() (0, 2) - sage: C.meet_of_Hrep(0,2,3).ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0,2,3).ambient_H_indices() (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) - sage: C.meet_of_Hrep().ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep().ambient_H_indices() () """ return self.face_generator().meet_of_Hrep(*indices) @@ -2697,38 +2702,39 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(dimension=2) # optional - sage.combinat - sage: face = next(it); face # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(dimension=2) + sage: face = next(it); face A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face.ambient_Vrepresentation() (A vertex at (1, 3, 2, 5, 4), A vertex at (2, 3, 1, 5, 4), A vertex at (3, 1, 2, 5, 4), A vertex at (3, 2, 1, 5, 4), A vertex at (2, 1, 3, 5, 4), A vertex at (1, 2, 3, 5, 4)) - sage: face = next(it); face # optional - sage.combinat + sage: face = next(it); face A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face.ambient_Vrepresentation() (A vertex at (2, 1, 4, 5, 3), A vertex at (3, 2, 4, 5, 1), A vertex at (3, 1, 4, 5, 2), A vertex at (1, 3, 4, 5, 2), A vertex at (1, 2, 4, 5, 3), A vertex at (2, 3, 4, 5, 1)) - sage: face.ambient_Hrepresentation() # optional - sage.combinat + sage: face.ambient_Hrepresentation() (An inequality (0, 0, -1, -1, 0) x + 9 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: face.ambient_H_indices() # optional - sage.combinat + sage: face.ambient_H_indices() (25, 29, 30) - sage: face = next(it); face # optional - sage.combinat + sage: face = next(it); face A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_H_indices() # optional - sage.combinat + sage: face.ambient_H_indices() (24, 29, 30) - sage: face.ambient_V_indices() # optional - sage.combinat + sage: face.ambient_V_indices() (32, 89, 90, 94) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) @@ -2840,31 +2846,31 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = Polyhedron(rays=[[1,0],[0,1]]) sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 5 elements sage: P = Polyhedron(rays=[[1,0,0], [-1,0,0], [0,-1,0], [0,1,0]]) sage: C = CombinatorialPolyhedron(P) sage: P1 = Polyhedron(rays=[[1,0], [-1,0]]) sage: C1 = CombinatorialPolyhedron(P1) - sage: C.face_lattice().is_isomorphic(C1.face_lattice()) # optional - sage.combinat + sage: C.face_lattice().is_isomorphic(C1.face_lattice()) # needs sage.combinat True - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.face_lattice() # optional - sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 542 elements TESTS:: sage: P = polytopes.cyclic_polytope(4,10) sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice().is_isomorphic(P.face_lattice()) # optional - sage.combinat + sage: C.face_lattice().is_isomorphic(P.face_lattice()) # needs sage.combinat True - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.face_lattice().is_isomorphic(P.face_lattice()) # optional - sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: C.face_lattice().is_isomorphic(P.face_lattice()) # needs sage.combinat True """ from sage.combinat.posets.lattices import FiniteLatticePoset @@ -2894,20 +2900,21 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field - sage: C = CombinatorialPolyhedron(P) # optional - sage.rings.number_field - sage: D = C.hasse_diagram(); D # optional - sage.graphs sage.rings.number_field + sage: # needs sage.graphs sage.rings.number_field + sage: P = polytopes.regular_polygon(4).pyramid() + sage: C = CombinatorialPolyhedron(P) + sage: D = C.hasse_diagram(); D Digraph on 20 vertices - sage: D.average_degree() # optional - sage.graphs sage.rings.number_field + sage: D.average_degree() 21/5 - sage: D.relabel(C.face_by_face_lattice_index) # optional - sage.graphs sage.rings.number_field - sage: dim_0_vert = D.vertices(sort=True)[1:6]; dim_0_vert # optional - sage.graphs sage.rings.number_field + sage: D.relabel(C.face_by_face_lattice_index) + sage: dim_0_vert = D.vertices(sort=True)[1:6]; dim_0_vert [A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: sorted(D.out_degree(vertices=dim_0_vert)) # optional - sage.graphs sage.rings.number_field + sage: sorted(D.out_degree(vertices=dim_0_vert)) [3, 3, 3, 3, 4] """ if not self._face_lattice_incidences: @@ -2936,12 +2943,12 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() # optional - sage.combinat + sage: F = C.face_lattice() # needs sage.combinat sage: def f(i): ....: return (i, C._face_lattice_dimension(i)) ....: - sage: G = F.relabel(f) # optional - sage.combinat - sage: set(G._elements) # optional - sage.combinat + sage: G = F.relabel(f) # needs sage.combinat + sage: set(G._elements) # needs sage.combinat {(0, -1), (1, 0), (2, 0), @@ -2990,15 +2997,16 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: + sage: # needs sage.combinat sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() # optional - sage.combinat - sage: F # optional - sage.combinat + sage: F = C.face_lattice() + sage: F Finite lattice containing 28 elements - sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat - sage: G.level_sets()[0] # optional - sage.combinat + sage: G = F.relabel(C.face_by_face_lattice_index) + sage: G.level_sets()[0] [A -1-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: G.level_sets()[3] # optional - sage.combinat + sage: G.level_sets()[3] [A 2-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron, @@ -3008,9 +3016,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = Polyhedron(rays=[[0,1], [1,0]]) sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() # optional - sage.combinat - sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat - sage: G._elements # optional - sage.combinat + sage: F = C.face_lattice() # needs sage.combinat + sage: G = F.relabel(C.face_by_face_lattice_index) # needs sage.combinat + sage: G._elements # needs sage.combinat (A -1-dimensional face of a 2-dimensional combinatorial polyhedron, A 0-dimensional face of a 2-dimensional combinatorial polyhedron, A 1-dimensional face of a 2-dimensional combinatorial polyhedron, @@ -3018,8 +3026,8 @@ cdef class CombinatorialPolyhedron(SageObject): A 2-dimensional face of a 2-dimensional combinatorial polyhedron) sage: def f(i): return C.face_by_face_lattice_index(i).ambient_V_indices() - sage: G = F.relabel(f) # optional - sage.combinat - sage: G._elements # optional - sage.combinat + sage: G = F.relabel(f) # needs sage.combinat + sage: G._elements # needs sage.combinat ((), (0,), (0, 1), (0, 2), (0, 1, 2)) """ self._record_all_faces() # Initialize ``_all_faces``, if not done yet. @@ -3064,13 +3072,14 @@ cdef class CombinatorialPolyhedron(SageObject): sage: [face.ambient_V_indices() for face in chain] [(15,), (6, 15), (5, 6, 14, 15), (0, 5, 6, 7, 8, 9, 14, 15)] - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = P.combinatorial_polyhedron() # optional - sage.combinat - sage: chain = C.a_maximal_chain(); chain # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = P.combinatorial_polyhedron() + sage: chain = C.a_maximal_chain(); chain [A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 1-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: [face.ambient_V_indices() for face in chain] # optional - sage.combinat + sage: [face.ambient_V_indices() for face in chain] [(16,), (15, 16), (8, 9, 14, 15, 16, 17)] sage: P = Polyhedron(rays=[[1,0]], lines=[[0,1]]) @@ -3366,7 +3375,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: D.f_vector() (1, 6, 12, 8, 1) sage: D1 = P.polar().combinatorial_polyhedron() - sage: D1.face_lattice().is_isomorphic(D.face_lattice()) # optional - sage.combinat + sage: D1.face_lattice().is_isomorphic(D.face_lattice()) # needs sage.combinat True Polar is an alias to be consistent with :class:`~sage.geometry.polyhedron.base.Polyhedron_base`:: @@ -3416,7 +3425,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C1 = C.pyramid() sage: P1 = P.pyramid() sage: C2 = P1.combinatorial_polyhedron() - sage: C2.vertex_facet_graph().is_isomorphic(C1.vertex_facet_graph()) # optional - sage.combinat + sage: C2.vertex_facet_graph().is_isomorphic(C1.vertex_facet_graph()) # needs sage.combinat True One can specify a name for the new vertex:: @@ -3435,10 +3444,11 @@ cdef class CombinatorialPolyhedron(SageObject): One can specify a name for the new facets:: - sage: P = polytopes.regular_polygon(4) # optional - sage.rings.number_field - sage: C = P.combinatorial_polyhedron() # optional - sage.rings.number_field - sage: C1 = C.pyramid(new_facet='base') # optional - sage.rings.number_field - sage: C1.Hrepresentation() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.regular_polygon(4) + sage: C = P.combinatorial_polyhedron() + sage: C1 = C.pyramid(new_facet='base') + sage: C1.Hrepresentation() (An inequality (-1/2, 1/2) x + 1/2 >= 0, An inequality (-1/2, -1/2) x + 1/2 >= 0, An inequality (1/2, 0.50000000000000000?) x + 1/2 >= 0, @@ -3823,17 +3833,18 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator() # optional - sage.combinat - sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator() + sage: tup = tuple((face.ambient_Vrepresentation(), ....: face.ambient_Hrepresentation()) for face in it) - sage: rg = range(1,sum(C.f_vector()) - 1) # optional - sage.combinat - sage: tup2 = tuple( # optional - sage.combinat + sage: rg = range(1,sum(C.f_vector()) - 1) + sage: tup2 = tuple( ....: (C.face_by_face_lattice_index(i).ambient_Vrepresentation(), ....: C.face_by_face_lattice_index(i).ambient_Hrepresentation()) ....: for i in rg) - sage: sorted(tup) == sorted(tup2) # optional - sage.combinat + sage: sorted(tup) == sorted(tup2) True sage: P = polytopes.cyclic_polytope(4,10) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx index e499afcbc1c..bf01025707f 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx @@ -22,9 +22,9 @@ Obtain a face from a face lattice index:: sage: P = polytopes.simplex(2) sage: C = CombinatorialPolyhedron(P) - sage: sorted(C.face_lattice()._elements) # optional - sage.combinat + sage: sorted(C.face_lattice()._elements) # needs sage.combinat [0, 1, 2, 3, 4, 5, 6, 7] - sage: face = C.face_by_face_lattice_index(0); face # optional - sage.combinat + sage: face = C.face_by_face_lattice_index(0); face A -1-dimensional face of a 2-dimensional combinatorial polyhedron Obtain further information regarding a face:: @@ -97,10 +97,10 @@ cdef class CombinatorialFace(SageObject): Obtain a combinatorial face from an index of the face lattice:: - sage: F = C.face_lattice() # optional - sage.combinat - sage: F._elements[3] # optional - sage.combinat + sage: F = C.face_lattice() # needs sage.combinat + sage: F._elements[3] # needs sage.combinat 34 - sage: C.face_by_face_lattice_index(29) # optional - sage.combinat + sage: C.face_by_face_lattice_index(29) A 1-dimensional face of a 5-dimensional combinatorial polyhedron Obtain the dimension of a combinatorial face:: @@ -260,15 +260,16 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(6) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(dimension=3, algorithm='primal') # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.__repr__() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(6) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(dimension=3, algorithm='primal') + sage: face = next(it) + sage: face.__repr__() 'A 3-dimensional face of a 5-dimensional combinatorial polyhedron' - sage: it = C.face_generator(dimension=3, algorithm='dual') # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.__repr__() # optional - sage.combinat + sage: it = C.face_generator(dimension=3, algorithm='dual') + sage: face = next(it) + sage: face.__repr__() 'A 3-dimensional face of a 5-dimensional combinatorial polyhedron' """ return "A {}-dimensional face of a {}-dimensional combinatorial polyhedron"\ @@ -318,15 +319,16 @@ cdef class CombinatorialFace(SageObject): TESTS:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: F = C.face_lattice() # optional - sage.combinat - sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: F = C.face_lattice() + sage: G = F.relabel(C.face_by_face_lattice_index) sage: P = polytopes.cyclic_polytope(4,10) sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() # optional - sage.combinat - sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat + sage: F = C.face_lattice() # needs sage.combinat + sage: G = F.relabel(C.face_by_face_lattice_index) # needs sage.combinat """ return self._hash_index @@ -349,7 +351,7 @@ cdef class CombinatorialFace(SageObject): sage: F2 = C.face_by_face_lattice_index(1) sage: F1 < F2 True - sage: for i,j in Combinations(range(28), 2): # optional - sage.combinat + sage: for i,j in Combinations(range(28), 2): ....: F1 = C.face_by_face_lattice_index(i) ....: F2 = C.face_by_face_lattice_index(j) ....: if F1.dim() != F2.dim(): @@ -361,7 +363,7 @@ cdef class CombinatorialFace(SageObject): sage: F2 = C.face_by_face_lattice_index(1) sage: F1 < F2 True - sage: for i,j in Combinations(range(28), 2): # optional - sage.combinat + sage: for i,j in Combinations(range(28), 2): ....: F1 = C.face_by_face_lattice_index(i) ....: F2 = C.face_by_face_lattice_index(j) ....: if F1.dim() != F2.dim(): @@ -501,16 +503,17 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.associahedron(['A', 3]) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator() # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.dimension() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.associahedron(['A', 3]) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator() + sage: face = next(it) + sage: face.dimension() 2 ``dim`` is an alias:: - sage: face.dim() # optional - sage.combinat + sage: face.dim() # needs sage.combinat 2 """ if self._dual: @@ -545,19 +548,20 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(dimension=2) # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(dimension=2) + sage: face = next(it) + sage: face.ambient_Vrepresentation() (A vertex at (1, 3, 2, 5, 4), A vertex at (2, 3, 1, 5, 4), A vertex at (3, 1, 2, 5, 4), A vertex at (3, 2, 1, 5, 4), A vertex at (2, 1, 3, 5, 4), A vertex at (1, 2, 3, 5, 4)) - sage: face = next(it) # optional - sage.combinat - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face = next(it) + sage: face.ambient_Vrepresentation() (A vertex at (2, 1, 4, 5, 3), A vertex at (3, 2, 4, 5, 1), A vertex at (3, 1, 4, 5, 2), @@ -609,13 +613,14 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(dimension=2) # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: next(it).ambient_V_indices() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(dimension=2) + sage: face = next(it) + sage: next(it).ambient_V_indices() (32, 91, 92, 93, 94, 95) - sage: next(it).ambient_V_indices() # optional - sage.combinat + sage: next(it).ambient_V_indices() (32, 89, 90, 94) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) @@ -688,14 +693,15 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(2) # optional - sage.combinat - sage: next(it).ambient_Hrepresentation() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(2) + sage: next(it).ambient_Hrepresentation() (An inequality (1, 1, 1, 0, 0) x - 6 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: next(it).ambient_Hrepresentation() # optional - sage.combinat + sage: next(it).ambient_Hrepresentation() (An inequality (0, 0, -1, -1, 0) x + 9 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) @@ -748,21 +754,22 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(2) # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.ambient_H_indices(add_equations=False) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(2) + sage: face = next(it) + sage: face.ambient_H_indices(add_equations=False) (28, 29) - sage: face2 = next(it) # optional - sage.combinat - sage: face2.ambient_H_indices(add_equations=False) # optional - sage.combinat + sage: face2 = next(it) + sage: face2.ambient_H_indices(add_equations=False) (25, 29) Add the indices of the equation:: - sage: face.ambient_H_indices(add_equations=True) # optional - sage.combinat + sage: face.ambient_H_indices(add_equations=True) # needs sage.combinat (28, 29, 30) - sage: face2.ambient_H_indices(add_equations=True) # optional - sage.combinat + sage: face2.ambient_H_indices(add_equations=True) # needs sage.combinat (25, 29, 30) Another example:: @@ -828,13 +835,14 @@ cdef class CombinatorialFace(SageObject): Specifying whether to count the equations or not:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(2) # optional - sage.combinat - sage: f = next(it) # optional - sage.combinat - sage: f.n_ambient_Hrepresentation(add_equations=True) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(2) + sage: f = next(it) + sage: f.n_ambient_Hrepresentation(add_equations=True) 3 - sage: f.n_ambient_Hrepresentation(add_equations=False) # optional - sage.combinat + sage: f.n_ambient_Hrepresentation(add_equations=False) 2 TESTS:: @@ -877,7 +885,7 @@ cdef class CombinatorialFace(SageObject): sage: F.f_vector() (1, 5, 10, 10, 5, 1) sage: F_alt = polytopes.cyclic_polytope(4,5).combinatorial_polyhedron() - sage: F_alt.vertex_facet_graph().is_isomorphic(F.vertex_facet_graph()) # optional - sage.graphs + sage: F_alt.vertex_facet_graph().is_isomorphic(F.vertex_facet_graph()) # needs sage.graphs True Obtaining the quotient:: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx index b670ad2e53f..baeb8fc4855 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx @@ -31,11 +31,12 @@ Obtain the facets of a polyhedron as :class:`~sage.geometry.polyhedron.combinato Obtain the Vrepresentation of a polyhedron as facet-incidences stored in :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`:: + sage: # needs sage.combinat sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import incidence_matrix_to_bit_rep_of_Vrep - sage: P = polytopes.associahedron(['A',4]) # optional - sage.combinat - sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) # optional - sage.combinat - sage: face_list.compute_dimension() # optional - sage.combinat + sage: P = polytopes.associahedron(['A',4]) + sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) + sage: face_list.compute_dimension() 4 Obtain the facets of a polyhedron as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces` from a facet list:: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx index cd24dd5be66..f0ac1e774a7 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx @@ -207,13 +207,13 @@ cdef class FaceIterator_base(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator() # indirect doctest # optional - sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator() # indirect doctest sage: f_vector = [1, 0, 0, 0, 1] - sage: for face in it: f_vector[face.dimension()+1] += 1 # optional - sage.combinat - sage: print ('f_vector of permutahedron(4): ', f_vector) # optional - sage.combinat + sage: for face in it: f_vector[face.dimension()+1] += 1 + sage: print ('f_vector of permutahedron(4): ', f_vector) f_vector of permutahedron(4): [1, 24, 36, 14, 1] sage: TestSuite(sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator).run() @@ -637,17 +637,18 @@ cdef class FaceIterator_base(SageObject): If the iterator has already been used, it must be reset before:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator() # optional - sage.rings.number_field - sage: _ = next(it), next(it) # optional - sage.rings.number_field - sage: next(it).ambient_V_indices() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator() + sage: _ = next(it), next(it) + sage: next(it).ambient_V_indices() (15, 16, 17, 18, 19) - sage: it.meet_of_Hrep(9,11) # optional - sage.rings.number_field + sage: it.meet_of_Hrep(9,11) Traceback (most recent call last): ... ValueError: please reset the face iterator - sage: it.reset() # optional - sage.rings.number_field - sage: it.meet_of_Hrep(9,11).ambient_H_indices() # optional - sage.rings.number_field + sage: it.reset() + sage: it.meet_of_Hrep(9,11).ambient_H_indices() (9, 11) TESTS: @@ -722,17 +723,18 @@ cdef class FaceIterator_base(SageObject): If the iterator has already been used, it must be reset before:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator() # optional - sage.rings.number_field - sage: _ = next(it), next(it) # optional - sage.rings.number_field - sage: next(it).ambient_V_indices() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator() + sage: _ = next(it), next(it) + sage: next(it).ambient_V_indices() (15, 16, 17, 18, 19) - sage: it.join_of_Vrep(1,10) # optional - sage.rings.number_field + sage: it.join_of_Vrep(1,10) Traceback (most recent call last): ... ValueError: please reset the face iterator - sage: it.reset() # optional - sage.rings.number_field - sage: it.join_of_Vrep(1,10).ambient_V_indices() # optional - sage.rings.number_field + sage: it.reset() + sage: it.join_of_Vrep(1,10).ambient_V_indices() (1, 10) In the case of an unbounded polyhedron, we try to make sense of the input:: @@ -846,9 +848,10 @@ cdef class FaceIterator_base(SageObject): The face iterator must not have the output dimension specified:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator(2) # optional - sage.rings.number_field - sage: it._meet_of_coatoms(1,2) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator(2) + sage: it._meet_of_coatoms(1,2) Traceback (most recent call last): ... ValueError: face iterator must not have the output dimension specified @@ -955,24 +958,26 @@ cdef class FaceIterator_base(SageObject): If the iterator has already been used, it must be reset before:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator() # optional - sage.rings.number_field - sage: _ = next(it), next(it) # optional - sage.rings.number_field - sage: next(it).ambient_V_indices() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator() + sage: _ = next(it), next(it) + sage: next(it).ambient_V_indices() (15, 16, 17, 18, 19) - sage: it._join_of_atoms(1,10) # optional - sage.rings.number_field + sage: it._join_of_atoms(1,10) Traceback (most recent call last): ... ValueError: please reset the face iterator - sage: it.reset() # optional - sage.rings.number_field - sage: it._join_of_atoms(1,10).ambient_V_indices() # optional - sage.rings.number_field + sage: it.reset() + sage: it._join_of_atoms(1,10).ambient_V_indices() (1, 10) The face iterator must not have the output dimension specified:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator(2) # optional - sage.rings.number_field - sage: it._join_of_atoms(1,2) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator(2) + sage: it._join_of_atoms(1,2) Traceback (most recent call last): ... ValueError: face iterator must not have the output dimension specified @@ -1574,12 +1579,12 @@ cdef class FaceIterator(FaceIterator_base): r""" EXAMPLES:: - sage: P = polytopes.associahedron(['A',3]) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.face_generator() # optional - sage.combinat + sage: P = polytopes.associahedron(['A',3]) # needs sage.combinat + sage: C = CombinatorialPolyhedron(P) # needs sage.combinat + sage: C.face_generator() # needs sage.combinat Iterator over the proper faces of a 3-dimensional combinatorial polyhedron - sage: C.face_generator(1) # optional - sage.combinat + sage: C.face_generator(1) # needs sage.combinat Iterator over the 1-faces of a 3-dimensional combinatorial polyhedron """ if self.structure.output_dimension != -2: @@ -1845,11 +1850,11 @@ cdef class FaceIterator_geom(FaceIterator_base): r""" EXAMPLES:: - sage: P = polytopes.associahedron(['A',3]) # optional - sage.combinat - sage: P.face_generator() # optional - sage.combinat + sage: P = polytopes.associahedron(['A',3]) # needs sage.combinat + sage: P.face_generator() # needs sage.combinat Iterator over the faces of a 3-dimensional polyhedron in QQ^3 - sage: P.face_generator(1) # optional - sage.combinat + sage: P.face_generator(1) # needs sage.combinat Iterator over the 1-faces of a 3-dimensional polyhedron in QQ^3 """ if self._requested_dim is not None: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx index d365ee3a24e..dffa76036fa 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx @@ -39,11 +39,12 @@ Obtain the facets of a polyhedron:: Obtain the Vrepresentation of a polyhedron as facet-incidences:: + sage: # needs sage.combinat sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import incidence_matrix_to_bit_rep_of_Vrep - sage: P = polytopes.associahedron(['A',3]) # optional - sage.combinat - sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) # optional - sage.combinat - sage: face_list.compute_dimension() # optional - sage.combinat + sage: P = polytopes.associahedron(['A',3]) + sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) + sage: face_list.compute_dimension() 3 Obtain the facets of a polyhedron as :class:`ListOfFaces` from a facet list:: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx index 0454c9bc19c..be6ffbda794 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx @@ -100,7 +100,7 @@ cdef class PolyhedronFaceLattice: sage: P = polytopes.Birkhoff_polytope(3) sage: C = CombinatorialPolyhedron(P) sage: C._record_all_faces() # indirect doctests - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 50 elements ALGORITHM: @@ -215,7 +215,7 @@ cdef class PolyhedronFaceLattice: sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) sage: C._record_all_faces() # indirect doctests - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 28 elements sage: TestSuite(sage.geometry.polyhedron.combinatorial_polyhedron.polyhedron_face_lattice.PolyhedronFaceLattice).run() diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index 4fd1eadb2d8..f18492f584f 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -176,8 +176,8 @@ exact way to work with roots in Sage is the :mod:`Algebraic Real Field ` :: - sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # optional - sage.rings.number_field sage.symbolic - sage: triangle.Hrepresentation() # optional - sage.rings.number_field sage.symbolic + sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: triangle.Hrepresentation() # needs sage.rings.number_field sage.symbolic (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) @@ -186,12 +186,12 @@ symbolic ring element and, therefore, the polyhedron defined over the symbolic ring. This is currently not supported as SR is not exact:: - sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) # optional - sage.symbolic + sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) # needs sage.symbolic Traceback (most recent call last): ... ValueError: no default backend for computations with Symbolic Ring - sage: SR.is_exact() # optional - sage.symbolic + sage: SR.is_exact() # needs sage.symbolic False Even faster than all algebraic real numbers (the field ``AA``) is @@ -199,8 +199,8 @@ triangle, that would be:: sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) # optional - sage.rings.number_field - sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) # needs sage.rings.number_field + sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # needs sage.rings.number_field A 2-dimensional polyhedron in (Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^2 defined as the convex hull of 3 vertices @@ -220,7 +220,7 @@ A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex sage: Polyhedron(vertices = [[1.12345678901234, 2.123456789012345]]) A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex - sage: Polyhedron(vertices = [[1.123456789012345, 2.123456789012345]]) # optional - sage.rings.real_mpfr + sage: Polyhedron(vertices = [[1.123456789012345, 2.123456789012345]]) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: the only allowed inexact ring is 'RDF' with backend 'cdd' @@ -452,26 +452,28 @@ def Polyhedron(vertices=None, rays=None, lines=None, by the cyclic shifts of `(0, \pm 1, \pm (1+\sqrt(5))/2)`, cf. :wikipedia:`Regular_icosahedron`. It needs a number field:: - sage: R0. = QQ[] # optional - sage.rings.number_field - sage: R1. = NumberField(r0^2-5, embedding=AA(5)**(1/2)) # optional - sage.rings.number_field - sage: gold = (1+r1)/2 # optional - sage.rings.number_field - sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]] # optional - sage.rings.number_field - sage: pp = Permutation((1, 2, 3)) # optional - sage.combinat sage.rings.number_field - sage: icosah = Polyhedron( # optional - sage.combinat sage.rings.number_field + sage: # needs sage.rings.number_field + sage: R0. = QQ[] + sage: R1. = NumberField(r0^2-5, embedding=AA(5)**(1/2)) + sage: gold = (1+r1)/2 + sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]] + sage: pp = Permutation((1, 2, 3)) + sage: icosah = Polyhedron( # needs sage.combinat ....: [(pp^2).action(w) for w in v] + [pp.action(w) for w in v] + v, ....: base_ring=R1) - sage: len(icosah.faces(2)) # optional - sage.combinat sage.rings.number_field + sage: len(icosah.faces(2)) # needs sage.combinat 20 When the input contains elements of a Number Field, they require an embedding:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K = NumberField(x^2 - 2,'s') # optional - sage.rings.number_field - sage: s = K.0 # optional - sage.rings.number_field - sage: L = NumberField(x^3 - 2,'t') # optional - sage.rings.number_field - sage: t = L.0 # optional - sage.rings.number_field - sage: P = Polyhedron(vertices=[[0,s], [t,0]]) # optional - sage.rings.number_field + sage: K = NumberField(x^2 - 2,'s') + sage: s = K.0 + sage: L = NumberField(x^3 - 2,'t') + sage: t = L.0 + sage: P = Polyhedron(vertices=[[0,s], [t,0]]) Traceback (most recent call last): ... ValueError: invalid base ring @@ -508,12 +510,13 @@ def Polyhedron(vertices=None, rays=None, lines=None, sage: Polyhedron(o, base_ring=QQ) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices - sage: H. = HyperplaneArrangements(QQ) # optional - sage.combinat - sage: h = x + y - 1; h # optional - sage.combinat + sage: # needs sage.combinat + sage: H. = HyperplaneArrangements(QQ) + sage: h = x + y - 1; h Hyperplane x + y - 1 - sage: Polyhedron(h, base_ring=ZZ) # optional - sage.combinat + sage: Polyhedron(h, base_ring=ZZ) A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 1 line - sage: Polyhedron(h) # optional - sage.combinat + sage: Polyhedron(h) A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line .. NOTE:: @@ -567,7 +570,7 @@ def Polyhedron(vertices=None, rays=None, lines=None, Check that input with too many bits of precision returns an error (see :trac:`22552`):: - sage: Polyhedron(vertices=[(8.3319544851638732, 7.0567045956967727), # optional - sage.rings.real_mpfr + sage: Polyhedron(vertices=[(8.3319544851638732, 7.0567045956967727), # needs sage.rings.real_mpfr ....: (6.4876921900819049, 4.8435898415984129)]) Traceback (most recent call last): ... @@ -575,11 +578,11 @@ def Polyhedron(vertices=None, rays=None, lines=None, Check that setting ``base_ring`` to a ``RealField`` returns an error (see :trac:`22552`):: - sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(40)) # optional - sage.rings.real_mpfr + sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(40)) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: no default backend for computations with Real Field with 40 bits of precision - sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(53)) # optional - sage.rings.real_mpfr + sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(53)) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: no default backend for computations with Real Field with 53 bits of precision diff --git a/src/sage/geometry/polyhedron/double_description.py b/src/sage/geometry/polyhedron/double_description.py index e8aad9bcd29..089580e3146 100644 --- a/src/sage/geometry/polyhedron/double_description.py +++ b/src/sage/geometry/polyhedron/double_description.py @@ -28,10 +28,10 @@ `\RR`, for example:: sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm - sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), # optional - sage.rings.number_field + sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), # needs sage.rings.number_field ....: (-AA(3).sqrt(),-AA(2).sqrt(),1)]) - sage: alg = StandardAlgorithm(A) # optional - sage.rings.number_field - sage: alg.run().R # optional - sage.rings.number_field + sage: alg = StandardAlgorithm(A) + sage: alg.run().R # needs sage.rings.number_field [(-0.4177376677004119?, 0.5822623322995881?, 0.4177376677004119?), (-0.2411809548974793?, -0.2411809548974793?, 0.2411809548974793?), (0.07665629029830300?, 0.07665629029830300?, 0.2411809548974793?), @@ -411,10 +411,11 @@ def matrix_space(self, nrows, ncols): sage: DD.matrix_space(3,2) Full MatrixSpace of 3 by 2 dense matrices over Rational Field - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: A = matrix([[1,sqrt2],[2,0]]) # optional - sage.rings.number_field - sage: DD, _ = Problem(A).initial_pair() # optional - sage.rings.number_field - sage: DD.matrix_space(1,2) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(2) + sage: A = matrix([[1,sqrt2],[2,0]]) + sage: DD, _ = Problem(A).initial_pair() + sage: DD.matrix_space(1,2) Full MatrixSpace of 1 by 2 dense matrices over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? """ @@ -597,9 +598,9 @@ def base_ring(self): EXAMPLES:: - sage: A = matrix(AA, [(1, 1), (-1, 1)]) # optional - sage.rings.number_field + sage: A = matrix(AA, [(1, 1), (-1, 1)]) # needs sage.rings.number_field sage: from sage.geometry.polyhedron.double_description import Problem - sage: Problem(A).base_ring() # optional - sage.rings.number_field + sage: Problem(A).base_ring() # needs sage.rings.number_field Algebraic Real Field """ return self._field diff --git a/src/sage/geometry/polyhedron/face.py b/src/sage/geometry/polyhedron/face.py index 64b14e39386..8a1e2dc2969 100644 --- a/src/sage/geometry/polyhedron/face.py +++ b/src/sage/geometry/polyhedron/face.py @@ -35,7 +35,7 @@ or :meth:`~sage.geometry.polyhedron.base.face_lattice` to get the whole face lattice as a poset:: - sage: P.face_lattice() # optional - sage.combinat + sage: P.face_lattice() # needs sage.combinat Finite lattice containing 28 elements The faces are printed in shorthand notation where each integer is the @@ -404,7 +404,7 @@ def ambient_Hrepresentation(self, index=None): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: for face in square.face_lattice(): # optional - sage.combinat + sage: for face in square.face_lattice(): # needs sage.combinat ....: print(face.ambient_Hrepresentation()) (An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0, An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0) @@ -445,7 +445,7 @@ def ambient_Vrepresentation(self, index=None): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: for fl in square.face_lattice(): # optional - sage.combinat + sage: for fl in square.face_lattice(): # needs sage.combinat ....: print(fl.ambient_Vrepresentation()) () (A vertex at (1, -1),) @@ -478,14 +478,14 @@ def n_ambient_Hrepresentation(self): EXAMPLES:: sage: p = polytopes.cross_polytope(4) - sage: face = p.face_lattice()[5]; face # optional - sage.combinat + sage: face = p.face_lattice()[5]; face # needs sage.combinat A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices - sage: face.ambient_Hrepresentation() # optional - sage.combinat + sage: face.ambient_Hrepresentation() # needs sage.combinat (An inequality (1, -1, 1, -1) x + 1 >= 0, An inequality (1, 1, 1, 1) x + 1 >= 0, An inequality (1, 1, 1, -1) x + 1 >= 0, An inequality (1, -1, 1, 1) x + 1 >= 0) - sage: face.n_ambient_Hrepresentation() # optional - sage.combinat + sage: face.n_ambient_Hrepresentation() # needs sage.combinat 4 """ return len(self.ambient_Hrepresentation()) @@ -504,11 +504,11 @@ def n_ambient_Vrepresentation(self): EXAMPLES:: sage: p = polytopes.cross_polytope(4) - sage: face = p.face_lattice()[5]; face # optional - sage.combinat + sage: face = p.face_lattice()[5]; face # needs sage.combinat A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face.ambient_Vrepresentation() # needs sage.combinat (A vertex at (-1, 0, 0, 0), A vertex at (0, 0, -1, 0)) - sage: face.n_ambient_Vrepresentation() # optional - sage.combinat + sage: face.n_ambient_Vrepresentation() # needs sage.combinat 2 """ return len(self.ambient_Vrepresentation()) @@ -593,8 +593,8 @@ def dim(self): EXAMPLES:: - sage: fl = polytopes.dodecahedron().face_lattice() # optional - sage.combinat sage.rings.number_field - sage: sorted(x.dim() for x in fl) # optional - sage.combinat sage.rings.number_field + sage: fl = polytopes.dodecahedron().face_lattice() # needs sage.combinat sage.rings.number_field + sage: sorted(x.dim() for x in fl) # needs sage.combinat sage.rings.number_field [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3] @@ -628,8 +628,8 @@ def _repr_(self): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: a_face = list( square.face_lattice() )[8] # optional - sage.combinat - sage: a_face.__repr__() # optional - sage.combinat + sage: a_face = list( square.face_lattice() )[8] # needs sage.combinat + sage: a_face.__repr__() # needs sage.combinat 'A 1-dimensional face of a Polyhedron in ZZ^2 defined as the convex hull of 2 vertices' """ desc = '' @@ -705,7 +705,7 @@ def ambient_vector_space(self, base_field=None): Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line sage: line.ambient_vector_space() Vector space of dimension 2 over Rational Field - sage: line.ambient_vector_space(AA) # optional - sage.rings.number_field + sage: line.ambient_vector_space(AA) # needs sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field """ return self.polyhedron().ambient_vector_space(base_field=base_field) diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index 1c788d2c1bc..a1a59cdfe65 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -117,7 +117,7 @@ def zero_sum_projection(d, base_ring=None): Exact computation in :class:`AA `:: - sage: zero_sum_projection(3, base_ring=AA) # optional - sage.rings.number_field + sage: zero_sum_projection(3, base_ring=AA) # needs sage.rings.number_field [ 0.7071067811865475? -0.7071067811865475? 0] [ 0.4082482904638630? 0.4082482904638630? -0.8164965809277260?] @@ -171,17 +171,17 @@ def project_points(*points, **kwds): Check that it is (almost) an isometry:: - sage: V = list(map(vector, IntegerVectors(n=5, length=3))) # optional - sage.combinat - sage: P = project_points(*V) # optional - sage.combinat - sage: for i in range(21): # optional - sage.combinat + sage: V = list(map(vector, IntegerVectors(n=5, length=3))) + sage: P = project_points(*V) + sage: for i in range(21): # needs sage.combinat ....: for j in range(21): ....: assert abs((V[i]-V[j]).norm() - (P[i]-P[j]).norm()) < 0.00001 Example with exact computation:: - sage: V = [ vector(v) for v in IntegerVectors(n=4, length=2) ] # optional - sage.combinat - sage: P = project_points(*V, base_ring=AA) # optional - sage.combinat sage.rings.number_field - sage: for i in range(len(V)): # optional - sage.combinat sage.rings.number_field + sage: V = [ vector(v) for v in IntegerVectors(n=4, length=2) ] + sage: P = project_points(*V, base_ring=AA) # needs sage.combinat sage.rings.number_field + sage: for i in range(len(V)): # needs sage.combinat sage.rings.number_field ....: for j in range(len(V)): ....: assert (V[i]-V[j]).norm() == (P[i]-P[j]).norm() @@ -515,15 +515,16 @@ def regular_polygon(self, n, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: octagon = polytopes.regular_polygon(8) # optional - sage.rings.number_field - sage: octagon # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: octagon = polytopes.regular_polygon(8) + sage: octagon A 2-dimensional polyhedron in AA^2 defined as the convex hull of 8 vertices - sage: octagon.n_vertices() # optional - sage.rings.number_field + sage: octagon.n_vertices() 8 - sage: v = octagon.volume() # optional - sage.rings.number_field - sage: v # optional - sage.rings.number_field + sage: v = octagon.volume() + sage: v 2.828427124746190? - sage: v == 2*QQbar(2).sqrt() # optional - sage.rings.number_field + sage: v == 2*QQbar(2).sqrt() True Its non exact version:: @@ -537,14 +538,16 @@ def regular_polygon(self, n, exact=True, base_ring=None, backend=None): TESTS:: - sage: octagon = polytopes.regular_polygon(8, backend='normaliz') # optional - pynormaliz sage.rings.number_field - sage: octagon # optional - pynormaliz sage.rings.number_field + sage: # optional - pynormaliz, needs sage.rings.number_field + sage: octagon = polytopes.regular_polygon(8, backend='normaliz') + sage: octagon A 2-dimensional polyhedron in AA^2 defined as the convex hull of 8 vertices - sage: octagon.n_vertices() # optional - pynormaliz sage.rings.number_field + sage: octagon.n_vertices() 8 - sage: octagon.volume() # optional - pynormaliz sage.rings.number_field + sage: octagon.volume() 2*a - sage: TestSuite(octagon).run() # long time # optional - sage.rings.number_field + sage: TestSuite(octagon).run() # long time + sage: TestSuite(polytopes.regular_polygon(5, exact=False)).run() """ n = ZZ(n) @@ -678,8 +681,8 @@ def simplex(self, dim=3, project=False, base_ring=None, backend=None): Computation in algebraic reals:: - sage: s3 = polytopes.simplex(3, project=True, base_ring=AA) # optional - sage.rings.number_field - sage: s3.volume() == sqrt(3+1) / factorial(3) # optional - sage.rings.number_field + sage: s3 = polytopes.simplex(3, project=True, base_ring=AA) # needs sage.rings.number_field + sage: s3.volume() == sqrt(3+1) / factorial(3) # needs sage.rings.number_field True TESTS:: @@ -716,47 +719,48 @@ def icosahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: ico = polytopes.icosahedron() # optional - sage.rings.number_field - sage: ico.f_vector() # optional - sage.rings.number_field + sage: ico = polytopes.icosahedron() # needs sage.rings.number_field + sage: ico.f_vector() # needs sage.rings.number_field (1, 12, 30, 20, 1) - sage: ico.volume() # optional - sage.rings.number_field + sage: ico.volume() # needs sage.rings.number_field 5/12*sqrt5 + 5/4 Its non exact version:: - sage: ico = polytopes.icosahedron(exact=False) # optional - sage.groups - sage: ico.base_ring() # optional - sage.groups + sage: ico = polytopes.icosahedron(exact=False) # needs sage.groups + sage: ico.base_ring() # needs sage.groups Real Double Field - sage: ico.volume() # known bug (trac 18214) # optional - sage.groups + sage: ico.volume() # known bug # needs sage.groups 2.181694990... A version using `AA `:: - sage: ico = polytopes.icosahedron(base_ring=AA) # long time # optional - sage.rings.number_field sage.groups - sage: ico.base_ring() # long time # optional - sage.rings.number_field sage.groups + sage: ico = polytopes.icosahedron(base_ring=AA) # long time # needs sage.groups sage.rings.number_field + sage: ico.base_ring() # long time # needs sage.groups sage.rings.number_field Algebraic Real Field - sage: ico.volume() # long time # optional - sage.rings.number_field sage.groups + sage: ico.volume() # long time # needs sage.groups sage.rings.number_field 2.181694990624913? Note that if base ring is provided it must contain the square root of `5`. Otherwise you will get an error:: - sage: polytopes.icosahedron(base_ring=QQ) # optional - sage.symbolic + sage: polytopes.icosahedron(base_ring=QQ) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert 1/4*sqrt(5) + 1/4 to a rational TESTS:: - sage: ico = polytopes.icosahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field sage.groups - sage: ico.f_vector() # optional - pynormaliz sage.rings.number_field sage.groups + sage: # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: ico = polytopes.icosahedron(backend='normaliz') + sage: ico.f_vector() (1, 12, 30, 20, 1) - sage: ico.volume() # optional - pynormaliz sage.rings.number_field sage.groups + sage: ico.volume() 5/12*sqrt5 + 5/4 - sage: TestSuite(ico).run() # optional - pynormaliz sage.rings.number_field sage.groups + sage: TestSuite(ico).run() - sage: ico = polytopes.icosahedron(exact=False) # optional - sage.groups - sage: TestSuite(ico).run(skip="_test_lawrence") # optional - sage.groups + sage: ico = polytopes.icosahedron(exact=False) # needs sage.groups + sage: TestSuite(ico).run(skip="_test_lawrence") # needs sage.groups """ if base_ring is None and exact: @@ -798,31 +802,32 @@ def dodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: d12 = polytopes.dodecahedron() # optional - sage.rings.number_field sage.groups - sage: d12.f_vector() # optional - sage.rings.number_field sage.groups + sage: # needs sage.groups sage.rings.number_field + sage: d12 = polytopes.dodecahedron() + sage: d12.f_vector() (1, 20, 30, 12, 1) - sage: d12.volume() # optional - sage.rings.number_field sage.groups + sage: d12.volume() -176*sqrt5 + 400 - sage: numerical_approx(_) # optional - sage.rings.number_field sage.groups + sage: numerical_approx(_) 6.45203596003699 - sage: d12 = polytopes.dodecahedron(exact=False) # optional - sage.groups - sage: d12.base_ring() # optional - sage.groups + sage: d12 = polytopes.dodecahedron(exact=False) # needs sage.groups + sage: d12.base_ring() # needs sage.groups Real Double Field Here is an error with a field that does not contain `\sqrt(5)`:: - sage: polytopes.dodecahedron(base_ring=QQ) # optional - sage.symbolic sage.groups + sage: polytopes.dodecahedron(base_ring=QQ) # needs sage.groups sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert 1/4*sqrt(5) + 1/4 to a rational TESTS:: - sage: d12 = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field sage.groups - sage: d12.f_vector() # optional - pynormaliz sage.rings.number_field sage.groups + sage: d12 = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: d12.f_vector() # optional - pynormaliz, needs sage.groups sage.rings.number_field (1, 20, 30, 12, 1) - sage: TestSuite(d12).run() # optional - pynormaliz sage.rings.number_field sage.groups + sage: TestSuite(d12).run() # optional - pynormaliz, needs sage.groups sage.rings.number_field """ return self.icosahedron(exact=exact, base_ring=base_ring, backend=backend).polar() @@ -847,17 +852,17 @@ def small_rhombicuboctahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: sr = polytopes.small_rhombicuboctahedron() # optional - sage.rings.number_field - sage: sr.f_vector() # optional - sage.rings.number_field + sage: sr = polytopes.small_rhombicuboctahedron() # needs sage.rings.number_field + sage: sr.f_vector() # needs sage.rings.number_field (1, 24, 48, 26, 1) - sage: sr.volume() # optional - sage.rings.number_field + sage: sr.volume() # needs sage.rings.number_field 80/3*sqrt2 + 32 The faces are `8` equilateral triangles and `18` squares:: - sage: sum(1 for f in sr.facets() if len(f.vertices()) == 3) # optional - sage.rings.number_field + sage: sum(1 for f in sr.facets() if len(f.vertices()) == 3) # needs sage.rings.number_field 8 - sage: sum(1 for f in sr.facets() if len(f.vertices()) == 4) # optional - sage.rings.number_field + sage: sum(1 for f in sr.facets() if len(f.vertices()) == 4) # needs sage.rings.number_field 18 Its non exact version:: @@ -871,12 +876,13 @@ def small_rhombicuboctahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: sr = polytopes.small_rhombicuboctahedron(backend='normaliz') # optional - sage.rings.number_field pynormaliz - sage: sr.f_vector() # optional - sage.rings.number_field pynormaliz + sage: # optional - pynormaliz, needs sage.rings.number_field + sage: sr = polytopes.small_rhombicuboctahedron(backend='normaliz') + sage: sr.f_vector() (1, 24, 48, 26, 1) - sage: sr.volume() # optional - sage.rings.number_field pynormaliz + sage: sr.volume() 80/3*sqrt2 + 32 - sage: TestSuite(sr).run() # long time # optional - sage.rings.number_field pynormaliz + sage: TestSuite(sr).run() # long time """ if base_ring is None and exact: from sage.rings.number_field.number_field import QuadraticField @@ -918,8 +924,8 @@ def great_rhombicuboctahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: gr = polytopes.great_rhombicuboctahedron() # long time ~ 3sec # optional - sage.rings.number_field - sage: gr.f_vector() # long time # optional - sage.rings.number_field + sage: gr = polytopes.great_rhombicuboctahedron() # long time # needs sage.rings.number_field + sage: gr.f_vector() # long time # needs sage.rings.number_field (1, 48, 72, 26, 1) A faster implementation is obtained by setting ``exact=False``:: @@ -1072,28 +1078,28 @@ def truncated_cube(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: co = polytopes.truncated_cube() # optional - sage.rings.number_field - sage: co.f_vector() # optional - sage.rings.number_field + sage: co = polytopes.truncated_cube() # needs sage.rings.number_field + sage: co.f_vector() # needs sage.rings.number_field (1, 24, 36, 14, 1) Its facets are 8 triangles and 6 octogons:: - sage: sum(1 for f in co.facets() if len(f.vertices()) == 3) # optional - sage.rings.number_field + sage: sum(1 for f in co.facets() if len(f.vertices()) == 3) # needs sage.rings.number_field 8 - sage: sum(1 for f in co.facets() if len(f.vertices()) == 8) # optional - sage.rings.number_field + sage: sum(1 for f in co.facets() if len(f.vertices()) == 8) # needs sage.rings.number_field 6 Some more computation:: - sage: co.volume() # optional - sage.rings.number_field + sage: co.volume() # needs sage.rings.number_field 56/3*sqrt2 - 56/3 TESTS:: - sage: co = polytopes.truncated_cube(backend='normaliz') # optional - pynormaliz sage.rings.number_field - sage: co.f_vector() # optional - pynormaliz sage.rings.number_field + sage: co = polytopes.truncated_cube(backend='normaliz') # optional - pynormaliz, needs sage.rings.number_field + sage: co.f_vector() # optional - pynormaliz # needs sage.rings.number_field (1, 24, 36, 14, 1) - sage: TestSuite(co).run() # optional - pynormaliz sage.rings.number_field + sage: TestSuite(co).run() # optional - pynormaliz # needs sage.rings.number_field """ if base_ring is None and exact: @@ -1218,28 +1224,28 @@ def truncated_octahedron(self, backend=None): EXAMPLES:: - sage: co = polytopes.truncated_octahedron() # optional - sage.combinat - sage: co.f_vector() # optional - sage.combinat + sage: co = polytopes.truncated_octahedron() + sage: co.f_vector() (1, 24, 36, 14, 1) Its facets are 6 squares and 8 hexagons:: - sage: sum(1 for f in co.facets() if len(f.vertices()) == 4) # optional - sage.combinat + sage: sum(1 for f in co.facets() if len(f.vertices()) == 4) 6 - sage: sum(1 for f in co.facets() if len(f.vertices()) == 6) # optional - sage.combinat + sage: sum(1 for f in co.facets() if len(f.vertices()) == 6) 8 Some more computation:: - sage: co.volume() # optional - sage.combinat + sage: co.volume() 32 - sage: co.ehrhart_polynomial() # optional - latte_int sage.combinat + sage: co.ehrhart_polynomial() # optional - latte_int # needs sage.combinat 32*t^3 + 18*t^2 + 6*t + 1 TESTS:: - sage: to_norm = polytopes.truncated_octahedron(backend='normaliz') # optional - pynormaliz sage.combinat - sage: TestSuite(to_norm).run() # optional - pynormaliz sage.combinat + sage: to_norm = polytopes.truncated_octahedron(backend='normaliz') # optional - pynormaliz, needs sage.combinat + sage: TestSuite(to_norm).run() # optional - pynormaliz, needs sage.combinat """ v = [(0, e, f) for e in [-1, 1] for f in [-2, 2]] v = [(xyz[sigma(1) - 1], xyz[sigma(2) - 1], xyz[sigma(3) - 1]) @@ -1313,14 +1319,17 @@ def snub_cube(self, exact=False, base_ring=None, backend=None, verbose=False): EXAMPLES:: - sage: sc_inexact = polytopes.snub_cube(exact=False); sc_inexact # optional - sage.groups + sage: # needs sage.groups + sage: sc_inexact = polytopes.snub_cube(exact=False); sc_inexact A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 24 vertices - sage: sc_inexact.f_vector() # optional - sage.groups + sage: sc_inexact.f_vector() (1, 24, 60, 38, 1) - sage: sc_exact = polytopes.snub_cube(exact=True) # long time # optional - sage.groups sage.rings.number_field - sage: sc_exact.f_vector() # long time # optional - sage.groups sage.rings.number_field + + sage: # long time, needs sage.groups sage.rings.number_field + sage: sc_exact = polytopes.snub_cube(exact=True) + sage: sc_exact.f_vector() (1, 24, 60, 38, 1) - sage: sorted(sc_exact.vertices()) # long time # optional - sage.groups sage.rings.number_field + sage: sorted(sc_exact.vertices()) [A vertex at (-1, -z, -z^2), A vertex at (-1, -z^2, z), A vertex at (-1, z^2, -z), @@ -1345,13 +1354,13 @@ def snub_cube(self, exact=False, base_ring=None, backend=None, verbose=False): A vertex at (1, -z^2, -z), A vertex at (1, z^2, z), A vertex at (1, z, -z^2)] - sage: sc_exact.is_combinatorially_isomorphic(sc_inexact) # long time # optional - sage.groups sage.rings.number_field + sage: sc_exact.is_combinatorially_isomorphic(sc_inexact) True TESTS:: - sage: sc = polytopes.snub_cube(exact=True, backend='normaliz') # optional - pynormaliz sage.groups sage.rings.number_field - sage: sc.f_vector() # optional - pynormaliz sage.groups sage.rings.number_field + sage: sc = polytopes.snub_cube(exact=True, backend='normaliz') # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: sc.f_vector() # optional - pynormaliz, needs sage.groups sage.rings.number_field (1, 24, 60, 38, 1) """ @@ -1416,34 +1425,35 @@ def buckyball(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: bb = polytopes.buckyball() # long time - 6secs # optional - sage.groups sage.rings.number_field - sage: bb.f_vector() # long time # optional - sage.groups sage.rings.number_field + sage: bb = polytopes.buckyball() # long time # needs sage.groups sage.rings.number_field + sage: bb.f_vector() # long time # needs sage.groups sage.rings.number_field (1, 60, 90, 32, 1) - sage: bb.base_ring() # long time # optional - sage.groups sage.rings.number_field + sage: bb.base_ring() # long time # needs sage.groups sage.rings.number_field Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? A much faster implementation using floating point approximations:: - sage: bb = polytopes.buckyball(exact=False) # optional - sage.groups - sage: bb.f_vector() # optional - sage.groups + sage: bb = polytopes.buckyball(exact=False) # needs sage.groups + sage: bb.f_vector() # needs sage.groups (1, 60, 90, 32, 1) - sage: bb.base_ring() # optional - sage.groups + sage: bb.base_ring() # needs sage.groups Real Double Field Its facets are 5 regular pentagons and 6 regular hexagons:: - sage: sum(1 for f in bb.facets() if len(f.vertices()) == 5) # optional - sage.groups + sage: sum(1 for f in bb.facets() if len(f.vertices()) == 5) # needs sage.groups 12 - sage: sum(1 for f in bb.facets() if len(f.vertices()) == 6) # optional - sage.groups + sage: sum(1 for f in bb.facets() if len(f.vertices()) == 6) # needs sage.groups 20 TESTS:: - sage: bb = polytopes.buckyball(backend='normaliz') # optional - pynormaliz sage.groups sage.rings.number_field - sage: bb.f_vector() # optional - pynormaliz sage.groups sage.rings.number_field + sage: # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: bb = polytopes.buckyball(backend='normaliz') + sage: bb.f_vector() (1, 60, 90, 32, 1) - sage: bb.base_ring() # optional - pynormaliz sage.groups sage.rings.number_field + sage: bb.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? @@ -1467,26 +1477,27 @@ def icosidodecahedron(self, exact=True, backend=None): EXAMPLES:: - sage: id = polytopes.icosidodecahedron() # optional - sage.rings.number_field sage.groups - sage: id.f_vector() # optional - sage.rings.number_field sage.groups + sage: id = polytopes.icosidodecahedron() # needs sage.groups sage.rings.number_field + sage: id.f_vector() # needs sage.groups sage.rings.number_field (1, 30, 60, 32, 1) TESTS:: - sage: id = polytopes.icosidodecahedron(exact=False); id # optional - sage.rings.number_field sage.groups + sage: id = polytopes.icosidodecahedron(exact=False); id # needs sage.groups sage.rings.number_field A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 30 vertices - sage: TestSuite(id).run(skip=["_test_is_combinatorially_isomorphic", # optional - sage.rings.number_field sage.groups + sage: TestSuite(id).run(skip=["_test_is_combinatorially_isomorphic", # needs sage.groups sage.rings.number_field ....: "_test_product", ....: "_test_pyramid", ....: "_test_lawrence"]) - sage: id = polytopes.icosidodecahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field sage.groups - sage: id.f_vector() # optional - pynormaliz sage.rings.number_field sage.groups + sage: # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: id = polytopes.icosidodecahedron(backend='normaliz') + sage: id.f_vector() (1, 30, 60, 32, 1) - sage: id.base_ring() # optional - pynormaliz sage.rings.number_field sage.groups + sage: id.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: TestSuite(id).run() # long time # optional - pynormaliz sage.rings.number_field sage.groups + sage: TestSuite(id).run() # long time """ from sage.rings.number_field.number_field import QuadraticField from itertools import product @@ -1556,13 +1567,14 @@ def icosidodecahedron_V2(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: id = polytopes.icosidodecahedron_V2(backend='normaliz') # optional - pynormaliz - sage: id.f_vector() # optional - pynormaliz + sage: # optional - pynormaliz + sage: id = polytopes.icosidodecahedron_V2(backend='normaliz') + sage: id.f_vector() (1, 30, 60, 32, 1) - sage: id.base_ring() # optional - pynormaliz + sage: id.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: TestSuite(id).run() # long time # optional - pynormaliz + sage: TestSuite(id).run() # long time """ if base_ring is None and exact: from sage.rings.number_field.number_field import QuadraticField @@ -1605,18 +1617,18 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: td = polytopes.truncated_dodecahedron() # optional - sage.rings.number_field - sage: td.f_vector() # optional - sage.rings.number_field + sage: td = polytopes.truncated_dodecahedron() # needs sage.rings.number_field + sage: td.f_vector() # needs sage.rings.number_field (1, 60, 90, 32, 1) - sage: td.base_ring() # optional - sage.rings.number_field + sage: td.base_ring() # needs sage.rings.number_field Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? Its facets are 20 triangles and 12 regular decagons:: - sage: sum(1 for f in td.facets() if len(f.vertices()) == 3) # optional - sage.rings.number_field + sage: sum(1 for f in td.facets() if len(f.vertices()) == 3) # needs sage.rings.number_field 20 - sage: sum(1 for f in td.facets() if len(f.vertices()) == 10) # optional - sage.rings.number_field + sage: sum(1 for f in td.facets() if len(f.vertices()) == 10) # needs sage.rings.number_field 12 The faster implementation using floating point approximations does not @@ -1639,10 +1651,11 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: td = polytopes.truncated_dodecahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field - sage: td.f_vector() # optional - pynormaliz sage.rings.number_field + sage: # optional - pynormaliz, needs sage.rings.number_field + sage: td = polytopes.truncated_dodecahedron(backend='normaliz') + sage: td.f_vector() (1, 60, 90, 32, 1) - sage: td.base_ring() # optional - pynormaliz sage.rings.number_field + sage: td.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? @@ -1701,15 +1714,15 @@ def pentakis_dodecahedron(self, exact=True, base_ring=None, backend=None): A much faster implementation is obtained when setting ``exact=False``:: - sage: pd = polytopes.pentakis_dodecahedron(exact=False) # optional - sage.groups - sage: pd.n_vertices() # optional - sage.groups + sage: pd = polytopes.pentakis_dodecahedron(exact=False) # needs sage.groups + sage: pd.n_vertices() # needs sage.groups 32 - sage: pd.n_inequalities() # optional - sage.groups + sage: pd.n_inequalities() # needs sage.groups 60 The 60 are triangles:: - sage: all(len(f.vertices()) == 3 for f in pd.facets()) # optional - sage.groups + sage: all(len(f.vertices()) == 3 for f in pd.facets()) # needs sage.groups True """ return self.buckyball(exact=exact, base_ring=base_ring, backend=backend).polar() @@ -1775,7 +1788,7 @@ def rhombicosidodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: rid = polytopes.rhombicosidodecahedron() # long time - 6secs + sage: rid = polytopes.rhombicosidodecahedron() # long time (6secs) sage: rid.f_vector() # long time (1, 60, 120, 62, 1) sage: rid.base_ring() # long time @@ -1801,10 +1814,11 @@ def rhombicosidodecahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: rid = polytopes.rhombicosidodecahedron(backend='normaliz') # optional - pynormaliz - sage: rid.f_vector() # optional - pynormaliz + sage: # optional - pynormaliz + sage: rid = polytopes.rhombicosidodecahedron(backend='normaliz') + sage: rid.f_vector() (1, 60, 120, 62, 1) - sage: rid.base_ring() # optional - pynormaliz + sage: rid.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? @@ -1881,7 +1895,7 @@ def truncated_icosidodecahedron(self, exact=True, base_ring=None, backend=None): TESTS:: sage: ti = polytopes.truncated_icosidodecahedron(backend='normaliz') # optional - pynormaliz - sage: ti.f_vector() # optional - pynormaliz + sage: ti.f_vector() (1, 120, 180, 62, 1) sage: ti.base_ring() # optional - pynormaliz Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? @@ -2242,22 +2256,23 @@ def six_hundred_cell(self, exact=False, backend=None): EXAMPLES:: - sage: p600 = polytopes.six_hundred_cell(); p600 # optional - sage.groups + sage: p600 = polytopes.six_hundred_cell(); p600 # needs sage.groups A 4-dimensional polyhedron in RDF^4 defined as the convex hull of 120 vertices - sage: p600.f_vector() # long time ~2sec # optional - sage.groups + sage: p600.f_vector() # long time (~2sec) # needs sage.groups (1, 120, 720, 1200, 600, 1) Computation with exact coordinates is currently too long to be useful:: - sage: p600 = polytopes.six_hundred_cell(exact=True) # not tested - very long time, optional - sage.groups - sage: len(list(p600.bounded_edges())) # not tested - very long time, optional - sage.groups + sage: p600 = polytopes.six_hundred_cell(exact=True) # long time, not tested, needs sage.groups + sage: len(list(p600.bounded_edges())) # long time, not tested, needs sage.groups 720 TESTS:: - sage: p600 = polytopes.six_hundred_cell(exact=True, # optional - pynormaliz sage.groups sage.rings.number_field + sage: # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: p600 = polytopes.six_hundred_cell(exact=True, ....: backend='normaliz') - sage: len(list(p600.bounded_edges())) # long time # optional - pynormaliz sage.groups sage.rings.number_field + sage: len(list(p600.bounded_edges())) # long time 720 """ if exact: @@ -2313,8 +2328,8 @@ def grand_antiprism(self, exact=True, backend=None, verbose=False): Computation with the backend ``'normaliz'`` is instantaneous:: - sage: gap_norm = polytopes.grand_antiprism(backend='normaliz') # optional - pynormaliz sage.rings.number_field - sage: gap_norm # optional - pynormaliz sage.rings.number_field + sage: gap_norm = polytopes.grand_antiprism(backend='normaliz') # optional - pynormaliz, needs sage.rings.number_field + sage: gap_norm # optional - pynormaliz, needs sage.rings.number_field A 4-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^4 defined as the convex hull of 100 vertices @@ -2470,21 +2485,23 @@ def hypersimplex(self, dim, k, project=False, backend=None): EXAMPLES:: - sage: h_4_2 = polytopes.hypersimplex(4, 2) # optional - sage.combinat - sage: h_4_2 # optional - sage.combinat + sage: # needs sage.combinat + sage: h_4_2 = polytopes.hypersimplex(4, 2) + sage: h_4_2 A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 6 vertices - sage: h_4_2.f_vector() # optional - sage.combinat + sage: h_4_2.f_vector() (1, 6, 12, 8, 1) - sage: h_4_2.ehrhart_polynomial() # optional - latte_int sage.combinat + sage: h_4_2.ehrhart_polynomial() # optional - latte_int 2/3*t^3 + 2*t^2 + 7/3*t + 1 - sage: TestSuite(h_4_2).run() # optional - sage.combinat + sage: TestSuite(h_4_2).run() - sage: h_7_3 = polytopes.hypersimplex(7, 3, project=True) # optional - sage.combinat - sage: h_7_3 # optional - sage.combinat + sage: # needs sage.combinat + sage: h_7_3 = polytopes.hypersimplex(7, 3, project=True) + sage: h_7_3 A 6-dimensional polyhedron in RDF^6 defined as the convex hull of 35 vertices - sage: h_7_3.f_vector() # optional - sage.combinat + sage: h_7_3.f_vector() (1, 35, 210, 350, 245, 84, 14, 1) - sage: TestSuite(h_7_3).run(skip=["_test_pyramid", "_test_lawrence"]) # optional - sage.combinat + sage: TestSuite(h_7_3).run(skip=["_test_pyramid", "_test_lawrence"]) """ verts = Permutations([0] * (dim - k) + [1] * k).list() if project: @@ -2530,9 +2547,9 @@ def permutahedron(self, n, project=False, backend=None): sage: perm4 = polytopes.permutahedron(4, project=True) sage: perm4 A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 24 vertices - sage: perm4.plot() # optional - sage.plot + sage: perm4.plot() # needs sage.plot Graphics3d Object - sage: perm4.graph().is_isomorphic(graphs.BubbleSortGraph(4)) # optional - sage.graphs + sage: perm4.graph().is_isomorphic(graphs.BubbleSortGraph(4)) # needs sage.graphs True As both Hrepresentation an Vrepresentation are known, the permutahedron can be set @@ -2610,35 +2627,36 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula EXAMPLES:: - sage: perm_a3 = polytopes.generalized_permutahedron(['A',3]); perm_a3 # optional - sage.combinat + sage: perm_a3 = polytopes.generalized_permutahedron(['A',3]); perm_a3 # needs sage.combinat A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 24 vertices You can put the starting point along the hyperplane of the first generator:: - sage: perm_a3_011 = polytopes.generalized_permutahedron(['A',3], [0,1,1]) # optional - sage.combinat + sage: # needs sage.combinat + sage: perm_a3_011 = polytopes.generalized_permutahedron(['A',3], [0,1,1]) sage: perm_a3_011 A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices - sage: perm_a3_110 = polytopes.generalized_permutahedron(['A',3], [1,1,0]) # optional - sage.combinat + sage: perm_a3_110 = polytopes.generalized_permutahedron(['A',3], [1,1,0]) sage: perm_a3_110 A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices - sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_011) # optional - sage.combinat + sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_011) True - sage: perm_a3_101 = polytopes.generalized_permutahedron(['A',3], [1,0,1]) # optional - sage.combinat + sage: perm_a3_101 = polytopes.generalized_permutahedron(['A',3], [1,0,1]) sage: perm_a3_101 A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices - sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_101) # optional - sage.combinat + sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_101) False - sage: perm_a3_011.f_vector() # optional - sage.combinat + sage: perm_a3_011.f_vector() (1, 12, 18, 8, 1) - sage: perm_a3_101.f_vector() # optional - sage.combinat + sage: perm_a3_101.f_vector() (1, 12, 24, 14, 1) The usual output does not necessarily give a polyhedron with isometric vertex figures:: - sage: perm_a2 = polytopes.generalized_permutahedron(['A',2]) # optional - sage.combinat - sage: perm_a2.vertices() # optional - sage.combinat + sage: perm_a2 = polytopes.generalized_permutahedron(['A',2]) # needs sage.combinat + sage: perm_a2.vertices() # needs sage.combinat (A vertex at (-1, -1), A vertex at (-1, 0), A vertex at (0, -1), @@ -2648,8 +2666,8 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula It works also with Coxeter types that lead to non-rational coordinates:: - sage: perm_b3 = polytopes.generalized_permutahedron(['B',3]) # long time # optional - sage.combinat sage.rings.number_field - sage: perm_b3 # long time # optional - sage.combinat sage.rings.number_field + sage: perm_b3 = polytopes.generalized_permutahedron(['B',3]) # long time, needs sage.combinat sage.rings.number_field + sage: perm_b3 # long time, needs sage.combinat sage.rings.number_field A 3-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095?)^3 defined as the convex hull of 48 vertices @@ -2659,9 +2677,9 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula rational coordinates. We first do the computations using floating point approximations (``RDF``):: - sage: perm_a2_inexact = polytopes.generalized_permutahedron( # optional - sage.combinat + sage: perm_a2_inexact = polytopes.generalized_permutahedron( # needs sage.combinat ....: ['A',2], exact=False) - sage: sorted(perm_a2_inexact.vertices()) # optional - sage.combinat + sage: sorted(perm_a2_inexact.vertices()) # needs sage.combinat [A vertex at (-1.0, -1.0), A vertex at (-1.0, 0.0), A vertex at (0.0, -1.0), @@ -2669,9 +2687,9 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula A vertex at (1.0, 0.0), A vertex at (1.0, 1.0)] - sage: perm_a2_inexact_reg = polytopes.generalized_permutahedron( # optional - sage.combinat + sage: perm_a2_inexact_reg = polytopes.generalized_permutahedron( # needs sage.combinat ....: ['A',2], exact=False, regular=True) - sage: sorted(perm_a2_inexact_reg.vertices()) # optional - sage.combinat + sage: sorted(perm_a2_inexact_reg.vertices()) # needs sage.combinat [A vertex at (-1.0, 0.0), A vertex at (-0.5, -0.8660254038), A vertex at (-0.5, 0.8660254038), @@ -2681,9 +2699,9 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula We can do the same computation using exact arithmetic with the field ``AA``:: - sage: perm_a2_reg = polytopes.generalized_permutahedron( # optional - sage.combinat sage.rings.number_field + sage: perm_a2_reg = polytopes.generalized_permutahedron( # needs sage.combinat sage.rings.number_field ....: ['A',2], regular=True) - sage: V = sorted(perm_a2_reg.vertices()); V # random # optional - sage.combinat sage.rings.number_field + sage: V = sorted(perm_a2_reg.vertices()); V # random # needs sage.combinat sage.rings.number_field [A vertex at (-1, 0), A vertex at (-1/2, -0.866025403784439?), A vertex at (-1/2, 0.866025403784439?), @@ -2694,61 +2712,65 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula Even though the numbers look like floating point approximations, the computation is actually exact. We can clean up the display a bit using ``exactify``:: - sage: for v in V: # optional - sage.combinat sage.rings.number_field + sage: for v in V: # needs sage.combinat sage.rings.number_field ....: for x in v: ....: x.exactify() - sage: V # optional - sage.combinat sage.rings.number_field + sage: V # needs sage.combinat sage.rings.number_field [A vertex at (-1, 0), A vertex at (-1/2, -0.866025403784439?), A vertex at (-1/2, 0.866025403784439?), A vertex at (1/2, -0.866025403784439?), A vertex at (1/2, 0.866025403784439?), A vertex at (1, 0)] - sage: perm_a2_reg.is_inscribed() # optional - sage.combinat sage.rings.number_field + sage: perm_a2_reg.is_inscribed() # needs sage.combinat sage.rings.number_field True Larger examples take longer:: - sage: perm_a3_reg = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field sage.combinat + sage: # needs sage.combinat sage.rings.number_field + sage: perm_a3_reg = polytopes.generalized_permutahedron( # long time ....: ['A',3], regular=True); perm_a3_reg A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices - sage: perm_a3_reg.is_inscribed() # long time # optional - sage.rings.number_field sage.combinat + sage: perm_a3_reg.is_inscribed() # long time True - sage: perm_b3_reg = polytopes.generalized_permutahedron( # not tested # optional - sage.rings.number_field sage.combinat # long time (12sec on 64 bits) + sage: perm_b3_reg = polytopes.generalized_permutahedron( # long time (12sec on 64 bits), not tested ....: ['B',3], regular=True); perm_b3_reg A 3-dimensional polyhedron in AA^3 defined as the convex hull of 48 vertices It is faster with the backend ``'number_field'``, which internally uses an embedded number field instead of doing the computations directly with the base ring (``AA``):: - sage: perm_a3_reg_nf = polytopes.generalized_permutahedron( # optional - sage.rings.number_field sage.combinat + sage: # needs sage.combinat sage.rings.number_field + sage: perm_a3_reg_nf = polytopes.generalized_permutahedron( ....: ['A',3], regular=True, backend='number_field'); perm_a3_reg_nf A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices - sage: perm_a3_reg_nf.is_inscribed() # optional - sage.rings.number_field sage.combinat + sage: perm_a3_reg_nf.is_inscribed() True - sage: perm_b3_reg_nf = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field sage.combinat + sage: perm_b3_reg_nf = polytopes.generalized_permutahedron( # long time ....: ['B',3], regular=True, backend='number_field'); perm_b3_reg_nf A 3-dimensional polyhedron in AA^3 defined as the convex hull of 48 vertices It is even faster with the backend ``'normaliz'``:: - sage: perm_a3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat + sage: # optional - pynormaliz, needs sage.combinat sage.rings.number_field + sage: perm_a3_reg_norm = polytopes.generalized_permutahedron( ....: ['A',3], regular=True, backend='normaliz'); perm_a3_reg_norm A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices - sage: perm_a3_reg_norm.is_inscribed() # optional - pynormaliz sage.rings.number_field sage.combinat + sage: perm_a3_reg_norm.is_inscribed() True - sage: perm_b3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat + sage: perm_b3_reg_norm = polytopes.generalized_permutahedron( ....: ['B',3], regular=True, backend='normaliz'); perm_b3_reg_norm A 3-dimensional polyhedron in AA^3 defined as the convex hull of 48 vertices The speedups from using backend ``'normaliz'`` allow us to go even further:: - sage: perm_h3 = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat + sage: # optional - pynormaliz, needs sage.combinat sage.rings.number_field + sage: perm_h3 = polytopes.generalized_permutahedron( ....: ['H',3], backend='normaliz'); perm_h3 A 3-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?)^3 defined as the convex hull of 120 vertices - sage: perm_f4 = polytopes.generalized_permutahedron( # long time, optional - pynormaliz sage.rings.number_field sage.combinat + sage: perm_f4 = polytopes.generalized_permutahedron( # long time ....: ['F',4], backend='normaliz'); perm_f4 A 4-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095?)^4 @@ -2761,7 +2783,7 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula TESTS:: - sage: TestSuite(perm_h3).run() # optional - pynormaliz sage.rings.number_field sage.combinat + sage: TestSuite(perm_h3).run() # optional - pynormaliz # needs sage.combinat sage.rings.number_field """ from sage.combinat.root_system.coxeter_group import CoxeterGroup try: @@ -3247,15 +3269,15 @@ def hypercube(self, dim, intervals=None, backend=None): sage: ls = [randint(-100,100) for _ in range(4)] sage: intervals = [[x, x+randint(1,50)] for x in ls] sage: P = polytopes.hypercube(4, intervals, backend='field') - sage: P1 = polytopes.hypercube(4, intervals, backend='ppl') # optional - pplpy - sage: assert P == P1 + sage: P1 = polytopes.hypercube(4, intervals, backend='ppl') # needs pplpy + sage: assert P == P1 # needs pplpy Check that coercion for input invervals is handled correctly:: sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1]]) sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1.0]]) - sage: P = polytopes.hypercube(2, [[1/2, 2], [0, AA(2).sqrt()]]) # optional - sage.rings.number_field - sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1.0]], backend='ppl') # optional - pplpy + sage: P = polytopes.hypercube(2, [[1/2, 2], [0, AA(2).sqrt()]]) # needs sage.rings.number_field + sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1.0]], backend='ppl') # needs pplpy Traceback (most recent call last): ... ValueError: specified backend ppl cannot handle the intervals @@ -3357,7 +3379,7 @@ def cube(self, intervals=None, backend=None): (1, 8, 12, 6, 1) sage: c.volume() 8 - sage: c.plot() # optional - sage.plot + sage: c.plot() # needs sage.plot Graphics3d Object Return the `0/1`-cube:: @@ -3441,16 +3463,16 @@ def parallelotope(self, generators, backend=None): sage: polytopes.parallelotope([[1,2,3,4], [0,1,0,7], [3,1,0,2], [0,0,1,0]]) A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 16 vertices - sage: K = QuadraticField(2, 'sqrt2') # optional - sage.rings.number_field - sage: sqrt2 = K.gen() # optional - sage.rings.number_field - sage: P = polytopes.parallelotope([(1, sqrt2), (1, -1)]); P # optional - sage.rings.number_field + sage: K = QuadraticField(2, 'sqrt2') # needs sage.rings.number_field + sage: sqrt2 = K.gen() # needs sage.rings.number_field + sage: P = polytopes.parallelotope([(1, sqrt2), (1, -1)]); P # needs sage.rings.number_field A 2-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?)^2 defined as the convex hull of 4 vertices TESTS:: - sage: TestSuite(P).run() # optional - sage.rings.number_field + sage: TestSuite(P).run() # needs sage.rings.number_field """ from sage.modules.free_module_element import vector generators = [vector(v) for v in generators] diff --git a/src/sage/geometry/polyhedron/misc.py b/src/sage/geometry/polyhedron/misc.py index ad0ad961bf1..b47e51f79b8 100644 --- a/src/sage/geometry/polyhedron/misc.py +++ b/src/sage/geometry/polyhedron/misc.py @@ -30,7 +30,7 @@ def _to_space_separated_string(l, base_ring=None): sage: import sage.geometry.polyhedron.misc as P sage: P._to_space_separated_string([2,3]) '2 3' - sage: P._to_space_separated_string([2, 1/5], RDF) # optional - sage.rings.real_double + sage: P._to_space_separated_string([2, 1/5], RDF) # needs sage.rings.real_double '2.0 0.2' """ if base_ring: diff --git a/src/sage/geometry/polyhedron/palp_database.py b/src/sage/geometry/polyhedron/palp_database.py index 70864270966..29b729cec18 100644 --- a/src/sage/geometry/polyhedron/palp_database.py +++ b/src/sage/geometry/polyhedron/palp_database.py @@ -5,7 +5,7 @@ EXAMPLES:: sage: from sage.geometry.polyhedron.palp_database import PALPreader - sage: for lp in PALPreader(2): + sage: for lp in PALPreader(2): # needs sage.graphs ....: cone = Cone([(1,r[0],r[1]) for r in lp.vertices()]) ....: fan = Fan([cone]) ....: X = ToricVariety(fan) diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 739a4e3edbb..92691fab081 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -64,7 +64,7 @@ def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, * EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: Polyhedra(AA, 3) # optional - sage.rings.number_field + sage: Polyhedra(AA, 3) # needs sage.rings.number_field Polyhedra in AA^3 sage: Polyhedra(ZZ, 3) Polyhedra in ZZ^3 @@ -96,34 +96,34 @@ def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, * TESTS:: - sage: Polyhedra(RR, 3, backend='field') # optional - sage.rings.real_mpfr + sage: Polyhedra(RR, 3, backend='field') # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: the 'field' backend for polyhedron cannot be used with non-exact fields - sage: Polyhedra(RR, 3) # optional - sage.rings.real_mpfr + sage: Polyhedra(RR, 3) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: no default backend for computations with Real Field with 53 bits of precision - sage: Polyhedra(QQ[I], 2) # optional - sage.rings.number_field + sage: Polyhedra(QQ[I], 2) # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: invalid base ring: Number Field in I with defining polynomial x^2 + 1 with I = 1*I cannot be coerced to a real field - sage: Polyhedra(AA, 3, backend='polymake') # optional - jupymake sage.rings.number_field + sage: Polyhedra(AA, 3, backend='polymake') # optional - jupymake # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: the 'polymake' backend for polyhedron cannot be used with Algebraic Real Field - sage: Polyhedra(QQ, 2, backend='normaliz') # optional - pynormaliz + sage: Polyhedra(QQ, 2, backend='normaliz') Polyhedra in QQ^2 - sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz sage.symbolic + sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz # needs sage.symbolic Polyhedra in (Symbolic Ring)^2 - sage: SCR = SR.subring(no_variables=True) # optional - sage.symbolic - sage: Polyhedra(SCR, 2, backend='normaliz') # optional - pynormaliz sage.symbolic + sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic + sage: Polyhedra(SCR, 2, backend='normaliz') # optional - pynormaliz # needs sage.symbolic Polyhedra in (Symbolic Constants Subring)^2 - sage: Polyhedra(SCR, 2, backend='number_field') # optional - sage.symbolic + sage: Polyhedra(SCR, 2, backend='number_field') # needs sage.symbolic Polyhedra in (Symbolic Constants Subring)^2 """ @@ -272,13 +272,14 @@ def list(self): sage: P.cardinality() +Infinity - sage: P = Polyhedra(AA, 0) # optional - sage.rings.number_field - sage: P.category() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = Polyhedra(AA, 0) + sage: P.category() Category of finite enumerated polyhedral sets over Algebraic Real Field - sage: P.list() # optional - sage.rings.number_field + sage: P.list() [The empty polyhedron in AA^0, A 0-dimensional polyhedron in AA^0 defined as the convex hull of 1 vertex] - sage: P.cardinality() # optional - sage.rings.number_field + sage: P.cardinality() 2 """ if self.ambient_dim(): @@ -516,8 +517,8 @@ def _repr_base_ring(self): sage: Polyhedra(QQ, 3)._repr_base_ring() 'QQ' sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # optional - sage.rings.number_field - sage: Polyhedra(K, 4)._repr_base_ring() # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # needs sage.rings.number_field + sage: Polyhedra(K, 4)._repr_base_ring() # needs sage.rings.number_field '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)' """ @@ -551,8 +552,8 @@ def _repr_ambient_module(self): sage: Polyhedra(QQ, 3)._repr_ambient_module() 'QQ^3' sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # optional - sage.rings.number_field - sage: Polyhedra(K, 4)._repr_ambient_module() # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # needs sage.rings.number_field + sage: Polyhedra(K, 4)._repr_ambient_module() # needs sage.rings.number_field '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^4' """ s = self._repr_base_ring() @@ -607,13 +608,14 @@ def _element_constructor_(self, *args, **kwds): Check that :trac:`21270` is fixed:: - sage: poly = polytopes.regular_polygon(7) # optional - sage.rings.number_field - sage: lp, x = poly.to_linear_program(solver='InteractiveLP', # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: poly = polytopes.regular_polygon(7) + sage: lp, x = poly.to_linear_program(solver='InteractiveLP', ....: return_variable=True) - sage: lp.set_objective(x[0] + x[1]) # optional - sage.rings.number_field - sage: b = lp.get_backend() # optional - sage.rings.number_field - sage: P = b.interactive_lp_problem() # optional - sage.rings.number_field - sage: p = P.plot() # optional - sage.plot sage.rings.number_field + sage: lp.set_objective(x[0] + x[1]) + sage: b = lp.get_backend() + sage: P = b.interactive_lp_problem() + sage: p = P.plot() # needs sage.plot sage: Q = Polyhedron(ieqs=[[-499999, 1000000], [1499999, -1000000]]) sage: P = Polyhedron(ieqs=[[0, 1.0], [1.0, -1.0]], base_ring=RDF) @@ -635,11 +637,12 @@ def _element_constructor_(self, *args, **kwds): When the parent of the object is not ``self``, the default is not to copy:: - sage: Q = P.base_extend(AA) # optional - sage.rings.number_field - sage: q = Q._element_constructor_(p) # optional - sage.rings.number_field - sage: q is p # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: Q = P.base_extend(AA) + sage: q = Q._element_constructor_(p) + sage: q is p False - sage: q = Q._element_constructor_(p, copy=False) # optional - sage.rings.number_field + sage: q = Q._element_constructor_(p, copy=False) Traceback (most recent call last): ... ValueError: you need to make a copy when changing the parent @@ -726,10 +729,10 @@ def _element_constructor_polyhedron(self, polyhedron, **kwds): sage: P(p) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices - sage: P = Polyhedra(AA, 3, backend='field') # optional - sage.rings.number_field + sage: P = Polyhedra(AA, 3, backend='field') # needs sage.rings.number_field sage: vertices = [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)] - sage: p = Polyhedron(vertices=vertices) # optional - sage.rings.number_field - sage: P(p) # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=vertices) + sage: P(p) # needs sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 4 vertices """ Vrep = None @@ -866,15 +869,15 @@ def _coerce_base_ring(self, other): Test that :trac:`28770` is fixed:: sage: z = QQ['z'].0 - sage: K = NumberField(z^2 - 2, 's') # optional - sage.rings.number_field - sage: triangle_QQ._coerce_base_ring(K) # optional - sage.rings.number_field + sage: K = NumberField(z^2 - 2, 's') # needs sage.rings.number_field + sage: triangle_QQ._coerce_base_ring(K) # needs sage.rings.number_field Number Field in s with defining polynomial z^2 - 2 - sage: triangle_QQ._coerce_base_ring(K.gen()) # optional - sage.rings.number_field + sage: triangle_QQ._coerce_base_ring(K.gen()) # needs sage.rings.number_field Number Field in s with defining polynomial z^2 - 2 sage: z = QQ['z'].0 - sage: K = NumberField(z^2 - 2, 's') # optional - sage.rings.number_field - sage: K.gen() * polytopes.simplex(backend='field') # optional - sage.rings.number_field + sage: K = NumberField(z^2 - 2, 's') # needs sage.rings.number_field + sage: K.gen() * polytopes.simplex(backend='field') # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in s with defining polynomial z^2 - 2)^4 defined as the convex hull of 4 vertices @@ -1286,9 +1289,9 @@ def does_backend_handle_base_ring(base_ring, backend): sage: from sage.geometry.polyhedron.parent import does_backend_handle_base_ring sage: does_backend_handle_base_ring(QQ, 'ppl') True - sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'ppl') # optional - sage.rings.number_field sage.symbolic + sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'ppl') # needs sage.rings.number_field sage.symbolic False - sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'field') # optional - sage.rings.number_field sage.symbolic + sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'field') # needs sage.rings.number_field sage.symbolic True """ try: diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py index 472ab1cf8c2..b6bb235b711 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -346,23 +346,24 @@ def __init__(self, polyhedron, proj=projection_func_identity): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups + sage: # needs sage.groups + sage: p = polytopes.icosahedron(exact=False) sage: from sage.geometry.polyhedron.plot import Projection - sage: Projection(p) # optional - sage.groups + sage: Projection(p) The projection of a polyhedron into 3 dimensions sage: def pr_12(x): return [x[1],x[2]] - sage: Projection(p, pr_12) # optional - sage.groups + sage: Projection(p, pr_12) The projection of a polyhedron into 2 dimensions - sage: Projection(p, lambda x: [x[1],x[2]] ) # another way of doing the same projection # optional - sage.groups + sage: Projection(p, lambda x: [x[1],x[2]] ) # another way of doing the same projection The projection of a polyhedron into 2 dimensions - sage: _.plot() # plot of the projected icosahedron in 2d # optional - sage.plot # optional - sage.groups + sage: _.plot() # plot of the projected icosahedron in 2d # needs sage.plot Graphics object consisting of 51 graphics primitives - sage: proj = Projection(p) # optional - sage.groups - sage: proj.stereographic([1,2,3]) # optional - sage.groups + sage: proj = Projection(p) + sage: proj.stereographic([1,2,3]) The projection of a polyhedron into 2 dimensions - sage: proj.plot() # optional - sage.plot # optional - sage.groups + sage: proj.plot() # needs sage.plot Graphics object consisting of 51 graphics primitives - sage: TestSuite(proj).run(skip='_test_pickling') # optional - sage.groups + sage: TestSuite(proj).run(skip='_test_pickling') """ self.parent_polyhedron = polyhedron self.coords = Sequence([]) @@ -411,12 +412,13 @@ def __call__(self, proj=projection_func_identity): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups + sage: # needs sage.groups + sage: p = polytopes.icosahedron(exact=False) sage: from sage.geometry.polyhedron.plot import Projection - sage: pproj = Projection(p) # optional - sage.groups + sage: pproj = Projection(p) sage: from sage.geometry.polyhedron.plot import ProjectionFuncStereographic - sage: pproj_stereo = pproj.__call__(proj=ProjectionFuncStereographic([1, 2, 3])) # optional - sage.groups - sage: sorted(pproj_stereo.polygons) # optional - sage.groups + sage: pproj_stereo = pproj.__call__(proj=ProjectionFuncStereographic([1, 2, 3])) + sage: sorted(pproj_stereo.polygons) [[2, 0, 9], [3, 1, 10], [4, 0, 8], @@ -435,11 +437,12 @@ def identity(self): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups + sage: # needs sage.groups + sage: p = polytopes.icosahedron(exact=False) sage: from sage.geometry.polyhedron.plot import Projection - sage: pproj = Projection(p) # optional - sage.groups - sage: ppid = pproj.identity() # optional - sage.groups - sage: ppid.dimension # optional - sage.groups + sage: pproj = Projection(p) + sage: ppid = pproj.identity() + sage: ppid.dimension 3 """ return self(projection_func_identity) @@ -458,7 +461,7 @@ def stereographic(self, projection_point=None): sage: from sage.geometry.polyhedron.plot import Projection sage: proj = Projection(polytopes.buckyball()); proj # long time The projection of a polyhedron into 3 dimensions - sage: proj.stereographic([5,2,3]).plot() # long time # optional - sage.plot + sage: proj.stereographic([5,2,3]).plot() # long time # needs sage.plot Graphics object consisting of 123 graphics primitives sage: Projection(polytopes.twenty_four_cell()).stereographic([2,0,0,0]) The projection of a polyhedron into 3 dimensions @@ -495,7 +498,7 @@ def schlegel(self, facet=None, position=None): sage: from sage.geometry.polyhedron.plot import Projection sage: Projection(cube4).schlegel() The projection of a polyhedron into 3 dimensions - sage: _.plot() # optional - sage.plot + sage: _.plot() # needs sage.plot Graphics3d Object The 4-cube with a truncated vertex seen into the resulting tetrahedron @@ -504,14 +507,14 @@ def schlegel(self, facet=None, position=None): sage: tcube4 = cube4.face_truncation(cube4.faces(0)[0]) sage: tcube4.facets()[4] A 3-dimensional face of a Polyhedron in QQ^4 defined as the convex hull of 4 vertices - sage: into_tetra = Projection(tcube4).schlegel(tcube4.facets()[4]) # optional - sage.symbolic - sage: into_tetra.plot() # optional - sage.plot sage.symbolic + sage: into_tetra = Projection(tcube4).schlegel(tcube4.facets()[4]) # needs sage.symbolic + sage: into_tetra.plot() # needs sage.plot sage.symbolic Graphics3d Object Taking a larger value for the position changes the image:: - sage: into_tetra_far = Projection(tcube4).schlegel(tcube4.facets()[4], 4) # optional - sage.symbolic - sage: into_tetra_far.plot() # optional - sage.plot sage.symbolic + sage: into_tetra_far = Projection(tcube4).schlegel(tcube4.facets()[4], 4) # needs sage.symbolic + sage: into_tetra_far.plot() # needs sage.plot sage.symbolic Graphics3d Object A value which is too large or negative give a projection point that @@ -917,8 +920,8 @@ def render_points_1d(self, **kwds): sage: cube1 = polytopes.hypercube(1) sage: proj = cube1.projection() - sage: points = proj.render_points_1d() # optional - sage.plot - sage: points._objects # optional - sage.plot + sage: points = proj.render_points_1d() # needs sage.plot + sage: points._objects # needs sage.plot [Point set defined by 2 point(s)] """ return point2d([c + [0] for c in self.coordinates_of(self.points)], **kwds) @@ -938,8 +941,8 @@ def render_line_1d(self, **kwds): EXAMPLES:: - sage: outline = polytopes.hypercube(1).projection().render_line_1d() # optional - sage.plot - sage: outline._objects[0] # optional - sage.plot + sage: outline = polytopes.hypercube(1).projection().render_line_1d() # needs sage.plot + sage: outline._objects[0] # needs sage.plot Line defined by 2 points """ if len(self.lines) == 0: @@ -956,10 +959,11 @@ def render_points_2d(self, **kwds): EXAMPLES:: - sage: hex = polytopes.regular_polygon(6) # optional - sage.rings.number_field - sage: proj = hex.projection() # optional - sage.rings.number_field - sage: hex_points = proj.render_points_2d() # optional - sage.plot sage.rings.number_field - sage: hex_points._objects # optional - sage.plot sage.rings.number_field + sage: # needs sage.rings.number_field + sage: hex = polytopes.regular_polygon(6) + sage: proj = hex.projection() + sage: hex_points = proj.render_points_2d() # needs sage.plot + sage: hex_points._objects # needs sage.plot [Point set defined by 6 point(s)] """ return point2d(self.coordinates_of(self.points), **kwds) @@ -970,9 +974,9 @@ def render_outline_2d(self, **kwds): EXAMPLES:: - sage: penta = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: outline = penta.projection().render_outline_2d() # optional - sage.plot sage.rings.number_field - sage: outline._objects[0] # optional - sage.plot sage.rings.number_field + sage: penta = polytopes.regular_polygon(5) # needs sage.rings.number_field + sage: outline = penta.projection().render_outline_2d() # needs sage.plot sage.rings.number_field + sage: outline._objects[0] # needs sage.plot sage.rings.number_field Line defined by 2 points """ wireframe = [] @@ -993,8 +997,8 @@ def render_fill_2d(self, **kwds): sage: cps = [i^3 for i in srange(-2, 2, 1/5)] sage: p = Polyhedron(vertices=[[(t^2-1)/(t^2+1), 2*t/(t^2+1)] for t in cps]) sage: proj = p.projection() - sage: filled_poly = proj.render_fill_2d() # optional - sage.plot - sage: filled_poly.axes_width() # optional - sage.plot + sage: filled_poly = proj.render_fill_2d() # needs sage.plot + sage: filled_poly.axes_width() # needs sage.plot 0.8 """ poly = [polygon2d(self.coordinates_of(p), **kwds) @@ -1009,8 +1013,8 @@ def render_vertices_3d(self, **kwds): sage: p = polytopes.cross_polytope(3) sage: proj = p.projection() - sage: verts = proj.render_vertices_3d() # optional - sage.plot - sage: verts.bounding_box() # optional - sage.plot + sage: verts = proj.render_vertices_3d() # needs sage.plot + sage: verts.bounding_box() # needs sage.plot ((-1.0, -1.0, -1.0), (1.0, 1.0, 1.0)) """ return point3d(self.coordinates_of(self.points), **kwds) @@ -1023,8 +1027,8 @@ def render_wireframe_3d(self, **kwds): sage: cube = polytopes.hypercube(3) sage: cube_proj = cube.projection() - sage: wire = cube_proj.render_wireframe_3d() # optional - sage.plot - sage: print(wire.tachyon().split('\n')[77]) # for testing # optional - sage.plot + sage: wire = cube_proj.render_wireframe_3d() # needs sage.plot + sage: print(wire.tachyon().split('\n')[77]) # for testing # needs sage.plot FCylinder base 1.0 1.0 -1.0 apex -1.0 1.0 -1.0 rad 0.005 texture... """ wireframe = [] @@ -1043,8 +1047,8 @@ def render_solid_3d(self, **kwds): EXAMPLES:: sage: p = polytopes.hypercube(3).projection() - sage: p_solid = p.render_solid_3d(opacity=.7) # optional - sage.plot - sage: type(p_solid) # optional - sage.plot + sage: p_solid = p.render_solid_3d(opacity=.7) # needs sage.plot + sage: type(p_solid) # needs sage.plot """ polys = self.polygons @@ -1074,10 +1078,10 @@ def render_0d(self, point_opts=None, line_opts=None, polygon_opts=None): EXAMPLES:: - sage: print(Polyhedron([]).projection().render_0d().description()) # optional - sage.plot + sage: print(Polyhedron([]).projection().render_0d().description()) # needs sage.plot sage: P = Polyhedron(ieqs=[(1,)]) - sage: print(P.projection().render_0d().description()) # optional - sage.plot + sage: print(P.projection().render_0d().description()) # needs sage.plot Point set defined by 1 point(s): [(0.0, 0.0)] """ if point_opts is None: @@ -1106,7 +1110,7 @@ def render_1d(self, point_opts=None, line_opts=None, polygon_opts=None): EXAMPLES:: - sage: Polyhedron([(0,), (1,)]).projection().render_1d() # optional - sage.plot + sage: Polyhedron([(0,), (1,)]).projection().render_1d() # needs sage.plot Graphics object consisting of 2 graphics primitives """ plt = Graphics() @@ -1138,7 +1142,7 @@ def render_2d(self, point_opts=None, line_opts=None, polygon_opts=None): sage: q3 = p3.projection() sage: p4 = Polyhedron(vertices=[[2,0]], rays=[[1,-1]], lines=[[1,1]]) sage: q4 = p4.projection() - sage: q1.plot() + q2.plot() + q3.plot() + q4.plot() # optional - sage.plot + sage: q1.plot() + q2.plot() + q3.plot() + q4.plot() # needs sage.plot Graphics object consisting of 18 graphics primitives """ plt = Graphics() @@ -1171,31 +1175,32 @@ def render_3d(self, point_opts=None, line_opts=None, polygon_opts=None): sage: p2 = Polyhedron(vertices=[[2,0,0], [0,2,0], [0,0,2]]) sage: p3 = Polyhedron(vertices=[[1,0,0], [0,1,0], [0,0,1]], ....: rays=[[-1,-1,-1]]) - sage: (p1.projection().plot() + p2.projection().plot() # optional - sage.plot + sage: (p1.projection().plot() + p2.projection().plot() # needs sage.plot ....: + p3.projection().plot()) Graphics3d Object It correctly handles various degenerate cases:: - sage: Polyhedron(lines=[[1,0,0], [0,1,0], [0,0,1]]).plot() # whole space # optional - sage.plot + sage: # needs sage.plot + sage: Polyhedron(lines=[[1,0,0], [0,1,0], [0,0,1]]).plot() # whole space Graphics3d Object - sage: Polyhedron(vertices=[[1,1,1]], rays=[[1,0,0]], # optional - sage.plot + sage: Polyhedron(vertices=[[1,1,1]], rays=[[1,0,0]], ....: lines=[[0,1,0], [0,0,1]]).plot() # half space Graphics3d Object - sage: Polyhedron(lines=[[0,1,0], [0,0,1]], # optional - sage.plot + sage: Polyhedron(lines=[[0,1,0], [0,0,1]], ....: vertices=[[1,1,1]]).plot() # R^2 in R^3 Graphics3d Object - sage: Polyhedron(rays=[[0,1,0], [0,0,1]], # quadrant wedge in R^2 # optional - sage.plot + sage: Polyhedron(rays=[[0,1,0], [0,0,1]], # quadrant wedge in R^2 ....: lines=[[1,0,0]]).plot() Graphics3d Object - sage: Polyhedron(rays=[[0,1,0]], # upper half plane in R^3 # optional - sage.plot + sage: Polyhedron(rays=[[0,1,0]], # upper half plane in R^3 ....: lines=[[1,0,0]]).plot() Graphics3d Object - sage: Polyhedron(lines=[[1,0,0]]).plot() # R^1 in R^2 # optional - sage.plot + sage: Polyhedron(lines=[[1,0,0]]).plot() # R^1 in R^2 Graphics3d Object - sage: Polyhedron(rays=[[0,1,0]]).plot() # Half-line in R^3 # optional - sage.plot + sage: Polyhedron(rays=[[0,1,0]]).plot() # Half-line in R^3 Graphics3d Object - sage: Polyhedron(vertices=[[1,1,1]]).plot() # point in R^3 # optional - sage.plot + sage: Polyhedron(vertices=[[1,1,1]]).plot() # point in R^3 Graphics3d Object The origin is not included, if it is not in the polyhedron (:trac:`23555`):: @@ -1203,13 +1208,13 @@ def render_3d(self, point_opts=None, line_opts=None, polygon_opts=None): sage: Q = Polyhedron([[100],[101]]) sage: P = Q*Q*Q; P A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices - sage: p = P.plot() # optional - sage.plot - sage: p.bounding_box() # optional - sage.plot + sage: p = P.plot() # needs sage.plot + sage: p.bounding_box() # needs sage.plot ((100.0, 100.0, 100.0), (101.0, 101.0, 101.0)) Plot 3d polytope with rainbow colors:: - sage: polytopes.hypercube(3).plot(polygon='rainbow', alpha=0.4) # optional - sage.plot + sage: polytopes.hypercube(3).plot(polygon='rainbow', alpha=0.4) # needs sage.plot Graphics3d Object """ pplt = None @@ -1300,12 +1305,13 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, EXAMPLES:: - sage: P1 = polytopes.small_rhombicuboctahedron() # optional - sage.rings.number_field - sage: Image1 = P1.projection().tikz([1,3,5], 175, scale=4, # optional - sage.rings.number_field + sage: # needs sage.plot sage.rings.number_field + sage: P1 = polytopes.small_rhombicuboctahedron() + sage: Image1 = P1.projection().tikz([1,3,5], 175, scale=4, ....: output_type='TikzPicture') - sage: type(Image1) # optional - sage.rings.number_field + sage: type(Image1) - sage: Image1 # optional - sage.rings.number_field + sage: Image1 \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -1322,10 +1328,10 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: _ = Image1.tex('polytope-tikz1.tex') # not tested # optional - sage.rings.number_field - sage: _ = Image1.png('polytope-tikz1.png') # not tested # optional - sage.rings.number_field - sage: _ = Image1.pdf('polytope-tikz1.pdf') # not tested # optional - sage.rings.number_field - sage: _ = Image1.svg('polytope-tikz1.svg') # not tested # optional - sage.rings.number_field + sage: _ = Image1.tex('polytope-tikz1.tex') # not tested + sage: _ = Image1.png('polytope-tikz1.png') # not tested + sage: _ = Image1.pdf('polytope-tikz1.pdf') # not tested + sage: _ = Image1.svg('polytope-tikz1.svg') # not tested A second example:: @@ -1354,6 +1360,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, The second example using a LatexExpr as output type:: + sage: # needs sage.plot sage: Image2 = P2.projection().tikz(scale=3, edge_color='blue!95!black', ....: facet_color='orange!95!black', opacity=0.4, ....: vertex_color='yellow', axis=True, @@ -1365,19 +1372,20 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, [scale=3.000000, back/.style={loosely dotted, thin}, edge/.style={color=blue!95!black, thick}, - sage: with open('polytope-tikz2.tex', 'w') as f: # not tested + sage: with open('polytope-tikz2.tex', 'w') as f: # not tested ....: _ = f.write(Image2) A third example:: + sage: # needs sage.plot sage: P3 = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]); P3 A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices - sage: Image3 = P3.projection().tikz([0.5, -1, -0.1], 55, scale=3, # optional - sage.plot + sage: Image3 = P3.projection().tikz([0.5, -1, -0.1], 55, scale=3, ....: edge_color='blue!95!black', ....: facet_color='orange!95!black', opacity=0.7, ....: vertex_color='yellow', axis=True, ....: output_type='TikzPicture') - sage: Image3 # optional - sage.plot + sage: Image3 \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -1394,10 +1402,10 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: _ = Image3.tex('polytope-tikz3.tex') # not tested # optional - sage.plot - sage: _ = Image3.png('polytope-tikz3.png') # not tested # optional - sage.plot - sage: _ = Image3.pdf('polytope-tikz3.pdf') # not tested # optional - sage.plot - sage: _ = Image3.svg('polytope-tikz3.svg') # not tested # optional - sage.plot + sage: _ = Image3.tex('polytope-tikz3.tex') # not tested + sage: _ = Image3.png('polytope-tikz3.png') # not tested + sage: _ = Image3.pdf('polytope-tikz3.pdf') # not tested + sage: _ = Image3.svg('polytope-tikz3.svg') # not tested A fourth example:: @@ -1618,26 +1626,26 @@ def _tikz_2d_in_3d(self, view, angle, scale, edge_color, facet_color, EXAMPLES:: - sage: P = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]) - sage: P + sage: # needs sage.plot + sage: P = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]); P A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices - sage: Image = P.projection()._tikz_2d_in_3d(view=[0.5, -1, -0.5], angle=55, scale=3, # optional - sage.plot + sage: Image = P.projection()._tikz_2d_in_3d(view=[0.5, -1, -0.5], angle=55, scale=3, ....: edge_color='blue!95!black', facet_color='orange', ....: opacity=0.5, vertex_color='yellow', axis=True) - sage: print('\n'.join(Image.splitlines()[:4])) # optional - sage.plot + sage: print('\n'.join(Image.splitlines()[:4])) \begin{tikzpicture}% [x={(0.644647cm, -0.476559cm)}, y={(0.192276cm, 0.857859cm)}, z={(-0.739905cm, -0.192276cm)}, - sage: with open('polytope-tikz3.tex', 'w') as f: # not tested # optional - sage.plot + sage: with open('polytope-tikz3.tex', 'w') as f: # not tested ....: _ = f.write(Image) :: sage: p = Polyhedron(vertices=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) sage: proj = p.projection() - sage: Img = proj.tikz([1, 1, 1], 130, axis=True, output_type='LatexExpr') # optional - sage.plot - sage: print('\n'.join(Img.splitlines()[12:21])) # optional - sage.plot + sage: Img = proj.tikz([1, 1, 1], 130, axis=True, output_type='LatexExpr') # needs sage.plot + sage: print('\n'.join(Img.splitlines()[12:21])) # needs sage.plot %% with the command: ._tikz_2d_in_3d and parameters: %% view = [1, 1, 1] %% angle = 130 @@ -1772,28 +1780,30 @@ def _tikz_3d_in_3d(self, view, angle, scale, edge_color, EXAMPLES:: - sage: P = polytopes.small_rhombicuboctahedron() # optional - sage.rings.number_field - sage: Image = P.projection()._tikz_3d_in_3d([3, 7, 5], 100, scale=3, # optional - sage.rings.number_field + sage: # needs sage.plot sage.rings.number_field + sage: P = polytopes.small_rhombicuboctahedron() + sage: Image = P.projection()._tikz_3d_in_3d([3, 7, 5], 100, scale=3, ....: edge_color='blue', facet_color='orange', ....: opacity=0.5, vertex_color='green', axis=True) - sage: type(Image) # optional - sage.rings.number_field + sage: type(Image) - sage: print('\n'.join(Image.splitlines()[:4])) # optional - sage.rings.number_field + sage: print('\n'.join(Image.splitlines()[:4])) \begin{tikzpicture}% [x={(-0.046385cm, 0.837431cm)}, y={(-0.243536cm, 0.519228cm)}, z={(0.968782cm, 0.170622cm)}, - sage: with open('polytope-tikz1.tex', 'w') as f: # not tested # optional - sage.rings.number_field + sage: with open('polytope-tikz1.tex', 'w') as f: # not tested ....: _ = f.write(Image) :: + sage: # needs sage.plot sage: Associahedron = Polyhedron(vertices=[[1, 0, 1], [1, 0, 0], [1, 1, 0], ....: [0, 0, -1], [0, 1, 0], [-1, 0, 0], ....: [0, 1, 1], [0, 0, 1], [0, -1, 0]]).polar() - sage: ImageAsso = Associahedron.projection().tikz([-15, -755, -655], 116, scale=1, # optional - sage.plot + sage: ImageAsso = Associahedron.projection().tikz([-15, -755, -655], 116, scale=1, ....: output_type='LatexExpr') - sage: print('\n'.join(ImageAsso.splitlines()[12:30])) # optional - sage.plot + sage: print('\n'.join(ImageAsso.splitlines()[12:30])) %% with the command: ._tikz_3d_in_3d and parameters: %% view = [-15, -755, -655] %% angle = 116 diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polygon.py b/src/sage/geometry/polyhedron/ppl_lattice_polygon.py index c7eac168fad..933275357d8 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polygon.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polygon.py @@ -407,11 +407,11 @@ def plot(self): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: P = LatticePolytope_PPL((1,0), (0,1), (0,0), (2,2)) - sage: P.plot() # optional - sage.plot + sage: P.plot() # needs sage.plot Graphics object consisting of 6 graphics primitives - sage: LatticePolytope_PPL([0], [1]).plot() # optional - sage.plot + sage: LatticePolytope_PPL([0], [1]).plot() # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: LatticePolytope_PPL([0]).plot() # optional - sage.plot + sage: LatticePolytope_PPL([0]).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives """ from sage.plot.point import point2d diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index 6cd4cd457f0..91e4d4de82f 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -48,7 +48,7 @@ sage: square = LatticePolytope_PPL((-1,-1), (-1,1), (1,-1), (1,1)) sage: fibers = [ f.vertices() for f in square.fibration_generator(1) ]; fibers [((1, 0), (-1, 0)), ((0, 1), (0, -1)), ((-1, -1), (1, 1)), ((-1, 1), (1, -1))] - sage: square.pointsets_mod_automorphism(fibers) # optional - sage.groups + sage: square.pointsets_mod_automorphism(fibers) # needs sage.groups (frozenset({(-1, -1), (1, 1)}), frozenset({(-1, 0), (1, 0)})) AUTHORS: @@ -118,36 +118,36 @@ def LatticePolytope_PPL(*args): sage: LatticePolytope_PPL((0,0), (1,0), (0,1)) A 2-dimensional lattice polytope in ZZ^2 with 3 vertices - sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # optional - pplpy - sage: p = point(Linear_Expression([2,3],0)); p # optional - pplpy + sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # needs pplpy + sage: p = point(Linear_Expression([2,3],0)); p # needs pplpy point(2/1, 3/1) - sage: LatticePolytope_PPL(p) # optional - pplpy + sage: LatticePolytope_PPL(p) # needs pplpy A 0-dimensional lattice polytope in ZZ^2 with 1 vertex - sage: P = C_Polyhedron(Generator_System(p)); P # optional - pplpy + sage: P = C_Polyhedron(Generator_System(p)); P # needs pplpy A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point - sage: LatticePolytope_PPL(P) # optional - pplpy + sage: LatticePolytope_PPL(P) # needs pplpy A 0-dimensional lattice polytope in ZZ^2 with 1 vertex A ``TypeError`` is raised if the arguments do not specify a lattice polytope:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((0,0), (1/2,1)) # optional - pplpy + sage: LatticePolytope_PPL((0,0), (1/2,1)) # needs pplpy Traceback (most recent call last): ... TypeError: unable to convert rational 1/2 to an integer - sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # optional - pplpy - sage: p = point(Linear_Expression([2,3],0), 5); p # optional - pplpy + sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # needs pplpy + sage: p = point(Linear_Expression([2,3],0), 5); p # needs pplpy point(2/5, 3/5) - sage: LatticePolytope_PPL(p) # optional - pplpy + sage: LatticePolytope_PPL(p) # needs pplpy Traceback (most recent call last): ... TypeError: generator is not a lattice polytope generator - sage: P = C_Polyhedron(Generator_System(p)); P # optional - pplpy + sage: P = C_Polyhedron(Generator_System(p)); P # needs pplpy A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point - sage: LatticePolytope_PPL(P) # optional - pplpy + sage: LatticePolytope_PPL(P) # needs pplpy Traceback (most recent call last): ... TypeError: polyhedron has non-integral generators @@ -386,14 +386,14 @@ def integral_points(self): ....: (-1,2,-1), (-1,2,-2), (-1,1,-2), (-1,-1,2), (-1,-3,2)] sage: P = LatticePolytope_PPL(*v) sage: pts1 = P.integral_points() # Sage's own code - sage: pts2 = LatticePolytope(v).points() # optional - palp + sage: pts2 = LatticePolytope(v).points() # needs palp sage: for p in pts1: p.set_immutable() - sage: set(pts1) == set(pts2) # optional - palp + sage: set(pts1) == set(pts2) # needs palp True sage: len(Polyhedron(v).integral_points()) # takes about 1 ms 23 - sage: len(LatticePolytope(v).points()) # takes about 13 ms # optional - palp + sage: len(LatticePolytope(v).points()) # takes about 13 ms # needs palp 23 sage: len(LatticePolytope_PPL(*v).integral_points()) # takes about 0.5 ms 23 @@ -648,7 +648,7 @@ def pointsets_mod_automorphism(self, pointsets): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: square = LatticePolytope_PPL((-1,-1), (-1,1), (1,-1), (1,1)) sage: fibers = [f.vertices() for f in square.fibration_generator(1)] - sage: square.pointsets_mod_automorphism(fibers) # optional - sage.groups sage.graphs + sage: square.pointsets_mod_automorphism(fibers) # needs sage.graphs sage.groups (frozenset({(-1, -1), (1, 1)}), frozenset({(-1, 0), (1, 0)})) sage: cell24 = LatticePolytope_PPL( @@ -657,7 +657,7 @@ def pointsets_mod_automorphism(self, pointsets): ....: (1,-1,-1,0), (0,0,-1,0), (0,-1,0,0), (-1,0,0,0), (1,-1,0,0), (1,0,-1,0), ....: (0,1,1,-1), (-1,1,1,0), (-1,1,0,0), (-1,0,1,0), (0,-1,-1,1), (0,0,0,-1)) sage: fibers = [f.vertices() for f in cell24.fibration_generator(2)] - sage: cell24.pointsets_mod_automorphism(fibers) # long time # optional - sage.groups sage.graphs + sage: cell24.pointsets_mod_automorphism(fibers) # long time # needs sage.graphs sage.groups (frozenset({(-1, 0, 0, 0), (-1, 0, 0, 1), (0, 0, 0, -1), @@ -975,19 +975,20 @@ def restricted_automorphism_group(self, vertex_labels=None): EXAMPLES:: + sage: # needs sage.graphs sage.groups sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: Z3square = LatticePolytope_PPL((0,0), (1,2), (2,1), (3,3)) - sage: G1234 = Z3square.restricted_automorphism_group( # optional - sage.groups sage.graphs + sage: G1234 = Z3square.restricted_automorphism_group( ....: vertex_labels=(1,2,3,4)) - sage: G1234 == PermutationGroup([[(2,3)], [(1,2),(3,4)]]) # optional - sage.groups sage.graphs + sage: G1234 == PermutationGroup([[(2,3)], [(1,2),(3,4)]]) True - sage: G = Z3square.restricted_automorphism_group() # optional - sage.groups sage.graphs - sage: G == PermutationGroup([[((1,2),(2,1))], [((0,0),(1,2)), # optional - sage.groups sage.graphs + sage: G = Z3square.restricted_automorphism_group() + sage: G == PermutationGroup([[((1,2),(2,1))], [((0,0),(1,2)), ....: ((2,1),(3,3))], [((0,0),(3,3))]]) True - sage: set(G.domain()) == set(Z3square.vertices()) # optional - sage.groups sage.graphs + sage: set(G.domain()) == set(Z3square.vertices()) True - sage: (set(tuple(x) for x in G.orbit(Z3square.vertices()[0])) # optional - sage.groups sage.graphs + sage: (set(tuple(x) for x in G.orbit(Z3square.vertices()[0])) ....: == set([(0, 0), (1, 2), (3, 3), (2, 1)])) True sage: cell24 = LatticePolytope_PPL( @@ -995,7 +996,7 @@ def restricted_automorphism_group(self, vertex_labels=None): ....: (0,-1,0,1), (-1,0,0,1), (1,0,0,-1), (0,1,0,-1), (0,0,1,-1), (-1,1,1,-1), ....: (1,-1,-1,0), (0,0,-1,0), (0,-1,0,0), (-1,0,0,0), (1,-1,0,0), (1,0,-1,0), ....: (0,1,1,-1), (-1,1,1,0), (-1,1,0,0), (-1,0,1,0), (0,-1,-1,1), (0,0,0,-1)) - sage: cell24.restricted_automorphism_group().cardinality() # optional - sage.groups sage.graphs + sage: cell24.restricted_automorphism_group().cardinality() 1152 """ if not self.is_full_dimensional(): @@ -1048,25 +1049,25 @@ def lattice_automorphism_group(self, points=None, point_labels=None): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: Z3square = LatticePolytope_PPL((0,0), (1,2), (2,1), (3,3)) - sage: Z3square.lattice_automorphism_group() # optional - sage.groups sage.graphs + sage: Z3square.lattice_automorphism_group() # needs sage.graphs sage.groups Permutation Group with generators [(), ((1,2),(2,1)), ((0,0),(3,3)), ((0,0),(3,3))((1,2),(2,1))] - sage: G1 = Z3square.lattice_automorphism_group(point_labels=(1,2,3,4)) # optional - sage.groups sage.graphs - sage: G1 + sage: G1 = Z3square.lattice_automorphism_group(point_labels=(1,2,3,4)) # needs sage.graphs sage.groups + sage: G1 # needs sage.graphs sage.groups Permutation Group with generators [(), (2,3), (1,4), (1,4)(2,3)] - sage: G1.cardinality() # optional - sage.groups sage.graphs + sage: G1.cardinality() # needs sage.graphs sage.groups 4 - sage: G2 = Z3square.restricted_automorphism_group(vertex_labels=(1,2,3,4)) # optional - sage.groups sage.graphs - sage: G2 == PermutationGroup([[(2,3)], [(1,2),(3,4)], [(1,4)]]) # optional - sage.groups sage.graphs + sage: G2 = Z3square.restricted_automorphism_group(vertex_labels=(1,2,3,4)) # needs sage.graphs sage.groups + sage: G2 == PermutationGroup([[(2,3)], [(1,2),(3,4)], [(1,4)]]) # needs sage.graphs sage.groups True - sage: G2.cardinality() # optional - sage.groups sage.graphs + sage: G2.cardinality() # needs sage.graphs sage.groups 8 sage: points = Z3square.integral_points(); points ((0, 0), (1, 1), (1, 2), (2, 1), (2, 2), (3, 3)) - sage: Z3square.lattice_automorphism_group(points, # optional - sage.groups sage.graphs + sage: Z3square.lattice_automorphism_group(points, # needs sage.graphs sage.groups ....: point_labels=(1,2,3,4,5,6)) Permutation Group with generators [(), (3,4), (1,6)(2,5), (1,6)(2,5)(3,4)] @@ -1075,7 +1076,7 @@ def lattice_automorphism_group(self, points=None, point_labels=None): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: lp = LatticePolytope_PPL((1,0,0), (0,1,0), (-1,-1,0)) - sage: lp.lattice_automorphism_group(point_labels=(0,1,2)) # optional - sage.groups sage.graphs + sage: lp.lattice_automorphism_group(point_labels=(0,1,2)) # needs sage.graphs sage.groups Permutation Group with generators [(), (1,2), (0,1), (0,1,2), (0,2,1), (0,2)] """ if not self.is_full_dimensional(): diff --git a/src/sage/geometry/polyhedron/representation.py b/src/sage/geometry/polyhedron/representation.py index bab34f3481d..554e36ec239 100644 --- a/src/sage/geometry/polyhedron/representation.py +++ b/src/sage/geometry/polyhedron/representation.py @@ -799,8 +799,8 @@ def is_facet_defining_inequality(self, other): sage: Q = Polyhedron(ieqs=[[0,2,0,3]]) sage: Q.inequalities()[0].is_facet_defining_inequality(P) True - sage: Q = Polyhedron(ieqs=[[0,AA(2).sqrt(),0,3]]) # optional - sage.rings.number_field - sage: Q.inequalities()[0].is_facet_defining_inequality(P) # optional - sage.rings.number_field + sage: Q = Polyhedron(ieqs=[[0,AA(2).sqrt(),0,3]]) # needs sage.rings.number_field + sage: Q.inequalities()[0].is_facet_defining_inequality(P) True sage: Q = Polyhedron(ieqs=[[1,1,0,0]]) sage: Q.inequalities()[0].is_facet_defining_inequality(P) @@ -902,9 +902,9 @@ def _repr_(self): Test that :trac:`21105` has been fixed:: sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^3 - 2, 'a', embedding=1.26) # optional - sage.rings.number_field - sage: P = Polyhedron(vertices=[(1,1,cbrt2),(cbrt2,1,1)]) # optional - sage.rings.number_field - sage: P.inequalities() # optional - sage.rings.number_field + sage: K. = NumberField(x^3 - 2, 'a', embedding=1.26) # needs sage.rings.number_field + sage: P = Polyhedron(vertices=[(1,1,cbrt2),(cbrt2,1,1)]) # needs sage.rings.number_field + sage: P.inequalities() # needs sage.rings.number_field (An inequality (-cbrt2^2 - cbrt2 - 1, 0, 0) x + cbrt2^2 + cbrt2 + 2 >= 0, An inequality (cbrt2^2 + cbrt2 + 1, 0, 0) x - cbrt2^2 + cbrt2 + 1 >= 0) """ @@ -994,7 +994,7 @@ def outer_normal(self): EXAMPLES:: - sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) + sage: p = Polyhedron(vertices=[[0,0,0],[1,1,0],[1,2,0]]) sage: a = next(p.inequality_generator()) sage: a.outer_normal() (1, -1, 0) diff --git a/src/sage/geometry/pseudolines.py b/src/sage/geometry/pseudolines.py index 4bb8d6ac8c9..8ce4496c65a 100644 --- a/src/sage/geometry/pseudolines.py +++ b/src/sage/geometry/pseudolines.py @@ -49,7 +49,7 @@ sage: p = PseudolineArrangement(permutations) sage: p Arrangement of pseudolines of size 4 - sage: p.show() # optional - sage.plot + sage: p.show() # needs sage.plot **Sequence of transpositions** @@ -67,7 +67,7 @@ sage: p = PseudolineArrangement(transpositions) sage: p Arrangement of pseudolines of size 4 - sage: p.show() # optional - sage.plot + sage: p.show() # needs sage.plot Note that this ordering is not necessarily unique. @@ -129,9 +129,9 @@ avoid a common crossing of three lines by adding a random noise to `b`:: sage: n = 20 - sage: l = sorted(zip(Subsets(20*n, n).random_element(), # optional - sage.combinat + sage: l = sorted(zip(Subsets(20*n, n).random_element(), ....: [randint(0, 20*n) + random() for i in range(n)])) - sage: print(l[:5]) # not tested # optional - sage.combinat + sage: print(l[:5]) # not tested # needs sage.combinat [(96, 278.0130613051349), (74, 332.92512282478714), (13, 155.65820951249867), (209, 34.753946221755307), (147, 193.51376457741441)] @@ -140,16 +140,16 @@ sage: permutations = [[0..i-1] + [i+1..n-1] for i in range(n)] sage: def a(x): return l[x][0] sage: def b(x): return l[x][1] - sage: for i, perm in enumerate(permutations): # optional - sage.combinat + sage: for i, perm in enumerate(permutations): ....: perm.sort(key=lambda j: (b(j)-b(i))/(a(i)-a(j))) And finally build the line arrangement:: sage: from sage.geometry.pseudolines import PseudolineArrangement - sage: p = PseudolineArrangement(permutations) # optional - sage.combinat - sage: print(p) # optional - sage.combinat + sage: p = PseudolineArrangement(permutations) + sage: print(p) Arrangement of pseudolines of size 20 - sage: p.show(figsize=[20,8]) # optional - sage.combinat sage.plot + sage: p.show(figsize=[20,8]) # needs sage.combinat sage.plot Author ^^^^^^ @@ -419,14 +419,14 @@ def show(self, **args): sage: from sage.geometry.pseudolines import PseudolineArrangement sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]] sage: p = PseudolineArrangement(permutations) - sage: p.show(figsize=[7,5]) # optional - sage.plot + sage: p.show(figsize=[7,5]) # needs sage.plot TESTS:: sage: from sage.geometry.pseudolines import PseudolineArrangement sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 0, 1], [2, 0, 1]] sage: p = PseudolineArrangement(permutations) - sage: p.show() # optional - sage.plot + sage: p.show() # needs sage.plot Traceback (most recent call last): ... ValueError: There has been a problem while plotting the figure... diff --git a/src/sage/geometry/relative_interior.py b/src/sage/geometry/relative_interior.py index d9ba65bbff5..8f4a63a8a14 100644 --- a/src/sage/geometry/relative_interior.py +++ b/src/sage/geometry/relative_interior.py @@ -324,11 +324,11 @@ def __eq__(self, other): sage: ri_segment = segment.relative_interior(); ri_segment Relative interior of a 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices - sage: segment2 = Polyhedron([[1, 2], [3, 4]], base_ring=AA) # optional - sage.rings.number_field - sage: ri_segment2 = segment2.relative_interior(); ri_segment2 # optional - sage.rings.number_field + sage: segment2 = Polyhedron([[1, 2], [3, 4]], base_ring=AA) # needs sage.rings.number_field + sage: ri_segment2 = segment2.relative_interior(); ri_segment2 # needs sage.rings.number_field Relative interior of a 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: ri_segment == ri_segment2 # optional - sage.rings.number_field + sage: ri_segment == ri_segment2 # needs sage.rings.number_field True TESTS:: @@ -337,7 +337,7 @@ def __eq__(self, other): sage: ri_segment == empty False """ - if type(self) != type(other): + if type(self) is not type(other): return False return self._polyhedron == other._polyhedron @@ -355,11 +355,11 @@ def __ne__(self, other): sage: ri_segment = segment.relative_interior(); ri_segment Relative interior of a 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices - sage: segment2 = Polyhedron([[1, 2], [3, 4]], base_ring=AA) # optional - sage.rings.number_field - sage: ri_segment2 = segment2.relative_interior(); ri_segment2 # optional - sage.rings.number_field + sage: segment2 = Polyhedron([[1, 2], [3, 4]], base_ring=AA) # needs sage.rings.number_field + sage: ri_segment2 = segment2.relative_interior(); ri_segment2 # needs sage.rings.number_field Relative interior of a 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: ri_segment != ri_segment2 # optional - sage.rings.number_field + sage: ri_segment != ri_segment2 # needs sage.rings.number_field False """ return not (self == other) diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index 0253cdc1888..c0161ab0c4f 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -99,7 +99,7 @@ class ParametrizedSurface3D(SageObject): sage: ellipsoid = ParametrizedSurface3D(ellipsoid_eq, coords, 'ellipsoid'); ellipsoid Parametrized surface ('ellipsoid') with equation (cos(u1)*cos(u2), 2*cos(u2)*sin(u1), 3*sin(u2)) - sage: ellipsoid.plot() # optional - sage.plot + sage: ellipsoid.plot() # needs sage.plot Graphics3d Object Standard surfaces can be constructed using the ``surfaces`` generator:: @@ -127,7 +127,7 @@ class ParametrizedSurface3D(SageObject): sage: enneper = surfaces.Enneper(); enneper Parametrized surface ('Enneper's surface') with equation (-1/9*(u^2 - 3*v^2 - 3)*u, -1/9*(3*u^2 - v^2 + 3)*v, 1/3*u^2 - 1/3*v^2) - sage: enneper.plot(aspect_ratio='automatic') # optional - sage.plot + sage: enneper.plot(aspect_ratio='automatic') # needs sage.plot Graphics3d Object We construct an ellipsoid whose axes are given by symbolic variables `a`, @@ -255,6 +255,7 @@ class ParametrizedSurface3D(SageObject): We can easily generate a color plot of the Gaussian curvature of a surface. Here we deal with the ellipsoid:: + sage: # needs numpy sage: u1, u2 = var('u1,u2', domain='real') sage: u = [u1,u2] sage: ellipsoid_equation(u1,u2) = [2*cos(u1)*cos(u2),1.5*cos(u1)*sin(u2),sin(u1)] @@ -264,27 +265,27 @@ class ParametrizedSurface3D(SageObject): sage: u2min, u2max = 0, 6.28 sage: u1num, u2num = 10, 20 sage: # make the arguments array - sage: from numpy import linspace # optional - numpy - sage: u1_array = linspace(u1min, u1max, u1num) # optional - numpy - sage: u2_array = linspace(u2min, u2max, u2num) # optional - numpy - sage: u_array = [(uu1,uu2) for uu1 in u1_array for uu2 in u2_array] # optional - numpy + sage: from numpy import linspace + sage: u1_array = linspace(u1min, u1max, u1num) + sage: u2_array = linspace(u2min, u2max, u2num) + sage: u_array = [(uu1,uu2) for uu1 in u1_array for uu2 in u2_array] sage: # Find the gaussian curvature - sage: K(u1,u2) = ellipsoid.gauss_curvature() # optional - numpy - sage: # Make array of K values # optional - numpy - sage: K_array = [K(uu[0],uu[1]) for uu in u_array] # optional - numpy + sage: K(u1,u2) = ellipsoid.gauss_curvature() + sage: # Make array of K values + sage: K_array = [K(uu[0],uu[1]) for uu in u_array] sage: # Find minimum and max of the Gauss curvature - sage: K_max = max(K_array) # optional - numpy - sage: K_min = min(K_array) # optional - numpy + sage: K_max = max(K_array) + sage: K_min = min(K_array) sage: # Make the array of color coefficients - sage: cc_array = [(ccc - K_min)/(K_max - K_min) for ccc in K_array] # optional - numpy - sage: points_array = [ellipsoid_equation(u_array[counter][0], # optional - numpy + sage: cc_array = [(ccc - K_min)/(K_max - K_min) for ccc in K_array] + sage: points_array = [ellipsoid_equation(u_array[counter][0], ....: u_array[counter][1]) ....: for counter in range(0,len(u_array))] - sage: curvature_ellipsoid_plot = sum(point([xx # optional - numpy sage.plot + sage: curvature_ellipsoid_plot = sum(point([xx # needs sage.plot ....: for xx in points_array[counter]], ....: color=hue(cc_array[counter]/2)) ....: for counter in range(0,len(u_array))) - sage: curvature_ellipsoid_plot.show(aspect_ratio=1) # optional - numpy sage.plot + sage: curvature_ellipsoid_plot.show(aspect_ratio=1) # needs sage.plot We can find the principal curvatures and principal directions of the elliptic paraboloid:: @@ -341,7 +342,7 @@ class ParametrizedSurface3D(SageObject): sage: g3 = [c[-1] for c in S.geodesics_numerical((0,0), ....: (cos(2*pi/3),sin(2*pi/3)), ....: (0,2*pi,100))] - sage: (S.plot(opacity=0.3) + line3d(g1, color='red') # optional - sage.plot + sage: (S.plot(opacity=0.3) + line3d(g1, color='red') # needs sage.plot ....: + line3d(g2, color='red') + line3d(g3, color='red')).show() """ @@ -514,7 +515,7 @@ def plot(self, urange=None, vrange=None, **kwds): sage: u, v = var('u, v', domain='real') sage: eq = (3*u + 3*u*v^2 - u^3, 3*v + 3*u^2*v - v^3, 3*(u^2-v^2)) sage: enneper = ParametrizedSurface3D(eq, (u, v), 'Enneper Surface') - sage: enneper.plot((-5, 5), (-5, 5)) # optional - sage.plot + sage: enneper.plot((-5, 5), (-5, 5)) # needs sage.plot Graphics3d Object """ diff --git a/src/sage/geometry/riemannian_manifolds/surface3d_generators.py b/src/sage/geometry/riemannian_manifolds/surface3d_generators.py index 3619c6c2952..ba8eff2ed2a 100644 --- a/src/sage/geometry/riemannian_manifolds/surface3d_generators.py +++ b/src/sage/geometry/riemannian_manifolds/surface3d_generators.py @@ -53,7 +53,7 @@ def Catenoid(c=1, name="Catenoid"): sage: cat = surfaces.Catenoid(); cat Parametrized surface ('Catenoid') with equation (cos(u)*cosh(v), cosh(v)*sin(u), v) - sage: cat.plot() # optional - sage.plot + sage: cat.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -86,7 +86,7 @@ def Crosscap(r=1, name="Crosscap"): sage: crosscap = surfaces.Crosscap(); crosscap Parametrized surface ('Crosscap') with equation ((cos(v) + 1)*cos(u), (cos(v) + 1)*sin(u), -sin(v)*tanh(-pi + u)) - sage: crosscap.plot() # optional - sage.plot + sage: crosscap.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -120,7 +120,7 @@ def Dini(a=1, b=1, name="Dini's surface"): sage: dini = surfaces.Dini(a=3, b=4); dini Parametrized surface ('Dini's surface') with equation (3*cos(u)*sin(v), 3*sin(u)*sin(v), 4*u + 3*cos(v) + 3*log(tan(1/2*v))) - sage: dini.plot() # optional - sage.plot + sage: dini.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -158,7 +158,7 @@ def Ellipsoid(center=(0, 0, 0), axes=(1, 1, 1), name="Ellipsoid"): sage: ell = surfaces.Ellipsoid(axes=(1, 2, 3)); ell Parametrized surface ('Ellipsoid') with equation (cos(u)*cos(v), 2*cos(v)*sin(u), 3*sin(v)) - sage: ell.plot() # optional - sage.plot + sage: ell.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -193,7 +193,7 @@ def Enneper(name="Enneper's surface"): sage: enn = surfaces.Enneper(); enn Parametrized surface ('Enneper's surface') with equation (-1/9*(u^2 - 3*v^2 - 3)*u, -1/9*(3*u^2 - v^2 + 3)*v, 1/3*u^2 - 1/3*v^2) - sage: enn.plot() # optional - sage.plot + sage: enn.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -227,7 +227,7 @@ def Helicoid(h=1, name="Helicoid"): sage: helicoid = surfaces.Helicoid(h=2); helicoid Parametrized surface ('Helicoid') with equation (rho*cos(theta), rho*sin(theta), theta/pi) - sage: helicoid.plot() # optional - sage.plot + sage: helicoid.plot() # needs sage.plot Graphics3d Object """ rho, theta = var('rho, theta') @@ -260,7 +260,7 @@ def Klein(r=1, name="Klein bottle"): sage: klein = surfaces.Klein(); klein Parametrized surface ('Klein bottle') with equation (-(sin(1/2*u)*sin(2*v) - cos(1/2*u)*sin(v) - 1)*cos(u), -(sin(1/2*u)*sin(2*v) - cos(1/2*u)*sin(v) - 1)*sin(u), cos(1/2*u)*sin(2*v) + sin(1/2*u)*sin(v)) - sage: klein.plot() # optional - sage.plot + sage: klein.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -291,7 +291,7 @@ def MonkeySaddle(name="Monkey saddle"): sage: saddle = surfaces.MonkeySaddle(); saddle Parametrized surface ('Monkey saddle') with equation (u, v, u^3 - 3*u*v^2) - sage: saddle.plot() # optional - sage.plot + sage: saddle.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -327,12 +327,12 @@ def Paraboloid(a=1, b=1, c=1, elliptic=True, name=None): sage: epar = surfaces.Paraboloid(1, 3, 2); epar Parametrized surface ('Elliptic paraboloid') with equation (u, v, 2*u^2 + 2/9*v^2) - sage: epar.plot() # optional - sage.plot + sage: epar.plot() # needs sage.plot Graphics3d Object sage: hpar = surfaces.Paraboloid(2, 3, 1, elliptic=False); hpar Parametrized surface ('Hyperbolic paraboloid') with equation (u, v, -1/4*u^2 + 1/9*v^2) - sage: hpar.plot() # optional - sage.plot + sage: hpar.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -372,7 +372,7 @@ def Sphere(center=(0, 0, 0), R=1, name="Sphere"): sage: sphere = surfaces.Sphere(center=(0, 1, -1), R=2); sphere Parametrized surface ('Sphere') with equation (2*cos(u)*cos(v), 2*cos(v)*sin(u) + 1, 2*sin(v) - 1) - sage: sphere.plot() # optional - sage.plot + sage: sphere.plot() # needs sage.plot Graphics3d Object Note that the radius of the sphere can be negative. The surface thus @@ -382,14 +382,14 @@ def Sphere(center=(0, 0, 0), R=1, name="Sphere"): sage: octant1 = surfaces.Sphere(R=1); octant1 Parametrized surface ('Sphere') with equation (cos(u)*cos(v), cos(v)*sin(u), sin(v)) - sage: octant1.plot((0, pi/2), (0, pi/2)) # optional - sage.plot + sage: octant1.plot((0, pi/2), (0, pi/2)) # needs sage.plot Graphics3d Object with the first octant of the unit sphere with negative radius:: sage: octant2 = surfaces.Sphere(R=-1); octant2 Parametrized surface ('Sphere') with equation (-cos(u)*cos(v), -cos(v)*sin(u), -sin(v)) - sage: octant2.plot((0, pi/2), (0, pi/2)) # optional - sage.plot + sage: octant2.plot((0, pi/2), (0, pi/2)) # needs sage.plot Graphics3d Object """ return SurfaceGenerators.Ellipsoid(center, (R, R, R), name) @@ -421,7 +421,7 @@ def Torus(r=2, R=3, name="Torus"): sage: torus = surfaces.Torus(); torus Parametrized surface ('Torus') with equation ((2*cos(v) + 3)*cos(u), (2*cos(v) + 3)*sin(u), 2*sin(v)) - sage: torus.plot() # optional - sage.plot + sage: torus.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -448,7 +448,7 @@ def WhitneyUmbrella(name="Whitney's umbrella"): sage: whitney = surfaces.WhitneyUmbrella(); whitney Parametrized surface ('Whitney's umbrella') with equation (u*v, u, v^2) - sage: whitney.plot() # optional - sage.plot + sage: whitney.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py index a8a2ad38ba6..c5d35bb2002 100644 --- a/src/sage/geometry/toric_lattice.py +++ b/src/sage/geometry/toric_lattice.py @@ -951,7 +951,7 @@ def __richcmp__(self, right, op): """ if self is right: return rich_to_bool(op, 0) - if type(self) != type(right): + if type(self) is not type(right): return NotImplemented lx = self.rank() @@ -1068,7 +1068,7 @@ def plot(self, **options): EXAMPLES:: sage: N = ToricLattice(3) - sage: N.plot() # optional - sage.plot + sage: N.plot() # needs sage.plot Graphics3d Object """ if "show_lattice" not in options: @@ -1215,12 +1215,12 @@ def plot(self, **options): sage: N = ToricLattice(3) sage: sublattice = N.submodule_with_basis([(1,1,0), (3,2,1)]) - sage: sublattice.plot() # optional - sage.plot + sage: sublattice.plot() # needs sage.plot Graphics3d Object Now we plot both the ambient lattice and its sublattice:: - sage: N.plot() + sublattice.plot(point_color="red") # optional - sage.plot + sage: N.plot() + sublattice.plot(point_color="red") # needs sage.plot Graphics3d Object """ if "show_lattice" not in options: diff --git a/src/sage/geometry/toric_lattice_element.pyx b/src/sage/geometry/toric_lattice_element.pyx index 6c6d28800b9..40897c019f5 100644 --- a/src/sage/geometry/toric_lattice_element.pyx +++ b/src/sage/geometry/toric_lattice_element.pyx @@ -394,7 +394,7 @@ cdef class ToricLatticeElement(Vector_integer_dense): sage: N = ToricLattice(3) sage: n = N(1,2,3) - sage: n.plot() # optional - sage.plot + sage: n.plot() # needs sage.plot Graphics3d Object """ tp = ToricPlotter(options, self.parent().degree()) diff --git a/src/sage/geometry/toric_plotter.py b/src/sage/geometry/toric_plotter.py index 9a14918a2ab..50b4008eb0f 100644 --- a/src/sage/geometry/toric_plotter.py +++ b/src/sage/geometry/toric_plotter.py @@ -14,8 +14,8 @@ In most cases, this module is used indirectly, e.g. :: - sage: fan = toric_varieties.dP6().fan() # optional - palp - sage: fan.plot() # optional - palp sage.plot + sage: fan = toric_varieties.dP6().fan() # needs palp sage.graphs + sage: fan.plot() # needs palp sage.graphs sage.plot Graphics object consisting of 31 graphics primitives You may change default plotting options as follows:: @@ -25,12 +25,12 @@ sage: toric_plotter.options(show_rays=False) sage: toric_plotter.options("show_rays") False - sage: fan.plot() # optional - palp sage.plot + sage: fan.plot() # needs palp sage.graphs sage.plot Graphics object consisting of 19 graphics primitives sage: toric_plotter.reset_options() sage: toric_plotter.options("show_rays") True - sage: fan.plot() # optional - palp sage.plot + sage: fan.plot() # needs palp sage.graphs sage.plot Graphics object consisting of 31 graphics primitives """ @@ -134,10 +134,10 @@ class ToricPlotter(SageObject): directly. Instead, use plotting method of the object which you want to plot, e.g. :: - sage: fan = toric_varieties.dP6().fan() # optional - palp - sage: fan.plot() # optional - palp sage.plot + sage: fan = toric_varieties.dP6().fan() # needs palp sage.graphs + sage: fan.plot() # needs palp sage.graphs sage.plot Graphics object consisting of 31 graphics primitives - sage: print(fan.plot()) # optional - palp sage.plot + sage: print(fan.plot()) # needs palp sage.graphs sage.plot Graphics object consisting of 31 graphics primitives If you do want to create your own plotting function for some toric @@ -163,24 +163,25 @@ class ToricPlotter(SageObject): For example, the plot from the previous example can be obtained as follows:: + sage: # needs palp sage.graphs sage.plot sage: from sage.geometry.toric_plotter import ToricPlotter sage: options = dict() # use default for everything - sage: tp = ToricPlotter(options, fan.lattice().degree()) # optional - palp - sage: tp.include_points(fan.rays()) # optional - palp - sage: tp.adjust_options() # optional - palp - sage: tp.set_rays(fan.rays()) # optional - palp - sage: result = tp.plot_lattice() # optional - palp sage.plot - sage: result += tp.plot_rays() # optional - palp sage.plot - sage: result += tp.plot_generators() # optional - palp sage.plot - sage: result += tp.plot_walls(fan(2)) # optional - palp sage.plot - sage: result # optional - palp sage.plot + sage: tp = ToricPlotter(options, fan.lattice().degree()) + sage: tp.include_points(fan.rays()) + sage: tp.adjust_options() + sage: tp.set_rays(fan.rays()) + sage: result = tp.plot_lattice() + sage: result += tp.plot_rays() + sage: result += tp.plot_generators() + sage: result += tp.plot_walls(fan(2)) + sage: result Graphics object consisting of 31 graphics primitives In most situations it is only necessary to include generators of rays, in this case they can be passed to the constructor as an optional argument. In the example above, the toric plotter can be completely set up using :: - sage: tp = ToricPlotter(options, fan.lattice().degree(), fan.rays()) # optional - palp + sage: tp = ToricPlotter(options, fan.lattice().degree(), fan.rays()) # needs palp sage.graphs sage.plot All options are exposed as attributes of toric plotters and can be modified after constructions, however you will have to manually call @@ -389,7 +390,7 @@ def plot_generators(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, [(3,4)]) - sage: tp.plot_generators() # optional - sage.plot + sage: tp.plot_generators() # needs sage.plot Graphics object consisting of 1 graphics primitive """ generators = self.generators @@ -440,7 +441,7 @@ def plot_labels(self, labels, positions): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) - sage: tp.plot_labels("u", [(1.5,0)]) # optional - sage.plot + sage: tp.plot_labels("u", [(1.5,0)]) # needs sage.plot Graphics object consisting of 1 graphics primitive """ result = Graphics() @@ -474,7 +475,7 @@ def plot_lattice(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) sage: tp.adjust_options() - sage: tp.plot_lattice() # optional - sage.plot + sage: tp.plot_lattice() # needs sage.plot Graphics object consisting of 1 graphics primitive """ if not self.show_lattice: @@ -518,7 +519,7 @@ def plot_points(self, points): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) sage: tp.adjust_options() - sage: tp.plot_points([(1,0), (0,1)]) # optional - sage.plot + sage: tp.plot_points([(1,0), (0,1)]) # needs sage.plot Graphics object consisting of 1 graphics primitive """ return point(points, color=self.point_color, size=self.point_size, @@ -542,7 +543,7 @@ def plot_ray_labels(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, [(3,4)]) - sage: tp.plot_ray_labels() # optional - sage.plot + sage: tp.plot_ray_labels() # needs sage.plot Graphics object consisting of 1 graphics primitive """ return self.plot_labels(self.ray_label, @@ -563,7 +564,7 @@ def plot_rays(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, [(3,4)]) - sage: tp.plot_rays() # optional - sage.plot + sage: tp.plot_rays() # needs sage.plot Graphics object consisting of 2 graphics primitives """ result = Graphics() @@ -605,14 +606,14 @@ def plot_walls(self, walls): sage: quadrant = Cone([(1,0), (0,1)]) sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, quadrant.rays()) - sage: tp.plot_walls([quadrant]) # optional - sage.plot + sage: tp.plot_walls([quadrant]) # needs sage.plot Graphics object consisting of 2 graphics primitives Let's also check that the truncating polyhedron is functioning correctly:: sage: tp = ToricPlotter({"mode": "box"}, 2, quadrant.rays()) - sage: tp.plot_walls([quadrant]) # optional - sage.plot + sage: tp.plot_walls([quadrant]) # needs sage.plot Graphics object consisting of 2 graphics primitives """ result = Graphics() @@ -702,12 +703,12 @@ def set_rays(self, generators): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) sage: tp.adjust_options() - sage: tp.plot_rays() # optional - sage.plot + sage: tp.plot_rays() # needs sage.plot Traceback (most recent call last): ... AttributeError: 'ToricPlotter' object has no attribute 'rays' sage: tp.set_rays([(0,1)]) - sage: tp.plot_rays() # optional - sage.plot + sage: tp.plot_rays() # needs sage.plot Graphics object consisting of 2 graphics primitives """ d = self.dimension @@ -781,21 +782,22 @@ def color_list(color, n): EXAMPLES:: + sage: # needs sage.plot sage: from sage.geometry.toric_plotter import color_list - sage: color_list("grey", 1) # optional - sage.plot + sage: color_list("grey", 1) [RGB color (0.5019607843137255, 0.5019607843137255, 0.5019607843137255)] - sage: len(color_list("grey", 3)) # optional - sage.plot + sage: len(color_list("grey", 3)) 3 - sage: L = color_list("rainbow", 3) # optional - sage.plot - sage: L # optional - sage.plot + sage: L = color_list("rainbow", 3) + sage: L [RGB color (1.0, 0.0, 0.0), RGB color (0.0, 1.0, 0.0), RGB color (0.0, 0.0, 1.0)] - sage: color_list(L, 3) # optional - sage.plot + sage: color_list(L, 3) [RGB color (1.0, 0.0, 0.0), RGB color (0.0, 1.0, 0.0), RGB color (0.0, 0.0, 1.0)] - sage: color_list(L, 4) # optional - sage.plot + sage: color_list(L, 4) Traceback (most recent call last): ... ValueError: expected 4 colors, got 3! @@ -1106,9 +1108,9 @@ def sector(ray1, ray2, **extra_options): EXAMPLES:: sage: from sage.geometry.toric_plotter import sector - sage: sector((1,0), (0,1)) + sage: sector((1,0), (0,1)) # needs sage.symbolic Graphics object consisting of 1 graphics primitive - sage: sector((3,2,1), (1,2,3)) + sage: sector((3,2,1), (1,2,3)) # needs sage.plot Graphics3d Object """ ray1 = vector(RDF, ray1) diff --git a/src/sage/geometry/triangulation/base.pyx b/src/sage/geometry/triangulation/base.pyx index 8fa5b82e213..d66186db098 100644 --- a/src/sage/geometry/triangulation/base.pyx +++ b/src/sage/geometry/triangulation/base.pyx @@ -18,7 +18,7 @@ AUTHORS: # # Distributed under the terms of the GNU General Public License (GPL) # -# http://www.gnu.org/licenses/ +# https://www.gnu.org/licenses/ ######################################################################## from sage.misc.fast_methods cimport hash_by_id @@ -76,7 +76,6 @@ cdef class Point(SageObject): cdef object _point_configuration cdef object _reduced_affine_vector, _reduced_projective_vector - def __init__(self, point_configuration, i, projective, affine, reduced): r""" Construct a :class:`Point`. @@ -129,7 +128,6 @@ cdef class Point(SageObject): """ return self._point_configuration - def __iter__(self): r""" Iterate through the affine ambient space coordinates of the point. @@ -160,7 +158,6 @@ cdef class Point(SageObject): """ return len(self._affine) - cpdef index(self): """ Return the index of the point in the point configuration. @@ -175,7 +172,6 @@ cdef class Point(SageObject): """ return self._index - cpdef projective(self): r""" Return the projective coordinates of the point in the ambient space. @@ -202,7 +198,6 @@ cdef class Point(SageObject): """ return self._projective - cpdef affine(self): r""" Return the affine coordinates of the point in the ambient space. @@ -229,7 +224,6 @@ cdef class Point(SageObject): """ return self._affine - cpdef reduced_affine(self): r""" Return the affine coordinates of the point on the hyperplane @@ -257,7 +251,6 @@ cdef class Point(SageObject): """ return self._reduced_affine - cpdef reduced_projective(self): r""" Return the projective coordinates of the point on the hyperplane @@ -285,7 +278,6 @@ cdef class Point(SageObject): """ return tuple(self._reduced_affine)+(1,) - cpdef reduced_affine_vector(self): """ Return the affine coordinates of the point on the hyperplane @@ -313,7 +305,6 @@ cdef class Point(SageObject): """ return self._reduced_affine_vector - cpdef reduced_projective_vector(self): """ Return the affine coordinates of the point on the hyperplane @@ -359,7 +350,7 @@ cdef class Point(SageObject): sage: p._repr_() 'P(0, 0)' """ - return 'P'+str(self._affine) + return 'P' + str(self._affine) ######################################################################## @@ -398,7 +389,6 @@ cdef class PointConfiguration_base(Parent): self._init_points(points) self._is_affine = defined_affine - cdef tuple _pts cdef int _ambient_dim cdef int _dim @@ -406,7 +396,6 @@ cdef class PointConfiguration_base(Parent): cdef bint _is_affine cdef object _reduced_affine_vector_space, _reduced_projective_vector_space - cdef _init_points(self, tuple projective_points): """ Internal method to determine coordinates of points. @@ -449,20 +438,20 @@ cdef class PointConfiguration_base(Parent): else: raise NotImplementedError # TODO - if n>1: + if n > 1: # shift first point to origin - red = matrix([ aff.column(i)-aff.column(0) for i in range(n) ]).transpose() + red = matrix([aff.column(i)-aff.column(0) for i in range(n)]).transpose() # pick linearly independent rows - red = matrix([ red.row(i) for i in red.pivot_rows()]) + red = matrix([red.row(i) for i in red.pivot_rows()]) else: - red = matrix(0,1) + red = matrix(0, 1) self._dim = red.nrows() from sage.modules.free_module import VectorSpace self._reduced_affine_vector_space = VectorSpace(self._base_ring.fraction_field(), self._dim) self._reduced_projective_vector_space = VectorSpace(self._base_ring.fraction_field(), self._dim+1) self._pts = tuple([Point(self, i, proj.column(i), - aff.column(i), red.column(i)) + aff.column(i), red.column(i)) for i in range(n)]) def __hash__(self): @@ -497,7 +486,6 @@ cdef class PointConfiguration_base(Parent): """ return self._reduced_affine_vector_space - cpdef reduced_projective_vector_space(self): """ Return the vector space that is spanned by the homogeneous @@ -519,7 +507,6 @@ cdef class PointConfiguration_base(Parent): """ return self._reduced_projective_vector_space - cpdef ambient_dim(self): """ Return the dimension of the ambient space of the point @@ -537,11 +524,9 @@ cdef class PointConfiguration_base(Parent): """ return self._ambient_dim - cpdef dim(self): """ - Return the actual dimension of the point - configuration. + Return the actual dimension of the point configuration. See also :meth:`ambient_dim` @@ -555,7 +540,6 @@ cdef class PointConfiguration_base(Parent): """ return self._dim - cpdef base_ring(self): r""" Return the base ring, that is, the ring containing the @@ -581,10 +565,9 @@ cdef class PointConfiguration_base(Parent): """ return self._base_ring - cpdef bint is_affine(self): """ - Whether the configuration is defined by affine points. + Return whether the configuration is defined by affine points. OUTPUT: @@ -603,7 +586,6 @@ cdef class PointConfiguration_base(Parent): """ return self._is_affine - def _assert_is_affine(self): """ Raise a ``ValueError`` if the point configuration is not @@ -622,7 +604,6 @@ cdef class PointConfiguration_base(Parent): if not self.is_affine(): raise ValueError('The point configuration contains projective points.') - def __getitem__(self, i): """ Return the ``i``-th point. @@ -651,7 +632,6 @@ cdef class PointConfiguration_base(Parent): """ return self._pts[i] - cpdef n_points(self): """ Return the number of points. @@ -673,14 +653,13 @@ cdef class PointConfiguration_base(Parent): """ return len(self._pts) - cpdef points(self): """ Return a list of the points. OUTPUT: - Returns a list of the points. See also the :meth:`__iter__` + A list of the points. See also the :meth:`__iter__` method, which returns the corresponding generator. EXAMPLES:: @@ -699,7 +678,6 @@ cdef class PointConfiguration_base(Parent): """ return self._pts - def point(self, i): """ Return the i-th point of the configuration. @@ -753,10 +731,9 @@ cdef class PointConfiguration_base(Parent): """ return len(self._pts) - cpdef simplex_to_int(self, simplex): r""" - Returns an integer that uniquely identifies the given simplex. + Return an integer that uniquely identifies the given simplex. See also the inverse method :meth:`int_to_simplex`. @@ -790,19 +767,18 @@ cdef class PointConfiguration_base(Parent): cdef int k = 1 cdef int n = self.n_points() cdef int d = len(simplex) - assert d==self.dim()+1 + assert d == self.dim()+1 cdef int i, j - for i in range(1,d+1): + for i in range(1, d+1): l = simplex[i-1]+1 - for j in range(k,l): - s += binomial(n-j,d-i) + for j in range(k, l): + s += binomial(n-j, d-i) k = l+1 return s - cpdef int_to_simplex(self, int s): r""" - Reverses the enumeration of possible simplices in + Reverse the enumeration of possible simplices in :meth:`simplex_to_int`. The enumeration is compatible with [PUNTOS]_. @@ -930,7 +906,6 @@ cdef class ConnectedTriangulationsIterator(SageObject): cdef triangulations_ptr _tp - def __cinit__(self): """ The Cython constructor. @@ -944,7 +919,6 @@ cdef class ConnectedTriangulationsIterator(SageObject): """ self._tp = NULL - def __init__(self, point_configuration, seed=None, star=None, fine=False): r""" The Python constructor. @@ -978,14 +952,12 @@ cdef class ConnectedTriangulationsIterator(SageObject): enumerated_simplices_seed, point_configuration.bistellar_flips()) - def __dealloc__(self): r""" The Cython destructor. """ delete_triangulations(self._tp) - def __iter__(self): r""" The iterator interface: Start iterating. diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index 793b383f9dc..7486488adb1 100644 --- a/src/sage/geometry/triangulation/element.py +++ b/src/sage/geometry/triangulation/element.py @@ -23,7 +23,7 @@ sage: points = PointConfiguration(p) sage: triang = points.triangulate(); triang (<0,1,2,5>, <0,1,3,5>, <1,3,4,5>) - sage: triang.plot(axes=False) # optional - sage.plot + sage: triang.plot(axes=False) # needs sage.plot Graphics3d Object See :mod:`sage.geometry.triangulation.point_configuration` for more details. @@ -68,7 +68,7 @@ def triangulation_render_2d(triangulation, **kwds): sage: points = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) sage: triang = points.triangulate() - sage: triang.plot(axes=False, aspect_ratio=1) # indirect doctest # optional - sage.plot + sage: triang.plot(axes=False, aspect_ratio=1) # indirect doctest # needs sage.plot Graphics object consisting of 12 graphics primitives """ from sage.plot.all import point2d, line2d, polygon2d @@ -130,7 +130,7 @@ def triangulation_render_3d(triangulation, **kwds): sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]] sage: points = PointConfiguration(p) sage: triang = points.triangulate() - sage: triang.plot(axes=False) # indirect doctest # optional - sage.plot + sage: triang.plot(axes=False) # indirect doctest # needs sage.plot Graphics3d Object """ from sage.plot.plot3d.all import point3d, line3d, polygon3d @@ -407,7 +407,7 @@ def plot(self, **kwds): sage: triangulation = p.triangulate() sage: triangulation (<1,3,4>, <2,3,4>) - sage: triangulation.plot(axes=False) # optional - sage.plot + sage: triangulation.plot(axes=False) # needs sage.plot Graphics object consisting of 12 graphics primitives """ dim = self.point_configuration().dim() @@ -524,7 +524,7 @@ def fan(self, origin=None): sage: triangulation = pc.triangulate() sage: fan = triangulation.fan(); fan Rational polyhedral fan in 2-d lattice N - sage: fan.is_equivalent(toric_varieties.P2().fan()) # optional - palp + sage: fan.is_equivalent(toric_varieties.P2().fan()) # needs palp sage.graphs True Toric diagrams (the `\ZZ_5` hyperconifold):: @@ -567,12 +567,12 @@ def simplicial_complex(self): EXAMPLES:: sage: p = polytopes.cuboctahedron() - sage: sc = p.triangulate(engine='internal').simplicial_complex(); sc # optional - sage.graphs + sage: sc = p.triangulate(engine='internal').simplicial_complex(); sc # needs sage.graphs Simplicial complex with 12 vertices and 16 facets Any convex set is contractable, so its reduced homology groups vanish:: - sage: sc.homology() # optional - sage.graphs + sage: sc.homology() # needs sage.graphs {0: 0, 1: 0, 2: 0, 3: 0} """ from sage.topology.simplicial_complex import SimplicialComplex @@ -670,19 +670,19 @@ def boundary_simplicial_complex(self): sage: p = polytopes.cuboctahedron() sage: triangulation = p.triangulate(engine='internal') - sage: bd_sc = triangulation.boundary_simplicial_complex(); bd_sc # optional - sage.graphs + sage: bd_sc = triangulation.boundary_simplicial_complex(); bd_sc # needs sage.graphs Simplicial complex with 12 vertices and 20 facets The boundary of every convex set is a topological sphere, so it has spherical homology:: - sage: bd_sc.homology() # optional - sage.graphs + sage: bd_sc.homology() # needs sage.graphs {0: 0, 1: 0, 2: Z} It is a subcomplex of ``self`` as a :meth:`simplicial_complex`:: - sage: sc = triangulation.simplicial_complex() # optional - sage.graphs - sage: all(f in sc for f in bd_sc.maximal_faces()) # optional - sage.graphs + sage: sc = triangulation.simplicial_complex() # needs sage.graphs + sage: all(f in sc for f in bd_sc.maximal_faces()) # needs sage.graphs True """ from sage.topology.simplicial_complex import SimplicialComplex @@ -739,9 +739,9 @@ def polyhedral_complex(self, **kwds): sage: pc = PointConfiguration(P.vertices()) sage: T = pc.placing_triangulation(); T (<0,1,2,7>, <0,1,5,7>, <0,2,3,7>, <0,3,4,7>, <0,4,5,7>, <1,5,6,7>) - sage: C = T.polyhedral_complex(); C # optional - sage.graphs + sage: C = T.polyhedral_complex(); C # needs sage.graphs Polyhedral complex with 6 maximal cells - sage: [P.vertices_list() for P in C.maximal_cells_sorted()] # optional - sage.graphs + sage: [P.vertices_list() for P in C.maximal_cells_sorted()] # needs sage.graphs [[[-1, -1, -1], [-1, -1, 1], [-1, 1, 1], [1, -1, -1]], [[-1, -1, -1], [-1, 1, -1], [-1, 1, 1], [1, 1, -1]], [[-1, -1, -1], [-1, 1, 1], [1, -1, -1], [1, 1, -1]], @@ -775,9 +775,9 @@ def boundary_polyhedral_complex(self, **kwds): sage: pc = PointConfiguration(P.vertices()) sage: T = pc.placing_triangulation(); T (<0,1,2,7>, <0,1,5,7>, <0,2,3,7>, <0,3,4,7>, <0,4,5,7>, <1,5,6,7>) - sage: bd_C = T.boundary_polyhedral_complex(); bd_C # optional - sage.graphs + sage: bd_C = T.boundary_polyhedral_complex(); bd_C # needs sage.graphs Polyhedral complex with 12 maximal cells - sage: [P.vertices_list() for P in bd_C.maximal_cells_sorted()] # optional - sage.graphs + sage: [P.vertices_list() for P in bd_C.maximal_cells_sorted()] # needs sage.graphs [[[-1, -1, -1], [-1, -1, 1], [-1, 1, 1]], [[-1, -1, -1], [-1, -1, 1], [1, -1, -1]], [[-1, -1, -1], [-1, 1, -1], [-1, 1, 1]], @@ -793,8 +793,8 @@ def boundary_polyhedral_complex(self, **kwds): It is a subcomplex of ``self`` as a :meth:`polyhedral_complex`:: - sage: C = T.polyhedral_complex() # optional - sage.graphs - sage: bd_C.is_subcomplex(C) # optional - sage.graphs + sage: C = T.polyhedral_complex() # needs sage.graphs + sage: bd_C.is_subcomplex(C) # needs sage.graphs True """ from sage.geometry.polyhedral_complex import PolyhedralComplex @@ -918,7 +918,7 @@ def adjacency_graph(self): sage: p = PointConfiguration([[1,0,0], [0,1,0], [0,0,1], [-1,0,1], ....: [1,0,-1], [-1,0,0], [0,-1,0], [0,0,-1]]) sage: t = p.triangulate() - sage: t.adjacency_graph() # optional - sage.graphs + sage: t.adjacency_graph() # needs sage.graphs Graph on 8 vertices """ diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 4f1bbde16d7..d75af2af4ce 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -65,7 +65,7 @@ (2, 3, 4) sage: list(t) [(1, 3, 4), (2, 3, 4)] - sage: t.plot(axes=False) # optional - sage.plot + sage: t.plot(axes=False) # needs sage.plot Graphics object consisting of 12 graphics primitives .. PLOT:: @@ -95,7 +95,7 @@ sage: p = [[0,-1,-1], [0,0,1], [0,1,0], [1,-1,-1], [1,0,1], [1,1,0]] sage: points = PointConfiguration(p) sage: triang = points.triangulate() - sage: triang.plot(axes=False) # optional - sage.plot + sage: triang.plot(axes=False) # needs sage.plot Graphics3d Object .. PLOT:: @@ -108,18 +108,19 @@ The standard example of a non-regular triangulation (requires TOPCOM):: - sage: PointConfiguration.set_engine('topcom') # optional - topcom + sage: # optional - topcom + sage: PointConfiguration.set_engine('topcom') sage: p = PointConfiguration([[-1,-5/9], [0,10/9], [1,-5/9], ....: [-2,-10/9], [0,20/9], [2,-10/9]]) - sage: p_regular = p.restrict_to_regular_triangulations(True) # optional - topcom - sage: regular = p_regular.triangulations_list() # optional - topcom - sage: p_nonregular = p.restrict_to_regular_triangulations(False) # optional - topcom - sage: nonregular = p_nonregular.triangulations_list() # optional - topcom - sage: len(regular) # optional - topcom + sage: p_regular = p.restrict_to_regular_triangulations(True) + sage: regular = p_regular.triangulations_list() + sage: p_nonregular = p.restrict_to_regular_triangulations(False) + sage: nonregular = p_nonregular.triangulations_list() + sage: len(regular) 16 - sage: len(nonregular) # optional - topcom + sage: len(nonregular) 2 - sage: nonregular[0].plot(aspect_ratio=1, axes=False) # optional - topcom sage.plot + sage: nonregular[0].plot(aspect_ratio=1, axes=False) # needs sage.plot Graphics object consisting of 25 graphics primitives sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM @@ -375,14 +376,15 @@ def set_engine(cls, engine='auto'): EXAMPLES:: + sage: # optional - topcom sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sage: p.set_engine('internal') # to make doctests independent of TOPCOM sage: p.triangulate() (<1,3,4>, <2,3,4>) - sage: p.set_engine('topcom') # optional - topcom - sage: p.triangulate() # optional - topcom + sage: p.set_engine('topcom') + sage: p.triangulate() (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ engine = engine.lower() if engine not in ['auto', 'topcom', 'internal']: @@ -738,13 +740,14 @@ def _TOPCOM_triangulate(self, verbose=True): EXAMPLES:: + sage: # optional - topcom sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) - sage: p.set_engine('topcom') # optional - topcom - sage: p._TOPCOM_triangulate(verbose=False) # optional - topcom + sage: p.set_engine('topcom') + sage: p._TOPCOM_triangulate(verbose=False) (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: list( p.triangulate() ) # optional - topcom + sage: list( p.triangulate() ) [(0, 1, 2), (0, 1, 4), (0, 2, 4), (1, 2, 3)] - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ assert self._regular is not False, \ 'When asked for a single triangulation TOPCOM ' + \ @@ -787,7 +790,7 @@ def restrict_to_regular_triangulations(self, regular=True): fine, not necessarily regular. sage: len(p.triangulations_list()) 4 - sage: PointConfiguration.set_engine('topcom') # optional - topcom + sage: PointConfiguration.set_engine('topcom') sage: p_regular = p.restrict_to_regular_triangulations() # optional - topcom sage: len(p_regular.triangulations_list()) # optional - topcom 4 @@ -831,7 +834,7 @@ def restrict_to_connected_triangulations(self, connected=True): fine, not necessarily regular. sage: len(p.triangulations_list()) 4 - sage: PointConfiguration.set_engine('topcom') # optional - topcom + sage: PointConfiguration.set_engine('topcom') sage: p_all = p.restrict_to_connected_triangulations(connected=False) # optional - topcom sage: len(p_all.triangulations_list()) # optional - topcom 4 @@ -961,27 +964,28 @@ def triangulations(self, verbose=False): compute the triangulations. Using TOPCOM, we obtain the same triangulations but in a different order:: - sage: p.set_engine('topcom') # optional - topcom - sage: iter = p.triangulations() # optional - topcom - sage: next(iter) # optional - topcom + sage: # optional - topcom + sage: p.set_engine('topcom') + sage: iter = p.triangulations() + sage: next(iter) (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: next(iter) # optional - topcom + sage: next(iter) (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>) - sage: next(iter) # optional - topcom + sage: next(iter) (<1,2,3>, <1,2,4>) - sage: next(iter) # optional - topcom + sage: next(iter) (<1,3,4>, <2,3,4>) - sage: p.triangulations_list() # optional - topcom + sage: p.triangulations_list() [(<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>), (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>), (<1,2,3>, <1,2,4>), (<1,3,4>, <2,3,4>)] - sage: p_fine = p.restrict_to_fine_triangulations() # optional - topcom - sage: p_fine.set_engine('topcom') # optional - topcom - sage: p_fine.triangulations_list() # optional - topcom + sage: p_fine = p.restrict_to_fine_triangulations() + sage: p_fine.set_engine('topcom') + sage: p_fine.triangulations_list() [(<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>), (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>)] - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ if self._use_TOPCOM: for triangulation in self._TOPCOM_triangulations(verbose): @@ -1017,10 +1021,10 @@ def triangulations_list(self, verbose=False): [(<0,1,2>, <1,2,3>), (<0,1,3>, <0,2,3>)] sage: list(map(list, p.triangulations_list())) [[(0, 1, 2), (1, 2, 3)], [(0, 1, 3), (0, 2, 3)]] - sage: p.set_engine('topcom') # optional - topcom + sage: p.set_engine('topcom') sage: p.triangulations_list() # optional - topcom [(<0,1,2>, <1,2,3>), (<0,1,3>, <0,2,3>)] - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ return list(self.triangulations(verbose)) @@ -1049,12 +1053,13 @@ def triangulate(self, verbose=False): Using TOPCOM yields a different, but equally good, triangulation:: - sage: p.set_engine('topcom') # optional - topcom - sage: p.triangulate() # optional - topcom + sage: # optional - topcom + sage: p.set_engine('topcom') + sage: p.triangulate() (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: list(p.triangulate()) # optional - topcom + sage: list(p.triangulate()) [(0, 1, 2), (0, 1, 4), (0, 2, 4), (1, 2, 3)] - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ if self._use_TOPCOM and self._regular is not False: try: @@ -1127,10 +1132,10 @@ def restricted_automorphism_group(self): sage: pyramid = PointConfiguration([[1,0,0], [0,1,1], [0,1,-1], ....: [0,-1,-1], [0,-1,1]]) - sage: G = pyramid.restricted_automorphism_group() # optional - sage.graphs sage.groups - sage: G == PermutationGroup([[(3,5)], [(2,3),(4,5)], [(2,4)]]) # optional - sage.graphs sage.groups + sage: G = pyramid.restricted_automorphism_group() # needs sage.graphs sage.groups + sage: G == PermutationGroup([[(3,5)], [(2,3),(4,5)], [(2,4)]]) # needs sage.graphs sage.groups True - sage: DihedralGroup(4).is_isomorphic(G) # optional - sage.graphs sage.groups + sage: DihedralGroup(4).is_isomorphic(G) # needs sage.graphs sage.groups True The square with an off-center point in the middle. Note that @@ -1138,9 +1143,9 @@ def restricted_automorphism_group(self): `D_4` of the convex hull:: sage: square = PointConfiguration([(3/4,3/4), (1,1), (1,-1), (-1,-1), (-1,1)]) - sage: square.restricted_automorphism_group() # optional - sage.graphs sage.groups + sage: square.restricted_automorphism_group() # needs sage.graphs sage.groups Permutation Group with generators [(3,5)] - sage: DihedralGroup(1).is_isomorphic(_) # optional - sage.graphs sage.groups + sage: DihedralGroup(1).is_isomorphic(_) # needs sage.graphs sage.groups True """ v_list = [ vector(p.projective()) for p in self ] @@ -1530,9 +1535,9 @@ def bistellar_flips(self): sage: pc.bistellar_flips() (((<0,1,3>, <0,2,3>), (<0,1,2>, <1,2,3>)),) sage: Tpos, Tneg = pc.bistellar_flips()[0] - sage: Tpos.plot(axes=False) # optional - sage.plot + sage: Tpos.plot(axes=False) # needs sage.plot Graphics object consisting of 11 graphics primitives - sage: Tneg.plot(axes=False) # optional - sage.plot + sage: Tneg.plot(axes=False) # needs sage.plot Graphics object consisting of 11 graphics primitives The 3d analog:: @@ -1547,7 +1552,7 @@ def bistellar_flips(self): sage: pc.bistellar_flips() (((<0,1,3>, <0,2,3>), (<0,1,2>, <1,2,3>)),) sage: Tpos, Tneg = pc.bistellar_flips()[0] - sage: Tpos.plot(axes=False) # optional - sage.plot + sage: Tpos.plot(axes=False) # needs sage.plot Graphics3d Object """ flips = [] @@ -2085,7 +2090,7 @@ def plot(self, **kwds): EXAMPLES:: sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) - sage: p.plot(axes=False) # optional - sage.plot + sage: p.plot(axes=False) # needs sage.plot Graphics object consisting of 5 graphics primitives .. PLOT:: diff --git a/src/sage/geometry/voronoi_diagram.py b/src/sage/geometry/voronoi_diagram.py index 1e9629aa646..0cea1e91377 100644 --- a/src/sage/geometry/voronoi_diagram.py +++ b/src/sage/geometry/voronoi_diagram.py @@ -51,18 +51,19 @@ class VoronoiDiagram(SageObject): Get the Voronoi diagram of a regular pentagon in ``AA^2``. All cells meet at the origin:: - sage: DV = VoronoiDiagram([[AA(c) for c in v] for v in polytopes.regular_polygon(5).vertices_list()]); DV # optional - sage.rings.number_field + sage: DV = VoronoiDiagram([[AA(c) for c in v] # needs sage.rings.number_field + ....: for v in polytopes.regular_polygon(5).vertices_list()]); DV The Voronoi diagram of 5 points of dimension 2 in the Algebraic Real Field - sage: all(P.contains([0, 0]) for P in DV.regions().values()) # optional - sage.rings.number_field + sage: all(P.contains([0, 0]) for P in DV.regions().values()) # needs sage.rings.number_field True - sage: any(P.interior_contains([0, 0]) for P in DV.regions().values()) # optional - sage.rings.number_field + sage: any(P.interior_contains([0, 0]) for P in DV.regions().values()) # needs sage.rings.number_field False If the vertices are not converted to ``AA`` before, the method throws an error:: - sage: polytopes.dodecahedron().vertices_list()[0][0].parent() # optional - sage.rings.number_field + sage: polytopes.dodecahedron().vertices_list()[0][0].parent() # needs sage.rings.number_field Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: VoronoiDiagram(polytopes.dodecahedron().vertices_list()) # optional - sage.rings.number_field + sage: VoronoiDiagram(polytopes.dodecahedron().vertices_list()) # needs sage.rings.number_field Traceback (most recent call last): ... NotImplementedError: Base ring of the Voronoi diagram must be @@ -230,9 +231,9 @@ def _repr_(self): EXAMPLES:: - sage: V = VoronoiDiagram(polytopes.regular_polygon(3).vertices()); V # optional - sage.rings.number_field + sage: V = VoronoiDiagram(polytopes.regular_polygon(3).vertices()); V # needs sage.rings.number_field The Voronoi diagram of 3 points of dimension 2 in the Algebraic Real Field - sage: VoronoiDiagram([]) # optional - sage.rings.number_field + sage: VoronoiDiagram([]) The empty Voronoi diagram. """ if self._n: @@ -260,18 +261,17 @@ def plot(self, cell_colors=None, **kwds): EXAMPLES:: - sage: P = [[0.671, 0.650], [0.258, 0.767], [0.562, 0.406], [0.254, 0.709], [0.493, 0.879]] - - sage: V = VoronoiDiagram(P); S=V.plot() # optional - sage.plot - sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) # optional - sage.plot - - sage: S=V.plot(cell_colors={0:'red', 1:'blue', 2:'green', 3:'white', 4:'yellow'}) # optional - sage.plot - sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) # optional - sage.plot - - sage: S=V.plot(cell_colors=['red','blue','red','white', 'white']) # optional - sage.plot - sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) # optional - sage.plot - - sage: S=V.plot(cell_colors='something else') # optional - sage.plot + sage: # needs sage.plot + sage: P = [[0.671, 0.650], [0.258, 0.767], [0.562, 0.406], + ....: [0.254, 0.709], [0.493, 0.879]] + sage: V = VoronoiDiagram(P); S=V.plot() + sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) + sage: S = V.plot(cell_colors={0: 'red', 1: 'blue', 2: 'green', + ....: 3: 'white', 4: 'yellow'}) + sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) + sage: S = V.plot(cell_colors=['red', 'blue', 'red', 'white', 'white']) + sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) + sage: S = V.plot(cell_colors='something else') Traceback (most recent call last): ... AssertionError: 'cell_colors' must be a list or a dictionary @@ -280,7 +280,7 @@ def plot(self, cell_colors=None, **kwds): Trying to plot a Voronoi diagram of dimension other than 2 gives an error:: - sage: VoronoiDiagram([[1, 2, 3], [6, 5, 4]]).plot() # optional - sage.plot + sage: VoronoiDiagram([[1, 2, 3], [6, 5, 4]]).plot() # needs sage.plot Traceback (most recent call last): ... NotImplementedError: Plotting of 3-dimensional Voronoi diagrams not diff --git a/src/sage/graphs/base/static_sparse_graph.pyx b/src/sage/graphs/base/static_sparse_graph.pyx index 6fd78510c94..b5462299058 100644 --- a/src/sage/graphs/base/static_sparse_graph.pyx +++ b/src/sage/graphs/base/static_sparse_graph.pyx @@ -1032,15 +1032,16 @@ def spectral_radius(G, prec=1e-10): A larger example:: + sage: # needs sage.modules sage: G = DiGraph() sage: G.add_edges((i,i+1) for i in range(200)) sage: G.add_edge(200,0) sage: G.add_edge(1,0) sage: e_min, e_max = spectral_radius(G, 0.00001) - sage: p = G.adjacency_matrix(sparse=True).charpoly() # needs sage.modules - sage: p # needs sage.modules + sage: p = G.adjacency_matrix(sparse=True).charpoly() + sage: p x^201 - x^199 - 1 - sage: r = p.roots(AA, multiplicities=False)[0] # needs sage.modules + sage: r = p.roots(AA, multiplicities=False)[0] sage: e_min < r < e_max True diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index b2c9fdbf3db..f707ee2a968 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -45,7 +45,6 @@ from .generic_graph import GenericGraph from .graph import Graph from sage.rings.integer import Integer -from sage.misc.decorators import rename_keyword from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import lazy_import @@ -2226,7 +2225,6 @@ class :class:`MixedIntegerLinearProgram raise ValueError('algorithm must be "Hopcroft-Karp", ' '"Eppstein", "Edmonds" or "LP"') - @rename_keyword(deprecation=32238, verbosity='verbose') def vertex_cover(self, algorithm="Konig", value_only=False, reduction_rules=True, solver=None, verbose=0, *, integrality_tolerance=1e-3): diff --git a/src/sage/graphs/bliss.pyx b/src/sage/graphs/bliss.pyx index 5911778953c..3126086babc 100644 --- a/src/sage/graphs/bliss.pyx +++ b/src/sage/graphs/bliss.pyx @@ -67,8 +67,8 @@ cdef extern from "bliss_cpp/bliss_find_automorphisms.h": cdef int encoding_numbits(int n): r""" - Return the number of bits needed to encode the ``n`` numbers from ``1`` to ``n``. In - other words, the last bit set in ``n``. + Return the number of bits needed to encode the `n` numbers from `1` to + `n`. In other words, the last bit set in `n`. """ if n <= 0: return 0 @@ -480,9 +480,9 @@ cpdef canonical_form(G, partition=None, return_graph=False, use_edge_labels=True sage: # needs sage.modules sage: g1 = Graph([(0, 1, matrix(ZZ, 2)), (0, 2, RDF.pi()), (1, 2, 'a')]) sage: g2 = Graph([(1, 2, matrix(ZZ, 2)), (2, 0, RDF.pi()), (0, 1, 'a')]) - sage: g1can = canonical_form(g1, use_edge_labels=True) # optional - bliss - sage: g2can = canonical_form(g2, use_edge_labels=True) # optional - bliss - sage: g1can == g2can # optional - bliss + sage: g1can = canonical_form(g1, use_edge_labels=True) # optional - bliss + sage: g2can = canonical_form(g2, use_edge_labels=True) # optional - bliss + sage: g1can == g2can # optional - bliss True Check that :trac:`32395` is fixed:: @@ -666,12 +666,12 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): - ``G`` -- a Sage graph - - ``partition`` -- ``list``(default: ``None``); a partition of the vertices + - ``partition`` -- ``list`` (default: ``None``); a partition of the vertices of ``G`` into color classes. Defaults to ``None``, which is equivalent to a partition of size 1. - - ``use_edge_labels`` -- boolean (default: ``True``); whether to consider edge - labels + - ``use_edge_labels`` -- boolean (default: ``True``); whether to consider + edge labels EXAMPLES:: @@ -687,9 +687,9 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): sage: automorphism_group(D).cardinality() 2 - Observe that the order 12 is given by permuting the first three vertices, or the last two - in the case of a graph, while only the latter two are possible in the case of a directed - graph. + Observe that the order 12 is given by permuting the first three vertices, or + the last two in the case of a graph, while only the latter two are possible + in the case of a directed graph. Partitioning the vertices into classes:: @@ -701,24 +701,23 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): 2 sage: automorphism_group(G,partition=[[0],[1,2],[3,4]]).cardinality() 4 - - sage: automorphism_group(G,partition=[[1,2],[0,3],[4]]).cardinality() # optional - bliss + sage: automorphism_group(G,partition=[[1,2],[0,3],[4]]).cardinality() 2 Partitioning the edges into classes:: - sage: G = Graph(graphs.CompleteMultipartiteGraph([8, 2]), sparse=True) # optional - bliss - sage: for i,j in G.edges(labels=False, sort=False): # optional - bliss + sage: # optional - bliss + sage: G = Graph(graphs.CompleteMultipartiteGraph([8, 2]), sparse=True) + sage: for i,j in G.edges(labels=False, sort=False): ....: if 0 <= i < 3: ....: G.set_edge_label(i, j, "A") ....: if 3 <= i < 6: ....: G.set_edge_label(i, j, "B") ....: if 6 <= i < 8: ....: G.set_edge_label(i, j, "C") - - sage: factor(automorphism_group(G).cardinality()) # optional - bliss + sage: factor(automorphism_group(G).cardinality()) 2^4 * 3^2 - sage: automorphism_group(G,[[0],[1],[2,3],[4,5],[6,7],[8],[9]]).cardinality() # optional - bliss + sage: automorphism_group(G,[[0],[1],[2,3],[4,5],[6,7],[8],[9]]).cardinality() 4 TESTS:: @@ -735,9 +734,9 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): sage: automorphism_group(G, partition=p).is_isomorphic(A) True - sage: G = graphs.CompleteMultipartiteGraph([5,7,11]) + sage: G = graphs.CompleteMultipartiteGraph([5, 7, 11]) sage: B = automorphism_group(G) # optional - bliss - sage: B.cardinality() == prod(factorial(n) for n in [5,7,11]) # optional - bliss + sage: B.cardinality() == prod(factorial(n) for n in [5, 7, 11]) # optional - bliss True sage: # optional - bliss @@ -749,11 +748,14 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): ....: G.set_edge_label(i, j, "B") ....: if 6 <= i < 8: ....: G.set_edge_label(i, j, "C") - sage: automorphism_group(G).cardinality() == prod( factorial(n) for n in [3,3,2,8,8,5,2] ) + sage: card = automorphism_group(G).cardinality() + sage: card == prod(factorial(n) for n in [3, 3, 2, 8, 8, 5, 2]) True - sage: automorphism_group(G, use_edge_labels=False).cardinality() == prod( factorial(n) for n in [8,8,8,5,3] ) + sage: card = automorphism_group(G, use_edge_labels=False).cardinality() + sage: card == prod(factorial(n) for n in [8, 8, 8, 5, 3]) True - sage: automorphism_group(G,[[0 .. 7],[8 .. 11],[12 .. 28]]).cardinality() == prod( factorial(n) for n in [3,3,2,4,4,8,5] ) + sage: card = automorphism_group(G, [[0 .. 7], [8 .. 11] ,[12 .. 28]]).cardinality() + sage: card == prod(factorial(n) for n in [3, 3, 2, 4, 4, 8, 5]) True sage: # optional - bliss @@ -764,35 +766,34 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): sage: G.add_edges((i,j,"D") for i in range(9,14) for j in range(14,20)) sage: A = automorphism_group(G) sage: print(A.gens()) # random - [(9,13), (18,19), (17,18), (16,17), (15,16), (14,15), (12,9), (11,12), - (10,11), (7,8), (6,7), (5,6), (3,4), (2,3), (0,1)] + ((12,13), (11,12), (10,11), (9,10), (7,8), (6,7), (5,6), (3,4), + (2,3), (1,0), (18,19), (17,18), (16,17), (15,16), (14,15)) sage: A.cardinality() == prod(factorial(n) for n in [2,3,4,5,6]) True - sage: alpha = "abcdefghijklmnopqrstuvwxyz" - sage: # optional - bliss sage: G = Graph() + sage: alpha = "abcdefghijklmnopqrstuvwxyz" sage: G.add_edges((alpha[i],alpha[j],"A") for i in range(0, 2) for j in range(14,20)) sage: G.add_edges((alpha[i],alpha[j],"B") for i in range(2, 5) for j in range(14,20)) sage: G.add_edges((alpha[i],alpha[j],"C") for i in range(5, 9) for j in range(14,20)) sage: G.add_edges((alpha[i],alpha[j],"D") for i in range(9,14) for j in range(14,20)) sage: A = automorphism_group(G) sage: print(A.gens()) - [('r','t'), ('s','r'), ('p','s'), ('q','p'), ('o','q'), ('l','n'), - ('m','l'), ('j','m'), ('k','j'), ('i','h'), ('f','i'), ('g','f'), - ('e','d'), ('c','e'), ('a','b')] - sage: A.cardinality() == prod(factorial(n) for n in [2,3,4,5,6]) + (('m','n'), ('l','m'), ('k','l'), ('j','k'), ('h','i'), + ('g','h'), ('f','g'), ('d','e'), ('c','d'), ('s','t'), + ('r','s'), ('q','r'), ('p','q'), ('o','p'), ('a','b')) + sage: A.cardinality() == prod(factorial(n) for n in [2, 3, 4, 5, 6]) True sage: # optional - bliss sage: gg = graphs.CompleteGraph(5) sage: gg.allow_loops(True) - sage: gg.add_edge(0,0) - sage: gg.add_edge(1,1) + sage: gg.add_edge(0, 0) + sage: gg.add_edge(1, 1) sage: automorphism_group(gg).cardinality() 12 - sage: automorphism_group(gg,[[0],[1,2,3,4]]).cardinality() + sage: automorphism_group(gg, [[0], [1, 2, 3, 4]]).cardinality() 6 """ # We need this to convert the numbers from to diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index 1017f8490eb..a8e6e9997b1 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -925,8 +925,8 @@ def is_directed(self): # Properties def is_directed_acyclic(self, certificate=False): - """ - Return whether the digraph is acyclic or not. + r""" + Check whether the digraph is acyclic or not. A directed graph is acyclic if for any vertex `v`, there is no directed path that starts and ends at `v`. Every directed acyclic graph (DAG) @@ -945,8 +945,8 @@ def is_directed_acyclic(self, certificate=False): * When ``certificate=True``: * If the graph is acyclic, returns a pair ``(True, ordering)`` where - ``ordering`` is a list of the vertices such that ``u`` appears - before ``v`` in ``ordering`` if ``u, v`` is an edge. + ``ordering`` is a list of the vertices such that `u` appears + before `v` in ``ordering`` if `uv` is an edge. * Else, returns a pair ``(False, cycle)`` where ``cycle`` is a list of vertices representing a circuit in the graph. @@ -1274,8 +1274,7 @@ def in_degree(self, vertices=None, labels=False): return self._backend.in_degree(vertices) elif labels: return {v: d for v, d in self.in_degree_iterator(vertices, labels=labels)} - else: - return list(self.in_degree_iterator(vertices, labels=labels)) + return list(self.in_degree_iterator(vertices, labels=labels)) def in_degree_iterator(self, vertices=None, labels=False): """ @@ -1345,8 +1344,7 @@ def out_degree(self, vertices=None, labels=False): return self._backend.out_degree(vertices) elif labels: return {v: d for v, d in self.out_degree_iterator(vertices, labels=labels)} - else: - return list(self.out_degree_iterator(vertices, labels=labels)) + return list(self.out_degree_iterator(vertices, labels=labels)) def out_degree_iterator(self, vertices=None, labels=False): """ @@ -1636,14 +1634,16 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, if self.has_loops(): # We solve the problem on a copy without loops of the digraph D = DiGraph(self.edges(sort=False), multiedges=self.allows_multiple_edges(), loops=True) - D.allow_loops(False) + loops = D.loops(labels=None) + D.delete_edges(loops) + D.allow_loops(False, check=False) FAS = D.feedback_edge_set(constraint_generation=constraint_generation, value_only=value_only, solver=solver, verbose=verbose, integrality_tolerance=integrality_tolerance) if value_only: - return FAS + self.number_of_loops() + return FAS + len(loops) else: - return FAS + self.loops(labels=None) + return FAS + loops if not self.is_strongly_connected(): # If the digraph is not strongly connected, we solve the problem on @@ -1652,6 +1652,8 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, FAS = 0 if value_only else [] for h in self.strongly_connected_components_subgraphs(): + if not h.size(): + continue if value_only: FAS += h.feedback_edge_set(constraint_generation=constraint_generation, value_only=True, solver=solver, verbose=verbose, @@ -1696,9 +1698,8 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, if isok: if value_only: return sum(1 for e in self.edge_iterator(labels=False) if val[e]) - else: - # listing the edges contained in the MFAS - return [e for e in self.edge_iterator(labels=False) if val[e]] + # listing the edges contained in the MFAS + return [e for e in self.edge_iterator(labels=False) if val[e]] # There is a circuit left. Let's add the corresponding # constraint ! @@ -1741,28 +1742,92 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, if value_only: return sum(1 for e in self.edge_iterator(labels=False) if b_sol[e]) - else: - return [e for e in self.edge_iterator(labels=False) if b_sol[e]] + return [e for e in self.edge_iterator(labels=False) if b_sol[e]] # Construction - def reverse(self): + def reverse(self, immutable=None): """ Return a copy of digraph with edges reversed in direction. + INPUT: + + - ``immutable`` -- boolean (default: ``None``); whether to return an + immutable digraph or not. By default (``None``), the returned digraph + has the same setting than ``self``. That is, if ``self`` is immutable, + the returned digraph also is. + EXAMPLES:: - sage: D = DiGraph({0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1]}) - sage: D.reverse() + sage: adj = {0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1]} + sage: D = DiGraph(adj) + sage: R = D.reverse(); R Reverse of (): Digraph on 6 vertices + sage: H = R.reverse() + sage: adj == H.to_dictionary() + True + + TESTS:: + + sage: adj = {0: [1, 1], 1: [1]} + sage: D = DiGraph(adj, immutable=True, multiedges=True, loops=True) + sage: R = D.reverse() + sage: R.is_immutable() and R.allows_loops() and R.allows_multiple_edges() + True + sage: adj == R.reverse().to_dictionary(multiple_edges=True) + True + + Check the behavior of parameter ``immutable``:: + + sage: D = DiGraph([(0, 1)], immutable=False) + sage: R = D.reverse() + sage: R.is_immutable() + False + sage: R = D.reverse(immutable=True) + sage: R.is_immutable() + True + sage: H = R.reverse() + sage: H.is_immutable() + True + sage: H = R.reverse(immutable=False) + sage: H.is_immutable() + False """ - H = DiGraph(multiedges=self.allows_multiple_edges(), loops=self.allows_loops()) + from sage.graphs.base.dense_graph import DenseGraphBackend + if isinstance(self._backend, DenseGraphBackend): + data_structure = "dense" + else: + data_structure = "sparse" + + H = DiGraph(data_structure=data_structure, + multiedges=self.allows_multiple_edges(), loops=self.allows_loops(), + pos=copy(self._pos), weighted=self.weighted(), + hash_labels=self._hash_labels) H.add_vertices(self) H.add_edges((v, u, d) for u, v, d in self.edge_iterator()) name = self.name() if name is None: name = '' H.name("Reverse of (%s)" % name) + + attributes_to_copy = ('_assoc', '_embedding') + for attr in attributes_to_copy: + if hasattr(self, attr): + copy_attr = {} + old_attr = getattr(self, attr) + if isinstance(old_attr, dict): + for v, value in old_attr.items(): + try: + copy_attr[v] = value.copy() + except AttributeError: + copy_attr[v] = copy(value) + setattr(H, attr, copy_attr) + else: + setattr(H, attr, copy(old_attr)) + + if immutable or (immutable is None and self.is_immutable()): + return H.copy(immutable=True) + return H def reverse_edge(self, u, v=None, label=None, inplace=True, multiedges=None): @@ -3614,7 +3679,8 @@ def flow_polytope(self, edges=None, ends=None, backend=None): Using a different order for the edges of the graph:: - sage: fl = G.flow_polytope(edges=G.edges(key=lambda x: x[0] - x[1])); fl # needs sage.geometry.polyhedron + sage: ordered_edges = G.edges(sort=True, key=lambda x: x[0] - x[1]) + sage: fl = G.flow_polytope(edges=ordered_edges); fl # needs sage.geometry.polyhedron A 1-dimensional polyhedron in QQ^4 defined as the convex hull of 2 vertices sage: fl.vertices() # needs sage.geometry.polyhedron (A vertex at (0, 1, 1, 0), A vertex at (1, 0, 0, 1)) diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py index 00cc3ed5900..4b664e3eb65 100644 --- a/src/sage/graphs/domination.py +++ b/src/sage/graphs/domination.py @@ -137,7 +137,7 @@ def is_redundant(G, dom, focus=None): False """ dom = list(dom) - focus = list(G) if focus is None else list(focus) + focus = G if focus is None else set(focus) # dominator[v] (for v in focus) will be equal to: # - (0, None) if v has no neighbor in dom @@ -345,13 +345,20 @@ def dominating_sets(g, k=1, independent=False, total=False, Traceback (most recent call last): ... ValueError: the domination distance must be a non-negative integer + + The method is robust to vertices with incomparable labels:: + + sage: G = Graph([(1, 'A'), ('A', 2), (2, 3), (3, 1)]) + sage: L = list(G.dominating_sets()) + sage: len(L) + 6 """ g._scream_if_not_simple(allow_multiple_edges=True, allow_loops=not total) if not k: yield list(g) return - elif k < 0: + if k < 0: raise ValueError("the domination distance must be a non-negative integer") from sage.numerical.mip import MixedIntegerLinearProgram @@ -721,8 +728,8 @@ def _aux_with_rep(H, to_dom, u_next): # Here we use aux_with_rep twice to enumerate the minimal # dominating sets while avoiding repeated outputs - for (X, i) in _aux_with_rep(G, to_dom, u_next): - for (Y, j) in _aux_with_rep(G, to_dom, u_next): + for X, i in _aux_with_rep(G, to_dom, u_next): + for Y, j in _aux_with_rep(G, to_dom, u_next): if j >= i: # This is the first time we meet X: we output it yield X @@ -732,7 +739,7 @@ def _aux_with_rep(H, to_dom, u_next): break -def minimal_dominating_sets(G, to_dominate=None, work_on_copy=False, k=1): +def minimal_dominating_sets(G, to_dominate=None, work_on_copy=True, k=1): r""" Return an iterator over the minimal dominating sets of a graph. @@ -743,7 +750,7 @@ def minimal_dominating_sets(G, to_dominate=None, work_on_copy=False, k=1): - ``to_dominate`` -- vertex iterable or ``None`` (default: ``None``); the set of vertices to be dominated. - - ``work_on_copy`` -- boolean (default: ``False``); whether or not to work on + - ``work_on_copy`` -- boolean (default: ``True``); whether or not to work on a copy of the input graph; if set to ``False``, the input graph will be modified (relabeled). @@ -836,6 +843,19 @@ def minimal_dominating_sets(G, to_dominate=None, work_on_copy=False, k=1): sage: list(G.minimal_dominating_sets(k=3)) [{(0, 0)}, {(0, 1)}, {(0, 2)}, {(1, 0)}, {(1, 1)}, {(1, 2)}] + When parameter ``work_on_copy`` is ``False``, the input graph is modified + (relabeled):: + + sage: G = Graph([('A', 'B')]) + sage: _ = list(G.minimal_dominating_sets(work_on_copy=True)) + sage: set(G) == {'A', 'B'} + True + sage: _ = list(G.minimal_dominating_sets(work_on_copy=False)) + sage: set(G) == {'A', 'B'} + False + sage: set(G) == {0, 1} + True + TESTS: The empty graph is handled correctly:: @@ -891,6 +911,15 @@ def minimal_dominating_sets(G, to_dominate=None, work_on_copy=False, k=1): Traceback (most recent call last): ... ValueError: vertex (foo) is not a vertex of the graph + + The method is robust to vertices with incomparable labels:: + + sage: G = Graph([(1, 'A'), ('A', 2), (2, 3), (3, 1)]) + sage: L = list(G.minimal_dominating_sets()) + sage: len(L) + 6 + sage: {3, 'A'} in L + True """ def tree_search(H, plng, dom, i): r""" @@ -944,7 +973,8 @@ def tree_search(H, plng, dom, i): # We complete dom with can_ext -> canD canD = set().union(can_ext, dom) - if (not H.is_redundant(canD, V_next)) and set(dom) == set(_parent(H, canD, plng[i][1])): + if (not H.is_redundant(canD, V_next) + and set(dom) == set(_parent(H, canD, plng[i][1]))): # By construction, can_ext is a dominating set of # `V_next - N[dom]`, so canD dominates V_next. # If canD is a legitimate child of dom and is not redundant, we @@ -954,6 +984,12 @@ def tree_search(H, plng, dom, i): ## # end of tree-search routine + if k < 0: + raise ValueError("the domination distance must be a non-negative integer") + if not k: + yield set(G) if to_dominate is None else set(to_dominate) + return + int_to_vertex = list(G) vertex_to_int = {u: i for i, u in enumerate(int_to_vertex)} @@ -965,28 +1001,24 @@ def tree_search(H, plng, dom, i): raise ValueError(f"vertex ({u}) is not a vertex of the graph") vertices_to_dominate = {vertex_to_int[u] for u in to_dominate} - if k < 0: - raise ValueError("the domination distance must be a non-negative integer") - elif not k: - yield set(int_to_vertex) if to_dominate is None else set(to_dominate) + if not vertices_to_dominate: + # base case: vertices_to_dominate is empty + # the empty set/list is the only minimal DS of the empty set + yield set() return - elif k > 1: + if k > 1: # We build a graph H with an edge between u and v if these vertices are # at distance at most k in G H = G.__class__(G.order()) for u, ui in vertex_to_int.items(): - H.add_edges((ui, vertex_to_int[v]) for v in G.breadth_first_search(u, distance=k) if u != v) + H.add_edges((ui, vertex_to_int[v]) + for v in G.breadth_first_search(u, distance=k) if u != v) G = H elif work_on_copy: - G.relabel(perm=vertex_to_int) - else: G = G.relabel(perm=vertex_to_int, inplace=False) - - if not vertices_to_dominate: - # base case: vertices_to_dominate is empty - # the empty set/list is the only minimal DS of the empty set - yield set() - return + else: + # The input graph is modified + G.relabel(perm=vertex_to_int, inplace=True) peeling = _peel(G, vertices_to_dominate) @@ -1119,6 +1151,12 @@ def greedy_dominating_set(G, k=1, vertices=None, ordering=None, return_sets=Fals sage: G = graphs.PathGraph(5) sage: dom = greedy_dominating_set(G, vertices=[0, 1, 3, 4]) + The method is robust to vertices with incomparable labels:: + + sage: G = Graph([(1, 'A')]) + sage: len(greedy_dominating_set(G)) + 1 + Check parameters:: sage: greedy_dominating_set(G, ordering="foo") diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index a770ecdbd28..bf1aa04e933 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -1284,20 +1284,20 @@ def CossidentePenttilaGraph(q): For `q=3` one gets Sims-Gewirtz graph. :: - sage: G = graphs.CossidentePenttilaGraph(3) # optional - gap_packages (grape) - sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) + sage: G = graphs.CossidentePenttilaGraph(3) # optional - gap_package_grape + sage: G.is_strongly_regular(parameters=True) # optional - gap_package_grape (56, 10, 0, 2) For `q>3` one gets new graphs. :: - sage: G = graphs.CossidentePenttilaGraph(5) # optional - gap_packages (grape) - sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) + sage: G = graphs.CossidentePenttilaGraph(5) # optional - gap_package_grape + sage: G.is_strongly_regular(parameters=True) # optional - gap_package_grape (378, 52, 1, 8) TESTS:: - sage: G = graphs.CossidentePenttilaGraph(7) # optional - gap_packages (grape) # long time - sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) # long time + sage: G = graphs.CossidentePenttilaGraph(7) # optional - gap_package_grape, long time + sage: G.is_strongly_regular(parameters=True) # optional - gap_package_grape, long time (1376, 150, 2, 18) sage: graphs.CossidentePenttilaGraph(2) Traceback (most recent call last): diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index 15bd3594185..b90795b86a1 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -103,8 +103,8 @@ def locally_GQ42_distance_transitive_graph(): EXAMPLES:: - sage: G = graphs.locally_GQ42_distance_transitive_graph() # optional - internet gap_packages - sage: G.is_distance_regular(True) # optional - internet gap_packages + sage: G = graphs.locally_GQ42_distance_transitive_graph() # optional - internet gap_package_atlasrep + sage: G.is_distance_regular(True) # optional - internet gap_package_atlasrep ([45, 32, 12, 1, None], [None, 1, 6, 32, 45]) REFERENCES: @@ -217,8 +217,8 @@ def graph_3O73(): EXAMPLES:: - sage: G = graphs.graph_3O73() # optional - internet gap_packages - sage: G.is_distance_regular(True) # optional - internet gap_packages + sage: G = graphs.graph_3O73() # optional - internet gap_package_atlasrep + sage: G.is_distance_regular(True) # optional - internet gap_package_atlasrep ([117, 80, 24, 1, None], [None, 1, 12, 80, 117]) REFERENCES: @@ -272,8 +272,8 @@ def J2Graph(): EXAMPLES:: - sage: G = graphs.J2Graph() # optional - internet gap_packages - sage: G.is_distance_regular(True) # optional - internet gap_packages + sage: G = graphs.J2Graph() # optional - internet gap_package_atlasrep + sage: G.is_distance_regular(True) # optional - internet gap_package_atlasrep ([10, 8, 8, 2, None], [None, 1, 1, 4, 5]) REFERENCES: @@ -295,8 +295,8 @@ def IvanovIvanovFaradjevGraph(): EXAMPLES:: - sage: G = graphs.IvanovIvanovFaradjevGraph() # optional - internet gap_packages - sage: G.is_distance_regular(True) # optional - internet gap_packages + sage: G = graphs.IvanovIvanovFaradjevGraph() # optional - internet gap_package_atlasrep + sage: G.is_distance_regular(True) # optional - internet gap_package_atlasrep ([7, 6, 4, 4, 4, 1, 1, 1, None], [None, 1, 1, 1, 2, 4, 4, 6, 7]) REFERENCES: @@ -1310,7 +1310,7 @@ def GeneralisedDodecagonGraph(const int s, const int t): EXAMPLES:: - sage: # optional - gap_packages internet + sage: # optional - gap_package_atlasrep internet sage: G = graphs.GeneralisedDodecagonGraph(1, 5) sage: G.is_distance_regular(True) ([6, 5, 5, 5, 5, 5, None], [None, 1, 1, 1, 1, 1, 6]) @@ -1335,7 +1335,7 @@ def GeneralisedDodecagonGraph(const int s, const int t): Test all graphs of order `(1, q)`:: - sage: # optional - gap_packages internet + sage: # optional - gap_package_atlasrep internet sage: G = graphs.GeneralisedDodecagonGraph(1, 4) sage: G.is_distance_regular(True) ([5, 4, 4, 4, 4, 4, None], [None, 1, 1, 1, 1, 1, 5]) @@ -1351,7 +1351,7 @@ def GeneralisedDodecagonGraph(const int s, const int t): Now test all graphs of order `(q, 1)`:: - sage: # optional - gap_packages internet + sage: # optional - gap_package_atlasrep internet sage: G = graphs.GeneralisedDodecagonGraph(4, 1) sage: G.is_distance_regular(True) ([8, 4, 4, 4, 4, 4, None], [None, 1, 1, 1, 1, 1, 2]) @@ -1422,8 +1422,8 @@ def GeneralisedOctagonGraph(const int s, const int t): sage: G = graphs.GeneralisedOctagonGraph(1, 4) sage: G.is_distance_regular(True) ([5, 4, 4, 4, None], [None, 1, 1, 1, 5]) - sage: G = graphs.GeneralisedOctagonGraph(2, 4) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedOctagonGraph(2, 4) # optional - gap_package_atlasrep internet + sage: G.is_distance_regular(True) # optional - gap_package_atlasrep internet ([10, 8, 8, 8, None], [None, 1, 1, 1, 5]) sage: G = graphs.GeneralisedOctagonGraph(5, 1) sage: G.is_distance_regular(True) @@ -1530,8 +1530,8 @@ def GeneralisedHexagonGraph(const int s, const int t): EXAMPLES:: sage: # needs sage.libs.gap - sage: G = graphs.GeneralisedHexagonGraph(5, 5) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedHexagonGraph(5, 5) # optional - gap_package_atlasrep internet + sage: G.is_distance_regular(True) # optional - gap_package_atlasrep internet ([30, 25, 25, None], [None, 1, 1, 6]) sage: G = graphs.GeneralisedHexagonGraph(7, 1) sage: G.is_distance_regular(True) @@ -1552,7 +1552,7 @@ def GeneralisedHexagonGraph(const int s, const int t): TESTS:: - sage: # optional - gap_packages internet + sage: # optional - gap_package_atlasrep internet sage: G = graphs.GeneralisedHexagonGraph(4, 4) sage: G.is_distance_regular(True) ([20, 16, 16, None], [None, 1, 1, 5]) @@ -1755,15 +1755,15 @@ def _line_graph_generalised_polygon(H): EXAMPLES:: sage: # needs sage.libs.gap - sage: from sage.graphs.generators.distance_regular import \ - ....: _line_graph_generalised_polygon + sage: from sage.graphs.generators.distance_regular import ( + ....: _line_graph_generalised_polygon) sage: G = graphs.GeneralisedHexagonGraph(1, 8) sage: H = _line_graph_generalised_polygon(G) sage: H.is_distance_regular(True) ([16, 8, 8, None], [None, 1, 1, 2]) - sage: G = graphs.GeneralisedHexagonGraph(3, 3) # optional - gap_packages internet - sage: H = _line_graph_generalised_polygon(G) # optional - gap_packages internet - sage: G.is_isomorphic(H) # optional - gap_packages internet + sage: G = graphs.GeneralisedHexagonGraph(3, 3) # optional - gap_package_atlasrep internet + sage: H = _line_graph_generalised_polygon(G) # optional - gap_package_atlasrep internet + sage: G.is_isomorphic(H) # optional - gap_package_atlasrep internet True REFERENCES: @@ -1908,7 +1908,7 @@ def is_classical_parameters_graph(list array): ....: is_classical_parameters_graph sage: is_classical_parameters_graph([68, 64, 1, 17]) # srg not drg # needs sage.combinat False - sage: G = graphs.GossetGraph() # sporadic classical parameters graph + sage: G = graphs.GossetGraph() # sporadic classical parameters graph sage: G.is_distance_regular(True) ([27, 10, 1, None], [None, 1, 10, 27]) sage: is_classical_parameters_graph([27, 10, 1, 1, 10, 27]) # needs sage.combinat @@ -2145,7 +2145,7 @@ def graph_with_classical_parameters(int d, int b, alpha_in, beta_in, int gamma): Symplectic Dual Polar Graph DSp(6, 2): Graph on 135 vertices sage: graph_with_classical_parameters(3, 2, 2, 14, 7) # long time Grassmann graph J_2(6, 3): Graph on 1395 vertices - sage: graph_with_classical_parameters(3, -2, -2, 6, 6) # optional - gap_packages internet + sage: graph_with_classical_parameters(3, -2, -2, 6, 6) # optional - gap_package_atlasrep internet Generalised hexagon of order (2, 8): Graph on 819 vertices """ from sage.rings.rational import Rational @@ -2728,7 +2728,7 @@ def distance_regular_graph(list arr, existence=False, check=True): sage: graphs.distance_regular_graph([3, 2, 2, 1, 2, 1, 1, 2, 2, 3], ....: existence=True) False - sage: graphs.distance_regular_graph([18, 16, 16, 1, 1, 9]) # optional - internet gap_packages + sage: graphs.distance_regular_graph([18, 16, 16, 1, 1, 9]) # optional - internet gap_package_atlasrep Generalised hexagon of order (2, 8): Graph on 819 vertices sage: # needs sage.combinat diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 3ef2c3a5556..a5916a13b5c 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -3937,12 +3937,12 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): [-4 -3 -2 2 3 4 -1 0 1] [-2 -4 -3 4 2 3 1 -1 0] - sage: # needs sage.modules sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings sage.groups sage.libs.gap sage: G.relabel(range(9)) - sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L) # needs sage.groups sage.libs.gap + sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L) sage: G3x3.is_strongly_regular(parameters=True) (441, 220, 109, 110) - sage: G3x3.automorphism_group(algorithm="bliss").order() # optional - bliss + sage: G3x3.automorphism_group(algorithm="bliss").order() # optional - bliss 27 sage: G9 = graphs.MathonPseudocyclicStronglyRegularGraph(2) sage: G9.is_strongly_regular(parameters=True) diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index e58248f05c8..bb73e4c487e 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -3394,9 +3394,9 @@ def LocalMcLaughlinGraph(): EXAMPLES:: - sage: g = graphs.LocalMcLaughlinGraph(); g # long time # optional - gap_packages + sage: g = graphs.LocalMcLaughlinGraph(); g # long time, optional - gap_package_design Local McLaughlin Graph: Graph on 162 vertices - sage: g.is_strongly_regular(parameters=True) # long time # optional - gap_packages + sage: g.is_strongly_regular(parameters=True) # long time, optional - gap_package_design (162, 56, 10, 24) """ g = McLaughlinGraph() @@ -3677,10 +3677,10 @@ def McLaughlinGraph(): EXAMPLES:: - sage: g = graphs.McLaughlinGraph() # optional gap_packages - sage: g.is_strongly_regular(parameters=True) # optional gap_packages + sage: g = graphs.McLaughlinGraph() # optional - gap_package_design + sage: g.is_strongly_regular(parameters=True) # optional - gap_package_design (275, 112, 30, 56) - sage: set(g.spectrum()) == {112, 2, -28} # optional gap_packages + sage: set(g.spectrum()) == {112, 2, -28} # optional - gap_package_design True """ from sage.combinat.designs.block_design import WittDesign @@ -5129,8 +5129,8 @@ def U42Graph216(): EXAMPLES:: - sage: G=graphs.U42Graph216() # optional - gap_packages (grape) - sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) + sage: G=graphs.U42Graph216() # optional - gap_package_grape + sage: G.is_strongly_regular(parameters=True) # optional - gap_package_grape (216, 40, 4, 8) """ from sage.libs.gap.libgap import libgap @@ -5176,8 +5176,8 @@ def U42Graph540(): EXAMPLES:: - sage: G=graphs.U42Graph540() # optional - gap_packages (grape) - sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) + sage: G = graphs.U42Graph540() # optional - gap_package_grape + sage: G.is_strongly_regular(parameters=True) # optional - gap_package_grape (540, 187, 58, 68) """ from sage.libs.gap.libgap import libgap diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 0c2dc0a79df..2deb533f7f1 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -439,7 +439,6 @@ from sage.misc.decorators import options from sage.misc.cachefunc import cached_method from sage.misc.prandom import random -from sage.misc.superseded import deprecation from sage.misc.lazy_import import lazy_import, LazyImport from sage.rings.integer_ring import ZZ @@ -3515,7 +3514,7 @@ def allow_multiple_edges(self, new, check=True, keep_label='any'): self._backend.multiple_edges(new) - def multiple_edges(self, to_undirected=False, labels=True, sort=False): + def multiple_edges(self, to_undirected=False, labels=True, sort=False, key=None): """ Return any multiple edges in the (di)graph. @@ -3525,7 +3524,11 @@ def multiple_edges(self, to_undirected=False, labels=True, sort=False): - ``labels`` -- boolean (default: ``True``); whether to include labels - - ``sort`` - boolean (default: ``False``); whether to sort the result + - ``sort`` -- boolean (default: ``False``); whether to sort the result + + - ``key`` -- a function (default: ``None``); a function that takes an + edge as its one argument and returns a value that can be used for + comparisons in the sorting algorithm (we must have ``sort=True``) EXAMPLES:: @@ -3574,7 +3577,36 @@ def multiple_edges(self, to_undirected=False, labels=True, sort=False): [] sage: G.multiple_edges(to_undirected=True, sort=True) [(1, 2, 'h'), (2, 1, 'g')] + + Using the ``key`` argument to order multiple edges of incomparable + types (see :trac:`35903`):: + + sage: G = Graph([('A', 'B', 3), (1, 2, 1), ('A', 'B', 4), (1, 2, 2)], multiedges=True) + sage: G.multiple_edges(sort=True) + Traceback (most recent call last): + ... + TypeError: unsupported operand parent(s) for <: 'Integer Ring' and ' ' + sage: G.multiple_edges(labels=False, sort=True, key=str) + [('A', 'B'), ('A', 'B'), (1, 2), (1, 2)] + sage: G.multiple_edges(sort=True, key=str) + [('A', 'B', 3), ('A', 'B', 4), (1, 2, 1), (1, 2, 2)] + sage: G.multiple_edges(labels=True, sort=True, key=lambda e:e[2]) + [(1, 2, 1), (1, 2, 2), ('A', 'B', 3), ('A', 'B', 4)] + sage: G.multiple_edges(labels=False, sort=True, key=lambda e:e[2]) + Traceback (most recent call last): + ... + IndexError: tuple index out of range + + TESTS:: + + sage: Graph().multiple_edges(sort=False, key=str) + Traceback (most recent call last): + ... + ValueError: sort keyword is False, yet a key function is given """ + if (not sort) and key: + raise ValueError('sort keyword is False, yet a key function is given') + multi_edges = [] seen = set() @@ -3647,7 +3679,7 @@ def multiple_edges(self, to_undirected=False, labels=True, sort=False): multi_edges.extend((u, v) for _ in L) if sort: - multi_edges.sort() + return sorted(multi_edges, key=key) return multi_edges def name(self, new=None): @@ -5092,7 +5124,7 @@ def cycle_basis(self, output='vertex'): sage: G.cycle_basis() # needs networkx [[0, 2], [2, 1, 0]] sage: G.cycle_basis(output='edge') # needs networkx - [[(0, 2, 'a'), (2, 0, 'b')], [(2, 1, 'd'), (1, 0, 'c'), (0, 2, 'a')]] + [[(0, 2, 'b'), (2, 0, 'a')], [(2, 1, 'd'), (1, 0, 'c'), (0, 2, 'a')]] sage: H = Graph([(1, 2), (2, 3), (2, 3), (3, 4), (1, 4), ....: (1, 4), (4, 5), (5, 6), (4, 6), (6, 7)], multiedges=True) sage: H.cycle_basis() # needs networkx @@ -5134,10 +5166,9 @@ def cycle_basis(self, output='vertex'): sage: G.cycle_basis() # needs networkx [[2, 3], [4, 3, 2, 1], [4, 3, 2, 1]] sage: G.cycle_basis(output='edge') # needs networkx - [[(2, 3, 'b'), (3, 2, 'c')], + [[(2, 3, 'c'), (3, 2, 'b')], [(4, 3, 'd'), (3, 2, 'b'), (2, 1, 'a'), (1, 4, 'f')], [(4, 3, 'e'), (3, 2, 'b'), (2, 1, 'a'), (1, 4, 'f')]] - """ if output not in ['vertex', 'edge']: raise ValueError('output must be either vertex or edge') @@ -11332,19 +11363,15 @@ def neighbor_iterator(self, vertex, closed=False): for u in self._backend.iterator_nbrs(vertex): yield u - def vertices(self, sort=None, key=None, degree=None, vertex_property=None): + def vertices(self, sort=False, key=None, degree=None, vertex_property=None): r""" Return a list of the vertices. INPUT: - - ``sort`` -- boolean (default: ``None``); if ``True``, vertices are - sorted according to the default ordering - - As of :trac:`22349`, this argument must be explicitly - specified (unless a ``key`` is given); otherwise a warning - is printed and ``sort=True`` is used. The default will - eventually be changed to ``False``. + - ``sort`` -- boolean (default: ``False``); whether to sort vertices + according the ordering specified with parameter ``key``. If ``False`` + (default), vertices are not sorted. - ``key`` -- a function (default: ``None``); a function that takes a vertex as its one argument and returns a value that can be used for @@ -11432,20 +11459,7 @@ def vertices(self, sort=None, key=None, degree=None, vertex_property=None): Traceback (most recent call last): ... ValueError: sort keyword is False, yet a key function is given - - Deprecation warning for ``sort=None`` (:trac:`22349`):: - - sage: G = graphs.HouseGraph() - sage: G.vertices() - doctest:...: DeprecationWarning: parameter 'sort' will be set to False by default in the future - See https://github.com/sagemath/sage/issues/22349 for details. - [0, 1, 2, 3, 4] """ - if sort is None: - if key is None: - deprecation(22349, "parameter 'sort' will be set to False by default in the future") - sort = True - if (not sort) and key: raise ValueError('sort keyword is False, yet a key function is given') @@ -12371,7 +12385,7 @@ def has_edge(self, u, v=None, label=None): label = None return self._backend.has_edge(u, v, label) - def edges(self, vertices=None, labels=True, sort=None, key=None, + def edges(self, vertices=None, labels=True, sort=False, key=None, ignore_direction=False, sort_vertices=True): r""" Return a :class:`~EdgesView` of edges. @@ -12395,13 +12409,10 @@ def edges(self, vertices=None, labels=True, sort=None, key=None, - ``labels`` -- boolean (default: ``True``); if ``False``, each edge is simply a pair ``(u, v)`` of vertices - - ``sort`` -- boolean (default: ``None``); if ``True``, edges are sorted - according to the default ordering - - As of :trac:`22349`, this argument must be explicitly - specified (unless a ``key`` is given); otherwise a warning - is printed and ``sort=True`` is used. The default will - eventually be changed to ``False``. + - ``sort`` -- boolean (default: ``False``); whether to sort edges + according the ordering specified with parameter ``key``. If ``False`` + (default), edges are not sorted. This is the fastest and less memory + consuming method for iterating over edges. - ``key`` -- a function (default: ``None``); a function that takes an edge (a pair or a triple, according to the ``labels`` keyword) as its @@ -12497,7 +12508,7 @@ def edges(self, vertices=None, labels=True, sort=None, key=None, ....: G.set_edge_label(e[0], e[1], chr(ord('A') + e[0] + 5 * e[1])) sage: G.edges(sort=True) [(0, 1, 'F'), (0, 4, 'U'), (1, 2, 'L'), (2, 3, 'R'), (3, 4, 'X')] - sage: G.edges(key=lambda x: x[2]) + sage: G.edges(sort=True, key=lambda x: x[2]) [(0, 1, 'F'), (1, 2, 'L'), (2, 3, 'R'), (0, 4, 'U'), (3, 4, 'X')] We can restrict considered edges to those incident to a given set:: @@ -12548,27 +12559,14 @@ def edges(self, vertices=None, labels=True, sort=None, key=None, sage: G.edge_label(0, 1)[0] += 1 sage: G.edges(sort=True) [(0, 1, [8]), (0, 2, [7])] - - Deprecation warning for ``sort=None`` (:trac:`27408`):: - - sage: G = graphs.HouseGraph() - sage: G.edges(sort=None) - doctest:...: DeprecationWarning: parameter 'sort' will be set to False by default in the future - See https://github.com/sagemath/sage/issues/27408 for details. - [(0, 1, None), (0, 2, None), (1, 3, None), (2, 3, None), (2, 4, None), (3, 4, None)] """ - if sort is None: - if key is None: - deprecation(27408, "parameter 'sort' will be set to False by default in the future") - sort = True - if vertices is not None and vertices in self: vertices = [vertices] return EdgesView(self, vertices=vertices, labels=labels, sort=sort, key=key, ignore_direction=ignore_direction, sort_vertices=sort_vertices) - def edge_boundary(self, vertices1, vertices2=None, labels=True, sort=False): + def edge_boundary(self, vertices1, vertices2=None, labels=True, sort=False, key=None): r""" Return a list of edges ``(u,v,l)`` with ``u`` in ``vertices1`` and ``v`` in ``vertices2``. @@ -12586,6 +12584,10 @@ def edge_boundary(self, vertices1, vertices2=None, labels=True, sort=False): - ``sort`` -- boolean (default: ``False``); whether to sort the result + - ``key`` -- a function (default: ``None``); a function that takes an + edge as its one argument and returns a value that can be used for + comparisons in the sorting algorithm (we must have ``sort=True``) + EXAMPLES:: sage: K = graphs.CompleteBipartiteGraph(9, 3) @@ -12610,6 +12612,23 @@ def edge_boundary(self, vertices1, vertices2=None, labels=True, sort=False): sage: D.edge_boundary([0], labels=False, sort=True) [(0, 1), (0, 2)] + Using the ``key`` argument to order multiple edges of incomparable + types (see :trac:`35903`):: + + sage: G = Graph([(1, 'A', 4), (1, 2, 3)]) + sage: G.edge_boundary([1], sort=True) + Traceback (most recent call last): + ... + TypeError: unsupported operand parent(s) for <: 'Integer Ring' and '