11package clusters
22
33import (
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+
1318type 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
246255func (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
339392func (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