示例#1
0
            protected Result CheckIfProperPath(out string message)
            {
                if (path.Length == 0)
                {
                    message = "empty path returned";
                    return(Result.BadResult);
                }
                if (path[0].From != a)
                {
                    message = "wrong starting point";
                    return(Result.BadResult);
                }
                if (path[path.Length - 1].To != b)
                {
                    message = "wrong final point";
                    return(Result.BadResult);
                }

                double sum   = 0;
                Edge   last  = new Edge();
                bool   first = true;

                foreach (var e in path)
                {
                    if (e.From == b)
                    {
                        message = $"destination vertex appears inside the path";
                        return(Result.BadResult);
                    }
                    if (!g.OutEdges(e.From).Contains(e))
                    {
                        message = $"edge {e} does not exist";
                        return(Result.BadResult);
                    }
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        if (e.From != last.To)
                        {
                            message = $"edge {last} cannot be followed by {e}";
                            return(Result.BadResult);
                        }
                    }
                    sum += e.Weight;
                    last = e;
                }
                if (sum != result.Value)
                {
                    message = $"path does not match the length, expected {result}, is {sum}";
                    return(Result.BadResult);
                }
                message = "OK";
                return(Result.Success);
            }
        /// <summary>
        /// Algorytm znajdujący drugą pod względem długości najkrótszą ścieżkę między a i b.
        /// Możliwe, że jej długość jest równa najkrótszej (jeśli są dwie najkrótsze ścieżki,
        /// algorytm zwróci jedną z nich).
        /// Dopuszczamy, aby na ścieżce powtarzały się wierzchołki/krawędzie.
        /// Można założyć, że a!=b oraz że w grafie nie występują pętle.
        /// </summary>
        /// <remarks>
        /// Wymagana złożoność do O(D), gdzie D jest złożonością implementacji alogorytmu Dijkstry w bibliotece Graph.
        /// </remarks>
        /// <param name="g"></param>
        /// <param name="path">null jeśli druga ścieżka nie istnieje, wpp ściezka jako ciąg krawędzi</param>
        /// <returns>null jeśli druga ścieżka nie istnieje, wpp długość znalezionej ścieżki</returns>
        public static double?FindSecondShortestPath(this Graph g, int a, int b, out Edge[] path)
        {
            PathsInfo[] d, dC;
            g.DijkstraShortestPaths(a, out d);
            Graph gC;

            if (g.Directed)
            {
                gC = g.Clone().Reverse();
            }
            else
            {
                gC = g;
            }
            gC.DijkstraShortestPaths(b, out dC);
            Edge[] shortestPath = PathsInfo.ConstructPath(a, b, d);
            if (null == shortestPath)
            {
                path = null;
                return(null);
            }
            double minDist = double.MaxValue;
            int    c = -1, c2 = -1;
            Edge   tE        = new Edge();
            bool   foundSame = false;

            foreach (Edge e in shortestPath)
            {
                if (foundSame)
                {
                    break;
                }
                foreach (Edge e2 in g.OutEdges(e.From))
                {
                    if (e2.To == e.To)
                    {
                        continue;
                    }
                    double currMin = dC[e2.To].Dist + d[e.From].Dist + e2.Weight;
                    if (minDist > currMin)
                    {
                        tE      = e2;
                        c       = e.From;
                        c2      = e2.To;
                        minDist = currMin;
                    }
                    if (currMin == d[b].Dist)
                    {
                        break;
                    }
                }
            }

            if (c2 == -1)
            {
                path = null;
                return(null);
            }
            gC.DijkstraShortestPaths(c2, out dC);
            Edge[]      shortestPath1 = PathsInfo.ConstructPath(a, c, d);
            Edge[]      shortestPath3 = PathsInfo.ConstructPath(c2, b, dC);
            List <Edge> z             = new List <Edge>();

            if (g.Directed)
            {
                gC.DijkstraShortestPaths(b, out dC);
                shortestPath3 = PathsInfo.ConstructPath(b, c2, dC);
            }
            foreach (Edge e in shortestPath1)
            {
                z.Add(e);
            }
            z.Add(tE);
            if (shortestPath3 == null)
            {
                path = null;
                return(null);
            }
            List <Edge> z2 = new List <Edge>();

            foreach (Edge e in shortestPath3)
            {
                if (!g.Directed)
                {
                    z.Add(e);
                }
                z2.Add(e);
            }
            if (g.Directed)
            {
                z2.Reverse();
                foreach (Edge e in z2)
                {
                    z.Add(new Edge(e.To, e.From, e.Weight));
                }
            }
            path = z.ToArray(); // shortestPath1 + tE + shortestPath3
            return(minDist);
        }
