79c0ce9546470ffde24539f4c7a252c219328dda
[IRC.git] / Robust / src / Analysis / SSJava / BuildLattice.java
1 package Analysis.SSJava;
2
3 import java.util.HashMap;
4 import java.util.HashSet;
5 import java.util.Iterator;
6 import java.util.Map;
7 import java.util.Set;
8
9 import IR.Descriptor;
10 import IR.MethodDescriptor;
11 import Util.Pair;
12
13 public class BuildLattice {
14
15   private LocationInference infer;
16
17   private final HNode topNode;
18   private final HNode bottomNode;
19
20   public BuildLattice(LocationInference infer) {
21     this.infer = infer;
22     topNode = new HNode(infer.ssjava.TOP);
23     bottomNode = new HNode(infer.ssjava.BOTTOM);
24   }
25
26   public SSJavaLattice<String> buildLattice(Descriptor desc) {
27
28     HierarchyGraph inputGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
29     LocationSummary locSummary = infer.getLocationSummary(desc);
30
31     Set<HNode> nodeSetWithCompositeLocation = new HashSet<HNode>();
32     if (desc instanceof MethodDescriptor) {
33       FlowGraph flowGraph = infer.getFlowGraph((MethodDescriptor) desc);
34
35       for (Iterator iterator = inputGraph.getNodeSet().iterator(); iterator.hasNext();) {
36         HNode hnode = (HNode) iterator.next();
37         Descriptor hnodeDesc = hnode.getDescriptor();
38         if (hnodeDesc != null) {
39           NTuple<Descriptor> descTuple = new NTuple<Descriptor>();
40           descTuple.add(hnodeDesc);
41
42           if (flowGraph.contains(descTuple)) {
43             FlowNode flowNode = flowGraph.getFlowNode(descTuple);
44             if (flowNode.getCompositeLocation() != null) {
45               nodeSetWithCompositeLocation.add(hnode);
46             }
47           }
48
49         }
50       }
51
52     }
53
54     BasisSet basisSet = inputGraph.computeBasisSet(nodeSetWithCompositeLocation);
55     debug_print(inputGraph);
56
57     Family family = generateFamily(basisSet);
58     Map<Set<Integer>, Set<Set<Integer>>> mapImSucc = coveringGraph(basisSet, family);
59
60     SSJavaLattice<String> lattice = buildLattice(basisSet, inputGraph, locSummary, mapImSucc);
61     return lattice;
62
63   }
64
65   private SSJavaLattice<String> buildLattice(BasisSet basisSet, HierarchyGraph inputGraph,
66       LocationSummary locSummary, Map<Set<Integer>, Set<Set<Integer>>> mapImSucc) {
67
68     SSJavaLattice<String> lattice =
69         new SSJavaLattice<String>(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM);
70
71     Map<Set<Integer>, String> mapFToLocName = new HashMap<Set<Integer>, String>();
72
73     Set<Set<Integer>> keySet = mapImSucc.keySet();
74     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
75       Set<Integer> higher = (Set<Integer>) iterator.next();
76
77       String higherName = generateElementName(basisSet, inputGraph, mapFToLocName, higher);
78
79       HNode higherNode = inputGraph.getHNode(higherName);
80       if (higherNode != null && higherNode.isSharedNode()) {
81         lattice.addSharedLoc(higherName);
82       }
83       Set<Descriptor> descSet = inputGraph.getDescSetOfNode(higherNode);
84       // System.out.println("higherName=" + higherName + "  higherNode=" + higherNode + "  descSet="
85       // + descSet);
86       for (Iterator iterator2 = descSet.iterator(); iterator2.hasNext();) {
87         Descriptor d = (Descriptor) iterator2.next();
88         locSummary.addMapHNodeNameToLocationName(d.getSymbol(), higherName);
89       }
90       // locSummary.addMapHNodeNameToLocationName(higherName, higherName);
91
92       Set<Set<Integer>> lowerSet = mapImSucc.get(higher);
93       for (Iterator iterator2 = lowerSet.iterator(); iterator2.hasNext();) {
94         Set<Integer> lower = (Set<Integer>) iterator2.next();
95
96         String lowerName = generateElementName(basisSet, inputGraph, mapFToLocName, lower);
97         HNode lowerNode = inputGraph.getHNode(lowerName);
98         if (lowerNode != null && lowerNode.isSharedNode()) {
99           lattice.addSharedLoc(lowerName);
100         }
101
102         Set<Descriptor> lowerDescSet = inputGraph.getDescSetOfNode(lowerNode);
103         // System.out.println("lowerName=" + lowerName + "  lowerNode=" + lowerNode + "  descSet="
104         // + lowerDescSet);
105         for (Iterator iterator3 = lowerDescSet.iterator(); iterator3.hasNext();) {
106           Descriptor d = (Descriptor) iterator3.next();
107           locSummary.addMapHNodeNameToLocationName(d.getSymbol(), lowerName);
108         }
109         // locSummary.addMapHNodeNameToLocationName(lowerName, lowerName);
110
111         if (higher.size() == 0) {
112           // empty case
113           lattice.put(lowerName);
114         } else {
115           lattice.addRelationHigherToLower(higherName, lowerName);
116         }
117
118       }
119
120     }
121
122     return lattice;
123   }
124
125   public HNode getCombinationNodeInSCGraph(Descriptor desc, HNode nodeFromSimpleGraph) {
126
127     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
128
129     if (nodeFromSimpleGraph.isSkeleton()) {
130       return scGraph.getCurrentHNode(nodeFromSimpleGraph);
131     }
132
133     Set<HNode> combineSkeletonNodeSet =
134         infer.getSimpleHierarchyGraph(desc).getCombineSetByCombinationNode(nodeFromSimpleGraph);
135     HNode combinationNodeInSCGraph =
136         infer.getSkeletonCombinationHierarchyGraph(desc).getMapCombineNodeSetToCombinationNode()
137             .get(combineSkeletonNodeSet);
138
139     // Set<HNode> combineSkeletonNodeSet =
140     // infer.getSimpleHierarchyGraph(desc).getCombineSetByCombinationNode(simpleGraphNode);
141     // HNode combinationNodeInSCGraph =
142     // infer.getSkeletonCombinationHierarchyGraph(desc).getCombinationNode(combineSkeletonNodeSet);
143     return combinationNodeInSCGraph;
144   }
145
146   public SSJavaLattice<String> insertIntermediateNodesToStraightLine(Descriptor desc,
147       SSJavaLattice<String> skeletonLattice) {
148
149     // perform DFS that starts from each skeleton/combination node and ends by another
150     // skeleton/combination node
151
152     HierarchyGraph simpleGraph = infer.getSimpleHierarchyGraph(desc);
153     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
154     LocationSummary locSummary = infer.getLocationSummary(desc);
155
156     SSJavaLattice<String> lattice = skeletonLattice.clone();
157
158     Set<HNode> visited = new HashSet<HNode>();
159
160     Set<HNode> nodeSet = simpleGraph.getNodeSet();
161
162     Map<TripleItem, String> mapIntermediateLoc = new HashMap<TripleItem, String>();
163
164     System.out.println("*insert=" + desc);
165     System.out.println("***nodeSet=" + nodeSet);
166     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
167       HNode node = (HNode) iterator.next();
168       System.out.println("node=" + node);
169       if (node.isSkeleton() && (!visited.contains(node))) {
170         visited.add(node);
171
172         Set<HNode> outSet = simpleGraph.getOutgoingNodeSet(node);
173         for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
174           HNode outNode = (HNode) iterator2.next();
175
176           if (!outNode.isSkeleton()) {
177             if (outNode.isCombinationNode()) {
178               expandCombinationNode(desc, lattice, visited, mapIntermediateLoc, locSummary, outNode);
179             } else {
180               // we have a node that is neither combination or skeleton node
181               // System.out.println("%%%skeleton node=" + node + "  outNode=" + outNode);
182               HNode startNode = scGraph.getCurrentHNode(node);
183
184               // if (node.getDescriptor() != null) {
185               // // node is a skeleton node and it might be merged into another node in the SC
186               // graph.
187               // startNode = scGraph.getHNode(node.getDescriptor());
188               // } else {
189               // // this node has already been merged before the SC graph.
190               // startNode = node;
191               // }
192
193               Set<HNode> endNodeSetFromSimpleGraph =
194                   simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(outNode, null);
195
196               // System.out.println("endNodeSetFromSimpleGraph=" + endNodeSetFromSimpleGraph
197               // + "   from=" + outNode);
198               Set<HNode> endCombNodeSet = new HashSet<HNode>();
199               for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
200                 HNode endNode = (HNode) iterator3.next();
201                 endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
202               }
203               // System.out.println("endCombNodeSet=" + endCombNodeSet);
204               visited.add(outNode);
205               if (endCombNodeSet.size() > 0) {
206                 // follows the straight line up to another skeleton/combination node
207                 // endCombNodeSet = removeTransitivelyReachToNode(desc, startNode, endCombNodeSet);
208               } else if (endCombNodeSet.size() == 0) {
209                 // the outNode is (directly/transitively) connected to the bottom node
210                 // therefore, we just add a dummy bottom HNode to the endCombNodeSet.
211                 endCombNodeSet.add(bottomNode);
212               }
213
214               startNode = refineStartNode(desc, startNode, endCombNodeSet);
215
216               recurDFSNormalNode(desc, lattice, startNode, endCombNodeSet, visited,
217                   mapIntermediateLoc, 1, locSummary, outNode);
218             }
219
220           }
221
222         }
223       } else if (!node.isSkeleton() && !node.isCombinationNode() && !node.isMergeNode()
224           && !visited.contains(node)) {
225
226         System.out.println("n=" + node);
227
228         // an intermediate node 'node' may be located between "TOP" location and a skeleton node
229         int sizeIncomingNode = simpleGraph.getIncomingNodeSet(node).size();
230
231         if (sizeIncomingNode == 0) {
232           // this node will be directly connected to the TOP location
233           // start adding the following nodes from this node
234
235           Set<HNode> endNodeSetFromSimpleGraph =
236               simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(node, null);
237
238           Set<HNode> endCombNodeSet = new HashSet<HNode>();
239           for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
240             HNode endNode = (HNode) iterator3.next();
241             endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
242           }
243
244           HNode startNode = topNode;
245           visited.add(startNode);
246           if (endCombNodeSet.size() > 0) {
247             // follows the straight line up to another skeleton/combination node
248             // endCombNodeSet = removeTransitivelyReachToNode(desc, node, endCombNodeSet);
249             recurDFSNormalNode(desc, lattice, startNode, endCombNodeSet, visited,
250                 mapIntermediateLoc, 1, locSummary, node);
251           }
252
253         }
254
255       }
256     }
257
258     return lattice;
259
260   }
261
262   private void expandCombinationNode(Descriptor desc, SSJavaLattice<String> lattice,
263       Set<HNode> visited, Map<TripleItem, String> mapIntermediateLoc, LocationSummary locSummary,
264       HNode cnode) {
265
266     // expand the combination node 'outNode'
267     // here we need to expand the corresponding combination location in the lattice
268     HNode combinationNodeInSCGraph = getCombinationNodeInSCGraph(desc, cnode);
269
270     HierarchyGraph simpleGraph = infer.getSimpleHierarchyGraph(desc);
271
272     Set<HNode> combineSkeletonNodeSet = simpleGraph.getCombineSetByCombinationNode(cnode);
273
274     // System.out.println("combineSkeletonNodeSet=" + combineSkeletonNodeSet);
275
276     Set<HNode> combinationNodeSet =
277         simpleGraph.getCombinationNodeSetByCombineNodeSet(combineSkeletonNodeSet);
278
279     // System.out.println("combinationNodeSet=" + combinationNodeSet);
280
281     Set<HNode> endNodeSetFromSimpleGraph =
282         simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(cnode, combinationNodeSet);
283     // System.out.println("-endNodeSetFromSimpleGraph=" + endNodeSetFromSimpleGraph);
284     Set<HNode> endCombNodeSet = new HashSet<HNode>();
285     for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
286       HNode endNode = (HNode) iterator3.next();
287       endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
288     }
289     visited.add(cnode);
290
291     // follows the straight line up to another skeleton/combination node
292     if (endCombNodeSet.size() > 0) {
293       System.out.println("---endCombNodeSet=" + endCombNodeSet);
294       // endCombNodeSet =
295       // removeTransitivelyReachToNode(desc, combinationNodeInSCGraph, endCombNodeSet);
296
297       combinationNodeInSCGraph = refineStartNode(desc, combinationNodeInSCGraph, endCombNodeSet);
298
299       recurDFS(desc, lattice, combinationNodeInSCGraph, endCombNodeSet, visited,
300           mapIntermediateLoc, 1, locSummary, cnode);
301     } else {
302       endCombNodeSet.add(bottomNode);
303       System.out.println("---endCombNodeSet is zero");
304       System.out.println("---endNodeSetFromSimpleGraph=" + endNodeSetFromSimpleGraph);
305       System.out.println("---incoming=" + simpleGraph.getIncomingNodeSet(cnode));
306       recurDFS(desc, lattice, combinationNodeInSCGraph, endCombNodeSet, visited,
307           mapIntermediateLoc, 1, locSummary, cnode);
308
309     }
310
311   }
312
313   private HNode refineStartNode(Descriptor desc, HNode startNode, Set<HNode> endNodeSet) {
314
315     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
316
317     HNode newStartNode = getDirectlyReachableSCNodeFromEndNode(scGraph, startNode, endNodeSet);
318
319     System.out.println("---removeTransitivelyReachToNode2 startNode=" + startNode + " old="
320         + endNodeSet + "  newStartNode=" + newStartNode);
321
322     return newStartNode;
323
324   }
325
326   private Set<HNode> removeTransitivelyReachToNode(Descriptor desc, HNode startNode,
327       Set<HNode> endNodeSet) {
328
329     // if an end node is not directly connected to the start node in the SC graph
330     // replace it with a directly connected one which transitively reaches to it.
331
332     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
333
334     Set<HNode> newEndNodeSet = new HashSet<HNode>();
335     for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
336       HNode endNode = (HNode) iterator.next();
337       if (scGraph.isDirectlyConnectedTo(startNode, endNode)) {
338         newEndNodeSet.add(endNode);
339       } else {
340         HNode newEndNode =
341             getDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, endNode);
342         // System.out.println("#### old END NODE=" + endNode + " --->" + newEndNode);
343         newEndNodeSet.add(newEndNode);
344       }
345     }
346
347     // System.out.println("removeTransitivelyReachToNode=" + endNodeSet + "  newSet=" +
348     // newEndNodeSet);
349
350     return newEndNodeSet;
351
352   }
353
354   private HNode getDirectlyReachableSCNodeFromEndNode(HierarchyGraph scGraph, HNode startNode,
355       Set<HNode> endNodeSet) {
356
357     System.out.println("getDirectlyReachableSCNodeFromEndNode start=" + startNode + " endNodeSet="
358         + endNodeSet);
359     Set<HNode> newStartNodeSet = new HashSet<HNode>();
360
361     for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
362       HNode endNode = (HNode) iterator.next();
363       Set<HNode> connectedToEndNodeSet = scGraph.getIncomingNodeSet(endNode);
364
365       for (Iterator iterator2 = connectedToEndNodeSet.iterator(); iterator2.hasNext();) {
366         HNode curNode = (HNode) iterator2.next();
367         if (recurConnectedFromStartNode(scGraph, startNode, curNode, new HashSet<HNode>())) {
368           newStartNodeSet.add(curNode);
369         }
370       }
371     }
372
373     System.out.println("newStartNodeSet=" + newStartNodeSet);
374
375     if (newStartNodeSet.size() == 0) {
376       newStartNodeSet.add(startNode);
377     }
378
379     return newStartNodeSet.iterator().next();
380   }
381
382   private boolean recurConnectedFromStartNode(HierarchyGraph scGraph, HNode startNode,
383       HNode curNode, Set<HNode> visited) {
384     // return true if curNode is transitively connected from the startNode
385
386     boolean isConnected = false;
387     Set<HNode> inNodeSet = scGraph.getIncomingNodeSet(curNode);
388     for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
389       HNode in = (HNode) iterator.next();
390       if (in.equals(startNode)) {
391         return true;
392       } else {
393         visited.add(in);
394         isConnected |= recurConnectedFromStartNode(scGraph, startNode, in, visited);
395       }
396     }
397
398     return isConnected;
399   }
400
401   private HNode getDirectlyReachableNodeFromStartNodeReachToEndNode(HierarchyGraph scGraph,
402       HNode startNode, HNode endNode) {
403     System.out.println("getDirectlyReachableNodeFromStartNodeReachToEndNode start=" + startNode
404         + " end=" + endNode);
405     Set<HNode> connected = new HashSet<HNode>();
406     recurDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, endNode, connected);
407     if (connected.size() == 0) {
408       connected.add(endNode);
409     }
410     System.out.println("connected=" + connected);
411
412     return connected.iterator().next();
413   }
414
415   private void recurDirectlyReachableNodeFromStartNodeReachToEndNode(HierarchyGraph scGraph,
416       HNode startNode, HNode curNode, Set<HNode> connected) {
417
418     Set<HNode> inNodeSet = scGraph.getIncomingNodeSet(curNode);
419     for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
420       HNode inNode = (HNode) iterator.next();
421       if (inNode.equals(startNode)) {
422         connected.add(curNode);
423       } else {
424         recurDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, inNode, connected);
425       }
426     }
427
428   }
429
430   private void recurDFSNormalNode(Descriptor desc, SSJavaLattice<String> lattice, HNode startNode,
431       Set<HNode> endNodeSet, Set<HNode> visited, Map<TripleItem, String> mapIntermediateLoc,
432       int idx, LocationSummary locSummary, HNode curNode) {
433
434     TripleItem item = new TripleItem(startNode, endNodeSet, idx);
435     // System.out.println("item=" + item);
436     if (!mapIntermediateLoc.containsKey(item)) {
437       // need to create a new intermediate location in the lattice
438       String newLocName = "ILOC" + (LocationInference.locSeed++);
439       String above;
440       if (idx == 1) {
441         above = startNode.getName();
442       } else {
443         int prevIdx = idx - 1;
444         TripleItem prevItem = new TripleItem(startNode, endNodeSet, prevIdx);
445         above = mapIntermediateLoc.get(prevItem);
446       }
447
448       Set<String> belowSet = new HashSet<String>();
449       for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
450         HNode endNode = (HNode) iterator.next();
451         belowSet.add(endNode.getName());
452       }
453
454       lattice.insertNewLocationBetween(above, belowSet, newLocName);
455
456       mapIntermediateLoc.put(item, newLocName);
457     }
458
459     String locName = mapIntermediateLoc.get(item);
460
461     HierarchyGraph graph = infer.getSimpleHierarchyGraph(desc);
462
463     Set<Descriptor> descSet = graph.getDescSetOfNode(curNode);
464     for (Iterator iterator = descSet.iterator(); iterator.hasNext();) {
465       Descriptor d = (Descriptor) iterator.next();
466       locSummary.addMapHNodeNameToLocationName(d.getSymbol(), locName);
467     }
468     locSummary.addMapHNodeNameToLocationName(curNode.getName(), locName);
469
470     if (curNode.isSharedNode()) {
471       lattice.addSharedLoc(locName);
472     }
473
474     System.out.println("-TripleItem=" + item);
475     System.out.println("-curNode=" + curNode.getName() + " locName=" + locName);
476
477     Set<HNode> outSet = graph.getOutgoingNodeSet(curNode);
478     for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
479       HNode outNode = (HNode) iterator2.next();
480       if (!outNode.isSkeleton() && !outNode.isCombinationNode() && !visited.contains(outNode)) {
481         visited.add(outNode);
482         recurDFSNormalNode(desc, lattice, startNode, endNodeSet, visited, mapIntermediateLoc,
483             idx + 1, locSummary, outNode);
484       } else if (!outNode.isSkeleton() && outNode.isCombinationNode() && !visited.contains(outNode)) {
485         expandCombinationNode(desc, lattice, visited, mapIntermediateLoc, locSummary, outNode);
486       }
487     }
488
489   }
490
491   private void recurDFS(Descriptor desc, SSJavaLattice<String> lattice,
492       HNode combinationNodeInSCGraph, Set<HNode> endNodeSet, Set<HNode> visited,
493       Map<TripleItem, String> mapIntermediateLoc, int idx, LocationSummary locSummary, HNode curNode) {
494
495     TripleItem item = new TripleItem(combinationNodeInSCGraph, endNodeSet, idx);
496
497     if (!mapIntermediateLoc.containsKey(item)) {
498       // need to create a new intermediate location in the lattice
499       String above;
500       if (idx == 1) {
501         String newLocName = combinationNodeInSCGraph.getName();
502         mapIntermediateLoc.put(item, newLocName);
503       } else {
504         String newLocName = "ILOC" + (LocationInference.locSeed++);
505         int prevIdx = idx - 1;
506         TripleItem prevItem = new TripleItem(combinationNodeInSCGraph, endNodeSet, prevIdx);
507         above = mapIntermediateLoc.get(prevItem);
508
509         Set<String> belowSet = new HashSet<String>();
510         for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
511           HNode endNode = (HNode) iterator.next();
512           belowSet.add(endNode.getName());
513         }
514         lattice.insertNewLocationBetween(above, belowSet, newLocName);
515         mapIntermediateLoc.put(item, newLocName);
516
517       }
518
519     }
520
521     HierarchyGraph graph = infer.getSimpleHierarchyGraph(desc);
522     String locName = mapIntermediateLoc.get(item);
523     Set<Descriptor> descSet = graph.getDescSetOfNode(curNode);
524     for (Iterator iterator = descSet.iterator(); iterator.hasNext();) {
525       Descriptor d = (Descriptor) iterator.next();
526       locSummary.addMapHNodeNameToLocationName(d.getSymbol(), locName);
527     }
528     locSummary.addMapHNodeNameToLocationName(curNode.getName(), locName);
529
530     // System.out.println("-TripleItem=" + item);
531     // System.out.println("-curNode=" + curNode.getName() + " locName=" + locName);
532
533     Set<HNode> outSet = graph.getOutgoingNodeSet(curNode);
534     for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
535       HNode outNode = (HNode) iterator2.next();
536       if (!outNode.isSkeleton() && !visited.contains(outNode)) {
537         if (combinationNodeInSCGraph.equals(getCombinationNodeInSCGraph(desc, outNode))) {
538           visited.add(outNode);
539           recurDFS(desc, lattice, combinationNodeInSCGraph, endNodeSet, visited,
540               mapIntermediateLoc, idx + 1, locSummary, outNode);
541         }
542       }
543     }
544
545   }
546
547   private String generateElementName(BasisSet basisSet, HierarchyGraph inputGraph,
548       Map<Set<Integer>, String> mapF2LocName, Set<Integer> F) {
549
550     if (mapF2LocName.containsKey(F)) {
551       return mapF2LocName.get(F);
552     }
553
554     HNode node = basisSet.getHNode(F);
555     if (node != null) {
556       mapF2LocName.put(F, node.getName());
557       return node.getName();
558     } else {
559       if (inputGraph.BASISTOPELEMENT.equals(F)) {
560         return SSJavaAnalysis.BOTTOM;
561       } else {
562         String str = "LOC" + (LocationInference.locSeed++);
563         mapF2LocName.put(F, str);
564         return str;
565       }
566     }
567   }
568
569   private void resetCount(Map<Set<Integer>, Integer> mapFtoCount, Family family) {
570     for (Iterator<Set<Integer>> iter = family.FIterator(); iter.hasNext();) {
571       Set<Integer> F = iter.next();
572       mapFtoCount.put(F, 0);
573     }
574   }
575
576   private Map<Set<Integer>, Set<Set<Integer>>> coveringGraph(BasisSet basisSet, Family family) {
577
578     Map<Set<Integer>, Integer> mapFtoCount = new HashMap<Set<Integer>, Integer>();
579     Map<Set<Integer>, Set<Set<Integer>>> mapImSucc = new HashMap<Set<Integer>, Set<Set<Integer>>>();
580
581     // initialize COUNT(F) to 0 for all elements of the family
582     resetCount(mapFtoCount, family);
583
584     for (Iterator<Set<Integer>> iter = family.FIterator(); iter.hasNext();) {
585       Set<Integer> F = iter.next();
586       Set<HNode> gammaF = family.getGamma(F);
587
588       Set<HNode> curHNodeSet = basisSet.getHNodeSet();
589       curHNodeSet.removeAll(gammaF);
590       Set<Set<Integer>> Bset = basisSet.getBasisSetByHNodeSet(curHNodeSet);
591
592       for (Iterator iterator = Bset.iterator(); iterator.hasNext();) {
593         Set<Integer> B = (Set<Integer>) iterator.next();
594
595         Set<Integer> Fprime = new HashSet<Integer>();
596         Fprime.addAll(F);
597         Fprime.addAll(B);
598
599         // COUNT(F')++;
600         mapFtoCount.put(Fprime, mapFtoCount.get(Fprime) + 1);
601
602         // if |gamma(F')|==COUNT(F') + |gamma(F)|
603         int numGammaFprime = family.getGamma(Fprime).size();
604         int countFprime = mapFtoCount.get(Fprime);
605         int numGammaF = family.getGamma(F).size();
606         if (numGammaFprime == (countFprime + numGammaF)) {
607           // ImSucc(F)=IMSucc(F) union F'
608           addImSucc(mapImSucc, F, Fprime);
609         }
610
611       }
612       resetCount(mapFtoCount, family);
613     }
614
615     // System.out.println("mapImSucc=" + mapImSucc);
616
617     return mapImSucc;
618   }
619
620   private Set<Set<Integer>> getImSucc(Map<Set<Integer>, Set<Set<Integer>>> mapImSucc, Set<Integer> F) {
621     if (!mapImSucc.containsKey(F)) {
622       mapImSucc.put(F, new HashSet<Set<Integer>>());
623     }
624     return mapImSucc.get(F);
625   }
626
627   private void addImSucc(Map<Set<Integer>, Set<Set<Integer>>> mapImSucc, Set<Integer> F,
628       Set<Integer> Fprime) {
629
630     if (!mapImSucc.containsKey(F)) {
631       mapImSucc.put(F, new HashSet<Set<Integer>>());
632     }
633
634     mapImSucc.get(F).add(Fprime);
635
636   }
637
638   private Family generateFamily(BasisSet basisSet) {
639
640     Family family = new Family();
641
642     for (Iterator<Set<Integer>> iterator = basisSet.basisIterator(); iterator.hasNext();) {
643       Set<Integer> B = iterator.next();
644
645       Set<Pair<Set<Integer>, Set<HNode>>> tobeadded = new HashSet<Pair<Set<Integer>, Set<HNode>>>();
646
647       for (Iterator<Set<Integer>> iterator2 = family.FIterator(); iterator2.hasNext();) {
648         Set<Integer> F = iterator2.next();
649
650         Set<Integer> Fprime = new HashSet<Integer>();
651         Fprime.addAll(F);
652         Fprime.addAll(B);
653
654         Set<HNode> gammaFPrimeSet = new HashSet<HNode>();
655         gammaFPrimeSet.addAll(family.getGamma(F));
656         gammaFPrimeSet.add(basisSet.getHNode(B));
657
658         if (!family.containsF(Fprime)) {
659           Pair<Set<Integer>, Set<HNode>> pair =
660               new Pair<Set<Integer>, Set<HNode>>(Fprime, gammaFPrimeSet);
661           tobeadded.add(pair);
662         } else {
663           family.updateGammaF(Fprime, gammaFPrimeSet);
664         }
665       }
666
667       for (Iterator<Pair<Set<Integer>, Set<HNode>>> iterator2 = tobeadded.iterator(); iterator2
668           .hasNext();) {
669         Pair<Set<Integer>, Set<HNode>> pair = iterator2.next();
670         family.addFElement(pair.getFirst());
671         family.updateGammaF(pair.getFirst(), pair.getSecond());
672       }
673
674     }
675     return family;
676   }
677
678   private void debug_print(HierarchyGraph inputGraph) {
679     System.out.println("\nBuild Lattice:" + inputGraph.getName());
680     // System.out.println("Node2Index:\n" + inputGraph.getMapHNodeToUniqueIndex());
681     // System.out.println("Node2Basis:\n" + inputGraph.getMapHNodeToBasis());
682   }
683
684 }
685
686 class Identifier {
687   public HNode node;
688   public int idx;
689
690   public Identifier(HNode n, int i) {
691     node = n;
692     idx = i;
693   }
694
695   public int hashCode() {
696     return node.hashCode() + idx;
697   }
698
699   public boolean equals(Object obj) {
700
701     if (obj instanceof Identifier) {
702       Identifier in = (Identifier) obj;
703       if (node.equals(in.node) && idx == in.idx) {
704         return true;
705       }
706     }
707
708     return false;
709   }
710
711 }
712
713 class TripleItem {
714   public HNode higherNode;
715   public Set<HNode> lowerNodeSet;
716   public int idx;
717
718   public TripleItem(HNode h, Set<HNode> l, int i) {
719     higherNode = h;
720     lowerNodeSet = l;
721     idx = i;
722   }
723
724   public int hashCode() {
725
726     int h = 0;
727     if (higherNode != null) {
728       h = higherNode.hashCode();
729     }
730
731     return h + lowerNodeSet.hashCode() + idx;
732   }
733
734   public boolean equals(Object obj) {
735
736     if (obj instanceof TripleItem) {
737       TripleItem in = (TripleItem) obj;
738       if ((higherNode == null || (higherNode != null && higherNode.equals(in.higherNode)))
739           && lowerNodeSet.equals(in.lowerNodeSet) && idx == in.idx) {
740         return true;
741       }
742     }
743
744     return false;
745   }
746
747   public String toString() {
748     return higherNode + "-" + idx + "->" + lowerNodeSet;
749   }
750 }