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

qilin.util.graph.Reachability Maven / Gradle / Ivy

/* Qilin - a Java Pointer Analysis Framework
 * Copyright (C) 2021-2030 Qilin developers
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3.0 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 */

package qilin.util.graph;

import java.util.*;

public class Reachability {
  private final DirectedGraph graph;
  private final Map> reachableNodes;
  private final Map> reachToNodes;

  public Reachability(final DirectedGraph graph) {
    this.reachableNodes = new HashMap<>();
    this.reachToNodes = new HashMap<>();
    this.graph = graph;
  }

  public Set reachableNodesFrom(final N source) {
    if (!this.reachableNodes.containsKey(source)) {
      final Set visited = new HashSet<>();
      final Deque stack = new ArrayDeque<>();
      stack.push(source);
      while (!stack.isEmpty()) {
        final N node = stack.pop();
        visited.add(node);
        this.graph.succsOf(node).stream().filter(n -> !visited.contains(n)).forEach(stack::push);
      }
      this.reachableNodes.put(source, visited);
    }
    return this.reachableNodes.get(source);
  }

  public Set nodesReach(final N target) {
    if (!this.reachToNodes.containsKey(target)) {
      final Set visited = new HashSet<>();
      final Deque stack = new ArrayDeque<>();
      stack.push(target);
      while (!stack.isEmpty()) {
        final N node = stack.pop();
        visited.add(node);
        this.graph.predsOf(node).stream().filter(n -> !visited.contains(n)).forEach(stack::push);
      }
      this.reachToNodes.put(target, visited);
    }
    return this.reachToNodes.get(target);
  }

  public Set passedNodes(final N source, final N target) {
    final Set reachableFromSource = this.reachableNodesFrom(source);
    final Set reachToTarget = this.nodesReach(target);
    final Set ret = new HashSet<>(reachableFromSource);
    ret.retainAll(reachToTarget);
    return ret;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy