/// <summary>
        /// <para><paramref name="from"/> からの最短経路長をベルマン・フォード法で求める。負の長さにも使える</para>
        /// <para>計算量: O(|V|・|E|)</para>
        /// </summary>
        public static T[] BellmanFord <T, TOp, TNode, TEdge>(this IWGraph <T, TOp, TNode, TEdge> graph, int from)
            where T : struct
            where TOp : struct, INumOperator <T>
            where TNode : IGraphNode <TEdge>
            where TEdge : IWGraphEdge <T>
        {
            TOp op       = default;
            var graphArr = graph.AsArray();
            var INF      = op.Divide(op.MaxValue, op.Increment(op.MultiplyIdentity));
            var res      = new T[graphArr.Length];

            Array.Fill(res, INF);
            res[from] = default;

            for (int i = 1; i <= graphArr.Length; i++)
            {
                foreach (var node in graphArr)
                {
                    foreach (var e in node.Children)
                    {
                        var to = e.To;
                        var x  = op.Add(res[node.Index], e.Value);
                        if (op.GreaterThan(res[to], x))
                        {
                            res[to] = x;
                            if (i == graphArr.Length)
                            {
                                throw new InvalidOperationException("負の閉路");
                            }
                        }
                    }
                }
            }
            return(res);
        }
Beispiel #2
0
        /// <summary>
        /// <para><paramref name="from"/> からの最短経路長を01-BSFで求める。</para>
        /// <para>計算量: O(|E| + |V|)</para>
        /// </summary>
        public static T[] ShortestPath01BFS <T, TOp, TNode, TEdge>(this IWGraph <T, TOp, TNode, TEdge> graph, int from)
            where T : struct
            where TOp : struct, INumOperator <T>
            where TNode : IGraphNode <TEdge>
            where TEdge : IWGraphEdge <T>
        {
            TOp op       = default;
            var graphArr = graph.AsArray();
            var INF      = op.MaxValue;
            var res      = new T[graphArr.Length];

            System.Array.Fill(res, INF);
            res[from] = default;

            var used    = new bool[graphArr.Length];
            int count   = 0;
            var remains = new Deque <int>(graphArr.Length)
            {
                from
            };

            while (remains.Count > 0)
            {
                var ix = remains.PopFirst();
                if (used[ix])
                {
                    continue;
                }
                used[ix] = true;
                if (++count >= graphArr.Length)
                {
                    break;
                }
                var len = res[ix];
                foreach (var e in graphArr[ix].Children)
                {
                    var to         = e.To;
                    var nextLength = len;
                    if (EqualityComparer <T> .Default.Equals(e.Value, default))
                    {
                        if (op.GreaterThan(res[to], nextLength))
                        {
                            res[to] = nextLength;
                            remains.AddFirst(to);
                        }
                    }
                    else
                    {
                        nextLength = op.Increment(nextLength);
                        if (op.GreaterThan(res[to], nextLength))
                        {
                            res[to] = nextLength;
                            remains.AddLast(to);
                        }
                    }
                }
            }
            return(res);
        }
