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 }