package org.seqcode.gseutils.graphs;
import java.util.*;
import org.seqcode.gseutils.*;
import java.io.*;
public class DirectedGraph implements Graph {
private static SetTools<String> tools;
static {
tools = new SetTools<String>();
}
private HashSet<String> nodes;
private Map<String,Set<String>> edges, parents;
public DirectedGraph() {
nodes = new HashSet<String>();
edges = new HashMap<String,Set<String>>();
parents = new HashMap<String,Set<String>>();
}
public DirectedGraph(Collection<String> ns) {
nodes = new HashSet<String>(ns);
edges = new HashMap<String,Set<String>>();
parents = new HashMap<String,Set<String>>();
}
public DirectedGraph(GraphModel m) {
this();
for(int i = 0; i < m.nodes.length; i++) {
addVertex(m.nodes[i]);
}
for(int i = 0; i < m.edges.length; i++) {
addEdge(m.edges[i][0], m.edges[i][1]);
}
}
public GraphModel asModel() { return new GraphModel(this); }
public DirectedGraph(Collection<String> n, Map<String,Set<String>> e) {
nodes = new HashSet<String>(n);
edges = new HashMap<String,Set<String>>();
parents = new HashMap<String,Set<String>>();
for(String node : nodes) {
edges.put(node, new HashSet<String>());
parents.put(node, new HashSet<String>());
}
for(String v1 : e.keySet()) {
for(String v2 : e.get(v1)) {
if(nodes.contains(v1) && nodes.contains(v2)) {
addEdge(v1, v2);
}
}
}
}
public DirectedGraph(DirectedGraph dg) {
nodes = new HashSet<String>(dg.nodes);
edges = new HashMap<String,Set<String>>();
parents = new HashMap<String,Set<String>>();
for(String v : nodes) {
edges.put(v, new HashSet<String>(dg.edges.get(v)));
parents.put(v, new HashSet<String>(dg.parents.get(v)));
}
}
public DirectedGraph reverse() {
DirectedGraph dg = new DirectedGraph();
dg.nodes.addAll(nodes);
for(String n : edges.keySet()) {
dg.parents.put(n, new HashSet<String>(edges.get(n)));
}
for(String n : parents.keySet()) {
dg.edges.put(n, new HashSet<String>(parents.get(n)));
}
return dg;
}
public void printGraph(PrintStream ps) {
TreeSet<String> nodesOrdered = new TreeSet<String>(nodes);
for(String n : nodesOrdered) {
ps.print(n + " : ( ");
for(String nn : edges.get(n)) {
ps.print(nn + " ");
}
ps.println(")");
}
}
public void addVertex(String v) {
if(!nodes.contains(v)) {
nodes.add(v);
edges.put(v, new HashSet<String>());
parents.put(v, new HashSet<String>());
}
}
public void addEdge(String v1, String v2) {
if(nodes.contains(v1) && nodes.contains(v2)) {
edges.get(v1).add(v2);
parents.get(v2).add(v1);
} else if (!nodes.contains(v1)) {
throw new IllegalArgumentException(v1);
} else {
throw new IllegalArgumentException(v2);
}
}
public void removeEdge(String v1, String v2) {
if(containsEdge(v1, v2)) {
edges.get(v1).remove(v2);
parents.get(v2).remove(v1);
}
}
public void removeVertex(String n) {
if(nodes.contains(n)) {
nodes.remove(n);
parents.remove(n);
edges.remove(n);
for(String k : edges.keySet()) {
if(parents.get(k).contains(n)) { parents.get(k).remove(n); }
if(edges.get(k).contains(n)) { edges.get(k).remove(n); }
}
}
}
public void removeAllEdges() {
edges.clear();
parents.clear();
}
public String chooseNeighbor(String n) {
if(edges.containsKey(n) && !edges.get(n).isEmpty()) {
Iterator<String> nitr = edges.get(n).iterator();
return nitr.next();
} else {
return null;
}
}
public boolean isNeighbor(String v, String n) { return containsEdge(v, n); }
public boolean containsEdge(String v1, String v2) {
return edges.get(v1).contains(v2);
}
public boolean containsVertex(String searchOrf) {
return nodes.contains(searchOrf);
}
public Set<String> getAncestors(String vertex) {
Set<String> searched = new HashSet<String>();
LinkedList<String> pending = new LinkedList<String>();
pending.addAll(parents.get(vertex));
while(!pending.isEmpty()) {
String cv = pending.removeFirst();
searched.add(cv);
Set<String> ns = tools.subtract(parents.get(cv), searched);
ns.removeAll(pending);
pending.addAll(ns);
}
return searched;
}
public Set<String> getDescendants(String vertex) {
Set<String> searched = new HashSet<String>();
LinkedList<String> pending = new LinkedList<String>();
pending.addAll(edges.get(vertex));
while(!pending.isEmpty()) {
String cv = pending.removeFirst();
searched.add(cv);
Set<String> ns = tools.subtract(edges.get(cv), searched);
ns.removeAll(pending);
pending.addAll(ns);
}
return searched;
}
public Set<String> getRoots() {
HashSet<String> roots = new HashSet<String>();
for(String node : nodes) {
if(parents.get(node).size() == 0) {
roots.add(node);
}
}
return roots;
}
public Set<String> getVertices() {
return new HashSet<String>(nodes);
}
public Set<String> getParents(String vertex) {
return parents.get(vertex);
}
public Set<String> getNeighbors(String vertex) {
return edges.get(vertex);
}
public UndirectedGraph createUndirected() {
return new UndirectedGraph(nodes, edges);
}
public UndirectedGraph moralize() {
UndirectedGraph analog = createUndirected();
for(String v : nodes) {
Vector<String> pv = new Vector<String>(parents.get(v));
for(int i = 0; i < pv.size(); i++) {
String p1 = pv.get(i);
for(int j = i + 1; j < pv.size(); j++) {
String p2 = pv.get(j);
analog.addEdge(p1, p2);
}
}
}
return analog;
}
public Graph getSubgraph(Set<String> vs) {
return new DirectedGraph(vs, edges);
}
public int size() {
return nodes.size();
}
}