コード例 #1
0
        private readonly DirectedEdge[] _edgeTo;   // edgeTo[v] = last edge on shortest s->v path


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

            // visit vertices in toplogical order
            var topological = new Topological(g);

            if (!topological.HasOrder())
            {
                throw new ArgumentException("Digraph is not acyclic.");
            }
            foreach (int v in topological.Order())
            {
                foreach (var e in g.Adj(v))
                {
                    Relax(e);
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// certify that digraph is either acyclic or has a directed cycle
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool Check(EdgeWeightedDigraph g)
        {
            // edge-weighted digraph is cyclic
            if (HasCycle())
            {
                // verify cycle
                DirectedEdge first = null, last = null;
                foreach (var e in Cycle())
                {
                    if (first == null) first = e;
                    if (last != null)
                    {
                        if (last.To() != e.From())
                        {
                            Console.Error.WriteLine($"cycle edges {last} and {e} not incident{Environment.NewLine}");
                            return false;
                        }
                    }
                    last = e;
                }

                if (last != null && last.To() != first.From())
                {
                    Console.Error.WriteLine($"cycle edges {last} and {first} not incident{Environment.NewLine}");
                    return false;
                }
            }

            return true;
        }
コード例 #3
0
ファイル: DijkstraSP.cs プロジェクト: vladdnc/Algorithms-NET
        private readonly IndexMinPQ<Double> _pq; // priority queue of vertices

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Computes a shortest-paths tree from the source vertex <tt>s</tt> to every other
        /// vertex in the edge-weighted digraph <tt>G</tt>.
        /// </summary>
        /// <param name="g">g the edge-weighted digraph</param>
        /// <param name="s">s the source vertex</param>
        /// <exception cref="ArgumentException">if an edge weight is negative</exception>
        /// <exception cref="ArgumentException">unless 0 &lt;= <tt>s</tt> &lt;= <tt>V</tt> - 1</exception>
        public DijkstraSP(EdgeWeightedDigraph g, int s)
        {
            foreach (var 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 (var 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())
            {
                var v = _pq.DelMin();
                foreach (var e in g.Adj(v))
                    Relax(e);
            }

            // check optimality conditions
            //assert check(G, s);
        }
コード例 #4
0
 /// <summary>
 /// Computes a shortest paths tree from each vertex to to every other vertex in
 /// the edge-weighted digraph <tt>G</tt>.
 /// </summary>
 /// <param name="g">G the edge-weighted digraph</param>
 /// <exception cref="ArgumentException">if an edge weight is negative</exception>
 /// <exception cref="ArgumentException">unless 0 &lt;= <tt>s</tt> &lt;= <tt>V</tt> - 1</exception>
 public DijkstraAllPairsSP(EdgeWeightedDigraph g)
 {
     _all = new DijkstraSP[g.V];
     for (var v = 0; v < g.V; v++)
     {
         _all[v] = new DijkstraSP(g, v);
     }
 }
コード例 #5
0
ファイル: Topological.cs プロジェクト: vladdnc/Algorithms-NET
 /// <summary>
 /// Determines whether the edge-weighted digraph <tt>G</tt> has a topological
 /// order and, if so, finds such an order.
 /// </summary>
 /// <param name="g">g the edge-weighted digraph</param>
 public Topological(EdgeWeightedDigraph g)
 {
     var finder = new EdgeWeightedDirectedCycle(g);
     if (!finder.HasCycle())
     {
         var dfs = new DepthFirstOrder(g);
         _order = dfs.ReversePost();
     }
 }
コード例 #6
0
        /// <summary>
        /// Determines whether the edge-weighted digraph <tt>G</tt> has a topological
        /// order and, if so, finds such an order.
        /// </summary>
        /// <param name="g">g the edge-weighted digraph</param>
        public Topological(EdgeWeightedDigraph g)
        {
            var finder = new EdgeWeightedDirectedCycle(g);

            if (!finder.HasCycle())
            {
                var dfs = new DepthFirstOrder(g);
                _order = dfs.ReversePost();
            }
        }
コード例 #7
0
 /// <summary>
 /// Determines a depth-first order for the edge-weighted digraph <tt>G</tt>.
 /// </summary>
 /// <param name="g">g the edge-weighted digraph</param>
 public DepthFirstOrder(EdgeWeightedDigraph g)
 {
     _pre = new int[g.V];
     _post = new int[g.V];
     _postorder = new Collections.Queue<Integer>();
     _preorder = new Collections.Queue<Integer>();
     _marked = new bool[g.V];
     for (var v = 0; v < g.V; v++)
         if (!_marked[v]) Dfs(g, v);
 }
コード例 #8
0
        private Collections.Stack<DirectedEdge> _cycle; // directed cycle (or null if no such cycle)

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Determines whether the edge-weighted digraph <tt>G</tt> has a directed cycle and,
        /// if so, finds such a cycle.
        /// </summary>
        /// <param name="g">g the edge-weighted digraph</param>
        public EdgeWeightedDirectedCycle(EdgeWeightedDigraph g)
        {
            _marked = new bool[g.V];
            _onStack = new bool[g.V];
            _edgeTo = new DirectedEdge[g.V];
            for (var v = 0; v < g.V; v++)
                if (!_marked[v]) Dfs(g, v);

            // check that digraph has a cycle
            //assert check(G);
        }
コード例 #9
0
        public void Run()
        {
            // create random DAG with V vertices and E edges; then add F random edges
            const int vv = 50;
            const int e = 100;
            const int f = 20;
            var digraph = new EdgeWeightedDigraph(vv);
            var vertices = new int[vv];
            for (var i = 0; i < vv; i++)
                vertices[i] = i;
            StdRandom.Shuffle(vertices);
            for (var i = 0; i < e; i++)
            {
                int v, w;
                do
                {
                    v = StdRandom.Uniform(vv);
                    w = StdRandom.Uniform(vv);
                } while (v >= w);
                var weight = StdRandom.Uniform();
                digraph.AddEdge(new DirectedEdge(v, w, weight));
            }

            // add F extra edges
            for (var i = 0; i < f; i++)
            {
                var v = StdRandom.Uniform(vv);
                var w = StdRandom.Uniform(vv);
                var weight = StdRandom.Uniform(0.0, 1.0);
                digraph.AddEdge(new DirectedEdge(v, w, weight));
            }

            Console.WriteLine(digraph);

            // find a directed cycle
            var finder = new EdgeWeightedDirectedCycle(digraph);
            if (finder.HasCycle())
            {
                Console.Write("Cycle: ");
                foreach (var edge in finder.Cycle())
                {
                    Console.Write(edge + " ");
                }
                Console.WriteLine();
            }

            // or give topologial sort
            else
            {
                Console.WriteLine("No directed cycle");
            }

            Console.ReadLine();
        }
コード例 #10
0
ファイル: DijkstraSP.cs プロジェクト: vladdnc/Algorithms-NET
        /// <summary>
        /// check optimality conditions:
        /// (i) for all edges e:            distTo[e.to()] &lt;= distTo[e.from()] + e.weight()
        /// (ii) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight()
        /// </summary>
        /// <param name="g"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public bool Check(EdgeWeightedDigraph g, int s)
        {
            // check that edge weights are nonnegative
            if (g.Edges().Any(e => e.Weight < 0))
            {
                Console.Error.WriteLine("negative edge weight detected");
                return false;
            }

            // check that distTo[v] and edgeTo[v] are consistent
            if (Math.Abs(_distTo[s]) > 1E12 || _edgeTo[s] != null)
            {
                Console.Error.WriteLine("distTo[s] and edgeTo[s] inconsistent");
                return false;
            }
            for (var v = 0; v < g.V; v++)
            {
                if (v == s) continue;
                if (_edgeTo[v] == null && !double.IsPositiveInfinity(_distTo[v]))
                {
                    Console.Error.WriteLine("distTo[] and edgeTo[] inconsistent");
                    return false;
                }
            }

            // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()
            for (var v = 0; v < g.V; v++)
            {
                foreach (var 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 (var w = 0; w < g.V; w++)
            {
                if (_edgeTo[w] == null) continue;
                var e = _edgeTo[w];
                var v = e.From();
                if (w != e.To()) return false;
                if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) > 1E12)
                {
                    Console.Error.WriteLine($"edge {e} on shortest path not tight");
                    return false;
                }
            }
            return true;
        }
コード例 #11
0
 /// <summary>
 /// Determines a depth-first order for the edge-weighted digraph <tt>G</tt>.
 /// </summary>
 /// <param name="g">g the edge-weighted digraph</param>
 public DepthFirstOrder(EdgeWeightedDigraph g)
 {
     _pre       = new int[g.V];
     _post      = new int[g.V];
     _postorder = new Collections.Queue <Integer>();
     _preorder  = new Collections.Queue <Integer>();
     _marked    = new bool[g.V];
     for (var v = 0; v < g.V; v++)
     {
         if (!_marked[v])
         {
             Dfs(g, v);
         }
     }
 }
コード例 #12
0
        private Collections.Stack <DirectedEdge> _cycle; // directed cycle (or null if no such cycle)

        /// <summary>
        /// Determines whether the edge-weighted digraph <tt>G</tt> has a directed cycle and,
        /// if so, finds such a cycle.
        /// </summary>
        /// <param name="g">g the edge-weighted digraph</param>
        public EdgeWeightedDirectedCycle(EdgeWeightedDigraph g)
        {
            _marked  = new bool[g.V];
            _onStack = new bool[g.V];
            _edgeTo  = new DirectedEdge[g.V];
            for (var v = 0; v < g.V; v++)
            {
                if (!_marked[v])
                {
                    Dfs(g, v);
                }
            }

            // check that digraph has a cycle
            //assert check(G);
        }
コード例 #13
0
 /// <summary>
 /// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder
 /// </summary>
 /// <param name="g"></param>
 /// <param name="v"></param>
 private void Dfs(EdgeWeightedDigraph g, int v)
 {
     _marked[v] = true;
     _pre[v]    = _preCounter++;
     _preorder.Enqueue(v);
     foreach (var e in g.Adj(v))
     {
         var w = e.To();
         if (!_marked[w])
         {
             Dfs(g, w);
         }
     }
     _postorder.Enqueue(v);
     _post[v] = _postCounter++;
 }
コード例 #14
0
        // by finding a cycle in predecessor graph
        private void FindNegativeCycle()
        {
            var vv  = _edgeTo.Length;
            var spt = new EdgeWeightedDigraph(vv);

            for (var v = 0; v < vv; v++)
            {
                if (_edgeTo[v] != null)
                {
                    spt.AddEdge(_edgeTo[v]);
                }
            }

            var finder = new EdgeWeightedDirectedCycle(spt);

            _cycle = finder.Cycle();
        }
コード例 #15
0
ファイル: AcyclicLP.cs プロジェクト: vladdnc/Algorithms-NET
        private readonly DirectedEdge[] _edgeTo; // edgeTo[v] = last edge on longest s->v path

        #endregion Fields

        #region Constructors

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

            // relax vertices in toplogical order
            var topological = new Topological(g);
            if (!topological.HasOrder())
                throw new ArgumentException("Digraph is not acyclic.");
            foreach (int v in topological.Order())
            {
                foreach (var e in g.Adj(v))
                    Relax(e);
            }
        }
コード例 #16
0
        private IEnumerable<DirectedEdge> _cycle; // negative cycle (or null if no such cycle)

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Computes a shortest paths tree from <tt>s</tt> to every other vertex in
        /// the edge-weighted digraph <tt>G</tt>.
        /// </summary>
        /// <param name="g">g the acyclic digraph</param>
        /// <param name="s">s the source vertex</param>
        /// <exception cref="ArgumentException">unless 0 le; <tt>s</tt> le; <tt>V</tt> - 1</exception>
        public BellmanFordSP(EdgeWeightedDigraph g, int s)
        {
            _distTo = new double[g.V];
            _edgeTo = new DirectedEdge[g.V];
            _onQueue = new bool[g.V];
            for (var v = 0; v < g.V; v++)
                _distTo[v] = double.PositiveInfinity;
            _distTo[s] = 0.0;

            // Bellman-Ford algorithm
            _queue = new Collections.Queue<Integer>();
            _queue.Enqueue(s);
            _onQueue[s] = true;
            while (!_queue.IsEmpty() && !HasNegativeCycle())
            {
                int v = _queue.Dequeue();
                _onQueue[v] = false;
                Relax(g, v);
            }
        }
コード例 #17
0
 /// <summary>
 /// Returns a negative cycle, or <tt>null</tt> if there is no such cycle.
 /// </summary>
 /// <returns>a negative cycle as an iterable of edges, or <tt>null</tt> if there is no such cycle</returns>
 public IEnumerable <DirectedEdge> NegativeCycle()
 {
     for (var v = 0; v < _distTo.Length; v++)
     {
         // negative cycle in v's predecessor graph
         if (_distTo[v][v] < 0.0)
         {
             var spt = new EdgeWeightedDigraph(_edgeTo.Length);
             for (var w = 0; w < _edgeTo.Length; w++)
             {
                 if (_edgeTo[v][w] != null)
                 {
                     spt.AddEdge(_edgeTo[v][w]);
                 }
             }
             var finder = new EdgeWeightedDirectedCycle(spt);
             return(finder.Cycle());
         }
     }
     return(null);
 }
コード例 #18
0
 /// <summary>
 /// Initializes a new edge-weighted digraph that is a deep copy of <tt>G</tt>.
 /// </summary>
 /// <param name="g">g the edge-weighted digraph to copy</param>
 public EdgeWeightedDigraph(EdgeWeightedDigraph g) : this(g.V)
 {
     E = g.E;
     for (var v = 0; v < g.V; v++)
     {
         _indegree[v] = g.Indegree(v);
     }
     for (var v = 0; v < g.V; v++)
     {
         // reverse so that adjacency list is in same order as original
         var reverse = new Collections.Stack <DirectedEdge>();
         foreach (var e in g._adj[v])
         {
             reverse.Push(e);
         }
         foreach (var e in reverse)
         {
             _adj[v].Add(e);
         }
     }
 }
コード例 #19
0
        private IEnumerable <DirectedEdge> _cycle;           // negative cycle (or null if no such cycle)

        /// <summary>
        /// Computes a shortest paths tree from <tt>s</tt> to every other vertex in
        /// the edge-weighted digraph <tt>G</tt>.
        /// </summary>
        /// <param name="g">g the acyclic digraph</param>
        /// <param name="s">s the source vertex</param>
        /// <exception cref="ArgumentException">unless 0 le; <tt>s</tt> le; <tt>V</tt> - 1</exception>

        public BellmanFordSP(EdgeWeightedDigraph g, int s)
        {
            _distTo  = new double[g.V];
            _edgeTo  = new DirectedEdge[g.V];
            _onQueue = new bool[g.V];
            for (var v = 0; v < g.V; v++)
            {
                _distTo[v] = double.PositiveInfinity;
            }
            _distTo[s] = 0.0;

            // Bellman-Ford algorithm
            _queue = new Collections.Queue <Integer>();
            _queue.Enqueue(s);
            _onQueue[s] = true;
            while (!_queue.IsEmpty() && !HasNegativeCycle())
            {
                int v = _queue.Dequeue();
                _onQueue[v] = false;
                Relax(g, v);
            }
        }
コード例 #20
0
 // check optimality conditions
 private bool Check(EdgeWeightedDigraph g, int s)
 {
     // no negative cycle
     if (!HasNegativeCycle)
     {
         for (var v = 0; v < g.V; v++)
         {
             foreach (var e in g.Adj(v))
             {
                 var w = e.To();
                 for (var i = 0; i < g.V; i++)
                 {
                     if (_distTo[i][w] > _distTo[i][v] + e.Weight)
                     {
                         Console.WriteLine($"edge {e} is eligible");
                         return(false);
                     }
                 }
             }
         }
     }
     return(true);
 }
コード例 #21
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())
            {
                var weight = NegativeCycle().Sum(e => e.Weight);
                if (weight >= 0.0)
                {
                    Console.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 (Math.Abs(_distTo[s]) > 0.0001 || _edgeTo[s] != null)
                {
                    Console.WriteLine("distanceTo[s] and edgeTo[s] inconsistent");
                    return(false);
                }
                for (var v = 0; v < g.V; v++)
                {
                    if (v == s)
                    {
                        continue;
                    }
                    if (_edgeTo[v] != null || double.IsPositiveInfinity(_distTo[v]))
                    {
                        continue;
                    }
                    Console.WriteLine("distTo[] and edgeTo[] inconsistent");
                    return(false);
                }

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

                // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()
                for (var w = 0; w < g.V; w++)
                {
                    if (_edgeTo[w] == null)
                    {
                        continue;
                    }
                    var e = _edgeTo[w];
                    var v = e.From();
                    if (w != e.To())
                    {
                        return(false);
                    }
                    if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) < 0.0001)
                    {
                        continue;
                    }
                    Console.WriteLine($"edge {e} on shortest path not tight");
                    return(false);
                }
            }
            Console.WriteLine("Satisfies optimality conditions");
            Console.WriteLine();
            return(true);
        }