示例#3
0
        /// <summary>
        /// Algorytm znajdujący drugą pod względem długości najkrótszą ścieżkę między a i b.
        /// Możliwe, że jej długość jest równa najkrótszej (jeśli są dwie najkrótsze ścieżki,
        /// algorytm zwróci jedną z nich).
        /// Dopuszczamy, aby na ścieżce powtarzały się wierzchołki/krawędzie.
        /// Można założyć, że a!=b oraz że w grafie nie występują pętle.
        /// </summary>
        /// <remarks>
        /// Wymagana złożoność do O(D), gdzie D jest złożonością implementacji alogorytmu Dijkstry w bibliotece Graph.
        /// </remarks>
        /// <param name="g"></param>
        /// <param name="path">null jeśli druga ścieżka nie istnieje, wpp ściezka jako ciąg krawędzi</param>
        /// <returns>null jeśli druga ścieżka nie istnieje, wpp długość znalezionej ścieżki</returns>
        public static double?FindSecondShortestPath(this Graph g, int a, int b, out Edge[] path)
        {
            path = null;
            double?min = Double.MaxValue;

            PathsInfo[] d;
            Graph       G;
            Edge        edge  = new Edge();
            int         index = 0;

            if (g.Directed)
            {
                G = g.Reverse();
            }
            else
            {
                G = g;
            }

            G.DijkstraShortestPaths(b, out d);
            if (d[a].Dist.IsNaN())
            {
                return(null);
            }

            Edge[] firstpath = PathsInfo.ConstructPath(b, a, d);

            for (int i = 0; i < firstpath.Length; i++)
            {
                int v = firstpath[i].To;
                foreach (Edge e in g.OutEdges(v))
                {
                    if (e.To != firstpath[i].From && d[e.To].Dist + e.Weight + d[a].Dist - d[v].Dist < min)
                    {
                        min   = d[e.To].Dist + e.Weight + d[a].Dist - d[v].Dist;
                        edge  = e;
                        index = i;
                    }
                }
            }

            if (min == Double.MaxValue)
            {
                return(null);
            }

            Edge[] tmp = PathsInfo.ConstructPath(b, edge.To, d);
            Array.Reverse(tmp);
            for (int i = 0; i < tmp.Length; i++)
            {
                tmp[i] = new Edge(tmp[i].To, tmp[i].From, tmp[i].Weight);
            }

            path = new Edge[firstpath.Length - index + tmp.Length];
            for (int i = 0; i < firstpath.Length - index - 1; i++)
            {
                path[i] = new Edge(firstpath[firstpath.Length - i - 1].To, firstpath[firstpath.Length - i - 1].From, firstpath[firstpath.Length - i - 1].Weight);
            }
            path[firstpath.Length - index - 1] = edge;
            Array.Copy(tmp, 0, path, firstpath.Length - index, tmp.Length);

            return(min);
        }
示例#4
0
        /// <summary>
        /// Algorytm znajdujący drugą pod względem długości najkrótszą ścieżkę między a i b.
        /// Możliwe, że jej długość jest równa najkrótszej (jeśli są dwie najkrótsze ścieżki,
        /// algorytm zwróci jedną z nich).
        /// Dopuszczamy, aby na ścieżce powtarzały się wierzchołki/krawędzie.
        /// Można założyć, że a!=b oraz że w grafie nie występują pętle.
        /// </summary>
        /// <remarks>
        /// Wymagana złożoność do O(D), gdzie D jest złożonością implementacji alogorytmu Dijkstry w bibliotece Graph.
        /// </remarks>
        /// <param name="g"></param>
        /// <param name="path">null jeśli druga ścieżka nie istnieje, wpp ściezka jako ciąg krawędzi</param>
        /// <returns>null jeśli druga ścieżka nie istnieje, wpp długość znalezionej ścieżki</returns>
        public static double?FindSecondShortestPath(this Graph g, int a, int b, out Edge[] path)
        {
            PathsInfo[] pi;
            PathsInfo[] pi2;
            Graph       G = g.Clone();

            G.DijkstraShortestPaths(a, out pi);

            if (double.IsNaN(pi[b].Dist))
            {
                path = null;
                return(null);
            }

            Edge[] firstPath = PathsInfo.ConstructPath(a, b, pi);

            List <Edge> finalPath = new List <Edge>();

            if (G.Directed)
            {
                G = G.Reverse();
            }

            G.DijkstraShortestPaths(b, out pi2);

            if (pi2 == null)
            {
                path = null;
                return(null);
            }

            int u = -1, v = -1;

            double secondShortest = double.PositiveInfinity;

            for (int i = firstPath.Length - 1; i >= 0; i--)
            {
                foreach (Edge ed in g.OutEdges(firstPath[i].From))
                {
                    if (ed.To != firstPath[i].To)
                    {
                        double current;

                        if (double.IsNaN(pi2[ed.To].Dist))
                        {
                            continue;
                        }

                        if ((current = (ed.Weight + pi[firstPath[i].From].Dist + pi2[ed.To].Dist)) < secondShortest)
                        {
                            secondShortest = current;
                            u = firstPath[i].From;
                            v = ed.To;
                        }
                    }
                }
            }

            if (u == -1)
            {
                path = null;
                return(null);
            }

            int ind = 0;

            while (firstPath[ind].From != u)
            {
                finalPath.Add(firstPath[ind++]);
            }

            Edge[] second = PathsInfo.ConstructPath(b, v, pi2);

            finalPath.Add(new Edge(u, v, g.GetEdgeWeight(u, v)));
            ind = v;
            Edge?last;

            while ((last = pi2[ind].Last) != null)
            {
                Edge e = pi2[ind].Last.Value;
                finalPath.Add(new Edge(e.To, e.From, e.Weight));
                ind = last.Value.From;
            }
            path = finalPath.ToArray();
            return(secondShortest);
        }
