Beispiel #1
0
        /// <summary>
        /// Compute a minimum spanning tree (or forest) of an edge-weighted graph.
        /// </summary>
        /// <param name="g">g the edge-weighted graph</param>
        public KruskalMST(EdgeWeightedGraph g)
        {
            // more efficient to build heap by passing array of edges
            var pq = new MinPQ<EdgeW>();
            foreach (var e in g.Edges())
            {
                pq.Insert(e);
            }

            // run greedy algorithm
            var uf = new UF(g.V);
            while (!pq.IsEmpty() && _mst.Size() < g.V - 1)
            {
                var e = pq.DelMin();
                var v = e.Either();
                var w = e.Other(v);
                if (!uf.Connected(v, w))
                { // v-w does not create a cycle
                    uf.Union(v, w);  // merge v and w components
                    _mst.Enqueue(e);  // add edge e to mst
                    _weight += e.Weight;
                }
            }

            // check optimality conditions
            //assert check(G);
        }
        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 graph <tt>G</tt>.
        /// </summary>
        /// <param name="g">g the edge-weighted graph</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 DijkstraUndirectedSP(EdgeWeightedGraph 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 EdgeW[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, v);
            }

            // check optimality conditions
            //assert check(G, s);
        }
Beispiel #3
0
        private double _weight; // total weight of MST

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Compute a minimum spanning tree (or forest) of an edge-weighted graph.
        /// </summary>
        /// <param name="g">g the edge-weighted graph</param>
        public LazyPrimMST(EdgeWeightedGraph g)
        {
            _mst = new Collections.Queue<EdgeW>();
            _pq = new MinPQ<EdgeW>();
            _marked = new bool[g.V];
            for (var v = 0; v < g.V; v++)     // run Prim from all vertices to
                if (!_marked[v]) Prim(g, v);     // get a minimum spanning forest

            // check optimality conditions
            //assert check(G);
        }
        /// <summary>
        /// check optimality conditions:
        /// (i) for all edges e = v-w:            distTo[w] &lt;= distTo[v] + e.weight()
        /// (ii) for all edge e = v-w on the SPT: distTo[w] == distTo[v] + e.weight()
        /// </summary>
        /// <param name="g"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public bool Check(EdgeWeightedGraph 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))
                {
                    var w = e.Other(v);
                    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];
                if (w != e.Either() && w != e.Other(e.Either())) return false;
                int v = e.Other(w);
                if (Math.Abs(_distTo[v] + e.Weight - _distTo[w]) > 1E12)
                {
                    Console.Error.WriteLine($"edge {e} on shortest path not tight");
                    return false;
                }
            }
            return true;
        }
Beispiel #5
0
        /// <summary>
        /// Compute a minimum spanning tree (or forest) of an edge-weighted graph.
        /// </summary>
        /// <param name="g">g the edge-weighted graph</param>
        public PrimMST(EdgeWeightedGraph g)
        {
            _edgeTo = new EdgeW[g.V];
            _distTo = new double[g.V];
            _marked = new bool[g.V];
            _pq = new IndexMinPQ<Double>(g.V);
            for (var v = 0; v < g.V; v++)
                _distTo[v] = double.PositiveInfinity;

            for (var v = 0; v < g.V; v++)      // run from each vertex to find
                if (!_marked[v]) Prim(g, v);      // minimum spanning forest

            // check optimality conditions
            //assert check(G);
        }
Beispiel #6
0
        /// <summary>
        /// Compute a minimum spanning tree (or forest) of an edge-weighted graph.
        /// </summary>
        /// <param name="g">g the edge-weighted graph</param>
        public BoruvkaMST(EdgeWeightedGraph g)
        {
            var uf = new UF(g.V);

            // repeat at most log V times or until we have V-1 edges
            for (var t = 1; t < g.V && _mst.Size() < g.V - 1; t = t + t)
            {

                // foreach tree in forest, find closest edge
                // if edge weights are equal, ties are broken in favor of first edge in G.edges()
                var closest = new EdgeW[g.V];
                foreach (var e in g.Edges())
                {
                    int v = e.Either(), w = e.Other(v);
                    int i = uf.Find(v), j = uf.Find(w);
                    if (i == j) continue;   // same tree
                    if (closest[i] == null || Less(e, closest[i])) closest[i] = e;
                    if (closest[j] == null || Less(e, closest[j])) closest[j] = e;
                }

                // add newly discovered edges to MST
                for (var i = 0; i < g.V; i++)
                {
                    var e = closest[i];
                    if (e != null)
                    {
                        int v = e.Either(), w = e.Other(v);
                        // don't add the same edge twice
                        if (!uf.Connected(v, w))
                        {
                            _mst.Add(e);
                            _weight += e.Weight;
                            uf.Union(v, w);
                        }
                    }
                }
            }

            // check optimality conditions
            //assert check(G);
        }
