Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/graphs/generators/intersection.py
8815 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Intersection graphs
4
5
The methods defined here appear in :mod:`sage.graphs.graph_generators`.
6
"""
7
8
###########################################################################
9
#
10
# Copyright (C) 2006 Robert L. Miller <[email protected]>
11
# and Emily A. Kirkman
12
# Copyright (C) 2009 Michael C. Yurko <[email protected]>
13
#
14
# Distributed under the terms of the GNU General Public License (GPL)
15
# http://www.gnu.org/licenses/
16
###########################################################################
17
18
# import from Sage library
19
from sage.graphs.graph import Graph
20
21
def IntervalGraph(intervals, points_ordered = False):
22
r"""
23
Returns the graph corresponding to the given intervals.
24
25
An interval graph is built from a list `(a_i,b_i)_{1\leq i \leq n}` of
26
intervals : to each interval of the list is associated one vertex, two
27
vertices being adjacent if the two corresponding (closed) intervals
28
intersect.
29
30
INPUT:
31
32
- ``intervals`` -- the list of pairs `(a_i,b_i)` defining the graph.
33
34
- ``points_ordered`` -- states whether every interval `(a_i,b_i)` of
35
`intervals` satisfies `a_i<b_i`. If satisfied then setting
36
``points_ordered`` to ``True`` will speed up the creation of the graph.
37
38
.. NOTE::
39
40
* The vertices are named 0, 1, 2, and so on. The intervals used
41
to create the graph are saved with the graph and can be recovered
42
using ``get_vertex()`` or ``get_vertices()``.
43
44
EXAMPLE:
45
46
The following line creates the sequence of intervals
47
`(i, i+2)` for i in `[0, ..., 8]`::
48
49
sage: intervals = [(i,i+2) for i in range(9)]
50
51
In the corresponding graph ::
52
53
sage: g = graphs.IntervalGraph(intervals)
54
sage: g.get_vertex(3)
55
(3, 5)
56
sage: neigh = g.neighbors(3)
57
sage: for v in neigh: print g.get_vertex(v)
58
(1, 3)
59
(2, 4)
60
(4, 6)
61
(5, 7)
62
63
The is_interval() method verifies that this graph is an interval graph. ::
64
65
sage: g.is_interval()
66
True
67
68
The intervals in the list need not be distinct. ::
69
70
sage: intervals = [ (1,2), (1,2), (1,2), (2,3), (3,4) ]
71
sage: g = graphs.IntervalGraph(intervals,True)
72
sage: g.clique_maximum()
73
[0, 1, 2, 3]
74
sage: g.get_vertices()
75
{0: (1, 2), 1: (1, 2), 2: (1, 2), 3: (2, 3), 4: (3, 4)}
76
77
The endpoints of the intervals are not ordered we get the same graph
78
(except for the vertex labels). ::
79
80
sage: rev_intervals = [ (2,1), (2,1), (2,1), (3,2), (4,3) ]
81
sage: h = graphs.IntervalGraph(rev_intervals,False)
82
sage: h.get_vertices()
83
{0: (2, 1), 1: (2, 1), 2: (2, 1), 3: (3, 2), 4: (4, 3)}
84
sage: g.edges() == h.edges()
85
True
86
"""
87
88
n = len(intervals)
89
g = Graph(n)
90
91
if points_ordered:
92
for i in xrange(n-1):
93
li,ri = intervals[i]
94
for j in xrange(i+1,n):
95
lj,rj = intervals[j]
96
if ri < lj or rj < li: continue
97
g.add_edge(i,j)
98
else:
99
for i in xrange(n-1):
100
I = intervals[i]
101
for j in xrange(i+1,n):
102
J = intervals[j]
103
if max(I) < min(J) or max(J) < min(I): continue
104
g.add_edge(i,j)
105
106
rep = dict( zip(range(n),intervals) )
107
g.set_vertices(rep)
108
109
return g
110
111
def PermutationGraph(second_permutation, first_permutation = None):
112
r"""
113
Builds a permutation graph from one (or two) permutations.
114
115
General definition
116
117
A Permutation Graph can be encoded by a permutation `\sigma`
118
of `1, ..., n`. It is then built in the following way :
119
120
Take two horizontal lines in the euclidean plane, and mark points `1, ...,
121
n` from left to right on the first of them. On the second one, still from
122
left to right, mark point in the order in which they appear in `\sigma`.
123
Now, link by a segment the two points marked with 1, then link together
124
the points marked with 2, and so on. The permutation graph defined by the
125
permutation is the intersection graph of those segments : there exists a
126
point in this graph for each element from `1` to `n`, two vertices `i, j`
127
being adjacent if the segments `i` and `j` cross each other.
128
129
The set of edges of the resulting graph is equal to the set of inversions of
130
the inverse of the given permutation.
131
132
INPUT:
133
134
- ``second_permutation`` -- the permutation from which the graph should be
135
built. It corresponds to the ordering of the elements on the second line
136
(see previous definition)
137
138
- ``first_permutation`` (optional) -- the ordering of the elements on the
139
*first* line. This is useful when the elements have no natural ordering,
140
for instance when they are strings, or tuples, or anything else.
141
142
When ``first_permutation == None`` (default), it is set to be equal to
143
``sorted(second_permutation)``, which just yields the expected
144
ordering when the elements of the graph are integers.
145
146
.. SEEALSO:
147
148
- Recognition of Permutation graphs in the :mod:`comparability module
149
<sage.graphs.comparability>`.
150
151
- Drawings of permutation graphs as intersection graphs of segments is
152
possible through the
153
:meth:`~sage.combinat.permutation.Permutation.show` method of
154
:class:`~sage.combinat.permutation.Permutation` objects.
155
156
The correct argument to use in this case is ``show(representation =
157
"braid")``.
158
159
- :meth:`~sage.combinat.permutation.Permutation.inversions`
160
161
EXAMPLE::
162
163
sage: p = Permutations(5).random_element()
164
sage: edges = graphs.PermutationGraph(p).edges(labels =False)
165
sage: set(edges) == set(p.inverse().inversions())
166
True
167
168
TESTS::
169
170
sage: graphs.PermutationGraph([1, 2, 3], [4, 5, 6])
171
Traceback (most recent call last):
172
...
173
ValueError: The two permutations do not contain the same set of elements ...
174
"""
175
if first_permutation == None:
176
first_permutation = sorted(second_permutation)
177
else:
178
if set(second_permutation) != set(first_permutation):
179
raise ValueError("The two permutations do not contain the same "+
180
"set of elements ! It is going to be pretty "+
181
"hard to define a permutation graph from that !")
182
183
vertex_to_index = {}
184
for i, v in enumerate(first_permutation):
185
vertex_to_index[v] = i+1
186
187
from sage.combinat.permutation import Permutation
188
p2 = Permutation(map(lambda x:vertex_to_index[x], second_permutation))
189
p1 = Permutation(map(lambda x:vertex_to_index[x], first_permutation))
190
p2 = p2 * p1.inverse()
191
p2 = p2.inverse()
192
193
g = Graph(name="Permutation graph for "+str(second_permutation))
194
g.add_vertices(second_permutation)
195
196
for u,v in p2.inversions():
197
g.add_edge(first_permutation[u-1], first_permutation[v-1])
198
199
return g
200
201
def ToleranceGraph(tolrep):
202
r"""
203
Returns the graph generated by the tolerance representation ``tolrep``.
204
205
The tolerance representation ``tolrep`` is described by the list
206
`((l_0,r_0,t_0), (l_1,r_1,t_1), ..., (l_k,r_k,t_k))` where `I_i = (l_i,r_i)`
207
denotes a closed interval on the real line with `l_i < r_i` and `t_i` a
208
positive value, called tolerance. This representation generates the
209
tolerance graph with the vertex set {0,1, ..., k} and the edge set `{(i,j):
210
|I_i \cap I_j| \ge \min{t_i, t_j}}` where `|I_i \cap I_j|` denotes the
211
length of the intersection of `I_i` and `I_j`.
212
213
INPUT:
214
215
- ``tolrep`` -- list of triples `(l_i,r_i,t_i)` where `(l_i,r_i)` denotes a
216
closed interval on the real line and `t_i` a positive value.
217
218
.. NOTE::
219
220
The vertices are named 0, 1, ..., k. The tolerance representation used
221
to create the graph is saved with the graph and can be recovered using
222
``get_vertex()`` or ``get_vertices()``.
223
224
EXAMPLE:
225
226
The following code creates a tolerance representation ``tolrep``, generates
227
its tolerance graph ``g``, and applies some checks::
228
229
sage: tolrep = [(1,4,3),(1,2,1),(2,3,1),(0,3,3)]
230
sage: g = graphs.ToleranceGraph(tolrep)
231
sage: g.get_vertex(3)
232
(0, 3, 3)
233
sage: neigh = g.neighbors(3)
234
sage: for v in neigh: print g.get_vertex(v)
235
(1, 2, 1)
236
(2, 3, 1)
237
sage: g.is_interval()
238
False
239
sage: g.is_weakly_chordal()
240
True
241
242
The intervals in the list need not be distinct ::
243
244
sage: tolrep2 = [(0,4,5),(1,2,1),(2,3,1),(0,4,5)]
245
sage: g2 = graphs.ToleranceGraph(tolrep2)
246
sage: g2.get_vertices()
247
{0: (0, 4, 5), 1: (1, 2, 1), 2: (2, 3, 1), 3: (0, 4, 5)}
248
sage: g2.is_isomorphic(g)
249
True
250
251
Real values are also allowed ::
252
253
sage: tolrep = [(0.1,3.3,4.4),(1.1,2.5,1.1),(1.4,4.4,3.3)]
254
sage: g = graphs.ToleranceGraph(tolrep)
255
sage: g.is_isomorphic(graphs.PathGraph(3))
256
True
257
258
TEST:
259
260
Giving negative third value::
261
262
sage: tolrep = [(0.1,3.3,-4.4),(1.1,2.5,1.1),(1.4,4.4,3.3)]
263
sage: g = graphs.ToleranceGraph(tolrep)
264
Traceback (most recent call last):
265
...
266
ValueError: Invalid tolerance representation at position 0; third value must be positive!
267
"""
268
n = len(tolrep)
269
270
for i in xrange(n):
271
if tolrep[i][2] <= 0:
272
raise ValueError("Invalid tolerance representation at position "+str(i)+"; third value must be positive!")
273
274
g = Graph(n)
275
276
for i in xrange(n-1):
277
li,ri,ti = tolrep[i]
278
for j in xrange(i+1,n):
279
lj,rj,tj = tolrep[j]
280
if min(ri,rj) - max(li,lj) >= min(ti,tj):
281
g.add_edge(i,j)
282
283
rep = dict( zip(range(n),tolrep) )
284
g.set_vertices(rep)
285
286
return g
287
288