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;
104 std::vector<std::string> attrs;
105 std::string log_string =
"Adding init-predicate "
106 + boost::get<pddl_parser::Predicate>(pred.
expression).function
107 +
" with arguments:";
109 boost::get<pddl_parser::Predicate>(pred.
expression).arguments) {
110 attrs.push_back(boost::get<pddl_parser::Atom>(a.expression));
111 log_string +=
" " + boost::get<pddl_parser::Atom>(a.expression);
113 log_info(log_string);
117 init_predicates.push_back(init_pred);
135 log_info(
"Loading extended PDDL domain into STN.");
137 for (
auto &action : dom.
actions) {
138 log_info(
"Processing action " + action.name);
139 std::vector<std::string> params;
140 for (
auto ¶m : action.action_params) {
141 params.push_back(param.first);
143 std::vector<Predicate> preconds;
144 build_pred_list(action.precondition, &preconds,
true);
145 std::vector<Predicate> effects;
146 build_pred_list(action.effect, &effects,
true);
147 int duration = (int)std::stof(boost::get<pddl_parser::Atom>(action.duration.expression));
148 std::vector<std::string> cond_breakups;
149 log_info(std::to_string(action.cond_breakup.expression.which()));
150 if (action.cond_breakup.expression.which() == 1) {
151 build_breakup_list(action.cond_breakup, &cond_breakups);
153 std::vector<std::string> temp_breakups;
154 if (action.temp_breakup.expression.which() == 1) {
155 build_breakup_list(action.temp_breakup, &temp_breakups);
157 DomainAction da(action.name, params, preconds, effects, duration, cond_breakups, temp_breakups);
158 domain_actions_.push_back(da);
161 log_info(
"Initialized " + std::to_string(domain_actions_.size()) +
" domain actions");
163 if (gen_classic_dom_) {
164 log_info(
"Generation of classic domain file is configured, starting...");
165 generate_classic_pddl_domain(&dom, classic_dom_path_);
175 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e.
expression).function;
176 if (
function ==
"and" ||
function ==
"not") {
177 if (
function ==
"not") {
178 condition = !condition;
180 for (
auto &child : boost::get<pddl_parser::Predicate>(e.
expression).arguments) {
181 build_pred_list(child, preconds, condition);
184 std::vector<std::string> args;
185 for (
auto &arg : boost::get<pddl_parser::Predicate>(e.
expression).arguments) {
186 args.push_back(boost::get<std::string>(arg.expression));
188 Predicate p(boost::get<pddl_parser::Predicate>(e.
expression).function, condition, args);
189 preconds->push_back(p);
190 log_info(
"Added " + boost::get<pddl_parser::Predicate>(e.
expression).function);
197 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e.
expression).function;
199 if (
function ==
"and" ||
function ==
"not") {
200 for (
auto &child : boost::get<pddl_parser::Predicate>(e.
expression).arguments) {
201 build_breakup_list(child, breakups);
204 std::string pred_name = boost::get<pddl_parser::Predicate>(e.
expression).function;
205 std::cout <<
"Adding breakup " << pred_name << std::endl;
206 breakups->push_back(pred_name);
214 stn_actions_.clear();
217 for (plan_action pa : plan_actions_) {
218 std::vector<DomainAction>::iterator it = domain_actions_.begin();
219 for (; it != domain_actions_.end(); ++it) {
220 if (it->getName() == pa.name) {
224 if (it == domain_actions_.end())
225 throw(
"could not find fitting DomainAction");
230 std::cout <<
"Imported " << stn_actions_.size() <<
" actions into STN" << std::endl;
232 for (
int i = stn_actions_.size() - 1; i >= 0; i--) {
233 std::vector<StnAction> candidate_actions =
234 std::vector<StnAction>(stn_actions_.begin(), stn_actions_.begin() + i);
236 stn_actions_.at(i).genConditionalActions(candidate_actions);
237 }
catch (std::exception &e) {
238 std::cout <<
"ERROR stn.cpp:" << e.what() << std::endl;
242 std::vector<Predicate> predicates;
243 for (std::vector<StnAction>::iterator it = stn_actions_.begin(); it != stn_actions_.end(); ++it) {
245 for (
auto const &cond_action : it->condActionIds()) {
246 std::pair<StnAction, StnAction> edge(findActionById(cond_action), findActionById(it->id()));
247 cond_edges_.push_back(edge);
250 bool break_edge =
false;
252 if (it->checkForBreakup(EdgeType::TEMPORAL, p)) {
257 if (!break_edge && it != stn_actions_.begin()) {
258 std::pair<StnAction, StnAction> edge(findActionById((it - 1)->
id()),
259 findActionById(it->id()));
260 temp_edges_.push_back(edge);
265 std::vector<Predicate>::iterator it = std::find(predicates.begin(), predicates.end(), p);
266 if (it == predicates.end()) {
267 predicates.push_back(p);
272 Predicate neg_pred(p.name(),
true, p.attrs());
273 std::vector<Predicate>::iterator it =
274 std::find(predicates.begin(), predicates.end(), neg_pred);
275 if (it != predicates.end()) {
277 predicates.erase(it);
283 for (
auto &a : stn_actions_) {
284 bool no_temp_edge =
true;
285 for (
auto &e : temp_edges_) {
287 no_temp_edge =
false;
292 for (
auto &ce : cond_edges_) {
294 std::pair<StnAction, StnAction> edge(a, ce.second);
295 temp_edges_.push_back(edge);
312 char graph_name[] =
"STN";
314 G = agopen(graph_name, Agdirected, 0);
316 std::map<size_t, Agnode_t *> node_map;
319 std::string node_name = a.genGraphNodeName();
320 node_map.insert(std::make_pair(a.id(), agnode(G, (
char *)node_name.c_str(),
true)));
323 std::vector<Agedge_t *> edge_list;
324 for (
auto &edge : cond_edges_) {
325 Agnode_t *node1 = node_map.at(edge.first.id());
326 Agnode_t *node2 = node_map.at(edge.second.id());
327 Agedge_t *graph_edge = agedge(G, node1, node2, (
char *)
"conditional",
true);
328 edge_list.push_back(graph_edge);
330 std::string edge_label = edge.second.genConditionEdgeLabel(edge.first.id());
331 agsafeset(graph_edge,
333 agstrdup_html(G, (
char *)edge_label.c_str()),
335 agsafeset(graph_edge, (
char *)
"color", (
char *)
"red", (
char *)
"");
338 for (
auto &edge : temp_edges_) {
339 Agnode_t *node1 = node_map.at(edge.first.id());
340 Agnode_t *node2 = node_map.at(edge.second.id());
341 Agedge_t *graph_edge = agedge(G, node1, node2, (
char *)
"temporal",
true);
342 edge_list.push_back(graph_edge);
344 std::string edge_label = edge.second.genTemporalEdgeLabel();
345 agsafeset(graph_edge,
347 agstrdup_html(G, (
char *)edge_label.c_str()),
349 agsafeset(graph_edge, (
char *)
"color", (
char *)
"blue", (
char *)
"");
352 gvLayout(gvc, G,
"dot");
353 gvRenderFilename(gvc, G,
"png",
"stn.png");
355 gvFreeLayout(gvc, G);
363 std::vector<bsoncxx::document::value>
366 std::vector<bsoncxx::document::value> stn;
367 for (
auto &action : stn_actions_) {
368 using namespace bsoncxx::builder;
369 basic::document bson_action;
370 bson_action.append(basic::kvp(
"id",
static_cast<int64_t
>(action.id())));
371 bson_action.append(basic::kvp(
"name", action.name()));
372 bson_action.append(basic::kvp(
"duration",
static_cast<int64_t
>(action.duration())));
373 bson_action.append(basic::kvp(
"cond-actions", [action](basic::sub_array cond_actions) {
374 for (
auto &cond : action.condActionIds()) {
375 cond_actions.append(static_cast<int64_t>(cond));
378 bson_action.append(basic::kvp(
"opts", [action](basic::sub_array opts) {
379 std::stringstream opts_ss(action.opts());
380 std::istream_iterator<std::string> end;
381 for (std::istream_iterator<std::string> it(opts_ss); it != end; it++) {
385 stn.push_back(bson_action.extract());
391 Stn::findActionById(
size_t id)
398 throw(
" Action with id " + std::to_string(
id) +
" not found");
402 Stn::log_warn(
const std::string &s)
404 log(s, LogLevel::WARN);
408 Stn::log_info(
const std::string &s)
410 log(s, LogLevel::INFO);
414 Stn::log_debug(
const std::string &s)
416 log(s, LogLevel::DEBUG);
419 Stn::log(
const std::string &s, Stn::LogLevel log_level)
421 std::string name =
"STN";
423 case LogLevel::WARN: logger_->
log_warn(name.c_str(),
"%s", s.c_str());
break;
424 case LogLevel::INFO: logger_->
log_info(name.c_str(),
"%s", s.c_str());
break;
425 case LogLevel::DEBUG: logger_->
log_debug(name.c_str(),
"%s", s.c_str());
break;
430 Stn::generate_classic_pddl_domain(
pddl_parser::Domain *dom,
const std::string &classic_dom_path)
432 log_info(
"Writing domain to " + classic_dom_path);
433 std::ofstream out(classic_dom_path);
435 out <<
"(define (domain " << dom->
name <<
")" << std::endl;
437 out <<
"\t(:requirements";
441 out <<
")" << std::endl;
443 out <<
"\t(:types" << std::endl;
444 for (
auto &type : dom->
types) {
445 out <<
"\t\t" << type.first <<
" - " << type.second << std::endl;
447 out <<
"\t)" << std::endl;
449 out <<
"\t(:constants" << std::endl;
450 for (
auto &const_type : dom->
constants) {
452 for (
auto &constant : const_type.first) {
453 out << constant <<
" ";
455 out <<
"- " << const_type.second << std::endl;
457 out <<
"\t)" << std::endl;
459 out <<
"\t(:predicates" << std::endl;
461 out <<
"\t\t(" << predicate.first;
462 for (
auto &pred_type : predicate.second) {
463 out <<
" ?" << pred_type.first <<
" - " << pred_type.second;
465 out <<
")" << std::endl;
467 out <<
"\t)" << std::endl;
469 for (
auto &action : dom->
actions) {
470 out <<
"\t(:action " << action.name << std::endl;
471 out <<
"\t\t:parameters (";
472 for (
auto ¶m : action.action_params) {
473 out <<
" ?" << param.first <<
" - " << param.second;
475 out <<
")" << std::endl;
476 out <<
"\t\t:precondition" << std::endl <<
"\t\t\t";
477 output_pred_list(action.precondition, out);
479 out << std::endl <<
"\t\t:effect" << std::endl <<
"\t\t\t";
480 output_pred_list(action.effect, out);
482 out << std::endl <<
"\t)" << std::endl;
493 pddl_parser::Atom
function = boost::get<pddl_parser::Predicate>(e.
expression).function;
494 if (
function ==
"not" ||
function ==
"and") {
495 if (
function ==
"not") {
497 }
else if (
function ==
"and") {
500 for (
auto &child : boost::get<pddl_parser::Predicate>(e.
expression).arguments) {
501 output_pred_list(child, out);
505 out <<
"(" << boost::get<pddl_parser::Predicate>(e.
expression).function;
506 for (
auto &arg : boost::get<pddl_parser::Predicate>(e.
expression).arguments) {
507 out <<
" " << boost::get<std::string>(arg.expression);
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 Domain parseDomain(const std::string &pddl_domain)
Parse the PDDL domain.
static Problem parseProblem(const std::string &pddl_problem)
Parse the PDDL problem.
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.
expression_t expression
The expression formula.
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.