/// <summary> /// Finds negative cycle /// </summary> /// <param name="searchResult">Search result returned by <code>CalculateShortestPaths</code> method</param> /// <returns></returns> public static Path <TNode, TEdge, TVal> GetNegativeCycle <TVal>(SparseGraph <TNode, TEdge> graph, PathLogic <TEdge, TVal> pathLogic, PathSearchResult <TNode, TEdge, TVal> searchResult) { var lastNodeId = -1; foreach (var edge in graph.Edges) { if (pathLogic.E(searchResult.Distance[edge.From.Id], pathLogic.UnreachableValue)) { continue; } var newDist = pathLogic.Relax(searchResult.Distance[edge.From.Id], edge); if (pathLogic.Gt(searchResult.Distance[edge.To.Id], newDist)) { searchResult.Distance[edge.To.Id] = newDist; searchResult.Ancestors[edge.To.Id] = edge; lastNodeId = edge.To.Id; } } if (lastNodeId == -1) { return(null); } var visited = new bool[graph.NodesCnt]; for (; !visited[lastNodeId]; lastNodeId = searchResult.Ancestors[lastNodeId].From.Id) { visited[lastNodeId] = true; } var pathEdges = new List <TEdge> { searchResult.Ancestors[lastNodeId] }; for (var nodeId = searchResult.Ancestors[lastNodeId].From.Id; nodeId != lastNodeId; nodeId = searchResult.Ancestors[nodeId].From.Id) { pathEdges.Add(searchResult.Ancestors[nodeId]); } pathEdges.Reverse(); return(new Path <TNode, TEdge, TVal>(graph, pathLogic.ZeroValue, pathEdges)); }
private static bool ExecutePhase <TVal>(SparseGraph <TNode, TEdge> graph, PathLogic <TEdge, TVal> pathLogic, PathSearchResult <TNode, TEdge, TVal> res) { var anyAction = false; foreach (var edge in graph.Edges) { if (pathLogic.E(res.Distance[edge.From.Id], pathLogic.UnreachableValue)) { continue; } var newDist = pathLogic.Relax(res.Distance[edge.From.Id], edge); if (pathLogic.Gt(res.Distance[edge.To.Id], newDist) && !res.IsAncestor(edge.From.Id, edge.To.Id)) { res.Distance[edge.To.Id] = newDist; res.Ancestors[edge.To.Id] = edge; anyAction = true; } } return(anyAction); }