/// <summary> /// Check a neighbour of the current node to see if it needs to be added to the tentative list /// or the shortest route to it needs to be updated. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void checkNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { float newDistance = dist + link.Weight; try { //If the new route from root to neighbour is shorter than the old route or there was no old route //set the current node as the first step towards the root from neighbour if (_cont && !_tentative.Contains(neighbour)) { _tentative.AddFirst(neighbour); neighbour.SetDistanceFromRoot(ID, newDistance, current, link); } else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, current, link); } } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) { VisualisedNode = null; } Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } //Incase another thread has modified the distance if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link); } }
/// <summary> /// The main loop which is the body of the algorithm. /// Loops through every neighbour of the current node checking to see if they: /// A. Have been visited before /// B. Have been visited before but are now a shorter route /// </summary> /// <param name="current">The node currently being checked.</param> /// <param name="prev">The previous node that was checked.</param> /// <returns>The last node to be checked.</returns> private void MainLoop(DijkstraNode current, DijkstraNode prev) { while (_cont && current != null && !hitTarget(current)) { //If necessary display text and wait if (_cont && _text && _visualise) { current.Say("4. Iterating through neighbours excluding neighbours in Confirmed"); Pause(); } //Get the current distance to the target float dist = current.GetDistanceFromRoot(ID); foreach (var n in current.Neighbours) { IMLink link = current.Links[n.ID]; if (_visualise) { _links.AddFirst(link); } var neighbour = this.GetAlgNode <DijkstraNode>(n.ID); if (_cont && !_confirmed.Contains(neighbour)) { if (_visualise && _text) { VisualiseCheckNeighbourText(neighbour, current, dist, link); } else if (_visualise) { VisualiseCheckNeighbour(neighbour, current, dist, link); } checkNeighbour(neighbour, current, dist, link); } if (!_cont) { break; } } //Store the old previous node prev = current; if (_cont && _text && _visualise) { Say("Finished iterating through current's (" + current.Name + "'s) neighbours, getting next current from tentative list"); Pause(); } //Get the next node to be checked (the one which has the shortest path to it) current = getNext(current); } FinishedReset(current, prev); }
/// <summary> /// Visualise the process of choosing the next node. Will output text about what is going on if necessary. /// </summary> /// <param name="next">The next node to be current.</param> /// <param name="prev">The node that was previously current.</param> private void VisualiseChooseNext(DijkstraNode next, DijkstraNode prev) { if (_cont && !next.Equals(this)) { if (_cont && _text) { Say("8. There are nodes in the tentative list. Finding the node in tentative with the smallest cost"); Pause(); } Pause(3f); if (_cont && _text) { Say("9. new current = " + next.Name + " with cost " + next.GetDistanceFromRoot(ID)); Pause(); Say("10. Adding link between ct (" + prev.Name + ") and new current (" + next.Name + ") to the shortest path"); Pause(); } } prev.Reset(); IMLink confirmedLink = next.GetWIPRoute(ID); if (_cont && confirmedLink != null) { Pause(6f); confirmedLink.Colour = Color.Red; } if (_cont && _text) { Say((next.Equals(this) ? "2a" : "11a") + ". Adding " + (next.Equals(this) ? "root" : "new current") + " (" + next.Name + ") to Confirmed"); Pause(); Say((next.Equals(this) ? "2b" : "11b") + ". Setting current to " + (next.Equals(this) ? "root" : "new current") + " (" + next.Name + ")"); } next.Reset(); next.Selected = currentGlow; next.Colour = Color.White; if (_cont && _text && !next.Equals(this)) { Pause(); Say("11c. Going to step 4"); Pause(); } }
/// <summary> /// Visualises the process of checking a neighbour node and prints out text explaining what is happening. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void VisualiseCheckNeighbourText(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { if (!_visualise && !_text) return; float newDistance = dist + link.Weight; if (_cont) { //if (_cont && _text) // current.Say("Examining neighbour " + neighbour.Name); Pause(4f); link.Colour = Color.Blue; if (_cont && _text) { Pause(); current.Say("5. Test cost to " + neighbour.Name + " = " + dist + " + " + link.Weight + " = " + newDistance); Pause(); } Pause(4f); } try { if (_cont && !_tentative.Contains(neighbour)) { if (_cont && _text) current.Say(neighbour.Name + " is not in tentative list"); _tentative.AddFirst(neighbour); neighbour.SetDistanceFromRoot(ID, newDistance, current, link); if (_cont) { Pause(4f); neighbour.Selected = tentativeGlow; if (_cont && _text) { current.Say("6a. Adding " + neighbour.Name + " to the tentative list"); Pause(); current.Say("6b. " + neighbour.Name + ".cost = test cost (" + newDistance + ")"); } } } //If the new route from root to neighbour is shorter than the old route or there was no old route //set the current node as the first step towards the root from neighbour else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, current, link); if (_cont && _text) { current.Say(neighbour.Name + ".cost (" + neighbour.GetDistanceFromRoot(ID) + ") > test cost (" + newDistance + ")"); Pause(); current.Say("7. " + neighbour.Name + ".cost = test cost (" + newDistance + ")"); Pause(); } } } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) VisualisedNode = null; Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID)) neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link); if (_cont) { Pause(4f); link.Colour = Color.White; Pause(6f); } }
/// <summary> /// The main loop which is the body of the algorithm. /// Loops through every neighbour of the current node checking to see if they: /// A. Have been visited before /// B. Have been visited before but are now a shorter route /// </summary> /// <param name="current">The node currently being checked.</param> /// <param name="prev">The previous node that was checked.</param> /// <returns>The last node to be checked.</returns> private void MainLoop(DijkstraNode current, DijkstraNode prev) { while (_cont && current != null && !hitTarget(current)) { //If necessary display text and wait if (_cont && _text && _visualise) { current.Say("4. Iterating through neighbours excluding neighbours in Confirmed"); Pause(); } //Get the current distance to the target float dist = current.GetDistanceFromRoot(ID); foreach (var n in current.Neighbours) { IMLink link = current.Links[n.ID]; if (_visualise) _links.AddFirst(link); var neighbour = this.GetAlgNode<DijkstraNode>(n.ID); if (_cont && !_confirmed.Contains(neighbour)) { if (_visualise && _text) VisualiseCheckNeighbourText(neighbour, current, dist, link); else if (_visualise) VisualiseCheckNeighbour(neighbour, current, dist, link); checkNeighbour(neighbour, current, dist, link); } if (!_cont) break; } //Store the old previous node prev = current; if (_cont && _text && _visualise) { Say("Finished iterating through current's (" + current.Name + "'s) neighbours, getting next current from tentative list"); Pause(); } //Get the next node to be checked (the one which has the shortest path to it) current = getNext(current); } FinishedReset(current, prev); }
/// <summary> /// Check a neighbour of the current node to see if it needs to be added to the tentative list /// or the shortest route to it needs to be updated. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void checkNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { float newDistance = dist + link.Weight; try { //If the new route from root to neighbour is shorter than the old route or there was no old route //set the current node as the first step towards the root from neighbour if (_cont && !_tentative.Contains(neighbour)) { _tentative.AddFirst(neighbour); neighbour.SetDistanceFromRoot(ID, newDistance, current, link); } else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) neighbour.SetDistanceFromRoot(ID, newDistance, current, link); } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) VisualisedNode = null; Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } //Incase another thread has modified the distance if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID)) neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link); }
/// <summary> /// Visualises the process of checking a neighbour node and prints out text explaining what is happening. /// </summary> /// <param name="neighbour">The neighbour to check.</param> /// <param name="current">The current node.</param> /// <param name="dist">The distance from the root to the current node.</param> /// <param name="link">The link between current and neighbour.</param> private void VisualiseCheckNeighbourText(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link) { if (!_visualise && !_text) { return; } float newDistance = dist + link.Weight; if (_cont) { //if (_cont && _text) // current.Say("Examining neighbour " + neighbour.Name); Pause(4f); link.Colour = Color.Blue; if (_cont && _text) { Pause(); current.Say("5. Test cost to " + neighbour.Name + " = " + dist + " + " + link.Weight + " = " + newDistance); Pause(); } Pause(4f); } try { if (_cont && !_tentative.Contains(neighbour)) { if (_cont && _text) { current.Say(neighbour.Name + " is not in tentative list"); } _tentative.AddFirst(neighbour); neighbour.SetDistanceFromRoot(ID, newDistance, current, link); if (_cont) { Pause(4f); neighbour.Selected = tentativeGlow; if (_cont && _text) { current.Say("6a. Adding " + neighbour.Name + " to the tentative list"); Pause(); current.Say("6b. " + neighbour.Name + ".cost = test cost (" + newDistance + ")"); } } } //If the new route from root to neighbour is shorter than the old route or there was no old route //set the current node as the first step towards the root from neighbour else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, current, link); if (_cont && _text) { current.Say(neighbour.Name + ".cost (" + neighbour.GetDistanceFromRoot(ID) + ") > test cost (" + newDistance + ")"); Pause(); current.Say("7. " + neighbour.Name + ".cost = test cost (" + newDistance + ")"); Pause(); } } } catch (KeyNotFoundException e) { //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop _cont = false; if (_visualise) { VisualisedNode = null; } Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " + current.Name + " (root = " + Name + ")"); } if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID)) { neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link); } if (_cont) { Pause(4f); link.Colour = Color.White; Pause(6f); } }