]> Git — Sourcephile - gargantext.git/blob - src/Gargantext/Viz/Graph/Distances/Distributional.hs
[Phylo][Merge] Fix warnings and adding Eq instance to Phylo for Behavior test.
[gargantext.git] / src / Gargantext / Viz / Graph / Distances / Distributional.hs
1 {-|
2 Module : Gargantext.Graph.Distances.Distributional
3 Description :
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
8 Portability : POSIX
9
10 Motivation and definition of the @Distributional@ distance.
11 -}
12
13 {-# LANGUAGE BangPatterns #-}
14 {-# LANGUAGE NoImplicitPrelude #-}
15 {-# LANGUAGE FlexibleContexts #-}
16 {-# LANGUAGE Strict #-}
17
18
19 module Gargantext.Viz.Graph.Distances.Distributional
20 where
21
22 import Data.Matrix hiding (identity)
23
24 import qualified Data.Map as M
25
26 import Data.Vector (Vector)
27 import qualified Data.Vector as V
28
29 import Gargantext.Prelude
30 import Gargantext.Viz.Graph.Utils
31
32
33 distributional :: (Floating a, Ord a) => Matrix a -> [((Int, Int), a)]
34 distributional m = filter (\((x,y), d) -> foldl' (&&) True (conditions x y d) ) distriList
35 where
36 conditions x y d = [ (x /= y)
37 , (d > miniMax')
38 , ((M.lookup (x,y) distriMap) > (M.lookup (y,x) distriMap))
39 ]
40 distriList = toListsWithIndex distriMatrix
41 distriMatrix = ri (mi m)
42
43 distriMap = M.fromList $ distriList
44 miniMax' = miniMax distriMatrix
45
46 ri :: (Ord a, Fractional a) => Matrix a -> Matrix a
47 ri m = matrix c r doRi
48 where
49 doRi (x,y) = doRi' x y m
50 doRi' x y mi'' = sumMin x y mi'' / (V.sum $ ax Col x y mi'')
51
52 sumMin x y mi' = V.sum $ V.map (\(a,b) -> min a b )
53 $ V.zip (ax Col x y mi') (ax Row x y mi')
54 (c,r) = (nOf Col m, nOf Row m)
55
56
57 mi :: (Ord a, Floating a) => Matrix a -> Matrix a
58 mi m = matrix c r createMat
59 where
60 (c,r) = (nOf Col m, nOf Row m)
61 createMat (x,y) = doMi x y m
62 doMi x y m' = if x == y then 0 else (max (log (doMi' x y m')) 0 )
63
64 doMi' x y m' = (getElem x y m) / ( cross x y m / total m' )
65
66 cross x y m' = (V.sum $ ax Col x y m) * (V.sum $ ax Row x y m')
67
68
69
70 ax :: Axis -> Int -> Int -> Matrix a -> Vector a
71 ax a i j m = dropAt j' $ axis a i' m
72 where
73 i' = div i c + 1
74 j' = mod r j + 1
75 (c,r) = (nOf Col m, nOf Row m)
76
77 miniMax :: (Ord a) => Matrix a -> a
78 miniMax m = V.minimum $ V.map (\c -> V.maximum $ getCol c m) (V.enumFromTo 1 (nOf Col m))
79
80