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 package graphlab.library.algorithms.util; 006 007 import graphlab.library.BaseEdge; 008 import graphlab.library.BaseGraph; 009 import graphlab.library.BaseVertex; 010 import graphlab.library.algorithms.Algorithm; 011 import graphlab.library.algorithms.AutomatedAlgorithm; 012 import graphlab.library.algorithms.traversal.DepthFirstSearch; 013 import graphlab.library.event.MessageEvent; 014 import graphlab.library.event.handlers.PreWorkPostWorkHandler; 015 import graphlab.library.event.typedef.BaseGraphRequest; 016 import graphlab.library.exceptions.InvalidGraphException; 017 018 /** 019 * Checks whether a graph is acyclic. 020 * Usage: 021 * <p/> 022 * graphlab.library.algorithms.util.AcyclicChecker.isGraphAcyclic(graph); 023 * <p/> 024 * The above statement returns true if the graph is acyclic. The graph 025 * parameter is your graph object. Note that there is no need to explicitly 026 * parameterize the generic method isGraphAcyclic. Types are automatically 027 * deduced from the supplied graph object with no java unchecked convertion warning. 028 * 029 * @author Omid Aladini 030 */ 031 public class AcyclicChecker extends Algorithm implements AutomatedAlgorithm { 032 /** 033 * Checks whether the current graph is acyclic. 034 * 035 * @return True if graph is acyclic and false otherwise. 036 * @throws InvalidGraphException 037 */ 038 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 039 boolean isGraphAcyclic(BaseGraph<VertexType, EdgeType> graph) { 040 if (!graph.isDirected()) { 041 int n = graph.getVerticesCount(); 042 int m = graph.getEdgesCount(); 043 int components = 0; 044 045 if (m >= n) 046 return false; 047 048 for (VertexType v : graph) { 049 if (v.getMark()) 050 continue; 051 052 ++components; 053 054 new DepthFirstSearch<VertexType, EdgeType>(graph) 055 .doSearch(v, new AcyclicCheckerHandler<VertexType, EdgeType>(graph), false); 056 } 057 058 return (n == m + components); 059 } else { 060 return true; 061 062 063 } 064 } 065 066 /** 067 * Prework-PostWork Handler for checking whether the graph is acyclic. 068 * 069 * @author Omid Aladini 070 * @param <VertexType> Graph's vertices type. 071 * @param <EdgeType> Graph's edges type. 072 */ 073 private static class AcyclicCheckerHandler<VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 074 implements PreWorkPostWorkHandler<VertexType> { 075 BaseGraph<VertexType, EdgeType> graph; 076 077 public AcyclicCheckerHandler(BaseGraph<VertexType, EdgeType> graph) { 078 this.graph = graph; 079 } 080 081 public boolean doPreWork(VertexType fromVertex, VertexType toVertex) { 082 toVertex.setMark(true); 083 return false; 084 } 085 086 public boolean doPostWork(VertexType returnFrom, VertexType returnTo) { 087 return false; 088 } 089 } 090 091 public void doAlgorithm() { 092 BaseGraphRequest gr = new BaseGraphRequest(); 093 dispatchEvent(gr); 094 BaseGraph<BaseVertex, BaseEdge<BaseVertex>> graph = gr.getGraph(); 095 096 if (isGraphAcyclic(graph)) { 097 dispatchEvent(new MessageEvent("Graph is acyclic.")); 098 } else 099 dispatchEvent(new MessageEvent("Graph is NOT acyclic.")); 100 101 } 102 103 }