Improved termination analysis so that daikon generated specifications won't have...
[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                 /* See if this is a relation wellformedness constraint
281                    that is trivially satisfied. */
282                 if (abstractinterferes.checkrelationconstraint(ar, cons))
283                     continue;
284                 if (AbstractInterferes.interferesquantifier(ar,cons)) {
285                     GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
286                     gn.addEdge(e);
287                 } else {
288                     for(int i=0;i<conj.size();i++) {
289                         DNFPredicate dp=conj.get(i);
290                         if (getConstraint(gn)!=null&&
291                             abstractinterferes.interferemodifies(ar,getConstraint(gn),dp,cons))
292                             continue;
293
294                         if (abstractinterferes.interfereswithpredicate(ar,dp)) {
295                             GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
296                             gn.addEdge(e);
297                             break;
298                         }
299                     }
300                 }
301             }
302             for(Iterator scopeiterator=scopenodes.iterator();scopeiterator.hasNext();) {
303                 GraphNode gn2=(GraphNode)scopeiterator.next();
304                 TermNode tn2=(TermNode)gn2.getOwner();
305                 ScopeNode sn2=tn2.getScope();
306                 if (AbstractInterferes.interfereswithrule(ar,sn2.getRule(),sn2.getSatisfy())) {
307                     GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
308                     gn.addEdge(e);
309                 }
310             }
311         }
312     }
313
314     Constraint getConstraint(GraphNode gn) {
315         for(Iterator it=gn.inedges();it.hasNext();) {
316             GraphNode.Edge e=(GraphNode.Edge)it.next();
317             GraphNode gnsource=e.getSource();
318             TermNode tnsource=(TermNode)gnsource.getOwner();
319             if (tnsource.getType()==TermNode.CONJUNCTION) {
320                 return tnsource.getConstraint();
321             }
322         }
323         return null;
324     }
325
326     void generatescopenodes() {
327         for(int i=0;i<state.vRules.size();i++) {
328             Rule r=(Rule) state.vRules.get(i);
329             ScopeNode satisfy=new ScopeNode(r,true);
330             TermNode tnsatisfy=new TermNode(satisfy);
331             GraphNode gnsatisfy=new GraphNode("SatisfyRule"+i,tnsatisfy);
332             ConsequenceNode cnsatisfy=new ConsequenceNode();
333             TermNode ctnsatisfy=new TermNode(cnsatisfy);
334             GraphNode cgnsatisfy=new GraphNode("ConseqSatisfyRule"+i,ctnsatisfy);
335             consequence.put(satisfy,cgnsatisfy);
336             GraphNode.Edge esat=new GraphNode.Edge("consequencesatisfy"+i,cgnsatisfy);
337             gnsatisfy.addEdge(esat);
338             consequencenodes.add(cgnsatisfy);
339             scopesatisfy.put(r,gnsatisfy);
340             scopenodes.add(gnsatisfy);
341
342             ScopeNode falsify=new ScopeNode(r,false);
343             TermNode tnfalsify=new TermNode(falsify);
344             GraphNode gnfalsify=new GraphNode("FalsifyRule"+i,tnfalsify);
345             ConsequenceNode cnfalsify=new ConsequenceNode();
346             TermNode ctnfalsify=new TermNode(cnfalsify);
347             GraphNode cgnfalsify=new GraphNode("ConseqFalsifyRule"+i,ctnfalsify);
348             consequence.put(falsify,cgnfalsify);
349             GraphNode.Edge efals=new GraphNode.Edge("consequencefalsify"+i,cgnfalsify);
350             gnfalsify.addEdge(efals);
351             consequencenodes.add(cgnfalsify);
352             scopefalsify.put(r,gnfalsify);
353             scopenodes.add(gnfalsify);
354         }
355     }
356
357     void generatescopeedges() {
358         for(Iterator scopeiterator=scopenodes.iterator();scopeiterator.hasNext();) {
359             GraphNode gn=(GraphNode)scopeiterator.next();
360             TermNode tn=(TermNode)gn.getOwner();
361             ScopeNode sn=tn.getScope();
362
363             /* Interference edges with conjunctions */
364             for(Iterator conjiterator=conjunctions.iterator();conjiterator.hasNext();) {
365                 GraphNode gn2=(GraphNode)conjiterator.next();
366                 TermNode tn2=(TermNode)gn2.getOwner();
367                 Conjunction conj=tn2.getConjunction();
368                 Constraint constr=tn2.getConstraint();
369                 for(int i=0;i<conj.size();i++) {
370                     DNFPredicate dp=conj.get(i);
371                     if (abstractinterferes.scopeinterfereswithpredicate(sn,dp)||
372                         AbstractInterferes.interfereswithquantifier(sn.getDescriptor(),sn.getSatisfy(),constr)) {
373                         GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
374                         GraphNode gnconseq=(GraphNode)consequence.get(sn);
375                         gnconseq.addEdge(e);
376                         break;
377                     }
378                 }
379             }
380
381             /* Now see if this could effect other model defintion rules */
382             for(int i=0;i<state.vRules.size();i++) {
383                 Rule r=(Rule) state.vRules.get(i);
384                 if (AbstractInterferes.interfereswithrule(sn.getDescriptor(),sn.getSatisfy(),r,true)) {
385                     GraphNode scopenode=(GraphNode)scopesatisfy.get(r);
386                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
387                     GraphNode gnconseq=(GraphNode)consequence.get(sn);
388                     gnconseq.addEdge(e);
389                 }
390                 if (AbstractInterferes.interfereswithrule(sn.getDescriptor(),sn.getSatisfy(),r,false)) {
391                     GraphNode scopenode=(GraphNode)scopefalsify.get(r);
392                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
393                     GraphNode gnconseq=(GraphNode)consequence.get(sn);
394                     gnconseq.addEdge(e);
395                 }
396             }
397         }
398     }
399
400     /** This method generates the abstract repair nodes. */
401     void generaterepairnodes() {
402         /* Generate repairs of conjunctions */
403         for(Iterator conjiterator=conjunctions.iterator();conjiterator.hasNext();) {
404             GraphNode gn=(GraphNode)conjiterator.next();
405             TermNode tn=(TermNode)gn.getOwner();
406             Conjunction conj=tn.getConjunction();
407         loop:
408             for(int i=0;i<conj.size();i++) {
409                 DNFPredicate dp=conj.get(i);
410                 int[] array=dp.getPredicate().getRepairs(dp.isNegated(),this);
411                 Descriptor d=dp.getPredicate().getDescriptor();
412                 if ((dp.getPredicate() instanceof ExprPredicate)&&
413                     (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.SIZE)) {
414                     boolean neg=dp.isNegated();
415                     Opcode op=((ExprPredicate)dp.getPredicate()).getOp();
416                     int size=((ExprPredicate)dp.getPredicate()).rightSize();
417                     op=Opcode.translateOpcode(neg,op);
418                     if (((size==1)&&(op==Opcode.EQ))||
419                         ((size!=1)&&(op==Opcode.NE))||
420                         ((size<=1)&&(op==Opcode.GE))||
421                         ((size<1)&&(op==Opcode.GT))||
422                         ((size>1)&&(op==Opcode.LT))||
423                         ((size>=1)&&(op==Opcode.LE))) {
424                         for(int i2=0;i2<conj.size();i2++) {
425                             DNFPredicate dp2=conj.get(i2);
426                             if ((dp2.getPredicate() instanceof ExprPredicate)&&
427                                 (((ExprPredicate)dp2.getPredicate()).getType()==ExprPredicate.COMPARISON)) {
428                                 if (equivalent(((SizeofExpr)((OpExpr)((ExprPredicate)dp.getPredicate()).expr).left).setexpr,
429                                                (RelationExpr)((OpExpr)((ExprPredicate)dp2.getPredicate()).expr).left))
430                                     continue loop; // comparison predicate ensure that size expr is true - no need to generate abstract repairs...
431                             }
432                         }
433                     }
434                 }
435
436                 for(int j=0;j<array.length;j++) {
437                     AbstractRepair ar=new AbstractRepair(dp,array[j],d,sources);
438                     TermNode tn2=new TermNode(ar);
439                     GraphNode gn2=new GraphNode(gn.getLabel()+"A"+i+"B"+ar.type(),gn.getTextLabel()+" #"+i+" "+ar.type(),tn2);
440                     GraphNode.Edge e=new GraphNode.Edge("abstract",gn2);
441                     gn.addEdge(e);
442                     if (!predtoabstractmap.containsKey(dp))
443                         predtoabstractmap.put(dp,new HashSet());
444                     ((Set)predtoabstractmap.get(dp)).add(gn2);
445                     abstractrepair.add(gn2);
446                 }
447             }
448         }
449         /* Generate additional abstract repairs */
450         Vector setdescriptors=state.stSets.getAllDescriptors();
451         for(int i=0;i<setdescriptors.size();i++) {
452             SetDescriptor sd=(SetDescriptor)setdescriptors.get(i);
453
454             VarExpr ve=new VarExpr("DUMMY");
455             InclusionPredicate ip=new InclusionPredicate(ve,new SetExpr(sd));
456             DNFPredicate tp=new DNFPredicate(false,ip);
457             AbstractRepair ar=new AbstractRepair(tp, AbstractRepair.ADDTOSET, sd,sources);
458             TermNode tn=new TermNode(ar);
459             GraphNode gn=new GraphNode("AbstractAddSetRule"+i,tn);
460             if (!predtoabstractmap.containsKey(tp))
461                 predtoabstractmap.put(tp,new HashSet());
462             ((Set)predtoabstractmap.get(tp)).add(gn);
463             abstractrepair.add(gn);
464             abstractrepairadd.add(gn);
465             abstractadd.put(sd,gn);
466
467             DNFPredicate tp2=new DNFPredicate(true,ip);
468             AbstractRepair ar2=new AbstractRepair(tp2, AbstractRepair.REMOVEFROMSET, sd,sources);
469             TermNode tn2=new TermNode(ar2);
470             GraphNode gn2=new GraphNode("AbstractRemSetRule"+i,tn2);
471             if (!predtoabstractmap.containsKey(tp2))
472                 predtoabstractmap.put(tp2,new HashSet());
473             ((Set)predtoabstractmap.get(tp2)).add(gn2);
474             abstractrepair.add(gn2);
475             abstractrepairadd.add(gn2);
476             abstractremove.put(sd,gn2);
477         }
478
479         Vector relationdescriptors=state.stRelations.getAllDescriptors();
480         for(int i=0;i<relationdescriptors.size();i++) {
481             RelationDescriptor rd=(RelationDescriptor)relationdescriptors.get(i);
482             VarDescriptor vd1=new VarDescriptor("DUMMY1");
483             VarExpr ve2=new VarExpr("DUMMY2");
484
485             InclusionPredicate ip=new InclusionPredicate(ve2,new ImageSetExpr(vd1, rd));
486
487             DNFPredicate tp=new DNFPredicate(false,ip);
488             AbstractRepair ar=new AbstractRepair(tp, AbstractRepair.ADDTORELATION, rd,sources);
489             TermNode tn=new TermNode(ar);
490             GraphNode gn=new GraphNode("AbstractAddRelRule"+i,tn);
491             if (!predtoabstractmap.containsKey(tp))
492                 predtoabstractmap.put(tp,new HashSet());
493             ((Set)predtoabstractmap.get(tp)).add(gn);
494             abstractrepair.add(gn);
495             abstractrepairadd.add(gn);
496             abstractadd.put(rd,gn);
497
498             DNFPredicate tp2=new DNFPredicate(true,ip);
499             AbstractRepair ar2=new AbstractRepair(tp2, AbstractRepair.REMOVEFROMRELATION, rd,sources);
500             TermNode tn2=new TermNode(ar2);
501             GraphNode gn2=new GraphNode("AbstractRemRelRule"+i,tn2);
502             if (!predtoabstractmap.containsKey(tp2))
503                 predtoabstractmap.put(tp2,new HashSet());
504             ((Set)predtoabstractmap.get(tp2)).add(gn2);
505             abstractrepair.add(gn2);
506             abstractrepairadd.add(gn2);
507             abstractremove.put(rd,gn2);
508         }
509     }
510
511     int compensationcount=0;
512     void generatecompensationnodes() {
513         for(int i=0;i<state.vRules.size();i++) {
514             Rule r=(Rule) state.vRules.get(i);
515             Vector possiblerules=new Vector();
516
517             for(int j=0;j<(r.numQuantifiers()+r.getDNFNegGuardExpr().size());j++) {
518                 GraphNode gn=(GraphNode)scopesatisfy.get(r);
519                 TermNode tn=(TermNode) gn.getOwner();
520                 ScopeNode sn=tn.getScope();
521                 MultUpdateNode mun=new MultUpdateNode(sn);
522                 TermNode tn2=new TermNode(mun);
523                 GraphNode gn2=new GraphNode("CompRem"+compensationcount,tn2);
524                 UpdateNode un=new UpdateNode(r);
525
526                 if (j<r.numQuantifiers()) {
527                     /* Remove quantifier */
528                     Quantifier q=r.getQuantifier(j);
529                     if (q instanceof RelationQuantifier) {
530                         RelationQuantifier rq=(RelationQuantifier)q;
531                         TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
532                         toe.td=ReservedTypeDescriptor.INT;
533                         Updates u=new Updates(toe,true);
534                         un.addUpdate(u);
535                         if (abstractremove.containsKey(rq.relation)) {
536                             GraphNode agn=(GraphNode)abstractremove.get(rq.relation);
537                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
538                             gn2.addEdge(e);
539                         } else {
540                             continue; /* Abstract repair doesn't exist */
541                         }
542                     } else if (q instanceof SetQuantifier) {
543                         SetQuantifier sq=(SetQuantifier)q;
544                         ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
545                         eoe.td=ReservedTypeDescriptor.INT;
546                         Updates u=new Updates(eoe,true);
547                         un.addUpdate(u);
548                         if (abstractremove.containsKey(sq.set)) {
549                             GraphNode agn=(GraphNode)abstractremove.get(sq.set);
550                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
551                             gn2.addEdge(e);
552                         } else {
553                             continue; /* Abstract repair doesn't exist */
554                         }
555                     } else {
556                         continue;
557                     }
558                 } else {
559                     /* Negate conjunction */
560                     int c=j-r.numQuantifiers();
561                     if (!processconjunction(un,r.getDNFNegGuardExpr().get(c),null)) {
562                         continue;
563                     }
564                 }
565                 if (!un.checkupdates()) /* Make sure we have a good update */
566                     continue;
567
568                 mun.addUpdate(un);
569                 GraphNode.Edge e=new GraphNode.Edge("abstract"+compensationcount,gn2);
570                 compensationcount++;
571                 gn.addEdge(e);
572                 updatenodes.add(gn2);
573             }
574         }
575     }
576
577     void generatedatastructureupdatenodes() {
578         for(Iterator absiterator=abstractrepair.iterator();absiterator.hasNext();) {
579             GraphNode gn=(GraphNode)absiterator.next();
580             System.out.println("Analysing: "+gn.getTextLabel());
581             TermNode tn=(TermNode) gn.getOwner();
582             AbstractRepair ar=tn.getAbstract();
583             if (ar.getType()==AbstractRepair.ADDTOSET) {
584                 generateaddtosetrelation(gn,ar);
585             } else if (ar.getType()==AbstractRepair.REMOVEFROMSET) {
586                 generateremovefromsetrelation(gn,ar);
587             } else if (ar.getType()==AbstractRepair.ADDTORELATION) {
588                 generateaddtosetrelation(gn,ar);
589             } else if (ar.getType()==AbstractRepair.REMOVEFROMRELATION) {
590                 generateremovefromsetrelation(gn,ar);
591             } else if (ar.getType()==AbstractRepair.MODIFYRELATION) {
592                 /* Generate remove/add pairs */
593                 if (ar.needsRemoves(state))
594                     generateremovefromsetrelation(gn,ar);
595                 generateaddtosetrelation(gn,ar);
596                 /* Generate atomic modify */
597                 generatemodifyrelation(gn,ar);
598             }
599         }
600     }
601
602
603     /** This method generates concrete data structure updates which
604      * remove an object (or tuple) from a set (or relation).*/
605
606     int removefromcount=0;
607     void generateremovefromsetrelation(GraphNode gn,AbstractRepair ar) {
608         /* Construct the set of all rules which could add something to the given set or relation */
609
610         Vector possiblerules=new Vector();
611         for(int i=0;i<state.vRules.size();i++) {
612             Rule r=(Rule) state.vRules.get(i);
613             if ((r.getInclusion() instanceof SetInclusion)&&
614                 (ar.getDescriptor()==((SetInclusion)r.getInclusion()).getSet()))
615                 possiblerules.add(r);
616             if ((r.getInclusion() instanceof RelationInclusion)&&
617                 (ar.getDescriptor()==((RelationInclusion)r.getInclusion()).getRelation()))
618                 possiblerules.add(r);
619         }
620         if (possiblerules.size()==0)
621             return;
622
623         /* Loop through different ways of falsifying each of these rules */
624         int[] count=new int[possiblerules.size()];
625         while(remains(count,possiblerules,true)) {
626             MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.REMOVE);
627             TermNode tn=new TermNode(mun);
628             GraphNode gn2=new GraphNode("UpdateRem"+removefromcount,tn);
629
630             boolean goodflag=true;
631             for(int i=0;i<possiblerules.size();i++) {
632                 Rule r=(Rule)possiblerules.get(i);
633                 UpdateNode un=new UpdateNode(r);
634
635                 if (count[i]<r.numQuantifiers()) {
636                     /* Remove quantifier */
637                     Quantifier q=r.getQuantifier(count[i]);
638                     if (q instanceof RelationQuantifier) {
639                         RelationQuantifier rq=(RelationQuantifier)q;
640                         TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
641                         toe.td=ReservedTypeDescriptor.INT;
642                         Updates u=new Updates(toe,true);
643                         un.addUpdate(u);
644                         if (abstractremove.containsKey(rq.relation)) {
645                             GraphNode agn=(GraphNode)abstractremove.get(rq.relation);
646                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
647                             gn2.addEdge(e);
648                         } else {
649                             goodflag=false;break; /* Abstract repair doesn't exist */
650                         }
651                     } else if (q instanceof SetQuantifier) {
652                         SetQuantifier sq=(SetQuantifier)q;
653                         ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
654                         eoe.td=ReservedTypeDescriptor.INT;
655                         Updates u=new Updates(eoe,true);
656                         un.addUpdate(u);
657                         if (abstractremove.containsKey(sq.set)) {
658                             GraphNode agn=(GraphNode)abstractremove.get(sq.set);
659                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
660                             gn2.addEdge(e);
661                         } else {
662                             goodflag=false;break; /* Abstract repair doesn't exist */
663                         }
664                     } else {goodflag=false;break;}
665                 } else {
666                     int c=count[i]-r.numQuantifiers();
667                     if (!processconjunction(un,r.getDNFNegGuardExpr().get(c),null)) {
668                         goodflag=false;break;
669                     }
670                 }
671                 if (!un.checkupdates()) {
672                     goodflag=false;
673                     break;
674                 }
675                 mun.addUpdate(un);
676             }
677             if (goodflag) {
678                 GraphNode.Edge e=new GraphNode.Edge("abstract"+(removefromcount++),gn2);
679                 gn.addEdge(e);
680                 updatenodes.add(gn2);
681             }
682             increment(count,possiblerules,true);
683         }
684     }
685
686     /** This method increments to the next possibility. */
687
688     static private void increment(int count[], Vector rules,boolean isremove) {
689         count[0]++;
690         for(int i=0;i<(rules.size()-1);i++) {
691             int num=isremove?(((Rule)rules.get(i)).numQuantifiers()+(((Rule)rules.get(i)).getDNFNegGuardExpr().size())):((Rule)rules.get(i)).getDNFGuardExpr().size();
692             if (count[i]>=num) {
693                 count[i+1]++;
694                 count[i]=0;
695             } else break;
696         }
697     }
698
699
700     /** This method test if there remain any possibilities to loop
701      * through. */
702     static private boolean remains(int count[], Vector rules, boolean isremove) {
703         for(int i=0;i<rules.size();i++) {
704             int num=isremove?(((Rule)rules.get(i)).numQuantifiers()+(((Rule)rules.get(i)).getDNFNegGuardExpr().size())):((Rule)rules.get(i)).getDNFGuardExpr().size();
705             if (count[i]>=num) {
706                 return false;
707             }
708         }
709         return true;
710     }
711
712     /** This method generates data structure updates to implement the
713      *  abstract atomic modification specified by ar. */
714
715     int modifycount=0;
716     void generatemodifyrelation(GraphNode gn, AbstractRepair ar) {
717         RelationDescriptor rd=(RelationDescriptor)ar.getDescriptor();
718         ExprPredicate exprPredicate=(ExprPredicate)ar.getPredicate().getPredicate();
719         boolean inverted=exprPredicate.inverted();
720         int leftindex=0;
721         int rightindex=1;
722         if (inverted)
723             leftindex=2;
724         else
725             rightindex=2;
726
727         // construct set of possible rules
728         Vector possiblerules=new Vector();
729         for(int i=0;i<state.vRules.size();i++) {
730             Rule r=(Rule) state.vRules.get(i);
731             if ((r.getInclusion() instanceof RelationInclusion)&&
732                 (rd==((RelationInclusion)r.getInclusion()).getRelation()))
733                 possiblerules.add(r);
734         }
735         if (possiblerules.size()==0)
736             return;
737
738         // increment through this set
739         int[] count=new int[possiblerules.size()];
740         while(remains(count,possiblerules,false)) {
741             MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.MODIFY);
742             TermNode tn=new TermNode(mun);
743             GraphNode gn2=new GraphNode("UpdateMod"+modifycount,tn);
744
745             boolean goodflag=true;
746             for(int i=0;i<possiblerules.size();i++) {
747                 Rule r=(Rule)possiblerules.get(i);
748                 UpdateNode un=new UpdateNode(r);
749
750                 int c=count[i];
751                 if (!processconjunction(un,r.getDNFGuardExpr().get(c),null)) {
752                     goodflag=false;break;
753                 }
754                 RelationInclusion ri=(RelationInclusion)r.getInclusion();
755                 if (!(ri.getLeftExpr() instanceof VarExpr)) {
756                     if (ri.getLeftExpr().isValue(ri.getRelation().getDomain().getType())) {
757                         Updates up=new Updates(ri.getLeftExpr(),leftindex,ri.getRelation().getDomain().getType());
758                         un.addUpdate(up);
759                     } else {
760                         if (inverted)
761                             goodflag=false;
762                         else un.addInvariant(ri.getLeftExpr());
763                     }
764                 } else {
765                     VarDescriptor vd=((VarExpr)ri.getLeftExpr()).getVar();
766                     if (vd.isGlobal()) {
767                         Updates up=new Updates(ri.getLeftExpr(),leftindex,null);
768                         un.addUpdate(up);
769                     } else if (inverted)
770                         goodflag=false;
771                 }
772                 if (!(ri.getRightExpr() instanceof VarExpr)) {
773                     if (ri.getRightExpr().isValue(ri.getRelation().getRange().getType())) {
774                         Updates up=new Updates(ri.getRightExpr(),rightindex,ri.getRelation().getRange().getType());
775                         un.addUpdate(up);
776                     } else {
777                         if (!inverted)
778                             goodflag=false;
779                         else
780                             un.addInvariant(ri.getLeftExpr());
781                     }
782                 } else {
783                     VarDescriptor vd=((VarExpr)ri.getRightExpr()).getVar();
784                     if (vd.isGlobal()) {
785                         Updates up=new Updates(ri.getRightExpr(),rightindex,null);
786                         un.addUpdate(up);
787                     } else if (!inverted)
788                         goodflag=false;
789                 }
790
791                 if (!un.checkupdates()) {
792                     goodflag=false;
793                     break;
794                 }
795                 mun.addUpdate(un);
796             }
797             if (goodflag) {
798                 GraphNode.Edge e=new GraphNode.Edge("abstract"+modifycount,gn2);
799                 modifycount++;
800                 gn.addEdge(e);
801                 updatenodes.add(gn2);
802             }
803             increment(count,possiblerules,false);
804         }
805     }
806
807     /** Generate concrete data structure update to add an object(or
808      * tuple) to a set (or relation). */
809
810     static int addtocount=0;
811     void generateaddtosetrelation(GraphNode gn, AbstractRepair ar) {
812         for(int i=0;i<state.vRules.size();i++) {
813             Rule r=(Rule) state.vRules.get(i);
814
815
816             /* See if this is a good rule*/
817             if ((r.getInclusion() instanceof SetInclusion&&
818                  ar.getDescriptor()==((SetInclusion)r.getInclusion()).getSet())||
819                 (r.getInclusion() instanceof RelationInclusion&&
820                  ar.getDescriptor()==((RelationInclusion)r.getInclusion()).getRelation())) {
821
822                 /* First solve for quantifiers */
823                 Vector bindings=new Vector();
824                 /* Construct bindings */
825
826                 Hashtable setmapping=new Hashtable();
827                 System.out.println("Attempting to construct bindings");
828
829                 if (!constructbindings(bindings,r,ar,setmapping,false))
830                     continue;
831                 System.out.println("Bindings constructed");
832                 //Generate add instruction
833                 DNFRule dnfrule=r.getDNFGuardExpr();
834                  endloop:
835                 for(int j=0;j<dnfrule.size();j++) {
836                     Inclusion inc=r.getInclusion();
837                     UpdateNode un=new UpdateNode(r);
838                     un.addBindings(bindings);
839                     /* Now build update for tuple/set inclusion condition */
840                     if(inc instanceof SetInclusion) {
841                         SetInclusion si=(SetInclusion)inc;
842                         Expr e=si.elementexpr;
843
844                         while(e instanceof CastExpr) {
845                             CastExpr ce=(CastExpr)e;
846                             if (ce.getType()!=si.getSet().getType())
847                                 continue endloop;
848                             e=ce.getExpr();
849                         }
850
851                         if (!(e instanceof VarExpr)) {
852                             if (e.isValue(si.getSet().getType())) {
853                                 Updates up=new Updates(e,0,si.getSet().getType());
854                                 un.addUpdate(up);
855                             } else {
856                                 /* We're an add to set*/
857                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
858                                 SetDescriptor set=sources.setSource(si.getSet())?
859                                     sources.getSourceSet(si.getSet()):null;
860                                 if (set==null)
861                                     continue;
862                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
863                                 if (rap==ArrayAnalysis.AccessPath.NONE)
864                                     continue;
865                                 if (!rap.equal(ap))
866                                     continue;
867                                 if (!constructarrayupdate(un, e, rap, 0))
868                                     continue;
869                             }
870                         } else {
871                             VarDescriptor vd=((VarExpr)e).getVar();
872                             if (vd.isGlobal()) {
873                                 Updates up=new Updates(e,0,null);
874                                 un.addUpdate(up);
875                             }
876                         }
877                     } else if (inc instanceof RelationInclusion) {
878                         RelationInclusion ri=(RelationInclusion)inc;
879
880                         Expr e=ri.getLeftExpr();
881
882                         while(e instanceof CastExpr) {
883                             CastExpr ce=(CastExpr)e;
884                             if (ce.getType()!=ri.getRelation().getDomain().getType())
885                                 continue endloop;
886                             e=ce.getExpr();
887                         }
888                         if (!(e instanceof VarExpr)) {
889                             if (e.isValue(ri.getRelation().getDomain().getType())) {
890                                 Updates up=new Updates(e,0,ri.getRelation().getDomain().getType());
891                                 if (ar.getDomainSet()!=null)
892                                     setmapping.put(e,ar.getDomainSet());
893                                 un.addUpdate(up);
894                             } else {
895                                 /* We don't handly relation modifies */
896                                 if (ar.getType()==AbstractRepair.MODIFYRELATION)
897                                     continue;
898                                 /* We're an add to relation*/
899                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
900                                 SetDescriptor set=sources.relsetSource(ri.getRelation(),true /* Domain*/)?
901                                     sources.relgetSourceSet(ri.getRelation(),true):null;
902                                 if (set==null)
903                                     continue;
904                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
905                                 if (rap==ArrayAnalysis.AccessPath.NONE||
906                                     !rap.equal(ap)||
907                                     !constructarrayupdate(un, e, rap, 0))
908                                     continue;
909                                 if (ar.getDomainSet()!=null)
910                                     setmapping.put(e,ar.getDomainSet());
911
912                             }
913                         } else {
914                             VarDescriptor vd=((VarExpr)e).getVar();
915                             if (vd.isGlobal()) {
916                                 Updates up=new Updates(e,0,null);
917                                 if (ar.getDomainSet()!=null)
918                                     setmapping.put(e,ar.getDomainSet());
919                                 un.addUpdate(up);
920                             }
921                         }
922
923                         e=ri.getRightExpr();
924
925                         while(e instanceof CastExpr) {
926                             CastExpr ce=(CastExpr)e;
927                             if (ce.getType()!=ri.getRelation().getRange().getType())
928                                 continue endloop;
929                             e=ce.getExpr();
930                         }
931                         if (!(e instanceof VarExpr)) {
932                             if (e.isValue(ri.getRelation().getRange().getType())) {
933                                 Updates up=new Updates(e,1,ri.getRelation().getRange().getType());
934                                 un.addUpdate(up);
935                             } else {
936                                 /* We don't handly relation modifies */
937                                 if (ar.getType()==AbstractRepair.MODIFYRELATION)
938                                     continue;
939                                 /* We're an add to relation*/
940                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
941                                 SetDescriptor set=sources.relsetSource(ri.getRelation(),false /* Range*/)?
942                                     sources.relgetSourceSet(ri.getRelation(),false):null;
943                                 if (set==null)
944                                     continue;
945                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
946
947                                 if (rap==ArrayAnalysis.AccessPath.NONE||
948                                     !rap.equal(ap)||
949                                     !constructarrayupdate(un, e, rap, 1))
950                                     continue;
951                                 if (ar.getRangeSet()!=null)
952                                     setmapping.put(e,ar.getRangeSet());
953                             }
954                         } else {
955                             VarDescriptor vd=((VarExpr)e).getVar();
956                             if (vd.isGlobal()) {
957                                 Updates up=new Updates(e,1,null);
958                                 if (ar.getRangeSet()!=null)
959                                     setmapping.put(e,ar.getRangeSet());
960                                 un.addUpdate(up);
961                             }
962                         }
963                     }
964                     System.out.println("Built inclusion condition updates.");
965                     //Finally build necessary updates to satisfy conjunction
966                     RuleConjunction ruleconj=dnfrule.get(j);
967
968                     /* Add in updates for quantifiers */
969                     MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.ADD);
970                     TermNode tn=new TermNode(mun);
971                     GraphNode gn2=new GraphNode("UpdateAdd"+addtocount,tn);
972
973                     if (debugmsg("Start processing quantifiers")&&
974                         processquantifiers(gn2,un, r,setmapping)&&
975                         debugmsg("Finished processing quantifiers")&&
976                         processconjunction(un,ruleconj,setmapping)&&
977                         debugmsg("Finished processing conjunction")&&
978                         un.checkupdates()&&
979                         debugmsg("Updates checked")) {
980                         mun.addUpdate(un);
981                         GraphNode.Edge e=new GraphNode.Edge("abstract"+addtocount,gn2);
982                         addtocount++;
983                         gn.addEdge(e);
984                         updatenodes.add(gn2);
985                     }
986                 }
987             }
988         }
989     }
990
991     boolean debugmsg(String st) {
992         System.out.println(st);
993         return true;
994     }
995
996     boolean constructarrayupdate(UpdateNode un, Expr lexpr, ArrayAnalysis.AccessPath ap, int slotnumber) {
997         System.out.println("Constructing array update");
998         Expr e=null;
999         for (int i=ap.numFields()-1;i>=0;i--) {
1000             if (e==null)
1001                 e=lexpr;
1002             else
1003                 e=((DotExpr)e).getExpr();
1004
1005             while (e instanceof CastExpr)
1006                 e=((CastExpr)e).getExpr();
1007
1008             DotExpr de=(DotExpr)e;
1009             FieldDescriptor fd=ap.getField(i);
1010             if (fd instanceof ArrayDescriptor) {
1011                 // We have an ArrayDescriptor!
1012                 Expr index=de.getIndex();
1013                 if (!index.isValue(null)) {/* Not assignable */
1014                     System.out.println("ERROR:Index isn't assignable");
1015                     return false;
1016                 }
1017                 Updates updates=new Updates(index,i,ap,lexpr,slotnumber);
1018                 un.addUpdate(updates);
1019             }
1020         }
1021         return true;
1022     }
1023
1024     /** This method constructs bindings for an update using rule
1025      * r. The boolean flag isremoval indicates that the update
1026      * performs a removal.  The function returns true if it is able to
1027      * generate a valid set of bindings and false otherwise. */
1028
1029     boolean constructbindings(Vector bindings, Rule r, AbstractRepair ar, Hashtable setmapping, boolean isremoval) {
1030         boolean goodupdate=true;
1031         Inclusion inc=r.getInclusion();
1032
1033         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
1034             Quantifier q=(Quantifier)iterator.next();
1035             if ((q instanceof SetQuantifier)||(q instanceof ForQuantifier)) {
1036                 VarDescriptor vd=null;
1037                 SetDescriptor set=null;
1038                 if (q instanceof SetQuantifier) {
1039                     vd=((SetQuantifier)q).getVar();
1040                     set=((SetQuantifier)q).getSet();
1041                 } else {
1042                     vd=((ForQuantifier)q).getVar();
1043                 }
1044                 if(inc instanceof SetInclusion) {
1045                     SetInclusion si=(SetInclusion)inc;
1046                     Expr tmpe=si.elementexpr;
1047                     Expr e=si.elementexpr;
1048
1049                     while(e instanceof CastExpr) {
1050                         CastExpr ce=(CastExpr)e;
1051                         if (ce.getType()!=si.getSet().getType())
1052                             return false;
1053                         e=ce.getExpr();
1054                     }
1055
1056                     if ((e instanceof VarExpr)&&
1057                         (((VarExpr)e).getVar()==vd)) {
1058                         /* Can solve for v */
1059                         if (!si.getSet().getType().isSubtypeOf(set.getType()))
1060                             return false;
1061                         Binding binding=new Binding(vd,0);
1062                         bindings.add(binding);
1063                     } else {
1064                         goodupdate=false;
1065                     }
1066                 } else if (inc instanceof RelationInclusion) {
1067                     RelationInclusion ri=(RelationInclusion)inc;
1068                     boolean f1=true;
1069                     boolean f2=true;
1070
1071                     Expr e=ri.getLeftExpr();
1072
1073                     while(e instanceof CastExpr) {
1074                         CastExpr ce=(CastExpr)e;
1075                         if (ce.getType()!=ri.getRelation().getDomain().getType())
1076                             return false;
1077                         e=ce.getExpr();
1078                     }
1079
1080                     if ((e instanceof VarExpr)&&
1081                         (((VarExpr)e).getVar()==vd)) {
1082                                 /* Can solve for v */
1083                         Binding binding=new Binding(vd,0);
1084                         if (!ri.getRelation().getDomain().getType().isSubtypeOf(set.getType()))
1085                             return false;
1086                         if (ar.getDomainSet()!=null)
1087                             setmapping.put(ri.getLeftExpr(),ar.getDomainSet());
1088                         bindings.add(binding);
1089                     } else f1=false;
1090
1091
1092                     e=ri.getRightExpr();
1093
1094                     while(e instanceof CastExpr) {
1095                         CastExpr ce=(CastExpr)e;
1096                         if (ce.getType()!=ri.getRelation().getRange().getType())
1097                             return false;
1098                         e=ce.getExpr();
1099                     }
1100
1101                     if ((e instanceof VarExpr)&&
1102                         (((VarExpr)e).getVar()==vd)) {
1103                                 /* Can solve for v */
1104                         Binding binding=new Binding(vd,1);
1105                         if (!ri.getRelation().getRange().getType().isSubtypeOf(set.getType()))
1106                             return false;
1107                         if (ar.getRangeSet()!=null)
1108                             setmapping.put(ri.getRightExpr(),ar.getRangeSet());
1109                         bindings.add(binding);
1110                     } else f2=false;
1111                     if (!(f1||f2))
1112                         goodupdate=false;
1113                 } else throw new Error("Inclusion not recognized");
1114                 if (!goodupdate)
1115                     if (isremoval) {
1116                         /* Removals don't need bindings anymore
1117                            Binding binding=new Binding(vd);
1118                            bindings.add(binding);*/
1119                         goodupdate=true;
1120                     } else if (q instanceof SetQuantifier) {
1121                         /* Create new element to bind to */
1122                         // search if the set 'set' has a size
1123                         Binding binding=new Binding(vd,set,exactsize.getsize(set)==1);
1124                         bindings.add(binding);
1125                         goodupdate=true;
1126
1127                     } else
1128                         goodupdate=false;
1129             } else if (q instanceof RelationQuantifier) {
1130                 RelationQuantifier rq=(RelationQuantifier)q;
1131                 for(int k=0;k<2;k++) {
1132                     VarDescriptor vd=(k==0)?rq.x:rq.y;
1133                     TypeDescriptor td=(k==0)?rq.getRelation().getDomain().getType():rq.getRelation().getRange().getType();
1134                     if(inc instanceof SetInclusion) {
1135                         SetInclusion si=(SetInclusion)inc;
1136
1137                         Expr e=si.elementexpr;
1138
1139                         while(e instanceof CastExpr) {
1140                             CastExpr ce=(CastExpr)e;
1141                             if (ce.getType()!=td)
1142                                 return false;
1143                             e=ce.getExpr();
1144                         }
1145
1146                         if ((e instanceof VarExpr)&&
1147                             (((VarExpr)e).getVar()==vd)) {
1148                             /* Can solve for v */
1149                             Binding binding=new Binding(vd,0);
1150
1151                             if (!si.getSet().getType().isSubtypeOf(td))
1152                                 return false;
1153                             bindings.add(binding);
1154                         } else
1155                             goodupdate=false;
1156                     } else if (inc instanceof RelationInclusion) {
1157                         RelationInclusion ri=(RelationInclusion)inc;
1158                         boolean f1=true;
1159                         boolean f2=true;
1160
1161
1162                         Expr e=ri.getLeftExpr();
1163
1164                         while(e instanceof CastExpr) {
1165                             CastExpr ce=(CastExpr)e;
1166                             if (ce.getType()!=ri.getRelation().getDomain().getType())
1167                                 return false;
1168                             e=ce.getExpr();
1169                         }
1170                         if ((ri.getLeftExpr() instanceof VarExpr)&&
1171                             (((VarExpr)ri.getLeftExpr()).getVar()==vd)) {
1172                             /* Can solve for v */
1173                             Binding binding=new Binding(vd,0);
1174                             if (!ri.getRelation().getDomain().getType().isSubtypeOf(td))
1175                                 return false;
1176                             if (ar.getDomainSet()!=null)
1177                                 setmapping.put(ri.getLeftExpr(),ar.getDomainSet());
1178                             bindings.add(binding);
1179                         } else f1=false;
1180
1181
1182                         e=ri.getRightExpr();
1183
1184                         while(e instanceof CastExpr) {
1185                             CastExpr ce=(CastExpr)e;
1186                             if (ce.getType()!=ri.getRelation().getRange().getType())
1187                                 return false;
1188                             e=ce.getExpr();
1189                         }
1190                         if ((ri.getRightExpr() instanceof VarExpr)&&
1191                             (((VarExpr)ri.getRightExpr()).getVar()==vd)) {
1192                             /* Can solve for v */
1193                             Binding binding=new Binding(vd,1);
1194                             if (!ri.getRelation().getRange().getType().isSubtypeOf(td))
1195                                 return false;
1196                             if (ar.getRangeSet()!=null)
1197                                 setmapping.put(ri.getRightExpr(),ar.getRangeSet());
1198                             bindings.add(binding);
1199                         } else f2=false;
1200                         if (!(f1||f2))
1201                             goodupdate=false;
1202                     } else throw new Error("Inclusion not recognized");
1203                     if (!goodupdate)
1204                         if (isremoval) {
1205                             /* Removals don't need bindings anymore
1206                                Binding binding=new Binding(vd);
1207                                bindings.add(binding);*/
1208                             goodupdate=true;
1209                         } else
1210                             break;
1211                 }
1212                 if (!goodupdate)
1213                     break;
1214             } else throw new Error("Quantifier not recognized");
1215         }
1216         return goodupdate;
1217     }
1218
1219     /** Adds updates that add an item to the appropriate set or
1220      * relation quantified over by the model definition rule.. */
1221
1222     boolean processquantifiers(GraphNode gn,UpdateNode un, Rule r,Hashtable setmapping) {
1223         Inclusion inc=r.getInclusion();
1224         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
1225             Quantifier q=(Quantifier)iterator.next();
1226             /* Add quantifier */
1227             if (q instanceof RelationQuantifier) {
1228                 RelationQuantifier rq=(RelationQuantifier)q;
1229                 TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
1230                 toe.td=ReservedTypeDescriptor.INT;
1231                 Updates u=new Updates(toe,false);
1232                 un.addUpdate(u);
1233                 if (abstractadd.containsKey(rq.relation)) {
1234                     GraphNode agn=(GraphNode)abstractadd.get(rq.relation);
1235                     GraphNode.Edge e=new GraphNode.Edge("requires",agn);
1236                     gn.addEdge(e);
1237                 } else {
1238                     return false;
1239                 }
1240             } else if (q instanceof SetQuantifier) {
1241                 SetQuantifier sq=(SetQuantifier)q;
1242                 if (un.getBinding(sq.var).getType()==Binding.SEARCH) {
1243                     Binding b=un.getBinding(sq.var);
1244                     Constraint reqc=exactsize.getConstraint(b.getSet());
1245                     constraintdependence.requiresConstraint(gn,reqc);
1246                     continue; /* Don't need to ensure addition for search */
1247                 }
1248                 VarExpr ve=new VarExpr(sq.var);
1249                 SetDescriptor sd=findExpr(setmapping, ve);
1250                 if (sd!=null&&sd.isSubset(sq.set))
1251                     continue; /* this update is trivially true */
1252
1253                 ElementOfExpr eoe=new ElementOfExpr(ve,sq.set);
1254                 eoe.td=ReservedTypeDescriptor.INT;
1255                 Updates u=new Updates(eoe,false);
1256                 un.addUpdate(u);
1257                 if (abstractadd.containsKey(sq.set)) {
1258                     GraphNode agn=(GraphNode)abstractadd.get(sq.set);
1259                     GraphNode.Edge e=new GraphNode.Edge("requires",agn);
1260                     gn.addEdge(e);
1261                 } else {
1262                     return false;
1263                 }
1264             } else return false;
1265         }
1266         return true;
1267     }
1268
1269     static SetDescriptor findExpr(Hashtable setmapping, Expr e) {
1270         if (setmapping==null)
1271             return null;
1272         Set kset=setmapping.keySet();
1273         for(Iterator it=kset.iterator();it.hasNext();) {
1274             Expr expr=(Expr)it.next();
1275             if (expr.equals(null,e)) {
1276                 return (SetDescriptor)setmapping.get(expr);
1277             }
1278         }
1279         return null;
1280     }
1281
1282     /** This method generates the necessary updates to satisfy the
1283      * conjunction ruleconj. */
1284
1285     boolean  processconjunction(UpdateNode un,RuleConjunction ruleconj,Hashtable setmapping) {
1286         boolean okay=true;
1287         for(int k=0;k<ruleconj.size();k++) {
1288             DNFExpr de=ruleconj.get(k);
1289             Expr e=de.getExpr();
1290             if (e instanceof OpExpr) {
1291                 OpExpr ex=(OpExpr)de.getExpr();
1292                 Opcode op=ex.getOpcode();
1293                 Updates up=new Updates(ex.left,ex.right,op, de.getNegation());
1294                 un.addUpdate(up);
1295             } else if (e instanceof ElementOfExpr) {
1296                 SetDescriptor sd=findExpr(setmapping, ((ElementOfExpr)e).element);
1297                 if (sd!=null&&sd.isSubset(((ElementOfExpr)e).set))
1298                     continue; /* this update is trivially true */
1299                 Updates up=new Updates(e,de.getNegation());
1300                 un.addUpdate(up);
1301             } else if (e instanceof TupleOfExpr) {
1302                 Updates up=new Updates(e,de.getNegation());
1303                 un.addUpdate(up);
1304             } else if (e instanceof BooleanLiteralExpr) {
1305                 boolean truth=((BooleanLiteralExpr)e).getValue();
1306                 if (de.getNegation())
1307                     truth=!truth;
1308                 if (!truth) {
1309                     okay=false;
1310                     break;
1311                 }
1312             } else {
1313                 System.out.println(e.getClass().getName());
1314                 throw new Error("Unrecognized Expr");
1315             }
1316         }
1317         return okay;
1318     }
1319
1320     /** This method sees if when the quantifiers listed in set are
1321      *  fixed, whether there can be more than one unique binding for
1322      *  the constraint or model definition rule qs.*/
1323     public boolean analyzeQuantifiers(Quantifiers qs,Set set) {
1324         for(int i=0;i<qs.numQuantifiers();i++) {
1325             Quantifier q=qs.getQuantifier(i);
1326             if (set.contains(q))
1327                 continue;
1328             if (q instanceof SetQuantifier) {
1329                 SetDescriptor sd=((SetQuantifier)q).getSet();
1330                 if (maxsize.getsize(sd)<=1&&
1331                     maxsize.getsize(sd)>=0)
1332                     continue;
1333             } else if (q instanceof RelationQuantifier) {
1334                 RelationDescriptor rd=((RelationQuantifier)q).getRelation();
1335                 if (maxsize.getsize(rd)<=1&&
1336                     maxsize.getsize(rd)>=0)
1337                     continue;
1338             }
1339             return false;
1340         }
1341         return true;
1342     }
1343
1344     public boolean mutuallyexclusive(SetDescriptor sd1, SetDescriptor sd2) {
1345         if (mutualexclusive(sd1,sd2)||
1346             mutualexclusive(sd2,sd1))
1347             return true;
1348         else
1349             return false;
1350     }
1351
1352     private boolean mutualexclusive(SetDescriptor sd1, SetDescriptor sd2) {
1353         Vector rules=state.vRules;
1354         for(int i=0;i<rules.size();i++) {
1355             Rule r=(Rule)rules.get(i);
1356             if (r.getInclusion().getTargetDescriptors().contains(sd1)) {
1357                 /* Rule may add items to sd1 */
1358                 SetInclusion si=(SetInclusion)r.getInclusion();
1359                 Expr ve=si.getExpr();
1360                 DNFRule drule=r.getDNFGuardExpr();
1361                 for(int j=0;j<drule.size();j++) {
1362                     RuleConjunction rconj=drule.get(j);
1363                     boolean containsexclusion=false;
1364                     for (int k=0;k<rconj.size();k++) {
1365                         DNFExpr dexpr=rconj.get(k);
1366                         if (dexpr.getNegation()&&
1367                             dexpr.getExpr() instanceof ElementOfExpr&&
1368                             ((ElementOfExpr)dexpr.getExpr()).element.equals(null,ve)) {
1369                             SetDescriptor sd=((ElementOfExpr)dexpr.getExpr()).set;
1370                             if (sd.isSubset(sd2))
1371                                 containsexclusion=true;
1372                         }
1373                     }
1374                     if (!containsexclusion)
1375                         return false;
1376                 }
1377             }
1378         }
1379         return true;
1380     }
1381
1382     boolean equivalent(SetExpr se, RelationExpr re) {
1383         if (!(se instanceof ImageSetExpr))
1384             return false;
1385         ImageSetExpr ise=(ImageSetExpr)se;
1386         while(re!=null&&ise!=null) {
1387             if (re.getRelation()!=ise.getRelation())
1388                 return false;
1389             if (re.inverted()!=ise.inverted())
1390                 return false;
1391             if (ise.isimageset) {
1392                 ise=ise.getImageSetExpr();
1393                 if (!(re.getExpr() instanceof RelationExpr))
1394                     return false;
1395                 re=(RelationExpr)re.getExpr();
1396             } else {
1397                 if (!(re.getExpr() instanceof VarExpr))
1398                     return false;
1399                 if (((VarExpr)re.getExpr()).getVar()==ise.getVar())
1400                     return true; //everything matches
1401                 return false;
1402             }
1403         }
1404         return false;
1405     }
1406 }