/// <summary> /// Building a graph on cluster /// </summary> /// <param name="c">input cluster</param> /// <param name="df">distance function</param> /// <returns>a graph as collection of Edges</returns> public static ICollection <Edge> GetEdgesForCluster(Cluster c, distanceFunction df) { List <Edge> edgesRes = new List <Edge>(); for (int i = 0; i < c.Size; i++) { int tmpV = i == 0 ? c.Size - 1 : 0; double minDist = df(c.GetElementByLocalIndex(i), c.GetElementByLocalIndex(tmpV)); for (int j = 0; j < c.Size; j++) { if (i != j) { double tmpDist = df(c.GetElementByLocalIndex(i), c.GetElementByLocalIndex(j)); if (tmpDist < minDist) { minDist = tmpDist; tmpV = j; } } } Edge mEdge = new Edge(minDist, i, tmpV); if (!edgesRes.Contains(mEdge)) { edgesRes.Add(mEdge); } } return(edgesRes); }
public static ICollection <Cluster> SplitClusterGraph(Cluster k1, distanceFunction yDist, clusterCenterFunction cnf, double[] cnfPars, double[] splitPars) { List <Edge> edges = new List <Edge>(GetEdgesForCluster(k1, yDist)); List <int> inds = new List <int>(); for (int i = 0; i < k1.Size; i++) { inds.Add(i); } for (int i = 0; i < edges.Count; i++) { if (edges[i].Distance > splitPars[0]) { edges.RemoveAt(i); i--; } } List <ICollection <int> > components = new List <ICollection <int> >(GetLinkedComponents(edges, inds)); List <Cluster> res = new List <Cluster>(); for (int i = 0; i < components.Count; i++) { List <double[]> data = new List <double[]>(); List <int> gInds = new List <int>(); for (int j = 0; j < components[i].Count; j++) { data.Add(k1.GetElementByLocalIndex(components[i].ElementAt(j))); gInds.Add(k1.GetGlobalIndexByLocal(components[i].ElementAt(j))); } res.Add(new Cluster(gInds.ToArray(), data)); } return(res); }
public static float SimilarClusterBrute(Cluster y1, Cluster y2, distanceFunction yDist, clusterCenterFunction cnf, double[] cnfPars) { double[] center1 = cnf(y1, yDist, cnfPars), center2 = cnf(y2, yDist, cnfPars); double max1 = yDist(center1, y1.GetElementByLocalIndex(0)), max2 = yDist(center2, y2.GetElementByLocalIndex(0)); double tmpDist; for (int i = 0; i < y1.Size; i++) { tmpDist = yDist(y1.GetElementByLocalIndex(i), center1); if (tmpDist > max1) { max1 = tmpDist; } } for (int i = 0; i < y2.Size; i++) { tmpDist = yDist(y2.GetElementByLocalIndex(i), center2); if (tmpDist > max2) { max2 = tmpDist; } } double cDist = yDist(center1, center2); double maxAvg = (max1 + max2) / 2; if (cDist < maxAvg) { return(1.0f); } else { return((float)maxAvg / (float)cDist); } }
public static double[] AbsClusterCenter(Cluster c, distanceFunction df, double[] pars) { //ищем среднее double[] avg = new double[c.Dimensions]; for (int i = 0; i < avg.Length; i++) { avg[i] = 0; } for (int i = 0; i < c.Size; i++) { for (int j = 0; j < avg.Length; j++) { avg[j] += c.GetElementByLocalIndex(i)[j]; } } for (int i = 0; i < avg.Length; i++) { avg[i] /= c.Size; } //ищем ближайшее к среднему double minDist = df(avg, c.GetElementByLocalIndex(0)), tmpDist; int ind = 0; for (int i = 0; i < c.Size; i++) { tmpDist = df(avg, c.GetElementByLocalIndex(i)); if (tmpDist < minDist) { minDist = tmpDist; ind = i; } } return(c.GetElementByLocalIndex(ind)); }
/** * Creates the DTW object and sets signal feature object. * * @param signal feature extractor object */ public Dtw(Extractor signal) { from = signal; points = new DtwPoint[signal.GetFramesCount()][]; distanceFn = new distanceFunction(Functions.euclideanDistance); passType = PassType.Neighbors; }
/// <summary> /// A neighbour density oriented function for input data space-conversion preprocessing /// </summary> /// <param name="xDist">distance function for input data space</param> /// <param name="xSpc">input data</param> /// <param name="pars">array of two values [k, alpha] where k is checked neighbour count and alpha is accepded max distance to min distance ratio</param> /// <returns>a set of points in statistical metrics for neighbors of [average value, mean square, median, dispersion]</returns> public static Cluster DensityConversionFunction(distanceFunction xDist, Cluster xSpc, double[] pars) { List <double[]> resData = new List <double[]>(); List <int> resInds = new List <int>(); int k = (int)pars[0]; double alpha = pars[1]; for (int i = 0; i < xSpc.Size; i++) { double[] dst; List <int> checkInds = new List <int>(); List <double[]> pts = new List <double[]>(FindClosest(i, xDist, xSpc, k, out dst)); //filtering distances by alpha parameter for (int j = 0; j < dst.Length; j++) { for (int l = 0; l < dst.Length; l++) { double mx = Math.Max(dst[l], dst[j]), mn = Math.Min(dst[l], dst[j]); if ((l != j) && (mx / mn > alpha)) { double distLJ = xDist(pts[j], pts[l]); double mxL = Math.Max(dst[l], distLJ), mnL = Math.Min(dst[l], distLJ); double mxJ = Math.Max(dst[j], distLJ), mnJ = Math.Min(dst[j], distLJ); if ((mxL / mnL > alpha) || (mxJ / mnJ > alpha)) { if (dst[j] > dst[l]) { checkInds.Add(j); } else { checkInds.Add(l); } } } } } //filtering result List <double> resDstI = new List <double>(); for (int j = 0; j < dst.Length; j++) { if (!checkInds.Contains(j)) { resDstI.Add(dst[j]); } } //preparing statistical data double avg = AvgVal(resDstI); double meanSq = MeanSq(avg, resDstI); double median = Median(resDstI); double disp = Dispersion(resDstI); //filling resData.Add(new double[] { avg, meanSq, median, disp }); resInds.Add(xSpc.GetGlobalIndexByLocal(i)); } Cluster res = new Cluster(resInds.ToArray(), resData); return(res); }
/** * Chooses a distance function. * * @param index function index in the distanceFunctions array */ public void SetDistanceFunction(int index) { int functionsCount = distanceFunctions.Length; if (index > 0 && index < functionsCount) { distanceFn = distanceFunctions[index]; } }
/// <summary> /// конструктор алгоритма /// </summary> /// <param name="xDist">distance function for input data space</param> /// <param name="yDist">distance function for preprocessed data space</param> /// <param name="xyConv">space conversion function (in some cases could be similar to feature mapping)</param> /// <param name="comparePointFunction">nearest neihbor function for clusters, shoud return constant -1 to be trivial</param> /// <param name="clusterFusionCriteria">similarity function to define cluster fusion, should return constant -1 to be trivial</param> /// <param name="clusterDivider">a function for spliting cluster in two, should return empty collection of clusters to be trivial</param> /// <param name="clusterSortCriteria">a function for cluster comparing</param> /// <param name="cnt">cluster center function</param> public ClusterAlgorithm(distanceFunction xDist, distanceFunction yDist, spaceConversionFunction xyConv, sameCluster comparePointFunction, similarClusters clusterFusionCriteria, splitCluster clusterDivider, comapreClusters clusterSortCriteria, clusterCenterFunction cnt, bool isSplitTrivial = false) { this.xDist = xDist; this.yDist = yDist; this.xyConv = xyConv; this.comparePointFunction = comparePointFunction; this.clusterFusionCriteria = clusterFusionCriteria; this.clusterDivider = clusterDivider; this.clusterSortCriteria = clusterSortCriteria; this.cntFunc = cnt; this.isSplitingTrivial = isSplitTrivial; }
public static float SameClusterBrute(Cluster y1, Cluster y2, distanceFunction yDist, clusterCenterFunction cnf, double[] cnfPars) { double[] center1 = cnf(y1, yDist, cnfPars), center2 = cnf(y2, yDist, cnfPars); double max1 = yDist(center1, y1.GetElementByLocalIndex(0)), max2 = yDist(center2, y2.GetElementByLocalIndex(0)); double tmpDist; for (int i = 0; i < y1.Size; i++) { tmpDist = yDist(y1.GetElementByLocalIndex(i), center1); if (tmpDist > max1) { max1 = tmpDist; } } for (int i = 0; i < y2.Size; i++) { tmpDist = yDist(y2.GetElementByLocalIndex(i), center2); if (tmpDist > max2) { max2 = tmpDist; } } int counter1 = 0, counter2 = 0; for (int i = 0; i < y1.Size; i++) { tmpDist = yDist(y1.GetElementByLocalIndex(i), center2); if (tmpDist < max1) { counter1++; } } for (int i = 0; i < y2.Size; i++) { tmpDist = yDist(y2.GetElementByLocalIndex(i), center1); if (tmpDist < max2) { counter2++; } } //подсчёт float pre1 = ((float)counter1) / y1.Size, pre2 = ((float)counter2) / y2.Size; return(pre1 * pre2); }
/// <summary> /// Finding k closest elements to the element with known local index /// </summary> /// <param name="localPointInd">Local index of cluster element</param> /// <param name="xDist">distance function for </param> /// <param name="xSpc">input cluster</param> /// <param name="k">a number of closest element to search</param> /// <param name="dists">out distances</param> /// <returns>a collection of k closest elements as arrays of double values</returns> private static ICollection <double[]> FindClosest(int localPointInd, distanceFunction xDist, Cluster xSpc, int k, out double[] dists) { List <double[]> res = new List <double[]>(); List <double> dist = new List <double>(); double[] pt = xSpc.GetElementByLocalIndex(localPointInd); for (int i = 0; i < xSpc.Size; i++) { if (i != localPointInd) { double[] tmp = xSpc.GetElementByLocalIndex(i); double tmpDist = xDist(tmp, pt); if (res.Count == 0) { res.Add(tmp); dist.Add(tmpDist); } else { int j = 0; for (j = dist.Count - 1; j >= 0; j--) { if (tmpDist > dist[j] || j == 0) { break; } } dist.Insert(j, tmpDist); res.Insert(j, tmp); } if (res.Count > k) { res.RemoveAt(res.Count - 1); dist.RemoveAt(dist.Count - 1); } } } dists = dist.ToArray(); return(res); }
public static List <Tuple <int, int> > reduceFingerPoints(List <Tuple <int, int> > fingerPoints) { int len = fingerPoints.Count; int next_x, next_y, center_x = -1, center_y = -1, pointCount = 0; double dist; List <Tuple <int, int> > reducedList = new List <Tuple <int, int> >(); for (int i = 0; i < len; i++) { next_x = fingerPoints[i].Item1; next_y = fingerPoints[i].Item2; if (pointCount == 0) { center_x = next_x; center_y = next_y; pointCount++; } else { dist = Math.Sqrt((center_x - next_x) * (center_x - next_x) + (center_y - next_y) * (center_y - next_y)); if (Math.Abs(dist) <= 20) { //update center averaging in new point center_x = (center_x * pointCount + next_x) / (pointCount + 1); center_y = (center_y * pointCount + next_y) / (pointCount + 1); pointCount++; } else { reducedList.Add(new Tuple <int, int>(center_x, center_y)); pointCount = 0; //reset and look for next finger } } } return(reducedList); }
public static float ComapreClustersBySize(Cluster k1, Cluster k2, distanceFunction yDist, clusterCenterFunction cnf, double[] cnfPars) { return(k1.Size - k2.Size); }
public static ICollection <Cluster> SplitClusterTrivial(Cluster k1, distanceFunction yDist, clusterCenterFunction cnf, double[] cnfPars, double[] splitPars) { return(new Cluster[] { k1 }); }
/// <summary> /// A trivialized function for cases with no difference before and after space-conversion preprocessing /// </summary> /// <param name="xDist">distance function for input data</param> /// <param name="xSpc">input data</param> /// <param name="pars">conversion params, can be empty for this case</param> /// <returns>came cluster as in input</returns> public static Cluster TrivialConversionFunction(distanceFunction xDist, Cluster xSpc, double[] pars) { return(xSpc); }