コード例 #22
0
        public void Run()
        {
            Console.WriteLine("Choose file:"); // Prompt
            Console.WriteLine("1 - tinyEWD.txt"); // Prompt
            Console.WriteLine("2 - mediumEWD.txt"); // Prompt
            //Console.WriteLine("3 - mediumEWG.txt"); // Prompt

            Console.WriteLine("or quit"); // Prompt

            var fileNumber = Console.ReadLine();
            string fileName;
            switch (fileNumber)
            {
                case "1":
                    fileName = "tinyEWD.txt";
                    break;
                case "2":
                    fileName = "mediumEWD.txt";
                    break;
                //case "3":
                //    fileName = "largeEWG.zip";
                //    break;
                case "quit":
                    return;
                default:
                    return;
            }

            var @in = new In($"Files\\Graphs\\{fileName}");
            var lines = @in.ReadAllLines();

            var lineIterator = 0;
            var v = 0;
            var e = 0;
            var edges = new List<DirectedEdge>();
            foreach (var line in lines)
            {
                if (lineIterator == 0)
                {
                    v = Convert.ToInt32(line);
                }
                if (lineIterator == 1)
                {
                    e = Convert.ToInt32(line);
                }
                if (lineIterator > 1)
                {
                    var lineSplitted = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
                    var ve = Convert.ToInt32(lineSplitted[0]);
                    var we = Convert.ToInt32(lineSplitted[1]);
                    var weight = Convert.ToDouble(lineSplitted[2], CultureInfo.InvariantCulture);
                    var edge = new DirectedEdge(ve, we, weight);
                    edges.Add(edge);
                }

                lineIterator++;
            }

            var edgeWeightedGraph = new EdgeWeightedDigraph(v, e, edges);
            Console.WriteLine(edgeWeightedGraph);
            Console.ReadLine();
        }
