/// <summary> /// Returns a cycle digraph on <c>V</c> vertices.</summary> /// <param name="V">the number of vertices in the cycle</param> /// <returns>a digraph that is a directed cycle on <c>V</c> vertices</returns> /// public static Digraph Cycle(int V) { Digraph G = new Digraph(V); int[] vertices = new int[V]; for (int i = 0; i < V; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); for (int i = 0; i < V - 1; i++) { G.AddEdge(vertices[i], vertices[i + 1]); } G.AddEdge(vertices[V - 1], vertices[0]); return(G); }
/// <summary> /// Returns a random rooted-out DAG on <c>V</c> vertices and <c>E</c> edges. /// A rooted out-tree is a DAG in which every vertex is reachable from a /// single vertex. /// The DAG returned is not chosen uniformly at random among all such DAGs.</summary> /// <param name="V">the number of vertices</param> /// <param name="E">the number of edges</param> /// <returns>a random rooted-out DAG on <c>V</c> vertices and <c>E</c> edges</returns> /// public static Digraph RootedOutDAG(int V, int E) { if (E > (long)V * (V - 1) / 2) { throw new ArgumentException("Too many edges"); } if (E < V - 1) { throw new ArgumentException("Too few edges"); } Digraph G = new Digraph(V); SET <Edge> set = new SET <Edge>(); // fix a topological order int[] vertices = new int[V]; for (int i = 0; i < V; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); // one edge pointing from each vertex, other than the root = vertices[V-1] for (int v = 0; v < V - 1; v++) { int w = StdRandom.Uniform(v + 1, V); Edge e = new Edge(w, v); set.Add(e); G.AddEdge(vertices[w], vertices[v]); } while (G.E < E) { int v = StdRandom.Uniform(V); int w = StdRandom.Uniform(V); Edge e = new Edge(w, v); if ((v < w) && !set.Contains(e)) { set.Add(e); G.AddEdge(vertices[w], vertices[v]); } } return(G); }
// tournament /// <summary> /// Returns a random tournament digraph on <c>V</c> vertices. A tournament digraph /// is a DAG in which for every two vertices, there is one directed edge. /// A tournament is an oriented complete graph.</summary> /// <param name="V">the number of vertices</param> /// <returns>a random tournament digraph on <c>V</c> vertices</returns> /// public static Digraph Tournament(int V) { Digraph G = new Digraph(V); for (int v = 0; v < G.V; v++) { for (int w = v + 1; w < G.V; w++) { if (StdRandom.Bernoulli(0.5)) { G.AddEdge(v, w); } else { G.AddEdge(w, v); } } } return(G); }
/// <summary> /// Returns the reverse of the digraph.</summary> /// <returns>the reverse of the digraph</returns> /// public Digraph Reverse() { Digraph R = new Digraph(V); for (int v = 0; v < V; v++) { foreach (int w in Adj(v)) { R.AddEdge(w, v); } } return(R); }
/// <summary> /// Initializes a digraph from a file using the specified delimiter. /// Each line in the file contains /// the name of a vertex, followed by a list of the names /// of the vertices adjacent to that vertex, separated by the delimiter.</summary> /// <param name="filename">the name of the file</param> /// <param name="delimiter">the delimiter between fields</param> /// public SymbolDigraph(string filename, string delimiter) { st = new ST <string, int>(); // First pass builds the index by reading strings to associate // distinct strings with an index FileStream fsIn = File.OpenRead(filename); using (TextReader reader = new StreamReader(fsIn)) { string nextLine = reader.ReadLine(); while (nextLine != null) { string[] a = nextLine.Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < a.Length; i++) { if (!st.Contains(a[i])) { st.Put(a[i], st.Count); } } nextLine = reader.ReadLine(); } } // inverted index to get string keys in an aray keys = new string[st.Count]; foreach (string name in st.Keys()) { keys[st[name]] = name; } // second pass builds the digraph by connecting first vertex on each // line to all others g = new Digraph(st.Count); fsIn = File.OpenRead(filename); using (TextReader reader = new StreamReader(fsIn)) { string nextLine = reader.ReadLine(); while (nextLine != null) { string[] a = nextLine.Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); int v = st[a[0]]; for (int i = 1; i < a.Length; i++) { int w = st[a[i]]; g.AddEdge(v, w); } nextLine = reader.ReadLine(); } } }
/// <summary> /// Returns an Eulerian cycle digraph on <c>V</c> vertices.</summary> /// <param name="V">the number of vertices in the cycle</param> /// <param name="E">the number of edges in the cycle</param> /// <returns>a digraph that is a directed Eulerian cycle on <c>V</c> vertices /// and <c>E</c> edges</returns> /// <exception cref="ArgumentException">if either V <= 0 or E <= 0</exception> /// public static Digraph EulerianCycle(int V, int E) { if (E <= 0) { throw new ArgumentException("An Eulerian cycle must have at least one edge"); } if (V <= 0) { throw new ArgumentException("An Eulerian cycle must have at least one vertex"); } Digraph G = new Digraph(V); int[] vertices = new int[E]; for (int i = 0; i < E; i++) { vertices[i] = StdRandom.Uniform(V); } for (int i = 0; i < E - 1; i++) { G.AddEdge(vertices[i], vertices[i + 1]); } G.AddEdge(vertices[E - 1], vertices[0]); return(G); }
public static void MainTest(string[] args) { int V = int.Parse(args[0]); int E = int.Parse(args[1]); // Eulerian cycle Digraph G1 = DigraphGenerator.EulerianCycle(V, E); DirectedEulerianPath.UnitTest(G1, "Eulerian cycle"); // Eulerian path Digraph G2 = DigraphGenerator.EulerianPath(V, E); DirectedEulerianPath.UnitTest(G2, "Eulerian path"); // add one random edge Digraph G3 = new Digraph(G2); G3.AddEdge(StdRandom.Uniform(V), StdRandom.Uniform(V)); DirectedEulerianPath.UnitTest(G3, "one random edge added to Eulerian path"); // self loop Digraph G4 = new Digraph(V); int v4 = StdRandom.Uniform(V); G4.AddEdge(v4, v4); DirectedEulerianPath.UnitTest(G4, "single self loop"); // single edge Digraph G5 = new Digraph(V); G5.AddEdge(StdRandom.Uniform(V), StdRandom.Uniform(V)); DirectedEulerianPath.UnitTest(G5, "single edge"); // empty digraph Digraph G6 = new Digraph(V); DirectedEulerianPath.UnitTest(G6, "empty digraph"); // random digraph Digraph G7 = DigraphGenerator.Simple(V, E); DirectedEulerianPath.UnitTest(G7, "simple digraph"); // 4-vertex digraph //Digraph G8 = new Digraph(new TextInput("eulerianD.txt")); //DirectedEulerianPath.UnitTest(G8, "4-vertex Eulerian digraph"); }
/// <summary> /// Returns a complete binary tree digraph on <c>V</c> vertices.</summary> /// <param name="V">the number of vertices in the binary tree</param> /// <returns>a digraph that is a complete binary tree on <c>V</c> vertices</returns> /// public static Digraph BinaryTree(int V) { Digraph G = new Digraph(V); int[] vertices = new int[V]; for (int i = 0; i < V; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); for (int i = 1; i < V; i++) { G.AddEdge(vertices[i], vertices[(i - 1) / 2]); } return(G); }
/// <summary> /// Returns an Eulerian path digraph on <c>V</c> vertices.</summary> /// <param name="V">the number of vertices in the path</param> /// <param name="E">the number of edges in the path</param> /// <returns>a digraph that is a directed Eulerian path on <c>V</c> vertices</returns> /// and <c>E</c> edges /// <exception cref="ArgumentException">if either V <= 0 or E < 0</exception> /// public static Digraph EulerianPath(int V, int E) { if (E < 0) { throw new ArgumentException("negative number of edges"); } if (V <= 0) { throw new ArgumentException("An Eulerian path must have at least one vertex"); } Digraph G = new Digraph(V); int[] vertices = new int[E + 1]; for (int i = 0; i < E + 1; i++) { vertices[i] = StdRandom.Uniform(V); } for (int i = 0; i < E; i++) { G.AddEdge(vertices[i], vertices[i + 1]); } return(G); }
/// <summary> /// Returns a random simple digraph on <c>V</c> vertices, with an /// edge between any two vertices with probability <c>p</c>. This is sometimes /// referred to as the Erdos-Renyi random digraph model. /// This implementations takes time propotional to V^2 (even if <c>p</c> is small).</summary> /// <param name="V">the number of vertices</param> /// <param name="p">the probability of choosing an edge</param> /// <returns>a random simple digraph on <c>V</c> vertices, with an edge between /// any two vertices with probability <c>p</c></returns> /// <exception cref="ArgumentException">if probability is not between 0 and 1</exception> /// public static Digraph Simple(int V, double p) { if (p < 0.0 || p > 1.0) { throw new ArgumentException("Probability must be between 0 and 1"); } Digraph G = new Digraph(V); for (int v = 0; v < V; v++) { for (int w = 0; w < V; w++) { if (v != w) { if (StdRandom.Bernoulli(p)) { G.AddEdge(v, w); } } } } return(G); }
public static void MainTest(string[] args) { int V = int.Parse(args[0]); int E = int.Parse(args[1]); // Eulerian cycle Digraph G1 = DigraphGenerator.EulerianCycle(V, E); DirectedEulerianCycle.UnitTest(G1, "Eulerian cycle"); // Eulerian path Digraph G2 = DigraphGenerator.EulerianPath(V, E); DirectedEulerianCycle.UnitTest(G2, "Eulerian path"); // empty digraph Digraph G3 = new Digraph(V); DirectedEulerianCycle.UnitTest(G3, "empty digraph"); // self loop Digraph G4 = new Digraph(V); int v4 = StdRandom.Uniform(V); G4.AddEdge(v4, v4); DirectedEulerianCycle.UnitTest(G4, "single self loop"); // union of two disjoint cycles Digraph H1 = DigraphGenerator.EulerianCycle(V / 2, E / 2); Digraph H2 = DigraphGenerator.EulerianCycle(V - V / 2, E - E / 2); int[] perm = new int[V]; for (int i = 0; i < V; i++) { perm[i] = i; } StdRandom.Shuffle(perm); Digraph G5 = new Digraph(V); for (int v = 0; v < H1.V; v++) { foreach (int w in H1.Adj(v)) { G5.AddEdge(perm[v], perm[w]); } } for (int v = 0; v < H2.V; v++) { foreach (int w in H2.Adj(v)) { G5.AddEdge(perm[V / 2 + v], perm[V / 2 + w]); } } DirectedEulerianCycle.UnitTest(G5, "Union of two disjoint cycles"); // random digraph Digraph G6 = DigraphGenerator.Simple(V, E); DirectedEulerianCycle.UnitTest(G6, "simple digraph"); // 4-vertex digraph - no data file //Digraph G7 = new Digraph(new TextInput("eulerianD.txt")); //DirectedEulerianCycle.UnitTest(G7, "4-vertex Eulerian digraph"); }
/// <summary> /// Returns a random simple digraph on <c>V</c> vertices, <c>E</c> /// edges and (at least) <c>c</c> strong components. The vertices are randomly /// assigned integer labels between <c>0</c> and <c>c-1</c> (corresponding to /// strong components). Then, a strong component is creates among the vertices /// with the same label. Next, random edges (either between two vertices with /// the same labels or from a vetex with a smaller label to a vertex with a /// larger label). The number of components will be equal to the number of /// distinct labels that are assigned to vertices.</summary> /// <param name="V">the number of vertices</param> /// <param name="E">the number of edges</param> /// <param name="c">the (maximum) number of strong components</param> /// <returns>a random simple digraph on <c>V</c> vertices and /// <c>E</c> edges, with (at most) <c>c</c> strong components</returns> /// <exception cref="ArgumentException">if <c>c</c> is larger than <c>V</c></exception> /// public static Digraph Strong(int V, int E, int c) { if (c >= V || c <= 0) { throw new ArgumentException("Number of components must be between 1 and V"); } if (E <= 2 * (V - c)) { throw new ArgumentException("Number of edges must be at least 2(V-c)"); } if (E > (long)V * (V - 1) / 2) { throw new ArgumentException("Too many edges"); } // the digraph Digraph G = new Digraph(V); // edges added to G (to avoid duplicate edges) SET <Edge> set = new SET <Edge>(); int[] label = new int[V]; for (int v = 0; v < V; v++) { label[v] = StdRandom.Uniform(c); } // make all vertices with label c a strong component by // combining a rooted in-tree and a rooted out-tree for (int i = 0; i < c; i++) { // how many vertices in component c int count = 0; for (int v = 0; v < G.V; v++) { if (label[v] == i) { count++; } } // if (count == 0) System.err.println("less than desired number of strong components"); int[] vertices = new int[count]; int j = 0; for (int v = 0; v < V; v++) { if (label[v] == i) { vertices[j++] = v; } } StdRandom.Shuffle(vertices); // rooted-in tree with root = vertices[count-1] for (int v = 0; v < count - 1; v++) { int w = StdRandom.Uniform(v + 1, count); Edge e = new Edge(w, v); set.Add(e); G.AddEdge(vertices[w], vertices[v]); } // rooted-out tree with root = vertices[count-1] for (int v = 0; v < count - 1; v++) { int w = StdRandom.Uniform(v + 1, count); Edge e = new Edge(v, w); set.Add(e); G.AddEdge(vertices[v], vertices[w]); } } while (G.E < E) { int v = StdRandom.Uniform(V); int w = StdRandom.Uniform(V); Edge e = new Edge(v, w); if (!set.Contains(e) && v != w && label[v] <= label[w]) { set.Add(e); G.AddEdge(v, w); } } return(G); }