📄 adseliminatepseudostatenodes.c
字号:
// h is initialised with g. bool Elim::FillAH(Graph *g, ADSHyperGraph *h){ // Fill h with nodes of g List <Subject *> gnodes; // nodes of g g->GetNodes(&gnodes); for (gnodes.first();!gnodes.done();gnodes.next()){ if ((gnodes.cur()->GetClassType()==Code::NOTE)|| (gnodes.cur()->GetClassType()==Code::COMMENT)) continue; if (check(gnodes.cur())) h->AddNode((Node *)gnodes.cur()); // BUG: gnodes.cur() now part of both g and h Fixing this bug is too much work for the moment. If the new hypergraph architecture for TCM is adopted, the problem will disappear } // Fill h with edges of g List <Subject *> gedges; // edges of g g->GetEdges(&gedges); for (gedges.first();!gedges.done();gedges.next()){ string cons; // the string to be parsed if (gedges.cur()->GetName()->contains("[else]")){ List <Subject *> outgoing; g->GetEdgesFrom(&outgoing,((Edge *)(gedges.cur()))->GetSubject1()); // get all edges that leave gedges.cur() string str=""; // the string that will replace "else" for (outgoing.first();!outgoing.done();outgoing.next()){ if (outgoing.cur()!=gedges.cur()){ // do not check gedges.cur() string temp=outgoing.cur()->GetName()->getstr(); //::adsedgelabel_constraint; if (temp.contains("else")) return False; if (temp.contains('[')){ // if label has guard while (!(temp[0]=='[')) temp.remove(0); // strip event part temp.replace('[','('); temp.replace(']',')'); } else temp="true"; // if label has no guard, guard "true" is assumed if (str!="") str= str + "|" + temp; // put or (|) only if there is more than basic guard constraint else str = temp; // } } if (str=="") // else was the only outgoing edge of gedges.cur() ... return False; // that is against syntax else str = "[~(" + str + ")]"; // make str a guard expression string event = gedges.cur()->GetName()->getstr(); while (!event.endsWith("[")) event.remove(); // get the event part of adsedgelabel constraint (might be NULL) event.remove(); // remove [ cons=event+str; // new label for gedges.cur } else{ cons = gedges.cur()->GetName()->getstr(); } ADSHyperEdge *he= new ADSHyperEdge(h,(Edge *)gedges.cur()); //source and target of new hyperedge he are copied from gedges.cur() // parse the label of gedges.cur() // initialise variables of the parser ::iprop=0; // counter for propisitions in guards ::ivar=0; // counter for propisitions in guards ::iselse=0; // ::iclock=0; ::isclock=0; ::indexin=0; ::notindexin=0; cons.replace('-','_'); if (ParseGuardLabel(&cons)){ // the label can be parsed if (::isclock){ // event part is clock constraint (e.g. after(10)) if (cons.contains('[')){ // cons has guard while (!(cons[0]=='[')) cons.remove(0); // strip event part (clock constraint) from cons } else{ cons=""; // empty trigger event; clock constraint is modelled separately } } he->SetLabel(cons); int j; // insert the properies into h and he for (j=0;j<(::iprop);j++){ Prop *p=new Prop(::propname[j],::proptype[j]); if (!(h->AddProp(p))){ he->AddProp(h->FindSimilarProp(p)); delete p; } else he->AddProp(p); } // insert the vars into h and he for (j=0;j<(::ivar);j++){ ADSVar *v=new ADSVar(::varname[j],::vartype[j]); if (!(h->AddVar(v))){ he->AddVar(h->FindSimilarVar(v)); delete v; } else he->AddVar(v); } // insert clock constraint into he for (j=0;j<(::iclock);j++){ if (he->hasClockConstraint()) return False; // cannot occur in practice Clock *c; if (::clockconstrainttype[j]==AFTER){ c = new Clock(he); ClockConstraint *cc=new ClockConstraint(c,AFTER,clockconstraint[j]); he->SetClockConstraint(cc); } else{ // when, not yet implemented c = new Clock(); } } // insert `in' nodes List <Subject *> hnodes; // nodes of h h->GetNodes(&hnodes); for (j=0;j<(::indexin);j++){ string iname=inname[j]; for (hnodes.first();!hnodes.done();hnodes.next()){ string hname=*(hnodes.cur()->GetName()); if (replace(hname)==replace(iname)){ he->AddInNode(hnodes.cur()); break; } } } // insert `notin' nodes for (j=0;j<(::notindexin);j++){ string notiname=notinname[j]; for (hnodes.first();!hnodes.done();hnodes.next()){ string hname=*(hnodes.cur()->GetName()); if (replace(hname)==replace(notiname)){ he->AddNotInNode(hnodes.cur()); break; } } } if (::hasaction){ //TODO : add check that action is double defined Prop *p=new Prop(::sendeventname,SENDEVENT); h->AddProp(p); he->SetSendEvent(p); } } else { // not Parseguardlabel error( "Guard label %s could not be parsed! (edge %d)\n",gedges.cur()->GetName()->getstr(), gedges.cur()->GetId()); return False; } // he->Write(); h->AddHyperEdge(he); // add he to h } return True;}// for every AND pseudo state do // glue all in and out going hyper edges togetherbool Elim::ElimAndNodes(ADSHyperGraph *h){ List <Subject *> l; // nodes of h h->GetNodes(&l); for (l.first();!l.done();l.next()){ if (l.cur()->GetClassType()==Code::ATD_SYNCHRONIZATION_NODE){ // AND pseudo state node ADSHyperEdge *he =new ADSHyperEdge(h); // the new hyperedge List <Subject *> efrom; // hyperedges that enter the AND node h->GetHyperEdgesFrom(&efrom,l.cur()); List <Subject *> eto; // hyperedges that leave the AND node h->GetHyperEdgesTo(&eto,l.cur()); for (efrom.first();!efrom.done();efrom.next()){ for (eto.first();!eto.done();eto.next()){ if (efrom.cur()==eto.cur()) { // hyperedge has AND as source and target error("There is an and state node with a cycle\n"); return False; } if (((ADSHyperEdge *)efrom.cur())->hasClockConstraint() && ((ADSHyperEdge *)eto.cur())->hasClockConstraint()){ error("There are two segments in the hyperedge with a clock constraint\n"); return False; } } } string event; // only of one incoming edge ClockConstraint *cc=NULL; // only of one incoming edge // fill the new hyperedge he with all the sources // of all hyperedges that enter the and node for (eto.first();!eto.done();eto.next()){ cc= ((ADSHyperEdge *)eto.cur())->GetClockConstraint(); if ((!((ADSHyperEdge *)eto.cur())->HasEmptyEvent()) && (event=="")){ event=((ADSHyperEdge *)eto.cur())->GetEvent(); List <Prop *> p; ((ADSHyperEdge *)eto.cur())->GetPropList(p); for (p.first();!p.done();p.next()){ if (p.cur()->GetType()==EVENT) he->AddProp(p.cur()); } } List <Subject *> *sources; sources = ((ADSHyperEdge *)eto.cur())->GetSubject1(); for (sources->first();!sources->done();sources->next()){ if (sources->cur()!=l.cur()) // do not insert the AND node as sources he->AddSubject1(sources->cur()); } List <Subject *> *targets; targets = ((ADSHyperEdge *)eto.cur())->GetSubject2(); for (targets->first();!targets->done();targets->next()){ if (targets->cur()!=l.cur()) // do not insert the AND node as sources he->AddSubject2(targets->cur()); } List <Subject *> ls; ((ADSHyperEdge *)eto.cur())->GetEdges(&ls);// the edges in the original activity diagram that are represented by the hyperedge he->AddEdges(ls); } // add to he the pseudo state node that is being eliminated // he->AddPseudoNode(l.cur()); // fill the new hyperedge he with all the targets // of all hyperedges that leave the and node for (efrom.first();!efrom.done();efrom.next()){ if ((!((ADSHyperEdge *)efrom.cur())->HasEmptyEvent()) && (event=="")){ event=((ADSHyperEdge *)efrom.cur())->GetEvent(); List <Prop *> p; ((ADSHyperEdge *)efrom.cur())->GetPropList(p); for (p.first();!p.done();p.next()){ if (p.cur()->GetType()==EVENT) he->AddProp(p.cur()); } } List <Subject *> *sources; sources = ((ADSHyperEdge *)efrom.cur())->GetSubject1(); for (sources->first();!sources->done();sources->next()){ if (sources->cur()!=l.cur()) // do not insert the AND node as target he->AddSubject1(sources->cur()); } List <Subject *> *targets; targets = ((ADSHyperEdge *)efrom.cur())->GetSubject2(); for (targets->first();!targets->done();targets->next()){ if (targets->cur()!=l.cur()) // do not insert the AND node as target he->AddSubject2(targets->cur()); } List <Subject *> ls; ((ADSHyperEdge *)efrom.cur())->GetEdges(&ls); // the edges in the original activity diagram that are represented by the hyperedge he->AddEdges(ls); } he->SetLabel(event); he->SetClockConstraint(cc); if (!he->GetSubject1()->isSet()){ error("There is a hyper edge whose source is no set!\n"); return False; } else if (!he->GetSubject2()->isSet()){ error("There is a hyper edge whose target is no set!\n"); return False; } if (!h->ExistsSimilarHyperEdge(he)) h->AddHyperEdge(he); h->RemoveNode((Node *)l.cur()); // remove the and node } } return True;}// set for each basic prop that refers to a var, the var it refers to.// not necessary for elimination of pseudo state nodesvoid Elim::UpdatePropList(ADSHyperGraph *ah){ List <Prop *> pl; ah->GetPropList(pl); List <ADSVar *> vl; ah->GetVarList(vl); for (pl.first();!pl.done();pl.next()){ if ((pl.cur()->GetType() == (::INT))||(pl.cur()->GetType() == (::PROP)) || (pl.cur()->GetType() == (::STRING))){ ::iprop=0; // counter for propisitions in guards ::ivar=0; ::iselse=0; ::iclock=0; ::isclock=0; ::indexin=0; ::notindexin=0; string prop =pl.cur()->GetName(); string guard= "[" + prop + "]"; if (ParseGuardLabel(&guard)) { // always true int j; for (j=0;j<(::ivar);j++){ ADSVar *v=new ADSVar(::varname[j],::vartype[j]); bool found=False; for (vl.first();!vl.done();vl.next()){ if (*v==*vl.cur()){ pl.cur()->SetVar(vl.cur()); found=True; break; } } if (!found) error("I could not find the variable...!\n"); // var should already be present } } else error( "I could not parse a label that I could parse before. Am I growing old?\n"); } }} bool Elim::EliminatePseudoStateNodes(Graph *g, ADSHyperGraph *h){ if (Check(g)){ if (FillAH(g,h)){ ElimAndNodes(h); ElimOrNodes(h); UpdatePropList(h); return True; } } return False;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -