/// <summary> /// sort point @A 's all neighbor index by their distance to @A /// </summary> /// <param name="A"></param> /// <param name="index"></param> /// <returns></returns> private static List <DPoint> sortIndexOfNborByDist(DStatusPacket A, int index) { List <DPoint> distList = new List <DPoint>(LENGTH - 1); DPoint tmp; double AB; // dist(A, B) for (int i = 0; i < LENGTH; i++) { if (i == index) { continue; } else if (i < index) { AB = distTable[i, index]; } else { AB = distTable[index, i]; } tmp = new DPoint(i, AB); // i: the index of B in the database distList.Add(tmp); } distList.Sort(); // sort by tmp.Value (distance) ascending return(distList); }
/// <summary> /// drop index form packet (convert DStatus to DStatusPacket) /// </summary> /// <param name="src"></param> /// <returns></returns> private static DStatusPacket dropIndexFromPacket(DStatus src) { DStatusPacket dst = new DStatusPacket(); dst.ID = src.ID; dst.Attributes = src.Attributes; return(dst); }
/// <summary> /// add index of database to DStatusPacket @src /// </summary> /// <param name="index"></param> /// <param name="src"></param> /// <returns></returns> private static DStatus addIndexToPacket(int index, DStatusPacket src) { DStatus dst = new DStatus(); dst.Index = index; dst.ID = src.ID; dst.Attributes = src.Attributes; return(dst); }
/// <summary> /// Parse statusData table /// </summary> /// <param name="p_Ds">Dataset</param> /// <returns>Parsing results</returns> public static List <DStatusPacket> RawDataToDStatusPacket(DataSet p_Ds) { // Resulting list List <DStatusPacket> packets = new List <DStatusPacket>(); // Check if table exists or if table is empty if (p_Ds.Tables.Contains(tableName) == false || p_Ds.Tables[tableName].Rows.Count < 1) { return(packets); } int Dimension = p_Ds.Tables[tableName].Columns.Count; // Convert each row in table "Neighbor" to a "DNeighborPacket" structure foreach (DataRow row in p_Ds.Tables[tableName].Rows) { try { // Create a new DStatusPacket DStatusPacket status_packet = new DStatusPacket(); // get the value of ID int p_ID = int.Parse(row["ID"].ToString()); // add to the object attributes status_packet.ID = p_ID; // Convert every elements in the attributes for (int i = 1; i < Dimension; i++) { int p_Ai; // get the value of each element of attributes if (DBNull.Value.Equals(row[i])) { p_Ai = ErrorReadingInt; } else { p_Ai = int.Parse(row[i].ToString()); } // add to the structure status_packet.Attributes.Add(p_Ai); } // Add it to results packets.Add(status_packet); } catch (Exception e) { //TODO //SystemLog.Log("SQLServerDBConvert", "RawDataToDStatusPacket", e.Message, null); } } return(packets); }
/// <summary> /// calculate dot product of vector @A and @B /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <returns>A * B</returns> private static double calcDotProduct(DStatusPacket vectorAB, DStatusPacket vectorAC) { double result = 0.0; for (int i = 0; i < vectorAB.Attributes.Count(); i++) { result += vectorAB.Attributes[i] * vectorAC.Attributes[i]; } return(result); }
/// <summary> /// Parse statusData table /// </summary> /// <param name="p_Ds">Dataset</param> /// <returns>Parsing results</returns> public static List<DStatusPacket> RawDataToDStatusPacket(DataSet p_Ds) { // Resulting list List<DStatusPacket> packets = new List<DStatusPacket>(); // Check if table exists or if table is empty if (p_Ds.Tables.Contains(tableName) == false || p_Ds.Tables[tableName].Rows.Count < 1) { return packets; } int Dimension = p_Ds.Tables[tableName].Columns.Count; // Convert each row in table "Neighbor" to a "DNeighborPacket" structure foreach (DataRow row in p_Ds.Tables[tableName].Rows) { try { // Create a new DStatusPacket DStatusPacket status_packet = new DStatusPacket(); // get the value of ID int p_ID = int.Parse(row["ID"].ToString()); // add to the object attributes status_packet.ID = p_ID; // Convert every elements in the attributes for(int i = 1; i < Dimension; i++) { int p_Ai; // get the value of each element of attributes if (DBNull.Value.Equals(row[i])) { p_Ai = ErrorReadingInt; } else { p_Ai = int.Parse(row[i].ToString()); } // add to the structure status_packet.Attributes.Add(p_Ai); } // Add it to results packets.Add(status_packet); } catch (Exception e) { //TODO //SystemLog.Log("SQLServerDBConvert", "RawDataToDStatusPacket", e.Message, null); } } return packets; }
/// <summary> /// get index of @kNN points of point @A in the database /// </summary> /// <param name="index"></param> /// <param name="kNN"></param> /// <returns>kNN Index</returns> private static int[] getkNNIndexOfA(DStatusPacket A, int index, int kNN) { int[] kNNIndex = new int[kNN]; // index of database, not ID List <DPoint> distList = sortIndexOfNborByDist(A, index); for (int i = 0; i < kNN; i++) { kNNIndex[i] = (int)distList[i].ID; } return(kNNIndex); }
/// <summary> /// calculate euclidean distTableance of point @A and @B /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <returns>|AB|</returns> private static double euclDistance(DStatusPacket A, DStatusPacket B) { DStatusPacket tmp = new DStatusPacket(); tmp = A - B; // vector BA = A - B, we have reloaded the operator - in class DStatusPacket double result = 0.0; for (int i = 0; i < A.Attributes.Count(); i++) { result += Math.Pow(tmp.Attributes[i], 2); } return(Math.Sqrt(result)); }
/// <summary> /// calculate the approximate ABOF of point @A /// </summary> /// <param name="A"></param> /// <param name="index"></param> /// <param name="kNN"></param> /// <returns>ApproxABOF(A)</returns> private static double ApproxABOF(DStatusPacket A, int index, int kNN) { int[] kNNIndex = getkNNIndexOfA(A, index, kNN); List <DStatus> Nk = new List <DStatus>(); DStatusPacket B; double variance; for (int i = 0; i < kNNIndex.Length; i++) { B = data.getDataByID(kNNIndex[i]); Nk.Add(addIndexToPacket(kNNIndex[i], B)); } variance = ABOF(Nk, A, index); return(variance); }
/// <summary> /// calculate angle BAC(<AB, AC>) /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <param name="C"></param> /// <returns><AB, AC></returns> private static double calcAngleBAC(DStatusPacket A, DStatusPacket B, DStatusPacket C, double AB, double AC) { DStatusPacket vector_AB = B - A; DStatusPacket vector_AC = C - A; double dotProduct, cos_BAC = 0.0, angle; dotProduct = calcDotProduct(vector_AB, vector_AC); try { cos_BAC = dotProduct / (AB * AC); } catch (DivideByZeroException e) { Console.WriteLine("Overflow Exception:" + e.Message); } if (Math.Abs(cos_BAC) > 1) { Console.WriteLine("DotProduct: " + dotProduct + "\tAB: " + AB + "\tAC: " + AC); Console.WriteLine("Math Domain Error: |cos<AB, AC>| <= 1"); } angle = Math.Acos(cos_BAC); return(angle); }
/// <summary> /// add index of database to DStatusPacket @src /// </summary> /// <param name="index"></param> /// <param name="src"></param> /// <returns></returns> private static DStatus addIndexToPacket(int index, DStatusPacket src) { DStatus dst = new DStatus(); dst.Index = index; dst.ID = src.ID; dst.Attributes = src.Attributes; return dst; }
/// <summary> /// calculate ABOF of point @A /// </summary> /// <param name="D">neighbour of point A</param> /// <param name="A"></param> /// <param name="index"></param> /// <returns>ABOF(A)</returns> private static double ABOF(List <DStatus> D, DStatusPacket A, int index) { DStatusPacket B, C; int indexB, indexC; double AB, AC; // AB = |AB|, AC = |AC| double angle_BAC, tmp = 0.0, variance; double dotProductOfABandAC; // AB * AC /* * For ABOD, D include all the points, except for the point @A, the size * of @tmpList is (D.Count() - 1) * (D.Count() - 2) / 2 ; * However, for Fast ABOD, @D is the k nearest neighbor of point @A, when * index >= Nk.Count(), there's no need to except @A, therefore, the size * of @tmpList is D.Count * (D.Count - 1) / 2. */ double[] tmpList = new double[D.Count() * (D.Count() - 1) / 2]; int k = 0; for (int i = 0; i < D.Count(); i++) { indexB = D[i].Index; if (indexB == index) { continue; } B = dropIndexFromPacket(D[i]); if (indexB < index) { AB = distTable[indexB, index]; } else { AB = distTable[index, indexB]; } for (int j = i + 1; j < D.Count(); j++) { indexC = D[j].Index; if (indexC == index || indexC == indexB) { continue; } C = dropIndexFromPacket(D[j]); if (indexC < index) { AC = distTable[indexC, index]; } else { AC = distTable[index, indexC]; } dotProductOfABandAC = calcDotProduct(B - A, C - A); /* //debug * angle_BAC = calcAngleBAC(A, B, C, AB, AC); * if (AB == 0 || AC == 0 || angle_BAC == 0) * Console.WriteLine("indexA: {0}\tindexB: {1}\tindexC: {2}\tAB: {3}\tAC: {4}\tangle_BAC = {5}", index, indexB, indexC, AB, AC, angle_BAC); */ try { tmp = dotProductOfABandAC / Math.Pow(AB * AC, 2); } catch (DivideByZeroException e) { Console.WriteLine("Overflow Exception:" + e.Message); } tmpList[k++] = tmp; } } variance = calcVariance(tmpList); return(variance); }
/// <summary> /// calculate the approximate ABOF of point @A /// </summary> /// <param name="A"></param> /// <param name="index"></param> /// <param name="kNN"></param> /// <returns>ApproxABOF(A)</returns> private static double ApproxABOF(DStatusPacket A, int index, int kNN) { int[] kNNIndex = getkNNIndexOfA(A, index, kNN); List<DStatus> Nk = new List<DStatus>(); DStatusPacket B; double variance; for (int i = 0; i < kNNIndex.Length; i++) { B = data.getDataByID(kNNIndex[i]); Nk.Add(addIndexToPacket(kNNIndex[i], B)); } variance = ABOF(Nk, A, index); return variance; }
/// <summary> /// calculate dot product of vector @A and @B /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <returns>A * B</returns> private static double calcDotProduct(DStatusPacket vectorAB, DStatusPacket vectorAC) { double result = 0.0; for (int i = 0; i < vectorAB.Attributes.Count(); i++) { result += vectorAB.Attributes[i] * vectorAC.Attributes[i]; } return result; }
/// <summary> /// calculate angle BAC(<AB, AC>) /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <param name="C"></param> /// <returns><AB, AC></returns> private static double calcAngleBAC(DStatusPacket A, DStatusPacket B, DStatusPacket C, double AB, double AC) { DStatusPacket vector_AB = B - A; DStatusPacket vector_AC = C - A; double dotProduct, cos_BAC = 0.0, angle; dotProduct = calcDotProduct(vector_AB, vector_AC); try { cos_BAC = dotProduct / (AB * AC); } catch (DivideByZeroException e) { Console.WriteLine("Overflow Exception:" + e.Message); } if (Math.Abs(cos_BAC) > 1) { Console.WriteLine("DotProduct: " + dotProduct + "\tAB: " + AB + "\tAC: " + AC); Console.WriteLine("Math Domain Error: |cos<AB, AC>| <= 1"); } angle = Math.Acos(cos_BAC); return angle; }
/// <summary> /// calculate LB-ABOF of point @A /// </summary> /// <param name="A"></param> /// <param name="index"></param> /// <param name="kNN"></param> /// <returns>LB-ABOF(A)</returns> private static double LB_ABOF(List <DStatus> D, DStatusPacket A, int index, int kNN) { int[] kNNIndex = getkNNIndexOfA(A, index, kNN); List <DStatus> Nk = new List <DStatus>(kNNIndex.Length); int indexB, indexC; DStatusPacket B, C; double AB, AC, dotProductOfABandAC, angle_BAC, R1 = 0.0, R2, tmp = 0.0; double Minuend_Numerator = 0.0, Subtrahend_Numerator = 0.0, Denominator; double Minuend = 0.0, Subtrahend = 0.0; for (int i = 0; i < kNNIndex.Length; i++) // Nk { indexB = kNNIndex[i]; if (indexB == index) { continue; } B = data.getDataByID(indexB); Nk.Add(addIndexToPacket(indexB, B)); // k nearest neighbor of point A if (indexB < index) { AB = distTable[indexB, index]; } else { AB = distTable[index, indexB]; } for (int j = i + 1; j < kNNIndex.Length; j++) { indexC = kNNIndex[j]; if (indexC == index || indexC == indexB) { continue; } C = data.getDataByID(indexC); if (indexC < index) { AC = distTable[indexC, index]; } else { AC = distTable[index, indexC]; } //angle_BAC = calcAngleBAC(A, B, C, AB, AC); dotProductOfABandAC = calcDotProduct(B - A, C - A); try { tmp = dotProductOfABandAC / Math.Pow(AB * AC, 3); // <AB, AC> / (|AB| * |AC|) ^ 3 } catch (DivideByZeroException e) { Console.WriteLine("Overflow Exception:" + e.Message); } Minuend_Numerator += Math.Pow(tmp, 2) * AB * AC; Subtrahend_Numerator += tmp; } } R2 = calcR2(D, Nk, index); //R1 = R2; Denominator = rcpcOfModePlot_Linear(D, index, 1); // D try { Minuend = 2.0 * (Minuend_Numerator + R1) / Denominator; Subtrahend = Math.Pow(((2.0 * Subtrahend_Numerator + R2) / Denominator), 2); } catch (DivideByZeroException e) { Console.WriteLine("Deominator != 0" + e.Message); } return(Minuend - Subtrahend); // return LB-ABOF(A) }
/// <summary> /// calculate ABOF of point @A /// </summary> /// <param name="D">neighbour of point A</param> /// <param name="A"></param> /// <param name="index"></param> /// <returns>ABOF(A)</returns> private static double ABOF(List<DStatus> D, DStatusPacket A, int index) { DStatusPacket B, C; int indexB, indexC; double AB, AC; // AB = |AB|, AC = |AC| double angle_BAC, tmp = 0.0, variance; double dotProductOfABandAC; // AB * AC /* * For ABOD, D include all the points, except for the point @A, the size * of @tmpList is (D.Count() - 1) * (D.Count() - 2) / 2 ; * However, for Fast ABOD, @D is the k nearest neighbor of point @A, when * index >= Nk.Count(), there's no need to except @A, therefore, the size * of @tmpList is D.Count * (D.Count - 1) / 2. */ double[] tmpList = new double[D.Count() * (D.Count() - 1) / 2]; int k = 0; for (int i = 0; i < D.Count(); i++) { indexB = D[i].Index; if (indexB == index) continue; B = dropIndexFromPacket(D[i]); if (indexB < index) AB = distTable[indexB, index]; else AB = distTable[index, indexB]; for (int j = i + 1; j < D.Count(); j++) { indexC = D[j].Index; if (indexC == index || indexC == indexB) continue; C = dropIndexFromPacket(D[j]); if (indexC < index) AC = distTable[indexC, index]; else AC = distTable[index, indexC]; dotProductOfABandAC = calcDotProduct(B - A, C - A); /* //debug angle_BAC = calcAngleBAC(A, B, C, AB, AC); if (AB == 0 || AC == 0 || angle_BAC == 0) Console.WriteLine("indexA: {0}\tindexB: {1}\tindexC: {2}\tAB: {3}\tAC: {4}\tangle_BAC = {5}", index, indexB, indexC, AB, AC, angle_BAC); */ try { tmp = dotProductOfABandAC / Math.Pow(AB * AC, 2); } catch (DivideByZeroException e) { Console.WriteLine("Overflow Exception:" + e.Message); } tmpList[k++] = tmp; } } variance = calcVariance(tmpList); return variance; }
/// <summary> /// calculate LB-ABOF of point @A /// </summary> /// <param name="A"></param> /// <param name="index"></param> /// <param name="kNN"></param> /// <returns>LB-ABOF(A)</returns> private static double LB_ABOF(List<DStatus> D, DStatusPacket A, int index, int kNN) { int[] kNNIndex = getkNNIndexOfA(A, index, kNN); List<DStatus> Nk = new List<DStatus>(kNNIndex.Length); int indexB, indexC; DStatusPacket B, C; double AB, AC, dotProductOfABandAC, angle_BAC, R1 = 0.0, R2, tmp = 0.0; double Minuend_Numerator = 0.0, Subtrahend_Numerator = 0.0, Denominator; double Minuend = 0.0, Subtrahend = 0.0; for (int i = 0; i < kNNIndex.Length; i++) // Nk { indexB = kNNIndex[i]; if (indexB == index) continue; B = data.getDataByID(indexB); Nk.Add(addIndexToPacket(indexB, B)); // k nearest neighbor of point A if (indexB < index) AB = distTable[indexB, index]; else AB = distTable[index, indexB]; for (int j = i + 1; j < kNNIndex.Length; j++) { indexC = kNNIndex[j]; if (indexC == index || indexC == indexB) continue; C = data.getDataByID(indexC); if (indexC < index) AC = distTable[indexC, index]; else AC = distTable[index, indexC]; //angle_BAC = calcAngleBAC(A, B, C, AB, AC); dotProductOfABandAC = calcDotProduct(B - A, C - A); try { tmp = dotProductOfABandAC / Math.Pow(AB * AC, 3); // <AB, AC> / (|AB| * |AC|) ^ 3 } catch (DivideByZeroException e) { Console.WriteLine("Overflow Exception:" + e.Message); } Minuend_Numerator += Math.Pow(tmp, 2) * AB * AC; Subtrahend_Numerator += tmp; } } R2 = calcR2(D, Nk, index); //R1 = R2; Denominator = rcpcOfModePlot_Linear(D, index, 1); // D try { Minuend = 2.0 * (Minuend_Numerator + R1) / Denominator; Subtrahend = Math.Pow(((2.0 * Subtrahend_Numerator + R2) / Denominator), 2); } catch (DivideByZeroException e) { Console.WriteLine("Deominator != 0" + e.Message); } return (Minuend - Subtrahend); // return LB-ABOF(A) }
/// <summary> /// get index of @kNN points of point @A in the database /// </summary> /// <param name="index"></param> /// <param name="kNN"></param> /// <returns>kNN Index</returns> private static int[] getkNNIndexOfA(DStatusPacket A, int index, int kNN) { int[] kNNIndex = new int[kNN]; // index of database, not ID List<DPoint> distList = sortIndexOfNborByDist(A, index); for (int i = 0; i < kNN; i++) { kNNIndex[i] = (int)distList[i].ID; } return kNNIndex; }
/// <summary> /// calculate euclidean distTableance of point @A and @B /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <returns>|AB|</returns> private static double euclDistance(DStatusPacket A, DStatusPacket B) { DStatusPacket tmp = new DStatusPacket(); tmp = A - B; // vector BA = A - B, we have reloaded the operator - in class DStatusPacket double result = 0.0; for (int i = 0; i < A.Attributes.Count(); i++) { result += Math.Pow(tmp.Attributes[i], 2); } return Math.Sqrt(result); }
/// <summary> /// drop index form packet (convert DStatus to DStatusPacket) /// </summary> /// <param name="src"></param> /// <returns></returns> private static DStatusPacket dropIndexFromPacket(DStatus src) { DStatusPacket dst = new DStatusPacket(); dst.ID = src.ID; dst.Attributes = src.Attributes; return dst; }
/// <summary> /// code by H-P. Kerigel /// </summary> /// <param name="D"></param> /// <param name="A"></param> /// <param name="index"></param> /// <param name="kNN"></param> /// <returns></returns> private static double calcLBABOF(DStatusPacket A, int index, int kNN) { List<DPoint> NkIndex = new List<DPoint>(); // Compute nearest neighbors and distances. double simAA = calcDotProduct(A, A); // Sum of 1./(|AB|) and 1./(|AB|^2); for computing R2. double sumid = 0, sumisqd = 0; for (int j = 0; j < LENGTH; j++) { if (index == j) { continue; } DStatusPacket nB = data.getDataByID(j); double simBB = calcDotProduct(nB, nB); double simAB = calcDotProduct(A, nB); double sqdAB = simAA + simBB - simAB - simAB; if (!(sqdAB > 0)) { continue; } sumid += 1 / Math.Sqrt(sqdAB); sumisqd += 1 / sqdAB; // Update heap DPoint temp = new DPoint(j, sqdAB); if (NkIndex.Count < kNN) { NkIndex.Add(temp); } else if (sqdAB < NkIndex.Max().Value) { //移出最大的 NkIndex.Remove(NkIndex.Max()); NkIndex.Add(temp); } } // Compute FastABOD approximation, adjust for lower bound. // LB-ABOF is defined via a numerically unstable formula. // Variance as E(X^2)-E(X)^2 suffers from catastrophic cancellation! // TODO: ensure numerical precision! double nnsum = 0, nnsumsq = 0, nnsumisqd = 0; for (int k = 0; k < NkIndex.Count; k++) { DPoint iB = NkIndex[k]; DStatusPacket nB = data.getDataByID(iB.ID); double sqdAB = iB.Value; double simAB = calcDotProduct(A, nB); if (!(sqdAB > 0)) { continue; } for (int l = 0; l < NkIndex.Count; l++) { if (k == l) { continue; } DPoint iC = NkIndex[l]; DStatusPacket nC = data.getDataByID(iC.ID); double sqdAC = iC.Value; double simAC = calcDotProduct(A, nC); if (!(sqdAC > 0)) { continue; } // Exploit bilinearity of scalar product: // <B-A, C-A> = <B, C-A> - <A,C-A> // = <B,C> - <B,A> - <A,C> + <A,A> double simBC = calcDotProduct(nB, nC); double numerator = simBC - simAB - simAC + simAA; double sqweight = 1 / (sqdAB * sqdAC); double weight = Math.Sqrt(sqweight); double val = numerator * sqweight; nnsum += val * weight; nnsumsq += val * val * weight; nnsumisqd += sqweight; } } // Remaining weight, term R2: double r2 = sumisqd * sumisqd - 2 * nnsumisqd; double tmp = (2 * nnsum + r2) / (sumid * sumid); double lbabof = 2 * nnsumsq / (sumid * sumid) - tmp * tmp; return lbabof; }
/// <summary> /// code by H-P. Kerigel /// </summary> /// <param name="D"></param> /// <param name="A"></param> /// <param name="index"></param> /// <param name="kNN"></param> /// <returns></returns> private static double calcLBABOF(DStatusPacket A, int index, int kNN) { List <DPoint> NkIndex = new List <DPoint>(); // Compute nearest neighbors and distances. double simAA = calcDotProduct(A, A); // Sum of 1./(|AB|) and 1./(|AB|^2); for computing R2. double sumid = 0, sumisqd = 0; for (int j = 0; j < LENGTH; j++) { if (index == j) { continue; } DStatusPacket nB = data.getDataByID(j); double simBB = calcDotProduct(nB, nB); double simAB = calcDotProduct(A, nB); double sqdAB = simAA + simBB - simAB - simAB; if (!(sqdAB > 0)) { continue; } sumid += 1 / Math.Sqrt(sqdAB); sumisqd += 1 / sqdAB; // Update heap DPoint temp = new DPoint(j, sqdAB); if (NkIndex.Count < kNN) { NkIndex.Add(temp); } else if (sqdAB < NkIndex.Max().Value) { //移出最大的 NkIndex.Remove(NkIndex.Max()); NkIndex.Add(temp); } } // Compute FastABOD approximation, adjust for lower bound. // LB-ABOF is defined via a numerically unstable formula. // Variance as E(X^2)-E(X)^2 suffers from catastrophic cancellation! // TODO: ensure numerical precision! double nnsum = 0, nnsumsq = 0, nnsumisqd = 0; for (int k = 0; k < NkIndex.Count; k++) { DPoint iB = NkIndex[k]; DStatusPacket nB = data.getDataByID(iB.ID); double sqdAB = iB.Value; double simAB = calcDotProduct(A, nB); if (!(sqdAB > 0)) { continue; } for (int l = 0; l < NkIndex.Count; l++) { if (k == l) { continue; } DPoint iC = NkIndex[l]; DStatusPacket nC = data.getDataByID(iC.ID); double sqdAC = iC.Value; double simAC = calcDotProduct(A, nC); if (!(sqdAC > 0)) { continue; } // Exploit bilinearity of scalar product: // <B-A, C-A> = <B, C-A> - <A,C-A> // = <B,C> - <B,A> - <A,C> + <A,A> double simBC = calcDotProduct(nB, nC); double numerator = simBC - simAB - simAC + simAA; double sqweight = 1 / (sqdAB * sqdAC); double weight = Math.Sqrt(sqweight); double val = numerator * sqweight; nnsum += val * weight; nnsumsq += val * val * weight; nnsumisqd += sqweight; } } // Remaining weight, term R2: double r2 = sumisqd * sumisqd - 2 * nnsumisqd; double tmp = (2 * nnsum + r2) / (sumid * sumid); double lbabof = 2 * nnsumsq / (sumid * sumid) - tmp * tmp; return(lbabof); }
/// <summary> /// sort point @A 's all neighbor index by their distance to @A /// </summary> /// <param name="A"></param> /// <param name="index"></param> /// <returns></returns> private static List<DPoint> sortIndexOfNborByDist(DStatusPacket A, int index) { List<DPoint> distList = new List<DPoint>(LENGTH - 1); DPoint tmp; double AB; // dist(A, B) for (int i = 0; i < LENGTH; i++) { if (i == index) continue; else if (i < index) AB = distTable[i, index]; else AB = distTable[index, i]; tmp = new DPoint(i, AB); // i: the index of B in the database distList.Add(tmp); } distList.Sort(); // sort by tmp.Value (distance) ascending return distList; }