/* * JFLAP - Formal Languages and Automata Package * * * Susan H. Rodger * Computer Science Department * Duke University * August 27, 2009 * Copyright (c) 2002-2009 * All rights reserved. * JFLAP is open source software. Please see the LICENSE for terms. * */ package automata.graph.layout; import java.util.ArrayList; import automata.graph.Graph; /** * Class that orders vertices assigned to it one-dimensionally. The order of the vertices is changed as vertices * are added in order to minimize the number of edges between non-adjacent vertices. * * @author Chris Morgan */ public class VertexChain{ /** * List of vertices in the chain. */ ArrayList vertices; /** * The graph from which edge information is processed. */ Graph graph; /** * Constructor. * * @param g - The graph from which edge information is processed. */ public VertexChain(Graph g) { vertices = new ArrayList(); graph = g; } /** * Returns the object held in vertices in the given index. * * @return the object in the given index. */ public Object get(int index) { return vertices.get(index); } /** * Returns the ArrayList containing the vertices in the VertexChain. * * @return the vertices in the chain. */ public ArrayList getVertices() { return vertices; } /** * Returns the number of elements stored in this chain. * * @return the number of elements stored in this chain. */ public int size() { return vertices.size(); } /** * Returns whether the given vertex has an edge to a VertexChain member. * * @return whether the given vertex has an edge to a VertexChain member. */ public boolean isEdgeToChainMember(Object vertex) { if (getDegreeInChain(vertex) > 0) return true; return false; } /** * Returns the degree of a given vertex with respect to current vertices in the VertexChain. * The vertex does not need to be in the graph, but is not counted toward the degree if it is. * * @return the given vertex's degree with respect to the VertexChain. */ public int getDegreeInChain(Object vertex) { int count = 0; for (int i=0; iVertexChain. The subchain is removed * from its present position in the VertexChain and placed next to a given vertex. * * @param destIndex * the index of the vertex in the VertexChain next to which the subchain will be placed. * @param matchingIndex * either the start or the end value. Determines the vertex that is * closest to the destIndex's vertex in the new VertexChain ordering. Often * is the index of a vertex linking to the destIndex's vertex. * @param start * the index in the VertexChain representing the start of the subchain. * @param end * the index in the VertexChain representing the end of the subchain. * @param shuffleDirection * if true, the subchain will be placed to the right of the destIndex's vertex. * If false, to the left. */ public void orientSubChain(int destIndex, int matchingIndex, int start, int end, boolean shuffleDirection) { Object[] toMove = new Object[end-start+1]; int dest, chainSize; chainSize = size(); if (destIndex > 0 && destIndex >= start) dest = destIndex+start-end-1; else dest = destIndex; for (int i=start; i<=end; i++) toMove[i-start] = get(i); for (int i=0; iVertexChain, adjusting the VertexChain's order to * minimize the number of edges between non-adjacent vertices. * * @param vertex the vertex to be added */ public void addVertex(Object vertex) { int destIndex, subChainBound; for (int i=0; ii+2 && graph.hasEdge(get(subChainBound-1), get(subChainBound))) subChainBound--; orientSubChain(destIndex, j, subChainBound, j, (destIndex==i+1)); } return; } return; } //Added at end if there are no adjacencies. vertices.add(vertex); } /** * If there is an edge between a vertex in first and a vertex in last, then the two * vertices are moved in their respective chains to their common border, with subchains in tow behind them. This * only happens for the first matching pair, and other matching pairs have no effect. The vertex in * first will be moved to the end of vertices in its VertexChain, and the vertex in * last will be moved to the beginning of vertices in its VertexChain. * * @param first * the first VertexChain to search * @param next * the second VertexChain to search * @param graph * the graph used to search for edges */ public static void alignTwoChains(VertexChain first, VertexChain next, Graph graph) { int fstart, fend, nstart, nend; for (int j=0; j 0 && graph.hasEdge(first.get(fstart), first.get(fstart-1))) fstart--; while (fend < first.size()-1 && graph.hasEdge(first.get(fend), first.get(fend+1))) fend++; while (nstart > 0 && graph.hasEdge(next.get(nstart), next.get(nstart-1))) nstart--; while (nend < next.size()-1 && graph.hasEdge(next.get(nend), next.get(nend+1))) nend++; first.orientSubChain(first.size()-1, fstart+fend-j, fstart, fend, true); next.orientSubChain(0, nstart+nend-k, nstart, nend, false); return; } } }