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