Ejemplo n.º 1
0
        private DirectedEdge[] edgeTo; // edgeTo[v] = last edge on longest s->v path

        /// <summary>
        /// Computes a longest paths tree from <c>s</c> to every other vertex in
        /// the directed acyclic graph <c>G</c>.</summary>
        /// <param name="G">the acyclic digraph</param>
        /// <param name="s">the source vertex</param>
        /// <exception cref="ArgumentException">if the digraph is not acyclic</exception>
        /// <exception cref="ArgumentException">unless 0 &lt;= <c>s</c> &lt;= <c>V</c> - 1</exception>
        ///
        public AcyclicLP(EdgeWeightedDigraph G, int s)
        {
            distTo = new double[G.V];
            edgeTo = new DirectedEdge[G.V];
            for (int v = 0; v < G.V; v++)
            {
                distTo[v] = double.NegativeInfinity;
            }
            distTo[s] = 0.0;

            // relax vertices in toplogical order
            Topological topological = new Topological(G);

            if (!topological.HasOrder)
            {
                throw new ArgumentException("Digraph is not acyclic.");
            }
            foreach (int v in topological.Order())
            {
                foreach (DirectedEdge e in G.Adj(v))
                {
                    relax(e);
                }
            }
        }
Ejemplo n.º 2
0
 // relax vertex v and put other endpoints on queue if changed
 private void relax(EdgeWeightedDigraph G, int v)
 {
     foreach (DirectedEdge e in G.Adj(v))
     {
         int w = e.To;
         if (distTo[w] > distTo[v] + e.Weight)
         {
             distTo[w] = distTo[v] + e.Weight;
             edgeTo[w] = e;
             if (!onQueue[w])
             {
                 queue.Enqueue(w);
                 onQueue[w] = true;
             }
         }
         if (cost++ % G.V == 0)
         {
             findNegativeCycle();
             if (HasNegativeCycle)
             {
                 return;          // found a negative cycle
             }
         }
     }
 }
Ejemplo n.º 3
0
        private IndexMinPQ <double> pq; // priority queue of vertices

        /// <summary>Computes a shortest-paths tree from the source vertex <c>s</c> to every other
        /// vertex in the edge-weighted digraph <c>G</c>.</summary>
        /// <param name="G">the edge-weighted digraph</param>
        /// <param name="s">the source vertex</param>
        /// <exception cref="ArgumentException">if an edge weight is negative</exception>
        /// <exception cref="ArgumentException">unless 0 &lt;= <c>s</c> &lt;=e <c>V</c> - 1</exception>
        ///
        public DijkstraSP(EdgeWeightedDigraph G, int s)
        {
            foreach (DirectedEdge e in G.Edges())
            {
                if (e.Weight < 0)
                {
                    throw new ArgumentException("edge " + e + " has negative weight");
                }
            }

            distTo = new double[G.V];
            edgeTo = new DirectedEdge[G.V];
            for (int v = 0; v < G.V; v++)
            {
                distTo[v] = double.PositiveInfinity;
            }
            distTo[s] = 0.0;

            // relax vertices in order of distance from s
            pq = new IndexMinPQ <double>(G.V);
            pq.Insert(s, distTo[s]);
            while (!pq.IsEmpty)
            {
                int v = pq.DelMin();
                foreach (DirectedEdge e in G.Adj(v))
                {
                    relax(e);
                }
            }

            // check optimality conditions
            Debug.Assert(check(G, s));
        }
