org.jgrapht.alg.BlockCutpointGraph Maven / Gradle / Ivy
/*
* (C) Copyright 2007-2018, by France Telecom and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* This program and the accompanying materials are dual-licensed under
* either
*
* (a) the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation, or (at your option) any
* later version.
*
* or (per the licensee's choosing)
*
* (b) the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation.
*/
package org.jgrapht.alg;
import org.jgrapht.*;
import org.jgrapht.graph.*;
import java.util.*;
/**
* 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$.
*
*
* @param the graph vertex type
* @param the graph edge type
*
* @since July 5, 2007
* @deprecated Moved to package org.jgrapht.connectivity
*/
@Deprecated
public class BlockCutpointGraph
extends
SimpleGraph, DefaultEdge>
{
private static final long serialVersionUID = -9101341117013163934L;
private Set cutpoints = new HashSet<>();
/**
* DFS (Depth-First-Search) tree.
*/
private Graph dfsTree;
private Graph graph;
private int numOrder;
private Deque stack = new ArrayDeque<>();
private Map>> vertex2biconnectedSubgraphs = new HashMap<>();
private Map> vertex2block = new HashMap<>();
private Map vertex2numOrder = new HashMap<>();
/**
* Running time = $O(m)$ where m is the number of edges.
*
* @param graph the input graph
*/
public BlockCutpointGraph(Graph graph)
{
super(DefaultEdge.class);
this.graph = GraphTests.requireUndirected(graph, "Graph must be undirected");
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 (V cutpoint : this.cutpoints) {
Graph subgraph = new SimpleGraph<>(this.graph.getEdgeFactory());
subgraph.addVertex(cutpoint);
this.vertex2block.put(cutpoint, subgraph);
addVertex(subgraph);
Set> biconnectedSubgraphs = getBiconnectedSubgraphs(cutpoint);
for (Graph biconnectedSubgraph : biconnectedSubgraphs) {
assert (vertexSet().contains(biconnectedSubgraph));
addEdge(subgraph, biconnectedSubgraph);
}
}
}
/**
* 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.
* @return the biconnected component containing the vertex
*/
public Graph 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.
*
* @return the cutpoints of the initial graph
*/
public Set getCutpoints()
{
return this.cutpoints;
}
/**
* Returns true
if the vertex is a cutpoint, false
otherwise.
*
* @param vertex vertex in the initial graph.
* @return true
if the vertex is a cutpoint, false
otherwise.
*/
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.removeLast();
while ((getNumOrder(edge.getSource()) >= getNumOrder(n)) && !this.stack.isEmpty()) {
edgeComponent.add(edge);
vertexComponent.add(edge.getSource());
vertexComponent.add(edge.getTarget());
edge = this.stack.removeLast();
}
edgeComponent.add(edge);
// edgeComponent is an equivalence class.
vertexComponent.add(edge.getSource());
vertexComponent.add(edge.getTarget());
Graph biconnectedSubgraph =
new MaskSubgraph<>(this.graph, v -> !vertexComponent.contains(v), e -> false);
for (V vertex : vertexComponent) {
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 (E edge : this.graph.edgesOf(s)) {
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.add(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.add(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)
{
return this.vertex2biconnectedSubgraphs.computeIfAbsent(vertex, k -> new HashSet<>());
}
/**
* Returns the traverse order of the vertex in the DFS.
*/
private int getNumOrder(V vertex)
{
assert (vertex != null);
return this.vertex2numOrder.getOrDefault(vertex, 0);
}
private void setNumOrder(V vertex, int numOrder)
{
this.vertex2numOrder.put(vertex, numOrder);
}
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;
}
@Override
public V getSource()
{
return this.source;
}
@Override
public V getTarget()
{
return this.target;
}
}
}
// End BlockCutpointGraph.java
© 2015 - 2025 Weber Informatics LLC | Privacy Policy