コード例 #23
0
        /// <summary>
        /// check optimality conditions:
        /// (i) for all edges e:            distTo[e.to()] &lt;= distTo[e.from()] + e.weight()
        /// (ii) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight()
        /// </summary>
        /// <param name="g"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public bool Check(EdgeWeightedDigraph g, int s)
        {
            // check that edge weights are nonnegative
            if (g.Edges().Any(e => e.Weight < 0))
            {
                Console.Error.WriteLine("negative edge weight detected");
                return(false);
            }

            // check that distTo[v] and edgeTo[v] are consistent
            if (Math.Abs(_distTo[s]) > 1E12 || _edgeTo[s] != null)
            {
                Console.Error.WriteLine("distTo[s] and edgeTo[s] inconsistent");
                return(false);
            }
            for (var v = 0; v < g.V; v++)
            {
                if (v == s)
                {
                    continue;
                }
                if (_edgeTo[v] == null && !double.IsPositiveInfinity(_distTo[v]))
                {
                    Console.Error.WriteLine("distTo[] and edgeTo[] inconsistent");
                    return(false);
                }
            }

            // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()
            for (var v = 0; v < g.V; v++)
            {
                foreach (var 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 (var w = 0; w < g.V; w++)
            {
                if (_edgeTo[w] == null)
                {
                    continue;
                }
                var e = _edgeTo[w];
                var v = e.From();
                if (w != e.To())
                {
                    return(false);
                }
                if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) > 1E12)
                {
                    Console.Error.WriteLine($"edge {e} on shortest path not tight");
                    return(false);
                }
            }
            return(true);
        }