Beispiel #3
0
    private static Dictionary <NodeType, NodeType> DijekstraBuilder <NodeType>(IWGraph <NodeType> graph, NodeType source)
    {
        Dictionary <NodeType, int>      graphCurrW = new Dictionary <NodeType, int>();
        Dictionary <NodeType, NodeType> Fathers    = new Dictionary <NodeType, NodeType>();
        Dictionary <NodeType, bool>     visted     = new Dictionary <NodeType, bool>();

        List <NodeType> Mins = new List <NodeType>();

        Mins.Add(source);
        graphCurrW.Add(source, 0);
        while (Mins.Count != 0)
        {
            NodeType currNode = Mins[0];
            if (!visted.ContainsKey(currNode))
            {
                visted.Add(currNode, true);
                Mins.RemoveAt(0);
                foreach (var neighbor in graph.Neighbors(currNode))
                {
                    if (graphCurrW.ContainsKey(neighbor))
                    {
                        // Debug.Log("27");
                        if (graphCurrW[neighbor] > graphCurrW[currNode] + graph.Weight(neighbor))
                        {
                            //   Debug.Log("30");
                            graphCurrW[neighbor] = graphCurrW[currNode] + graph.Weight(neighbor);
                            // Debug.Log("32");
                            Fathers[neighbor] = currNode;
                            if (!visted.ContainsKey(neighbor))
                            {
                                //  Debug.Log("36");
                                Mins.Insert(getPosInArray(Mins, graphCurrW[neighbor], graph), neighbor);
                            }
                        }
                    }
                    else
                    {
                        //  Debug.Log("44");
                        graphCurrW[neighbor] = graphCurrW[currNode] + graph.Weight(neighbor);
                        // Debug.Log("46");
                        Fathers[neighbor] = currNode;
                        if (!visted.ContainsKey(neighbor))
                        {
                            //   Debug.Log("50");
                            Mins.Insert(getPosInArray(Mins, graphCurrW[neighbor], graph), neighbor);
                        }
                    }
                }
            }
            else
            {
                Mins.RemoveAt(0);
            }
        }
        return(Fathers);
    }
        /// <summary>
        /// <para><paramref name="from"/> からの最短経路長をダイクストラ法で求める。</para>
        /// <para>計算量: O( (|E| + |V|) log |V| )</para>
        /// </summary>
        public static T[] Dijkstra <T, TOp, TNode, TEdge>(this IWGraph <T, TOp, TNode, TEdge> graph, int from)
            where T : struct
            where TOp : struct, INumOperator <T>
            where TNode : IGraphNode <TEdge>
            where TEdge : IWGraphEdge <T>
        {
            TOp op       = default;
            var graphArr = graph.AsArray();
            var INF      = op.MaxValue;
            var res      = new T[graphArr.Length];

            System.Array.Fill(res, INF);
            res[from] = default;

            var used    = new bool[graphArr.Length];
            int count   = 0;
            var remains = new PriorityQueueDijkstra <T, TOp>(graphArr.Length);

            remains.Enqueue(default, from);
Beispiel #5
0
    public static List <NodeType> GetPath <NodeType>(IWGraph <NodeType> graph, NodeType source, NodeType dest)
    {
        List <NodeType> path = new List <NodeType>();
        Dictionary <NodeType, NodeType> route = DijekstraBuilder(graph, source);

        //Checking the destination node exists in the possible paths
        if (route.ContainsKey(dest))
        {
            NodeType tempD = dest;
            path.Insert(0, tempD);
            //creating the list for the path
            while (!path[0].Equals(source))
            {
                tempD = route[tempD];
                path.Insert(0, tempD);
            }
        }
        return(path);
    }
Beispiel #6
0
    public static List <NodeType> GetPath <NodeType>(IWGraph <NodeType> graph, NodeType source, NodeType dest)
    {
        List <NodeType> path = new List <NodeType>();
        Dictionary <NodeType, NodeType> route = DijekstraBuilder(graph, source);

        if (route.ContainsKey(dest))
        {
            NodeType tempD = dest;
            path.Insert(0, tempD); //

            while (!path[0].Equals(source))
            {
                //Debug.Log("END?");
                tempD = route[tempD];
                path.Insert(0, tempD);
            }
            // Debug.Log("return");
        }
        return(path);
    }
Beispiel #7
0
        /// <summary>
        /// <para>各頂点間の最短経路長をワーシャルフロイド法で求める</para>
        /// <para>計算量: O(|V|^3)</para>
        /// </summary>
        public static T[][] WarshallFloyd <T, TOp, TNode, TEdge>(this IWGraph <T, TOp, TNode, TEdge> graph)
            where T : struct
            where TOp : struct, INumOperator <T>
            where TNode : IGraphNode <TEdge>
            where TEdge : IWGraphEdge <T>
        {
            TOp op       = default;
            var graphArr = graph.AsArray();
            var INF      = op.Divide(op.MaxValue, op.Increment(op.MultiplyIdentity));
            var res      = new T[graphArr.Length][];

            for (var i = 0; i < graphArr.Length; i++)
            {
                res[i] = new T[graphArr.Length];
                System.Array.Fill(res[i], INF);
                res[i][i] = default;
                foreach (var e in graphArr[i].Children)
                {
                    res[i][e.To] = e.Value;
                }
            }
            for (var k = 0; k < graphArr.Length; k++)
            {
                for (var i = 0; i < graphArr.Length; i++)
                {
                    for (var j = 0; j < graphArr.Length; j++)
                    {
                        var x = op.Add(res[i][k], res[k][j]);
                        if (op.GreaterThan(res[i][j], x))
                        {
                            res[i][j] = x;
                        }
                    }
                }
            }
            return(res);
        }
Beispiel #8
0
    private static int getPosInArray <NodeType>(List <NodeType> Mins, int destNodeW, IWGraph <NodeType> graph)
    {
        int minIndex = 0;
        int maxIndex = Mins.Count - 1;
        int middle   = minIndex + (maxIndex - minIndex) / 2;

        while (minIndex <= maxIndex)
        {
            if (graph.Weight(Mins[middle]) == destNodeW)
            {
                return(middle);
            }
            if (destNodeW > graph.Weight(Mins[middle]))
            {
                minIndex = middle + 1;
            }
            if (destNodeW < graph.Weight(Mins[middle]))
            {
                maxIndex = middle - 1;
            }
            middle = minIndex + (maxIndex - minIndex) / 2;
        }
        return(middle);
    }
Beispiel #9
0
    //A Dijkstra building algorithm, returns a Dictionary of paths
    private static Dictionary <NodeType, NodeType> DijekstraBuilder <NodeType>(IWGraph <NodeType> graph, NodeType source)
    {
        //Current weights for each visited node
        Dictionary <NodeType, int> graphCurrW = new Dictionary <NodeType, int>();
        //"Fathers" of each nodes, needed to find the path back
        Dictionary <NodeType, NodeType> Fathers = new Dictionary <NodeType, NodeType>();
        //Marking nodes that are done
        Dictionary <NodeType, bool> visted = new Dictionary <NodeType, bool>();
        //List of Nodes needed to visit. A sorted list from minimum weight to maximum weight.
        List <NodeType> Mins = new List <NodeType>();

        // Adding the source node
        Mins.Add(source);
        // Setting first node weight to 0
        graphCurrW.Add(source, 0);
        // Running while we have any node to work on
        while (Mins.Count != 0)
        {
            //Taking the minimum weighted node from the list
            NodeType currNode = Mins[0];
            //Making sure that this node is not yet worked on
            if (!visted.ContainsKey(currNode))
            {
                //Adding this node to visited nodes, which means we don't need to work on it anymore
                visted.Add(currNode, true);
                //Removing it from the list of nodes
                Mins.RemoveAt(0);
                foreach (var neighbor in graph.Neighbors(currNode))
                {
                    //Checking if we have "worked" on the node previously
                    if (graphCurrW.ContainsKey(neighbor))
                    {
                        //Checking if the current weight is higher then new weight
                        if (graphCurrW[neighbor] > graphCurrW[currNode] + graph.Weight(neighbor))
                        {
                            //Set new weight
                            graphCurrW[neighbor] = graphCurrW[currNode] + graph.Weight(neighbor);
                            //Set the new father of the node
                            Fathers[neighbor] = currNode;
                            //if the neighbor is not yet worked on then add it the nodes that need to be worked on
                            if (!visted.ContainsKey(neighbor))
                            {
                                //add the node in a position to keep the list sorted
                                Mins.Insert(getPosInArray(Mins, graphCurrW[neighbor], graph), neighbor);
                            }
                        }
                    }
                    else
                    {
                        //if its a new node completely set weights and father
                        graphCurrW[neighbor] = graphCurrW[currNode] + graph.Weight(neighbor);
                        Fathers[neighbor]    = currNode;
                        if (!visted.ContainsKey(neighbor))
                        {
                            Mins.Insert(getPosInArray(Mins, graphCurrW[neighbor], graph), neighbor);
                        }
                    }
                }
            }
            else
            {
                //remove nodes that we don't need to work on
                Mins.RemoveAt(0);
            }
        }
        return(Fathers);
    }