View Javadoc

1   /*
2    * Copyright (c) 2003, the JUNG Project and the Regents of the University of
3    * California All rights reserved.
4    * 
5    * This software is open-source under the BSD license; see either "license.txt"
6    * or http://jung.sourceforge.net/license.txt for a description.
7    */
8   /*
9    * Created on Jul 2, 2003
10   *  
11   */
12  package edu.uci.ics.jung.graph.util;
13  
14  import java.util.ArrayList;
15  import java.util.HashSet;
16  import java.util.List;
17  import java.util.Set;
18  
19  import edu.uci.ics.jung.graph.DirectedGraph;
20  import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
21  import edu.uci.ics.jung.graph.Graph;
22  import edu.uci.ics.jung.graph.SparseMultigraph;
23  import edu.uci.ics.jung.graph.UndirectedGraph;
24  import edu.uci.ics.jung.graph.UndirectedSparseMultigraph;
25  
26  /**
27   * Provides generators for several different test graphs.
28   */
29  public class TestGraphs {
30  
31  	/**
32  	 * A series of pairs that may be useful for generating graphs. The
33  	 * miniature graph consists of 8 edges, 10 nodes, and is formed of two
34  	 * connected components, one of 8 nodes, the other of 2.
35  	 *  
36  	 */
37  	public static String[][] pairs = { { "a", "b", "3" }, {
38  			"a", "c", "4" }, {
39  			"a", "d", "5" }, {
40  			"d", "c", "6" }, {
41  			"d", "e", "7" }, {
42  			"e", "f", "8" }, {
43  			"f", "g", "9" }, {
44  			"h", "i", "1" }
45  	};
46  
47  	/**
48  	 * Creates a small sample graph that can be used for testing purposes. The
49  	 * graph is as described in the section on {@link #pairs pairs}. If <code>isDirected</code>,
50  	 * the graph is a {@link DirectedSparseMultigraph DirectedSparseMultigraph},
51  	 * otherwise, it is an {@link UndirectedSparseMultigraph UndirectedSparseMultigraph}.
52  	 * 
53  	 * @return a graph consisting of eight edges and ten nodes.
54  	 */
55  	public static Graph<String, Number> createTestGraph(boolean directed) {
56  		Graph<String, Number> graph = null;
57  		if(directed) {
58  			graph = new DirectedSparseMultigraph<String,Number>();
59  		} else {
60  			graph = new UndirectedSparseMultigraph<String,Number>();
61  		}
62  
63  		for (int i = 0; i < pairs.length; i++) {
64  			String[] pair = pairs[i];
65  			graph.addEdge(Integer.parseInt(pair[2]), pair[0], pair[1]);
66  		}
67  		return graph;
68  	}
69  
70      /**
71       * Returns a graph consisting of a chain of <code>vertex_count - 1</code> vertices
72       * plus one isolated vertex.
73       */
74      public static Graph<String,Number> createChainPlusIsolates(int chain_length, int isolate_count)
75      {
76      	Graph<String,Number> g = new UndirectedSparseMultigraph<String,Number>();
77          if (chain_length > 0)
78          {
79              String[] v = new String[chain_length];
80              v[0] = "v"+0;
81              g.addVertex(v[0]);
82              for (int i = 1; i < chain_length; i++)
83              {
84                  v[i] = "v"+i;
85                  g.addVertex(v[i]);
86                  g.addEdge(new Double(Math.random()), v[i], v[i-1]);
87              }
88          }
89          for (int i = 0; i < isolate_count; i++) {
90              String v = "v"+(chain_length+i);
91              g.addVertex(v);
92          }
93          return g;
94      }
95      
96  	/**
97  	 * Creates a sample directed acyclic graph by generating several "layers",
98  	 * and connecting nodes (randomly) to nodes in earlier (but never later)
99  	 * layers. Each layer has some random number of nodes in it 1 less than n
100 	 * less than maxNodesPerLayer.
101 	 * 
102 	 * @return the created graph
103 	 */
104 	public static Graph<String,Number> createDirectedAcyclicGraph(
105 		int layers,
106 		int maxNodesPerLayer,
107 		double linkprob) {
108 
109 		DirectedGraph<String,Number> dag = new DirectedSparseMultigraph<String,Number>();
110 		Set<String> previousLayers = new HashSet<String>();
111 		Set<String> inThisLayer = new HashSet<String>();
112 		for (int i = 0; i < layers; i++) {
113 
114 			int nodesThisLayer = (int) (Math.random() * maxNodesPerLayer) + 1;
115 			for (int j = 0; j < nodesThisLayer; j++) {
116                 String v = i+":"+j;
117 				dag.addVertex(v);
118 				inThisLayer.add(v);
119 				// for each previous node...
120                 for(String v2 : previousLayers) {
121 					if (Math.random() < linkprob) {
122                         Double de = new Double(Math.random());
123 						dag.addEdge(de, v, v2);
124 					}
125 				}
126 			}
127 
128 			previousLayers.addAll(inThisLayer);
129 			inThisLayer.clear();
130 		}
131 		return dag;
132 	}
133 	
134 	private static void createEdge(
135 			Graph<String, Number> g,
136 			String v1Label,
137 			String v2Label,
138 			int weight) {
139 			g.addEdge(new Double(Math.random()), v1Label, v2Label);
140 	}
141 	
142 	/**
143 	 * Returns a bigger, undirected test graph with a just one component. This
144 	 * graph consists of a clique of ten edges, a partial clique (randomly
145 	 * generated, with edges of 0.6 probability), and one series of edges
146 	 * running from the first node to the last.
147 	 * 
148 	 * @return the testgraph
149 	 */
150 	public static Graph<String,Number> getOneComponentGraph() {
151 
152 		UndirectedGraph<String,Number> g = new UndirectedSparseMultigraph<String,Number>();
153 		// let's throw in a clique, too
154 		for (int i = 1; i <= 10; i++) {
155 			for (int j = i + 1; j <= 10; j++) {
156 				String i1 = "" + i;
157 				String i2 = "" + j;
158 				g.addEdge(Math.pow(i+2,j), i1, i2);
159 			}
160 		}
161 
162 		// and, last, a partial clique
163 		for (int i = 11; i <= 20; i++) {
164 			for (int j = i + 1; j <= 20; j++) {
165 				if (Math.random() > 0.6)
166 					continue;
167 				String i1 = "" + i;
168 				String i2 = "" + j;
169 				g.addEdge(Math.pow(i+2,j), i1, i2);
170 			}
171 		}
172 
173 		List<String> index = new ArrayList<String>();
174 		index.addAll(g.getVertices());
175 		// and one edge to connect them all
176 		for (int i = 0; i < index.size() - 1; i++) 
177 		    g.addEdge(new Integer(i), index.get(i), index.get(i+1));
178 
179 		return g;
180 	}
181 
182 	/**
183 	 * Returns a bigger test graph with a clique, several components, and other
184 	 * parts.
185 	 * 
186 	 * @return a demonstration graph of type <tt>UndirectedSparseMultigraph</tt>
187 	 *         with 28 vertices.
188 	 */
189 	public static Graph<String, Number> getDemoGraph() {
190 		UndirectedGraph<String, Number> g = 
191             new UndirectedSparseMultigraph<String, Number>();
192 
193 		for (int i = 0; i < pairs.length; i++) {
194 			String[] pair = pairs[i];
195 			createEdge(g, pair[0], pair[1], Integer.parseInt(pair[2]));
196 		}
197 
198 		// let's throw in a clique, too
199 		for (int i = 1; i <= 10; i++) {
200 			for (int j = i + 1; j <= 10; j++) {
201 				String i1 = "c" + i;
202 				String i2 = "c" + j;
203                 g.addEdge(Math.pow(i+2,j), i1, i2);
204 			}
205 		}
206 
207 		// and, last, a partial clique
208 		for (int i = 11; i <= 20; i++) {
209 			for (int j = i + 1; j <= 20; j++) {
210 				if (Math.random() > 0.6)
211 					continue;
212 				String i1 = "p" + i;
213 				String i2 = "p" + j;
214                 g.addEdge(Math.pow(i+2,j), i1, i2);
215 			}
216 		}
217 		return g;
218 	}
219 
220     /**
221      * Returns a small graph with directed and undirected edges, and parallel edges.
222      */
223     public static Graph<String, Number> getSmallGraph() {
224         Graph<String, Number> graph = 
225             new SparseMultigraph<String, Number>();
226         String[] v = new String[3];
227         for (int i = 0; i < 3; i++) {
228             v[i] = String.valueOf(i);
229             graph.addVertex(v[i]);
230         }
231         graph.addEdge(new Double(0), v[0], v[1], EdgeType.DIRECTED);
232         graph.addEdge(new Double(.1), v[0], v[1], EdgeType.DIRECTED);
233         graph.addEdge(new Double(.2), v[0], v[1], EdgeType.DIRECTED);
234         graph.addEdge(new Double(.3), v[1], v[0], EdgeType.DIRECTED);
235         graph.addEdge(new Double(.4), v[1], v[0], EdgeType.DIRECTED);
236         graph.addEdge(new Double(.5), v[1], v[2]);
237         graph.addEdge(new Double(.6), v[1], v[2]);
238 
239         return graph;
240     }
241 }