IsNotLocallyOptimal.cpp
Go to the documentation of this file.
00001 #include "IsNotLocallyOptimal.h"
00002 
00003 #include <actasp/AnswerSet.h>
00004 #include <actasp/action_utils.h>
00005 #include <actasp/state_utils.h>
00006 
00007 #include <algorithm>
00008 
00009 #include <iostream>
00010 #include <iterator>
00011 
00012 using namespace std;
00013 
00014 namespace actasp {
00015   
00016 IsNotLocallyOptimal::IsNotLocallyOptimal(const PlanSet* good, PlanSet* bad, 
00017                                          const ActionSet& allActions, 
00018                                          unsigned int shortestLength,
00019                                          bool planFiltered
00020                                         ) :
00021                                          good(good), bad(bad), allActions(allActions), 
00022                                          shortestLength(shortestLength),
00023                                          planFiltered(planFiltered){}
00024 
00025   
00026 bool IsNotLocallyOptimal::operator()(const AnswerSet& plan) {
00027   
00028 //   cout << "*** test IsNotLocallyOptimal" << endl;
00029   
00030 //       PlanSet::const_iterator badIt = bad->begin();
00031 //     cout << " --- bad plans --- " << bad->size() << endl;
00032 //     for(; badIt != bad->end(); ++badIt) {
00033 //       copy(badIt->begin(), badIt->end(), ostream_iterator<string>(cout, " "));
00034 //       cout << endl;
00035 //     }
00036 //     cout << " --- " << endl;
00037   
00038   if(!planFiltered) {
00039     bool loops = hasLoops(plan);
00040     if(loops)
00041       return true;
00042   }
00043   
00044 
00045   const list<AspFluentRef> planCleaned = cleanPlan(plan); //remove fluents that are not actions
00046 
00047 //   cout << "piano pulito: ";
00048 //   copy(planCleaned.begin(), planCleaned.end(), ostream_iterator<string>(cout, " "));
00049 //   cout << endl;
00050   
00051   //find the first action that does not belong to any minimal plan
00052   list<AspFluentRef>::const_iterator firstSuspect = findFirstSuspiciousAction(planCleaned); 
00053 
00054   
00055   if(firstSuspect == planCleaned.end()) {
00056 //     cout << "good" << endl;
00057     return false;
00058   }
00059   
00060 //   cout << "first suspect: " << firstSuspect->toString() << endl;
00061   
00062   for(int l = 1, size = planCleaned.size(); l <= size - shortestLength; ++l) {
00063 
00064     if(checkSectionWithLength(planCleaned,firstSuspect,l)) {
00065       bad->insert(planCleaned);
00066       return true;
00067     }
00068 
00069   }
00070   
00071   //last check, if the action before the suspect is useless
00072   
00073   list<AspFluentRef>::const_iterator beforeSuspect = firstSuspect;
00074   advance(beforeSuspect, -1);
00075   list<AspFluentRef> withoutBeforeSuspect(planCleaned.begin(),beforeSuspect);
00076   withoutBeforeSuspect.insert(withoutBeforeSuspect.end(),firstSuspect,planCleaned.end());
00077   bool lastCheck = checkPlanValidity(withoutBeforeSuspect);
00078   if(lastCheck) {
00079     bad->insert(planCleaned);
00080     //cout <<  "bad!" << endl;
00081   }
00082 //  else
00083 //    cout << "good after check" << endl;
00084   
00085   return lastCheck;
00086   
00087   
00088 //   bool valid1 = validFrom(planCleaned,firstSuspect);
00089 //   
00090 //   bool valid2 = false;
00091 //   
00092 //   if(!valid1 && firstSuspect != planCleaned.begin())
00093 //     valid2 = validFrom(planCleaned, -- firstSuspect);
00094 //   
00095 // //     badIt = bad->begin();
00096 // //     cout << " --- bad plans --- " << bad->size() << endl;
00097 // //     for(; badIt != bad->end(); ++badIt) {
00098 // //       copy(badIt->begin(), badIt->end(), ostream_iterator<string>(cout, " "));
00099 // //       cout << endl;
00100 // //     }
00101 // //     cout << " --- " << endl;
00102 //     
00103 //   return valid1 || valid2;
00104  
00105 }
00106 
00107 bool IsNotLocallyOptimal::hasLoops(const AnswerSet& plan) const {
00108     set<AspFluentRef> state;
00109     
00110     set< set<AspFluentRef>, StateComparator<AspFluentRef> > allStates;
00111     
00112     IsAnAction isAnAction(allActions);
00113     int timeStep = 0;
00114     
00115     AnswerSet::FluentSet::const_iterator p = plan.getFluents().begin();
00116     for(; p!= plan.getFluents().end(); ++p) {
00117       
00118       if(p->getTimeStep() != timeStep) {
00119 
00120         bool present = !(allStates.insert(state).second);
00121 
00122         if(present)
00123           return true;
00124         
00125         state.clear();
00126         ++timeStep;
00127       }
00128 
00129       if(!isAnAction(*p))
00130         state.insert(*p);
00131 
00132     }
00133     
00134     //last state
00135     bool present = !(allStates.insert(state).second);
00136 
00137     if(present)
00138         return true;
00139         
00140     return false;
00141 }
00142 
00143 
00144 bool IsNotLocallyOptimal::checkSectionWithLength(const std::list<AspFluentRef>& planCleaned, 
00145                               const std::list<AspFluentRef>::const_iterator firstSuspect,
00146                                int length) const {
00147   
00148 
00149   int pos = distance(planCleaned.begin(), firstSuspect); 
00150   int diffPos = std::max(-(length -1), -pos);
00151   unsigned int initialPos = pos + diffPos;
00152   
00153 //    cout << "pos " << pos << " diffpos " << diffPos << " initialPos " << initialPos << endl;
00154 
00155   
00156   std::list<AspFluentRef>::const_iterator initial = firstSuspect;
00157   advance(initial, diffPos);
00158   
00159   for(int size = planCleaned.size(); initialPos <= pos && initialPos + length <= size; ++ initialPos, ++initial) {
00160     
00161 //       cout << "initialPos: " << initialPos << endl;
00162     
00163       list<AspFluentRef> testPlan(planCleaned.begin(), initial);
00164       
00165       std::list<AspFluentRef>::const_iterator final = initial;
00166       advance(final,length);
00167       
00168       testPlan.insert(testPlan.end(),final,planCleaned.end());
00169       
00170 //         cout << "test plan: ";
00171 //         copy(testPlan.begin(), testPlan.end(), ostream_iterator<string>(cout, " "));
00172 //         cout << endl;
00173     
00174       if(checkPlanValidity(testPlan)) {
00175 //         cout << "bad" << endl;
00176         return true;
00177       }
00178   }
00179   
00180 //   cout << "done with length " << length << endl;
00181   
00182   return false;
00183 }
00184 
00185 
00186 bool IsNotLocallyOptimal::validFrom(const list<AspFluentRef>& planCleaned, list<AspFluentRef>::const_iterator firstSuspect) const{
00187 
00188  //create a test plan without the suspicious action
00189   list<AspFluentRef> testPlan(planCleaned.begin(), firstSuspect);
00190   list<AspFluentRef>::iterator suspectInTest = testPlan.end();
00191   
00192   testPlan.insert(testPlan.end(),(++firstSuspect),planCleaned.end());
00193   advance(suspectInTest, -distance(firstSuspect,planCleaned.end()));
00194   
00195   bool done = false;
00196   while(!done) {
00197   
00198 //   cout << "test plan: ";
00199 //   copy(testPlan.begin(), testPlan.end(), ostream_iterator<string>(cout, " "));
00200 //   cout << endl;
00201     
00202   bool isValid = checkPlanValidity(testPlan);
00203   if(isValid) {
00204     bad->insert(planCleaned);
00205 
00206 //     cout << "bad" << endl;
00207     
00208     return true;
00209     
00210   }
00211   //keep removing actions starting from the first suspicious one
00212   if(suspectInTest == testPlan.end())
00213     done = true;
00214   else 
00215     suspectInTest = testPlan.erase(suspectInTest);
00216   
00217   }
00218   
00219 //   cout << "good" << endl;
00220   return false;
00221 }
00222 
00223 list<AspFluentRef> IsNotLocallyOptimal::cleanPlan(const AnswerSet& plan) const{
00224   
00225   
00226   list<AspFluentRef> actionsOnly;
00227   
00228   if(planFiltered) {
00229     actionsOnly.insert(actionsOnly.end(),plan.getFluents().begin(),plan.getFluents().end());
00230   }
00231   else {
00232   remove_copy_if(plan.getFluents().begin(), plan.getFluents().end(),
00233                    back_inserter(actionsOnly),not1(IsAnAction(allActions)));
00234   }
00235   
00236   return actionsOnly;
00237 
00238 }
00239 
00240 list<AspFluentRef>::const_iterator IsNotLocallyOptimal::findFirstSuspiciousAction(const list<AspFluentRef>& plan) const {
00241   
00242   if(good->empty())
00243     return plan.end(); //shouldn't really happen...
00244     
00245 
00246   //either the lower bound or the element before it are the most similar plans to mine.
00247   PlanSet::iterator lb =  good->lower_bound(plan);
00248   
00249 //   if(lb != good->end()) {
00250 //     cout << "lower bound: ";
00251 //     copy(lb->begin(), lb->end(), ostream_iterator<string>(cout, " "));
00252 //     cout <<endl;
00253 //   }
00254   
00255 
00256   int dist1 = -1, dist2 = -1;
00257   list<AspFluentRef>::const_iterator sus1=plan.end(), sus2= plan.end();
00258   
00259   if(lb != good->end()) {
00260     pair< list<AspFluentRef>::const_iterator, list<AspFluentRef>::const_iterator > different = 
00261               mismatch(lb->begin(), lb->end(), plan.begin(), ActionEquality());
00262     dist1 = distance(plan.begin(), different.second);
00263     sus1 = different.second;
00264   }
00265   
00266  
00267   if (lb != good->begin()) {
00268     --lb;
00269 
00270 //     cout << "-- lower bound: ";
00271 //     copy(lb->begin(), lb->end(), ostream_iterator<string>(cout, " "));
00272 //     cout <<endl;
00273     
00274     pair< list<AspFluentRef>::const_iterator, list<AspFluentRef>::const_iterator > different =
00275       mismatch(lb->begin(), lb->end(), plan.begin(), ActionEquality());
00276     dist2 = distance(plan.begin(), different.second);
00277     sus2 = different.second;
00278   }
00279   
00280 //    cout << "dist " << dist1 << " " << dist2 << endl;
00281   if(dist1 > dist2){
00282 //     cout << "dist1" << endl;
00283     return sus1;
00284   }
00285 //   else 
00286 //     cout << "dist2" << endl;
00287   
00288   return sus2;
00289   
00290 }
00291   
00292 bool IsNotLocallyOptimal::checkPlanValidity(const list<AspFluentRef>& plan) const {
00293   PlanSet::const_iterator found = good->find(plan);
00294   if(found != good->end())
00295     return true;
00296   
00297   found = bad->find(plan);
00298   
00299   return found != bad->end();
00300 }
00301 
00302 
00303 }
00304 


bwi_kr_execution
Author(s): Matteo Leonetti, Piyush Khandelwal
autogenerated on Thu Jun 6 2019 17:57:37