2 bug fixes to getRequiredConstraints
[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(state)) /* 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(state)) {
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(state)) {
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                         if (!(e instanceof VarExpr)) {
918                             if (e.isValue(si.getSet().getType())) {
919                                 Updates up=new Updates(e,0,si.getSet().getType());
920                                 un.addUpdate(up);
921                             } else {
922                                 /* We're an add to set*/
923                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
924                                 SetDescriptor set=sources.setSource(si.getSet())?
925                                     sources.getSourceSet(si.getSet()):null;
926                                 if (set==null)
927                                     continue;
928                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
929                                 if (rap==ArrayAnalysis.AccessPath.NONE)
930                                     continue;
931                                 if (!rap.equal(ap))
932                                     continue;
933                                 if (!constructarrayupdate(un, e, rap, 0))
934                                     continue;
935                             }
936                         } else {
937                             VarDescriptor vd=((VarExpr)e).getVar();
938                             if (vd.isGlobal()) {
939                                 Updates up=new Updates(e,0,null);
940                                 un.addUpdate(up);
941                             }
942                         }
943                     } else if (inc instanceof RelationInclusion) {
944                         RelationInclusion ri=(RelationInclusion)inc;
945
946                         Expr e=ri.getLeftExpr();
947
948                         while(e instanceof CastExpr) {
949                             CastExpr ce=(CastExpr)e;
950                             if (ce.getType()!=ri.getRelation().getDomain().getType())
951                                 continue endloop;
952                             e=ce.getExpr();
953                         }
954                         if (!(e instanceof VarExpr)) {
955                             if (e.isValue(ri.getRelation().getDomain().getType())) {
956                                 Updates up=new Updates(e,0,ri.getRelation().getDomain().getType());
957                                 if (ar.getDomainSet()!=null)
958                                     setmapping.put(e,ar.getDomainSet());
959                                 un.addUpdate(up);
960                             } else {
961                                 /* We don't handly relation modifies */
962                                 if (ar.getType()==AbstractRepair.MODIFYRELATION)
963                                     continue;
964                                 /* We're an add to relation*/
965                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
966                                 SetDescriptor set=sources.relsetSource(ri.getRelation(),true /* Domain*/)?
967                                     sources.relgetSourceSet(ri.getRelation(),true):null;
968                                 if (set==null)
969                                     continue;
970                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
971                                 if (rap==ArrayAnalysis.AccessPath.NONE||
972                                     !rap.equal(ap)||
973                                     !constructarrayupdate(un, e, rap, 0))
974                                     continue;
975                                 if (ar.getDomainSet()!=null)
976                                     setmapping.put(e,ar.getDomainSet());
977
978                             }
979                         } else {
980                             VarDescriptor vd=((VarExpr)e).getVar();
981                             if (vd.isGlobal()) {
982                                 Updates up=new Updates(e,0,null);
983                                 if (ar.getDomainSet()!=null)
984                                     setmapping.put(e,ar.getDomainSet());
985                                 un.addUpdate(up);
986                             }
987                         }
988
989                         e=ri.getRightExpr();
990
991                         while(e instanceof CastExpr) {
992                             CastExpr ce=(CastExpr)e;
993                             if (ce.getType()!=ri.getRelation().getRange().getType())
994                                 continue endloop;
995                             e=ce.getExpr();
996                         }
997                         if (!(e instanceof VarExpr)) {
998                             if (e.isValue(ri.getRelation().getRange().getType())) {
999                                 Updates up=new Updates(e,1,ri.getRelation().getRange().getType());
1000                                 un.addUpdate(up);
1001                             } else {
1002                                 /* We don't handly relation modifies */
1003                                 if (ar.getType()==AbstractRepair.MODIFYRELATION)
1004                                     continue;
1005                                 /* We're an add to relation*/
1006                                 ArrayAnalysis.AccessPath rap=arrayanalysis.analyzeExpr(r,e);
1007                                 SetDescriptor set=sources.relsetSource(ri.getRelation(),false /* Range*/)?
1008                                     sources.relgetSourceSet(ri.getRelation(),false):null;
1009                                 if (set==null)
1010                                     continue;
1011                                 ArrayAnalysis.AccessPath ap=arrayanalysis.getSet(set);
1012
1013                                 if (rap==ArrayAnalysis.AccessPath.NONE||
1014                                     !rap.equal(ap)||
1015                                     !constructarrayupdate(un, e, rap, 1))
1016                                     continue;
1017                                 if (ar.getRangeSet()!=null)
1018                                     setmapping.put(e,ar.getRangeSet());
1019                             }
1020                         } else {
1021                             VarDescriptor vd=((VarExpr)e).getVar();
1022                             if (vd.isGlobal()) {
1023                                 Updates up=new Updates(e,1,null);
1024                                 if (ar.getRangeSet()!=null)
1025                                     setmapping.put(e,ar.getRangeSet());
1026                                 un.addUpdate(up);
1027                             }
1028                         }
1029                     }
1030                     System.out.println("Built inclusion condition updates.");
1031                     //Finally build necessary updates to satisfy conjunction
1032                     RuleConjunction ruleconj=dnfrule.get(j);
1033
1034                     /* Add in updates for quantifiers */
1035                     MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.ADD);
1036                     TermNode tn=new TermNode(mun);
1037                     GraphNode gn2=new GraphNode("UpdateAdd"+addtocount,tn);
1038                     gn2.setOption(updateoption);
1039
1040                     if (debugmsg("Start processing quantifiers")&&
1041                         processquantifiers(gn2,un, r,setmapping)&&
1042                         debugmsg("Finished processing quantifiers")&&
1043                         processconjunction(un,ruleconj,setmapping)&&
1044                         debugmsg("Finished processing conjunction")&&
1045                         un.checkupdates(state)&&
1046                         debugmsg("Updates checked")) {
1047                         mun.addUpdate(un);
1048                         GraphNode.Edge e=new GraphNode.Edge("abstract5"+addtocount,gn2);
1049                         addtocount++;
1050                         gn.addEdge(e);
1051                         updatenodes.add(gn2);
1052                     }
1053                 }
1054             }
1055         }
1056     }
1057
1058     boolean debugmsg(String st) {
1059         System.out.println(st);
1060         return true;
1061     }
1062
1063     boolean constructarrayupdate(UpdateNode un, Expr lexpr, ArrayAnalysis.AccessPath ap, int slotnumber) {
1064         System.out.println("Constructing array update");
1065         Expr e=null;
1066         for (int i=ap.numFields()-1;i>=0;i--) {
1067             if (e==null)
1068                 e=lexpr;
1069             else
1070                 e=((DotExpr)e).getExpr();
1071
1072             while (e instanceof CastExpr)
1073                 e=((CastExpr)e).getExpr();
1074
1075             DotExpr de=(DotExpr)e;
1076             FieldDescriptor fd=ap.getField(i);
1077             if (fd instanceof ArrayDescriptor) {
1078                 // We have an ArrayDescriptor!
1079                 Expr index=de.getIndex();
1080                 if (!index.isValue(null)) {/* Not assignable */
1081                     System.out.println("ERROR:Index isn't assignable");
1082                     return false;
1083                 }
1084                 Updates updates=new Updates(index,i,ap,lexpr,slotnumber);
1085                 un.addUpdate(updates);
1086             }
1087         }
1088         return true;
1089     }
1090
1091     /** This method constructs bindings for an update using rule
1092      * r. The boolean flag isremoval indicates that the update
1093      * performs a removal.  The function returns true if it is able to
1094      * generate a valid set of bindings and false otherwise. */
1095
1096     boolean constructbindings(Vector bindings, Rule r, AbstractRepair ar, Hashtable setmapping, boolean isremoval) {
1097         boolean goodupdate=true;
1098         Inclusion inc=r.getInclusion();
1099
1100         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
1101             Quantifier q=(Quantifier)iterator.next();
1102             if ((q instanceof SetQuantifier)||(q instanceof ForQuantifier)) {
1103                 VarDescriptor vd=null;
1104                 SetDescriptor set=null;
1105                 if (q instanceof SetQuantifier) {
1106                     vd=((SetQuantifier)q).getVar();
1107                     set=((SetQuantifier)q).getSet();
1108                 } else {
1109                     vd=((ForQuantifier)q).getVar();
1110                 }
1111                 if(inc instanceof SetInclusion) {
1112                     SetInclusion si=(SetInclusion)inc;
1113                     Expr tmpe=si.elementexpr;
1114                     Expr e=si.elementexpr;
1115
1116                     while(e instanceof CastExpr) {
1117                         CastExpr ce=(CastExpr)e;
1118                         if (ce.getType()!=si.getSet().getType())
1119                             return false;
1120                         e=ce.getExpr();
1121                     }
1122
1123                     if ((e instanceof VarExpr)&&
1124                         (((VarExpr)e).getVar()==vd)) {
1125                         /* Can solve for v */
1126                         if (set==null||!si.getSet().getType().isSubtypeOf(set.getType()))
1127                             return false;
1128                         Binding binding=new Binding(vd,0);
1129                         bindings.add(binding);
1130                     } else {
1131                         goodupdate=false;
1132                     }
1133                 } else if (inc instanceof RelationInclusion) {
1134                     RelationInclusion ri=(RelationInclusion)inc;
1135                     boolean f1=true;
1136                     boolean f2=true;
1137
1138                     Expr e=ri.getLeftExpr();
1139
1140                     while(e instanceof CastExpr) {
1141                         CastExpr ce=(CastExpr)e;
1142                         if (ce.getType()!=ri.getRelation().getDomain().getType())
1143                             return false;
1144                         e=ce.getExpr();
1145                     }
1146
1147                     if ((e instanceof VarExpr)&&
1148                         (((VarExpr)e).getVar()==vd)) {
1149                                 /* Can solve for v */
1150                         Binding binding=new Binding(vd,0);
1151                         if (!ri.getRelation().getDomain().getType().isSubtypeOf(set.getType()))
1152                             return false;
1153                         if (ar.getDomainSet()!=null)
1154                             setmapping.put(ri.getLeftExpr(),ar.getDomainSet());
1155                         bindings.add(binding);
1156                     } else f1=false;
1157
1158
1159                     e=ri.getRightExpr();
1160
1161                     while(e instanceof CastExpr) {
1162                         CastExpr ce=(CastExpr)e;
1163                         if (ce.getType()!=ri.getRelation().getRange().getType())
1164                             return false;
1165                         e=ce.getExpr();
1166                     }
1167
1168                     if ((e instanceof VarExpr)&&
1169                         (((VarExpr)e).getVar()==vd)) {
1170                                 /* Can solve for v */
1171                         Binding binding=new Binding(vd,1);
1172                         if (!ri.getRelation().getRange().getType().isSubtypeOf(set.getType()))
1173                             return false;
1174                         if (ar.getRangeSet()!=null)
1175                             setmapping.put(ri.getRightExpr(),ar.getRangeSet());
1176                         bindings.add(binding);
1177                     } else f2=false;
1178                     if (!(f1||f2))
1179                         goodupdate=false;
1180                 } else throw new Error("Inclusion not recognized");
1181                 if (!goodupdate)
1182                     if (isremoval) {
1183                         /* Removals don't need bindings anymore
1184                            Binding binding=new Binding(vd);
1185                            bindings.add(binding);*/
1186                         goodupdate=true;
1187                     } else if (q instanceof SetQuantifier) {
1188                         /* Create new element to bind to */
1189                         // search if the set 'set' has a size
1190                         Binding binding=new Binding(vd,set,exactsize.getsize(set)==1);
1191                         bindings.add(binding);
1192                         goodupdate=true;
1193
1194                     } else
1195                         goodupdate=false;
1196             } else if (q instanceof RelationQuantifier) {
1197                 RelationQuantifier rq=(RelationQuantifier)q;
1198                 for(int k=0;k<2;k++) {
1199                     VarDescriptor vd=(k==0)?rq.x:rq.y;
1200                     TypeDescriptor td=(k==0)?rq.getRelation().getDomain().getType():rq.getRelation().getRange().getType();
1201                     if(inc instanceof SetInclusion) {
1202                         SetInclusion si=(SetInclusion)inc;
1203
1204                         Expr e=si.elementexpr;
1205
1206                         while(e instanceof CastExpr) {
1207                             CastExpr ce=(CastExpr)e;
1208                             if (ce.getType()!=td)
1209                                 return false;
1210                             e=ce.getExpr();
1211                         }
1212
1213                         if ((e instanceof VarExpr)&&
1214                             (((VarExpr)e).getVar()==vd)) {
1215                             /* Can solve for v */
1216                             Binding binding=new Binding(vd,0);
1217
1218                             if (!si.getSet().getType().isSubtypeOf(td))
1219                                 return false;
1220                             bindings.add(binding);
1221                         } else
1222                             goodupdate=false;
1223                     } else if (inc instanceof RelationInclusion) {
1224                         RelationInclusion ri=(RelationInclusion)inc;
1225                         boolean f1=true;
1226                         boolean f2=true;
1227
1228
1229                         Expr e=ri.getLeftExpr();
1230
1231                         while(e instanceof CastExpr) {
1232                             CastExpr ce=(CastExpr)e;
1233                             if (ce.getType()!=ri.getRelation().getDomain().getType())
1234                                 return false;
1235                             e=ce.getExpr();
1236                         }
1237                         if ((ri.getLeftExpr() instanceof VarExpr)&&
1238                             (((VarExpr)ri.getLeftExpr()).getVar()==vd)) {
1239                             /* Can solve for v */
1240                             Binding binding=new Binding(vd,0);
1241                             if (!ri.getRelation().getDomain().getType().isSubtypeOf(td))
1242                                 return false;
1243                             if (ar.getDomainSet()!=null)
1244                                 setmapping.put(ri.getLeftExpr(),ar.getDomainSet());
1245                             bindings.add(binding);
1246                         } else f1=false;
1247
1248
1249                         e=ri.getRightExpr();
1250
1251                         while(e instanceof CastExpr) {
1252                             CastExpr ce=(CastExpr)e;
1253                             if (ce.getType()!=ri.getRelation().getRange().getType())
1254                                 return false;
1255                             e=ce.getExpr();
1256                         }
1257                         if ((ri.getRightExpr() instanceof VarExpr)&&
1258                             (((VarExpr)ri.getRightExpr()).getVar()==vd)) {
1259                             /* Can solve for v */
1260                             Binding binding=new Binding(vd,1);
1261                             if (!ri.getRelation().getRange().getType().isSubtypeOf(td))
1262                                 return false;
1263                             if (ar.getRangeSet()!=null)
1264                                 setmapping.put(ri.getRightExpr(),ar.getRangeSet());
1265                             bindings.add(binding);
1266                         } else f2=false;
1267                         if (!(f1||f2))
1268                             goodupdate=false;
1269                     } else throw new Error("Inclusion not recognized");
1270                     if (!goodupdate)
1271                         if (isremoval) {
1272                             /* Removals don't need bindings anymore
1273                                Binding binding=new Binding(vd);
1274                                bindings.add(binding);*/
1275                             goodupdate=true;
1276                         } else
1277                             break;
1278                 }
1279                 if (!goodupdate)
1280                     break;
1281             } else throw new Error("Quantifier not recognized");
1282         }
1283         return goodupdate;
1284     }
1285
1286     /** Adds updates that add an item to the appropriate set or
1287      * relation quantified over by the model definition rule.. */
1288
1289     boolean processquantifiers(GraphNode gn,UpdateNode un, Rule r,Hashtable setmapping) {
1290         Inclusion inc=r.getInclusion();
1291         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
1292             Quantifier q=(Quantifier)iterator.next();
1293             /* Add quantifier */
1294             if (q instanceof RelationQuantifier) {
1295                 RelationQuantifier rq=(RelationQuantifier)q;
1296                 TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
1297                 toe.td=ReservedTypeDescriptor.INT;
1298                 Updates u=new Updates(toe,false);
1299                 un.addUpdate(u);
1300                 if (abstractadd.containsKey(rq.relation)) {
1301                     GraphNode agn=(GraphNode)abstractadd.get(rq.relation);
1302                     GraphNode.Edge e=new GraphNode.Edge("requiresadd5",agn);
1303                     gn.addEdge(e);
1304                 } else {
1305                     return false;
1306                 }
1307             } else if (q instanceof SetQuantifier) {
1308                 SetQuantifier sq=(SetQuantifier)q;
1309                 if (un.getBinding(sq.var).getType()==Binding.SEARCH) {
1310                     Binding b=un.getBinding(sq.var);
1311                     Constraint reqc=exactsize.getConstraint(b.getSet());
1312                     constraintdependence.requiresConstraint(gn,reqc);
1313                     continue; /* Don't need to ensure addition for search */
1314                 }
1315                 VarExpr ve=new VarExpr(sq.var);
1316                 SetDescriptor sd=findExpr(setmapping, ve);
1317                 if (sd!=null&&sd.isSubset(sq.set))
1318                     continue; /* this update is trivially true */
1319
1320                 ElementOfExpr eoe=new ElementOfExpr(ve,sq.set);
1321                 eoe.td=ReservedTypeDescriptor.INT;
1322                 Updates u=new Updates(eoe,false);
1323                 un.addUpdate(u);
1324                 if (abstractadd.containsKey(sq.set)) {
1325                     GraphNode agn=(GraphNode)abstractadd.get(sq.set);
1326                     GraphNode.Edge e=new GraphNode.Edge("requiresadd6",agn);
1327                     gn.addEdge(e);
1328                 } else {
1329                     return false;
1330                 }
1331             } else return false;
1332         }
1333         return true;
1334     }
1335
1336     static SetDescriptor findExpr(Hashtable setmapping, Expr e) {
1337         if (setmapping==null)
1338             return null;
1339         Set kset=setmapping.keySet();
1340         for(Iterator it=kset.iterator();it.hasNext();) {
1341             Expr expr=(Expr)it.next();
1342             if (expr.equals(null,e)) {
1343                 return (SetDescriptor)setmapping.get(expr);
1344             }
1345         }
1346         return null;
1347     }
1348
1349     /** This method generates the necessary updates to satisfy the
1350      * conjunction ruleconj. */
1351
1352     boolean  processconjunction(UpdateNode un,RuleConjunction ruleconj,Hashtable setmapping) {
1353         boolean okay=true;
1354         for(int k=0;k<ruleconj.size();k++) {
1355             DNFExpr de=ruleconj.get(k);
1356             Expr e=de.getExpr();
1357             if (e instanceof OpExpr) {
1358                 OpExpr ex=(OpExpr)de.getExpr();
1359                 Opcode op=ex.getOpcode();
1360                 Updates up=new Updates(ex.left,ex.right,op, de.getNegation());
1361                 un.addUpdate(up);
1362             } else if (e instanceof ElementOfExpr) {
1363                 SetDescriptor sd=findExpr(setmapping, ((ElementOfExpr)e).element);
1364                 if (sd!=null&&sd.isSubset(((ElementOfExpr)e).set))
1365                     continue; /* this update is trivially true */
1366                 Updates up=new Updates(e,de.getNegation());
1367                 un.addUpdate(up);
1368             } else if (e instanceof TupleOfExpr) {
1369                 Updates up=new Updates(e,de.getNegation());
1370                 un.addUpdate(up);
1371             } else if (e instanceof BooleanLiteralExpr) {
1372                 boolean truth=((BooleanLiteralExpr)e).getValue();
1373                 if (de.getNegation())
1374                     truth=!truth;
1375                 if (!truth) {
1376                     okay=false;
1377                     break;
1378                 }
1379             } else {
1380                 System.out.println(e.getClass().getName());
1381                 throw new Error("Unrecognized Expr");
1382             }
1383         }
1384         return okay;
1385     }
1386
1387     /** This method sees if when the quantifiers listed in set are
1388      *  fixed, whether there can be more than one unique binding for
1389      *  the constraint or model definition rule qs.*/
1390     public boolean analyzeQuantifiers(Quantifiers qs,Set set) {
1391         for(int i=0;i<qs.numQuantifiers();i++) {
1392             Quantifier q=qs.getQuantifier(i);
1393             if (set.contains(q))
1394                 continue;
1395             if (q instanceof SetQuantifier) {
1396                 SetDescriptor sd=((SetQuantifier)q).getSet();
1397                 if (maxsize.getsize(sd)<=1&&
1398                     maxsize.getsize(sd)>=0)
1399                     continue;
1400             } else if (q instanceof RelationQuantifier) {
1401                 RelationDescriptor rd=((RelationQuantifier)q).getRelation();
1402                 if (maxsize.getsize(rd)<=1&&
1403                     maxsize.getsize(rd)>=0)
1404                     continue;
1405             }
1406             return false;
1407         }
1408         return true;
1409     }
1410
1411     public boolean mutuallyexclusive(SetDescriptor sd1, SetDescriptor sd2) {
1412         if (mutualexclusive(sd1,sd2)||
1413             mutualexclusive(sd2,sd1))
1414             return true;
1415         else
1416             return false;
1417     }
1418
1419     private boolean mutualexclusive(SetDescriptor sd1, SetDescriptor sd2) {
1420         Vector rules=state.vRules;
1421         for(int i=0;i<rules.size();i++) {
1422             Rule r=(Rule)rules.get(i);
1423             if (r.getInclusion().getTargetDescriptors().contains(sd1)) {
1424                 /* Rule may add items to sd1 */
1425                 SetInclusion si=(SetInclusion)r.getInclusion();
1426                 Expr ve=si.getExpr();
1427                 DNFRule drule=r.getDNFGuardExpr();
1428                 for(int j=0;j<drule.size();j++) {
1429                     RuleConjunction rconj=drule.get(j);
1430                     boolean containsexclusion=false;
1431                     for (int k=0;k<rconj.size();k++) {
1432                         DNFExpr dexpr=rconj.get(k);
1433                         if (dexpr.getNegation()&&
1434                             dexpr.getExpr() instanceof ElementOfExpr&&
1435                             ((ElementOfExpr)dexpr.getExpr()).element.equals(null,ve)) {
1436                             SetDescriptor sd=((ElementOfExpr)dexpr.getExpr()).set;
1437                             if (sd.isSubset(sd2))
1438                                 containsexclusion=true;
1439                         }
1440                     }
1441                     if (!containsexclusion)
1442                         return false;
1443                 }
1444             }
1445         }
1446         return true;
1447     }
1448
1449     boolean equivalent(SetExpr se, RelationExpr re) {
1450         if (!(se instanceof ImageSetExpr))
1451             return false;
1452         ImageSetExpr ise=(ImageSetExpr)se;
1453         while(re!=null&&ise!=null) {
1454             if (re.getRelation()!=ise.getRelation())
1455                 return false;
1456             if (re.inverted()!=ise.inverted())
1457                 return false;
1458             if (ise.isimageset) {
1459                 ise=ise.getImageSetExpr();
1460                 if (!(re.getExpr() instanceof RelationExpr))
1461                     return false;
1462                 re=(RelationExpr)re.getExpr();
1463             } else {
1464                 if (!(re.getExpr() instanceof VarExpr))
1465                     return false;
1466                 if (((VarExpr)re.getExpr()).getVar()==ise.getVar())
1467                     return true; //everything matches
1468                 return false;
1469             }
1470         }
1471         return false;
1472     }
1473 }