Moved makelib
[repair.git] / Repair / RepairInterpreter / ActionEQ1.cc
1 // Repairs and destroys size propositions of the form "size(SE)=1"
2
3 #include <assert.h>
4 #include "ActionEQ1.h"
5 #include "dmodel.h"
6 #include "normalizer.h"
7 #include "omodel.h"
8 #include "model.h"
9 #include "Relation.h"
10 #include "set.h"
11 #include "Hashtable.h"
12 #include "Guidance.h"
13
14 ActionEQ1::ActionEQ1(DomainRelation *drel, model *m) {
15   domrelation=drel;
16   globalmodel=m;
17 }
18
19 void ActionEQ1::repairpredicate(Hashtable *env,CoercePredicate *p) {
20   switch(p->getpredicate()->getsetexpr()->gettype()) {  
21   // size(S)=1
22   case SETEXPR_LABEL: { 
23     char *setname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
24     DomainSet *ds=domrelation->getset(setname);
25     if (ds->getset()->size()>1) {
26       Guidance *g=globalmodel->getguidance();
27       WorkSet *ws=ds->getset();
28       while(ws->size()>1) {
29         Element *e=(Element *)ws->firstelement();
30         domrelation->delfromsetmovetoset(e,domrelation->getset(setname), globalmodel);
31       }
32     } else
33       this->ActionGEQ1::repairpredicate(env,p);
34   }
35   break;
36
37   // size(V.R)=1
38   case SETEXPR_REL: { 
39     DRelation *dr=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname());
40     WorkRelation *wr=dr->getrelation();
41     Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
42     WorkSet *ws=wr->getset(key);
43
44     if (ws!=NULL&&ws->size()>1) {
45       //Remove elements
46       int size=ws->size();
47       for(int i=0;i<(size-1);i++) {
48         void *objtoremove=ws->firstelement();
49         wr->remove(key,objtoremove);
50       }
51     } else
52       this->ActionGEQ1::repairpredicate(env,p);
53   }
54   break;
55
56   // size(R.V)=1
57   case SETEXPR_INVREL: {
58     DRelation *dr=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname());
59     WorkRelation *wr=dr->getrelation();
60     Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
61     WorkSet *ws=wr->invgetset(key);
62
63     if (ws!=NULL&&ws->size()>1) {
64       //Remove elements
65       int size=ws->size();
66       for(int i=0;i<(size-1);i++) {
67         void *objtoremove=ws->firstelement();
68         wr->remove(objtoremove,key);
69       }
70     } else 
71       this->ActionGEQ1::repairpredicate(env,p);
72   }
73   break;
74   }
75 }
76
77
78
79
80 void ActionEQ1::breakpredicate(Hashtable *env, CoercePredicate *p)
81 {
82 #ifdef DEBUGMESSAGES
83   printf("ActionEQ1::breakpredicate CALLED\n");
84   p->getpredicate()->print(); printf("\n");
85 #endif
86
87   this->ActionGEQ1::breakpredicate(env, p);
88 }
89
90
91
92
93 bool ActionEQ1::conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2) {
94   assert(canrepairpredicate(p1));
95   Setexpr *pse=p1->getpredicate()->getsetexpr();
96   if(comparepredicates(c1,p1,c2,p2))
97     return false; /*same predicates don't conflict*/
98
99   switch(pse->gettype()) {
100   case SETEXPR_LABEL: {
101     char *boundname=NULL;
102     Guidance *g=globalmodel->getguidance();
103     //DomainSet *fromset=domrelation->getsource(domrelation->getset(pse->getsetlabel()->getname()));
104     char *setname=pse->getsetlabel()->getname();
105     
106     DomainSet *fromset=domrelation->getset(setname);
107
108     {
109       Source s=g->sourceforsetsize(fromset->getname());
110       if (s.setname!=NULL)
111         boundname=s.setname;
112     }
113
114     {
115       /* See what additional addsets we get*/
116
117       WorkSet *ws=domrelation->conflictaddsets(pse->getsetlabel()->getname(),boundname,globalmodel);
118       DomainSet *ds=(DomainSet *) ws->firstelement();
119       while(ds!=NULL) {
120         if (conflictwithaddtoset(ds->getname(),c2,p2)) {
121           delete(ws);
122           return true;
123         }
124         ds=(DomainSet *) ws->getnextelement(ds);
125       }
126       delete(ws);
127     }
128     {
129       /* What additions do we get from removal */
130       WorkSet *ws=domrelation->removeconflictaddsets(pse->getsetlabel()->getname(),globalmodel);
131       DomainSet *ds=(DomainSet *) ws->firstelement();
132       while(ds!=NULL) {
133         if (conflictwithaddtoset(ds->getname(),c2,p2)) {
134           delete(ws);
135           return true;
136         }
137         ds=(DomainSet *) ws->getnextelement(ds);
138       }
139       delete(ws);
140     }
141
142     /* Check what removals addition into set can cause */
143     if (boundname!=NULL) {
144       WorkSet *ws=domrelation->conflictdelsets(pse->getsetlabel()->getname(), boundname);
145       DomainSet *ds=(DomainSet *) ws->firstelement();
146       while (ds!=NULL) {
147         if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
148           delete(ws);
149           return true;
150         }
151         ds=(DomainSet *) ws->getnextelement(ds);
152       }
153       delete(ws);
154     }
155     /* What sets will removal cause removal from */
156     {
157       WorkSet *ws=domrelation->removeconflictdelsets(pse->getsetlabel()->getname());
158       DomainSet *ds=(DomainSet *) ws->firstelement();
159       while (ds!=NULL) {
160         if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
161           delete(ws);
162           return true;
163         }
164         ds=(DomainSet *) ws->getnextelement(ds);
165       }
166       delete(ws);
167     }
168     return false;
169   }
170   case SETEXPR_REL: {
171     char *fromname=NULL;
172     /* we have a in v.r */
173     /* add <v,a> to r */
174     if (p2->isrule()&&
175         (p2->getpredicate()->gettype()==PREDICATE_GTE1||
176          p2->getpredicate()->gettype()==PREDICATE_EQ1)&&
177         p2->getpredicate()->getsetexpr()->gettype()==SETEXPR_REL) {
178       return false; 
179     }
180
181     /* Compute bounding set if there is one */
182     
183
184     DomainRelation *drel=globalmodel->getdomainrelation();
185     char *insertset=drel->getrelation(pse->getrelation()->getname())->getrange();
186     Guidance *g=globalmodel->getguidance();
187     Source s=g->sourceforsetsize(insertset);
188
189
190     /* Check conflicts arrising from addition to set */
191     {
192       WorkSet *ws=domrelation->conflictaddsets(insertset,s.setname,globalmodel);
193       DomainSet *ds=(DomainSet *) ws->firstelement();
194       while(ds!=NULL) {
195         if (conflictwithaddtoset(ds->getname(),c2,p2)) {
196           delete(ws);
197           return true;
198         }
199         ds=(DomainSet *) ws->getnextelement(ds);
200       }
201       delete(ws);
202     }
203     /* Check conflicts arrising from deletions from set */
204     {
205       WorkSet *ws=domrelation->conflictdelsets(insertset, s.setname);    
206       DomainSet *ds=(DomainSet *) ws->firstelement();
207       while (ds!=NULL) {
208         if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
209           delete(ws);
210           return true;
211         }
212         ds=(DomainSet *) ws->getnextelement(ds);
213       }
214       delete(ws);
215     }
216
217
218     return testforconflict(getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()), fromname,
219                            p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2)||testforconflictremove(getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()), fromname,
220                                                                                                                     p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
221   }
222   case SETEXPR_INVREL: {
223     char *fromname=NULL;
224     /* we have a in v.r */
225     /* add <a,v> to r */
226     if (p2->isrule()&&
227         (p2->getpredicate()->gettype()==PREDICATE_GTE1||
228          p2->getpredicate()->gettype()==PREDICATE_EQ1)&&
229         p2->getpredicate()->getsetexpr()->gettype()==SETEXPR_INVREL) {
230       return false;
231     }
232
233     /* Compute bounding set if there is one */
234     
235
236     DomainRelation *drel=globalmodel->getdomainrelation();
237     char *insertset=drel->getrelation(pse->getrelation()->getname())->getdomain();
238     Guidance *g=globalmodel->getguidance();
239     Source s=g->sourceforsetsize(insertset);
240
241
242     /* Check conflicts arrising from addition to set */
243     {
244       WorkSet *ws=domrelation->conflictaddsets(insertset,s.setname,globalmodel);
245       DomainSet *ds=(DomainSet *) ws->firstelement();
246       while(ds!=NULL) {
247         if (conflictwithaddtoset(ds->getname(),c2,p2)) {
248           delete(ws);
249           return true;
250         }
251         ds=(DomainSet *) ws->getnextelement(ds);
252       }
253       delete(ws);
254     }
255     /* Check conflicts arrising from deletions from set */
256     {
257       WorkSet *ws=domrelation->conflictdelsets(insertset, s.setname);    
258       DomainSet *ds=(DomainSet *) ws->firstelement();
259       while (ds!=NULL) {
260         if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
261           delete(ws);
262           return true;
263         }
264         ds=(DomainSet *) ws->getnextelement(ds);
265       }
266       delete(ws);
267     }
268
269     return testforconflict(fromname,
270                            getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
271                            p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2)||
272       testforconflictremove(fromname,
273                             getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
274                             p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
275   }
276   }
277 }
278
279
280
281
282 bool ActionEQ1::canrepairpredicate(CoercePredicate *cp) {
283   if (cp->getcoercebool()==false)
284     return false;
285   Predicate *p=cp->getpredicate();
286
287
288   if (p->gettype()!=PREDICATE_EQ1)
289     return false;
290
291   /* Coercing set membership */
292   Setexpr *se=p->getsetexpr();
293   int setexprtype=se->gettype();
294   if (setexprtype==SETEXPR_REL||
295       setexprtype==SETEXPR_INVREL) {
296     DRelation *dr=domrelation->getrelation(se->getrelation()->getname());
297     if (dr->isstatic())
298       return false; /* Can't change static domain relations */
299   }
300
301   return true;
302 }