2 Module : Gargantext.Core.Viz.Graph.Bridgeness
3 Description : Bridgeness filter
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
10 Let be a graph with partitions (from Louvain algo), Bridgeness uniformly
11 filters inter-communities links.
13 TODO rewrite Bridgeness with "equivalence structurale" metrics (Confluence)
14 TODO use Map LouvainNodeId (Map LouvainNodeId)
18 module Gargantext.Core.Viz.Graph.Bridgeness -- (bridgeness)
21 import Data.List (concat, sortOn)
22 import Data.Map (Map, fromListWith, lookup, toList, mapWithKey, elems)
23 import Data.Maybe (catMaybes)
24 import Data.Ord (Down(..))
25 import Gargantext.Prelude
26 import Graph.Types (ClusterNode(..))
27 import qualified Data.Map as DM
31 ----------------------------------------------------------------------
32 type Partitions a = Map (Int, Int) Double -> IO [a]
33 ----------------------------------------------------------------------
35 nodeId2comId :: a -> (NodeId,CommunityId)
38 type CommunityId = Int
40 ----------------------------------------------------------------------
41 instance ToComId ClusterNode where
42 nodeId2comId (ClusterNode i1 i2) = (i1, i2)
44 ----------------------------------------------------------------------
45 ----------------------------------------------------------------------
46 type Bridgeness = Double
48 bridgeness :: ToComId a => Bridgeness
50 -> Map (NodeId, NodeId) Double
51 -> Map (NodeId, NodeId) Double
52 bridgeness = bridgeness' nodeId2comId
55 bridgeness' :: (a -> (Int, Int))
58 -> Map (Int, Int) Double
59 -> Map (Int, Int) Double
60 bridgeness' f b ns = DM.fromList
64 . groupEdges (DM.fromList $ map f ns)
67 groupEdges :: (Ord a, Ord b1)
70 -> Map (a, a) [((b1, b1), b2)]
71 groupEdges m = fromListWith (<>)
75 n1n2_m = (,) <$> lookup n1 m <*> lookup n2 m
76 n1n2_d = Just [((n1,n2),d)]
77 in (,) <$> n1n2_m <*> n1n2_d
81 -- | TODO : sortOn Confluence
82 filterComs :: (Ord n1, Eq n2)
84 -> Map (n2, n2) [(a3, n1)]
85 -> Map (n2, n2) [(a3, n1)]
86 filterComs _b m = DM.filter (\n -> length n > 0) $ mapWithKey filter' m
91 | otherwise = take 1 $ sortOn (Down . snd) a
94 _n = round $ 100 * a' / t
95 a'= fromIntegral $ length a
97 t = fromIntegral $ length $ concat $ elems m