Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.jbpt.algo.tree.mdt;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jbpt.algo.tree.mdt.ComponentGraph;
import org.jbpt.algo.tree.mdt.MDTNode;
import org.jbpt.graph.abs.AbstractDirectedGraph;
import org.jbpt.graph.abs.AbstractTree;
import org.jbpt.graph.abs.IDirectedEdge;
import org.jbpt.hypergraph.abs.IVertex;
/**
* This class computes the Modular Decomposition Tree of a directed graph.
* It implements the algorithm described in the following article:
*
* A. Ehrenfeucht, H.N. Gabow, R.M. McConnell, and S.J. Sullivan
* An O(n^2) Divide-and Conquer Algorithm for the Prime Tree Decomposition of
* Two-Structures and Modular Decomposition of Graphs
* JOURNAL OF ALGORITHMS 16, 283-294 (1994)
*
* @author Luciano Garcia-Banuelos
*/
public class MDT, V extends IVertex> extends AbstractTree> {
private AbstractDirectedGraph graph;
public MDT(AbstractDirectedGraph graph) {
this.graph = graph;
this.root = decompose(graph.getVertices());
}
/**
* Given vertex v, this method partitions a set of vertices into four
* partitions according to their connectivity pattern with v:
* 1: Bidirectional connected
* 2: Directed edge having v as target vertex
* 3: Directed edge having v as source vertex
* 4: Disconnected
*
* @param vertices Set of vertices to partition
* @param v Vertex to guide partitioning
*/
private List> partitionSubsets(Collection vertices, V v) {
List> partitions = new ArrayList>(4);
for (int i = 0; i<4; i++)
partitions.add(new HashSet());
for (V w: vertices) {
E w_v = graph.getDirectedEdge(w, v);
E v_w = graph.getDirectedEdge(v, w);
// Four cases:
if (w_v != null && v_w != null) // (w,v),(v,w) \in E(G)
partitions.get(0).add(w);
else if (w_v != null) // (w,v) \in E(G) /\ (v,w) \nin E(G)
partitions.get(1).add(w);
else if (v_w != null) // (w,v) \nin E(G) /\ (v,w) \in E(G)
partitions.get(2).add(w);
else // (w,v), (v,w) \nin E(G)
partitions.get(3).add(w);
}
return partitions ;
}
/**
* Algorithm 3.1 Compute M(g, v)
*
* @param vertices AKA dom(g) in the reference paper, corresponds with the set of vertices of graph g
* @param v vertex used for partitioning
* @return
*/
private Collection> partition(Collection vertices, V v) {
// L - Family of partition classes
Set> l = new HashSet>();
// Z - Unprocessed outsiders
Map, Set> z = new HashMap, Set>();
// Place holder
Set> result = new LinkedHashSet>();
// Initially, there is one partition class S = V(g) \ {v} in L
Set s = new HashSet(vertices);
s.remove(v);
l.add(s);
// with Z(S) = {v}
Set _v_ = new HashSet();
_v_.add(v);
z.put(s, _v_);
while(!l.isEmpty()) {
// Remove S from L
s = l.iterator().next(); l.remove(s);
// Let w be an arbitrary member of Z(S)
V w = z.get(s).iterator().next();
// Partition S into maximal subsets that are not distinguished by w
// -- for each resulting subset W
for (Set W: partitionSubsets(s, w)) {
if (W.isEmpty()) continue;
// Let Z(W) = (S \ W) \cup Z(S) \ {w}
Set tmp = new HashSet(s);
tmp.removeAll(W);
tmp.addAll(z.get(s));
tmp.remove(w);
if (!tmp.isEmpty()) {
// Make W a member of L
l.add(W);
z.put(W, tmp); // Actual assignment to Z
} else
result.add(W);
}
}
return result;
}
/**
* Algorithm 6.1 Compute the PRIME TREE FAMILY (aka Modular Decomposition Tree) for
* an arbitrary two-structure.
*
* @param dom
* @return
*/
private IMDTNode decompose(Collection dom) {
if (dom.size() == 0) return null; // Nothing to do
// Select one vertex from dom
V v = dom.iterator().next();
// Create a node in the MDT
MDTNode t = new MDTNode(this, dom, v);
addVertex(t);
// Dom is a singleton, then t is a TRIVIAL
if (dom.size() == 1) return t;
Collection> m = partition(dom, v);
ComponentGraph gpp = new ComponentGraph(graph, m, v);
MDTNode u = t;
while (gpp.getVertices().size() > 0) {
Set tmp = gpp.getPartitionUnion();
tmp.add(v);
u.setClan(tmp);
tmp = new HashSet();
tmp.add(v);
MDTNode w = new MDTNode(this, tmp, v);
addVertex(w);
addChild(u, w);
Set sinks = gpp.getSinkNodes();
Set> F = gpp.getPartitions(sinks);
gpp.removeVertices(sinks);
if (sinks.size() == 1 && F.size() > 1)
u.setType(MDTType.PRIMITIVE);
else {
V x = F.iterator().next().iterator().next();
if ((graph.getDirectedEdge(v, x) != null && graph.getDirectedEdge(x, v) != null) ||
(!(graph.getDirectedEdge(v, x) != null) && !(graph.getDirectedEdge(x, v) != null))) {
u.setType(MDTType.COMPLETE);
u.setColor(graph.getDirectedEdge(v, x) != null ? 1 : 0);
} else
u.setType(MDTType.LINEAR);
}
for (Set partition: F) {
IMDTNode root = decompose(partition);
if (((u.getType() == MDTType.COMPLETE && root.getType() == MDTType.COMPLETE) ||
(u.getType() == MDTType.LINEAR && root.getType() == MDTType.LINEAR)) &&
u.getColor() == root.getColor())
for (IMDTNode child: getChildren(root))
addChild(u, child);
else
addChild(u, root);
}
u = w;
}
return t;
}
@Override
public String toString() {
return root.toString();
}
@Override
public IMDTNode reRoot(IMDTNode v) {
throw new UnsupportedOperationException("An MDT cannot be modified!");
}
}