aboutsummaryrefslogtreecommitdiff
path: root/src/uk/ac/ox/cs/pagoda/constraints/DependencyGraph.java
blob: d1615c71690a386c45f038169558e70002005033 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package uk.ac.ox.cs.pagoda.constraints;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

public abstract class DependencyGraph<T> {
	
	protected abstract void build(); 

	protected Map<T, Set<T>> edges = new HashMap<T, Set<T>>();
	protected Map<T, Set<T>> reverseEdges = new HashMap<T, Set<T>>(); 
	
	public void addLink(T subEntity, T superEntity) {
		Set<T> dests = edges.get(subEntity);
		if (dests == null)  
			edges.put(subEntity, dests = new HashSet<T>());
		dests.add(superEntity);
		
		Set<T> srcs = reverseEdges.get(superEntity); 
		if (srcs == null) 
			reverseEdges.put(superEntity, srcs = new HashSet<T>()); 
		srcs.add(subEntity); 
	}
	
	public void output() {
		for (Map.Entry<T, Set<T>> pair: edges.entrySet()) {
			T src = pair.getKey(); 
			for (T dest: pair.getValue())
				System.out.println(src + " -> " + dest); 
		}
	}
	
	public int distance(Set<T> dsts, T src) {
		Set<T> visited = new HashSet<T>(); 
		if (dsts.contains(src)) return 0; 
		visited.add(src); 
		return distance(dsts, visited); 
	}
	
	public int distance(Set<T> dsts, T src1, T src2) {
		Set<T> visited = new HashSet<T>(); 
		if (dsts.contains(src1)) return 0; 
		if (dsts.contains(src2)) return 0; 
		visited.add(src1); 
		visited.add(src2); 
		return distance(dsts, visited); 
	}
	
	private int distance(Set<T> dsts, Set<T> visited) {
		Queue<Entry> queue = new LinkedList<Entry>();
		for (T src: visited)
			queue.add(new Entry(src, 0, visited));

		Entry entry;
		Set<T> edge; 
		while (!queue.isEmpty()) {
			entry = queue.poll(); 
			edge = edges.get(entry.m_entity); 
			if (edge != null)
				for (T next: edge) {
					if (dsts.contains(next)) return entry.m_dist + 1;
					
					if (!visited.contains(next)) 
						queue.add(new Entry(next, entry.m_dist + 1, visited));
				}
		}

		return Integer.MAX_VALUE;
	}
	
	public Set<T> getAncesters(T p) {
		return getDependency(p, false); 
	}
	
	public Set<T> getSuccessors(T p) {
		return getDependency(p, true); 
	}
	
	private Set<T> getDependency(T p, boolean succ) {
		return succ ? getDependency(p, edges) : getDependency(p, reverseEdges); 
	}
	
	private Set<T> getDependency(T p, Map<T, Set<T>> graph) {
		Set<T> visited = new HashSet<T>(); 
		Queue<T> queue = new LinkedList<T>();
		visited.add(p);
		queue.add(p);
		Set<T> edge;
		
		while (!queue.isEmpty()) {
			if ((edge = graph.get(queue.poll())) != null)
				for (T next: edge) 
					if (!visited.contains(next)) {
						queue.add(next); 
						visited.add(next); 
					}
		}
		
		return visited; 
	}
	
	private class Entry {
		
		T m_entity; 
		int m_dist; 
		
		public Entry(T entity, int distance, Set<T> v) {
			m_entity = entity; 
			m_dist = distance; 
			v.add(entity); 
		}
		
	}
	
}