libFAUDES

Sections

Index

cfl_project.cpp

Go to the documentation of this file.
00001 /** @file cfl_project.cpp projection and subset construction */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2006  Bernd Opitz
00006    Exclusive copyright is granted to Klaus Schmidt
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Lesser General Public
00010    License as published by the Free Software Foundation; either
00011    version 2.1 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Lesser General Public License for more details.
00017 
00018    You should have received a copy of the GNU Lesser General Public
00019    License along with this library; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00021 
00022 
00023 #include "cfl_project.h"
00024 
00025 namespace faudes {
00026 
00027 // UniqueInit(rGen&)
00028 void UniqueInit(vGenerator& rGen) {
00029   Idx inituni;
00030   StateSet::Iterator lit;
00031   TransSet::Iterator tit;
00032   // check number of initial states
00033   if(rGen.InitStatesSize() == 1) return;
00034   // introduce new initial state
00035   if(rGen.StateNamesEnabled()) {
00036     std::string initname=rGen.UniqueStateName("InitUni");
00037     inituni = rGen.InsState(initname); 
00038   } else {
00039     inituni = rGen.InsState();
00040   }
00041   FD_DF("UniqueInit: introducing new initial state: " << inituni);
00042   // introduce outgoing transitions from initial state
00043   FD_DF("UniqueInit: introduce outgoing transitions: ");
00044   for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) {
00045     for (tit = rGen.TransRelBegin(*lit); tit != rGen.TransRelEnd(*lit); ++tit) {
00046       rGen.SetTransition(inituni, tit->Ev, tit->X2);
00047       FD_DF("UniqueInit:   " << inituni << "-" << tit->Ev << "-" << tit->X2);
00048     }
00049   }
00050   // mark the new init state if there exists an originally marked init state (tm 20101206)
00051   if(!(rGen.InitStates() *  rGen.MarkedStates()).Empty()){
00052     rGen.SetMarkedState(inituni);
00053     FD_DF("UniqueInit: set marked state: " << inituni);
00054   }
00055   // delete old istates
00056   rGen.ClearInitStates();
00057   // set inituni as new initial state 
00058   rGen.SetInitState(inituni);
00059 }
00060 
00061 // Deterministic(rGen&, rResGen&)
00062 void Deterministic(const vGenerator& rGen, vGenerator& rResGen) {
00063   // temporary vectors
00064   std::vector<StateSet> power_states;
00065   std::vector<Idx> det_states;
00066   Deterministic(rGen, power_states, det_states, rResGen);
00067 }
00068 
00069 
00070 // aDeterministic(rGen&, rResGen&)
00071 void aDeterministic(const vGenerator& rGen, vGenerator& rResGen) {
00072   // prepare result to keep original alphabet
00073   vGenerator* pResGen = &rResGen;
00074   if(&rResGen==&rGen) {
00075     pResGen= rResGen.New();
00076   }
00077   // perform op
00078   Deterministic(rGen,*pResGen);
00079   // set old attributes
00080   pResGen->EventAttributes(rGen.Alphabet());
00081   // copy result
00082   if(pResGen != &rResGen) {
00083     pResGen->Move(rResGen);
00084     delete pResGen;
00085   }
00086 }
00087 
00088 
00089 // Deterministic(rGen&, rEntryStatesMap&, rResGen&)
00090 void Deterministic(const vGenerator& rGen, std::map<Idx,StateSet>& rEntryStatesMap,
00091        vGenerator& rResGen) {
00092   // prepare result:
00093   rEntryStatesMap.clear();
00094   // helpers:
00095   std::vector<StateSet> power_states;
00096   std::vector<Idx> det_states;
00097   // call Deterministic function
00098   Deterministic(rGen, power_states, det_states, rResGen);
00099   // build entry states map
00100   std::vector<StateSet>::size_type i;
00101   for (i = 0; i < power_states.size(); ++i) {
00102     rEntryStatesMap.insert(std::pair<Idx,StateSet>(det_states[i], power_states[i]));
00103   }
00104 }
00105 
00106 
00107 void Deterministic(const vGenerator& rGen, std::vector<StateSet>& rPowerStates,
00108        std::vector<Idx>& rDetStates, vGenerator& rResGen) {
00109   // FIXME: implement the hashtable as a map<Idx, list< vector<int>::size_type > > 
00110   // or something like that
00111 
00112   // note: there is a demonstrative description of the multiway merge
00113   // algorithm in the master thesis. (Bernd Opitz)
00114 
00115   FD_DF("Deterministic(): core function #" << rGen.Size());
00116 
00117   // use pointer pResGen to result rResGen
00118   vGenerator* pResGen = &rResGen;
00119   if(&rResGen== &rGen) {
00120     pResGen= rResGen.New();
00121   }
00122 
00123   // prepare result
00124   pResGen->Clear();  
00125   rPowerStates.clear();
00126   rDetStates.clear();
00127   // set the name
00128   pResGen->Name(CollapsString("Det(" + rGen.Name() + ")"));
00129   // copy alphabet
00130   FD_DF("Deterministic A " << rGen.Alphabet().ToString());
00131   pResGen->InjectAlphabet(rGen.Alphabet());
00132   FD_DF("Deterministic B");
00133 
00134   // helpers
00135   TransSetEvX1X2 trel_evx1x2;
00136   rGen.TransRel(trel_evx1x2);
00137   typedef std::multimap< Idx,std::vector<StateSet>::size_type > T_HASHMAP;
00138   T_HASHMAP hashmap;
00139   std::vector<StateSet>::size_type current_vecindex;
00140   std::pair< std::map<StateSet,Idx>::iterator,bool > result;
00141   TransSet::Iterator transrel_end = rGen.TransRelEnd();
00142   StateSet newset;
00143   StateSet::Iterator lit;
00144   const Idx max_idx = std::numeric_limits<Idx>::max();
00145   
00146   // bail out on empty input 
00147   if(rGen.InitStatesEmpty()) {
00148     if(pResGen != &rResGen) {
00149       pResGen->Move(rResGen);
00150       delete pResGen;
00151     }
00152     FD_DF("Deterministic(): done (empty)"); 
00153     return;
00154   }
00155   
00156   Idx newstate = pResGen->InsInitState();
00157   // initialize rPowerStates with subset of initial states
00158   for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) {
00159     // clear set and insert single state
00160     newset.Insert(*lit);
00161     // if marked state set in res generator
00162     if (rGen.ExistsMarkedState(*lit)) {
00163       pResGen->SetMarkedState(newstate);
00164       FD_DF("Deterministic: setting as mstate: " << rGen.SStr(newstate));
00165     }
00166   }
00167   FD_DF("Deterministic: created subset of initial states {"
00168   << newset.ToString() << "} with deterministic state index "
00169   << rGen.SStr(newstate));
00170   // insert newset in rPowerStates
00171   rPowerStates.push_back(newset);
00172   rDetStates.push_back(newstate);
00173   hashmap.insert(std::make_pair(newset.Signature(), (Idx)rPowerStates.size() - 1));
00174 
00175   // iteration over all states
00176   for (current_vecindex = 0; current_vecindex < rPowerStates.size(); 
00177        ++current_vecindex) {
00178     FD_WPC(current_vecindex,rPowerStates.size(), "Deterministic(): current/size: "<<  current_vecindex << " / " << rPowerStates.size());
00179     FD_DF("Deterministic: current power set: {" 
00180     << rPowerStates[current_vecindex].ToString() << "} -> " 
00181     << rDetStates[current_vecindex]);
00182 
00183     std::vector<StateSet> newset_vec;
00184     std::vector<Idx> event_vec;
00185 
00186     // multiway merge begin
00187     FD_DF("Deterministic: starting multiway merge...");
00188     std::list<TransSet::Iterator> merge_iterators;
00189     std::vector<Transition> trans_vec;
00190 
00191     // add transset iterator at begin of each state's transitions
00192     TransSet::Iterator tit;
00193     for (lit = rPowerStates[current_vecindex].Begin(); 
00194    lit != rPowerStates[current_vecindex].End(); ++lit) {
00195       tit = rGen.TransRelBegin(*lit);
00196       if (tit != rGen.TransRelEnd(*lit)) {
00197   merge_iterators.push_back(tit);
00198   FD_DF("Deterministic: added merge iterator: " << rGen.SStr(tit->X1) 
00199         << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2));
00200       }
00201     }
00202 
00203     // find first iterator with lowest event
00204     while (! merge_iterators.empty()) {
00205       Idx currentevent = max_idx;
00206       std::list<TransSet::Iterator>::iterator i; 
00207       std::list<TransSet::Iterator>::iterator currentit = merge_iterators.end();
00208       for (i = merge_iterators.begin(); i != merge_iterators.end(); ++i) {
00209   if ((*i)->Ev < currentevent) {
00210     currentevent = (*i)->Ev;
00211     currentit = i;
00212   }
00213       }
00214       // currentit now holds the iterator
00215       // currentevent holds the lowest event (lowest Idx)
00216 
00217       // merge all transitions with currentevent at each iterator in a row
00218       // this is a modification of multiway merge as after projection the
00219       // automaton most likely holds states with many transitions that share 
00220       // the same event. only merging the lowest transition and continue with
00221       // search for the lowest event again would be to slow here (because
00222       // of too much iterator dereferencing).
00223       Idx currentstate;
00224       while (currentit != merge_iterators.end()) {
00225   currentstate = (*currentit)->X1;
00226   TransSet::Iterator& j = *currentit;
00227   while (1) {
00228     // remove iterator if it reaches the end of the transition set
00229     if (j == transrel_end) {
00230       std::list<TransSet::Iterator>::iterator tmpit = currentit;
00231       ++currentit;
00232       merge_iterators.erase(tmpit);
00233       break;
00234     }
00235     // if current iterator is in its original state
00236     else if (j->X1 == currentstate) {
00237       // if the event is still the same add the transition
00238       if (j->Ev == currentevent) {
00239         trans_vec.push_back(*j); 
00240         FD_DF("Deterine: adding transition to list: " 
00241         << rGen.SStr(j->X1) << "-" << rGen.EStr(j->Ev) << "-"
00242         << rGen.SStr(j->X2));
00243       }
00244       // else go to next iterator
00245       else {
00246         ++currentit;
00247         break;
00248       }
00249     }
00250     // if the iterator is beyond its original state remove it
00251     else {
00252       std::list<TransSet::Iterator>::iterator tmpit = currentit;
00253       ++currentit;
00254       merge_iterators.erase(tmpit);
00255       break;
00256     }
00257     ++j;
00258   }
00259       }
00260     }
00261 
00262     // partition transition vector by events. optimizable? 
00263     FD_DF("Deterministic: partitioning the transition vector...");
00264     std::vector<Transition>::iterator tv_it;
00265     StateSet newset;
00266     Idx lastevent = 0;
00267     for (tv_it = trans_vec.begin(); tv_it != trans_vec.end(); ++tv_it) {
00268       if ((tv_it->Ev == lastevent) || (lastevent == 0)) {
00269   newset.Insert(tv_it->X2);
00270   lastevent = tv_it->Ev;
00271       }
00272       else {
00273   FD_DF("Deterministic: partition: {" << newset.ToString() 
00274         << "} with event " << rGen.EStr(lastevent));
00275   newset_vec.push_back(newset);
00276   event_vec.push_back(lastevent);
00277   newset.Clear();
00278   newset.Insert(tv_it->X2);
00279   lastevent = tv_it->Ev;
00280       }
00281     }
00282     if (! newset.Empty()) {
00283       FD_DF("Deterministic: partition: {" << newset.ToString() 
00284       << "} with event " << rGen.EStr(lastevent));
00285       newset_vec.push_back(newset);
00286       event_vec.push_back(lastevent);
00287     }
00288     FD_DF("Deterministic: partitioning the transition vector finished");
00289     FD_DF("Deterministic: multiway merge finished");
00290     // multiway merge end
00291 
00292     std::vector<StateSet>::size_type nsv_index;
00293     for (nsv_index = 0; nsv_index < newset_vec.size(); ++nsv_index) {
00294       StateSet& currentset = newset_vec[nsv_index];
00295       Idx currentevent = event_vec[nsv_index];
00296       Idx tmp_x2 = 0;
00297       Idx sig = currentset.Signature();
00298       // test if newset signature is already known
00299       std::pair<T_HASHMAP::iterator,T_HASHMAP::iterator> phit
00300   = hashmap.equal_range(sig);
00301       T_HASHMAP::iterator hit = phit.first;
00302       for (hit = phit.first; hit != phit.second; ++hit) {
00303   // test set of every matching signature for equality
00304   if (currentset == rPowerStates[hit->second]) {
00305     tmp_x2 = rDetStates[hit->second];
00306     break;
00307   }
00308       }
00309 
00310       // if new set is unique within the existing power sets
00311       if (tmp_x2 == 0) {
00312   // create new state in res generator
00313   tmp_x2 = pResGen->InsState();
00314   // insert newset in rPowerStates and get iterator,bool pair
00315   rPowerStates.push_back(currentset);
00316   rDetStates.push_back(tmp_x2);
00317   hashmap.insert(std::make_pair(sig, (Idx)rPowerStates.size() - 1));
00318   FD_DF("Deterministic: added new state " 
00319         << rGen.SStr(tmp_x2) 
00320         << " for new subset {" << currentset.ToString() << "}");
00321   // set marked if one of the states in current set is marked
00322   for (lit = currentset.Begin(); lit != currentset.End(); ++lit) {
00323     if (rGen.ExistsMarkedState(*lit)) {
00324       pResGen->SetMarkedState(tmp_x2);
00325       break;
00326     }
00327   }
00328       }
00329       // introduce transition
00330       pResGen->SetTransition(rDetStates[current_vecindex], currentevent, tmp_x2);
00331     }
00332   }
00333   // fix names
00334   if (rGen.StateNamesEnabled() && pResGen->StateNamesEnabled()) {
00335     FD_DF("Deterministic: fixing names...");
00336     // rPowerStates / rDetStates index "iterator"
00337     std::vector<StateSet>::size_type i;
00338     // deterministic states iterator
00339     std::vector<Idx>::const_iterator dit;
00340     for (i = 0; i < rPowerStates.size(); ++i) {
00341       // temporary state name
00342       std::string name = "{";
00343       for (lit = rPowerStates[i].Begin();  lit != rPowerStates[i].End(); ++lit) {
00344   if (rGen.StateName(*lit) != "") {
00345     name = name + rGen.StateName(*lit) + ",";
00346   }
00347   else {
00348     name = name + ToStringInteger(*lit) + ",";
00349   }
00350       }
00351       name.erase(name.length() - 1);
00352       name = name + "}";
00353       FD_DF("Deterministic: setting state name \"" << name << "\" for index "
00354       << rDetStates[i]);
00355       pResGen->StateName(rDetStates[i], name);
00356     }
00357   }
00358   
00359   // move pResGen to rResGen
00360   if(pResGen != &rResGen) {
00361     pResGen->Move(rResGen);
00362     delete pResGen;
00363   }
00364 
00365   FD_DF("Deterministic(): core function: done");
00366     
00367 }
00368 
00369 
00370 
00371 // ProjectNonDet(rGen&, rProjectAlphabet&)
00372 // (version 2009/05, Barthel)
00373 void ProjectNonDet(vGenerator& rGen, const EventSet& rProjectAlphabet) {
00374 
00375   // HELPERS:
00376 
00377   StateSet reach, reachext; // StateSet for reachable states
00378   StateSet todo; // states todo
00379   StateSet done; // states done 
00380   Idx currentstate; // the currently processed state
00381   StateSet::Iterator lit;
00382   StateSet::Iterator lit2;
00383   TransSet::Iterator tit;
00384   TransSet::Iterator tit_end;
00385 
00386   // NAME
00387   std::string name=CollapsString("ProjectNonDet(" + rGen.Name() + ")");
00388 
00389   // ALGORITHM:
00390   // set all locally reachable states to init states
00391   for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) {
00392     reach.Clear();
00393     LocalAccessibleReach(rGen, rProjectAlphabet, *lit, reach);
00394     for (lit2 = reach.Begin(); lit2 != reach.End(); ++lit2) {
00395       if (!rGen.InitStates().Exists(*lit2)) {
00396   FD_DF("ProjectNonDet: set initial state: " << rGen.SStr(*lit2));
00397   rGen.SetInitState(*lit2);
00398       }
00399     }
00400   }
00401   // initialize algorithm by adding init states to todo 
00402   for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) {
00403     FD_DF("ProjectNonDet: todo add: " << rGen.SStr(*lit));
00404     todo.Insert(*lit);
00405   }
00406     
00407   // process todo stack
00408   while (!todo.Empty()) {
00409     currentstate = *todo.Begin();
00410     todo.Erase(*todo.Begin());
00411     done.Insert(currentstate); // mark as done
00412     //std::cout << "###" << std::endl;
00413     FD_DF("ProjectNonDet: current state: " << rGen.SStr(currentstate));
00414 
00415     // comp accessible reach
00416     reach.Clear();
00417     LocalAccessibleReach(rGen, rProjectAlphabet, currentstate, reach);
00418     FD_DF("ProjectNonDet: local reach: " << reach.ToString());
00419     
00420     // relink outgoing transitions
00421     FD_DF("ProjectNonDet: relinking outgoing transitions...");
00422     for (lit = reach.Begin(); lit != reach.End(); ++lit) {
00423       tit = rGen.TransRelBegin(*lit);
00424       tit_end = rGen.TransRelEnd(*lit);
00425       for (; tit != tit_end; ++tit) {
00426   if (rProjectAlphabet.Exists(tit->Ev)) {
00427     FD_DF("ProjectNonDet: relinking transition: " << rGen.TStr(*tit) << " to " << rGen.SStr(currentstate));
00428     rGen.SetTransition(currentstate, tit->Ev, tit->X2);
00429     //if (!done.Exists(tit->X2) && !todo.Exists(*lit2)) {
00430     if (!done.Exists(tit->X2)) {
00431       FD_DF("ProjectNonDet: todo insert: " << rGen.SStr(tit->X2));
00432       todo.Insert(tit->X2);
00433     }
00434     // add transistions to all states in extended local reach
00435     reachext.Clear();
00436     LocalAccessibleReach(rGen, rProjectAlphabet, tit->X2, reachext);
00437     FD_DF("ProjectNonDet: local reach from state " << tit->X2 << ": " << reachext.ToString());
00438     for (lit2 = reachext.Begin(); lit2 != reachext.End(); ++lit2) {
00439       if (!rGen.ExistsTransition(tit->X2, tit->Ev, *lit2) && (tit->X2 != *lit2)) {
00440         rGen.SetTransition(tit->X1, tit->Ev, *lit2);
00441         FD_DF("ProjectNonDet: setting transition: " << rGen.SStr(tit->X1) << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(*lit2));
00442         //if (!done.Exists(*lit2) && !todo.Exists(*lit2)) {
00443         if (!done.Exists(*lit2)) {
00444     FD_DF("ProjectNonDet: todo insert: " << rGen.SStr(tit->X2));
00445     todo.Insert(*lit2);
00446         }
00447       }
00448     }
00449     //std::cout << "---" << std::endl;
00450   }
00451       }
00452       // marked status test
00453       if (rGen.ExistsMarkedState(*lit)) {
00454   FD_DF("ProjectNonDet: setting marked state " << rGen.SStr(currentstate));
00455   rGen.SetMarkedState(currentstate);
00456       }
00457     }
00458    
00459     // remove all transitions that leave current state 
00460     // with an invisible event
00461     tit = rGen.TransRelBegin(currentstate);
00462     tit_end = rGen.TransRelEnd(currentstate);
00463     while(tit != tit_end) {
00464       FD_DF("ProjectNonDet: current transition: " << rGen.SStr(tit->X1)
00465       << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2));
00466       if (! rProjectAlphabet.Exists(tit->Ev)) {
00467   FD_DF("ProjectNonDet: deleting current transition");
00468   TransSet::Iterator tit_tmp = tit;
00469   ++tit;
00470   rGen.ClrTransition(tit_tmp);
00471       } else {
00472   ++tit;
00473       }
00474     }
00475 
00476   }// todo loop
00477 
00478   // inject projection alphabet, keep Attributes
00479   rGen.RestrictAlphabet(rProjectAlphabet);
00480 
00481   // make accessile
00482   rGen.Accessible();
00483   
00484   // set name
00485   rGen.Name(name);
00486 }
00487 
00488 // wrapper
00489 void aProjectNonDet(vGenerator& rGen, const EventSet& rProjectAlphabet) {
00490   ProjectNonDet(rGen,rProjectAlphabet);
00491 }
00492 
00493 /*
00494 
00495 // reference, 2008/12
00496 
00497 // Project(rGen&, rProjectAlphabet&)
00498 void ProjectNonDet(vGenerator& rGen, const EventSet& rProjectAlphabet) {
00499 
00500 // HELPERS:
00501 
00502 StateSet reach; // StateSet for reachable states
00503 std::stack<Idx> todo; // todo stack
00504 StateSet done; // done set
00505 Idx currentstate; // the currently processed state
00506 StateSet::Iterator lit; 
00507 TransSet::Iterator tit;
00508 TransSet::Iterator tit_end;
00509 
00510 // ALGORITHM:
00511 // initialize algorithm by pushing init states on todo stack
00512 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) {
00513 FD_DF("ProjectNonDet: todo add: " << rGen.SStr(*lit));
00514 todo.push(*lit);
00515 }
00516 
00517 // process todo stack
00518 while (! todo.empty()) {
00519 currentstate = todo.top();
00520 todo.pop();
00521 done.Insert(currentstate); // mark as done
00522 FD_DF("ProjectNonDet: current state: " << rGen.SStr(currentstate));
00523 
00524 // comp accessible reach
00525 reach.Clear();
00526 LocalAccessibleReach(rGen, rProjectAlphabet, currentstate, reach);
00527 FD_DF("ProjectNonDet: local reach: " << reach.ToString());
00528 
00529 // remove all transitions that leave current state 
00530 // with an invisible event
00531 tit = rGen.TransRelBegin(currentstate);
00532 tit_end = rGen.TransRelEnd(currentstate);
00533 while(tit != tit_end) {
00534 FD_DF("ProjectNonDet: current transition: " << rGen.SStr(tit->X1)
00535 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2));
00536 if (! rProjectAlphabet.Exists(tit->Ev)) {
00537 FD_DF("ProjectNonDet: deleting current transition");
00538 TransSet::Iterator tit_tmp = tit;
00539 ++tit;
00540 rGen.ClrTransition(tit_tmp);
00541 } else {
00542 ++tit;
00543 }
00544 }
00545     
00546 // relink outgoing transitions
00547 FD_DF("ProjectNonDet: relinking outgoing transitions...");
00548 for (lit = reach.Begin(); lit != reach.End(); ++lit) {
00549 tit = rGen.TransRelBegin(*lit);
00550 tit_end = rGen.TransRelEnd(*lit);
00551 for (; tit != tit_end; ++tit) {
00552 if (rProjectAlphabet.Exists(tit->Ev)) {
00553 FD_DF("ProjectNonDet: relinking transition: " << rGen.TStr(*tit) << " to " << rGen.SStr(currentstate));
00554 rGen.SetTransition(currentstate, tit->Ev, tit->X2);
00555 if (! done.Exists(tit->X2)) {
00556 FD_DF("ProjectNonDet: todo push: " << rGen.SStr(tit->X2));
00557 todo.push(tit->X2);
00558 }
00559 }
00560 }
00561 // marked status test
00562 if (rGen.ExistsMarkedState(*lit)) {
00563 FD_DF("ProjectNonDet: setting marked state " << rGen.SStr(currentstate));
00564 rGen.SetMarkedState(currentstate);
00565 }
00566 }
00567 }
00568 
00569 // inject projection alphabet
00570 rGen.InjectAlphabet(rProjectAlphabet);
00571   
00572 // set name
00573 rGen.Name(CollapsString("Pro(" + rGen.Name() + ")"));
00574 }
00575 
00576 */
00577       
00578 // Project(rGen, rProjectAlphabet, rResGen&)
00579 void Project(const vGenerator& rGen, const EventSet& rProjectAlphabet, vGenerator& rResGen) {
00580   FD_DF("Project(...)");
00581   // temporarily assign rGen to rResGen
00582   if(&rResGen != &rGen) rResGen.Assign(rGen);
00583   // turn of state names
00584   bool se= rResGen.StateNamesEnabled();
00585   rResGen.StateNamesEnabled(false);
00586   // project non det version
00587   ProjectNonDet(rResGen, rProjectAlphabet);
00588   // make deterministic
00589   vGenerator* g2 = rGen.New(); 
00590   g2->StateNamesEnabled(false);
00591   Deterministic(rResGen, *g2);
00592   // minimize states and write result to rResGen
00593   StateMin(*g2, rResGen);
00594   delete g2;
00595   // restore state names
00596   rResGen.StateNamesEnabled(se);
00597   // set name
00598   rResGen.Name("Project("+CollapsString(rGen.Name()+")")); 
00599 }
00600 
00601    
00602 // Project(rGen, rProjectAlphabet, rResGen&)
00603 void aProject(const vGenerator& rGen, const EventSet& rProjectAlphabet, vGenerator& rResGen) {
00604   // prepare result to keep original alphabet
00605   vGenerator* pResGen = &rResGen;
00606   if(&rResGen== &rGen) {
00607     pResGen= rResGen.New();
00608   }
00609   // perform op
00610   Project(rGen,rProjectAlphabet,*pResGen);
00611   // set old attributes
00612   pResGen->EventAttributes(rGen.Alphabet());
00613   // copy result
00614   if(pResGen != &rResGen) {
00615     pResGen->Move(rResGen);
00616     delete pResGen;
00617   }
00618 }
00619 
00620 
00621 
00622 // Project(rGen, rProjectAlphabet, rEntryStatesMap&, rResGen&)
00623 void Project(const vGenerator& rGen, const EventSet& rProjectAlphabet,
00624        std::map<Idx,StateSet>& rEntryStatesMap, vGenerator& rResGen) {
00625   FD_DF("Project(...)");
00626   // temporary entry state map
00627   std::map<Idx,StateSet> tmp_entrystatemap;
00628   // temporarily assign rGen to rResGen
00629   if(&rResGen != &rGen) rResGen.Assign(rGen); 
00630   // project tmp with respect to palphabet
00631   ProjectNonDet(rResGen, rProjectAlphabet); 
00632   // put deterministic result into tmp
00633   vGenerator* tmp = rGen.New();
00634   Deterministic(rResGen, tmp_entrystatemap, *tmp);
00635   // write entry state map for minimized generator
00636   std::vector<StateSet> subsets;
00637   std::vector<Idx> newindices;
00638   // minimize states and rewrite result to rResGen
00639   StateMin(*tmp, rResGen, subsets, newindices);
00640   // build entry state map
00641   std::vector<StateSet>::size_type i;
00642   std::map<Idx,StateSet>::iterator esmit;
00643   StateSet::Iterator sit;
00644   for (i = 0; i < subsets.size(); ++i) {  
00645     StateSet tmpstates;
00646     for (sit = subsets[i].Begin(); sit != subsets[i].End(); ++sit) {
00647       esmit = tmp_entrystatemap.find(*sit);
00648 #ifdef FAUDES_DEBUG_CODE
00649       if (esmit == tmp_entrystatemap.end()) {
00650         FD_DF("project internal error");
00651   abort();
00652       }
00653 #endif
00654       // insert entry states in temporary StateSet
00655       tmpstates.InsertSet(esmit->second);
00656     }
00657 
00658     rEntryStatesMap.insert(std::make_pair(newindices[i], tmpstates));
00659   }
00660   delete tmp;
00661 }
00662 
00663 
00664 // InvProject(rGen&, rProjectAlphabet)
00665 void InvProject(vGenerator& rGen, const EventSet& rProjectAlphabet) {
00666   // test if the alphabet of the generator is included in the given alphabet
00667   if(! (rProjectAlphabet >= (EventSet) rGen.Alphabet() ) ){
00668     std::stringstream errstr;
00669     errstr << "Input alphabet has to contain alphabet of generator \"" << rGen.Name() << "\"";
00670     throw Exception("InvProject(Generator,EventSet)", errstr.str(), 506);
00671   }
00672   EventSet newevents = rProjectAlphabet - rGen.Alphabet();
00673   // insert events into generator
00674   rGen.InsEvents(newevents);
00675   FD_DF("InvProject: adding events \"" << newevents.ToString() 
00676   << "\" at every state");
00677   StateSet::Iterator lit;
00678   EventSet::Iterator eit;
00679   for (lit = rGen.StatesBegin(); lit != rGen.StatesEnd(); ++lit) {
00680     for (eit = newevents.Begin(); eit != newevents.End(); ++eit) {
00681       rGen.SetTransition(*lit, *eit, *lit);
00682     }
00683   }
00684 }
00685 
00686 // InvProject(rGen&, rProjectAlphabet)
00687 void aInvProject(vGenerator& rGen, const EventSet& rProjectAlphabet) {
00688   FD_DF("aInvProject(..)");
00689   // see whether the generator can digest attribues
00690   if(!rGen.Alphabet().AttributeTry(rProjectAlphabet.Attribute())) {
00691     InvProject(rGen,rProjectAlphabet);
00692     return;
00693   }
00694   // record extra events
00695   EventSet newevents = rProjectAlphabet - rGen.Alphabet();
00696   // perform
00697   InvProject(rGen,rProjectAlphabet);
00698   // copy all attributes from input alphabets
00699   FD_DF("aInvProject(..): fixing attributes: source " << typeid(rProjectAlphabet.Attribute()).name() <<
00700     " dest " << typeid(rGen.Alphabet().Attribute()).name());
00701   for(EventSet::Iterator eit=newevents.Begin(); eit!=newevents.End(); ++eit)  
00702     rGen.EventAttribute(*eit,rProjectAlphabet.Attribute(*eit));
00703 }
00704 
00705 
00706 // InvProject
00707 void aInvProject(
00708   const vGenerator& rGen,
00709   const EventSet& rProjectAlphabet,
00710   vGenerator& rResGen)
00711 {
00712   rResGen=rGen;
00713   aInvProject(rResGen, rProjectAlphabet);
00714 }
00715 
00716 
00717 
00718 
00719 // CreateEntryStatesMap(rRevEntryStatesMap, rEntryStatesMap)
00720 void CreateEntryStatesMap(const std::map<StateSet,Idx>& rRevEntryStatesMap,
00721         std::map<Idx,StateSet>& rEntryStatesMap) {
00722   std::map<StateSet,Idx>::const_iterator it;
00723   for (it = rRevEntryStatesMap.begin(); it != rRevEntryStatesMap.end(); ++it) {
00724     rEntryStatesMap.insert(std::make_pair(it->second, it->first));
00725   }
00726 }
00727 
00728 
00729 
00730 } // namespace faudes

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3