public static void process_node(note_node temp_node_, int current_cost_) { note_node temp_node2 = temp_node_; //Add to the stack temp_note_stk.Push(temp_node_); //Work through the child nodes for the passed parent foreach (note_node temp_child_ in DecisionTree.get_Children(temp_node_)) { //When at the last note in the list notes then push current stack out to an arrangemenet if (temp_child_.NoteDetails.position == MatchNotes.last_note_position) { //Push the current child to the stack to get the last note in the current tree thread temp_note_stk.Push(temp_child_); //Copy the current the stack snapshot to an arrangemenet List<note_node> temp2; //TO DO : Clean up the following as creation of temp array object not great but works for the mo note_node[] tempArray = new note_node[temp_note_stk.Count]; temp_note_stk.ToArray().CopyTo(tempArray, 0); temp2 = tempArray.ToList(); temp2.Reverse(); // Stack values will be the wrong way round so need to reverse //Generate the Arrangement Arrangement tempArrange = new Arrangement(temp2); tempArrange.number_of_notes = temp2.Count(); //Check if the arrangement has all the required notes //If yes then add the arrangment if (temp2.Count() == Arrangemenet_engine.original_note_count) { //Calculate the total costs of the arrangemenet foreach (note_node temp_node in temp2) { tempArrange.total_Cost += temp_node.cost; if (temp_node.cost < 0) tempArrange.total_neg += temp_node.cost; if (temp_node.cost > 0) tempArrange.total_pos += temp_node.cost; }; Arrangemenets.add_arrangemenet(tempArrange); }; temp_note_stk.Pop(); } else { // Call process node again for the next set of children process_node(temp_child_, current_cost_); // Pop the last child off the stack temp_note_stk.Pop(); } }; }
public static int compare_Cost(note_node temp_node) { try { return temp_node.cost - DicBestNodes[temp_node.NoteDetails.position].cost; } catch { return 0; } }
public static void add_Node(note_node temp_node) { //Check if the note exists else not add if (DicBestNodes.ContainsKey(temp_node.NoteDetails.position)) { //Find the position in the dictioary and check the paramter note against the current note if (DicBestNodes[temp_node.NoteDetails.position].cost > temp_node.cost) { DicBestNodes[temp_node.NoteDetails.position] = temp_node; } } else { DicBestNodes.Add(temp_node.NoteDetails.position, temp_node); } }
public static int get_note_cost2(note_node temp_node, note_node parent_node_) { //New version of the cost engine to support "Best Arrangements" option note_node temp_note = new note_node(); temp_note = temp_node; temp_note.cost = 0; // Check if the note is an open string and if (temp_note.NoteDetails.fret == 0) { temp_note.cost = -2; } // Check if it's a route node if (temp_node.parent_node_index == null) { // Currently perform no checks } else { //TODO the whole section below needs a bit of a re-write to allow for a gradual costing based on the parent, // parent's parent, parents parents parent etc..... // Check the last note is the same string as last note if (temp_node.NoteDetails.banjoString == parent_node_.NoteDetails.banjoString && temp_node.NoteDetails.notenumber != parent_node_.NoteDetails.notenumber && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost += 12; } // Check distance between last note and current note if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.NoteDetails.fret) > 4 && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost += 10; } try { // Check distance between current note and 2 notes ago if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.parent_node.NoteDetails.fret) > 4 && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost += 8; } } catch { }; try { //// Check distance between current note and 3 notes ago if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.parent_node.parent_node.NoteDetails.fret) > 4 && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost += 6; } } catch { }; try { //// Check distance between current note and 3 notes ago if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.parent_node.parent_node.parent_node.NoteDetails.fret) > 4 && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost += 4; } } catch { }; try { //// Check distance between current note and 3 notes ago if (System.Math.Abs(temp_node.NoteDetails.fret - parent_node_.parent_node.parent_node.parent_node.parent_node.NoteDetails.fret) > 4 && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost += 2; } } catch { }; } return temp_note.cost; }
private static note_node get_note_cost(note_node temp_node, List<note_node> DTArray) { note_node temp_note = new note_node(); temp_note = temp_node; int index = DTArray.IndexOf(temp_node); // Check if the note is an open string and if (temp_note.NoteDetails.fret == 0) { temp_note.cost = -2; } // Check if it's a route node if (temp_node.parent_node_index == null) { // Currently perform no checks } else { // Check the last note is the same string as last note if (temp_node.NoteDetails.banjoString == DTArray[index - 1].NoteDetails.banjoString && temp_node.NoteDetails.notenumber != DTArray[index - 1].NoteDetails.notenumber && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost = 12; } // Check distance between last note and current note if (System.Math.Abs(temp_node.NoteDetails.fret - DTArray[index - 1].NoteDetails.fret) > 4 && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost = 9; } try { // Check distance between current note and 2 notes ago if (System.Math.Abs(temp_node.NoteDetails.fret - DTArray[index - 2].NoteDetails.fret) > 4 && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost = 6; } } catch { }; try { //// Check distance between current note and 3 notes ago if (System.Math.Abs(temp_node.NoteDetails.fret - DTArray[index - 3].NoteDetails.fret) > 4 && (temp_node.NoteDetails.fret != 0 || temp_node.NoteDetails.fret != 0)) { temp_note.cost = 3; } } catch { }; } return temp_note; }
//Accept the parent index as a parameter to allow for recursave calls public static void Process_Note_Range(int last_note_index, int? last_DT_index, note_node parent_node_, MatchNote currentMatchNote, int cost_limit, int max_end_notes, CancellationToken cts) { Logging.Update_note_position(parent_node_.NoteDetails.position); //Logging.Update_Status("Processing Notes for parent:" + parent_node_.ToString()); /* Start the loop at the current index position and work forwards through the note results untill the next note position is found */ //try //{ //Get ordered list List<MatchNote> MatchLoop = MatchNotes.getNextMatchNotes(currentMatchNote); if (MatchLoop == null) { //No more notes left so finish return; } //First pass of maatching note, calculate cost and add to the BestNodes foreach (MatchNote tempMatchNote in MatchLoop) { int i = 0; // Current note note is 'next' in the position then add the current note to the DT note_node new_node = new note_node(last_DT_index, last_note_index, i, tempMatchNote, parent_node_); new_node.cost = CostCalculator.get_note_cost2(new_node, parent_node_); BestNodes.add_Node(new_node);// Need to add the note node to the best nodes incase the position is currently empty int costcomp = BestNodes.compare_Cost(new_node); if (i <= cost_limit) { DecisionTree.add_node(new_node); } } //Get a list of the new DT Nodes order by lowest cost first List<note_node> Note_Nodes_list = DecisionTree.get_Children(parent_node_) .OrderBy(p => p.cost) .ToList(); // Next loop though the newly created DT Nodes with the parent foreach (note_node temp_node in Note_Nodes_list) { int i; //Check the cost comparison is less than or = to the current best node //if yes then add to the DT & cotinue to process the notes children i = BestNodes.compare_Cost(temp_node); if (i <= cost_limit) { //If not the last note in if (temp_node.NoteDetails.last_note == false) { if (cts.IsCancellationRequested || currentEndCount_ == max_end_notes) { return; } // DANGER !!!! This is a stab in the dark approach to sort the bigger problem regards // total processing time if (temp_node.NoteDetails.position == MatchNotes.get_last_note_position()) { currentEndCount_ += 1; Logging.Update_Status("End note found :" + currentEndCount_.ToString()); return; } Process_Note_Range(i, temp_node.tree_index, temp_node, temp_node.NoteDetails, cost_limit, max_end_notes, cts); } } else temp_node.Excluded = true; } }
public static List<note_node> Process_Route_Notes(List<MatchNote> matchingresults, int cost_limit, int max_end_notes, CancellationToken cts) { BestNodes.Clear(); //First sort the list by fret & include only the root notes list into List<MatchNote> Root_Notes = matchingresults .Where(f => f.position == MatchNotes.get_first_note_position()) .OrderBy(f => f.fret) .ToList(); // get the int matchindex = 0; //Loop thought root notes foreach (MatchNote matchresult in Root_Notes) { Logging.Update_Status("Starting matching process for :" + matchresult.ToString()); // Read the route note and check its not the 2nd note in the file // If it is then exit the loop as the processing is finished if (matchingresults[0].position != matchingresults[matchindex].position) { //If the route note is position is different than last route note (I.e. not the first note position then stop) break; } //Add the note as a route node to the DT note_node new_node = new note_node(0, 0, matchresult, null); BestNodes.add_Node(new_node); // Need to add the note node to the best nodes incase the position is currently empty DecisionTree.add_node(new_node); //Run the note through the BestNodes process // Note is still the same so process from this point if (new_node.NoteDetails.last_note == false) { //If the note is not the last note then continue to process i's children //await Task.Run(() => currentEndCount_ = 0; Process_Note_Range(matchindex, new_node.tree_index, new_node, matchingresults[matchindex], cost_limit, max_end_notes, cts); } matchindex++; // Track the index of the current matched note in the list of notes } return DecisionTree.get_all_nodes(); // } // catch (Exception ex) // { // throw new System.ArgumentException("Error processing route notes"+ex.ToString()); // } }
//Accept the parent index as a parameter to allow for recursave calls public static void Process_Note_Range(int last_note_index, int? last_DT_index, note_node parent_node_, MatchNote currentMatchNote, int cost_limit, CancellationToken cts) { Logging.Update_note_position(parent_node_.NoteDetails.position); //Logging.Update_Status("Processing Notes for parent:" + parent_node_.ToString()); /* Start the loop at the current index position and work forwards through the note results untill the next note position is found */ //try //{ if (parent_node_.NoteDetails.last_note == true) { //Logging.Update_Status("End note found!"); return; } List<MatchNote> MatchLoop = MatchNotes.getNextMatchNotes(currentMatchNote); if (MatchLoop == null) { //No more notes left return; } foreach (MatchNote tempMatchNote in MatchLoop) { int i = 0; // Current note note is 'next' in the position then add the current note to the DT //TODO Extract Add note from Decision tree to allow cost evaluation before tree has // an added value note_node new_node = new note_node(last_DT_index, last_note_index, i, tempMatchNote, parent_node_); new_node.cost = CostCalculator.get_note_cost2(new_node, parent_node_); i = BestNodes.compare_Cost(new_node); BestNodes.add_Node(new_node);// Need to add the note node to the best nodes incase the position is currently empty //Check the cost comparison is less than or = to the current best node //if yes then add to the DT & cotinue to process the notes children if (i <= cost_limit) { DecisionTree.add_node(new_node); //If not the last note in if (tempMatchNote.last_note == false) { if (cts.IsCancellationRequested) { return; } // If not the last note position then perform recursive call to generate the next tree node //await Task.Run(() => Process_Note_Range(i, new_node.tree_index, new_node, tempMatchNote, cost_limit, cts), cts); Process_Note_Range(i, new_node.tree_index, new_node, tempMatchNote, cost_limit, cts); // Finished processing of the note to break from the loop } } } // } // catch (Exception Ex) // { // throw new System.ArgumentException("Some notes cannot be match with this tranposition, Error : " +Ex.ToString()); // } }