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