con_cctrim.cppGo 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 |