24 #include <pddl_parser/pddl_parser.h> 49 : logger_(logger), classic_dom_path_(classic_dom_path)
51 gen_classic_dom_ =
true;
65 domain_actions_.push_back(action);
75 plan_actions_.push_back(plan_action{name, params});
86 initial_state_ = action;
98 log_info(
"Parsing PDDL Problem for STN generation.");
100 log_info(
"Parsed problem " + prob.
name);
101 std::vector<stn::Predicate> init_predicates;
102 for (pddl_parser::Expression pred : prob.
init) {
103 std::vector<std::string> attrs;
104 std::string log_string =
"Adding init-predicate " 105 + boost::get<pddl_parser::Predicate>(pred).function
106 +
" with arguments:";
107 for (pddl_parser::Expression a : boost::get<pddl_parser::Predicate>(pred).arguments) {
108 attrs.push_back(boost::get<pddl_parser::Atom>(a));
109 log_string +=
" " + boost::get<pddl_parser::Atom>(a);
111 log_info(log_string);
112 stn::Predicate init_pred(boost::get<pddl_parser::Predicate>(pred).
function,
true, attrs);
113 init_predicates.push_back(init_pred);
131 log_info(
"Loading extended PDDL domain into STN.");
133 for (
auto &action : dom.
actions) {
134 log_info(
"Processing action " + action.name);
135 std::vector<std::string> params;
136 for (
auto ¶m : action.action_params) {
137 params.push_back(param.first);
139 std::vector<Predicate> preconds;
140 build_pred_list(action.precondition, &preconds,
true);
141 std::vector<Predicate> effects;
142 build_pred_list(action.effect, &effects,
true);
143 int duration = action.duration;
144 std::vector<std::string> cond_breakups;
145 log_info(std::to_string(action.cond_breakup.which()));
146 if (action.cond_breakup.which() == 1) {
147 build_breakup_list(action.cond_breakup, &cond_breakups);
149 std::vector<std::string> temp_breakups;
150 if (action.temp_breakup.which() == 1) {
151 build_breakup_list(action.temp_breakup, &temp_breakups);
153 DomainAction da(action.name, params, preconds, effects, duration, cond_breakups, temp_breakups);
154 domain_actions_.push_back(da);
157 log_info(
"Initialized " + std::to_string(domain_actions_.size()) +
" domain actions");
159 if (gen_classic_dom_) {
160 log_info(
"Generation of classic domain file is configured, starting...");
161 generate_classic_pddl_domain(&dom, classic_dom_path_);
169 Stn::build_pred_list(pddl_parser::Expression e, std::vector<Predicate> *preconds,
bool condition)
171 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e).function;
172 if (
function ==
"and" ||
function ==
"not") {
173 if (
function ==
"not") {
174 condition = !condition;
176 for (
auto &child : boost::get<pddl_parser::Predicate>(e).arguments) {
177 build_pred_list(child, preconds, condition);
180 std::vector<std::string> args;
181 for (
auto &arg : boost::get<pddl_parser::Predicate>(e).arguments) {
182 args.push_back(boost::get<std::string>(arg));
184 Predicate p(boost::get<pddl_parser::Predicate>(e).
function, condition, args);
185 preconds->push_back(p);
186 log_info(
"Added " + boost::get<pddl_parser::Predicate>(e).
function);
191 Stn::build_breakup_list(pddl_parser::Expression e, std::vector<std::string> *breakups)
193 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e).function;
195 if (
function ==
"and" ||
function ==
"not") {
196 for (
auto &child : boost::get<pddl_parser::Predicate>(e).arguments) {
197 build_breakup_list(child, breakups);
200 std::string pred_name = boost::get<pddl_parser::Predicate>(e).function;
201 std::cout <<
"Adding breakup " << pred_name << std::endl;
202 breakups->push_back(pred_name);
210 stn_actions_.clear();
213 for (plan_action pa : plan_actions_) {
214 std::vector<DomainAction>::iterator it = domain_actions_.begin();
215 for (; it != domain_actions_.end(); ++it) {
216 if (it->getName() == pa.name) {
220 if (it == domain_actions_.end())
221 throw(
"could not find fitting DomainAction");
226 std::cout <<
"Imported " << stn_actions_.size() <<
" actions into STN" << std::endl;
228 for (
int i = stn_actions_.size() - 1; i >= 0; i--) {
229 std::vector<StnAction> candidate_actions =
230 std::vector<StnAction>(stn_actions_.begin(), stn_actions_.begin() + i);
232 stn_actions_.at(i).genConditionalActions(candidate_actions);
233 }
catch (std::exception &e) {
234 std::cout <<
"ERROR stn.cpp:" << e.what() << std::endl;
238 std::vector<Predicate> predicates;
239 for (std::vector<StnAction>::iterator it = stn_actions_.begin(); it != stn_actions_.end(); ++it) {
241 for (
auto const &cond_action : it->condActionIds()) {
242 std::pair<StnAction, StnAction> edge(findActionById(cond_action), findActionById(it->id()));
243 cond_edges_.push_back(edge);
246 bool break_edge =
false;
248 if (it->checkForBreakup(EdgeType::TEMPORAL, p)) {
253 if (!break_edge && it != stn_actions_.begin()) {
254 std::pair<StnAction, StnAction> edge(findActionById((it - 1)->
id()),
255 findActionById(it->id()));
256 temp_edges_.push_back(edge);
261 std::vector<Predicate>::iterator it = std::find(predicates.begin(), predicates.end(), p);
262 if (it == predicates.end()) {
263 predicates.push_back(p);
268 Predicate neg_pred(p.name(),
true, p.attrs());
269 std::vector<Predicate>::iterator it =
270 std::find(predicates.begin(), predicates.end(), neg_pred);
271 if (it != predicates.end()) {
273 predicates.erase(it);
279 for (
auto &a : stn_actions_) {
280 bool no_temp_edge =
true;
281 for (
auto &e : temp_edges_) {
283 no_temp_edge =
false;
288 for (
auto &ce : cond_edges_) {
290 std::pair<StnAction, StnAction> edge(a, ce.second);
291 temp_edges_.push_back(edge);
308 char graph_name[] =
"STN";
310 G = agopen(graph_name, Agdirected, 0);
312 std::map<size_t, Agnode_t *> node_map;
315 std::string node_name = a.genGraphNodeName();
316 node_map.insert(std::make_pair(a.id(), agnode(G, (
char *)node_name.c_str(),
true)));
319 std::vector<Agedge_t *> edge_list;
320 for (
auto &edge : cond_edges_) {
321 Agnode_t *node1 = node_map.at(edge.first.id());
322 Agnode_t *node2 = node_map.at(edge.second.id());
323 Agedge_t *graph_edge = agedge(G, node1, node2, (
char *)
"conditional",
true);
324 edge_list.push_back(graph_edge);
326 std::string edge_label = edge.second.genConditionEdgeLabel(edge.first.id());
327 agsafeset(graph_edge,
329 agstrdup_html(G, (
char *)edge_label.c_str()),
331 agsafeset(graph_edge, (
char *)
"color", (
char *)
"red", (
char *)
"");
334 for (
auto &edge : temp_edges_) {
335 Agnode_t *node1 = node_map.at(edge.first.id());
336 Agnode_t *node2 = node_map.at(edge.second.id());
337 Agedge_t *graph_edge = agedge(G, node1, node2, (
char *)
"temporal",
true);
338 edge_list.push_back(graph_edge);
340 std::string edge_label = edge.second.genTemporalEdgeLabel();
341 agsafeset(graph_edge,
343 agstrdup_html(G, (
char *)edge_label.c_str()),
345 agsafeset(graph_edge, (
char *)
"color", (
char *)
"blue", (
char *)
"");
348 gvLayout(gvc, G,
"dot");
349 gvRenderFilename(gvc, G,
"png",
"stn.png");
351 gvFreeLayout(gvc, G);
359 std::vector<mongo::BSONObj>
362 std::vector<mongo::BSONObj> stn;
363 for (
auto &action : stn_actions_) {
364 mongo::BSONObjBuilder bson_action;
365 bson_action <<
"id" << static_cast<long long>(action.id());
366 bson_action <<
"name" << action.name();
367 bson_action <<
"duration" << static_cast<long long>(action.duration());
368 mongo::BSONArrayBuilder cond_actions;
369 for (
auto &cond : action.condActionIds()) {
370 cond_actions << static_cast<long long>(cond);
372 bson_action <<
"cond-actions" << cond_actions.arr();
373 mongo::BSONArrayBuilder opts_arr;
374 std::stringstream opts_ss(action.opts());
375 std::istream_iterator<std::string> end;
376 for (std::istream_iterator<std::string> it(opts_ss); it != end; it++) {
379 bson_action <<
"opts" << opts_arr.arr();
380 stn.push_back(bson_action.obj());
386 Stn::findActionById(
size_t id)
393 throw(
" Action with id " + std::to_string(
id) +
" not found");
397 Stn::log_warn(
const std::string &s)
399 log(s, LogLevel::WARN);
403 Stn::log_info(
const std::string &s)
405 log(s, LogLevel::INFO);
409 Stn::log_debug(
const std::string &s)
411 log(s, LogLevel::DEBUG);
414 Stn::log(
const std::string &s, Stn::LogLevel log_level)
416 std::string name =
"STN";
418 case LogLevel::WARN: logger_->
log_warn(name.c_str(),
"%s", s.c_str());
break;
419 case LogLevel::INFO: logger_->
log_info(name.c_str(),
"%s", s.c_str());
break;
420 case LogLevel::DEBUG: logger_->
log_debug(name.c_str(),
"%s", s.c_str());
break;
425 Stn::generate_classic_pddl_domain(
pddl_parser::Domain *dom,
const std::string &classic_dom_path)
427 log_info(
"Writing domain to " + classic_dom_path);
428 std::ofstream out(classic_dom_path);
430 out <<
"(define (domain " << dom->
name <<
")" << std::endl;
432 out <<
"\t(:requirements";
436 out <<
")" << std::endl;
438 out <<
"\t(:types" << std::endl;
439 for (
auto &type : dom->
types) {
440 out <<
"\t\t" << type.first <<
" - " << type.second << std::endl;
442 out <<
"\t)" << std::endl;
444 out <<
"\t(:constants" << std::endl;
445 for (
auto &const_type : dom->
constants) {
447 for (
auto &constant : const_type.first) {
448 out << constant <<
" ";
450 out <<
"- " << const_type.second << std::endl;
452 out <<
"\t)" << std::endl;
454 out <<
"\t(:predicates" << std::endl;
456 out <<
"\t\t(" << predicate.first;
457 for (
auto &pred_type : predicate.second) {
458 out <<
" ?" << pred_type.first <<
" - " << pred_type.second;
460 out <<
")" << std::endl;
462 out <<
"\t)" << std::endl;
464 for (
auto &action : dom->
actions) {
465 out <<
"\t(:action " << action.name << std::endl;
466 out <<
"\t\t:parameters (";
467 for (
auto ¶m : action.action_params) {
468 out <<
" ?" << param.first <<
" - " << param.second;
470 out <<
")" << std::endl;
471 out <<
"\t\t:precondition" << std::endl <<
"\t\t\t";
472 output_pred_list(action.precondition, out);
474 out << std::endl <<
"\t\t:effect" << std::endl <<
"\t\t\t";
475 output_pred_list(action.effect, out);
477 out << std::endl <<
"\t)" << std::endl;
486 Stn::output_pred_list(pddl_parser::Expression e, std::ofstream &out)
488 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e).function;
489 if (
function ==
"not" ||
function ==
"and") {
490 if (
function ==
"not") {
492 }
else if (
function ==
"and") {
495 for (
auto &child : boost::get<pddl_parser::Predicate>(e).arguments) {
496 output_pred_list(child, out);
500 out <<
"(" << boost::get<pddl_parser::Predicate>(e).function;
501 for (
auto &arg : boost::get<pddl_parser::Predicate>(e).arguments) {
502 out <<
" " << boost::get<std::string>(arg);
void read_initial_state(const std::string &pddl_problem_string)
Read the initial state from the given PDDL problem.
Parse a PDDL domain file or problem.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
static Domain parseDomain(const std::string pddl_domain)
Parse the PDDL domain.
Fawkes library namespace.
static Problem parseProblem(const std::string pddl_problem)
Parse the PDDL problem.
void generate()
Regenerate the STN.
std::vector< Action > actions
A list of actions defined in the domain.
virtual ~Stn()
Destructor.
A representation of a Predicate in the STN.
Stn(fawkes::Logger *logger)
Constructor.
void set_initial_state(const StnAction &action)
Set the initial state.
pairs_multi_consts constants
A typed list of constants defined in the domain.
void add_plan_action(const std::string &name, const std::string ¶ms)
Add a (grounded action).
void set_pddl_domain(const std::string &pddl_domain_string)
Set the domain of the STN to the given PDDL domain.
std::vector< predicate_type > predicates
A list of predicate names in the domain, including the types of their arguments.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
A representation of an action used by the STN generator.
pairs_type types
A list of types with their super types.
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
std::vector< mongo::BSONObj > get_bson()
Get a BSON representation of the STN.
std::vector< std::string > requirements
A list of PDDL features required by the domain.
std::vector< Expression > init
A list of facts that are initially true.
void drawGraph()
Render a graph representation of the STN.
StnAction generateStnAction(const std::string &name, const std::string ¶ms)
Generate an StnAction from the DomainAction.
std::string name
The name of the problem.
std::string name
The name of the domain.
A structured representation of a PDDL problem.
An action representation within an STN.
A structured representation of a PDDL domain.