diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8d936616077..ada020d8722 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -103,12 +103,24 @@ jobs:
run: pyright
working-directory: ./worktree-image
- - name: Build (fallback to non-incremental)
- id: build
+ - name: Clean (fallback to non-incremental)
+ id: clean
if: always() && steps.worktree.outcome == 'success' && steps.incremental.outcome != 'success'
run: |
set -ex
- ./bootstrap && make doc-clean doc-uninstall sagelib-clean && git clean -fx src/sage && ./config.status && make build
+ ./bootstrap && make doc-clean doc-uninstall sagelib-clean && git clean -fx src/sage && ./config.status
+ working-directory: ./worktree-image
+ env:
+ MAKE: make -j2
+ SAGE_NUM_THREADS: 2
+
+ - name: Build
+ # This step is needed because building the modularized distributions installs some optional packages,
+ # so the editable install of sagelib needs to build the corresponding optional extension modules.
+ id: build
+ if: always() && (steps.incremental.outcome == 'success' || steps.clean.outcome == 'success')
+ run: |
+ make build
working-directory: ./worktree-image
env:
MAKE: make -j2
@@ -125,14 +137,14 @@ jobs:
COLUMNS: 120
- name: Test all files (sage -t --all --long)
- if: always() && (steps.incremental.outcome == 'success' || steps.build.outcome == 'success')
+ if: always() && steps.build.outcome == 'success'
run: |
../sage -python -m pip install coverage
../sage -python -m coverage run ./bin/sage-runtests --all --long -p2 --random-seed=286735480429121101562228604801325644303
working-directory: ./worktree-image/src
- name: Prepare coverage results
- if: always() && (steps.incremental.outcome == 'success' || steps.build.outcome == 'success')
+ if: always() && steps.build.outcome == 'success'
run: |
./venv/bin/python3 -m coverage combine src/.coverage/
./venv/bin/python3 -m coverage xml
@@ -140,7 +152,7 @@ jobs:
working-directory: ./worktree-image
- name: Upload coverage to codecov
- if: always() && (steps.incremental.outcome == 'success' || steps.build.outcome == 'success')
+ if: always() && steps.build.outcome == 'success'
uses: codecov/codecov-action@v3
with:
files: ./worktree-image/coverage.xml
diff --git a/CITATION.cff b/CITATION.cff
index 6f4f46a6d8a..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.beta8
+version: 10.1.rc0
doi: 10.5281/zenodo.593563
-date-released: 2023-07-30
+date-released: 2023-08-13
repository-code: "https://github.com/sagemath/sage"
url: "https://www.sagemath.org/"
diff --git a/README.md b/README.md
index 9982460cd78..2e5419541af 100644
--- a/README.md
+++ b/README.md
@@ -65,7 +65,7 @@ your Windows. Make sure you allocate WSL sufficient RAM; 5GB is known to work, w
Then all instructions for installation in Linux apply.
As an alternative, you can also run Linux on Windows using Docker (see
-above) or other virtualization solutions.
+below) or other virtualization solutions.
[macOS] Preparing the Platform
------------------------------
@@ -416,6 +416,18 @@ You need to install `sage_conf`, a wheelhouse of various python packages. You ca
**NOTE:** You can find `sage` and `sagemath` pip packages but with these packages, you will encounter `ModuleNotFoundError`.
+SageMath Docker images
+----------------------
+
+[![Docker Status](http://dockeri.co/image/sagemath/sagemath)](https://hub.docker.com/r/sagemath/sagemath)
+
+SageMath is available on Docker Hub and can be downloaded by:
+``` bash
+docker pull sagemath/sagemath
+```
+
+Currently, only stable versions are kept up to date.
+
Troubleshooting
---------------
diff --git a/VERSION.txt b/VERSION.txt
index d9562f0204a..a62521f032f 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-SageMath version 10.1.beta8, Release Date: 2023-07-30
+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 e489dd26d2e..ba26592020a 100644
--- a/build/pkgs/configure/checksums.ini
+++ b/build/pkgs/configure/checksums.ini
@@ -1,4 +1,4 @@
tarball=configure-VERSION.tar.gz
-sha1=5930a5bb8c0164176122d6ffb1143df61b990213
-md5=b70ab1eaa247dce59a59910ec8e89051
-cksum=3869087595
+sha1=139bcabc03fbf74d05379ff27713c7e3496fc362
+md5=2631cd73e85221b77dea105e30f6165d
+cksum=2003135383
diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt
index 33340576bb6..b18e430562c 100644
--- a/build/pkgs/configure/package-version.txt
+++ b/build/pkgs/configure/package-version.txt
@@ -1 +1 @@
-79dc3510abb05344ac7ef23d42d1228f186b7493
+50208b761995b49bf6f0702f4b9d36da24fae1a0
diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt
index 308956090b6..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.1b8
+sage-conf ~= 10.1rc0
diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt
index f2408da3bef..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.1b8
+sage-docbuild ~= 10.1rc0
diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt
index 3fb4f9bd897..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.1b8
+sage-setup ~= 10.1rc0
diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt
index 5705cd5cef9..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.1b8
+sage-sws2rst ~= 10.1rc0
diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt
index 09ddf8e9f0e..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.1b8
+sagemath-standard ~= 10.1rc0
diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt
index 175856b245f..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.1b8
+sagemath-bliss ~= 10.1rc0
diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt
index 2bc854cfebc..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.1b8
+sagemath-categories ~= 10.1rc0
diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt
index 7576be637d3..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.1b8
+sagemath-coxeter3 ~= 10.1rc0
diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt
index ac5083c4105..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.1b8
+sagemath-environment ~= 10.1rc0
diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt
index 211e612c18e..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.1b8
+sagemath-mcqd ~= 10.1rc0
diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt
index 1ca467ef1b7..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.1b8
+sagemath-meataxe ~= 10.1rc0
diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt
index c8da8347647..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.1b8
+sagemath-objects ~= 10.1rc0
diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt
index da36117bd6e..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.1b8
+sagemath-repl ~= 10.1rc0
diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt
index 417fc0e71cf..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.1b8
+sagemath-sirocco ~= 10.1rc0
diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt
index 949a775737d..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.1b8
+sagemath-tdlib ~= 10.1rc0
diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sage-conf/VERSION.txt
+++ b/pkgs/sage-conf/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sage-conf_pypi/VERSION.txt
+++ b/pkgs/sage-conf_pypi/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sage-docbuild/VERSION.txt
+++ b/pkgs/sage-docbuild/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sage-setup/VERSION.txt
+++ b/pkgs/sage-setup/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sage-sws2rst/VERSION.txt
+++ b/pkgs/sage-sws2rst/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sagemath-bliss/MANIFEST.in b/pkgs/sagemath-bliss/MANIFEST.in
index 689b87560e0..6d981b9d30e 100644
--- a/pkgs/sagemath-bliss/MANIFEST.in
+++ b/pkgs/sagemath-bliss/MANIFEST.in
@@ -1,5 +1,3 @@
-global-include all__sagemath_bliss.py
-
include VERSION.txt
graft sage/graphs/bliss_cpp
@@ -7,6 +5,9 @@ graft sage/graphs/bliss_cpp
global-exclude *.c
global-exclude *.cpp
+global-exclude all__sagemath_*.*
+global-include all__sagemath_bliss.py
+
global-exclude __pycache__
global-exclude *.py[co]
global-exclude *.bak
diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sagemath-bliss/VERSION.txt
+++ b/pkgs/sagemath-bliss/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sagemath-categories/MANIFEST.in.m4 b/pkgs/sagemath-categories/MANIFEST.in.m4
index 361132e0cfa..b2e35673ec0 100644
--- a/pkgs/sagemath-categories/MANIFEST.in.m4
+++ b/pkgs/sagemath-categories/MANIFEST.in.m4
@@ -3,7 +3,6 @@ prune sage
include VERSION.txt
-global-include all__sagemath_categories.py
graft sage/categories
# Exclude what is already shipped in sagemath-objects
exclude sage/categories/action.*
@@ -42,6 +41,9 @@ graft sage/typeset # dep of sage.categories.tensor
global-exclude *.c
global-exclude *.cpp
+global-exclude all__sagemath_*.*
+global-include all__sagemath_categories.py
+
global-exclude __pycache__
global-exclude *.py[co]
global-exclude *.bak
diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sagemath-categories/VERSION.txt
+++ b/pkgs/sagemath-categories/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sagemath-coxeter3/MANIFEST.in b/pkgs/sagemath-coxeter3/MANIFEST.in
index 003ab8d5180..a69f2e71363 100644
--- a/pkgs/sagemath-coxeter3/MANIFEST.in
+++ b/pkgs/sagemath-coxeter3/MANIFEST.in
@@ -1,7 +1,5 @@
prune sage
-global-include all__sagemath_coxeter3.py
-
include VERSION.txt
graft sage/libs/coxeter3
@@ -9,6 +7,9 @@ graft sage/libs/coxeter3
global-exclude *.c
global-exclude *.cpp
+global-exclude all__sagemath_*.*
+global-include all__sagemath_coxeter3.py
+
global-exclude __pycache__
global-exclude *.py[co]
global-exclude *.bak
diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sagemath-coxeter3/VERSION.txt
+++ b/pkgs/sagemath-coxeter3/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sagemath-environment/MANIFEST.in b/pkgs/sagemath-environment/MANIFEST.in
index 36f8fae1845..ca4266e2bf4 100644
--- a/pkgs/sagemath-environment/MANIFEST.in
+++ b/pkgs/sagemath-environment/MANIFEST.in
@@ -1,7 +1,5 @@
prune sage
-global-include all__sagemath_environment.py
-
include sage/env.py
include sage/version.py
include sage/misc/package.py
@@ -12,4 +10,14 @@ graft sage/features
include VERSION.txt
+global-exclude all__*.py
+global-include all__sagemath_environment.py
+
+global-exclude __pycache__
global-exclude *.py[co]
+global-exclude *.bak
+global-exclude *.so
+global-exclude *~
+prune .tox
+prune build
+prune dist
diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sagemath-environment/VERSION.txt
+++ b/pkgs/sagemath-environment/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sagemath-mcqd/MANIFEST.in b/pkgs/sagemath-mcqd/MANIFEST.in
index 392d97b78e0..801e1b3e48d 100644
--- a/pkgs/sagemath-mcqd/MANIFEST.in
+++ b/pkgs/sagemath-mcqd/MANIFEST.in
@@ -1,7 +1,5 @@
prune sage
-global-include all__sagemath_mcqd.py
-
include VERSION.txt
include sage/graphs/mcqd.p*
@@ -9,6 +7,9 @@ include sage/graphs/mcqd.p*
global-exclude *.c
global-exclude *.cpp
+global-exclude all__sagemath_*.*
+global-include all__sagemath_mcqd.py
+
global-exclude __pycache__
global-exclude *.py[co]
global-exclude *.bak
diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt
index d06eca61e5a..72237f23c26 100644
--- a/pkgs/sagemath-mcqd/VERSION.txt
+++ b/pkgs/sagemath-mcqd/VERSION.txt
@@ -1 +1 @@
-10.1.beta8
+10.1.rc0
diff --git a/pkgs/sagemath-meataxe/MANIFEST.in b/pkgs/sagemath-meataxe/MANIFEST.in
index 4cf78dd5d02..c69ce68fc40 100644
--- a/pkgs/sagemath-meataxe/MANIFEST.in
+++ b/pkgs/sagemath-meataxe/MANIFEST.in
@@ -1,7 +1,5 @@
prune sage
-global-include all__sagemath_meataxe.py
-
include VERSION.txt
include sage/libs/meataxe.p*
@@ -10,6 +8,9 @@ include sage/matrix/matrix_gfpn_dense.p*
global-exclude *.c
global-exclude *.cpp
+global-exclude all__sagemath_*.*
+global-include all__sagemath_meataxe.py
+
global-exclude __pycache__
global-exclude *.py[co]
global-exclude *.bak
diff --git a/pkgs/sagemath-meataxe/README.rst b/pkgs/sagemath-meataxe/README.rst
index 088ce86478b..659edb3cf9f 100644
--- a/pkgs/sagemath-meataxe/README.rst
+++ b/pkgs/sagemath-meataxe/README.rst
@@ -28,8 +28,8 @@ About this pip-installable source distribution
This pip-installable source distribution ``sagemath-meataxe`` is a small
optional distribution for use with ``sagemath-standard``.
-This distribution provides the SageMath modules :mod:`sage.libs.meataxe`
-and :mod:`sage.matrix.matrix_gfpn_dense`.
+This distribution provides the SageMath modules ``sage.libs.meataxe``
+and ``sage.matrix.matrix_gfpn_dense``.
It provides a specialized implementation of matrices over the finite field F_q, where
q <= 255, using the `SharedMeatAxe
= 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.