module TimeSeries.Correlation where
import Data.Array.Base
import Data.List (sort)
import TimeSeries.PRG64
import TimeSeries.Window (Window(..))
import qualified TimeSeries.Window as W
direct :: Window -> Window -> Double
direct (Window x) (Window y) = sigma_x_y_minus_means / sqrt_sigma_x_y_squared
where
sigma_x_y_minus_means =
sum [ (xix_mean)*(yiy_mean)
| (xi,yi) <- zip (elems x) (elems y)]
sqrt_sigma_x_y_squared = sqrt (sum xs' * sum ys') where
xs' = [square (xix_mean) | xi <- elems x]
ys' = [square (yiy_mean) | yi <- elems y]
x_mean = mean (elems x)
y_mean = mean (elems y)
sketch_naive ::
[Window]
-> Int
-> Window
-> Window
-> Double
sketch_naive rs sz (Window wx) (Window wy) = 1 (d'/len')
where
d' = sqrt $ sum ds
ds = [ square (xjyj)
| (xi,yi) <- zip skX skY
, let xj = (xiavg_x) / var_x
, let yj = (yiavg_y) / var_y
]
skX = [dotp (elems r) (elems wx)|Window r <- rs]
skY = [dotp (elems r) (elems wy)|Window r <- rs]
len' = 2 * (len x1)
avg_x = mean x
avg_y = mean y
var_x = (sum [square (xi avg_x)|xi<-x]) / sz'
var_y = (sum [square (yi avg_y)|yi<-y]) / sz'
x = elems wx
y = elems wy
sz' = fromIntegral sz
sketch ::
Window
-> Window
-> Double
sketch wx wy = 1 (d'/len') where
d' = sum [square (xy)|(x,y)<-zip (W.toList wx) (W.toList wy)]
len' = 2 * fromIntegral (W.length wx)
sketch_distance ::
Int
-> [Double]
-> [Double]
-> Double
sketch_distance d x w = median norms / sqrt (fromIntegral d) where
norms = map norm $ zipWith (zipWith ()) ys zs
median xs = sort xs !! (length xs `div` 2)
b = 8
m = length x
prg64s = chunks m $ concat $ prg64Bits (prg64Init 0x9834219)
(ys,zs) = foldr f ([],[]) [0..2*b] where
f n (yacc,zacc) =
let y = [dotp x r | r <- rs]
z = [dotp w r | r <- rs]
rs = take d $ drop (n*d) prg64s
in (y:yacc,z:zacc)
norm :: Floating a => [a] -> a
norm as = sqrt $ sum [square a|a <- as]
mean :: Fractional a => [a] -> a
mean zs = sum zs / len zs
stddev :: [Double] -> Double
stddev zs = sqrt (mean [square zi|zi<-zs] (square (mean zs)))
stddev' :: Window -> Double
stddev' (Window x) = stddev $ elems x
len :: Num b => [a] -> b
len zs = fromIntegral (length zs)
dotp :: Num a => [a] -> [a] -> a
dotp a b = sum $ zipWith (*) a b
chunks :: Int -> [a] -> [[a]]
chunks sz ys
| null ys = []
| otherwise = let (pre,post) = splitAt sz ys in pre : chunks sz post
square :: Fractional a => a -> a
square = (^ (2::Int))