Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/graphs/modular_decomposition/modular_decomposition.pyx
4057 views
1
r"""
2
Modular decomposition
3
"""
4
5
#####################################################
6
# The following code is mainly a Cythonized
7
# copy of code found in src/random.c and src/dm.c
8
#####################################################
9
10
############################
11
# CONSTANTS
12
############################
13
14
cdef int FEUILLE = 0 # the node is a leaf
15
cdef int UNKN = 1
16
cdef int MODULE = 2
17
cdef int ARTEFACT = 3
18
cdef int SERIE = 4 # series composition
19
cdef int PARALLELE = 5 # parallel composition
20
cdef int PREMIER = 6 # prime composition
21
22
cdef dict codes = {
23
UNKN: "Node",
24
MODULE: "Module",
25
ARTEFACT: "Artefact",
26
SERIE: "Serie",
27
PARALLELE: "Parallel",
28
PREMIER: "Prime"
29
}
30
31
cpdef modular_decomposition(g):
32
r"""
33
Returns a modular decomposition of the given graph.
34
35
INPUT:
36
37
- ``g`` -- a graph
38
39
OUTPUT:
40
41
A pair of two values (recursively encoding the decomposition) :
42
43
* The type of the current module :
44
45
* ``"Parallel"``
46
* ``"Prime"``
47
* ``"Serie"``
48
49
* The list of submodules (as list of pairs ``(type, list)``,
50
recursively...) or the vertex's name if the module is a
51
singleton.
52
53
.. NOTE::
54
55
As this fuction could be used by efficient C routines, the
56
vertices returned are not labels but identifiants from ``[0,
57
..., g.order()-1]``
58
59
ALGORITHM:
60
61
This function uses a C implementation of a 2-step algorithm
62
implemented by Fabien de Montgolfier [FMDecb]_ :
63
64
* Computation of a factorizing permutation [HabibViennot1999b]_.
65
66
* Computation of the tree itself [CapHabMont02b]_.
67
68
EXAMPLES:
69
70
The Bull Graph is prime::
71
72
sage: from sage.graphs.modular_decomposition.modular_decomposition import modular_decomposition
73
sage: modular_decomposition(graphs.BullGraph())
74
('Prime', [3, 4, 0, 1, 2])
75
76
The Petersen Graph too::
77
78
sage: modular_decomposition(graphs.PetersenGraph())
79
('Prime', [2, 6, 3, 9, 7, 8, 0, 1, 5, 4])
80
81
This a clique on 5 vertices with 2 pendant edges, though, has a more
82
interesting decomposition ::
83
84
sage: g = graphs.CompleteGraph(5)
85
sage: g.add_edge(0,5)
86
sage: g.add_edge(0,6)
87
sage: modular_decomposition(g)
88
('Serie', [0, ('Parallel', [5, ('Serie', [1, 4, 3, 2]), 6])])
89
90
91
REFERENCES:
92
93
.. [FMDecb] Fabien de Montgolfier
94
http://www.liafa.jussieu.fr/~fm/algos/index.html
95
96
.. [HabibViennot1999b] Michel Habib, Christiphe Paul, Laurent Viennot
97
Partition refinement techniques: An interesting algorithmic tool kit
98
International Journal of Foundations of Computer Science
99
vol. 10 n2 pp.147--170, 1999
100
101
.. [CapHabMont02b] C. Capelle, M. Habib et F. de Montgolfier
102
Graph decomposition and Factorising Permutations
103
Discrete Mathematics and Theoretical Computer Sciences, vol 5 no. 1 , 2002.
104
"""
105
cdef c_graphe G
106
cdef c_adj * a
107
cdef c_noeud * R
108
109
cdef dict label_id = {}
110
111
cdef int i
112
cdef int j
113
114
# Building the dictionary associating id to labels
115
for id,label in enumerate(g.vertices()):
116
label_id[label] = id
117
118
G.n = g.order()
119
G.G = <c_adj **> sage_malloc(G.n*sizeof(c_adj *))
120
121
memset( G.G, 0, G.n*sizeof(c_adj *))
122
123
# Creating the graph structure
124
for u,v in g.edges(labels = False):
125
126
i = label_id[u]
127
j = label_id[v]
128
129
a=<c_adj *> sage_malloc(sizeof(c_adj))
130
a.s = j
131
a.suiv = G.G[i]
132
G.G[i] = a
133
134
a=<c_adj *> sage_malloc(sizeof(c_adj))
135
a.s = i
136
a.suiv = G.G[j]
137
G.G[j] = a
138
139
140
R = decomposition_modulaire(G)
141
142
return build_dict_from_decomposition(R)
143
144
cdef build_dict_from_decomposition(c_noeud * N):
145
r"""
146
Returns the dictionary corresponding to a decomposition
147
"""
148
149
# recursively building the decomposition
150
151
cdef c_fils *ffils
152
cdef c_noeud *nfils
153
cdef int i
154
155
ffils = N.fils
156
157
cdef list value = []
158
159
while ffils != NULL:
160
161
nfils = <c_noeud *> ffils.pointe
162
if nfils.type == FEUILLE:
163
value.append(nfils.nom)
164
else:
165
value.append(build_dict_from_decomposition(nfils))
166
167
ffils = ffils.suiv
168
169
return (codes[N.type], value)
170
171