コード例 #24
0
 /// <summary>
 /// Computes a shortest paths tree from each vertex to to every other vertex in
 /// the edge-weighted digraph <tt>G</tt>.
 /// </summary>
 /// <param name="g">G the edge-weighted digraph</param>
 /// <exception cref="ArgumentException">if an edge weight is negative</exception>
 /// <exception cref="ArgumentException">unless 0 &lt;= <tt>s</tt> &lt;= <tt>V</tt> - 1</exception>
 public DijkstraAllPairsSP(EdgeWeightedDigraph g)
 {
     _all = new DijkstraSP[g.V];
     for (var v = 0; v < g.V; v++)
         _all[v] = new DijkstraSP(g, v);
 }
コード例 #25
0
 // check optimality conditions
 private bool Check(EdgeWeightedDigraph g, int s)
 {
     // no negative cycle
     if (!HasNegativeCycle)
     {
         for (var v = 0; v < g.V; v++)
         {
             foreach (var e in g.Adj(v))
             {
                 var w = e.To();
                 for (var i = 0; i < g.V; i++)
                 {
                     if (_distTo[i][w] > _distTo[i][v] + e.Weight)
                     {
                         Console.WriteLine($"edge {e} is eligible");
                         return false;
                     }
                 }
             }
         }
     }
     return true;
 }
