Пример #1
0
        /// <summary>
        /// Runs the Special Distance Test to reduce the graph.
        /// </summary>
        /// <param name="graph">The graph on which to run the test.</param>
        /// <returns>The reduced graph.</returns>
        public static ReductionResult RunTest(Graph graph)
        {
            List<Edge> redundant = new List<Edge>();
            var result = new ReductionResult();

            var distanceGraph = graph.CreateDistanceGraph();
            var specialDistanceGraph = CreateInitialSpecialDistanceGraph(graph);
            for (int i = 0; i < graph.NumberOfVertices; i++)
            {
                Console.Write("SD Test: {0}/{1}   \r", i, graph.NumberOfVertices);
                // Step 1. L := { i }
                //         for all j set delta_j = d_ij
                // In each iteration, delta_j means the current special distance from the start vertex to j.
                var vFrom = graph.Vertices[i];
                List<Vertex> L = new List<Vertex>(new [] { vFrom }); // Initially only the start veretx is labeled.
                // Initially set special distance equal to distance
                foreach (var edge in specialDistanceGraph.GetEdgesForVertex(vFrom))
                {
                    edge.Cost =
                        distanceGraph.GetEdgesForVertex(vFrom).Single(x => x.Other(vFrom) == edge.Other(vFrom)).Cost;
                    //edge.Cost = Math.Min(edge.Cost,
                    //    distanceGraph.GetEdgesForVertex(vFrom).Single(x => x.Other(vFrom) == edge.Other(vFrom)).Cost);
                }

                List<Vertex> unhandledTerminals = null; // K \ L
                while ((unhandledTerminals = graph.Terminals.Where(x => !L.Contains(x)).ToList()).Count > 0)
                { // While K \ L is not empty
                    // Find the terminal which minimizes delta(j) for all j in K \ L
                    int currentMinimum = int.MaxValue;
                    Vertex k = null;
                    var edgesFrom = specialDistanceGraph.GetEdgesForVertex(vFrom);
                    foreach (var terminal in unhandledTerminals)
                    {
                        var deltaEdge = edgesFrom.First(x => x.Other(vFrom) == terminal);
                        if (deltaEdge.Cost < currentMinimum)
                        {
                            currentMinimum = deltaEdge.Cost;
                            k = terminal;
                        }
                    }

                    L.Add(k);

                    // Re-lable all vertices that haven't gotten a definitive label yet.
                    var delta_k = edgesFrom.First(x => x.Other(vFrom) == k).Cost;
                    foreach (var unlabeled in graph.Vertices.Where(x => !L.Contains(x)))
                    {
                        var d_kj = distanceGraph.GetEdgesForVertex(k).First(x => x.Other(k) == unlabeled).Cost;
                        var deltaEdge = edgesFrom.First(x => x.Other(vFrom) == unlabeled);
                        deltaEdge.Cost = Math.Min(deltaEdge.Cost, Math.Max(delta_k, d_kj));
                    }
                }

                var specialEdges = specialDistanceGraph.GetEdgesForVertex(vFrom);
                var distanceEdges = distanceGraph.GetEdgesForVertex(vFrom);
                var edges = graph.GetEdgesForVertex(vFrom);
                foreach (var redundantEdge in specialEdges.Where(x => x.Cost < distanceEdges.First(y => y.Other(vFrom) == x.Other(vFrom)).Cost))
                {
                    // Special distance is smaller than distance. Edge is redundant.
                    var edge = edges.FirstOrDefault(x => x.Other(vFrom) == redundantEdge.Other(vFrom));
                    if (edge != null)
                        redundant.Add(edge);
                }
            }

            foreach (var edge in redundant)
            {
                graph.RemoveEdge(edge);
                result.RemovedEdges.Add(edge);
            }

            Console.Write("                                  \r");

            return result;
        }