1
2
3
4
5
6
7
8
9
10
11 package edu.uci.ics.jung.algorithms.blockmodel;
12
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22
23 import com.google.common.base.Function;
24
25 import edu.uci.ics.jung.graph.Graph;
26 import edu.uci.ics.jung.graph.util.Pair;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class StructurallyEquivalent<V,E> implements Function<Graph<V,E>, VertexPartition<V,E>>
45 {
46 public VertexPartition<V,E> apply(Graph<V,E> g)
47 {
48 Set<Pair<V>> vertex_pairs = getEquivalentPairs(g);
49
50 Set<Set<V>> rv = new HashSet<Set<V>>();
51 Map<V, Set<V>> intermediate = new HashMap<V, Set<V>>();
52 for (Pair<V> p : vertex_pairs)
53 {
54 Set<V> res = intermediate.get(p.getFirst());
55 if (res == null)
56 res = intermediate.get(p.getSecond());
57 if (res == null)
58 res = new HashSet<V>();
59 res.add(p.getFirst());
60 res.add(p.getSecond());
61 intermediate.put(p.getFirst(), res);
62 intermediate.put(p.getSecond(), res);
63 }
64 rv.addAll(intermediate.values());
65
66
67
68 Collection<V> singletons = new ArrayList<V>(g.getVertices());
69 singletons.removeAll(intermediate.keySet());
70 for (V v : singletons)
71 {
72 Set<V> v_set = Collections.singleton(v);
73 intermediate.put(v, v_set);
74 rv.add(v_set);
75 }
76
77 return new VertexPartition<V, E>(g, intermediate, rv);
78 }
79
80
81
82
83
84
85
86
87
88
89 protected Set<Pair<V>> getEquivalentPairs(Graph<V,?> g) {
90
91 Set<Pair<V>> rv = new HashSet<Pair<V>>();
92 Set<V> alreadyEquivalent = new HashSet<V>();
93
94 List<V> l = new ArrayList<V>(g.getVertices());
95
96 for (V v1 : l)
97 {
98 if (alreadyEquivalent.contains(v1))
99 continue;
100
101 for (Iterator<V> iterator = l.listIterator(l.indexOf(v1) + 1); iterator.hasNext();) {
102 V v2 = iterator.next();
103
104 if (alreadyEquivalent.contains(v2))
105 continue;
106
107 if (!canBeEquivalent(v1, v2))
108 continue;
109
110 if (isStructurallyEquivalent(g, v1, v2)) {
111 Pair<V> p = new Pair<V>(v1, v2);
112 alreadyEquivalent.add(v2);
113 rv.add(p);
114 }
115 }
116 }
117
118 return rv;
119 }
120
121
122
123
124
125
126
127
128 protected boolean isStructurallyEquivalent(Graph<V,?> g, V v1, V v2) {
129
130 if( g.degree(v1) != g.degree(v2)) {
131 return false;
132 }
133
134 Set<V> n1 = new HashSet<V>(g.getPredecessors(v1));
135 n1.remove(v2);
136 n1.remove(v1);
137 Set<V> n2 = new HashSet<V>(g.getPredecessors(v2));
138 n2.remove(v1);
139 n2.remove(v2);
140
141 Set<V> o1 = new HashSet<V>(g.getSuccessors(v1));
142 Set<V> o2 = new HashSet<V>(g.getSuccessors(v2));
143 o1.remove(v1);
144 o1.remove(v2);
145 o2.remove(v1);
146 o2.remove(v2);
147
148
149 boolean b = (n1.equals(n2) && o1.equals(o2));
150 if (!b)
151 return b;
152
153
154 b &= ( g.isSuccessor(v1, v2) == g.isSuccessor(v2, v1));
155
156
157 b &= ( g.isSuccessor(v1, v1) == g.isSuccessor(v2, v2));
158
159 return b;
160
161 }
162
163
164
165
166
167
168
169
170
171 protected boolean canBeEquivalent(V v1, V v2) {
172 return true;
173 }
174 }