Moved the interpreter
[repair.git] / Repair / RepairInterpreter / dmodel.cc
diff --git a/Repair/RepairInterpreter/dmodel.cc b/Repair/RepairInterpreter/dmodel.cc
new file mode 100755 (executable)
index 0000000..f26fc78
--- /dev/null
@@ -0,0 +1,609 @@
+// defines the sets and the relations used
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "dmodel.h"
+#include "set.h"
+#include "Relation.h"
+#include "Hashtable.h"
+#include "model.h"
+#include "Guidance.h"
+
+
+// class DomainSet
+
+DomainSet::DomainSet(char *name) {
+  setname=name;
+  flag=0;
+  this->type=NULL;
+  numsubsets=0;
+  subsets=NULL;
+  set=new WorkSet();
+}
+
+void DomainSet::reset() {
+  delete(set);
+  set=new WorkSet();
+}
+
+char * DomainSet::getelementtype() {
+  return type;
+}
+
+int DomainSet::gettype() {
+  return flag%DOMAINSET_TYPED;
+}
+
+void DomainSet::settype(char *type) {
+  this->type=type;
+  flag|=DOMAINSET_TYPED;
+}
+  
+void DomainSet::setsubsets(char **subsets, int numsubsets) {
+  this->subsets=subsets;
+  this->numsubsets=numsubsets;
+  flag=DOMAINSET_SUBSET;
+}
+
+void DomainSet::setpartition(char **subsets, int numsubsets) {
+  this->subsets=subsets;
+  this->numsubsets=numsubsets;
+  flag=DOMAINSET_PARTITION;
+}
+void DomainSet::print() {
+  printf("%s",setname);
+  if (DOMAINSET_TYPED&flag)
+    printf("(%s)",type);
+  printf(":");
+  if (DOMAINSET_PARTITION&flag)
+    printf("partition ");
+  for(int i=0;i<numsubsets;i++)
+    if (i==0)
+      printf("%s ",subsets[i]);
+    else
+      printf("| %s",subsets[i]);
+  printf("Size: %d",set->size());
+}
+
+char * DomainSet::getname() {
+  return setname;
+}
+WorkSet * DomainSet::getset() {
+  return set;
+}
+
+int DomainSet::getnumsubsets() {
+  return numsubsets;
+}
+
+char * DomainSet::getsubset(int i) {
+  return subsets[i];
+}
+
+
+
+
+// class DRelation
+
+DRelation::DRelation(char *n, char *d, char *r, int t, bool b) {
+  domain=d;range=r;type=t;name=n;
+  relation=new WorkRelation();
+  staticrel=b;
+  tokenrange = NULL;
+}
+
+void DRelation::reset() {
+  delete(relation);
+  relation=new WorkRelation();
+}
+
+bool DRelation::isstatic() {
+  return staticrel;
+}
+
+char * DRelation::getdomain() {
+  return domain;
+}
+
+char * DRelation::getrange() {
+  return range;
+}
+
+WorkSet* DRelation::gettokenrange() {
+  return tokenrange;
+}
+
+void DRelation::settokenrange(WorkSet *ws) {
+  tokenrange = ws;
+}
+
+
+
+void DRelation::print() {
+  printf("%s: %s -> %s (",name,domain,range);
+  if (type&DRELATION_MANYDOMAIN)
+    printf("M");
+  else
+    printf("1");
+  printf("->");
+  if (type&DRELATION_MANYRANGE)
+    printf("M");
+  else
+    printf("1");
+  printf(")");
+
+}
+
+char * DRelation::getname() {
+  return name;
+}
+
+WorkRelation * DRelation::getrelation() {
+  return relation;
+}
+
+
+
+
+// class DomainRelation
+
+DomainRelation::DomainRelation(DomainSet **s, int ns, DRelation **r,int nr) {
+  sets=s; numsets=ns;
+  relations=r;numrelations=nr;
+  settable=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
+  relationtable=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
+  for(int i=0;i<numsets;i++)
+    settable->put(sets[i]->getname(),sets[i]);
+  for(int i=0;i<numrelations;i++)
+    relationtable->put(relations[i]->getname(),relations[i]);
+}
+
+void DomainRelation::reset() {
+  for(int i=0;i<numsets;i++) {
+    sets[i]->reset();
+  }
+  for(int i=0;i<numrelations;i++) {
+    relations[i]->reset();
+  }
+}
+
+bool DomainRelation::issupersetof(DomainSet *sub,DomainSet *super) {
+  while(sub!=NULL) {
+    if (sub==super)
+      return true;
+    sub=getsuperset(sub);
+  }
+  return false;
+}
+
+void DomainRelation::print() {
+  for(int i=0;i<numsets;i++) {
+    sets[i]->print();
+    printf("\n");
+  }
+  printf("\n");
+  for(int i=0;i<numrelations;i++) {
+    relations[i]->print();
+    printf("\n");
+  }
+}
+
+DomainSet * DomainRelation::getset(char * setname) {
+  if (setname!=NULL)
+    return (DomainSet *)settable->get(setname);
+  else return NULL;
+}
+
+DRelation * DomainRelation::getrelation(char * relationname) {
+  if (relationname!=NULL)
+    return (DRelation *)relationtable->get(relationname);
+  else
+    return NULL;
+}
+
+DomainRelation::~DomainRelation() {
+  delete(settable);
+  delete(relationtable);
+  for(int i=0;i<numsets;i++)
+    delete(sets[i]);
+  for(int i=0;i<numrelations;i++)
+    delete(relations[i]);
+  delete(sets);
+  delete(relations);
+}
+
+void DomainRelation::addallsubsets(DomainSet *ds, WorkSet *ws) {
+  WorkSet *tmp=new WorkSet(true);
+  tmp->addobject(ds);
+  while(!tmp->isEmpty()) {
+    DomainSet *s=(DomainSet *)tmp->firstelement();
+    tmp->removeobject(s);
+    ws->addobject(s);
+    for(int j=0;j<s->getnumsubsets();j++) {
+      tmp->addobject(getset(s->getsubset(j)));
+    }
+  }
+  delete(tmp);
+}
+
+WorkSet * DomainRelation::conflictdelsets(char * setname, char * boundset) {
+  /* Want to know what set removals insertion into "setname" could cause */
+  if (equivalentstrings(setname,"int"))
+    return new WorkSet(true);
+  if (equivalentstrings(setname,"token"))
+    return new WorkSet(true);
+  DomainSet *bs=getset(boundset);
+  WorkSet *wsret=new WorkSet(true);
+  WorkSet *ws=new WorkSet(true);
+  while(bs!=NULL) {
+    ws->addobject(bs);
+    bs=getsuperset(bs);
+  }
+
+  DomainSet *oldcs=getset(setname);
+  DomainSet *cs=getsuperset(oldcs);
+  
+
+  while(cs!=NULL) {
+    if (ws->contains(cs)) {
+      if (cs->gettype()==DOMAINSET_PARTITION &&
+         !equivalentstrings(cs->getname(),boundset)) {
+       delete(ws);
+       delete(wsret);
+       ws=new WorkSet(true);
+
+       DomainSet *bs=getset(boundset);
+       addallsubsets(bs,ws);
+       DomainSet *oldbs=bs;
+       bs=getsuperset(oldbs);
+       while(bs!=cs) {
+         ws->addobject(bs);
+         if (bs->gettype()!=DOMAINSET_PARTITION) {
+           for(int i=0;i<bs->getnumsubsets();i++) {
+             DomainSet *tss=getset(bs->getsubset(i));
+             if (oldbs!=tss) {
+               addallsubsets(tss,ws);
+             }
+           }
+         }
+         oldbs=bs;
+         bs=getsuperset(oldbs);
+       }
+       return ws;
+      }
+      break;
+    }
+    if (cs->gettype()==DOMAINSET_PARTITION) {
+      /* We have a partition...got to look at all other subsets */
+      for(int i=0;i<cs->getnumsubsets();i++) {
+       if (!equivalentstrings(cs->getsubset(i),oldcs->getname())) {
+         addallsubsets(getset(cs->getsubset(i)),wsret);
+       }
+      }
+    }
+    oldcs=cs;
+    cs=getsuperset(cs);
+  }
+  delete(ws);
+  return wsret;
+}
+
+DomainSet * DomainRelation::getsuperset(DomainSet *s) {
+  char *name=s->getname();
+  for(int i=0;i<numsets;i++)
+    for (int j=0;j<sets[i]->getnumsubsets();j++) {
+      if(equivalentstrings(name,sets[i]->getsubset(j)))
+       return sets[i];
+    }
+  return NULL;
+}
+
+WorkSet * DomainRelation::conflictaddsets(char * setname, char *boundset, model *m) {
+  /* Want to know what set additions insertion into "setname" could cause */
+  if (equivalentstrings(setname,"int"))
+    return new WorkSet(true);
+  if (equivalentstrings(setname,"token"))
+    return new WorkSet(true);
+  DomainSet *bs=getset(boundset);
+  WorkSet *wsret=new WorkSet(true);
+  WorkSet *ws=new WorkSet(true);
+  while(bs!=NULL) {
+    ws->addobject(bs);
+    bs=getsuperset(bs);
+  }
+
+  Guidance *g=m->getguidance();
+  DomainSet *ds=getset(g->insertiontoset(setname));
+  while(ds!=NULL) {
+    if (ws->contains(ds))
+      break;
+    wsret->addobject(ds);
+    ds=getsuperset(ds);
+  }
+
+  delete(ws);
+  return wsret;
+}
+
+WorkSet * DomainRelation::removeconflictdelsets(char *setname) {
+  /* Obviously remove from all subsets*/
+  WorkSet *tmp=new WorkSet(true);
+  WorkSet *wsret=new WorkSet(true);
+  tmp->addobject(getset(setname));
+  while(!tmp->isEmpty()) {
+    DomainSet *s=(DomainSet *)tmp->firstelement();
+    tmp->removeobject(s);
+    wsret->addobject(s);
+    for(int j=0;j<s->getnumsubsets();j++)
+      tmp->addobject(getset(s->getsubset(j)));
+  }
+  delete(tmp);
+  return wsret;
+}
+
+WorkSet * DomainRelation::removeconflictaddsets(char *setname, model *m) {
+  /* Remove could cause addition to a new set...*/
+  DomainSet *ds=getset(setname);
+  Guidance *g=m->getguidance();
+  char *settoputin=g->removefromset(setname);
+  if (settoputin==NULL)
+    return new WorkSet(true);
+  return conflictaddsets(settoputin, setname, m);
+}
+
+DomainSet * DomainRelation::getsource(DomainSet *s) {
+  return getsuperset(s);
+}
+
+void DomainRelation::addtoset(Element *ele, DomainSet *settoadd, model *m) {
+  /* Assumption is that object is not in set*/
+  if(settoadd->getset()->contains(ele)) /* Already in set-no worries */
+    return;
+  if(settoadd->gettype()==DOMAINSET_PARTITION) {
+    /* Have to find subset to add to */
+    char *subsettoadd=m->getguidance()->insertiontoset(settoadd->getname());
+    DomainSet *setptr=getset(subsettoadd);
+    while(setptr!=settoadd) {
+      setptr->getset()->addobject(ele);
+      m->triggerrule(ele,setptr->getname());
+      setptr=getsuperset(setptr);
+    }
+  }
+  settoadd->getset()->addobject(ele);
+  m->triggerrule(ele,settoadd->getname());
+  DomainSet *oldptr=settoadd;
+  DomainSet *ptr=getsuperset(oldptr);
+  while((ptr!=NULL)&&(!ptr->getset()->contains(ele))) {
+    ptr->getset()->addobject(ele);
+    m->triggerrule(ele,ptr->getname());
+    oldptr=ptr;
+    ptr=getsuperset(ptr);
+  }
+  if(ptr!=NULL&&
+     ptr->gettype()==DOMAINSET_PARTITION) {
+    /* may have to do removes....*/
+    for(int i=0;i<ptr->getnumsubsets();i++) {
+      char *subset=ptr->getsubset(i);
+      DomainSet *ptrsubset=getset(subset);
+      if (oldptr!=ptrsubset&&
+         ptrsubset->getset()->contains(ele)) {
+       /* GOT THE ONE*/
+       WorkSet *ws=new WorkSet(true);
+       ws->addobject(ptrsubset);
+       while(!ws->isEmpty()) {
+         DomainSet *ds=(DomainSet *)ws->firstelement();
+         ws->removeobject(ds);
+         if (ds->getset()->contains(ele)) {
+           for(int j=0;j<ds->getnumsubsets();j++) {
+             ws->addobject(getset(ds->getsubset(j)));
+           }
+           removefromthisset(ele, ds,m);
+         }
+       }
+       delete(ws);
+       break;
+      }
+    }
+  }
+}
+
+void DomainRelation::abstaddtoset(Element *ele, DomainSet *settoadd, model *m) {
+  /* Assumption is that object is not in set*/
+  if(settoadd->getset()->contains(ele)) /* Already in set-no worries */
+    return;
+  if(settoadd->gettype()==DOMAINSET_PARTITION) {
+    /* Have to find subset to add to */
+    char *subsettoadd=m->getguidance()->insertiontoset(settoadd->getname());
+    DomainSet *setptr=getset(subsettoadd);
+    while(setptr!=settoadd) {
+      setptr->getset()->addobject(ele);
+      m->triggerrule(ele,setptr->getname());
+      setptr=getsuperset(setptr);
+    }
+  }
+  settoadd->getset()->addobject(ele);
+  m->triggerrule(ele,settoadd->getname());
+  DomainSet *oldptr=settoadd;
+  DomainSet *ptr=getsuperset(oldptr);
+  while((ptr!=NULL)&&(!ptr->getset()->contains(ele))) {
+    ptr->getset()->addobject(ele);
+    m->triggerrule(ele,ptr->getname());
+    oldptr=ptr;
+    ptr=getsuperset(ptr);
+  }
+}
+
+void DomainRelation::removefromthisset(Element *ele, DomainSet *ds, model *m) {
+  ds->getset()->removeobject(ele); /*removed from set*/
+  /* Next need to search relations */
+  for(int i=0;i<numrelations;i++) {
+    DRelation * relation=relations[i];
+    if (equivalentstrings(relation->getdomain(),ds->getname()))
+      for(Element *target=(Element *) relation->getrelation()->getobj(ele);target!=NULL;target=(Element *) relation->getrelation()->getobj(ele)) {
+       relation->getrelation()->remove(ele,target);
+       if (relation->isstatic()) {
+         /* Have to actually remove target*/
+         DomainSet *targetset=getset(relation->getrange());
+         delfromsetmovetoset(target,targetset,m);
+       }
+      }
+    if (equivalentstrings(relation->getrange(),ds->getname()))
+      for(Element *target=(Element *) relation->getrelation()->invgetobj(ele);target!=NULL;target=(Element *) relation->getrelation()->invgetobj(ele)) {
+       relation->getrelation()->remove(target,ele);
+       if (relation->isstatic()) {
+         DomainSet *targetset=getset(relation->getdomain());
+         delfromsetmovetoset(target,targetset,m);
+       }
+      }
+  }
+}
+
+void DomainRelation::delfromsetmovetoset(Element *ele,DomainSet *deletefromset,model *m) {
+  WorkSet *ws=new WorkSet(true);
+  ws->addobject(deletefromset);
+  while(!ws->isEmpty()) {
+    DomainSet *ds=(DomainSet *)ws->firstelement();
+    ws->removeobject(ds);
+    if (ds->getset()->contains(ele)) {
+      for(int j=0;j<ds->getnumsubsets();j++) {
+       ws->addobject(getset(ds->getsubset(j)));
+      }
+      removefromthisset(ele, ds,m);
+    }
+  }
+  delete(ws);
+  char *mts=m->getguidance()->removefromset(deletefromset->getname());
+  DomainSet *movetoset=getset(mts);
+  addtoset(ele, movetoset, m); //Add to the movetoset now...
+}
+
+int DomainRelation::getnumrelation() {
+  return numrelations;
+}
+
+DRelation * DomainRelation::getrelation(int i) {
+  return relations[i];
+}
+
+
+bool DomainRelation::fixstuff() {
+  bool anychange=false;
+  /* Guaranteed fixpoint because we keep removing items...finite # of items */
+  while(true) {
+    bool changed=false;
+    for(int i=0;i<numsets;i++) {
+      if(checksubset(sets[i])) {
+       changed=true;
+       anychange=true;
+      }
+    }
+    for(int i=0;i<numrelations;i++) {
+      if(checkrelations(relations[i])) {
+       changed=true;
+       anychange=true;
+      }
+    }
+#ifdef REPAIR
+    /* Fix point only necessary if repairing */
+    if(!changed)
+#endif
+      break;
+  }
+  return anychange;
+}
+
+
+
+
+/* propagate the changes so that all the subset inclusion and partition
+   constraints are satisfied. */
+bool DomainRelation::checksubset(DomainSet *ds) {
+  // remove all elements in ds that are not contained by its superset
+  bool changed=false;
+  DomainSet *superset=getsuperset(ds);
+  WorkSet *ws=ds->getset();
+  WorkSet *wssuper=ds->getset();
+
+  void *ele=ws->firstelement();
+  while(ele!=NULL) {
+    if (!wssuper->contains(ele)) {
+      void *old=ele;
+      ele=ws->getnextelement(ele);
+      changed=true;
+#ifdef REPAIR
+      ws->removeobject(old);
+#endif
+    } else
+      ele=ws->getnextelement(ele);
+  }
+  /* Superset inclusion property guaranteed */
+
+
+  /* If an element is contained by more than one subset, remove it from
+     all subsets but the first one.  If an element is not contained by 
+     any subset, remove it from the superset */
+  if (ds->gettype()==DOMAINSET_PARTITION) {
+    ele=ws->firstelement();
+    while(ele!=NULL) {
+      int inccount=0;
+      for(int i=0;i<ds->getnumsubsets();i++) {
+       char *subsetname=ds->getsubset(i);
+       DomainSet *subset=getset(subsetname);
+       if (subset->getset()->contains(ele)) {
+         if (inccount==0)
+           inccount++;
+         else {
+           /* Partition exclusion property */
+           changed=true;
+#ifdef REPAIR
+           subset->getset()->removeobject(ele);
+#endif
+         }
+       }
+      }
+      if (inccount==0) {
+       /* Partition inclusion property */
+       changed=true;
+#ifdef REPAIR
+       ws->removeobject(ele);
+#endif
+      }
+      ele=ws->getnextelement(ele);
+    }
+  }
+  return changed;
+}
+
+
+
+bool DomainRelation::checkrelations(DRelation *dr) {
+  DomainSet  *range=getset(dr->getrange());
+  DomainSet *domain=getset(dr->getdomain());
+  WorkSet *rangeset=NULL,*domainset=NULL;
+  bool changed=false;
+  if (range!=NULL)
+    rangeset=range->getset();
+  if (domain!=NULL)
+    domainset=domain->getset();
+  WorkRelation *rel=dr->getrelation();
+  Tuple ele=rel->firstelement();
+  while(!ele.isnull()) {
+    if((domainset!=NULL&&!domainset->contains(ele.left))||
+        (rangeset!=NULL&&!rangeset->contains(ele.right))) {
+      void *l=ele.left;
+      void *r=ele.right;
+      ele=rel->getnextelement(l,r);
+      changed=true;
+#ifdef REPAIR
+      rel->remove(l,r);
+#endif
+    } else {
+      ele=rel->getnextelement(ele.left,ele.right);
+    }
+  }
+  /* Relation is clean now also */
+  return changed;
+}