8aa0370964d51c712852ef95bbb73ea657fca7d7
[repair.git] / Repair / RepairCompiler / MCC / IR / Termination.java
1 package MCC.IR;
2 import java.util.*;
3 import java.io.*;
4 import MCC.State;
5 import MCC.Compiler;
6
7 public class Termination {
8     HashSet conjunctions;
9     Hashtable conjunctionmap;
10
11     HashSet abstractrepair;
12     HashSet updatenodes;
13     HashSet consequencenodes;
14
15     HashSet scopenodes;
16     Hashtable scopesatisfy;
17     Hashtable scopefalsify;
18     Hashtable consequence;
19     Hashtable abstractadd;
20     Hashtable abstractremove;
21     Hashtable conjtonodemap;
22     Set removedset;
23
24     State state;
25
26     public Termination(State state) {
27         this.state=state;
28         conjunctions=new HashSet();
29         conjunctionmap=new Hashtable();
30         abstractrepair=new HashSet();
31         scopenodes=new HashSet();
32         scopesatisfy=new Hashtable();
33         scopefalsify=new Hashtable();
34         consequence=new Hashtable();
35         updatenodes=new HashSet();
36         consequencenodes=new HashSet();
37         abstractadd=new Hashtable();
38         abstractremove=new Hashtable();
39         conjtonodemap=new Hashtable();
40         if (!Compiler.REPAIR)
41             return;
42
43         generateconjunctionnodes();
44         generatescopenodes();
45         generaterepairnodes();
46         generatedatastructureupdatenodes();
47         generatecompensationnodes();
48
49         generateabstractedges();
50         generatescopeedges();
51         generateupdateedges();
52
53         HashSet superset=new HashSet();
54         superset.addAll(conjunctions);
55         HashSet closureset=new HashSet();
56         //      closureset.addAll(updatenodes);
57         //superset.addAll(abstractrepair);
58         //superset.addAll(updatenodes);
59         //superset.addAll(scopenodes);
60         //superset.addAll(consequencenodes);
61         GraphNode.computeclosure(superset,closureset);
62         try {
63             GraphNode.DOTVisitor.visit(new FileOutputStream("graph.dot"),superset);
64         } catch (Exception e) {
65             e.printStackTrace();
66             System.exit(-1);
67         }
68         for(Iterator it=updatenodes.iterator();it.hasNext();) {
69             GraphNode gn=(GraphNode)it.next();
70             TermNode tn=(TermNode)gn.getOwner();
71             MultUpdateNode mun=tn.getUpdate();
72             System.out.println(gn.getTextLabel());
73             System.out.println(mun.toString());
74         }
75         GraphAnalysis ga=new GraphAnalysis(this);
76         removedset=ga.doAnalysis();
77         if (removedset==null) {
78             System.out.println("Can't generate terminating repair algorithm!");
79             System.exit(-1);
80         }
81         System.out.println("Removing:");
82         for(Iterator it=removedset.iterator();it.hasNext();) {
83             GraphNode gn=(GraphNode)it.next();
84             System.out.println(gn.getTextLabel());
85         }
86
87         superset=new HashSet();
88         superset.addAll(conjunctions);
89         superset.removeAll(removedset);
90         GraphNode.computeclosure(superset,removedset);
91         try {
92             GraphNode.DOTVisitor.visit(new FileOutputStream("graphfinal.dot"),superset);
93         } catch (Exception e) {
94             e.printStackTrace();
95             System.exit(-1);
96         }
97
98     }
99     
100     void generateconjunctionnodes() {
101         Vector constraints=state.vConstraints;
102         for(int i=0;i<constraints.size();i++) {
103             Constraint c=(Constraint)constraints.get(i);
104             DNFConstraint dnf=c.dnfconstraint;
105             for(int j=0;j<dnf.size();j++) {
106                 TermNode tn=new TermNode(c,dnf.get(j));
107                 GraphNode gn=new GraphNode("Conj"+i+"A"+j,
108                                            "Conj ("+i+","+j+") "+dnf.get(j).name()
109                                            ,tn);
110                 conjunctions.add(gn);
111                 if (!conjunctionmap.containsKey(c))
112                     conjunctionmap.put(c,new HashSet());
113                 ((Set)conjunctionmap.get(c)).add(gn);
114                 conjtonodemap.put(dnf.get(j),gn);
115             }
116             for(int j=0;j<c.numQuantifiers();j++) {
117                 Quantifier q=c.getQuantifier(j);
118                 if (q instanceof SetQuantifier) {
119                     SetQuantifier sq=(SetQuantifier)q;
120                     VarExpr ve=new VarExpr(sq.getVar());
121                     InclusionPredicate ip=new InclusionPredicate(ve,new SetExpr(sq.getSet()));
122                     DNFConstraint dconst=new DNFConstraint(ip);
123                     dconst=dconst.not();
124                     TermNode tn=new TermNode(c,dconst.get(0));
125                     GraphNode gn=new GraphNode("Conj"+i+"AQ"+j,
126                                                "Conj ("+i+","+j+") "+dconst.get(0).name()
127                                                ,tn);
128                     conjunctions.add(gn);
129                     if (!conjunctionmap.containsKey(c))
130                         conjunctionmap.put(c,new HashSet());
131                     ((Set)conjunctionmap.get(c)).add(gn);
132                     conjtonodemap.put(dconst.get(0),gn);
133                 } else if (q instanceof RelationQuantifier) {
134                     RelationQuantifier rq=(RelationQuantifier)q;
135                     VarExpr ve=new VarExpr(rq.y);
136                     InclusionPredicate ip=new InclusionPredicate(ve,new ImageSetExpr(rq.x,rq.getRelation()));
137                     DNFConstraint dconst=new DNFConstraint(ip);
138                     dconst=dconst.not();
139                     TermNode tn=new TermNode(c,dconst.get(0));
140                     GraphNode gn=new GraphNode("Conj"+i+"AQ"+j,
141                                                "Conj ("+i+","+j+") "+dconst.get(0).name()
142                                                ,tn);
143                     conjunctions.add(gn);
144                     if (!conjunctionmap.containsKey(c))
145                         conjunctionmap.put(c,new HashSet());
146                     ((Set)conjunctionmap.get(c)).add(gn);
147                     conjtonodemap.put(dconst.get(0),gn);
148                 }
149             }
150         }
151     }
152
153     void generateupdateedges() {
154         for(Iterator updateiterator=updatenodes.iterator();updateiterator.hasNext();) {
155             GraphNode gn=(GraphNode)updateiterator.next();
156             TermNode tn=(TermNode)gn.getOwner();
157             MultUpdateNode mun=tn.getUpdate();
158             /* Cycle through the rules to look for possible conflicts */
159             for(int i=0;i<state.vRules.size();i++) {
160                 Rule r=(Rule) state.vRules.get(i);  
161                 if (ConcreteInterferes.interferes(mun,r,true)) {
162                     GraphNode scopenode=(GraphNode)scopesatisfy.get(r);
163                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
164                     gn.addEdge(e);
165                 }
166                 if (ConcreteInterferes.interferes(mun,r,false)) {
167                     GraphNode scopenode=(GraphNode)scopefalsify.get(r);
168                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
169                     gn.addEdge(e);
170                 }
171             }
172         }
173     }
174
175     void generateabstractedges() {
176         for(Iterator absiterator=abstractrepair.iterator();absiterator.hasNext();) {
177             GraphNode gn=(GraphNode)absiterator.next();
178             TermNode tn=(TermNode)gn.getOwner();
179             AbstractRepair ar=(AbstractRepair)tn.getAbstract();
180         
181             for(Iterator conjiterator=conjunctions.iterator();conjiterator.hasNext();) {
182                 GraphNode gn2=(GraphNode)conjiterator.next();
183                 TermNode tn2=(TermNode)gn2.getOwner();
184                 Conjunction conj=tn2.getConjunction();
185                 Constraint cons=tn2.getConstraint();
186
187                 for(int i=0;i<conj.size();i++) {
188                     DNFPredicate dp=conj.get(i);
189                     if (AbstractInterferes.interferes(ar,cons)||
190                         AbstractInterferes.interferes(ar,dp)) {
191                         GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
192                         gn.addEdge(e);
193                         break;
194                     }
195                 }
196             }
197
198             for(Iterator scopeiterator=scopenodes.iterator();scopeiterator.hasNext();) {
199                 GraphNode gn2=(GraphNode)scopeiterator.next();
200                 TermNode tn2=(TermNode)gn2.getOwner();
201                 ScopeNode sn2=tn2.getScope();
202                 if (AbstractInterferes.interferes(ar,sn2.getRule(),sn2.getSatisfy())) {
203                     GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
204                     gn.addEdge(e);
205                 }
206             }
207         }
208     }
209     
210     void generatescopeedges() {
211         for(Iterator scopeiterator=scopenodes.iterator();scopeiterator.hasNext();) {
212             GraphNode gn=(GraphNode)scopeiterator.next();
213             TermNode tn=(TermNode)gn.getOwner();
214             ScopeNode sn=tn.getScope();
215             
216             /* Interference edges with conjunctions */
217             for(Iterator conjiterator=conjunctions.iterator();conjiterator.hasNext();) {
218                 GraphNode gn2=(GraphNode)conjiterator.next();
219                 TermNode tn2=(TermNode)gn2.getOwner();
220                 Conjunction conj=tn2.getConjunction();
221                 Constraint constr=tn2.getConstraint();
222                 for(int i=0;i<conj.size();i++) {
223                     DNFPredicate dp=conj.get(i);
224                     if (AbstractInterferes.interferes(sn,dp)||
225                         AbstractInterferes.interferes(sn.getDescriptor(),sn.getSatisfy(),constr)) {
226                         GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
227                         GraphNode gnconseq=(GraphNode)consequence.get(sn);
228                         gnconseq.addEdge(e);
229                         break;
230                     }
231                 }
232             }
233
234             /* Now see if this could effect other model defintion rules */
235             for(int i=0;i<state.vRules.size();i++) {
236                 Rule r=(Rule) state.vRules.get(i);
237                 if (AbstractInterferes.interferes(sn.getDescriptor(),sn.getSatisfy(),r,true)) {
238                     GraphNode scopenode=(GraphNode)scopesatisfy.get(r);
239                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
240                     GraphNode gnconseq=(GraphNode)consequence.get(sn);
241                     gnconseq.addEdge(e);
242                 }
243                 if (AbstractInterferes.interferes(sn.getDescriptor(),sn.getSatisfy(),r,false)) {
244                     GraphNode scopenode=(GraphNode)scopefalsify.get(r);
245                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
246                     GraphNode gnconseq=(GraphNode)consequence.get(sn);
247                     gnconseq.addEdge(e);
248                 }
249             }
250         }
251     }
252
253     /* Generates the abstract repair nodes */
254     void generaterepairnodes() {
255         /* Generate repairs of conjunctions */
256         for(Iterator conjiterator=conjunctions.iterator();conjiterator.hasNext();) {
257             GraphNode gn=(GraphNode)conjiterator.next();
258             TermNode tn=(TermNode)gn.getOwner();
259             Conjunction conj=tn.getConjunction();
260             for(int i=0;i<conj.size();i++) {
261                 DNFPredicate dp=conj.get(i);
262                 int[] array=dp.getPredicate().getRepairs(dp.isNegated());
263                 Descriptor d=dp.getPredicate().getDescriptor();
264                 for(int j=0;j<array.length;j++) {
265                     AbstractRepair ar=new AbstractRepair(dp,array[j],d);
266                     TermNode tn2=new TermNode(ar);
267                     GraphNode gn2=new GraphNode(gn.getLabel()+"A"+i+"B"+ar.type(),gn.getTextLabel()+" #"+i+" "+ar.type(),tn2);
268                     GraphNode.Edge e=new GraphNode.Edge("abstract",gn2);
269                     gn.addEdge(e);
270                     abstractrepair.add(gn2);
271                 }
272             }
273         }
274         /* Generate additional abstract repairs */
275         Vector setdescriptors=state.stSets.getAllDescriptors();
276         for(int i=0;i<setdescriptors.size();i++) {
277             SetDescriptor sd=(SetDescriptor)setdescriptors.get(i);
278
279             /* XXXXXXX: Not sure what to do here */
280             VarExpr ve=new VarExpr("DUMMY");
281             InclusionPredicate ip=new InclusionPredicate(ve,new SetExpr(sd));
282             
283             DNFPredicate tp=new DNFPredicate(false,ip);
284             AbstractRepair ar=new AbstractRepair(tp, AbstractRepair.ADDTOSET, sd);
285             TermNode tn=new TermNode(ar);
286             GraphNode gn=new GraphNode("AbstractAddSetRule"+i,tn);
287             abstractrepair.add(gn);
288             abstractadd.put(sd,gn);
289             
290             DNFPredicate tp2=new DNFPredicate(true,ip);
291             AbstractRepair ar2=new AbstractRepair(tp2, AbstractRepair.REMOVEFROMSET, sd);
292             TermNode tn2=new TermNode(ar2);
293             GraphNode gn2=new GraphNode("AbstractRemSetRule"+i,tn2);
294             abstractrepair.add(gn2);
295             abstractremove.put(sd,gn2);
296         }
297
298         Vector relationdescriptors=state.stRelations.getAllDescriptors();
299         for(int i=0;i<relationdescriptors.size();i++) {
300             RelationDescriptor rd=(RelationDescriptor)relationdescriptors.get(i);
301
302             /* XXXXXXX: Not sure what to do here */
303             VarDescriptor vd1=new VarDescriptor("DUMMY1");
304             VarExpr ve2=new VarExpr("DUMMY2");
305
306             InclusionPredicate ip=new InclusionPredicate(ve2,new ImageSetExpr(vd1, rd));
307             
308             DNFPredicate tp=new DNFPredicate(false,ip);
309             AbstractRepair ar=new AbstractRepair(tp, AbstractRepair.ADDTORELATION, rd);
310             TermNode tn=new TermNode(ar);
311             GraphNode gn=new GraphNode("AbstractAddRelRule"+i,tn);
312             abstractrepair.add(gn);
313             abstractadd.put(rd,gn);
314             
315             DNFPredicate tp2=new DNFPredicate(true,ip);
316             AbstractRepair ar2=new AbstractRepair(tp2, AbstractRepair.REMOVEFROMRELATION, rd);
317             TermNode tn2=new TermNode(ar2);
318             GraphNode gn2=new GraphNode("AbstractRemRelRule"+i,tn2);
319             abstractrepair.add(gn2);
320             abstractremove.put(rd,gn2);
321         }
322         
323     }
324
325     int compensationcount=0;
326     void generatecompensationnodes() {
327         for(int i=0;i<state.vRules.size();i++) {
328             Rule r=(Rule) state.vRules.get(i);
329             Vector possiblerules=new Vector();
330             /* Construct bindings */
331             /* No need to construct bindings on remove
332                Vector bindings=new Vector();
333                constructbindings(bindings, r,true);
334             */
335             for(int j=0;j<(r.numQuantifiers()+r.getDNFNegGuardExpr().size());j++) {
336                 GraphNode gn=(GraphNode)scopesatisfy.get(r);
337                 TermNode tn=(TermNode) gn.getOwner();
338                 ScopeNode sn=tn.getScope();
339                 MultUpdateNode mun=new MultUpdateNode(sn);
340                 TermNode tn2=new TermNode(mun);
341                 GraphNode gn2=new GraphNode("CompRem"+compensationcount,tn2);
342                 UpdateNode un=new UpdateNode(r);
343                 //              un.addBindings(bindings);
344                 // Not necessary
345                 if (j<r.numQuantifiers()) {
346                     /* Remove quantifier */
347                     Quantifier q=r.getQuantifier(j);
348                     if (q instanceof RelationQuantifier) {
349                         RelationQuantifier rq=(RelationQuantifier)q;
350                         TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
351                         toe.td=ReservedTypeDescriptor.INT;
352                         Updates u=new Updates(toe,true);
353                         un.addUpdate(u);
354                         if (abstractremove.containsKey(rq.relation)) {
355                             GraphNode agn=(GraphNode)abstractremove.get(rq.relation);
356                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
357                             gn2.addEdge(e);
358                         } else {
359                             continue; /* Abstract repair doesn't exist */
360                         }
361                     } else if (q instanceof SetQuantifier) {
362                         SetQuantifier sq=(SetQuantifier)q;
363                         ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
364                         eoe.td=ReservedTypeDescriptor.INT;
365                         Updates u=new Updates(eoe,true);
366                         un.addUpdate(u);
367                         if (abstractremove.containsKey(sq.set)) {
368                             GraphNode agn=(GraphNode)abstractremove.get(sq.set);
369                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
370                             gn2.addEdge(e);
371                         } else {
372                             continue; /* Abstract repair doesn't exist */
373                         }
374                     } else {
375                         continue;
376                     }
377                 } else {
378                     int c=j-r.numQuantifiers();
379                     if (!processconjunction(un,r.getDNFNegGuardExpr().get(c))) {
380                         continue;
381                     }
382                 }
383                 if (!un.checkupdates()) /* Make sure we have a good update */
384                     continue;
385                 
386                 mun.addUpdate(un);
387
388                 GraphNode.Edge e=new GraphNode.Edge("abstract"+compensationcount,gn2);
389                 compensationcount++;
390                 gn.addEdge(e);
391                 updatenodes.add(gn2);
392             }
393         }
394     }
395
396     void generatedatastructureupdatenodes() {
397         for(Iterator absiterator=abstractrepair.iterator();absiterator.hasNext();) {
398             GraphNode gn=(GraphNode)absiterator.next();
399             TermNode tn=(TermNode) gn.getOwner();
400             AbstractRepair ar=tn.getAbstract();
401             if (ar.getType()==AbstractRepair.ADDTOSET) {
402                 generateaddtosetrelation(gn,ar);
403             } else if (ar.getType()==AbstractRepair.REMOVEFROMSET) {
404                 generateremovefromsetrelation(gn,ar);
405             } else if (ar.getType()==AbstractRepair.ADDTORELATION) {
406                 generateaddtosetrelation(gn,ar);
407             } else if (ar.getType()==AbstractRepair.REMOVEFROMRELATION) {
408                 generateremovefromsetrelation(gn,ar);
409             } else if (ar.getType()==AbstractRepair.MODIFYRELATION) {
410                 /* Generate remove/add pairs */
411                 generateremovefromsetrelation(gn,ar);
412                 generateaddtosetrelation(gn,ar);
413                 /* Generate atomic modify */
414                 generatemodifyrelation(gn,ar);
415             }
416         }
417     }
418
419     int removefromcount=0;
420     void generateremovefromsetrelation(GraphNode gn,AbstractRepair ar) {
421         Vector possiblerules=new Vector();
422         for(int i=0;i<state.vRules.size();i++) {
423             Rule r=(Rule) state.vRules.get(i);
424             if ((r.getInclusion() instanceof SetInclusion)&&
425                 (ar.getDescriptor()==((SetInclusion)r.getInclusion()).getSet()))
426                 possiblerules.add(r);
427             if ((r.getInclusion() instanceof RelationInclusion)&&
428                 (ar.getDescriptor()==((RelationInclusion)r.getInclusion()).getRelation()))
429                 possiblerules.add(r);
430         }
431         if (possiblerules.size()==0)
432             return;
433         int[] count=new int[possiblerules.size()];
434         while(remains(count,possiblerules,true)) {
435             MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.REMOVE);
436             TermNode tn=new TermNode(mun);
437             GraphNode gn2=new GraphNode("UpdateRem"+removefromcount,tn);
438
439             boolean goodflag=true;
440             for(int i=0;i<possiblerules.size();i++) {
441                 Rule r=(Rule)possiblerules.get(i);
442                 UpdateNode un=new UpdateNode(r);
443                 /* Construct bindings */
444                 /* No Need to construct bindings on remove
445                    Vector bindings=new Vector();
446                    constructbindings(bindings, r,true);
447                   un.addBindings(bindings);*/
448                 if (count[i]<r.numQuantifiers()) {
449                     /* Remove quantifier */
450                     Quantifier q=r.getQuantifier(count[i]);
451                     if (q instanceof RelationQuantifier) {
452                         RelationQuantifier rq=(RelationQuantifier)q;
453                         TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
454                         toe.td=ReservedTypeDescriptor.INT;
455                         Updates u=new Updates(toe,true);
456                         un.addUpdate(u);
457                         if (abstractremove.containsKey(rq.relation)) {
458                             GraphNode agn=(GraphNode)abstractremove.get(rq.relation);
459                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
460                             gn2.addEdge(e);
461                         } else {
462                             goodflag=false;break; /* Abstract repair doesn't exist */
463                         }
464                     } else if (q instanceof SetQuantifier) {
465                         SetQuantifier sq=(SetQuantifier)q;
466                         ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
467                         eoe.td=ReservedTypeDescriptor.INT;
468                         Updates u=new Updates(eoe,true);
469                         un.addUpdate(u);
470                         if (abstractremove.containsKey(sq.set)) {
471                             GraphNode agn=(GraphNode)abstractremove.get(sq.set);
472                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
473                             gn2.addEdge(e);
474                         } else {
475                             goodflag=false;break; /* Abstract repair doesn't exist */
476                         }
477                     } else {goodflag=false;break;}
478                 } else {
479                     int c=count[i]-r.numQuantifiers();
480                     if (!processconjunction(un,r.getDNFNegGuardExpr().get(c))) {
481                         goodflag=false;break;
482                     }
483                 }
484                 if (!un.checkupdates()) {
485                     goodflag=false;
486                     break;
487                 }
488                 mun.addUpdate(un);
489             }
490             if (goodflag) {
491                 GraphNode.Edge e=new GraphNode.Edge("abstract"+removefromcount,gn2);
492                 removefromcount++;
493                 gn.addEdge(e);
494                 updatenodes.add(gn2);
495             }
496             increment(count,possiblerules,true);
497         }
498     }
499
500     static void increment(int count[], Vector rules,boolean isremove) {
501         count[0]++;
502         for(int i=0;i<(rules.size()-1);i++) {
503             int num=isremove?(((Rule)rules.get(i)).numQuantifiers()+(((Rule)rules.get(i)).getDNFNegGuardExpr().size())):((Rule)rules.get(i)).getDNFGuardExpr().size();
504             if (count[i]>=num) {
505                 count[i+1]++;
506                 count[i]=0;
507             } else break;
508         }
509     }
510
511     static boolean remains(int count[], Vector rules, boolean isremove) {
512         for(int i=0;i<rules.size();i++) {
513             int num=isremove?(((Rule)rules.get(i)).numQuantifiers()+(((Rule)rules.get(i)).getDNFNegGuardExpr().size())):((Rule)rules.get(i)).getDNFGuardExpr().size();
514             if (count[i]>=num) {
515                 return false;
516             }
517         }
518         return true;
519     }
520
521     /** This method generates data structure updates to implement the
522      *  abstract atomic modification specified by ar. */
523     int modifycount=0;
524     void generatemodifyrelation(GraphNode gn, AbstractRepair ar) {
525         RelationDescriptor rd=(RelationDescriptor)ar.getDescriptor();
526         ExprPredicate exprPredicate=(ExprPredicate)ar.getPredicate().getPredicate();
527         boolean inverted=exprPredicate.inverted();
528         int leftindex=0;
529         int rightindex=1;
530         if (inverted)
531             leftindex=2;
532         else 
533             rightindex=2;
534
535
536         Vector possiblerules=new Vector();
537         for(int i=0;i<state.vRules.size();i++) {
538             Rule r=(Rule) state.vRules.get(i);
539             if ((r.getInclusion() instanceof RelationInclusion)&&
540                 (rd==((RelationInclusion)r.getInclusion()).getRelation()))
541                 possiblerules.add(r);
542         }
543         if (possiblerules.size()==0)
544             return;
545         int[] count=new int[possiblerules.size()];
546         while(remains(count,possiblerules,false)) {
547             MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.MODIFY);
548             TermNode tn=new TermNode(mun);
549             GraphNode gn2=new GraphNode("UpdateMod"+removefromcount,tn);
550
551             boolean goodflag=true;
552             for(int i=0;i<possiblerules.size();i++) {
553                 Rule r=(Rule)possiblerules.get(i);
554                 UpdateNode un=new UpdateNode(r);
555                 /* No Need to construct bindings on modify */
556                 
557                 int c=count[i];
558                 if (!processconjunction(un,r.getDNFGuardExpr().get(c))) {
559                     goodflag=false;break;
560                 }
561                 RelationInclusion ri=(RelationInclusion)r.getInclusion();
562                 if (!(ri.getLeftExpr() instanceof VarExpr)) {
563                     Updates up=new Updates(ri.getLeftExpr(),leftindex);
564                     un.addUpdate(up);
565                 } else {
566                     VarDescriptor vd=((VarExpr)ri.getLeftExpr()).getVar();
567                     if (vd.isGlobal()) {
568                         Updates up=new Updates(ri.getLeftExpr(),leftindex);
569                         un.addUpdate(up);
570                     } else if (inverted)
571                         goodflag=false;
572                 }
573                 if (!(ri.getRightExpr() instanceof VarExpr)) {
574                     Updates up=new Updates(ri.getRightExpr(),rightindex);
575                     un.addUpdate(up);
576                 } else {
577                     VarDescriptor vd=((VarExpr)ri.getRightExpr()).getVar();
578                     if (vd.isGlobal()) {
579                         Updates up=new Updates(ri.getRightExpr(),rightindex);
580                         un.addUpdate(up);
581                     } else if (!inverted) 
582                         goodflag=false;
583                 }
584                                 
585                 if (!un.checkupdates()) {
586                     goodflag=false;
587                     break;
588                 }
589                 mun.addUpdate(un);
590             }
591             if (goodflag) {
592                 GraphNode.Edge e=new GraphNode.Edge("abstract"+modifycount,gn2);
593                 modifycount++;
594                 gn.addEdge(e);
595                 updatenodes.add(gn2);
596             }
597             increment(count,possiblerules,false);
598         }
599     }
600
601
602     boolean constructbindings(Vector bindings, Rule r, boolean isremoval) {
603         boolean goodupdate=true;
604         Inclusion inc=r.getInclusion();
605         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
606             Quantifier q=(Quantifier)iterator.next();
607             if ((q instanceof SetQuantifier)||(q instanceof ForQuantifier)) {
608                 VarDescriptor vd=null;
609                 SetDescriptor set=null;
610                 if (q instanceof SetQuantifier) {
611                     vd=((SetQuantifier)q).getVar();
612                 } else
613                     vd=((ForQuantifier)q).getVar();
614                 if(inc instanceof SetInclusion) {
615                     SetInclusion si=(SetInclusion)inc;
616                     if ((si.elementexpr instanceof VarExpr)&&
617                         (((VarExpr)si.elementexpr).getVar()==vd)) {
618                         /* Can solve for v */
619                         Binding binding=new Binding(vd,0);
620                         bindings.add(binding);
621                     } else
622                         goodupdate=false;
623                 } else if (inc instanceof RelationInclusion) {
624                     RelationInclusion ri=(RelationInclusion)inc;
625                     boolean f1=true;
626                     boolean f2=true;
627                     if ((ri.getLeftExpr() instanceof VarExpr)&&
628                         (((VarExpr)ri.getLeftExpr()).getVar()==vd)) {
629                                 /* Can solve for v */
630                         Binding binding=new Binding(vd,0);
631                         bindings.add(binding);
632                     } else f1=false;
633                     if ((ri.getRightExpr() instanceof VarExpr)&&
634                         (((VarExpr)ri.getRightExpr()).getVar()==vd)) {
635                                 /* Can solve for v */
636                         Binding binding=new Binding(vd,0);
637                         bindings.add(binding);
638                     } else f2=false;
639                     if (!(f1||f2))
640                         goodupdate=false;
641                 } else throw new Error("Inclusion not recognized");
642                 if (!goodupdate)
643                     if (isremoval) {
644                         Binding binding=new Binding(vd);
645                         bindings.add(binding);
646                         goodupdate=true;
647                     } else
648                         break;
649             } else if (q instanceof RelationQuantifier) {
650                 RelationQuantifier rq=(RelationQuantifier)q;
651                 for(int k=0;k<2;k++) {
652                     VarDescriptor vd=(k==0)?rq.x:rq.y;
653                     if(inc instanceof SetInclusion) {
654                         SetInclusion si=(SetInclusion)inc;
655                         if ((si.elementexpr instanceof VarExpr)&&
656                             (((VarExpr)si.elementexpr).getVar()==vd)) {
657                             /* Can solve for v */
658                             Binding binding=new Binding(vd,0);
659                             bindings.add(binding);
660                         } else
661                             goodupdate=false;
662                     } else if (inc instanceof RelationInclusion) {
663                         RelationInclusion ri=(RelationInclusion)inc;
664                         boolean f1=true;
665                         boolean f2=true;
666                         if ((ri.getLeftExpr() instanceof VarExpr)&&
667                             (((VarExpr)ri.getLeftExpr()).getVar()==vd)) {
668                             /* Can solve for v */
669                             Binding binding=new Binding(vd,0);
670                             bindings.add(binding);
671                         } else f1=false;
672                         if ((ri.getRightExpr() instanceof VarExpr)&&
673                             (((VarExpr)ri.getRightExpr()).getVar()==vd)) {
674                             /* Can solve for v */
675                             Binding binding=new Binding(vd,0);
676                             bindings.add(binding);
677                         } else f2=false;
678                         if (!(f1||f2))
679                             goodupdate=false;
680                     } else throw new Error("Inclusion not recognized");
681                     if (!goodupdate)
682                         if (isremoval) {
683                             Binding binding=new Binding(vd);
684                             bindings.add(binding);
685                             goodupdate=true;
686                         } else
687                             break;
688                 }
689                 if (!goodupdate)
690                     break;
691             } else throw new Error("Quantifier not recognized");
692         }
693         return goodupdate;
694     }
695
696     static int addtocount=0;
697     void generateaddtosetrelation(GraphNode gn, AbstractRepair ar) {
698         //      System.out.println("Attempting to generate add to set");
699         //System.out.println(ar.getPredicate().getPredicate().name());
700         //System.out.println(ar.getPredicate().isNegated());
701         for(int i=0;i<state.vRules.size();i++) {
702             Rule r=(Rule) state.vRules.get(i);
703             /* See if this is a good rule*/
704             //System.out.println(r.getGuardExpr().name());
705             if ((r.getInclusion() instanceof SetInclusion&&
706                 ar.getDescriptor()==((SetInclusion)r.getInclusion()).getSet())||
707                 (r.getInclusion() instanceof RelationInclusion&&
708                  ar.getDescriptor()==((RelationInclusion)r.getInclusion()).getRelation())) {
709
710                 /* First solve for quantifiers */
711                 Vector bindings=new Vector();
712                 /* Construct bindings */
713                 //System.out.println("Attempting to generate add to set: #2");
714                 if (!constructbindings(bindings,r,false))
715                     continue;
716                 //System.out.println("Attempting to generate add to set: #3");
717                 //Generate add instruction
718                 DNFRule dnfrule=r.getDNFGuardExpr();
719                 for(int j=0;j<dnfrule.size();j++) {
720                     Inclusion inc=r.getInclusion();
721                     UpdateNode un=new UpdateNode(r);
722                     un.addBindings(bindings);
723                     /* Now build update for tuple/set inclusion condition */
724                     if(inc instanceof SetInclusion) {
725                         SetInclusion si=(SetInclusion)inc;
726                         if (!(si.elementexpr instanceof VarExpr)) {
727                             Updates up=new Updates(si.elementexpr,0);
728                             un.addUpdate(up);
729                         } else {
730                             VarDescriptor vd=((VarExpr)si.elementexpr).getVar();
731                             if (un.getBinding(vd)==null) {
732                                 Updates up=new Updates(si.elementexpr,0);
733                                 un.addUpdate(up);
734                             }
735                         }
736                     } else if (inc instanceof RelationInclusion) {
737                         RelationInclusion ri=(RelationInclusion)inc;
738                         if (!(ri.getLeftExpr() instanceof VarExpr)) {
739                             Updates up=new Updates(ri.getLeftExpr(),0);
740                             un.addUpdate(up);
741                         } else {
742                             VarDescriptor vd=((VarExpr)ri.getLeftExpr()).getVar();
743                             if (un.getBinding(vd)==null) {
744                                 Updates up=new Updates(ri.getLeftExpr(),0);
745                                 un.addUpdate(up);
746                             }
747                         }
748                         if (!(ri.getRightExpr() instanceof VarExpr)) {
749                             Updates up=new Updates(ri.getRightExpr(),1);
750                             un.addUpdate(up);
751                         } else {
752                             VarDescriptor vd=((VarExpr)ri.getRightExpr()).getVar();
753                             if (un.getBinding(vd)==null) {
754                                 Updates up=new Updates(ri.getRightExpr(),1);
755                                 un.addUpdate(up);
756                             }
757                         }
758                     }
759                     //Finally build necessary updates to satisfy conjunction
760                     RuleConjunction ruleconj=dnfrule.get(j);
761                     /* Add in updates for quantifiers */
762                     //System.out.println("Attempting to generate add to set #4");
763                     MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.ADD);
764                     TermNode tn=new TermNode(mun);
765                     GraphNode gn2=new GraphNode("UpdateAdd"+addtocount,tn);
766
767                     if (processquantifers(gn2,un, r)&&debugdd()&&
768                         processconjunction(un,ruleconj)&&
769                         un.checkupdates()) {
770                         //System.out.println("Attempting to generate add to set #5");
771                         mun.addUpdate(un);
772                         GraphNode.Edge e=new GraphNode.Edge("abstract"+addtocount,gn2);
773                         addtocount++;
774                         gn.addEdge(e);
775                         updatenodes.add(gn2);}
776                 }
777             }
778         }
779     }
780
781     boolean debugdd() {
782         //System.out.println("Attempting to generate add to set DD");
783         return true;
784     }
785
786     boolean processquantifers(GraphNode gn,UpdateNode un, Rule r) {
787         Inclusion inc=r.getInclusion();
788         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
789             Quantifier q=(Quantifier)iterator.next();
790             /* Add quantifier */
791             /* FIXME: Analysis to determine when this update is necessary */
792             if (q instanceof RelationQuantifier) {
793                 RelationQuantifier rq=(RelationQuantifier)q;
794                 TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
795                 toe.td=ReservedTypeDescriptor.INT;
796                 Updates u=new Updates(toe,false);
797                 un.addUpdate(u);
798                 if (abstractremove.containsKey(rq.relation)) {
799                     GraphNode agn=(GraphNode)abstractadd.get(rq.relation);
800                     GraphNode.Edge e=new GraphNode.Edge("requires",agn);
801                     gn.addEdge(e);
802                 } else {
803                     return false;
804                 }
805
806             } else if (q instanceof SetQuantifier) {
807                 SetQuantifier sq=(SetQuantifier)q;
808                 ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
809                 eoe.td=ReservedTypeDescriptor.INT;
810                 Updates u=new Updates(eoe,false);
811                 un.addUpdate(u);
812                 if (abstractremove.containsKey(sq.set)) {
813                     GraphNode agn=(GraphNode)abstractadd.get(sq.set);
814                     GraphNode.Edge e=new GraphNode.Edge("requires",agn);
815                     gn.addEdge(e);
816                 } else {
817                     return false;
818                 }
819             } else return false;
820         }
821         return true;
822     }
823
824     boolean  processconjunction(UpdateNode un,RuleConjunction ruleconj){
825         boolean okay=true;
826         for(int k=0;k<ruleconj.size();k++) {
827             DNFExpr de=ruleconj.get(k);
828             Expr e=de.getExpr();
829             if (e instanceof OpExpr) {
830                 OpExpr ex=(OpExpr)de.getExpr();
831                 Opcode op=ex.getOpcode();
832                 Updates up=new Updates(ex.left,ex.right,op, de.getNegation());
833                 un.addUpdate(up);
834             } else if (e instanceof ElementOfExpr) {
835                 Updates up=new Updates(e,de.getNegation());
836                 un.addUpdate(up);
837             } else if (e instanceof TupleOfExpr) {
838                 Updates up=new Updates(e,de.getNegation());
839                 un.addUpdate(up);
840             } else if (e instanceof BooleanLiteralExpr) { 
841                 boolean truth=((BooleanLiteralExpr)e).getValue();
842                 if (de.getNegation())
843                     truth=!truth;
844                 if (!truth) {
845                     okay=false;
846                     break;
847                 }
848             } else {
849                 System.out.println(e.getClass().getName());
850                 throw new Error("Unrecognized Expr");
851             }
852         }
853         return okay;
854     }
855
856     void generatescopenodes() {
857         for(int i=0;i<state.vRules.size();i++) {
858             Rule r=(Rule) state.vRules.get(i);
859             ScopeNode satisfy=new ScopeNode(r,true);
860             TermNode tnsatisfy=new TermNode(satisfy);
861             GraphNode gnsatisfy=new GraphNode("SatisfyRule"+i,tnsatisfy);
862             ConsequenceNode cnsatisfy=new ConsequenceNode();
863             TermNode ctnsatisfy=new TermNode(cnsatisfy);
864             GraphNode cgnsatisfy=new GraphNode("ConseqSatisfyRule"+i,ctnsatisfy);
865             consequence.put(satisfy,cgnsatisfy);
866             GraphNode.Edge esat=new GraphNode.Edge("consequencesatisfy"+i,cgnsatisfy);
867             gnsatisfy.addEdge(esat);
868             consequencenodes.add(cgnsatisfy);
869             scopesatisfy.put(r,gnsatisfy);
870             scopenodes.add(gnsatisfy);
871
872             ScopeNode falsify=new ScopeNode(r,false);
873             TermNode tnfalsify=new TermNode(falsify);
874             GraphNode gnfalsify=new GraphNode("FalsifyRule"+i,tnfalsify);
875             ConsequenceNode cnfalsify=new ConsequenceNode();
876             TermNode ctnfalsify=new TermNode(cnfalsify);
877             GraphNode cgnfalsify=new GraphNode("ConseqFalsifyRule"+i,ctnfalsify);
878             consequence.put(falsify,cgnfalsify);
879             GraphNode.Edge efals=new GraphNode.Edge("consequencefalsify"+i,cgnfalsify);
880             gnfalsify.addEdge(efals);
881             consequencenodes.add(cgnfalsify);
882             scopefalsify.put(r,gnfalsify);
883             scopenodes.add(gnfalsify);
884         }
885     }
886 }