com.ibm.wala.util.graph.traverse.BFSPathFinder Maven / Gradle / Ivy
Show all versions of com.ibm.wala.util Show documentation
/*
* 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 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 java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;
/**
* 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 {
private final boolean DEBUG = false;
/** The graph to search */
private final Graph G;
/** The Filter which defines the target set of nodes to find */
private final Predicate filter;
/** an enumeration of all nodes to search from */
private final Iterator 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 G, T N, Predicate 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<>(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 G, T src, final T target) throws IllegalArgumentException {
if (G == null) {
throw new IllegalArgumentException("G is null");
}
this.G = G;
this.roots = new NonNullSingletonIterator<>(src);
if (!G.containsNode(src)) {
throw new IllegalArgumentException("src is not in graph " + src);
}
this.filter = target::equals;
}
/**
* 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 G, T src, Iterator targets) {
if (targets == null) {
throw new IllegalArgumentException("targets is null");
}
final Set ts = HashSetFactory.make();
while (targets.hasNext()) {
ts.add(targets.next());
}
this.G = G;
this.roots = new NonNullSingletonIterator<>(src);
this.filter = ts::contains;
}
/**
* 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 G, Iterator 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 = target::equals;
}
/**
* 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 G, Iterator nodes, Predicate 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");
}
}
private @Nullable ArrayDeque Q = null;
private @Nullable HashMap