コード例 #26
0
 /// <summary>
 /// Returns a negative cycle, or <tt>null</tt> if there is no such cycle.
 /// </summary>
 /// <returns>a negative cycle as an iterable of edges, or <tt>null</tt> if there is no such cycle</returns>
 public IEnumerable<DirectedEdge> NegativeCycle()
 {
     for (var v = 0; v < _distTo.Length; v++)
     {
         // negative cycle in v's predecessor graph
         if (_distTo[v][v] < 0.0)
         {
             var spt = new EdgeWeightedDigraph(_edgeTo.Length);
             for (var w = 0; w < _edgeTo.Length; w++)
                 if (_edgeTo[v][w] != null)
                     spt.AddEdge(_edgeTo[v][w]);
             var finder = new EdgeWeightedDirectedCycle(spt);
             return finder.Cycle();
         }
     }
     return null;
 }
コード例 #27
0
        public void Run()
        {
            Console.WriteLine("Choose file:"); // Prompt
            Console.WriteLine("1 - rates.txt"); // Prompt
            //Console.WriteLine("2 - mediumEWD.txt"); // Prompt
            //Console.WriteLine("3 - mediumEWG.txt"); // Prompt

            Console.WriteLine("or quit"); // Prompt

            var fileNumber = Console.ReadLine();
            string fileName;
            switch (fileNumber)
            {
                case "1":
                    fileName = "rates.txt";
                    break;
                //case "2":
                //    fileName = "mediumEWD.txt";
                //    break;
                //case "3":
                //    fileName = "largeEWG.zip";
                //    break;
                case "quit":
                    return;
                default:
                    return;
            }

            var @in = new In($"Files\\Graphs\\{fileName}");
            var lines = @in.ReadAllLines();

            var lineIterator = 0;
            var currencyIterator = 0;
            // number of jobs
            var n = 0;

            // source and sink
            var source = 0;
            var sink = 0;

            var v = 0;
            var e = 0;
            var edges = new List<DirectedEdge>();
            string[] names = {};
            foreach (var line in lines)
            {
                if (lineIterator == 0)
                {
                    v = Convert.ToInt32(line);
                    names = new string[v];

                }

                if (lineIterator > 0)
                {
                    var wordsIterator = 0;
                    var ratesIterator = 0;
                    var lineSplitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var word in lineSplitted)
                    {
                        if (wordsIterator == 0)
                        {
                            names[wordsIterator] = word;
                        }

                        if (wordsIterator > 0)
                        {
                            double rate = Convert.ToSingle(word,CultureInfo.InvariantCulture);
                            var edge = new DirectedEdge(currencyIterator, ratesIterator, -Math.Log(rate));
                            edges.Add(edge);
                            e++;
                            ratesIterator++;
                        }
                        wordsIterator ++;
                    }

                    currencyIterator++;

                }

                lineIterator++;

            }

            var edgeWeightedDigraph = new EdgeWeightedDigraph(v, e, edges);
            Console.WriteLine(edgeWeightedDigraph);

            // find shortest path from s to each other vertex in DAG
            var arbitrage = new Arbitrage(edgeWeightedDigraph,source);
            var spt = arbitrage.GetShotestPath();
            // print results
            Console.WriteLine(" job   start  finish");
            Console.WriteLine("--------------------");
            if (spt.HasNegativeCycle())
            {
                var stake = 1000.0;
                foreach (var edge in spt.NegativeCycle())
                {
                    Console.Write($"{stake:0.00000} {names[edge.From()]} ");
                    stake *= Math.Exp(-edge.Weight);
                    Console.Write($"= {stake:0.00000} {names[edge.To()]}{Environment.NewLine}");
                }
            }
            else
            {
                Console.WriteLine("No arbitrage opportunity");
            }

            Console.ReadLine();
        }
