net.maizegenetics.util.GraphUtils Maven / Gradle / Ivy
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.maizegenetics.util;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;
/**
* Functions used for Graph traversal and analysis
* @author Eli Rodgers-Melnick
*/
public final class GraphUtils {
/**
* Produces edges in a depth-first search starting at source and labeled
* -1,0,1 for forward, reverse, and nontree (direction type). Based on
* http://www.ics.uci.edu/~eppstein/PADS/DFS.py by D. Eppstein, July, 2004
* @param G A graph
* @param source The source node of the graph
* @return A tuple of an arraylist containing the edges and an ArrayList containing the
* direction types
*/
public static Tuple>, ArrayList> dfsLabeledEdges(Graph G, T source) {
Set visited = new HashSet();
ArrayList> edges = new ArrayList();
ArrayList directions = new ArrayList();
// Add source reference
edges.add(new Tuple(source,source));
directions.add((byte)1);
visited.add(source);
// Instantiate stack
Stack>> stack = new Stack();
stack.push(new Tuple(source, G.neighbors(source).iterator()));
while (!stack.empty()) {
Tuple> toVisit = stack.peek();
// Check for child
if(toVisit.y.hasNext()) {
T child = toVisit.y.next();
// Check if child already visited
if (visited.contains(child)) {
// This is a nontree type direction. Do not add child to stack
edges.add(new Tuple(toVisit.x, child));
directions.add((byte)0);
} else {
// This is a forward type direction. Add child to stack after
// adding edge to return edges
edges.add(new Tuple(toVisit.x, child));
directions.add((byte)1);
stack.push(new Tuple(child, G.neighbors(child).iterator()));
// Add child to visited
visited.add(child);
}
} else {
// Remove from top of stack
stack.pop();
// If stack not empty, put in a direction reversal
if (!stack.empty()) {
Tuple> nextVisit = stack.peek();
edges.add(new Tuple(nextVisit.x, toVisit.x));
directions.add((byte)-1);
}
}
}
// Put in reversal for source node
edges.add(new Tuple(source, source));
directions.add((byte)-1);
return new Tuple(edges, directions);
}
/**
* Produces nodes in a depth-first search pre-ordering starting at source (i.e. listing node
* starting with the source node)
* @param The class of the node
* @param G A graph
* @param source The source node of the graph
* @return An ArrayList with a depth-first search pre-ordering starting from source
*/
public static ArrayList dfsPreorderNodes(Graph G, T source) {
Tuple>, ArrayList> dfs = dfsLabeledEdges(G, source);
ArrayList pre = new ArrayList();
// Go through labeled edges, adding all forward traversals target nodes
for (int i = 0; i < dfs.x.size(); i++) {
if (dfs.y.get(i) == 1) {
pre.add(dfs.x.get(i).y);
}
}
return pre;
}
/**
* Produces nodes in a depth-first search post-ordering starting at source (i.e. listing node
* starting with the last node and headed toward source)
* @param The class of the node
* @param G A graph
* @param source The source node of the graph
* @return An ArrayList with a depth-first search post-ordering starting from source
*/
public static ArrayList dfsPostorderNodes(Graph G, T source) {
Tuple>, ArrayList> dfs = dfsLabeledEdges(G, source);
ArrayList pre = new ArrayList();
// Go through labeled edges, adding all reverse traversals target nodes
for (int i = 0; i < dfs.x.size(); i++) {
if (dfs.y.get(i) == -1) {
pre.add(dfs.x.get(i).y);
}
}
return pre;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy