001    // GraphLab Project: http://graphlab.sharif.edu
002    // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
003    // Distributed under the terms of the GNU Lesser General Public License (LGPL): http://www.gnu.org/licenses/
004    
005    /*
006     * BreadthFirstSearch.java
007     *
008     * Created on November 21, 2004, 12:58 AM
009     */
010    
011    package graphlab.library.algorithms.traversal;
012    
013    import graphlab.library.BaseEdge;
014    import graphlab.library.BaseGraph;
015    import graphlab.library.BaseVertex;
016    import graphlab.library.algorithms.Algorithm;
017    import graphlab.library.algorithms.AutomatedAlgorithm;
018    import graphlab.library.algorithms.util.EventUtils;
019    import graphlab.library.event.GraphRequest;
020    import graphlab.library.event.PreWorkEvent;
021    import graphlab.library.event.VertexRequest;
022    import graphlab.library.event.handlers.PreWorkHandler;
023    import graphlab.library.exceptions.InvalidVertexException;
024    
025    import java.util.LinkedList;
026    
027    /**
028     * Description here.
029     *
030     * @author Omid Aladini
031     */
032    public class BreadthFirstSearch<VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>>
033            extends Algorithm implements AutomatedAlgorithm {
034        private BaseGraph<VertexType, EdgeType> graph;
035    
036        public BreadthFirstSearch(BaseGraph<VertexType, EdgeType> graph) {
037            this.graph = graph;
038        }
039    
040        public BreadthFirstSearch() {
041            this.graph = null;
042        }
043    
044        public boolean doSearch(VertexType vertex, PreWorkHandler<VertexType> handler)
045                throws InvalidVertexException {
046            //int vertexId = vertex.getId();
047    
048            for (VertexType v : graph)
049                v.setMark(false);
050    
051            vertex.setMark(true);
052            LinkedList<VertexType> queue = new LinkedList<VertexType>();
053            LinkedList<VertexType> roots = new LinkedList<VertexType>();
054            queue.offer(vertex);
055            roots.offer(vertex);
056            try {
057                while (queue.size() != 0) {
058                    VertexType index = queue.poll();
059                    VertexType root = roots.poll();
060    
061                    if (handler != null)
062                        if (handler.doPreWork(root, index))
063                            return true;
064    
065                    dispatchEvent(new PreWorkEvent<VertexType, EdgeType>(root, index, graph));
066                    EventUtils.algorithmStep(this, "explore: " + index.getId());
067    
068    
069                    for (VertexType i : graph) {
070                        if (graph.isEdge(index, i) && !i.getMark()) {
071                            i.setMark(true);
072                            EventUtils.algorithmStep(this, "visit: " + i.getId());
073                            queue.offer(i);
074                            roots.offer(index);
075                        }
076    
077                    }
078                }
079            } catch (Exception e) {
080                throw new RuntimeException(e);
081            }
082            return false;
083        }
084    
085        public void doAlgorithm() {
086            GraphRequest<VertexType, EdgeType> gr = new GraphRequest<VertexType, EdgeType>();
087            dispatchEvent(gr);
088            this.graph = gr.getGraph();
089            VertexRequest<VertexType, EdgeType> vr = new VertexRequest<VertexType, EdgeType>(graph, "Please choose a vertex for the BFS algorithm.");
090            dispatchEvent(vr);
091            this.doSearch(vr.getVertex(), null);
092        }
093    }