org.jgrapht.alg.BlockCutpointGraph Maven / Gradle / Ivy
Go to download
JGraphT is a free Java graph library
that provides mathematical graph-theory objects and algorithms
The newest version!
/* ==========================================
* JGraphT : a free Java graph-theory library
* ==========================================
*
* Project Info: http://jgrapht.sourceforge.net/
* Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh)
*
* (C) Copyright 2003-2007, by Barak Naveh and Contributors.
*
* This library 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 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/* -------------------------
* BlockCutpointGraph.java
* -------------------------
* (C) Copyright 2007-2007, by France Telecom
*
* Original Author: Guillaume Boulmier and Contributors.
* Contributor(s): John V. Sichi
*
* $Id: BlockCutpointGraph.java 588 2008-01-28 01:38:08Z perfecthash $
*
* Changes
* -------
* 05-Jun-2007 : Initial revision (GB);
* 05-Jul-2007 : Added support for generics (JVS);
*
*/
package org.jgrapht.alg;
import java.util.*;
import org.jgrapht.*;
import org.jgrapht.graph.*;
/**
* Definition of a block of a
* graph in MathWorld.
* Definition and lemma taken from the article
* Structure-Based Resilience Metrics for Service-Oriented Networks:
*
*
* - Definition 4.5 Let G(V; E) be a connected undirected graph. The
* block-cut point graph (BC graph) of G, denoted by GB(VB; EB), is the
* bipartite graph defined as follows. (a) VB has one node corresponding to each
* block and one node corresponding to each cut point of G. (b) Each edge fx; yg
* in EB joins a block node x to a cut point y if the block corresponding to x
* contains the cut point node corresponding to y.
* - Lemma 4.4 Let G(V; E) be a connected undirected graph. (a) Each
* pair of blocks of G share at most one node, and that node is a cutpoint. (b)
* The BC graph of G is a tree in which each leaf node corresponds to a block of
* G.
*
*
* @author Guillaume Boulmier
* @since July 5, 2007
*/
public class BlockCutpointGraph
extends SimpleGraph, DefaultEdge>
{
//~ Static fields/initializers ---------------------------------------------
/**
*/
private static final long serialVersionUID = -9101341117013163934L;
//~ Instance fields --------------------------------------------------------
private Set cutpoints = new HashSet();
/**
* DFS (Depth-First-Search) tree.
*/
private DirectedGraph dfsTree;
private UndirectedGraph graph;
private int numOrder;
private Stack stack = new Stack();
private Map>> vertex2biconnectedSubgraphs =
new HashMap>>();
private Map> vertex2block =
new HashMap>();
private Map vertex2numOrder = new HashMap();
//~ Constructors -----------------------------------------------------------
/**
* Running time = O(m) where m is the number of edges.
*/
public BlockCutpointGraph(UndirectedGraph graph)
{
super(DefaultEdge.class);
this.graph = graph;
this.dfsTree =
new SimpleDirectedGraph(
DefaultEdge.class);
V s = graph.vertexSet().iterator().next();
this.dfsTree.addVertex(s);
dfsVisit(s, s);
if (this.dfsTree.edgesOf(s).size() > 1) {
this.cutpoints.add(s);
} else {
this.cutpoints.remove(s);
}
for (Iterator iter = this.cutpoints.iterator(); iter.hasNext();) {
V cutpoint = iter.next();
UndirectedGraph subgraph =
new SimpleGraph(this.graph.getEdgeFactory());
subgraph.addVertex(cutpoint);
this.vertex2block.put(cutpoint, subgraph);
addVertex(subgraph);
Set> biconnectedSubgraphs =
getBiconnectedSubgraphs(cutpoint);
for (
Iterator> iterator =
biconnectedSubgraphs.iterator();
iterator.hasNext();)
{
UndirectedGraph biconnectedSubgraph = iterator.next();
assert (vertexSet().contains(biconnectedSubgraph));
addEdge(subgraph, biconnectedSubgraph);
}
}
}
//~ Methods ----------------------------------------------------------------
/**
* Returns the vertex if vertex is a cutpoint, and otherwise returns the
* block (biconnected component) containing the vertex.
*
* @param vertex vertex in the initial graph.
*/
public UndirectedGraph getBlock(V vertex)
{
if (!this.graph.vertexSet().contains(vertex)) {
throw new IllegalArgumentException("No such vertex in the graph!");
}
return this.vertex2block.get(vertex);
}
/**
* Returns the cutpoints of the initial graph.
*/
public Set getCutpoints()
{
return this.cutpoints;
}
/**
* Renvoie true
if the vertex is a cutpoint, false
* otherwise.
*
* @param vertex vertex in the initial graph.
*/
public boolean isCutpoint(V vertex)
{
if (!this.graph.vertexSet().contains(vertex)) {
throw new IllegalArgumentException("No such vertex in the graph!");
}
return this.cutpoints.contains(vertex);
}
private void biconnectedComponentFinished(V s, V n)
{
this.cutpoints.add(s);
Set vertexComponent = new HashSet();
Set edgeComponent = new HashSet();
BCGEdge edge = this.stack.pop();
while (
(getNumOrder(edge.getSource()) >= getNumOrder(n))
&& !this.stack.isEmpty())
{
edgeComponent.add(edge);
vertexComponent.add(edge.getSource());
vertexComponent.add(edge.getTarget());
edge = this.stack.pop();
}
edgeComponent.add(edge);
// edgeComponent is an equivalence class.
vertexComponent.add(edge.getSource());
vertexComponent.add(edge.getTarget());
VertexComponentForbiddenFunction mask =
new VertexComponentForbiddenFunction(
vertexComponent);
UndirectedGraph biconnectedSubgraph =
new UndirectedMaskSubgraph(
this.graph,
mask);
for (Iterator iter = vertexComponent.iterator(); iter.hasNext();) {
V vertex = iter.next();
this.vertex2block.put(vertex, biconnectedSubgraph);
getBiconnectedSubgraphs(vertex).add(biconnectedSubgraph);
}
addVertex(biconnectedSubgraph);
}
private int dfsVisit(V s, V father)
{
this.numOrder++;
int minS = this.numOrder;
setNumOrder(s, this.numOrder);
for (
Iterator iter = this.graph.edgesOf(s).iterator();
iter.hasNext();)
{
E edge = iter.next();
V n = Graphs.getOppositeVertex(this.graph, edge, s);
if (getNumOrder(n) == 0) {
this.dfsTree.addVertex(n);
BCGEdge dfsEdge = new BCGEdge(s, n);
this.dfsTree.addEdge(s, n, dfsEdge);
this.stack.push(dfsEdge);
// minimum of the traverse orders of the "attach points" of
// the vertex n.
int minN = dfsVisit(n, s);
minS = Math.min(minN, minS);
if (minN >= getNumOrder(s)) {
// s is a cutpoint.
// it has a son whose "attach depth" is greater or equal.
biconnectedComponentFinished(s, n);
}
} else if ((getNumOrder(n) < getNumOrder(s)) && !n.equals(father)) {
BCGEdge backwardEdge = new BCGEdge(s, n);
this.stack.push(backwardEdge);
// n is an "attach point" of s. {s->n} is a backward edge.
minS = Math.min(getNumOrder(n), minS);
}
}
// minimum of the traverse orders of the "attach points" of
// the vertex s.
return minS;
}
/**
* Returns the biconnected components containing the vertex. A vertex which
* is not a cutpoint is contained in exactly one component. A cutpoint is
* contained is at least 2 components.
*
* @param vertex vertex in the initial graph.
*/
private Set> getBiconnectedSubgraphs(V vertex)
{
Set> biconnectedSubgraphs =
this.vertex2biconnectedSubgraphs.get(vertex);
if (biconnectedSubgraphs == null) {
biconnectedSubgraphs = new HashSet>();
this.vertex2biconnectedSubgraphs.put(vertex, biconnectedSubgraphs);
}
return biconnectedSubgraphs;
}
/**
* Returns the traverse order of the vertex in the DFS.
*/
private int getNumOrder(V vertex)
{
assert (vertex != null);
Integer numOrder = this.vertex2numOrder.get(vertex);
if (numOrder == null) {
return 0;
} else {
return numOrder.intValue();
}
}
private void setNumOrder(V vertex, int numOrder)
{
this.vertex2numOrder.put(vertex, Integer.valueOf(numOrder));
}
//~ Inner Classes ----------------------------------------------------------
private class BCGEdge
extends DefaultEdge
{
/**
*/
private static final long serialVersionUID = -5115006161815760059L;
private V source;
private V target;
public BCGEdge(V source, V target)
{
super();
this.source = source;
this.target = target;
}
public V getSource()
{
return this.source;
}
public V getTarget()
{
return this.target;
}
}
private class VertexComponentForbiddenFunction
implements MaskFunctor
{
private Set vertexComponent;
public VertexComponentForbiddenFunction(Set vertexComponent)
{
this.vertexComponent = vertexComponent;
}
public boolean isEdgeMasked(E edge)
{
return false;
}
public boolean isVertexMasked(V vertex)
{
if (this.vertexComponent.contains(vertex)) {
// vertex belongs to component then we do not mask it.
return false;
} else {
return true;
}
}
}
}
// End BlockCutpointGraph.java