![JAR search and dependency download from the Maven repository](/logo.png)
edu.berkeley.nlp.syntax.TreePathFinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of berkeleyparser Show documentation
Show all versions of berkeleyparser Show documentation
The Berkeley parser analyzes the grammatical structure of natural language using probabilistic context-free grammars (PCFGs).
The newest version!
package edu.berkeley.nlp.syntax;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
/**
* Tool for finding path relationships between nodes in a tree
*
* @author David Burkett
*/
public class TreePathFinder {
private Tree root;
private IdentityHashMap, List>> pathsFromRoot;
public Tree getRoot() { return root; }
public TreePathFinder(Tree tree) {
root = tree;
pathsFromRoot = new IdentityHashMap, List>>(tree.getPreOrderTraversal().size());
constructPaths(root, new ArrayList>());
}
private void constructPaths(Tree node, List> path) {
path.add(node);
pathsFromRoot.put(node, path);
for (Tree child : node.getChildren()) {
ArrayList> childPath = new ArrayList>(path.size()+1);
childPath.addAll(path);
constructPaths(child, childPath);
}
}
public Tree findParent(Tree node) {
if (!pathsFromRoot.containsKey(node)) {
throw new IllegalArgumentException("Tree must be node in the tree used to initialize the TreePathFinder");
}
if (node == root) {
return null;
}
List> path = pathsFromRoot.get(node);
return path.get(path.size() - 2);
}
public TreePath findPath(Tree start, Tree end) {
validateInput(start, end);
List> transitions = new ArrayList>();
if (start != end) {
List> startPath = pathsFromRoot.get(start);
List> endPath = pathsFromRoot.get(end);
// Find root of common subtree
int rootIndex = findRootIndex(startPath, endPath);
// Transitions from start node up to root of common subtree
for (int i = startPath.size() - 1; i > rootIndex; i--) {
transitions.add(new TreePath.Transition(startPath.get(i), startPath.get(i-1), TreePath.Direction.UP));
}
// First transition down from root of common subtree (directional if there have been up transitions)
if (rootIndex < endPath.size() - 1) {
TreePath.Direction postRootDirection = TreePath.Direction.DOWN;
if (rootIndex < startPath.size() - 1) {
postRootDirection = TreePath.Direction.DOWN_RIGHT;
for (Tree rootChild : startPath.get(rootIndex).getChildren()) {
if (startPath.get(rootIndex+1) == rootChild) {
break;
}
if (endPath.get(rootIndex+1) == rootChild) {
postRootDirection = TreePath.Direction.DOWN_LEFT;
break;
}
}
}
transitions.add(new TreePath.Transition(endPath.get(rootIndex), endPath.get(rootIndex+1), postRootDirection));
}
// Remaining transitions down to end node
for (int i = rootIndex + 1; i < endPath.size() - 1; i++) {
transitions.add(new TreePath.Transition(endPath.get(i), endPath.get(i+1), TreePath.Direction.DOWN));
}
}
return new TreePath(transitions);
}
private int findRootIndex(List> startPath, List> endPath) {
int rootIndex = 0;
for (Tree node : startPath) {
if (rootIndex == endPath.size() || node != endPath.get(rootIndex)) {
break;
}
rootIndex++;
}
rootIndex--;
return rootIndex;
}
public Tree findLowestCommonAncestor(Tree start, Tree end) {
validateInput(start, end);
if (start == end)
return start;
List> startPath = pathsFromRoot.get(start);
List> endPath = pathsFromRoot.get(end);
int rootIndex = findRootIndex(startPath, endPath);
return startPath.get(rootIndex);
}
private void validateInput(Tree start, Tree end) {
if (start == null || end == null) {
throw new IllegalArgumentException("Cannot provide null trees");
}
if (!pathsFromRoot.containsKey(start) || !pathsFromRoot.containsKey(end)) {
throw new IllegalArgumentException("Both trees must be nodes in the tree used to initialize the TreePathFinder");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy