equivalent-exchange-3/common/com/pahimar/ee3/emc/graph/WeightedDirectedGraph.java
2013-08-23 10:59:50 -04:00

272 lines
7.6 KiB
Java

package com.pahimar.ee3.emc.graph;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Logger;
import com.pahimar.ee3.core.util.LogHelper;
public class WeightedDirectedGraph<T> implements Iterable<T> {
private final Map<T, SortedSet<WeightedEdge<T>>> graph = new HashMap<T, SortedSet<WeightedEdge<T>>>();
private List<T> orderedNodes = new ArrayList<T>();
public boolean addNode(T node) {
// Ignore nodes already added
if (graph.containsKey(node))
return false;
orderedNodes.add(node);
graph.put(node, new TreeSet<WeightedEdge<T>>(new Comparator<WeightedEdge<T>>() {
@Override
public int compare(WeightedEdge<T> o1, WeightedEdge<T> o2) {
return orderedNodes.indexOf(o1.getTarget()) - orderedNodes.indexOf(o2.getTarget());
}
}));
return true;
}
public void addEdge(T from, T to) {
addEdge(from, to, 1);
}
public void addEdge(T from, T to, float weight) {
if (!(graph.containsKey(from) && graph.containsKey(to))) {
if (!graph.containsKey(from)) {
LogHelper.severe("From node doesn't exist: " + from.toString());
LogHelper.severe("To node: " + to.toString());
}
if (!graph.containsKey(to)) {
LogHelper.severe("From node: " + from.toString());
LogHelper.severe("To node doesn't exist: " + to.toString());
}
throw new NoSuchElementException("Missing nodes from graph");
}
// If a directed edge of the same weight doesn't already exist, add the new edge
if (!edgeExists(from, to, weight)) {
graph.get(from).add(new WeightedEdge<T>(weight, to));
}
}
public boolean edgeExists(T from, T to) {
if (!(graph.containsKey(from) && graph.containsKey(to)))
throw new NoSuchElementException("Missing nodes from graph");
Iterator<WeightedEdge<T>> edgeIterator = graph.get(from).iterator();
while (edgeIterator.hasNext()) {
if (edgeIterator.next().getTarget().equals(to))
return true;
}
return false;
}
public boolean edgeExists(T from, T to, float weight) {
if (!(graph.containsKey(from) && graph.containsKey(to))) {
if (!graph.containsKey(from)) {
LOGGER.severe("From node doesn't exist: " + from.toString());
LOGGER.severe("To node: " + to.toString());
}
if (!graph.containsKey(to)) {
LOGGER.severe("To node doesn't exist: " + to.toString());
LOGGER.severe("From node: " + from.toString());
}
throw new NoSuchElementException("Missing nodes from graph");
}
return graph.get(from).contains(new WeightedEdge<T>(weight, to));
}
public boolean nodeExists(T node) {
return graph.containsKey(node);
}
public Set<WeightedEdge<T>> edgesFrom(T from) {
if (!graph.containsKey(from))
throw new NoSuchElementException("Missing node from graph");
return Collections.unmodifiableSortedSet(graph.get(from));
}
public Set<WeightedEdge<T>> edgesTo(T to) {
if (!graph.containsKey(to))
throw new NoSuchElementException("Missing node from graph");
Set<WeightedEdge<T>> edgesTo = new TreeSet<WeightedEdge<T>>(new Comparator<WeightedEdge<T>>() {
@Override
public int compare(WeightedEdge<T> o1, WeightedEdge<T> o2) {
return o1.hashCode() - o2.hashCode();
}
});
for (T node : graph.keySet()) {
if (!node.equals(to)) {
Set<WeightedEdge<T>> edgesFrom = edgesFrom(node);
for (WeightedEdge<T> fromEdge : edgesFrom) {
if (fromEdge.getTarget().equals(to)) {
edgesTo.add(new WeightedEdge<T>(fromEdge.getWeight(), node));
}
}
}
}
return Collections.unmodifiableSet(edgesTo);
}
public void removeNode(T node) {
if (!graph.containsKey(node))
throw new NoSuchElementException("Missing node from graph");
// Remove all edges from and to the node
removeAllEdgesFrom(node);
removeAllEdgesTo(node);
// Remove the node
graph.remove(node);
}
public void removeEdge(T from, T to) {
removeEdge(from, to, 1);
}
public void removeEdge(T from, T to, float weight) {
if (!(graph.containsKey(from) && graph.containsKey(to)))
throw new NoSuchElementException("Missing nodes from graph");
graph.get(from).remove(new WeightedEdge<T>(weight, to));
}
public void removeAllEdgesFrom(T node) {
if (!graph.containsKey(node))
throw new NoSuchElementException("Missing node from graph");
graph.get(node).clear();
}
public void removeAllEdgesTo(T node) {
if (!graph.containsKey(node))
throw new NoSuchElementException("Missing node from graph");
for (T aNode : graph.keySet()) {
Set<WeightedEdge<T>> edgesFrom = edgesFrom(aNode);
for (WeightedEdge<T> fromEdge : edgesFrom) {
if (fromEdge.getTarget().equals(node)) {
graph.get(aNode).remove(fromEdge);
}
}
}
}
public void removeAllEdgesBetween(T firstNode, T secondNode) {
if (!(graph.containsKey(firstNode) && graph.containsKey(secondNode)))
throw new NoSuchElementException("Missing nodes from graph");
for (WeightedEdge<T> edgeFrom : edgesFrom(firstNode)) {
if (edgeFrom.getTarget().equals(secondNode)) {
graph.get(firstNode).remove(edgeFrom);
}
}
for (WeightedEdge<T> edgeFrom : edgesFrom(secondNode)) {
if (edgeFrom.getTarget().equals(firstNode)) {
graph.get(secondNode).remove(edgeFrom);
}
}
}
public List<T> getAllNodes() {
return orderedNodes;
}
public List<T> getCriticalNodes() {
ArrayList<T> criticalNodes = new ArrayList<T>();
Iterator<T> nodeIter = orderedNodes.iterator();
while (nodeIter.hasNext()) {
T currentNode = nodeIter.next();
if (this.edgesFrom(currentNode).size() == 0) {
criticalNodes.add(currentNode);
}
}
return criticalNodes;
}
public List<T> getOrphanNodes() {
ArrayList<T> orphanedNodes = new ArrayList<T>();
Iterator<T> nodeIter = orderedNodes.iterator();
while (nodeIter.hasNext()) {
T currentNode = nodeIter.next();
if (this.edgesFrom(currentNode).size() == 0 && this.edgesTo(currentNode).size() == 0) {
orphanedNodes.add(currentNode);
}
}
return orphanedNodes;
}
@Override
public Iterator<T> iterator() {
return orderedNodes.iterator();
}
public int size() {
return graph.size();
}
public boolean isEmpty() {
return graph.isEmpty();
}
@Override
public String toString() {
return graph.toString();
}
private static final Logger LOGGER = Logger.getLogger(WeightedDirectedGraph.class.getName());
}