Package stallone.cluster

Source Code of stallone.cluster.DensityBasedClusteringOPTICS$OrderedPointComparator

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package stallone.cluster;

import java.util.Comparator;
import java.util.PriorityQueue;
import stallone.api.cluster.INeighborSearch;
import stallone.api.datasequence.DataSequence;
import stallone.api.datasequence.IDataInput;
import stallone.api.datasequence.IDataList;
import stallone.api.datasequence.IDataSequence;
import stallone.api.doubles.Doubles;
import stallone.api.doubles.DoublesPrimitive;
import stallone.api.doubles.IDoubleArray;
import stallone.api.doubles.IMetric;
import stallone.api.ints.IIntArray;
import stallone.api.ints.Ints;
import stallone.doubles.EuclideanDistance;

/**
* Density-based clustering algorithm OPTICS:
*
* Mihael Ankerst, Markus M. Breunig, Hans-Peter Kriegel, Jörg Sander (1999).
* "OPTICS: Ordering Points To Identify the Clustering Structure". ACM SIGMOD
* international conference on Management of data. ACM Press. pp. 49–60.
*
* @author noe
*/
public class DensityBasedClusteringOPTICS extends AbstractRegularClustering
{
    private IDataSequence datasequence;
    private INeighborSearch neighborSearch;

    // working data
    private boolean[] processed;
    private int[] numberOfNeighbors; // number of neighbors to point i within distance epsilon
    private double[] reachability_distance;
    private int[] orderedPoints;
    private int[] clusterIndexes;


    // parameters
    private double eps; // distance
    private int minpts; // minpoints
    private int nclusters; // number of clusters

    public DensityBasedClusteringOPTICS(double _epsilon, int _minpoints, int _nclusters)
    {
        this.eps = _epsilon;
        this.minpts = _minpoints;
        this.nclusters = _nclusters;

        neighborSearch = new NeighborSearchTrivial(null,new EuclideanDistance());
    }

    @Override
    public void setInput(IDataSequence data)
    {
        super.setInput(data);
        this.datasequence = data;
        neighborSearch.setData(data);

        this.reachability_distance = new double[data.size()];
        java.util.Arrays.fill(this.reachability_distance, -1);

        processed = new boolean[data.size()];
        java.util.Arrays.fill(processed, false);

        orderedPoints = new int[data.size()];
    }


    @Override
    public void setInput(IDataInput data)
    {
        throw new RuntimeException("Currently not implemented");
    }


    @Override
    public void setMetric(IMetric<IDoubleArray> metric)
    {
        super.setMetric(metric);
        neighborSearch.setMetric(metric);
    }

    @Override
    public void perform()
    {
        // initialize clusters:
        super.clusterCenters = DataSequence.create.list();

        optics();

        for (int p : orderedPoints)
            System.out.println(p+"\t"+reachability_distance[p]);
        System.exit(0);

        selectClusters();
    }

    private double coreDistance(int i)
    {
        int[] neighbors = neighborSearch.neighbors(i, eps);
        if (neighbors.length < minpts)
        {
            return -1;
        }
        else
        {
            double[] distances = new double[neighbors.length];
            for (int j = 0; j < distances.length; j++)
            {
                distances[j] = metric.distance(datasequence.get(i), datasequence.get(neighbors[j]));
            }
            DoublesPrimitive.util.sort(distances);
            return distances[minpts - 1];
        }
    }

    public double reachabilityDistance(int i, int j)
    {
        double cd = coreDistance(j);
        if (cd == -1)
        {
            return -1;
        }
        else
        {
            return Math.max(cd, metric.distance(datasequence.get(i), datasequence.get(j)));
        }
    }

    private void optics()
    {
        // iterate
        int nprocessed = 0;
        for (int i = 0; i < processed.length; i++)
        {
            System.out.println("Processing "+i);

            // skip if done
            if (processed[i])
            {
                continue;
            }

            int[] N = neighborSearch.neighbors(i, eps);
            processed[i] = true;
            System.out.println(" Neighbors: "+Ints.util.toString(Ints.create.arrayFrom(N)));

            // point p done;
            orderedPoints[nprocessed] = i;
            nprocessed++;

            PriorityQueue<Integer> seeds = new PriorityQueue<Integer>();

            double coredist_i = coreDistance(i);
            System.out.println(" core distance: "+coredist_i);
            if (coredist_i != -1)
            {
                update(N, i, seeds);
                while (!seeds.isEmpty())
                {
                    int q = seeds.poll();

                    System.out.println("  polling "+q);

                    int[] N2 = neighborSearch.neighbors(q, eps);

                    // point q done.
                    processed[q] = true;
                    orderedPoints[nprocessed] = q;
                    nprocessed++;

                    if (coreDistance(q) != -1)
                    {
                        update(N2, q, seeds);
                    }
                }
            }
        }
    }

    private void update(int[] neighbors, int p, PriorityQueue<Integer> seeds)
    {
        double coredist = coreDistance(p);

        for (int o : neighbors)
        {
            if (processed[o])
            {
                continue;
            }

            double newReachDist = Math.max(coredist, metric.distance(datasequence.get(o), datasequence.get(p)));
            if (reachability_distance[o] == -1)
            {
                reachability_distance[o] = newReachDist;
                seeds.add(o);
            }
            else               // o in Seeds, check for improvement
            {
                if (newReachDist < reachability_distance[o])
                {
                    reachability_distance[o] = newReachDist;
                    seeds.remove(o);
                    seeds.add(o);
                }
            }
        }
    }

    /**
     * Finds the right number of clusters.
     */
    private void selectClusters()
    {
        double rmin = 0;
        double rmax = DoublesPrimitive.util.max(reachability_distance);
        double r = rmax/2.0;

        int nclusters = 0;
        boolean inACluster = false;
        for (int p : orderedPoints)
        {
            if (r < reachability_distance[p])
            {
                if (inACluster)
                    clusterIndexes[p] = (nclusters-1);
                else
                {
                    nclusters++;
                    inACluster = true;
                    clusterIndexes[p] = (nclusters-1);
                }
            }
            else
            {

            }
        }

    }

    class OrderedPointComparator implements Comparator<Integer>
    {

        @Override
        public int compare(Integer p1, Integer p2)
        {
            if (reachability_distance[p1] < reachability_distance[p2])
            {
                return -1;
            }
            if (reachability_distance[p1] > reachability_distance[p2])
            {
                return 1;
            }
            return 0;
        }
    }

    @Override
    public IIntArray getClusterIndexes()
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public static void main(String[] args)
    {
        IDataList data = DataSequence.create.list();
        data.add(Doubles.create.arrayFrom(-1.4));
        data.add(Doubles.create.arrayFrom(-1));
        data.add(Doubles.create.arrayFrom(1));
        data.add(Doubles.create.arrayFrom(1.1));
        data.add(Doubles.create.arrayFrom(1.2));
        data.add(Doubles.create.arrayFrom(-1.3));
        data.add(Doubles.create.arrayFrom(-1.2));
        data.add(Doubles.create.arrayFrom(-1.1));
        data.add(Doubles.create.arrayFrom(1.3));
        data.add(Doubles.create.arrayFrom(1.4));

        DensityBasedClusteringOPTICS clustering = new DensityBasedClusteringOPTICS(0.5, 2, 2);
        clustering.setInput(data);
        clustering.setMetric(new EuclideanDistance());
        clustering.perform();
    }
}
TOP

Related Classes of stallone.cluster.DensityBasedClusteringOPTICS$OrderedPointComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.