コード例 #28
0
        public void Run()
        {
            Console.WriteLine("Choose file:"); // Prompt
            Console.WriteLine("1 - tinyEWDAG.txt"); // Prompt
            //Console.WriteLine("2 - mediumEWD.txt"); // Prompt
            //Console.WriteLine("3 - mediumEWG.txt"); // Prompt

            Console.WriteLine("or quit"); // Prompt

            var fileNumber = Console.ReadLine();
            string fileName;
            switch (fileNumber)
            {
                case "1":
                    fileName = "tinyEWDAG.txt";
                    break;
                //case "2":
                //    fileName = "mediumEWD.txt";
                //    break;
                //case "3":
                //    fileName = "largeEWG.zip";
                //    break;
                case "quit":
                    return;
                default:
                    return;
            }

            var @in = new In($"Files\\Graphs\\{fileName}");
            var lines = @in.ReadAllLines();

            var lineIterator = 0;
            var v = 0;
            var e = 0;
            var edges = new List<DirectedEdge>();
            foreach (var line in lines)
            {
                if (lineIterator == 0)
                {
                    v = Convert.ToInt32(line);
                }
                if (lineIterator == 1)
                {
                    e = Convert.ToInt32(line);
                }
                if (lineIterator > 1)
                {
                    var lineSplitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    var ve = Convert.ToInt32(lineSplitted[0]);
                    var we = Convert.ToInt32(lineSplitted[1]);
                    var weight = Convert.ToDouble(lineSplitted[2], CultureInfo.InvariantCulture);
                    var edge = new DirectedEdge(ve, we, weight);
                    edges.Add(edge);
                }

                lineIterator++;
            }

            var edgeWeightedDigraph = new EdgeWeightedDigraph(v, e, edges);
            Console.WriteLine(edgeWeightedDigraph);

            const int s = 5;

            // find shortest path from s to each other vertex in DAG
            var sp = new AcyclicSP(edgeWeightedDigraph, s);
            for (var vi = 0; vi < edgeWeightedDigraph.V; vi++)
            {
                if (sp.HasPathTo(vi))
                {
                    Console.Write($"{s} to {vi} {$"{sp.DistTo(vi):0.00}"}  ");
                    foreach (var ei in sp.PathTo(vi))
                    {
                        Console.Write($"{ei}   ");
                    }
                    Console.WriteLine();
                }
                else
                {
                    Console.Write($"{s} to {vi}         no path{Environment.NewLine}");
                }
            }
            Console.ReadLine();
        }
