Added Strongly Connected Component support into GraphNodes.
[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
6 public class Termination {
7     HashSet conjunctions;
8     Hashtable conjunctionmap;
9
10     HashSet abstractrepair;
11     HashSet updatenodes;
12     HashSet consequencenodes;
13
14     HashSet scopenodes;
15     Hashtable scopesatisfy;
16     Hashtable scopefalsify;
17     Hashtable consequence;
18     Hashtable abstractadd;
19     Hashtable abstractremove;
20     Hashtable conjtonodemap;
21     Set removedset;
22
23     State state;
24
25     public Termination(State state) {
26         this.state=state;
27         conjunctions=new HashSet();
28         conjunctionmap=new Hashtable();
29         abstractrepair=new HashSet();
30         scopenodes=new HashSet();
31         scopesatisfy=new Hashtable();
32         scopefalsify=new Hashtable();
33         consequence=new Hashtable();
34         updatenodes=new HashSet();
35         consequencenodes=new HashSet();
36         abstractadd=new Hashtable();
37         abstractremove=new Hashtable();
38         conjtonodemap=new Hashtable();
39
40         generateconjunctionnodes();
41         generatescopenodes();
42         generaterepairnodes();
43         generatedatastructureupdatenodes();
44         generatecompensationnodes();
45
46         generateabstractedges();
47         generatescopeedges();
48         generateupdateedges();
49
50         HashSet superset=new HashSet();
51         superset.addAll(conjunctions);
52         HashSet closureset=new HashSet();
53         //      closureset.addAll(updatenodes);
54         //superset.addAll(abstractrepair);
55         //superset.addAll(updatenodes);
56         //superset.addAll(scopenodes);
57         //superset.addAll(consequencenodes);
58         GraphNode.computeclosure(superset,closureset);
59         try {
60             GraphNode.DOTVisitor.visit(new FileOutputStream("graph.dot"),superset);
61         } catch (Exception e) {
62             e.printStackTrace();
63             System.exit(-1);
64         }
65         for(Iterator it=updatenodes.iterator();it.hasNext();) {
66             GraphNode gn=(GraphNode)it.next();
67             TermNode tn=(TermNode)gn.getOwner();
68             MultUpdateNode mun=tn.getUpdate();
69             System.out.println(gn.getTextLabel());
70             System.out.println(mun.toString());
71         }
72         GraphAnalysis ga=new GraphAnalysis(this);
73         removedset=ga.doAnalysis();
74         if (removedset==null) {
75             System.out.println("Can't generate terminating repair algorithm!");
76             System.exit(-1);
77         }
78         System.out.println("Removing:");
79         for(Iterator it=removedset.iterator();it.hasNext();) {
80             GraphNode gn=(GraphNode)it.next();
81             System.out.println(gn.getTextLabel());
82         }
83
84         superset=new HashSet();
85         superset.addAll(conjunctions);
86         superset.removeAll(removedset);
87         GraphNode.computeclosure(superset,removedset);
88         try {
89             GraphNode.DOTVisitor.visit(new FileOutputStream("graphfinal.dot"),superset);
90         } catch (Exception e) {
91             e.printStackTrace();
92             System.exit(-1);
93         }
94
95     }
96     
97     void generateconjunctionnodes() {
98         Vector constraints=state.vConstraints;
99         for(int i=0;i<constraints.size();i++) {
100             Constraint c=(Constraint)constraints.get(i);
101             DNFConstraint dnf=c.dnfconstraint;
102             for(int j=0;j<dnf.size();j++) {
103                 TermNode tn=new TermNode(c,dnf.get(j));
104                 GraphNode gn=new GraphNode("Conj"+i+"A"+j,
105                                            "Conj ("+i+","+j+") "+dnf.get(j).name()
106                                            ,tn);
107                 conjunctions.add(gn);
108                 if (!conjunctionmap.containsKey(c))
109                     conjunctionmap.put(c,new HashSet());
110                 ((Set)conjunctionmap.get(c)).add(gn);
111                 conjtonodemap.put(dnf.get(j),gn);
112             }
113             for(int j=0;j<c.numQuantifiers();j++) {
114                 Quantifier q=c.getQuantifier(j);
115                 if (q instanceof SetQuantifier) {
116                     SetQuantifier sq=(SetQuantifier)q;
117                     VarExpr ve=new VarExpr(sq.getVar());
118                     InclusionPredicate ip=new InclusionPredicate(ve,new SetExpr(sq.getSet()));
119                     DNFConstraint dconst=new DNFConstraint(ip);
120                     dconst=dconst.not();
121                     TermNode tn=new TermNode(c,dconst.get(0));
122                     GraphNode gn=new GraphNode("Conj"+i+"AQ"+j,
123                                                "Conj ("+i+","+j+") "+dconst.get(0).name()
124                                                ,tn);
125                     conjunctions.add(gn);
126                     if (!conjunctionmap.containsKey(c))
127                         conjunctionmap.put(c,new HashSet());
128                     ((Set)conjunctionmap.get(c)).add(gn);
129                     conjtonodemap.put(dconst.get(0),gn);
130                 } else if (q instanceof RelationQuantifier) {
131                     RelationQuantifier rq=(RelationQuantifier)q;
132                     VarExpr ve=new VarExpr(rq.y);
133                     InclusionPredicate ip=new InclusionPredicate(ve,new ImageSetExpr(rq.x,rq.getRelation()));
134                     DNFConstraint dconst=new DNFConstraint(ip);
135                     dconst=dconst.not();
136                     TermNode tn=new TermNode(c,dconst.get(0));
137                     GraphNode gn=new GraphNode("Conj"+i+"AQ"+j,
138                                                "Conj ("+i+","+j+") "+dconst.get(0).name()
139                                                ,tn);
140                     conjunctions.add(gn);
141                     if (!conjunctionmap.containsKey(c))
142                         conjunctionmap.put(c,new HashSet());
143                     ((Set)conjunctionmap.get(c)).add(gn);
144                     conjtonodemap.put(dconst.get(0),gn);
145                 }
146             }
147         }
148     }
149
150     void generateupdateedges() {
151         for(Iterator updateiterator=updatenodes.iterator();updateiterator.hasNext();) {
152             GraphNode gn=(GraphNode)updateiterator.next();
153             TermNode tn=(TermNode)gn.getOwner();
154             MultUpdateNode mun=tn.getUpdate();
155             /* Cycle through the rules to look for possible conflicts */
156             for(int i=0;i<state.vRules.size();i++) {
157                 Rule r=(Rule) state.vRules.get(i);  
158                 if (ConcreteInterferes.interferes(mun,r,true)) {
159                     GraphNode scopenode=(GraphNode)scopesatisfy.get(r);
160                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
161                     gn.addEdge(e);
162                 }
163                 if (ConcreteInterferes.interferes(mun,r,false)) {
164                     GraphNode scopenode=(GraphNode)scopefalsify.get(r);
165                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
166                     gn.addEdge(e);
167                 }
168             }
169         }
170     }
171
172     void generateabstractedges() {
173         for(Iterator absiterator=abstractrepair.iterator();absiterator.hasNext();) {
174             GraphNode gn=(GraphNode)absiterator.next();
175             TermNode tn=(TermNode)gn.getOwner();
176             AbstractRepair ar=(AbstractRepair)tn.getAbstract();
177         
178             for(Iterator conjiterator=conjunctions.iterator();conjiterator.hasNext();) {
179                 GraphNode gn2=(GraphNode)conjiterator.next();
180                 TermNode tn2=(TermNode)gn2.getOwner();
181                 Conjunction conj=tn2.getConjunction();
182                 Constraint cons=tn2.getConstraint();
183
184                 for(int i=0;i<conj.size();i++) {
185                     DNFPredicate dp=conj.get(i);
186                     if (AbstractInterferes.interferes(ar,cons)||
187                         AbstractInterferes.interferes(ar,dp)) {
188                         GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
189                         gn.addEdge(e);
190                         break;
191                     }
192                 }
193             }
194
195             for(Iterator scopeiterator=scopenodes.iterator();scopeiterator.hasNext();) {
196                 GraphNode gn2=(GraphNode)scopeiterator.next();
197                 TermNode tn2=(TermNode)gn2.getOwner();
198                 ScopeNode sn2=tn2.getScope();
199                 if (AbstractInterferes.interferes(ar,sn2.getRule(),sn2.getSatisfy())) {
200                     GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
201                     gn.addEdge(e);
202                 }
203             }
204         }
205     }
206     
207     void generatescopeedges() {
208         for(Iterator scopeiterator=scopenodes.iterator();scopeiterator.hasNext();) {
209             GraphNode gn=(GraphNode)scopeiterator.next();
210             TermNode tn=(TermNode)gn.getOwner();
211             ScopeNode sn=tn.getScope();
212             
213             /* Interference edges with conjunctions */
214             for(Iterator conjiterator=conjunctions.iterator();conjiterator.hasNext();) {
215                 GraphNode gn2=(GraphNode)conjiterator.next();
216                 TermNode tn2=(TermNode)gn2.getOwner();
217                 Conjunction conj=tn2.getConjunction();
218                 Constraint constr=tn2.getConstraint();
219                 for(int i=0;i<conj.size();i++) {
220                     DNFPredicate dp=conj.get(i);
221                     if (AbstractInterferes.interferes(sn,dp)||
222                         AbstractInterferes.interferes(sn.getDescriptor(),sn.getSatisfy(),constr)) {
223                         GraphNode.Edge e=new GraphNode.Edge("interferes",gn2);
224                         GraphNode gnconseq=(GraphNode)consequence.get(sn);
225                         gnconseq.addEdge(e);
226                         break;
227                     }
228                 }
229             }
230
231             /* Now see if this could effect other model defintion rules */
232             for(int i=0;i<state.vRules.size();i++) {
233                 Rule r=(Rule) state.vRules.get(i);
234                 if (AbstractInterferes.interferes(sn.getDescriptor(),sn.getSatisfy(),r,true)) {
235                     GraphNode scopenode=(GraphNode)scopesatisfy.get(r);
236                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
237                     GraphNode gnconseq=(GraphNode)consequence.get(sn);
238                     gnconseq.addEdge(e);
239                 }
240                 if (AbstractInterferes.interferes(sn.getDescriptor(),sn.getSatisfy(),r,false)) {
241                     GraphNode scopenode=(GraphNode)scopefalsify.get(r);
242                     GraphNode.Edge e=new GraphNode.Edge("interferes",scopenode);
243                     GraphNode gnconseq=(GraphNode)consequence.get(sn);
244                     gnconseq.addEdge(e);
245                 }
246             }
247         }
248     }
249
250     /* Generates the abstract repair nodes */
251     void generaterepairnodes() {
252         /* Generate repairs of conjunctions */
253         for(Iterator conjiterator=conjunctions.iterator();conjiterator.hasNext();) {
254             GraphNode gn=(GraphNode)conjiterator.next();
255             TermNode tn=(TermNode)gn.getOwner();
256             Conjunction conj=tn.getConjunction();
257             for(int i=0;i<conj.size();i++) {
258                 DNFPredicate dp=conj.get(i);
259                 int[] array=dp.getPredicate().getRepairs(dp.isNegated());
260                 Descriptor d=dp.getPredicate().getDescriptor();
261                 for(int j=0;j<array.length;j++) {
262                     AbstractRepair ar=new AbstractRepair(dp,array[j],d);
263                     TermNode tn2=new TermNode(ar);
264                     GraphNode gn2=new GraphNode(gn.getLabel()+"A"+i+"B"+ar.type(),gn.getTextLabel()+" #"+i+" "+ar.type(),tn2);
265                     GraphNode.Edge e=new GraphNode.Edge("abstract",gn2);
266                     gn.addEdge(e);
267                     abstractrepair.add(gn2);
268                 }
269             }
270         }
271         /* Generate additional abstract repairs */
272         Vector setdescriptors=state.stSets.getAllDescriptors();
273         for(int i=0;i<setdescriptors.size();i++) {
274             SetDescriptor sd=(SetDescriptor)setdescriptors.get(i);
275
276             /* XXXXXXX: Not sure what to do here */
277             VarExpr ve=new VarExpr("DUMMY");
278             InclusionPredicate ip=new InclusionPredicate(ve,new SetExpr(sd));
279             
280             DNFPredicate tp=new DNFPredicate(false,ip);
281             AbstractRepair ar=new AbstractRepair(tp, AbstractRepair.ADDTOSET, sd);
282             TermNode tn=new TermNode(ar);
283             GraphNode gn=new GraphNode("AbstractAddSetRule"+i,tn);
284             abstractrepair.add(gn);
285             abstractadd.put(sd,gn);
286             
287             DNFPredicate tp2=new DNFPredicate(true,ip);
288             AbstractRepair ar2=new AbstractRepair(tp2, AbstractRepair.REMOVEFROMSET, sd);
289             TermNode tn2=new TermNode(ar2);
290             GraphNode gn2=new GraphNode("AbstractRemSetRule"+i,tn2);
291             abstractrepair.add(gn2);
292             abstractremove.put(sd,gn2);
293         }
294
295         Vector relationdescriptors=state.stRelations.getAllDescriptors();
296         for(int i=0;i<relationdescriptors.size();i++) {
297             RelationDescriptor rd=(RelationDescriptor)relationdescriptors.get(i);
298
299             /* XXXXXXX: Not sure what to do here */
300             VarDescriptor vd1=new VarDescriptor("DUMMY1");
301             VarExpr ve2=new VarExpr("DUMMY2");
302
303             InclusionPredicate ip=new InclusionPredicate(ve2,new ImageSetExpr(vd1, rd));
304             
305             DNFPredicate tp=new DNFPredicate(false,ip);
306             AbstractRepair ar=new AbstractRepair(tp, AbstractRepair.ADDTORELATION, rd);
307             TermNode tn=new TermNode(ar);
308             GraphNode gn=new GraphNode("AbstractAddRelRule"+i,tn);
309             abstractrepair.add(gn);
310             abstractadd.put(rd,gn);
311             
312             DNFPredicate tp2=new DNFPredicate(true,ip);
313             AbstractRepair ar2=new AbstractRepair(tp2, AbstractRepair.REMOVEFROMRELATION, rd);
314             TermNode tn2=new TermNode(ar2);
315             GraphNode gn2=new GraphNode("AbstractRemRelRule"+i,tn2);
316             abstractrepair.add(gn2);
317             abstractremove.put(rd,gn2);
318         }
319         
320     }
321
322     int compensationcount=0;
323     void generatecompensationnodes() {
324         for(int i=0;i<state.vRules.size();i++) {
325             Rule r=(Rule) state.vRules.get(i);
326             Vector possiblerules=new Vector();
327             /* Construct bindings */
328             /* No need to construct bindings on remove
329                Vector bindings=new Vector();
330                constructbindings(bindings, r,true);
331             */
332             for(int j=0;j<(r.numQuantifiers()+r.getDNFNegGuardExpr().size());j++) {
333                 GraphNode gn=(GraphNode)scopesatisfy.get(r);
334                 TermNode tn=(TermNode) gn.getOwner();
335                 ScopeNode sn=tn.getScope();
336                 MultUpdateNode mun=new MultUpdateNode(sn);
337                 TermNode tn2=new TermNode(mun);
338                 GraphNode gn2=new GraphNode("CompRem"+compensationcount,tn2);
339                 UpdateNode un=new UpdateNode(r);
340                 //              un.addBindings(bindings);
341                 // Not necessary
342                 if (j<r.numQuantifiers()) {
343                     /* Remove quantifier */
344                     Quantifier q=r.getQuantifier(j);
345                     if (q instanceof RelationQuantifier) {
346                         RelationQuantifier rq=(RelationQuantifier)q;
347                         TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
348                         toe.td=ReservedTypeDescriptor.INT;
349                         Updates u=new Updates(toe,true);
350                         un.addUpdate(u);
351                         if (abstractremove.containsKey(rq.relation)) {
352                             GraphNode agn=(GraphNode)abstractremove.get(rq.relation);
353                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
354                             gn2.addEdge(e);
355                         } else {
356                             continue; /* Abstract repair doesn't exist */
357                         }
358                     } else if (q instanceof SetQuantifier) {
359                         SetQuantifier sq=(SetQuantifier)q;
360                         ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
361                         eoe.td=ReservedTypeDescriptor.INT;
362                         Updates u=new Updates(eoe,true);
363                         un.addUpdate(u);
364                         if (abstractremove.containsKey(sq.set)) {
365                             GraphNode agn=(GraphNode)abstractremove.get(sq.set);
366                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
367                             gn2.addEdge(e);
368                         } else {
369                             continue; /* Abstract repair doesn't exist */
370                         }
371                     } else {
372                         continue;
373                     }
374                 } else {
375                     int c=j-r.numQuantifiers();
376                     if (!processconjunction(un,r.getDNFNegGuardExpr().get(c))) {
377                         continue;
378                     }
379                 }
380                 if (!un.checkupdates()) /* Make sure we have a good update */
381                     continue;
382                 
383                 mun.addUpdate(un);
384
385                 GraphNode.Edge e=new GraphNode.Edge("abstract"+compensationcount,gn2);
386                 compensationcount++;
387                 gn.addEdge(e);
388                 updatenodes.add(gn2);
389             }
390         }
391     }
392
393     void generatedatastructureupdatenodes() {
394         for(Iterator absiterator=abstractrepair.iterator();absiterator.hasNext();) {
395             GraphNode gn=(GraphNode)absiterator.next();
396             TermNode tn=(TermNode) gn.getOwner();
397             AbstractRepair ar=tn.getAbstract();
398             if (ar.getType()==AbstractRepair.ADDTOSET) {
399                 generateaddtosetrelation(gn,ar);
400             } else if (ar.getType()==AbstractRepair.REMOVEFROMSET) {
401                 generateremovefromsetrelation(gn,ar);
402             } else if (ar.getType()==AbstractRepair.ADDTORELATION) {
403                 generateaddtosetrelation(gn,ar);
404             } else if (ar.getType()==AbstractRepair.REMOVEFROMRELATION) {
405                 generateremovefromsetrelation(gn,ar);
406             } else if (ar.getType()==AbstractRepair.MODIFYRELATION) {
407                 /* Generate remove/add pairs */
408                 generateremovefromsetrelation(gn,ar);
409                 generateaddtosetrelation(gn,ar);
410                 /* Generate atomic modify */
411                 generatemodifyrelation(gn,ar);
412             }
413         }
414     }
415
416     int removefromcount=0;
417     void generateremovefromsetrelation(GraphNode gn,AbstractRepair ar) {
418         Vector possiblerules=new Vector();
419         for(int i=0;i<state.vRules.size();i++) {
420             Rule r=(Rule) state.vRules.get(i);
421             if ((r.getInclusion() instanceof SetInclusion)&&
422                 (ar.getDescriptor()==((SetInclusion)r.getInclusion()).getSet()))
423                 possiblerules.add(r);
424             if ((r.getInclusion() instanceof RelationInclusion)&&
425                 (ar.getDescriptor()==((RelationInclusion)r.getInclusion()).getRelation()))
426                 possiblerules.add(r);
427         }
428         if (possiblerules.size()==0)
429             return;
430         int[] count=new int[possiblerules.size()];
431         while(remains(count,possiblerules)) {
432             MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.REMOVE);
433             TermNode tn=new TermNode(mun);
434             GraphNode gn2=new GraphNode("UpdateRem"+removefromcount,tn);
435
436             boolean goodflag=true;
437             for(int i=0;i<possiblerules.size();i++) {
438                 Rule r=(Rule)possiblerules.get(i);
439                 UpdateNode un=new UpdateNode(r);
440                 /* Construct bindings */
441                 /* No Need to construct bindings on remove
442                    Vector bindings=new Vector();
443                    constructbindings(bindings, r,true);
444                   un.addBindings(bindings);*/
445                 if (count[i]<r.numQuantifiers()) {
446                     /* Remove quantifier */
447                     Quantifier q=r.getQuantifier(count[i]);
448                     if (q instanceof RelationQuantifier) {
449                         RelationQuantifier rq=(RelationQuantifier)q;
450                         TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
451                         toe.td=ReservedTypeDescriptor.INT;
452                         Updates u=new Updates(toe,true);
453                         un.addUpdate(u);
454                         if (abstractremove.containsKey(rq.relation)) {
455                             GraphNode agn=(GraphNode)abstractremove.get(rq.relation);
456                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
457                             gn2.addEdge(e);
458                         } else {
459                             goodflag=false;break; /* Abstract repair doesn't exist */
460                         }
461                     } else if (q instanceof SetQuantifier) {
462                         SetQuantifier sq=(SetQuantifier)q;
463                         ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
464                         eoe.td=ReservedTypeDescriptor.INT;
465                         Updates u=new Updates(eoe,true);
466                         un.addUpdate(u);
467                         if (abstractremove.containsKey(sq.set)) {
468                             GraphNode agn=(GraphNode)abstractremove.get(sq.set);
469                             GraphNode.Edge e=new GraphNode.Edge("requires",agn);
470                             gn2.addEdge(e);
471                         } else {
472                             goodflag=false;break; /* Abstract repair doesn't exist */
473                         }
474                     } else {goodflag=false;break;}
475                 } else {
476                     int c=count[i]-r.numQuantifiers();
477                     if (!processconjunction(un,r.getDNFNegGuardExpr().get(c))) {
478                         goodflag=false;break;
479                     }
480                 }
481                 if (!un.checkupdates()) {
482                     goodflag=false;
483                     break;
484                 }
485                 mun.addUpdate(un);
486             }
487             if (goodflag) {
488                 GraphNode.Edge e=new GraphNode.Edge("abstract"+removefromcount,gn2);
489                 removefromcount++;
490                 gn.addEdge(e);
491                 updatenodes.add(gn2);
492             }
493             increment(count,possiblerules);
494         }
495     }
496
497     static void increment(int count[], Vector rules) {
498         count[0]++;
499         for(int i=0;i<(rules.size()-1);i++) {
500             if (count[i]>=(((Rule)rules.get(i)).numQuantifiers()+(((Rule)rules.get(i)).getDNFNegGuardExpr().size()))) {
501                 count[i+1]++;
502                 count[i]=0;
503             } else break;
504         }
505     }
506
507     static boolean remains(int count[], Vector rules) {
508         for(int i=0;i<rules.size();i++) {
509             if (count[i]>=(((Rule)rules.get(i)).numQuantifiers()+(((Rule)rules.get(i)).getDNFNegGuardExpr().size()))) {
510                 return false;
511             }
512         }
513         return true;
514     }
515     /** This method generates data structure updates to implement the
516      *  abstract atomic modification specified by ar. */
517
518     void generatemodifyrelation(GraphNode gn, AbstractRepair ar) {
519         
520     }
521
522
523     boolean constructbindings(Vector bindings, Rule r, boolean isremoval) {
524         boolean goodupdate=true;
525         Inclusion inc=r.getInclusion();
526         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
527             Quantifier q=(Quantifier)iterator.next();
528             if ((q instanceof SetQuantifier)||(q instanceof ForQuantifier)) {
529                 VarDescriptor vd=null;
530                 SetDescriptor set=null;
531                 if (q instanceof SetQuantifier) {
532                     vd=((SetQuantifier)q).getVar();
533                 } else
534                     vd=((ForQuantifier)q).getVar();
535                 if(inc instanceof SetInclusion) {
536                     SetInclusion si=(SetInclusion)inc;
537                     if ((si.elementexpr instanceof VarExpr)&&
538                         (((VarExpr)si.elementexpr).getVar()==vd)) {
539                         /* Can solve for v */
540                         Binding binding=new Binding(vd,0);
541                         bindings.add(binding);
542                     } else
543                         goodupdate=false;
544                 } else if (inc instanceof RelationInclusion) {
545                     RelationInclusion ri=(RelationInclusion)inc;
546                     boolean f1=true;
547                     boolean f2=true;
548                     if ((ri.getLeftExpr() instanceof VarExpr)&&
549                         (((VarExpr)ri.getLeftExpr()).getVar()==vd)) {
550                                 /* Can solve for v */
551                         Binding binding=new Binding(vd,0);
552                         bindings.add(binding);
553                     } else f1=false;
554                     if ((ri.getRightExpr() instanceof VarExpr)&&
555                         (((VarExpr)ri.getRightExpr()).getVar()==vd)) {
556                                 /* Can solve for v */
557                         Binding binding=new Binding(vd,0);
558                         bindings.add(binding);
559                     } else f2=false;
560                     if (!(f1||f2))
561                         goodupdate=false;
562                 } else throw new Error("Inclusion not recognized");
563                 if (!goodupdate)
564                     if (isremoval) {
565                         Binding binding=new Binding(vd);
566                         bindings.add(binding);
567                         goodupdate=true;
568                     } else
569                         break;
570             } else if (q instanceof RelationQuantifier) {
571                 RelationQuantifier rq=(RelationQuantifier)q;
572                 for(int k=0;k<2;k++) {
573                     VarDescriptor vd=(k==0)?rq.x:rq.y;
574                     if(inc instanceof SetInclusion) {
575                         SetInclusion si=(SetInclusion)inc;
576                         if ((si.elementexpr instanceof VarExpr)&&
577                             (((VarExpr)si.elementexpr).getVar()==vd)) {
578                             /* Can solve for v */
579                             Binding binding=new Binding(vd,0);
580                             bindings.add(binding);
581                         } else
582                             goodupdate=false;
583                     } else if (inc instanceof RelationInclusion) {
584                         RelationInclusion ri=(RelationInclusion)inc;
585                         boolean f1=true;
586                         boolean f2=true;
587                         if ((ri.getLeftExpr() instanceof VarExpr)&&
588                             (((VarExpr)ri.getLeftExpr()).getVar()==vd)) {
589                             /* Can solve for v */
590                             Binding binding=new Binding(vd,0);
591                             bindings.add(binding);
592                         } else f1=false;
593                         if ((ri.getRightExpr() instanceof VarExpr)&&
594                             (((VarExpr)ri.getRightExpr()).getVar()==vd)) {
595                             /* Can solve for v */
596                             Binding binding=new Binding(vd,0);
597                             bindings.add(binding);
598                         } else f2=false;
599                         if (!(f1||f2))
600                             goodupdate=false;
601                     } else throw new Error("Inclusion not recognized");
602                     if (!goodupdate)
603                         if (isremoval) {
604                             Binding binding=new Binding(vd);
605                             bindings.add(binding);
606                             goodupdate=true;
607                         } else
608                             break;
609                 }
610                 if (!goodupdate)
611                     break;
612             } else throw new Error("Quantifier not recognized");
613         }
614         return goodupdate;
615     }
616
617     static int addtocount=0;
618     void generateaddtosetrelation(GraphNode gn, AbstractRepair ar) {
619         //      System.out.println("Attempting to generate add to set");
620         //System.out.println(ar.getPredicate().getPredicate().name());
621         //System.out.println(ar.getPredicate().isNegated());
622         for(int i=0;i<state.vRules.size();i++) {
623             Rule r=(Rule) state.vRules.get(i);
624             /* See if this is a good rule*/
625             //System.out.println(r.getGuardExpr().name());
626             if ((r.getInclusion() instanceof SetInclusion&&
627                 ar.getDescriptor()==((SetInclusion)r.getInclusion()).getSet())||
628                 (r.getInclusion() instanceof RelationInclusion&&
629                  ar.getDescriptor()==((RelationInclusion)r.getInclusion()).getRelation())) {
630
631                 /* First solve for quantifiers */
632                 Vector bindings=new Vector();
633                 /* Construct bindings */
634                 //System.out.println("Attempting to generate add to set: #2");
635                 if (!constructbindings(bindings,r,false))
636                     continue;
637                 //System.out.println("Attempting to generate add to set: #3");
638                 //Generate add instruction
639                 DNFRule dnfrule=r.getDNFGuardExpr();
640                 for(int j=0;j<dnfrule.size();j++) {
641                     Inclusion inc=r.getInclusion();
642                     UpdateNode un=new UpdateNode(r);
643                     un.addBindings(bindings);
644                     /* Now build update for tuple/set inclusion condition */
645                     if(inc instanceof SetInclusion) {
646                         SetInclusion si=(SetInclusion)inc;
647                         if (!(si.elementexpr instanceof VarExpr)) {
648                             Updates up=new Updates(si.elementexpr,0);
649                             un.addUpdate(up);
650                         } else {
651                             VarDescriptor vd=((VarExpr)si.elementexpr).getVar();
652                             if (un.getBinding(vd)==null) {
653                                 Updates up=new Updates(si.elementexpr,0);
654                                 un.addUpdate(up);
655                             }
656                         }
657                     } else if (inc instanceof RelationInclusion) {
658                         RelationInclusion ri=(RelationInclusion)inc;
659                         if (!(ri.getLeftExpr() instanceof VarExpr)) {
660                             Updates up=new Updates(ri.getLeftExpr(),0);
661                             un.addUpdate(up);
662                         } else {
663                             VarDescriptor vd=((VarExpr)ri.getLeftExpr()).getVar();
664                             if (un.getBinding(vd)==null) {
665                                 Updates up=new Updates(ri.getLeftExpr(),0);
666                                 un.addUpdate(up);
667                             }
668                         }
669                         if (!(ri.getRightExpr() instanceof VarExpr)) {
670                             Updates up=new Updates(ri.getRightExpr(),1);
671                             un.addUpdate(up);
672                         } else {
673                             VarDescriptor vd=((VarExpr)ri.getRightExpr()).getVar();
674                             if (un.getBinding(vd)==null) {
675                                 Updates up=new Updates(ri.getRightExpr(),1);
676                                 un.addUpdate(up);
677                             }
678                         }
679                     }
680                     //Finally build necessary updates to satisfy conjunction
681                     RuleConjunction ruleconj=dnfrule.get(j);
682                     /* Add in updates for quantifiers */
683                     //System.out.println("Attempting to generate add to set #4");
684                     MultUpdateNode mun=new MultUpdateNode(ar,MultUpdateNode.ADD);
685                     TermNode tn=new TermNode(mun);
686                     GraphNode gn2=new GraphNode("UpdateAdd"+addtocount,tn);
687
688                     if (processquantifers(gn2,un, r)&&debugdd()&&
689                         processconjunction(un,ruleconj)&&
690                         un.checkupdates()) {
691                         //System.out.println("Attempting to generate add to set #5");
692                         mun.addUpdate(un);
693                         GraphNode.Edge e=new GraphNode.Edge("abstract"+addtocount,gn2);
694                         addtocount++;
695                         gn.addEdge(e);
696                         updatenodes.add(gn2);}
697                 }
698             }
699         }
700     }
701
702     boolean debugdd() {
703         //System.out.println("Attempting to generate add to set DD");
704         return true;
705     }
706
707     boolean processquantifers(GraphNode gn,UpdateNode un, Rule r) {
708         Inclusion inc=r.getInclusion();
709         for(Iterator iterator=r.quantifiers();iterator.hasNext();) {
710             Quantifier q=(Quantifier)iterator.next();
711             /* Add quantifier */
712             /* FIXME: Analysis to determine when this update is necessary */
713             if (q instanceof RelationQuantifier) {
714                 RelationQuantifier rq=(RelationQuantifier)q;
715                 TupleOfExpr toe=new TupleOfExpr(new VarExpr(rq.x),new VarExpr(rq.y),rq.relation);
716                 toe.td=ReservedTypeDescriptor.INT;
717                 Updates u=new Updates(toe,false);
718                 un.addUpdate(u);
719                 if (abstractremove.containsKey(rq.relation)) {
720                     GraphNode agn=(GraphNode)abstractadd.get(rq.relation);
721                     GraphNode.Edge e=new GraphNode.Edge("requires",agn);
722                     gn.addEdge(e);
723                 } else {
724                     return false;
725                 }
726
727             } else if (q instanceof SetQuantifier) {
728                 SetQuantifier sq=(SetQuantifier)q;
729                 ElementOfExpr eoe=new ElementOfExpr(new VarExpr(sq.var),sq.set);
730                 eoe.td=ReservedTypeDescriptor.INT;
731                 Updates u=new Updates(eoe,false);
732                 un.addUpdate(u);
733                 if (abstractremove.containsKey(sq.set)) {
734                     GraphNode agn=(GraphNode)abstractadd.get(sq.set);
735                     GraphNode.Edge e=new GraphNode.Edge("requires",agn);
736                     gn.addEdge(e);
737                 } else {
738                     return false;
739                 }
740             } else return false;
741         }
742         return true;
743     }
744
745     boolean  processconjunction(UpdateNode un,RuleConjunction ruleconj){
746         boolean okay=true;
747         for(int k=0;k<ruleconj.size();k++) {
748             DNFExpr de=ruleconj.get(k);
749             Expr e=de.getExpr();
750             if (e instanceof OpExpr) {
751                 OpExpr ex=(OpExpr)de.getExpr();
752                 Opcode op=ex.getOpcode();
753                 Updates up=new Updates(ex.left,ex.right,op, de.getNegation());
754                 un.addUpdate(up);
755             } else if (e instanceof ElementOfExpr) {
756                 Updates up=new Updates(e,de.getNegation());
757                 un.addUpdate(up);
758             } else if (e instanceof TupleOfExpr) {
759                 Updates up=new Updates(e,de.getNegation());
760                 un.addUpdate(up);
761             } else if (e instanceof BooleanLiteralExpr) { 
762                 boolean truth=((BooleanLiteralExpr)e).getValue();
763                 if (de.getNegation())
764                     truth=!truth;
765                 if (!truth) {
766                     okay=false;
767                     break;
768                 }
769             } else {
770                 System.out.println(e.getClass().getName());
771                 throw new Error("Error #213");
772             }
773         }
774         return okay;
775     }
776
777     void generatescopenodes() {
778         for(int i=0;i<state.vRules.size();i++) {
779             Rule r=(Rule) state.vRules.get(i);
780             ScopeNode satisfy=new ScopeNode(r,true);
781             TermNode tnsatisfy=new TermNode(satisfy);
782             GraphNode gnsatisfy=new GraphNode("SatisfyRule"+i,tnsatisfy);
783             ConsequenceNode cnsatisfy=new ConsequenceNode();
784             TermNode ctnsatisfy=new TermNode(cnsatisfy);
785             GraphNode cgnsatisfy=new GraphNode("ConseqSatisfyRule"+i,ctnsatisfy);
786             consequence.put(satisfy,cgnsatisfy);
787             GraphNode.Edge esat=new GraphNode.Edge("consequencesatisfy"+i,cgnsatisfy);
788             gnsatisfy.addEdge(esat);
789             consequencenodes.add(cgnsatisfy);
790             scopesatisfy.put(r,gnsatisfy);
791             scopenodes.add(gnsatisfy);
792
793             ScopeNode falsify=new ScopeNode(r,false);
794             TermNode tnfalsify=new TermNode(falsify);
795             GraphNode gnfalsify=new GraphNode("FalsifyRule"+i,tnfalsify);
796             ConsequenceNode cnfalsify=new ConsequenceNode();
797             TermNode ctnfalsify=new TermNode(cnfalsify);
798             GraphNode cgnfalsify=new GraphNode("ConseqFalsifyRule"+i,ctnfalsify);
799             consequence.put(falsify,cgnfalsify);
800             GraphNode.Edge efals=new GraphNode.Edge("consequencefalsify"+i,cgnfalsify);
801             gnfalsify.addEdge(efals);
802             consequencenodes.add(cgnfalsify);
803             scopefalsify.put(r,gnfalsify);
804             scopenodes.add(gnfalsify);
805         }
806     }
807 }