示例#5
0
        /// <summary>
        /// Algorytm znajdujący drugą pod względem długości najkrótszą ścieżkę między a i b.
        /// Możliwe, że jej długość jest równa najkrótszej (jeśli są dwie najkrótsze ścieżki,
        /// algorytm zwróci jedną z nich).
        /// Dopuszczamy, aby na ścieżce powtarzały się wierzchołki/krawędzie.
        /// Można założyć, że a!=b oraz że w grafie nie występują pętle.
        /// </summary>
        /// <remarks>
        /// Wymagana złożoność do O(D), gdzie D jest złożonością implementacji alogorytmu Dijkstry w bibliotece Graph.
        /// </remarks>
        /// <param name="g"></param>
        /// <param name="path">null jeśli druga ścieżka nie istnieje, wpp ściezka jako ciąg krawędzi</param>
        /// <returns>null jeśli druga ścieżka nie istnieje, wpp długość znalezionej ścieżki</returns>
        public static double?FindSecondShortestPath(this Graph g, int a, int b, out Edge[] path)
        {
            path = null;
            PathsInfo[] reversePathInfo;
            List <Edge> bestPath = new List <Edge>();

            if (g.Directed)
            {
                Graph gReversed = g.Reverse();
                if (!gReversed.DijkstraShortestPaths(b, out reversePathInfo))
                {
                    return(null);
                }
            }
            else
            if (!g.DijkstraShortestPaths(b, out reversePathInfo))
            {
                return(null);
            }
            int v = a;

            while (reversePathInfo[v].Last != null)
            {
                var last = (Edge)reversePathInfo[v].Last;
                bestPath.Add(new Edge(last.To, last.From, last.Weight));
                v = last.From;
            }
            double currentDistance = 0.0;
            double secondDistance  = double.PositiveInfinity;
            Edge   extended        = new Edge(-1, -1, double.PositiveInfinity);

            foreach (var currentEdge in bestPath)
            {
                foreach (var e in g.OutEdges(currentEdge.From))
                {
                    if (e == currentEdge)
                    {
                        continue;
                    }
                    if (currentDistance + e.Weight + reversePathInfo[e.To].Dist <= secondDistance)
                    {
                        extended       = e;
                        secondDistance = currentDistance + e.Weight + reversePathInfo[e.To].Dist;
                    }
                }
                currentDistance += currentEdge.Weight;
            }
            List <Edge> pathList = new List <Edge>();

            if (extended.Weight != double.PositiveInfinity)
            {
                foreach (var e in bestPath)
                {
                    if (e.From == extended.From)
                    {
                        break;
                    }
                    else
                    {
                        pathList.Add(e);
                    }
                }
                pathList.Add(extended);
                v = extended.To;
                while (reversePathInfo[v].Last != null)
                {
                    var last = (Edge)reversePathInfo[v].Last;
                    pathList.Add(new Edge(last.To, last.From, last.Weight));
                    v = last.From;
                }
                path = pathList.ToArray();
            }
            if (path == null)
            {
                return(null);
            }
            else
            {
                return(secondDistance);
            }
        }