2 Module : Gargantext.Graph.Distances.Distributional
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
10 Motivation and definition of the @Conditional@ distance.
13 {-# LANGUAGE BangPatterns #-}
14 {-# LANGUAGE NoImplicitPrelude #-}
15 {-# LANGUAGE FlexibleContexts #-}
16 {-# LANGUAGE Strict #-}
19 module Gargantext.Graph.Distances.Distributional
22 import Data.Matrix hiding (identity)
23 import Data.String.Conversions (ConvertibleStrings(..))
26 import qualified Data.Map as M
29 import qualified Data.Set as S
31 import Data.Vector (Vector)
32 import qualified Data.Vector as V
34 import Gargantext.Prelude
35 import Gargantext.Graph.Utils
38 distributional :: (Floating a, Ord a) => Matrix a -> [((Int, Int), a)]
39 distributional m = filter (\((x,y), d) -> foldl' (&&) True (conditions x y d) ) distriList
41 conditions x y d = [ (x /= y)
43 , ((M.lookup (x,y) distriMap) > (M.lookup (y,x) distriMap))
45 distriList = toListsWithIndex distriMatrix
46 distriMatrix = ri (mi m)
48 distriMap = M.fromList $ distriList
49 miniMax' = miniMax distriMatrix
51 ri :: (Ord a, Fractional a) => Matrix a -> Matrix a
52 ri m = matrix c r doRi
54 doRi (x,y) = doRi' x y m
55 doRi' x y mi'' = sumMin x y mi'' / (V.sum $ ax Col x y mi'')
57 sumMin x y mi' = V.sum $ V.map (\(a,b) -> min a b )
58 $ V.zip (ax Col x y mi') (ax Row x y mi')
59 (c,r) = (nOf Col m, nOf Row m)
62 mi :: (Ord a, Floating a) => Matrix a -> Matrix a
63 mi m = matrix c r createMat
65 (c,r) = (nOf Col m, nOf Row m)
66 createMat (x,y) = doMi x y m
67 doMi x y m = if x == y then 0 else (nonNegative $ log (doMi' x y m))
69 doMi' x y m = (getElem x y m) / ( cross x y m / total m )
71 cross x y m = (V.sum $ ax Col x y m) * (V.sum $ ax Row x y m)
75 ax :: Axis -> Int -> Int -> Matrix a -> Vector a
76 ax a i j m = dropAt j' $ axis a i' m
80 (c,r) = (nOf Col m, nOf Row m)
82 nonNegative :: (Ord a, Num a) => a -> a
83 nonNegative x = if x > 0 then x else 0
85 miniMax :: (Ord a) => Matrix a -> a
86 miniMax m = V.minimum $ V.map (\c -> V.maximum $ getCol c m) (V.enumFromTo 1 (nOf Col m))