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