Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/geometry/polyhedron/representation.py
4069 views
1
"""
2
H(yperplane) and V(ertex) representation objects for polyhedra
3
"""
4
5
########################################################################
6
# Copyright (C) 2008 Marshall Hampton <[email protected]>
7
# Copyright (C) 2011 Volker Braun <[email protected]>
8
#
9
# Distributed under the terms of the GNU General Public License (GPL)
10
#
11
# http://www.gnu.org/licenses/
12
########################################################################
13
14
15
from sage.structure.sage_object import SageObject
16
from sage.structure.element import is_Vector
17
from sage.rings.all import QQ, ZZ, RDF
18
from sage.modules.free_module_element import vector
19
from sage.misc.all import cached_method
20
21
22
23
#########################################################################
24
# PolyhedronRepresentation
25
# / \
26
# / \
27
# Hrepresentation Vrepresentation
28
# / \ / | \
29
# / \ / | \
30
# Inequality Equation Vertex Ray Line
31
32
class PolyhedronRepresentation(SageObject):
33
"""
34
The internal base class for all representation objects of
35
``Polyhedron`` (vertices/rays/lines and inequalites/equations)
36
37
.. note::
38
39
You should not (and cannot) instantiate it yourself. You can
40
only obtain them from a Polyhedron() class.
41
42
"""
43
44
# Numeric values for the output of the type() method
45
INEQUALITY = 0
46
EQUATION = 1
47
VERTEX = 2
48
RAY = 3
49
LINE = 4
50
51
def __init__(self, polyhedron, data):
52
"""
53
Initializes the PolyhedronRepresentation object.
54
55
TESTS::
56
57
sage: import sage.geometry.polyhedron.representation as P
58
sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])
59
sage: tuple(pr)
60
(1, 2, 3)
61
sage: TestSuite(pr).run(skip='_test_pickling')
62
"""
63
self._representation_data = tuple(data)
64
self._polyhedron = polyhedron
65
66
def __len__(self):
67
"""
68
Returns the length of the representation data.
69
70
TESTS::
71
72
sage: import sage.geometry.polyhedron.representation as P
73
sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])
74
sage: pr.__len__()
75
3
76
"""
77
return len(self._representation_data)
78
79
def __getitem__(self, i):
80
"""
81
Supports indexing.
82
83
TESTS::
84
85
sage: import sage.geometry.polyhedron.representation as P
86
sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])
87
sage: pr.__getitem__(1)
88
2
89
"""
90
return self._representation_data[i]
91
92
def polyhedron(self):
93
"""
94
Returns the underlying polyhedron.
95
96
TESTS::
97
98
sage: import sage.geometry.polyhedron.representation as P
99
sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])
100
sage: pr.polyhedron()
101
A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex
102
"""
103
return self._polyhedron
104
105
def __call__(self):
106
"""
107
Returns the vector representation of the representation
108
object. Shorthand for the vector() method.
109
110
Note that the vector() method is only implemented in derived
111
classes.
112
113
TESTS::
114
115
sage: import sage.geometry.polyhedron.representation as P
116
sage: pr = Polyhedron(vertices = [[1,2,3]]).Vrepresentation(0)
117
sage: pr.__call__()
118
(1, 2, 3)
119
120
sage: pr = P.PolyhedronRepresentation(Polyhedron(vertices = [[1,2,3]]), [1,2,3])
121
sage: pr.__call__()
122
Traceback (most recent call last):
123
...
124
AttributeError: 'PolyhedronRepresentation' object has no attribute 'vector'
125
"""
126
return self.vector()
127
128
def index(self):
129
"""
130
Returns an arbitrary but fixed number according to the internal
131
storage order.
132
133
NOTES:
134
135
H-representation and V-representation objects are enumerated
136
independently. That is, amongst all vertices/rays/lines there
137
will be one with ``index()==0``, and amongs all
138
inequalities/equations there will be one with ``index()==0``,
139
unless the polyhedron is empty or spans the whole space.
140
141
EXAMPLES::
142
143
sage: s = Polyhedron(vertices=[[1],[-1]])
144
sage: first_vertex = s.vertex_generator().next()
145
sage: first_vertex.index()
146
0
147
sage: first_vertex == s.Vrepresentation(0)
148
True
149
"""
150
return self._index
151
152
153
154
class Hrepresentation(PolyhedronRepresentation):
155
"""
156
The internal base class for H-representation objects of
157
a polyhedron. Inherits from ``PolyhedronRepresentation``.
158
"""
159
def __init__(self, polyhedron, data):
160
"""
161
Initialization function.
162
163
TESTS::
164
165
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
166
sage: pH = p.Hrepresentation(0)
167
sage: TestSuite(pH).run(skip='_test_pickling')
168
"""
169
if len(data) != 1+polyhedron.ambient_dim():
170
raise ValueError, \
171
'H-representation data requires a list of length ambient_dim+1'
172
super(Hrepresentation, self).__init__(polyhedron, data)
173
self._index = len(polyhedron._Hrepresentation)
174
polyhedron._Hrepresentation.append(self)
175
176
@cached_method
177
def vector(self):
178
"""
179
Returns the vector representation of the H-representation object.
180
181
OUTPUT:
182
183
A vector of length
184
:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.ambient_dim` + 1.
185
186
EXAMPLES::
187
188
sage: s = polytopes.cuboctahedron()
189
sage: v = s.vertex_generator().next()
190
sage: v
191
A vertex at (-1/2, -1/2, 0)
192
sage: v.vector()
193
(-1/2, -1/2, 0)
194
sage: v()
195
(-1/2, -1/2, 0)
196
sage: type(v())
197
<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>
198
"""
199
return self.polyhedron().Hrepresentation_space()(self._representation_data)
200
201
def is_H(self):
202
"""
203
Returns True if the object is part of a H-representation
204
(inequality or equation).
205
206
EXAMPLES::
207
208
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
209
sage: pH = p.Hrepresentation(0)
210
sage: pH.is_H()
211
True
212
"""
213
return True
214
215
def is_inequality(self):
216
"""
217
Returns True if the object is an inequality of the H-representation.
218
219
EXAMPLES::
220
221
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
222
sage: pH = p.Hrepresentation(0)
223
sage: pH.is_inequality()
224
True
225
"""
226
return False
227
228
def is_equation(self):
229
"""
230
Returns True if the object is an equation of the H-representation.
231
232
EXAMPLES::
233
234
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]], eqns = [[1,1,-1]])
235
sage: pH = p.Hrepresentation(0)
236
sage: pH.is_equation()
237
True
238
"""
239
return False
240
241
@cached_method
242
def A(self):
243
r"""
244
Returns the coefficient vector `A` in `A\vec{x}+b`.
245
246
EXAMPLES::
247
248
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
249
sage: pH = p.Hrepresentation(2)
250
sage: pH.A()
251
(1, 0)
252
"""
253
return self.polyhedron().ambient_space()(self._representation_data[1:])
254
255
@cached_method
256
def b(self):
257
r"""
258
Returns the constant `b` in `A\vec{x}+b`.
259
260
EXAMPLES::
261
262
sage: p = Polyhedron(ieqs = [[0,1,0],[0,0,1],[1,-1,0,],[1,0,-1]])
263
sage: pH = p.Hrepresentation(2)
264
sage: pH.b()
265
0
266
"""
267
return self._representation_data[0]
268
269
def neighbors(self):
270
"""
271
Iterate over the adjacent facets (i.e. inequalities/equations)
272
273
EXAMPLES::
274
275
sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],
276
... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])
277
sage: pH = p.Hrepresentation(0)
278
sage: a = list(pH.neighbors())
279
sage: a[0]
280
An inequality (0, -1, 0) x + 1 >= 0
281
sage: list(a[0])
282
[1, 0, -1, 0]
283
"""
284
adjacency_matrix = self.polyhedron().facet_adjacency_matrix()
285
for x in self.polyhedron().Hrep_generator():
286
if adjacency_matrix[self.index(), x.index()] == 1:
287
yield x
288
289
def adjacent(self):
290
"""
291
Alias for neighbors().
292
293
TESTS::
294
295
sage: p = Polyhedron(ieqs = [[0,0,0,2],[0,0,1,0,],[0,10,0,0],
296
... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])
297
sage: pH = p.Hrepresentation(0)
298
sage: a = list(pH.neighbors())
299
sage: b = list(pH.adjacent())
300
sage: a==b
301
True
302
"""
303
return self.neighbors()
304
305
def is_incident(self, Vobj):
306
"""
307
Returns whether the incidence matrix element (Vobj,self) == 1
308
309
EXAMPLES::
310
311
sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],
312
... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])
313
sage: pH = p.Hrepresentation(0)
314
sage: pH.is_incident(p.Vrepresentation(1))
315
True
316
sage: pH.is_incident(p.Vrepresentation(5))
317
False
318
"""
319
return self.polyhedron().incidence_matrix()[Vobj.index(), self.index()] == 1
320
321
def __mul__(self, Vobj):
322
"""
323
Shorthand for ``self.eval(x)``
324
325
EXAMPLES::
326
327
sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0,],[0,1,0,0],
328
... [1,-1,0,0],[1,0,-1,0,],[1,0,0,-1]])
329
sage: pH = p.Hrepresentation(0)
330
sage: pH*p.Vrepresentation(5)
331
1
332
"""
333
return self.eval(Vobj)
334
335
def eval(self, Vobj):
336
r"""
337
Evaluates the left hand side `A\vec{x}+b` on the given
338
vertex/ray/line.
339
340
NOTES:
341
342
* Evaluating on a vertex returns `A\vec{x}+b`
343
* Evaluating on a ray returns `A\vec{r}`. Only the sign or
344
whether it is zero is meaningful.
345
* Evaluating on a line returns `A\vec{l}`. Only whether it
346
is zero or not is meaningful.
347
348
EXAMPLES::
349
350
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])
351
sage: ineq = triangle.inequality_generator().next()
352
sage: ineq
353
An inequality (2, -1) x + 1 >= 0
354
sage: [ ineq.eval(v) for v in triangle.vertex_generator() ]
355
[0, 0, 3]
356
sage: [ ineq * v for v in triangle.vertex_generator() ]
357
[0, 0, 3]
358
359
If you pass a vector, it is assumed to be the coordinate vector of a point::
360
361
sage: ineq.eval( vector(ZZ, [3,2]) )
362
5
363
"""
364
if is_Vector(Vobj):
365
return self.A() * Vobj + self.b()
366
return Vobj.evaluated_on(self)
367
#return self.A() * Vobj.vector() + self.b()
368
369
def incident(self):
370
"""
371
Returns a generator for the incident H-representation objects,
372
that is, the vertices/rays/lines satisfying the (in)equality.
373
374
EXAMPLES::
375
376
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])
377
sage: ineq = triangle.inequality_generator().next()
378
sage: ineq
379
An inequality (2, -1) x + 1 >= 0
380
sage: [ v for v in ineq.incident()]
381
[A vertex at (-1, -1), A vertex at (0, 1)]
382
sage: p = Polyhedron(vertices=[[0,0,0],[0,1,0],[0,0,1]], rays=[[1,-1,-1]])
383
sage: ineq = p.Hrepresentation(2)
384
sage: ineq
385
An inequality (1, 0, 1) x + 0 >= 0
386
sage: [ x for x in ineq.incident() ]
387
[A vertex at (0, 0, 0),
388
A vertex at (0, 1, 0),
389
A ray in the direction (1, -1, -1)]
390
"""
391
incidence_matrix = self.polyhedron().incidence_matrix()
392
for V in self.polyhedron().Vrep_generator():
393
if incidence_matrix[V.index(), self.index()] == 1:
394
yield V
395
396
397
class Inequality(Hrepresentation):
398
"""
399
A linear inequality (supporting hyperplane) of the
400
polyhedron. Inherits from ``Hrepresentation``.
401
"""
402
def __init__(self, polyhedron, data):
403
"""
404
A linear inequality (supporting hyperplane) of the
405
polyhedron. Inherits from ``Hrepresentation``.
406
407
TESTS::
408
409
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
410
sage: a = p.inequality_generator().next()
411
sage: a
412
An inequality (-1, 1, 0) x + 0 >= 0
413
sage: TestSuite(a).run(skip='_test_pickling')
414
"""
415
super(Inequality, self).__init__(polyhedron, data)
416
417
418
def type(self):
419
r"""
420
Returns the type (equation/inequality/vertex/ray/line) as an
421
integer.
422
423
OUTPUT:
424
425
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
426
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
427
428
EXAMPLES::
429
430
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
431
sage: repr_obj = p.inequality_generator().next()
432
sage: repr_obj.type()
433
0
434
sage: repr_obj.type() == repr_obj.INEQUALITY
435
True
436
sage: repr_obj.type() == repr_obj.EQUATION
437
False
438
sage: repr_obj.type() == repr_obj.VERTEX
439
False
440
sage: repr_obj.type() == repr_obj.RAY
441
False
442
sage: repr_obj.type() == repr_obj.LINE
443
False
444
"""
445
return self.INEQUALITY
446
447
448
def is_inequality(self):
449
"""
450
Returns True since this is, by construction, an inequality.
451
452
EXAMPLES::
453
454
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
455
sage: a = p.inequality_generator().next()
456
sage: a.is_inequality()
457
True
458
"""
459
return True
460
461
def _repr_(self):
462
"""
463
The string representation of the inequality.
464
465
EXAMPLES::
466
467
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
468
sage: a = p.inequality_generator().next()
469
sage: a._repr_()
470
'An inequality (-1, 1, 0) x + 0 >= 0'
471
sage: Polyhedron(ieqs=[(1,-1),(-1,2)]).Hrepresentation()
472
(An inequality (-1) x + 1 >= 0, An inequality (2) x - 1 >= 0)
473
sage: Polyhedron(eqns=[(1,0)]).Hrepresentation()
474
(An equation -1 == 0,)
475
sage: Polyhedron(eqns=[(-1,0)]).Hrepresentation()
476
(An equation -1 == 0,)
477
"""
478
s = 'An inequality '
479
have_A = not self.A().is_zero()
480
if have_A:
481
s += repr(self.A()) + ' x '
482
if self.b()>=0:
483
if have_A:
484
s += '+'
485
else:
486
s += '-'
487
if have_A:
488
s += ' '
489
s += repr(abs(self.b())) + ' >= 0'
490
return s
491
492
def contains(self, Vobj):
493
"""
494
Tests whether the halfspace (including its boundary) defined
495
by the inequality contains the given vertex/ray/line.
496
497
EXAMPLES::
498
499
sage: p = polytopes.cross_polytope(3)
500
sage: i1 = p.inequality_generator().next()
501
sage: [i1.contains(q) for q in p.vertex_generator()]
502
[True, True, True, True, True, True]
503
sage: p2 = 3*polytopes.n_cube(3)
504
sage: [i1.contains(q) for q in p2.vertex_generator()]
505
[True, False, False, False, True, True, True, False]
506
"""
507
try:
508
if Vobj.is_vector(): # assume we were passed a point
509
return self.polyhedron()._is_nonneg( self.eval(Vobj) )
510
except AttributeError:
511
pass
512
513
if Vobj.is_line():
514
return self.polyhedron()._is_zero( self.eval(Vobj) )
515
else:
516
return self.polyhedron()._is_nonneg( self.eval(Vobj) )
517
518
def interior_contains(self, Vobj):
519
"""
520
Tests whether the interior of the halfspace (excluding its
521
boundary) defined by the inequality contains the given
522
vertex/ray/line.
523
524
EXAMPLES::
525
526
sage: p = polytopes.cross_polytope(3)
527
sage: i1 = p.inequality_generator().next()
528
sage: [i1.interior_contains(q) for q in p.vertex_generator()]
529
[False, True, True, False, False, True]
530
sage: p2 = 3*polytopes.n_cube(3)
531
sage: [i1.interior_contains(q) for q in p2.vertex_generator()]
532
[True, False, False, False, True, True, True, False]
533
534
If you pass a vector, it is assumed to be the coordinate vector of a point::
535
536
sage: P = Polyhedron(vertices=[[1,1],[1,-1],[-1,1],[-1,-1]])
537
sage: p = vector(ZZ, [1,0] )
538
sage: [ ieq.interior_contains(p) for ieq in P.inequality_generator() ]
539
[True, True, False, True]
540
"""
541
try:
542
if Vobj.is_vector(): # assume we were passed a point
543
return self.polyhedron()._is_positive( self.eval(Vobj) )
544
except AttributeError:
545
pass
546
547
if Vobj.is_line():
548
return self.polyhedron()._is_zero( self.eval(Vobj) )
549
elif Vobj.is_vertex():
550
return self.polyhedron()._is_positive( self.eval(Vobj) )
551
else: # Vobj.is_ray()
552
return self.polyhedron()._is_nonneg( self.eval(Vobj) )
553
554
555
class Equation(Hrepresentation):
556
"""
557
A linear equation of the polyhedron. That is, the polyhedron is
558
strictly smaller-dimensional than the ambient space, and contained
559
in this hyperplane. Inherits from ``Hrepresentation``.
560
"""
561
def __init__(self, polyhedron, data):
562
"""
563
Initializes an equation object.
564
565
TESTS::
566
567
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
568
sage: a = p.equation_generator().next()
569
sage: a
570
An equation (0, 0, 1) x + 0 == 0
571
sage: TestSuite(a).run(skip='_test_pickling')
572
"""
573
super(Equation, self).__init__(polyhedron, data)
574
575
576
def type(self):
577
r"""
578
Returns the type (equation/inequality/vertex/ray/line) as an
579
integer.
580
581
OUTPUT:
582
583
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
584
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
585
586
EXAMPLES::
587
588
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
589
sage: repr_obj = p.equation_generator().next()
590
sage: repr_obj.type()
591
1
592
sage: repr_obj.type() == repr_obj.INEQUALITY
593
False
594
sage: repr_obj.type() == repr_obj.EQUATION
595
True
596
sage: repr_obj.type() == repr_obj.VERTEX
597
False
598
sage: repr_obj.type() == repr_obj.RAY
599
False
600
sage: repr_obj.type() == repr_obj.LINE
601
False
602
"""
603
return self.EQUATION
604
605
606
def is_equation(self):
607
"""
608
Tests if this object is an equation. By construction, it must be.
609
610
TESTS::
611
612
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
613
sage: a = p.equation_generator().next()
614
sage: a.is_equation()
615
True
616
"""
617
return True
618
619
def _repr_(self):
620
"""
621
A string representation of this object.
622
623
TESTS::
624
625
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
626
sage: a = p.equation_generator().next()
627
sage: a._repr_()
628
'An equation (0, 0, 1) x + 0 == 0'
629
sage: Polyhedron().Hrepresentation(0)
630
An equation -1 == 0
631
"""
632
s = 'An equation '
633
have_A = not self.A().is_zero()
634
if have_A:
635
s += repr(self.A()) + ' x '
636
if self.b()>=0:
637
if have_A:
638
s += '+'
639
else:
640
s += '-'
641
if have_A:
642
s += ' '
643
s += repr(abs(self.b())) + ' == 0'
644
return s
645
646
def contains(self, Vobj):
647
"""
648
Tests whether the hyperplane defined by the equation contains
649
the given vertex/ray/line.
650
651
EXAMPLES::
652
653
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
654
sage: v = p.vertex_generator().next()
655
sage: v
656
A vertex at (0, 0, 0)
657
sage: a = p.equation_generator().next()
658
sage: a
659
An equation (0, 0, 1) x + 0 == 0
660
sage: a.contains(v)
661
True
662
"""
663
return self.polyhedron()._is_zero( self.eval(Vobj) )
664
665
def interior_contains(self, Vobj):
666
"""
667
Tests whether the interior of the halfspace (excluding its
668
boundary) defined by the inequality contains the given
669
vertex/ray/line.
670
671
NOTE:
672
673
Returns False for any equation.
674
675
EXAMPLES::
676
677
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
678
sage: v = p.vertex_generator().next()
679
sage: v
680
A vertex at (0, 0, 0)
681
sage: a = p.equation_generator().next()
682
sage: a
683
An equation (0, 0, 1) x + 0 == 0
684
sage: a.interior_contains(v)
685
False
686
"""
687
return False
688
689
690
class Vrepresentation(PolyhedronRepresentation):
691
"""
692
The base class for V-representation objects of a
693
polyhedron. Inherits from ``PolyhedronRepresentation``.
694
"""
695
def __init__(self, polyhedron, data):
696
"""
697
Initialization function for the vertex representation.
698
699
TESTS::
700
701
sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])
702
sage: from sage.geometry.polyhedron.representation import Vrepresentation
703
sage: p._Vrepresentation = Sequence([])
704
sage: vr = Vrepresentation(p,[1,2,3,4])
705
sage: vr.__init__(p,[1,2,3,5])
706
sage: vr.vector()
707
(1, 2, 3, 5)
708
sage: TestSuite(vr).run(skip='_test_pickling')
709
"""
710
if len(data) != polyhedron.ambient_dim():
711
raise ValueError, \
712
'V-representation data requires a list of length ambient_dim'
713
super(Vrepresentation, self).__init__(polyhedron, data)
714
self._index = len(polyhedron._Vrepresentation)
715
polyhedron._Vrepresentation.append(self)
716
717
@cached_method
718
def vector(self):
719
"""
720
Returns the vector representation of the V-representation object.
721
722
OUTPUT:
723
724
A vector of length
725
:meth:`~sage.geometry.polyhedron.base.Polyhedron_base.ambient_dim`.
726
727
EXAMPLES::
728
729
sage: s = polytopes.cuboctahedron()
730
sage: v = s.vertex_generator().next()
731
sage: v
732
A vertex at (-1/2, -1/2, 0)
733
sage: v.vector()
734
(-1/2, -1/2, 0)
735
sage: v()
736
(-1/2, -1/2, 0)
737
sage: type(v())
738
<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>
739
"""
740
return self.polyhedron().Vrepresentation_space()(self._representation_data)
741
742
def is_V(self):
743
"""
744
Returns True if the object is part of a V-representation
745
(a vertex, ray, or line).
746
747
EXAMPLES::
748
749
sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]])
750
sage: v = p.vertex_generator().next()
751
sage: v.is_V()
752
True
753
"""
754
return True
755
756
def is_vertex(self):
757
"""
758
Returns True if the object is a vertex of the V-representation.
759
This method is over-ridden by the corresponding method in the
760
derived class Vertex.
761
762
EXAMPLES::
763
764
sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,3]])
765
sage: v = p.vertex_generator().next()
766
sage: v.is_vertex()
767
True
768
sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])
769
sage: r1 = p.ray_generator().next()
770
sage: r1.is_vertex()
771
False
772
"""
773
return False
774
775
def is_ray(self):
776
"""
777
Returns True if the object is a ray of the V-representation.
778
This method is over-ridden by the corresponding method in the
779
derived class Ray.
780
781
EXAMPLES::
782
783
sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])
784
sage: r1 = p.ray_generator().next()
785
sage: r1.is_ray()
786
True
787
sage: v1 = p.vertex_generator().next()
788
sage: v1
789
A vertex at (-1, -1, 0, -1)
790
sage: v1.is_ray()
791
False
792
"""
793
return False
794
795
def is_line(self):
796
"""
797
Returns True if the object is a line of the V-representation.
798
This method is over-ridden by the corresponding method in the
799
derived class Line.
800
801
EXAMPLES::
802
803
sage: p = Polyhedron(ieqs = [[1, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0]])
804
sage: line1 = p.line_generator().next()
805
sage: line1.is_line()
806
True
807
sage: v1 = p.vertex_generator().next()
808
sage: v1.is_line()
809
False
810
"""
811
return False
812
813
def neighbors(self):
814
"""
815
Returns a generator for the adjacent vertices/rays/lines.
816
817
EXAMPLES::
818
819
sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]])
820
sage: v = p.vertex_generator().next()
821
sage: v.neighbors().next()
822
A vertex at (0, 3)
823
"""
824
adjacency_matrix = self.polyhedron().vertex_adjacency_matrix()
825
for x in self.polyhedron().Vrep_generator():
826
if adjacency_matrix[self.index(), x.index()] == 1:
827
yield x
828
829
def adjacent(self):
830
"""
831
Alias for neighbors().
832
833
TESTS::
834
835
sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,3],[1,4]])
836
sage: v = p.vertex_generator().next()
837
sage: a = v.neighbors().next()
838
sage: b = v.adjacent().next()
839
sage: a==b
840
True
841
"""
842
return self.neighbors()
843
844
def is_incident(self, Hobj):
845
"""
846
Returns whether the incidence matrix element (self,Hobj) == 1
847
848
EXAMPLES::
849
850
sage: p = polytopes.n_cube(3)
851
sage: h1 = p.inequality_generator().next()
852
sage: h1
853
An inequality (0, 0, -1) x + 1 >= 0
854
sage: v1 = p.vertex_generator().next()
855
sage: v1
856
A vertex at (-1, -1, -1)
857
sage: v1.is_incident(h1)
858
False
859
"""
860
return self.polyhedron().incidence_matrix()[self.index(), Hobj.index()] == 1
861
862
def __mul__(self, Hobj):
863
"""
864
Shorthand for self.evaluated_on(Hobj)
865
866
TESTS::
867
868
sage: p = polytopes.n_cube(3)
869
sage: h1 = p.inequality_generator().next()
870
sage: v1 = p.vertex_generator().next()
871
sage: v1.__mul__(h1)
872
2
873
"""
874
return self.evaluated_on(Hobj)
875
876
def incident(self):
877
"""
878
Returns a generator for the equations/inequalities that are satisfied on the given
879
vertex/ray/line.
880
881
EXAMPLES::
882
883
sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[-1,-1]])
884
sage: ineq = triangle.inequality_generator().next()
885
sage: ineq
886
An inequality (2, -1) x + 1 >= 0
887
sage: [ v for v in ineq.incident()]
888
[A vertex at (-1, -1), A vertex at (0, 1)]
889
sage: p = Polyhedron(vertices=[[0,0,0],[0,1,0],[0,0,1]], rays=[[1,-1,-1]])
890
sage: ineq = p.Hrepresentation(2)
891
sage: ineq
892
An inequality (1, 0, 1) x + 0 >= 0
893
sage: [ x for x in ineq.incident() ]
894
[A vertex at (0, 0, 0),
895
A vertex at (0, 1, 0),
896
A ray in the direction (1, -1, -1)]
897
"""
898
incidence_matrix = self.polyhedron().incidence_matrix()
899
for H in self.polyhedron().Hrep_generator():
900
if incidence_matrix[self.index(), H.index()] == 1:
901
yield H
902
903
904
class Vertex(Vrepresentation):
905
"""
906
A vertex of the polyhedron. Inherits from ``Vrepresentation``.
907
"""
908
def __init__(self, polyhedron, data):
909
"""
910
Initializes the vertex object.
911
912
TESTS::
913
914
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
915
sage: v1 = p.vertex_generator().next()
916
sage: v1
917
A vertex at (1, 0)
918
sage: TestSuite(v1).run(skip='_test_pickling')
919
"""
920
super(Vertex, self).__init__(polyhedron, data)
921
922
923
def type(self):
924
r"""
925
Returns the type (equation/inequality/vertex/ray/line) as an
926
integer.
927
928
OUTPUT:
929
930
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
931
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
932
933
EXAMPLES::
934
935
sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]])
936
sage: repr_obj = p.vertex_generator().next()
937
sage: repr_obj.type()
938
2
939
sage: repr_obj.type() == repr_obj.INEQUALITY
940
False
941
sage: repr_obj.type() == repr_obj.EQUATION
942
False
943
sage: repr_obj.type() == repr_obj.VERTEX
944
True
945
sage: repr_obj.type() == repr_obj.RAY
946
False
947
sage: repr_obj.type() == repr_obj.LINE
948
False
949
"""
950
return self.VERTEX
951
952
953
def is_vertex(self):
954
"""
955
Tests if this object is a vertex. By construction it always is.
956
957
EXAMPLES::
958
959
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
960
sage: a = p.vertex_generator().next()
961
sage: a.is_vertex()
962
True
963
"""
964
return True
965
966
def _repr_(self):
967
"""
968
Returns a string representation of the vertex.
969
970
OUTPUT:
971
972
String.
973
974
TESTS::
975
976
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
977
sage: v = p.vertex_generator().next()
978
sage: v.__repr__()
979
'A vertex at (1, 0)'
980
"""
981
return 'A vertex at ' + repr(self.vector());
982
983
def evaluated_on(self, Hobj):
984
r"""
985
Returns `A\vec{x}+b`
986
987
EXAMPLES::
988
989
sage: p = polytopes.n_cube(3)
990
sage: v = p.vertex_generator().next()
991
sage: h = p.inequality_generator().next()
992
sage: v
993
A vertex at (-1, -1, -1)
994
sage: h
995
An inequality (0, 0, -1) x + 1 >= 0
996
sage: v.evaluated_on(h)
997
2
998
"""
999
return Hobj.A() * self.vector() + Hobj.b()
1000
1001
@cached_method
1002
def is_integral(self):
1003
r"""
1004
Return whether the coordinates of the vertex are all integral.
1005
1006
OUTPUT:
1007
1008
Boolean.
1009
1010
EXAMPLES::
1011
1012
sage: p = Polyhedron([(1/2,3,5), (0,0,0), (2,3,7)])
1013
sage: [ v.is_integral() for v in p.vertex_generator() ]
1014
[True, False, True]
1015
"""
1016
return all(x in ZZ for x in self._representation_data)
1017
1018
1019
class Ray(Vrepresentation):
1020
"""
1021
A ray of the polyhedron. Inherits from ``Vrepresentation``.
1022
"""
1023
def __init__(self, polyhedron, data):
1024
"""
1025
Initializes a ray object.
1026
1027
TESTS::
1028
1029
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
1030
sage: r1 = p.ray_generator().next()
1031
sage: r1
1032
A ray in the direction (0, 1)
1033
sage: TestSuite(r1).run(skip='_test_pickling')
1034
"""
1035
super(Ray, self).__init__(polyhedron, data)
1036
1037
1038
def type(self):
1039
r"""
1040
Returns the type (equation/inequality/vertex/ray/line) as an
1041
integer.
1042
1043
OUTPUT:
1044
1045
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
1046
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
1047
1048
EXAMPLES::
1049
1050
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
1051
sage: repr_obj = p.ray_generator().next()
1052
sage: repr_obj.type()
1053
3
1054
sage: repr_obj.type() == repr_obj.INEQUALITY
1055
False
1056
sage: repr_obj.type() == repr_obj.EQUATION
1057
False
1058
sage: repr_obj.type() == repr_obj.VERTEX
1059
False
1060
sage: repr_obj.type() == repr_obj.RAY
1061
True
1062
sage: repr_obj.type() == repr_obj.LINE
1063
False
1064
"""
1065
return self.RAY
1066
1067
1068
def is_ray(self):
1069
"""
1070
Tests if this object is a ray. Always True by construction.
1071
1072
EXAMPLES::
1073
1074
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
1075
sage: a = p.ray_generator().next()
1076
sage: a.is_ray()
1077
True
1078
"""
1079
return True
1080
1081
def _repr_(self):
1082
"""
1083
A string representation of the ray.
1084
1085
TESTS::
1086
1087
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
1088
sage: a = p.ray_generator().next()
1089
sage: a._repr_()
1090
'A ray in the direction (0, 1)'
1091
"""
1092
return 'A ray in the direction ' + repr(self.vector());
1093
1094
def evaluated_on(self, Hobj):
1095
r"""
1096
Returns `A\vec{r}`
1097
1098
EXAMPLES::
1099
1100
sage: p = Polyhedron(ieqs = [[0,0,1],[0,1,0],[1,-1,0]])
1101
sage: a = p.ray_generator().next()
1102
sage: h = p.inequality_generator().next()
1103
sage: a.evaluated_on(h)
1104
0
1105
"""
1106
return Hobj.A() * self.vector()
1107
1108
1109
class Line(Vrepresentation):
1110
r"""
1111
A line (Minkowski summand `\simeq\RR`) of the
1112
polyhedron. Inherits from ``Vrepresentation``.
1113
"""
1114
def __init__(self, polyhedron, data):
1115
"""
1116
Initializes the line object.
1117
1118
TESTS::
1119
1120
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
1121
sage: a = p.line_generator().next()
1122
sage: p._Vrepresentation = Sequence([])
1123
sage: a.__init__(p,[1,2,3])
1124
sage: a
1125
A line in the direction (1, 2, 3)
1126
sage: TestSuite(a).run(skip='_test_pickling')
1127
"""
1128
super(Line, self).__init__(polyhedron, data)
1129
1130
1131
def type(self):
1132
r"""
1133
Returns the type (equation/inequality/vertex/ray/line) as an
1134
integer.
1135
1136
OUTPUT:
1137
1138
Integer. One of ``PolyhedronRepresentation.INEQUALITY``,
1139
``.EQUATION``, ``.VERTEX``, ``.RAY``, or ``.LINE``.
1140
1141
EXAMPLES::
1142
1143
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
1144
sage: repr_obj = p.line_generator().next()
1145
sage: repr_obj.type()
1146
4
1147
sage: repr_obj.type() == repr_obj.INEQUALITY
1148
False
1149
sage: repr_obj.type() == repr_obj.EQUATION
1150
False
1151
sage: repr_obj.type() == repr_obj.VERTEX
1152
False
1153
sage: repr_obj.type() == repr_obj.RAY
1154
False
1155
sage: repr_obj.type() == repr_obj.LINE
1156
True
1157
"""
1158
return self.LINE
1159
1160
1161
def is_line(self):
1162
"""
1163
Tests if the object is a line. By construction it must be.
1164
1165
TESTS::
1166
1167
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
1168
sage: a = p.line_generator().next()
1169
sage: a.is_line()
1170
True
1171
"""
1172
return True
1173
1174
def _repr_(self):
1175
"""
1176
A string representation of the line.
1177
1178
TESTS::
1179
1180
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
1181
sage: a = p.line_generator().next()
1182
sage: a.__repr__()
1183
'A line in the direction (0, 1, 0)'
1184
"""
1185
return 'A line in the direction ' + repr(self.vector());
1186
1187
def evaluated_on(self, Hobj):
1188
r"""
1189
Returns `A\vec{\ell}`
1190
1191
EXAMPLES::
1192
1193
sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]])
1194
sage: a = p.line_generator().next()
1195
sage: h = p.inequality_generator().next()
1196
sage: a.evaluated_on(h)
1197
0
1198
"""
1199
return Hobj.A() * self.vector()
1200
1201
1202
1203