24 #include <pddl_parser/pddl_parser.h>
26 #include <bsoncxx/builder/basic/document.hpp>
50 : logger_(logger), classic_dom_path_(classic_dom_path)
52 gen_classic_dom_ =
true;
66 domain_actions_.push_back(action);
76 plan_actions_.push_back(plan_action{name, params});
87 initial_state_ = action;
99 log_info(
"Parsing PDDL Problem for STN generation.");
101 log_info(
"Parsed problem " + prob.
name);
102 std::vector<stn::Predicate> init_predicates;
103 for (pddl_parser::Expression pred : prob.
init) {
104 std::vector<std::string> attrs;
105 std::string log_string =
"Adding init-predicate "
106 + boost::get<pddl_parser::Predicate>(pred).function
107 +
" with arguments:";
108 for (pddl_parser::Expression a : boost::get<pddl_parser::Predicate>(pred).arguments) {
109 attrs.push_back(boost::get<pddl_parser::Atom>(a));
110 log_string +=
" " + boost::get<pddl_parser::Atom>(a);
112 log_info(log_string);
113 stn::Predicate init_pred(boost::get<pddl_parser::Predicate>(pred).
function,
true, attrs);
114 init_predicates.push_back(init_pred);
132 log_info(
"Loading extended PDDL domain into STN.");
134 for (
auto &action : dom.
actions) {
135 log_info(
"Processing action " + action.name);
136 std::vector<std::string> params;
137 for (
auto ¶m : action.action_params) {
138 params.push_back(param.first);
140 std::vector<Predicate> preconds;
141 build_pred_list(action.precondition, &preconds,
true);
142 std::vector<Predicate> effects;
143 build_pred_list(action.effect, &effects,
true);
144 int duration = action.duration;
145 std::vector<std::string> cond_breakups;
146 log_info(std::to_string(action.cond_breakup.which()));
147 if (action.cond_breakup.which() == 1) {
148 build_breakup_list(action.cond_breakup, &cond_breakups);
150 std::vector<std::string> temp_breakups;
151 if (action.temp_breakup.which() == 1) {
152 build_breakup_list(action.temp_breakup, &temp_breakups);
154 DomainAction da(action.name, params, preconds, effects, duration, cond_breakups, temp_breakups);
155 domain_actions_.push_back(da);
158 log_info(
"Initialized " + std::to_string(domain_actions_.size()) +
" domain actions");
160 if (gen_classic_dom_) {
161 log_info(
"Generation of classic domain file is configured, starting...");
162 generate_classic_pddl_domain(&dom, classic_dom_path_);
170 Stn::build_pred_list(pddl_parser::Expression e, std::vector<Predicate> *preconds,
bool condition)
172 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e).function;
173 if (
function ==
"and" ||
function ==
"not") {
174 if (
function ==
"not") {
175 condition = !condition;
177 for (
auto &child : boost::get<pddl_parser::Predicate>(e).arguments) {
178 build_pred_list(child, preconds, condition);
181 std::vector<std::string> args;
182 for (
auto &arg : boost::get<pddl_parser::Predicate>(e).arguments) {
183 args.push_back(boost::get<std::string>(arg));
185 Predicate p(boost::get<pddl_parser::Predicate>(e).
function, condition, args);
186 preconds->push_back(p);
187 log_info(
"Added " + boost::get<pddl_parser::Predicate>(e).
function);
192 Stn::build_breakup_list(pddl_parser::Expression e, std::vector<std::string> *breakups)
194 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e).function;
196 if (
function ==
"and" ||
function ==
"not") {
197 for (
auto &child : boost::get<pddl_parser::Predicate>(e).arguments) {
198 build_breakup_list(child, breakups);
201 std::string pred_name = boost::get<pddl_parser::Predicate>(e).function;
202 std::cout <<
"Adding breakup " << pred_name << std::endl;
203 breakups->push_back(pred_name);
211 stn_actions_.clear();
214 for (plan_action pa : plan_actions_) {
215 std::vector<DomainAction>::iterator it = domain_actions_.begin();
216 for (; it != domain_actions_.end(); ++it) {
217 if (it->getName() == pa.name) {
221 if (it == domain_actions_.end())
222 throw(
"could not find fitting DomainAction");
227 std::cout <<
"Imported " << stn_actions_.size() <<
" actions into STN" << std::endl;
229 for (
int i = stn_actions_.size() - 1; i >= 0; i--) {
230 std::vector<StnAction> candidate_actions =
231 std::vector<StnAction>(stn_actions_.begin(), stn_actions_.begin() + i);
233 stn_actions_.at(i).genConditionalActions(candidate_actions);
234 }
catch (std::exception &e) {
235 std::cout <<
"ERROR stn.cpp:" << e.what() << std::endl;
239 std::vector<Predicate> predicates;
240 for (std::vector<StnAction>::iterator it = stn_actions_.begin(); it != stn_actions_.end(); ++it) {
242 for (
auto const &cond_action : it->condActionIds()) {
243 std::pair<StnAction, StnAction> edge(findActionById(cond_action), findActionById(it->id()));
244 cond_edges_.push_back(edge);
247 bool break_edge =
false;
249 if (it->checkForBreakup(EdgeType::TEMPORAL, p)) {
254 if (!break_edge && it != stn_actions_.begin()) {
255 std::pair<StnAction, StnAction> edge(findActionById((it - 1)->
id()),
256 findActionById(it->id()));
257 temp_edges_.push_back(edge);
262 std::vector<Predicate>::iterator it = std::find(predicates.begin(), predicates.end(), p);
263 if (it == predicates.end()) {
264 predicates.push_back(p);
269 Predicate neg_pred(p.name(),
true, p.attrs());
270 std::vector<Predicate>::iterator it =
271 std::find(predicates.begin(), predicates.end(), neg_pred);
272 if (it != predicates.end()) {
274 predicates.erase(it);
280 for (
auto &a : stn_actions_) {
281 bool no_temp_edge =
true;
282 for (
auto &e : temp_edges_) {
284 no_temp_edge =
false;
289 for (
auto &ce : cond_edges_) {
291 std::pair<StnAction, StnAction> edge(a, ce.second);
292 temp_edges_.push_back(edge);
309 char graph_name[] =
"STN";
311 G = agopen(graph_name, Agdirected, 0);
313 std::map<size_t, Agnode_t *> node_map;
316 std::string node_name = a.genGraphNodeName();
317 node_map.insert(std::make_pair(a.id(), agnode(G, (
char *)node_name.c_str(),
true)));
320 std::vector<Agedge_t *> edge_list;
321 for (
auto &edge : cond_edges_) {
322 Agnode_t *node1 = node_map.at(edge.first.id());
323 Agnode_t *node2 = node_map.at(edge.second.id());
324 Agedge_t *graph_edge = agedge(G, node1, node2, (
char *)
"conditional",
true);
325 edge_list.push_back(graph_edge);
327 std::string edge_label = edge.second.genConditionEdgeLabel(edge.first.id());
328 agsafeset(graph_edge,
330 agstrdup_html(G, (
char *)edge_label.c_str()),
332 agsafeset(graph_edge, (
char *)
"color", (
char *)
"red", (
char *)
"");
335 for (
auto &edge : temp_edges_) {
336 Agnode_t *node1 = node_map.at(edge.first.id());
337 Agnode_t *node2 = node_map.at(edge.second.id());
338 Agedge_t *graph_edge = agedge(G, node1, node2, (
char *)
"temporal",
true);
339 edge_list.push_back(graph_edge);
341 std::string edge_label = edge.second.genTemporalEdgeLabel();
342 agsafeset(graph_edge,
344 agstrdup_html(G, (
char *)edge_label.c_str()),
346 agsafeset(graph_edge, (
char *)
"color", (
char *)
"blue", (
char *)
"");
349 gvLayout(gvc, G,
"dot");
350 gvRenderFilename(gvc, G,
"png",
"stn.png");
352 gvFreeLayout(gvc, G);
360 std::vector<bsoncxx::document::value>
363 std::vector<bsoncxx::document::value> stn;
364 for (
auto &action : stn_actions_) {
365 using namespace bsoncxx::builder;
366 basic::document bson_action;
367 bson_action.append(basic::kvp(
"id",
static_cast<int64_t
>(action.id())));
368 bson_action.append(basic::kvp(
"name", action.name()));
369 bson_action.append(basic::kvp(
"duration",
static_cast<int64_t
>(action.duration())));
370 bson_action.append(basic::kvp(
"cond-actions", [action](basic::sub_array cond_actions) {
371 for (
auto &cond : action.condActionIds()) {
372 cond_actions.append(static_cast<int64_t>(cond));
375 bson_action.append(basic::kvp(
"opts", [action](basic::sub_array opts) {
376 std::stringstream opts_ss(action.opts());
377 std::istream_iterator<std::string> end;
378 for (std::istream_iterator<std::string> it(opts_ss); it != end; it++) {
382 stn.push_back(bson_action.extract());
388 Stn::findActionById(
size_t id)
395 throw(
" Action with id " + std::to_string(
id) +
" not found");
399 Stn::log_warn(
const std::string &s)
401 log(s, LogLevel::WARN);
405 Stn::log_info(
const std::string &s)
407 log(s, LogLevel::INFO);
411 Stn::log_debug(
const std::string &s)
413 log(s, LogLevel::DEBUG);
416 Stn::log(
const std::string &s, Stn::LogLevel log_level)
418 std::string name =
"STN";
420 case LogLevel::WARN: logger_->
log_warn(name.c_str(),
"%s", s.c_str());
break;
421 case LogLevel::INFO: logger_->
log_info(name.c_str(),
"%s", s.c_str());
break;
422 case LogLevel::DEBUG: logger_->
log_debug(name.c_str(),
"%s", s.c_str());
break;
427 Stn::generate_classic_pddl_domain(
pddl_parser::Domain *dom,
const std::string &classic_dom_path)
429 log_info(
"Writing domain to " + classic_dom_path);
430 std::ofstream out(classic_dom_path);
432 out <<
"(define (domain " << dom->
name <<
")" << std::endl;
434 out <<
"\t(:requirements";
438 out <<
")" << std::endl;
440 out <<
"\t(:types" << std::endl;
441 for (
auto &type : dom->
types) {
442 out <<
"\t\t" << type.first <<
" - " << type.second << std::endl;
444 out <<
"\t)" << std::endl;
446 out <<
"\t(:constants" << std::endl;
447 for (
auto &const_type : dom->
constants) {
449 for (
auto &constant : const_type.first) {
450 out << constant <<
" ";
452 out <<
"- " << const_type.second << std::endl;
454 out <<
"\t)" << std::endl;
456 out <<
"\t(:predicates" << std::endl;
458 out <<
"\t\t(" << predicate.first;
459 for (
auto &pred_type : predicate.second) {
460 out <<
" ?" << pred_type.first <<
" - " << pred_type.second;
462 out <<
")" << std::endl;
464 out <<
"\t)" << std::endl;
466 for (
auto &action : dom->
actions) {
467 out <<
"\t(:action " << action.name << std::endl;
468 out <<
"\t\t:parameters (";
469 for (
auto ¶m : action.action_params) {
470 out <<
" ?" << param.first <<
" - " << param.second;
472 out <<
")" << std::endl;
473 out <<
"\t\t:precondition" << std::endl <<
"\t\t\t";
474 output_pred_list(action.precondition, out);
476 out << std::endl <<
"\t\t:effect" << std::endl <<
"\t\t\t";
477 output_pred_list(action.effect, out);
479 out << std::endl <<
"\t)" << std::endl;
488 Stn::output_pred_list(pddl_parser::Expression e, std::ofstream &out)
490 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e).function;
491 if (
function ==
"not" ||
function ==
"and") {
492 if (
function ==
"not") {
494 }
else if (
function ==
"and") {
497 for (
auto &child : boost::get<pddl_parser::Predicate>(e).arguments) {
498 output_pred_list(child, out);
502 out <<
"(" << boost::get<pddl_parser::Predicate>(e).function;
503 for (
auto &arg : boost::get<pddl_parser::Predicate>(e).arguments) {
504 out <<
" " << boost::get<std::string>(arg);
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
A representation of an action used by the STN generator.
StnAction generateStnAction(const std::string &name, const std::string ¶ms)
Generate an StnAction from the DomainAction.
A representation of a Predicate in the STN.
An action representation within an STN.
Stn(fawkes::Logger *logger)
Constructor.
void add_plan_action(const std::string &name, const std::string ¶ms)
Add a (grounded action).
virtual ~Stn()
Destructor.
void set_pddl_domain(const std::string &pddl_domain_string)
Set the domain of the STN to the given PDDL domain.
std::vector< bsoncxx::document::value > get_bson()
Get a BSON representation of the STN.
void read_initial_state(const std::string &pddl_problem_string)
Read the initial state from the given PDDL problem.
void generate()
Regenerate the STN.
void set_initial_state(const StnAction &action)
Set the initial state.
void drawGraph()
Render a graph representation of the STN.
Parse a PDDL domain file or problem.
static Problem parseProblem(const std::string pddl_problem)
Parse the PDDL problem.
static Domain parseDomain(const std::string pddl_domain)
Parse the PDDL domain.
Fawkes library namespace.
A structured representation of a PDDL domain.
std::vector< Action > actions
A list of actions defined in the domain.
std::string name
The name of the domain.
pairs_multi_consts constants
A typed list of constants defined in the domain.
pairs_type types
A list of types with their super types.
std::vector< predicate_type > predicates
A list of predicate names in the domain, including the types of their arguments.
std::vector< std::string > requirements
A list of PDDL features required by the domain.
A structured representation of a PDDL problem.
std::string name
The name of the problem.
std::vector< Expression > init
A list of facts that are initially true.