5 #include "normalizer.h"
8 #include "processobject.h"
9 #include "ActionInSet.h"
10 #include "ActionNotInSet.h"
11 #include "ActionGEQ1.h"
12 #include "ActionEQ1.h"
13 #include "ActionAssign.h"
14 #include "ActionNormal.h"
20 #include "fieldcheck.h"
21 #include "Hashtable.h"
23 Repair::Repair(model *m) {
25 removedsentences=NULL;
26 List *list=new List();
27 /* list->addobject(); --build action array */
28 list->addobject(new ActionGEQ1(m->getdomainrelation(),m));
29 list->addobject(new ActionEQ1(m->getdomainrelation(),m));
30 list->addobject(new ActionAssign(m->getdomainrelation(),m));
31 // list->addobject(new ActionNotAssign(m->getdomainrelation()));
32 list->addobject(new ActionInSet(m->getdomainrelation(),m));
33 list->addobject(new ActionNotInSet(m->getdomainrelation(),m));
34 numactions=list->size();
35 repairactions=new Action *[list->size()];
36 list->toArray((void **)repairactions);
41 void Repair::repaireleexpr(Constraint *c, processobject *po, Elementexpr *ee, Hashtable *env) {
42 /* We're here because we have a bad elementexpr */
43 switch(ee->gettype()) {
46 case ELEMENTEXPR_MULT:
47 repaireleexpr(c,po,ee->getleft(),env);
48 repaireleexpr(c,po,ee->getright(),env);
50 case ELEMENTEXPR_RELATION: {
51 /* Could have problem here */
52 repaireleexpr(c,po,ee->getleft(),env);
53 Element *e=evaluateexpr(ee,env,globalmodel);
55 /* found bad relation */
56 FieldCheck *fc=globalmodel->getfieldcheck();
60 Elementexpr *left=ee->getleft();
61 int tleft=left->gettype();
62 if (tleft==ELEMENTEXPR_LABEL) {
63 set=getset(c, left->getlabel()->label());
64 } else if (tleft==ELEMENTEXPR_RELATION) {
65 DRelation *drl=globalmodel->getdomainrelation()->getrelation(left->getrelation()->getname());
69 printf("Can't determine domain-shouldn't be here because of static analysis...\n");
74 Element *e2=evaluateexpr(ee->getleft(),env,globalmodel);
75 int index=fc->getindexthatprovides(ee->getrelation()->getname(), set);
76 Hashtable *env2=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
78 Constraint *crep=globalmodel->getconstraint(index);
79 DomainRelation *dr=globalmodel->getdomainrelation();
80 for(int j=0;j<crep->numquants();j++) {
81 Quantifier *qrep=crep->getquant(j);
82 char *label=qrep->getlabel()->label();
83 char *setname=qrep->getset()->getname();
84 DomainSet *dset=dr->getset(setname);
85 if (dset->getset()->contains(e2)) {
88 env2->put(label,dset->getset()->firstelement()); /*This shouldn't happen right now*/
89 printf("Funnyness in repair.cc\n");
92 this->repairconstraint(globalmodel->getconstraint(index),po,env2);
105 void Repair::repairconstraint(Constraint *c, processobject *po, Hashtable *env) {
106 NormalForm *nf=globalmodel->getnormalform(c);
107 CoerceSentence *coercionstate=nf->closestmatch(removedsentences,po,env);
108 /* Now we just need to coerce the predicates!!!*/
109 for(int i=0;i<coercionstate->getnumpredicates();i++) {
110 CoercePredicate *cp=coercionstate->getpredicate(i);
111 int status=po->processpredicate(cp->getpredicate(),env);
112 while (status==PFAIL) {
113 /* Bad dereference...need to fix things*/
114 repaireleexpr(c, po,cp->getpredicate()->geteleexpr(), env);
115 status=po->processpredicate(cp->getpredicate(),env);
118 if (status!=cp->getcoercebool()) {
120 Action *act=findrepairaction(cp);
121 act->repairpredicate(env,cp);
122 /* Data structure fixed - well eventually*/
128 // returns the action that can repair the given predicate
129 Action * Repair::findrepairaction(CoercePredicate *cp) {
130 for(int i=0;i<numactions;i++) {
131 if (repairactions[i]->canrepairpredicate(cp))
132 return repairactions[i];
139 // returns the action that can break the given predicate
140 Action * Repair::findbreakaction(CoercePredicate *cp)
142 return findrepairaction(cp);
146 bool Repair::analyzetermination() {
147 WorkRelation *wr=new WorkRelation(true);
150 WorkSet *cycleset=searchcycles(wr);
151 if (!cycleset->isEmpty()) {
152 WorkSet *removeedges=new WorkSet(true);
153 for(int i=1;i<=cycleset->size();i++) {
154 if (breakcycles(removeedges, i, cycleset,wr)) {
155 removedsentences=removeedges;
156 printf("Modified constraints for repairability!\n");
157 outputgraph(removeedges, wr, "cycle.dot");
164 outputgraph(NULL,wr, "cycle.dot");
171 bool Repair::breakcycles(WorkSet *removeedge, int number, WorkSet *cyclelinks, WorkRelation *wr) {
172 for(CoerceSentence *cs=(CoerceSentence *)cyclelinks->firstelement();
173 cs!=NULL;cs=(CoerceSentence *)cyclelinks->getnextelement(cs)) {
174 if (!removeedge->contains(cs)) {
175 removeedge->addobject(cs);
177 if (!checkforcycles(removeedge, wr))
180 if (breakcycles(removeedge,number-1,cyclelinks,wr))
183 removeedge->removeobject(cs);
189 void Repair::outputgraph(WorkSet *removededges, WorkRelation *wr, char *filename) {
190 FILE * dotfile=fopen(filename,"w");
191 fprintf(dotfile,"digraph cyclegraph {\n");
192 fprintf(dotfile,"ratio=auto\n");
193 for(int i=0;i<globalmodel->getnumconstraints();i++) {
194 NormalForm *nf=globalmodel->getnormalform(i);
195 fprintf(dotfile, "%lu[label=\"",nf);
197 fprintf(dotfile,"\"];\n");
198 for(int j=0;j<nf->getnumsentences();j++) {
199 CoerceSentence *cs=nf->getsentence(j);
200 for(int i=0;i<cs->getnumpredicates();i++) {
201 CoercePredicate *cp=cs->getpredicate(i);
202 fprintf(dotfile,"%lu -> %lu [style=dashed]\n",nf,cp);
203 WorkSet *setofnf=wr->getset(cp);
205 NormalForm *nf2=(NormalForm*)setofnf->firstelement();
207 /* cp interferes with nf2 */
208 bool removed=(removededges!=NULL)&&removededges->contains(cs); /*tells what color of edge to generate*/
210 fprintf(dotfile,"%lu -> %lu [style=dotted]\n",cp,nf2);
212 fprintf(dotfile,"%lu -> %lu\n",cp,nf2);
213 nf2=(NormalForm *)setofnf->getnextelement(nf2);
219 fprintf(dotfile,"}\n");
223 bool Repair::checkforcycles(WorkSet *removededges, WorkRelation *wr) {
224 /* Check that there are no cycles and
225 that system is solvable */
226 for(int i=0;i<globalmodel->getnumconstraints();i++) {
227 NormalForm *nf=globalmodel->getnormalform(i);
229 for(int j=0;j<nf->getnumsentences();j++) {
230 if (!removededges->contains(nf->getsentence(j))) {
231 CoerceSentence *cs=nf->getsentence(j);
233 for(int k=0;k<cs->getnumpredicates();k++) {
234 if(cs->getpredicate(k)->isrule()&&
235 findrepairaction(cs->getpredicate(k))==NULL) {
249 WorkSet *tmpset=new WorkSet(true);
250 for(int i=0;i<globalmodel->getnumconstraints();i++) {
251 NormalForm *nf=globalmodel->getnormalform(i);
253 for(int j=0;j<nf->getnumsentences();j++) {
254 CoerceSentence *cs=nf->getsentence(j);
255 if (checkcycles(cs,removededges,tmpset,wr)) {
262 return false; /*yeah...no cycles*/
267 bool Repair::checkcycles(CoerceSentence *cs,WorkSet *removededges, WorkSet *searchset,WorkRelation *wr) {
268 if (searchset->contains(cs)) {
272 if (removededges->contains(cs))
273 return false; /* this edge is removed...don't consider it*/
275 searchset->addobject(cs);
276 for(int i=0;i<cs->getnumpredicates();i++) {
277 CoercePredicate *cp=cs->getpredicate(i);
278 WorkSet *setofnf=wr->getset(cp);
280 /* Might not mess up anything */
281 NormalForm *nf=(NormalForm*)setofnf->firstelement();
283 for(int j=0;j<nf->getnumsentences();j++) {
284 CoerceSentence *cssearch=nf->getsentence(j);
285 if (checkcycles(cssearch, removededges, searchset, wr))
288 nf=(NormalForm *)setofnf->getnextelement(nf);
292 searchset->removeobject(cs);
298 WorkSet * Repair::searchcycles(WorkRelation *wr) {
299 /* Do cycle search */
300 WorkSet *cycleset=new WorkSet(true);
301 WorkSet *searchset=new WorkSet(true);
302 for(int i=0;i<globalmodel->getnumconstraints();i++) {
303 NormalForm *nf=globalmodel->getnormalform(i);
304 for(int j=0;j<nf->getnumsentences();j++) {
305 detectcycles(nf->getsentence(j),searchset,cycleset,wr);
314 void Repair::detectcycles(CoerceSentence *cs,WorkSet *searchset,WorkSet *cycleset, WorkRelation *wr) {
315 if (searchset->contains(cs)) {
317 CoerceSentence *csptr=(CoerceSentence *)searchset->firstelement();
319 cycleset->addobject(csptr);
320 csptr=(CoerceSentence *)searchset->getnextelement(csptr);
324 searchset->addobject(cs);
325 for(int i=0;i<cs->getnumpredicates();i++) {
326 CoercePredicate *cp=cs->getpredicate(i);
327 WorkSet *setofnf=wr->getset(cp);
329 /* Might not have any interference edges*/
330 NormalForm *nf=(NormalForm*)setofnf->firstelement();
332 for(int j=0;j<nf->getnumsentences();j++) {
333 CoerceSentence *cssearch=nf->getsentence(j);
334 detectcycles(cssearch, searchset, cycleset, wr);
336 nf=(NormalForm*)setofnf->getnextelement(nf);
340 searchset->removeobject(cs);
345 void Repair::buildmap(WorkRelation *wr) {
346 for(int i=0;i<globalmodel->getnumconstraints();i++) {
347 NormalForm *nf=globalmodel->getnormalform(i);
348 for(int j=0;j<nf->getnumsentences();j++) {
349 CoerceSentence *cs=nf->getsentence(j);
350 for (int k=0;k<cs->getnumpredicates();k++) {
351 Action *repairaction=findrepairaction(cs->getpredicate(k));
352 if (repairaction==NULL) {
353 /* Nothing will repair this */
354 cs->getpredicate(k)->getpredicate()->print();
355 printf(" can't be repaired!!!");
358 checkpredicate(repairaction,wr, globalmodel->getconstraint(i),cs->getpredicate(k));
362 ActionNormal *repairnormal=new ActionNormal(globalmodel);
363 for(int i=0;i<globalmodel->getnumrulenormal();i++) {
364 NormalForm *nf=globalmodel->getrulenormal(i);
365 CoercePredicate *cpo=nf->getsentence(0)->getpredicate(0);
366 /* Check for conflicts between abstraction functions */
367 for(int j=0;j<globalmodel->getnumrulenormal();j++) {
368 NormalForm *nfn=globalmodel->getrulenormal(j);
369 CoercePredicate *cpn=nfn->getsentence(0)->getpredicate(0);
370 if (!cpo->istuple()&&
371 equivalentstrings(cpo->getrelset(),cpn->gettriggerset()))
375 /* Check for conflict between abstraction functions and model constraints */
376 for(int i2=0;i2<globalmodel->getnumconstraints();i2++) {
377 NormalForm *nf2=globalmodel->getnormalform(i2);
378 for(int j2=0;j2<nf2->getnumsentences();j2++) {
379 CoerceSentence *cs2=nf2->getsentence(j2);
380 for (int k2=0;k2<cs2->getnumpredicates();k2++) {
381 if (repairnormal->conflict(NULL,cpo,globalmodel->getconstraint(i2),cs2->getpredicate(k2)))
387 delete(repairnormal);
392 void Repair::checkpredicate(Action *repair,WorkRelation *wr, Constraint *c,CoercePredicate *cp) {
393 for(int i=0;i<globalmodel->getnumconstraints();i++) {
394 NormalForm *nf=globalmodel->getnormalform(i);
395 for(int j=0;j<nf->getnumsentences();j++) {
396 CoerceSentence *cs=nf->getsentence(j);
397 for (int k=0;k<cs->getnumpredicates();k++) {
398 if (repair->conflict(c,cp,globalmodel->getconstraint(i),cs->getpredicate(k)))
403 for(int i=0;i<globalmodel->getnumrulenormal();i++) {
404 NormalForm *nf=globalmodel->getrulenormal(i);
405 if (repair->conflict(c,cp,NULL, nf->getsentence(0)->getpredicate(0)))