Skip to content

Commit 57f2cba

Browse files
committed
energy stats algorithm and test
1 parent 54d4289 commit 57f2cba

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

internal/cmd/perfcomp/energystatistics.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,42 @@
55
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
66

77
package main
8+
9+
import (
10+
"math"
11+
12+
"gonum.org/v1/gonum/mat"
13+
)
14+
15+
// Given two matrices, this function returns
16+
// (e, t, h) = (E-statistic, test statistic, e-coefficient of inhomogeneity)
17+
func getEnergyStatistics(x, y *mat.Dense) (float64, float64, float64) {
18+
n, _ := x.Dims()
19+
m, _ := y.Dims()
20+
nf := float64(n)
21+
mf := float64(m)
22+
A := getDistance(x, y) / (nf * mf) // E|X-Y|
23+
B := getDistance(x, x) / (nf * nf) // E|X-X'|
24+
C := getDistance(y, y) / (mf * mf) // E|Y-Y'|
25+
26+
E := 2*A - B - C // D^2(F_x, F_y)
27+
T := ((nf * mf) / (nf + mf)) * E
28+
H := E / (2 * A)
29+
return E, T, H
30+
}
31+
32+
// Given two vectors (expected 1 col),
33+
// this function returns the sum of distances between each pair.
34+
func getDistance(x, y *mat.Dense) float64 {
35+
xrows, _ := x.Dims()
36+
yrows, _ := y.Dims()
37+
38+
var sum float64
39+
40+
for i := 0; i < xrows; i++ {
41+
for j := 0; j < yrows; j++ {
42+
sum += math.Sqrt(math.Pow((x.At(i, 0) - y.At(j, 0)), 2))
43+
}
44+
}
45+
return sum
46+
}

internal/cmd/perfcomp/energystatistics_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,65 @@
55
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
66

77
package main
8+
9+
import (
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
"gonum.org/v1/gonum/mat"
14+
)
15+
16+
func createTestVectors(start1 int, stop1 int, step1 int, start2 int, stop2 int, step2 int) (*mat.Dense, *mat.Dense) {
17+
xData := []float64{}
18+
i := start1
19+
for i < stop1 {
20+
xData = append(xData, float64(i))
21+
i += step1
22+
}
23+
24+
yData := []float64{}
25+
j := start2
26+
for j < stop2 {
27+
yData = append(yData, float64(j))
28+
j += step2
29+
}
30+
31+
x := mat.NewDense(len(xData), 1, xData)
32+
y := mat.NewDense(len(yData), 1, yData)
33+
34+
return x, y
35+
}
36+
37+
func TestEnergyStatistics(t *testing.T) {
38+
39+
t.Run("similar distributions should have small e,t,h values ", func(t *testing.T) {
40+
x, y := createTestVectors(1, 100, 1, 1, 105, 1)
41+
e, tstat, h := getEnergyStatistics(x, y)
42+
43+
del := 1e-3
44+
45+
assert.InDelta(t, 0.160, e, del) // |0.160 - e| < 1/100
46+
assert.InDelta(t, 8.136, tstat, del)
47+
assert.InDelta(t, 0.002, h, del)
48+
})
49+
50+
t.Run("different distributions should have large e,t,h values", func(t *testing.T) {
51+
x, y := createTestVectors(1, 100, 1, 10000, 13000, 14)
52+
e, tstat, h := getEnergyStatistics(x, y)
53+
del := 1e-3
54+
55+
assert.InDelta(t, 21859.691, e, del)
56+
assert.InDelta(t, 1481794.709, tstat, del)
57+
assert.InDelta(t, 0.954, h, del)
58+
})
59+
60+
t.Run("uni-variate distributions", func(t *testing.T) {
61+
x, y := createTestVectors(1, 300, 1, 1000, 5000, 10)
62+
e, tstat, h := getEnergyStatistics(x, y)
63+
del := 1e-3
64+
65+
assert.InDelta(t, 4257.009, e, del)
66+
assert.InDelta(t, 1481794.709, tstat, del)
67+
assert.InDelta(t, 0.954, h, del)
68+
})
69+
}

0 commit comments

Comments
 (0)