예제 #1
0
        private static void normalizePaths(List <Path> paths)
        {
            Array.Clear(normalizedPaths, 0, normalizedPaths.Count());
            float maxX = -1f, maxY = -1f, maxT = -1f;
            float minX = Single.PositiveInfinity, minY = Single.PositiveInfinity, minT = Single.PositiveInfinity;

            foreach (Path p in paths)
            {
                foreach (Node n in p.points)
                {
                    if (n.x > maxX)
                    {
                        maxX = (float)n.xD;
                    }
                    if (n.y > maxY)
                    {
                        maxY = (float)n.yD;
                    }
                    if (n.t > maxT)
                    {
                        maxT = (float)n.tD;
                    }

                    if (n.x < minX)
                    {
                        minX = (float)n.xD;
                    }
                    if (n.y < minY)
                    {
                        minY = (float)n.yD;
                    }
                    if (n.t < minT)
                    {
                        minT = (float)n.tD;
                    }
                }
            }

            float maxVal = 1000f;

            for (int count = 0; count < paths.Count; count++)
            {
                int index = Convert.ToInt32(paths[count].name);
                normalizedPaths[index] = new Path(paths[count]);
                foreach (Node n in normalizedPaths[index].points)
                {
                    n.xD = (((n.xD - minX) * maxVal) / (maxX - minX));
                    n.yD = (((n.yD - minY) * maxVal) / (maxY - minY));
                    n.tD = (((n.tD - minT) * maxVal) / (maxT - minT));

                    n.x = (int)n.xD;
                    n.y = (int)n.yD;
                    n.t = (int)n.tD;
                }
            }
        }
예제 #2
0
        static List <Path> GetRegion(List <Path> points, Path p, double eps)
        {
            List <Path> region = new List <Path>();

            for (int i = 0; i < points.Count; i++)
            {
                double dist = FindDistance(p, points[i]);
                if (dist <= eps)
                {
                    region.Add(points[i]);
                }
            }
            return(region);
        }
예제 #3
0
        public static List <PathCollection> cluster(List <Path> points, double eps, int minPts, int noise)
        {
            if (points == null)
            {
                return(null);
            }

            List <PathCollection> clusters = new List <PathCollection>();

            eps *= eps;             // square eps
            int clusterID = 1;

            for (int i = 0; i < points.Count; i++)
            {
                Path p = points[i];
                if (p.clusterID == Path.UNCLASSIFIED)
                {
                    if (ExpandCluster(points, p, clusterID, eps, minPts))
                    {
                        clusterID++;
                    }
                }
            }
            int maxclusterID = points.OrderBy(p => p.clusterID).Last().clusterID;

            if (maxclusterID < 1)
            {
                return(clusters);                              // no clusters, so list is empty
            }
            for (int i = 0; i < maxclusterID; i++)
            {
                clusters.Add(new PathCollection());
            }

            foreach (Path p in points)
            {
                if (p.clusterID > 0)
                {
                    clusters[p.clusterID - 1].Add(p);
                }
            }
            return(clusters);
        }
예제 #4
0
        static bool ExpandCluster(List <Path> points, Path p, int clusterID, double eps, int minPts)
        {
            List <Path> seeds = GetRegion(points, p, eps);

            if (seeds.Count < minPts)             // no core point
            {
                p.clusterID = Path.NOISE;
                return(false);
            }
            else     // all points in seeds are density reachable from point 'p'
            {
                for (int i = 0; i < seeds.Count; i++)
                {
                    seeds[i].clusterID = clusterID;
                }
                seeds.Remove(p);
                while (seeds.Count > 0)
                {
                    Path        currentP = seeds[0];
                    List <Path> result   = GetRegion(points, currentP, eps);
                    if (result.Count >= minPts)
                    {
                        for (int i = 0; i < result.Count; i++)
                        {
                            Path resultP = result[i];
                            if (resultP.clusterID == Path.UNCLASSIFIED || resultP.clusterID == Path.NOISE)
                            {
                                if (resultP.clusterID == Path.UNCLASSIFIED)
                                {
                                    seeds.Add(resultP);
                                }
                                resultP.clusterID = clusterID;
                            }
                        }
                    }
                    seeds.Remove(currentP);
                }

                return(true);
            }
        }
        public static int FindNearestCluster(List <PathCollection> allClusters, Path path)
        { // src : http://codeding.com/articles/k-means-algorithm
            double minimumDistance     = 0.0;
            int    nearestClusterIndex = -1;

            for (int k = 0; k < allClusters.Count; k++) //find nearest cluster
            {
                double distance = FindDistance(path, allClusters[k].Centroid);
                if (k == 0)
                {
                    minimumDistance     = distance;
                    nearestClusterIndex = 0;
                }
                else if (minimumDistance > distance)
                {
                    minimumDistance     = distance;
                    nearestClusterIndex = k;
                }
            }

            return(nearestClusterIndex);
        }
