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