con_cctrim.cpp

Go to the documentation of this file.
00001 /** @file con_cctrim.cpp more efficient Trim() operation */
00002 
00003 /*
00004  *
00005  * Copyright (C) 2011  Tomas Masopust
00006  *
00007  * Implementation of a bit more efficient Trim() function
00008  * based on graph algorithms
00009  *
00010  */
00011 
00012 #include "con_cctrim.h"
00013 #include <vector>
00014 #include <string>
00015 #include <queue>
00016 
00017 using namespace std;
00018 
00019 namespace faudes {
00020 
00021 //  The graph adjecency list representation
00022 class adjlist {
00023   private:
00024     unsigned int root;
00025     StateSet finalStates;
00026     unsigned int numberOfNodes;
00027         struct node {
00028               unsigned int state;
00029               node *link;
00030       node *blink;
00031     };
00032     vector<node*> nodeArray;
00033     vector<bool> examined;
00034   public:
00035     adjlist(const Generator& gen);
00036     unsigned int getRoot();
00037     unsigned int getNumberOfNodes();
00038     void Display();
00039     void SetExamined(bool b);
00040     StateSet Accessible();
00041     StateSet CoAccessible();
00042     void ReverseAndRoot();
00043     bool IsAccessible();
00044     ~adjlist();
00045 };
00046 
00047 // Constructor
00048 adjlist::adjlist(const Generator& gen) : 
00049   root(gen.InitState()), 
00050   finalStates(gen.MarkedStates()),
00051   numberOfNodes(gen.States().MaxIndex()), 
00052   nodeArray(gen.States().MaxIndex()),
00053   examined(gen.States().MaxIndex()) {
00054   // Better to use gen.Size() instead of gen.States().MaxIndex(), but there is a problem with numbered states!
00055   // Or add some additional table with refering my indexes to the original indexes
00056   // The array of nodes and examine flags
00057   for (unsigned int i=0; i < numberOfNodes; i++) {  
00058     nodeArray[i] = NULL;
00059     examined[i]  = false;
00060   }
00061   // List of adjecent nodes to each node
00062   TransSet::Iterator eit;
00063   for (eit = gen.TransRelBegin(); eit != gen.TransRelEnd(); ++eit) {
00064     if (eit->X1 != eit->X2) {  // we can ignore loops
00065       node* n = new node;
00066       n->state = eit->X2;
00067       n->link = nodeArray[eit->X1-1];
00068       n->blink = NULL;
00069       if (nodeArray[eit->X1-1] == NULL) {
00070         nodeArray[eit->X1-1] = n;
00071       } else {
00072         nodeArray[eit->X1-1]->blink = n;
00073         nodeArray[eit->X1-1] = n;
00074       }
00075     }
00076   }
00077   // remove multiedges
00078   vector<unsigned int> mult (numberOfNodes);
00079   for (unsigned int i=0; i < numberOfNodes; i++) {  
00080     mult[i] = 0;
00081   }
00082   for (unsigned int i=0; i < nodeArray.size(); i++) {
00083     node* q=nodeArray[i]; 
00084     while (q != NULL) {
00085       if (mult[q->state-1] != i+1) {
00086         mult[q->state-1] = i+1;
00087         q=q->link;
00088       } else {
00089         if (q->blink != NULL) {
00090           node* p = q->blink;
00091           p->link = q->link;
00092           if (p->link != NULL) {
00093             p->link->blink = p;
00094           }
00095           delete q;
00096           q = p->link;
00097         } else {
00098           nodeArray[i] = q->link;
00099           node* p = q;
00100           delete p;
00101           if (nodeArray[i] != NULL) {
00102             nodeArray[i]->blink = NULL;
00103           } 
00104           q = nodeArray[i];
00105         }
00106       }
00107     }
00108   }
00109 }
00110 
00111 unsigned int adjlist::getRoot() {
00112   return root;
00113 }
00114 
00115 unsigned int adjlist::getNumberOfNodes() {
00116   return numberOfNodes;
00117 }
00118 
00119 void adjlist::Display() {
00120   cout << " ===== Displaying the graph ===== " << endl;
00121   for (unsigned int i=0; i < nodeArray.size(); i++) {  
00122     node *q;
00123     cout << "Neighbours of " << i+1 << ": ";
00124     for(q=nodeArray[i]; q != NULL; q=q->link) {
00125       cout << q->state << ", ";
00126     }
00127     cout << endl;
00128   }
00129 }
00130 
00131 // Sets all examined flags of nodes to a value b
00132 void adjlist::SetExamined(bool b) {
00133   for (unsigned int i=0; i < nodeArray.size(); i++) {
00134     examined[i] = false;
00135   }
00136 }
00137 
00138 // Returns the set of accessible states
00139 StateSet adjlist::Accessible() {
00140   this->SetExamined(false);
00141   StateSet AccessibleSet;
00142   queue<Idx> que;
00143   que.push(root);
00144   examined[root-1]=true;
00145   Idx index;
00146   while (!que.empty()) {
00147     index = que.front();
00148     que.pop();
00149     AccessibleSet.Insert(index);
00150     node* q=nodeArray[index-1];
00151     while (q != NULL) {
00152       if (!examined[q->state-1]) {
00153         que.push(q->state);
00154         examined[q->state-1] = true;
00155       }
00156       q=q->link;
00157     }
00158   }
00159   return AccessibleSet;
00160 }
00161 
00162 // Returns the set of coaccessible states
00163 StateSet adjlist::CoAccessible() {
00164   // Reverse the graph -- adds new root node
00165   this->ReverseAndRoot();
00166   // Check if the reversed rooted graph is accessible
00167   return this->Accessible();
00168 }
00169 
00170 // Reverses the graph and creates a new unique root
00171 void adjlist::ReverseAndRoot() {
00172   vector<node*> v(numberOfNodes+1);
00173   for (unsigned int i=0; i < v.size(); i++) {
00174     v[i] = NULL;
00175   }
00176   for (unsigned int i=0; i < nodeArray.size(); i++) {  
00177     for(node* q=nodeArray[i]; q != NULL; q=q->link) {
00178       node* sNode = new node;
00179       sNode->state = i+1;
00180       sNode->link = v[q->state-1];
00181       v[q->state-1] = sNode;
00182     }
00183   }
00184   nodeArray.resize(numberOfNodes+1);
00185   nodeArray = v;
00186   // new root node linked with all original final states
00187   StateSet::Iterator sit;
00188   for (sit = finalStates.Begin(); sit != finalStates.End(); ++sit) {
00189     node* n = new node;
00190     n->state = *sit;
00191     n->link = nodeArray[numberOfNodes]; 
00192     nodeArray[numberOfNodes] = n;
00193   }
00194   root = numberOfNodes+1;
00195 }
00196 
00197 bool adjlist::IsAccessible() {
00198   StateSet acc = this->Accessible();
00199   if (this->getNumberOfNodes() == acc.Size()) {
00200     return true;
00201   }
00202   return false;
00203 }
00204 
00205 // Destructor
00206 adjlist::~adjlist() {
00207   for (unsigned int i=0; i < nodeArray.size(); i++) {  
00208     node* p = nodeArray[i];
00209     node* q;
00210     while (p != NULL) {
00211       q = p->link;
00212       delete p;
00213       p = q;
00214     }
00215   }
00216 } 
00217 // end of the adjacency list
00218 
00219 
00220 // ccTrim() function
00221 bool ccTrim(const Generator& gen, Generator& trimGen) {
00222   // This means that states are number
00223   if (gen.Size() != gen.States().MaxIndex()) {
00224     cerr    << "=============================================================================\n" 
00225       << "You probably use numbers for state names, and some state-numbers are missing.\n" 
00226       << "Rename states for the algorithm to work more efficiently.\n"
00227       << "=============================================================================" << endl;
00228   }
00229 
00230   if (!IsDeterministic(gen)) {
00231     cerr << "The generator is not deterministic." << endl;
00232     return false;
00233   }
00234   
00235   if (gen.InitStatesSize() != 1) {
00236     cerr << "The generator does not have only one initial state." << endl;
00237     return false;
00238   }
00239 
00240   trimGen = gen;
00241   // Create the graph representation of the generator gen
00242   adjlist graph (trimGen);
00243   // Set of accessible states
00244   StateSet acc = graph.Accessible();
00245   // Set of unaccessible states
00246   StateSet unacc = trimGen.States() - acc;
00247   // Set of coaccessible states
00248   StateSet coacc = graph.CoAccessible();
00249   // Set of uncoaccessible states
00250   StateSet uncoacc = trimGen.States() - coacc;
00251   // Set of states that are not accessible or coaccessible
00252   StateSet un = unacc + uncoacc;
00253   trimGen.DelStates(un);
00254   return un.Size()==0;
00255 }
00256 
00257 } //end namespace

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen