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