Clingo4_2.cpp
Go to the documentation of this file.
00001 #include <actasp/reasoners/Clingo4_2.h>
00002 
00003 #include <actasp/AspRule.h>
00004 #include <actasp/AnswerSet.h>
00005 #include <actasp/AspAtom.h>
00006 #include <actasp/action_utils.h>
00007 
00008 #include <algorithm>
00009 #include <iterator>
00010 #include <sstream>
00011 #include <fstream>
00012 #include <cstdlib>
00013 #include <iostream>
00014 #include <limits>
00015 
00016 #define CURRENT_STATE_FILE std::string("/tmp/current.asp")
00017 
00018 using namespace std;
00019 
00020 namespace actasp {
00021 
00022 Clingo4_2::Clingo4_2(const std::string& incrementalVar,
00023                       const std::string& queryDir,
00024                       const std::string& domainDir,
00025                       const ActionSet& allActions,
00026                       unsigned int max_time
00027                     ) throw() :
00028   incrementalVar(incrementalVar),
00029   max_time(max_time),
00030   queryDir(queryDir),
00031   domainDir(domainDir),
00032   allActions(allActions),
00033   currentFilePath(CURRENT_STATE_FILE) {
00034 
00035   if (max_time > 0 && !system("timeout 2>/dev/null")) //make sure timeout is available
00036     max_time = 0;
00037   
00038   //make sure directory ends with '/'
00039   
00040   if (this->queryDir.find_last_of("/") != (this->queryDir.length() -1))
00041     this->queryDir += "/";
00042 
00043   if ((this->domainDir.find_last_of("/")) != (this->domainDir.length() -1))
00044     this->domainDir += "/";
00045 
00046   //TODO test the existance of the directories
00047 
00048   //create current file
00049   ifstream currentFile(currentFilePath.c_str());
00050   if (!currentFile.good()) //doesn't exist, create it or clingo will go mad
00051     setCurrentState(set<AspFluent>());
00052 
00053   currentFile.close();
00054 }
00055 
00056 Clingo4_2::Clingo4_2(const std::string& incrementalVar,
00057                      const std::string& queryDir,
00058                      const std::string& domainDir,
00059                      const ActionSet& allActions,
00060                      const std::string& currentFilePath,
00061                      unsigned int max_time
00062                     ) throw() :
00063   incrementalVar(incrementalVar),
00064   max_time(max_time),
00065   queryDir(queryDir),
00066   domainDir(domainDir),
00067   allActions(allActions),
00068   currentFilePath(currentFilePath) {
00069 
00070   if (max_time > 0 && !system("timeout 2>/dev/null")) //make sure timeout is available
00071     max_time = 0;
00072 
00073   //make sure directory ends with '/'
00074 
00075   if (this->queryDir.find_last_of("/") != (this->queryDir.length() -1))
00076     this->queryDir += "/";
00077 
00078   if ((this->domainDir.find_last_of("/")) != (this->domainDir.length() -1))
00079     this->domainDir += "/";
00080 
00081   //TODO test the existance of the directories
00082 
00083   //create current file
00084   ifstream currentFile((currentFilePath).c_str());
00085   if (!currentFile.good()) //doesn't exist, create it or clingo will go mad
00086     setCurrentState(set<AspFluent>());
00087 
00088   currentFile.close();
00089 }
00090 
00091 struct RuleToString4_2 {
00092   RuleToString4_2(unsigned int timeStepNum) {
00093     stringstream ss;
00094     ss << timeStepNum;
00095     timeStep = ss.str();
00096   }
00097 
00098   RuleToString4_2(const std::string& timeStepVar) : timeStep(timeStepVar) {}
00099 
00100   RuleToString4_2() : timeStep("") {}
00101 
00102   std::string operator()(const AspRule& rule) const {
00103 
00104     stringstream ruleStream;
00105 
00106     //iterate over head
00107     for (int i =0, size = rule.head.size(); i <size; ++i) {
00108       if (timeStep.size() >0)
00109         ruleStream << rule.head[i].toString(timeStep);
00110       else
00111         ruleStream << rule.head[i].toString();
00112 
00113       if (i < (size-1))
00114         ruleStream << ", ";
00115     }
00116 
00117     if (!(rule.body.empty()))
00118       ruleStream << ":- ";
00119 
00120     //iterate over body
00121     for (int i =0, size = rule.body.size(); i <size; ++i) {
00122       if (timeStep.size() >0)
00123         ruleStream << rule.body[i].toString(timeStep);
00124       else
00125         ruleStream << rule.body[i].toString();
00126 
00127       if (i < (size-1))
00128         ruleStream << "| ";
00129     }
00130 
00131     if (!(rule.head.empty() && rule.body.empty()))
00132       ruleStream << "." << std::endl;
00133 
00134     return ruleStream.str();
00135   }
00136 
00137   string timeStep;
00138 };
00139 
00140 struct RuleToCumulativeString4_2 {
00141 
00142   RuleToCumulativeString4_2(const std::string& timeStepVar) : timeStep(timeStepVar) {}
00143 
00144   std::string operator()(const AspRule& rule) const {
00145 
00146     stringstream ruleStream;
00147     unsigned int headTimeStep = 0;
00148 
00149     //iterate over head
00150     for (int i =0, size = rule.head.size(); i <size; ++i) {
00151       ruleStream << rule.head[i].toString(timeStep+"-1");
00152       headTimeStep = std::max(headTimeStep,rule.head[i].getTimeStep());
00153 
00154       if (i < (size-1))
00155         ruleStream << " | ";
00156     }
00157 
00158     if (!(rule.head.empty() && rule.body.empty()))
00159       ruleStream << ":- ";
00160 
00161     //iterate over body
00162     for (int i =0, size = rule.body.size(); i <size; ++i) {
00163       ruleStream << rule.body[i].toString();
00164 
00165       if (i < (size-1))
00166         ruleStream << ", ";
00167     }
00168 
00169     if (!rule.head.empty()) {
00170       if (!rule.body.empty())
00171         ruleStream << ", ";
00172 
00173       ruleStream << timeStep << "=" << headTimeStep << "+1";
00174     }
00175 
00176 
00177     if (!(rule.head.empty() && rule.body.empty()))
00178       ruleStream << "." << endl;
00179 
00180     return ruleStream.str();
00181   }
00182 
00183   string timeStep;
00184 };
00185 
00186 struct RuleToGoalString4_2 {
00187 
00188   RuleToGoalString4_2(const std::string& timeStepVar) : timeStep(timeStepVar) {}
00189 
00190   std::string operator()(const AspRule& rule) const {
00191 
00192     stringstream ruleStream;
00193     unsigned int headTimeStep = 0;
00194 
00195     //iterate over head
00196     for (int i =0, size = rule.head.size(); i <size; ++i) {
00197       ruleStream << rule.head[i].toString(timeStep+"-1");
00198       headTimeStep = std::max(headTimeStep,rule.head[i].getTimeStep());
00199 
00200       if (i < (size-1))
00201         ruleStream << " | ";
00202     }
00203 
00204     if (!(rule.head.empty() && rule.body.empty()))
00205       ruleStream << ":- ";
00206 
00207     //iterate over body
00208     for (int i =0, size = rule.body.size(); i <size; ++i) {
00209       ruleStream << rule.body[i].toString(timeStep+"-1");
00210 
00211       if (i < (size-1))
00212         ruleStream << ", ";
00213     }
00214 
00215     if (!(rule.head.empty() && rule.body.empty()))
00216       ruleStream << ", query(" << timeStep << ")." << endl;
00217 
00218     return ruleStream.str();
00219   }
00220 
00221   string timeStep;
00222 };
00223 
00224 
00225 static string cumulativeString(const std::vector<actasp::AspRule>& query, const string& timeStepVar) {
00226 
00227   stringstream aspStream;
00228   transform(query.begin(),query.end(),ostream_iterator<std::string>(aspStream),RuleToCumulativeString4_2(timeStepVar));
00229   return aspStream.str();
00230 }
00231 
00232 static string aspString(const std::vector<actasp::AspRule>& query, const string& timeStepVar) {
00233 
00234   stringstream aspStream;
00235   transform(query.begin(),query.end(),ostream_iterator<std::string>(aspStream),RuleToString4_2(timeStepVar));
00236   return aspStream.str();
00237 }
00238 
00239 static string aspString(const std::vector<actasp::AspRule>& query, unsigned int timeStep) {
00240 
00241   stringstream vs;
00242   vs << timeStep;
00243 
00244   return aspString(query,vs.str());
00245 }
00246 
00247 static std::list<AspFluent> parseAnswerSet(const std::string& answerSetContent) throw() {
00248 
00249   stringstream predicateLine(answerSetContent);
00250 
00251   list<AspFluent> predicates;
00252 
00253   //split the line based on spaces
00254   copy(istream_iterator<string>(predicateLine),
00255        istream_iterator<string>(),
00256        back_inserter(predicates));
00257 
00258   return predicates;
00259 }
00260 
00261 
00262 static std::list<actasp::AnswerSet> readAnswerSets(const std::string& filePath) throw() {
00263 
00264   ifstream file(filePath.c_str());
00265 
00266   list<AnswerSet> allSets;
00267   bool interrupted = false;
00268 
00269   string line;
00270   while (file) {
00271 
00272     getline(file,line);
00273 
00274     if (line == "UNSATISFIABLE")
00275       return list<AnswerSet>();
00276 
00277     if (line.find("INTERRUPTED : 1") != string::npos)
00278       interrupted = true;
00279 
00280     if (line.find("Answer") != string::npos) {
00281       getline(file,line);
00282       while (line.find("Answer") != string::npos) 
00283         getline(file,line);
00284       try {
00285         list<AspFluent> fluents = parseAnswerSet(line);
00286         allSets.push_back(AnswerSet(fluents.begin(), fluents.end()));
00287       } catch (std::invalid_argument& arg) {
00288         //swollow it and skip this answer set.
00289       }
00290     }
00291   }
00292 
00293   if (interrupted) //the last answer set might be invalid
00294     allSets.pop_back();
00295 
00296   return allSets;
00297 }
00298 
00299 static actasp::AnswerSet readOptimalAnswerSet(const std::string& filePath, const bool minimum) throw() {
00300 
00301   ifstream file(filePath.c_str());
00302 
00303   AnswerSet optimalAnswer;
00304   AnswerSet currentAnswer;
00305   unsigned int optimization = std::numeric_limits<unsigned int>::max();
00306   unsigned int currentOptimization;
00307   bool interrupted = false;
00308 
00309   string line;
00310   while (file) {
00311 
00312     getline(file,line);
00313 
00314     if(line == "UNSATISFIABLE" || line == "UNKNOWN") {
00315       return optimalAnswer;
00316     }
00317 
00318     if (line.find("INTERRUPTED : 1") != string::npos)
00319       interrupted = true;
00320 
00321     if (line.find("Answer") != string::npos) {
00322       getline(file,line);
00323       while (line.find("Answer") != string::npos) 
00324         getline(file,line);
00325       try {
00326         list<AspFluent> fluents = parseAnswerSet(line);
00327         currentAnswer = AnswerSet(fluents.begin(), fluents.end());
00328       } catch (std::invalid_argument& arg) {
00329         //swollow it and skip this answer set.
00330       }
00331     }
00332 
00333     if (line.find("Optimization: ") != string::npos) {
00334       size_t space = line.find_first_of(" ");
00335       currentOptimization = atoi(line.substr(space+1).c_str());
00336 
00337       if (minimum && (currentOptimization < optimization)) {
00338         optimalAnswer = currentAnswer;
00339         optimization = currentOptimization;
00340       }
00341       else if ((!minimum) && (currentOptimization > optimization)) {
00342         optimalAnswer = currentAnswer;
00343         optimization = currentOptimization;
00344       }
00345 
00346     }
00347   }
00348 
00349   return optimalAnswer;
00350 }
00351 
00352 string Clingo4_2::generatePlanQuery(std::vector<actasp::AspRule> goalRules) const throw() {
00353   stringstream goal;
00354   goal << "#program volatile(" << incrementalVar << ")." << endl;
00355   goal << "#external query(" << incrementalVar << ")." << endl;
00356   //I don't like this -1 too much, but it makes up for the incremental variable starting at 1
00357 
00358   transform(goalRules.begin(),goalRules.end(),ostream_iterator<std::string>(goal),RuleToGoalString4_2(incrementalVar));
00359 
00360   goal << endl;
00361 
00362   return goal.str();
00363 }
00364 
00365 
00366 static list<AnswerSet> filterPlans(const list<AnswerSet> unfiltered_plans, const ActionSet& allActions) {
00367 
00368   list<AnswerSet> plans;
00369 
00370   list<AnswerSet>::const_iterator ans = unfiltered_plans.begin();
00371   for (; ans != unfiltered_plans.end(); ++ans) {
00372     list<AspFluent> actionsOnly;
00373     remove_copy_if(ans->getFluents().begin(),ans->getFluents().end(),back_inserter(actionsOnly),not1(IsAnAction(allActions)));
00374 
00375     plans.push_back(AnswerSet(actionsOnly.begin(), actionsOnly.end()));
00376   }
00377 
00378   return plans;
00379 }
00380 
00381 std::list<actasp::AnswerSet> Clingo4_2::minimalPlanQuery(const std::vector<actasp::AspRule>& goalRules,
00382     bool filterActions,
00383     unsigned int  max_plan_length,
00384     unsigned int answerset_number) const throw() {
00385 
00386   string planquery = generatePlanQuery(goalRules);
00387 
00388   list<AnswerSet> answers = genericQuery(planquery,0,max_plan_length,"planQuery",answerset_number,true);
00389 
00390   if (filterActions)
00391     return filterPlans(answers,allActions);
00392   else
00393     return answers;
00394 
00395 }
00396 
00397 struct MaxTimeStepLessThan4_2 {
00398 
00399   MaxTimeStepLessThan4_2(unsigned int initialTimeStep) : initialTimeStep(initialTimeStep) {}
00400 
00401   bool operator()(const AnswerSet& answer) {
00402     return !answer.getFluents().empty() &&  answer.maxTimeStep() < initialTimeStep;
00403   }
00404 
00405   unsigned int initialTimeStep;
00406 };
00407 
00408 std::list<actasp::AnswerSet> Clingo4_2::lengthRangePlanQuery(const std::vector<actasp::AspRule>& goalRules,
00409     bool filterActions,
00410     unsigned int min_plan_length,
00411     unsigned int  max_plan_length,
00412     unsigned int answerset_number) const throw() {
00413 
00414   string planquery = generatePlanQuery(goalRules);
00415 
00416   //cout << "min " << min_plan_length << " max " << max_plan_length << endl;
00417 
00418   std::list<actasp::AnswerSet> allplans =  genericQuery(planquery,max_plan_length,max_plan_length,"planQuery",answerset_number,true);
00419 
00420   //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
00421   //we can only filter them out afterwards
00422 
00423   allplans.remove_if(MaxTimeStepLessThan4_2(min_plan_length));
00424 
00425   if (filterActions)
00426     return filterPlans(allplans,allActions);
00427   else
00428     return allplans;
00429 
00430 }
00431 
00432 actasp::AnswerSet Clingo4_2::optimalPlanQuery(const std::vector<actasp::AspRule>& goalRules,
00433     bool filterActions,
00434     unsigned int  max_plan_length,
00435     unsigned int answerset_number,
00436     bool minimum) const throw() {
00437 
00438   string planquery = generatePlanQuery(goalRules);
00439 
00440   string outputFilePath = makeQuery(planquery,max_plan_length,max_plan_length,"planQuery",answerset_number,true);
00441 
00442   AnswerSet optimalPlan = readOptimalAnswerSet(outputFilePath,minimum);
00443 
00444   if (filterActions) {
00445     list<AnswerSet> sets;
00446     sets.push_back(optimalPlan);
00447     return *(filterPlans(sets,allActions).begin());
00448   }
00449   else
00450     return optimalPlan;
00451 }
00452 
00453 AnswerSet Clingo4_2::currentStateQuery(const std::vector<actasp::AspRule>& query) const throw() {
00454   list<AnswerSet> sets = genericQuery(aspString(query,0),0,0,"stateQuery",1,true);
00455 
00456   return (sets.empty())? AnswerSet() : *(sets.begin());
00457 }
00458 
00459 struct HasTimeStepZeroInHead4_2 : unary_function<const AspRule&,bool> {
00460 
00461   bool operator()(const AspRule &rule) const {
00462     if (rule.head.empty())
00463       return false;
00464 
00465     return rule.head[0].getTimeStep() == 0; //I am assuming the heads have a single fluent
00466     //If the that's not the case, the option --shift has to be added to clingo's command line
00467   }
00468 };
00469 
00470 std::list<actasp::AnswerSet> Clingo4_2::genericQuery(const std::vector<actasp::AspRule>& query,
00471     unsigned int timeStep,
00472     const std::string& fileName,
00473     unsigned int answerSetsNumber) const throw() {
00474 
00475   std::vector<actasp::AspRule> base;
00476   remove_copy_if(query.begin(),query.end(),back_inserter(base), not1(HasTimeStepZeroInHead4_2()));
00477 
00478   string base_part = aspString(base,0);
00479 
00480   stringstream thequery(base_part, ios_base::app | ios_base::out);
00481 
00482   std::vector<actasp::AspRule> cumulative;
00483   remove_copy_if(query.begin(),query.end(),back_inserter(cumulative), HasTimeStepZeroInHead4_2());
00484 
00485   string cumulative_part = cumulativeString(cumulative,incrementalVar);
00486 
00487   thequery << endl << "#program cumulative(" << incrementalVar << ")." << endl;
00488   thequery << cumulative_part << endl;
00489 
00490   return genericQuery(thequery.str(),timeStep,timeStep,fileName,answerSetsNumber,true);
00491 
00492 }
00493 
00494 std::string Clingo4_2::generateMonitorQuery(const std::vector<actasp::AspRule>& goalRules,
00495     const AnswerSet& plan) const throw() {
00496    string planQuery = generatePlanQuery(goalRules);
00497 
00498   stringstream monitorQuery(planQuery, ios_base::app | ios_base::out);
00499 
00500   monitorQuery << "#program cumulative(" << incrementalVar << ")." << endl;
00501 
00502 
00503   const AnswerSet::FluentSet &actionSet = plan.getFluents();
00504   AnswerSet::FluentSet::const_iterator actionIt = actionSet.begin();
00505   vector<AspRule> plan_in_rules;
00506 
00507   for (int i=1; actionIt != actionSet.end(); ++actionIt, ++i) {
00508     AspFluent action(*actionIt);
00509     action.setTimeStep(i);
00510     AspRule actionRule;
00511     actionRule.head.push_back(action);
00512     plan_in_rules.push_back(actionRule);
00513   }
00514 
00515   monitorQuery << cumulativeString(plan_in_rules,"n");
00516   
00517   return monitorQuery.str();
00518 }
00519 
00520 std::list<actasp::AnswerSet> Clingo4_2::monitorQuery(const std::vector<actasp::AspRule>& goalRules,
00521     const AnswerSet& plan) const throw() {
00522 
00523   //   clock_t kr1_begin = clock();
00524       
00525   string monitorQuery = generateMonitorQuery(goalRules,plan);
00526 
00527   list<actasp::AnswerSet> result = genericQuery(monitorQuery,plan.getFluents().size(),plan.getFluents().size(),"monitorQuery",1,true);
00528 
00529   result.remove_if(MaxTimeStepLessThan4_2(plan.getFluents().size()));
00530 
00531 //   clock_t kr1_end = clock();
00532 //   cout << "Verifying plan time: " << (double(kr1_end - kr1_begin) / CLOCKS_PER_SEC) << " seconds" << endl;
00533 
00534   return result;
00535 }
00536 
00537 std::string Clingo4_2::makeQuery(const std::string& query,
00538                                  unsigned int initialTimeStep,
00539                                  unsigned int finalTimeStep,
00540                                  const std::string& fileName,
00541                                  unsigned int answerSetsNumber,
00542                                  bool useCurrentState
00543                                 ) const  throw() {
00544   //this depends on our way of representing stuff.
00545   //iclingo starts from 1, while we needed the initial state and first action to be at time step 0
00546   initialTimeStep++;
00547   finalTimeStep++;
00548 
00549   //cout << "initialTimeStep is " << initialTimeStep << " ; finalTimeStep is " << finalTimeStep << endl;
00550 
00551   string queryPath = queryDir + fileName + ".asp";
00552 
00553   ofstream queryFile(queryPath.c_str());
00554   queryFile << query << endl;
00555   queryFile.close();
00556 
00557   stringstream commandLine;
00558 
00559   const string outputFilePath = queryDir + fileName + "_output.txt";
00560 
00561   if (max_time > 0) {
00562     commandLine << "timeout " << max_time << " ";
00563   }
00564 
00565   stringstream iterations;
00566   iterations << "-cimin=" << initialTimeStep;
00567 //   if ( finalTimeStep > initialTimeStep ) //when max and initial are the same, we do not want max
00568     iterations << " -cimax=" << finalTimeStep;
00569 
00570   commandLine << "clingo " << iterations.str() << " " << queryPath << " " << domainDir << "*.asp ";
00571   if(useCurrentState)
00572     commandLine<< (currentFilePath);
00573   
00574   commandLine << " > " << outputFilePath << " " << answerSetsNumber;
00575 
00576 
00577   if (!system(commandLine.str().c_str())) {
00578     //maybe do something here, or just kill the warning about the return value not being used.
00579   }
00580 
00581   return outputFilePath;
00582 }
00583 
00584 std::list<actasp::AnswerSet> Clingo4_2::genericQuery(const std::string& query,
00585     unsigned int initialTimeStep,
00586     unsigned int finalTimeStep,
00587     const std::string& fileName,
00588     unsigned int answerSetsNumber,
00589     bool useCurrentState ) const throw() {
00590 
00591   string outputFilePath = makeQuery(query,initialTimeStep,finalTimeStep,fileName,answerSetsNumber,useCurrentState);
00592 
00593   list<AnswerSet> allAnswers = readAnswerSets(outputFilePath);
00594 
00595   return allAnswers;
00596 }
00597 
00598 std::list< std::list<AspAtom> > Clingo4_2::genericQuery(const std::string& query,
00599     unsigned int timestep,
00600     const std::string& fileName,
00601     unsigned int answerSetsNumber) const throw() {
00602 
00603   string outputFilePath = makeQuery(query,timestep,timestep,fileName,answerSetsNumber,true);
00604 
00605   ifstream file(outputFilePath.c_str());
00606 
00607   list<list <AspAtom> > allSets;
00608   bool answerFound = false;
00609 
00610   string line;
00611   while (file) {
00612 
00613     getline(file,line);
00614 
00615     if (answerFound && line == "UNSATISFIABLE")
00616       return list<list <AspAtom> >();
00617 
00618     if (line.find("Answer") != string::npos) {
00619       getline(file,line);
00620       try {
00621         stringstream predicateLine(line);
00622 
00623         list<AspAtom> atoms;
00624 
00625         //split the line based on spaces
00626         copy(istream_iterator<string>(predicateLine),
00627              istream_iterator<string>(),
00628              back_inserter(atoms));
00629 
00630         allSets.push_back(atoms);
00631       } catch (std::invalid_argument& arg) {
00632         //swollow it and skip this answer set.
00633       }
00634     }
00635   }
00636 
00637   return allSets;
00638 
00639 }
00640 
00641 void Clingo4_2::setCurrentState(const std::set<actasp::AspFluent>& newState) {
00642 
00643   //copy the current state in a file
00644   ofstream currentFile((currentFilePath).c_str());
00645 
00646   set<AspFluent>::const_iterator stateIt = newState.begin();
00647   for (; stateIt != newState.end(); ++stateIt)
00648     currentFile << stateIt->toString(0) << "." << endl;
00649 
00650   currentFile.close();
00651 
00652 }
00653 
00654 std::list<actasp::AnswerSet> Clingo4_2::filteringQuery(const AnswerSet& currentState, const AnswerSet& plan,const std::vector<actasp::AspRule>& goals) {
00655 
00656   //generate a string with all the fluents "0{fluent}1."
00657   //and add the minimize statement ( eg: :~ pos(x,y,z), ... . [1@1] )
00658   stringstream fluentsString, minimizeString;
00659 
00660   fluentsString << "#program base." << endl;
00661 
00662   std::vector<actasp::AspFluent>::const_iterator fluent = currentState.getFluents().begin();
00663   for (; fluent != currentState.getFluents().end(); ++fluent) {
00664     fluentsString << "0{" << fluent->toString() << "}1." << endl;
00665     minimizeString  << ":~ " << fluent->toString() << ". [1]" << endl;
00666   }
00667 
00668   fluentsString << endl;
00669   minimizeString << endl;
00670 
00671   string monitorString = generateMonitorQuery(goals,plan);
00672 
00673   //combine this plan with all the fluents stuff created before
00674   stringstream total;
00675   total << fluentsString.str() << std::endl << monitorString << endl << minimizeString.str() << endl;
00676 
00677   //make a query that only uses the domain and what I created, not current.asp
00678   return  genericQuery(total.str(),plan.getFluents().size(),plan.getFluents().size(),"filterState",0,false);
00679 
00680 }
00681 
00682 
00683 }


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