| 1 | package weka.clusterers.forMetisMQI; |
|---|
| 2 | |
|---|
| 3 | import java.util.ArrayList; |
|---|
| 4 | import java.util.HashMap; |
|---|
| 5 | import java.util.HashSet; |
|---|
| 6 | import java.util.Iterator; |
|---|
| 7 | import java.util.List; |
|---|
| 8 | import java.util.Set; |
|---|
| 9 | import java.util.SortedSet; |
|---|
| 10 | import java.util.TreeSet; |
|---|
| 11 | import java.util.Map.Entry; |
|---|
| 12 | |
|---|
| 13 | public class Subgraph { |
|---|
| 14 | |
|---|
| 15 | private UndirectedGraph g = null; |
|---|
| 16 | |
|---|
| 17 | private Set<Node> nodes = null; |
|---|
| 18 | |
|---|
| 19 | // private BitSet nodes = null; |
|---|
| 20 | // private List<Integer> listOfNodes = null; |
|---|
| 21 | private HashMap<Node,Integer> ID = null; |
|---|
| 22 | private HashMap<Node,Integer> ED = null; |
|---|
| 23 | private HashMap<Integer,List<Node>> bucketGain = null; |
|---|
| 24 | private SortedSet<Integer> gainSet = null; |
|---|
| 25 | private boolean recomputeGain = true; |
|---|
| 26 | |
|---|
| 27 | public Subgraph(UndirectedGraph g){ |
|---|
| 28 | this.g = g; |
|---|
| 29 | nodes = new HashSet<Node>(); |
|---|
| 30 | ID = new HashMap<Node,Integer>(); |
|---|
| 31 | ED = new HashMap<Node,Integer>(); |
|---|
| 32 | bucketGain = new HashMap<Integer, List<Node>>(); |
|---|
| 33 | gainSet = new TreeSet<Integer>(); |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | public UndirectedGraph getGraph() { |
|---|
| 37 | return g; |
|---|
| 38 | } |
|---|
| 39 | |
|---|
| 40 | public void addVertex(Node u) { |
|---|
| 41 | nodes.add(u); |
|---|
| 42 | ID.put(u, 0); |
|---|
| 43 | ED.put(u, 0); |
|---|
| 44 | recomputeGain = true; |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | private void computeDegree() { |
|---|
| 48 | Iterator<Node> subgraphIterator = nodes.iterator(); |
|---|
| 49 | while(subgraphIterator.hasNext()) { |
|---|
| 50 | Node u = subgraphIterator.next(); |
|---|
| 51 | Iterator<Node> nborsIterator = g.getNeighbors(u).iterator(); |
|---|
| 52 | int newID = 0; |
|---|
| 53 | int newED = 0; |
|---|
| 54 | while(nborsIterator.hasNext()) { |
|---|
| 55 | Node v = nborsIterator.next(); |
|---|
| 56 | if(contains(v)) |
|---|
| 57 | newID = newID + g.findEdge(u, v).getWeight(); |
|---|
| 58 | else |
|---|
| 59 | newED = newED + g.findEdge(u, v).getWeight(); |
|---|
| 60 | ID.put(u, newID); |
|---|
| 61 | ED.put(u, newED); |
|---|
| 62 | } |
|---|
| 63 | } |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | private void computeGain() { |
|---|
| 67 | bucketGain.clear(); |
|---|
| 68 | gainSet.clear(); |
|---|
| 69 | ID.clear(); |
|---|
| 70 | ED.clear(); |
|---|
| 71 | computeDegree(); |
|---|
| 72 | Iterator<Node> subgraphIterator = nodes.iterator(); |
|---|
| 73 | while(subgraphIterator.hasNext()) { |
|---|
| 74 | Node u = subgraphIterator.next(); |
|---|
| 75 | int gainU = ED.get(u) - ID.get(u); |
|---|
| 76 | if(!bucketGain.containsKey(gainU)) { |
|---|
| 77 | bucketGain.put(gainU, new ArrayList<Node>()); |
|---|
| 78 | } |
|---|
| 79 | bucketGain.get(gainU).add(u); |
|---|
| 80 | gainSet.add(gainU); |
|---|
| 81 | } |
|---|
| 82 | recomputeGain = false; |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | public Node getCandidate() { |
|---|
| 86 | return getCandidate(new HashSet<Node>()); |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | /** |
|---|
| 90 | * |
|---|
| 91 | * @param marked |
|---|
| 92 | * @return the candidate node for swap or <code>null</code> if there aren't available nodes. |
|---|
| 93 | */ |
|---|
| 94 | public Node getCandidate(Set<Node> marked) { |
|---|
| 95 | if(recomputeGain) |
|---|
| 96 | computeGain(); |
|---|
| 97 | Node candidate = null; |
|---|
| 98 | Iterator<Integer> iterator = ((TreeSet<Integer>)gainSet).descendingIterator(); |
|---|
| 99 | while(iterator.hasNext() && (candidate == null)) { |
|---|
| 100 | int gain = iterator.next(); |
|---|
| 101 | Iterator<Node> nodes = bucketGain.get(gain).iterator(); |
|---|
| 102 | while(nodes.hasNext() && (candidate == null)) { |
|---|
| 103 | Node u = nodes.next(); |
|---|
| 104 | if(!marked.contains(u)) |
|---|
| 105 | candidate = u; |
|---|
| 106 | } |
|---|
| 107 | } |
|---|
| 108 | return candidate; |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | public int gain(Node u){ |
|---|
| 112 | if(recomputeGain) |
|---|
| 113 | computeGain(); |
|---|
| 114 | return ED.get(u) - ID.get(u); |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | public void removeVertex(Node u) { |
|---|
| 118 | if(recomputeGain) |
|---|
| 119 | computeGain(); |
|---|
| 120 | int gainU = gain(u); |
|---|
| 121 | nodes.remove(u); |
|---|
| 122 | ID.remove(u); |
|---|
| 123 | ED.remove(u); |
|---|
| 124 | List<Node> l = bucketGain.get(gainU); |
|---|
| 125 | l.remove(l.indexOf(u)); |
|---|
| 126 | if(l.size() == 0) { |
|---|
| 127 | bucketGain.remove(gainU); |
|---|
| 128 | gainSet.remove(gainU); |
|---|
| 129 | } |
|---|
| 130 | recomputeGain = true; |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | public int getVertexCount() { |
|---|
| 134 | return nodes.size(); |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | public Edge findEdge(Node v1, Node v2) { |
|---|
| 138 | Edge e = null; |
|---|
| 139 | if(contains(v1) && contains(v2)) |
|---|
| 140 | e = g.findEdge(v1, v2); |
|---|
| 141 | return e; |
|---|
| 142 | } |
|---|
| 143 | |
|---|
| 144 | public int getWeight(Node u, Node v) { |
|---|
| 145 | int ret = -1; |
|---|
| 146 | if(containsEdge(u,v)) |
|---|
| 147 | ret = g.findEdge(u, v).getWeight(); |
|---|
| 148 | return ret; |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | public Iterator<Node> iterator() { |
|---|
| 152 | return nodes.iterator(); |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | public boolean containsEdge(Node u, Node v) { |
|---|
| 156 | return contains(u) && contains(v) && g.containsEdge(u, v); |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | public boolean contains(Node u) { |
|---|
| 160 | return nodes.contains(u); |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | public List<Node> getNeighbors(Node u) { |
|---|
| 164 | List<Node> neighbors = new ArrayList<Node>(); |
|---|
| 165 | Iterator<Node> iterator = g.getNeighbors(u).iterator(); |
|---|
| 166 | while(iterator.hasNext()) { |
|---|
| 167 | Node v = iterator.next(); |
|---|
| 168 | if(contains(v) && containsEdge(u, v)) |
|---|
| 169 | neighbors.add(v); |
|---|
| 170 | } |
|---|
| 171 | return neighbors; |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | public int getExternalDegree() { |
|---|
| 175 | if(recomputeGain) |
|---|
| 176 | computeGain(); |
|---|
| 177 | int acc = 0; |
|---|
| 178 | Iterator<Integer> it = ED.values().iterator(); |
|---|
| 179 | while(it.hasNext()) |
|---|
| 180 | acc = acc + it.next(); |
|---|
| 181 | return acc; |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | @Override |
|---|
| 185 | public String toString() { |
|---|
| 186 | String out = "["; |
|---|
| 187 | Iterator<Node> it = nodes.iterator(); |
|---|
| 188 | while(it.hasNext()) { |
|---|
| 189 | Node u = it.next(); |
|---|
| 190 | out = out + u + ","; |
|---|
| 191 | } |
|---|
| 192 | out = out + "]"; |
|---|
| 193 | return out; |
|---|
| 194 | } |
|---|
| 195 | |
|---|
| 196 | public List<Node> getBoundary() { |
|---|
| 197 | if(recomputeGain) |
|---|
| 198 | computeGain(); |
|---|
| 199 | Iterator<Entry<Node,Integer>> EDIterator = ED.entrySet().iterator(); |
|---|
| 200 | List<Node> boundary = new ArrayList<Node>(); |
|---|
| 201 | while(EDIterator.hasNext()) { |
|---|
| 202 | Entry<Node,Integer> entry = EDIterator.next(); |
|---|
| 203 | if(entry.getValue() > 0) |
|---|
| 204 | boundary.add(entry.getKey()); |
|---|
| 205 | } |
|---|
| 206 | return boundary; |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | private Subgraph() { |
|---|
| 210 | |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | @Override |
|---|
| 214 | public Subgraph clone() { |
|---|
| 215 | Subgraph clone = new Subgraph(); |
|---|
| 216 | clone.g = g.clone(); |
|---|
| 217 | |
|---|
| 218 | clone.nodes = new HashSet<Node>(); |
|---|
| 219 | Iterator<Node> graphIterator =clone.g.getVertices().iterator(); |
|---|
| 220 | while(graphIterator.hasNext()) { |
|---|
| 221 | Node u = graphIterator.next(); |
|---|
| 222 | if(contains(u)) |
|---|
| 223 | clone.nodes.add(u); |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | clone.bucketGain = new HashMap<Integer, List<Node>>(); |
|---|
| 227 | clone.gainSet = new TreeSet<Integer>(); |
|---|
| 228 | clone.ID = new HashMap<Node, Integer>(); |
|---|
| 229 | clone.ED = new HashMap<Node, Integer>(); |
|---|
| 230 | |
|---|
| 231 | clone.computeGain(); |
|---|
| 232 | |
|---|
| 233 | return clone; |
|---|
| 234 | } |
|---|
| 235 | } |
|---|