// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea // Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology // Distributed under the terms of the GNU Lesser General Public License (LGPL): http://www.gnu.org/licenses/ package graphtea.library.algorithms.util; import graphtea.library.BaseEdge; import graphtea.library.BaseGraph; import graphtea.library.BaseVertex; import graphtea.library.algorithms.Algorithm; import graphtea.library.algorithms.AutomatedAlgorithm; import graphtea.library.algorithms.traversal.DepthFirstSearch; import graphtea.library.event.MessageEvent; import graphtea.library.event.handlers.PreWorkPostWorkHandler; import graphtea.library.event.typedef.BaseGraphRequest; import graphtea.library.exceptions.InvalidGraphException; /** * Checks whether a graph is acyclic. * Usage: * <p/> * graphtea.library.algorithms.util.AcyclicChecker.isGraphAcyclic(graph); * <p/> * The above statement returns true if the graph is acyclic. The graph * parameter is your graph object. Note that there is no need to explicitly * parameterize the generic method isGraphAcyclic. Types are automatically * deduced from the supplied graph object with no java unchecked convertion warning. * * @author Omid Aladini */ public class AcyclicChecker extends Algorithm implements AutomatedAlgorithm { /** * Checks whether the current graph is acyclic. * * @return True if graph is acyclic and false otherwise. * @throws InvalidGraphException The invalid graph */ public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> boolean isGraphAcyclic(BaseGraph<VertexType, EdgeType> graph) { if (!graph.isDirected()) { int n = graph.getVerticesCount(); int m = graph.getEdgesCount(); int components = 0; if (m >= n) return false; for (VertexType v : graph) { if (v.getMark()) continue; ++components; new DepthFirstSearch<>(graph) .doSearch(v, new AcyclicCheckerHandler<>(graph), false); } return (n == m + components); } else { return true; } } /** * Prework-PostWork Handler for checking whether the graph is acyclic. * * @author Omid Aladini * @param <VertexType> Graph's vertices type. * @param <EdgeType> Graph's edges type. */ private static class AcyclicCheckerHandler<VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> implements PreWorkPostWorkHandler<VertexType> { BaseGraph<VertexType, EdgeType> graph; public AcyclicCheckerHandler(BaseGraph<VertexType, EdgeType> graph) { this.graph = graph; } public boolean doPreWork(VertexType fromVertex, VertexType toVertex) { toVertex.setMark(true); return false; } public boolean doPostWork(VertexType returnFrom, VertexType returnTo) { return false; } } public void doAlgorithm() { BaseGraphRequest gr = new BaseGraphRequest(); dispatchEvent(gr); BaseGraph<BaseVertex, BaseEdge<BaseVertex>> graph = gr.getGraph(); if (isGraphAcyclic(graph)) { dispatchEvent(new MessageEvent("Graph is acyclic.")); } else dispatchEvent(new MessageEvent("Graph is NOT acyclic.")); } }