d0197b5d8b000337659ead3f847cdd95b978cef4
[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                 if (ar.needsRemoves(state))
551                     generateremovefromsetrelation(gn,ar);
552                 generateaddtosetrelation(gn,ar);
553                 /* Generate atomic modify */
554                 generatemodifyrelation(gn,ar);
555             }
556         }
557     }
558
559
560     /** This method generates concrete data structure updates which
561      * remove an object (or tuple) from a set (or relation).*/
562
563     int removefromcount=0;
564     void generateremovefromsetrelation(GraphNode gn,AbstractRepair ar) {
565         /* Construct the set of all rules which could add something to the given set or relation */
566
567         Vector possiblerules=new Vector();
568         for(int i=0;i<state.vRules.size();i++) {
569             Rule r=(Rule) state.vRules.get(i);
570             if ((r.getInclusion() instanceof SetInclusion)&&
571                 (ar.getDescriptor()==((SetInclusion)r.getInclusion()).getSet()))
572                 possiblerules.add(r);
573             if ((r.getInclusion() instanceof RelationInclusion)&&
574                 (ar.getDescriptor()==((RelationInclusion)r.getInclusion()).getRelation()))
575                 possiblerules.add(r);
576         }
577         if (possiblerules.size()==0)
578             return;
579         
580         /* Loop through different ways of falsifying each of these rules */
581         int[] count=new int[possiblerules.size()];
582         while(remains(count,possiblerules,true)) {
583             MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.REMOVE);
584             TermNode tn=new TermNode(mun);
585             GraphNode gn2=new GraphNode("UpdateRem"+removefromcount,tn);
586
587             boolean goodflag=true;
588             for(int i=0;i<possiblerules.size();i++) {
589                 Rule r=(Rule)possiblerules.get(i);
590                 UpdateNode un=new UpdateNode(r);
591
592                 if (count[i]<r.numQuantifiers()) {
593                     /* Remove quantifier */
594                     Quantifier q=r.getQuantifier(count[i]);
595                     if (q instanceof RelationQuantifier) {
596                         RelationQuantifier rq=(RelationQuantifier)q;
597                         TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
598                         toe.td=ReservedTypeDescriptor.INT;
599                         Updates u=new Updates(toe,true);
600                         un.addUpdate(u);
601                         if (abstractremove.containsKey(rq.relation)) {
602                             GraphNode agn=(GraphNode)abstractremove.get(rq.relation);
603                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
604                             gn2.addEdge(e);
605                         } else {
606                             goodflag=false;break; /* Abstract repair doesn't exist */
607                         }
608                     } else if (q instanceof SetQuantifier) {
609                         SetQuantifier sq=(SetQuantifier)q;
610                         ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
611                         eoe.td=ReservedTypeDescriptor.INT;
612                         Updates u=new Updates(eoe,true);
613                         un.addUpdate(u);
614                         if (abstractremove.containsKey(sq.set)) {
615                             GraphNode agn=(GraphNode)abstractremove.get(sq.set);
616                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
617                             gn2.addEdge(e);
618                         } else {
619                             goodflag=false;break; /* Abstract repair doesn't exist */
620                         }
621                     } else {goodflag=false;break;}
622                 } else {
623                     int c=count[i]-r.numQuantifiers();
624                     if (!processconjunction(un,r.getDNFNegGuardExpr().get(c),null)) {
625                         goodflag=false;break;
626                     }
627                 }
628                 if (!un.checkupdates()) {
629                     goodflag=false;
630                     break;
631                 }
632                 mun.addUpdate(un);
633             }
634             if (goodflag) {
635                 GraphNode.Edge e=new GraphNode.Edge("abstract"+removefromcount,gn2);
636                 removefromcount++;
637                 gn.addEdge(e);
638                 updatenodes.add(gn2);
639             }
640             increment(count,possiblerules,true);
641         }
642     }
643
644     /** This method increments to the next possibility. */
645
646     static private void increment(int count[], Vector rules,boolean isremove) {
647         count[0]++;
648         for(int i=0;i<(rules.size()-1);i++) {
649             int num=isremove?(((Rule)rules.get(i)).numQuantifiers()+(((Rule)rules.get(i)).getDNFNegGuardExpr().size())):((Rule)rules.get(i)).getDNFGuardExpr().size();
650             if (count[i]>=num) {
651                 count[i+1]++;
652                 count[i]=0;
653             } else break;
654         }
655     }
656
657
658     /** This method test if there remain any possibilities to loop
659      * through. */
660     static private boolean remains(int count[], Vector rules, boolean isremove) {
661         for(int i=0;i<rules.size();i++) {
662             int num=isremove?(((Rule)rules.get(i)).numQuantifiers()+(((Rule)rules.get(i)).getDNFNegGuardExpr().size())):((Rule)rules.get(i)).getDNFGuardExpr().size();
663             if (count[i]>=num) {
664                 return false;
665             }
666         }
667         return true;
668     }
669
670     /** This method generates data structure updates to implement the
671      *  abstract atomic modification specified by ar. */
672
673     int modifycount=0;
674     void generatemodifyrelation(GraphNode gn, AbstractRepair ar) {
675         RelationDescriptor rd=(RelationDescriptor)ar.getDescriptor();
676         ExprPredicate exprPredicate=(ExprPredicate)ar.getPredicate().getPredicate();
677         boolean inverted=exprPredicate.inverted();
678         int leftindex=0;
679         int rightindex=1;
680         if (inverted)
681             leftindex=2;
682         else 
683             rightindex=2;
684
685         // construct set of possible rules
686         Vector possiblerules=new Vector();
687         for(int i=0;i<state.vRules.size();i++) {
688             Rule r=(Rule) state.vRules.get(i);
689             if ((r.getInclusion() instanceof RelationInclusion)&&
690                 (rd==((RelationInclusion)r.getInclusion()).getRelation()))
691                 possiblerules.add(r);
692         }
693         if (possiblerules.size()==0)
694             return;
695
696         // increment through this set
697         int[] count=new int[possiblerules.size()];
698         while(remains(count,possiblerules,false)) {
699             MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.MODIFY);
700             TermNode tn=new TermNode(mun);
701             GraphNode gn2=new GraphNode("UpdateMod"+removefromcount,tn);
702
703             boolean goodflag=true;
704             for(int i=0;i<possiblerules.size();i++) {
705                 Rule r=(Rule)possiblerules.get(i);
706                 UpdateNode un=new UpdateNode(r);
707                 
708                 int c=count[i];
709                 if (!processconjunction(un,r.getDNFGuardExpr().get(c),null)) {
710                     goodflag=false;break;
711                 }
712                 RelationInclusion ri=(RelationInclusion)r.getInclusion();
713                 if (!(ri.getLeftExpr() instanceof VarExpr)) {
714                     if (ri.getLeftExpr().isValue(ri.getRelation().getDomain().getType())) {
715                         Updates up=new Updates(ri.getLeftExpr(),leftindex,ri.getRelation().getDomain().getType());
716                         un.addUpdate(up);
717                     } else {
718                         if (inverted)
719                             goodflag=false;
720                         else un.addInvariant(ri.getLeftExpr());
721                     }
722                 } else {
723                     VarDescriptor vd=((VarExpr)ri.getLeftExpr()).getVar();
724                     if (vd.isGlobal()) {
725                         Updates up=new Updates(ri.getLeftExpr(),leftindex,null);
726                         un.addUpdate(up);
727                     } else if (inverted)
728                         goodflag=false;
729                 }
730                 if (!(ri.getRightExpr() instanceof VarExpr)) {
731                     if (ri.getRightExpr().isValue(ri.getRelation().getRange().getType())) {
732                         Updates up=new Updates(ri.getRightExpr(),rightindex,ri.getRelation().getRange().getType());
733                         un.addUpdate(up);
734                     } else {
735                         if (!inverted)
736                             goodflag=false;
737                         else
738                             un.addInvariant(ri.getLeftExpr());
739                     }
740                 } else {
741                     VarDescriptor vd=((VarExpr)ri.getRightExpr()).getVar();
742                     if (vd.isGlobal()) {
743                         Updates up=new Updates(ri.getRightExpr(),rightindex,null);
744                         un.addUpdate(up);
745                     } else if (!inverted) 
746                         goodflag=false;
747                 }
748                                 
749                 if (!un.checkupdates()) {
750                     goodflag=false;
751                     break;
752                 }
753                 mun.addUpdate(un);
754             }
755             if (goodflag) {
756                 GraphNode.Edge e=new GraphNode.Edge("abstract"+modifycount,gn2);
757                 modifycount++;
758                 gn.addEdge(e);
759                 updatenodes.add(gn2);
760             }
761             increment(count,possiblerules,false);
762         }
763     }
764
765     /** Generate concrete data structure update to add an object(or
766      * tuple) to a set (or relation). */
767
768     static int addtocount=0;
769     void generateaddtosetrelation(GraphNode gn, AbstractRepair ar) {
770         for(int i=0;i<state.vRules.size();i++) {
771             Rule r=(Rule) state.vRules.get(i);
772
773
774             /* See if this is a good rule*/
775             if ((r.getInclusion() instanceof SetInclusion&&
776                  ar.getDescriptor()==((SetInclusion)r.getInclusion()).getSet())||
777                 (r.getInclusion() instanceof RelationInclusion&&
778                  ar.getDescriptor()==((RelationInclusion)r.getInclusion()).getRelation())) {
779                 
780                 /* First solve for quantifiers */
781                 Vector bindings=new Vector();
782                 /* Construct bindings */
783
784                 Hashtable setmapping=new Hashtable();
785                 System.out.println("Attempting to construct bindings");
786
787                 if (!constructbindings(bindings,r,ar,setmapping,false))
788                     continue;
789                 System.out.println("Bindings constructed");
790                 //Generate add instruction
791                 DNFRule dnfrule=r.getDNFGuardExpr();
792                  endloop:
793                 for(int j=0;j<dnfrule.size();j++) {
794                     Inclusion inc=r.getInclusion();
795                     UpdateNode un=new UpdateNode(r);
796                     un.addBindings(bindings);
797                     /* Now build update for tuple/set inclusion condition */
798                     if(inc instanceof SetInclusion) {
799                         SetInclusion si=(SetInclusion)inc;
800                         Expr e=si.elementexpr;
801                         
802                         while(e instanceof CastExpr) {
803                             CastExpr ce=(CastExpr)e;
804                             if (ce.getType()!=si.getSet().getType())
805                                 continue endloop;
806                             e=ce.getExpr();
807                         }
808
809                         if (!(e instanceof VarExpr)) {
810                             if (e.isValue(si.getSet().getType())) {
811                                 Updates up=new Updates(e,0,si.getSet().getType());
812                                 un.addUpdate(up);
813                             } else {
814                                 /* We're an add to set*/
815                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
816                                 SetDescriptor set=sources.setSource(si.getSet())?
817                                     sources.getSourceSet(si.getSet()):null;
818                                 if (set==null)
819                                     continue;
820                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
821                                 if (rap==ArrayAnalysis.AccessPath.NONE)
822                                     continue;
823                                 if (!rap.equal(ap))
824                                     continue;
825                                 if (!constructarrayupdate(un, e, rap, 0))
826                                     continue;
827                             }
828                         } else {
829                             VarDescriptor vd=((VarExpr)e).getVar();
830                             if (vd.isGlobal()) {
831                                 Updates up=new Updates(e,0,null);
832                                 un.addUpdate(up);
833                             }
834                         }
835                     } else if (inc instanceof RelationInclusion) {
836                         RelationInclusion ri=(RelationInclusion)inc;
837
838                         Expr e=ri.getLeftExpr();
839                         
840                         while(e instanceof CastExpr) {
841                             CastExpr ce=(CastExpr)e;
842                             if (ce.getType()!=ri.getRelation().getDomain().getType())
843                                 continue endloop;
844                             e=ce.getExpr();
845                         }
846                         if (!(e instanceof VarExpr)) {
847                             if (e.isValue(ri.getRelation().getDomain().getType())) {
848                                 Updates up=new Updates(e,0,ri.getRelation().getDomain().getType());
849                                 if (ar.getDomainSet()!=null)
850                                     setmapping.put(e,ar.getDomainSet());
851                                 un.addUpdate(up);
852                             } else {
853                                 /* We don't handly relation modifies */
854                                 if (ar.getType()==AbstractRepair.MODIFYRELATION)
855                                     continue;
856                                 /* We're an add to relation*/
857                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
858                                 SetDescriptor set=sources.relsetSource(ri.getRelation(),true /* Domain*/)?
859                                     sources.relgetSourceSet(ri.getRelation(),true):null;
860                                 if (set==null)
861                                     continue;
862                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
863                                 if (rap==ArrayAnalysis.AccessPath.NONE||
864                                     !rap.equal(ap)||
865                                     !constructarrayupdate(un, e, rap, 0))
866                                     continue;
867                                 if (ar.getDomainSet()!=null)
868                                     setmapping.put(e,ar.getDomainSet());
869
870                             }
871                         } else {
872                             VarDescriptor vd=((VarExpr)e).getVar();
873                             if (vd.isGlobal()) {
874                                 Updates up=new Updates(e,0,null);
875                                 if (ar.getDomainSet()!=null)
876                                     setmapping.put(e,ar.getDomainSet());
877                                 un.addUpdate(up);
878                             }
879                         }
880                         
881                         e=ri.getRightExpr();
882                         
883                         while(e instanceof CastExpr) {
884                             CastExpr ce=(CastExpr)e;
885                             if (ce.getType()!=ri.getRelation().getRange().getType())
886                                 continue endloop;
887                             e=ce.getExpr();
888                         }
889                         if (!(e instanceof VarExpr)) {
890                             if (e.isValue(ri.getRelation().getRange().getType())) {
891                                 Updates up=new Updates(e,1,ri.getRelation().getRange().getType());
892                                 un.addUpdate(up);
893                             } else {
894                                 /* We don't handly relation modifies */
895                                 if (ar.getType()==AbstractRepair.MODIFYRELATION)
896                                     continue;
897                                 /* We're an add to relation*/
898                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
899                                 SetDescriptor set=sources.relsetSource(ri.getRelation(),false /* Range*/)?
900                                     sources.relgetSourceSet(ri.getRelation(),false):null;
901                                 if (set==null)
902                                     continue;
903                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
904                                 
905                                 if (rap==ArrayAnalysis.AccessPath.NONE||
906                                     !rap.equal(ap)||
907                                     !constructarrayupdate(un, e, rap, 1))
908                                     continue;
909                                 if (ar.getRangeSet()!=null)
910                                     setmapping.put(e,ar.getRangeSet());
911                             }
912                         } else {
913                             VarDescriptor vd=((VarExpr)e).getVar();
914                             if (vd.isGlobal()) {
915                                 Updates up=new Updates(e,1,null);
916                                 if (ar.getRangeSet()!=null)
917                                     setmapping.put(e,ar.getRangeSet());
918                                 un.addUpdate(up);
919                             }
920                         }
921                     }
922                     System.out.println("Built inclusion condition updates.");
923                     //Finally build necessary updates to satisfy conjunction
924                     RuleConjunction ruleconj=dnfrule.get(j);
925
926                     /* Add in updates for quantifiers */
927                     MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.ADD);
928                     TermNode tn=new TermNode(mun);
929                     GraphNode gn2=new GraphNode("UpdateAdd"+addtocount,tn);
930
931                     if (debugmsg("Start processing quantifiers")&&
932                         processquantifiers(gn2,un, r,setmapping)&&
933                         debugmsg("Finished processing quantifiers")&&
934                         processconjunction(un,ruleconj,setmapping)&&
935                         debugmsg("Finished processing conjunction")&&
936                         un.checkupdates()&&
937                         debugmsg("Updates checked")) {
938                         mun.addUpdate(un);
939                         GraphNode.Edge e=new GraphNode.Edge("abstract"+addtocount,gn2);
940                         addtocount++;
941                         gn.addEdge(e);
942                         updatenodes.add(gn2);
943                     }
944                 }
945             }
946         }
947     }
948
949     boolean debugmsg(String st) {
950         System.out.println(st);
951         return true;
952     }
953
954     boolean constructarrayupdate(UpdateNode un, Expr lexpr, ArrayAnalysis.AccessPath ap, int slotnumber) {
955         System.out.println("Constructing array update");
956         Expr e=null;
957         for (int i=ap.numFields()-1;i>=0;i--) {
958             if (e==null)
959                 e=lexpr;
960             else 
961                 e=((DotExpr)e).getExpr();
962
963             while (e instanceof CastExpr)
964                 e=((CastExpr)e).getExpr();
965
966             DotExpr de=(DotExpr)e;
967             FieldDescriptor fd=ap.getField(i);
968             if (fd instanceof ArrayDescriptor) {
969                 // We have an ArrayDescriptor!
970                 Expr index=de.getIndex();
971                 if (!index.isValue(null)) {/* Not assignable */
972                     System.out.println("ERROR:Index isn't assignable");
973                     return false;
974                 }
975                 Updates updates=new Updates(index,i,ap,lexpr,slotnumber);
976                 un.addUpdate(updates);
977             }
978         }
979         return true;
980     }
981
982     /** This method constructs bindings for an update using rule
983      * r. The boolean flag isremoval indicates that the update
984      * performs a removal.  The function returns true if it is able to
985      * generate a valid set of bindings and false otherwise. */
986
987     boolean constructbindings(Vector bindings, Rule r, AbstractRepair ar, Hashtable setmapping, boolean isremoval) {
988         boolean goodupdate=true;
989         Inclusion inc=r.getInclusion();
990
991         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
992             Quantifier q=(Quantifier)iterator.next();
993             if ((q instanceof SetQuantifier)||(q instanceof ForQuantifier)) {
994                 VarDescriptor vd=null;
995                 SetDescriptor set=null;
996                 if (q instanceof SetQuantifier) {
997                     vd=((SetQuantifier)q).getVar();
998                     set=((SetQuantifier)q).getSet();
999                 } else {
1000                     vd=((ForQuantifier)q).getVar();
1001                 }
1002                 if(inc instanceof SetInclusion) {
1003                     SetInclusion si=(SetInclusion)inc;
1004                     Expr tmpe=si.elementexpr;
1005                     Expr e=si.elementexpr;
1006
1007                     while(e instanceof CastExpr) {
1008                         CastExpr ce=(CastExpr)e;
1009                         if (ce.getType()!=si.getSet().getType())
1010                             return false;
1011                         e=ce.getExpr();
1012                     }
1013                     
1014                     if ((e instanceof VarExpr)&&
1015                         (((VarExpr)e).getVar()==vd)) {
1016                         /* Can solve for v */
1017                         if (!si.getSet().getType().isSubtypeOf(set.getType()))
1018                             return false;
1019                         Binding binding=new Binding(vd,0);
1020                         bindings.add(binding);
1021                     } else {
1022                         goodupdate=false;
1023                     }
1024                 } else if (inc instanceof RelationInclusion) {
1025                     RelationInclusion ri=(RelationInclusion)inc;
1026                     boolean f1=true;
1027                     boolean f2=true;
1028
1029                     Expr e=ri.getLeftExpr();
1030
1031                     while(e instanceof CastExpr) {
1032                         CastExpr ce=(CastExpr)e;
1033                         if (ce.getType()!=ri.getRelation().getDomain().getType())
1034                             return false;
1035                         e=ce.getExpr();
1036                     }
1037                     
1038                     if ((e instanceof VarExpr)&&
1039                         (((VarExpr)e).getVar()==vd)) {
1040                                 /* Can solve for v */
1041                         Binding binding=new Binding(vd,0);
1042                         if (!ri.getRelation().getDomain().getType().isSubtypeOf(set.getType()))
1043                             return false;
1044                         if (ar.getDomainSet()!=null)
1045                             setmapping.put(ri.getLeftExpr(),ar.getDomainSet());
1046                         bindings.add(binding);
1047                     } else f1=false;
1048
1049
1050                     e=ri.getRightExpr();
1051
1052                     while(e instanceof CastExpr) {
1053                         CastExpr ce=(CastExpr)e;
1054                         if (ce.getType()!=ri.getRelation().getRange().getType())
1055                             return false;
1056                         e=ce.getExpr();
1057                     }
1058                     
1059                     if ((e instanceof VarExpr)&&
1060                         (((VarExpr)e).getVar()==vd)) {
1061                                 /* Can solve for v */
1062                         Binding binding=new Binding(vd,1);
1063                         if (!ri.getRelation().getRange().getType().isSubtypeOf(set.getType()))
1064                             return false;
1065                         if (ar.getRangeSet()!=null)
1066                             setmapping.put(ri.getRightExpr(),ar.getRangeSet());
1067                         bindings.add(binding);
1068                     } else f2=false;
1069                     if (!(f1||f2))
1070                         goodupdate=false;
1071                 } else throw new Error("Inclusion not recognized");
1072                 if (!goodupdate)
1073                     if (isremoval) {
1074                         /* Removals don't need bindings anymore
1075                            Binding binding=new Binding(vd);
1076                            bindings.add(binding);*/
1077                         goodupdate=true;
1078                     } else if (q instanceof SetQuantifier) {
1079                         /* Create new element to bind to */
1080                         // search if the set 'set' has a size
1081                         Binding binding=new Binding(vd,set,exactsize.getsize(set)==1);
1082                         bindings.add(binding);
1083                         goodupdate=true;
1084
1085                     } else
1086                         goodupdate=false;
1087             } else if (q instanceof RelationQuantifier) {
1088                 RelationQuantifier rq=(RelationQuantifier)q;
1089                 for(int k=0;k<2;k++) {
1090                     VarDescriptor vd=(k==0)?rq.x:rq.y;
1091                     TypeDescriptor td=(k==0)?rq.getRelation().getDomain().getType():rq.getRelation().getRange().getType();
1092                     if(inc instanceof SetInclusion) {
1093                         SetInclusion si=(SetInclusion)inc;
1094
1095                         Expr e=si.elementexpr;
1096                         
1097                         while(e instanceof CastExpr) {
1098                             CastExpr ce=(CastExpr)e;
1099                             if (ce.getType()!=td)
1100                                 return false;
1101                             e=ce.getExpr();
1102                         }
1103
1104                         if ((e instanceof VarExpr)&&
1105                             (((VarExpr)e).getVar()==vd)) {
1106                             /* Can solve for v */
1107                             Binding binding=new Binding(vd,0);
1108
1109                             if (!si.getSet().getType().isSubtypeOf(td))
1110                                 return false;
1111                             bindings.add(binding);
1112                         } else
1113                             goodupdate=false;
1114                     } else if (inc instanceof RelationInclusion) {
1115                         RelationInclusion ri=(RelationInclusion)inc;
1116                         boolean f1=true;
1117                         boolean f2=true;
1118
1119
1120                         Expr e=ri.getLeftExpr();
1121                         
1122                         while(e instanceof CastExpr) {
1123                             CastExpr ce=(CastExpr)e;
1124                             if (ce.getType()!=ri.getRelation().getDomain().getType())
1125                                 return false;
1126                             e=ce.getExpr();
1127                         }
1128                         if ((ri.getLeftExpr() instanceof VarExpr)&&
1129                             (((VarExpr)ri.getLeftExpr()).getVar()==vd)) {
1130                             /* Can solve for v */
1131                             Binding binding=new Binding(vd,0);
1132                             if (!ri.getRelation().getDomain().getType().isSubtypeOf(td))
1133                                 return false;
1134                             if (ar.getDomainSet()!=null)
1135                                 setmapping.put(ri.getLeftExpr(),ar.getDomainSet());
1136                             bindings.add(binding);
1137                         } else f1=false;
1138
1139
1140                         e=ri.getRightExpr();
1141                         
1142                         while(e instanceof CastExpr) {
1143                             CastExpr ce=(CastExpr)e;
1144                             if (ce.getType()!=ri.getRelation().getRange().getType())
1145                                 return false;
1146                             e=ce.getExpr();
1147                         }
1148                         if ((ri.getRightExpr() instanceof VarExpr)&&
1149                             (((VarExpr)ri.getRightExpr()).getVar()==vd)) {
1150                             /* Can solve for v */
1151                             Binding binding=new Binding(vd,1);
1152                             if (!ri.getRelation().getRange().getType().isSubtypeOf(td))
1153                                 return false;
1154                             if (ar.getRangeSet()!=null)
1155                                 setmapping.put(ri.getRightExpr(),ar.getRangeSet());
1156                             bindings.add(binding);
1157                         } else f2=false;
1158                         if (!(f1||f2))
1159                             goodupdate=false;
1160                     } else throw new Error("Inclusion not recognized");
1161                     if (!goodupdate)
1162                         if (isremoval) {
1163                             /* Removals don't need bindings anymore
1164                                Binding binding=new Binding(vd);
1165                                bindings.add(binding);*/
1166                             goodupdate=true;
1167                         } else
1168                             break;
1169                 }
1170                 if (!goodupdate)
1171                     break;
1172             } else throw new Error("Quantifier not recognized");
1173         }
1174         return goodupdate;
1175     }
1176     
1177     /** Adds updates that add an item to the appropriate set or
1178      * relation quantified over by the model definition rule.. */
1179     
1180     boolean processquantifiers(GraphNode gn,UpdateNode un, Rule r,Hashtable setmapping) {
1181         Inclusion inc=r.getInclusion();
1182         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
1183             Quantifier q=(Quantifier)iterator.next();
1184             /* Add quantifier */
1185             if (q instanceof RelationQuantifier) {
1186                 RelationQuantifier rq=(RelationQuantifier)q;
1187                 TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
1188                 toe.td=ReservedTypeDescriptor.INT;
1189                 Updates u=new Updates(toe,false);
1190                 un.addUpdate(u);
1191                 if (abstractadd.containsKey(rq.relation)) {
1192                     GraphNode agn=(GraphNode)abstractadd.get(rq.relation);
1193                     GraphNode.Edge e=new GraphNode.Edge("requires",agn);
1194                     gn.addEdge(e);
1195                 } else {
1196                     return false;
1197                 }
1198             } else if (q instanceof SetQuantifier) {
1199                 SetQuantifier sq=(SetQuantifier)q;
1200                 if (un.getBinding(sq.var).getType()==Binding.SEARCH) {
1201                     Binding b=un.getBinding(sq.var);
1202                     Constraint reqc=exactsize.getConstraint(b.getSet());
1203                     constraintdependence.requiresConstraint(gn,reqc);
1204                     continue; /* Don't need to ensure addition for search */
1205                 }
1206                 VarExpr ve=new VarExpr(sq.var);
1207                 SetDescriptor sd=findExpr(setmapping, ve);
1208                 if (sd!=null&&sd.isSubset(sq.set))
1209                     continue; /* this update is trivially true */
1210
1211                 ElementOfExpr eoe=new ElementOfExpr(ve,sq.set);
1212                 eoe.td=ReservedTypeDescriptor.INT;
1213                 Updates u=new Updates(eoe,false);
1214                 un.addUpdate(u);
1215                 if (abstractadd.containsKey(sq.set)) {
1216                     GraphNode agn=(GraphNode)abstractadd.get(sq.set);
1217                     GraphNode.Edge e=new GraphNode.Edge("requires",agn);
1218                     gn.addEdge(e);
1219                 } else {
1220                     return false;
1221                 }
1222             } else return false;
1223         }
1224         return true;
1225     }
1226
1227     static SetDescriptor findExpr(Hashtable setmapping, Expr e) {
1228         if (setmapping==null)
1229             return null;
1230         Set kset=setmapping.keySet();
1231         for(Iterator it=kset.iterator();it.hasNext();) {
1232             Expr expr=(Expr)it.next();
1233             if (expr.equals(null,e)) {
1234                 return (SetDescriptor)setmapping.get(expr);
1235             }
1236         }
1237         return null;
1238     }
1239
1240     /** This method generates the necessary updates to satisfy the
1241      * conjunction ruleconj. */
1242
1243     boolean  processconjunction(UpdateNode un,RuleConjunction ruleconj,Hashtable setmapping) {
1244         boolean okay=true;
1245         for(int k=0;k<ruleconj.size();k++) {
1246             DNFExpr de=ruleconj.get(k);
1247             Expr e=de.getExpr();
1248             if (e instanceof OpExpr) {
1249                 OpExpr ex=(OpExpr)de.getExpr();
1250                 Opcode op=ex.getOpcode();
1251                 Updates up=new Updates(ex.left,ex.right,op, de.getNegation());
1252                 un.addUpdate(up);
1253             } else if (e instanceof ElementOfExpr) {
1254                 SetDescriptor sd=findExpr(setmapping, ((ElementOfExpr)e).element);
1255                 if (sd!=null&&sd.isSubset(((ElementOfExpr)e).set))
1256                     continue; /* this update is trivially true */
1257                 Updates up=new Updates(e,de.getNegation());
1258                 un.addUpdate(up);
1259             } else if (e instanceof TupleOfExpr) {
1260                 Updates up=new Updates(e,de.getNegation());
1261                 un.addUpdate(up);
1262             } else if (e instanceof BooleanLiteralExpr) { 
1263                 boolean truth=((BooleanLiteralExpr)e).getValue();
1264                 if (de.getNegation())
1265                     truth=!truth;
1266                 if (!truth) {
1267                     okay=false;
1268                     break;
1269                 }
1270             } else {
1271                 System.out.println(e.getClass().getName());
1272                 throw new Error("Unrecognized Expr");
1273             }
1274         }
1275         return okay;
1276     }
1277
1278     /** This method sees if when the quantifiers listed in set are
1279      *  fixed, whether there can be more than one unique binding for
1280      *  the constraint or model definition rule qs.*/
1281     public boolean analyzeQuantifiers(Quantifiers qs,Set set) {
1282         for(int i=0;i<qs.numQuantifiers();i++) {
1283             Quantifier q=qs.getQuantifier(i);
1284             if (set.contains(q))
1285                 continue;
1286             if (q instanceof SetQuantifier) {
1287                 SetDescriptor sd=((SetQuantifier)q).getSet();
1288                 if (maxsize.getsize(sd)<=1&&
1289                     maxsize.getsize(sd)>=0)
1290                     continue;
1291             } else if (q instanceof RelationQuantifier) {
1292                 RelationDescriptor rd=((RelationQuantifier)q).getRelation();
1293                 if (maxsize.getsize(rd)<=1&&
1294                     maxsize.getsize(rd)>=0)
1295                     continue;
1296             }
1297             return false;
1298         }
1299         return true;
1300     }
1301
1302     public boolean mutuallyexclusive(SetDescriptor sd1, SetDescriptor sd2) {
1303         if (mutualexclusive(sd1,sd2)||
1304             mutualexclusive(sd2,sd1))
1305             return true;
1306         else
1307             return false;
1308     }
1309
1310     private boolean mutualexclusive(SetDescriptor sd1, SetDescriptor sd2) {
1311         Vector rules=state.vRules;
1312         for(int i=0;i<rules.size();i++) {
1313             Rule r=(Rule)rules.get(i);
1314             if (r.getInclusion().getTargetDescriptors().contains(sd1)) {
1315                 /* Rule may add items to sd1 */
1316                 SetInclusion si=(SetInclusion)r.getInclusion();
1317                 Expr ve=si.getExpr();
1318                 DNFRule drule=r.getDNFGuardExpr();
1319                 for(int j=0;j<drule.size();j++) {
1320                     RuleConjunction rconj=drule.get(j);
1321                     boolean containsexclusion=false;
1322                     for (int k=0;k<rconj.size();k++) {
1323                         DNFExpr dexpr=rconj.get(k);
1324                         if (dexpr.getNegation()&&
1325                             dexpr.getExpr() instanceof ElementOfExpr&&
1326                             ((ElementOfExpr)dexpr.getExpr()).element.equals(null,ve)) {
1327                             SetDescriptor sd=((ElementOfExpr)dexpr.getExpr()).set;
1328                             if (sd.isSubset(sd2))
1329                                 containsexclusion=true;
1330                         }
1331                     }
1332                     if (!containsexclusion)
1333                         return false;
1334                 }
1335             }
1336         }
1337         return true;
1338     }
1339 }