1 package Analysis.SSJava;
3 import java.io.BufferedWriter;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Iterator;
13 import IR.FieldDescriptor;
15 public class HierarchyGraph {
20 Map<Descriptor, HNode> mapDescToHNode;
21 Map<HNode, Set<Descriptor>> mapHNodeToDescSet;
22 Map<HNode, Set<HNode>> mapHNodeToIncomingSet;
23 Map<HNode, Set<HNode>> mapHNodeToOutgoingSet;
24 Map<Set<HNode>, HNode> mapSkeletonNodeSetToCombinationNode;
25 Map<HNode, Set<HNode>> mapCombinationNodeToCombineNodeSet;
26 Map<Set<HNode>, HNode> mapCombineNodeSetToCombinationNode;
27 Map<Set<HNode>, Set<HNode>> mapCombineNodeSetToOutgoingNodeSet;
28 Map<HNode, String> mapHNodeToLocationName;
32 public static int seed = 0;
34 // for the lattice generation
35 Map<HNode, Integer> mapHNodeToUniqueIndex;
36 Map<HNode, Set<Integer>> mapHNodeToBasis;
37 Set<Integer> BASISTOPELEMENT;
39 public HierarchyGraph() {
40 mapHNodeToIncomingSet = new HashMap<HNode, Set<HNode>>();
41 mapHNodeToOutgoingSet = new HashMap<HNode, Set<HNode>>();
42 mapHNodeToDescSet = new HashMap<HNode, Set<Descriptor>>();
43 mapDescToHNode = new HashMap<Descriptor, HNode>();
44 mapSkeletonNodeSetToCombinationNode = new HashMap<Set<HNode>, HNode>();
45 mapCombinationNodeToCombineNodeSet = new HashMap<HNode, Set<HNode>>();
46 mapCombineNodeSetToOutgoingNodeSet = new HashMap<Set<HNode>, Set<HNode>>();
47 mapCombineNodeSetToCombinationNode = new HashMap<Set<HNode>, HNode>();
48 nodeSet = new HashSet<HNode>();
50 mapHNodeToUniqueIndex = new HashMap<HNode, Integer>();
51 mapHNodeToBasis = new HashMap<HNode, Set<Integer>>();
53 mapHNodeToLocationName = new HashMap<HNode, String>();
57 public Descriptor getDesc() {
61 public void setDesc(Descriptor desc) {
65 public void addMapHNodeToLocationName(HNode node, String locName) {
66 mapHNodeToLocationName.put(node, locName);
69 public String getLocationName(HNode node) {
70 return mapHNodeToLocationName.get(node);
73 public String getName() {
77 public void setName(String name) {
81 public HierarchyGraph(Descriptor d) {
87 public Map<HNode, Set<Descriptor>> getMapHNodeToDescSet() {
88 return mapHNodeToDescSet;
91 public void setMapHNodeToDescSet(Map<HNode, Set<Descriptor>> map) {
92 mapHNodeToDescSet.putAll(map);
95 public Map<Descriptor, HNode> getMapDescToHNode() {
96 return mapDescToHNode;
99 public void setMapDescToHNode(Map<Descriptor, HNode> map) {
100 mapDescToHNode.putAll(map);
103 public Set<HNode> getNodeSet() {
107 public void addEdge(HNode srcHNode, HNode dstHNode) {
109 if (!nodeSet.contains(srcHNode)) {
110 nodeSet.add(srcHNode);
113 if (!nodeSet.contains(dstHNode)) {
114 nodeSet.add(dstHNode);
117 Set<HNode> possibleCycleSet = getPossibleCycleNodes(srcHNode, dstHNode);
119 if (possibleCycleSet.size() > 0) {
121 if (possibleCycleSet.size() == 1) {
122 if (dstHNode.isSharedNode()) {
123 // it has already been assigned shared node.
128 HNode newMergeNode = mergeNodes(possibleCycleSet, false);
129 newMergeNode.setSharedNode(true);
130 System.out.println("### INTRODUCE A NEW MERGE NODE: " + newMergeNode);
131 System.out.println("### CYCLIC VALUE FLOW: " + srcHNode + " -> " + dstHNode);
133 getIncomingNodeSet(dstHNode).add(srcHNode);
134 getOutgoingNodeSet(srcHNode).add(dstHNode);
135 System.out.println("add an edge " + srcHNode + " -> " + dstHNode);
140 public void addNode(HNode node) {
144 public void addEdge(Descriptor src, Descriptor dst) {
145 HNode srcHNode = getHNode(src);
146 HNode dstHNode = getHNode(dst);
148 addEdge(srcHNode, dstHNode);
152 public void setParamHNode(Descriptor d) {
153 getHNode(d).setSkeleton(true);
156 public HNode getHNode(Descriptor d) {
157 if (!mapDescToHNode.containsKey(d)) {
158 HNode newNode = new HNode(d);
159 if (d instanceof FieldDescriptor) {
160 newNode.setSkeleton(true);
162 mappingDescriptorToHNode(d, newNode);
163 nodeSet.add(newNode);
165 return mapDescToHNode.get(d);
168 private void mappingDescriptorToHNode(Descriptor desc, HNode node) {
169 mapDescToHNode.put(desc, node);
170 if (!mapHNodeToDescSet.containsKey(node)) {
171 mapHNodeToDescSet.put(node, new HashSet<Descriptor>());
173 mapHNodeToDescSet.get(node).add(desc);
176 public HierarchyGraph generateSkeletonGraph() {
178 // compose a skeleton graph that only consists of fields or parameters
179 HierarchyGraph skeletonGraph = new HierarchyGraph(desc);
180 skeletonGraph.setName(desc + "_SKELETON");
182 for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
183 HNode src = (HNode) iterator.next();
184 if (src.isSkeleton()) {
185 Set<HNode> reachSet = getDirectlyReachSkeletonSet(src);
186 if (reachSet.size() > 0) {
187 for (Iterator iterator2 = reachSet.iterator(); iterator2.hasNext();) {
188 HNode dst = (HNode) iterator2.next();
189 skeletonGraph.addEdge(src, dst);
192 skeletonGraph.addNode(src);
197 skeletonGraph.setMapDescToHNode(getMapDescToHNode());
198 skeletonGraph.setMapHNodeToDescSet(getMapHNodeToDescSet());
200 return skeletonGraph;
204 private Set<HNode> getDirectlyReachSkeletonSet(HNode node) {
206 Set<HNode> visited = new HashSet<HNode>();
207 Set<HNode> connected = new HashSet<HNode>();
208 recurReachSkeletonSet(node, connected, visited);
213 public void removeRedundantEdges() {
215 for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
216 HNode src = (HNode) iterator.next();
217 Set<HNode> connectedSet = getOutgoingNodeSet(src);
218 Set<HNode> toberemovedSet = new HashSet<HNode>();
219 for (Iterator iterator2 = connectedSet.iterator(); iterator2.hasNext();) {
220 HNode dst = (HNode) iterator2.next();
221 Set<HNode> otherNeighborSet = new HashSet<HNode>();
222 otherNeighborSet.addAll(connectedSet);
223 otherNeighborSet.remove(dst);
224 for (Iterator iterator3 = otherNeighborSet.iterator(); iterator3.hasNext();) {
225 HNode neighbor = (HNode) iterator3.next();
226 if (reachTo(neighbor, dst, new HashSet<HNode>())) {
227 toberemovedSet.add(dst);
231 if (toberemovedSet.size() > 0) {
232 connectedSet.removeAll(toberemovedSet);
234 for (Iterator iterator2 = toberemovedSet.iterator(); iterator2.hasNext();) {
235 HNode node = (HNode) iterator2.next();
236 getIncomingNodeSet(node).remove(src);
244 public void simplifyHierarchyGraph() {
245 removeRedundantEdges();
246 combineRedundantNodes(false);
249 public void simplifySkeletonCombinationHierarchyGraph() {
250 removeRedundantEdges();
251 combineRedundantNodes(true);
254 public void combineRedundantNodes(boolean onlyCombinationNodes) {
255 // Combine field/parameter nodes who have the same set of incoming/outgoing edges.
256 boolean isUpdated = false;
258 isUpdated = combineTwoRedundatnNodes(onlyCombinationNodes);
262 private Set<HNode> getIncomingNodeSet(HNode node) {
263 if (!mapHNodeToIncomingSet.containsKey(node)) {
264 mapHNodeToIncomingSet.put(node, new HashSet<HNode>());
266 return mapHNodeToIncomingSet.get(node);
269 public Set<HNode> getOutgoingNodeSet(HNode node) {
270 if (!mapHNodeToOutgoingSet.containsKey(node)) {
271 mapHNodeToOutgoingSet.put(node, new HashSet<HNode>());
273 return mapHNodeToOutgoingSet.get(node);
276 private boolean combineTwoRedundatnNodes(boolean onlyCombinationNodes) {
277 for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
278 HNode node1 = (HNode) iterator.next();
280 if ((onlyCombinationNodes && (!node1.isCombinationNode()))
281 || (!onlyCombinationNodes && (!node1.isSkeleton()))) {
285 Set<HNode> incomingNodeSet1 = getIncomingNodeSet(node1);
286 Set<HNode> outgoingNodeSet1 = getOutgoingNodeSet(node1);
288 for (Iterator iterator2 = nodeSet.iterator(); iterator2.hasNext();) {
289 HNode node2 = (HNode) iterator2.next();
291 if ((onlyCombinationNodes && (!node2.isCombinationNode()))
292 || (!onlyCombinationNodes && (!node2.isSkeleton()))) {
296 if (!node1.equals(node2)) {
298 Set<HNode> incomingNodeSet2 = getIncomingNodeSet(node2);
299 Set<HNode> outgoingNodeSet2 = getOutgoingNodeSet(node2);
301 if (incomingNodeSet1.equals(incomingNodeSet2)
302 && outgoingNodeSet1.equals(outgoingNodeSet2)) {
303 // need to merge node1 and node2
305 Set<HNode> mergeSet = new HashSet<HNode>();
308 mergeNodes(mergeSet, onlyCombinationNodes);
319 private void addEdgeWithNoCycleCheck(HNode srcHNode, HNode dstHNode) {
320 getIncomingNodeSet(dstHNode).add(srcHNode);
321 getOutgoingNodeSet(srcHNode).add(dstHNode);
322 System.out.println("addEdgeWithNoCycleCheck src=" + srcHNode + " -> " + dstHNode);
325 private HNode mergeNodes(Set<HNode> set, boolean onlyCombinationNodes) {
327 Set<HNode> incomingNodeSet = new HashSet<HNode>();
328 Set<HNode> outgoingNodeSet = new HashSet<HNode>();
330 for (Iterator iterator = set.iterator(); iterator.hasNext();) {
331 HNode node = (HNode) iterator.next();
332 incomingNodeSet.addAll(getIncomingNodeSet(node));
333 outgoingNodeSet.addAll(getOutgoingNodeSet(node));
337 if (onlyCombinationNodes) {
338 nodeName = "Comb" + (seed++);
340 nodeName = "Node" + (seed++);
342 HNode newMergeNode = new HNode(nodeName);
344 nodeSet.add(newMergeNode);
345 nodeSet.removeAll(set);
347 // if the input set contains a skeleton node, need to set a new merge node as skeleton also
348 boolean hasSkeleton = false;
349 for (Iterator iterator = set.iterator(); iterator.hasNext();) {
350 HNode inNode = (HNode) iterator.next();
351 if (inNode.isSkeleton()) {
356 System.out.println("--Set merging node=" + newMergeNode + " as a skeleton=" + set
357 + " hasSkeleton=" + hasSkeleton);
358 newMergeNode.setSkeleton(hasSkeleton);
360 for (Iterator iterator = set.iterator(); iterator.hasNext();) {
361 HNode node = (HNode) iterator.next();
362 Set<Descriptor> descSetOfNode = getDescSetOfNode(node);
363 for (Iterator iterator2 = descSetOfNode.iterator(); iterator2.hasNext();) {
364 Descriptor desc = (Descriptor) iterator2.next();
365 mappingDescriptorToHNode(desc, newMergeNode);
369 for (Iterator iterator = incomingNodeSet.iterator(); iterator.hasNext();) {
370 HNode inNode = (HNode) iterator.next();
371 Set<HNode> outSet = getOutgoingNodeSet(inNode);
372 outSet.removeAll(set);
373 if (!set.contains(inNode)) {
374 addEdgeWithNoCycleCheck(inNode, newMergeNode);
378 for (Iterator iterator = outgoingNodeSet.iterator(); iterator.hasNext();) {
379 HNode outNode = (HNode) iterator.next();
380 Set<HNode> inSet = getIncomingNodeSet(outNode);
381 inSet.removeAll(set);
382 if (!set.contains(outNode)) {
383 addEdgeWithNoCycleCheck(newMergeNode, outNode);
387 System.out.println("###MERGING NODE=" + set + " new node=" + newMergeNode);
391 private Set<Descriptor> getDescSetOfNode(HNode node) {
392 if (!mapHNodeToDescSet.containsKey(node)) {
393 mapHNodeToDescSet.put(node, new HashSet<Descriptor>());
395 return mapHNodeToDescSet.get(node);
398 private boolean reachTo(HNode src, HNode dst, Set<HNode> visited) {
399 Set<HNode> connectedSet = getOutgoingNodeSet(src);
400 for (Iterator<HNode> iterator = connectedSet.iterator(); iterator.hasNext();) {
401 HNode n = iterator.next();
405 if (!visited.contains(n)) {
407 if (reachTo(n, dst, visited)) {
415 private void recurReachSkeletonSet(HNode node, Set<HNode> connected, Set<HNode> visited) {
417 Set<HNode> outSet = getOutgoingNodeSet(node);
418 for (Iterator iterator = outSet.iterator(); iterator.hasNext();) {
419 HNode outNode = (HNode) iterator.next();
421 if (outNode.isSkeleton()) {
422 connected.add(outNode);
423 } else if (!visited.contains(outNode)) {
424 visited.add(outNode);
425 recurReachSkeletonSet(outNode, connected, visited);
431 public Set<HNode> getDirectlyReachableSkeletonCombinationNodeFrom(HNode node,
432 Set<HNode> combinationNodeSet) {
433 Set<HNode> reachable = new HashSet<HNode>();
434 Set<HNode> visited = new HashSet<HNode>();
436 recurDirectlyReachableSkeletonCombinationNodeFrom(node, visited, reachable, combinationNodeSet);
440 public void recurDirectlyReachableSkeletonCombinationNodeFrom(HNode node, Set<HNode> visited,
441 Set<HNode> reachable, Set<HNode> combinationNodeSet) {
443 Set<HNode> outSet = getOutgoingNodeSet(node);
444 for (Iterator iterator = outSet.iterator(); iterator.hasNext();) {
445 HNode out = (HNode) iterator.next();
447 if (!visited.contains(out)) {
449 if (out.isSkeleton()) {
451 } else if (out.isCombinationNode()) {
452 if (combinationNodeSet == null) {
454 } else if (!combinationNodeSet.contains(out)) {
457 recurDirectlyReachableSkeletonCombinationNodeFrom(out, visited, reachable,
461 recurDirectlyReachableSkeletonCombinationNodeFrom(out, visited, reachable,
471 public HNode getDirectlyReachableSkeletonCombinationNodeFrom(HNode node) {
472 Set<HNode> visited = new HashSet<HNode>();
473 return recurDirectlyReachableSkeletonCombinationNodeFrom(node, visited);
476 public HNode recurDirectlyReachableSkeletonCombinationNodeFrom(HNode node, Set<HNode> visited) {
478 Set<HNode> outSet = getOutgoingNodeSet(node);
479 for (Iterator iterator = outSet.iterator(); iterator.hasNext();) {
480 HNode out = (HNode) iterator.next();
481 // if (!visited.contains(out)) {
482 if (out.isCombinationNode() || out.isSkeleton()) {
486 return getDirectlyReachableSkeletonCombinationNodeFrom(out);
494 public Set<HNode> getPossibleCycleNodes(HNode src, HNode dst) {
495 // if an edge from src to dst introduces a new cycle flow,
496 // the method returns the set of elements consisting of the cycle
497 Set<HNode> cycleNodeSet = new HashSet<HNode>();
498 // if the dst node reaches to the src node, the new relation
499 // introduces a cycle to the lattice
500 if (dst.equals(src)) {
501 cycleNodeSet.add(dst);
502 cycleNodeSet.add(src);
503 } else if (reachTo(dst, src)) {
504 cycleNodeSet.add(dst);
505 cycleNodeSet.add(src);
506 getInBetweenElements(dst, src, cycleNodeSet);
511 private void getInBetweenElements(HNode start, HNode end, Set<HNode> nodeSet) {
512 Set<HNode> connectedSet = getOutgoingNodeSet(start);
513 for (Iterator iterator = connectedSet.iterator(); iterator.hasNext();) {
514 HNode cur = (HNode) iterator.next();
515 if ((!start.equals(cur)) && (!cur.equals(end)) && reachTo(cur, end)) {
517 getInBetweenElements(cur, end, nodeSet);
522 public boolean reachTo(HNode node1, HNode node2) {
523 return reachTo(node1, node2, new HashSet<HNode>());
526 public Set<HNode> getCombineSetByCombinationNode(HNode node) {
527 if (!mapCombinationNodeToCombineNodeSet.containsKey(node)) {
528 mapCombinationNodeToCombineNodeSet.put(node, new HashSet<HNode>());
530 return mapCombinationNodeToCombineNodeSet.get(node);
533 public HNode getCombinationNode(Set<HNode> combineSet) {
534 if (!mapCombineNodeSetToCombinationNode.containsKey(combineSet)) {
535 String name = "COMB" + (seed++);
536 HNode node = new HNode(name);
537 node.setCombinationNode(true);
539 mapCombineNodeSetToCombinationNode.put(combineSet, node);
540 mapCombinationNodeToCombineNodeSet.put(node, combineSet);
543 return mapCombineNodeSetToCombinationNode.get(combineSet);
546 public Set<Set<HNode>> getCombineNodeSet() {
547 return mapCombineNodeSetToOutgoingNodeSet.keySet();
550 public void insertCombinationNodesToGraph(HierarchyGraph hierarchyGraph) {
551 // add a new combination node where parameter/field flows are actually combined.
553 hierarchyGraph.identifyCombinationNodes();
555 Set<Set<HNode>> keySet = hierarchyGraph.getCombineNodeSet();
556 for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
557 Set<HNode> combineSet = (Set<HNode>) iterator.next();
558 System.out.println("--combineSet=" + combineSet);
559 HNode combinationNode = getCombinationNode(combineSet);
560 System.out.println("--combinationNode=" + combinationNode);
561 // add an edge from a skeleton node to a combination node
562 for (Iterator iterator2 = combineSet.iterator(); iterator2.hasNext();) {
563 HNode inSkeletonNode = (HNode) iterator2.next();
564 // System.out.println("--inSkeletonNode=" + inSkeletonNode + " desc="
565 // + inSkeletonNode.getDescriptor());
567 if (inSkeletonNode.getDescriptor() == null) {
568 // the node is merging one...
569 srcNode = inSkeletonNode;
571 srcNode = getHNode(inSkeletonNode.getDescriptor());
573 // System.out.println("--srcNode=" + srcNode);
574 addEdgeWithNoCycleCheck(srcNode, combinationNode);
577 // add an edge from the combination node to outgoing nodes
578 Set<HNode> outSet = hierarchyGraph.getOutgoingNodeSetByCombineSet(combineSet);
579 for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
580 HNode curNode = (HNode) iterator2.next();
581 if (curNode.isCombinationNode()) {
582 Set<HNode> combineNode = hierarchyGraph.getCombineSetByCombinationNode(curNode);
583 HNode outNode = getCombinationNode(combineNode);
584 addEdgeWithNoCycleCheck(combinationNode, outNode);
585 } else if (curNode.isSkeleton()) {
586 addEdgeWithNoCycleCheck(combinationNode, curNode);
590 System.out.println("--");
596 private void addCombinationNode(HNode curNode, Set<HNode> reachToSet, Set<HNode> reachableSet) {
597 if (!mapSkeletonNodeSetToCombinationNode.containsKey(reachToSet)) {
598 // need to create a new combination node
599 String nodeName = "Comb" + (seed++);
600 HNode newCombinationNode = new HNode(nodeName);
601 newCombinationNode.setCombinationNode(true);
603 nodeSet.add(newCombinationNode);
604 mapSkeletonNodeSetToCombinationNode.put(reachToSet, newCombinationNode);
606 for (Iterator iterator = reachToSet.iterator(); iterator.hasNext();) {
607 HNode reachToNode = (HNode) iterator.next();
608 addEdge(reachToNode, newCombinationNode);
613 HNode combinationNode = mapSkeletonNodeSetToCombinationNode.get(reachToSet);
614 for (Iterator iterator = reachableSet.iterator(); iterator.hasNext();) {
615 HNode reachableNode = (HNode) iterator.next();
616 addEdge(combinationNode, reachableNode);
621 private Set<HNode> getSkeleteNodeSetReachTo(HNode node) {
623 Set<HNode> reachToSet = new HashSet<HNode>();
624 Set<HNode> visited = new HashSet<HNode>();
625 recurSkeletonReachTo(node, reachToSet, visited);
627 // if a node reaches to one of elements in the reachToSet, we do not need to keep it
628 // because the node is not directly connected to the combination node
630 removeRedundantReachToNodes(reachToSet);
635 private void removeRedundantReachToNodes(Set<HNode> reachToSet) {
637 Set<HNode> toberemoved = new HashSet<HNode>();
638 for (Iterator iterator = reachToSet.iterator(); iterator.hasNext();) {
639 HNode cur = (HNode) iterator.next();
641 for (Iterator iterator2 = reachToSet.iterator(); iterator2.hasNext();) {
642 HNode dst = (HNode) iterator2.next();
643 if (!cur.equals(dst) && reachTo(cur, dst)) {
645 toberemoved.add(cur);
649 reachToSet.removeAll(toberemoved);
652 private void recurSkeletonReachTo(HNode node, Set<HNode> reachToSet, Set<HNode> visited) {
654 Set<HNode> inSet = getIncomingNodeSet(node);
655 for (Iterator iterator = inSet.iterator(); iterator.hasNext();) {
656 HNode inNode = (HNode) iterator.next();
658 if (inNode.isSkeleton()) {
659 reachToSet.add(inNode);
660 } else if (!visited.contains(inNode)) {
662 recurSkeletonReachTo(inNode, reachToSet, visited);
668 public Map<HNode, Set<HNode>> getMapHNodeToOutgoingSet() {
669 return mapHNodeToOutgoingSet;
672 public Map<HNode, Set<HNode>> getMapHNodeToIncomingSet() {
673 return mapHNodeToIncomingSet;
676 public void setMapHNodeToOutgoingSet(Map<HNode, Set<HNode>> in) {
677 mapHNodeToOutgoingSet.clear();
678 Set<HNode> keySet = in.keySet();
679 for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
680 HNode key = (HNode) iterator.next();
681 Set<HNode> inSet = in.get(key);
682 Set<HNode> newSet = new HashSet<HNode>();
683 newSet.addAll(inSet);
684 mapHNodeToOutgoingSet.put(key, newSet);
688 public void setMapHNodeToIncomingSet(Map<HNode, Set<HNode>> in) {
689 mapHNodeToIncomingSet.clear();
690 Set<HNode> keySet = in.keySet();
691 for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
692 HNode key = (HNode) iterator.next();
693 Set<HNode> inSet = in.get(key);
694 Set<HNode> newSet = new HashSet<HNode>();
695 newSet.addAll(inSet);
696 mapHNodeToIncomingSet.put(key, newSet);
700 public void setNodeSet(Set<HNode> inSet) {
702 nodeSet.addAll(inSet);
705 public HierarchyGraph clone() {
706 HierarchyGraph clone = new HierarchyGraph();
707 clone.setDesc(getDesc());
708 clone.setName(getName());
709 clone.setNodeSet(getNodeSet());
710 clone.setMapHNodeToIncomingSet(getMapHNodeToIncomingSet());
711 clone.setMapHNodeToOutgoingSet(getMapHNodeToOutgoingSet());
712 clone.setMapDescToHNode(getMapDescToHNode());
713 clone.setMapHNodeToDescSet(getMapHNodeToDescSet());
718 public Set<HNode> getOutgoingNodeSetByCombineSet(Set<HNode> combineSet) {
720 if (!mapCombineNodeSetToOutgoingNodeSet.containsKey(combineSet)) {
721 mapCombineNodeSetToOutgoingNodeSet.put(combineSet, new HashSet<HNode>());
723 return mapCombineNodeSetToOutgoingNodeSet.get(combineSet);
726 public void identifyCombinationNodes() {
728 // 1) set combination node flag if a node combines more than one skeleton node.
729 for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
730 HNode node = (HNode) iterator.next();
731 if (!node.isSkeleton()) {
732 Set<HNode> reachToSet = getSkeleteNodeSetReachTo(node);
733 // if (reachToSet.size() > 1) {
734 if (countSkeletonNodes(reachToSet) > 1) {
735 System.out.println("-node=" + node + " reachToSet=" + reachToSet);
736 System.out.println("-set combinationnode=" + node);
737 node.setCombinationNode(true);
738 mapCombinationNodeToCombineNodeSet.put(node, reachToSet);
743 // 2) compute the outgoing set that needs to be directly connected from the combination node
744 for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
745 HNode node = (HNode) iterator.next();
746 if (node.isCombinationNode()) {
747 Set<HNode> combineSet = mapCombinationNodeToCombineNodeSet.get(node);
748 Set<HNode> outSet = getDirectlyReachableNodeSetFromCombinationNode(node);
749 addMapCombineSetToOutgoingSet(combineSet, outSet);
755 public Map<HNode, Set<HNode>> getMapCombinationNodeToCombineNodeSet() {
756 return mapCombinationNodeToCombineNodeSet;
759 public int countSkeletonNodes(Set<HNode> set) {
762 for (Iterator iterator = set.iterator(); iterator.hasNext();) {
763 HNode node = (HNode) iterator.next();
764 Set<Descriptor> descSet = getDescSetOfNode(node);
765 count += descSet.size();
771 private void addMapCombineSetToOutgoingSet(Set<HNode> combineSet, Set<HNode> outSet) {
772 if (!mapCombineNodeSetToOutgoingNodeSet.containsKey(combineSet)) {
773 mapCombineNodeSetToOutgoingNodeSet.put(combineSet, new HashSet<HNode>());
775 mapCombineNodeSetToOutgoingNodeSet.get(combineSet).addAll(outSet);
778 private Set<HNode> getDirectlyReachableNodeSetFromCombinationNode(HNode node) {
779 // the method returns the set of nodes that are reachable from the current node
780 // and do not combine the same set of skeleton nodes...
782 Set<HNode> visited = new HashSet<HNode>();
783 Set<HNode> reachableSet = new HashSet<HNode>();
784 Set<HNode> combineSet = mapCombinationNodeToCombineNodeSet.get(node);
786 recurDirectlyReachableNodeSetFromCombinationNode(node, combineSet, reachableSet, visited);
791 private void recurDirectlyReachableNodeSetFromCombinationNode(HNode node, Set<HNode> combineSet,
792 Set<HNode> reachableSet, Set<HNode> visited) {
794 Set<HNode> outSet = getOutgoingNodeSet(node);
795 for (Iterator iterator = outSet.iterator(); iterator.hasNext();) {
796 HNode outNode = (HNode) iterator.next();
798 if (outNode.isCombinationNode()) {
799 Set<HNode> combineSetOfOutNode = mapCombinationNodeToCombineNodeSet.get(outNode);
800 if (combineSetOfOutNode.equals(combineSet)) {
801 recurDirectlyReachableNodeSetFromCombinationNode(outNode, combineSet, reachableSet,
804 reachableSet.add(outNode);
806 } else if (outNode.isSkeleton()) {
807 reachableSet.add(outNode);
814 private Set<HNode> getReachableNodeSetFrom(HNode node) {
816 Set<HNode> reachableSet = new HashSet<HNode>();
817 Set<HNode> visited = new HashSet<HNode>();
819 recurReachableNodeSetFrom(node, reachableSet, visited);
824 private void recurReachableNodeSetFrom(HNode node, Set<HNode> reachableSet, Set<HNode> visited) {
826 Set<HNode> outgoingNodeSet = getOutgoingNodeSet(node);
827 for (Iterator iterator = outgoingNodeSet.iterator(); iterator.hasNext();) {
828 HNode outNode = (HNode) iterator.next();
829 reachableSet.add(outNode);
830 if (!visited.contains(outNode)) {
831 visited.add(outNode);
832 recurReachableNodeSetFrom(outNode, reachableSet, visited);
838 public void assignUniqueIndexToNode() {
840 for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
841 HNode node = (HNode) iterator.next();
842 mapHNodeToUniqueIndex.put(node, idx);
846 BASISTOPELEMENT = new HashSet<Integer>();
847 for (int i = 1; i < idx + 1; i++) {
848 BASISTOPELEMENT.add(i);
852 public BasisSet computeBasisSet() {
854 // assign a unique index to a node
855 assignUniqueIndexToNode();
857 // compute basis for each node
858 for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
859 HNode node = (HNode) iterator.next();
861 Set<Integer> basis = new HashSet<Integer>();
862 basis.addAll(BASISTOPELEMENT);
864 Set<HNode> reachableNodeSet = getReachableNodeSetFrom(node);
865 System.out.println("node=" + node + " reachableNodeSet=" + reachableNodeSet);
867 // if a node is reachable from the current node
868 // need to remove the index of the reachable node from the basis
870 basis.remove(getHNodeIndex(node));
871 for (Iterator iterator2 = reachableNodeSet.iterator(); iterator2.hasNext();) {
872 HNode reachableNode = (HNode) iterator2.next();
873 int idx = getHNodeIndex(reachableNode);
877 mapHNodeToBasis.put(node, basis);
880 // construct the basis set
882 BasisSet basisSet = new BasisSet();
884 Set<HNode> keySet = mapHNodeToBasis.keySet();
885 for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
886 HNode node = (HNode) iterator.next();
887 Set<Integer> basis = mapHNodeToBasis.get(node);
888 basisSet.addElement(basis, node);
895 public int getHNodeIndex(HNode node) {
896 return mapHNodeToUniqueIndex.get(node).intValue();
899 public Map<HNode, Integer> getMapHNodeToUniqueIndex() {
900 return mapHNodeToUniqueIndex;
903 public Map<HNode, Set<Integer>> getMapHNodeToBasis() {
904 return mapHNodeToBasis;
907 public Set<HNode> getCombinationNodeSetByCombineNodeSet(Set<HNode> combineSkeletonNodeSet) {
909 Set<HNode> combinationNodeSet = new HashSet<HNode>();
910 Set<HNode> keySet = mapCombinationNodeToCombineNodeSet.keySet();
911 for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
912 HNode key = (HNode) iterator.next();
914 if (mapCombinationNodeToCombineNodeSet.get(key).equals(combineSkeletonNodeSet)) {
915 combinationNodeSet.add(key);
919 return combinationNodeSet;
922 public void writeGraph() {
924 String graphName = "hierarchy" + name;
925 graphName = graphName.replaceAll("[\\W]", "");
928 BufferedWriter bw = new BufferedWriter(new FileWriter(graphName + ".dot"));
930 bw.write("digraph " + graphName + " {\n");
932 Iterator<HNode> iter = nodeSet.iterator();
934 Set<HNode> addedNodeSet = new HashSet<HNode>();
936 while (iter.hasNext()) {
937 HNode u = iter.next();
939 Set<HNode> outSet = getOutgoingNodeSet(u);
941 if (outSet.size() == 0) {
942 if (!addedNodeSet.contains(u)) {
947 for (Iterator iterator = outSet.iterator(); iterator.hasNext();) {
948 HNode v = (HNode) iterator.next();
949 if (!addedNodeSet.contains(u)) {
953 if (!addedNodeSet.contains(v)) {
957 bw.write("" + u.getName() + " -> " + v.getName() + ";\n");
966 } catch (IOException e) {
971 private void drawNode(BufferedWriter bw, HNode node) throws IOException {
972 String nodeName = node.toString();
973 nodeName = nodeName.substring(1, nodeName.length() - 1);
974 bw.write(node.getName() + " [label=\"" + nodeName + "\"]" + ";\n");