Path: blob/master/sage/geometry/polyhedron/representation.py
4069 views
"""1H(yperplane) and V(ertex) representation objects for polyhedra2"""34########################################################################5# Copyright (C) 2008 Marshall Hampton <[email protected]>6# Copyright (C) 2011 Volker Braun <[email protected]>7#8# Distributed under the terms of the GNU General Public License (GPL)9#10# http://www.gnu.org/licenses/11########################################################################121314from sage.structure.sage_object import SageObject15from sage.structure.element import is_Vector16from sage.rings.all import QQ, ZZ, RDF17from sage.modules.free_module_element import vector18from sage.misc.all import cached_method19202122#########################################################################23# PolyhedronRepresentation24# / \25# / \26# Hrepresentation Vrepresentation27# / \ / | \28# / \ / | \29# Inequality Equation Vertex Ray Line3031class PolyhedronRepresentation(SageObject):32"""33The internal base class for all representation objects of34``Polyhedron`` (vertices/rays/lines and inequalites/equations)3536.. note::3738You should not (and cannot) instantiate it yourself. You can39only obtain them from a Polyhedron() class.4041"""4243# Numeric values for the output of the type() method44INEQUALITY = 045EQUATION = 146VERTEX = 247RAY = 348LINE = 44950def __init__(self, polyhedron, data):51"""52Initializes the PolyhedronRepresentation object.5354TESTS::5556sage: import sage.geometry.polyhedron.representation as P57sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])58sage: tuple(pr)59(1, 2, 3)60sage: TestSuite(pr).run(skip='_test_pickling')61"""62self._representation_data = tuple(data)63self._polyhedron = polyhedron6465def __len__(self):66"""67Returns the length of the representation data.6869TESTS::7071sage: import sage.geometry.polyhedron.representation as P72sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])73sage: pr.__len__()74375"""76return len(self._representation_data)7778def __getitem__(self, i):79"""80Supports indexing.8182TESTS::8384sage: import sage.geometry.polyhedron.representation as P85sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])86sage: pr.__getitem__(1)87288"""89return self._representation_data[i]9091def polyhedron(self):92"""93Returns the underlying polyhedron.9495TESTS::9697sage: import sage.geometry.polyhedron.representation as P98sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])99sage: pr.polyhedron()100A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex101"""102return self._polyhedron103104def __call__(self):105"""106Returns the vector representation of the representation107object. Shorthand for the vector() method.108109Note that the vector() method is only implemented in derived110classes.111112TESTS::113114sage: import sage.geometry.polyhedron.representation as P115sage: pr = Polyhedron(vertices = [[1,2,3]]).Vrepresentation(0)116sage: pr.__call__()117(1, 2, 3)118119sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])120sage: pr.__call__()121Traceback (most recent call last):122...123AttributeError: 'PolyhedronRepresentation' object has no attribute 'vector'124"""125return self.vector()126127def index(self):128"""129Returns an arbitrary but fixed number according to the internal130storage order.131132NOTES:133134H-representation and V-representation objects are enumerated135independently. That is, amongst all vertices/rays/lines there136will be one with ``index()==0``, and amongs all137inequalities/equations there will be one with ``index()==0``,138unless the polyhedron is empty or spans the whole space.139140EXAMPLES::141142sage: s = Polyhedron(vertices=[[1],[-1]])143sage: first_vertex = s.vertex_generator().next()144sage: first_vertex.index()1450146sage: first_vertex == s.Vrepresentation(0)147True148"""149return self._index150151152153class Hrepresentation(PolyhedronRepresentation):154"""155The internal base class for H-representation objects of156a polyhedron. Inherits from ``PolyhedronRepresentation``.157"""158def __init__(self, polyhedron, data):159"""160Initialization function.161162TESTS::163164sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])165sage: pH = p.Hrepresentation(0)166sage: TestSuite(pH).run(skip='_test_pickling')167"""168if len(data) != 1+polyhedron.ambient_dim():169raise ValueError, \170'H-representation data requires a list of length ambient_dim+1'171super(Hrepresentation, self).__init__(polyhedron, data)172self._index = len(polyhedron._Hrepresentation)173polyhedron._Hrepresentation.append(self)174175@cached_method176def vector(self):177"""178Returns the vector representation of the H-representation object.179180OUTPUT:181182A vector of length183:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.ambient_dim` + 1.184185EXAMPLES::186187sage: s = polytopes.cuboctahedron()188sage: v = s.vertex_generator().next()189sage: v190A vertex at (-1/2, -1/2, 0)191sage: v.vector()192(-1/2, -1/2, 0)193sage: v()194(-1/2, -1/2, 0)195sage: type(v())196<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>197"""198return self.polyhedron().Hrepresentation_space()(self._representation_data)199200def is_H(self):201"""202Returns True if the object is part of a H-representation203(inequality or equation).204205EXAMPLES::206207sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])208sage: pH = p.Hrepresentation(0)209sage: pH.is_H()210True211"""212return True213214def is_inequality(self):215"""216Returns True if the object is an inequality of the H-representation.217218EXAMPLES::219220sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])221sage: pH = p.Hrepresentation(0)222sage: pH.is_inequality()223True224"""225return False226227def is_equation(self):228"""229Returns True if the object is an equation of the H-representation.230231EXAMPLES::232233sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]], eqns = [[1,1,-1]])234sage: pH = p.Hrepresentation(0)235sage: pH.is_equation()236True237"""238return False239240@cached_method241def A(self):242r"""243Returns the coefficient vector `A` in `A\vec{x}+b`.244245EXAMPLES::246247sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])248sage: pH = p.Hrepresentation(2)249sage: pH.A()250(1, 0)251"""252return self.polyhedron().ambient_space()(self._representation_data[1:])253254@cached_method255def b(self):256r"""257Returns the constant `b` in `A\vec{x}+b`.258259EXAMPLES::260261sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])262sage: pH = p.Hrepresentation(2)263sage: pH.b()2640265"""266return self._representation_data[0]267268def neighbors(self):269"""270Iterate over the adjacent facets (i.e. inequalities/equations)271272EXAMPLES::273274sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],275... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])276sage: pH = p.Hrepresentation(0)277sage: a = list(pH.neighbors())278sage: a[0]279An inequality (0, -1, 0) x + 1 >= 0280sage: list(a[0])281[1, 0, -1, 0]282"""283adjacency_matrix = self.polyhedron().facet_adjacency_matrix()284for x in self.polyhedron().Hrep_generator():285if adjacency_matrix[self.index(), x.index()] == 1:286yield x287288def adjacent(self):289"""290Alias for neighbors().291292TESTS::293294sage: p = Polyhedron(ieqs = [[0,0,0,2],[0,0,1,0,],[0,10,0,0],295... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])296sage: pH = p.Hrepresentation(0)297sage: a = list(pH.neighbors())298sage: b = list(pH.adjacent())299sage: a==b300True301"""302return self.neighbors()303304def is_incident(self, Vobj):305"""306Returns whether the incidence matrix element (Vobj,self) == 1307308EXAMPLES::309310sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],311... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])312sage: pH = p.Hrepresentation(0)313sage: pH.is_incident(p.Vrepresentation(1))314True315sage: pH.is_incident(p.Vrepresentation(5))316False317"""318return self.polyhedron().incidence_matrix()[Vobj.index(), self.index()] == 1319320def __mul__(self, Vobj):321"""322Shorthand for ``self.eval(x)``323324EXAMPLES::325326sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],327... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])328sage: pH = p.Hrepresentation(0)329sage: pH*p.Vrepresentation(5)3301331"""332return self.eval(Vobj)333334def eval(self, Vobj):335r"""336Evaluates the left hand side `A\vec{x}+b` on the given337vertex/ray/line.338339NOTES:340341* Evaluating on a vertex returns `A\vec{x}+b`342* Evaluating on a ray returns `A\vec{r}`. Only the sign or343whether it is zero is meaningful.344* Evaluating on a line returns `A\vec{l}`. Only whether it345is zero or not is meaningful.346347EXAMPLES::348349sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])350sage: ineq = triangle.inequality_generator().next()351sage: ineq352An inequality (2, -1) x + 1 >= 0353sage: [ ineq.eval(v) for v in triangle.vertex_generator() ]354[0, 0, 3]355sage: [ ineq * v for v in triangle.vertex_generator() ]356[0, 0, 3]357358If you pass a vector, it is assumed to be the coordinate vector of a point::359360sage: ineq.eval( vector(ZZ, [3,2]) )3615362"""363if is_Vector(Vobj):364return self.A() * Vobj + self.b()365return Vobj.evaluated_on(self)366#return self.A() * Vobj.vector() + self.b()367368def incident(self):369"""370Returns a generator for the incident H-representation objects,371that is, the vertices/rays/lines satisfying the (in)equality.372373EXAMPLES::374375sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])376sage: ineq = triangle.inequality_generator().next()377sage: ineq378An inequality (2, -1) x + 1 >= 0379sage: [ v for v in ineq.incident()]380[A vertex at (-1, -1), A vertex at (0, 1)]381sage: p = Polyhedron(vertices=[[0,0,0],[0,1,0],[0,0,1]], rays=[[1,-1,-1]])382sage: ineq = p.Hrepresentation(2)383sage: ineq384An inequality (1, 0, 1) x + 0 >= 0385sage: [ x for x in ineq.incident() ]386[A vertex at (0, 0, 0),387A vertex at (0, 1, 0),388A ray in the direction (1, -1, -1)]389"""390incidence_matrix = self.polyhedron().incidence_matrix()391for V in self.polyhedron().Vrep_generator():392if incidence_matrix[V.index(), self.index()] == 1:393yield V394395396class Inequality(Hrepresentation):397"""398A linear inequality (supporting hyperplane) of the399polyhedron. Inherits from ``Hrepresentation``.400"""401def __init__(self, polyhedron, data):402"""403A linear inequality (supporting hyperplane) of the404polyhedron. Inherits from ``Hrepresentation``.405406TESTS::407408sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])409sage: a = p.inequality_generator().next()410sage: a411An inequality (-1, 1, 0) x + 0 >= 0412sage: TestSuite(a).run(skip='_test_pickling')413"""414super(Inequality, self).__init__(polyhedron, data)415416417def type(self):418r"""419Returns the type (equation/inequality/vertex/ray/line) as an420integer.421422OUTPUT:423424Integer. One of ``PolyhedronRepresentation.INEQUALITY``,425``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.426427EXAMPLES::428429sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])430sage: repr_obj = p.inequality_generator().next()431sage: repr_obj.type()4320433sage: repr_obj.type() == repr_obj.INEQUALITY434True435sage: repr_obj.type() == repr_obj.EQUATION436False437sage: repr_obj.type() == repr_obj.VERTEX438False439sage: repr_obj.type() == repr_obj.RAY440False441sage: repr_obj.type() == repr_obj.LINE442False443"""444return self.INEQUALITY445446447def is_inequality(self):448"""449Returns True since this is, by construction, an inequality.450451EXAMPLES::452453sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])454sage: a = p.inequality_generator().next()455sage: a.is_inequality()456True457"""458return True459460def _repr_(self):461"""462The string representation of the inequality.463464EXAMPLES::465466sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])467sage: a = p.inequality_generator().next()468sage: a._repr_()469'An inequality (-1, 1, 0) x + 0 >= 0'470sage: Polyhedron(ieqs=[(1,-1),(-1,2)]).Hrepresentation()471(An inequality (-1) x + 1 >= 0, An inequality (2) x - 1 >= 0)472sage: Polyhedron(eqns=[(1,0)]).Hrepresentation()473(An equation -1 == 0,)474sage: Polyhedron(eqns=[(-1,0)]).Hrepresentation()475(An equation -1 == 0,)476"""477s = 'An inequality '478have_A = not self.A().is_zero()479if have_A:480s += repr(self.A()) + ' x '481if self.b()>=0:482if have_A:483s += '+'484else:485s += '-'486if have_A:487s += ' '488s += repr(abs(self.b())) + ' >= 0'489return s490491def contains(self, Vobj):492"""493Tests whether the halfspace (including its boundary) defined494by the inequality contains the given vertex/ray/line.495496EXAMPLES::497498sage: p = polytopes.cross_polytope(3)499sage: i1 = p.inequality_generator().next()500sage: [i1.contains(q) for q in p.vertex_generator()]501[True, True, True, True, True, True]502sage: p2 = 3*polytopes.n_cube(3)503sage: [i1.contains(q) for q in p2.vertex_generator()]504[True, False, False, False, True, True, True, False]505"""506try:507if Vobj.is_vector(): # assume we were passed a point508return self.polyhedron()._is_nonneg( self.eval(Vobj) )509except AttributeError:510pass511512if Vobj.is_line():513return self.polyhedron()._is_zero( self.eval(Vobj) )514else:515return self.polyhedron()._is_nonneg( self.eval(Vobj) )516517def interior_contains(self, Vobj):518"""519Tests whether the interior of the halfspace (excluding its520boundary) defined by the inequality contains the given521vertex/ray/line.522523EXAMPLES::524525sage: p = polytopes.cross_polytope(3)526sage: i1 = p.inequality_generator().next()527sage: [i1.interior_contains(q) for q in p.vertex_generator()]528[False, True, True, False, False, True]529sage: p2 = 3*polytopes.n_cube(3)530sage: [i1.interior_contains(q) for q in p2.vertex_generator()]531[True, False, False, False, True, True, True, False]532533If you pass a vector, it is assumed to be the coordinate vector of a point::534535sage: P = Polyhedron(vertices=[[1,1],[1,-1],[-1,1],[-1,-1]])536sage: p = vector(ZZ, [1,0] )537sage: [ ieq.interior_contains(p) for ieq in P.inequality_generator() ]538[True, True, False, True]539"""540try:541if Vobj.is_vector(): # assume we were passed a point542return self.polyhedron()._is_positive( self.eval(Vobj) )543except AttributeError:544pass545546if Vobj.is_line():547return self.polyhedron()._is_zero( self.eval(Vobj) )548elif Vobj.is_vertex():549return self.polyhedron()._is_positive( self.eval(Vobj) )550else: # Vobj.is_ray()551return self.polyhedron()._is_nonneg( self.eval(Vobj) )552553554class Equation(Hrepresentation):555"""556A linear equation of the polyhedron. That is, the polyhedron is557strictly smaller-dimensional than the ambient space, and contained558in this hyperplane. Inherits from ``Hrepresentation``.559"""560def __init__(self, polyhedron, data):561"""562Initializes an equation object.563564TESTS::565566sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])567sage: a = p.equation_generator().next()568sage: a569An equation (0, 0, 1) x + 0 == 0570sage: TestSuite(a).run(skip='_test_pickling')571"""572super(Equation, self).__init__(polyhedron, data)573574575def type(self):576r"""577Returns the type (equation/inequality/vertex/ray/line) as an578integer.579580OUTPUT:581582Integer. One of ``PolyhedronRepresentation.INEQUALITY``,583``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.584585EXAMPLES::586587sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])588sage: repr_obj = p.equation_generator().next()589sage: repr_obj.type()5901591sage: repr_obj.type() == repr_obj.INEQUALITY592False593sage: repr_obj.type() == repr_obj.EQUATION594True595sage: repr_obj.type() == repr_obj.VERTEX596False597sage: repr_obj.type() == repr_obj.RAY598False599sage: repr_obj.type() == repr_obj.LINE600False601"""602return self.EQUATION603604605def is_equation(self):606"""607Tests if this object is an equation. By construction, it must be.608609TESTS::610611sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])612sage: a = p.equation_generator().next()613sage: a.is_equation()614True615"""616return True617618def _repr_(self):619"""620A string representation of this object.621622TESTS::623624sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])625sage: a = p.equation_generator().next()626sage: a._repr_()627'An equation (0, 0, 1) x + 0 == 0'628sage: Polyhedron().Hrepresentation(0)629An equation -1 == 0630"""631s = 'An equation '632have_A = not self.A().is_zero()633if have_A:634s += repr(self.A()) + ' x '635if self.b()>=0:636if have_A:637s += '+'638else:639s += '-'640if have_A:641s += ' '642s += repr(abs(self.b())) + ' == 0'643return s644645def contains(self, Vobj):646"""647Tests whether the hyperplane defined by the equation contains648the given vertex/ray/line.649650EXAMPLES::651652sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])653sage: v = p.vertex_generator().next()654sage: v655A vertex at (0, 0, 0)656sage: a = p.equation_generator().next()657sage: a658An equation (0, 0, 1) x + 0 == 0659sage: a.contains(v)660True661"""662return self.polyhedron()._is_zero( self.eval(Vobj) )663664def interior_contains(self, Vobj):665"""666Tests whether the interior of the halfspace (excluding its667boundary) defined by the inequality contains the given668vertex/ray/line.669670NOTE:671672Returns False for any equation.673674EXAMPLES::675676sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])677sage: v = p.vertex_generator().next()678sage: v679A vertex at (0, 0, 0)680sage: a = p.equation_generator().next()681sage: a682An equation (0, 0, 1) x + 0 == 0683sage: a.interior_contains(v)684False685"""686return False687688689class Vrepresentation(PolyhedronRepresentation):690"""691The base class for V-representation objects of a692polyhedron. Inherits from ``PolyhedronRepresentation``.693"""694def __init__(self, polyhedron, data):695"""696Initialization function for the vertex representation.697698TESTS::699700sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])701sage: from sage.geometry.polyhedron.representation import Vrepresentation702sage: p._Vrepresentation = Sequence([])703sage: vr = Vrepresentation(p,[1,2,3,4])704sage: vr.__init__(p,[1,2,3,5])705sage: vr.vector()706(1, 2, 3, 5)707sage: TestSuite(vr).run(skip='_test_pickling')708"""709if len(data) != polyhedron.ambient_dim():710raise ValueError, \711'V-representation data requires a list of length ambient_dim'712super(Vrepresentation, self).__init__(polyhedron, data)713self._index = len(polyhedron._Vrepresentation)714polyhedron._Vrepresentation.append(self)715716@cached_method717def vector(self):718"""719Returns the vector representation of the V-representation object.720721OUTPUT:722723A vector of length724:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.ambient_dim`.725726EXAMPLES::727728sage: s = polytopes.cuboctahedron()729sage: v = s.vertex_generator().next()730sage: v731A vertex at (-1/2, -1/2, 0)732sage: v.vector()733(-1/2, -1/2, 0)734sage: v()735(-1/2, -1/2, 0)736sage: type(v())737<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>738"""739return self.polyhedron().Vrepresentation_space()(self._representation_data)740741def is_V(self):742"""743Returns True if the object is part of a V-representation744(a vertex, ray, or line).745746EXAMPLES::747748sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]])749sage: v = p.vertex_generator().next()750sage: v.is_V()751True752"""753return True754755def is_vertex(self):756"""757Returns True if the object is a vertex of the V-representation.758This method is over-ridden by the corresponding method in the759derived class Vertex.760761EXAMPLES::762763sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]])764sage: v = p.vertex_generator().next()765sage: v.is_vertex()766True767sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])768sage: r1 = p.ray_generator().next()769sage: r1.is_vertex()770False771"""772return False773774def is_ray(self):775"""776Returns True if the object is a ray of the V-representation.777This method is over-ridden by the corresponding method in the778derived class Ray.779780EXAMPLES::781782sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])783sage: r1 = p.ray_generator().next()784sage: r1.is_ray()785True786sage: v1 = p.vertex_generator().next()787sage: v1788A vertex at (-1, -1, 0, -1)789sage: v1.is_ray()790False791"""792return False793794def is_line(self):795"""796Returns True if the object is a line of the V-representation.797This method is over-ridden by the corresponding method in the798derived class Line.799800EXAMPLES::801802sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])803sage: line1 = p.line_generator().next()804sage: line1.is_line()805True806sage: v1 = p.vertex_generator().next()807sage: v1.is_line()808False809"""810return False811812def neighbors(self):813"""814Returns a generator for the adjacent vertices/rays/lines.815816EXAMPLES::817818sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]])819sage: v = p.vertex_generator().next()820sage: v.neighbors().next()821A vertex at (0, 3)822"""823adjacency_matrix = self.polyhedron().vertex_adjacency_matrix()824for x in self.polyhedron().Vrep_generator():825if adjacency_matrix[self.index(), x.index()] == 1:826yield x827828def adjacent(self):829"""830Alias for neighbors().831832TESTS::833834sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]])835sage: v = p.vertex_generator().next()836sage: a = v.neighbors().next()837sage: b = v.adjacent().next()838sage: a==b839True840"""841return self.neighbors()842843def is_incident(self, Hobj):844"""845Returns whether the incidence matrix element (self,Hobj) == 1846847EXAMPLES::848849sage: p = polytopes.n_cube(3)850sage: h1 = p.inequality_generator().next()851sage: h1852An inequality (0, 0, -1) x + 1 >= 0853sage: v1 = p.vertex_generator().next()854sage: v1855A vertex at (-1, -1, -1)856sage: v1.is_incident(h1)857False858"""859return self.polyhedron().incidence_matrix()[self.index(), Hobj.index()] == 1860861def __mul__(self, Hobj):862"""863Shorthand for self.evaluated_on(Hobj)864865TESTS::866867sage: p = polytopes.n_cube(3)868sage: h1 = p.inequality_generator().next()869sage: v1 = p.vertex_generator().next()870sage: v1.__mul__(h1)8712872"""873return self.evaluated_on(Hobj)874875def incident(self):876"""877Returns a generator for the equations/inequalities that are satisfied on the given878vertex/ray/line.879880EXAMPLES::881882sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])883sage: ineq = triangle.inequality_generator().next()884sage: ineq885An inequality (2, -1) x + 1 >= 0886sage: [ v for v in ineq.incident()]887[A vertex at (-1, -1), A vertex at (0, 1)]888sage: p = Polyhedron(vertices=[[0,0,0],[0,1,0],[0,0,1]], rays=[[1,-1,-1]])889sage: ineq = p.Hrepresentation(2)890sage: ineq891An inequality (1, 0, 1) x + 0 >= 0892sage: [ x for x in ineq.incident() ]893[A vertex at (0, 0, 0),894A vertex at (0, 1, 0),895A ray in the direction (1, -1, -1)]896"""897incidence_matrix = self.polyhedron().incidence_matrix()898for H in self.polyhedron().Hrep_generator():899if incidence_matrix[self.index(), H.index()] == 1:900yield H901902903class Vertex(Vrepresentation):904"""905A vertex of the polyhedron. Inherits from ``Vrepresentation``.906"""907def __init__(self, polyhedron, data):908"""909Initializes the vertex object.910911TESTS::912913sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])914sage: v1 = p.vertex_generator().next()915sage: v1916A vertex at (1, 0)917sage: TestSuite(v1).run(skip='_test_pickling')918"""919super(Vertex, self).__init__(polyhedron, data)920921922def type(self):923r"""924Returns the type (equation/inequality/vertex/ray/line) as an925integer.926927OUTPUT:928929Integer. One of ``PolyhedronRepresentation.INEQUALITY``,930``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.931932EXAMPLES::933934sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])935sage: repr_obj = p.vertex_generator().next()936sage: repr_obj.type()9372938sage: repr_obj.type() == repr_obj.INEQUALITY939False940sage: repr_obj.type() == repr_obj.EQUATION941False942sage: repr_obj.type() == repr_obj.VERTEX943True944sage: repr_obj.type() == repr_obj.RAY945False946sage: repr_obj.type() == repr_obj.LINE947False948"""949return self.VERTEX950951952def is_vertex(self):953"""954Tests if this object is a vertex. By construction it always is.955956EXAMPLES::957958sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])959sage: a = p.vertex_generator().next()960sage: a.is_vertex()961True962"""963return True964965def _repr_(self):966"""967Returns a string representation of the vertex.968969OUTPUT:970971String.972973TESTS::974975sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])976sage: v = p.vertex_generator().next()977sage: v.__repr__()978'A vertex at (1, 0)'979"""980return 'A vertex at ' + repr(self.vector());981982def evaluated_on(self, Hobj):983r"""984Returns `A\vec{x}+b`985986EXAMPLES::987988sage: p = polytopes.n_cube(3)989sage: v = p.vertex_generator().next()990sage: h = p.inequality_generator().next()991sage: v992A vertex at (-1, -1, -1)993sage: h994An inequality (0, 0, -1) x + 1 >= 0995sage: v.evaluated_on(h)9962997"""998return Hobj.A() * self.vector() + Hobj.b()9991000@cached_method1001def is_integral(self):1002r"""1003Return whether the coordinates of the vertex are all integral.10041005OUTPUT:10061007Boolean.10081009EXAMPLES::10101011sage: p = Polyhedron([(1/2,3,5), (0,0,0), (2,3,7)])1012sage: [ v.is_integral() for v in p.vertex_generator() ]1013[True, False, True]1014"""1015return all(x in ZZ for x in self._representation_data)101610171018class Ray(Vrepresentation):1019"""1020A ray of the polyhedron. Inherits from ``Vrepresentation``.1021"""1022def __init__(self, polyhedron, data):1023"""1024Initializes a ray object.10251026TESTS::10271028sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1029sage: r1 = p.ray_generator().next()1030sage: r11031A ray in the direction (0, 1)1032sage: TestSuite(r1).run(skip='_test_pickling')1033"""1034super(Ray, self).__init__(polyhedron, data)103510361037def type(self):1038r"""1039Returns the type (equation/inequality/vertex/ray/line) as an1040integer.10411042OUTPUT:10431044Integer. One of ``PolyhedronRepresentation.INEQUALITY``,1045``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.10461047EXAMPLES::10481049sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1050sage: repr_obj = p.ray_generator().next()1051sage: repr_obj.type()105231053sage: repr_obj.type() == repr_obj.INEQUALITY1054False1055sage: repr_obj.type() == repr_obj.EQUATION1056False1057sage: repr_obj.type() == repr_obj.VERTEX1058False1059sage: repr_obj.type() == repr_obj.RAY1060True1061sage: repr_obj.type() == repr_obj.LINE1062False1063"""1064return self.RAY106510661067def is_ray(self):1068"""1069Tests if this object is a ray. Always True by construction.10701071EXAMPLES::10721073sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1074sage: a = p.ray_generator().next()1075sage: a.is_ray()1076True1077"""1078return True10791080def _repr_(self):1081"""1082A string representation of the ray.10831084TESTS::10851086sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1087sage: a = p.ray_generator().next()1088sage: a._repr_()1089'A ray in the direction (0, 1)'1090"""1091return 'A ray in the direction ' + repr(self.vector());10921093def evaluated_on(self, Hobj):1094r"""1095Returns `A\vec{r}`10961097EXAMPLES::10981099sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1100sage: a = p.ray_generator().next()1101sage: h = p.inequality_generator().next()1102sage: a.evaluated_on(h)110301104"""1105return Hobj.A() * self.vector()110611071108class Line(Vrepresentation):1109r"""1110A line (Minkowski summand `\simeq\RR`) of the1111polyhedron. Inherits from ``Vrepresentation``.1112"""1113def __init__(self, polyhedron, data):1114"""1115Initializes the line object.11161117TESTS::11181119sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1120sage: a = p.line_generator().next()1121sage: p._Vrepresentation = Sequence([])1122sage: a.__init__(p,[1,2,3])1123sage: a1124A line in the direction (1, 2, 3)1125sage: TestSuite(a).run(skip='_test_pickling')1126"""1127super(Line, self).__init__(polyhedron, data)112811291130def type(self):1131r"""1132Returns the type (equation/inequality/vertex/ray/line) as an1133integer.11341135OUTPUT:11361137Integer. One of ``PolyhedronRepresentation.INEQUALITY``,1138``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.11391140EXAMPLES::11411142sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1143sage: repr_obj = p.line_generator().next()1144sage: repr_obj.type()114541146sage: repr_obj.type() == repr_obj.INEQUALITY1147False1148sage: repr_obj.type() == repr_obj.EQUATION1149False1150sage: repr_obj.type() == repr_obj.VERTEX1151False1152sage: repr_obj.type() == repr_obj.RAY1153False1154sage: repr_obj.type() == repr_obj.LINE1155True1156"""1157return self.LINE115811591160def is_line(self):1161"""1162Tests if the object is a line. By construction it must be.11631164TESTS::11651166sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1167sage: a = p.line_generator().next()1168sage: a.is_line()1169True1170"""1171return True11721173def _repr_(self):1174"""1175A string representation of the line.11761177TESTS::11781179sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1180sage: a = p.line_generator().next()1181sage: a.__repr__()1182'A line in the direction (0, 1, 0)'1183"""1184return 'A line in the direction ' + repr(self.vector());11851186def evaluated_on(self, Hobj):1187r"""1188Returns `A\vec{\ell}`11891190EXAMPLES::11911192sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1193sage: a = p.line_generator().next()1194sage: h = p.inequality_generator().next()1195sage: a.evaluated_on(h)119601197"""1198return Hobj.A() * self.vector()11991200120112021203