Fixed some errors in the Repair Generator code.
[repair.git] / Repair / RepairCompiler / MCC / IR / GraphAnalysis.java
index 1e5a0ce0a2a6e97dc75e4c7da7b30e0e0b4fa98d..16a51f781861c0a263d3f88e263f629778309427 100755 (executable)
@@ -2,6 +2,7 @@ package MCC.IR;
 import java.util.*;
 import java.io.*;
 import MCC.State;
+import MCC.Compiler;
 
 public class GraphAnalysis {
     Termination termination;
@@ -15,6 +16,61 @@ public class GraphAnalysis {
        termination=t;
     }
 
+    private boolean safetransclosure(GraphNode gn, Set removed, Set cantremove, Set couldremove) {
+       Stack workset=new Stack();
+       HashSet closureset=new HashSet();
+       boolean needcyclecheck=false;
+       HashSet cantremovetrans=new HashSet();
+       workset.push(gn);
+       while(!workset.empty()) {
+           GraphNode gn2=(GraphNode)workset.pop();
+           if (!closureset.contains(gn2)) {
+               closureset.add(gn2);
+               boolean goodoption=false;
+               for(Iterator edgeit=gn2.edges();edgeit.hasNext();) {
+                   GraphNode gn3=((GraphNode.Edge)edgeit.next()).getTarget();
+                   if (removed.contains(gn3))
+                       continue;
+                   if (((cantremove.contains(gn2)||!couldremove.contains(gn2))
+                        &&termination.conjunctions.contains(gn2))||
+                       cantremovetrans.contains(gn2))
+                       cantremovetrans.add(gn3);
+                   
+                   if (termination.abstractrepair.contains(gn3)||
+                       termination.conjunctions.contains(gn3)||
+                       termination.updatenodes.contains(gn3)) {
+                       /**  Check for cycles if the graphnode can't
+                        * be removed (we know we aren't introducing
+                        * new things to repair). */
+                       if ((!termination.abstractrepair.contains(gn3)&&
+                            cantremove.contains(gn3))||
+                           cantremovetrans.contains(gn3)) {
+                           needcyclecheck=true;
+                       } else return false;
+                   }
+                   if ((!couldremove.contains(gn3))||cantremove.contains(gn3))
+                       goodoption=true;
+                   workset.push(gn3);
+               }
+               if (!goodoption) {
+                   if (termination.scopenodes.contains(gn2))
+                       return false;
+               }                   
+           }
+       }
+       if (needcyclecheck) {
+           Set cycles=GraphNode.findcycles(closureset);
+           for(Iterator it=cycles.iterator();it.hasNext();) {
+               GraphNode gn2=(GraphNode)it.next();
+               if (termination.abstractrepair.contains(gn2)||
+                   termination.conjunctions.contains(gn2)||
+                   termination.updatenodes.contains(gn2))
+                   return false;
+           }
+       }
+       return true;
+    }
+
     public Set doAnalysis() {
        HashSet cantremove=new HashSet();
        HashSet mustremove=new HashSet();
@@ -35,6 +91,67 @@ public class GraphAnalysis {
            couldremove.addAll(termination.consequencenodes);
            couldremove.retainAll(nodes);
 
+
+           /* Check for consequence nodes which are fine */
+
+           for(Iterator it=termination.consequencenodes.iterator();it.hasNext();) {
+               GraphNode gn=(GraphNode) it.next();
+               if (safetransclosure(gn, mustremove,cantremove, couldremove)) {
+                           couldremove.remove(gn);
+               }
+           }
+
+           /* Check for update nodes which are fine */
+
+           for(Iterator it=termination.updatenodes.iterator();it.hasNext();) {
+               GraphNode gn=(GraphNode) it.next();
+               if (safetransclosure(gn, mustremove,cantremove, cantremove)) {
+                       couldremove.remove(gn);
+               }
+           }
+
+           /* Check for conjunction nodes which are fine */
+
+           for(Iterator it=termination.conjunctions.iterator();it.hasNext();) {
+               GraphNode gn=(GraphNode) it.next();
+               if (mustremove.contains(gn)||cantremove.contains(gn))
+                   continue;
+
+               boolean allgood=true;
+               for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
+                   GraphNode gn2=((GraphNode.Edge)edgeit.next()).getTarget();
+                   TermNode tn2=(TermNode)gn2.getOwner();
+                   assert tn2.getType()==TermNode.ABSTRACT;
+                   boolean foundupdate=false;
+                   for(Iterator edgeit2=gn2.edges();edgeit2.hasNext();) {
+                       GraphNode gn3=((GraphNode.Edge)edgeit2.next()).getTarget();                 
+                       if (!couldremove.contains(gn3)&&!mustremove.contains(gn3)) {
+                           TermNode tn3=(TermNode)gn3.getOwner();
+                           if (tn3.getType()==TermNode.UPDATE)
+                               foundupdate=true;
+                       }
+                   }
+                   if (!foundupdate)
+                       allgood=false;
+               }
+               if (allgood) {
+                   couldremove.remove(gn);
+                   if (Compiler.PRUNEQUANTIFIERS) {
+                       TermNode tn=(TermNode)gn.getOwner();
+                       Constraint constr=tn.getConstraint();
+                       for(Iterator consit=((Set)termination.conjunctionmap.get(constr)).iterator();consit.hasNext();) {
+                           GraphNode gn4=(GraphNode)consit.next();
+                           TermNode tn4=(TermNode)gn4.getOwner();
+                           if (tn4.getquantifiernode()) {
+                               mustremove.add(gn4); /* This node is history */
+                               System.out.println("Eliminating: "+gn4.getTextLabel());
+                           }
+                       }
+                   }
+               }
+           }
+
+
            /* Look for constraints which can only be satisfied one way */
            
            Vector constraints=termination.state.vConstraints;
@@ -110,6 +227,28 @@ public class GraphAnalysis {
                }
            }
            
+           if (Compiler.AGGRESSIVESEARCH) {
+               /* Aggressively remove compensation nodes */
+               for(Iterator scopeit=termination.scopenodes.iterator();scopeit.hasNext();) {
+                   GraphNode gn=(GraphNode)scopeit.next();
+                   HashSet tmpset=new HashSet();
+                   boolean doremove=false;
+                   for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
+                       GraphNode.Edge e=(GraphNode.Edge)edgeit.next();
+                       GraphNode gn2=e.getTarget();
+                       if (termination.consequencenodes.contains(gn2)) {
+                           if (((!couldremove.contains(gn2))||cantremove.contains(gn2))&&
+                               !mustremove.contains(gn2)) {
+                               doremove=true;
+                           } else
+                               break;
+                       } else tmpset.add(gn2);
+                   }
+                   if (doremove)
+                       mustremove.addAll(tmpset);
+               }
+           }
+
            Set cycles2=GraphNode.findcycles(cantremove);
            for(Iterator it=cycles2.iterator();it.hasNext();) {
                GraphNode gn=(GraphNode)it.next();
@@ -122,6 +261,16 @@ public class GraphAnalysis {
                    }
 
                    System.out.println("Cycle through conjunction "+gn.getTextLabel() +" which can't be removed.");
+                   System.out.println("CANTREMOVE");
+                   for(Iterator it2=cantremove.iterator();it2.hasNext();) {
+                       GraphNode gn2=(GraphNode)it2.next();
+                       System.out.println(gn2.getTextLabel());
+                   }
+                   System.out.println("MUSTREMOVE");
+                   for(Iterator it2=mustremove.iterator();it2.hasNext();) {
+                       GraphNode gn2=(GraphNode)it2.next();
+                       System.out.println(gn2.getTextLabel());
+                   }
                    return null; // Out of luck
                }
            }
