Hack grammar to add unary minus.
[repair.git] / Repair / RepairInterpreter / ActionGEQ1.cc
1 #include <stdlib.h>
2 #include <assert.h>
3 #include "ActionGEQ1.h"
4 #include "dmodel.h"
5 #include "normalizer.h"
6 #include "omodel.h"
7 #include "model.h"
8 #include "Relation.h"
9 #include "set.h"
10 #include "element.h"
11 #include "Hashtable.h"
12 #include "Guidance.h"
13
14
15 ActionGEQ1::ActionGEQ1(DomainRelation *drel, model *m) {
16   domrelation=drel;
17   globalmodel=m;
18 }
19
20 void ActionGEQ1::repairpredicate(Hashtable *env,CoercePredicate *p) {
21 #ifdef DEBUGMESSAGES
22   printf("ActionGEQ1::repairpredicate CALLED\n");
23   fflush(NULL);
24 #endif
25   switch(p->getpredicate()->getsetexpr()->gettype()) {
26   case SETEXPR_LABEL: {
27     /* Set should be too small if we are doing a repair
28        We need to add 1 element */
29     Guidance *g=globalmodel->getguidance();
30     char * newsetname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
31     Source s=g->sourceforsetsize(newsetname);
32     if (s.setname!=NULL) {
33       /* just pick an element from s.setname */
34       char *setname=s.setname;
35       if (equivalentstrings(s.setname,"int")) {
36         /* special case for ints*/
37         WorkSet *wsnew=domrelation->getset(newsetname)->getset();
38         for(int i=0;;i++) {
39           Element *e=new Element(i);
40           if (!wsnew->contains(e)) {
41             /* Got our element */
42             domrelation->addtoset(e,domrelation->getset(newsetname),globalmodel);
43             return;
44           }
45           delete(e);
46         }
47       } else {
48         WorkSet *ws=domrelation->getset(setname)->getset();
49         WorkSet *wsnew=domrelation->getset(newsetname)->getset();
50         Element *e=(Element *)ws->firstelement();
51         while(e!=NULL) {
52           if (!wsnew->contains(e)) {
53             /* Got our element */
54             domrelation->addtoset(e,domrelation->getset(newsetname),globalmodel);
55             //printf("HERE?!\n"); fflush(NULL);
56             return;
57           }
58           e=(Element *)ws->getnextelement(e);
59         }
60         printf("Error...set %s doesn't have enough elements for %s\n",setname,newsetname);
61         exit(-1);
62       }
63     } else {
64       /* call functionpointer */
65       DomainSet *newset=domrelation->getset(newsetname);
66       char *type=newset->getelementtype();
67       structure *st=globalmodel->getstructure(type);
68       Element *ele=s.functionptr(st,globalmodel);
69       if (ele==NULL) {
70         printf("Error...allocation function doesn't return structure for %s\n",newsetname);
71         exit(-1);
72       }
73       domrelation->addtoset(ele,newset,globalmodel);
74       return;
75     }
76   }
77   break;
78
79
80
81   case SETEXPR_REL: {
82     /* Set should be too small if we are doing a repair
83        We need to add 1 element */
84     Guidance *g=globalmodel->getguidance();
85     char * relationname=p->getpredicate()->getsetexpr()->getrelation()->getname();
86     Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
87     DRelation *relation=domrelation->getrelation(relationname);
88     char *rangeset=relation->getrange();
89     Source s=g->sourceforrelation(rangeset);
90     if (s.setname!=NULL) {
91       /* just pick an element from s.setname */
92       char *setname=s.setname;
93       if (equivalentstrings(s.setname,"int")) {
94         /* special case for ints*/
95         for(int i=0;;i++) {
96           WorkSet *wsnew=domrelation->getrelation(relationname)->getrelation()->getset(key);
97           Element *e=new Element(i);
98           if (wsnew==NULL||!wsnew->contains(e)) {
99             /* Got our element */
100             domrelation->addtoset(e,domrelation->getset(rangeset),globalmodel);
101             relation->getrelation()->put(key,e);
102             return;
103           }
104           delete(e);
105         }
106       } else {
107         WorkSet *ws=domrelation->getset(s.setname)->getset();
108         Element *e=(Element *)ws->firstelement();
109         while(e!=NULL) {
110           WorkSet *wsnew=domrelation->getrelation(relationname)->getrelation()->getset(key);
111           if (wsnew==NULL||!wsnew->contains(e)) {
112             /* Got our element */
113             domrelation->addtoset(e,domrelation->getset(rangeset),globalmodel);
114             relation->getrelation()->put(key,e);
115             return;
116           }
117           e=(Element *)ws->getnextelement(e);
118         }
119         printf("Error...set %s doesn't have enough elements for relation\n",setname);
120         exit(-1);
121       }
122     } else {
123       /* call functionpointer */
124       DomainSet *newset=domrelation->getset(rangeset);
125       char *type=newset->getelementtype();
126       structure *st=globalmodel->getstructure(type);
127       Element *ele=s.functionptr(st,globalmodel);
128       if (ele==NULL) {
129         printf("Error...allocation function doesn't return structure for %s\n",rangeset);
130         exit(-1);
131       }
132       domrelation->addtoset(ele,domrelation->getset(rangeset),globalmodel);
133       relation->getrelation()->put(key,ele);
134       return;
135     }
136   }
137
138   
139   break;
140   case SETEXPR_INVREL: {
141     /* Set should be too small if we are doing a repair
142        We need to add 1 element */
143     Guidance *g=globalmodel->getguidance();
144     char * relationname=p->getpredicate()->getsetexpr()->getrelation()->getname();
145     Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
146     DRelation *relation=domrelation->getrelation(relationname);
147     char *domainset=relation->getdomain();
148     Source s=g->sourceforrelation(domainset);
149     if (s.setname!=NULL) {
150       /* just pick an element from s.setname */
151       char *setname=s.setname;
152       if (equivalentstrings(s.setname,"int")) {
153         /* special case for ints*/
154         for(int i=0;;i++) {
155           Element *e=new Element(i);
156           WorkSet *wsnew=domrelation->getrelation(relationname)->getrelation()->invgetset(key);
157           if (wsnew==NULL||!wsnew->contains(e)) {
158             /* Got our element */
159             domrelation->addtoset(e,domrelation->getset(domainset),globalmodel);
160             relation->getrelation()->put(e,key);
161             return;
162           }
163           delete(e);
164         }
165       } else {
166         WorkSet *ws=domrelation->getset(s.setname)->getset();
167         Element *e=(Element *)ws->firstelement();
168         while(e!=NULL) {
169           WorkSet *wsnew=domrelation->getrelation(relationname)->getrelation()->invgetset(key);
170           if (wsnew==NULL||!wsnew->contains(e)) {
171             /* Got our element */
172             domrelation->addtoset(e,domrelation->getset(domainset),globalmodel);
173             relation->getrelation()->put(e,key);
174             return;
175           }
176           e=(Element *)ws->getnextelement(e);
177         }
178         printf("Error...set %s doesn't have enough elements for relation\n",setname);
179         exit(-1);
180       }
181     } else {
182       /* call functionpointer */
183       DomainSet *newset=domrelation->getset(domainset);
184       char *type=newset->getelementtype();
185       structure *st=globalmodel->getstructure(type);
186       Element *ele=s.functionptr(st,globalmodel);
187       if (ele==NULL) {
188         printf("Error...allocation function doesn't return structure for %s\n",domainset);
189         exit(-1);
190       }
191       domrelation->addtoset(ele,domrelation->getset(domainset),globalmodel);
192       relation->getrelation()->put(ele,key);
193       return;
194     }
195   }
196   break;
197   }
198 }
199
200
201
202
203 void ActionGEQ1::breakpredicate(Hashtable *env, CoercePredicate *p)
204 {
205 #ifdef DEBUGMESSAGES
206   printf("ActionGEQ1::breakpredicate CALLED\n");
207   p->getpredicate()->print(); printf("\n");
208 #endif
209  
210   switch(p->getpredicate()->getsetexpr()->gettype()) {  
211   // size(S)>=1
212   case SETEXPR_LABEL: 
213     { 
214 #ifdef DEBUGMESSAGES      
215       printf("LABEL\n");
216 #endif
217
218       char *setname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
219       DomainSet *ds=domrelation->getset(setname); //S
220
221       // simply delete all elements that S currently contains
222       Guidance *g=globalmodel->getguidance();
223       WorkSet *ws=ds->getset();
224       while(ws->size()>0) 
225         {
226           Element *e=(Element *)ws->firstelement();
227           domrelation->delfromsetmovetoset(e,domrelation->getset(setname), globalmodel);
228         }
229     }
230     break;
231       
232
233     // size(V.R)>=1
234     case SETEXPR_REL: 
235       {
236 #ifdef DEBUGMESSAGES
237         printf("REL\n");
238 #endif
239
240         DRelation *dr=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname());
241         WorkRelation *wr=dr->getrelation(); //R
242         Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label()); //V
243         WorkSet *ws=wr->getset(key); //V.R
244         
245         // simply delete all elements that V.R currently contains
246         int size=ws->size();
247         for(int i=0; i<size; i++)         
248           {
249             void *objtoremove=ws->firstelement();
250             wr->remove(key, objtoremove);
251           }
252       }
253       break;
254     
255     // size(R.V)=1
256     case SETEXPR_INVREL:
257       {
258 #ifdef DEBUGMESSAGES
259         printf("INVREL\n");
260 #endif
261
262         DRelation *dr=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname());
263         //dr->print(); printf("\n");
264         WorkRelation *wr=dr->getrelation(); //R 
265         Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label()); //V
266         WorkSet *ws=wr->invgetset(key); //R.V
267
268 #ifdef DEBUGMESSAGES
269         printf("ws size = %d\n", ws->size());
270 #endif
271
272         // simply delete all elements that R.V currently contains
273         int size=ws->size();
274         for(int i=0; i<size; i++)         
275           {
276             void *objtoremove = ws->firstelement();
277             wr->remove(objtoremove, key);
278           }
279
280 #ifdef DEBUGMESSAGES
281         printf("INVREL finished\n");
282 #endif
283       }
284       break;
285   } 
286 }
287   
288
289
290 bool ActionGEQ1::conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2) {
291   assert(canrepairpredicate(p1));
292   Setexpr *pse=p1->getpredicate()->getsetexpr();
293   if(comparepredicates(c1,p1,c2,p2))
294     return false; /*same predicates don't conflict*/
295   char *fromname=NULL;
296   DomainSet *fromset=domrelation->getsource(domrelation->getset(pse->getsetlabel()->getname()));
297   if (fromset!=NULL)
298     fromname=fromset->getname();
299   /* FIXME: fromname should cycle through set of possibilities ...
300      if it is null, it should be replaced with the type name the object will have for the REL tests...this is okay already for the label tests...
301   */
302
303   switch(pse->gettype()) {
304   case SETEXPR_LABEL: {
305     char *boundname=NULL;
306     Guidance *g=globalmodel->getguidance();
307     DomainSet *fromset=domrelation->getsource(domrelation->getset(pse->getsetlabel()->getname()));
308
309     if (fromset!=NULL) {
310       Source s=g->sourceforsetsize(fromset->getname());
311       if (s.setname!=NULL)
312         boundname=s.setname;
313     }
314     char *setname=pse->getsetlabel()->getname();
315
316     {
317       WorkSet *ws=domrelation->conflictaddsets(pse->getsetlabel()->getname(),boundname,globalmodel);
318       DomainSet *ds=(DomainSet *) ws->firstelement();
319       while(ds!=NULL) {
320         if (conflictwithaddtoset(ds->getname(),c2,p2)) {
321           delete(ws);
322           return true;
323         }
324         ds=(DomainSet *) ws->getnextelement(ds);
325       }
326       delete(ws);
327     }
328     /* Check conflicts arrising from deletions from set */
329     {
330       WorkSet *ws=domrelation->conflictdelsets(pse->getsetlabel()->getname(), boundname);
331       DomainSet *ds=(DomainSet *) ws->firstelement();
332       while (ds!=NULL) {
333         if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
334           delete(ws);
335           return true;
336         }
337         ds=(DomainSet *) ws->getnextelement(ds);
338       }
339       delete(ws);
340     }
341     return false;
342   }
343
344   case SETEXPR_REL: {
345     /* we have a in v.r */
346     /* add <v,a> to r */
347     if (p2->isrule()&&
348         (p2->getpredicate()->gettype()==PREDICATE_GTE1||
349          p2->getpredicate()->gettype()==PREDICATE_EQ1)&&
350         p2->getpredicate()->getsetexpr()->gettype()==SETEXPR_REL) {
351       return false; 
352     }
353     /* Compute bounding set if there is one */
354     
355
356     DomainRelation *drel=globalmodel->getdomainrelation();
357     char *insertset=drel->getrelation(pse->getrelation()->getname())->getrange();
358     Guidance *g=globalmodel->getguidance();
359     Source s=g->sourceforsetsize(insertset);
360
361
362     /* Check conflicts arrising from addition to set */
363     {
364       WorkSet *ws=domrelation->conflictaddsets(insertset,s.setname,globalmodel);
365       DomainSet *ds=(DomainSet *) ws->firstelement();
366       while(ds!=NULL) {
367         if (conflictwithaddtoset(ds->getname(),c2,p2)) {
368           delete(ws);
369           return true;
370         }
371         ds=(DomainSet *) ws->getnextelement(ds);
372       }
373       delete(ws);
374     }
375     /* Check conflicts arrising from deletions from set */
376     {
377       WorkSet *ws=domrelation->conflictdelsets(insertset, s.setname);    
378       DomainSet *ds=(DomainSet *) ws->firstelement();
379       while (ds!=NULL) {
380         if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
381           delete(ws);
382           return true;
383         }
384         ds=(DomainSet *) ws->getnextelement(ds);
385       }
386       delete(ws);
387     }
388
389
390     return testforconflict(getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
391                            fromname,
392                            p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
393   }
394   case SETEXPR_INVREL: {
395     /* we have a in v.r */
396     /* add <a,v> to r */
397     if (p2->isrule()&&
398         (p2->getpredicate()->gettype()==PREDICATE_GTE1||
399          p2->getpredicate()->gettype()==PREDICATE_EQ1)&&
400         p2->getpredicate()->getsetexpr()->gettype()==SETEXPR_INVREL) {
401       return false;
402     }
403     /* Compute bounding set if there is one */
404     
405
406     DomainRelation *drel=globalmodel->getdomainrelation();
407     char *insertset=drel->getrelation(pse->getrelation()->getname())->getdomain();
408     Guidance *g=globalmodel->getguidance();
409     Source s=g->sourceforsetsize(insertset);
410
411
412     /* Check conflicts arrising from addition to set */
413     {
414       WorkSet *ws=domrelation->conflictaddsets(insertset,s.setname,globalmodel);
415       DomainSet *ds=(DomainSet *) ws->firstelement();
416       while(ds!=NULL) {
417         if (conflictwithaddtoset(ds->getname(),c2,p2)) {
418           delete(ws);
419           return true;
420         }
421         ds=(DomainSet *) ws->getnextelement(ds);
422       }
423       delete(ws);
424     }
425     /* Check conflicts arrising from deletions from set */
426     {
427       WorkSet *ws=domrelation->conflictdelsets(insertset, s.setname);    
428       DomainSet *ds=(DomainSet *) ws->firstelement();
429       while (ds!=NULL) {
430         if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
431           delete(ws);
432           return true;
433         }
434         ds=(DomainSet *) ws->getnextelement(ds);
435       }
436       delete(ws);
437     }
438
439     return testforconflict(fromname,
440                            getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
441                            p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
442   }
443   }
444 }
445
446 bool ActionGEQ1::canrepairpredicate(CoercePredicate *cp) {
447   if (cp->getcoercebool()==false)
448     return false;
449   Predicate *p=cp->getpredicate();
450   
451   if (p->gettype()!=PREDICATE_GTE1)
452     return false;
453
454   Setexpr *se=p->getsetexpr();
455   int setexprtype=se->gettype();
456   if (setexprtype==SETEXPR_REL||
457       setexprtype==SETEXPR_INVREL) {
458     DRelation *dr=domrelation->getrelation(se->getrelation()->getname());
459     if (dr->isstatic())
460       return false; /* Can't change static domain relations */
461   }
462
463   /* Coercing set membership */
464   return true;
465 }