net.maizegenetics.util.GraphUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tassel Show documentation
Show all versions of tassel Show documentation
TASSEL is a software package to evaluate traits associations, evolutionary patterns, and linkage
disequilibrium.
The newest version!
/*
* 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;
}
}