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 //   cout << "good" << endl;
00071   return false;
00072   
00073   
00074 //   bool valid1 = validFrom(planCleaned,firstSuspect);
00075 //   
00076 //   bool valid2 = false;
00077 //   
00078 //   if(!valid1 && firstSuspect != planCleaned.begin())
00079 //     valid2 = validFrom(planCleaned, -- firstSuspect);
00080 //   
00081 // //     badIt = bad->begin();
00082 // //     cout << " --- bad plans --- " << bad->size() << endl;
00083 // //     for(; badIt != bad->end(); ++badIt) {
00084 // //       copy(badIt->begin(), badIt->end(), ostream_iterator<string>(cout, " "));
00085 // //       cout << endl;
00086 // //     }
00087 // //     cout << " --- " << endl;
00088 //     
00089 //   return valid1 || valid2;
00090  
00091 }
00092 
00093 bool IsNotLocallyOptimal::hasLoops(const AnswerSet& plan) const {
00094     set<AspFluentRef> state;
00095     
00096     set< set<AspFluentRef>, StateComparator<AspFluentRef> > allStates;
00097     
00098     IsAnAction isAnAction(allActions);
00099     int timeStep = 0;
00100     
00101     AnswerSet::FluentSet::const_iterator p = plan.getFluents().begin();
00102     for(p; p!= plan.getFluents().end(); ++p) {
00103       
00104       if(p->getTimeStep() != timeStep) {
00105 
00106         bool present = !(allStates.insert(state).second);
00107 
00108         if(present)
00109           return true;
00110         
00111         state.clear();
00112         ++timeStep;
00113       }
00114 
00115       if(!isAnAction(*p))
00116         state.insert(*p);
00117 
00118     }
00119     
00120     //last state
00121     bool present = !(allStates.insert(state).second);
00122 
00123     if(present)
00124         return true;
00125         
00126     return false;
00127 }
00128 
00129 
00130 bool IsNotLocallyOptimal::checkSectionWithLength(const std::list<AspFluentRef>& planCleaned, 
00131                               const std::list<AspFluentRef>::const_iterator firstSuspect,
00132                                int length) const {
00133   
00134 
00135   int pos = distance(planCleaned.begin(), firstSuspect); 
00136   int diffPos = std::max(-(length -1), -pos);
00137   unsigned int initialPos = pos + diffPos;
00138   
00139 //    cout << "pos " << pos << " diffpos " << diffPos << " initialPos " << initialPos << endl;
00140 
00141   
00142   std::list<AspFluentRef>::const_iterator initial = firstSuspect;
00143   advance(initial, diffPos);
00144   
00145   for(int size = planCleaned.size(); initialPos <= pos && initialPos + length <= size; ++ initialPos, ++initial) {
00146     
00147 //       cout << "initialPos: " << initialPos << endl;
00148     
00149       list<AspFluentRef> testPlan(planCleaned.begin(), initial);
00150       
00151       std::list<AspFluentRef>::const_iterator final = initial;
00152       advance(final,length);
00153       
00154       testPlan.insert(testPlan.end(),final,planCleaned.end());
00155       
00156 //         cout << "test plan: ";
00157 //         copy(testPlan.begin(), testPlan.end(), ostream_iterator<string>(cout, " "));
00158 //         cout << endl;
00159     
00160       if(checkPlanValidity(testPlan)) {
00161 //         cout << "bad" << endl;
00162         return true;
00163       }
00164   }
00165   
00166 //   cout << "done with length " << length << endl;
00167   
00168   return false;
00169 }
00170 
00171 
00172 bool IsNotLocallyOptimal::validFrom(const list<AspFluentRef>& planCleaned, list<AspFluentRef>::const_iterator firstSuspect) const{
00173 
00174  //create a test plan without the suspicious action
00175   list<AspFluentRef> testPlan(planCleaned.begin(), firstSuspect);
00176   list<AspFluentRef>::iterator suspectInTest = testPlan.end();
00177   
00178   testPlan.insert(testPlan.end(),(++firstSuspect),planCleaned.end());
00179   advance(suspectInTest, -distance(firstSuspect,planCleaned.end()));
00180   
00181   bool done = false;
00182   while(!done) {
00183   
00184 //   cout << "test plan: ";
00185 //   copy(testPlan.begin(), testPlan.end(), ostream_iterator<string>(cout, " "));
00186 //   cout << endl;
00187     
00188   bool isValid = checkPlanValidity(testPlan);
00189   if(isValid) {
00190     bad->insert(planCleaned);
00191 
00192 //     cout << "bad" << endl;
00193     
00194     return true;
00195     
00196   }
00197   //keep removing actions starting from the first suspicious one
00198   if(suspectInTest == testPlan.end())
00199     done = true;
00200   else 
00201     suspectInTest = testPlan.erase(suspectInTest);
00202   
00203   }
00204   
00205 //   cout << "good" << endl;
00206   return false;
00207 }
00208 
00209 list<AspFluentRef> IsNotLocallyOptimal::cleanPlan(const AnswerSet& plan) const{
00210   
00211   
00212   list<AspFluentRef> actionsOnly;
00213   
00214   if(planFiltered) {
00215     actionsOnly.insert(actionsOnly.end(),plan.getFluents().begin(),plan.getFluents().end());
00216   }
00217   else {
00218   remove_copy_if(plan.getFluents().begin(), plan.getFluents().end(),
00219                    back_inserter(actionsOnly),not1(IsAnAction(allActions)));
00220   }
00221   
00222   return actionsOnly;
00223 
00224 }
00225 
00226 list<AspFluentRef>::const_iterator IsNotLocallyOptimal::findFirstSuspiciousAction(const list<AspFluentRef>& plan) const {
00227   
00228   if(good->empty())
00229     return plan.end(); //shouldn't really happen...
00230     
00231 
00232   //either the lower bound or the element before it are the most similar plans to mine.
00233   PlanSet::iterator lb =  good->lower_bound(plan);
00234   
00235 //   if(lb != good->end()) {
00236 //     cout << "lower bound: ";
00237 //     copy(lb->begin(), lb->end(), ostream_iterator<string>(cout, " "));
00238 //     cout <<endl;
00239 //   }
00240   
00241 
00242   int dist1 = -1, dist2 = -1;
00243   list<AspFluentRef>::const_iterator sus1=plan.end(), sus2= plan.end();
00244   
00245   if(lb != good->end()) {
00246     pair< list<AspFluentRef>::const_iterator, list<AspFluentRef>::const_iterator > different = 
00247               mismatch(lb->begin(), lb->end(), plan.begin(), ActionEquality());
00248     dist1 = distance(plan.begin(), different.second);
00249     sus1 = different.second;
00250   }
00251   
00252  
00253   if (lb != good->begin()) {
00254     --lb;
00255 
00256 //     cout << "-- lower bound: ";
00257 //     copy(lb->begin(), lb->end(), ostream_iterator<string>(cout, " "));
00258 //     cout <<endl;
00259     
00260     pair< list<AspFluentRef>::const_iterator, list<AspFluentRef>::const_iterator > different =
00261       mismatch(lb->begin(), lb->end(), plan.begin(), ActionEquality());
00262     dist2 = distance(plan.begin(), different.second);
00263     sus2 = different.second;
00264   }
00265   
00266 //    cout << "dist " << dist1 << " " << dist2 << endl;
00267   if(dist1 > dist2){
00268 //     cout << "dist1" << endl;
00269     return sus1;
00270   }
00271 //   else 
00272 //     cout << "dist2" << endl;
00273   
00274   return sus2;
00275   
00276 }
00277   
00278 bool IsNotLocallyOptimal::checkPlanValidity(const list<AspFluentRef>& plan) const {
00279   PlanSet::const_iterator found = good->find(plan);
00280   if(found != good->end())
00281     return true;
00282   
00283   found = bad->find(plan);
00284   
00285   return found != bad->end();
00286 }
00287 
00288 
00289 }
00290 


bwi_kr_execution
Author(s): Matteo Leonetti, Piyush Khandelwal
autogenerated on Fri Aug 28 2015 10:14:46