/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT 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 3 of the License, or
(at your option) any later version.
HermiT 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 HermiT. If not, see <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT.graph;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
public class Graph<T> implements Serializable {
private static final long serialVersionUID = 5372948202031042380L;
protected final Set<T> m_elements;
protected final Map<T,Set<T>> m_successorsByNodes;
public Graph() {
m_elements=new HashSet<T>();
m_successorsByNodes=new HashMap<T,Set<T>>();
}
public void addEdge(T from,T to) {
Set<T> successors=m_successorsByNodes.get(from);
if (successors==null) {
successors=new HashSet<T>();
m_successorsByNodes.put(from,successors);
}
successors.add(to);
m_elements.add(from);
m_elements.add(to);
}
public void addEdges(T from,Set<T> to) {
Set<T> successors=m_successorsByNodes.get(from);
if (successors==null) {
successors=new HashSet<T>();
m_successorsByNodes.put(from,successors);
}
successors.addAll(to);
m_elements.add(from);
m_elements.addAll(to);
}
public Set<T> getElements() {
return m_elements;
}
public Set<T> getSuccessors(T node) {
Set<T> result=m_successorsByNodes.get(node);
if (result==null)
result=Collections.emptySet();
return result;
}
public void transitivelyClose() {
List<T> toProcess=new ArrayList<T>();
for (Set<T> reachable : m_successorsByNodes.values()) {
toProcess.clear();
toProcess.addAll(reachable);
while (!toProcess.isEmpty()) {
T elementOnPath=toProcess.remove(toProcess.size()-1);
Set<T> elementOnPathSuccessors=m_successorsByNodes.get(elementOnPath);
if (elementOnPathSuccessors!=null)
for (T elementOnPathSuccessor : elementOnPathSuccessors)
if (reachable.add(elementOnPathSuccessor))
toProcess.add(elementOnPathSuccessor);
}
}
}
public Graph<T> getInverse() {
Graph<T> result=new Graph<T>();
for (Map.Entry<T,Set<T>> entry : m_successorsByNodes.entrySet()) {
T from=entry.getKey();
for (T successor : entry.getValue())
result.addEdge(successor,from);
}
return result;
}
public Graph<T> clone() {
Graph<T> result=new Graph<T>();
result.m_elements.addAll( m_elements );
for (Map.Entry<T,Set<T>> entry : m_successorsByNodes.entrySet()) {
T from=entry.getKey();
for (T successor : entry.getValue())
result.addEdge(from,successor);
}
return result;
}
public void removeElements(Set<T> elements) {
for(T element : elements){
m_elements.remove( element );
m_successorsByNodes.remove( element );
}
}
public boolean isReachableSuccessor(T fromNode,T toNode) {
if (fromNode.equals(toNode))
return true;
Set<T> result=new HashSet<T>();
Queue<T> toVisit=new LinkedList<T>();
toVisit.add(fromNode);
while (!toVisit.isEmpty()) {
T current=toVisit.poll();
Set<T> successors = getSuccessors(current);
if (successors.contains(toNode))
return true;
if (result.add(current))
toVisit.addAll(successors);
}
return false;
}
public Set<T> getReachableSuccessors(T fromNode) {
Set<T> result = new HashSet<T>();
Queue<T> toVisit=new LinkedList<T>();
toVisit.add(fromNode);
while (!toVisit.isEmpty()) {
T current=toVisit.poll();
if (result.add(current))
toVisit.addAll(getSuccessors(current));
}
return result;
}
public String toString() {
StringBuffer buffer=new StringBuffer();
for (T element : m_elements) {
buffer.append(element.toString());
buffer.append(" -> { ");
boolean firstSuccessor=true;
Set<T> successors=m_successorsByNodes.get(element);
if (successors!=null) {
for (T successor : successors) {
if (firstSuccessor)
firstSuccessor=false;
else
buffer.append(", ");
buffer.append(successor.toString());
}
}
buffer.append(" }");
buffer.append(System.getProperty("line.separator"));
}
return buffer.toString();
}
}