Ejemplo n.º 4
0
        // certify that digraph is acyclic
        private bool check(EdgeWeightedDigraph G)
        {
            // digraph is acyclic
            if (HasOrder)
            {
                // check that ranks are a permutation of 0 to V-1
                bool[] found = new bool[G.V];
                for (int i = 0; i < G.V; i++)
                {
                    found[Rank(i)] = true;
                }
                for (int i = 0; i < G.V; i++)
                {
                    if (!found[i])
                    {
                        Console.Error.WriteLine("No vertex with rank " + i);
                        return(false);
                    }
                }

                // check that ranks provide a valid topological order
                for (int v = 0; v < G.V; v++)
                {
                    foreach (DirectedEdge e in G.Adj(v))
                    {
                        int w = e.To;
                        if (Rank(v) > Rank(w))
                        {
                            Console.Error.WriteLine("{0}-{1}: rank({2}) = {3}, rank({4}) = {5}\n",
                                                    v, w, v, Rank(v), w, Rank(w));
                            return(false);
                        }
                    }
                }

                // check that order() is consistent with rank()
                int r = 0;
                foreach (int v in Order())
                {
                    if (Rank(v) != r)
                    {
                        Console.Error.WriteLine("Order() and Rank() inconsistent");
                        return(false);
                    }
                    r++;
                }
            }
            return(true);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Determines whether the edge-weighted digraph <c>G</c> has a
        /// topological order and, if so, finds such a topological order.</summary>
        /// <param name="G">the digraph</param>
        ///
        public TopologicalX(EdgeWeightedDigraph G)
        {
            // indegrees of remaining vertices
            int[] indegree = new int[G.V];
            for (int v = 0; v < G.V; v++)
            {
                indegree[v] = G.Indegree(v);
            }

            // initialize
            rank  = new int[G.V];
            order = new LinkedQueue <int>();
            int count = 0;

            // initialize queue to contain all vertices with indegree = 0
            LinkedQueue <int> queue = new LinkedQueue <int>();

            for (int v = 0; v < G.V; v++)
            {
                if (indegree[v] == 0)
                {
                    queue.Enqueue(v);
                }
            }

            for (int j = 0; !queue.IsEmpty; j++)
            {
                int v = queue.Dequeue();
                order.Enqueue(v);
                rank[v] = count++;
                foreach (DirectedEdge e in G.Adj(v))
                {
                    int w = e.To;
                    indegree[w]--;
                    if (indegree[w] == 0)
                    {
                        queue.Enqueue(w);
                    }
                }
            }

            // there is a directed cycle in subgraph of vertices with indegree >= 1.
            if (count != G.V)
            {
                order = null;
            }

            Debug.Assert(check(G));
        }
Ejemplo n.º 6
0
 // run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder
 private void dfs(EdgeWeightedDigraph G, int v)
 {
     marked[v] = true;
     pre[v]    = preCounter++;
     preorder.Enqueue(v);
     foreach (DirectedEdge e in G.Adj(v))
     {
         int w = e.To;
         if (!marked[w])
         {
             dfs(G, w);
         }
     }
     postorder.Enqueue(v);
     post[v] = postCounter++;
 }
Ejemplo n.º 7
0
 // check optimality conditions
 private bool check(EdgeWeightedDigraph G, int s)
 {
     // no negative cycle
     if (!HasNegativeCycle)
     {
         for (int v = 0; v < G.V; v++)
         {
             foreach (DirectedEdge e in G.Adj(v))
             {
                 int w = e.To;
                 for (int i = 0; i < G.V; i++)
                 {
                     if (distTo[i, w] > distTo[i, v] + e.Weight)
                     {
                         Console.Error.WriteLine("edge " + e + " is eligible");
                         return(false);
                     }
                 }
             }
         }
     }
     return(true);
 }
Ejemplo n.º 8
0
        // check that algorithm computes either the topological order or finds a directed cycle
        private void dfs(EdgeWeightedDigraph G, int v)
        {
            onStack[v] = true;
            marked[v]  = true;
            foreach (DirectedEdge e in G.Adj(v))
            {
                int w = e.To;

                // short circuit if directed cycle found
                if (cycle != null)
                {
                    return;
                }
                else if (!marked[w])
                {
                    //found new vertex, so recur
                    edgeTo[w] = e;
                    dfs(G, w);
                }
                else if (onStack[w])
                {
                    // trace back directed cycle
                    cycle = new LinkedStack <DirectedEdge>();
                    DirectedEdge eTemp = e;
                    while (eTemp.From != w)
                    {
                        cycle.Push(eTemp);
                        eTemp = edgeTo[eTemp.From];
                    }
                    cycle.Push(eTemp);
                    return;
                }
            }

            onStack[v] = false;
        }
Ejemplo n.º 9
0
        // check optimality conditions: either
        // (i) there exists a negative cycle reacheable from s
        //     or
        // (ii)  for all edges e = v->w:            distTo[w] <= distTo[v] + e.Weight
        // (ii') for all edges e = v->w on the SPT: distTo[w] == distTo[v] + e.Weight
        private bool check(EdgeWeightedDigraph G, int s)
        {
            // has a negative cycle
            if (HasNegativeCycle)
            {
                double weight = 0.0;
                foreach (DirectedEdge e in GetNegativeCycle())
                {
                    weight += e.Weight;
                }
                if (weight >= 0.0)
                {
                    Console.Error.WriteLine("error: weight of negative cycle = " + weight);
                    return(false);
                }
            }

            // no negative cycle reachable from source
            else
            {
                // check that distTo[v] and edgeTo[v] are consistent
                if (distTo[s] != 0.0 || edgeTo[s] != null)
                {
                    Console.Error.WriteLine("distanceTo[s] and edgeTo[s] inconsistent");
                    return(false);
                }
                for (int v = 0; v < G.V; v++)
                {
                    if (v == s)
                    {
                        continue;
                    }
                    if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity)
                    {
                        Console.Error.WriteLine("distTo[] and edgeTo[] inconsistent");
                        return(false);
                    }
                }

                // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.Weight
                for (int v = 0; v < G.V; v++)
                {
                    foreach (DirectedEdge e in G.Adj(v))
                    {
                        int w = e.To;
                        if (distTo[v] + e.Weight < distTo[w])
                        {
                            Console.Error.WriteLine("edge " + e + " not relaxed");
                            return(false);
                        }
                    }
                }

                // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.Weight
                for (int w = 0; w < G.V; w++)
                {
                    if (edgeTo[w] == null)
                    {
                        continue;
                    }
                    DirectedEdge e = edgeTo[w];
                    int          v = e.From;
                    if (w != e.To)
                    {
                        return(false);
                    }
                    if (distTo[v] + e.Weight != distTo[w])
                    {
                        Console.Error.WriteLine("edge " + e + " on shortest path not tight");
                        return(false);
                    }
                }
            }

            //Console.WriteLine("Satisfies optimality conditions");
            return(true);
        }
