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

libFAUDES 2.22k --- 2013.04.02 --- c++ source docu by doxygen