diff --git a/src/java/org/apache/commons/graph/algorithm/path/AllPairsShortestPath.java b/src/java/org/apache/commons/graph/algorithm/path/AllPairsShortestPath.java new file mode 100644 index 0000000..259776c --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/path/AllPairsShortestPath.java @@ -0,0 +1,405 @@ +package org.apache.commons.graph.algorithm.path; + +/* ==================================================================== + * 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 + * . + */ + +/** + * AllPairs solves the All Points Shortest Path problem for a DirectedGraph. (If + * it is weighted, it will do shortest path by weight. Otherwise shortest path + * by jumps.) Uses Floyd's Algorithm. + */ + +import java.util.Set; +import java.util.Map; +import java.util.List; +import java.util.HashMap; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.AbstractList; + +import org.apache.commons.graph.*; +import org.apache.commons.graph.exception.*; + +/** + * Description of the Class + */ +public class AllPairsShortestPath +{ + private int pred[][]; + private double cost[][]; + private Vertex vArray[]; + private DirectedGraph graph; + private Map vertexIndex = new HashMap();// VERTEX X INTEGER + + /** + * Description of the Class + */ + public class EdgeList + extends AbstractList + { + private DirectedGraph graph; + private List vertices; + + /** + * Constructor for the EdgeList object + * + * @param graph + * @param vertices + */ + public EdgeList(DirectedGraph graph, + List vertices) + { + this.graph = graph; + this.vertices = vertices; + } + + /** + * Description of the Method + */ + public int size() + { + return vertices.size() - 1; + } + + /** + * Description of the Method + */ + public Object get(int index) + { + Edge RC = null; + + Vertex source = (Vertex) vertices.get(index); + Vertex target = (Vertex) vertices.get(index + 1); + + Set outboundSet = graph.getOutbound(source); + if (outboundSet == null) + { + return null; + } + + Iterator outbound = outboundSet.iterator(); + while (outbound.hasNext()) + { + RC = (Edge) outbound.next(); + if (graph.getTarget(RC) == target) + { + break; + } + } + + if (graph.getTarget(RC) != target) + { + return null; + } + + return RC; + } + } + + /** + * Description of the Class + */ + public class WPath + implements WeightedPath + { + private Vertex start; + private Vertex finish; + private List vertexList = new ArrayList(); + private DirectedGraph graph; + private double cost; + + /** + * Constructor for the WPath object + * + * @param graph + * @param vArray + * @param pred + * @param start + * @param finish + * @param cost + * @exception GraphException + */ + public WPath(DirectedGraph graph, + Vertex vArray[], int pred[][], + int start, int finish, double cost) + throws GraphException + { + this.start = vArray[start]; + this.finish = vArray[finish]; + this.cost = cost; + this.graph = graph; + + vertexList.addAll(segment(vArray, pred, + start, finish)); + vertexList.add(vArray[finish]); + } + + /** + * Returns a List of Vectors in order. Includes the start, but not the + * finish. + */ + private List segment(Vertex vArray[], int pred[][], + int start, int finish) + throws GraphException + { + int mid = pred[start][finish]; + if (mid == -1) + { + throw new NoPathException("No SubPath Available: " + + vArray[start] + " -> " + + vArray[finish]); + } + List RC = new ArrayList(); + + if (start == finish) + { + return RC; + } + + if (start == mid) + { + RC.add(vArray[start]); + + } + else + { + RC.addAll(segment(vArray, pred, + start, mid)); + RC.add(vArray[mid]); + } + + if (mid == pred[mid][finish]) + { + } + else + { + RC.addAll(segment(vArray, pred, + mid, finish)); + } + return RC; + } + + /** + * Gets the weight attribute of the WPath object + */ + public double getWeight() + { + return cost; + } + + /** + * Gets the vertices attribute of the WPath object + */ + public List getVertices() + { + return vertexList; + } + + /** + * Gets the edges attribute of the WPath object + */ + public List getEdges() + { + return new EdgeList(graph, vertexList); + } + + /** + * Gets the start attribute of the WPath object + */ + public Vertex getStart() + { + return start; + } + + /** + * Gets the end attribute of the WPath object + */ + public Vertex getEnd() + { + return finish; + } + + public int size() { + return vertexList.size(); + } + } + + /** + * Constructor for the AllPairsShortestPath object + * + * @param graph + * @exception NegativeCycleException + */ + public AllPairsShortestPath(DirectedGraph graph) + throws NegativeCycleException + { + update(graph); + } + + + /** + * Description of the Method + */ + private void initIndex(Vertex vArray[]) + { + for (int i = 0; i < vArray.length; i++) + { + vertexIndex.put(vArray[i], new Integer(i)); + } + } + + /** + * Description of the Method + */ + public void update(DirectedGraph graph) + { + this.graph = graph; + + Set vertexSet = graph.getVertices(); + vArray = (Vertex[]) vertexSet.toArray(new Vertex[vertexSet.size()]); + + initIndex(vArray); + + pred = new int[vArray.length][vArray.length]; + cost = new double[vArray.length][vArray.length]; + + for (int i = 0; i < vArray.length; i++) + { + for (int j = 0; j < vArray.length; j++) + { + pred[i][j] = -1; + cost[i][j] = Double.POSITIVE_INFINITY; + } + + // First round values need to be in the matrix. + Iterator edgeSet = graph.getOutbound(vArray[i]).iterator(); + while (edgeSet.hasNext()) + { + Edge e = (Edge) edgeSet.next(); + int j = index(graph.getTarget(e)); + pred[i][j] = i; + if (graph instanceof WeightedGraph) + { + cost[i][j] = ((WeightedGraph) graph).getWeight(e); + } + else + { + cost[i][j] = 1.0; + } + } + + // Cost from any node to itself is 0.0 + cost[i][i] = 0.0; + pred[i][i] = i; + } + + compute(graph, vArray); + + } + + /** + * Description of the Method + */ + private int index(Vertex v) + { + return ((Integer) vertexIndex.get(v)).intValue(); + } + + /** + * Description of the Method + */ + private void compute(DirectedGraph graph, Vertex vArray[]) + throws NegativeCycleException + { + for (int k = 0; k < vArray.length; k++) + {// Mid Point + for (int i = 0; i < vArray.length; i++) + {// Source + for (int j = 0; j < vArray.length; j++) + {// Target + if (cost[i][k] + cost[k][j] < cost[i][j]) + { + if (i == j) + { + throw new NegativeCycleException(); + } + + // It is cheaper to go through K. + cost[i][j] = cost[i][k] + cost[k][j]; + pred[i][j] = k; + } + } + } + } + } + + /** + * Gets the shortestPath attribute of the AllPairsShortestPath object + */ + public WeightedPath getShortestPath(Vertex start, Vertex end) + throws GraphException + { + return new WPath(graph, vArray, pred, + index(start), index(end), + cost[index(start)][index(end)]); + } + + /** + * Determines if a path exists or not. + */ + public boolean hasPath( Vertex start, Vertex end ) + { + return cost[index(start)][index(end)] < Double.POSITIVE_INFINITY; + } +} diff --git a/src/java/org/apache/commons/graph/algorithm/path/AllPaths.java b/src/java/org/apache/commons/graph/algorithm/path/AllPaths.java new file mode 100644 index 0000000..3036979 --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/path/AllPaths.java @@ -0,0 +1,206 @@ +package org.apache.commons.graph.algorithm.path; + +/* ==================================================================== + * 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 i + * 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 + * . + */ + +/** + * AllPaths finds for each pair of vertices, {i, j} the set of + * all potential paths between them. (Unrolling loops by a set + * amount. + */ + +import java.util.Map; +import java.util.Set; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +import org.apache.commons.graph.*; +import org.apache.commons.graph.algorithm.util.*; + +public class AllPaths +{ + private Map allPaths = new HashMap(); // VERTEX PAIR X SET( PATHS ) + + private AllPairsShortestPath apsp = null; + private DirectedGraph graph = null; + + public AllPaths( DirectedGraph graph ) { + this.graph = graph; + try { + apsp = new AllPairsShortestPath( graph ); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public Iterator findPaths( final Vertex i, + final Vertex j ) { + final PathIterator RC = new PathIterator(); + + Runnable run = new Runnable() { + public void run() { + findPaths( RC, i, j, Integer.MAX_VALUE ); + } + }; + Thread thread = new Thread( run ); + + RC.setThread( thread ); + + thread.start(); + + return RC; + } + + public void findPaths( PathListener listener, + Vertex i, Vertex j, + int maxLength ) { + Set workingSet = new HashSet(); + workingSet.add( new PathImpl( i )); + + for (int k = 0; k < maxLength; k++) { + Iterator workingPaths = workingSet.iterator(); + if (!workingPaths.hasNext()) break; + + Set newWorkingSet = new HashSet(); + + while (workingPaths.hasNext()) { + PathImpl workingPath = (PathImpl) workingPaths.next(); + + Iterator outbound = + graph.getOutbound(workingPath.getEnd()).iterator(); + + while (outbound.hasNext()) { + Edge obEdge = (Edge) outbound.next(); + if (apsp.hasPath( graph.getTarget( obEdge ), j)) { + + PathImpl path = + workingPath.append(graph.getTarget(obEdge), + obEdge ); + + + newWorkingSet.add( path ); + + if (path.getEnd() == j) { + listener.notifyPath( path ); + } + } + } + } + + workingSet = newWorkingSet; + } + } + + /** + * getAllPaths will return the set of all possible ways of moving + * from i to j using the directed graph AllPaths was initialized + * with. + * + * @deprecated Use findPaths instead. Doesn't work, but code + * may be useful in the near future. + */ + public Set getAllPaths( Vertex i, Vertex j ) { + Set RC = new HashSet(); + VertexPair key = new VertexPair( i, j ); + + // If we have already started this, return what we + // were doing. (May still be in progress.) + // + // If we haven't started, go ahead and start. . . + if (allPaths.containsKey( key )) { + return (Set) allPaths.get( key ); + } else { + allPaths.put( key, RC ); + } + + Iterator outbounds = graph.getOutbound(i).iterator(); + + while (outbounds.hasNext()) { + Edge outbound = (Edge) outbounds.next(); + if (graph.getTarget( outbound ) == j) { + RC.add( new PathImpl( i, j, outbound )); + } + } + + Iterator ks = graph.getVertices().iterator(); + while (ks.hasNext()) { + Vertex k = (Vertex) ks.next(); + if (k != i && k != j) { + appendPaths( RC, + getAllPaths( i, k ), + getAllPaths( k, j )); + } + } + + allPaths.put( key, RC ); + return RC; + } + + public void appendPaths( Set RC, Set iks, Set kjs ) { + Iterator ikPaths = iks.iterator(); + while (ikPaths.hasNext()) { + PathImpl ik = (PathImpl) ikPaths.next(); + + Iterator kjPaths = kjs.iterator(); + while (kjPaths.hasNext()) { + PathImpl kj = (PathImpl) kjPaths.next(); + RC.add( ik.append( kj )); + } + } + } +} + + + diff --git a/src/java/org/apache/commons/graph/algorithm/path/PathIterator.java b/src/java/org/apache/commons/graph/algorithm/path/PathIterator.java new file mode 100644 index 0000000..676d52c --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/path/PathIterator.java @@ -0,0 +1,71 @@ +package org.apache.commons.graph.algorithm.path; + +import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.NoSuchElementException; + +import org.apache.commons.graph.Path; + +public class PathIterator + implements PathListener, + Iterator +{ + private List queue = new LinkedList(); + private Thread thread = null; + private int highMark = 50; + + /** + * @t is the thread which is generating the paths. + * if this thread is terminated, we assume that + * we have recieved everything. + */ + public PathIterator() { + } + + public void setThread( Thread thread ) { + this.thread = thread; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public void notifyPath( Path path ) { + synchronized (queue) { + try { + if (queue.size() >= highMark) { + queue.wait(); + } + } catch (InterruptedException ex) {} + + queue.add( path ); + queue.notifyAll(); + } + } + + public boolean hasNext() { + synchronized (queue) { + if (queue.size() > 0) return true; + + while ((queue.size() == 0) && + (thread.isAlive())) { + try { + queue.wait(100); + } catch (InterruptedException ex) { } + } + + return queue.size() > 0; + } + } + + public Object next() { + synchronized (queue) { + if (hasNext()) { + return queue.remove( 0 ); + } else { + throw new NoSuchElementException(); + } + } + } +} diff --git a/src/java/org/apache/commons/graph/algorithm/path/PathListener.java b/src/java/org/apache/commons/graph/algorithm/path/PathListener.java new file mode 100644 index 0000000..05b26f6 --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/path/PathListener.java @@ -0,0 +1,69 @@ +package org.apache.commons.graph.algorithm.path; + +/* ==================================================================== + * 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 i + * 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 + * . + */ + +/** + * PathListener + * + * This interface is passed into the AllPaths algorithm, and + * is notified of all qualifing paths. + */ + +import org.apache.commons.graph.Path; + +public interface PathListener +{ + public void notifyPath( Path path ); +} diff --git a/src/java/org/apache/commons/graph/algorithm/search/CostSearch.java b/src/java/org/apache/commons/graph/algorithm/search/CostSearch.java new file mode 100644 index 0000000..e6c7d0e --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/search/CostSearch.java @@ -0,0 +1,291 @@ +package org.apache.commons.graph.algorithm.search; + +/* ==================================================================== + * 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 + * . + */ + +/** + * This is a Cost searching algorithm. It will basically follow edges/paths with + * minimal cost first, and then go to the later costs. + */ + +import java.util.Set; +import java.util.Map; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +import org.apache.commons.graph.*; + +import org.apache.commons.collections.*; + +/** + * Description of the Class + */ +public class CostSearch +{ + /** + * Description of the Class + */ + public class ComparableEdge + implements Edge, Comparable + { + private Edge e; + private double cost; + + /** + * Constructor for the ComparableEdge object + * + * @param e + * @param cost + */ + public ComparableEdge(Edge e, double cost) + { + this.e = e; + this.cost = cost; + } + + /** + * Gets the edge attribute of the ComparableEdge object + */ + public Edge getEdge() + { + return e; + } + + /** + * Gets the cost attribute of the ComparableEdge object + */ + public double getCost() + { + return cost; + } + + /** + * Description of the Method + */ + public int compareTo(Object o) + { + ComparableVertex cv = (ComparableVertex) o; + if (cv.cost > cost) + { + return 1; + } + if (cv.cost == cost) + { + return 0; + } + if (cv.cost < cost) + { + return -1; + } + return 0; + } + } + + /** + * Description of the Class + */ + public class ComparableVertex + implements Vertex, Comparable + { + private Vertex v; + private double cost; + + /** + * Constructor for the ComparableVertex object + * + * @param v + * @param cost + */ + public ComparableVertex(Vertex v, double cost) + { + this.v = v; + this.cost = cost; + } + + /** + * Description of the Method + */ + public int compareTo(Object o) + { + ComparableVertex cv = (ComparableVertex) o; + if (cv.cost > cost) + { + return 1; + } + if (cv.cost == cost) + { + return 0; + } + if (cv.cost < cost) + { + return -1; + } + return 0; + } + + /** + * Gets the vertex attribute of the ComparableVertex object + */ + public Vertex getVertex() + { + return v; + } + } + + private Map colors = new HashMap();// VERTEX X COLOR + private PriorityQueue tasks = null; + + private String WHITE = "white"; + private String BLACK = "black"; + private String GRAY = "gray"; + + /** + * Constructor for the CostSearch object + */ + public CostSearch() + { + tasks = new BinaryHeap(true); + } + + /** + * Constructor for the CostSearch object + * + * @param isMin + */ + public CostSearch(boolean isMin) + { + tasks = new BinaryHeap(isMin); + } + + /** + * Description of the Method + */ + public void visitVertex(WeightedGraph graph, + Vertex vertex, + double cost, + Visitor visitor) + { + colors.remove(vertex); + colors.put(vertex, GRAY); + + visitor.discoverVertex(vertex); + Iterator edges = graph.getEdges(vertex).iterator(); + while (edges.hasNext()) + { + Edge edge = (Edge) edges.next(); + + double edgeCost = graph.getWeight(edge); + ComparableEdge wEdge = + new ComparableEdge(edge, edgeCost + cost); + tasks.insert(wEdge); + } + + visitor.finishVertex(vertex); + colors.remove(vertex); + colors.put(vertex, BLACK); + } + + /** + * Description of the Method + */ + public void visitEdge(WeightedGraph graph, + Edge e, + double cost, + Visitor visitor) + { + visitor.discoverEdge(e); + + Iterator vertices = graph.getVertices(e).iterator(); + while (vertices.hasNext()) + { + Vertex v = (Vertex) vertices.next(); + if (colors.get(v) == WHITE) + { + visitVertex(graph, v, cost, visitor); + } + } + + visitor.finishEdge(e); + } + + + /** + * Description of the Method + */ + public void visit(WeightedGraph graph, + Vertex root, + Visitor visitor) + { + Iterator vertices = graph.getVertices().iterator(); + while (vertices.hasNext()) + { + colors.put(vertices.next(), WHITE); + } + + visitor.discoverGraph(graph); + + visitVertex(graph, root, 0.0, visitor); + + while (!tasks.isEmpty()) + { + ComparableEdge wEdge = (ComparableEdge) tasks.pop(); + visitEdge(graph, wEdge.getEdge(), wEdge.getCost(), visitor); + } + + visitor.finishGraph(graph); + } +} + + diff --git a/src/java/org/apache/commons/graph/algorithm/search/DFS.java b/src/java/org/apache/commons/graph/algorithm/search/DFS.java new file mode 100644 index 0000000..7525db9 --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/search/DFS.java @@ -0,0 +1,168 @@ +package org.apache.commons.graph.algorithm.search; + +/* ==================================================================== + * 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 + * . + */ + +/** + * This class does a Depth First Search. It visits all of the children nodes + * before moving to the siblling nodes. + */ + +import java.util.Set; +import java.util.Map; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.commons.graph.*; + +/** + * Description of the Class + */ +public class DFS +{ + private Map colors = new HashMap();// VERTEX X COLOR + /** + * Description of the Field + */ + public final static String WHITE = "white"; + /** + * Description of the Field + */ + public final static String BLACK = "black"; + /** + * Description of the Field + */ + public final static String GRAY = "gray"; + + /** + * Constructor for the DFS object + */ + public DFS() { } + + /** + * Gets the color attribute of the DFS object + */ + public String getColor(Vertex v) + { + return (String) colors.get(v); + } + + + /** + * Description of the Method + */ + private void visitEdge(DirectedGraph graph, + Edge e, + Visitor visitor) + { + visitor.discoverEdge(e); + + Vertex v = graph.getTarget(e); + + if (colors.get(v) == WHITE) + { + visitVertex(graph, v, visitor); + } + + visitor.finishEdge(e); + } + + /** + * Description of the Method + */ + private void visitVertex(DirectedGraph graph, + Vertex v, + Visitor visitor) + { + colors.remove(v); + colors.put(v, GRAY); + + visitor.discoverVertex(v); + + Iterator edges = graph.getOutbound(v).iterator(); + while (edges.hasNext()) + { + Edge e = (Edge) edges.next(); + visitEdge(graph, e, visitor); + } + + visitor.finishVertex(v); + + colors.remove(v); + colors.put(v, BLACK); + } + + /** + * visit - Visits the graph + */ + public void visit(DirectedGraph graph, + Vertex root, + Visitor visitor) + { + Iterator vertices = graph.getVertices().iterator(); + while (vertices.hasNext()) + { + colors.put(vertices.next(), WHITE); + } + + visitor.discoverGraph(graph); + + visitVertex(graph, root, visitor); + + visitor.finishGraph(graph); + } + +} + diff --git a/src/java/org/apache/commons/graph/algorithm/search/Visitor.java b/src/java/org/apache/commons/graph/algorithm/search/Visitor.java new file mode 100644 index 0000000..a3733c2 --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/search/Visitor.java @@ -0,0 +1,93 @@ +package org.apache.commons.graph.algorithm.search; + +/* ==================================================================== + * 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 org.apache.commons.graph.*; + +/** + * Description of the Interface + */ +public interface Visitor +{ + /** + * Description of the Method + */ + public void discoverGraph(Graph graph); + + /** + * Description of the Method + */ + public void discoverVertex(Vertex vertex); + + /** + * Description of the Method + */ + public void discoverEdge(Edge edge); + + /** + * Description of the Method + */ + public void finishEdge(Edge edge); + + /** + * Description of the Method + */ + public void finishVertex(Vertex vertex); + + /** + * Description of the Method + */ + public void finishGraph(Graph graph); +} diff --git a/src/java/org/apache/commons/graph/algorithm/spanning/MinimumSpanningForest.java b/src/java/org/apache/commons/graph/algorithm/spanning/MinimumSpanningForest.java new file mode 100644 index 0000000..9b235dd --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/spanning/MinimumSpanningForest.java @@ -0,0 +1,151 @@ +package org.apache.commons.graph.algorithm.spanning; + +import org.apache.commons.graph.*; +import org.apache.commons.graph.exception.*; +import org.apache.commons.graph.decorator.*; +import org.apache.commons.graph.domain.basic.*; +import org.apache.commons.graph.algorithm.util.*; + +import org.apache.commons.collections.PriorityQueue; +import org.apache.commons.collections.BinaryHeap; + +import java.util.Map; +import java.util.Set; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Comparator; + +public class MinimumSpanningForest + extends UndirectedGraphImpl + implements UndirectedGraph, + WeightedGraph +{ + private PriorityQueue queue = null; + private Map labels = new HashMap(); // VERTEX X LABEL + private Set chords = new HashSet(); // Edges not in MSF. + + private DDirectedGraph ddg = null; + + public class WeightedEdgeComparator + implements Comparator + { + private WeightedGraph graph = null; + public WeightedEdgeComparator( WeightedGraph graph ) { + this.graph = graph; + } + + public int compare( Object o1, Object o2 ) { + if ((o1 instanceof Edge) && + (o2 instanceof Edge)) { + double val = ( graph.getWeight( (Edge) o1 ) - + graph.getWeight( (Edge) o2 )); + if (val > 0) return 1; + if (val == 0) return 0; + if (val < 0) return -1; + } + + return -1; + } + } + + public MinimumSpanningForest( WeightedGraph graph ) { + calculateMSF( true, graph ); + } + + public MinimumSpanningForest( boolean isMin, WeightedGraph graph ) { + calculateMSF( isMin, graph ); + } + + protected Label findLabel( Vertex v ) { + return (Label) labels.get( v ); + } + + protected boolean connectsLabels( Graph graph, + Edge e ) + { + Label first = null; + Label second = null; + + Iterator vertices = graph.getVertices( e ).iterator(); + if (vertices.hasNext()) { + first = findLabel( (Vertex) vertices.next() ); + } else { return false; } + + if (vertices.hasNext()) { + second = findLabel( (Vertex) vertices.next() ); + } else { return false; } + + if (vertices.hasNext()) { + throw new HyperGraphException("Unable to compute MSF on Hypergraph."); + } + + return !first.getRoot().equals( second.getRoot() ); + } + + protected void addEdge( WeightedGraph graph, + Edge edge ) { + addEdge( edge ); + chords.remove( edge ); + Iterator vertices = graph.getVertices( edge ).iterator(); + Label prime = null; + + if (vertices.hasNext()) { + Vertex p = (Vertex) vertices.next(); + prime = findLabel( p ); + + connect( edge, p ); + } + + while (vertices.hasNext()) { + Vertex v = (Vertex) vertices.next(); + + Label l = findLabel( v ); + l.setRoot( prime ); + + connect( edge, v ); + } + + setWeight( edge, graph.getWeight( edge )); + } + + protected void calculateMSF( boolean isMin, + WeightedGraph graph ) { + + PriorityQueue queue = + new BinaryHeap( isMin, new WeightedEdgeComparator( graph )); + + chords = new HashSet( graph.getEdges() ); + + // Fill the Queue with all the edges. + Iterator edges = graph.getEdges().iterator(); + while (edges.hasNext()) { + queue.insert( edges.next() ); + } + + // Fill the graph we have with all the Vertexes. + Iterator vertices = graph.getVertices().iterator(); + while (vertices.hasNext()) { + Vertex v = (Vertex) vertices.next(); + labels.put( v, new Label() ); + addVertex( v ); + } + + // Bring the edges out in the right order. + while (!queue.isEmpty()) { + Edge e = (Edge) queue.pop(); + + if ( connectsLabels( graph, e )) { + addEdge( graph, e ); + } + } + } + + public Set getChords() { + return chords; + } +} + + + + diff --git a/src/java/org/apache/commons/graph/algorithm/util/Label.java b/src/java/org/apache/commons/graph/algorithm/util/Label.java new file mode 100644 index 0000000..5f9400f --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/util/Label.java @@ -0,0 +1,39 @@ +package org.apache.commons.graph.algorithm.util; + +public class Label +{ + private Label root = null; + + public Label() { + } + + public Label( Label root ) { + this.root = root.getRoot(); + } + + public void setRoot( Label root ) { + if (this.root == null ) { + this.root = root.getRoot(); + } else { + if (root != this.root) { + this.root.setRoot( root.getRoot() ); + this.root = root.getRoot(); + } + } + } + + public Label getRoot() { + if ((root == null) || + (root == this)) { + return this; + } else { + root = root.getRoot(); + return root; + } + } +} + + + + + diff --git a/src/java/org/apache/commons/graph/algorithm/util/PathImpl.java b/src/java/org/apache/commons/graph/algorithm/util/PathImpl.java new file mode 100644 index 0000000..1cdf5a5 --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/util/PathImpl.java @@ -0,0 +1,81 @@ +package org.apache.commons.graph.algorithm.util; + +import java.util.List; +import java.util.ArrayList; + +import org.apache.commons.graph.*; + +public class PathImpl + implements Path +{ + protected List vertexList = new ArrayList(); + protected List edgeList = new ArrayList(); + + public PathImpl( List vertexList, + List edgeList ) { + this.vertexList = vertexList; + this.edgeList = edgeList; + } + + public PathImpl( Vertex start ) { + this.vertexList.add( start ); + } + + public PathImpl( Vertex start, + Vertex end, + Edge edge ) { + vertexList = new ArrayList(); + vertexList.add( start ); + vertexList.add( end ); + + edgeList = new ArrayList(); + edgeList.add( edge ); + } + + public PathImpl append( PathImpl impl ) { + List newVertices = new ArrayList( vertexList ); + newVertices.remove( newVertices.size() - 1 ); // Last should be duplicated + newVertices.addAll( impl.getVertices() ); + + List newEdges = new ArrayList( edgeList ); + newEdges.addAll( impl.getEdges() ); + + return new PathImpl( newVertices, newEdges ); + } + + public PathImpl append( Vertex v, Edge e ) { + List newVertices = new ArrayList( vertexList ); + newVertices.add( v ); + + List newEdges = new ArrayList( edgeList ); + newEdges.add( e ); + + return new PathImpl( newVertices, newEdges ); + } + + public Vertex getStart() { + return (Vertex) vertexList.get( 0 ); + } + + public Vertex getEnd() { + return (Vertex) vertexList.get( vertexList.size() - 1 ); + } + + public List getVertices() { + return vertexList; + } + + public List getEdges() { + return edgeList; + } + + public int size() { + return vertexList.size(); + } + + public String toString() { + return vertexList.toString(); + } +} + + diff --git a/src/java/org/apache/commons/graph/algorithm/util/VertexPair.java b/src/java/org/apache/commons/graph/algorithm/util/VertexPair.java new file mode 100644 index 0000000..826bdb9 --- /dev/null +++ b/src/java/org/apache/commons/graph/algorithm/util/VertexPair.java @@ -0,0 +1,88 @@ +package org.apache.commons.graph.algorithm.util; + +/* ==================================================================== + * 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 + * . + */ + + +/** + * VertexPair + * + * This is a tuple of two vertices which is capable + * of storing things in a Hashtable. + */ + +import org.apache.commons.graph.*; + +public class VertexPair { + public Vertex i = null; + public Vertex j = null; + + public VertexPair( Vertex i, Vertex j ) { + this.i = i; + this.j = j; + } + + public boolean equals( Object o ) { + VertexPair vp = (VertexPair) o; + return ( this.i == vp.i && + this.j == vp.j ); + } + + public int hashCode() { + return (17 * i.hashCode()) + j.hashCode(); + } +} + + +