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