From 31906994cfeaa60abca4df9970edea2ce183ae8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Labb=C3=A9?= Date: Tue, 4 Feb 2020 13:56:02 +0100 Subject: [PATCH] fixed construction normal cone --- src/sage/geometry/polyhedron/face.py | 54 +++++++++++++++++++++------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/src/sage/geometry/polyhedron/face.py b/src/sage/geometry/polyhedron/face.py index aa1d5aad1b5..4dd8a1ad85f 100644 --- a/src/sage/geometry/polyhedron/face.py +++ b/src/sage/geometry/polyhedron/face.py @@ -701,33 +701,61 @@ def normal_cone(self, direction='outer'): ....: nc = v.normal_cone().rays_list() ....: print("{} has outer normal cone spanned by {}".format(vect,nc)) ....: - (-2, -2) has outer normal cone spanned by [[-1, 0], [0, -1]] - (-2, 2) has outer normal cone spanned by [[-1, 0], [0, 1]] + (2, 1) has outer normal cone spanned by [[1, 0], [1, 1]] (1, 2) has outer normal cone spanned by [[0, 1], [1, 1]] (2, -2) has outer normal cone spanned by [[0, -1], [1, 0]] - (2, 1) has outer normal cone spanned by [[1, 0], [1, 1]] + (-2, -2) has outer normal cone spanned by [[-1, 0], [0, -1]] + (-2, 2) has outer normal cone spanned by [[-1, 0], [0, 1]] sage: for v in p.faces(0): ....: vect = v.vertices()[0].vector() ....: nc = v.normal_cone(direction='inner').rays_list() ....: print("{} has inner normal cone spanned by {}".format(vect,nc)) ....: - (-2, -2) has inner normal cone spanned by [[0, 1], [1, 0]] - (-2, 2) has inner normal cone spanned by [[0, -1], [1, 0]] + (2, 1) has inner normal cone spanned by [[-1, -1], [-1, 0]] (1, 2) has inner normal cone spanned by [[-1, -1], [0, -1]] (2, -2) has inner normal cone spanned by [[-1, 0], [0, 1]] - (2, 1) has inner normal cone spanned by [[-1, -1], [-1, 0]] + (-2, -2) has inner normal cone spanned by [[0, 1], [1, 0]] + (-2, 2) has inner normal cone spanned by [[0, -1], [1, 0]] - """ - if direction == 'outer': - normal_vectors = [-facet.A() for facet in self.ambient_Hrepresentation()] - elif direction == 'inner': - normal_vectors = [facet.A() for facet in self.ambient_Hrepresentation()] - else: + The function works for polytopes that are not full-dimensional:: + + sage: p = polytopes.permutahedron(3) + sage: f1 = p.faces(0)[0] + sage: f2 = p.faces(1)[0] + sage: f3 = p.faces(2)[0] + sage: f1.normal_cone() + A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line + sage: f2.normal_cone() + A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex, 1 ray, 1 line + sage: f3.normal_cone() + A 0-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex + + Normal cones are only defined for non-empty faces:: + + sage: f0 = p.faces(-1)[0] + sage: f0.normal_cone() + Traceback (most recent call last): + ... + ValueError: the empty face does not have a normal cone + """ + if self.dim() == -1: + raise ValueError("the empty face does not have a normal cone") + elif direction not in ['outer','inner']: raise ValueError("the direction should be either 'outer' or 'inner'") + rays = [] + lines = [] + for facet in self.ambient_Hrepresentation(): + if facet.is_equation(): + lines += [facet.A()] + elif direction == 'outer': + rays += [-facet.A()] + else: # 'inner' + rays += [facet.A()] parent = self.polyhedron().parent() origin = parent.zero().vertices()[0].vector() - return parent.element_class(parent,[[origin], normal_vectors, []], None) + return parent.element_class(parent, [[origin], rays, lines], None) + def combinatorial_face_to_polyhedral_face(polyhedron, combinatorial_face): r"""