Beispiel #7
0
        /// <summary>
        /// check optimality conditions (takes time proportional to E V lg* V)
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool Check(EdgeWeightedGraph g)
        {
            // check total weight
            var total = Edges().Sum(e => e.Weight);
            if (Math.Abs(total - Weight()) > FLOATING_POINT_EPSILON)
            {
                Console.Error.WriteLine($"Weight of edges does not equal weight(): {total} vs. {Weight()}{Environment.NewLine}");
                return false;
            }

            // check that it is acyclic
            var uf = new UF(g.V);
            foreach (var e in Edges())
            {
                int v = e.Either(), w = e.Other(v);
                if (uf.Connected(v, w))
                {
                    Console.Error.WriteLine("Not a forest");
                    return false;
                }
                uf.Union(v, w);
            }

            // check that it is a spanning forest
            foreach (var e in g.Edges())
            {
                int v = e.Either(), w = e.Other(v);
                if (!uf.Connected(v, w))
                {
                    Console.Error.WriteLine("Not a spanning forest");
                    return false;
                }
            }

            // check that it is a minimal spanning forest (cut optimality conditions)
            foreach (var e in Edges())
            {

                // all edges in MST except e
                uf = new UF(g.V);
                foreach (var f in _mst)
                {
                    int x = f.Either(), y = f.Other(x);
                    if (f != e) uf.Union(x, y);
                }

                // check that e is min weight edge in crossing cut
                foreach (var f in g.Edges())
                {
                    int x = f.Either(), y = f.Other(x);
                    if (!uf.Connected(x, y))
                    {
                        if (f.Weight < e.Weight)
                        {
                            Console.Error.WriteLine($"Edge {f}  violates cut optimality conditions");
                            return false;
                        }
                    }
                }

            }

            return true;
        }
        public void Run()
        {
            Console.WriteLine("Choose file:"); // Prompt
            Console.WriteLine("1 - tinyEWG.txt"); // Prompt
            Console.WriteLine("2 - mediumEWG.txt"); // Prompt
            //Console.WriteLine("3 - mediumEWG.txt"); // Prompt

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

            var fileNumber = Console.ReadLine();
            string fileName;
            int source;
            switch (fileNumber)
            {
                case "1":
                    fileName = "tinyEWG.txt";
                    source = 6;
                    break;
                case "2":
                    fileName = "mediumEWG.txt";
                    source = 6;
                    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<EdgeW>();
            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 EdgeW(ve, we, weight);
                    edges.Add(edge);
                }

                lineIterator++;
            }

            var edgeWeightedGraph = new EdgeWeightedGraph(v, e, edges);
            Console.WriteLine(edgeWeightedGraph);

            // compute shortest paths
            var sp = new DijkstraUndirectedSP(edgeWeightedGraph, source);

            // print shortest path
            for (var t = 0; t < edgeWeightedGraph.V; t++)
            {
                if (sp.HasPathTo(t))
                {
                    Console.Write($"{source} to {t} {$"{sp.DistTo(t):0.00000}"}  ");
                    foreach (var edge in sp.PathTo(t))
                    {
                        Console.Write($"{edge}   ");
                    }
                    Console.WriteLine();
                }
                else
                {
                    Console.WriteLine($"{source} to {t}         no path{Environment.NewLine}");
                }
            }

            Console.ReadLine();
        }
 /// <summary>
 /// Initializes a new edge-weighted graph that is a deep copy of <tt>G</tt>.
 /// </summary>
 /// <param name="g">g the edge-weighted graph to copy</param>
 public EdgeWeightedGraph(EdgeWeightedGraph g)
     : this(g.V)
 {
     E = g.E;
     for (var v = 0; v < g.V; v++)
     {
         // reverse so that adjacency list is in same order as original
         var reverse = new Collections.Stack<EdgeW>();
         foreach (var e in g._adj[v])
         {
             reverse.Push(e);
         }
         foreach (var e in reverse)
         {
             _adj[v].Add(e);
         }
     }
 }
Beispiel #10
0
 /// <summary>
 /// add all edges e incident to v onto pq if the other endpoint has not yet been scanned
 /// </summary>
 /// <param name="g"></param>
 /// <param name="v"></param>
 private void Scan(EdgeWeightedGraph g, int v)
 {
     //assert !marked[v];
     _marked[v] = true;
     foreach (var e in g.Adj(v))
         if (!_marked[e.Other(v)]) _pq.Insert(e);
 }
