// Assign all points to nearest cluster
        public void UpdatePointsByCentroid() // O(n*k)
        {
            // Clear points in the buckets, they will be re-inserted
            foreach (var bucket in BucketsLookup.Values)
            {
                bucket.Points.Clear();
            }

            foreach (var p in this.points)
            {
                var minDist = Double.MaxValue;
                var index   = string.Empty;
                foreach (var i in BucketsLookup.Keys)
                {
                    var bucket = BucketsLookup[i];
                    if (bucket.IsUsed == false)
                    {
                        continue;
                    }

                    var centroid = bucket.Centroid;
                    var dist     = MathTool.Distance(p, centroid);
                    if (dist < minDist)
                    {
                        // update
                        minDist = dist;
                        index   = i;
                    }
                }
                // re-insert
                var closestBucket = BucketsLookup[index];
                closestBucket.Points.Add(p);
            }
        }
예제 #2
0
            static double RunOneIteration() //O(k*n)
            {
                GlobalClass.program += "35. Runoneiteration .. ";
                // update points, assign points to cluster
                UpdatePointsByCentroid();
                // update centroid pos by its points
                BaseSetCentroidForAllBuckets(BaseBucketsLookup.Values);//O(k*n)
                var clustersCount = BaseBucketsLookup.Count;

                for (int i = 0; i < clustersCount; i++)
                {
                    var currentBucket = BaseBucketsLookup[i.ToString()];
                    if (currentBucket.IsUsed == false)
                    {
                        continue;
                    }

                    //update centroid
                    var newcontroid = BaseGetCentroidFromCluster(currentBucket.Points);
                    //no need to update CGroup, autoset
                    currentBucket.Centroid   = newcontroid;
                    currentBucket.ErrorLevel = 0;
                    //update error
                    foreach (var p in currentBucket.Points)
                    {
                        var dist = MathTool.Distance(newcontroid, p);
                        currentBucket.ErrorLevel += dist;
                    }
                    var val = currentBucket.ErrorLevel / currentBucket.Points.Count;
                    currentBucket.ErrorLevel = val; //Math.Sqrt(val);
                }

                Profile("RunOneIteration");
                return(BaseGetTotalError());
            }
예제 #3
0
        public void DistanceTest(double x1, double y1, double x2, double y2)
        {
            Assert.AreEqual(x2.Hypot2(y2), MathTool.Distance(x1, y1, x2, y2), 0.000000001d);

            var p1 = new PointF((float)x1, (float)y1);
            var p2 = new PointF((float)x2, (float)y2);

            Assert.AreEqual(x2.Hypot2(y2), p1.Distance(p2), 0.000000001d);
        }
예제 #4
0
            private static Segment MyClosestRec(List <XY> pointsByX)
            {
                int count = pointsByX.Count;

                if (count <= 4)
                {
                    return(Segment.Closest_BruteForce(pointsByX));
                }
                // left and right lists sorted by X, as order retained from full list
                var leftByX    = pointsByX.Take(count / 2).ToList();
                var leftResult = MyClosestRec(leftByX);

                var rightByX    = pointsByX.Skip(count / 2).ToList();
                var rightResult = MyClosestRec(rightByX);

                var result = rightResult.Length() < leftResult.Length() ? rightResult : leftResult;

                // There may be a shorter distance that crosses the divider
                // Thus, extract all the points within result.Length either side
                var mxid      = leftByX.Last().X;
                var bandWidth = result.Length();
                var inBandByX = pointsByX.Where(p => Math.Abs(mxid - p.X) <= bandWidth);

                // Sort by Y, so we can efficiently check for closer pairs
                var inBandByY = inBandByX.OrderBy(p => p.Y).ToArray();

                int iLast = inBandByY.Length - 1;

                for (int i = 0; i < iLast; i++)
                {
                    var pLower = inBandByY[i];

                    for (int j = i + 1; j <= iLast; j++)
                    {
                        var pUpper = inBandByY[j];

                        // Comparing each point to successivly increasing Y values
                        // Thus, can terminate as soon as deltaY is greater than best result
                        if ((pUpper.Y - pLower.Y) >= result.Length())
                        {
                            break;
                        }

                        if (MathTool.Distance(pLower, pUpper) < result.Length())
                        {
                            result = new Segment(pLower, pUpper);
                        }
                    }
                }

                return(result);
            }