コード例 #29
0
        /// <summary>
        /// check that algorithm computes either the topological order or finds a directed cycle
        /// </summary>
        /// <param name="g"></param>
        /// <param name="v"></param>
        private void Dfs(EdgeWeightedDigraph g, int v)
        {
            _onStack[v] = true;
            _marked[v] = true;
            foreach (var e in g.Adj(v))
            {
                var w = e.To();

                // short circuit if directed cycle found
                if (_cycle != null) return;

                //found new vertex, so recur
                if (!_marked[w])
                {
                    _edgeTo[w] = e;
                    Dfs(g, w);
                }

                // trace back directed cycle
                else if (_onStack[w])
                {
                    TraceBackDirectedCycle(e, w);
                    return;
                }
            }

            _onStack[v] = false;
        }
コード例 #30
0
ファイル: CPMWorker.cs プロジェクト: vladdnc/Algorithms-NET
        public void Run()
        {
            Console.WriteLine("Choose file:"); // Prompt
            Console.WriteLine("1 - jobsPC.txt"); // Prompt
            //Console.WriteLine("2 - mediumEWD.txt"); // Prompt
            //Console.WriteLine("3 - mediumEWG.txt"); // Prompt

            Console.WriteLine("or quit"); // Prompt

            var fileNumber = Console.ReadLine();
            string fileName;
            switch (fileNumber)
            {
                case "1":
                    fileName = "jobsPC.txt";
                    break;
                //case "2":
                //    fileName = "mediumEWD.txt";
                //    break;
                //case "3":
                //    fileName = "largeEWG.zip";
                //    break;
                case "quit":
                    return;
                default:
                    return;
            }

            var @in = new In($"Files\\Graphs\\{fileName}");
            var lines = @in.ReadAllLines();

            var lineIterator = 0;
            var i = 0;
            // number of jobs
            var n = 0;

            // source and sink
            var source = 0;
            var sink = 0;

            var v = 0;
            var e = 0;
            var edges = new List<DirectedEdge>();
            foreach (var line in lines)
            {
                if (lineIterator == 0)
                {
                    n = Convert.ToInt32(line);
                    source = 2*n;
                    sink = 2*n + 1;
                    v = sink+1;
                }

                if (lineIterator > 0)
                {
                    var lineSplitted = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);

                    var duration = Convert.ToDouble(lineSplitted[0], CultureInfo.InvariantCulture);

                    edges.Add(new DirectedEdge(source, i, 0.0));
                    e++;
                    edges.Add(new DirectedEdge(i + n, sink, 0.0));
                    e++;
                    edges.Add(new DirectedEdge(i, i + n, duration));
                    e++;

                    // precedence constraints
                    var m = Convert.ToInt32(lineSplitted[1], CultureInfo.InvariantCulture);
                    for (var j = 0; j < m; j++)
                    {
                        var precedent = Convert.ToInt32(lineSplitted[1 + (j + 1)], CultureInfo.InvariantCulture);
                        edges.Add(new DirectedEdge(n + i, precedent, 0.0));
                        e++;
                    }

                    i++;
                }

                lineIterator++;

            }

            var edgeWeightedDigraph = new EdgeWeightedDigraph(v, e, edges);
            Console.WriteLine(edgeWeightedDigraph);

            // find shortest path from s to each other vertex in DAG
            var lp = new AcyclicLP(edgeWeightedDigraph, source);
            // print results
            Console.WriteLine(" job   start  finish");
            Console.WriteLine("--------------------");
            for (var k = 0; k < n; k++)
            {
                Console.Write($"{k} {lp.DistTo(k)} {lp.DistTo(k + n)}{Environment.NewLine}");
            }
            Console.Write($"Finish time: {lp.DistTo(sink)}{Environment.NewLine}");

            Console.ReadLine();
        }
