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