Skip to content

Commit e09aa9c

Browse files
committed
Finished ExtractClusters
1 parent aac20d4 commit e09aa9c

1 file changed

Lines changed: 66 additions & 11 deletions

File tree

optics.go

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package clusters
22

33
import (
4+
"fmt"
45
"math"
56
"sync"
67
)
@@ -10,13 +11,16 @@ type steepDownArea struct {
1011
mib float64
1112
}
1213

14+
type clusterBounds struct {
15+
start, end int
16+
}
17+
1318
type opticsClusterer struct {
1419
minpts int
1520
workers int
1621
eps float64
1722

18-
// 1 - xi
19-
x float64
23+
xi, x float64
2024

2125
distance DistanceFunc
2226

@@ -76,6 +80,7 @@ func OPTICS(minpts int, eps, xi float64, workers int, distance DistanceFunc) (Ha
7680
minpts: minpts,
7781
workers: workers,
7882
eps: eps,
83+
xi: xi,
7984
x: 1 - xi,
8085
distance: d,
8186
}, nil
@@ -115,12 +120,16 @@ func (c *opticsClusterer) Learn(data [][]float64) error {
115120

116121
c.endWorkers()
117122

123+
fmt.Printf("Done running\n")
124+
118125
c.v = nil
119126
c.p = nil
120127
c.r = nil
121128

122129
c.extract()
123130

131+
fmt.Printf("Done extracting\n")
132+
124133
c.re = nil
125134
c.so = nil
126135

@@ -245,13 +254,15 @@ func (c *opticsClusterer) update(p int, d float64, l *int, r *[]int, q *priority
245254

246255
func (c *opticsClusterer) extract() {
247256
var (
248-
i, e int
249-
mib float64
250-
areas []*steepDownArea = make([]*steepDownArea, 0)
257+
i, e, us, ue, cs, ce, s int
258+
mib, d float64
259+
areas []*steepDownArea = make([]*steepDownArea, 0)
260+
clusters map[int]*clusterBounds = make(map[int]*clusterBounds)
251261
)
252262

253263
for i < c.l-1 {
254264
if c.re[c.so[i]] == nil || c.re[c.so[i+1]] == nil {
265+
i++
255266
continue
256267
}
257268

@@ -279,8 +290,10 @@ func (c *opticsClusterer) extract() {
279290

280291
i = e + 1
281292
mib = c.re[c.so[i]].p
282-
283293
} else if c.isSteepUp(i, &e) {
294+
us = i
295+
ue = e + 1
296+
284297
as := areas[:0]
285298
for j := 0; j < len(areas); j++ {
286299
if c.re[c.so[areas[j].start]].p*c.x < mib {
@@ -299,7 +312,45 @@ func (c *opticsClusterer) extract() {
299312
mib = c.re[c.so[i]].p
300313

301314
for j := 0; j < len(areas); j++ {
302-
// check for cluster satisfying conditions outlined by Ankerst at al.
315+
if c.re[c.so[ue]].p*c.x < areas[j].mib {
316+
continue
317+
}
318+
319+
d = (c.re[c.so[areas[j].start]].p - c.re[c.so[ue]].p) / c.re[c.so[areas[j].start]].p
320+
321+
if math.Abs(d) <= c.xi {
322+
cs = areas[j].start
323+
ce = ue
324+
} else if d > c.xi {
325+
for k := areas[j].end; k > areas[j].end; k-- {
326+
if math.Abs((c.re[c.so[k]].p-c.re[c.so[ue]].p)/c.re[c.so[k]].p) <= c.xi {
327+
cs = k
328+
break
329+
}
330+
}
331+
ce = ue
332+
} else {
333+
cs = areas[j].start
334+
for k := us; k < ue-1; k++ {
335+
if math.Abs((c.re[c.so[k]].p-c.re[c.so[us]].p)/c.re[c.so[k]].p) <= c.xi {
336+
ce = k
337+
break
338+
}
339+
}
340+
}
341+
342+
if ce-cs < c.minpts {
343+
continue
344+
}
345+
346+
s = cs + ce
347+
348+
if _, ok := clusters[s]; !ok {
349+
clusters[s] = &clusterBounds{
350+
start: cs,
351+
end: ce,
352+
}
353+
}
303354
}
304355
} else {
305356
i++
@@ -317,7 +368,7 @@ func (c *opticsClusterer) isSteepDown(i int, e *int) bool {
317368
*e = j
318369

319370
for {
320-
if c.re[c.so[j]].p < c.re[c.so[j+1]].p {
371+
if c.re[c.so[j+1]] == nil || c.re[c.so[j]].p < c.re[c.so[j+1]].p {
321372
break
322373
}
323374

@@ -331,9 +382,11 @@ func (c *opticsClusterer) isSteepDown(i int, e *int) bool {
331382
if counter > c.minpts {
332383
break
333384
}
385+
386+
j++
334387
}
335388

336-
return *e != j
389+
return *e != i+1
337390
}
338391

339392
func (c *opticsClusterer) isSteepUp(i int, e *int) bool {
@@ -346,7 +399,7 @@ func (c *opticsClusterer) isSteepUp(i int, e *int) bool {
346399
*e = j
347400

348401
for {
349-
if c.re[c.so[j]].p > c.re[c.so[j+1]].p {
402+
if c.re[c.so[j+1]] == nil || c.re[c.so[j]].p > c.re[c.so[j+1]].p {
350403
break
351404
}
352405

@@ -360,9 +413,11 @@ func (c *opticsClusterer) isSteepUp(i int, e *int) bool {
360413
if counter > c.minpts {
361414
break
362415
}
416+
417+
j++
363418
}
364419

365-
return *e != j
420+
return *e != i+1
366421
}
367422

368423
/* Divide work among c.s workers, where c.s is determined

0 commit comments

Comments
 (0)