migrate more stuff to wala.util

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4036 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
sjfink 2011-01-17 22:21:01 +00:00
parent 5e4e9f010e
commit 16e9c0fa67
70 changed files with 0 additions and 7260 deletions

View File

@ -1,31 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util;
/**
* An exception for when work is canceled in eclipse. This version forces every API that uses it to declare it. Use
* {@link CancelRuntimeException} to avoid the need to declare a cancel exception.
*/
public class CancelException extends Exception {
protected CancelException(String msg) {
super(msg);
}
public CancelException(Exception cause) {
super(cause);
}
public static CancelException make(String msg) {
return new CancelException(msg);
}
}

View File

@ -1,76 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util;
/**
* Simple utilities for Eclipse progress monitors
*/
public class MonitorUtil {
/**
* Use this interface to decouple core utilities from the Eclipse layer
*/
public interface IProgressMonitor {
void beginTask(String task, int totalWork);
boolean isCanceled();
void done();
void worked(int units);
}
public static void beginTask(IProgressMonitor monitor, String task, int totalWork) throws CancelException {
if (monitor != null) {
monitor.beginTask(task, totalWork);
if (monitor.isCanceled()) {
throw CancelException.make("cancelled in " + task);
}
}
}
public static void done(IProgressMonitor monitor) throws CancelException {
if (monitor != null) {
monitor.done();
if (monitor.isCanceled()) {
throw CancelException.make("cancelled in " + monitor.toString());
}
}
}
public static void worked(IProgressMonitor monitor, int units) throws CancelException {
if (monitor != null) {
monitor.worked(units);
if (monitor.isCanceled()) {
throw CancelException.make("cancelled in " + monitor.toString());
}
}
}
public static void throwExceptionIfCanceled(IProgressMonitor progressMonitor) throws CancelException {
if (progressMonitor != null) {
if (progressMonitor.isCanceled()) {
throw CancelException.make("operation cancelled");
}
}
}
// public static IProgressMonitor subProgress(ProgressMaster progress, int i) {
// if (progress == null) {
// return null;
// } else {
// return new SubProgressMonitor(progress, i);
// }
// }
}

View File

