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);
        }
예제 #2
0
        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();
                }
            }
        }