1 {-| Module : Gargantext.Viz.Graph.MaxClique
2 Description : MaxCliques function
3 Copyright : (c) CNRS, 2017-Present
4 License : AGPL + CECILL v3
5 Maintainer : team@gargantext.org
6 Stability : experimental
9 - First written by Bruno Gaume in Python (see below for details)
10 - Then written by Alexandre Delanoë in Haskell (see below for details)
13 def fast_maximal_cliques(g):
15 def rec_maximal_cliques(g, subv):
17 if subv == []: # stop condition
20 for i in range(len(subv)):
21 newsubv = [j for j in subv[i+1:len(subv)]
22 if (j in g.neighbors(subv[i]))]
23 mci = rec_maximal_cliques(g, newsubv)
30 clustset = [set(x) for x in clust]
32 for i in range(len(clustset)):
34 for j in range(len(clustset)):
35 if clustset[i].issubset(clustset[j]) and (not (len(clustset[i]) == len(clustset[j])) ):
37 if ok and (not (clustset[i] in new_clust)):
38 new_clust.append(clustset[i])
39 return [list(x) for x in new_clust]
41 # to optimize : rank the vertices on the degrees
42 subv = [(v.index, v.degree()) for v in g.vs()]
43 subv.sort(key = lambda z:z[1])
44 subv = [x for (x, y) in subv]
45 return purge(rec_maximal_cliques(g, subv))
50 {-# LANGUAGE NoImplicitPrelude #-}
52 module Gargantext.Viz.Graph.MaxClique where
54 import Gargantext.Prelude
55 import Data.List (sortOn, nub, concat, length)
57 import Data.Set (fromList, toList, isSubsetOf)
58 import Data.Graph.Inductive hiding (Graph, neighbors, subgraph, (&))
59 import Gargantext.Viz.Graph.FGL (Graph_Undirected, degree, neighbors, mkGraphUfromEdges)
63 type Graph = Graph_Undirected
66 maxCliques :: Graph -> [[Node]]
67 maxCliques g = map (\n -> subMaxCliques g (n:ns)) ns & concat & takeMax
70 ns = sortOn (degree g) $ nodes g
72 subMaxCliques :: Graph -> [Node] -> [[Node]]
73 subMaxCliques _ [] = [[]]
74 subMaxCliques g' (x:xs) = add x $ subMaxCliques g' ns'
76 ns' = [n | n <- xs, elem n $ neighborsOut g' x]
78 add :: Node -> [[Node]] -> [[Node]]
80 add n (m:ms) = [n:m] <> add n ms
81 -- | Note, it is same as :
82 -- add n ns = map (\m -> n : m) ns
83 -- -- (but using pattern matching and recursivity)
84 -- -- (map is redefined in fact)
86 -- | To be sure self is not in neighbors of self
87 -- (out to exclude the self)
88 neighborsOut :: Graph -> Node -> [Node]
89 neighborsOut g'' n = filter (/= n) $ neighbors g'' n
92 takeMax :: [[Node]] -> [[Node]]
93 takeMax = map toList . purge . map fromList . sortOn length . nub
95 purge :: [Set Node] -> [Set Node]
97 purge (x:xs) = x' <> purge xs
99 x' = if all (== False) (map (isSubsetOf x) xs)
104 ------------------------------------------------------------------------
106 -- test_graph = mkGraphUfromEdges [(1,1), (2,2), (3,3)]
107 test_graph = mkGraphUfromEdges [(1,2), (3,3)]
110 test_graph' = mkGraphUfromEdges [(1,2), (3,3), (3,2)]
112 test_graph'' :: Graph
113 test_graph'' = mkGraphUfromEdges [(1,2), (2,3), (1,3)]
115 test_graph''' :: Graph
116 test_graph''' = mkGraphUfromEdges [ (4,1)