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
55 import Gargantext.Prelude
56 import Data.List (sortOn, nub, concat, length)
58 import Data.Set (fromList, toList, isSubsetOf)
59 import Data.Graph.Inductive hiding (Graph, neighbors, subgraph, (&))
60 import Gargantext.Viz.Graph.FGL (Graph_Undirected, degree, neighbors, mkGraphUfromEdges)
63 type Graph = Graph_Undirected
70 -- pré-filtre: spécifiques
71 -- soit conditionnelle, matrice spécifiques
72 -- combien de voisins maximum avant le calcul de cliques (les génériques)
74 -- calcul de densité/inclusion si graph gros
76 -- FIS: ensemble de termes un niveau du document
77 -- maxclique: ensemble de termes au niveau de l'ensemble du document
80 maxCliques' :: [[Text]] -> Map (Set Ngrams) Density
81 maxCliques' = undefined
85 maxCliques :: Graph -> [[Node]]
86 maxCliques g = map (\n -> subMaxCliques g (n:ns)) ns & concat & takeMax
89 ns = sortOn (degree g) $ nodes g
91 subMaxCliques :: Graph -> [Node] -> [[Node]]
92 subMaxCliques _ [] = [[]]
93 subMaxCliques g' (x:xs) = add x $ subMaxCliques g' ns'
95 ns' = [n | n <- xs, elem n $ neighborsOut g' x]
97 add :: Node -> [[Node]] -> [[Node]]
99 add n (m:ms) = [n:m] <> add n ms
100 -- | Note, it is same as :
101 -- add n ns = map (\m -> n : m) ns
102 -- -- (but using pattern matching and recursivity)
103 -- -- (map is redefined in fact)
105 -- | To be sure self is not in neighbors of self
106 -- (out to exclude the self)
107 neighborsOut :: Graph -> Node -> [Node]
108 neighborsOut g'' n = filter (/= n) $ neighbors g'' n
111 takeMax :: [[Node]] -> [[Node]]
118 purge :: [Set Node] -> [Set Node]
120 purge (x:xs) = x' <> purge xs
122 x' = if all (== False) (map (isSubsetOf x) xs)
127 ------------------------------------------------------------------------
129 -- test_graph = mkGraphUfromEdges [(1,1), (2,2), (3,3)]
130 test_graph = mkGraphUfromEdges [(1,2), (3,3)]
133 test_graph' = mkGraphUfromEdges [(1,2), (3,3), (3,2)]
135 test_graph'' :: Graph
136 test_graph'' = mkGraphUfromEdges [(1,2), (2,3), (1,3)]
138 test_graph''' :: Graph
139 test_graph''' = mkGraphUfromEdges [ (4,1)