fr.lirmm.graphik.util.graph.scc.StronglyConnectedComponentsGraph Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of integraal-graal-ruleset-analysis Show documentation
Show all versions of integraal-graal-ruleset-analysis Show documentation
Rule base analysis for InteGraal. This is imported from Graal
The newest version!
/*
* Copyright (C) Inria Sophia Antipolis - Méditerranée / LIRMM
* (Université de Montpellier & CNRS) (2014 - 2017)
*
* Contributors :
*
* Clément SIPIETER
* Mélanie KÖNIG
* Swan ROCHER
* Jean-François BAGET
* Michel LECLÈRE
* Marie-Laure MUGNIER
*
*
* This file is part of Graal .
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
/**
*
*/
package fr.lirmm.graphik.util.graph.scc;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.jgrapht.Graph;
import org.jgrapht.alg.connectivity.GabowStrongConnectivityInspector;
import org.jgrapht.graph.DefaultDirectedGraph;
/**
* The StronglyConnectedComponentsGraph represents a graph of strongly connected
* components of an other graph.
*
* @author Clément Sipieter (INRIA) {@literal }
*
*/
public class StronglyConnectedComponentsGraph extends
DefaultDirectedGraph {
private static final long serialVersionUID = -2816870306827502776L;
private int edgeMaxIndex = -1;
private final Map> map = new TreeMap>();
public StronglyConnectedComponentsGraph() {
super(Integer.class);
}
/**
* Construct the StronglyConnectedComponentsGraph of the specified graph
*
* @param graph
*/
public StronglyConnectedComponentsGraph(Graph graph) {
this();
List> stronglyConnectedSets = new GabowStrongConnectivityInspector(graph).stronglyConnectedSets();
// add components
int componentIndex = -1;
for (Set component : stronglyConnectedSets) {
++componentIndex;
this.addComponent(componentIndex, component);
}
// construct the graph
for (int src : this.vertexSet()) {
for (int target : this.vertexSet()) {
if (src != target) {
for (V s : this.getComponent(src)) {
for (V t : this.getComponent(target)) {
if (graph.getEdge(s, t) != null) {
this.addEdge(src, target);
break;
}
}
if (this.getEdge(src, target) != null)
break;
}
}
// Actually we prefere to not have these edges so
// that getSources work as we want it to work...
/*else if (this.getComponent(src).size() > 1)
this.addEdge(src,src);*/
}
}
}
// /////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
// /////////////////////////////////////////////////////////////////////////
public void addEdge(int tail, int head) {
this.addEdge(tail, head, ++edgeMaxIndex);
}
public void addComponent(int vertex, Set vertices) {
this.addVertex(vertex);
this.map.put(vertex, vertices);
}
public Set getComponent(int vertex) {
return this.map.get(vertex);
}
public Set getSources() {
Set sources = new TreeSet();
for (Integer i : this.vertexSet()) {
Iterator it = this.incomingEdgesOf(i).iterator();
if (!it.hasNext()) {
sources.add(i);
}
}
return sources;
}
public Set getSinks() {
Set sinks = new TreeSet();
for (Integer i : this.vertexSet()) {
Iterator it = this.outgoingEdgesOf(i).iterator();
if (!it.hasNext()) {
sinks.add(i);
}
}
return sinks;
}
public int getNbrComponents() {
return this.vertexSet().size();
}
/**
* @param sources
* @param direction
* if true, following the direction of the edges, otherwise
* follows the reverse direction.
* @return an array of int containing the layer number of each components of this graph.
*/
public int[] computeLayers(Iterable sources,
boolean direction) {
Iterable firstLayer = sources;
int size = 0;
Iterator it = this.vertexSet().iterator();
while (it.hasNext()) {
it.next();
++size;
}
int[] layers = new int[size];
// init
for (int i = 0; i < size; ++i) {
layers[i] = -1;
}
for (int i : firstLayer) {
layers[i] = 0;
computeLayersRec(i, layers, 1, direction);
}
return layers;
}
private void computeLayersRec(int v, int[] layers, int actualLayer, boolean direction) {
Iterable it = null;
if(direction)
it = this.outgoingEdgesOf(v);
else
it = this.incomingEdgesOf(v);
for (int s : it) {
int succ;
if (direction) succ = this.getEdgeTarget(s);
else succ = this.getEdgeSource(s);
if (layers[succ] < actualLayer && v != succ) {
layers[succ] = actualLayer;
computeLayersRec(succ, layers, actualLayer + 1, direction);
}
}
}
}