Path: blob/master/src/sage/geometry/polyhedron/representation.py
8817 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 vector18192021#########################################################################22# PolyhedronRepresentation23# / \24# / \25# Hrepresentation Vrepresentation26# / \ / | \27# / \ / | \28# Inequality Equation Vertex Ray Line2930class PolyhedronRepresentation(SageObject):31"""32The internal base class for all representation objects of33``Polyhedron`` (vertices/rays/lines and inequalites/equations)3435.. note::3637You should not (and cannot) instantiate it yourself. You can38only obtain them from a Polyhedron() class.3940TESTS::4142sage: import sage.geometry.polyhedron.representation as P43sage: P.PolyhedronRepresentation()44<class 'sage.geometry.polyhedron.representation.PolyhedronRepresentation'>45"""4647# Numeric values for the output of the type() method48INEQUALITY = 049EQUATION = 150VERTEX = 251RAY = 352LINE = 45354def __len__(self):55"""56Returns the length of the representation data.5758TESTS::5960sage: p = Polyhedron(vertices=[[1,2,3]])61sage: v = p.Vrepresentation(0)62sage: v.__len__()63364"""65return self._vector.degree()6667def __getitem__(self, i):68"""69Supports indexing.7071TESTS::7273sage: p = Polyhedron(vertices=[[1,2,3]])74sage: v = p.Vrepresentation(0)75sage: v.__getitem__(1)76277"""78return self._vector[i]7980def __cmp__(self, other):81"""82Compare two representation objects8384They are equal if and only if they define the same85vertex/ray/line or inequality/equation in the ambient space,86regardless of the polyhedron that they belong to.8788INPUT:8990- ``other`` -- anything.9192OUTPUT:9394One of `-1`, `0`, `+1`. ``True`` if and only if ``other`` represents the same95H-representation object.9697EXAMPLES::9899sage: triangle = Polyhedron([(0,0), (1,0), (0,1)])100sage: ieq = triangle.inequality_generator().next(); ieq101An inequality (1, 0) x + 0 >= 0102sage: ieq == copy(ieq)103True104sage: cmp(ieq, copy(ieq))1050106107sage: cmp(ieq, 'a string')108-1109110sage: square = Polyhedron([(0,0), (1,0), (0,1), (1,1)], base_ring=QQ)111sage: cmp(square.Vrepresentation(0), triangle.Vrepresentation(0))1120113114sage: ieq = square.Hrepresentation(0); ieq.vector()115(0, 1, 0)116sage: abs(cmp(ieq, Polyhedron([(0,1,0)]).Vrepresentation(0)))1171118"""119if not isinstance(other, PolyhedronRepresentation):120return -1121type_cmp = cmp(type(self), type(other))122if (type_cmp != 0): return type_cmp123return cmp(self._vector, other._vector)124125def vector(self, base_ring=None):126"""127Returns the vector representation of the H/V-representation object.128129INPUT:130131- ``base_ring`` -- the base ring of the vector.132133OUTPUT:134135For a V-representation object, a vector of length136:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.ambient_dim`. For137a H-representation object, a vector of length138:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.ambient_dim`139+ 1.140141EXAMPLES::142143sage: s = polytopes.cuboctahedron()144sage: v = s.vertex_generator().next()145sage: v146A vertex at (-1/2, -1/2, 0)147sage: v.vector()148(-1/2, -1/2, 0)149sage: v()150(-1/2, -1/2, 0)151sage: type(v())152<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>153154Conversion to a different base ring can be forced with the optional argument::155156sage: v.vector(RDF)157(-0.5, -0.5, 0.0)158sage: vector(RDF, v)159(-0.5, -0.5, 0.0)160"""161if (base_ring is None) or (base_ring is self._base_ring):162return self._vector163else:164return vector(base_ring, self._vector)165166_vector_ = vector167168def polyhedron(self):169"""170Returns the underlying polyhedron.171172TESTS::173174sage: p = Polyhedron(vertices=[[1,2,3]])175sage: v = p.Vrepresentation(0)176sage: v.polyhedron()177A 0-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex178"""179return self._polyhedron180181def __call__(self):182"""183Returns the vector representation of the representation184object. Shorthand for the vector() method.185186TESTS::187188sage: p = Polyhedron(vertices=[[1,2,3]])189sage: v = p.Vrepresentation(0)190sage: v.__call__()191(1, 2, 3)192"""193return self._vector194195def index(self):196"""197Returns an arbitrary but fixed number according to the internal198storage order.199200NOTES:201202H-representation and V-representation objects are enumerated203independently. That is, amongst all vertices/rays/lines there204will be one with ``index()==0``, and amongs all205inequalities/equations there will be one with ``index()==0``,206unless the polyhedron is empty or spans the whole space.207208EXAMPLES::209210sage: s = Polyhedron(vertices=[[1],[-1]])211sage: first_vertex = s.vertex_generator().next()212sage: first_vertex.index()2130214sage: first_vertex == s.Vrepresentation(0)215True216"""217return self._index218219def __add__(self, coordinate_list):220"""221Return the coordinates concatenated with ``coordinate_list``.222223INPUT:224225- ``coordinate_list`` -- a list.226227OUTPUT:228229The coordinates of ``self`` concatenated with ``coordinate_list``.230231EXAMPLES::232233sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])234sage: v = p.Vrepresentation(0); v235A vertex at (1, 0)236sage: v + [4,5]237[1, 0, 4, 5]238"""239if not isinstance(coordinate_list, list):240raise TypeError('Can only concatenate with a list of coordinates')241return list(self) + coordinate_list242243def __radd__(self, coordinate_list):244"""245Return ``coordinate_list`` concatenated with the coordinates.246247INPUT:248249- ``coordinate_list`` -- a list.250251OUTPUT:252253``coordinate_list`` concatenated with the coordinates of ``self``.254255EXAMPLES::256257sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])258sage: v = p.Vrepresentation(0); v259A vertex at (1, 0)260sage: [4,5] + v261[4, 5, 1, 0]262"""263if not isinstance(coordinate_list, list):264raise TypeError('Can only concatenate with a list of coordinates')265return coordinate_list + list(self)266267def count(self, i):268"""269Count the number of occurrences of ``i`` in the coordinates.270271INPUT:272273- ``i`` -- Anything.274275OUTPUT:276277Integer. The number of occurrences of ``i`` in the coordinates.278279EXAMPLES::280281sage: p = Polyhedron(vertices=[(0,1,1,2,1)])282sage: v = p.Vrepresentation(0); v283A vertex at (0, 1, 1, 2, 1)284sage: v.count(1)2853286"""287return sum([1 for j in self if i==j])288289290class Hrepresentation(PolyhedronRepresentation):291"""292The internal base class for H-representation objects of293a polyhedron. Inherits from ``PolyhedronRepresentation``.294"""295296def __init__(self, polyhedron_parent):297"""298Initializes the PolyhedronRepresentation object.299300TESTS::301302sage: from sage.geometry.polyhedron.representation import Hrepresentation303sage: pr = Hrepresentation(Polyhedron(vertices = [[1,2,3]]).parent())304sage: tuple(pr)305(0, 0, 0, 0)306sage: TestSuite(pr).run(skip='_test_pickling')307"""308self._polyhedron_parent = polyhedron_parent309self._base_ring = polyhedron_parent.base_ring()310self._vector = polyhedron_parent.Hrepresentation_space()(0)311self._A = polyhedron_parent.ambient_space()(0)312self._b = polyhedron_parent.base_ring()(0)313self._index = 0314315def _set_data(self, polyhedron, data):316"""317Initialization function.318319The H/V-representation objects are kept in a pool, and this320function is used to reassign new values to already existing321(but unused) objects. You must not call this function on322objects that are in normal use.323324INPUT:325326- ``polyhedron`` -- the new polyhedron.327328- ``data`` -- the H-representation data.329330TESTS::331332sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])333sage: pH = p.Hrepresentation(0) # indirect doctest334sage: TestSuite(pH).run(skip='_test_pickling')335"""336assert polyhedron.parent() is self._polyhedron_parent337if len(data) != self._vector.degree():338raise ValueError, \339'H-representation data requires a list of length ambient_dim+1'340341for i in range(0, self._vector.degree()):342self._vector.set(i, data[i])343for i in range(0, self._A.degree()):344self._A.set(i, data[i+1])345self._b = self._base_ring(data[0])346347self._index = len(polyhedron._Hrepresentation)348polyhedron._Hrepresentation.append(self)349self._polyhedron = polyhedron350351def is_H(self):352"""353Returns True if the object is part of a H-representation354(inequality or equation).355356EXAMPLES::357358sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])359sage: pH = p.Hrepresentation(0)360sage: pH.is_H()361True362"""363return True364365def is_inequality(self):366"""367Returns True if the object is an inequality of the H-representation.368369EXAMPLES::370371sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])372sage: pH = p.Hrepresentation(0)373sage: pH.is_inequality()374True375"""376return False377378def is_equation(self):379"""380Returns True if the object is an equation of the H-representation.381382EXAMPLES::383384sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]], eqns = [[1,1,-1]])385sage: pH = p.Hrepresentation(0)386sage: pH.is_equation()387True388"""389return False390391def A(self):392r"""393Returns the coefficient vector `A` in `A\vec{x}+b`.394395EXAMPLES::396397sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])398sage: pH = p.Hrepresentation(2)399sage: pH.A()400(1, 0)401"""402return self._A403404def b(self):405r"""406Returns the constant `b` in `A\vec{x}+b`.407408EXAMPLES::409410sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])411sage: pH = p.Hrepresentation(2)412sage: pH.b()4130414"""415return self._b416417def neighbors(self):418"""419Iterate over the adjacent facets (i.e. inequalities/equations)420421EXAMPLES::422423sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],424... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])425sage: pH = p.Hrepresentation(0)426sage: a = list(pH.neighbors())427sage: a[0]428An inequality (0, -1, 0) x + 1 >= 0429sage: list(a[0])430[1, 0, -1, 0]431"""432adjacency_matrix = self.polyhedron().facet_adjacency_matrix()433for x in self.polyhedron().Hrep_generator():434if adjacency_matrix[self.index(), x.index()] == 1:435yield x436437def adjacent(self):438"""439Alias for neighbors().440441TESTS::442443sage: p = Polyhedron(ieqs = [[0,0,0,2],[0,0,1,0,],[0,10,0,0],444... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])445sage: pH = p.Hrepresentation(0)446sage: a = list(pH.neighbors())447sage: b = list(pH.adjacent())448sage: a==b449True450"""451return self.neighbors()452453def is_incident(self, Vobj):454"""455Returns whether the incidence matrix element (Vobj,self) == 1456457EXAMPLES::458459sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],460... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])461sage: pH = p.Hrepresentation(0)462sage: pH.is_incident(p.Vrepresentation(1))463True464sage: pH.is_incident(p.Vrepresentation(5))465False466"""467return self.polyhedron().incidence_matrix()[Vobj.index(), self.index()] == 1468469def __mul__(self, Vobj):470"""471Shorthand for ``self.eval(x)``472473EXAMPLES::474475sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],476... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])477sage: pH = p.Hrepresentation(0)478sage: pH*p.Vrepresentation(5)4791480"""481return self.eval(Vobj)482483def eval(self, Vobj):484r"""485Evaluates the left hand side `A\vec{x}+b` on the given486vertex/ray/line.487488NOTES:489490* Evaluating on a vertex returns `A\vec{x}+b`491* Evaluating on a ray returns `A\vec{r}`. Only the sign or492whether it is zero is meaningful.493* Evaluating on a line returns `A\vec{l}`. Only whether it494is zero or not is meaningful.495496EXAMPLES::497498sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])499sage: ineq = triangle.inequality_generator().next()500sage: ineq501An inequality (2, -1) x + 1 >= 0502sage: [ ineq.eval(v) for v in triangle.vertex_generator() ]503[0, 0, 3]504sage: [ ineq * v for v in triangle.vertex_generator() ]505[0, 0, 3]506507If you pass a vector, it is assumed to be the coordinate vector of a point::508509sage: ineq.eval( vector(ZZ, [3,2]) )5105511"""512if is_Vector(Vobj):513return self.A() * Vobj + self.b()514return Vobj.evaluated_on(self)515516def incident(self):517"""518Returns a generator for the incident H-representation objects,519that is, the vertices/rays/lines satisfying the (in)equality.520521EXAMPLES::522523sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])524sage: ineq = triangle.inequality_generator().next()525sage: ineq526An inequality (2, -1) x + 1 >= 0527sage: [ v for v in ineq.incident()]528[A vertex at (-1, -1), A vertex at (0, 1)]529sage: p = Polyhedron(vertices=[[0,0,0],[0,1,0],[0,0,1]], rays=[[1,-1,-1]])530sage: ineq = p.Hrepresentation(2)531sage: ineq532An inequality (1, 0, 1) x + 0 >= 0533sage: [ x for x in ineq.incident() ]534[A vertex at (0, 0, 0),535A vertex at (0, 1, 0),536A ray in the direction (1, -1, -1)]537"""538incidence_matrix = self.polyhedron().incidence_matrix()539for V in self.polyhedron().Vrep_generator():540if incidence_matrix[V.index(), self.index()] == 1:541yield V542543544class Inequality(Hrepresentation):545"""546A linear inequality (supporting hyperplane) of the547polyhedron. Inherits from ``Hrepresentation``.548"""549550def type(self):551r"""552Returns the type (equation/inequality/vertex/ray/line) as an553integer.554555OUTPUT:556557Integer. One of ``PolyhedronRepresentation.INEQUALITY``,558``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.559560EXAMPLES::561562sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])563sage: repr_obj = p.inequality_generator().next()564sage: repr_obj.type()5650566sage: repr_obj.type() == repr_obj.INEQUALITY567True568sage: repr_obj.type() == repr_obj.EQUATION569False570sage: repr_obj.type() == repr_obj.VERTEX571False572sage: repr_obj.type() == repr_obj.RAY573False574sage: repr_obj.type() == repr_obj.LINE575False576"""577return self.INEQUALITY578579580def is_inequality(self):581"""582Returns True since this is, by construction, an inequality.583584EXAMPLES::585586sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])587sage: a = p.inequality_generator().next()588sage: a.is_inequality()589True590"""591return True592593def _repr_(self):594"""595The string representation of the inequality.596597EXAMPLES::598599sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])600sage: a = p.inequality_generator().next()601sage: a._repr_()602'An inequality (-1, 1, 0) x + 0 >= 0'603sage: Polyhedron(ieqs=[(1,-1),(-1,2)]).Hrepresentation()604(An inequality (-1) x + 1 >= 0, An inequality (2) x - 1 >= 0)605sage: Polyhedron(eqns=[(1,0)]).Hrepresentation()606(An equation -1 == 0,)607sage: Polyhedron(eqns=[(-1,0)]).Hrepresentation()608(An equation -1 == 0,)609"""610s = 'An inequality '611have_A = not self.A().is_zero()612if have_A:613s += repr(self.A()) + ' x '614if self.b()>=0:615if have_A:616s += '+'617else:618s += '-'619if have_A:620s += ' '621s += repr(abs(self.b())) + ' >= 0'622return s623624def contains(self, Vobj):625"""626Tests whether the halfspace (including its boundary) defined627by the inequality contains the given vertex/ray/line.628629EXAMPLES::630631sage: p = polytopes.cross_polytope(3)632sage: i1 = p.inequality_generator().next()633sage: [i1.contains(q) for q in p.vertex_generator()]634[True, True, True, True, True, True]635sage: p2 = 3*polytopes.n_cube(3)636sage: [i1.contains(q) for q in p2.vertex_generator()]637[True, False, False, False, True, True, True, False]638"""639try:640if Vobj.is_vector(): # assume we were passed a point641return self.polyhedron()._is_nonneg( self.eval(Vobj) )642except AttributeError:643pass644645if Vobj.is_line():646return self.polyhedron()._is_zero( self.eval(Vobj) )647else:648return self.polyhedron()._is_nonneg( self.eval(Vobj) )649650def interior_contains(self, Vobj):651"""652Tests whether the interior of the halfspace (excluding its653boundary) defined by the inequality contains the given654vertex/ray/line.655656EXAMPLES::657658sage: p = polytopes.cross_polytope(3)659sage: i1 = p.inequality_generator().next()660sage: [i1.interior_contains(q) for q in p.vertex_generator()]661[False, True, True, False, False, True]662sage: p2 = 3*polytopes.n_cube(3)663sage: [i1.interior_contains(q) for q in p2.vertex_generator()]664[True, False, False, False, True, True, True, False]665666If you pass a vector, it is assumed to be the coordinate vector of a point::667668sage: P = Polyhedron(vertices=[[1,1],[1,-1],[-1,1],[-1,-1]])669sage: p = vector(ZZ, [1,0] )670sage: [ ieq.interior_contains(p) for ieq in P.inequality_generator() ]671[True, True, False, True]672"""673try:674if Vobj.is_vector(): # assume we were passed a point675return self.polyhedron()._is_positive( self.eval(Vobj) )676except AttributeError:677pass678679if Vobj.is_line():680return self.polyhedron()._is_zero( self.eval(Vobj) )681elif Vobj.is_vertex():682return self.polyhedron()._is_positive( self.eval(Vobj) )683else: # Vobj.is_ray()684return self.polyhedron()._is_nonneg( self.eval(Vobj) )685686687class Equation(Hrepresentation):688"""689A linear equation of the polyhedron. That is, the polyhedron is690strictly smaller-dimensional than the ambient space, and contained691in this hyperplane. Inherits from ``Hrepresentation``.692"""693694def type(self):695r"""696Returns the type (equation/inequality/vertex/ray/line) as an697integer.698699OUTPUT:700701Integer. One of ``PolyhedronRepresentation.INEQUALITY``,702``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.703704EXAMPLES::705706sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])707sage: repr_obj = p.equation_generator().next()708sage: repr_obj.type()7091710sage: repr_obj.type() == repr_obj.INEQUALITY711False712sage: repr_obj.type() == repr_obj.EQUATION713True714sage: repr_obj.type() == repr_obj.VERTEX715False716sage: repr_obj.type() == repr_obj.RAY717False718sage: repr_obj.type() == repr_obj.LINE719False720"""721return self.EQUATION722723724def is_equation(self):725"""726Tests if this object is an equation. By construction, it must be.727728TESTS::729730sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])731sage: a = p.equation_generator().next()732sage: a.is_equation()733True734"""735return True736737def _repr_(self):738"""739A string representation of this object.740741TESTS::742743sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])744sage: a = p.equation_generator().next()745sage: a._repr_()746'An equation (0, 0, 1) x + 0 == 0'747sage: Polyhedron().Hrepresentation(0)748An equation -1 == 0749"""750s = 'An equation '751have_A = not self.A().is_zero()752if have_A:753s += repr(self.A()) + ' x '754if self.b()>=0:755if have_A:756s += '+'757else:758s += '-'759if have_A:760s += ' '761s += repr(abs(self.b())) + ' == 0'762return s763764def contains(self, Vobj):765"""766Tests whether the hyperplane defined by the equation contains767the given vertex/ray/line.768769EXAMPLES::770771sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])772sage: v = p.vertex_generator().next()773sage: v774A vertex at (0, 0, 0)775sage: a = p.equation_generator().next()776sage: a777An equation (0, 0, 1) x + 0 == 0778sage: a.contains(v)779True780"""781return self.polyhedron()._is_zero( self.eval(Vobj) )782783def interior_contains(self, Vobj):784"""785Tests whether the interior of the halfspace (excluding its786boundary) defined by the inequality contains the given787vertex/ray/line.788789NOTE:790791Returns False for any equation.792793EXAMPLES::794795sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])796sage: v = p.vertex_generator().next()797sage: v798A vertex at (0, 0, 0)799sage: a = p.equation_generator().next()800sage: a801An equation (0, 0, 1) x + 0 == 0802sage: a.interior_contains(v)803False804"""805return False806807808class Vrepresentation(PolyhedronRepresentation):809"""810The base class for V-representation objects of a811polyhedron. Inherits from ``PolyhedronRepresentation``.812"""813814def __init__(self, polyhedron_parent):815"""816Initializes the PolyhedronRepresentation object.817818TESTS::819820sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])821sage: a = p.inequality_generator().next()822sage: a823An inequality (-1, 1, 0) x + 0 >= 0824sage: TestSuite(a).run(skip='_test_pickling')825"""826self._polyhedron_parent = polyhedron_parent827self._base_ring = polyhedron_parent.base_ring()828self._vector = polyhedron_parent.Vrepresentation_space()(0)829self._index = 0830831def _set_data(self, polyhedron, data):832"""833Initialization function.834835The H/V-representation objects are kept in a pool, and this836function is used to reassign new values to already existing837(but unused) objects. You must not call this function on838objects that are in normal use.839840INPUT:841842- ``polyhedron`` -- the new polyhedron.843844- ``data`` -- the V-representation data.845846TESTS::847848sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])849sage: pV = p.Vrepresentation(0) # indirect doctest850sage: TestSuite(pV).run(skip='_test_pickling')851"""852assert polyhedron.parent() is self._polyhedron_parent853if len(data) != self._vector.degree():854raise ValueError, \855'V-representation data requires a list of length ambient_dim'856857for i in range(0, self._vector.degree()):858self._vector.set(i, data[i])859860self._index = len(polyhedron._Vrepresentation)861polyhedron._Vrepresentation.append(self)862self._polyhedron = polyhedron863864def is_V(self):865"""866Returns True if the object is part of a V-representation867(a vertex, ray, or line).868869EXAMPLES::870871sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]])872sage: v = p.vertex_generator().next()873sage: v.is_V()874True875"""876return True877878def is_vertex(self):879"""880Returns True if the object is a vertex of the V-representation.881This method is over-ridden by the corresponding method in the882derived class Vertex.883884EXAMPLES::885886sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]])887sage: v = p.vertex_generator().next()888sage: v.is_vertex()889True890sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])891sage: r1 = p.ray_generator().next()892sage: r1.is_vertex()893False894"""895return False896897def is_ray(self):898"""899Returns True if the object is a ray of the V-representation.900This method is over-ridden by the corresponding method in the901derived class Ray.902903EXAMPLES::904905sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])906sage: r1 = p.ray_generator().next()907sage: r1.is_ray()908True909sage: v1 = p.vertex_generator().next()910sage: v1911A vertex at (-1, -1, 0, -1)912sage: v1.is_ray()913False914"""915return False916917def is_line(self):918"""919Returns True if the object is a line of the V-representation.920This method is over-ridden by the corresponding method in the921derived class Line.922923EXAMPLES::924925sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])926sage: line1 = p.line_generator().next()927sage: line1.is_line()928True929sage: v1 = p.vertex_generator().next()930sage: v1.is_line()931False932"""933return False934935def neighbors(self):936"""937Returns a generator for the adjacent vertices/rays/lines.938939EXAMPLES::940941sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]])942sage: v = p.vertex_generator().next()943sage: v.neighbors().next()944A vertex at (0, 3)945"""946adjacency_matrix = self.polyhedron().vertex_adjacency_matrix()947for x in self.polyhedron().Vrep_generator():948if adjacency_matrix[self.index(), x.index()] == 1:949yield x950951def adjacent(self):952"""953Alias for neighbors().954955TESTS::956957sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]])958sage: v = p.vertex_generator().next()959sage: a = v.neighbors().next()960sage: b = v.adjacent().next()961sage: a==b962True963"""964return self.neighbors()965966def is_incident(self, Hobj):967"""968Returns whether the incidence matrix element (self,Hobj) == 1969970EXAMPLES::971972sage: p = polytopes.n_cube(3)973sage: h1 = p.inequality_generator().next()974sage: h1975An inequality (0, 0, -1) x + 1 >= 0976sage: v1 = p.vertex_generator().next()977sage: v1978A vertex at (-1, -1, -1)979sage: v1.is_incident(h1)980False981"""982return self.polyhedron().incidence_matrix()[self.index(), Hobj.index()] == 1983984def __mul__(self, Hobj):985"""986Shorthand for self.evaluated_on(Hobj)987988TESTS::989990sage: p = polytopes.n_cube(3)991sage: h1 = p.inequality_generator().next()992sage: v1 = p.vertex_generator().next()993sage: v1.__mul__(h1)9942995"""996return self.evaluated_on(Hobj)997998def incident(self):999"""1000Returns a generator for the equations/inequalities that are satisfied on the given1001vertex/ray/line.10021003EXAMPLES::10041005sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])1006sage: ineq = triangle.inequality_generator().next()1007sage: ineq1008An inequality (2, -1) x + 1 >= 01009sage: [ v for v in ineq.incident()]1010[A vertex at (-1, -1), A vertex at (0, 1)]1011sage: p = Polyhedron(vertices=[[0,0,0],[0,1,0],[0,0,1]], rays=[[1,-1,-1]])1012sage: ineq = p.Hrepresentation(2)1013sage: ineq1014An inequality (1, 0, 1) x + 0 >= 01015sage: [ x for x in ineq.incident() ]1016[A vertex at (0, 0, 0),1017A vertex at (0, 1, 0),1018A ray in the direction (1, -1, -1)]1019"""1020incidence_matrix = self.polyhedron().incidence_matrix()1021for H in self.polyhedron().Hrep_generator():1022if incidence_matrix[self.index(), H.index()] == 1:1023yield H102410251026class Vertex(Vrepresentation):1027"""1028A vertex of the polyhedron. Inherits from ``Vrepresentation``.1029"""10301031def type(self):1032r"""1033Returns the type (equation/inequality/vertex/ray/line) as an1034integer.10351036OUTPUT:10371038Integer. One of ``PolyhedronRepresentation.INEQUALITY``,1039``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.10401041EXAMPLES::10421043sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])1044sage: repr_obj = p.vertex_generator().next()1045sage: repr_obj.type()104621047sage: repr_obj.type() == repr_obj.INEQUALITY1048False1049sage: repr_obj.type() == repr_obj.EQUATION1050False1051sage: repr_obj.type() == repr_obj.VERTEX1052True1053sage: repr_obj.type() == repr_obj.RAY1054False1055sage: repr_obj.type() == repr_obj.LINE1056False1057"""1058return self.VERTEX105910601061def is_vertex(self):1062"""1063Tests if this object is a vertex. By construction it always is.10641065EXAMPLES::10661067sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1068sage: a = p.vertex_generator().next()1069sage: a.is_vertex()1070True1071"""1072return True10731074def _repr_(self):1075"""1076Returns a string representation of the vertex.10771078OUTPUT:10791080String.10811082TESTS::10831084sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1085sage: v = p.vertex_generator().next()1086sage: v.__repr__()1087'A vertex at (1, 0)'1088"""1089return 'A vertex at ' + repr(self.vector());10901091def evaluated_on(self, Hobj):1092r"""1093Returns `A\vec{x}+b`10941095EXAMPLES::10961097sage: p = polytopes.n_cube(3)1098sage: v = p.vertex_generator().next()1099sage: h = p.inequality_generator().next()1100sage: v1101A vertex at (-1, -1, -1)1102sage: h1103An inequality (0, 0, -1) x + 1 >= 01104sage: v.evaluated_on(h)110521106"""1107return Hobj.A() * self.vector() + Hobj.b()11081109def is_integral(self):1110r"""1111Return whether the coordinates of the vertex are all integral.11121113OUTPUT:11141115Boolean.11161117EXAMPLES::11181119sage: p = Polyhedron([(1/2,3,5), (0,0,0), (2,3,7)])1120sage: [ v.is_integral() for v in p.vertex_generator() ]1121[True, False, True]1122"""1123return (self._base_ring is ZZ) or all(x in ZZ for x in self)112411251126class Ray(Vrepresentation):1127"""1128A ray of the polyhedron. Inherits from ``Vrepresentation``.1129"""11301131def type(self):1132r"""1133Returns the type (equation/inequality/vertex/ray/line) as an1134integer.11351136OUTPUT:11371138Integer. One of ``PolyhedronRepresentation.INEQUALITY``,1139``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.11401141EXAMPLES::11421143sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1144sage: repr_obj = p.ray_generator().next()1145sage: repr_obj.type()114631147sage: repr_obj.type() == repr_obj.INEQUALITY1148False1149sage: repr_obj.type() == repr_obj.EQUATION1150False1151sage: repr_obj.type() == repr_obj.VERTEX1152False1153sage: repr_obj.type() == repr_obj.RAY1154True1155sage: repr_obj.type() == repr_obj.LINE1156False1157"""1158return self.RAY115911601161def is_ray(self):1162"""1163Tests if this object is a ray. Always True by construction.11641165EXAMPLES::11661167sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1168sage: a = p.ray_generator().next()1169sage: a.is_ray()1170True1171"""1172return True11731174def _repr_(self):1175"""1176A string representation of the ray.11771178TESTS::11791180sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1181sage: a = p.ray_generator().next()1182sage: a._repr_()1183'A ray in the direction (0, 1)'1184"""1185return 'A ray in the direction ' + repr(self.vector());11861187def evaluated_on(self, Hobj):1188r"""1189Returns `A\vec{r}`11901191EXAMPLES::11921193sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])1194sage: a = p.ray_generator().next()1195sage: h = p.inequality_generator().next()1196sage: a.evaluated_on(h)119701198"""1199return Hobj.A() * self.vector()120012011202class Line(Vrepresentation):1203r"""1204A line (Minkowski summand `\simeq\RR`) of the1205polyhedron. Inherits from ``Vrepresentation``.1206"""12071208def type(self):1209r"""1210Returns the type (equation/inequality/vertex/ray/line) as an1211integer.12121213OUTPUT:12141215Integer. One of ``PolyhedronRepresentation.INEQUALITY``,1216``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.12171218EXAMPLES::12191220sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1221sage: repr_obj = p.line_generator().next()1222sage: repr_obj.type()122341224sage: repr_obj.type() == repr_obj.INEQUALITY1225False1226sage: repr_obj.type() == repr_obj.EQUATION1227False1228sage: repr_obj.type() == repr_obj.VERTEX1229False1230sage: repr_obj.type() == repr_obj.RAY1231False1232sage: repr_obj.type() == repr_obj.LINE1233True1234"""1235return self.LINE12361237def is_line(self):1238"""1239Tests if the object is a line. By construction it must be.12401241TESTS::12421243sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1244sage: a = p.line_generator().next()1245sage: a.is_line()1246True1247"""1248return True12491250def _repr_(self):1251"""1252A string representation of the line.12531254TESTS::12551256sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1257sage: a = p.line_generator().next()1258sage: a.__repr__()1259'A line in the direction (0, 1, 0)'1260"""1261return 'A line in the direction ' + repr(self.vector());12621263def evaluated_on(self, Hobj):1264r"""1265Returns `A\vec{\ell}`12661267EXAMPLES::12681269sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])1270sage: a = p.line_generator().next()1271sage: h = p.inequality_generator().next()1272sage: a.evaluated_on(h)127301274"""1275return Hobj.A() * self.vector()12761277127812791280