View Javadoc
1   /*
2    * Created on May 3, 2004
3    *
4    * Copyright (c) 2004, The JUNG Authors 
5    *
6    * All rights reserved.
7    *
8    * This software is open-source under the BSD license; see either
9    * "license.txt" or
10   * https://github.com/jrtom/jung/blob/master/LICENSE for a description.
11   */
12  package edu.uci.ics.jung.io;
13  
14  import java.awt.geom.Point2D;
15  import java.io.File;
16  import java.io.FileNotFoundException;
17  import java.io.IOException;
18  import java.io.Reader;
19  import java.io.StringReader;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  import junit.framework.Assert;
27  import junit.framework.TestCase;
28  
29  import com.google.common.base.Function;
30  import com.google.common.base.Functions;
31  import com.google.common.base.Supplier;
32  
33  import edu.uci.ics.jung.graph.DirectedGraph;
34  import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
35  import edu.uci.ics.jung.graph.Graph;
36  import edu.uci.ics.jung.graph.SparseMultigraph;
37  import edu.uci.ics.jung.graph.UndirectedGraph;
38  import edu.uci.ics.jung.graph.UndirectedSparseMultigraph;
39  import edu.uci.ics.jung.graph.util.EdgeType;
40  import edu.uci.ics.jung.graph.util.Pair;
41  
42  
43  /**
44   * Needed tests:
45   * - edgeslist, arcslist
46   * - unit test to catch bug in readArcsOrEdges() [was skipping until e_pred, not c_pred]
47   * 
48   * @author Joshua O'Madadhain
49   * @author Tom Nelson - converted to jung2
50   */
51  public class PajekNetIOTest extends TestCase
52  {
53      protected String[] vertex_labels = {"alpha", "beta", "gamma", "delta", "epsilon"};
54      
55  	Supplier<DirectedGraph<Number,Number>> directedGraphFactory;
56  	Supplier<UndirectedGraph<Number,Number>> undirectedGraphFactory;
57  	Supplier<Graph<Number,Number>> graphFactory;
58  	Supplier<Number> vertexFactory;
59  	Supplier<Number> edgeFactory;
60      PajekNetReader<Graph<Number, Number>, Number,Number> pnr; 
61  	
62      @Override
63      protected void setUp() {
64      	directedGraphFactory = new Supplier<DirectedGraph<Number,Number>>() {
65      		public DirectedGraph<Number,Number> get() {
66      			return new DirectedSparseMultigraph<Number,Number>();
67      		}
68      	};
69      	undirectedGraphFactory = new Supplier<UndirectedGraph<Number,Number>>() {
70      		public UndirectedGraph<Number,Number> get() {
71      			return new UndirectedSparseMultigraph<Number,Number>();
72      		}
73      	};
74      	graphFactory = new Supplier<Graph<Number,Number>>() {
75      		public Graph<Number,Number> get() {
76      			return new SparseMultigraph<Number,Number>();
77      		}
78      	};
79      	vertexFactory = new Supplier<Number>() {
80      		int n = 0;
81      		public Number get() { return n++; }
82      	};
83      	edgeFactory = new Supplier<Number>() {
84      		int n = 0;
85      		public Number get() { return n++; }
86      	};
87          pnr = new PajekNetReader<Graph<Number, Number>, Number,Number>(vertexFactory, edgeFactory);
88  
89      }
90  
91      public void testNull()
92      {
93          
94      }
95      
96  
97      public void testFileNotFound()
98      {
99          try
100         {
101             pnr.load("/dev/null/foo", graphFactory);
102             fail("File load did not fail on nonexistent file");
103         }
104         catch (FileNotFoundException fnfe)
105         {
106         }
107         catch (IOException ioe)
108         {
109             fail("unexpected IOException");
110         }
111     }
112 
113     public void testNoLabels() throws IOException
114     {
115         String test = "*Vertices 3\n1\n2\n3\n*Edges\n1 2\n2 2";
116         Reader r = new StringReader(test);
117         
118         Graph<Number, Number> g = pnr.load(r, undirectedGraphFactory);
119         assertEquals(g.getVertexCount(), 3);
120         assertEquals(g.getEdgeCount(), 2);
121     }
122     
123     public void testDirectedSaveLoadSave() throws IOException
124     {
125         Graph<Number,Number> graph1 = directedGraphFactory.get();
126         for(int i=0; i<5; i++) {
127         	graph1.addVertex(i);
128         }
129 //        GraphUtils.addVertices(graph1, 5);
130         List<Number> id = new ArrayList<Number>(graph1.getVertices());//Indexer.getIndexer(graph1);
131         GreekLabels<Number> gl = new GreekLabels<Number>(id);
132         int j=0;
133         graph1.addEdge(j++, 0, 1);
134         graph1.addEdge(j++, 0, 2);
135         graph1.addEdge(j++, 1, 2);
136         graph1.addEdge(j++, 1, 3);
137         graph1.addEdge(j++, 1, 4);
138         graph1.addEdge(j++, 4, 3);
139         
140         
141 //        System.err.println("graph1 = "+graph1);
142 //        for(Number edge : graph1.getEdges()) {
143 //        	System.err.println("edge "+edge+" is directed? "+graph1.getEdgeType(edge));
144 //        }
145 //        for(Number v : graph1.getVertices()) {
146 //        	System.err.println(v+" outedges are "+graph1.getOutEdges(v));
147 //        	System.err.println(v+" inedges are "+graph1.getInEdges(v));
148 //        	System.err.println(v+" incidentedges are "+graph1.getIncidentEdges(v));
149 //        }
150 
151         assertEquals(graph1.getEdgeCount(), 6);
152 
153         String testFilename = "dtest.net";
154         String testFilename2 = testFilename + "2";
155 
156         PajekNetWriter<Number,Number> pnw = new PajekNetWriter<Number,Number>();
157         pnw.save(graph1, testFilename, gl, null, null);
158 
159         Graph<Number,Number> graph2 = pnr.load(testFilename, directedGraphFactory);
160 
161 //        System.err.println("graph2 = "+graph2);
162 //        for(Number edge : graph2.getEdges()) {
163 //        	System.err.println("edge "+edge+" is directed? "+graph2.getEdgeType(edge));
164 //        }
165 //        for(Number v : graph2.getVertices()) {
166 //        	System.err.println(v+" outedges are "+graph2.getOutEdges(v));
167 //        	System.err.println(v+" inedges are "+graph2.getInEdges(v));
168 //        	System.err.println(v+" incidentedges are "+graph2.getIncidentEdges(v));
169 //       }
170 
171         assertEquals(graph1.getVertexCount(), graph2.getVertexCount());
172         assertEquals(graph1.getEdgeCount(), graph2.getEdgeCount());
173 
174         pnw.save(graph2, testFilename2, pnr.getVertexLabeller(), null, null);
175 
176         compareIndexedGraphs(graph1, graph2);
177 
178         Graph<Number,Number> graph3 = pnr.load(testFilename2, graphFactory);
179 
180 //        System.err.println("graph3 = "+graph3);
181 //        for(Number edge : graph3.getEdges()) {
182 //        	System.err.println("edge "+edge+" is directed? "+graph3.getEdgeType(edge));
183 //        }
184 //        for(Number v : graph3.getVertices()) {
185 //        	System.err.println(v+" outedges are "+graph3.getOutEdges(v));
186 //        	System.err.println(v+" inedges are "+graph3.getInEdges(v));
187 //        	System.err.println(v+" incidentedges are "+graph3.getIncidentEdges(v));
188 //        }
189 
190         compareIndexedGraphs(graph2, graph3);
191 
192         File file1 = new File(testFilename);
193         File file2 = new File(testFilename2);
194 
195         Assert.assertTrue(file1.length() == file2.length());
196         file1.delete();
197         file2.delete();
198     }
199 
200     public void testUndirectedSaveLoadSave() throws IOException
201     {
202         UndirectedGraph<Number,Number> graph1 = 
203         	undirectedGraphFactory.get();
204         for(int i=0; i<5; i++) {
205         	graph1.addVertex(i);
206         }
207 
208         List<Number> id = new ArrayList<Number>(graph1.getVertices());
209         int j=0;
210         GreekLabels<Number> gl = new GreekLabels<Number>(id);
211         graph1.addEdge(j++, 0, 1);
212         graph1.addEdge(j++, 0, 2);
213         graph1.addEdge(j++, 1, 2);
214         graph1.addEdge(j++, 1, 3);
215         graph1.addEdge(j++, 1, 4);
216         graph1.addEdge(j++, 4, 3);
217 
218         assertEquals(graph1.getEdgeCount(), 6);
219 
220 //        System.err.println("graph1 = "+graph1);
221 //        for(Number edge : graph1.getEdges()) {
222 //        	System.err.println("edge "+edge+" is directed? "+graph1.getEdgeType(edge));
223 //        }
224 //        for(Number v : graph1.getVertices()) {
225 //        	System.err.println(v+" outedges are "+graph1.getOutEdges(v));
226 //        	System.err.println(v+" inedges are "+graph1.getInEdges(v));
227 //        	System.err.println(v+" incidentedges are "+graph1.getIncidentEdges(v));
228 //        }
229 
230         String testFilename = "utest.net";
231         String testFilename2 = testFilename + "2";
232 
233         PajekNetWriter<Number,Number> pnw = new PajekNetWriter<Number,Number>();
234         pnw.save(graph1, testFilename, gl, null, null);
235 
236         Graph<Number,Number> graph2 = pnr.load(testFilename, undirectedGraphFactory);
237         
238         
239 //        System.err.println("graph2 = "+graph2);
240 //        for(Number edge : graph2.getEdges()) {
241 //        	System.err.println("edge "+edge+" is directed? "+graph2.getEdgeType(edge));
242 //        }
243 //        for(Number v : graph2.getVertices()) {
244 //        	System.err.println(v+" outedges are "+graph2.getOutEdges(v));
245 //        	System.err.println(v+" inedges are "+graph2.getInEdges(v));
246 //        	System.err.println(v+" incidentedges are "+graph2.getIncidentEdges(v));
247 //        }
248 
249 
250         assertEquals(graph1.getVertexCount(), graph2.getVertexCount());
251         assertEquals(graph1.getEdgeCount(), graph2.getEdgeCount());
252 
253         pnw.save(graph2, testFilename2, pnr.getVertexLabeller(), null, null);
254         compareIndexedGraphs(graph1, graph2);
255 
256         Graph<Number,Number> graph3 = pnr.load(testFilename2, graphFactory);
257 //        System.err.println("graph3 = "+graph3);
258 //        for(Number edge : graph3.getEdges()) {
259 //        	System.err.println("edge "+edge+" is directed? "+graph3.getEdgeType(edge));
260 //        }
261 //        for(Number v : graph3.getVertices()) {
262 //        	System.err.println(v+" outedges are "+graph3.getOutEdges(v));
263 //        	System.err.println(v+" inedges are "+graph3.getInEdges(v));
264 //        	System.err.println(v+" incidentedges are "+graph3.getIncidentEdges(v));
265 //        }
266 
267         compareIndexedGraphs(graph2, graph3);
268 
269         File file1 = new File(testFilename);
270         File file2 = new File(testFilename2);
271 
272         Assert.assertTrue(file1.length() == file2.length());
273         file1.delete();
274         file2.delete();
275     }
276 
277     public void testMixedSaveLoadSave() throws IOException
278     {
279         Graph<Number,Number> graph1 = new SparseMultigraph<Number,Number>();
280         for(int i=0; i<5; i++) {
281         	graph1.addVertex(i);
282         }
283         int j=0;
284 
285         List<Number> id = new ArrayList<Number>(graph1.getVertices());
286         GreekLabels<Number> gl = new GreekLabels<Number>(id);
287         Number[] edges = { 0,1,2,3,4,5 };
288 
289         graph1.addEdge(j++, 0, 1, EdgeType.DIRECTED);
290         graph1.addEdge(j++, 0, 2, EdgeType.DIRECTED);
291         graph1.addEdge(j++, 1, 2, EdgeType.DIRECTED);
292         graph1.addEdge(j++, 1, 3);
293         graph1.addEdge(j++, 1, 4);
294         graph1.addEdge(j++, 4, 3);
295 
296         Map<Number,Number> nr = new HashMap<Number,Number>();
297         for (int i = 0; i < edges.length; i++)
298         {
299             nr.put(edges[i], new Float(Math.random()));
300         }
301         
302         assertEquals(graph1.getEdgeCount(), 6);
303 
304 //        System.err.println(" mixed graph1 = "+graph1);
305 //        for(Number edge : graph1.getEdges()) {
306 //        	System.err.println("edge "+edge+" is directed? "+graph1.getEdgeType(edge));
307 //        }
308 //        for(Number v : graph1.getVertices()) {
309 //        	System.err.println(v+" outedges are "+graph1.getOutEdges(v));
310 //        	System.err.println(v+" inedges are "+graph1.getInEdges(v));
311 //        	System.err.println(v+" incidentedges are "+graph1.getIncidentEdges(v));
312 //        }
313 
314         String testFilename = "mtest.net";
315         String testFilename2 = testFilename + "2";
316 
317         // assign arbitrary locations to each vertex
318         Map<Number, Point2D> locations = new HashMap<Number, Point2D>();
319         for (Number v : graph1.getVertices()) {
320         	locations.put(v, new Point2D.Double(v.intValue() * v.intValue(), 1 << v.intValue()));
321         }
322         Function<Number, Point2D> vld = Functions.forMap(locations);
323         
324         PajekNetWriter<Number,Number> pnw = new PajekNetWriter<Number,Number>();
325         pnw.save(graph1, testFilename, gl, Functions.forMap(nr), vld);
326         
327         Graph<Number,Number> graph2 = pnr.load(testFilename, graphFactory);
328         Function<Number, String> pl = pnr.getVertexLabeller();
329         List<Number> id2 = new ArrayList<Number>(graph2.getVertices());
330         Function<Number,Point2D> vld2 = pnr.getVertexLocationTransformer();
331         
332         assertEquals(graph1.getVertexCount(), graph2.getVertexCount());
333         assertEquals(graph1.getEdgeCount(), graph2.getEdgeCount());
334 
335         // test vertex labels and locations
336         for (int i = 0; i < graph1.getVertexCount(); i++)
337         {
338             Number v1 = id.get(i);
339             Number v2 = id2.get(i);
340             assertEquals(gl.apply(v1), pl.apply(v2));
341             assertEquals(vld.apply(v1), vld2.apply(v2));
342         }
343         
344         // test edge weights
345         Function<Number,Number> nr2 = pnr.getEdgeWeightTransformer();
346         for (Number e2 : graph2.getEdges()) 
347         {
348             Pair<Number> endpoints = graph2.getEndpoints(e2);
349             Number v1_2 = endpoints.getFirst();
350             Number v2_2 = endpoints.getSecond();
351             Number v1_1 = id.get(id2.indexOf(v1_2));
352             Number v2_1 = id.get(id2.indexOf(v2_2));
353             Number e1 = graph1.findEdge(v1_1, v2_1);
354             assertNotNull(e1);
355             assertEquals(nr.get(e1).floatValue(), nr2.apply(e2).floatValue(), 0.0001);
356         }
357 
358         pnw.save(graph2, testFilename2, pl, nr2, vld2);
359 
360         compareIndexedGraphs(graph1, graph2);
361 
362         pnr.setVertexLabeller(null);
363         Graph<Number,Number> graph3 = pnr.load(testFilename2, graphFactory);
364 
365         compareIndexedGraphs(graph2, graph3);
366 
367         File file1 = new File(testFilename);
368         File file2 = new File(testFilename2);
369 
370         Assert.assertTrue(file1.length() == file2.length());
371         file1.delete();
372         file2.delete();
373         
374     }
375 
376     
377     /**
378      * Tests to see whether these two graphs are structurally equivalent, based
379      * on the connectivity of the vertices with matching indices in each graph.
380      * Assumes a 0-based index. 
381      * 
382      * @param g1
383      * @param g2
384      */
385     private void compareIndexedGraphs(Graph<Number,Number> g1, Graph<Number,Number> g2)
386     {
387         int n1 = g1.getVertexCount();
388         int n2 = g2.getVertexCount();
389 
390         assertEquals(n1, n2);
391 
392         assertEquals(g1.getEdgeCount(), g2.getEdgeCount());
393 
394         List<Number> id1 = new ArrayList<Number>(g1.getVertices());
395         List<Number> id2 = new ArrayList<Number>(g2.getVertices());
396 
397         for (int i = 0; i < n1; i++)
398         {
399             Number v1 = id1.get(i);
400             Number v2 = id2.get(i);
401             assertNotNull(v1);
402             assertNotNull(v2);
403             
404             checkSets(g1.getPredecessors(v1), g2.getPredecessors(v2), id1, id2);
405             checkSets(g1.getSuccessors(v1), g2.getSuccessors(v2), id1, id2);
406         }
407     }
408 
409     private void checkSets(Collection<Number> s1, Collection<Number> s2, List<Number> id1, List<Number> id2)
410     {
411         for (Number u : s1)
412         {
413             int j = id1.indexOf(u);
414             assertTrue(s2.contains(id2.get(j)));
415         }
416     }
417 
418     private class GreekLabels<V> implements Function<V,String>
419     {
420         private List<V> id; 
421         
422         public GreekLabels(List<V> id)
423         {
424             this.id = id;
425         }
426         
427         public String apply(V v)
428         {
429             return vertex_labels[id.indexOf(v)];
430         }
431         
432     }    
433 }