Ejemplo n.º 10
0
        // check optimality conditions:
        // (i) for all edges e:            distTo[e.To] <= distTo[e.From] + e.Weight
        // (ii) for all edge e on the SPT: distTo[e.To] == distTo[e.From] + e.Weight
        private bool check(EdgeWeightedDigraph G, int s)
        {
            // check that edge weights are nonnegative
            foreach (DirectedEdge e in G.Edges())
            {
                if (e.Weight < 0)
                {
                    Console.Error.WriteLine("negative edge weight detected");
                    return(false);
                }
            }

            // check that distTo[v] and edgeTo[v] are consistent
            if (distTo[s] != 0.0 || edgeTo[s] != null)
            {
                Console.Error.WriteLine("distTo[s] and edgeTo[s] inconsistent");
                return(false);
            }
            for (int v = 0; v < G.V; v++)
            {
                if (v == s)
                {
                    continue;
                }
                if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity)
                {
                    Console.Error.WriteLine("distTo[] and edgeTo[] inconsistent");
                    return(false);
                }
            }

            // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()
            for (int v = 0; v < G.V; v++)
            {
                foreach (DirectedEdge e in G.Adj(v))
                {
                    int w = e.To;
                    if (distTo[v] + e.Weight < distTo[w])
                    {
                        Console.Error.WriteLine("edge " + e + " not relaxed");
                        return(false);
                    }
                }
            }

            // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()
            for (int w = 0; w < G.V; w++)
            {
                if (edgeTo[w] == null)
                {
                    continue;
                }
                DirectedEdge e = edgeTo[w];
                int          v = e.From;
                if (w != e.To)
                {
                    return(false);
                }
                if (distTo[v] + e.Weight != distTo[w])
                {
                    Console.Error.WriteLine("edge " + e + " on shortest path not tight");
                    return(false);
                }
            }
            return(true);
        }