libFAUDES

Sections

Index

project.cpp

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

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6