Beispiel #11
0
 /// <summary>
 /// run Prim's algorithm
 /// </summary>
 /// <param name="g"></param>
 /// <param name="s"></param>
 private void Prim(EdgeWeightedGraph g, int s)
 {
     Scan(g, s);
     while (!_pq.IsEmpty())
     {                        // better to stop when mst has V-1 edges
         var e = _pq.DelMin();                      // smallest edge on pq
         int v = e.Either(), w = e.Other(v);        // two endpoints
         //assert marked[v] || marked[w];
         if (_marked[v] && _marked[w]) continue;      // lazy, both v and w already scanned
         _mst.Enqueue(e);                            // add e to MST
         _weight += e.Weight;
         if (!_marked[v]) Scan(g, v);               // v becomes part of tree
         if (!_marked[w]) Scan(g, w);               // w becomes part of tree
     }
 }
        public void Run()
        {
            Console.WriteLine("Choose file:"); // Prompt
            Console.WriteLine("1 - tinyEWG.txt"); // Prompt
            Console.WriteLine("2 - mediumEWG.txt"); // Prompt
            //Console.WriteLine("3 - mediumEWG.txt"); // Prompt

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

            var fileNumber = Console.ReadLine();
            string fileName;
            switch (fileNumber)
            {
                case "1":
                    fileName = "tinyEWG.txt";
                    break;
                case "2":
                    fileName = "mediumEWG.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<EdgeW>();
            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 EdgeW(ve, we, weight);
                    edges.Add(edge);
                }

                lineIterator++;
            }

            var edgeWeightedGraph = new EdgeWeightedGraph(v, e, edges);
            Console.WriteLine(edgeWeightedGraph);
            Console.ReadLine();
        }
Beispiel #13
0
        /// <summary>
        /// check optimality conditions (takes time proportional to E V lg* V)
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool Check(EdgeWeightedGraph g)
        {
            // check weight
            var totalWeight = Edges().Sum(e => e.Weight);

            if (Math.Abs(totalWeight - Weight()) > FLOATING_POINT_EPSILON)
            {
                Console.Error.WriteLine($"Weight of edges does not equal weight(): {totalWeight} vs. {Weight()}{Environment.NewLine}");
                return(false);
            }

            // check that it is acyclic
            var uf = new UF(g.V);

            foreach (var e in Edges())
            {
                int v = e.Either(), w = e.Other(v);
                if (uf.Connected(v, w))
                {
                    Console.Error.WriteLine("Not a forest");
                    return(false);
                }
                uf.Union(v, w);
            }

            // check that it is a spanning forest
            foreach (var e in g.Edges())
            {
                int v = e.Either(), w = e.Other(v);
                if (!uf.Connected(v, w))
                {
                    Console.Error.WriteLine("Not a spanning forest");
                    return(false);
                }
            }

            // check that it is a minimal spanning forest (cut optimality conditions)
            foreach (var e in Edges())
            {
                // all edges in MST except e
                uf = new UF(g.V);
                foreach (var f in Edges())
                {
                    int x = f.Either(), y = f.Other(x);
                    if (f != e)
                    {
                        uf.Union(x, y);
                    }
                }

                // check that e is min weight edge in crossing cut
                foreach (var f in g.Edges())
                {
                    int x = f.Either(), y = f.Other(x);
                    if (!uf.Connected(x, y))
                    {
                        if (f.Weight < e.Weight)
                        {
                            Console.Error.WriteLine($"Edge {f} violates cut optimality conditions");
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
Beispiel #14
0
 /// <summary>
 /// scan vertex v
 /// </summary>
 /// <param name="g"></param>
 /// <param name="v"></param>
 private void Scan(EdgeWeightedGraph g, int v)
 {
     _marked[v] = true;
     foreach (var e in g.Adj(v))
     {
         var w = e.Other(v);
         if (_marked[w]) continue;         // v-w is obsolete edge
         if (e.Weight < _distTo[w])
         {
             _distTo[w] = e.Weight;
             _edgeTo[w] = e;
             if (_pq.Contains(w)) _pq.DecreaseKey(w, _distTo[w]);
             else _pq.Insert(w, _distTo[w]);
         }
     }
 }
Beispiel #15
0
 /// <summary>
 /// run Prim's algorithm in graph G, starting from vertex s
 /// </summary>
 /// <param name="g"></param>
 /// <param name="s"></param>
 private void Prim(EdgeWeightedGraph g, int s)
 {
     _distTo[s] = 0.0;
     _pq.Insert(s, _distTo[s]);
     while (!_pq.IsEmpty())
     {
         var v = _pq.DelMin();
         Scan(g, v);
     }
 }