359dcc7a1dfe448d5590d174b4ab098c730ac274
[repair.git] / Repair / RepairCompiler / MCC / IR / AbstractInterferes.java
1 package MCC.IR;
2 import java.util.*;
3
4 class AbstractInterferes {
5     Termination termination;
6
7     public AbstractInterferes(Termination t) {
8         termination=t;
9     }
10
11     /** Does performing the AbstractRepair ar satisfy (or falsify if satisfy=false)
12      * Rule r. */
13
14     static public boolean interfereswithrule(AbstractRepair ar, Rule r, boolean satisfy) {
15         boolean mayadd=false;
16         boolean mayremove=false;
17         switch (ar.getType()) {
18         case AbstractRepair.ADDTOSET:
19         case AbstractRepair.ADDTORELATION:
20             if (interferesquantifier(ar.getDescriptor(), true, r, satisfy))
21                 return true;
22             mayadd=true;
23             break;
24         case AbstractRepair.REMOVEFROMSET:
25         case AbstractRepair.REMOVEFROMRELATION:
26             if (interferesquantifier(ar.getDescriptor(), false, r, satisfy))
27                 return true;
28             mayremove=true;
29             break;
30         case AbstractRepair.MODIFYRELATION:
31             if (interferesquantifier(ar.getDescriptor(), true, r, satisfy))
32                 return true;
33             if (interferesquantifier(ar.getDescriptor(), false, r, satisfy))
34                 return true;
35             mayadd=true;
36             mayremove=true;
37         break;
38         default:
39             throw new Error("Unrecognized Abstract Repair");
40         }
41         DNFRule drule=null;
42         if (satisfy)
43             drule=r.getDNFGuardExpr();
44         else
45             drule=r.getDNFNegGuardExpr();
46         
47         for(int i=0;i<drule.size();i++) {
48             RuleConjunction rconj=drule.get(i);
49             for(int j=0;j<rconj.size();j++) {
50                 DNFExpr dexpr=rconj.get(j);
51                 Expr expr=dexpr.getExpr();
52                 if (expr.usesDescriptor(ar.getDescriptor())) {
53                     /* Need to check */
54                     if ((mayadd&&!dexpr.getNegation())||(mayremove&&dexpr.getNegation()))
55                         return true;
56                 }
57             }
58         }
59         return false;
60     }
61
62     public boolean checkrelationconstraint(AbstractRepair ar, Constraint c) {
63         if (c.numQuantifiers()==1&&
64             (c.getQuantifier(0) instanceof RelationQuantifier)) {
65             RelationQuantifier rq=(RelationQuantifier)c.getQuantifier(0);
66             if (rq.getRelation()==ar.getDescriptor()) {
67                 Hashtable ht=new Hashtable();
68                 if (ar.getDomainSet()!=null)
69                     ht.put(rq.x,ar.getDomainSet());
70                 if (ar.getRangeSet()!=null)
71                     ht.put(rq.y,ar.getRangeSet());
72                 DNFConstraint dconst=c.dnfconstraint;
73             conjloop:
74                 for(int i=0;i<dconst.size();i++) {
75                     Conjunction conj=dconst.get(i);
76                 predloop:
77                     for(int j=0;j<conj.size();j++) {
78                         DNFPredicate dpred=conj.get(j);
79                         Predicate p=dpred.getPredicate();
80                         if ((p instanceof InclusionPredicate)&&(!dpred.isNegated())) {
81                             InclusionPredicate ip=(InclusionPredicate)p;
82                             if (ip.expr instanceof VarExpr&&
83                                 ip.setexpr.getDescriptor() instanceof SetDescriptor) {
84                                 VarDescriptor vd=((VarExpr)ip.expr).getVar();
85                                 if (ht.containsKey(vd)) {
86                                     SetDescriptor td=(SetDescriptor)ip.setexpr.getDescriptor();
87                                     SetDescriptor s=(SetDescriptor)ht.get(vd);
88                                     if (td.isSubset(s))
89                                         continue predloop;
90                                 }
91                             }
92                         }
93                         continue conjloop;
94                     }
95                     return true;
96                 }
97             }
98         }
99         return false;
100     }
101
102     /** Does performing the AbstractRepair ar falsify the predicate dp */
103
104     public boolean interfereswithpredicate(AbstractRepair ar, DNFPredicate dp) {
105         if ((ar.getDescriptor()!=dp.getPredicate().getDescriptor()) &&
106             //      ((ar.getDescriptor() instanceof SetDescriptor)||
107             // If the second predicate uses the size of the set, modifying the set size could falsify it...
108             !dp.getPredicate().usesDescriptor(ar.getDescriptor()))
109             //)
110             return false;
111
112         /* This if handles all the c comparisons in the paper */
113         if (ar.getDescriptor()==dp.getPredicate().getDescriptor()&&
114             (ar.getType()==AbstractRepair.ADDTOSET||ar.getType()==AbstractRepair.ADDTORELATION)&&
115             (ar.getPredicate().getPredicate() instanceof ExprPredicate)&&
116             (dp.getPredicate() instanceof ExprPredicate)&&
117             (dp.getPredicate().inverted()==ar.getPredicate().getPredicate().inverted())&&
118             (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.SIZE)) {
119             boolean neg1=ar.getPredicate().isNegated();
120             Opcode op1=((ExprPredicate)ar.getPredicate().getPredicate()).getOp();
121             int size1=((ExprPredicate)ar.getPredicate().getPredicate()).rightSize();
122             boolean neg2=dp.isNegated();
123             Opcode op2=((ExprPredicate)dp.getPredicate()).getOp();
124             int size2=((ExprPredicate)dp.getPredicate()).rightSize();
125             op1=Opcode.translateOpcode(neg1,op1);
126             op2=Opcode.translateOpcode(neg2,op2);
127
128             if ((op1==Opcode.EQ)||(op1==Opcode.NE)||(op1==Opcode.GT)||op1==Opcode.GE) {
129                 int size1a=0;
130                 if((op1==Opcode.EQ)||(op1==Opcode.GE))
131                     size1a=size1;
132                 if((op1==Opcode.GT)||(op1==Opcode.NE))
133                     size1a=size1+1;
134
135                 if (((op2==Opcode.EQ)&&(size1a==size2))||
136                     ((op2==Opcode.NE)&&(size1a!=size2))||
137                     (op2==Opcode.GE)||
138                     (op2==Opcode.GT)||
139                     ((op2==Opcode.LE)&&(size1a<=size2))||
140                     ((op2==Opcode.LT)&&(size1a<size2)))
141                     return false;
142             }
143         }
144         if (ar.getDescriptor()==dp.getPredicate().getDescriptor()&&
145             (ar.getType()==AbstractRepair.ADDTOSET||ar.getType()==AbstractRepair.ADDTORELATION)&&
146             (dp.getPredicate() instanceof ExprPredicate)&&
147             (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.SIZE)) {
148             boolean neg2=dp.isNegated();
149             Opcode op2=((ExprPredicate)dp.getPredicate()).getOp();
150             int size2=((ExprPredicate)dp.getPredicate()).rightSize();
151
152             op2=Opcode.translateOpcode(neg2,op2);
153
154             int maxsize=termination.maxsize.getsize(dp.getPredicate().getDescriptor());
155
156             if ((maxsize!=-1)&&
157                 ((op2==Opcode.LT&&size2>maxsize)||
158                  (op2==Opcode.LE&&size2>=maxsize)||
159                  (op2==Opcode.EQ&&size2>=maxsize)))
160                 return false;
161
162             if (((op2==Opcode.NE)&&(size2==0))||
163                 (op2==Opcode.GE)||
164                 (op2==Opcode.GT))
165                 return false;
166         }
167         if (ar.getDescriptor()==dp.getPredicate().getDescriptor()&&
168             (ar.getType()==AbstractRepair.MODIFYRELATION)&&
169             (dp.getPredicate() instanceof ExprPredicate)&&
170             (dp.getPredicate().inverted()==ar.getPredicate().getPredicate().inverted())&&
171             (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.COMPARISON)) {
172             
173             boolean neg1=ar.getPredicate().isNegated();
174             Opcode op1=((ExprPredicate)ar.getPredicate().getPredicate()).getOp();
175             boolean isInt1=((ExprPredicate)ar.getPredicate().getPredicate()).isRightInt();
176             int size1=isInt1?((ExprPredicate)ar.getPredicate().getPredicate()).rightSize():0;
177             Expr expr1=((OpExpr)((ExprPredicate)ar.getPredicate().getPredicate()).expr).right;
178
179
180             boolean neg2=dp.isNegated();
181             Opcode op2=((ExprPredicate)dp.getPredicate()).getOp();
182             boolean isInt2=((ExprPredicate)dp.getPredicate()).isRightInt();
183             int size2=isInt2?((ExprPredicate)dp.getPredicate()).rightSize():0;
184             Expr expr2=((OpExpr)((ExprPredicate)dp.getPredicate()).expr).right;
185
186             
187             /* If the left sides of the comparisons are both from
188                different sets, the update is orthogonal to the expr dp */
189             {
190                 Expr lexpr1=((RelationExpr)((OpExpr)((ExprPredicate)ar.getPredicate().getPredicate()).expr).getLeftExpr()).getExpr();
191                 Expr lexpr2=((RelationExpr)((OpExpr)((ExprPredicate)dp.getPredicate()).expr).getLeftExpr()).getExpr();
192                 SetDescriptor sd1=lexpr1.getSet();
193                 SetDescriptor sd2=lexpr2.getSet();
194                 if (termination.mutuallyexclusive(sd1,sd2))
195                     return false;
196             }
197
198             /* Translate the opcodes */
199             op1=Opcode.translateOpcode(neg1,op1);
200             op2=Opcode.translateOpcode(neg2,op2);
201             
202             /* Obvious cases which can't interfere */
203             if (((op1==Opcode.GT)||
204                 (op1==Opcode.GE))&&
205                 ((op2==Opcode.GT)||
206                  (op2==Opcode.GE)))
207                 return false;
208             if (((op1==Opcode.LT)||
209                 (op1==Opcode.LE))&&
210                 ((op2==Opcode.LT)||
211                  (op2==Opcode.LE)))
212                 return false;
213             // FIXME
214             if (((op1==Opcode.EQ)||(op1==Opcode.GE)||(op1==Opcode.LE))&&
215                 ((op2==Opcode.EQ)||(op2==Opcode.GE)||(op2==Opcode.LE))&&
216                 expr1.equals(null,expr2)) {
217                 // Need to check free variables...
218                 return false;
219             }
220             if (isInt1&&isInt2) {
221                 if (((op1==Opcode.EQ)||(op1==Opcode.GE)||(op1==Opcode.LE))&&
222                     ((op2==Opcode.EQ)||(op2==Opcode.GE)||(op2==Opcode.LE))&&
223                     size1==size2)
224                     return false;
225                 int size1a=size1;
226                 int size2a=size2;
227                 if (op1==Opcode.GT)
228                     size1a++;
229                 if (op1==Opcode.LT)
230                     size1a--;
231                 if (op1==Opcode.NE)
232                     size1a++; /*FLAGNE this is current behavior for NE repairs */
233                 
234                 if (op2==Opcode.GT)
235                     size2a++;
236                 if (op2==Opcode.LT)
237                     size2a--;
238                 if (((op1==Opcode.GE)||(op1==Opcode.GT))&&
239                     ((op2==Opcode.LE)||(op2==Opcode.EQ)||(op2==Opcode.LT))&&
240                     (size1a<=size2a))
241                     return false;
242                 if (((op1==Opcode.LE)||(op1==Opcode.LT))&&
243                     ((op2==Opcode.GE)||(op2==Opcode.EQ)||(op2==Opcode.GT))&&
244                     (size1a>=size2a))
245                     return false;
246                 if ((op1==Opcode.EQ)&&(op2==Opcode.EQ)&&
247                     (size1a==size2a))
248                     return false;
249                 if ((op1==Opcode.EQ)&&
250                     ((op2==Opcode.LE)||(op2==Opcode.LT))&&
251                     (size1a<=size2a))
252                     return false;
253                 if ((op1==Opcode.EQ)&&
254                     ((op2==Opcode.GE)||(op2==Opcode.GT))&&
255                     (size1a>=size2a))
256                     return false;
257                 if (op2==Opcode.NE)  /*FLAGNE this is current behavior for NE repairs */
258                     if (size1a!=size2)
259                         return false;
260                 if ((op1==Opcode.NE)&&
261                     (op2==Opcode.EQ)&&
262                     (size1!=size2))
263                     return false;
264                 if ((op1==Opcode.NE)&& /* FLAGNE relies on increasing or decreasing by 1 */
265                     ((op2==Opcode.GT)||(op2==Opcode.GE))&&
266                     (size1!=size2a))
267                     return false;
268                 if ((op1==Opcode.NE)&& /* FLAGNE relies on increasing or decreasing by 1 */
269                     ((op2==Opcode.LT)||(op2==Opcode.LE))&&
270                     (size1!=size2a))
271                     return false;
272             }
273         }
274         /* This handles all the c comparisons in the paper */
275         if (ar.getDescriptor()==dp.getPredicate().getDescriptor()&&
276             (ar.getType()==AbstractRepair.REMOVEFROMSET||ar.getType()==AbstractRepair.REMOVEFROMRELATION)&&
277             (ar.getPredicate().getPredicate() instanceof ExprPredicate)&&
278             (dp.getPredicate() instanceof ExprPredicate)&&
279             (dp.getPredicate().inverted()==ar.getPredicate().getPredicate().inverted())&&
280             (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.SIZE)) {
281             boolean neg1=ar.getPredicate().isNegated();
282             Opcode op1=((ExprPredicate)ar.getPredicate().getPredicate()).getOp();
283             int size1=((ExprPredicate)ar.getPredicate().getPredicate()).rightSize();
284             boolean neg2=dp.isNegated();
285             Opcode op2=((ExprPredicate)dp.getPredicate()).getOp();
286             int size2=((ExprPredicate)dp.getPredicate()).rightSize();
287             /* Translate the opcodes */
288             op1=Opcode.translateOpcode(neg1,op1);
289             op2=Opcode.translateOpcode(neg2,op2);
290
291             if (((op1==Opcode.EQ)||(op1==Opcode.LT)||op1==Opcode.LE)||(op1==Opcode.NE)) {
292                 int size1a=0;
293
294                 if((op1==Opcode.EQ)||(op1==Opcode.LE))
295                     size1a=size1;
296                 if((op1==Opcode.LT)||(op1==Opcode.NE))
297                     size1a=size1-1;
298
299                 if (((op2==Opcode.EQ)&&(size1a==size2))||
300                     ((op2==Opcode.NE)&&(size1a!=size2))||
301                     (op2==Opcode.LE)||
302                     (op2==Opcode.LT)||
303                     ((op2==Opcode.GE)&&(size1a>=size2))||
304                     ((op2==Opcode.GT)&&(size1a>size2)))
305                     return false;
306             }
307         }
308
309         if (ar.getDescriptor()==dp.getPredicate().getDescriptor()&&
310             (ar.getType()==AbstractRepair.REMOVEFROMSET||ar.getType()==AbstractRepair.REMOVEFROMRELATION)&&
311             (dp.getPredicate() instanceof ExprPredicate)&&
312             (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.SIZE)) {
313             boolean neg2=dp.isNegated();
314             Opcode op2=((ExprPredicate)dp.getPredicate()).getOp();
315             int size2=((ExprPredicate)dp.getPredicate()).rightSize();
316             op2=Opcode.translateOpcode(neg2,op2);
317
318             if (((op2==Opcode.EQ)&&(size2==0))||
319                 (op2==Opcode.LE)||
320                 (op2==Opcode.LT))
321                 return false;
322         }
323         if ((ar.getDescriptor()==dp.getPredicate().getDescriptor())&&
324             (ar.getType()==AbstractRepair.ADDTOSET||ar.getType()==AbstractRepair.ADDTORELATION)&&
325             (dp.getPredicate() instanceof InclusionPredicate)&&
326             (dp.isNegated()==false))
327             return false; /* Could only satisfy this predicate */
328
329         if ((ar.getDescriptor()==dp.getPredicate().getDescriptor())&&
330             (ar.getType()==AbstractRepair.REMOVEFROMSET||ar.getType()==AbstractRepair.REMOVEFROMRELATION)&&
331             (dp.getPredicate() instanceof InclusionPredicate)&&
332             (dp.isNegated()==true))
333             return false; /* Could only satisfy this predicate */
334         return true;
335     }
336
337     /** Does the increase (or decrease) in scope of a model defintion
338      * rule represented by sn falsify the predicate dp. */
339
340     public boolean scopeinterfereswithpredicate(ScopeNode sn, DNFPredicate dp) {
341         if (!sn.getSatisfy()&&(sn.getDescriptor() instanceof SetDescriptor)) {
342             Rule r=sn.getRule();
343             Set target=r.getInclusion().getTargetDescriptors();
344             boolean match=false;
345             for(int i=0;i<r.numQuantifiers();i++) {
346                 Quantifier q=r.getQuantifier(i);
347                 if (q instanceof SetQuantifier) {
348                     SetQuantifier sq=(SetQuantifier) q;
349                     if (target.contains(sq.getSet())) {
350                         match=true;
351                         break;
352                     }
353                 }
354             }
355             if (match&&
356                 sn.getDescriptor()==dp.getPredicate().getDescriptor()&&
357                 (dp.getPredicate() instanceof ExprPredicate)&&
358                 (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.SIZE)) {
359                 boolean neg=dp.isNegated();
360                 Opcode op=((ExprPredicate)dp.getPredicate()).getOp();
361                 int size=((ExprPredicate)dp.getPredicate()).rightSize();
362                 op=Opcode.translateOpcode(neg,op);
363
364                 if ((op==Opcode.GE)&&
365                     ((size==0)||(size==1)))
366                     return false;
367                 if ((op==Opcode.GT)&&
368                     (size==0))
369                     return false;
370             }
371         }
372         return interferes(sn.getDescriptor(), sn.getSatisfy(),dp);
373     }
374
375     /** Does increasing (or decreasing if satisfy=false) the size of
376      * the set or relation des falsify the predicate dp. */
377
378     private boolean interferes(Descriptor des, boolean satisfy, DNFPredicate dp) {
379         if ((des!=dp.getPredicate().getDescriptor()) &&
380             //((des instanceof SetDescriptor)||
381             !dp.getPredicate().usesDescriptor(des))//)
382             return false;
383
384         /* This if handles all the c comparisons in the paper */
385         if (des==dp.getPredicate().getDescriptor()&&
386             (satisfy)&&
387             (dp.getPredicate() instanceof ExprPredicate)&&
388             (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.SIZE)) {
389             boolean neg2=dp.isNegated();
390             Opcode op2=((ExprPredicate)dp.getPredicate()).getOp();
391             int size2=((ExprPredicate)dp.getPredicate()).rightSize();
392             op2=Opcode.translateOpcode(neg2,op2);
393
394
395             int maxsize=termination.maxsize.getsize(dp.getPredicate().getDescriptor());
396             {
397                 if ((maxsize!=-1)&&
398                     ((op2==Opcode.LT&&size2>maxsize)||
399                      (op2==Opcode.LE&&size2>=maxsize)||
400                      (op2==Opcode.EQ&&size2>=maxsize)))
401                     return false;
402
403                 if ((op2==Opcode.GE)||
404                     (op2==Opcode.GT)||
405                     (op2==Opcode.NE)&&(size2==0))
406                     return false;
407             }
408         }
409         /* This if handles all the c comparisons in the paper */
410         if (des==dp.getPredicate().getDescriptor()&&
411             (!satisfy)&&
412             (dp.getPredicate() instanceof ExprPredicate)&&
413             (((ExprPredicate)dp.getPredicate()).getType()==ExprPredicate.SIZE)) {
414             boolean neg2=dp.isNegated();
415             Opcode op2=((ExprPredicate)dp.getPredicate()).getOp();
416             int size2=((ExprPredicate)dp.getPredicate()).rightSize();
417             op2=Opcode.translateOpcode(neg2,op2);
418             {
419                 if (((op2==Opcode.EQ)&&(size2==0))||
420                     (op2==Opcode.LE)||
421                     (op2==Opcode.LT))
422                     return false;
423             } 
424         }
425         if ((des==dp.getPredicate().getDescriptor())&&
426             satisfy&&
427             (dp.getPredicate() instanceof InclusionPredicate)&&
428             (dp.isNegated()==false))
429             return false; /* Could only satisfy this predicate */
430
431         if ((des==dp.getPredicate().getDescriptor())&&
432             (!satisfy)&&
433             (dp.getPredicate() instanceof InclusionPredicate)&&
434             (dp.isNegated()==true))
435             return false; /* Could only satisfy this predicate */
436
437         return true;
438     }
439
440     /** This method test whether satisfying (or falsifying depending
441      * on the flag satisfy) a rule that adds an object(or tuple) to
442      * the set(or relation) descriptor may increase (or decrease
443      * depending on the flag satisfyrule) the scope of a constraint or
444      * model defintion rule r.  */
445
446     static private boolean interferesquantifier(Descriptor des, boolean satisfy, Quantifiers r, boolean satisfyrule) {
447         for(int i=0;i<r.numQuantifiers();i++) {
448             Quantifier q=r.getQuantifier(i);
449             if (q instanceof RelationQuantifier||q instanceof SetQuantifier) {
450                 if (q.getRequiredDescriptors().contains(des)&&(satisfy==satisfyrule))
451                     return true;
452             } else if (q instanceof ForQuantifier) {
453                 if (q.getRequiredDescriptors().contains(des))
454                     return true;
455             } else throw new Error("Unrecognized Quantifier");
456         }
457         return false;
458     }
459
460     static public boolean interferesquantifier(AbstractRepair ar, Quantifiers q) {
461         if (ar.getType()==AbstractRepair.ADDTOSET||ar.getType()==AbstractRepair.ADDTORELATION)
462             return interferesquantifier(ar.getDescriptor(),true,q,true);
463         return false;
464     }
465
466     static public boolean interfereswithquantifier(Descriptor des, boolean satisfy, Quantifiers q) {
467         return interferesquantifier(des, satisfy, q,true);
468     }
469
470     static public boolean interfereswithrule(Descriptor des, boolean satisfy, Rule r, boolean satisfyrule) {
471         if (interferesquantifier(des,satisfy,r,satisfyrule))
472             return true;
473         /* Scan DNF form */
474         DNFRule drule=r.getDNFGuardExpr();
475         for(int i=0;i<drule.size();i++) {
476             RuleConjunction rconj=drule.get(i);
477             for(int j=0;j<rconj.size();j++) {
478                 DNFExpr dexpr=rconj.get(j);
479                 Expr expr=dexpr.getExpr();
480                 boolean negated=dexpr.getNegation();
481                 /*
482                   satisfy  negated
483                   Yes      No             Yes
484                   Yes      Yes            No
485                   No       No             No
486                   No       Yes            Yes
487                 */
488                 boolean satisfiesrule=(satisfy^negated);/*XOR of these */
489                 if (satisfiesrule==satisfyrule) {
490                     /* Effect is the one being tested for */
491                     /* Only expr's to be concerned with are TupleOfExpr and
492                        ElementOfExpr */
493                     if (expr.getRequiredDescriptors().contains(des)) {
494                         if (((expr instanceof ElementOfExpr)||
495                             (expr instanceof TupleOfExpr))&&
496                             (expr.getRequiredDescriptors().size()==1))
497                             return true;
498                         else
499                             throw new Error("Unrecognized EXPR");
500                     }
501                 }
502             }
503         }
504         return false;
505     }
506 }