/** * eliminate null entries, move all entries to the start of the source node */ internal void reorganize(RTree <T> rtree) { int countdownIndex = rtree.maxNodeEntries - 1; for (int index = 0; index < entryCount; index++) { if (entries[index] == null) { while (entries[countdownIndex] == null && countdownIndex > index) { countdownIndex--; } entries[index] = entries[countdownIndex]; ids[index] = ids[countdownIndex]; entries[countdownIndex] = null; } } }
} // end RunOnline_Liu_edit public static List <double> RunOnline_LiuMethod_edited(List <double> buffer, int index_stream, List <double> removed_sub, RTree <int> this_RTree, double this_best_so_far_dist, int this_best_so_far_loc, int this_NLength, int this_D) { /* Liu's algorithm */ //calc 'currDist' which is the distance of the discord at time t and the new subsquence at time (t+1): double currDist = 0; if (this_best_so_far_loc > 0) // make sure we can calc CurrDist when 'this_best_so_far_loc - 1' >= 0 { currDist = Utils.MathFuncs.EuDistance(buffer.GetRange(this_best_so_far_loc - 1, this_NLength), buffer.GetRange(buffer.Count - this_NLength, this_NLength)); } //if the case (a): Modify the Rtree: call method1 if (currDist < this_best_so_far_dist || this_best_so_far_loc == 0) { Console.WriteLine("Running case (a)..."); return(LiuEdited_CaseA(buffer, index_stream, this_RTree, this_NLength, this_D)); } else //case (b): we can reduce the num of elements in the outer loop: { Console.WriteLine("Running case (b)........."); List <int> candidate_list_reduced = new List <int>(); //store outer loop /* Find the candidate_list:*/ //The local discord at time t: int first_candidate = (this_best_so_far_loc - 1); //The subsequence (m-n+1, n)(t+1): int second_candidate = (buffer.Count - this_NLength); /* we will do the rest by calling Liu_edit:*/ return(LiuEdited_CaseB(buffer, index_stream, first_candidate, second_candidate, removed_sub, this_RTree, this_NLength, this_D, this_best_so_far_dist)); } }
/* new_online_algorithm: */ public static List <double> NewOnlineAlgorithm(List <double> buffer, int startPoint, int index_stream, int period, List <double> new_sub, RTree <int> this_RTree, int this_NLength, int this_D, int this_R, int maxEntry, int minEntry, ref double this_best_so_far_dist_TheMostDiscord) { int best_so_far_loc = -1; // update data (for calculating thres) ? if (index_stream % period == 0) //update after a period { List <double> this_buffer_to_startPoint = buffer.GetRange(0, startPoint); // Useless variable to pass parameter int dumb = 0; List <int> dumb_list = new List <int>(); List <Rectangle> dumb_rectlist = new List <Rectangle>(); RTree <int> dumb_rtree = new RTree <int>(maxEntry, minEntry); //calc TheMostDiscord T[1:sp] (return at "this_best_so_far_dist_TheMostDiscord" variable): List <double> discord = RunOfflineMinDist(this_buffer_to_startPoint, this_NLength, maxEntry, minEntry, this_R, this_D, ref dumb, ref dumb_list, ref dumb_rectlist, ref dumb_rtree, false); this_best_so_far_dist_TheMostDiscord = discord[0]; Console.WriteLine("update data (for calculating thres), at index_stream " + index_stream); } //get threshold_dist: double threshold_dist = this_best_so_far_dist_TheMostDiscord; //index of new_subsequence q: int q_outer = buffer.Count - this_NLength; // get Inner list: Dictionary <int, Node <int> > nodeMap = this_RTree.getNodeMap(); List <Node <int> > leafNodes = nodeMap.Values.Where(node => node.level == 1).OrderBy(node => node.entryCount).ToList(); List <int> innerList = new List <int>(); for (int num = 0; num < leafNodes.Count; num++) { List <int> all_entry_IDs_from_a_node = leafNodes[num].entries.Where(mbr => (mbr != null) && (mbr.getIndexSubSeq(index_stream + 1) != q_outer)).Select(mbr => mbr.getIndexSubSeq(index_stream + 1)).ToList(); if (all_entry_IDs_from_a_node.Count == leafNodes[num].entryCount) // if q in the outer loop is NOT in this leaf: { innerList.AddRange(all_entry_IDs_from_a_node); } else // If q is IN this leaf: We add all entry ids in the leaf to the head of the innerList { innerList.InsertRange(0, all_entry_IDs_from_a_node); // note: In this case, all_Entry_IDs_from_a_node doesnt include 'q' id. } } double nearest_neighbor_dist = Constants.INFINITE; foreach (int p_inner in innerList) { if (Math.Abs(p_inner - q_outer) >= this_NLength) { //calculate the Distance between p and q double dist = MathFuncs.EuDistance(new_sub, buffer.GetRange(p_inner, this_NLength)); if (dist < nearest_neighbor_dist) { nearest_neighbor_dist = dist; // best_so_far_loc = p_inner; //store best_so_far_loc } if (dist < threshold_dist) { break; } } } if (nearest_neighbor_dist > threshold_dist) { best_so_far_loc = q_outer; Console.WriteLine("Discord!\nbest_so_far_loc = " + best_so_far_loc + "\nbest_so_far_dist = " + nearest_neighbor_dist); } else { Console.WriteLine("No discord"); best_so_far_loc = -1; nearest_neighbor_dist = -1; } return(new List <double>() { nearest_neighbor_dist, best_so_far_loc }); //return "-1" if there is no discord. }
} //end RunOnline_LiuEditedCaseA /* Called by RunOnline_LiuMethod_edited:*/ public static List <double> LiuEdited_CaseB(List <double> buffer, int index_stream, int first_candidate, int second_candidate, List <double> removed_sub, RTree <int> this_RTree, int this_NLength, int this_D, double this_best_so_far_dist) { List <int> candidateList = new List <int>(); List <int> beginIndexInner = new List <int>(); List <int> indexOfLeafMBRS = new List <int>(); Dictionary <int, Node <int> > nodeMap = this_RTree.getNodeMap(); List <Node <int> > leafNodes = nodeMap.Values.Where(node => ((node.level == 1))).OrderBy(node => node.entryCount).ToList(); List <Rectangle> leafMBRs = leafNodes.Select(node => node.mbr).ToList(); // List rectangle of leaf nodes in order of list leafNodes for (int num = 0; num < leafNodes.Count; num++) { List <Rectangle> leafEntries = leafNodes[num].entries.Where(mbr => mbr != null).Select(mbr => mbr).ToList(); if (leafEntries.Count > 0) { int beginIndex = candidateList.Count; // we change a bit at the following line, we subtract mbr indice by "index_stream + 1": candidateList.AddRange(leafEntries.Select(mbr => mbr.getIndexSubSeq(index_stream + 1))); beginIndexInner.AddRange(Enumerable.Range(1, leafEntries.Count).Select(x => beginIndex)); indexOfLeafMBRS.AddRange(Enumerable.Repeat(num, leafEntries.Count)); } } // end for // get the two first candidates to the head of candidateList int count = 0; int index = 0; while (count < 1) { if (candidateList[index] == first_candidate) { candidateList[index] = candidateList[0]; int temp = beginIndexInner[index]; beginIndexInner[index] = beginIndexInner[0]; beginIndexInner[0] = temp; count++; } if (candidateList[index] == second_candidate) { candidateList[index] = candidateList[1]; int temp = beginIndexInner[index]; beginIndexInner[index] = beginIndexInner[1]; beginIndexInner[1] = temp; count++; } index++; } candidateList[0] = first_candidate; candidateList[1] = second_candidate; double best_so_far_dist = 0; int best_so_far_loc = 0; double nearest_neighbor_dist = 0; double dist = 0; bool break_to_outer_loop = false; bool[] is_skipped_at_p = new bool[buffer.Count]; for (int i = 0; i < buffer.Count; i++) { is_skipped_at_p[i] = false; } for (int i = 0; i < candidateList.Count; i++) { int p = candidateList[i]; //check small_match: double small_match = Utils.MathFuncs.EuDistance(buffer.GetRange(p, this_NLength), removed_sub); if (i >= 2 && small_match >= this_best_so_far_dist) { continue; } if (is_skipped_at_p[p]) { //p was visited at inner loop before continue; } else { List <double> subseq_p = buffer.GetRange(p, this_NLength); //Rectangle p_rectangle = recList[p]; List <double> P_PAA = MathFuncs.PAA(subseq_p, this_D); nearest_neighbor_dist = Constants.INFINITE; List <bool> eliminatedMBR = new List <bool>(); for (int k = 0; k < leafMBRs.Count; k++) { eliminatedMBR.Add(false); } int indexMBRLeaf = -1; for (int j = 0; j < candidateList.Count; j++)// inner loop { // int q = innerList[j]; int index_inner = (beginIndexInner[i] + j) % candidateList.Count; int q = candidateList[index_inner]; int index_MBRInnner = (beginIndexInner[i] + j) % candidateList.Count; int MBRInnner = indexOfLeafMBRS[index_MBRInnner]; if (indexMBRLeaf < MBRInnner)//the first entry of the next node ? { indexMBRLeaf++; /* Test: * if (indexMBRInnner[j] == MBRInnner) * Console.WriteLine("OK");*/ //calc minDist: //double minDist = MathFuncs.MINDIST(p_rectangle, leafMBRs[MBRInnner], (NLength / (double)(D))); double minDist = MathFuncs.MINDIST(P_PAA, leafMBRs[MBRInnner], (this_NLength / (double)(this_D))); //if (minDist_keo > minDist) //{ // Console.WriteLine("STOPPP"); // return; //} if (minDist >= nearest_neighbor_dist) { eliminatedMBR[MBRInnner] = true; continue;// pruned => skip to the next one } else { if (Math.Abs(p - q) < this_NLength) { continue;// self-match => skip to the next one } //calculate the Distance between p and q dist = MathFuncs.EuDistance(subseq_p, buffer.GetRange(q, this_NLength)); if (dist < best_so_far_dist) { //skip the element q at oute_loop, 'cuz if (p,q) is not a solution, neither is (q,p). is_skipped_at_p[q] = true; break_to_outer_loop = true; //break, to the next loop at outer_loop break; // break at inner_loop first } if (dist < nearest_neighbor_dist) { nearest_neighbor_dist = dist; } } } else // still the same node { if (eliminatedMBR[MBRInnner]) // can prune ? { continue; } else //do it normally { if (Math.Abs(p - q) < this_NLength) { continue;// self-match => skip to the next one } else { //calculate the Distance between p and q dist = MathFuncs.EuDistance(subseq_p, buffer.GetRange(q, this_NLength)); if (dist < best_so_far_dist) { //skip the element q at oute_loop, 'cuz if (p,q) is not a solution, neither is (q,p). is_skipped_at_p[q] = true; break_to_outer_loop = true; //break, to the next loop at outer_loop break; // break at inner_loop first } if (dist < nearest_neighbor_dist) { nearest_neighbor_dist = dist; } } } } //end ELSE } //end for inner loop //Console.WriteLine("num_leaf_skips="+ num_leaf_skips); if (break_to_outer_loop) { break_to_outer_loop = false; //reset continue; //go to the next p in outer loop } if (nearest_neighbor_dist > best_so_far_dist) { best_so_far_dist = nearest_neighbor_dist; best_so_far_loc = p; } //////////////////////// } } // end for //update the results: Console.WriteLine("index_stream = " + index_stream); Console.WriteLine("best_so_far_loc = " + best_so_far_loc); Console.WriteLine("best_so_far_dist = " + best_so_far_dist); List <double> result = new List <double> { best_so_far_dist, best_so_far_loc }; return(result); } // end RunOnline_Liu_edit
//////////// Helper Functions /////////////// /* Called by RunOnline_LiuMethod_edited:*/ public static List <double> LiuEdited_CaseA(List <double> inputData, int index_stream, RTree <int> this_RTree, int this_NLength, int this_D) { /* This function is almost the same as Offline_minDist version. We just edit some lines*/ List <int> candidateList = new List <int>(); List <int> beginIndexInner = new List <int>(); List <int> indexOfLeafMBRS = new List <int>(); bool[] is_skipped_at_p = new bool[inputData.Count]; for (int i = 0; i < inputData.Count; i++) { is_skipped_at_p[i] = false; } double best_so_far_dist = 0; int best_so_far_loc = 0; double nearest_neighbor_dist = 0; double dist = 0; bool break_to_outer_loop = false; Dictionary <int, Node <int> > nodeMap = this_RTree.getNodeMap(); List <Node <int> > leafNodes = nodeMap.Values.Where(node => node.level == 1).OrderBy(node => node.entryCount).ToList(); List <Rectangle> leafMBRs = leafNodes.Select(node => node.mbr).ToList(); // List rectangle of leaf nodes in order of list leafNodes for (int i = 0; i < leafNodes.Count; i++) { List <Rectangle> leafEntries = leafNodes[i].entries.Where(mbr => mbr != null).Select(mbr => mbr).ToList(); if (leafEntries.Count > 0) { int beginIndex = candidateList.Count; // we change a bit at the following line, we subtract mbr indice by "index_stream + 1": candidateList.AddRange(leafEntries.Select(mbr => mbr.getIndexSubSeq(index_stream + 1))); beginIndexInner.AddRange(Enumerable.Repeat(beginIndex, leafEntries.Count)); indexOfLeafMBRS.AddRange(Enumerable.Repeat(i, leafEntries.Count)); } } for (int i = 0; i < candidateList.Count; i++)//outer loop { int p = candidateList[i]; if (is_skipped_at_p[p]) { //p was visited at inner loop before continue; } else { List <double> subseq_p = inputData.GetRange(p, this_NLength); //Rectangle p_rectangle = recList[p]; List <double> P_PAA = MathFuncs.PAA(subseq_p, this_D); nearest_neighbor_dist = Constants.INFINITE; List <bool> eliminatedMBR = new List <bool>(); for (int k = 0; k < leafMBRs.Count; k++) { eliminatedMBR.Add(false); } int indexMBRLeaf = -1; int num_leaf_skips = 0; for (int j = 0; j < candidateList.Count; j++)// inner loop { // int q = innerList[j]; int index_inner = (beginIndexInner[i] + j) % candidateList.Count; int q = candidateList[index_inner]; int index_MBRInnner = (beginIndexInner[i] + j) % candidateList.Count; int MBRInnner = indexOfLeafMBRS[index_MBRInnner]; if (indexMBRLeaf < MBRInnner)//the first entry of the next node ? { indexMBRLeaf++; //calc minDist: //double minDist = MathFuncs.MINDIST(p_rectangle, leafMBRs[MBRInnner], (NLength / (double)(D))); double minDist = MathFuncs.MINDIST(P_PAA, leafMBRs[MBRInnner], (this_NLength / (double)(this_D))); if (minDist >= nearest_neighbor_dist) { num_leaf_skips++; eliminatedMBR[MBRInnner] = true; continue;// pruned => skip to the next one } else { if (Math.Abs(p - q) < this_NLength) { continue;// self-match => skip to the next one } //calculate the Distance between p and q dist = MathFuncs.EuDistance(subseq_p, inputData.GetRange(q, this_NLength)); if (dist < best_so_far_dist) { //skip the element q at oute_loop, 'cuz if (p,q) is not a solution, neither is (q,p). is_skipped_at_p[q] = true; break_to_outer_loop = true; //break, to the next loop at outer_loop break; // break at inner_loop first } if (dist < nearest_neighbor_dist) { nearest_neighbor_dist = dist; } } } else // still the same node { if (eliminatedMBR[MBRInnner]) // can prune ? { continue; } else //do it normally { if (Math.Abs(p - q) < this_NLength) { continue;// self-match => skip to the next one } else { //calculate the Distance between p and q dist = MathFuncs.EuDistance(subseq_p, inputData.GetRange(q, this_NLength)); if (dist < best_so_far_dist) { //skip the element q at oute_loop, 'cuz if (p,q) is not a solution, neither is (q,p). is_skipped_at_p[q] = true; break_to_outer_loop = true; //break, to the next loop at outer_loop break; // break at inner_loop first } if (dist < nearest_neighbor_dist) { nearest_neighbor_dist = dist; } } } } //end ELSE } //end for inner loop if (break_to_outer_loop) { break_to_outer_loop = false; //reset continue; //go to the next p in outer loop } if (nearest_neighbor_dist > best_so_far_dist) { best_so_far_dist = nearest_neighbor_dist; best_so_far_loc = p; } } }//end outer loop Console.WriteLine("index_stream=" + index_stream); Console.WriteLine("best_so_far_loc=" + best_so_far_loc); Console.WriteLine("best_so_far_dist=" + best_so_far_dist); List <double> result = new List <double> { best_so_far_dist, best_so_far_loc }; return(result); } //end RunOnline_LiuEditedCaseA
} //end btnRunOnl_Click function /*Run Online - new method (inner loop only)*/ private void Btn_NewOnline_Click(List <double> training_data, List <double> streaming_data, int period, int NLength, int maxEntry, int minEntry, int R, int D) { //create a new buffer. In this demo, the buffer is training_data (edit later): List <double> this_buffer = new List <double>(); this_buffer.AddRange(training_data); // Store furnitures in RTree int this_id_item = int.MinValue; List <int> this_id_itemList = new List <int>(); RTree <int> this_RTree = new RTree <int>(maxEntry, minEntry); List <Rectangle> this_recList = new List <Rectangle>(); // Call 'Run Offline' for the first time, store results into variables ("this" object): List <double> discord_firsttime = RunOfflineMinDist(training_data, NLength, maxEntry, minEntry, R, D, ref this_id_item, ref this_id_itemList, ref this_recList, ref this_RTree, true); double this_best_so_far_dist_TheMostDiscord = discord_firsttime[0]; //store the last subsequence of the buffer: List <double> last_sub = this_buffer.GetRange(this_buffer.Count - NLength, NLength); // STREAMING: keep streaming until we have no more data points for (int index_stream = 0; index_stream < streaming_data.Count; index_stream++) { var watch = System.Diagnostics.Stopwatch.StartNew();///calc execution time double new_data_point = streaming_data[index_stream]; //update last_sub at time t to get new_sub at time (t+1): last_sub.Add(new_data_point); last_sub.RemoveAt(0); List <double> new_sub = last_sub; // the same object // Insert the new entry into the tree: this_id_item++; // Add the new rec to the tree: Rectangle new_rec = new Rectangle(Utils.MathFuncs.PAA_Lower(new_sub, D, R).ToArray(), Utils.MathFuncs.PAA_Upper(new_sub, D, R).ToArray(), this_buffer.Count - NLength + 1 + index_stream); this_RTree.Add(new_rec, this_id_item); this_recList.Add(new_rec); this_id_itemList.Add(this_id_item); //remove the oldest entry: this_RTree.Delete(this_recList[index_stream], this_id_itemList[index_stream]); // update buffer: this_buffer.Add(new_data_point); this_buffer.RemoveAt(0); /* 'til now, we have already updated the tree. * from now on, almost just copy the offline code: */ //Run new_online_algorithm: NewOnlineAlgorithm(this_buffer, 2 * period, index_stream, period, new_sub, this_RTree, NLength, D, R, maxEntry, minEntry, ref this_best_so_far_dist_TheMostDiscord); watch.Stop(); //stop timer long elapsedMs = watch.ElapsedMilliseconds; //this.txtExeTime.Text = elapsedMs.ToString(); Console.WriteLine("ExeTime_Online=" + elapsedMs.ToString()); Console.WriteLine("------------------------"); } // end For loop (streaming) Console.WriteLine("--- Streaming's done (run out of data) ---"); }
/*Run Online (Liu method)*/ private void btnRunOnl_Click(List <double> training_data, List <double> streaming_data, int period, int NLength, int maxEntry, int minEntry, int R, int D) { //create a new buffer. In this demo, the buffer is training_data (edit later): List <double> this_buffer = new List <double>(); this_buffer.AddRange(training_data); // Store furnitures in RTree int this_id_item = int.MinValue; List <int> this_id_itemList = new List <int>(); RTree <int> this_RTree = new RTree <int>(maxEntry, minEntry); List <Rectangle> this_recList = new List <Rectangle>(); // Call 'Run Offline' for the first time, store results into variables ("this" object): List <double> discord_firsttime = RunOfflineMinDist(training_data, NLength, maxEntry, minEntry, R, D, ref this_id_item, ref this_id_itemList, ref this_recList, ref this_RTree, true); // Store current discord in buffer double this_best_so_far_dist = discord_firsttime[0]; double this_best_so_far_loc = discord_firsttime[1]; //store the last subsequence of the buffer: List <double> last_sub = this_buffer.GetRange(this_buffer.Count - NLength, NLength); // STREAMING: keep streaming until we have no more data points for (int index_stream = 0; index_stream < streaming_data.Count; index_stream++) { var watch = System.Diagnostics.Stopwatch.StartNew();///calc execution time double new_data_point = streaming_data[index_stream]; //update last_sub at time t to get new_sub at time (t+1): last_sub.Add(new_data_point); last_sub.RemoveAt(0); List <double> new_sub = last_sub; // the same object // Insert the new entry into the tree: this_id_item++; // Add the new rec to the tree: Rectangle new_rec = new Rectangle(Utils.MathFuncs.PAA_Lower(new_sub, D, R).ToArray(), Utils.MathFuncs.PAA_Upper(new_sub, D, R).ToArray(), this_buffer.Count - NLength + 1 + index_stream); this_RTree.Add(new_rec, this_id_item); this_recList.Add(new_rec); this_id_itemList.Add(this_id_item); //remove the oldest entry: this_RTree.Delete(this_recList[index_stream], this_id_itemList[index_stream]); //get the first sub before update the buffer (help to find the small match in Liu's method) List <double> first_sub = this_buffer.GetRange(0, NLength); // update buffer: this_buffer.Add(new_data_point); this_buffer.RemoveAt(0); /* 'til now, we have already updated the tree. * from now on, almost just copy the offline code: */ //Method 1: just re-order the 2 loops: //RunOnline_Method1(this_buffer, index_stream); //Method 2: Liu's algorithm: //Note: Method_2 includes method_1 (case a) //RunOnline_LiuMethod_origin(this_buffer, index_stream, first_sub); //Method 3: motified_Liu's List <double> discord_Liu = RunOnline_LiuMethod_edited(this_buffer, index_stream, first_sub, this_RTree, this_best_so_far_dist, (int)this_best_so_far_loc, NLength, D); this_best_so_far_dist = discord_Liu[0]; this_best_so_far_loc = discord_Liu[1]; watch.Stop(); //stop timer long elapsedMs = watch.ElapsedMilliseconds; //this.txtExeTime.Text = elapsedMs.ToString(); Console.WriteLine("ExeTime_Online=" + elapsedMs.ToString()); // Useless variable to pass parameter int dumb = 0; List <int> dumb_list = new List <int>(); List <Rectangle> dumb_rectlist = new List <Rectangle>(); RTree <int> dumb_rtree = new RTree <int>(maxEntry, minEntry); //call offline version to assure the results and compare the time executions: var watch2 = System.Diagnostics.Stopwatch.StartNew();///calc execution time offline List <double> discord_offline = RunOfflineMinDist(training_data, NLength, maxEntry, minEntry, R, D, ref dumb, ref dumb_list, ref dumb_rectlist, ref dumb_rtree, false); double this_best_so_far_dist_offline = discord_offline[0]; watch2.Stop(); //stop timer long this_exeTimeOffline = watch2.ElapsedMilliseconds; //check: if (Math.Abs(this_best_so_far_dist - this_best_so_far_dist_offline) < 10e-7) { Console.WriteLine("checked, ok."); if (elapsedMs > this_exeTimeOffline) { Console.WriteLine("Online takes more time than Offline !!!"); } } else { Console.WriteLine("this.best_so_far_dist = " + this_best_so_far_dist); Console.WriteLine("this.best_so_far_dist_Offline = " + this_best_so_far_dist_offline); Console.WriteLine("The results are different. Stop Streaming !!!"); return; } Console.WriteLine("------------------------"); } // end For loop (streaming) Console.WriteLine("--- Streaming's done (run out of data) ---"); } //end btnRunOnl_Click function
////////////// Main Functions ////////////// /*Run new offline (minDist) */ public static List <double> RunOfflineMinDist(List <double> inputData, int NLength, int maxEntry, int minEntry, int R, int D, ref int this_id_item, ref List <int> this_id_itemList, ref List <Rectangle> this_rectList, ref RTree <int> this_RTree, bool is_first_time) { int id_item = int.MinValue; RTree <int> rtree = new RTree <int>(maxEntry, minEntry); List <int> candidateList = new List <int>(); List <int> beginIndexInner = new List <int>(); List <int> indexOfLeafMBRS = new List <int>(); double best_so_far_dist = 0; int best_so_far_loc = -1; double nearest_neighbor_dist = 0; double dist = 0; bool break_to_outer_loop = false; bool[] is_skipped_at_p = new bool[inputData.Count]; for (int i = 0; i < inputData.Count; i++) { is_skipped_at_p[i] = false; } if (minEntry > maxEntry / 2) { MessageBox.Show("Requirement: MinNodePerEntry <= MaxNodePerEntry/2"); return(new List <double> { best_so_far_dist, best_so_far_loc }); } List <Rectangle> recList = new List <Rectangle>(); List <int> id_itemList = new List <int>(); for (int i = 0; i <= inputData.Count - NLength; i++) { List <double> subseq = inputData.GetRange(i, NLength); id_item++; Rectangle new_rec = new Rectangle(MathFuncs.PAA_Lower(subseq, D, R).ToArray(), MathFuncs.PAA_Upper(subseq, D, R).ToArray(), i); rtree.Add(new_rec, id_item); recList.Add(new_rec); id_itemList.Add(id_item); } Dictionary <int, Node <int> > nodeMap = rtree.getNodeMap(); List <Node <int> > leafNodes = nodeMap.Values.Where(node => node.level == 1).OrderBy(node => node.entryCount).ToList(); List <Rectangle> leafMBRs = leafNodes.Select(node => node.mbr).ToList(); // List rectangle of leaf nodes in order of list leafNodes for (int i = 0; i < leafNodes.Count; i++) { List <Rectangle> leafEntries = leafNodes[i].entries.Where(mbr => mbr != null).Select(mbr => mbr).ToList(); if (leafEntries.Count > 0) { int beginIndex = candidateList.Count; candidateList.AddRange(leafEntries.Select(mbr => mbr.getIndexSubSeq())); beginIndexInner.AddRange(Enumerable.Repeat(beginIndex, leafEntries.Count)); indexOfLeafMBRS.AddRange(Enumerable.Repeat(i, leafEntries.Count)); } } for (int i = 0; i < candidateList.Count; i++)//outer loop { int p = candidateList[i]; // rectangle of subseq in p postion if (is_skipped_at_p[p]) { //p was visited at inner loop before continue; } else { List <double> subseq_p = inputData.GetRange(p, NLength); //Rectangle p_rectangle = recList[p]; List <double> P_PAA = MathFuncs.PAA(subseq_p, D); nearest_neighbor_dist = Constants.INFINITE; List <bool> eliminatedMBR = new List <bool>(); for (int k = 0; k < leafMBRs.Count; k++) { eliminatedMBR.Add(false); } int indexMBRLeaf = -1; int num_leaf_skips = 0; for (int j = 0; j < candidateList.Count; j++)// inner loop { // int q = innerList[j]; int index_inner = (beginIndexInner[i] + j) % candidateList.Count; int q = candidateList[index_inner]; int index_MBRInnner = (beginIndexInner[i] + j) % candidateList.Count; int MBRInnner = indexOfLeafMBRS[index_MBRInnner]; if (indexMBRLeaf < MBRInnner)//the first entry of the next node ? { indexMBRLeaf++; /* Test: * if (indexMBRInnner[j] == MBRInnner) * Console.WriteLine("OK");*/ //calc minDist: //double minDist = MathFuncss.MINDIST(p_rectangle, leafMBRs[MBRInnner], (NLength / (double)(D))); double minDist = MathFuncs.MINDIST(P_PAA, leafMBRs[MBRInnner], (NLength / (double)(D))); //if (minDist_keo > minDist) //{ // Console.WriteLine("STOPPP"); // return; //} if (minDist >= nearest_neighbor_dist) { num_leaf_skips++; eliminatedMBR[MBRInnner] = true; continue;// pruned => skip to the next one } else { if (Math.Abs(p - q) < NLength) { continue;// self-match => skip to the next one } //calculate the Distance between p and q dist = MathFuncs.EuDistance(subseq_p, inputData.GetRange(q, NLength)); if (dist < best_so_far_dist) { //skip the element q at oute_loop, 'cuz if (p,q) is not a solution, neither is (q,p). is_skipped_at_p[q] = true; break_to_outer_loop = true; //break, to the next loop at outer_loop break; // break at inner_loop first } if (dist < nearest_neighbor_dist) { nearest_neighbor_dist = dist; } } } else // still the same node { if (eliminatedMBR[MBRInnner]) // can prune ? { continue; } else //do it normally { if (Math.Abs(p - q) < NLength) { continue;// self-match => skip to the next one } else { //calculate the Distance between p and q dist = MathFuncs.EuDistance(subseq_p, inputData.GetRange(q, NLength)); if (dist < best_so_far_dist) { //skip the element q at oute_loop, 'cuz if (p,q) is not a solution, neither is (q,p). is_skipped_at_p[q] = true; break_to_outer_loop = true; //break, to the next loop at outer_loop break; // break at inner_loop first } if (dist < nearest_neighbor_dist) { nearest_neighbor_dist = dist; } } } } //end ELSE } //end for inner loop //Console.WriteLine("num_leaf_skips="+ num_leaf_skips); if (break_to_outer_loop) { break_to_outer_loop = false; //reset continue; //go to the next p in outer loop } if (nearest_neighbor_dist > best_so_far_dist) { best_so_far_dist = nearest_neighbor_dist; best_so_far_loc = p; } } }//end outer loop if (is_first_time) { this_id_item = id_item; this_id_itemList = id_itemList; this_RTree = rtree; this_rectList = recList; } return(new List <double> { best_so_far_dist, best_so_far_loc }); }