/*********************************************/ /****** Static Method ******/ /*********************************************/ public static double GetDistance(JPoint pt1, JPoint pt2) { double retValue = -1; if (pt1 != null && pt2 != null) { retValue = Math.Sqrt(Math.Pow(pt1.X - pt2.X, 2) + Math.Pow(pt1.Y - pt2.Y, 2)); } return(retValue); }
/// <summary> /// Make K-nearest graph(table) based on whole data points, K /// The output(table) will be given by knnTable /// </summary> /// <param name="wholePoints"> The whole data points that will be examined </param> /// <param name="K"> The K value </param> /// <param name="knnTable"> This is the output data structure which is the sorted k-th nearest distance value list </param> private static void MakeKnnTable(List <JPoint> wholePoints, int K, out List <double> knnTable) { knnTable = new List <double>(); for (int i = 0; i < wholePoints.Count; ++i) { double[] record = new double[K]; int recordIndex = 0; for (int j = 0; j < wholePoints.Count; ++j) { if (i == j) { continue; } var distanceValue = JPoint.GetDistance(wholePoints[i], wholePoints[j]); if (recordIndex <= K - 1) { record[recordIndex] = distanceValue; if (recordIndex == K - 1) { Array.Sort(record); } } else { for (int index = 0; index < K; ++index) { if (distanceValue < record[index]) { Array.Copy(record, index, record, index + 1, K - index - 1); record[index] = distanceValue; break; } } } recordIndex++; } //knnTable.Add(new MyPair(i, record[nMinPts - 2])); knnTable.Add(record[K - 1]); } knnTable.Sort(); }
private static void ReadDataFromFile(string fileName, out List <JPoint> wholePoints) { using (StreamReader reader = new StreamReader(new FileStream(fileName, FileMode.Open))) { wholePoints = new List <JPoint>(); while (!reader.EndOfStream) { string eachLine = reader.ReadLine(); string[] tokenList = eachLine.Split('\t'); int id = int.Parse(tokenList[0]); double x = Convert.ToDouble(tokenList[1]); double y = Convert.ToDouble(tokenList[2]); // make each point using each line of the input text file, and Add it! JPoint eachPoint = new JPoint(id, x, y); wholePoints.Add(eachPoint); } } }
/// <summary> /// /// It is the private cluster task method, it is invoked by ClusterUsingDBSCAN(), /// it does actual cluster task, based on given epsilon, minpts, whole data point set /// /// </summary> /// <param name="epsilon"> Epsilon parameter </param> /// <param name="minpts"> The minimum number of points to be dense area </param> /// <param name="wholePointSpace"> The set of all data points to be done clustering task </param> /// <param name="clusterList"> This is the result list which contains all clusters </param> private static void _ClusterUsingDBSCAN(double epsilon, double minpts, List <JPoint> wholePointSpace, out List <JCluster> clusterList) { List <JPoint> unvisitedPoints = new List <JPoint>(wholePointSpace); clusterList = new List <JCluster>(); Random ranGen = new Random(1); while (unvisitedPoints.Count != 0) { // randomly select an unvisited object from the list of unvisited objects JPoint chosenPoint = unvisitedPoints[ranGen.Next() % unvisitedPoints.Count]; // mark it as a visited object chosenPoint.Visited = true; // chosenPoint is visted, therefore it should be removed from unvisitedPoints list. unvisitedPoints.Remove(chosenPoint); // get its neighborhood var neighborPoints = chosenPoint.GetNeighborPoints(epsilon, wholePointSpace); // if its neighborhood contains more than MIN_PTS - 1 if (neighborPoints.Count >= minpts - 1) // If it is true, chosePoint must be the core object { // then make a new cluster, and expand this cluster as long as there exists points in N JCluster newCluster = new JCluster(); newCluster.AddPoint(chosenPoint); clusterList.Add(newCluster); // N is the candidate set HashSet <JPoint> nowTest = new HashSet <JPoint>(neighborPoints); HashSet <JPoint> candidate = new HashSet <JPoint>(); // N is the candidate set (whether the point is core or not) while (nowTest.Count != 0) { foreach (JPoint p in nowTest) { // test for p if (p.Visited == false) { // mark it as a visited object p.Visited = true; // remove p from unvisited points unvisitedPoints.Remove(p); // test whether p is the core object or not. So, get the neighbor points of it. var pNeighborPoints = p.GetNeighborPoints(epsilon, wholePointSpace); if (pNeighborPoints.Count >= minpts - 1) // if p is the core object { // the neighbor points of the p should be inserted to N // because p is the core object, there is a chance of being its neighbor points core objects foreach (JPoint eachPoint in pNeighborPoints) { if (nowTest.Contains(eachPoint) == false && unvisitedPoints.Contains(eachPoint) == true) { candidate.Add(eachPoint); } } } } // if it is not a member of any cluster, if (p.ParentExist == false) { newCluster.AddPoint(p); } } nowTest.Clear(); // role swap var k = nowTest; nowTest = candidate; candidate = k; } } } }
/************************************************/ /***** Public Method *****/ /************************************************/ public void AddPoint(JPoint point) { PointList.Add(point); point.SetParent(this); }