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