1
2
3
4
5
6
7
8
9
10
11
12 package edu.uci.ics.jung.graph;
13
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Map;
19 import java.util.Set;
20
21 import org.apache.commons.collections15.Factory;
22
23 import edu.uci.ics.jung.graph.util.EdgeType;
24 import edu.uci.ics.jung.graph.util.Pair;
25
26
27
28
29
30 @SuppressWarnings("serial")
31 public class SparseMultigraph<V,E>
32 extends AbstractGraph<V,E>
33 implements MultiGraph<V,E> {
34
35
36
37
38
39
40 public static <V,E> Factory<Graph<V,E>> getFactory() {
41 return new Factory<Graph<V,E>> () {
42 public Graph<V,E> create() {
43 return new SparseMultigraph<V,E>();
44 }
45 };
46 }
47
48
49
50 protected Map<V, Pair<Set<E>>> vertices;
51 protected Map<E, Pair<V>> edges;
52 protected Set<E> directedEdges;
53
54
55
56
57 public SparseMultigraph()
58 {
59 vertices = new HashMap<V, Pair<Set<E>>>();
60 edges = new HashMap<E, Pair<V>>();
61 directedEdges = new HashSet<E>();
62 }
63
64 public Collection<E> getEdges()
65 {
66 return Collections.unmodifiableCollection(edges.keySet());
67 }
68
69 public Collection<V> getVertices()
70 {
71 return Collections.unmodifiableCollection(vertices.keySet());
72 }
73
74 public boolean containsVertex(V vertex) {
75 return vertices.keySet().contains(vertex);
76 }
77
78 public boolean containsEdge(E edge) {
79 return edges.keySet().contains(edge);
80 }
81
82 protected Collection<E> getIncoming_internal(V vertex)
83 {
84 return vertices.get(vertex).getFirst();
85 }
86
87 protected Collection<E> getOutgoing_internal(V vertex)
88 {
89 return vertices.get(vertex).getSecond();
90 }
91
92 public boolean addVertex(V vertex) {
93 if(vertex == null) {
94 throw new IllegalArgumentException("vertex may not be null");
95 }
96 if (!vertices.containsKey(vertex)) {
97 vertices.put(vertex, new Pair<Set<E>>(new HashSet<E>(), new HashSet<E>()));
98 return true;
99 } else {
100 return false;
101 }
102 }
103
104 public boolean removeVertex(V vertex) {
105 if (!containsVertex(vertex))
106 return false;
107
108
109 Set<E> incident = new HashSet<E>(getIncoming_internal(vertex));
110 incident.addAll(getOutgoing_internal(vertex));
111
112 for (E edge : incident)
113 removeEdge(edge);
114
115 vertices.remove(vertex);
116
117 return true;
118 }
119
120 @Override
121 public boolean addEdge(E edge, Pair<? extends V> endpoints, EdgeType edgeType) {
122
123 Pair<V> new_endpoints = getValidatedEndpoints(edge, endpoints);
124 if (new_endpoints == null)
125 return false;
126
127 V v1 = new_endpoints.getFirst();
128 V v2 = new_endpoints.getSecond();
129
130 if (!vertices.containsKey(v1))
131 this.addVertex(v1);
132
133 if (!vertices.containsKey(v2))
134 this.addVertex(v2);
135
136
137 vertices.get(v1).getSecond().add(edge);
138 vertices.get(v2).getFirst().add(edge);
139 edges.put(edge, new_endpoints);
140 if(edgeType == EdgeType.DIRECTED) {
141 directedEdges.add(edge);
142 } else {
143 vertices.get(v1).getFirst().add(edge);
144 vertices.get(v2).getSecond().add(edge);
145 }
146 return true;
147 }
148
149 public boolean removeEdge(E edge)
150 {
151 if (!containsEdge(edge)) {
152 return false;
153 }
154
155 Pair<V> endpoints = getEndpoints(edge);
156 V v1 = endpoints.getFirst();
157 V v2 = endpoints.getSecond();
158
159
160 vertices.get(v1).getSecond().remove(edge);
161 vertices.get(v2).getFirst().remove(edge);
162
163 if(directedEdges.remove(edge) == false) {
164
165
166 vertices.get(v2).getSecond().remove(edge);
167 vertices.get(v1).getFirst().remove(edge);
168 }
169 edges.remove(edge);
170 return true;
171 }
172
173 public Collection<E> getInEdges(V vertex)
174 {
175 if (!containsVertex(vertex))
176 return null;
177 return Collections.unmodifiableCollection(vertices.get(vertex).getFirst());
178 }
179
180 public Collection<E> getOutEdges(V vertex)
181 {
182 if (!containsVertex(vertex))
183 return null;
184 return Collections.unmodifiableCollection(vertices.get(vertex).getSecond());
185 }
186
187
188 public Collection<V> getPredecessors(V vertex)
189 {
190 if (!containsVertex(vertex))
191 return null;
192
193 Set<V> preds = new HashSet<V>();
194 for (E edge : getIncoming_internal(vertex)) {
195 if(getEdgeType(edge) == EdgeType.DIRECTED) {
196 preds.add(this.getSource(edge));
197 } else {
198 preds.add(getOpposite(vertex, edge));
199 }
200 }
201 return Collections.unmodifiableCollection(preds);
202 }
203
204
205 public Collection<V> getSuccessors(V vertex)
206 {
207 if (!containsVertex(vertex))
208 return null;
209 Set<V> succs = new HashSet<V>();
210 for (E edge : getOutgoing_internal(vertex)) {
211 if(getEdgeType(edge) == EdgeType.DIRECTED) {
212 succs.add(this.getDest(edge));
213 } else {
214 succs.add(getOpposite(vertex, edge));
215 }
216 }
217 return Collections.unmodifiableCollection(succs);
218 }
219
220 public Collection<V> getNeighbors(V vertex)
221 {
222 if (!containsVertex(vertex))
223 return null;
224 Collection<V> out = new HashSet<V>();
225 out.addAll(this.getPredecessors(vertex));
226 out.addAll(this.getSuccessors(vertex));
227 return out;
228 }
229
230 public Collection<E> getIncidentEdges(V vertex)
231 {
232 if (!containsVertex(vertex))
233 return null;
234 Collection<E> out = new HashSet<E>();
235 out.addAll(this.getInEdges(vertex));
236 out.addAll(this.getOutEdges(vertex));
237 return out;
238 }
239
240 @Override
241 public E findEdge(V v1, V v2)
242 {
243 if (!containsVertex(v1) || !containsVertex(v2))
244 return null;
245 for (E edge : getOutgoing_internal(v1))
246 if (this.getOpposite(v1, edge).equals(v2))
247 return edge;
248
249 return null;
250 }
251
252 public Pair<V> getEndpoints(E edge)
253 {
254 return edges.get(edge);
255 }
256
257 public V getSource(E edge) {
258 if(directedEdges.contains(edge)) {
259 return this.getEndpoints(edge).getFirst();
260 }
261 return null;
262 }
263
264 public V getDest(E edge) {
265 if(directedEdges.contains(edge)) {
266 return this.getEndpoints(edge).getSecond();
267 }
268 return null;
269 }
270
271 public boolean isSource(V vertex, E edge) {
272 if (!containsEdge(edge) || !containsVertex(vertex))
273 return false;
274 return getSource(edge).equals(vertex);
275 }
276
277 public boolean isDest(V vertex, E edge) {
278 if (!containsEdge(edge) || !containsVertex(vertex))
279 return false;
280 return getDest(edge).equals(vertex);
281 }
282
283 public EdgeType getEdgeType(E edge) {
284 return directedEdges.contains(edge) ?
285 EdgeType.DIRECTED :
286 EdgeType.UNDIRECTED;
287 }
288
289 @SuppressWarnings("unchecked")
290 public Collection<E> getEdges(EdgeType edgeType) {
291 if(edgeType == EdgeType.DIRECTED) {
292 return Collections.unmodifiableSet(this.directedEdges);
293 } else if(edgeType == EdgeType.UNDIRECTED) {
294 Collection<E> edges = new HashSet<E>(getEdges());
295 edges.removeAll(directedEdges);
296 return edges;
297 } else {
298 return Collections.EMPTY_SET;
299 }
300
301 }
302
303 public int getEdgeCount() {
304 return edges.keySet().size();
305 }
306
307 public int getVertexCount() {
308 return vertices.keySet().size();
309 }
310
311 public int getEdgeCount(EdgeType edge_type)
312 {
313 return getEdges(edge_type).size();
314 }
315
316 public EdgeType getDefaultEdgeType()
317 {
318 return EdgeType.UNDIRECTED;
319 }
320 }