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