예제 #6
0
        public static double FindDistance(Path path1_, Path path2_)
        {
            if (path1_.points == null)
            {
                Console.WriteLine(("P1NULL")); return(-1);
            }                                                                                     ////{ Debug.Log("P1NULL"); return -1; }
            else if (path2_.points == null)
            {
                Console.WriteLine(("P2NULL")); return(-1);
            }                                                                                         ////{ Debug.Log("P2NULL"); return -1; }
            int p1num = Convert.ToInt32(path1_.name);
            int p2num = Convert.ToInt32(path2_.name);

            if (path1_.name == path2_.name)
            {             // same path
                return(0.0);
            }

            Path path1, path2;

            bool saveDistances = false;

            if (p1num <= Clustering.distances.Count() && p2num <= Clustering.distances.Count())
            {
                if (Clustering.distances[p1num][p2num] != -1)
                {
                    return(Clustering.distances[p1num][p2num]);
                }
                if (Clustering.distances[p2num][p1num] != -1)
                {
                    return(Clustering.distances[p2num][p1num]);
                }

                path1 = Clustering.normalizedPaths[p1num];
                path2 = Clustering.normalizedPaths[p2num];

                saveDistances = true;
            }
            else
            {
                Console.WriteLine("Note - not storing this distance.");                 ////Debug.Log("Note - not storing this distance.");

                path1 = path1_;
                path2 = path2_;
            }

            double result = 0.0;

            if (distMetric == (int)Metrics.Frechet || distMetric == (int)Metrics.Hausdorff)
            {
                double[][] curveA = new double[path1.points.Count][];
                double[][] curveB = new double[path2.points.Count][];

                for (int i = 0; i < path1.points.Count; i++)
                {
                    double[] curve    = new double[numSelectedDimensions];
                    int      curvePos = 0;
                    for (int j = 0; j < dimensionEnabled.Count(); j++)
                    {
                        if (dimensionEnabled[j])
                        {
                            if (j == (int)Dimensions.X)
                            {
                                curve[curvePos] = path1.points[i].xD;
                            }

                            else if (j == (int)Dimensions.Y)
                            {
                                curve[curvePos] = path1.points[i].yD;
                            }
                            else if (j == (int)Dimensions.Time)
                            {
                                curve[curvePos] = path1.points[i].tD;
                            }
                            curvePos++;
                        }
                    }
                    curveA[i] = curve;
                }

                for (int i = 0; i < path2.points.Count; i++)
                {
                    double[] curve    = new double[numSelectedDimensions];
                    int      curvePos = 0;
                    for (int j = 0; j < dimensionEnabled.Count(); j++)
                    {
                        if (dimensionEnabled[j])
                        {
                            if (j == (int)Dimensions.X)
                            {
                                curve[curvePos] = path2.points[i].xD;
                            }
                            else if (j == (int)Dimensions.Y)
                            {
                                curve[curvePos] = path2.points[i].yD;
                            }
                            else if (j == (int)Dimensions.Time)
                            {
                                curve[curvePos] = path2.points[i].tD;
                            }
                            curvePos++;
                        }
                    }
                    curveB[i] = curve;
                }

                if (distMetric == (int)Metrics.Frechet)
                {
                    result = frechet.computeDistance(curveA, curveB);
                }
            }

            else
            {
                Console.WriteLine("Invalid distance metric (" + distMetric + ")!");              ////Debug.Log("Invalid distance metric ("+distMetric+")!");
                return(-1);
            }

            if (saveDistances)
            {
                Clustering.distances[p1num][p2num] = result;
                Clustering.distances[p2num][p1num] = result;
            }
            return(result);
        }
 public static double FindDistance(Path path1, Path path2, int distMetric_)
 {
     setDistMetric(distMetric_);
     return(FindDistance(path1, path2));
 }
        public static List <PathCollection> cluster(List <PathCollection> allClusters, double[] weights_)
        {         // based on http://codeding.com/articles/k-means-algorithm
            for (int i = 0; i < allClusters.Count(); i++)
            {
                if (allClusters[i].Count() == 0)
                {
                    Console.WriteLine("Empty cluster, #" + i);
                }
            }
            weights = weights_;

            int movements = 1;
            int count     = 0;

            int[] previousMovements = new int[100];
            while (movements > 0)
            {
                Console.WriteLine(count);
                previousMovements[count] = movements;
                if (count > 25)
                {
                    int avgLastThree = (previousMovements[count - 2] + previousMovements[count - 1] + previousMovements[count]) / 3;
                    if (Math.Abs(avgLastThree - previousMovements[count]) <= 10)
                    {
                        Console.WriteLine("Not converging.");
                        break;
                    }
                }

                count++;

                movements = 0;

                for (int clusterIndex = 0; clusterIndex < allClusters.Count; clusterIndex++)
                {
                    for (int pathIndex = 0; pathIndex < allClusters[clusterIndex].Count; pathIndex++)                     //for all paths in each cluster
                    {
                        Path path = allClusters[clusterIndex][pathIndex];

                        int nearestCluster = FindNearestCluster(allClusters, path);
                        if (nearestCluster != clusterIndex)          //if path has moved
                        {
                            if (allClusters[clusterIndex].Count > 1) //cluster shall have minimum one path
                            {
                                Path removedPath = allClusters[clusterIndex].RemovePath(path);
                                allClusters[nearestCluster].AddPath(removedPath);
                                movements += 1;
                            }
                        }
                    }
                }
                foreach (PathCollection cluster in allClusters)
                {
                    if (cluster.changed)
                    {
                        cluster.UpdateCentroid(clustAlg);
                        movements      += 1;
                        cluster.changed = false;
                    }
                }
            }

            return(allClusters);
        }
        public static List <PathCollection> DoKMeans(List <Path> paths, int clusterCount, int distMetric_, int numPasses, double[] weights)
        {
            if (paths.Count == 0)
            {
                Console.WriteLine("No paths to cluster!");
                return(null);
            }

            setDistMetric(distMetric_);

            clustTime.Start();

            double bestE = double.MaxValue;
            List <PathCollection> bestClustering = new List <PathCollection>();

            for (int curPass = 0; curPass < numPasses; curPass++)
            {
                Console.WriteLine("Pass " + curPass);

                List <PathCollection> allClusters = new List <PathCollection>();
                if (useScalable)
                {
                    allClusters = cluster(initializeCentroidsScalable(paths, clusterCount), KMeans.weights);
                }
                else
                {
                    allClusters = cluster(initializeCentroids(paths, clusterCount, weights), weights);
                }

                // get, for each cluster, the average distance of all elements in that cluster to the cluster centroid

                Path[] averageCentroids = new Path[allClusters.Count()];
                for (int i = 0; i < allClusters.Count(); i++)
                {
                    averageCentroids[i] = allClusters[i].getAveragedCentroid();
                    int newIndex = paths.Count() + 1000 + i;
                    averageCentroids[i].name = newIndex.ToString();
                }

                double[] avgDists = new double[allClusters.Count()];
                for (int i = 0; i < allClusters.Count(); i++)
                {
                    avgDists[i] = 0.0;
                    foreach (Path p in allClusters[i])
                    {
                        avgDists[i] += FindDistance(p, averageCentroids[i]);
                    }
                }

                double sumMaxVals = 0.0;
                for (int i = 0; i < allClusters.Count(); i++)
                {                 // sum over all clusters
                    double maxVal = 0.0;

                    for (int j = 0; j < allClusters.Count(); j++)
                    {
                        if (i == j)
                        {
                            continue;
                        }

                        double distBetweenCentroids = FindDistance(averageCentroids[i], averageCentroids[j]);
                        double clustVal             = 0.0;
                        if (avgDists[i] + avgDists[j] != 0.0)
                        {
                            clustVal = (avgDists[i] + avgDists[j]) / distBetweenCentroids;
                        }

                        if (Double.IsInfinity(clustVal))
                        {
                            clustVal = 10000.0;
                        }

                        if (clustVal > maxVal)
                        {
                            maxVal = clustVal;
                        }
                    }

                    sumMaxVals += maxVal;
                }
                double clusteringQuality = sumMaxVals / allClusters.Count();                 // sum * 1/n


                Console.WriteLine("Pass " + curPass + ", DB val: " + clusteringQuality);
                if (clusteringQuality <= 0)
                {
                    Console.WriteLine("Something has gone horribly wrong.");
                }
                else if (clusteringQuality < bestE || curPass == 0)
                {
                    bestE    = clusteringQuality;
                    clustVal = bestE;

                    bestClustering.Clear();
                    foreach (PathCollection c in allClusters)
                    {
                        bestClustering.Add(c);
                    }
                }
            }

            clustTime.Stop();

            return(bestClustering);
        }