/// <summary> /// If possible, relax the given edge using the supplied base cost and edge-weight function. /// </summary> /// <param name="edge">The edge to relax.</param> /// <param name="cost">The base cost to reach the edge destination vertex.</param> /// <param name="ew">The edge weigher.</param> /// <param name="forbidNegatives">If true, negative values will forbid the link.</param> /// <returns>True if the edge was relaxed, otherwise false.</returns> public bool RelaxEdge(E edge, IWeight cost, IEdgeWeigher <V, E> ew, bool forbidNegatives = true) { V v = edge.Dst; IWeight hopCost = ew.GetWeight(edge); if ((!hopCost.IsViable) || (hopCost.IsNegative && forbidNegatives)) { return(false); } IWeight newCost = cost.Merge(hopCost); int compareResult = -1; if (HasCost(v)) { IWeight oldCost = GetCost(v); compareResult = newCost.CompareTo(oldCost); } if (compareResult <= 0) { UpdateVertex(v, edge, newCost, compareResult < 0); } return(compareResult < 0); }
public IWeight GetWeight(E edge) { if (subsetF[riskGrouping[edge]]) { return(weigher.GetWeight(edge)); } return(weigher.NonViableWeight); }
/// <summary> /// Sums the given edges using the given weigher. /// </summary> /// <param name="weigher">The weigher to use.</param> /// <param name="edges">The edges to sum.</param> /// <returns>The sum of path cost between the given edges.</returns> private IWeight CalculatePathCost(IEdgeWeigher <V, E> weigher, IEnumerable <E> edges) { IWeight totalCost = weigher.InitialWeight; foreach (E edge in edges) { totalCost = totalCost.Merge(weigher.GetWeight(edge)); } return(totalCost); }
/// <summary> /// Scans the specified graph, using recursion, and produces SCC results. /// </summary> /// <param name="graph">The graph to search.</param> /// <param name="vertex">The current vertex to scan and connect.</param> /// <param name="weigher">The optional weigher to use.</param> /// <param name="result">The graph search result.</param> /// <returns>Augmentation vertex data for the current vertex.</returns> private VertexData Connect(IGraph <V, E> graph, V vertex, IEdgeWeigher <V, E> weigher, SccResult result) { VertexData data = result.AddData(vertex); // Scan through all egress edges of the current vertex. foreach (E edge in graph.GetEdgesFrom(vertex)) { V nextVertex = edge.Dst; // If edge is not viable, skip it. if (weigher != null && !weigher.GetWeight(edge).IsViable) { continue; } // Attempt to get the augmentation vertex data for the next vertex. VertexData nextData = result.GetData(nextVertex); if (nextData is null) { // Next vertex has not been visited yet, so do this now. nextData = Connect(graph, nextVertex, weigher, result); data.LowLink = Math.Min(data.LowLink, nextData.LowLink); } else if (result.Visited(nextData)) { // Next vertex has been visited, which means // it is in the same cluster as the current vertex. data.LowLink = Math.Min(data.LowLink, nextData.Index); } } if (data.LowLink == data.Index) { result.AddCluster(data); } return(data); }