qilin.util.graph.SCCMergedGraph 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 SCCMergedGraph implements DirectedGraph> {
private Set> nodes;
private final Map> nodeMap = new HashMap<>();
public SCCMergedGraph(final DirectedGraph graph) {
this.init(graph);
}
public MergedNode getMergedNode(N contentNode) {
return nodeMap.get(contentNode);
}
@Override
public Collection> allNodes() {
return this.nodes;
}
@Override
public Collection> predsOf(final MergedNode node) {
return node.getPreds();
}
@Override
public Collection> succsOf(final MergedNode node) {
return node.getSuccs();
}
private void init(final DirectedGraph graph) {
this.nodes = new HashSet<>();
final StronglyConnectedComponents scc = new StronglyConnectedComponents<>(graph);
scc.getComponents()
.forEach(
component -> {
final MergedNode node2 = new MergedNode<>(component);
component.forEach(n -> nodeMap.put(n, node2));
this.nodes.add(node2);
});
this.nodes.forEach(
node ->
node.getContent().stream()
.map(graph::succsOf)
.flatMap(Collection::stream)
.map(nodeMap::get)
.filter(succ -> succ != node)
.forEach(
succ -> {
node.addSucc(succ);
succ.addPred(node);
}));
}
}