All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jbpt.algo.tree.mdt.ComponentGraph Maven / Gradle / Ivy

package org.jbpt.algo.tree.mdt;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import org.jbpt.graph.abs.AbstractDirectedGraph;
import org.jbpt.graph.abs.IDirectedEdge;
import org.jbpt.hypergraph.abs.IVertex;
import org.jbpt.hypergraph.abs.Vertex;

public class ComponentGraph, V extends IVertex> extends AbstractDirectedGraph {
	Map>> pmap;
	
	public ComponentGraph(AbstractDirectedGraph g, Collection> m, V v) {
		super();
		
		pmap = new HashMap>>();
		
		// Build component graph
		Map map = new HashMap();
		
		for (Set p: m) {
			@SuppressWarnings("unchecked")
			V vp = (V) new Vertex("CG:"+p.toString());
			addVertex(vp);
			
			// vp is a vertex in the ComponentGraph, which is then associated with
			// vertex from the partition in the original graph (any)
			map.put(vp, p.iterator().next());
			
			// Initialize the set of partitions associated to each node in the component graph
			Set> sopart =  new HashSet>();
			sopart.add(p);
			pmap.put(vp, sopart);
		}
		
		for (V xp: map.keySet()) {
			V x = map.get(xp);
			if (x.equals(v)) continue;
			for (V yp: map.keySet()) {
				V y = map.get(yp);
				if (y.equals(v) || x.equals(y)) continue;
				
				if (distinguishes(g, x, y, v))
					addEdge(xp, yp);
			}
		}
		
		// Compute connected components and collapse them
		contractSCC();
	}

	public Set> getPartitions(Set vertices) {
		Set> result = new HashSet>();
		for (V v: vertices)
			result.addAll(pmap.get(v));
		return result;
	}
	
	public Set getPartitionUnion() {
		Set result = new HashSet();
		for (V vertex: getVertices()) {
			for (Set bs: pmap.get(vertex))
				result.addAll(bs);
		}
		return result;
	}
	
	public void contractSCC() {		
		Set> scc = kosaraju();
		
		for (Set cc : scc) {
			if (cc.size() > 1) {
				Set> parts = getPartitions(cc);
				V v = cc.iterator().next();
				cc.remove(v);
				removeVertices(cc);
				pmap.put(v, parts);
			}
		}
	}

	
	// Computation of Strongly Connected Components using the Kosaraju-Sharir's algorithm
	private Set> kosaraju() {
		Set> scc = new HashSet>();
		Stack stack = new Stack();
		Set visited = new HashSet();
		for (V vertex: getVertices())
			if (!visited.contains(vertex))
				searchForward(vertex, stack, visited);			

		visited.clear();
		while(!stack.isEmpty()) {
			Set component = new HashSet();
			searchBackward(stack.peek(), visited, component);
			scc.add(component);
			stack.removeAll(component);
		}
		return scc;
	}

	private void searchBackward(V node, Set visited, Set component) {
		Stack worklist = new Stack();
		worklist.push(node);
		while (!worklist.isEmpty()) {
			V curr = worklist.pop();
			visited.add(curr);
			component.add(curr);
			for (V pred: getDirectPredecessors(curr))
				if (!visited.contains(pred) && !worklist.contains(pred))
					worklist.add(pred);
		}
	}

	private void searchForward(V curr, Stack stack, Set visited) {
		visited.add(curr);
		for (V succ: getDirectSuccessors(curr))
			if (!visited.contains(succ))
				searchForward(succ, stack, visited);
		stack.push(curr);
	}

	private boolean distinguishes(AbstractDirectedGraph g, V x, V y,
			V z) {		
		return (hasEdge(g, x, y) != hasEdge(g, x, z)) || (hasEdge(g, y, x) != hasEdge(g, z, x));
	}
	
	private boolean hasEdge(AbstractDirectedGraph g, V x, V y) {
		return g.getDirectedEdge(x, y) != null;
	}

	public Set getSinkNodes() {
		Set sinks = new HashSet(getVertices());
		for (E e: getEdges())
			sinks.remove(e.getSource());
		return sinks;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy