1
2
3
4
5
6
7
8
9
10 package edu.uci.ics.jung.algorithms.layout;
11
12 import java.awt.geom.Point2D;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.ConcurrentModificationException;
16 import java.util.List;
17
18 import com.google.common.cache.CacheBuilder;
19 import com.google.common.cache.CacheLoader;
20 import com.google.common.cache.LoadingCache;
21
22 import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer;
23 import edu.uci.ics.jung.algorithms.util.IterativeContext;
24 import edu.uci.ics.jung.graph.Graph;
25
26
27
28
29
30
31
32 public class ISOMLayout<V, E> extends AbstractLayout<V,E> implements IterativeContext {
33
34 protected LoadingCache<V, ISOMVertexData> isomVertexData =
35 CacheBuilder.newBuilder().build(new CacheLoader<V, ISOMVertexData>() {
36 public ISOMVertexData load(V vertex) {
37 return new ISOMVertexData();
38 }
39 });
40
41 private int maxEpoch;
42 private int epoch;
43
44 private int radiusConstantTime;
45 private int radius;
46 private int minRadius;
47
48 private double adaption;
49 private double initialAdaption;
50 private double minAdaption;
51
52 protected GraphElementAccessor<V,E> elementAccessor =
53 new RadiusGraphElementAccessor<V,E>();
54
55 private double coolingFactor;
56
57 private List<V> queue = new ArrayList<V>();
58 private String status = null;
59
60
61
62
63 public String getStatus() {
64 return status;
65 }
66
67 public ISOMLayout(Graph<V,E> g) {
68 super(g);
69 }
70
71 public void initialize() {
72
73 setInitializer(new RandomLocationTransformer<V>(getSize()));
74 maxEpoch = 2000;
75 epoch = 1;
76
77 radiusConstantTime = 100;
78 radius = 5;
79 minRadius = 1;
80
81 initialAdaption = 90.0D / 100.0D;
82 adaption = initialAdaption;
83 minAdaption = 0;
84
85
86 coolingFactor = 2;
87
88
89
90
91
92
93 }
94
95
96
97
98
99 public void step() {
100 status = "epoch: " + epoch + "; ";
101 if (epoch < maxEpoch) {
102 adjust();
103 updateParameters();
104 status += " status: running";
105 } else {
106 status += "adaption: " + adaption + "; ";
107 status += "status: done";
108
109 }
110 }
111
112 private synchronized void adjust() {
113
114 Point2D tempXYD = new Point2D.Double();
115
116
117 tempXYD.setLocation(10 + Math.random() * getSize().getWidth(),
118 10 + Math.random() * getSize().getHeight());
119
120
121 V winner = elementAccessor.getVertex(this, tempXYD.getX(), tempXYD.getY());
122
123 while(true) {
124 try {
125 for(V v : getGraph().getVertices()) {
126 ISOMVertexData ivd = getISOMVertexData(v);
127 ivd.distance = 0;
128 ivd.visited = false;
129 }
130 break;
131 } catch(ConcurrentModificationException cme) {}
132 }
133 adjustVertex(winner, tempXYD);
134 }
135
136 private synchronized void updateParameters() {
137 epoch++;
138 double factor = Math.exp(-1 * coolingFactor * (1.0 * epoch / maxEpoch));
139 adaption = Math.max(minAdaption, factor * initialAdaption);
140
141
142 if ((radius > minRadius) && (epoch % radiusConstantTime == 0)) {
143 radius--;
144 }
145 }
146
147 private synchronized void adjustVertex(V v, Point2D tempXYD) {
148 queue.clear();
149 ISOMVertexData ivd = getISOMVertexData(v);
150 ivd.distance = 0;
151 ivd.visited = true;
152 queue.add(v);
153 V current;
154
155 while (!queue.isEmpty()) {
156 current = queue.remove(0);
157 ISOMVertexData currData = getISOMVertexData(current);
158 Point2D currXYData = apply(current);
159
160 double dx = tempXYD.getX() - currXYData.getX();
161 double dy = tempXYD.getY() - currXYData.getY();
162 double factor = adaption / Math.pow(2, currData.distance);
163
164 currXYData.setLocation(currXYData.getX()+(factor*dx), currXYData.getY()+(factor*dy));
165
166 if (currData.distance < radius) {
167 Collection<V> s = getGraph().getNeighbors(current);
168 while(true) {
169 try {
170 for(V child : s) {
171 ISOMVertexData childData = getISOMVertexData(child);
172 if (childData != null && !childData.visited) {
173 childData.visited = true;
174 childData.distance = currData.distance + 1;
175 queue.add(child);
176 }
177 }
178 break;
179 } catch(ConcurrentModificationException cme) {}
180 }
181 }
182 }
183 }
184
185 protected ISOMVertexData getISOMVertexData(V v) {
186 return isomVertexData.getUnchecked(v);
187 }
188
189
190
191
192
193 public boolean isIncremental() {
194 return true;
195 }
196
197
198
199
200
201
202
203
204 public boolean done() {
205 return epoch >= maxEpoch;
206 }
207
208 protected static class ISOMVertexData {
209 int distance;
210 boolean visited;
211
212 protected ISOMVertexData() {
213 distance = 0;
214 visited = false;
215 }
216 }
217
218
219
220
221
222 public void reset() {
223 epoch = 0;
224 }
225 }