1 package edu.uci.ics.jung.algorithms.shortestpath;
2
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.Map;
7 import java.util.Set;
8
9 import org.apache.commons.collections15.Factory;
10 import org.apache.commons.collections15.functors.ConstantTransformer;
11 import org.apache.commons.collections15.map.LazyMap;
12
13 import edu.uci.ics.jung.graph.Forest;
14 import edu.uci.ics.jung.graph.Graph;
15 import edu.uci.ics.jung.graph.util.EdgeType;
16 import edu.uci.ics.jung.graph.util.Pair;
17
18
19
20
21
22
23
24
25
26
27 public class MinimumSpanningForest<V,E> {
28
29 protected Graph<V,E> graph;
30 protected Forest<V,E> forest;
31 protected Map<E,Double> weights;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public MinimumSpanningForest(Graph<V, E> graph, Factory<Forest<V,E>> factory,
48 V root, Map<E, Double> weights) {
49 this(graph, factory.create(), root, weights);
50 }
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public MinimumSpanningForest(Graph<V, E> graph, Forest<V,E> forest,
66 V root, Map<E, Double> weights) {
67
68 if(forest.getVertexCount() != 0) {
69 throw new IllegalArgumentException("Supplied Forest must be empty");
70 }
71 this.graph = graph;
72 this.forest = forest;
73 if(weights != null) {
74 this.weights = weights;
75 }
76 Set<E> unfinishedEdges = new HashSet<E>(graph.getEdges());
77 if(graph.getVertices().contains(root)) {
78 this.forest.addVertex(root);
79 }
80 updateForest(forest.getVertices(), unfinishedEdges);
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94
95 @SuppressWarnings("unchecked")
96 public MinimumSpanningForest(Graph<V, E> graph, Forest<V,E> forest,
97 V root) {
98
99 if(forest.getVertexCount() != 0) {
100 throw new IllegalArgumentException("Supplied Forest must be empty");
101 }
102 this.graph = graph;
103 this.forest = forest;
104 this.weights = LazyMap.decorate(new HashMap<E,Double>(),
105 new ConstantTransformer(1.0));
106 Set<E> unfinishedEdges = new HashSet<E>(graph.getEdges());
107 if(graph.getVertices().contains(root)) {
108 this.forest.addVertex(root);
109 }
110 updateForest(forest.getVertices(), unfinishedEdges);
111 }
112
113
114
115
116 public Forest<V,E> getForest() {
117 return forest;
118 }
119
120 protected void updateForest(Collection<V> tv, Collection<E> unfinishedEdges) {
121 double minCost = Double.MAX_VALUE;
122 E nextEdge = null;
123 V nextVertex = null;
124 V currentVertex = null;
125 for(E e : unfinishedEdges) {
126
127 if(forest.getEdges().contains(e)) continue;
128
129
130 Pair<V> endpoints = graph.getEndpoints(e);
131 V first = endpoints.getFirst();
132 V second = endpoints.getSecond();
133 if(tv.contains(first) == true && tv.contains(second) == false) {
134 if(weights.get(e) < minCost) {
135 minCost = weights.get(e);
136 nextEdge = e;
137 currentVertex = first;
138 nextVertex = second;
139 }
140 }
141 if(graph.getEdgeType(e) == EdgeType.UNDIRECTED &&
142 tv.contains(second) == true && tv.contains(first) == false) {
143 if(weights.get(e) < minCost) {
144 minCost = weights.get(e);
145 nextEdge = e;
146 currentVertex = second;
147 nextVertex = first;
148 }
149 }
150 }
151
152 if(nextVertex != null && nextEdge != null) {
153 unfinishedEdges.remove(nextEdge);
154 forest.addEdge(nextEdge, currentVertex, nextVertex);
155 updateForest(forest.getVertices(), unfinishedEdges);
156 }
157 Collection<V> leftovers = new HashSet<V>(graph.getVertices());
158 leftovers.removeAll(forest.getVertices());
159 if(leftovers.size() > 0) {
160 V anotherRoot = leftovers.iterator().next();
161 forest.addVertex(anotherRoot);
162 updateForest(forest.getVertices(), unfinishedEdges);
163 }
164 }
165 }