Skip to content

Instantly share code, notes, and snippets.

@lucidjargon
Created May 26, 2012 23:18
Show Gist options
  • Save lucidjargon/2795591 to your computer and use it in GitHub Desktop.
Save lucidjargon/2795591 to your computer and use it in GitHub Desktop.
Brownian Distance Covariance as described in http://arxiv.org/pdf/0803.4101.pdf for scalar values. Extensible to vector valued variables with a few character strokes
let foldRow2D, foldCol2D = 1, 0
let inline (@@) (m: 'a [,]) index = Array.Parallel.init (m.GetLength(1)) (fun i -> m.[index, i])
let inline (@@@) (m: 'a [,]) index = Array.Parallel.init (m.GetLength(0)) (fun i -> m.[i, index])
let inline cIndex ind k i (m:'a [,]) = if ind = 1 then m.[k,i] else m.[i,k]
let arr2DFoldAt r k (m : 'a [,]) f seed =
let top = m.GetLength(r)
let rec fold state = function
| i when i = top -> state
| i -> fold (f state (cIndex r k i m)) (i + 1)
fold seed 0
let arr2DFold (m : 'a [,]) f seed =
let top = m.GetLength(0)
let rec fold state = function | i when i = top -> state
| i -> fold (arr2DFoldAt 1 i m f state) (i+1)
fold seed 0
let distCov (v1:float[]) (v2:float[]) same =
let n = v1.Length
let nf = float n
let denum = nf ** 2.
let distMatrix (v:float[]) = Array2D.init v.Length v.Length (fun k l -> abs (v.[k] - v.[l]))
let rowMean (m:float[,]) k = (arr2DFoldAt 1 k m (+) 0.)/nf
let colMean (m:float[,]) l = (arr2DFoldAt 0 l m (+) 0.)/nf
let matrixMean (m:float[,]) = (arr2DFold m (+) 0.) / denum
let centredDist (v:float[]) =
let distm = distMatrix v
let meanoverall = matrixMean distm
let C = Array2D.create n n 0.
Threading.Tasks.Parallel.For(0, n, fun i ->
let curRowMean = rowMean distm i
for j in 0..n - 1 do
C.[i,j] <- distm.[i,j] - curRowMean - (colMean distm j) + meanoverall ) |> ignore
C
let A,B =
if same then let A2 = centredDist v1 in A2, A2
else let AB = [| async {return centredDist v1}
async {return centredDist v2} |] |> Async.Parallel |> Async.RunSynchronously
AB.[0], AB.[1]
let _,_,msum = arr2DFold A (fun (i,j,curSum) value -> let nsum = value * B.[i,j] + curSum
if j = n - 1 then i+1, 0,nsum else i, j+1,nsum) (0,0,0.)
msum / denum
let distCorr v1 v2 =
let VXY = [| async { return distCov v1 v1 true }
async { return distCov v2 v2 true} |] |> Async.Parallel |> Async.RunSynchronously
let vsig = VXY.[0] * VXY.[1]
if vsig = 0. then 0.
else sqrt((distCov v1 v2 false) / sqrt vsig)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment