protected override void InternalCompute() { var cancelManager = this.Services.CancelManager; TVertex root; if (!this.TryGetRootVertex(out root)) { throw new InvalidOperationException("root vertex not set"); } if (this.pairs == null) { throw new InvalidOperationException("pairs not set"); } var gpair = GraphExtensions.ToAdjacencyGraph(this.pairs); var disjointSet = new ForestDisjointSet <TVertex>(); var vancestors = new Dictionary <TVertex, TVertex>(); var dfs = new DepthFirstSearchAlgorithm <TVertex, TEdge>(this, this.VisitedGraph, new Dictionary <TVertex, GraphColor>(this.VisitedGraph.VertexCount)); dfs.InitializeVertex += v => disjointSet.MakeSet(v); dfs.DiscoverVertex += v => vancestors[v] = v; dfs.TreeEdge += edge => { disjointSet.Union(edge.Source, edge.Target); vancestors[disjointSet.FindSet(edge.Source)] = edge.Source; }; dfs.FinishVertex += v => { foreach (var e in gpair.OutEdges(v)) { if (dfs.VertexColors[e.Target] == GraphColor.Black) { this.ancestors[EdgeExtensions.ToVertexPair <TVertex, SEquatableEdge <TVertex> >(e)] = vancestors[disjointSet.FindSet(e.Target)]; } } }; // go! dfs.Compute(root); }
protected override void InternalCompute() { var cancelManager = this.Services.CancelManager; // matrix i,j -> path this.data.Clear(); var vertices = this.VisitedGraph.Vertices; var edges = this.VisitedGraph.Edges; // prepare the matrix with initial costs // walk each edge and add entry in cost dictionary foreach (var edge in edges) { var ij = EdgeExtensions.ToVertexPair <TVertex, TEdge>(edge); var cost = this.weights(edge); VertexData value; if (!data.TryGetValue(ij, out value)) { data[ij] = new VertexData(cost, edge); } else if (cost < value.Distance) { data[ij] = new VertexData(cost, edge); } } if (cancelManager.IsCancelling) { return; } // walk each vertices and make sure cost self-cost 0 foreach (var v in vertices) { data[new SEquatableEdge <TVertex>(v, v)] = new VertexData(0, default(TEdge)); } if (cancelManager.IsCancelling) { return; } // iterate k, i, j foreach (var vk in vertices) { if (cancelManager.IsCancelling) { return; } foreach (var vi in vertices) { var ik = new SEquatableEdge <TVertex>(vi, vk); VertexData pathik; if (data.TryGetValue(ik, out pathik)) { foreach (var vj in vertices) { var kj = new SEquatableEdge <TVertex>(vk, vj); VertexData pathkj; if (data.TryGetValue(kj, out pathkj)) { double combined = this.distanceRelaxer.Combine(pathik.Distance, pathkj.Distance); var ij = new SEquatableEdge <TVertex>(vi, vj); VertexData pathij; if (data.TryGetValue(ij, out pathij)) { if (this.distanceRelaxer.Compare(combined, pathij.Distance) < 0) { data[ij] = new VertexData(combined, vk); } } else { data[ij] = new VertexData(combined, vk); } } } } } } // check negative cycles foreach (var vi in vertices) { var ii = new SEquatableEdge <TVertex>(vi, vi); VertexData value; if (data.TryGetValue(ii, out value) && value.Distance < 0) { throw new NegativeCycleGraphException(); } } }