View Javadoc
1   /*
2    * Created on May 4, 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.BufferedWriter;
16  import java.io.FileWriter;
17  import java.io.IOException;
18  import java.io.Writer;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.HashSet;
22  import java.util.List;
23  
24  import com.google.common.base.Function;
25  
26  import edu.uci.ics.jung.graph.DirectedGraph;
27  import edu.uci.ics.jung.graph.Graph;
28  import edu.uci.ics.jung.graph.UndirectedGraph;
29  import edu.uci.ics.jung.graph.util.EdgeType;
30  import edu.uci.ics.jung.graph.util.Pair;
31  
32  /**
33   * Writes graphs in the Pajek NET format.
34   * 
35   * <p>Labels for vertices, edge weights, and vertex locations may each optionally
36   * be specified.  Note that vertex location coordinates 
37   * must be normalized to the interval [0, 1] on each axis in order to conform to the 
38   * Pajek specification.
39   * 
40   * @author Joshua O'Madadhain
41   * @author Tom Nelson - converted to jung2
42   */
43  public class PajekNetWriter<V,E>
44  {
45      /**
46       * Creates a new instance.
47       */
48      public PajekNetWriter()
49      {
50      }
51  
52      /**
53       * Saves the graph to the specified file.
54       * @param g the graph to be saved
55       * @param filename the filename of the file to write the graph to
56       * @param vs mapping from vertices to labels
57       * @param nev mapping from edges to weights
58       * @param vld mapping from vertices to locations
59       * @throws IOException if the graph cannot be saved
60       */
61      public void save(Graph<V,E> g, String filename, Function<V,String> vs, 
62              Function<E,Number> nev, Function<V,Point2D> vld) throws IOException
63      {
64          save(g, new FileWriter(filename), vs, nev, vld);
65      }
66      
67      /**
68       * Saves the graph to the specified file.
69       * @param g the graph to be saved
70       * @param filename the filename of the file to write the graph to
71       * @param vs mapping from vertices to labels
72       * @param nev mapping from edges to weights
73       * @throws IOException if the graph cannot be saved
74       */
75      public void save(Graph<V,E> g, String filename, Function<V,String> vs, 
76              Function<E,Number> nev) throws IOException
77      {
78          save(g, new FileWriter(filename), vs, nev, null);
79      }
80      
81      /**
82       * Saves the graph to the specified file.  No vertex labels are written, and the 
83       * edge weights are written as 1.0.
84       * @param g the graph to be saved
85       * @param filename the filename of the file to write the graph to
86       * @throws IOException if the graph cannot be saved
87       */
88      public void save(Graph<V,E> g, String filename) throws IOException
89      {
90          save(g, filename, null, null, null);
91      }
92  
93      /**
94       * Saves the graph to the specified writer.  No vertex labels are written, and the 
95       * edge weights are written as 1.0.
96       * @param g the graph to be saved
97       * @param w the writer instance to write the graph to
98       * @throws IOException if the graph cannot be saved
99       */
100     public void save(Graph<V,E> g, Writer w) throws IOException
101     {
102         save(g, w, null, null, null);
103     }
104 
105     /**
106      * Saves the graph to the specified writer.
107      * @param g the graph to be saved
108      * @param w the writer instance to write the graph to
109      * @param vs mapping from vertices to labels
110      * @param nev mapping from edges to weights
111      * @throws IOException if the graph cannot be saved
112      */
113     public void save(Graph<V,E> g, Writer w, Function<V,String> vs, 
114             Function<E,Number> nev) throws IOException
115     {
116         save(g, w, vs, nev, null);
117     }
118     
119     /**
120      * Saves the graph to the specified writer.
121      * @param graph the graph to be saved
122      * @param w the writer instance to write the graph to
123      * @param vs mapping from vertices to labels (no labels are written if null)
124      * @param nev mapping from edges to weights (defaults to weights of 1.0 if null)
125      * @param vld mapping from vertices to locations (no locations are written if null)
126      * @throws IOException if the graph cannot be saved
127      */
128 	public void save(Graph<V,E> graph, Writer w, Function<V,String> vs, 
129 	        Function<E,Number> nev, Function<V,Point2D> vld) throws IOException
130     {
131         /*
132          * TODO: Changes we might want to make:
133          * - optionally writing out in list form
134          */
135         
136         BufferedWriter writer = new BufferedWriter(w);
137         if (nev == null)
138             nev = new Function<E, Number>() { public Number apply(E e) { return 1; } };
139         writer.write("*Vertices " + graph.getVertexCount());
140         writer.newLine();
141         
142         List<V> id = new ArrayList<V>(graph.getVertices());
143         for (V currentVertex : graph.getVertices())
144         {
145             // convert from 0-based to 1-based index
146             int v_id = id.indexOf(currentVertex) + 1;
147             writer.write(""+v_id); 
148             if (vs != null)
149             { 
150                 String label = vs.apply(currentVertex);
151                 if (label != null)
152                     writer.write (" \"" + label + "\"");
153             }
154             if (vld != null)
155             {
156                 Point2D location = vld.apply(currentVertex);
157                 if (location != null)
158                     writer.write (" " + location.getX() + " " + location.getY() + " 0.0");
159             }
160             writer.newLine();
161         }
162 
163         Collection<E> d_set = new HashSet<E>();
164         Collection<E> u_set = new HashSet<E>();
165 
166         boolean directed = graph instanceof DirectedGraph;
167 
168         boolean undirected = graph instanceof UndirectedGraph;
169 
170         // if it's strictly one or the other, no need to create extra sets
171         if (directed)
172             d_set.addAll(graph.getEdges());
173         if (undirected)
174             u_set.addAll(graph.getEdges());
175         if (!directed && !undirected) // mixed-mode graph
176         {
177         	u_set.addAll(graph.getEdges());
178         	d_set.addAll(graph.getEdges());
179         	for(E e : graph.getEdges()) {
180         		if(graph.getEdgeType(e) == EdgeType.UNDIRECTED) {
181         			d_set.remove(e);
182         		} else {
183         			u_set.remove(e);
184         		}
185         	}
186         }
187 
188         // write out directed edges
189         if (!d_set.isEmpty())
190         {
191             writer.write("*Arcs");
192             writer.newLine();
193         }
194         for (E e : d_set)
195         {
196             int source_id = id.indexOf(graph.getEndpoints(e).getFirst()) + 1;
197             int target_id = id.indexOf(graph.getEndpoints(e).getSecond()) + 1;
198             float weight = nev.apply(e).floatValue();
199             writer.write(source_id + " " + target_id + " " + weight);
200             writer.newLine();
201         }
202 
203         // write out undirected edges
204         if (!u_set.isEmpty())
205         {
206             writer.write("*Edges");
207             writer.newLine();
208         }
209         for (E e : u_set)
210         {
211             Pair<V> endpoints = graph.getEndpoints(e);
212             int v1_id = id.indexOf(endpoints.getFirst()) + 1;
213             int v2_id = id.indexOf(endpoints.getSecond()) + 1;
214             float weight = nev.apply(e).floatValue();
215             writer.write(v1_id + " " + v2_id + " " + weight);
216             writer.newLine();
217         }
218         writer.close();
219     }
220 }