Skip to content

Commit e76fb63

Browse files
committed
replaced M window field with W
1 parent 5124a4e commit e76fb63

File tree

6 files changed

+156
-156
lines changed

6 files changed

+156
-156
lines changed

kmp.go

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,22 @@ type KMP struct {
2323
tStd [][]float64 // sliding standard deviation of each timeseries with a window of m each
2424
tF [][]complex128 // holds an existing calculation of the FFT for each timeseries
2525
n int // length of the timeseries
26-
M int // length of a subsequence
26+
W int // length of a subsequence
2727
MP [][]float64 // matrix profile
2828
Idx [][]int // matrix profile index
2929
}
3030

3131
// NewKMP creates a matrix profile struct specifically to be used with the k dimensional
3232
// matrix profile computation. The number of rows represents the number of dimensions,
3333
// and each row holds a series of points of equal length as each other.
34-
func NewKMP(t [][]float64, m int) (*KMP, error) {
34+
func NewKMP(t [][]float64, w int) (*KMP, error) {
3535
if t == nil || len(t) == 0 {
3636
return nil, fmt.Errorf("slice is nil or has a length of 0 dimensions")
3737
}
3838

3939
k := KMP{
4040
T: t,
41-
M: m,
41+
W: w,
4242
n: len(t[0]),
4343
}
4444

@@ -49,11 +49,11 @@ func NewKMP(t [][]float64, m int) (*KMP, error) {
4949
}
5050
}
5151

52-
if k.M*2 >= k.n {
52+
if k.W*2 >= k.n {
5353
return nil, fmt.Errorf("subsequence length must be less than half the timeseries")
5454
}
5555

56-
if k.M < 2 {
56+
if k.W < 2 {
5757
return nil, fmt.Errorf("subsequence length must be at least 2")
5858
}
5959

@@ -63,15 +63,15 @@ func NewKMP(t [][]float64, m int) (*KMP, error) {
6363
k.MP = make([][]float64, len(t))
6464
k.Idx = make([][]int, len(t))
6565
for d := 0; d < len(t); d++ {
66-
k.tMean[d] = make([]float64, k.n-k.M+1)
67-
k.tStd[d] = make([]float64, k.n-k.M+1)
68-
k.tF[d] = make([]complex128, k.n-k.M+1)
69-
k.MP[d] = make([]float64, k.n-k.M+1)
70-
k.Idx[d] = make([]int, k.n-k.M+1)
66+
k.tMean[d] = make([]float64, k.n-k.W+1)
67+
k.tStd[d] = make([]float64, k.n-k.W+1)
68+
k.tF[d] = make([]complex128, k.n-k.W+1)
69+
k.MP[d] = make([]float64, k.n-k.W+1)
70+
k.Idx[d] = make([]int, k.n-k.W+1)
7171
}
7272

7373
for d := 0; d < len(t); d++ {
74-
for i := 0; i < k.n-k.M+1; i++ {
74+
for i := 0; i < k.n-k.W+1; i++ {
7575
k.MP[d][i] = math.Inf(1)
7676
k.Idx[d][i] = math.MaxInt64
7777
}
@@ -136,7 +136,7 @@ func (k *KMP) initCaches() error {
136136
// precompute the mean and standard deviation for each window of size m for all
137137
// sliding windows across the b timeseries
138138
for d := 0; d < len(k.T); d++ {
139-
k.tMean[d], k.tStd[d], err = util.MovMeanStd(k.T[d], k.M)
139+
k.tMean[d], k.tStd[d], err = util.MovMeanStd(k.T[d], k.W)
140140
if err != nil {
141141
return err
142142
}
@@ -170,36 +170,36 @@ func (k *KMP) mStomp() error {
170170
var D [][]float64
171171
D = make([][]float64, len(k.T))
172172
for d := 0; d < len(D); d++ {
173-
D[d] = make([]float64, k.n-k.M+1)
173+
D[d] = make([]float64, k.n-k.W+1)
174174
}
175175

176176
dots := make([][]float64, len(k.T))
177177
for d := 0; d < len(dots); d++ {
178-
dots[d] = make([]float64, k.n-k.M+1)
178+
dots[d] = make([]float64, k.n-k.W+1)
179179
copy(dots[d], cachedDots[d])
180180
}
181181

182-
for idx := 0; idx < k.n-k.M+1; idx++ {
182+
for idx := 0; idx < k.n-k.W+1; idx++ {
183183
for d := 0; d < len(dots); d++ {
184184
if idx > 0 {
185-
for j := k.n - k.M; j > 0; j-- {
186-
dots[d][j] = dots[d][j-1] - k.T[d][j-1]*k.T[d][idx-1] + k.T[d][j+k.M-1]*k.T[d][idx+k.M-1]
185+
for j := k.n - k.W; j > 0; j-- {
186+
dots[d][j] = dots[d][j-1] - k.T[d][j-1]*k.T[d][idx-1] + k.T[d][j+k.W-1]*k.T[d][idx+k.W-1]
187187
}
188188
dots[d][0] = cachedDots[d][idx]
189189
}
190190

191-
for i := 0; i < k.n-k.M+1; i++ {
192-
D[d][i] = math.Sqrt(2 * float64(k.M) * math.Abs(1-(dots[d][i]-float64(k.M)*k.tMean[d][i]*k.tMean[d][idx])/(float64(k.M)*k.tStd[d][i]*k.tStd[d][idx])))
191+
for i := 0; i < k.n-k.W+1; i++ {
192+
D[d][i] = math.Sqrt(2 * float64(k.W) * math.Abs(1-(dots[d][i]-float64(k.W)*k.tMean[d][i]*k.tMean[d][idx])/(float64(k.W)*k.tStd[d][i]*k.tStd[d][idx])))
193193
}
194194
// sets the distance in the exclusion zone to +Inf
195-
util.ApplyExclusionZone(D[d], idx, k.M/2)
195+
util.ApplyExclusionZone(D[d], idx, k.W/2)
196196
}
197197

198198
k.columnWiseSort(D)
199199
k.columnWiseCumSum(D)
200200

201201
for d := 0; d < len(D); d++ {
202-
for i := 0; i < k.n-k.M+1; i++ {
202+
for i := 0; i < k.n-k.W+1; i++ {
203203
if D[d][i]/(float64(d)+1) < k.MP[d][i] {
204204
k.MP[d][i] = D[d][i] / (float64(d) + 1)
205205
k.Idx[d][i] = idx
@@ -222,8 +222,8 @@ func (k KMP) crossCorrelate(idx int, fft *fourier.FFT, D [][]float64) {
222222
var dot []float64
223223

224224
for d := 0; d < len(D); d++ {
225-
for i := 0; i < k.M; i++ {
226-
qpad[i] = k.T[d][idx+k.M-i-1]
225+
for i := 0; i < k.W; i++ {
226+
qpad[i] = k.T[d][idx+k.W-i-1]
227227
}
228228
qf = fft.Coefficients(nil, qpad)
229229

@@ -235,16 +235,16 @@ func (k KMP) crossCorrelate(idx int, fft *fourier.FFT, D [][]float64) {
235235

236236
dot = fft.Sequence(nil, qf)
237237

238-
for i := 0; i < k.n-k.M+1; i++ {
239-
dot[k.M-1+i] = dot[k.M-1+i] / float64(k.n)
238+
for i := 0; i < k.n-k.W+1; i++ {
239+
dot[k.W-1+i] = dot[k.W-1+i] / float64(k.n)
240240
}
241-
D[d] = dot[k.M-1:]
241+
D[d] = dot[k.W-1:]
242242
}
243243
}
244244

245245
func (k KMP) columnWiseSort(D [][]float64) {
246246
dist := make([]float64, len(D))
247-
for i := 0; i < k.n-k.M+1; i++ {
247+
for i := 0; i < k.n-k.W+1; i++ {
248248
for d := 0; d < len(D); d++ {
249249
dist[d] = D[d][i]
250250
}
@@ -259,7 +259,7 @@ func (k KMP) columnWiseCumSum(D [][]float64) {
259259
for d := 0; d < len(D); d++ {
260260
// change D to be a cumulative sum of distances across dimensions
261261
if d > 0 {
262-
for i := 0; i < k.n-k.M+1; i++ {
262+
for i := 0; i < k.n-k.W+1; i++ {
263263
D[d][i] += D[d-1][i]
264264
}
265265
}

kmp_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
func TestNewKMP(t *testing.T) {
1212
testdata := []struct {
1313
t [][]float64
14-
m int
14+
w int
1515
expectedErr bool
1616
}{
1717
{[][]float64{}, 2, true},
@@ -22,7 +22,7 @@ func TestNewKMP(t *testing.T) {
2222
}
2323

2424
for _, d := range testdata {
25-
_, err := NewKMP(d.t, d.m)
25+
_, err := NewKMP(d.t, d.w)
2626
if d.expectedErr && err == nil {
2727
t.Errorf("Expected an error, but got none for %v", d)
2828
}
@@ -38,7 +38,7 @@ func TestKCrossCorrelate(t *testing.T) {
3838

3939
testdata := []struct {
4040
t [][]float64
41-
m int
41+
w int
4242
expected [][]float64
4343
}{
4444
{[][]float64{{1, 1, 1, 1, 1}}, 2, [][]float64{{2, 2, 2, 2}}},
@@ -55,7 +55,7 @@ func TestKCrossCorrelate(t *testing.T) {
5555
}
5656

5757
for _, d := range testdata {
58-
mp, err = NewKMP(d.t, d.m)
58+
mp, err = NewKMP(d.t, d.w)
5959
if err != nil {
6060
if d.expected == nil {
6161
// Got an error while creating a new matrix profile
@@ -113,15 +113,15 @@ func TestColumnWiseSort(t *testing.T) {
113113
}
114114

115115
for _, d := range testdata {
116-
mp := &KMP{M: 5, n: 7}
116+
mp := &KMP{W: 5, n: 7}
117117
mp.columnWiseSort(d.d)
118118

119119
if len(d.d) != len(d.expectedD) {
120120
t.Errorf("Expected %d dimensions, but got %d, %+v", len(d.expectedD), len(d.d), d)
121121
break
122122
}
123123
for dim := 0; dim < len(d.d); dim++ {
124-
for i := 0; i < mp.n-mp.M-1; i++ {
124+
for i := 0; i < mp.n-mp.W-1; i++ {
125125
if math.Abs(d.d[dim][i]-d.expectedD[dim][i]) > 1e-7 {
126126
t.Errorf("Expected\n%.4f, but got\n%.4f for\n%+v", d.expectedD[dim], d.d[dim], d)
127127
break
@@ -183,7 +183,7 @@ func TestMStomp(t *testing.T) {
183183
t.Errorf("Expected %d dimensions, but got %d, %+v", len(d.expectedMP), len(mp.MP), d)
184184
}
185185
for dim := 0; dim < len(d.t); dim++ {
186-
for i := 0; i < mp.n-mp.M-1; i++ {
186+
for i := 0; i < mp.n-mp.W-1; i++ {
187187
if math.Abs(mp.MP[dim][i]-d.expectedMP[dim][i]) > 1e-7 {
188188
for dd := 0; dd < len(d.t); dd++ {
189189
t.Errorf("Expected\n%.12f, but got\n%.12f for\n%+v", d.expectedMP[dd], mp.MP[dd], d)
@@ -212,8 +212,8 @@ func TestKMPSave(t *testing.T) {
212212

213213
func TestKMPLoad(t *testing.T) {
214214
ts := [][]float64{{1, 2, 3, 4, 5, 6, 7, 8, 9}}
215-
m := 3
216-
p, err := NewKMP(ts, m)
215+
w := 3
216+
p, err := NewKMP(ts, w)
217217
p.Compute()
218218
filepath := "./kmp.json"
219219
if err = p.Save(filepath, "json"); err != nil {
@@ -229,8 +229,8 @@ func TestKMPLoad(t *testing.T) {
229229
t.Errorf("Could not remove file, %s, %v", filepath, err)
230230
}
231231

232-
if newP.M != m {
233-
t.Errorf("Expected m of %d, but got %d", m, newP.M)
232+
if newP.W != w {
233+
t.Errorf("Expected window of %d, but got %d", w, newP.W)
234234
}
235235
if len(newP.T) != len(ts) {
236236
t.Errorf("Expected timeseries length of %d, but got %d", len(ts), len(newP.T))

0 commit comments

Comments
 (0)