KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > classycle > graph > StrongComponent


1 /*
2  * Copyright (c) 2003-2006, Franz-Josef Elmer, All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * - Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
15  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */

25 package classycle.graph;
26
27 import java.util.ArrayList JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Vector JavaDoc;
30
31 /**
32  * A strong component is a subgraph of a directed graph where every two
33  * vertices are mutually reachable.
34  *
35  * @author Franz-Josef Elmer
36  */

37 public class StrongComponent extends Vertex {
38   private static class GeometryAttributes implements GraphAttributes {
39     private int _girth;
40     private int _radius;
41     private int _diameter;
42     private ArrayList JavaDoc _centerVertices = new ArrayList JavaDoc();
43     private int[] _eccentricities;
44     private int[] _maximumFragmentSizes;
45     private int _bestFragmentSize;
46     private ArrayList JavaDoc _bestFragmenters = new ArrayList JavaDoc();
47
48     public GeometryAttributes() {}
49
50     public int getGirth() {
51       return _girth;
52     }
53
54     void setGirth(int girth) {
55       _girth = girth;
56     }
57
58     public int getRadius() {
59       return _radius;
60     }
61
62     public int getDiameter() {
63       return _diameter;
64     }
65
66     public int getBestFragmentSize() {
67       return _bestFragmentSize;
68     }
69
70     public Vertex[] getCenterVertices() {
71       return (Vertex[]) _centerVertices.toArray(
72                                   new Vertex[_centerVertices.size()]);
73     }
74
75     void addVertex(Vertex vertex) {
76       _centerVertices.add(vertex);
77     }
78     
79     public Vertex[] getBestFragmenters() {
80       return (Vertex[]) _bestFragmenters.toArray(
81                                   new Vertex[_bestFragmenters.size()]);
82     }
83
84     void addFragmenter(Vertex vertex) {
85       _bestFragmenters.add(vertex);
86     }
87     
88     public int[] getEccentricities() {
89       return _eccentricities;
90     }
91     
92     void setEccentricities(int[] eccentricities) {
93       _eccentricities = eccentricities;
94
95       // Calculate radius and diameter
96
_radius = Integer.MAX_VALUE;
97       _diameter = 0;
98       for (int i = 0; i < eccentricities.length; i++) {
99         _radius = Math.min(_radius, eccentricities[i]);
100         _diameter = Math.max(_diameter, eccentricities[i]);
101       }
102     }
103     
104     public int[] getMaximumFragmentSizes() {
105       return _maximumFragmentSizes;
106     }
107     
108     void setMaximumFragmentSizes(int[] maximumFragmentSizes) {
109       _maximumFragmentSizes = maximumFragmentSizes;
110       
111       _bestFragmentSize = Integer.MAX_VALUE;
112       for (int i = 0; i < maximumFragmentSizes.length; i++) {
113         _bestFragmentSize = Math.min(_bestFragmentSize,
114                                      maximumFragmentSizes[i]);
115       }
116     }
117     
118     public int compareTo(Object JavaDoc object)
119     {
120       int result = 1;
121       if (object instanceof GeometryAttributes && _bestFragmenters.size() > 0)
122       {
123         ArrayList JavaDoc list = ((GeometryAttributes) object)._bestFragmenters;
124         if (list.size() > 0)
125         {
126           Attributes attributes
127               = ((Vertex) _bestFragmenters.get(0)).getAttributes();
128           Attributes objectAttributes = ((Vertex) list.get(0)).getAttributes();
129           result = attributes.compareTo(objectAttributes);
130         }
131       }
132       return result;
133     }
134
135   }
136
137   private final Vector JavaDoc _vertices = new Vector JavaDoc();
138   private boolean _active;
139   private int _longestWalk;
140
141   /**
142    * Default constructor. The {@link Attributes} of a strong component will
143    * a <tt>null</tt> pointer.
144    */

145   public StrongComponent() {
146     super(new GeometryAttributes());
147   }
148
149   /** Returns the number of vertices building this strong component. */
150   public int getNumberOfVertices() {
151     return _vertices.size();
152   }
153
154   /** Returns the vertex of the specified index. */
155   public AtomicVertex getVertex(int index) {
156     return (AtomicVertex) _vertices.elementAt(index);
157   }
158
159   /**
160    * Adds the specified vertex to this strong component. Note, that added
161    * vertices are inserted at index 0 of the list of vertices.
162    */

163   public void addVertex(AtomicVertex vertex) {
164     _vertices.insertElementAt(vertex, 0);
165   }
166
167   /**
168    * Calculates all graph properties of this component.
169    * These properties can be obtained from <tt>getAttributes</tt> casted as
170    * {@link GraphAttributes}.
171    */

172   public void calculateAttributes() {
173     HashMap JavaDoc indexMap = calculateIndexMap();
174     int[][] distances = calculateDistances(indexMap);
175
176     // Calculate girth and eccentricity
177
GeometryAttributes attributes = (GeometryAttributes) getAttributes();
178     int girth = Integer.MAX_VALUE;
179     int[] eccentricities = new int[distances.length];
180     for (int i = 0; i < distances.length; i++) {
181       girth = Math.min(girth, distances[i][i]);
182       eccentricities[i] = 0;
183       for (int j = 0; j < distances.length; j++) {
184         if (i != j) {
185           eccentricities[i] = Math.max(eccentricities[i], distances[i][j]);
186         }
187       }
188     }
189     attributes.setEccentricities(eccentricities);
190     attributes.setGirth(girth);
191     attributes.setMaximumFragmentSizes(
192                             calculateMaximumFragmentSizes(indexMap));
193
194     // Obtain center vertices and best fragmenters
195
for (int i = 0, r = attributes.getRadius(),
196              s = attributes.getBestFragmentSize(); i < distances.length; i++) {
197       if (eccentricities[i] == r) {
198         attributes.addVertex(getVertex(i));
199       }
200       if (attributes.getMaximumFragmentSizes()[i] == s) {
201         attributes.addFragmenter(getVertex(i));
202       }
203     }
204     
205   }
206   
207   private int[][] calculateDistances(HashMap JavaDoc indexMap) {
208     // Calculate the adjacency matrix
209
int n = getNumberOfVertices();
210     int[][] distances = new int[n][n];
211     for (int i = 0; i < n; i++) {
212       int[] row = distances[i];
213       AtomicVertex vertex = getVertex(i);
214       for (int j = 0; j < n; j++) {
215         row[j] = Integer.MAX_VALUE / 2;
216       }
217       for (int j = 0, m = vertex.getNumberOfOutgoingArcs(); j < m; j++) {
218         Integer JavaDoc index = (Integer JavaDoc) indexMap.get(vertex.getHeadVertex(j));
219         if (index != null) {
220           row[index.intValue()] = 1;
221         }
222       }
223     }
224
225     // Floyd-Warshall algorithm for the distances
226
for (int k = 0; k < n; k++) {
227       for (int i = 0; i < n; i++) {
228         for (int j = 0; j < n; j++) {
229           if (distances[i][k] + distances[k][j] < distances[i][j]) {
230             distances[i][j] = distances[i][k] + distances[k][j];
231           }
232         }
233       }
234     }
235     
236     return distances;
237   }
238
239   private HashMap JavaDoc calculateIndexMap() {
240     HashMap JavaDoc result = new HashMap JavaDoc();
241     for (int i = 0, n = getNumberOfVertices(); i < n; i++) {
242       result.put(getVertex(i), new Integer JavaDoc(i));
243     }
244     return result;
245   }
246   
247   private int[] calculateMaximumFragmentSizes(HashMap JavaDoc indexMap) {
248     // clone graph defining this strong component
249
AtomicVertex[] graph = new AtomicVertex[getNumberOfVertices()];
250     for (int i = 0; i < graph.length; i++) {
251       graph[i] = new AtomicVertex(null);
252     }
253     for (int i = 0; i < graph.length; i++) {
254       AtomicVertex vertex = getVertex(i);
255       for (int j = 0, n = vertex.getNumberOfOutgoingArcs(); j < n; j++) {
256         Integer JavaDoc index = (Integer JavaDoc) indexMap.get(vertex.getHeadVertex(j));
257         if (index != null) {
258           graph[i].addOutgoingArcTo(graph[index.intValue()]);
259         }
260       }
261     }
262     
263     StrongComponentProcessor processor = new StrongComponentProcessor(false);
264     int[] maximumFragmentSizes = new int[getNumberOfVertices()];
265     for (int i = 0; i < maximumFragmentSizes.length; i++) {
266       graph[i].setDefaultValueOfGraphVertexFlag(false);
267       processor.deepSearchFirst(graph);
268       StrongComponent[] fragments = processor.getStrongComponents();
269       maximumFragmentSizes[i] = 0;
270       for (int j = 0; j < fragments.length; j++) {
271         maximumFragmentSizes[i] = Math.max(maximumFragmentSizes[i],
272                                            fragments[j].getNumberOfVertices());
273       }
274       graph[i].setDefaultValueOfGraphVertexFlag(true);
275     }
276     return maximumFragmentSizes;
277   }
278
279   /**
280    * Reset this component. Calls reset of the superclass. Sets the activity
281    * flag to false and the longest walk to -1.
282    */

283   public void reset() {
284     super.reset();
285     _active = false;
286     _longestWalk = -1;
287   }
288
289   public boolean isActive() {
290     return _active;
291   }
292
293   public void setActive(boolean active) {
294     _active = active;
295   }
296
297   public int getLongestWalk() {
298     return _longestWalk;
299   }
300
301   public void setLongestWalk(int longestWalk) {
302     _longestWalk = longestWalk;
303   }
304
305   public String JavaDoc toString() {
306     StringBuffer JavaDoc result = new StringBuffer JavaDoc("Strong component with ");
307     int n = getNumberOfVertices();
308     result.append(n).append(n > 1 ? " vertices." : " vertex.");
309     result.append(" Longest walk: ").append(getLongestWalk());
310     for (int i = 0; i < n; i++) {
311       result.append("\n ").append(getVertex(i));
312     }
313     return new String JavaDoc(result);
314   }
315 } //class
Popular Tags