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