public List <HexagonControl> Dijkstra(Graph graph) { var notVisited = graph.GetListNodes(); var track = new Dictionary <Node, DijkstraData>(); track[notVisited[0]] = new DijkstraData { Previous = null, Price = 0 }; while (true) { Node toOpen = null; float priceToOpen = float.PositiveInfinity; foreach (var v in notVisited) { if (track.ContainsKey(v) && track[v].Price < priceToOpen) { toOpen = v; priceToOpen = track[v].Price; } } if (toOpen == null) { //Debug.Log("Disconnected graph"); return(null); } if (toOpen == graph[graph.Length - 1]) { break; } List <Edge> edgesList = toOpen.IncidentEdge(); for (int i = 0; i < edgesList.Count; i++) { var currenPraise = track[toOpen].Price + edgesList[i].Price; var nextNode = edgesList[i].OtherNode(toOpen); if (!track.ContainsKey(nextNode) || track[nextNode].Price > currenPraise) { track[nextNode] = new DijkstraData { Price = currenPraise, Previous = toOpen }; } } notVisited.Remove(toOpen); } var result = new List <HexagonControl>(); Node end = graph[graph.Length - 1]; while (end != null) { result.Add(end.NodeHexagon); end = track[end].Previous; } result.Reverse(); //Debug.Log(result.Count); return(result); }
public static Graph LabelCorrecting(Graph g, int vert) { Output.WriteLine("[Label Correcting Output]"); //Not working, I think because of the two loops for in and out edges //Change this to assume g is an undirected graph //Keep a heap of vertices, based on their distance label //Each one is initially infinity, except the intial vertex, which is 0 Graph copy = new Graph(); Graph tree = new Graph(); //Create a copy to preserve g's state g.CopyTo(copy); List<Vertex> vertices = copy.GetVertices(); List<Edge> edges = copy.GetEdges(); DijkstraData v = new DijkstraData(); v.Predecessor = null; v.InQ = false; v.V = vertices[vert]; v.D = 0; v.InTree = false; v.EdgeLength = float.PositiveInfinity; vertices[vert].Tag = v; Heap<DijkstraData> q = new Heap<DijkstraData>(true); q.Add(vertices[vert].Tag as DijkstraData); (vertices[vert].Tag as DijkstraData).InQ = true; foreach (Vertex u in vertices) { if (!v.V.Equals(u)) { DijkstraData dd = new DijkstraData(); dd.D = float.PositiveInfinity; dd.V = u; dd.InTree = false; dd.InQ = false; u.Tag = dd; } } float maxEdgeWeight = float.NegativeInfinity; foreach (Edge e in edges) { if (Math.Abs(e.Weight) > maxEdgeWeight) { maxEdgeWeight = Math.Abs(e.Weight); } } int n = vertices.Count; float negativeCycleCheck = n * -maxEdgeWeight; while (q.HasNext()) { DijkstraData dd = q.Next(); dd.InQ = false; /*if (dd.Predecessor == null) { tree.AddVertex(dd.V); } else { tree.AddEdge(new Edge(dd.Predecessor, dd.V, dd.EdgeLength)); dd.InTree = true; }*/ foreach (Edge e in dd.V.GetOutEdges()) { Vertex connectedVertex = e.GetToVertex(); DijkstraData data = connectedVertex.Tag as DijkstraData; if (data.D > dd.D + e.Weight) { data.D = dd.D + e.Weight; if (data.D < negativeCycleCheck) { throw new Exception("Negative cycle detected!"); } data.Predecessor = dd.V; if (!q.Contains(data)) { q.Add(data); data.InQ = true; } } } if (g.Directed) { continue; } foreach (Edge e in dd.V.GetInEdges()) { Vertex connectedVertex = e.GetFromVertex(); DijkstraData data = connectedVertex.Tag as DijkstraData; if (data.D > dd.D + e.Weight) { data.D = dd.D + e.Weight; if (data.D < negativeCycleCheck) { throw new Exception("Negative cycle detected!"); } data.Predecessor = dd.V; if (!q.Contains(data)) { q.Add(data); data.InQ = true; } } } } Output.WriteLine("Distance from selected vertex to:"); foreach (Vertex vertex in vertices) { Output.WriteLine(vertex.ToString() + " = " + (vertex.Tag as DijkstraData).D); } Output.WriteLine("[End Label Correcting Output]"); return tree; }
/// <summary> /// Finds a shortest journey path when the start port not is equal to the end port (used dijkstra recursion algorithm). /// </summary> /// <param name="startPort">The start point of the route.</param> /// <param name="endPort">The end point of the route.</param> /// <param name="daysCount">The number of days that the journey lasts.</param> /// <returns>A collection of ports that is the shortest route of journey.</returns> private List <IPort> GetShortestJourneyByDijkstra(IPort startPort, IPort endPort, out int?daysCount) { // in the start all ports are not visited var notVisited = _shippingNetwork.Ports.ToList(); var track = new Dictionary <IPort, DijkstraData> { [startPort] = new DijkstraData { Price = 0, Previous = null } }; var routes = _shippingNetwork.Routes.ToList(); daysCount = null; while (true) { IPort toOpen = null; var bestPrice = int.MaxValue; // tries to get port with a minimal price foreach (var port in notVisited) { if (track.ContainsKey(port) && track[port].Price < bestPrice) { bestPrice = track[port].Price; toOpen = port; } } // the path not exists if (toOpen == null) { return(null); } // we found the path if (toOpen == endPort) { break; } // check all routes from the current port foreach (var route in routes.Where(r => r.PortFrom == toOpen)) { var currentPrice = track[toOpen].Price + route.TravelDays; var nextNode = route.PortTo; if (!track.ContainsKey(nextNode) || track[nextNode].Price > currentPrice) { track[nextNode] = new DijkstraData { Previous = toOpen, Price = currentPrice }; } } notVisited.Remove(toOpen); } daysCount = track[endPort].Price; // creates a collection of ports that is the shortest path var result = new List <IPort>(); while (endPort != null) { result.Add(endPort); endPort = track[endPort].Previous; } result.Reverse(); return(result); }
public static Graph Dijkstra(Graph g, int vert, bool directed) { Output.WriteLine("[Dijkstra Output]"); //If I get a negative edge weight, tell user to use label correcting instead of dijkstra's //Change this to assume g is an undirected graph //Keep a heap of vertices, based on their distance label //Each one is initially infinity, except the intial vertex, which is 0 Graph copy = new Graph(); Graph tree = new Graph(); //Create a copy to preserve g's state g.CopyTo(copy); List<Vertex> vertices = copy.GetVertices(); List<Edge> edges = copy.GetEdges(); DijkstraData v = new DijkstraData(); v.Predecessor = null; v.InQ = false; v.V = vertices[vert]; v.D = 0; v.InTree = false; v.EdgeLength = float.PositiveInfinity; vertices[vert].Tag = v; Heap<DijkstraData> q = new Heap<DijkstraData>(true); q.Add(vertices[vert].Tag as DijkstraData); (vertices[vert].Tag as DijkstraData).InQ = true; foreach (Vertex u in vertices) { if (!v.V.Equals(u)) { DijkstraData dd = new DijkstraData(); dd.D = float.PositiveInfinity; dd.V = u; dd.InTree = false; u.Tag = dd; q.Add(dd); dd.InQ = true; } } foreach (Edge e in edges) { if (e.Weight < 0) { Output.WriteLine("Negative edge weight detected. Use Label Correcting instead of Dijkstra"); return null; } } while (q.HasNext()) { DijkstraData dd = q.Next(); dd.InQ = false; /*if (dd.Predecessor == null) { tree.AddVertex(dd.V); dd.InTree = true; } else { tree.AddEdge(new Edge(dd.Predecessor, dd.V, dd.EdgeLength)); dd.InTree = true; }*/ foreach (Edge e in dd.V.GetOutEdges()) { Vertex connectedVertex = e.GetToVertex(); DijkstraData data = connectedVertex.Tag as DijkstraData; if (data.InQ) { if (dd.D + e.Weight < data.D) { if (dd.D + e.Weight < data.D) { data.D = dd.D + e.Weight; q.Update(data); } } } } //If this is a directed graph, don't consider in edges if (directed) { continue; } foreach (Edge e in dd.V.GetInEdges()) { Vertex connectedVertex = e.GetFromVertex(); DijkstraData data = connectedVertex.Tag as DijkstraData; if (data.InQ) { if (dd.D + e.Weight < data.D) { data.D = dd.D + e.Weight; q.Update(data); } } } } Output.WriteLine("Distance from selected vertex to:"); foreach (Vertex vertex in vertices) { Output.WriteLine(vertex.ToString() + " = " + (vertex.Tag as DijkstraData).D); } Output.WriteLine("[End Dijkstra Output]"); return tree; }