예제 #5
0
            void MergeClustersGridHelper(string currentKey, string[] neighborKeys)
            {
                GlobalClass.program += "41. GridBaseCluster.MergeClustersGridHelper .. ";
                double minDistX = DeltaX / 2.0;//heuristic, higher value gives less merging
                double minDistY = DeltaY / 2.0;
                //if clusters in grid are too close to each other, merge them
                double minDist = MathTool.Max(minDistX, minDistY);

                foreach (var neighborKey in neighborKeys)
                {
                    if (!BaseBucketsLookup.ContainsKey(neighborKey))
                    {
                        continue;
                    }

                    var neighbor = BaseBucketsLookup[neighborKey];
                    if (neighbor.IsUsed == false)
                    {
                        continue;
                    }

                    var current = BaseBucketsLookup[currentKey];
                    var dist    = MathTool.Distance(current.Centroid, neighbor.Centroid);
                    if (dist > minDist)
                    {
                        continue;
                    }

                    var centroidgroup = current.Centroid.CGroup;
                    foreach (var p in neighbor.Points)
                    {
                        //update CGroup
                        p.CGroup = centroidgroup;
                    }//end

                    neighP = neighbor.Points.ToArray();


                    current.Points.AddRange(neighbor.Points);//O(n)

                    // recalc centroid
                    var cp = BaseGetCentroidFromCluster(current.Points);
                    current.Centroid = cp;
                    neighbor.IsUsed  = false; //merged, then not used anymore
                }
            }
예제 #6
0
            void MergeClustersGridHelper(string currentKey, string[] neighborKeys)
            {
                double minDistX = DeltaX / 2.0;    //heuristic, higher value gives less merging
                double minDistY = DeltaY / 2.0;
                //if clusters in grid are too close to each other, merge them
                double minDist = MathTool.Max(minDistX, minDistY);

                foreach (var neighborKey in neighborKeys)
                {
                    if (!BaseBucketsLookup.ContainsKey(neighborKey))
                    {
                        continue;
                    }

                    var neighbor = BaseBucketsLookup[neighborKey];
                    if (neighbor.IsUsed == false)
                    {
                        continue;
                    }

                    var current = BaseBucketsLookup[currentKey];
                    var dist    = MathTool.Distance(current.Centroid, neighbor.Centroid);
                    if (dist > minDist)
                    {
                        continue;
                    }

                    // merge
                    var color = current.Centroid.Color;
                    foreach (var p in neighbor.Points)
                    {
                        //update color
                        p.Color = color;
                    }

                    current.Points.AddRange(neighbor.Points);    //O(n)

                    // recalc centroid
                    var cp = BaseGetCentroidFromCluster(current.Points);
                    current.Centroid = cp;
                    neighbor.IsUsed  = false;    //merged, then not used anymore
                    neighbor.Points.Clear();     //clear mem
                }
            }
        public MapPoint GetClosestPoint(MapPoint from, List <MapPoint> list) // O(n)
        {
            var      min      = double.MaxValue;
            MapPoint closests = null;

            foreach (var p in list)
            {
                var dist = MathTool.Distance(from, p);
                if (dist >= min)
                {
                    continue;
                }

                // update
                min      = dist;
                closests = p;
            }
            return(closests);
        }
예제 #8
0
            public XY BaseGetLongestPoint(XY from, List <XY> list)    //O(n)
            {
                double max     = -double.MaxValue;
                XY     longest = null;

                foreach (var p in list)
                {
                    var d = MathTool.Distance(from, p);
                    if (d <= max)
                    {
                        continue;
                    }

                    // update
                    max     = d;
                    longest = p;
                }
                return(longest);
            }
예제 #9
0
            public static XY BaseGetClosestPoint(XY from, List <XY> list)    //O(n)
            {
                double min      = double.MaxValue;
                XY     closests = null;

                foreach (var p in list)
                {
                    var d = MathTool.Distance(from, p);
                    if (d >= min)
                    {
                        continue;
                    }

                    // update
                    min      = d;
                    closests = p;
                }
                return(closests);
            }
        public IP GetClosestPoint(IP from, IPoints list) // O(n)
        {
            var min      = double.MaxValue;
            IP  closests = null;

            foreach (var p in list.Data)
            {
                var d = MathTool.Distance(from, p);
                if (d >= min)
                {
                    continue;
                }

                // update
                min      = d;
                closests = p;
            }
            return(closests);
        }
예제 #11
0
            public static XY BaseGetLongestPoint(XY from, List <XY> list) //O(n)
            {
                GlobalClass.program += "27. BaseClusternewKmeans.BaeGetLongestPoint .. ";
                double max     = -double.MaxValue;
                XY     longest = null;

                foreach (var p in list)
                {
                    var d = MathTool.Distance(from, p);
                    if (d <= max)
                    {
                        continue;
                    }

                    // update
                    max     = d;
                    longest = p;
                }
                return(longest);
            }
