Skip to content

Commit

Permalink
Trac #33646: face_iter/face_generator of polyhedra: Specify algorithm…
Browse files Browse the repository at this point in the history
… instead of dual=False/True

In addition we add a function alias: `face_generator` for
`CombinatorialPolyhedron` to make it consistent with `Polyhedron_base`.

We deprecate the keyword `dual`.

URL: https://trac.sagemath.org/33646
Reported by: gh-kliem
Ticket author(s): Jonathan Kliem
Reviewer(s): Travis Scrimshaw, Yuan Zhou
  • Loading branch information
Release Manager committed Apr 10, 2022
2 parents 38b13ef + ed15041 commit 608a2dc
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 126 deletions.
66 changes: 55 additions & 11 deletions src/sage/geometry/polyhedron/base3.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ def _test_combinatorial_polyhedron(self, tester=None, **options):
prefix=tester._prefix+" ")
tester.info(tester._prefix+" ", newline = False)

def face_generator(self, face_dimension=None, dual=None):
def face_generator(self, face_dimension=None, algorithm=None, **kwds):
r"""
Return an iterator over the faces of given dimension.
Expand All @@ -381,10 +381,11 @@ def face_generator(self, face_dimension=None, dual=None):
- ``face_dimension`` -- integer (default ``None``),
yield only faces of this dimension if specified
- ``dual`` -- boolean (default ``None``);
if ``True``, generate the faces using the vertices;
if ``False``, generate the faces using the facets;
if ``None``, pick automatically
- ``algorithm`` -- string (optional);
specify whether to start with facets or vertices:
* ``'primal'`` -- start with the facets
* ``'dual'`` -- start with the vertices
* ``None`` -- choose automatically
OUTPUT:
Expand Down Expand Up @@ -474,7 +475,7 @@ def face_generator(self, face_dimension=None, dual=None):
In non-dual mode we can skip subfaces of the current (proper) face::
sage: P = polytopes.cube()
sage: it = P.face_generator(dual=False)
sage: it = P.face_generator(algorithm='primal')
sage: _ = next(it), next(it)
sage: face = next(it)
sage: face.ambient_H_indices()
Expand All @@ -500,7 +501,7 @@ def face_generator(self, face_dimension=None, dual=None):
In dual mode we can skip supfaces of the current (proper) face::
sage: P = polytopes.cube()
sage: it = P.face_generator(dual=True)
sage: it = P.face_generator(algorithm='dual')
sage: _ = next(it), next(it)
sage: face = next(it)
sage: face.ambient_V_indices()
Expand Down Expand Up @@ -528,7 +529,7 @@ def face_generator(self, face_dimension=None, dual=None):
In non-dual mode, we cannot skip supfaces::
sage: it = P.face_generator(dual=False)
sage: it = P.face_generator(algorithm='primal')
sage: _ = next(it), next(it)
sage: next(it)
A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 4 vertices
Expand All @@ -539,7 +540,7 @@ def face_generator(self, face_dimension=None, dual=None):
In dual mode, we cannot skip subfaces::
sage: it = P.face_generator(dual=True)
sage: it = P.face_generator(algorithm='dual')
sage: _ = next(it), next(it)
sage: next(it)
A 0-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 1 vertex
Expand All @@ -550,7 +551,7 @@ def face_generator(self, face_dimension=None, dual=None):
We can only skip sub-/supfaces of proper faces::
sage: it = P.face_generator(dual=False)
sage: it = P.face_generator(algorithm='primal')
sage: next(it)
A 3-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 8 vertices
sage: it.ignore_subfaces()
Expand Down Expand Up @@ -585,7 +586,49 @@ def face_generator(self, face_dimension=None, dual=None):
sage: [f] = P.face_generator(2)
sage: f.ambient_Hrepresentation()
(An equation (1, 1, 1) x - 6 == 0,)
The ``dual`` keyword is deprecated::
sage: P = polytopes.hypercube(4)
sage: list(P.face_generator(dual=False))[:4]
doctest:...: DeprecationWarning: the keyword dual is deprecated; use algorithm instead
See https://trac.sagemath.org/33646 for details.
[A 4-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 16 vertices,
A -1-dimensional face of a Polyhedron in ZZ^4,
A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices,
A 3-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 8 vertices]
sage: list(P.face_generator(True))[:4]
[A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices,
A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices,
A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices,
A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices]
Check that we catch incorrect algorithms:
sage: list(P.face_generator(2, algorithm='integrate'))[:4]
Traceback (most recent call last):
...
ValueError: algorithm must be 'primal', 'dual' or None
"""
dual = None
if algorithm == 'primal':
dual = False
elif algorithm == 'dual':
dual = True
elif algorithm in (False, True):
from sage.misc.superseded import deprecation
deprecation(33646, "the keyword dual is deprecated; use algorithm instead")
dual = algorithm
elif algorithm is not None:
raise ValueError("algorithm must be 'primal', 'dual' or None")

if kwds:
from sage.misc.superseded import deprecation
deprecation(33646, "the keyword dual is deprecated; use algorithm instead")
if 'dual' in kwds and dual is None:
dual = kwds['dual']


from sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator import FaceIterator_geom
return FaceIterator_geom(self, output_dimension=face_dimension, dual=dual)

Expand Down Expand Up @@ -1781,7 +1824,8 @@ def _test_combinatorial_face_as_combinatorial_polyhedron(self, tester=None, **op
C1 = self.combinatorial_polyhedron()
it1 = C1.face_iter()
C2 = C1.dual()
it2 = C2.face_iter(dual=not it1.dual)
algorithm = 'primal' if it1.dual else 'dual'
it2 = C2.face_iter(algorithm=algorithm)

for f in it:
f1 = next(it1)
Expand Down
Loading

0 comments on commit 608a2dc

Please sign in to comment.