/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.graph; import java.util.ArrayList; import java.util.HashMap; import org.geotools.graph.build.GraphBuilder; import org.geotools.graph.build.GraphGenerator; import org.geotools.graph.build.opt.OptDirectedGraphBuilder; import org.geotools.graph.build.opt.OptGraphBuilder; import org.geotools.graph.structure.Edge; import org.geotools.graph.structure.GraphVisitor; import org.geotools.graph.structure.Graphable; import org.geotools.graph.structure.Node; import org.geotools.graph.structure.opt.OptDirectedNode; import org.geotools.graph.structure.opt.OptNode; import org.geotools.graph.util.FIFOQueue; public class GraphTestUtil { /** * Builds a graph with no bifurcations made up of a specified number of nodes. * Nodes are numbered from 0 to (# of nodes - 1).<BR> * <BR> * O----O----O--...--O----O----O * * @param builder Builder to use to construct graph. * @param nnodes Number of nodes in graph. * * @return 2 element object array containing references to the end points of * the graph. (The nodes of degree 1 at the end of the graph. */ public static Node[] buildNoBifurcations(GraphBuilder builder, int nnodes) { Node n1 = builder.buildNode(); builder.addNode(n1); n1.setID(0); Node n2 = null; Edge e = null; Node first = n1; for (int i = 1; i < nnodes; i++) { n2 = builder.buildNode(); builder.addNode(n2); n2.setID(i); e = builder.buildEdge(n1,n2); builder.addEdge(e); e.setID(i-1); n1 = n2; } return(new Node[]{first,n1}); } public static Node[] buildNoBifurcations(GraphGenerator gen, int nnodes) { String[] nodes = new String[nnodes]; Node[] ends = new Node[2]; for (int i = 0; i < nnodes; i++) { nodes[i] = new String(String.valueOf(i)); if (i > 0) { Edge e = (Edge)gen.add(new String[]{nodes[i-1], nodes[i]}); if (i == 1) ends[0] = e.getNodeA(); if (i == nnodes-1) ends[1] = e.getNodeB(); } } return(ends); } public static Object[] buildNoBifurcations( OptGraphBuilder builder, int nnodes ) { //use maps for id since optimized graphable doesn't use id's HashMap node2id = new HashMap(); HashMap edge2id = new HashMap(); OptNode n1 = (OptNode)builder.buildNode(); n1.setDegree(1); builder.addNode(n1); node2id.put(n1, new Integer(0)); OptNode n2 = null; Edge e = null; OptNode first = n1; for (int i = 1; i < nnodes; i++) { n2 = (OptNode)builder.buildNode(); if (i < nnodes-1) n2.setDegree(2); else n2.setDegree(1); builder.addNode(n2); node2id.put(n2, new Integer(i)); e = builder.buildEdge(n1,n2); builder.addEdge(e); edge2id.put(e, new Integer(i-1)); n1 = n2; } return(new Object[]{first,n1, node2id, edge2id}); } public static Object[] buildNoBifurcations( OptDirectedGraphBuilder builder, int nnodes ) { //use maps for id since optimized graphable doesn't use id's HashMap node2id = new HashMap(); HashMap edge2id = new HashMap(); OptDirectedNode n1 = (OptDirectedNode)builder.buildNode(); n1.setInDegree(0); n1.setOutDegree(1); builder.addNode(n1); node2id.put(n1, new Integer(0)); OptDirectedNode n2 = null; Edge e = null; OptDirectedNode first = n1; for (int i = 1; i < nnodes; i++) { n2 = (OptDirectedNode)builder.buildNode(); if (i < nnodes-1) { n2.setInDegree(1); n2.setOutDegree(1); } else { n2.setInDegree(1); n2.setOutDegree(0); } builder.addNode(n2); node2id.put(n2, new Integer(i)); e = builder.buildEdge(n1,n2); builder.addEdge(e); edge2id.put(e, new Integer(i-1)); n1 = n2; } return(new Object[]{first,n1, node2id, edge2id}); } public static Node[] buildSingleBifurcation( final GraphBuilder builder, int nnodes, final int bifurcation ) { Node[] ends = buildNoBifurcations(builder, nnodes-1); final Node n = builder.buildNode(); final ArrayList bif = new ArrayList(); builder.getGraph().visitNodes( new GraphVisitor() { public int visit(Graphable component) { if (component.getID() == bifurcation) { bif.add(component); } return(0); } } ); Edge e = builder.buildEdge(n, (Node) bif.get(0)); builder.addNode(n); builder.addEdge(e); Node[] bifends = new Node[]{ends[0], ends[1], (Node)bif.get(0)}; return(bifends); } /** * Creates a balanced binary tree consisting of a specefied number of levels. * Each node created contains a string representing the nodes location in * the tree.<BR> * <BR> * locstring(root) = "0"; * locstring(node) = locstring(parent) + ".0" (if left child); * locstring(node) = locstring(parent) + ".1" (if right child); * * @param builder Builder to construct graph with * @param levels Number of levels in the tree. * * @return A 2 element object array. * 0 = root node * 1 = map of locstring to node */ public static Object[] buildPerfectBinaryTree( GraphBuilder builder, int levels ) { HashMap id2node = new HashMap(); //a balanced binary tree Node root = builder.buildNode(); root.setObject(new String("0")); id2node.put(root.getObject(), root); builder.addNode(root); FIFOQueue queue = new FIFOQueue((int)Math.pow(2, levels+1)); queue.enq(root); //build a complete binary tree // number of nodes = 2^(n+1) - 1 int level = 0; while (level < levels) { int nnodes = (int)Math.pow(2, level); for (int i = 0; i < nnodes; i++) { Node n = (Node)queue.deq(); Node ln = builder.buildNode(); ln.setObject(n.getObject() + ".0"); id2node.put(ln.getObject(), ln); Node rn = builder.buildNode(); rn.setObject(n.getObject() + ".1"); id2node.put(rn.getObject(), rn); Edge le = builder.buildEdge(n, ln); Edge re = builder.buildEdge(n, rn); builder.addNode(ln); builder.addNode(rn); builder.addEdge(le); builder.addEdge(re); queue.enq(ln); queue.enq(rn); } level++; } return(new Object[]{root, id2node}); } public static Object[] buildPerfectBinaryTree( OptGraphBuilder builder, int levels ) { OptNode root = (OptNode)builder.buildNode(); root.setDegree(2); builder.addNode(root); FIFOQueue queue = new FIFOQueue((int)Math.pow(2, levels+1)); queue.enq(root); //build a complete binary tree // number of nodes = 2^(n+1) - 1 int level = 0; while (level < levels) { int nnodes = (int)Math.pow(2, level); for (int i = 0; i < nnodes; i++) { Node n = (Node)queue.deq(); OptNode ln = (OptNode) builder.buildNode(); if (level < levels-1) ln.setDegree(3); else ln.setDegree(1); OptNode rn = (OptNode) builder.buildNode(); if (level < levels-1) rn.setDegree(3); else rn.setDegree(1); Edge le = builder.buildEdge(n, ln); Edge re = builder.buildEdge(n, rn); builder.addNode(ln); builder.addNode(rn); builder.addEdge(le); builder.addEdge(re); queue.enq(ln); queue.enq(rn); } level++; } return(new Object[]{root}); } public static Object[] buildPerfectBinaryTree( OptDirectedGraphBuilder builder, int levels ) { OptDirectedNode root = (OptDirectedNode)builder.buildNode(); root.setInDegree(0); root.setOutDegree(2); builder.addNode(root); FIFOQueue queue = new FIFOQueue((int)Math.pow(2, levels+1)); queue.enq(root); //build a complete binary tree // number of nodes = 2^(n+1) - 1 int level = 0; while (level < levels) { int nnodes = (int)Math.pow(2, level); for (int i = 0; i < nnodes; i++) { Node n = (Node)queue.deq(); OptDirectedNode ln = (OptDirectedNode) builder.buildNode(); if (level < levels-1) { ln.setInDegree(1); ln.setOutDegree(2); } else { ln.setInDegree(1); ln.setOutDegree(0); } OptDirectedNode rn = (OptDirectedNode) builder.buildNode(); if (level < levels-1) { rn.setInDegree(1); rn.setOutDegree(2); } else { rn.setInDegree(1); rn.setOutDegree(0); } Edge le = builder.buildEdge(n, ln); Edge re = builder.buildEdge(n, rn); builder.addNode(ln); builder.addNode(rn); builder.addEdge(le); builder.addEdge(re); queue.enq(ln); queue.enq(rn); } level++; } return(new Object[]{root}); } public static Node[] buildCircular(GraphBuilder builder, int nnodes) { //build a graph with no bifurcations then join the first and last verticies Node[] ends = buildNoBifurcations(builder, nnodes); Edge e = builder.buildEdge(ends[1], ends[0]); builder.addEdge(e); return(ends); } public static Node[] buildCircular(GraphGenerator gen, int nnodes) { Node[] ends = buildNoBifurcations(gen, nnodes); gen.add(new Object[]{"0", String.valueOf(nnodes-1)}); return(ends); } }