All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.wala.util.graph.traverse.DFS Maven / Gradle / Ivy

The newest version!
/*
 * 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.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;
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 java.util.function.Predicate;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;

/** 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  Collection getReachableNodes(
      final Graph G, Collection C, final Predicate filter) {
    if (C == null) {
      throw new IllegalArgumentException("C is null");
    }
    Iterator dfs =
        new SlowDFSFinishTimeIterator<>(G, C.iterator()) {

          @Override
          protected Iterator getConnected(@Nullable T n) {
            return new FilterIterator<>(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  Set getReachableNodes(Graph G, Collection C) {
    if (C == null) {
      throw new IllegalArgumentException("C is null");
    }
    HashSet result = HashSetFactory.make();
    Iterator 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  Set getReachableNodes(Graph G) throws IllegalArgumentException {
    if (G == null) {
      throw new IllegalArgumentException("G == null");
    }
    HashSet result = HashSetFactory.make();
    Iterator 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  SortedSet sortByDepthFirstOrder(Graph G, T n) {
    Map order = HashMapFactory.make();
    TreeSet result = new TreeSet<>(new DFSComparator<>(order));

    Iterator dfs = iterateFinishTime(G, new NonNullSingletonIterator<>(n));
    int i = 0;
    while (dfs.hasNext()) {
      T nxt = dfs.next();
      order.put(nxt, i++);
      result.add(nxt);
    }
    return result;
  }

  /** Comparator class to order the nodes in the DFS according to the depth first order */
  static class DFSComparator implements Comparator {
    private final Map order;

    DFSComparator(Map order) {
      this.order = order;
    }

    @NullUnmarked
    @Override
    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 - t2);
    }
  }

  /**
   * @return iterator of nodes of G in order of DFS discover time
   */
  public static  DFSDiscoverTimeIterator iterateDiscoverTime(Graph G) {
    if (G instanceof NumberedGraph) {
      return new NumberedDFSDiscoverTimeIterator<>((NumberedGraph) G);
    } else {
      return new SlowDFSDiscoverTimeIterator<>(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  Iterator iterateDiscoverTime(Graph G, Iterator roots)
      throws IllegalArgumentException {
    if (roots == null) {
      throw new IllegalArgumentException("roots == null");
    }
    if (G instanceof NumberedGraph) {
      return new NumberedDFSDiscoverTimeIterator<>((NumberedGraph) G, roots);
    } else {
      return new SlowDFSDiscoverTimeIterator<>(G, roots);
    }
  }

  /**
   * @param N root of traversal
   * @return iterator of nodes of G in order of DFS discover time
   */
  public static  DFSDiscoverTimeIterator iterateDiscoverTime(Graph G, T N) {
    if (G == null) {
      throw new IllegalArgumentException("G == null");
    }
    if (G instanceof NumberedGraph) {
      return new NumberedDFSDiscoverTimeIterator<>((NumberedGraph) G, N);
    } else {
      return new SlowDFSDiscoverTimeIterator<>(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  DFSFinishTimeIterator iterateFinishTime(Graph G)
      throws IllegalArgumentException {
    if (G == null) {
      throw new IllegalArgumentException("G == null");
    }
    if (G instanceof NumberedGraph) {
      return new NumberedDFSFinishTimeIterator<>((NumberedGraph) G);
    } else {
      return new SlowDFSFinishTimeIterator<>(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  DFSFinishTimeIterator iterateFinishTime(
      Graph G, @Nullable Iterator ie) {
    if (ie == null) {
      throw new IllegalArgumentException("null ie");
    }
    if (G instanceof NumberedGraph) {
      return new NumberedDFSFinishTimeIterator<>((NumberedGraph) G, ie);
    } else {
      return new SlowDFSFinishTimeIterator<>(G, ie);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy