Clingo3.cpp
Go to the documentation of this file.
00001 #include <actasp/reasoners/Clingo3.h>
00002 
00003 #include <actasp/AspRule.h>
00004 #include <actasp/AnswerSet.h>
00005 #include <actasp/AspAtom.h>
00006 
00007 #include <algorithm>
00008 #include <iterator>
00009 #include <sstream>
00010 #include <fstream>
00011 #include <cstdlib>
00012 #include <iostream>
00013 
00014 #define CURRENT_FILE_HOME queryDir // was  std::string("/tmp/")
00015 #define CURRENT_STATE_FILE std::string("current.asp")
00016 
00017 using namespace std;
00018 
00019 namespace actasp {
00020   
00021 Clingo3::Clingo3(const std::string& incrementalVar,
00022          const std::string& queryDir,
00023          const std::string& domainDir,
00024          const ActionSet& allActions,
00025          unsigned int max_time
00026         ) throw() :
00027   incrementalVar(incrementalVar),
00028   max_time(max_time),
00029   queryDir(queryDir),
00030   domainDir(domainDir),
00031   actionFilter() {
00032 
00033   if (max_time > 0 && !system("timeout 2>/dev/null")) //make sure timeout is available
00034     max_time = 0;
00035 
00036   //make sure directory ends with '/'
00037 
00038   if (this->queryDir.find_last_of("/") != (this->queryDir.length() -1))
00039     this->queryDir += "/";
00040 
00041   if ((this->domainDir.find_last_of("/")) != (this->domainDir.length() -1))
00042     this->domainDir += "/";
00043 
00044   //TODO test the existance of the directories
00045   
00046   //create current file
00047   ifstream currentFile((CURRENT_FILE_HOME + CURRENT_STATE_FILE).c_str());
00048   if(!currentFile.good()) //doesn't exist, create it or clingo will go mad
00049     setCurrentState(set<AspFluent>());
00050   
00051   currentFile.close();
00052 
00053   stringstream filterStream;
00054   filterStream << "#hide." << endl;
00055 
00056   std::set<AspFluent>::const_iterator actIt = allActions.begin();
00057   for (; actIt != allActions.end(); ++actIt) {
00058     filterStream << "#show " << actIt->getName() << "/" << actIt->arity() << "." << endl;
00059   }
00060 
00061   actionFilter = filterStream.str();
00062 }
00063 
00064 struct RuleToString3 {
00065   RuleToString3(unsigned int timeStepNum) {
00066     stringstream ss;
00067     ss << timeStepNum;
00068     timeStep = ss.str();
00069   }
00070 
00071   RuleToString3(const std::string& timeStepVar) : timeStep(timeStepVar) {}
00072 
00073   RuleToString3() : timeStep("") {}
00074 
00075   std::string operator()(const AspRule& rule) {
00076 
00077     stringstream ruleStream;
00078 
00079     //iterate over head
00080     for (int i =0, size = rule.head.size(); i <size; ++i) {
00081       if (timeStep.size() >0)
00082         ruleStream << rule.head[i].toString(timeStep);
00083       else
00084         ruleStream << rule.head[i].toString();
00085 
00086       if (i < (size-1))
00087         ruleStream << ", ";
00088     }
00089 
00090     if (!(rule.body.empty()))
00091       ruleStream << ":- ";
00092 
00093     //iterate over body
00094     for (int i =0, size = rule.body.size(); i <size; ++i) {
00095       if (timeStep.size() >0)
00096         ruleStream << rule.body[i].toString(timeStep);
00097       else
00098         ruleStream << rule.body[i].toString();
00099 
00100       if (i < (size-1))
00101         ruleStream << ", ";
00102     }
00103 
00104     if (!(rule.head.empty() && rule.body.empty()))
00105       ruleStream << "." << std::endl;
00106 
00107     return ruleStream.str();
00108   }
00109 
00110   string timeStep;
00111 };
00112 
00113 
00114 static string aspString(const std::vector<actasp::AspRule>& query, const string& timeStepVar) {
00115 
00116   stringstream aspStream;
00117   transform(query.begin(),query.end(),ostream_iterator<std::string>(aspStream),RuleToString3(timeStepVar));
00118   return aspStream.str();
00119 }
00120 
00121 static string aspString(const std::vector<actasp::AspRule>& query, unsigned int timeStep) {
00122 
00123   stringstream vs;
00124   vs << timeStep;
00125 
00126   return aspString(query,vs.str());
00127 }
00128 
00129 static std::list<AspFluent> parseAnswerSet(const std::string& answerSetContent) throw() {
00130 
00131   stringstream predicateLine(answerSetContent);
00132 
00133   list<AspFluent> predicates;
00134 
00135   //split the line based on spaces
00136   copy(istream_iterator<string>(predicateLine),
00137        istream_iterator<string>(),
00138        back_inserter(predicates));
00139 
00140   return predicates;
00141 }
00142 
00143 
00144 static std::list<actasp::AnswerSet> readAnswerSets(const std::string& filePath) throw() {
00145 
00146   ifstream file(filePath.c_str());
00147 
00148   list<AnswerSet> allSets;
00149   bool interrupted = false;
00150 
00151   string line;
00152   while (file) {
00153 
00154     getline(file,line);
00155 
00156     if (line == "UNSATISFIABLE")
00157       return list<AnswerSet>();
00158 
00159     if (line.find("INTERRUPTED : 1") != string::npos)
00160       interrupted = true;
00161 
00162     if (line.find("Answer") != string::npos) {
00163       getline(file,line);
00164       try {
00165         list<AspFluent> fluents = parseAnswerSet(line);
00166         allSets.push_back(AnswerSet(fluents.begin(), fluents.end()));
00167       } catch (std::invalid_argument& arg) {
00168         //swollow it and skip this answer set.
00169       }
00170     }
00171   }
00172 
00173   if (interrupted) //the last answer set might be invalid
00174     allSets.pop_back();
00175 
00176   return allSets;
00177 }
00178 
00179 string Clingo3::generatePlanQuery(std::vector<actasp::AspRule> goalRules,
00180                                 bool filterActions) const throw() {
00181   stringstream goal;
00182   goal << "#volatile " << incrementalVar << "." << endl;
00183   //I don't like this -1 too much, but it makes up for the incremental variable starting at 1
00184   goal << aspString(goalRules,incrementalVar+"-1") << endl;
00185 
00186   if (filterActions)
00187     goal << actionFilter;
00188 
00189 
00190   return goal.str();
00191 }
00192 
00193 
00194 std::list<actasp::AnswerSet> Clingo3::minimalPlanQuery(const std::vector<actasp::AspRule>& goalRules,
00195     bool filterActions,
00196     unsigned int  max_plan_length,
00197     unsigned int answerset_number) const throw() {
00198 
00199   string planquery = generatePlanQuery(goalRules, filterActions);
00200 
00201   return genericQuery(planquery,0,max_plan_length,"planQuery",answerset_number);
00202 
00203 }
00204 
00205 struct MaxTimeStepLessThan3 {
00206 
00207   MaxTimeStepLessThan3(unsigned int initialTimeStep) : initialTimeStep(initialTimeStep) {}
00208 
00209   bool operator()(const AnswerSet& answer) {
00210     return !answer.getFluents().empty() &&  answer.maxTimeStep() < initialTimeStep;
00211   }
00212 
00213   unsigned int initialTimeStep;
00214 };
00215 
00216 std::list<actasp::AnswerSet> Clingo3::lengthRangePlanQuery(const std::vector<actasp::AspRule>& goalRules,
00217     bool filterActions,
00218     unsigned int min_plan_length,
00219     unsigned int  max_plan_length,
00220     unsigned int answerset_number) const throw() {
00221 
00222   string planquery = generatePlanQuery(goalRules, filterActions);
00223 
00224   std::list<actasp::AnswerSet> allplans =  genericQuery(planquery,max_plan_length,max_plan_length,"planQuery",answerset_number);
00225 
00226   //clingo 3 generates all plans up to a maximum length anyway, we can't avoid the plans shorter than min_plan_length to be generated
00227   //we can only filter them out afterwards
00228 
00229   allplans.remove_if(MaxTimeStepLessThan3(min_plan_length));
00230 
00231   return allplans;
00232 
00233 }
00234 
00235 AnswerSet Clingo3::currentStateQuery(const std::vector<actasp::AspRule>& query) const throw() {
00236   list<AnswerSet> sets = genericQuery(aspString(query,0),0,0,"stateQuery",1);
00237 
00238   return (sets.empty())? AnswerSet() : *(sets.begin());
00239 }
00240 
00241 std::list<actasp::AnswerSet> Clingo3::genericQuery(const std::vector<actasp::AspRule>& query,
00242     unsigned int timeStep,
00243     const std::string& fileName,
00244     unsigned int answerSetsNumber) const throw() {
00245   return genericQuery(aspString(query,""),timeStep,timeStep,fileName,answerSetsNumber);
00246 
00247 }
00248 
00249 std::list<actasp::AnswerSet> Clingo3::monitorQuery(const std::vector<actasp::AspRule>& goalRules,
00250     const AnswerSet& plan) const throw() {
00251 
00252   //   clock_t kr1_begin = clock();
00253 
00254   string planQuery = generatePlanQuery(goalRules,true);
00255 
00256   stringstream monitorQuery(planQuery, ios_base::app | ios_base::out);
00257 
00258   const AnswerSet::FluentSet &allActions = plan.getFluents();
00259   AnswerSet::FluentSet::const_iterator actionIt = allActions.begin();
00260 
00261   for (int i=1; actionIt != allActions.end(); ++actionIt, ++i)
00262     monitorQuery << actionIt->toString(i) << "." << endl;
00263 
00264   list<actasp::AnswerSet> result = genericQuery(monitorQuery.str(),plan.getFluents().size(),plan.getFluents().size(),"monitorQuery",1);
00265   
00266   result.remove_if(MaxTimeStepLessThan3(plan.getFluents().size()));
00267   
00268 //   clock_t kr1_end = clock();
00269 //   cout << "Verifying plan time: " << (double(kr1_end - kr1_begin) / CLOCKS_PER_SEC) << " seconds" << endl;
00270 
00271   return result;
00272 }
00273 
00274 std::string Clingo3::makeQuery(const std::string& query, 
00275                                unsigned int initialTimeStep, 
00276                                unsigned int finalTimeStep, 
00277                                const std::string& fileName,
00278                               unsigned int answerSetsNumber) const  throw() {
00279   //this depends on our way of representing stuff.
00280   //iclingo starts from 1, while we needed the initial state and first action to be at time step 0
00281   initialTimeStep++;
00282   finalTimeStep++;
00283 
00284   string queryPath = queryDir + fileName + ".asp";
00285 
00286   ofstream queryFile(queryPath.c_str());
00287   queryFile << query << endl;
00288   queryFile.close();
00289 
00290   stringstream commandLine;
00291 
00292   const string outputFilePath = queryDir + fileName + "_output.txt";
00293 
00294   if (max_time > 0) {
00295     commandLine << "timeout " << max_time << " ";
00296   }
00297 
00298   stringstream iterations;
00299   iterations << "--imin=" << initialTimeStep << " --imax=" << finalTimeStep;
00300 
00301   commandLine << "iclingo " << iterations.str() << " " << queryPath << " " << domainDir << "*.asp " << (CURRENT_FILE_HOME + CURRENT_STATE_FILE) << " > " << outputFilePath << " " << answerSetsNumber;
00302 
00303 
00304   if (!system(commandLine.str().c_str())) {
00305     //maybe do something here, or just kill the warning about the return value not being used.
00306   }
00307   
00308   return outputFilePath;
00309 }
00310 
00311 std::list<actasp::AnswerSet> Clingo3::genericQuery(const std::string& query,
00312     unsigned int initialTimeStep,
00313     unsigned int finalTimeStep,
00314     const std::string& fileName,
00315     unsigned int answerSetsNumber) const throw() {
00316 
00317   string outputFilePath = makeQuery(query,initialTimeStep,finalTimeStep,fileName,answerSetsNumber);
00318 
00319   list<AnswerSet> allAnswers = readAnswerSets(outputFilePath);
00320 
00321   return allAnswers;
00322 }
00323 
00324 std::list< std::list<AspAtom> > Clingo3::genericQuery(const std::string& query,
00325       unsigned int timestep,
00326       const std::string& fileName,
00327       unsigned int answerSetsNumber) const throw() {
00328         
00329 string outputFilePath = makeQuery(query,timestep,timestep,fileName,answerSetsNumber);
00330 
00331 ifstream file(outputFilePath.c_str());
00332 
00333   list<list <AspAtom> > allSets;
00334   bool answerFound = false;
00335 
00336   string line;
00337   while(file) {
00338 
00339     getline(file,line);
00340 
00341     if(answerFound && line == "UNSATISFIABLE")
00342       return list<list <AspAtom> >();
00343 
00344     if(line.find("Answer") != string::npos) {
00345       getline(file,line);
00346         try {
00347             stringstream predicateLine(line);
00348 
00349             list<AspAtom> atoms;
00350 
00351             //split the line based on spaces
00352             copy(istream_iterator<string>(predicateLine),
00353                   istream_iterator<string>(),
00354                   back_inserter(atoms));
00355 
00356           allSets.push_back(atoms);
00357         } catch (std::invalid_argument& arg) {
00358           //swollow it and skip this answer set.
00359         }
00360     }
00361   }
00362 
00363  return allSets;
00364         
00365 }
00366 
00367 void Clingo3::setCurrentState(const std::set<actasp::AspFluent>& newState) {
00368 
00369   //copy the current state in a file
00370   ofstream currentFile((CURRENT_FILE_HOME + CURRENT_STATE_FILE).c_str());
00371 
00372   set<AspFluent>::const_iterator stateIt = newState.begin();
00373   for (; stateIt != newState.end(); ++stateIt)
00374     currentFile << stateIt->toString(0) << "." << endl;
00375 
00376   currentFile.close();
00377 
00378 }
00379 
00380 
00381 }


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