001    /*
002     *  www.ti.bfh.ch
003     *
004     *  Copyright 2007, Berne University of Applied Sciences, 
005     *  School of Engineering and Information Technology
006     *  and individual contributors as indicated by the @authors tag.
007     *
008     *  This is free software; you can redistribute it and/or modify it under the terms of the 
009     *  GNU Lesser General Public License as published by the Free Software Foundation; 
010     *  either version 3 of the License, or (at your option) any later version.
011     *
012     *  This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
013     *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
014     *  See the GNU Lesser General Public License for more details.
015     *
016     *  You should have received a copy of the GNU Lesser General Public License along with this software; 
017     *  if not, see <http://www.gnu.org/licenses/>.
018     *
019     */
020    package ch.bfh.algo.example;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.Map;
024    
025    import ch.bfh.algo.Direction;
026    import ch.bfh.algo.Graph;
027    import ch.bfh.algo.Position;
028    import ch.bfh.algo.Sequence;
029    import ch.bfh.algo.graph.DefaultGraph;
030    import ch.bfh.algo.graph.DefaultGraphFactory;
031    import ch.bfh.algo.graph.Vertex;
032    import ch.bfh.algo.sequence.LinkedSequence;
033    
034    
035    
036    
037    /**
038     * The class <code>GraphExample3</code> contains an example of the
039     * <code>ch.bfh.algo.Graph</code> interface, using the Factory Pattern
040     * to have specialized Vertices.
041     * 
042     * This example contains the creation of one graph containing 10
043     * vertices and 12 edges. The vertices have two new properties visited
044     * which is used durring the algorithm and
045     * <code>connectedComponentNumber</code> which contains the number of
046     * the connencted component containing this vertex. They are
047     * implemented using another class and the Factory Pattern to create
048     * new instances without changing anything in the graph classes.
049     *
050     * @author <a href="mailto:">Emmanuel Benoist</a>
051     * @version 1.0
052     */
053    public class GraphExample3{
054    
055            private class DecoratedVertex extends Vertex<Integer,String>{
056    
057                // We add two properties to this vertex,
058                //
059                // First we have the visited boolean which indicates if this node
060                // has already been inserted in the buffer.
061                boolean visited;
062    
063                // The second property is a return property to indicate to which
064                // connected component the vertex belong to.
065                int connectedComponentNumber;
066    
067                /**
068                 * Get the Visited value.
069                 * @return the Visited value.
070                 */
071                public boolean isVisited() {
072                    return visited;
073                }
074    
075                /**
076                 * Set the Visited value.
077                 * @param newVisited The new Visited value.
078                 */
079                public void setVisited(boolean newVisited) {
080                    this.visited = newVisited;
081                }
082    
083                /**
084                 * Get the ConnectedComponentNumber value.
085                 * @return the ConnectedComponentNumber value.
086                 */
087                public int getConnectedComponentNumber() {
088                    return connectedComponentNumber;
089                }
090    
091                /**
092                 * Set the ConnectedComponentNumber value.
093                 * @param newConnectedComponentNumber The new ConnectedComponentNumber value.
094                 */
095                public void setConnectedComponentNumber(int newConnectedComponentNumber) {
096                    this.connectedComponentNumber = newConnectedComponentNumber;
097                }
098    
099                public String toString(){
100                    return element().toString()+"("+connectedComponentNumber+")";
101                    
102                }
103                
104            }
105    
106            private class DecoratedGraphFactory extends DefaultGraphFactory<Integer,String>{
107                    
108                public Vertex<Integer,String> createVertex(){
109                    return new DecoratedVertex();
110                }
111                    
112                public Vertex<Integer,String> castVertex(Position<?> p){
113                    return (Vertex<Integer,String>) p;
114                }
115            }
116    
117    
118            private class GraphCopier{
119    
120                Map<Position<String>,Position<String>> vertices;
121    
122    
123                /**
124                 * Creates a new <code>GraphCopier</code> instance.
125                 *
126                 */
127                public GraphCopier(){
128                    vertices = new HashMap<Position<String>,Position<String>>();
129                }
130    
131                /**
132                 * Get the MappingVertices value.
133                 * @return the MappingVertices value.
134                 */
135                public Map<Position<String>,Position<String>> getVertices() {
136                    return vertices;
137                }
138    
139                /**
140                 * Set the MappingVertices value.
141                 * @param newVertices The new MappingVertices value.
142                 */
143                public void setVertices(Map<Position<String>,Position<String>> newMappingVertices) {
144                    this.vertices = newMappingVertices;
145                }
146    
147    
148                public Graph<Integer,String> copy(Graph<Integer,String> g){
149                    //Graph<E,V> gRes = new DefaultGraph<Integer,String>(g.factory());
150                    Graph<Integer,String> gRes = new DefaultGraph<Integer,String>(new DecoratedGraphFactory());
151                    for(Position<String> v : g.vertices()){
152                        if(v!=null){
153                            vertices.put(v , gRes.insertVertex(v.element()));
154                        }
155                    }
156                    for(Position<Integer> e : g.edges(Direction.DIRECTED)){
157                        Position<String> origin ,destination;
158                        origin = g.origin(e);
159                        destination = g.destination(e);
160                        Position<Integer> edge = gRes.insertEdge(e.element());
161                        gRes.setOrigin(edge,vertices.get(origin));
162                        gRes.setDestination(edge,vertices.get(destination));
163                        gRes.setDirected(edge);
164                    }
165                    return gRes;
166                }
167                
168                public List<Position<String>> reverseList(List<Position<String>> lVertices){
169                    Sequence<Position<String>> seq = new LinkedSequence<Position<String>>();
170                    for(Position<String> vertexG1 : lVertices){
171                        Position<String> vertexG2 = vertices.get(vertexG1);
172                        //seq.insertFirst(vertexG2);
173                        if(seq.isEmpty()){
174                            seq.add(vertexG2);
175                        }
176                        else{
177                            seq.insertBefore(seq.first(),vertexG2);
178                            //seq.insertAfter(seq.last(),vertexG2);
179                        }
180                    }
181                    return seq;
182                }
183    
184    
185            }
186    
187    
188    
189    
190        /**
191         * The <code>dfsTraversal</code> is an example of the possible
192         * implementation of a Depth First Search traversal of a
193         * <code>Graph</code>. In this case, we use the
194         * <code>DecoratedVertex</code> to store inside each vertex if it
195         * has been visited.
196         *
197         * @return a <code>Sequence</code> value
198         */
199        public static Sequence<Position<String>> dfsTraversal(Graph<Integer,String> g, List<Position<String>> vertices){
200            Sequence<Position<String>> buffer = new LinkedSequence<Position<String>>();
201            Sequence<Position<String>> result = new LinkedSequence<Position<String>>();
202    
203            // ccNumber represents the number of the current Connected Component.
204            int ccNumber = 0;
205            for(Position<String> v1 : vertices){
206                DecoratedVertex v = (DecoratedVertex) v1;
207                if(!v.isVisited()){
208                    ccNumber++;
209                    buffer.add(v);
210                    v.setVisited(true);
211                    while(! buffer.isEmpty()){
212                        Position<Position<String>> pLast= buffer.last();
213                        v = (DecoratedVertex)buffer.element(pLast);
214                        buffer.delete(pLast);
215                        result.add(v);
216                        v.setConnectedComponentNumber(ccNumber);
217                        for(Position<String> v2 : g.adjacentVertices(v,Direction.OUT)){
218                            DecoratedVertex vv = (DecoratedVertex) v2;
219                            if(vv !=null && !vv.isVisited() ){
220                                vv.setVisited(true);
221                                buffer.add(vv);
222                            }
223                        }
224                    }
225                }
226                
227            }
228            return result;
229        }
230    
231    
232        public static void reverseAllEdges(Graph<Integer,String> g){
233            for(Position<Integer> e : g.edges(Direction.DIRECTED)){
234                g.reverse(e);
235            }
236        }
237    
238        /**
239         * The <code>constructDirectedGraph</code> method is used to
240         * initialize a default directed <code>Graph</code>.
241         *
242         * The returned graph contains 10 vertices and 12 directed edges. 
243         *
244         * @return a <code>Graph</code> value
245         */
246        public Graph<Integer,String> constructDirectedGraph(){
247        boolean directed=true;
248            Graph<Integer,String> g = 
249                new DefaultGraph<Integer,String>(new DecoratedGraphFactory(),directed);
250            Position<String> vertA = g.insertVertex("A");
251            Position<String> vertB = g.insertVertex("B");
252            Position<String> vertI = g.insertVertex("I");
253            Position<String> vertJ = g.insertVertex("J");
254            Position<String> vertC = g.insertVertex("C");
255            Position<String> vertH = g.insertVertex("H");
256            Position<String> vertD = g.insertVertex("D");
257            Position<String> vertE = g.insertVertex("E");
258            Position<String> vertF = g.insertVertex("F");
259            Position<String> vertG = g.insertVertex("G");
260    
261            g.insertEdge(0,vertA,vertE);
262            g.insertEdge(0,vertE,vertD);
263            g.insertEdge(0,vertC,vertE);
264            g.insertEdge(0,vertC,vertD);
265            g.insertEdge(0,vertB,vertC);
266            g.insertEdge(0,vertB,vertA);
267            g.insertEdge(0,vertA,vertF);
268            g.insertEdge(0,vertF,vertB);
269            g.insertEdge(0,vertG,vertH);
270            g.insertEdge(0,vertH,vertI);
271            g.insertEdge(0,vertJ,vertH);
272            g.insertEdge(0,vertI,vertJ);
273    
274            return g;
275        }
276    
277    
278        public void run(){
279            Graph<Integer,String> g = constructDirectedGraph();
280            Sequence<Position<String>> dfs = dfsTraversal(g,g.vertices());
281            System.out.println("DFS= " + dfs);
282            GraphCopier gc = new GraphCopier();
283            Graph<Integer,String> g2 = gc.copy(g);
284            System.out.println("VerticesMap="+gc.getVertices());
285            reverseAllEdges(g2);
286            //Sequence<Position<String>> dfs2 = dfsTraversal(g2,g2.vertices());
287            List<Position<String>> reverseDfs = gc.reverseList(dfs);
288            System.out.println("Reversed DFS= " + reverseDfs);
289    
290            Sequence<Position<String>> dfs2 = dfsTraversal(g2,reverseDfs);
291            System.out.println("DFS2= " + dfs2);
292    
293        }
294    
295    
296        public static void main(String[] args){
297            System.out.println("***************");
298            System.out.println("Example of use of a Directed Graphs with a decorated vertex.");
299            System.out.println("Computes for each Vertex its Strongly Connected Component (SCC-number):");
300            new GraphExample3().run();
301            System.out.println("***************");
302            System.out.println("");
303    
304        }
305    
306    
307    }