Path: blob/master/sage/graphs/modular_decomposition/modular_decomposition.pyx
4057 views
r"""1Modular decomposition2"""34#####################################################5# The following code is mainly a Cythonized6# copy of code found in src/random.c and src/dm.c7#####################################################89############################10# CONSTANTS11############################1213cdef int FEUILLE = 0 # the node is a leaf14cdef int UNKN = 115cdef int MODULE = 216cdef int ARTEFACT = 317cdef int SERIE = 4 # series composition18cdef int PARALLELE = 5 # parallel composition19cdef int PREMIER = 6 # prime composition2021cdef dict codes = {22UNKN: "Node",23MODULE: "Module",24ARTEFACT: "Artefact",25SERIE: "Serie",26PARALLELE: "Parallel",27PREMIER: "Prime"28}2930cpdef modular_decomposition(g):31r"""32Returns a modular decomposition of the given graph.3334INPUT:3536- ``g`` -- a graph3738OUTPUT:3940A pair of two values (recursively encoding the decomposition) :4142* The type of the current module :4344* ``"Parallel"``45* ``"Prime"``46* ``"Serie"``4748* The list of submodules (as list of pairs ``(type, list)``,49recursively...) or the vertex's name if the module is a50singleton.5152.. NOTE::5354As this fuction could be used by efficient C routines, the55vertices returned are not labels but identifiants from ``[0,56..., g.order()-1]``5758ALGORITHM:5960This function uses a C implementation of a 2-step algorithm61implemented by Fabien de Montgolfier [FMDecb]_ :6263* Computation of a factorizing permutation [HabibViennot1999b]_.6465* Computation of the tree itself [CapHabMont02b]_.6667EXAMPLES:6869The Bull Graph is prime::7071sage: from sage.graphs.modular_decomposition.modular_decomposition import modular_decomposition72sage: modular_decomposition(graphs.BullGraph())73('Prime', [3, 4, 0, 1, 2])7475The Petersen Graph too::7677sage: modular_decomposition(graphs.PetersenGraph())78('Prime', [2, 6, 3, 9, 7, 8, 0, 1, 5, 4])7980This a clique on 5 vertices with 2 pendant edges, though, has a more81interesting decomposition ::8283sage: g = graphs.CompleteGraph(5)84sage: g.add_edge(0,5)85sage: g.add_edge(0,6)86sage: modular_decomposition(g)87('Serie', [0, ('Parallel', [5, ('Serie', [1, 4, 3, 2]), 6])])888990REFERENCES:9192.. [FMDecb] Fabien de Montgolfier93http://www.liafa.jussieu.fr/~fm/algos/index.html9495.. [HabibViennot1999b] Michel Habib, Christiphe Paul, Laurent Viennot96Partition refinement techniques: An interesting algorithmic tool kit97International Journal of Foundations of Computer Science98vol. 10 n2 pp.147--170, 199999100.. [CapHabMont02b] C. Capelle, M. Habib et F. de Montgolfier101Graph decomposition and Factorising Permutations102Discrete Mathematics and Theoretical Computer Sciences, vol 5 no. 1 , 2002.103"""104cdef c_graphe G105cdef c_adj * a106cdef c_noeud * R107108cdef dict label_id = {}109110cdef int i111cdef int j112113# Building the dictionary associating id to labels114for id,label in enumerate(g.vertices()):115label_id[label] = id116117G.n = g.order()118G.G = <c_adj **> sage_malloc(G.n*sizeof(c_adj *))119120memset( G.G, 0, G.n*sizeof(c_adj *))121122# Creating the graph structure123for u,v in g.edges(labels = False):124125i = label_id[u]126j = label_id[v]127128a=<c_adj *> sage_malloc(sizeof(c_adj))129a.s = j130a.suiv = G.G[i]131G.G[i] = a132133a=<c_adj *> sage_malloc(sizeof(c_adj))134a.s = i135a.suiv = G.G[j]136G.G[j] = a137138139R = decomposition_modulaire(G)140141return build_dict_from_decomposition(R)142143cdef build_dict_from_decomposition(c_noeud * N):144r"""145Returns the dictionary corresponding to a decomposition146"""147148# recursively building the decomposition149150cdef c_fils *ffils151cdef c_noeud *nfils152cdef int i153154ffils = N.fils155156cdef list value = []157158while ffils != NULL:159160nfils = <c_noeud *> ffils.pointe161if nfils.type == FEUILLE:162value.append(nfils.nom)163else:164value.append(build_dict_from_decomposition(nfils))165166ffils = ffils.suiv167168return (codes[N.type], value)169170171