package org.apache.commons.graph; /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Commons" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * "Commons", nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ import java.util.*; import org.apache.commons.graph.algo.*; import org.apache.commons.graph.exception.*; /** * Collection of graph algorithms such as transposeGraph. * * @version $Id: GraphAlgorithms.java,v 1.3 2002/01/16 20:38:28 jvanzyl Exp $ * @author M. Dahm */ public abstract class GraphAlgorithms { /** * Compute the inverse of a graph, i.e. with all edges reverted */ public static final Graph transposeGraph(DirectedGraph g) { DirectedGraph graph = new DirectedGraph(); for(Iterator i=g.getVertices().iterator(); i.hasNext();) graph.addVertex((Vertex)i.next()); for(Iterator i=g.getEdges().iterator(); i.hasNext();) { Edge f = (Edge)i.next(); graph.addEdge(g.getTarget(f), g.getSource(f), f); } return graph; } /** * Get a Minimum Spanning Forest from a graph. */ public static MinimumSpanningForest getMinimumSpanningForest( Graph g ) { return MinimumSpanningForest.getMSF( g ); } public static MinimumSpanningForest getMinimumSpanningForest( Graph g, boolean isMin ) { return MinimumSpanningForest.getMSF( g, isMin ); } public static MinimumSpanningForest getMSF( Graph g ) { return MinimumSpanningForest.getMSF( g ); } public static MinimumSpanningForest getMSF( Graph g, boolean isMin ) { return MinimumSpanningForest.getMSF( g, isMin ); } /** * Perform a Topological Sort on a Directed * graph. * * Should throw BackEdgeException if it is not a DAG. */ public static List topoSort( DirectedGraph g ) { return Sort.getInstance().topologicalSort( g ); } public static List topologicalSort( DirectedGraph g ) { return Sort.getInstance().topologicalSort( g ); } /** * Identify all backedges in a directed graph * when starting from a particular vertex. */ public static Set getBackEdges( DirectedGraph g, Vertex start ) throws BackEdgeException { return BackEdges.getInstance().getBackEdges( g, start ); } /** * Test whether the SCC g is a loop. * * @param super_g super graph containing the subset of vertices * @param g subset of super_g (g must be SCC of super_g) */ public static final boolean isLoop(Graph super_g, Graph loop) { return findLoopEntry(super_g, loop) != null; } /** * Test whether the SCC g is a loop. * * @param super_g super graph containing the subset of vertices * @param g subset of super_g (g must be SCC of super_g) * @return root node of loop, i.e. the entry point, or null if this is no loop */ public static final Vertex findLoopEntry(Graph super_g, Graph loop) { switch(loop.getNoVertices()) { case 0: return null; // certainly not a loop case 1: // singleton must point to itself, i.e. be a self-loop Vertex v = loop.getVertexArray()[0]; Vertex[] edges = loop.getVertexArray(v); for(int i=0; i < edges.length; i++) if(edges[i] == v) return v; return null; } /* Make sure that the root node is the only entry point to the * SCC, i.e. there is no way from a node v \in (super_g \ g) into * a node in g except via the root node. * * So we have to find the root node first ... */ Vertex root = null; Vertex[] vertices = super_g.getVertexArray(); for(int i=0; i < vertices.length; i++) { Vertex v = vertices[i]; if(loop.contains(v)) // v is in the SCC, no check needed continue; Vertex[] edges = super_g.getVertexArray(v); // All nodes reachable from v for(int j=0; j < edges.length; j++) { Vertex u = edges[j]; if(loop.contains(u)) if(root == null) root = u; else return null; // Can't be a loop then, i.e. has more than one root node } } return root; // Has loop a root node at all !? } }