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