Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/graphs/cliquer.pyx
8815 views
1
r"""
2
Cliquer: routines for finding cliques in graphs
3
4
This module defines functions based on Cliquer, an exact
5
branch-and-bound algorithm developed by Patric R. J. Ostergard and
6
written by Sampo Niskanen.
7
8
AUTHORS:
9
10
- Nathann Cohen (2009-08-14): Initial version
11
12
- Jeroen Demeyer (2011-05-06): Make cliquer interruptible (#11252)
13
14
- Nico Van Cleemput (2013-05-27): Handle the empty graph (#14525)
15
16
REFERENCE:
17
18
.. [NisOst2003] Sampo Niskanen and Patric R. J. Ostergard,
19
"Cliquer User's Guide, Version 1.0,"
20
Communications Laboratory, Helsinki University of Technology,
21
Espoo, Finland, Tech. Rep. T48, 2003.
22
23
Methods
24
-------
25
"""
26
27
28
#*****************************************************************************
29
# Copyright (C) 2009 Nathann Cohen <[email protected]>
30
#
31
# Distributed under the terms of the GNU General Public License (GPL)
32
# as published by the Free Software Foundation; either version 2 of
33
# the License, or (at your option) any later version.
34
# http://www.gnu.org/licenses/
35
#*****************************************************************************
36
37
38
include "sage/ext/interrupt.pxi"
39
include 'sage/ext/stdsage.pxi'
40
41
def max_clique(graph):
42
"""
43
Returns the vertex set of a maximum complete subgraph.
44
45
Currently only implemented for undirected graphs. Use
46
to_undirected to convert a digraph to an undirected graph.
47
48
EXAMPLES::
49
50
sage: C=graphs.PetersenGraph()
51
sage: max_clique(C)
52
[7, 9]
53
54
TEST::
55
56
sage: g = Graph()
57
sage: g.clique_maximum()
58
[]
59
"""
60
if graph.order() == 0:
61
return []
62
63
graph,d = graph.relabel(inplace=False, return_map=True)
64
d_inv = {}
65
for v in d:
66
d_inv[d[v]] = v
67
68
cdef graph_t *g
69
g=graph_new(graph.order())
70
for e in graph.edge_iterator():
71
(u,v,w)=e
72
GRAPH_ADD_EDGE(g,u,v)
73
74
cdef int* list
75
cdef int size
76
sig_on()
77
size = sage_clique_max(g, &list)
78
sig_off()
79
b = []
80
cdef int i
81
for i in range(size):
82
b.append(list[i])
83
84
sage_free(list)
85
graph_free(g)
86
return list_composition(b,d_inv)
87
88
89
# computes all the maximum clique of a graph and return its list
90
91
def all_max_clique(graph):
92
"""
93
Returns the vertex sets of *ALL* the maximum complete subgraphs.
94
95
Returns the list of all maximum cliques, with each clique represented by a
96
list of vertices. A clique is an induced complete subgraph, and a maximum
97
clique is one of maximal order.
98
99
.. NOTE::
100
101
Currently only implemented for undirected graphs. Use to_undirected
102
to convert a digraph to an undirected graph.
103
104
ALGORITHM:
105
106
This function is based on Cliquer [NisOst2003]_.
107
108
EXAMPLES::
109
110
sage: graphs.ChvatalGraph().cliques_maximum() # indirect doctest
111
[[0, 1], [0, 4], [0, 6], [0, 9], [1, 2], [1, 5], [1, 7], [2, 3],
112
[2, 6], [2, 8], [3, 4], [3, 7], [3, 9], [4, 5], [4, 8], [5, 10],
113
[5, 11], [6, 10], [6, 11], [7, 8], [7, 11], [8, 10], [9, 10], [9, 11]]
114
sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]})
115
sage: G.show(figsize=[2,2])
116
sage: G.cliques_maximum()
117
[[0, 1, 2], [0, 1, 3]]
118
sage: C=graphs.PetersenGraph()
119
sage: C.cliques_maximum()
120
[[0, 1], [0, 4], [0, 5], [1, 2], [1, 6], [2, 3], [2, 7], [3, 4],
121
[3, 8], [4, 9], [5, 7], [5, 8], [6, 8], [6, 9], [7, 9]]
122
sage: C = Graph('DJ{')
123
sage: C.cliques_maximum()
124
[[1, 2, 3, 4]]
125
126
TEST::
127
128
sage: g = Graph()
129
sage: g.cliques_maximum()
130
[[]]
131
"""
132
if graph.order() == 0:
133
return [[]]
134
135
graph,d = graph.relabel(inplace=False, return_map=True)
136
d_inv = {}
137
for v in d:
138
d_inv[d[v]] = v
139
140
cdef graph_t *g
141
g=graph_new(graph.order())
142
143
for e in graph.edge_iterator():
144
(u,v,w)=e
145
GRAPH_ADD_EDGE(g,u,v)
146
147
cdef int* list
148
cdef int size
149
sig_on()
150
size = sage_all_clique_max(g, &list)
151
sig_off()
152
b = []
153
c=[]
154
cdef int i
155
for i in range(size):
156
if(list[i]!=-1):
157
c.append(list[i])
158
else:
159
b.append(list_composition(c,d_inv))
160
c=[]
161
162
sage_free(list)
163
graph_free(g)
164
165
return sorted(b)
166
167
168
#computes the clique number of a graph
169
170
def clique_number(graph):
171
"""
172
Returns the size of the largest clique of the graph (clique
173
number).
174
175
Currently only implemented for undirected graphs. Use
176
to_undirected to convert a digraph to an undirected graph.
177
178
EXAMPLES::
179
180
sage: C = Graph('DJ{')
181
sage: clique_number(C)
182
4
183
sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]})
184
sage: G.show(figsize=[2,2])
185
sage: clique_number(G)
186
3
187
188
TEST::
189
190
sage: g = Graph()
191
sage: g.clique_number()
192
0
193
"""
194
if graph.order() == 0:
195
return 0
196
197
graph=graph.relabel(inplace=False)
198
cdef graph_t *g
199
g=graph_new(graph.order())
200
201
for e in graph.edge_iterator():
202
(u,v,w)=e
203
GRAPH_ADD_EDGE(g,u,v)
204
205
cdef int c
206
sig_on()
207
c = sage_clique_number(g)
208
graph_free(g)
209
sig_off()
210
return c
211
212
213
def list_composition(a,b):
214
"""
215
Composes a list ``a`` with a map ``b``.
216
217
EXAMPLES::
218
219
sage: from sage.graphs.cliquer import list_composition
220
sage: list_composition([1,3,'a'], {'a':'b', 1:2, 2:3, 3:4})
221
[2, 4, 'b']
222
223
"""
224
value=[]
225
for i in a:
226
value.append(b[i])
227
return value
228
229
230
231