@ -1,197 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Iterator;
/**
* Basic functionality for a {@link Graph} that delegates node and edge management.
*/
public abstract class AbstractGraph<T> implements Graph<T> {
/**
* @return the object which manages nodes in the graph
*/
protected abstract NodeManager<T> getNodeManager();
/**
* @return the object which manages edges in the graph
*/
protected abstract EdgeManager<T> getEdgeManager();
/*
* @see com.ibm.wala.util.graph.Graph#iterateNodes()
*/
public Iterator<T> iterator() {
return getNodeManager().iterator();
}
/*
* @see com.ibm.wala.util.graph.Graph#getNumberOfNodes()
*/
public int getNumberOfNodes() {
return getNodeManager().getNumberOfNodes();
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodeCount(java.lang.Object)
*/
public int getPredNodeCount(T n) throws IllegalArgumentException {
if (n == null) {
throw new IllegalArgumentException("n cannot be null");
}
return getEdgeManager().getPredNodeCount(n);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodes(java.lang.Object)
*/
public Iterator<T> getPredNodes(T n) throws IllegalArgumentException {
if (n == null) {
throw new IllegalArgumentException("n cannot be null");
}
return getEdgeManager().getPredNodes(n);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(java.lang.Object)
*/
public int getSuccNodeCount(T n) throws IllegalArgumentException {
if (!containsNode(n) || n == null) {
throw new IllegalArgumentException("node not in graph " + n);
}
return getEdgeManager().getSuccNodeCount(n);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(java.lang.Object)
*/
public Iterator<T> getSuccNodes(T n) throws IllegalArgumentException {
if (n == null) {
throw new IllegalArgumentException("n cannot be null");
}
return getEdgeManager().getSuccNodes(n);
}
/*
* @see com.ibm.wala.util.graph.NodeManager#addNode(com.ibm.wala.util.graph.Node)
*/
public void addNode(T n) {
getNodeManager().addNode(n);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#addEdge(com.ibm.wala.util.graph.Node,
* com.ibm.wala.util.graph.Node)
*/
public void addEdge(T src, T dst) throws IllegalArgumentException {
getEdgeManager().addEdge(src, dst);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdge(java.lang.Object, java.lang.Object)
*/
public void removeEdge(T src, T dst) throws IllegalArgumentException {
getEdgeManager().removeEdge(src, dst);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#hasEdge(java.lang.Object, java.lang.Object)
*/
public boolean hasEdge(T src, T dst) {
if (src == null) {
throw new IllegalArgumentException("src is null");
}
if (dst == null) {
throw new IllegalArgumentException("dst is null");
}
return getEdgeManager().hasEdge(src, dst);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(com.ibm.wala.util.graph.Node)
*/
public void removeAllIncidentEdges(T node) throws IllegalArgumentException {
if (node == null) {
throw new IllegalArgumentException("node cannot be null");
}
getEdgeManager().removeAllIncidentEdges(node);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(com.ibm.wala.util.graph.Node)
*/
public void removeIncomingEdges(T node) throws IllegalArgumentException {
if (node == null) {
throw new IllegalArgumentException("node cannot be null");
}
getEdgeManager().removeIncomingEdges(node);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(com.ibm.wala.util.graph.Node)
*/
public void removeOutgoingEdges(T node) throws IllegalArgumentException {
if (node == null) {
throw new IllegalArgumentException("node cannot be null");
}
getEdgeManager().removeOutgoingEdges(node);
}
/*
* @see com.ibm.wala.util.graph.Graph#removeNode(com.ibm.wala.util.graph.Node)
*/
public void removeNodeAndEdges(T N) throws IllegalArgumentException {
if (N == null) {
throw new IllegalArgumentException("N cannot be null");
}
getEdgeManager().removeAllIncidentEdges(N);
getNodeManager().removeNode(N);
}
/*
* @see com.ibm.wala.util.graph.NodeManager#remove(com.ibm.wala.util.graph.Node)
*/
public void removeNode(T n) throws IllegalArgumentException {
if (n == null) {
throw new IllegalArgumentException("N cannot be null");
}
getNodeManager().removeNode(n);
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
for (Iterator<? extends T> ns = iterator(); ns.hasNext();) {
T n = ns.next();
sb.append(n.toString()).append("\n");
for (Iterator ss = getSuccNodes(n); ss.hasNext();) {
Object s = ss.next();
sb.append(" --> ").append(s);
sb.append("\n");
}
sb.append("\n");
}
return sb.toString();
}
/*
* @see com.ibm.wala.util.graph.NodeManager#containsNode(com.ibm.wala.util.graph.Node)
*/
public boolean containsNode(T n) {
if (n == null) {
throw new IllegalArgumentException("n cannot be null");
}
return getNodeManager().containsNode(n);
}
}

View File

@ -1,68 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Iterator;
import com.ibm.wala.util.graph.impl.NumberedNodeIterator;
import com.ibm.wala.util.intset.IntSet;
/**
* Basic functionality for a graph that delegates node and edge management, and tracks node numbers
*/
public abstract class AbstractNumberedGraph<T> extends AbstractGraph<T> implements NumberedGraph<T> {
/*
* @see com.ibm.wala.util.graph.NumberedNodeManager#getMaxNumber()
*/
public int getMaxNumber() {
return ((NumberedNodeManager<T>) getNodeManager()).getMaxNumber();
}
/*
* @see com.ibm.wala.util.graph.NumberedNodeManager#getNode(int)
*/
public T getNode(int number) {
return ((NumberedNodeManager<T>) getNodeManager()).getNode(number);
}
/*
* @see com.ibm.wala.util.graph.NumberedNodeManager#getNumber(com.ibm.wala.util.graph.Node)
*/
public int getNumber(T N) {
if (N == null) {
throw new IllegalArgumentException("N cannot be null");
}
return ((NumberedNodeManager<T>) getNodeManager()).getNumber(N);
}
/*
* @see com.ibm.wala.util.graph.NumberedNodeManager#iterateNodes(com.ibm.wala.util.intset.IntSet)
*/
public Iterator<T> iterateNodes(final IntSet s) {
return new NumberedNodeIterator<T>(s, this);
}
/*
* @see com.ibm.wala.util.graph.NumberedEdgeManager#getPredNodeNumbers(java.lang.Object)
*/
public IntSet getPredNodeNumbers(T node) throws IllegalArgumentException {
assert getEdgeManager() != null;
return ((NumberedEdgeManager<T>) getEdgeManager()).getPredNodeNumbers(node);
}
/*
* @see com.ibm.wala.util.graph.NumberedEdgeManager#getSuccNodeNumbers(java.lang.Object)
*/
public IntSet getSuccNodeNumbers(T node) throws IllegalArgumentException {
return ((NumberedEdgeManager<T>) getEdgeManager()).getSuccNodeNumbers(node);
}
}

View File

@ -1,218 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.intset.BasicNaturalRelation;
import com.ibm.wala.util.intset.IBinaryNaturalRelation;
import com.ibm.wala.util.intset.IntIterator;
import com.ibm.wala.util.intset.IntPair;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.MutableIntSet;
import com.ibm.wala.util.intset.MutableSparseIntSet;
/**
* Utilities for dealing with acyclic subgraphs
*/
public class Acyclic {
/*
* prevent instantiation
*/
private Acyclic() {
}
/**
* This is slow. Fix it.
*/
public static <T> boolean isAcyclic(NumberedGraph<T> G, T root) {
IBinaryNaturalRelation r = computeBackEdges(G, root);
Iterator<IntPair> it = r.iterator();
return !it.hasNext();
}
/**
* Compute a relation R s.t. (i,j) \in R iff (i,j) is a backedge according to a DFS of a numbered graph starting from some root.
*
* Not efficient. Recursive and uses hash sets.
*/
public static <T> IBinaryNaturalRelation computeBackEdges(NumberedGraph<T> G, T root) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
BasicNaturalRelation result = new BasicNaturalRelation();
Set<T> visited = HashSetFactory.make();
Set<T> onstack = HashSetFactory.make();
dfs(result, root, G, visited, onstack);
return result;
}
private static <T> void dfs(BasicNaturalRelation result, T root, NumberedGraph<T> G, Set<T> visited, Set<T> onstack) {
visited.add(root);
onstack.add(root);
for (Iterator<? extends T> it = G.getSuccNodes(root); it.hasNext();) {
T dstNode = it.next();
if (onstack.contains(dstNode)) {
int src = G.getNumber(root);
int dst = G.getNumber(dstNode);
result.add(src, dst);
}
if (!visited.contains(dstNode)) {
dfs(result, dstNode, G, visited, onstack);
}
}
onstack.remove(root);
}
public static <T> boolean hasIncomingBackEdges(Path p, NumberedGraph<T> G, T root) {
/*
* TODO: pull out computeBackEdges, and pass in the backedge relation as a parameter to this call
*/
IBinaryNaturalRelation backedges = computeBackEdges(G, root);
for (int index = 0; index < p.size(); index++) {
int gn = p.get(index);
Iterator<? extends T> predIter = G.getPredNodes(G.getNode(gn));
while (predIter.hasNext()) {
if (backedges.contains(G.getNumber(predIter.next()), gn))
return true;
}
}
return false;
}
/**
* Compute a set of acyclic paths through a graph G from a node src to a node sink.
*
* This is not terribly efficient.
*
* @param max the max number of paths to return.
*/
public static <T> Collection<Path> computeAcyclicPaths(NumberedGraph<T> G, T root, T src, T sink, int max) {
Collection<Path> result = HashSetFactory.make();
SubGraph<T> acyclic = new SubGraph<T>(G, computeBackEdges(G, root));
Collection<Path> worklist = HashSetFactory.make();
Path sinkPath = Path.make(G.getNumber(sink));
worklist.add(sinkPath);
while (!worklist.isEmpty() && result.size() <= max) {
Path p = worklist.iterator().next();
worklist.remove(p);
int first = p.get(0);
if (first == G.getNumber(src)) {
result.add(p);
} else {
for (IntIterator it = acyclic.getPredNodeNumbers(acyclic.getNode(first)).intIterator(); it.hasNext();) {
worklist.add(Path.prepend(it.next(), p));
}
}
}
return result;
}
private static class SubGraph<T> extends AbstractNumberedGraph<T> {
private final NumberedGraph<T> delegate;
private final IBinaryNaturalRelation ignoreEdges;
private final Edges edges;
SubGraph(NumberedGraph<T> delegate, IBinaryNaturalRelation ignoreEdges) {
super();
this.delegate = delegate;
this.ignoreEdges = ignoreEdges;
this.edges = new Edges();
}
@Override
protected EdgeManager<T> getEdgeManager() {
return edges;
}
private final class Edges implements NumberedEdgeManager<T> {
public void addEdge(T src, T dst) {
Assertions.UNREACHABLE();
}
public int getPredNodeCount(T N) {
Assertions.UNREACHABLE();
return 0;
}
public Iterator<T> getPredNodes(T N) {
Assertions.UNREACHABLE();
return null;
}
public int getSuccNodeCount(T N) {
Assertions.UNREACHABLE();
return 0;
}
public Iterator<T> getSuccNodes(T N) {
Assertions.UNREACHABLE();
return null;
}
public boolean hasEdge(T src, T dst) {
Assertions.UNREACHABLE();
return false;
}
public void removeAllIncidentEdges(T node) throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
public void removeEdge(T src, T dst) throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
public void removeIncomingEdges(T node) throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
public void removeOutgoingEdges(T node) throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
public IntSet getPredNodeNumbers(T node) {
IntSet s = delegate.getPredNodeNumbers(node);
MutableIntSet result = MutableSparseIntSet.makeEmpty();
for (IntIterator it = s.intIterator(); it.hasNext();) {
int y = it.next();
if (!ignoreEdges.contains(y, getNumber(node))) {
result.add(y);
}
}
return result;
}
public IntSet getSuccNodeNumbers(T node) {
Assertions.UNREACHABLE();
return null;
}
}
@Override
protected NodeManager<T> getNodeManager() {
return delegate;
}
}
}

View File

@ -1,58 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import com.ibm.wala.util.collections.SimpleVector;
/**
* A simple, extremely inefficient tree implementation
*/
public class BasicTree<T> {
private final T value;
final private SimpleVector<BasicTree<T>> children = new SimpleVector<BasicTree<T>>();
protected BasicTree(T value) {
this.value = value;
}
public static <T> BasicTree<T> make(T value) {
if (value == null) {
throw new IllegalArgumentException("null value");
}
return new BasicTree<T>(value);
}
public T getRootValue() {
return value;
}
public T getChildValue(int i) {
if (children.get(i) == null) {
return null;
} else {
return children.get(i).getRootValue();
}
}
public BasicTree<T> getChild(int i) {
return children.get(i);
}
public void setChild(int i, BasicTree<T> tree) {
children.set(i, tree);
}
public int getMaxChildIndex() {
return children.getMaxIndex();
}
}

View File

@ -1,66 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Iterator;
/**
* An object which manages edges in a directed graph.
*
* @param <T> the type of node in the graph
*/
public interface EdgeManager<T> {
/**
* Return an {@link Iterator} over the immediate predecessor nodes of n
*
* This method never returns <code>null</code>.
*
* @return an {@link Iterator} over the immediate predecessor nodes of this Node.
*/
public Iterator<T> getPredNodes(T n);
/**
* Return the number of {@link #getPredNodes immediate predecessor} nodes of n
*
* @return the number of immediate predecessors of n.
*/
public int getPredNodeCount(T n);
/**
* Return an Iterator over the immediate successor nodes of n
* <p>
* This method never returns <code>null</code>.
*
* @return an Iterator over the immediate successor nodes of n
*/
public Iterator<T> getSuccNodes(T n);
/**
* Return the number of {@link #getSuccNodes immediate successor} nodes of this Node in the Graph
*
* @return the number of immediate successor Nodes of this Node in the Graph.
*/
public int getSuccNodeCount(T N);
public void addEdge(T src, T dst);
public void removeEdge(T src, T dst) throws UnsupportedOperationException;
public void removeAllIncidentEdges(T node) throws UnsupportedOperationException;
public void removeIncomingEdges(T node) throws UnsupportedOperationException;
public void removeOutgoingEdges(T node) throws UnsupportedOperationException;
public boolean hasEdge(T src, T dst);
}

View File

@ -1,29 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
/**
* Basic interface for a directed graph.
*
* We choose to define a {@link Graph} as a composition of a {@link NodeManager} and an {@link EdgeManager}, which
* track nodes and edges, respectively. This way, in many cases we can compose separate {@link NodeManager} and
* {@link EdgeManager} implementations to create {@link Graph} implementations, using delegation.
*
* @param <T> the type of nodes in this graph.
*/
public interface Graph<T> extends NodeManager<T>, EdgeManager<T> {
/**
* remove a node and all its incident edges
* @throws UnsupportedOperationException if the graph implementation does not allow removal
*/
public void removeNodeAndEdges(T n) throws UnsupportedOperationException;
}

View File

@ -1,242 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.graph.traverse.BFSIterator;
import com.ibm.wala.util.graph.traverse.DFS;
/**
* Utility class to check integrity of a graph data structure.
*/
public class GraphIntegrity {
/**
* DEBUG_LEVEL:
* <ul>
* <li>0 No output
* <li>1 Print some simple stats and warning information
* <li>2 Detailed debugging
* </ul>
*/
static final int DEBUG_LEVEL = 0;
public static <T> void check(Graph<T> G) throws UnsoundGraphException {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
checkNodeCount(G);
checkEdges(G);
checkEdgeCounts(G);
}
/**
* @param G
*/
private static <T> void checkEdgeCounts(Graph<T> G) throws UnsoundGraphException {
for (Iterator<? extends T> it = G.iterator(); it.hasNext();) {
T N = it.next();
int count1 = G.getSuccNodeCount(N);
int count2 = 0;
for (Iterator it2 = G.getSuccNodes(N); it2.hasNext();) {
it2.next();
count2++;
}
if (count1 != count2) {
throw new UnsoundGraphException("getSuccNodeCount " + count1 + " is wrong for node " + N);
}
int count3 = G.getPredNodeCount(N);
int count4 = 0;
for (Iterator it2 = G.getPredNodes(N); it2.hasNext();) {
it2.next();
count4++;
}
if (count3 != count4) {
throw new UnsoundGraphException("getPredNodeCount " + count1 + " is wrong for node " + N);
}
}
}
/**
* @param G
*/
private static <T> void checkEdges(Graph<T> G) throws UnsoundGraphException {
for (Iterator<? extends T> it = G.iterator(); it.hasNext();) {
T N = it.next();
if (!G.containsNode(N)) {
throw new UnsoundGraphException(N + " is not contained in the the graph " + G.containsNode(N));
}
PRED: for (Iterator<? extends T> p = G.getPredNodes(N); p.hasNext();) {
T pred = p.next();
if (!G.containsNode(pred)) {
throw new UnsoundGraphException(pred + " is a predecessor of " + N + " but is not contained in the graph");
}
for (Iterator s = G.getSuccNodes(pred); s.hasNext();) {
Object succ = s.next();
if (succ.equals(N)) {
continue PRED;
}
}
// didn't find N
G.getPredNodes(N);
G.getSuccNodes(pred);
throw new UnsoundGraphException(pred + " is a predecessor of " + N + " but inverse doesn't hold");
}
SUCC: for (Iterator<? extends T> s = G.getSuccNodes(N); s.hasNext();) {
T succ = s.next();
if (!G.containsNode(succ)) {
throw new UnsoundGraphException(succ + " is a successor of " + N + " but is not contained in the graph");
}
for (Iterator p = G.getPredNodes(succ); p.hasNext();) {
Object pred = p.next();
if (pred.equals(N)) {
continue SUCC;
}
}
// didn't find N
throw new UnsoundGraphException(succ + " is a successor of " + N + " but inverse doesn't hold");
}
}
}
/**
* @param G
*/
private static <T> void checkNodeCount(Graph<T> G) throws UnsoundGraphException {
int n1 = 0;
int n2 = 0;
int n3 = 0;
int n4 = 0;
int n5 = 0;
try {
n1 = G.getNumberOfNodes();
n2 = 0;
for (Iterator it = G.iterator(); it.hasNext();) {
Object n = it.next();
if (DEBUG_LEVEL > 1) {
System.err.println(("n2 loop: " + n));
}
n2++;
}
n3 = 0;
for (Iterator it = new BFSIterator<T>(G); it.hasNext();) {
it.next();
n3++;
}
n4 = 0;
for (Iterator it = DFS.iterateDiscoverTime(G); it.hasNext();) {
it.next();
n4++;
}
n5 = 0;
for (Iterator it = DFS.iterateFinishTime(G); it.hasNext();) {
it.next();
n5++;
}
} catch (RuntimeException e) {
e.printStackTrace();
throw new UnsoundGraphException(e.toString());
}
if (n1 != n2) {
throw new UnsoundGraphException("n1: " + n1 + " n2: " + n2);
}
if (n1 != n3) {
throw setDiffException("n1: " + n1 + " n3: " + n3, G.iterator(), new BFSIterator<T>(G));
}
if (n1 != n4) {
throw new UnsoundGraphException("n1: " + n1 + " n4: " + n3);
}
if (n1 != n5) {
throw new UnsoundGraphException("n1: " + n1 + " n5: " + n3);
}
}
private static <T> UnsoundGraphException setDiffException(String msg, Iterator<? extends T> i1, Iterator<T> i2) {
HashSet<T> set1 = HashSetFactory.make();
while (i1.hasNext()) {
T o1 = i1.next();
boolean b = set1.add(o1);
if (!b) {
return new UnsoundGraphException("set1 already contained " + o1);
}
}
HashSet<T> set2 = HashSetFactory.make();
while (i2.hasNext()) {
T o2 = i2.next();
boolean b = set2.add(o2);
if (!b) {
return new UnsoundGraphException("set2 already contained " + o2);
}
}
GraphIntegrity.printCollection("set 1 ", set1);
GraphIntegrity.printCollection("set 2 ", set2);
HashSet s1clone = (HashSet) set1.clone();
set1.removeAll(set2);
if (set1.size() > 0) {
Object first = set1.iterator().next();
msg = msg + ", first iterator contained " + first;
return new UnsoundGraphException(msg);
} else {
set2.removeAll(s1clone);
if (set2.size() > 0) {
Object first = set2.iterator().next();
msg = msg + ", 2nd iterator contained " + first;
return new UnsoundGraphException(msg);
} else {
msg = msg + "set2.size = 0";
return new UnsoundGraphException(msg);
}
}
}
public static class UnsoundGraphException extends Exception {
private static final long serialVersionUID = 1503478788521696930L;
public UnsoundGraphException() {
super();
}
public UnsoundGraphException(String s) {
super(s);
}
}
/**
* @param string
* @param c
* @throws IllegalArgumentException if c is null
*/
public static void printCollection(String string, Collection c) {
if (c == null) {
throw new IllegalArgumentException("c is null");
}
System.err.println(string);
if (c.isEmpty()) {
System.err.println("none\n");
} else {
for (Iterator it = c.iterator(); it.hasNext();) {
System.err.println(it.next().toString());
}
System.err.println("\n");
}
}
}

View File

@ -1,40 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Iterator;
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph;
/**
* Simple graph printing utility
*/
public class GraphPrint {
public static <T> String genericToString(Graph<T> G) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
SlowSparseNumberedGraph<T> sg = SlowSparseNumberedGraph.make();
for (Iterator<? extends T> it = G.iterator(); it.hasNext(); ) {
sg.addNode(it.next());
}
for (Iterator<? extends T> it = G.iterator(); it.hasNext(); ) {
T n = it.next();
for (Iterator<? extends T> it2 = G.getSuccNodes(n); it2.hasNext(); ) {
T d = it2.next();
sg.addEdge(n,d);
}
}
return sg.toString();
}
}

View File

@ -1,141 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Iterator;
import com.ibm.wala.dataflow.graph.AbstractMeetOperator;
import com.ibm.wala.dataflow.graph.BitVectorFramework;
import com.ibm.wala.dataflow.graph.BitVectorIdentity;
import com.ibm.wala.dataflow.graph.BitVectorSolver;
import com.ibm.wala.dataflow.graph.BitVectorUnion;
import com.ibm.wala.dataflow.graph.BitVectorUnionConstant;
import com.ibm.wala.dataflow.graph.DataflowSolver;
import com.ibm.wala.dataflow.graph.ITransferFunctionProvider;
import com.ibm.wala.fixpoint.BitVectorVariable;
import com.ibm.wala.fixpoint.UnaryOperator;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.collections.FilterIterator;
import com.ibm.wala.util.collections.Iterator2Collection;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.impl.GraphInverter;
import com.ibm.wala.util.intset.MutableMapping;
import com.ibm.wala.util.intset.OrdinalSet;
import com.ibm.wala.util.intset.OrdinalSetMapping;
/**
* A dataflow system that computes, for each graph node, the set of "interesting" nodes that are reachable
*/
public class GraphReachability<T> {
/**
* Governing graph
*/
private final Graph<T> g;
/**
* Killdall-style dataflow solver
*/
private DataflowSolver solver;
/**
* set of "interesting" CGNodes
*/
final OrdinalSetMapping<T> domain;
/**
* @param g call graph to analyze
* @param filter "interesting" node definition
* @throws IllegalArgumentException if g is null
*/
public GraphReachability(Graph<T> g, Filter filter) {
if (g == null) {
throw new IllegalArgumentException("g is null");
}
this.g = g;
Iterator<T> i = new FilterIterator<T>(g.iterator(), filter);
domain = new MutableMapping<T>((Iterator2Collection.toSet(i)).toArray());
}
/**
* @param n
* @return the set of interesting nodes reachable from n
*/
public OrdinalSet<T> getReachableSet(Object n) throws IllegalStateException {
if (solver == null) {
throw new IllegalStateException("must call solve() before calling getReachableSet()");
}
BitVectorVariable v = (BitVectorVariable) solver.getOut(n);
assert v != null : "null variable for node " + n;
if (v.getValue() == null) {
return OrdinalSet.empty();
} else {
return new OrdinalSet<T>(v.getValue(), domain);
}
}
/**
* @return true iff the evaluation of some equation caused a change in the value of some variable.
*/
public boolean solve(IProgressMonitor monitor) throws CancelException {
ITransferFunctionProvider<T, BitVectorVariable> functions = new ITransferFunctionProvider<T, BitVectorVariable>() {
/*
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getNodeTransferFunction(java.lang.Object)
*/
public UnaryOperator<BitVectorVariable> getNodeTransferFunction(T n) {
int index = domain.getMappedIndex(n);
if (index > -1) {
return new BitVectorUnionConstant(index);
} else {
return BitVectorIdentity.instance();
}
}
/*
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#hasNodeTransferFunctions()
*/
public boolean hasNodeTransferFunctions() {
return true;
}
/*
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getEdgeTransferFunction(java.lang.Object, java.lang.Object)
*/
public UnaryOperator<BitVectorVariable> getEdgeTransferFunction(Object from, Object to) {
Assertions.UNREACHABLE();
return null;
}
/*
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#hasEdgeTransferFunctions()
*/
public boolean hasEdgeTransferFunctions() {
return false;
}
/*
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getMeetOperator()
*/
public AbstractMeetOperator<BitVectorVariable> getMeetOperator() {
return BitVectorUnion.instance();
}
};
BitVectorFramework<T, T> f = new BitVectorFramework<T, T>(GraphInverter.invert(g), functions, domain);
solver = new BitVectorSolver<T>(f);
return solver.solve(monitor);
}
}

View File

@ -1,307 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.collections.FilterIterator;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Iterator2Collection;
import com.ibm.wala.util.collections.IteratorUtil;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.functions.Function;
import com.ibm.wala.util.graph.impl.GraphInverter;
import com.ibm.wala.util.graph.traverse.DFS;
import com.ibm.wala.util.warnings.WalaException;
/**
*/
public class GraphSlicer {
/**
* Performs a backward slice.
*
* @param <T> type for nodes
* @param g the graph to slice
* @param f identifies targets for the backward slice
* @return the set of nodes in g, from which any of the targets (nodes that f accepts) is reachable.
* @throws WalaException
*/
public static <T> Set<T> slice(Graph<T> g, Filter<T> f) throws WalaException {
if (g == null) {
throw new IllegalArgumentException("g is null");
}
HashSet<T> roots = HashSetFactory.make();
for (Iterator<? extends T> it = g.iterator(); it.hasNext();) {
T o = it.next();
if (f.accepts(o)) {
roots.add(o);
}
}
Set<T> result = DFS.getReachableNodes(GraphInverter.invert(g), roots);
return result;
}
/**
* Prune a graph to only the nodes accepted by the filter f
*/
public static <T> Graph<T> prune(final Graph<T> g, final Filter<T> f) {
if (g == null) {
throw new IllegalArgumentException("g is null");
}
final NodeManager<T> n = new NodeManager<T>() {
int nodeCount = -1;
public Iterator<T> iterator() {
return new FilterIterator<T>(g.iterator(), f);
}
public int getNumberOfNodes() {
if (nodeCount == -1) {
nodeCount = IteratorUtil.count(iterator());
}
return nodeCount;
}
public void addNode(T n) {
Assertions.UNREACHABLE();
}
public void removeNode(T n) {
Assertions.UNREACHABLE();
}
public boolean containsNode(T N) {
return f.accepts(N) && g.containsNode(N);
}
};
final EdgeManager<T> e = new EdgeManager<T>() {
public Iterator<T> getPredNodes(T N) {
return new FilterIterator<T>(g.getPredNodes(N), f);
}
public int getPredNodeCount(T N) {
return IteratorUtil.count(getPredNodes(N));
}
public Iterator<T> getSuccNodes(T N) {
return new FilterIterator<T>(g.getSuccNodes(N), f);
}
public int getSuccNodeCount(T N) {
return IteratorUtil.count(getSuccNodes(N));
}
public void addEdge(T src, T dst) {
Assertions.UNREACHABLE();
}
public void removeEdge(T src, T dst) {
Assertions.UNREACHABLE();
}
public void removeAllIncidentEdges(T node) {
Assertions.UNREACHABLE();
}
public void removeIncomingEdges(T node) {
Assertions.UNREACHABLE();
}
public void removeOutgoingEdges(T node) {
Assertions.UNREACHABLE();
}
public boolean hasEdge(T src, T dst) {
return g.hasEdge(src, dst) && f.accepts(src) && f.accepts(dst);
}
};
AbstractGraph<T> output = new AbstractGraph<T>() {
@Override
protected NodeManager<T> getNodeManager() {
return n;
}
@Override
protected EdgeManager<T> getEdgeManager() {
return e;
}
};
return output;
}
public static <E> AbstractGraph<E> project(final Graph<E> G, final Filter<E> fmember) {
final NodeManager<E> nodeManager = new NodeManager<E>() {
private int count = -1;
public void addNode(E n) {
throw new UnsupportedOperationException();
}
public boolean containsNode(E N) {
return G.containsNode(N) && fmember.accepts(N);
}
public int getNumberOfNodes() {
if (count == -1) {
count = IteratorUtil.count(iterator());
}
return count;
}
public Iterator<E> iterator() {
return new FilterIterator<E>(G.iterator(), fmember);
}
public void removeNode(E n) {
throw new UnsupportedOperationException();
}
};
final EdgeManager<E> edgeManager = new EdgeManager<E>() {
private Map<E, Collection<E>> succs = new HashMap<E, Collection<E>>();
private Map<E, Collection<E>> preds = new HashMap<E, Collection<E>>();
private Set<E> getConnected(E inst, Function<E, Iterator<? extends E>> fconnected) {
Set<E> result = new LinkedHashSet<E>();
Set<E> seenInsts = new HashSet<E>();
Set<E> newInsts = Iterator2Collection.toSet(fconnected.apply(inst));
while (!newInsts.isEmpty()) {
Set<E> nextInsts = new HashSet<E>();
for (E s : newInsts) {
if (!seenInsts.contains(s)) {
seenInsts.add(s);
if (nodeManager.containsNode(s)) {
result.add(s);
} else {
Iterator<? extends E> ss = fconnected.apply(s);
while (ss.hasNext()) {
E n = ss.next();
if (!seenInsts.contains(n)) {
nextInsts.add(n);
}
}
}
}
}
newInsts = nextInsts;
}
return result;
}
private void setPredNodes(E N) {
preds.put(N, getConnected(N, new Function<E, Iterator<? extends E>>() {
public Iterator<? extends E> apply(E object) {
return G.getPredNodes(object);
}
}));
}
private void setSuccNodes(E N) {
succs.put(N, getConnected(N, new Function<E, Iterator<? extends E>>() {
public Iterator<? extends E> apply(E object) {
return G.getSuccNodes(object);
}
}));
}
public int getPredNodeCount(E N) {
if (!preds.containsKey(N)) {
setPredNodes(N);
}
return preds.get(N).size();
}
public Iterator<E> getPredNodes(E N) {
if (!preds.containsKey(N)) {
setPredNodes(N);
}
return preds.get(N).iterator();
}
public int getSuccNodeCount(E N) {
if (!succs.containsKey(N)) {
setSuccNodes(N);
}
return succs.get(N).size();
}
public Iterator<E> getSuccNodes(E N) {
if (!succs.containsKey(N)) {
setSuccNodes(N);
}
return succs.get(N).iterator();
}
public boolean hasEdge(E src, E dst) {
if (!preds.containsKey(dst)) {
setPredNodes(dst);
}
return preds.get(dst).contains(src);
}
public void addEdge(E src, E dst) {
throw new UnsupportedOperationException();
}
public void removeAllIncidentEdges(E node) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
public void removeEdge(E src, E dst) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
public void removeIncomingEdges(E node) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
public void removeOutgoingEdges(E node) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
};
return new AbstractGraph<E>() {
@Override
protected EdgeManager<E> getEdgeManager() {
return edgeManager;
}
@Override
protected NodeManager<E> getNodeManager() {
return nodeManager;
}
};
}
}

View File

@ -1,33 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
/**
* Utility methods for graphs.
*/
public class GraphUtil {
/**
* count the number of edges in g
*/
public static <T> long countEdges(Graph<T> g) {
if (g == null) {
throw new IllegalArgumentException("g is null");
}
long edgeCount = 0;
for (T t : g) {
edgeCount += g.getSuccNodeCount(t);
}
return edgeCount;
}
}

View File

@ -1,35 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
/**
* Basic interface for a node which lives in one graph ... it's id is used
* to implement the {@link NumberedGraph} interface.
*/
public interface INodeWithNumber {
/**
* A non-negative integer which serves as an identifier for this node in
* it's "dominant" graph. Initially this number is -1; a NumberedGraph
* will set it to a non-negative value when this node is inserted into
* the graph
* @return the identifier
*/
public int getGraphNodeId();
/**
* @param number
*/
void setGraphNodeId(int number);
}

View File

@ -1,54 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import com.ibm.wala.util.intset.IntSet;
/**
* Basic interface for a node which lives in one graph ... it's id is used to implement the {@link NumberedGraph} interface.
*/
public interface INodeWithNumberedEdges extends INodeWithNumber {
/**
* @return set of node numbers which are successors of this node
*/
public IntSet getSuccNumbers();
/**
* @return set of node numbers which are predecessors of this node
*/
public IntSet getPredNumbers();
/**
* Modify the graph so that node number n is a successor of this node
*/
public void addSucc(int n);
/**
* Modify the graph so that node number n is a predecessor of this node
*/
public void addPred(int n);
/**
* remove all edges that involve this node. This must fix up the other nodes involved in each edge removed.
*/
public void removeAllIncidentEdges();
/**
* remove all incoming edges to this this node. This must fix up the other nodes involved in each edge removed.
*/
public void removeIncomingEdges();
/**
* remove all outgoing edges to this this node. This must fix up the other nodes involved in each edge removed.
*/
public void removeOutgoingEdges();
}

View File

@ -1,37 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import com.ibm.wala.util.collections.HashSetFactory;
/**
* TODO: Move this somewhere.
*/
public class InferGraphRoots {
public static <T> Collection<T> inferRoots(Graph<T> g){
if (g == null) {
throw new IllegalArgumentException("g is null");
}
HashSet<T> s = HashSetFactory.make();
for (Iterator<? extends T> it = g.iterator(); it.hasNext();) {
T node = it.next();
if (g.getPredNodeCount(node) == 0) {
s.add(node);
}
}
return s;
}
}

View File

@ -1,50 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Collection;
import java.util.Iterator;
/**
* An object which tracks graph nodes.
*
* This is effectively a stripped-down collection interface. We choose to avoid using the full {@link Collection} interface, so that
* it takes less code to implement a new {@link NodeManager}.
*
* @param <T> the type of nodes this {@link NodeManager} tracks.
*/
public interface NodeManager<T> extends Iterable<T> {
/**
* @return an {@link Iterator} of the nodes in this graph
*/
public Iterator<T> iterator();
/**
* @return the number of nodes in this graph
*/
public int getNumberOfNodes();
/**
* add a node to this graph
*/
public void addNode(T n);
/**
* remove a node from this graph
*/
public void removeNode(T n) throws UnsupportedOperationException;
/**
* @return true iff the graph contains the specified node
*/
public boolean containsNode(T n);
}

View File

@ -1,30 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import com.ibm.wala.util.intset.IntSet;
/**
* Additional functionality for edges in numbered graphs
*/
public interface NumberedEdgeManager<T> extends EdgeManager<T> {
/**
* @return the numbers identifying the immediate successors of node
*/
public IntSet getSuccNodeNumbers(T node);
/**
* @return the numbers identifying the immediate predecessors of node
*/
public IntSet getPredNodeNumbers(T node);
}

View File

@ -1,18 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
/**
* A numbered graph is a {@link Graph} where each node has a unique persistent non-negative integer id.
*/
public interface NumberedGraph<T> extends Graph<T>, NumberedNodeManager<T>, NumberedEdgeManager<T> {
}

View File

@ -1,36 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import java.util.Iterator;
import com.ibm.wala.util.intset.IntSet;
/**
* An object which tracks nodes with numbers.
*/
public interface NumberedNodeManager<T> extends NodeManager<T> {
public abstract int getNumber(T N);
public abstract T getNode(int number);
public abstract int getMaxNumber();
/**
* @param s
* @return iterator of nodes with the numbers in set s
*/
public abstract Iterator<T> iterateNodes(IntSet s);
}

View File

@ -1,28 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
/**
*
*/
public interface OrderedMultiGraph<T> extends Graph<T> {
/**
* get the ith successor of a node
*/
public T getSuccessor(T node, int i);
/**
* add an edge and record it so dst is the ith successor of src
*/
public void addEdge(int i, T src, T dst);
}

View File

@ -1,89 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph;
import com.ibm.wala.util.intset.SimpleIntVector;
/**
* We represent a path in a numbered graph as a vector of integers <i_1, ...,
* i_n> where node i_1 is the src and node i_n is the sink
*/
public class Path extends SimpleIntVector {
final int size;
private Path(int defaultValue, int size) {
super(defaultValue, size);
this.size = size;
}
public static Path make(int value) {
return new Path(value, 1);
}
public static Path prepend(int x, Path p) {
if (p == null) {
throw new IllegalArgumentException("null p");
}
Path result = new Path(0, p.size + 1);
result.set(0, x);
for (int i = 0; i < p.size; i++) {
result.set(i + 1, p.get(i));
}
return result;
}
@Override
public int hashCode() {
int result = 7;
for (int i = 0; i < size; i++) {
result += 31 * (get(i) + 1);
}
return result;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Path) {
Path other = (Path) obj;
if (size == other.size) {
for (int i = 0; i < size; i++) {
if (get(i) != other.get(i)) {
return false;
}
}
return true;
} else {
return false;
}
} else {
return false;
}
}
public int size() {
return size;
}
@Override
public String toString() {
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < size; i++) {
result.append(get(i));
if (i < size -1) {
result.append(",");
}
}
result.append("]");
return result.toString();
}
}

View File

@ -1,93 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.dominators;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.traverse.DFS;
/**
* An object that computes the dominance frontiers of a graph
*/
public class DominanceFrontiers<T> {
final private Map<T, Set<T>> DF = HashMapFactory.make();
final private Dominators<T> dom;
final private Graph<T> G;
final private T root;
/**
* @param G
* The graph
* @param root
* The root from which to compute dominators
*/
public DominanceFrontiers(Graph<T> G, T root) {
this.root = root;
this.G = G;
this.dom = Dominators.make(G, root);
analyze();
}
public Iterator<T> getDominanceFrontier(T n) {
return DF.get(n).iterator();
}
public boolean isDominatedBy(T node, T master) {
return dom.isDominatedBy(node, master);
}
public Iterator<T> dominators(T node) {
return dom.dominators(node);
}
public Graph<T> dominatorTree() {
return dom.dominatorTree();
}
private void analyze() {
Graph<T> DT = dom.dominatorTree();
Iterator<T> XS = DFS.iterateFinishTime(DT, new NonNullSingletonIterator<T>(root));
while (XS.hasNext()) {
T X = XS.next();
Set<T> DF_X = HashSetFactory.make();
DF.put(X, DF_X);
// DF_local
for (Iterator<? extends T> YS = G.getSuccNodes(X); YS.hasNext();) {
T Y = YS.next();
if (dom.getIdom(Y) != X) {
DF_X.add(Y);
}
}
// DF_up
for (Iterator<? extends T> ZS = DT.getSuccNodes(X); ZS.hasNext();) {
T Z = ZS.next();
for (Iterator<T> YS2 = getDominanceFrontier(Z); YS2.hasNext();) {
T Y2 = YS2.next();
if (dom.getIdom(Y2) != X)
DF_X.add(Y2);
}
}
}
}
}

View File

@ -1,585 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.dominators;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.AbstractGraph;
import com.ibm.wala.util.graph.EdgeManager;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.NodeManager;
import com.ibm.wala.util.graph.NumberedGraph;
import com.ibm.wala.util.graph.traverse.DFSDiscoverTimeIterator;
import com.ibm.wala.util.graph.traverse.SlowDFSDiscoverTimeIterator;
/**
* Calculate dominators using Langauer and Tarjan's fastest algorithm. TOPLAS 1(1), July 1979. This implementation uses path
* compression and results in a O(e * alpha(e,n)) complexity, where e is the number of edges in the CFG and n is the number of
* nodes.
*
* Sources: TOPLAS article, Muchnick book
*/
public abstract class Dominators<T> {
static final boolean DEBUG = false;
/**
* a mapping from DFS number to node
*/
private final T[] vertex;
/**
* a convenient place to locate the graph to avoid passing it internally
*/
protected final Graph<T> G;
/**
* the root node from which to build dominators
*/
protected final T root;
/**
* the number of nodes reachable from the root
*/
protected int reachableNodeCount = 0;
/**
* @param G The graph
* @param root The root from which to compute dominators
* @throws IllegalArgumentException if G is null
*/
@SuppressWarnings("unchecked")
public Dominators(Graph<T> G, T root) throws IllegalArgumentException {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
this.G = G;
this.root = root;
if (G.getNumberOfNodes() == 0) {
throw new IllegalArgumentException("G has no nodes");
}
this.vertex = (T[]) new Object[G.getNumberOfNodes() + 1];
}
public static <T> Dominators<T> make(Graph<T> G, T root) {
if (G instanceof NumberedGraph) {
return new NumberedDominators<T>((NumberedGraph<T>) G, root);
} else {
return new GenericDominators<T>(G, root);
}
}
/**
* is node dominated by master?
*/
public boolean isDominatedBy(T node, T master) {
for (T ptr = node; ptr != null; ptr = getIdom(ptr))
// use equals() since sometimes the CFGs get
// reconstructed --MS
if (ptr.equals(master))
return true;
return false;
}
public Graph<T> getGraph() {
return G;
}
/**
* return the immediate dominator of node
*/
public T getIdom(T node) {
return getInfo(node).dominator;
}
/**
* return an Iterator over all nodes that dominate node
*/
public Iterator<T> dominators(final T node) {
return new Iterator<T>() {
private T current = node;
public void remove() {
throw new UnsupportedOperationException();
}
public boolean hasNext() {
return current != null;
}
public T next() {
if (current == null)
throw new NoSuchElementException();
T nextNode = current;
current = getIdom(current);
return nextNode;
}
};
}
/**
* return the dominator tree, which has an edge from n to n' if n dominates n'
*/
public Graph<T> dominatorTree() {
return new AbstractGraph<T>() {
@Override
protected NodeManager<T> getNodeManager() {
return G;
}
@Override
protected EdgeManager<T> getEdgeManager() {
return edges;
}
private final EdgeManager<T> edges = new EdgeManager<T>() {
private final Map<T, Set<T>> nextMap = HashMapFactory.make();
{
for (Iterator<? extends T> ns = G.iterator(); ns.hasNext();) {
T n = ns.next();
if (n != root) {
T prev = getIdom(n);
Set<T> next = nextMap.get(prev);
if (next == null)
nextMap.put(prev, next = HashSetFactory.make(2));
next.add(n);
}
}
}
public Iterator<T> getPredNodes(T N) {
if (N == root)
return EmptyIterator.instance();
else
return new NonNullSingletonIterator<T>(getIdom(N));
}
public int getPredNodeCount(Object N) {
return (N == root) ? 0 : 1;
}
public Iterator<T> getSuccNodes(Object N) {
if (nextMap.containsKey(N))
return nextMap.get(N).iterator();
else
return EmptyIterator.instance();
}
public int getSuccNodeCount(Object N) {
if (nextMap.containsKey(N))
return nextMap.get(N).size();
else
return 0;
}
public void addEdge(Object src, Object dst) {
Assertions.UNREACHABLE();
}
public void removeEdge(Object src, Object dst) {
Assertions.UNREACHABLE();
}
public void removeAllIncidentEdges(Object node) {
Assertions.UNREACHABLE();
}
public void removeIncomingEdges(Object node) {
// TODO Auto-generated method stub
Assertions.UNREACHABLE();
}
public void removeOutgoingEdges(Object node) {
// TODO Auto-generated method stub
Assertions.UNREACHABLE();
}
public boolean hasEdge(Object src, Object dst) {
// TODO Auto-generated method stub
Assertions.UNREACHABLE();
return false;
}
};
};
}
//
// IMPLEMENTATION -- MAIN ALGORITHM
//
/**
* analyze dominators
*/
protected void analyze() {
if (DEBUG)
System.out.println("Dominators for " + G);
// Step 1: Perform a DFS numbering
step1();
// Step 2: the heart of the algorithm
step2();
// Step 3: adjust immediate dominators of nodes whose current version of
// the immediate dominators differs from the nodes with the depth-first
// number of the node's semidominator.
step3();
if (DEBUG)
System.err.println(this);
}
/**
* The goal of this step is to perform a DFS numbering on the CFG, starting at the root. The exit node is not included.
*/
private void step1() {
reachableNodeCount = 0;
DFSDiscoverTimeIterator<T> dfs = new SlowDFSDiscoverTimeIterator<T>(G, root) {
public static final long serialVersionUID = 88831771771711L;
@Override
protected void visitEdge(T from, T to) {
if (DEBUG)
System.out.println("visiting edge " + from + " --> " + to);
setParent(to, from);
}
};
while (dfs.hasNext()) {
T node = dfs.next();
assert node != null;
vertex[++reachableNodeCount] = node;
setSemi(node, reachableNodeCount);
if (DEBUG)
System.out.println(node + " is DFS number " + reachableNodeCount);
}
}
/**
* This is the heart of the algorithm. See sources for details.
*/
private void step2() {
if (DEBUG) {
System.out.println(" ******* Beginning STEP 2 *******\n");
}
// Visit each node in reverse DFS order, except for the root, which
// has number 1
// for i=n downto 2
for (int i = reachableNodeCount; i > 1; i--) {
T node = vertex[i];
if (DEBUG) {
System.out.println(" Processing: " + node + "\n");
}
// visit each predecessor
Iterator<? extends T> e = G.getPredNodes(node);
while (e.hasNext()) {
T prev = e.next();
if (DEBUG) {
System.out.println(" Inspecting prev: " + prev);
}
T u = EVAL(prev);
// if semi(u) < semi(node) then semi(node) = semi(u)
// u may be part of infinite loop and thus, is unreachable from the exit
// node.
// In this case, it will have a semi value of 0. Thus, we screen for it
// here
if (getSemi(u) != 0 && getSemi(u) < getSemi(node)) {
setSemi(node, getSemi(u));
}
} // while prev
// add "node" to bucket(vertex(semi(node)));
addToBucket(vertex[getSemi(node)], node);
// LINK(parent(node), node)
LINK(getParent(node), node);
// foreach node2 in bucket(parent(node)) do
Iterator<T> bucketEnum = iterateBucket(getParent(node));
while (bucketEnum.hasNext()) {
T node2 = bucketEnum.next();
// u = EVAL(node2)
T u = EVAL(node2);
// if semi(u) < semi(node2) then
// dom(node2) = u
// else
// dom(node2) = parent(node)
if (getSemi(u) < getSemi(node2)) {
setDominator(node2, u);
} else {
setDominator(node2, getParent(node));
}
} // while bucket has more elements
} // for DFSCounter .. 1
} // method
/**
* This method inspects the passed node and returns the following: node, if node is a root of a tree in the forest
*
* any vertex, u != r such that otherwise r is the root of the tree containing node and * semi(u) is minimum on the path r -> v
*
* See TOPLAS 1(1), July 1979, p 128 for details.
*
* @param node the node to evaluate
* @return the node as described above
*/
private T EVAL(T node) {
if (DEBUG) {
System.out.println(" Evaling " + node);
}
if (getAncestor(node) == null) {
return getLabel(node);
} else {
compress(node);
if (getSemi(getLabel(getAncestor(node))) >= getSemi(getLabel(node))) {
return getLabel(node);
} else {
return getLabel(getAncestor(node));
}
}
}
/**
* This recursive method performs the path compression
*
* @param node node of interest
*/
private void compress(T node) {
if (getAncestor(getAncestor(node)) != null) {
compress(getAncestor(node));
if (getSemi(getLabel(getAncestor(node))) < getSemi(getLabel(node))) {
setLabel(node, getLabel(getAncestor(node)));
}
setAncestor(node, getAncestor(getAncestor(node)));
}
}
/**
* Adds edge (node1, node2) to the forest maintained as an auxiliary data structure. This implementation uses path compression and
* results in a O(e * alpha(e,n)) complexity, where e is the number of edges in the CFG and n is the number of nodes.
*
* @param node1 a basic node corresponding to the source of the new edge
* @param node2 a basic node corresponding to the source of the new edge
*/
private void LINK(T node1, T node2) {
if (DEBUG) {
System.out.println(" Linking " + node1 + " with " + node2);
}
T s = node2;
while (getSemi(getLabel(node2)) < getSemi(getLabel(getChild(s)))) {
if (getSize(s) + getSize(getChild(getChild(s))) >= 2 * getSize(getChild(s))) {
setAncestor(getChild(s), s);
setChild(s, getChild(getChild(s)));
} else {
setSize(getChild(s), getSize(s));
setAncestor(s, getChild(s));
s = getChild(s);
}
}
setLabel(s, getLabel(node2));
setSize(node1, getSize(node1) + getSize(node2));
if (getSize(node1) < 2 * getSize(node2)) {
T tmp = s;
s = getChild(node1);
setChild(node1, tmp);
}
while (s != null) {
setAncestor(s, node1);
s = getChild(s);
}
if (DEBUG) {
System.out.println(" .... done");
}
}
/**
* This final step sets the final dominator information.
*/
private void step3() {
// Visit each node in DFS order, except for the root, which has number 1
for (int i = 2; i <= reachableNodeCount; i++) {
T node = vertex[i];
// if dom(node) != vertex[semi(node)]
if (getDominator(node) != vertex[getSemi(node)]) {
// dom(node) = dom(dom(node))
setDominator(node, getDominator(getDominator(node)));
}
}
}
/**
* LOOK-ASIDE TABLE FOR PER-NODE STATE AND ITS ACCESSORS
*/
protected final class DominatorInfo {
/*
* The result of this computation: the immediate dominator of this node
*/
private T dominator;
/*
* The parent node in the DFS tree used in dominator computation
*/
private T parent;
/*
* the ``semi-dominator,'' which starts as the DFS number in step 1
*/
private int semiDominator;
/*
* The buckets used in step 2
*/
final private Set<T> bucket;
/*
* the labels used in the fast union-find structure
*/
private T label;
/*
* ancestor for fast union-find data structure
*/
private T ancestor;
/*
* the size used by the fast union-find structure
*/
private int size;
/*
* the child used by the fast union-find structure
*/
private T child;
DominatorInfo(T node) {
semiDominator = 0;
dominator = null;
parent = null;
bucket = HashSetFactory.make();
ancestor = null;
label = node;
size = 1;
child = null;
}
}
/*
* Look-aside table for DominatorInfo objects
*/
protected abstract DominatorInfo getInfo(T node);
private Iterator<T> iterateBucket(T node) {
return getInfo(node).bucket.iterator();
}
private void addToBucket(T node, T addend) {
getInfo(node).bucket.add(addend);
}
private T getDominator(T node) {
assert node != null;
return getInfo(node).dominator;
}
private void setDominator(T node, T dominator) {
getInfo(node).dominator = dominator;
}
private T getParent(T node) {
return getInfo(node).parent;
}
private void setParent(T node, T parent) {
getInfo(node).parent = parent;
}
private T getAncestor(T node) {
return getInfo(node).ancestor;
}
private void setAncestor(T node, T ancestor) {
getInfo(node).ancestor = ancestor;
}
private T getLabel(T node) {
if (node == null)
return null;
else
return getInfo(node).label;
}
private void setLabel(T node, T label) {
getInfo(node).label = label;
}
private int getSize(T node) {
if (node == null)
return 0;
else
return getInfo(node).size;
}
private void setSize(T node, int size) {
getInfo(node).size = size;
}
private T getChild(T node) {
return getInfo(node).child;
}
private void setChild(T node, T child) {
getInfo(node).child = child;
}
private int getSemi(T node) {
if (node == null)
return 0;
else
return getInfo(node).semiDominator;
}
private void setSemi(T node, int semi) {
getInfo(node).semiDominator = semi;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
for (Iterator<? extends T> i = G.iterator(); i.hasNext();) {
T node = i.next();
sb.append("Dominators of " + node + ":\n");
for (Iterator j = dominators(node); j.hasNext();)
sb.append(" " + j.next() + "\n");
sb.append("\n");
}
return sb.toString();
}
}

View File

@ -1,49 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.dominators;
import java.util.Map;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.graph.Graph;
/**
* Calculate dominators using Langauer and Tarjan's fastest algorithm. TOPLAS
* 1(1), July 1979. This implementation uses path compression and results in a
* O(e * alpha(e,n)) complexity, where e is the number of edges in the CFG and n
* is the number of nodes.
*
* Sources: TOPLAS article, Muchnick book
*/
public class GenericDominators<T> extends Dominators<T> {
public GenericDominators(Graph<T> G, T root)
throws IllegalArgumentException
{
super(G, root);
this.infoMap = HashMapFactory.make(G.getNumberOfNodes());
analyze();
}
/*
* Look-aside table for DominatorInfo objects
*/
private final Map<Object, DominatorInfo> infoMap;
@Override
protected DominatorInfo getInfo(T node) {
if (!infoMap.containsKey(node))
infoMap.put(node, new DominatorInfo(node));
return infoMap.get(node);
}
}

View File

@ -1,53 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.dominators;
import com.ibm.wala.util.graph.NumberedGraph;
/**
* Calculate dominators using Langauer and Tarjan's fastest algorithm. TOPLAS
* 1(1), July 1979. This implementation uses path compression and results in a
* O(e * alpha(e,n)) complexity, where e is the number of edges in the CFG and n
* is the number of nodes.
*
* Sources: TOPLAS article, Muchnick book
*/
public class NumberedDominators<T> extends Dominators<T> {
public NumberedDominators(NumberedGraph<T> G, T root) throws IllegalArgumentException {
super(G, root);
this.infoMap = new Object[G.getMaxNumber() + 1];
for (T n : G) {
infoMap[G.getNumber(n)] = new DominatorInfo(n);
}
analyze();
}
@Override
public NumberedGraph<T> getGraph() {
return (NumberedGraph<T>) G;
}
/*
* Look-aside table for DominatorInfo objects
*/
private final Object[] infoMap;
@Override
protected final DominatorInfo getInfo(T node) {
assert node != null;
return (DominatorInfo) infoMap[getGraph().getNumber(node)];
}
}

View File

@ -1,59 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.HashSet;
import java.util.Iterator;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.graph.NodeManager;
/**
* Simple implementation of a {@link NodeManager}.
*/
public class BasicNodeManager<T> implements NodeManager<T> {
final private HashSet<T> nodes = HashSetFactory.make();
public Iterator<T> iterator() {
return nodes.iterator();
}
/*
* @see com.ibm.wala.util.graph.NodeManager#getNumberOfNodes()
*/
public int getNumberOfNodes() {
return nodes.size();
}
/*
* @see com.ibm.wala.util.graph.NodeManager#addNode(com.ibm.wala.util.graph.Node)
*/
public void addNode(T n) {
nodes.add(n);
}
/*
* @see com.ibm.wala.util.graph.NodeManager#remove(com.ibm.wala.util.graph.Node)
*/
public void removeNode(T n) {
nodes.remove(n);
}
/*
* @see com.ibm.wala.util.graph.NodeManager#containsNode(com.ibm.wala.util.graph.Node)
*/
public boolean containsNode(T N) {
return nodes.contains(N);
}
}

View File

@ -1,143 +0,0 @@
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import java.util.Map;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.SimpleVector;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.UnimplementedError;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.OrderedMultiGraph;
/**
* Inefficient implementation of OrderedMultiGraph.
*
* UNDER CONSTRUCTION.
*
* @param <T> type of node in the graph
*/
public class BasicOrderedMultiGraph<T> implements OrderedMultiGraph<T> {
final Map<T, SimpleVector<T>> successorEdges = HashMapFactory.make();
private final Graph<T> delegate;
public BasicOrderedMultiGraph() {
this.delegate = SlowSparseNumberedGraph.make();
}
/**
* Add this edge, unconditionally setting it as the next successor.
*/
public void addEdge(T src, T dst) throws IllegalArgumentException {
delegate.addEdge(src, dst);
SimpleVector<T> s = successorEdges.get(src);
if (s == null) {
s = new SimpleVector<T>();
successorEdges.put(src, s);
}
s.set(s.getMaxIndex() + 1, dst);
}
public void addEdge(int i, T src, T dst) throws IllegalArgumentException {
delegate.addEdge(src, dst);
SimpleVector<T> s = successorEdges.get(src);
if (s == null) {
s = new SimpleVector<T>();
successorEdges.put(src, s);
}
s.set(i, dst);
}
public void addNode(T n) {
delegate.addNode(n);
}
public boolean containsNode(T N) {
return delegate.containsNode(N);
}
public int getNumberOfNodes() {
return delegate.getNumberOfNodes();
}
public int getPredNodeCount(T N) throws IllegalArgumentException {
return delegate.getPredNodeCount(N);
}
/**
* For now, this returns nodes in no particular order! Fix this when needed.
*/
public Iterator<T> getPredNodes(T N) throws IllegalArgumentException {
return delegate.getPredNodes(N);
}
public int getSuccNodeCount(T N) throws IllegalArgumentException {
return delegate.getSuccNodeCount(N);
}
public Iterator<T> getSuccNodes(T N) throws IllegalArgumentException {
return delegate.getSuccNodes(N);
}
public boolean hasEdge(T src, T dst) {
return delegate.hasEdge(src, dst);
}
public Iterator<T> iterator() {
return delegate.iterator();
}
public void removeAllIncidentEdges(T node) throws UnimplementedError {
Assertions.UNREACHABLE();
delegate.removeAllIncidentEdges(node);
}
public void removeEdge(T src, T dst) throws UnimplementedError {
Assertions.UNREACHABLE();
delegate.removeEdge(src, dst);
}
public void removeIncomingEdges(T node) throws UnimplementedError {
Assertions.UNREACHABLE();
delegate.removeIncomingEdges(node);
}
public void removeNode(T n) throws UnimplementedError {
Assertions.UNREACHABLE();
delegate.removeNode(n);
}
public void removeNodeAndEdges(T N) throws UnimplementedError {
Assertions.UNREACHABLE();
delegate.removeNodeAndEdges(N);
}
public void removeOutgoingEdges(T node) throws UnimplementedError {
Assertions.UNREACHABLE();
delegate.removeOutgoingEdges(node);
}
public T getSuccessor(T node, int i) throws IllegalArgumentException {
SimpleVector<T> s = successorEdges.get(node);
if (s == null) {
throw new IllegalArgumentException("no successors for node " + node);
}
if (i > s.getMaxIndex()) {
throw new IllegalArgumentException("no successor number " + i + " for " + node);
}
return s.get(i);
}
}

View File

@ -1,100 +0,0 @@
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import com.ibm.wala.util.graph.Graph;
/**
* A utility class.
*/
public class DelegatingGraph<T> implements Graph<T> {
private final Graph<T> delegate;
public DelegatingGraph(Graph<T> delegate) {
if (delegate == null) {
throw new IllegalArgumentException("delegate is null");
}
this.delegate = delegate;
}
public void addEdge(T src, T dst) throws IllegalArgumentException {
delegate.addEdge(src, dst);
}
public void addNode(T n) {
delegate.addNode(n);
}
public boolean containsNode(T N) {
return delegate.containsNode(N);
}
public int getNumberOfNodes() {
return delegate.getNumberOfNodes();
}
@Override
public String toString() {
return delegate.toString();
}
public int getPredNodeCount(T N) throws IllegalArgumentException {
return delegate.getPredNodeCount(N);
}
public Iterator<T> getPredNodes(T N) throws IllegalArgumentException {
return delegate.getPredNodes(N);
}
public int getSuccNodeCount(T N) throws IllegalArgumentException {
return delegate.getSuccNodeCount(N);
}
public Iterator<T> getSuccNodes(T N) throws IllegalArgumentException {
return delegate.getSuccNodes(N);
}
public boolean hasEdge(T src, T dst) {
return delegate.hasEdge(src, dst);
}
public Iterator<T> iterator() {
return delegate.iterator();
}
public void removeAllIncidentEdges(T node) throws IllegalArgumentException {
delegate.removeAllIncidentEdges(node);
}
public void removeEdge(T src, T dst) throws IllegalArgumentException {
delegate.removeEdge(src, dst);
}
public void removeIncomingEdges(T node) throws IllegalArgumentException {
delegate.removeIncomingEdges(node);
}
public void removeNode(T n) {
delegate.removeNode(n);
}
public void removeNodeAndEdges(T N) throws IllegalArgumentException {
delegate.removeNodeAndEdges(N);
}
public void removeOutgoingEdges(T node) throws IllegalArgumentException {
delegate.removeOutgoingEdges(node);
}
}

View File

@ -1,188 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.UnimplementedError;
import com.ibm.wala.util.graph.INodeWithNumberedEdges;
import com.ibm.wala.util.graph.NumberedEdgeManager;
import com.ibm.wala.util.intset.IntIterator;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.SparseIntSet;
/**
* An object that delegates edge management to the nodes, {@link INodeWithNumberedEdges}
*/
public class DelegatingNumberedEdgeManager<T extends INodeWithNumberedEdges> implements NumberedEdgeManager<T> {
private final DelegatingNumberedNodeManager<T> nodeManager;
public DelegatingNumberedEdgeManager(DelegatingNumberedNodeManager<T> nodeManager) {
if (nodeManager == null) {
throw new IllegalArgumentException("nodeManager is null");
}
this.nodeManager = nodeManager;
}
// TODO: optimization is possible
private class IntSetNodeIterator implements Iterator<T> {
private final IntIterator delegate;
IntSetNodeIterator(IntIterator delegate) {
this.delegate = delegate;
}
public boolean hasNext() {
return delegate.hasNext();
}
public T next() {
return nodeManager.getNode(delegate.next());
}
public void remove() {
// TODO Auto-generated method stub
Assertions.UNREACHABLE();
}
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodes(com.ibm.wala.util.graph.Node)
*/
public Iterator<T> getPredNodes(T N) throws IllegalArgumentException {
if (N == null) {
throw new IllegalArgumentException("N cannot be null");
}
INodeWithNumberedEdges en = N;
IntSet pred = en.getPredNumbers();
Iterator<T> empty = EmptyIterator.instance();
return (pred == null) ? empty : (Iterator<T>) new IntSetNodeIterator(pred.intIterator());
}
public IntSet getPredNodeNumbers(T node) {
if (node == null) {
throw new IllegalArgumentException("N cannot be null");
}
INodeWithNumberedEdges en = node;
IntSet pred = en.getPredNumbers();
return (pred == null) ? new SparseIntSet() : pred;
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodeCount(com.ibm.wala.util.graph.Node)
*/
public int getPredNodeCount(T N) throws IllegalArgumentException {
if (N == null) {
throw new IllegalArgumentException("N cannot be null");
}
INodeWithNumberedEdges en = N;
IntSet s = en.getPredNumbers();
if (s == null) {
return 0;
} else {
return s.size();
}
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(com.ibm.wala.util.graph.Node)
*/
public Iterator<T> getSuccNodes(T N) {
if (N == null) {
throw new IllegalArgumentException("N cannot be null");
}
INodeWithNumberedEdges en = N;
IntSet succ = en.getSuccNumbers();
Iterator<T> empty = EmptyIterator.instance();
return (succ == null) ? empty : (Iterator<T>) new IntSetNodeIterator(succ.intIterator());
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(com.ibm.wala.util.graph.Node)
*/
public int getSuccNodeCount(T N) {
if (N == null) {
throw new IllegalArgumentException("N is null");
}
INodeWithNumberedEdges en = N;
IntSet s = en.getSuccNumbers();
return s == null ? 0 : s.size();
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#addEdge(com.ibm.wala.util.graph.Node, com.ibm.wala.util.graph.Node)
*/
public void addEdge(T src, T dst) {
if (dst == null || src == null) {
throw new IllegalArgumentException("parameter is null");
}
src.addSucc(dst.getGraphNodeId());
dst.addPred(src.getGraphNodeId());
}
public void removeEdge(T src, T dst) throws UnimplementedError {
Assertions.UNREACHABLE("Implement me");
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(com.ibm.wala.util.graph.Node)
*/
public void removeAllIncidentEdges(T node) throws UnimplementedError {
if (node == null) {
throw new IllegalArgumentException("node is null");
}
INodeWithNumberedEdges n = node;
n.removeAllIncidentEdges();
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(com.ibm.wala.util.graph.Node)
*/
public void removeIncomingEdges(T node) throws UnimplementedError {
if (node == null) {
throw new IllegalArgumentException("node cannot be null");
}
INodeWithNumberedEdges n = node;
n.removeIncomingEdges();
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(com.ibm.wala.util.graph.Node)
*/
public void removeOutgoingEdges(T node) throws UnimplementedError {
if (node == null) {
throw new IllegalArgumentException("node cannot be null");
}
INodeWithNumberedEdges n = node;
n.removeOutgoingEdges();
}
public boolean hasEdge(T src, T dst) throws IllegalArgumentException {
if (dst == null) {
throw new IllegalArgumentException("dst == null");
}
return getSuccNodeNumbers(src).contains(dst.getGraphNodeId());
}
public IntSet getSuccNodeNumbers(T node) {
if (node == null) {
throw new IllegalArgumentException("node cannot be null");
}
INodeWithNumberedEdges en = node;
IntSet succ = en.getSuccNumbers();
return (succ == null) ? new SparseIntSet() : succ;
}
}

View File

@ -1,43 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import com.ibm.wala.util.graph.AbstractNumberedGraph;
import com.ibm.wala.util.graph.EdgeManager;
import com.ibm.wala.util.graph.INodeWithNumberedEdges;
import com.ibm.wala.util.graph.NodeManager;
/**
* Basic functionality for a graph that delegates node and edge management, and
* tracks node numbers
*/
public class DelegatingNumberedGraph<T extends INodeWithNumberedEdges> extends AbstractNumberedGraph<T> {
final private DelegatingNumberedNodeManager<T> nodeManager = new DelegatingNumberedNodeManager<T>();
final private DelegatingNumberedEdgeManager<T> edgeManager = new DelegatingNumberedEdgeManager<T>(nodeManager);
/*
* @see com.ibm.wala.util.graph.AbstractGraph#getNodeManager()
*/
@Override
protected NodeManager<T> getNodeManager() {
return nodeManager;
}
/*
* @see com.ibm.wala.util.graph.AbstractGraph#getEdgeManager()
*/
@Override
protected EdgeManager<T> getEdgeManager() {
return edgeManager;
}
}

View File

@ -1,215 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.INodeWithNumber;
import com.ibm.wala.util.graph.NumberedNodeManager;
import com.ibm.wala.util.intset.IntSet;
/**
* Basic implementation of a numbered graph -- this implementation relies on nodes that carry numbers and edges.
*
* The management of node numbers is a bit fragile, but designed this way for efficiency. Use this class with care.
*/
public class DelegatingNumberedNodeManager<T extends INodeWithNumber> implements NumberedNodeManager<T> {
private final double BUFFER_FACTOR = 1.5;
private INodeWithNumber[] nodes = new INodeWithNumber[20];
private int maxNumber = -1;
private int numberOfNodes = 0;
/*
* @see com.ibm.wala.util.graph.NumberedGraph#getNumber(com.ibm.wala.util.graph.Node)
*/
public int getNumber(T N) {
if (N == null) {
throw new IllegalArgumentException("N is null");
}
INodeWithNumber n = N;
return n.getGraphNodeId();
}
@SuppressWarnings("unchecked")
public T getNode(int number) {
try {
return (T) nodes[number];
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("Invalid number " + number);
}
}
/*
* @see com.ibm.wala.util.graph.NumberedGraph#getMaxNumber()
*/
public int getMaxNumber() {
return maxNumber;
}
/*
* @see com.ibm.wala.util.graph.Graph#iterateNodes()
*/
public Iterator<T> iterator() {
final INodeWithNumber[] arr = nodes;
return new Iterator<T>() {
int next = -1;
{
advance();
}
void advance() {
for (int i = next + 1; i < arr.length; i++) {
if (arr[i] != null) {
next = i;
return;
}
}
next = -1;
}
public boolean hasNext() {
return next != -1;
}
@SuppressWarnings("unchecked")
public T next() {
if (hasNext()) {
int r = next;
advance();
return (T) arr[r];
} else {
return null;
}
}
public void remove() {
Assertions.UNREACHABLE();
}
};
}
/*
* @see com.ibm.wala.util.graph.Graph#getNumberOfNodes()
*/
public int getNumberOfNodes() {
return numberOfNodes;
}
/**
* If N.getNumber() == -1, then set N.number and insert this node in the graph. Use with extreme care.
*
* @see com.ibm.wala.util.graph.NodeManager#addNode(java.lang.Object)
* @throws IllegalArgumentException if n is null
*/
public void addNode(T n) {
if (n == null) {
throw new IllegalArgumentException("n is null");
}
INodeWithNumber N = n;
int number = N.getGraphNodeId();
if (number == -1) {
maxNumber++;
N.setGraphNodeId(maxNumber);
number = maxNumber;
} else {
if (number > maxNumber) {
maxNumber = number;
}
}
ensureCapacity(number);
if (nodes[number] != null && nodes[number] != N) {
Assertions.UNREACHABLE("number: " + number + " N: " + N + " nodes[number]: " + nodes[number]);
}
nodes[number] = N;
numberOfNodes++;
}
/**
* @param number
*/
private void ensureCapacity(int number) {
if (nodes.length < number + 1) {
int newLength = (int) ((number + 1) * BUFFER_FACTOR);
INodeWithNumber[] old = nodes;
nodes = new INodeWithNumber[newLength];
System.arraycopy(old, 0, nodes, 0, old.length);
}
}
/*
* @see com.ibm.wala.util.graph.NodeManager#remove(com.ibm.wala.util.graph.Node)
*/
public void removeNode(T n) {
if (n == null) {
throw new IllegalArgumentException("n is null");
}
INodeWithNumber N = n;
int number = N.getGraphNodeId();
if (number == -1) {
throw new IllegalArgumentException("Cannot remove node, not in graph");
}
if (nodes[number] != null) {
nodes[number] = null;
numberOfNodes--;
}
}
@Override
public String toString() {
StringBuffer result = new StringBuffer("Nodes:\n");
for (int i = 0; i < maxNumber; i++) {
result.append(i).append(" ");
if (nodes[i] != null) {
result.append(nodes[i].toString());
}
result.append("\n");
}
return result.toString();
}
/*
* @see com.ibm.wala.util.graph.NodeManager#containsNode(com.ibm.wala.util.graph.Node)
*/
public boolean containsNode(T n) {
if (n == null) {
throw new IllegalArgumentException("n is null");
}
INodeWithNumber N = n;
int number = N.getGraphNodeId();
if (number == -1) {
return false;
}
if (number >= nodes.length) {
throw new IllegalArgumentException(
"node already has a graph node id, but is not registered there in this graph (number too big)\n"
+ "this graph implementation is fragile and won't support this kind of test\n" + n.getClass() + " : " + n);
}
if (nodes[number] != N) {
throw new IllegalArgumentException("node already has a graph node id, but is not registered there in this graph\n"
+ "this graph implementation is fragile and won't support this kind of test\n" + n.getClass() + " : " + n);
}
return true;
// return (nodes[number] == N);
}
/*
* @see com.ibm.wala.util.graph.NumberedNodeManager#iterateNodes(com.ibm.wala.util.intset.IntSet)
*/
public Iterator<T> iterateNodes(IntSet s) {
return new NumberedNodeIterator<T>(s, this);
}
}

View File

@ -1,51 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
/**
* A utility class for use by clients. Use with care ... this will be slow and a space hog.
*/
public class ExplicitEdge {
final private Object src;
final private Object dest;
public ExplicitEdge(Object src, Object dest) {
if (src == null) {
throw new IllegalArgumentException("null src");
}
if (dest == null) {
throw new IllegalArgumentException("null dest");
}
this.src = src;
this.dest = dest;
}
@Override
public String toString() {
return "<" + src + "->" + dest + ">";
}
@Override
public int hashCode() {
return src.hashCode() * 947 + dest.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass().equals(obj.getClass())) {
ExplicitEdge other = (ExplicitEdge)obj;
return src.equals(other.src) && dest.equals(other.dest);
} else {
return false;
}
}
}

View File

@ -1,33 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.NumberedGraph;
/**
* A graph view that reverses the edges in a graph
*/
public class GraphInverter {
/**
* @param G
* @return A graph view that reverses the edges in G
*/
public static <T> Graph<T> invert(final Graph<T> G) {
if (G instanceof NumberedGraph) {
return new InvertedNumberedGraph<T>((NumberedGraph<T>) G);
} else {
return new InvertedGraph<T>(G);
}
}
}

View File

@ -1,42 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import com.ibm.wala.util.graph.AbstractGraph;
import com.ibm.wala.util.graph.EdgeManager;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.NodeManager;
/**
* A graph view that reverses the edges in a graph
*/
public class InvertedGraph<T> extends AbstractGraph<T> {
final private NodeManager<T> nodes;
@Override
protected NodeManager<T> getNodeManager() {
return nodes;
}
final private EdgeManager<T> edges;
@Override
protected EdgeManager<T> getEdgeManager() {
return edges;
}
public InvertedGraph(Graph<T> G) {
nodes = G;
edges = new InvertingEdgeManager<T>(G);
}
}

View File

@ -1,43 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import com.ibm.wala.util.graph.AbstractNumberedGraph;
import com.ibm.wala.util.graph.EdgeManager;
import com.ibm.wala.util.graph.NodeManager;
import com.ibm.wala.util.graph.NumberedEdgeManager;
import com.ibm.wala.util.graph.NumberedGraph;
import com.ibm.wala.util.graph.NumberedNodeManager;
/**
* A graph view that reverses the edges in a graph
*/
public class InvertedNumberedGraph<T> extends AbstractNumberedGraph<T> {
final private NumberedNodeManager<T> nodes;
final private NumberedEdgeManager<T> edges;
@Override
protected NodeManager<T> getNodeManager() {
return nodes;
}
@Override
protected EdgeManager<T> getEdgeManager() {
return edges;
}
InvertedNumberedGraph(NumberedGraph<T> G) {
nodes = G;
edges = new InvertingNumberedEdgeManager<T>(G);
}
}

View File

@ -1,72 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import com.ibm.wala.util.graph.EdgeManager;
/**
* An edge manager that reverses the edges in a graph
*/
public class InvertingEdgeManager<T> implements EdgeManager<T> {
private final EdgeManager<T> original;
public InvertingEdgeManager(EdgeManager<T> original) {
if (original == null) {
throw new IllegalArgumentException("original is null");
}
this.original = original;
}
public Iterator<T> getPredNodes(T N) throws IllegalArgumentException {
return original.getSuccNodes(N);
}
public int getPredNodeCount(T N) throws IllegalArgumentException{
return original.getSuccNodeCount(N);
}
public Iterator<T> getSuccNodes(T N) throws IllegalArgumentException{
return original.getPredNodes(N);
}
public int getSuccNodeCount(T N) throws IllegalArgumentException{
return original.getPredNodeCount(N);
}
public void addEdge(T src, T dst)throws IllegalArgumentException {
original.addEdge(dst, src);
}
public void removeEdge(T src, T dst) throws IllegalArgumentException{
original.removeEdge(dst, src);
}
public boolean hasEdge(T src, T dst) {
return original.hasEdge(dst, src);
}
public void removeAllIncidentEdges(T node) throws IllegalArgumentException {
original.removeAllIncidentEdges(node);
}
public void removeIncomingEdges(T node) throws IllegalArgumentException{
original.removeOutgoingEdges(node);
}
public void removeOutgoingEdges(T node)throws IllegalArgumentException {
original.removeIncomingEdges(node);
}
}

View File

@ -1,80 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import com.ibm.wala.util.graph.NumberedEdgeManager;
import com.ibm.wala.util.intset.IntSet;
/**
* An edge manager that reverses the edges in a graph
*/
public class InvertingNumberedEdgeManager<T> implements NumberedEdgeManager<T> {
private final NumberedEdgeManager<T> original;
public InvertingNumberedEdgeManager(NumberedEdgeManager<T> original) {
if (original == null) {
throw new IllegalArgumentException("null original");
}
this.original = original;
}
public Iterator<T> getPredNodes(T N) throws IllegalArgumentException{
return original.getSuccNodes(N);
}
public int getPredNodeCount(T N) throws IllegalArgumentException{
return original.getSuccNodeCount(N);
}
public Iterator<T> getSuccNodes(T N) throws IllegalArgumentException{
return original.getPredNodes(N);
}
public int getSuccNodeCount(T N) throws IllegalArgumentException{
return original.getPredNodeCount(N);
}
public void addEdge(T src, T dst) throws IllegalArgumentException{
original.addEdge(dst, src);
}
public void removeEdge(T src, T dst)throws IllegalArgumentException {
original.removeEdge(dst, src);
}
public boolean hasEdge(T src, T dst) {
return original.hasEdge(dst, src);
}
public void removeAllIncidentEdges(T node) throws IllegalArgumentException{
original.removeAllIncidentEdges(node);
}
public void removeIncomingEdges(T node) throws IllegalArgumentException{
original.removeOutgoingEdges(node);
}
public void removeOutgoingEdges(T node) throws IllegalArgumentException{
original.removeIncomingEdges(node);
}
public IntSet getSuccNodeNumbers(T node) throws IllegalArgumentException{
return original.getPredNodeNumbers(node);
}
public IntSet getPredNodeNumbers(T node) throws IllegalArgumentException{
return original.getSuccNodeNumbers(node);
}
}

View File

@ -1,37 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import com.ibm.wala.util.graph.INodeWithNumber;
import com.ibm.wala.util.graph.NumberedGraph;
/**
* A node which carries it's own number; which identifies it in a {@link NumberedGraph} implementation.
*
* Note that a {@link NodeWithNumber} can live it at most one {@link NumberedGraph} at a time. The {@link NumberedGraph} will mutate
* the number here. So this is a bit fragile. Use this only if you know what you're doing.
*/
public class NodeWithNumber implements INodeWithNumber {
private int number = -1;
/**
* @return the number which identifies this node in the numbered graph
*/
public int getGraphNodeId() {
return number;
}
public void setGraphNodeId(int i) {
number = i;
}
}

View File

@ -1,111 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.UnimplementedError;
import com.ibm.wala.util.graph.INodeWithNumberedEdges;
import com.ibm.wala.util.intset.BimodalMutableIntSet;
import com.ibm.wala.util.intset.IntSet;
/**
* Simple implementation of {@link INodeWithNumberedEdges}
*/
public class NodeWithNumberedEdges extends NodeWithNumber implements INodeWithNumberedEdges {
private BimodalMutableIntSet predNumbers;
private BimodalMutableIntSet succNumbers;
public IntSet getSuccNumbers() {
return succNumbers;
}
public IntSet getPredNumbers() {
return predNumbers;
}
/**
* Note that this variable appears on the RHS of an equation.
*
* @param eqNumber
* the equation number
*/
public void addSucc(int eqNumber) {
if (succNumbers == null) {
succNumbers = new BimodalMutableIntSet();
succNumbers.add(eqNumber);
} else {
succNumbers.add(eqNumber);
}
}
/**
* Note that this variable appears on the LHS of an equation.
*
* @param eqNumber
* the equation number
*/
public void addPred(int eqNumber) {
if (predNumbers == null) {
predNumbers = new BimodalMutableIntSet();
predNumbers.add(eqNumber);
} else {
predNumbers.add(eqNumber);
}
}
/**
* remove the edge that indicates this variable is Succd by a certain equation
*
* @param eqNumber
*/
public void deleteSucc(int eqNumber) {
if (succNumbers != null) {
succNumbers.remove(eqNumber);
if (succNumbers.size() == 0) {
succNumbers = null;
}
}
}
/**
* remove the edge that indicates this variable is Predined by a certain
* equation
*
* @param eqNumber
*/
public void deletePred(int eqNumber) {
if (predNumbers != null) {
predNumbers.remove(eqNumber);
if (predNumbers.size() == 0) {
predNumbers = null;
}
}
}
/*
* @see com.ibm.wala.util.graph.INodeWithNumberedEdges#removeAllIncidentEdges()
*/
public void removeAllIncidentEdges() throws UnimplementedError {
Assertions.UNREACHABLE("Implement me");
}
public void removeIncomingEdges() throws UnimplementedError {
Assertions.UNREACHABLE("Implement me");
}
public void removeOutgoingEdges() throws UnimplementedError {
Assertions.UNREACHABLE("Implement me");
}
}

View File

@ -1,52 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.ibm.wala.util.graph.NumberedNodeManager;
import com.ibm.wala.util.intset.IntIterator;
import com.ibm.wala.util.intset.IntSet;
/**
*/
public class NumberedNodeIterator<T> implements Iterator<T> {
final IntIterator numbers;
final NumberedNodeManager<T> nodeManager;
/**
* @throws IllegalArgumentException if s is null
*/
public NumberedNodeIterator(IntSet s, NumberedNodeManager<T> nodeManager) {
if (s == null) {
throw new IllegalArgumentException("s is null");
}
this.numbers = s.intIterator();
this.nodeManager = nodeManager;
}
public boolean hasNext() {
return numbers.hasNext();
}
public T next() throws NoSuchElementException {
int i = numbers.next();
T result = nodeManager.getNode(i);
assert result != null : "null node for " + i;
return result;
}
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
}

View File

@ -1,99 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import com.ibm.wala.util.graph.NumberedNodeManager;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.MutableMapping;
/**
* An object which manages node numbers via a mapping.
*/
public class SlowNumberedNodeManager<T> implements NumberedNodeManager<T> {
/**
* A bijection between integer <-> node
*/
final private MutableMapping<T> map = MutableMapping.make();
public int getNumber(T obj) {
return map.getMappedIndex(obj);
}
public T getNode(int number) {
if (number < 0) {
throw new IllegalArgumentException("number must be >= 0");
}
T result = map.getMappedObject(number);
return result;
}
/*
* @see com.ibm.wala.util.graph.NumberedGraph#getMaxNumber()
*/
public int getMaxNumber() {
return map.getMaximumIndex();
}
public Iterator<T> iterator() {
return map.iterator();
}
public int getNumberOfNodes() {
return map.getSize();
}
public void addNode(T n) {
if (n == null) {
throw new IllegalArgumentException("n is null");
}
map.add(n);
}
/*
* @see com.ibm.wala.util.graph.NodeManager#remove(com.ibm.wala.util.graph.Node)
*/
public void removeNode(T n) {
map.deleteMappedObject(n);
}
@Override
public String toString() {
StringBuffer result = new StringBuffer("Nodes:\n");
for (int i = 0; i <= getMaxNumber(); i++) {
result.append(i).append(" ");
result.append(map.getMappedObject(i));
result.append("\n");
}
return result.toString();
}
/*
* @see com.ibm.wala.util.graph.NodeManager#containsNode(com.ibm.wala.util.graph.Node)
*/
public boolean containsNode(T N) {
return getNumber(N) != -1;
}
/*
* @see com.ibm.wala.util.graph.NumberedNodeManager#iterateNodes(com.ibm.wala.util.intset.IntSet)
*/
public Iterator<T> iterateNodes(IntSet s) {
return new NumberedNodeIterator<T>(s, this);
}
}

View File

@ -1,87 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Iterator;
import com.ibm.wala.util.graph.AbstractNumberedGraph;
import com.ibm.wala.util.graph.EdgeManager;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.NodeManager;
import com.ibm.wala.util.intset.BasicNaturalRelation;
/**
* A graph of numbered nodes, expected to have a fairly sparse edge structure.
*/
public class SlowSparseNumberedGraph<T> extends AbstractNumberedGraph<T> {
private final SlowNumberedNodeManager<T> nodeManager = new SlowNumberedNodeManager<T>();
private final SparseNumberedEdgeManager<T> edgeManager;
protected SlowSparseNumberedGraph() {
this(0);
}
/**
* If normalOutCount == n, this edge manager will eagerly allocated n words to hold out edges for each node. (performance
* optimization for time)
*
* @param normalOutCount what is the "normal" number of out edges for a node?
*/
public SlowSparseNumberedGraph(int normalOutCount) {
edgeManager = new SparseNumberedEdgeManager<T>(nodeManager, normalOutCount, BasicNaturalRelation.TWO_LEVEL);
}
/*
* @see com.ibm.wala.util.graph.AbstractGraph#getNodeManager()
*/
@Override
public NodeManager<T> getNodeManager() {
return nodeManager;
}
/*
* @see com.ibm.wala.util.graph.AbstractGraph#getEdgeManager()
*/
@Override
public EdgeManager<T> getEdgeManager() {
return edgeManager;
}
/**
* @return a graph with the same nodes and edges as g
*/
public static <T> SlowSparseNumberedGraph<T> duplicate(Graph<T> g) {
SlowSparseNumberedGraph<T> result = make();
copyInto(g, result);
return result;
}
public static <T> void copyInto(Graph<T> g, Graph<T> into) {
if (g == null) {
throw new IllegalArgumentException("g is null");
}
for (Iterator<? extends T> it = g.iterator(); it.hasNext();) {
into.addNode(it.next());
}
for (Iterator<? extends T> it = g.iterator(); it.hasNext();) {
T n = it.next();
for (Iterator<? extends T> it2 = g.getSuccNodes(n); it2.hasNext();) {
into.addEdge(n, it2.next());
}
}
}
public static <T> SlowSparseNumberedGraph<T> make() {
return new SlowSparseNumberedGraph<T>();
}
}

View File

@ -1,289 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import java.util.Arrays;
import java.util.Iterator;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.graph.NumberedEdgeManager;
import com.ibm.wala.util.graph.NumberedNodeManager;
import com.ibm.wala.util.intset.BasicNaturalRelation;
import com.ibm.wala.util.intset.BitVector;
import com.ibm.wala.util.intset.IBinaryNaturalRelation;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetAction;
/**
* An object which tracks edges for nodes that have numbers.
*/
public final class SparseNumberedEdgeManager<T> implements NumberedEdgeManager<T> {
private final NumberedNodeManager<T> nodeManager;
/**
* cache this state here for efficiency
*/
private final BitVector hasSuccessor = new BitVector();
/**
* @param nodeManager
* an object to track nodes
*/
public SparseNumberedEdgeManager(NumberedNodeManager<T> nodeManager) {
this(nodeManager, 0, BasicNaturalRelation.TWO_LEVEL);
}
/**
* If normalOutCount == n, this edge manager will eagerly allocated n words to
* hold out edges for each node. (performance optimization for time)
*
* @param nodeManager
* an object to track nodes
* @param normalCase
* what is the "normal" number of out edges for a node?
* @throws IllegalArgumentException if normalCase < 0
*/
public SparseNumberedEdgeManager(NumberedNodeManager<T> nodeManager, int normalCase, byte delegateImpl) throws IllegalArgumentException {
if (nodeManager == null) {
throw new IllegalArgumentException("null nodeManager");
}
if (normalCase < 0) {
throw new IllegalArgumentException("normalCase < 0");
}
this.nodeManager = nodeManager;
if (normalCase == 0) {
successors = new BasicNaturalRelation(defaultImpl, delegateImpl);
predecessors = new BasicNaturalRelation(defaultImpl, delegateImpl);
} else {
byte[] impl = new byte[normalCase];
Arrays.fill(impl, BasicNaturalRelation.SIMPLE);
successors = new BasicNaturalRelation(impl, delegateImpl);
predecessors = new BasicNaturalRelation(impl, delegateImpl);
}
}
/**
* The default implementation policy conservatively uses 2-level vectors, in
* an attempt to somewhat optimize for space.
*/
private final static byte[] defaultImpl = new byte[] { BasicNaturalRelation.TWO_LEVEL };
private final IBinaryNaturalRelation successors;
private final IBinaryNaturalRelation predecessors;
/*
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodes(java.lang.Object)
*/
public Iterator<T> getPredNodes(T N) throws IllegalArgumentException {
int number = nodeManager.getNumber(N);
if (number < 0) {
throw new IllegalArgumentException(N + " is not in graph");
}
IntSet s = predecessors.getRelated(number);
Iterator<T> empty = EmptyIterator.instance();
return (s == null) ? empty : nodeManager.iterateNodes(s);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodeCount(java.lang.Object)
*/
public int getPredNodeCount(T N) throws IllegalArgumentException {
int number = nodeManager.getNumber(N);
if (number < 0) {
throw new IllegalArgumentException(N + " is not in graph");
}
return predecessors.getRelatedCount(number);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(java.lang.Object)
*/
public Iterator<T> getSuccNodes(T N) throws IllegalArgumentException {
int number = nodeManager.getNumber(N);
if (number == -1) {
throw new IllegalArgumentException(N + " is not in graph");
}
IntSet s = successors.getRelated(number);
Iterator<T> empty = EmptyIterator.instance();
return (s == null) ? empty : nodeManager.iterateNodes(s);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(java.lang.Object)
*/
public Iterator<T> getSuccNodes(int number) {
IntSet s = successors.getRelated(number);
Iterator<T> empty = EmptyIterator.instance();
return (s == null) ? empty : nodeManager.iterateNodes(s);
}
public IntSet getSuccNodeNumbers(T node) throws IllegalArgumentException {
if (nodeManager.getNumber(node) < 0) {
throw new IllegalArgumentException("Node not in graph " + node);
}
return successors.getRelated(nodeManager.getNumber(node));
}
public IntSet getPredNodeNumbers(T node) throws IllegalArgumentException {
if (nodeManager.getNumber(node) < 0) {
throw new IllegalArgumentException("Node not in graph " + node);
}
return predecessors.getRelated(nodeManager.getNumber(node));
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(java.lang.Object)
*/
public int getSuccNodeCount(T N) throws IllegalArgumentException {
return getSuccNodeCount(nodeManager.getNumber(N));
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(java.lang.Object)
*/
public int getSuccNodeCount(int number) {
return successors.getRelatedCount(number);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#addEdge(java.lang.Object,
* java.lang.Object)
*/
public void addEdge(T src, T dst) throws IllegalArgumentException {
int x = nodeManager.getNumber(src);
int y = nodeManager.getNumber(dst);
if (x < 0) {
throw new IllegalArgumentException("src " + src + " is not in graph");
}
if (y < 0) {
throw new IllegalArgumentException("dst " + dst + " is not in graph");
}
predecessors.add(y, x);
successors.add(x, y);
hasSuccessor.set(x);
}
public boolean hasEdge(T src, T dst) {
int x = nodeManager.getNumber(src);
int y = nodeManager.getNumber(dst);
if (x < 0 || y < 0) {
return false;
}
return successors.contains(x, y);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(java.lang.Object)
*/
public void removeAllIncidentEdges(T node) throws IllegalArgumentException {
final int number = nodeManager.getNumber(node);
if (number < 0) {
throw new IllegalArgumentException("node not in graph: " + node);
}
IntSet succ = successors.getRelated(number);
if (succ != null) {
succ.foreach(new IntSetAction() {
public void act(int x) {
predecessors.remove(x, number);
}
});
}
IntSet pred = predecessors.getRelated(number);
if (pred != null) {
pred.foreach(new IntSetAction() {
public void act(int x) {
successors.remove(x, number);
if (successors.getRelatedCount(x) == 0) {
hasSuccessor.clear(x);
}
}
});
}
successors.removeAll(number);
hasSuccessor.clear(number);
predecessors.removeAll(number);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(java.lang.Object)
*/
public void removeIncomingEdges(T node) throws IllegalArgumentException {
final int number = nodeManager.getNumber(node);
if (number < 0) {
throw new IllegalArgumentException("node not in graph: " + node);
}
IntSet pred = predecessors.getRelated(number);
if (pred != null) {
pred.foreach(new IntSetAction() {
public void act(int x) {
successors.remove(x, number);
if (successors.getRelatedCount(x) == 0) {
hasSuccessor.clear(x);
}
}
});
}
predecessors.removeAll(number);
}
public void removeEdge(T src, T dst) throws IllegalArgumentException {
final int srcNumber = nodeManager.getNumber(src);
final int dstNumber = nodeManager.getNumber(dst);
if (srcNumber < 0) {
throw new IllegalArgumentException("src not in graph: " + src);
}
if (dstNumber < 0) {
throw new IllegalArgumentException("dst not in graph: " + dst);
}
successors.remove(srcNumber, dstNumber);
if (successors.getRelatedCount(srcNumber) == 0) {
hasSuccessor.clear(srcNumber);
}
predecessors.remove(dstNumber, srcNumber);
}
/*
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(java.lang.Object)
*/
public void removeOutgoingEdges(T node) throws IllegalArgumentException {
final int number = nodeManager.getNumber(node);
if (number < 0) {
throw new IllegalArgumentException("node not in graph: " + node);
}
IntSet succ = successors.getRelated(number);
if (succ != null) {
succ.foreach(new IntSetAction() {
public void act(int x) {
predecessors.remove(x, number);
}
});
}
successors.removeAll(number);
hasSuccessor.clear(number);
}
/**
* This is implemented as a shortcut for efficiency
*
* @return true iff that node has any successors
*/
public boolean hasAnySuccessor(int node) {
return hasSuccessor.get(node);
}
@Override
public String toString() {
return "Successors relation:\n" + successors;
}
}

View File

@ -1,64 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.impl;
import com.ibm.wala.util.graph.AbstractNumberedGraph;
import com.ibm.wala.util.graph.EdgeManager;
import com.ibm.wala.util.graph.INodeWithNumber;
import com.ibm.wala.util.graph.NodeManager;
import com.ibm.wala.util.intset.BasicNaturalRelation;
/**
* A graph of numbered nodes, expected to have a fairly sparse edge structure.
*/
public class SparseNumberedGraph<T extends INodeWithNumber> extends AbstractNumberedGraph<T> {
private final DelegatingNumberedNodeManager<T> nodeManager;
private final SparseNumberedEdgeManager<T> edgeManager;
public SparseNumberedGraph() {
nodeManager = new DelegatingNumberedNodeManager<T>();
edgeManager = new SparseNumberedEdgeManager<T>(nodeManager);
}
/**
* If normalCase == n, the s edge manager will eagerly allocated n words to hold out edges for each node. (performance
* optimization for time)
*
* @param normalCase what is the "normal" number of out edges for a node?
*/
public SparseNumberedGraph(int normalCase) {
nodeManager = new DelegatingNumberedNodeManager<T>();
edgeManager = new SparseNumberedEdgeManager<T>(nodeManager, normalCase, BasicNaturalRelation.TWO_LEVEL);
}
public SparseNumberedGraph(DelegatingNumberedNodeManager<T> nodeManager, SparseNumberedEdgeManager<T> edgeManager) {
this.nodeManager = nodeManager;
this.edgeManager = edgeManager;
}
/*
* @see com.ibm.wala.util.graph.AbstractGraph#getNodeManager()
*/
@Override
protected NodeManager<T> getNodeManager() {
return nodeManager;
}
/*
* @see com.ibm.wala.util.graph.AbstractGraph#getEdgeManager()
*/
@Override
protected EdgeManager<T> getEdgeManager() {
return edgeManager;
}
}

View File

@ -1,5 +0,0 @@
<HTML>
<BODY>
Graph implementations
</BODY>
</HTML>

View File

@ -1,104 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 Manu Sridharan and Juergen Graf
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Manu Sridharan
* Juergen Graf
*******************************************************************************/
/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html.
*
* This file is a derivative of code released by the University of
* California under the terms listed below.
*
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
* University of California (Regents). Provided that this notice and
* the following two paragraphs are included in any distribution of
* Refinement Analysis Tools or its derivative work, Regents agrees
* not to assert any of Regents' copyright rights in Refinement
* Analysis Tools against recipient for recipient's reproduction,
* preparation of derivative works, public display, public
* performance, distribution or sublicensing of Refinement Analysis
* Tools and derivative works, in source code and object code form.
* This agreement not to assert does not confer, by implication,
* estoppel, or otherwise any license or rights in any intellectual
* property of Regents, including, but not limited to, any patents
* of Regents or Regents' employees.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
package com.ibm.wala.util.graph.labeled;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.util.graph.AbstractGraph;
public abstract class AbstractLabeledGraph<T, U> extends AbstractGraph<T> implements LabeledGraph<T, U> {
/**
* @return the object which manages edges in the graph
*/
@Override
protected abstract LabeledEdgeManager<T, U> getEdgeManager();
public void addEdge(T src, T dst, U label) {
getEdgeManager().addEdge(src, dst, label);
}
public Iterator<? extends U> getPredLabels(T N) {
return getEdgeManager().getPredLabels(N);
}
public int getPredNodeCount(T N, U label) {
return getEdgeManager().getPredNodeCount(N, label);
}
public Iterator<T> getPredNodes(T N, U label) {
return getEdgeManager().getPredNodes(N, label);
}
public Iterator<? extends U> getSuccLabels(T N) {
return getEdgeManager().getSuccLabels(N);
}
public int getSuccNodeCount(T N, U label) {
return getEdgeManager().getSuccNodeCount(N, label);
}
public Iterator<? extends T> getSuccNodes(T N, U label) {
return getEdgeManager().getSuccNodes(N, label);
}
public boolean hasEdge(T src, T dst, U label) {
return getEdgeManager().hasEdge(src, dst, label);
}
public void removeEdge(T src, T dst, U label) {
getEdgeManager().removeEdge(src, dst, label);
}
public Set<? extends U> getEdgeLabels(T src, T dst) {
return getEdgeManager().getEdgeLabels(src, dst);
}
}

View File

@ -1,78 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 Juergen Graf
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Juergen Graf
*******************************************************************************/
package com.ibm.wala.util.graph.labeled;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.util.graph.AbstractNumberedGraph;
import com.ibm.wala.util.intset.IntSet;
public abstract class AbstractNumberedLabeledGraph<T, U> extends AbstractNumberedGraph<T> implements LabeledGraph<T, U> {
/**
* @return the object which manages edges in the graph
*/
@Override
protected abstract NumberedLabeledEdgeManager<T, U> getEdgeManager();
public void addEdge(T src, T dst, U label) {
getEdgeManager().addEdge(src, dst, label);
}
public Iterator<? extends U> getPredLabels(T N) {
return getEdgeManager().getPredLabels(N);
}
public int getPredNodeCount(T N, U label) {
return getEdgeManager().getPredNodeCount(N, label);
}
public Iterator<T> getPredNodes(T N, U label) {
return getEdgeManager().getPredNodes(N, label);
}
public Iterator<? extends U> getSuccLabels(T N) {
return getEdgeManager().getSuccLabels(N);
}
public int getSuccNodeCount(T N, U label) {
return getEdgeManager().getSuccNodeCount(N, label);
}
public Iterator<? extends T> getSuccNodes(T N, U label) {
return getEdgeManager().getSuccNodes(N, label);
}
public IntSet getPredNodeNumbers(T node, U label) throws IllegalArgumentException {
return getEdgeManager().getPredNodeNumbers(node, label);
}
public IntSet getSuccNodeNumbers(T node, U label) throws IllegalArgumentException {
return getEdgeManager().getSuccNodeNumbers(node, label);
}
public boolean hasEdge(T src, T dst, U label) {
return getEdgeManager().hasEdge(src, dst, label);
}
public void removeEdge(T src, T dst, U label) {
getEdgeManager().removeEdge(src, dst, label);
}
public Set<? extends U> getEdgeLabels(T src, T dst) {
return getEdgeManager().getEdgeLabels(src, dst);
}
public U getDefaultLabel() {
return getEdgeManager().getDefaultLabel();
}
}

View File

@ -1,132 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 Manu Sridharan and Juergen Graf
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Manu Sridharan
* Juergen Graf
*******************************************************************************/
/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html.
*
* This file is a derivative of code released by the University of
* California under the terms listed below.
*
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
* University of California (Regents). Provided that this notice and
* the following two paragraphs are included in any distribution of
* Refinement Analysis Tools or its derivative work, Regents agrees
* not to assert any of Regents' copyright rights in Refinement
* Analysis Tools against recipient for recipient's reproduction,
* preparation of derivative works, public display, public
* performance, distribution or sublicensing of Refinement Analysis
* Tools and derivative works, in source code and object code form.
* This agreement not to assert does not confer, by implication,
* estoppel, or otherwise any license or rights in any intellectual
* property of Regents, including, but not limited to, any patents
* of Regents or Regents' employees.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
package com.ibm.wala.util.graph.labeled;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.util.graph.EdgeManager;
/**
* An object which tracks labeled edges in a graph.
*
* @param <T> type of nodes in this graph
* @param <U> types of edge labels.
*/
public interface LabeledEdgeManager<T, U> extends EdgeManager<T> {
/**
* Sets the default object used as label for operations where no specific edge label is provided. This is due to compatibility
* with the EdgeManager interface
*/
public U getDefaultLabel();
/**
* Return an Iterator over the immediate predecessor nodes of this Node in the Graph on edges with some label.
*
* This method never returns <code>null</code>.
*
* @return an Iterator over the immediate predecessor nodes of this Node.
*/
public Iterator<T> getPredNodes(T N, U label);
/**
*
* @param N
* @return the labels on edges whose destination is N
*/
public Iterator<? extends U> getPredLabels(T N);
/**
* Return the number of {@link #getPredNodes immediate predecessor} nodes of this Node in the Graph on edges with some label.
*
* @return the number of immediate predecessor Nodes of this Node in the Graph.
*/
public int getPredNodeCount(T N, U label);
/**
* Return an Iterator over the immediate successor nodes of this Node in the Graph on edges with some label.
* <p>
* This method never returns <code>null</code>.
*
* @return an Iterator over the immediate successor Nodes of this Node.
*/
public Iterator<? extends T> getSuccNodes(T N, U label);
/**
* @return the labels on edges whose source is N
*/
public Iterator<? extends U> getSuccLabels(T N);
/**
* Return the number of {@link #getSuccNodes immediate successor} nodes of this Node in the Graph
*
* @return the number of immediate successor Nodes of this Node in the Graph.
*/
public int getSuccNodeCount(T N, U label);
/**
* adds an edge with some label
*/
public void addEdge(T src, T dst, U label);
public void removeEdge(T src, T dst, U label) throws UnsupportedOperationException;
public boolean hasEdge(T src, T dst, U label);
/**
* Returns a set of all labeled edges between node src and node dst
*
* @param src source node of the edge
* @param dst target node of the edge
* @return Set of edge labels
*/
public Set<? extends U> getEdgeLabels(T src, T dst);
}

View File

@ -1,58 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 Manu Sridharan and Juergen Graf
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Manu Sridharan
* Juergen Graf
*******************************************************************************/
/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html.
*
* This file is a derivative of code released by the University of
* California under the terms listed below.
*
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
* University of California (Regents). Provided that this notice and
* the following two paragraphs are included in any distribution of
* Refinement Analysis Tools or its derivative work, Regents agrees
* not to assert any of Regents' copyright rights in Refinement
* Analysis Tools against recipient for recipient's reproduction,
* preparation of derivative works, public display, public
* performance, distribution or sublicensing of Refinement Analysis
* Tools and derivative works, in source code and object code form.
* This agreement not to assert does not confer, by implication,
* estoppel, or otherwise any license or rights in any intellectual
* property of Regents, including, but not limited to, any patents
* of Regents or Regents' employees.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
package com.ibm.wala.util.graph.labeled;
import com.ibm.wala.util.graph.Graph;
/**
* A graph with labeled edges.
*/
public interface LabeledGraph<T, U> extends Graph<T>, LabeledEdgeManager<T, U> {
}

View File

@ -1,22 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.labeled;
import com.ibm.wala.util.graph.NumberedEdgeManager;
import com.ibm.wala.util.intset.IntSet;
public interface NumberedLabeledEdgeManager<T, U> extends LabeledEdgeManager<T, U>, NumberedEdgeManager<T> {
public IntSet getPredNodeNumbers(T node, U label) throws IllegalArgumentException;
public IntSet getSuccNodeNumbers(T node, U label) throws IllegalArgumentException;
}

View File

@ -1,81 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 Manu Sridharan and Juergen Graf
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Manu Sridharan
* Juergen Graf
*******************************************************************************/
/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html.
*
* This file is a derivative of code released by the University of
* California under the terms listed below.
*
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
* University of California (Regents). Provided that this notice and
* the following two paragraphs are included in any distribution of
* Refinement Analysis Tools or its derivative work, Regents agrees
* not to assert any of Regents' copyright rights in Refinement
* Analysis Tools against recipient for recipient's reproduction,
* preparation of derivative works, public display, public
* performance, distribution or sublicensing of Refinement Analysis
* Tools and derivative works, in source code and object code form.
* This agreement not to assert does not confer, by implication,
* estoppel, or otherwise any license or rights in any intellectual
* property of Regents, including, but not limited to, any patents
* of Regents or Regents' employees.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
package com.ibm.wala.util.graph.labeled;
import com.ibm.wala.util.graph.NodeManager;
import com.ibm.wala.util.graph.impl.SlowNumberedNodeManager;
/**
* A labeled graph implementation suitable for sparse graphs.
*/
public class SlowSparseNumberedLabeledGraph<T, U> extends AbstractNumberedLabeledGraph<T, U> {
private final SlowNumberedNodeManager<T> nodeManager;
private final SparseNumberedLabeledEdgeManager<T, U> edgeManager;
public SlowSparseNumberedLabeledGraph(U defaultLabel) {
if (defaultLabel == null) {
throw new IllegalArgumentException("null default label");
}
nodeManager = new SlowNumberedNodeManager<T>();
edgeManager = new SparseNumberedLabeledEdgeManager<T, U>(nodeManager, defaultLabel);
}
@Override
protected NumberedLabeledEdgeManager<T, U> getEdgeManager() {
return edgeManager;
}
@Override
protected NodeManager<T> getNodeManager() {
return nodeManager;
}
}

View File

@ -1,292 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 Manu Sridharan and Juergen Graf
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Manu Sridharan
* Juergen Graf
*******************************************************************************/
/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html.
*
* This file is a derivative of code released by the University of
* California under the terms listed below.
*
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
* University of California (Regents). Provided that this notice and
* the following two paragraphs are included in any distribution of
* Refinement Analysis Tools or its derivative work, Regents agrees
* not to assert any of Regents' copyright rights in Refinement
* Analysis Tools against recipient for recipient's reproduction,
* preparation of derivative works, public display, public
* performance, distribution or sublicensing of Refinement Analysis
* Tools and derivative works, in source code and object code form.
* This agreement not to assert does not confer, by implication,
* estoppel, or otherwise any license or rights in any intellectual
* property of Regents, including, but not limited to, any patents
* of Regents or Regents' employees.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
package com.ibm.wala.util.graph.labeled;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.util.collections.ArraySetMultiMap;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Iterator2Collection;
import com.ibm.wala.util.graph.NumberedNodeManager;
import com.ibm.wala.util.graph.impl.SparseNumberedEdgeManager;
import com.ibm.wala.util.intset.BitVectorIntSet;
import com.ibm.wala.util.intset.IntSet;
/**
*/
public class SparseNumberedLabeledEdgeManager<T, U> implements NumberedLabeledEdgeManager<T, U> {
/**
* the label to be attached to an edge when no label is specified
*/
private final U defaultLabel;
private final NumberedNodeManager<T> nodeManager;
/**
* maps each edge label to its own {@link SparseNumberedEdgeManager}
*/
private final Map<U, SparseNumberedEdgeManager<T>> edgeLabelToManager = HashMapFactory.make();
private final ArraySetMultiMap<T, U> nodeToPredLabels = new ArraySetMultiMap<T, U>();
private final ArraySetMultiMap<T, U> nodeToSuccLabels = new ArraySetMultiMap<T, U>();
private SparseNumberedEdgeManager<T> getManagerForLabel(U label) {
SparseNumberedEdgeManager<T> ret = edgeLabelToManager.get(label);
if (ret == null) {
ret = new SparseNumberedEdgeManager<T>(nodeManager);
edgeLabelToManager.put(label, ret);
}
return ret;
}
/*
* @see util.LabelledEdgeManager#addEdge(java.lang.Object, java.lang.Object,
* java.lang.Object)
*/
public void addEdge(T src, T dst, U label) {
nodeToSuccLabels.put(src, label);
nodeToPredLabels.put(dst, label);
getManagerForLabel(label).addEdge(src, dst);
}
/*
* @see util.LabelledEdgeManager#getPredNodeCount(java.lang.Object,
* java.lang.Object)
*/
public int getPredNodeCount(T N, U label) {
return getManagerForLabel(label).getPredNodeCount(N);
}
/*
* @see util.LabelledEdgeManager#getPredNodes(java.lang.Object,
* java.lang.Object)
*/
public Iterator<T> getPredNodes(T N, U label) {
return getManagerForLabel(label).getPredNodes(N);
}
/*
* @see util.LabelledEdgeManager#getSuccNodeCount(java.lang.Object,
* java.lang.Object)
*/
public int getSuccNodeCount(T N, U label) {
return getManagerForLabel(label).getSuccNodeCount(N);
}
/*
* @see util.LabelledEdgeManager#getSuccNodes(java.lang.Object,
* java.lang.Object)
*/
public Iterator<? extends T> getSuccNodes(T N, U label) {
return getManagerForLabel(label).getSuccNodes(N);
}
/*
* @see util.LabelledEdgeManager#hasEdge(java.lang.Object, java.lang.Object,
* java.lang.Object)
*/
public boolean hasEdge(T src, T dst, U label) {
return getManagerForLabel(label).hasEdge(src, dst);
}
/*
* (non-Javadoc)
*
* @see util.LabelledEdgeManager#removeAllIncidentEdges(java.lang.Object)
*/
public void removeAllIncidentEdges(T node) {
removeIncomingEdges(node);
removeOutgoingEdges(node);
}
/*
* @see util.LabelledEdgeManager#removeEdge(java.lang.Object,
* java.lang.Object, java.lang.Object)
*/
public void removeEdge(T src, T dst, U label) throws IllegalArgumentException {
getManagerForLabel(label).removeEdge(src, dst);
}
/*
* @see util.LabelledEdgeManager#removeIncomingEdges(java.lang.Object)
*/
public void removeIncomingEdges(T node) throws IllegalArgumentException {
for (Iterator<U> inLabelIter = nodeToPredLabels.get(node).iterator(); inLabelIter.hasNext();) {
U label = inLabelIter.next();
getManagerForLabel(label).removeIncomingEdges(node);
}
}
/*
* @see util.LabelledEdgeManager#removeOutgoingEdges(java.lang.Object)
*/
public void removeOutgoingEdges(T node) throws IllegalArgumentException {
for (Iterator<U> outLabelIter = nodeToSuccLabels.get(node).iterator(); outLabelIter.hasNext();) {
U label = outLabelIter.next();
getManagerForLabel(label).removeOutgoingEdges(node);
}
}
public SparseNumberedLabeledEdgeManager(final NumberedNodeManager<T> nodeManager, U defaultLabel) {
super();
this.defaultLabel = defaultLabel;
this.nodeManager = nodeManager;
if (defaultLabel == null) {
throw new IllegalArgumentException("null default label");
}
if (nodeManager == null) {
throw new IllegalArgumentException("null nodeManager");
}
}
public Iterator<? extends U> getPredLabels(T N) {
return nodeToPredLabels.get(N).iterator();
}
public Iterator<? extends U> getSuccLabels(T N) {
return nodeToSuccLabels.get(N).iterator();
}
public Set<? extends U> getEdgeLabels(T src, T dst) {
Set<U> labels = HashSetFactory.make();
for (U key : edgeLabelToManager.keySet()) {
if (edgeLabelToManager.get(key).hasEdge(src, dst)) {
labels.add(key);
}
}
return labels;
}
public void addEdge(T src, T dst) {
addEdge(src, dst, defaultLabel);
}
public int getPredNodeCount(T N) {
int count = 0;
for (U label : nodeToPredLabels.get(N)) {
count += getPredNodeCount(N, label);
}
return count;
}
public Iterator<T> getPredNodes(T N) {
Collection<T> preds = HashSetFactory.make();
for (U label : nodeToPredLabels.get(N)) {
preds.addAll(Iterator2Collection.toSet(getPredNodes(N, label)));
}
return preds.iterator();
}
public int getSuccNodeCount(T N) {
int count = 0;
for (U label : nodeToSuccLabels.get(N)) {
count += getSuccNodeCount(N, label);
}
return count;
}
public Iterator<T> getSuccNodes(T N) {
Collection<T> succs = HashSetFactory.make();
for (U label : nodeToSuccLabels.get(N)) {
succs.addAll(Iterator2Collection.toSet(getSuccNodes(N, label)));
}
return succs.iterator();
}
public boolean hasEdge(T src, T dst) {
return hasEdge(src, dst, defaultLabel);
}
public void removeEdge(T src, T dst) throws UnsupportedOperationException {
removeEdge(src, dst, defaultLabel);
}
public U getDefaultLabel() {
return defaultLabel;
}
public IntSet getPredNodeNumbers(T node, U label) throws IllegalArgumentException {
return getManagerForLabel(label).getPredNodeNumbers(node);
}
public IntSet getSuccNodeNumbers(T node, U label) throws IllegalArgumentException {
return getManagerForLabel(label).getSuccNodeNumbers(node);
}
public IntSet getPredNodeNumbers(T node) {
BitVectorIntSet preds = new BitVectorIntSet();
for (U label : nodeToPredLabels.get(node)) {
preds.addAll(getPredNodeNumbers(node, label));
}
return preds;
}
public IntSet getSuccNodeNumbers(T node) {
BitVectorIntSet succs = new BitVectorIntSet();
for (U label : nodeToSuccLabels.get(node)) {
succs.addAll(getSuccNodeNumbers(node, label));
}
return succs;
}
}

View File

@ -1,5 +0,0 @@
<HTML>
<BODY>
Graph interfaces
</BODY>
</HTML>

View File

@ -1,161 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.debug.UnimplementedError;
import com.ibm.wala.util.graph.Graph;
/**
* This class implements breadth-first search over a Graph, returning an Iterator of the nodes of the graph in order of discovery.
* This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by overriding the
* getConnected method.
*/
public class BFSIterator<T> implements Iterator<T> {
/**
* List of nodes as discovered
*/
final ArrayList<T> Q = new ArrayList<T>();
/**
* Set of nodes that have been visited
*/
final HashSet<T> visited = HashSetFactory.make();
/**
* index of the node currently being searched
*/
private int index = 0;
/**
* Governing Graph
*/
protected Graph<T> G;
/**
* Construct a breadth-first iterator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
* @throws IllegalArgumentException if G is null
*/
public BFSIterator(Graph<T> G, T N) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
init(G, new NonNullSingletonIterator<T>(N));
}
/**
* Construct a breadth-first enumerator across the (possibly improper) subset of nodes reachable from the nodes in the given
* enumeration.
*
* @param nodes the set of nodes from which to start searching
* @throws IllegalArgumentException if G is null
*/
public BFSIterator(Graph<T> G, Iterator<? extends T> nodes) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (nodes == null) {
throw new IllegalArgumentException("nodes is null");
}
init(G, nodes);
}
/**
* Constructor DFSFinishTimeIterator.
*
* @param G
* @throws NullPointerException if G is null
*/
public BFSIterator(Graph<T> G) throws NullPointerException {
this(G, G == null ? null : G.iterator());
}
private void init(Graph<T> G, Iterator<? extends T> nodes) {
this.G = G;
while (nodes.hasNext()) {
T o = nodes.next();
if (!visited.contains(o)) {
Q.add(o);
visited.add(o);
}
}
index = 0;
if (Q.size() > 0) {
T current = Q.get(0);
visitChildren(current);
}
}
private void visitChildren(T N) {
for (Iterator<? extends T> children = getConnected(N); children.hasNext();) {
T child = children.next();
if (!visited.contains(child)) {
Q.add(child);
visited.add(child);
}
}
}
/**
* Return whether there are any more nodes left to enumerate.
*
* @return true if there nodes left to enumerate.
*/
public boolean hasNext() {
return (Q.size() > index);
}
/**
* Find the next graph node in discover time order.
*
* @return the next graph node in discover time order.
*/
public T next() throws NoSuchElementException {
if (index >= Q.size()) {
throw new NoSuchElementException();
}
T result = Q.get(index);
index++;
if (hasNext()) {
T N = Q.get(index);
visitChildren(N);
}
return result;
}
/**
* get the out edges of a given node
*
* @param n the node of which to get the out edges
* @return the out edges
*
*/
protected Iterator<? extends T> getConnected(T n) {
return G.getSuccNodes(n);
}
/**
* @see java.util.Iterator#remove()
*/
public void remove() throws UnimplementedError {
throw new UnimplementedError();
}
}

View File

@ -1,218 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.Graph;
/**
* This class searches breadth-first for node that matches some criteria. If found, it reports a path to the first node found.
*
* This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by overriding the
* getConnected method.
*
* TODO: if finding many paths, use a dynamic programming algorithm instead of calling this repeatedly.
*/
public class BFSPathFinder<T> {
private final boolean DEBUG = false;
/**
* The graph to search
*/
final private Graph<T> G;
/**
* The Filter which defines the target set of nodes to find
*/
final private Filter<T> filter;
/**
* an enumeration of all nodes to search from
*/
final private Iterator<T> roots;
/**
* Construct a breadth-first enumerator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
*/
public BFSPathFinder(Graph<T> G, T N, Filter<T> f) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (f == null) {
throw new IllegalArgumentException("null f");
}
this.G = G;
this.roots = new NonNullSingletonIterator<T>(N);
this.filter = f;
}
/**
* Construct a breadth-first enumerator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
* @throws IllegalArgumentException if G is null
*/
public BFSPathFinder(Graph<T> G, T src, final T target) throws IllegalArgumentException {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
this.G = G;
this.roots = new NonNullSingletonIterator<T>(src);
if (!G.containsNode(src)) {
throw new IllegalArgumentException("src is not in graph " + src);
}
this.filter = new Filter<T>() {
public boolean accepts(T o) {
return target.equals(o);
}
};
}
/**
* Construct a breadth-first enumerator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
*/
public BFSPathFinder(Graph<T> G, T src, Iterator<T> targets) {
if (targets == null) {
throw new IllegalArgumentException("targets is null");
}
final Set<T> ts = HashSetFactory.make();
while (targets.hasNext()) {
ts.add(targets.next());
}
this.G = G;
this.roots = new NonNullSingletonIterator<T>(src);
this.filter = new Filter<T>() {
public boolean accepts(T o) {
return ts.contains(o);
}
};
}
/**
* Construct a breadth-first enumerator starting with any of a set of nodes in a directed graph.
*
* @param G the graph whose nodes to enumerate
*/
public BFSPathFinder(Graph<T> G, Iterator<T> sources, final T target) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (sources == null) {
throw new IllegalArgumentException("sources is null");
}
this.G = G;
this.roots = sources;
this.filter = new Filter<T>() {
public boolean accepts(T o) {
return target.equals(o);
}
};
}
/**
* Construct a breadth-first enumerator across the (possibly improper) subset of nodes reachable from the nodes in the given
* enumeration.
*
* @param nodes the set of nodes from which to start searching
*/
public BFSPathFinder(Graph<T> G, Iterator<T> nodes, Filter<T> f) {
this.G = G;
this.roots = nodes;
this.filter = f;
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (roots == null) {
throw new IllegalArgumentException("roots is null");
}
}
/**
* @return a List of nodes that specifies the first path found from a root to a node accepted by the filter. Returns null if no
* path found.
*/
public List<T> find() {
LinkedList<T> Q = new LinkedList<T>();
HashMap<Object, T> history = HashMapFactory.make();
while (roots.hasNext()) {
T next = roots.next();
Q.addLast(next);
history.put(next, null);
}
while (!Q.isEmpty()) {
T N = Q.removeFirst();
if (DEBUG) {
System.err.println(("visit " + N));
}
if (filter.accepts(N)) {
return makePath(N, history);
}
Iterator<? extends T> children = getConnected(N);
while (children.hasNext()) {
T c = children.next();
if (!history.containsKey(c)) {
Q.addLast(c);
history.put(c, N);
}
}
}
return null;
}
/**
* @return a List which represents a path in the breadth-first search to Q[i]. Q holds the nodes visited during the BFS, in order.
*/
private List<T> makePath(T node, Map<Object, T> history) {
ArrayList<T> result = new ArrayList<T>();
T n = node;
result.add(n);
while (true) {
T parent = history.get(n);
if (parent == null)
return result;
else {
result.add(parent);
n = parent;
}
}
}
/**
* get the out edges of a given node
*
* @param n the node of which to get the out edges
* @return the out edges
*
*/
protected Iterator<? extends T> getConnected(T n) {
return G.getSuccNodes(n);
}
}

View File

@ -1,193 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.Graph;
/**
* This class implements breadth-first search over a Graph, returning an Iterator of the nodes of the graph in order of discovery.
* This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by overriding the
* getConnected method.
*
* This traversal only visits nodes within k hops of a root.
*/
public class BoundedBFSIterator<T> implements Iterator<T> {
/**
* List of nodes as discovered
*/
final ArrayList<T> Q = new ArrayList<T>();
/**
* Set of nodes that have been visited
*/
final HashSet<T> visited = HashSetFactory.make();
/**
* index of the node currently being searched
*/
private int index = 0;
/**
* Governing Graph
*/
protected Graph<T> G;
/**
* limit on number of hops
*/
private final int k;
/**
* boundary[i] is the first index which represents a child that is > i hops away.
*/
private final int[] boundary;
/**
* how many hops away is the next element.
*/
private int currentHops = 0;
/**
* Construct a breadth-first iterator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
* @throws IllegalArgumentException if G is null
*/
public BoundedBFSIterator(Graph<T> G, T N, int k) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (k < 0) {
throw new IllegalArgumentException("invalid k : " + k);
}
this.k = k;
boundary = new int[k];
init(G, new NonNullSingletonIterator<T>(N));
}
/**
* Construct a breadth-first enumerator across the (possibly improper) subset of nodes reachable from the nodes in the given
* enumeration.
*
* @param G the graph whose nodes to enumerate
* @param nodes the set of nodes from which to start searching
* @throws IllegalArgumentException if G is null
*/
public BoundedBFSIterator(Graph<T> G, Iterator<? extends T> nodes, int k) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (k < 0) {
throw new IllegalArgumentException("invalid k: " + k);
}
this.k = k;
boundary = new int[k];
init(G, nodes);
}
private void init(Graph<T> G, Iterator<? extends T> nodes) {
this.G = G;
if (G.getNumberOfNodes() == 0) {
return;
}
while (nodes.hasNext()) {
T o = nodes.next();
if (!visited.contains(o)) {
Q.add(o);
visited.add(o);
}
}
index = 0;
if (Q.size() > 0) {
T current = Q.get(0);
visitChildren(current);
}
}
private void visitChildren(T N) {
if (currentHops == k) {
return;
}
if (boundary[currentHops] == 0) {
boundary[currentHops] = Q.size();
}
for (Iterator<? extends T> children = getConnected(N); children.hasNext();) {
T child = children.next();
if (!visited.contains(child)) {
Q.add(child);
visited.add(child);
}
}
}
/**
* Return whether there are any more nodes left to enumerate.
*
* @return true if there nodes left to enumerate.
*/
public boolean hasNext() {
return (Q.size() > index);
}
/**
* Find the next graph node in discover time order.
*
* @return the next graph node in discover time order.
*/
public T next() throws NoSuchElementException {
if (!hasNext()) {
throw new NoSuchElementException();
}
T result = Q.get(index);
index++;
if (currentHops < k && index == boundary[currentHops]) {
currentHops++;
}
if (hasNext()) {
T N = Q.get(index);
visitChildren(N);
}
return result;
}
/**
* get the out edges of a given node
*
* @param n the node of which to get the out edges
* @return the out edges
*
*/
protected Iterator<? extends T> getConnected(T n) {
return G.getSuccNodes(n);
}
/**
* @see java.util.Iterator#remove()
*/
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* @return the currentHops
*/
public int getCurrentHops() {
return currentHops;
}
}

View File

@ -1,215 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.collections.FilterIterator;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Iterator2Collection;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.NumberedGraph;
/**
* utilities related to depth-first search.
*/
public class DFS {
/**
* Perform a DFS starting with a particular node and return the set of all nodes visited.
*
* @param C collection of nodes to start from
* @param filter only traverse nodes that need this filter
* @throws IllegalArgumentException if C is null
*/
@SuppressWarnings("serial")
public static <T> Collection<T> getReachableNodes(final Graph<T> G, Collection<? extends T> C, final Filter filter) {
if (C == null) {
throw new IllegalArgumentException("C is null");
}
Iterator<T> dfs = new SlowDFSFinishTimeIterator<T>(G, C.iterator()) {
@Override
protected Iterator<T> getConnected(T n) {
return new FilterIterator<T>(G.getSuccNodes(n), filter);
}
};
return Iterator2Collection.toSet(dfs);
}
/**
* Perform a DFS starting with a particular node set and return the set of all nodes visited.
*
* @param G the graph containing n
* @return Set
* @throws IllegalArgumentException if C is null
*/
public static <T> Set<T> getReachableNodes(Graph<T> G, Collection<? extends T> C) {
if (C == null) {
throw new IllegalArgumentException("C is null");
}
HashSet<T> result = HashSetFactory.make();
Iterator<T> dfs = iterateFinishTime(G, C.iterator());
while (dfs.hasNext()) {
result.add(dfs.next());
}
return result;
}
/**
* Perform a DFS and return the set of all nodes visited.
*
* @param G the graph containing n
* @return Set
* @throws IllegalArgumentException if G == null
*/
public static <T> Set<T> getReachableNodes(Graph<T> G) throws IllegalArgumentException {
if (G == null) {
throw new IllegalArgumentException("G == null");
}
HashSet<T> result = HashSetFactory.make();
Iterator<T> dfs = iterateFinishTime(G);
while (dfs.hasNext()) {
result.add(dfs.next());
}
return result;
}
/**
* Perform a DFS of a graph starting with a specified node and return a sorted list of nodes. The nodes are sorted by depth first
* order.
*
* @param G a graph
* @param n the initial node
* @return a sorted set of nodes in the graph in depth first order
*/
public static <T> SortedSet<T> sortByDepthFirstOrder(Graph<T> G, T n) {
Map<T, Integer> order = HashMapFactory.make();
TreeSet<T> result = new TreeSet<T>(new DFSComparator<T>(order));
Iterator<T> dfs = iterateFinishTime(G, new NonNullSingletonIterator<T>(n));
int i = 0;
while (dfs.hasNext()) {
T nxt = dfs.next();
order.put(nxt, new Integer(i++));
result.add(nxt);
}
return result;
}
/**
* Comparator class to order the nodes in the DFS according to the depth first order
*/
static class DFSComparator<T> implements Comparator<T> {
final private Map<T, Integer> order;
DFSComparator(Map<T, Integer> order) {
this.order = order;
}
public int compare(T o1, T o2) {
// throws an exception if either argument is not a Node object
if (o1 == o2) {
return 0;
}
Integer t1 = order.get(o1);
Integer t2 = order.get(o2);
// throws an exception if either node has not been ordered
return (t1.intValue() - t2.intValue());
}
}
/**
* @param G
* @return iterator of nodes of G in order of DFS discover time
*/
public static <T> DFSDiscoverTimeIterator iterateDiscoverTime(Graph<T> G) {
if (G instanceof NumberedGraph) {
return new NumberedDFSDiscoverTimeIterator<T>((NumberedGraph<T>) G);
} else {
return new SlowDFSDiscoverTimeIterator<T>(G);
}
}
/**
* @param roots roots of traversal, in order to visit in outermost loop of DFS
* @return iterator of nodes of G in order of DFS discover time
* @throws IllegalArgumentException if roots == null
*/
public static <T> Iterator<T> iterateDiscoverTime(Graph<T> G, Iterator<T> roots) throws IllegalArgumentException {
if (roots == null) {
throw new IllegalArgumentException("roots == null");
}
if (G instanceof NumberedGraph) {
return new NumberedDFSDiscoverTimeIterator<T>((NumberedGraph<T>) G, roots);
} else {
return new SlowDFSDiscoverTimeIterator<T>(G, roots);
}
}
/**
* @param N root of traversal
* @return iterator of nodes of G in order of DFS discover time
*/
public static <T> DFSDiscoverTimeIterator<T> iterateDiscoverTime(Graph<T> G, T N) {
if (G == null) {
throw new IllegalArgumentException("G == null");
}
if (G instanceof NumberedGraph) {
return new NumberedDFSDiscoverTimeIterator<T>((NumberedGraph<T>) G, N);
} else {
return new SlowDFSDiscoverTimeIterator<T>(G, N);
}
}
/**
* @param G a graph
* @return iterator of nodes of G in order of DFS finish time
* @throws IllegalArgumentException if G == null
*/
public static <T> DFSFinishTimeIterator<T> iterateFinishTime(Graph<T> G) throws IllegalArgumentException {
if (G == null) {
throw new IllegalArgumentException("G == null");
}
if (G instanceof NumberedGraph) {
return new NumberedDFSFinishTimeIterator<T>((NumberedGraph<T>) G);
} else {
return new SlowDFSFinishTimeIterator<T>(G);
}
}
/**
* @param G a graph
* @param ie roots of traversal, in order to visit in outermost loop of DFS
* @return iterator of nodes of G in order of DFS finish time
*/
public static <T> DFSFinishTimeIterator<T> iterateFinishTime(Graph<T> G, Iterator<? extends T> ie) {
if (ie == null) {
throw new IllegalArgumentException("null ie");
}
if (G instanceof NumberedGraph) {
return new NumberedDFSFinishTimeIterator<T>((NumberedGraph<T>) G, ie);
} else {
return new SlowDFSFinishTimeIterator<T>(G, ie);
}
}
}

View File

@ -1,136 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Stack;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.debug.UnimplementedError;
import com.ibm.wala.util.graph.NumberedGraph;
/**
* This class implements depth-first search over a {@link NumberedGraph}, return an enumeration of the nodes of the graph in order of
* increasing discover time. This class follows the outNodes of the graph nodes to define the graph, but this behavior can be
* changed by overriding the getConnected method.
*/
public abstract class DFSDiscoverTimeIterator<T> extends Stack<T> implements Iterator<T> {
/**
* an enumeration of all nodes to search from
*/
private Iterator<? extends T> roots;
/**
* subclass constructors must call this!
*/
protected void init(Iterator<? extends T> nodes) {
roots = nodes;
assert nodes != null;
if (roots.hasNext()) {
T n = roots.next();
push(n);
setPendingChildren(n, getConnected(n));
}
}
/**
* subclass constructors must call this!
*/
protected void init(T N) {
init(new NonNullSingletonIterator<T>(N));
}
/**
* Return whether there are any more nodes left to enumerate.
*
* @return true if there nodes left to enumerate.
*/
public boolean hasNext() {
return (!empty());
}
abstract protected Iterator<? extends T> getPendingChildren(T n);
abstract protected void setPendingChildren(T v, Iterator<? extends T> iterator);
/**
* Find the next graph node in discover time order.
*
* @return the next graph node in discover time order.
*/
public T next() throws NoSuchElementException {
if (empty()) {
throw new NoSuchElementException();
}
// we always return the top node on the stack.
T toReturn = peek();
// compute the next node to return.
assert getPendingChildren(toReturn) != null;
do {
T stackTop = peek();
for (Iterator<? extends T> it = getPendingChildren(stackTop); it.hasNext();) {
T child = it.next();
if (getPendingChildren(child) == null) {
// found a new child.
visitEdge(stackTop, child);
setPendingChildren(child, getConnected(child));
push(child);
return toReturn;
}
}
// the following saves space by allowing the original iterator to be GCed
Iterator<T> empty = EmptyIterator.instance();
setPendingChildren(stackTop, empty);
// didn't find any new children. pop the stack and try again.
pop();
} while (!empty());
// search for the next unvisited root.
while (roots.hasNext()) {
T nextRoot = roots.next();
if (getPendingChildren(nextRoot) == null) {
push(nextRoot);
setPendingChildren(nextRoot, getConnected(nextRoot));
return toReturn;
}
}
return toReturn;
}
/**
* get the out edges of a given node
*
* @param n the node of which to get the out edges
* @return the out edges
*
*/
abstract protected Iterator<? extends T> getConnected(T n);
public void remove() throws UnimplementedError {
throw new UnimplementedError();
}
/**
* @param from source of the edge to visit
* @param to target of the edge to visit
*/
protected void visitEdge(T from, T to) {
// do nothing. subclasses will override.
}
}

View File

@ -1,140 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Stack;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.debug.UnimplementedError;
import com.ibm.wala.util.graph.Graph;
/**
* This class implements depth-first search over a {@link Graph}, return an enumeration of the nodes of the graph in order of increasing
* finishing time. This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by
* overriding the getConnected method.
*/
public abstract class DFSFinishTimeIterator<T> extends Stack<T> implements Iterator<T> {
/**
* the current next element in finishing time order
*/
private T theNextElement;
/**
* an enumeration of all nodes to search from
*/
private Iterator<? extends T> roots;
/**
* The governing graph.
*/
private Graph<T> G;
/**
* Subclasses must call this in the constructor!
*
* @param G
* @param nodes
*/
protected void init(Graph<T> G, Iterator<? extends T> nodes) {
this.G = G;
roots = nodes;
if (roots.hasNext())
theNextElement = roots.next();
}
/**
* Return whether there are any more nodes left to enumerate.
*
* @return true if there nodes left to enumerate.
*/
public boolean hasNext() {
return (!empty() || (theNextElement != null && getPendingChildren(theNextElement) == null));
}
/**
* Method getPendingChildren.
*
* @return Object
*/
abstract Iterator getPendingChildren(T n);
/**
* Method setPendingChildren.
*
* @param v
* @param iterator
*/
abstract void setPendingChildren(T v, Iterator<? extends T> iterator);
/**
* Find the next graph node in finishing time order.
*
* @return the next graph node in finishing time order.
*/
@SuppressWarnings("unchecked")
public T next() throws NoSuchElementException {
if (!hasNext()) {
throw new NoSuchElementException();
}
if (empty()) {
T v = theNextElement;
setPendingChildren(v, getConnected(v));
push(v);
}
recurse: while (!empty()) {
T v = peek();
Iterator<? extends T> pc = getPendingChildren(v);
for (Iterator<? extends T> e = pc; e.hasNext();) {
T n = e.next();
assert n != null : "null node in pc";
Iterator nChildren = getPendingChildren(n);
if (nChildren == null) {
// found a new child: recurse to it.
setPendingChildren(n, getConnected(n));
push(n);
continue recurse;
}
}
// the following saves space by allowing the original iterator to be GCed
setPendingChildren(v, (Iterator<T>) EmptyIterator.instance());
// no more children to visit: finished this vertex
while (getPendingChildren(theNextElement) != null && roots.hasNext()) {
theNextElement = roots.next();
}
return pop();
}
return null;
}
/**
* get the out edges of a given node
*
* @param n the node of which to get the out edges
* @return the out edges
*
*/
protected Iterator<? extends T> getConnected(T n) {
return G.getSuccNodes(n);
}
/**
* @see java.util.Iterator#remove()
*/
public void remove() throws UnimplementedError {
throw new UnimplementedError();
}
}

View File

@ -1,211 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.Graph;
/**
* This class searches depth-first search for node that matches some criteria. If found, it reports a path to the first node found.
*
* This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by overriding the
* getConnected method.
*/
public class DFSPathFinder<T> extends Stack<T> {
public static final long serialVersionUID = 9939900773328288L;
/**
* The graph to search
*/
final private Graph<T> G;
/**
* The Filter which defines the target set of nodes to find
*/
final private Filter<T> filter;
/**
* an enumeration of all nodes to search from
*/
final private Iterator<T> roots;
/**
* An iterator of child nodes for each node being searched
*/
final private Map<T, Iterator<? extends T>> pendingChildren = HashMapFactory.make(25);
/**
* Flag recording whether initialization has happened.
*/
private boolean initialized = false;
/**
* Construct a depth-first enumerator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
* @throws IllegalArgumentException if G is null
*/
public DFSPathFinder(Graph<T> G, T N, Filter<T> f) throws IllegalArgumentException {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (!G.containsNode(N)) {
throw new IllegalArgumentException("source node not in graph: " + N);
}
this.G = G;
this.roots = new NonNullSingletonIterator<T>(N);
this.filter = f;
}
/**
* Construct a depth-first enumerator across the (possibly improper) subset of nodes reachable from the nodes in the given
* enumeration.
*
* @param nodes the set of nodes from which to start searching
*/
public DFSPathFinder(Graph<T> G, Iterator<T> nodes, Filter<T> f) {
this.G = G;
this.roots = nodes;
this.filter = f;
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (roots == null) {
throw new IllegalArgumentException("roots is null");
}
if (filter == null) {
throw new IllegalArgumentException("filter is null");
}
}
private void init() {
initialized = true;
if (roots.hasNext()) {
T n = roots.next();
push(n);
setPendingChildren(n, getConnected(n));
}
}
/**
* @return a List of nodes that specifies the first path found from a root to a node accepted by the filter. Returns null if no
* path found.
*/
public List<T> find() {
if (!initialized) {
init();
}
while (hasNext()) {
T n = peek();
if (filter.accepts(n)) {
List<T> path = currentPath();
advance();
return path;
}
advance();
}
return null;
}
private List<T> currentPath() {
ArrayList<T> result = new ArrayList<T>();
for (Iterator<T> path = iterator(); path.hasNext();) {
result.add(0, path.next());
}
return result;
}
/**
* Return whether there are any more nodes left to enumerate.
*
* @return true if there nodes left to enumerate.
*/
public boolean hasNext() {
return (!empty());
}
/**
* Method getPendingChildren.
*
* @return Object
*/
private Iterator<? extends T> getPendingChildren(T n) {
return pendingChildren.get(n);
}
/**
* Method setPendingChildren.
*
* @param v
* @param iterator
*/
private void setPendingChildren(T v, Iterator<? extends T> iterator) {
pendingChildren.put(v, iterator);
}
/**
* Advance to the next graph node in discover time order.
*/
private void advance() {
// we always return the top node on the stack.
T currentNode = peek();
// compute the next node to return.
assert getPendingChildren(currentNode) != null;
do {
T stackTop = peek();
for (Iterator<? extends T> it = getPendingChildren(stackTop); it.hasNext();) {
T child = it.next();
if (getPendingChildren(child) == null) {
// found a new child.
setPendingChildren(child, getConnected(child));
push(child);
return;
}
}
// didn't find any new children. pop the stack and try again.
pop();
} while (!empty());
// search for the next unvisited root.
while (roots.hasNext()) {
T nextRoot = roots.next();
if (getPendingChildren(nextRoot) == null) {
push(nextRoot);
setPendingChildren(nextRoot, getConnected(nextRoot));
}
}
return;
}
/**
* get the out edges of a given node
*
* @param n the node of which to get the out edges
* @return the out edges
*
*/
protected Iterator<? extends T> getConnected(T n) {
return G.getSuccNodes(n);
}
}

View File

@ -1,184 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002-2010 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import com.ibm.wala.util.graph.NumberedGraph;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetAction;
import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.MutableIntSet;
public class FloydWarshall<T> {
public interface GetPath<T> {
List<T> getPath(T from, T to);
}
public interface GetPaths<T> {
Set<List<T>> getPaths(T from, T to);
}
protected final NumberedGraph<T> G;
public FloydWarshall(NumberedGraph<T> g) {
G = g;
}
protected int edgeCost(int from, int to) {
return 1;
}
protected void pathCallback(int i, int j, int k) {
}
int[][] allPairsShortestPaths() {
final int[][] result = new int[G.getNumberOfNodes()][G.getNumberOfNodes()];
for(int i = 0; i < result.length; i++) {
for(int j = 0; j < result[i].length; j++) {
result[i][j] = Integer.MAX_VALUE;
}
}
for(T from : G) {
final int fn = G.getNumber(from);
IntSet tos = G.getSuccNodeNumbers(from);
tos.foreach(new IntSetAction() {
public void act(int x) {
result[fn][x] = edgeCost(fn, x);
}
});
}
for(T kn : G) {
int k = G.getNumber(kn);
for(T in : G) {
int i = G.getNumber(in);
for(T jn : G) {
int j = G.getNumber(jn);
long newLen = (long)result[i][k] + (long)result[k][j];
if (newLen <= result[i][j]) {
pathCallback(i, j, k);
}
if (newLen < result[i][j]) {
result[i][j] = (int)newLen;
}
}
}
}
return result;
}
public static <T> int[][] shortestPathLengths(NumberedGraph<T> G) {
return new FloydWarshall<T>(G).allPairsShortestPaths();
}
public static <T> GetPath<T> allPairsShortestPath(final NumberedGraph<T> G) {
return new FloydWarshall<T>(G) {
int[][] next = new int[G.getNumberOfNodes()][G.getNumberOfNodes()];
@Override
protected void pathCallback(int i, int j, int k) {
next[i][j] = k;
}
private GetPath<T> doit() {
for(int i = 0; i < next.length; i++) {
for(int j = 0; j < next[i].length; j++) {
next[i][j] = -1;
}
}
final int[][] paths = allPairsShortestPaths();
return new GetPath<T>() {
public List<T> getPath(T from, T to) {
int fn = G.getNumber(from);
int tn = G.getNumber(to);
if (paths[fn][tn] == Integer.MAX_VALUE) {
throw new UnsupportedOperationException("no path from " + from + " to " + to);
} else {
int intermediate = next[fn][tn];
if (intermediate == -1) {
return Collections.emptyList();
} else {
T in = G.getNode(intermediate);
List<T> result = new LinkedList<T>(getPath(from, in));
result.add(in);
result.addAll(getPath(in, to));
return result;
}
}
}
};
}
}.doit();
}
public static <T> GetPaths<T> allPairsShortestPaths(final NumberedGraph<T> G) {
return new FloydWarshall<T>(G) {
MutableIntSet[][] next = new MutableIntSet[G.getNumberOfNodes()][G.getNumberOfNodes()];
@Override
protected void pathCallback(int i, int j, int k) {
if (next[i][j] == null) {
next[i][j] = IntSetUtil.make();
}
next[i][j].add(k);
}
private GetPaths<T> doit() {
final int[][] paths = allPairsShortestPaths();
return new GetPaths<T>() {
public Set<List<T>> getPaths(final T from, final T to) {
int fn = G.getNumber(from);
int tn = G.getNumber(to);
if (paths[fn][tn] == Integer.MAX_VALUE) {
throw new UnsupportedOperationException("no path from " + from + " to " + to);
} else {
MutableIntSet intermediate = next[fn][tn];
if (intermediate == null) {
List<T> none = Collections.emptyList();
return Collections.singleton(none);
} else {
final Set<List<T>> result = new HashSet<List<T>>();
intermediate.foreach(new IntSetAction() {
public void act(int x) {
T in = G.getNode(x);
for(List<T> pre : getPaths(from, in)) {
for(List<T> post : getPaths(in, to)) {
List<T> path = new LinkedList<T>(pre);
path.add(in);
path.addAll(post);
result.add(path);
}
}
}
});
return result;
}
}
}
};
}
}.doit();
}
}

View File

@ -1,36 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import com.ibm.wala.util.graph.Graph;
abstract class GraphDFSDiscoverTimeIterator<T> extends DFSDiscoverTimeIterator<T> {
/**
* the graph being searched
*/
private Graph<T> G;
protected void init(Graph<T> G, Iterator<? extends T> nodes) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
this.G = G;
super.init(nodes);
}
@Override
protected Iterator<? extends T> getConnected(T n) {
return G.getSuccNodes(n);
}
}

View File

@ -1,106 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.NumberedGraph;
/**
* This class implements depth-first search over a NumberedGraph, return an enumeration of the nodes of the graph in order of
* increasing discover time. This class follows the outNodes of the graph nodes to define the graph, but this behavior can be
* changed by overriding the getConnected method.
*/
public class NumberedDFSDiscoverTimeIterator<T> extends GraphDFSDiscoverTimeIterator<T> implements Iterator<T> {
private static final long serialVersionUID = -3919708273323217304L;
/**
* An iterator of child nodes for each node being searched
*/
private final Iterator<? extends T>[] pendingChildren;
/**
* The Graph being traversed
*/
protected final NumberedGraph<T> G;
/**
* Construct a depth-first enumerator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
* @throws IllegalArgumentException if G is null
*/
@SuppressWarnings("unchecked")
public NumberedDFSDiscoverTimeIterator(NumberedGraph<T> G, T N) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
this.G = G;
pendingChildren = new Iterator[G.getMaxNumber() + 1];
init(G, new NonNullSingletonIterator<T>(N));
}
/**
* Construct a depth-first enumerator across the (possibly improper) subset of nodes reachable from the nodes in the given
* enumeration.
*
* @param G the graph whose nodes to enumerate
* @param nodes the set of nodes from which to start searching
* @throws IllegalArgumentException if G is null
* @throws IllegalArgumentException if nodes == null
*/
@SuppressWarnings("unchecked")
public NumberedDFSDiscoverTimeIterator(NumberedGraph<T> G, Iterator<? extends T> nodes) throws IllegalArgumentException {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (nodes == null) {
throw new IllegalArgumentException("nodes == null");
}
this.G = G;
pendingChildren = new Iterator[G.getMaxNumber() + 1];
init(G, nodes);
}
/**
* Constructor DFSFinishTimeIterator.
*
* @param G
* @throws NullPointerException if G is null
*/
public NumberedDFSDiscoverTimeIterator(NumberedGraph<T> G) throws NullPointerException {
this(G, G == null ? null : G.iterator());
}
/**
* Method getPendingChildren.
*
* @return Object
*/
@Override
protected Iterator<? extends T> getPendingChildren(T n) {
return pendingChildren[G.getNumber(n)];
}
/**
* Method setPendingChildren.
*
* @param v
* @param iterator
*/
@Override
protected void setPendingChildren(T v, Iterator<? extends T> iterator) {
pendingChildren[G.getNumber(v)] = iterator;
}
}

View File

@ -1,95 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.NumberedGraph;
/**
* This class implements depth-first search over a NumberedGraph, return an enumeration of the nodes of the graph in order of
* increasing discover time. This class follows the outNodes of the graph nodes to define the graph, but this behavior can be
* changed by overriding the getConnected method.
*/
public class NumberedDFSFinishTimeIterator<T> extends DFSFinishTimeIterator<T> implements Iterator<T> {
public static final long serialVersionUID = 8737376661L;
/**
* An iterator of child nodes for each node being searched
*/
private Iterator[] pendingChildren;
/**
* The Graph being traversed
*/
private final NumberedGraph<T> G;
/**
* Construct a depth-first enumerator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
*/
NumberedDFSFinishTimeIterator(NumberedGraph<T> G, T N) {
this.G = G;
pendingChildren = new Iterator[G.getMaxNumber() + 1];
init(G, new NonNullSingletonIterator<T>(N));
}
/**
* Construct a depth-first enumerator across the (possibly improper) subset of nodes reachable from the nodes in the given
* enumeration.
*
* @param G the graph whose nodes to enumerate
* @param nodes the set of nodes from which to start searching
*/
NumberedDFSFinishTimeIterator(NumberedGraph<T> G, Iterator<? extends T> nodes) {
this.G = G;
pendingChildren = new Iterator[G.getMaxNumber() + 1];
init(G, nodes);
}
/**
* Constructor DFSFinishTimeIterator.
*
* @param G
*/
NumberedDFSFinishTimeIterator(NumberedGraph<T> G) {
this(G, G.iterator());
}
@Override
Iterator getPendingChildren(T n) {
int number = G.getNumber(n);
if (number >= pendingChildren.length) {
// the graph is probably growing as we travserse
Iterator[] old = pendingChildren;
pendingChildren = new Iterator[number * 2];
System.arraycopy(old, 0, pendingChildren, 0, old.length);
return null;
}
if (number < 0) {
assert false : "negative number for " + n + " " + n.getClass();
}
return pendingChildren[number];
}
/**
* Method setPendingChildren.
*
* @param v
* @param iterator
*/
@Override
void setPendingChildren(T v, Iterator<? extends T> iterator) {
pendingChildren[G.getNumber(v)] = iterator;
}
}

View File

@ -1,85 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.ReverseIterator;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.impl.GraphInverter;
/**
* This class computes strongly connected components for a Graph (or a subset of
* it). It does not store the SCCs in any lookaside structure, but rather simply
* generates an enumeration of them. See Cormen, Leiserson, Rivest Ch. 23 Sec. 5
*/
public class SCCIterator<T> implements Iterator<Set<T>> {
/**
* The second DFS (the reverse one) needed while computing SCCs
*/
final private DFSFinishTimeIterator<T> rev;
/**
* Construct an enumeration across the SCCs of a given graph.
*
* @param G
* The graph over which to construct SCCs
* @throws NullPointerException if G is null
*/
public SCCIterator(Graph<T> G) throws NullPointerException {
this(G, G == null ? null : G.iterator());
}
/**
* Construct an enumeration of the SCCs of the subset of a given graph
* determined by starting at a given set of nodes.
*/
public SCCIterator(Graph<T> G, Iterator<T> nodes) {
if (G == null) {
throw new IllegalArgumentException("G cannot be null");
}
Iterator<T> reverseFinishTime = ReverseIterator.reverse(DFS.iterateFinishTime(G, nodes));
rev = DFS.iterateFinishTime(GraphInverter.invert(G), reverseFinishTime);
}
/**
* Determine whether there are any more SCCs remaining in this enumeration.
*/
public boolean hasNext() {
return rev.hasNext();
}
/**
* Find the next SCC in this enumeration
*/
public Set<T> next() throws NoSuchElementException {
Set<T> currentSCC = HashSetFactory.make();
T v = rev.next();
currentSCC.add(v);
while (rev.hasNext() && !rev.isEmpty()) {
currentSCC.add(rev.next());
}
return currentSCC;
}
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
}

View File

@ -1,90 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import java.util.Map;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.Graph;
/**
* This class implements depth-first search over a Graph, return an enumeration of the nodes of the graph in order of increasing
* discover time. This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by
* overriding the getConnected method.
*/
public class SlowDFSDiscoverTimeIterator<T> extends GraphDFSDiscoverTimeIterator<T> implements Iterator<T> {
public static final long serialVersionUID = 9439217987188L;
/**
* An iterator of child nodes for each node being searched A Map: Node -> Iterator
*/
final private Map<T, Iterator<? extends T>> pendingChildren = HashMapFactory.make(25);
/**
* For use with extreme care by subclasses that know what they're doing.
*/
protected SlowDFSDiscoverTimeIterator() {
}
/**
* Construct a depth-first enumerator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
*/
public SlowDFSDiscoverTimeIterator(Graph<T> G, T N) {
init(G, new NonNullSingletonIterator<T>(N));
}
/**
* Construct a depth-first enumerator across the (possibly improper) subset of nodes reachable from the nodes in the given
* enumeration.
*
* @param G the graph whose nodes to enumerate
* @param nodes the set of nodes from which to start searching
*/
public SlowDFSDiscoverTimeIterator(Graph<T> G, Iterator<T> nodes) {
if (nodes == null) {
throw new IllegalArgumentException("null nodes");
}
init(G, nodes);
}
/**
* Constructor SlowDFSDiscoverTimeIterator.
*
* @param G
* @throws NullPointerException if G is null
*/
public SlowDFSDiscoverTimeIterator(Graph<T> G) throws NullPointerException {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
init(G, G.iterator());
}
@Override
protected Iterator<? extends T> getPendingChildren(Object n) {
return pendingChildren.get(n);
}
/**
* Method setPendingChildren.
*
* @param v
* @param iterator
*/
@Override
protected void setPendingChildren(T v, Iterator<? extends T> iterator) {
pendingChildren.put(v, iterator);
}
}

View File

@ -1,83 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import java.util.Map;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.graph.Graph;
/**
* This class implements depth-first search over a Graph, return an enumeration of the nodes of the graph in order of increasing
* finishing time. This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by
* overriding the getConnected method.
*/
public class SlowDFSFinishTimeIterator<T> extends DFSFinishTimeIterator<T> {
public static final long serialVersionUID = 3903190104743762628L;
/**
* An iterator of child nodes for each node being searched
*/
final private Map<T, Iterator<? extends T>> pendingChildren = HashMapFactory.make(25);
/**
* Construct a depth-first enumerator starting with a particular node in a directed graph.
*
* @param G the graph whose nodes to enumerate
* @throws IllegalArgumentException if G is null
*/
public SlowDFSFinishTimeIterator(Graph<T> G, T N) throws IllegalArgumentException {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (!G.containsNode(N)) {
throw new IllegalArgumentException("source node not in graph: " + N);
}
init(G, new NonNullSingletonIterator<T>(N));
}
/**
* Construct a depth-first enumerator across the (possibly improper) subset of nodes reachable from the nodes in the given
* enumeration.
*
* @param G the graph whose nodes to enumerate
* @param nodes the set of nodes from which to start searching
*/
public SlowDFSFinishTimeIterator(Graph<T> G, Iterator<? extends T> nodes) {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
if (nodes == null) {
throw new IllegalArgumentException("G is null");
}
init(G, nodes);
}
/**
* @throws NullPointerException if G is null
*/
public SlowDFSFinishTimeIterator(Graph<T> G) throws NullPointerException {
this(G, G == null ? null : G.iterator());
}
@Override
Iterator<? extends T> getPendingChildren(T n) {
return pendingChildren.get(n);
}
@Override
void setPendingChildren(T v, Iterator<? extends T> iterator) {
pendingChildren.put(v, iterator);
}
}

View File

@ -1,54 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.Iterator;
import com.ibm.wala.util.collections.ReverseIterator;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.impl.GraphInverter;
/**
* Utilities for iterating over graphs in topological order.
*/
public class Topological {
/**
* Build an Iterator over all the nodes in the graph, in an order such that SCCs are visited in topological order.
*
* @throws IllegalArgumentException if graph == null
*/
public static <T> Iterator<T> makeTopologicalIter(Graph<T> graph) throws IllegalArgumentException {
// the following code ensures a topological order over SCCs.
// note that the first two lines of the following give a topological
// order for dags, but that can get screwed up by cycles. so
// instead, we use Tarjan's SCC algorithm, which happens to
// visit nodes in an order consistent with a top. order over SCCs.
if (graph == null) {
throw new IllegalArgumentException("graph == null");
}
// finish time is post-order
// note that if you pay attention only to the first representative
// of each SCC discovered, we have a top. order of these SCC
// representatives
Iterator<T> finishTime = DFS.iterateFinishTime(graph);
// reverse postorder is usual topological sort.
Iterator<T> rev = ReverseIterator.reverse(finishTime);
// the following statement helps out the GC; note that finishTime holds
// on to a large array
finishTime = null;
Graph<T> G_T = GraphInverter.invert(graph);
Iterator<T> order = DFS.iterateFinishTime(G_T, rev);
return order;
}
}

View File

@ -1,5 +0,0 @@
<HTML>
<BODY>
Graph traversal algorithms
</BODY>
</HTML>