this repo has no description
1/************************************************************ WorkManager.cc 2 Copyright (c) 2010 Universite d'Orleans - Jeremie Vautard 3 4 Permission is hereby granted, free of charge, to any person obtaining a copy 5 of this software and associated documentation files (the "Software"), to deal 6 in the Software without restriction, including without limitation the rights 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 copies of the Software, and to permit persons to whom the Software is 9 furnished to do so, subject to the following conditions: 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 THE SOFTWARE. 21*************************************************************************/ 22 23#include "WorkManager.hh" 24bool isPrefix(vector<int> prefix,vector<int> a) { 25 if (a.size() < prefix.size()) 26 return false; 27 else 28 for (unsigned int i=0;i<prefix.size();i++) 29 if (prefix[i] != a[i]) 30 return false; 31 32 return true; 33} 34 35WorkPool::WorkPool(WorkComparator* a) { 36 cmp=a; 37} 38 39void WorkPool::push(QWork q) { 40 list<QWork>::iterator i = l.begin(); 41 while (i != l.end() && cmp->cmp((*i),q)) i++; 42 l.insert(i,q); 43} 44 45QWork WorkPool::pop() { 46 QWork ret=l.front(); 47 l.pop_front(); 48 return ret; 49} 50 51void WorkPool::trash(vector<int> prefix) { 52 // cout<<" WPT called on "; 53 //if (prefix.empty()) cout<<"empty"; 54 //for (int i=0;i< prefix.size();i++) cout<<prefix[i]<<" "; 55 //cout<<endl; 56 // cout<<"debug "<<l.size()<<endl; 57 58 list<QWork>::iterator i=l.begin(); 59 while (!(i == l.end())) { 60 // cout<<"| "; 61 // cout.flush(); 62 bool avance=true; 63 vector<int> root = (*i).root(); 64 if (isPrefix(prefix,root)) { 65 (*i).clean(); 66 i=l.erase(i); 67 avance = false; 68 // cout<<"erased"; 69 } 70 if (avance) i++; 71 } 72 //cout<<endl; 73 74 //for (list<QWork>::iterator i=l.begin();i != l.end();i++) { 75 //vector<int> root = (*i).root(); 76 //if (isPrefix(prefix,root)) { 77 // cout<<" trashing "; 78 // if (root.empty()) cout<<"empty"; 79 // for (int j=0;j< root.size();j++) cout<<root[j]<<" "; 80 // cout<<endl; 81 //(*i).clean(); 82 //l.erase(i); 83 //i--; 84 //} 85 // } 86} 87 88 89void WorkManager::getNewWorks() { 90 // cout<<"WM asking for "<<actives.front()<<" to stopandreturn"<<endl; 91 (actives.front())->stopAndReturn(); 92} 93 94WorkManager::WorkManager(Qcop* p,WorkComparator* c) : Todos(c) { 95 problem=p; 96 vector<int> v; 97 MySpace* espace=p->getSpace(0); 98 Options o; 99 Engine* solutions = new WorkerToEngine<Gecode::Search::Sequential::DFS>(espace,/*sizeof(MySpace),*/o); 100 QWork first(0,v,solutions); 101 Todos.push(first); 102 finished=false; 103 S = Strategy::Dummy(); 104 S.attach(Strategy::Stodo()); 105} 106 107QWork WorkManager::getWork(AQWorker* worker) { 108 // clock_t start = clock(); 109 // cout<<worker<<" WAIT getWork "<<start<<endl; 110 mex.acquire(); 111 // clock_t stop = clock(); 112 // cout<<worker<<" CONT getWork "<<stop<<" waited "<<(stop-start)<<endl; 113 114 // cout<<"G ";cout.flush(); 115 // cout<<"WM getwork acquired"<<endl; 116 QWork ret; 117 if (Todos.empty()) { 118 // cout<<"WM : Todos was empty"<<endl; 119 if (actives.empty()) { 120 // cout<<"WM : Actives was empty, stopping worker."<<endl; 121 ret = QWork::Stop(); 122 finished=true; 123 } 124 else { 125 getNewWorks(); 126 // cout<<"WM sleeping worker"<<endl; 127 ret = QWork::Wait(); 128 idles.push_back(worker); 129 } 130 } 131 else { 132 // cout<<"WM : giving work "; 133 ret = Todos.top(); 134 Todos.pop(); 135 // if (ret.root().empty()) cout<<"empty"; 136 // for (int i=0;i< ret.root().size();i++) cout<<ret.root()[i]<<" "; 137 // cout<<endl; 138 139 actives.push_back(worker); 140 } 141 // cout<<"WM getwork release"<<endl; 142 mex.release(); 143 return ret; 144} 145 146void WorkManager::returnWork(AQWorker* worker,Strategy ret,list<QWork> todo,vector<int> position) { 147 // If the worker is not among the actives ones, ignore his job. Else, withdraw it from the active workers 148 // and process its result 149 150 // clock_t start = clock(); 151 // cout<<worker<<" WAIT returnWork "<<start<<endl; 152 mex.acquire(); 153 // clock_t stop = clock(); 154 // cout<<worker<<" CONT returnWork "<<stop<<" waited "<<(stop-start)<<endl; 155 // cout<<"RW returnWork acquired"<<endl; 156 // cout<<"returning work at "; 157 // if (position.empty()) cout<<"empty"; 158 // for (int i=0;i< position.size();i++) cout<<position[i]<<" "; 159 // cout<<endl; 160 161 bool ok=false; 162 list<AQWorker*>::iterator i = actives.begin(); 163 while (!(i == actives.end()) && !ok) { 164 bool avance=true; 165 if ((*i) == worker) { 166 // cout<<"RW Worker found in actives. Deleting"<<endl; 167 i=actives.erase(i); 168 avance = false; 169 ok=true; 170 } 171 if (avance) ++i; 172 } 173 if (!ok) { 174 // cout<<"RW Ignoring work"<<endl; 175 // when ignoring the result, we have to delete every search engine from the eventual to-do works it did 176 for (list<QWork>::iterator j = todo.begin();j != todo.end();j++) { 177 (*j).clean(); 178 } 179 // cout<<"RW release"<<endl; 180 mex.release(); 181 return; 182 } 183 184 // processing results... 185 186 // adding todo to Todos 187 188 // going to father of substrategy 189 bool acceptable = true; 190 Strategy father = S.getSubStrategy(position); 191 if (father.isDummy() && (father.id() != S.id())) { 192 // cout<<"ERROR : RW Work was not in current strategy. Ignoring."<<endl; 193 acceptable=false; 194 } 195 // remove the Todo node that marked this work 196 if (acceptable) { 197 // cout<<" RW Father position is "; 198 // vector<int> checkPosition = father.getPosition(); 199 // if (checkPosition.empty()) cout<<"empty"; 200 // for (int i=0;i< checkPosition.size();i++) cout<<checkPosition[i]<<" "; 201 // cout<<endl; 202 203 for (list<QWork>::iterator j = todo.begin();j != todo.end();j++) { 204 // cout<<"WM todo + 1"<<endl; 205 if (!idles.empty()) { 206 // cout<<"WM waking an idle"<<endl; 207 AQWorker* towake = idles.back(); 208 idles.pop_back(); 209 towake->wake(); 210 } 211 // cout<<"RW Adding work in Todos : "; 212 // if ((*j).root().empty()) cout<<"empty"; 213 // for (int i=0;i< (*j).root().size();i++) cout<<(*j).root()[i]<<" "; 214 // cout<<endl; 215 216 Todos.push(*j); 217 } 218 219 for (unsigned int i=0;i<father.degree();i++) { 220 if (father.getChild(i).isTodo()) { 221 // cout<<"RW deleting Todo node"<<endl; 222 father.detach(i); 223 i--; 224 } 225 } 226 227 228 if (!ret.isComplete()) { // still work to do... 229 // attach the (incomplete) substrategy 230 // cout<<"RW returned work was incomplete. Attaching"<<endl; 231 father.attach(ret); 232 } 233 else if (!ret.isFalse()) { // complete substrategy 234 // attach the (complete) substrategy 235 // recursively update node 236 // cout<<"RW returned work was true. Attaching and updating"<<endl; 237 father.attach(ret); 238 updateTrue(father); 239 } 240 else { //ret is false 241 // cout<<"RW returned work was false. Attaching and updating"<<endl; 242 int myscope = problem->qt_of_var(position.size() + 1); 243 if (myscope) { // if ret was a forall node, the father itself is false 244 // cout<<"RW work is A -> father is false"<<endl; 245 updateFalse(father); 246 } 247 else if (father.degree() == 0) { // Here ret was an exists node. If the father has no other son, then the father itself is false 248 // cout<<"RW work is E, father is without child"<<endl; 249 updateFalse(father); 250 } 251 // else { 252 // // cout<<"RW work is E, father still has children"<<endl; 253 // } 254 } 255 } 256 else { // work was not acceptable 257 for (list<QWork>::iterator j = todo.begin();j != todo.end();j++) { 258 (*j).clean(); 259 } 260 } 261 262 // cout<<"RW release"<<endl; 263 mex.release(); 264} 265 266void WorkManager::updateTrue(Strategy s) { //called when s has a son who is a complete strategy 267 // cout<<" UT on "; 268 // vector<int> hihi = s.getPosition(); 269 // if (hihi.empty()) cout<<"empty"; 270 // for (int i=0;i< hihi.size();i++) cout<<hihi[i]<<" "; 271 // cout<<endl; 272 273 274 if (s.isComplete()) { 275 // cout<<" UT Complete "; 276 if (s.quantifier()) { 277 // cout<< " A "; 278 if (s.hasFather()) { 279 // cout<<" with father"<<endl; 280 updateTrue(s.getFather()); 281 } 282 else { 283 // cout<<" without father"<<endl; 284 } 285 } 286 else { 287 // cout<<" E "; 288 if (s.hasFather()) { 289 // cout<<" with father"<<endl; 290 Strategy father = s.getFather(); 291 while (father.degree() != 0) { 292 father.detach(father.degree()-1); 293 } 294 father.attach(s); 295 trashWorks(father.getPosition()); 296 updateTrue(father); 297 } 298 else { 299 // cout<<" without father"<<endl; 300 301 } 302 } 303 } 304 else { 305 // cout<<" UT incomplete"<<endl; 306 } 307} 308 309void WorkManager::updateFalse(Strategy s) { // called when s is false 310 // cout<<" UF on "; 311 // vector<int> hihi = s.getPosition(); 312 // if (hihi.empty()) cout<<"empty"; 313 // for (int i=0;i< hihi.size();i++) cout<<hihi[i]<<" "; 314 // cout<<endl; 315 316 trashWorks(s.getPosition()); 317 if (s.isDummy()) { 318 return; 319 } 320 Strategy father=s.getFather(); 321 322 if (s.quantifier()) { // if s is universal, its father is false 323 // cout<<" UF A"; 324 if (father.isDummy()) { // if father is dummy, it is the root of the strategy. We must cut all its children and ad a false node. 325 // cout<<" father root "<<endl; 326 while (father.degree() != 0) { 327 father.detach(father.degree()-1); 328 } 329 father.attach(Strategy::SFalse()); 330 } 331 // cout<<endl; 332 updateFalse(s.getFather()); 333 } 334 else { // if s is existential, it it detached from its father 335 // cout<<" UF E "; 336 father.detach(s); 337 if (father.degree() == 0) { 338 // cout<<" father false"<<endl; 339 updateFalse(father); 340 } 341 else { 342 // cout<<" father still not false"<<endl; 343 } 344 } 345} 346 347 348void WorkManager::trashWorks(vector<int> prefix) { 349 // cout<<" TW called on "; 350 // if (prefix.empty()) cout<<"empty"; 351 // for (int i=0;i< prefix.size();i++) cout<<prefix[i]<<" "; 352 // cout<<endl; 353 354 Todos.trash(prefix); 355 for (list<AQWorker*>::iterator i=actives.begin();i!=actives.end();i++) { 356 if (isPrefix(prefix,(*i)->workPosition())) { 357 // cout<<" TW stopping worker on"; 358 // vector<int> plop = (*i)->workPosition(); 359 // if (plop.empty()) cout<<"empty"; 360 // for (int j=0;j< plop.size();j++) cout<<plop[j]<<" "; 361 // cout<<endl; 362 (*i)->stopAndForget(); 363 i=actives.erase(i); 364 i--; 365 } 366 } 367} 368 369void WorkManager::printStatus() { 370 mex.acquire(); 371 cout<<(finished?"Problem solved":"Problem not solved")<<endl; 372 cout<<"Size of pool : "<<Todos.size()<<endl; 373 cout<<"# idles : "<<idles.size()<<endl; 374 cout<<"# actives : "<<actives.size()<<endl; 375 mex.release(); 376}