コード例 #31
0
 /// <summary>
 /// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder
 /// </summary>
 /// <param name="g"></param>
 /// <param name="v"></param>
 private void Dfs(EdgeWeightedDigraph g, int v)
 {
     _marked[v] = true;
     _pre[v] = _preCounter++;
     _preorder.Enqueue(v);
     foreach (var e in g.Adj(v))
     {
         var w = e.To();
         if (!_marked[w])
         {
             Dfs(g, w);
         }
     }
     _postorder.Enqueue(v);
     _post[v] = _postCounter++;
 }
コード例 #32
0
        // by finding a cycle in predecessor graph
        private void FindNegativeCycle()
        {
            var vv = _edgeTo.Length;
            var spt = new EdgeWeightedDigraph(vv);
            for (var v = 0; v < vv; v++)
                if (_edgeTo[v] != null)
                    spt.AddEdge(_edgeTo[v]);

            var finder = new EdgeWeightedDirectedCycle(spt);
            _cycle = finder.Cycle();
        }
コード例 #33
0
 // relax vertex v and put other endpoints on queue if changed
 private void Relax(EdgeWeightedDigraph g, int v)
 {
     foreach (var e in g.Adj(v))
     {
         var 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
         }
     }
 }
コード例 #34
0
 /// <summary>
 /// Initializes a new edge-weighted digraph that is a deep copy of <tt>G</tt>.
 /// </summary>
 /// <param name="g">g the edge-weighted digraph to copy</param>
 public EdgeWeightedDigraph(EdgeWeightedDigraph g)
     : this(g.V)
 {
     E = g.E;
     for (var v = 0; v < g.V; v++)
         _indegree[v] = g.Indegree(v);
     for (var v = 0; v < g.V; v++)
     {
         // reverse so that adjacency list is in same order as original
         var reverse = new Collections.Stack<DirectedEdge>();
         foreach (var e in g._adj[v])
         {
             reverse.Push(e);
         }
         foreach (var e in reverse)
         {
             _adj[v].Add(e);
         }
     }
 }
コード例 #35
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())
            {
                var weight = NegativeCycle().Sum(e => e.Weight);
                if (weight >= 0.0)
                {
                    Console.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 (Math.Abs(_distTo[s]) > 0.0001 || _edgeTo[s] != null)
                {
                    Console.WriteLine("distanceTo[s] and edgeTo[s] inconsistent");
                    return false;
                }
                for (var v = 0; v < g.V; v++)
                {
                    if (v == s) continue;
                    if (_edgeTo[v] != null || double.IsPositiveInfinity(_distTo[v])) continue;
                    Console.WriteLine("distTo[] and edgeTo[] inconsistent");
                    return false;
                }

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

                // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()
                for (var w = 0; w < g.V; w++)
                {
                    if (_edgeTo[w] == null) continue;
                    var e = _edgeTo[w];
                    var v = e.From();
                    if (w != e.To()) return false;
                    if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) < 0.0001) continue;
                    Console.WriteLine($"edge {e} on shortest path not tight");
                    return false;
                }
            }
            Console.WriteLine("Satisfies optimality conditions");
            Console.WriteLine();
            return true;
        }