@@ -210,7 +359,7 @@ public class GraphAnalysis {
                        if (!containsgn3)
                            cantremove.remove(gn3);
                    }
-                   if (ismodify&&((numadd==0)||(numremove==0))) {
+                   if (ismodify&&((numadd==0)||(numremove==0&&ar.needsRemoves(termination.state)))) {
                        for (Iterator edgeit2=gn2.edges();edgeit2.hasNext();) {
                            GraphNode.Edge e2=(GraphNode.Edge)edgeit2.next();
                            GraphNode gn3=e2.getTarget();
@@ -299,7 +448,14 @@ public class GraphAnalysis {
                continue; //recalculate
 
            try {
-               GraphNode.DOTVisitor.visit(new FileOutputStream("graphsearch.dot"),nodes);
+               GraphNode.DOTVisitor.visit(new FileOutputStream("graphsearch.dot"),nodes,couldremove);
+           } catch (Exception e) {
+               e.printStackTrace();
+               System.exit(-1);
+           }
+
+           try {
+               GraphNode.DOTVisitor.visit(new FileOutputStream("graphcycle.dot"),GraphNode.findcycles(nodes),couldremove);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(-1);
@@ -373,7 +529,7 @@ public class GraphAnalysis {
                            numremove++;
                    }
                }
-               if ((numadd==0)||(numremove==0)) {
+               if ((numadd==0)||(numremove==0&&ar.needsRemoves(termination.state))) {
                    for(Iterator it2=gn.edges();it2.hasNext();) {
                        GraphNode.Edge edge=(GraphNode.Edge)it2.next();
                        GraphNode gn2=edge.getTarget();
@@ -435,7 +591,7 @@ public class GraphAnalysis {
        }
        if (incremented==false) /* Increase length */ {
            combination.add(new Integer(0));
-           System.out.println("Expanding to :"+combination.size());
+           System.out.println("Expanding to"+combination.size());
        }
     }