예제 #12
0
            public static XY BaseGetClosestPoint(XY from, List <XY> list) //O(n)
            {
                GlobalClass.program += "26. BaseClusternewKmeans.BaseGetClosestPoint .. ";
                double min      = double.MaxValue;
                XY     closests = null;

                foreach (var p in list)
                {
                    var d = MathTool.Distance(from, p);
                    if (d >= min)
                    {
                        continue;
                    }

                    // update
                    min      = d;
                    closests = p;
                }
                return(closests);
            }
예제 #13
0
            static void UpdatePointsByCentroid()//O(n*k)
            {
                GlobalClass.program += "36. Updatepointsbycentroid.. ";
                int count = BaseBucketsLookup.Count();

                // clear points in the buckets, they will be re-inserted
                foreach (var bucket in BaseBucketsLookup.Values)
                {
                    bucket.Points.Clear();
                }

                foreach (XY p in BaseDataset)
                {
                    double minDist = Double.MaxValue;
                    int    index   = -1;
                    for (int i = 0; i < count; i++)
                    {
                        var bucket = BaseBucketsLookup[i.ToString()];
                        if (bucket.IsUsed == false)
                        {
                            continue;
                        }

                        var centroid = bucket.Centroid;
                        var dist     = MathTool.Distance(p, centroid);
                        if (dist < minDist)
                        {
                            // update
                            minDist = dist;
                            index   = i;
                        }
                    }
                    //update CGroup for point to match centroid and re-insert
                    var closestBucket = BaseBucketsLookup[index.ToString()];
                    p.CGroup = closestBucket.Centroid.CGroup;
                    closestBucket.Points.Add(p);
                }

                Profile("UpdatePointsByCentroid");
            }
예제 #14
0
            // assign all points to nearest cluster
            public void BaseUpdatePointsByCentroid()    //O(n*k)
            {
                Profile("UpdatePointsByCentroid beg");
                int count = BaseBucketsLookup.Count();

                // clear points in the buckets, they will be re-inserted
                foreach (var bucket in BaseBucketsLookup.Values)
                {
                    bucket.Points.Clear();
                }

                foreach (XY p in BaseDataset)
                {
                    double minDist = Double.MaxValue;
                    string index   = string.Empty;
                    //for (int i = 0; i < count; i++)
                    foreach (var i in BaseBucketsLookup.Keys)
                    {
                        var bucket = BaseBucketsLookup[i];
                        if (bucket.IsUsed == false)
                        {
                            continue;
                        }

                        var centroid = bucket.Centroid;
                        var dist     = MathTool.Distance(p, centroid);
                        if (dist < minDist)
                        {
                            // update
                            minDist = dist;
                            index   = i;
                        }
                    }
                    //update color for point to match centroid and re-insert
                    var closestBucket = BaseBucketsLookup[index];
                    p.Color = closestBucket.Centroid.Color;
                    closestBucket.Points.Add(p);
                }
            }
        void MergeClustersGridHelper(string currentKey, IEnumerable <string> neighborKeys)
        {
            double minDistX = DeltaX / GmcSettings.Get.MergeWithin;
            double minDistY = DeltaY / GmcSettings.Get.MergeWithin;
            // If clusters in grid are too close to each other, merge them
            double withinDist = Math.Max(minDistX, minDistY);

            foreach (var neighborKey in neighborKeys)
            {
                if (!BucketsLookup.ContainsKey(neighborKey))
                {
                    continue;
                }

                var neighbor = BucketsLookup[neighborKey];
                if (neighbor.IsUsed == false)
                {
                    continue;
                }

                var current = BucketsLookup[currentKey];
                var dist    = MathTool.Distance(current.Centroid, neighbor.Centroid);
                if (dist > withinDist)
                {
                    continue;
                }

                current.Points.AddRange(neighbor.Points);                 //O(n)

                // recalc centroid
                var centroidPoint = GetCentroidFromClusterLatLon(current.Points);
                current.Centroid = centroidPoint;
                neighbor.IsUsed  = false;                // merged, then not used anymore
                neighbor.Points.Clear();                 // clear mem
            }
        }
예제 #16
0
 public void DistanceTest()
 {
     Assert.AreEqual(5, MathTool.Distance(0, 0, 3, 4, 1));
 }