Fawkes API  Fawkes Development Version
precondition_visitor.cpp
1 /***************************************************************************
2  * precondition_visitor.cpp - A static visitor to translate a precondition
3  *
4  * Created: Mon 16 Oct 2017 18:34:44 CEST 18:34
5  * Copyright 2017 Till Hofmann <hofmann@kbsg.rwth-aachen.de>
6  ****************************************************************************/
7 
8 /* This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Library General Public License for more details.
17  *
18  * Read the full text in the LICENSE.GPL file in the doc directory.
19  */
20 
21 #include "precondition_visitor.h"
22 
23 using namespace std;
24 using namespace pddl_parser;
25 
26 /** @class PreconditionToCLIPSFactVisitor "precondition_visitor.h"
27  * Translate a PDDL precondition into CLIPS facts.
28  * @author Till Hofmann
29  * Helper class to translate a precondition from pddl_parser::Expression to a
30  * CLIPS fact. An expression is a boost::variant, and this class is a visitor
31  * for the variant that translates the Expression into a a vector of CLIPS
32  * facts.
33  */
34 
35 /** Constructor.
36  * @param parent The name of the parent (either an operator or a precondition)
37  * @param sub_counter Counter passed by the parent to enumerate sub-conditions
38  * @param is_main true if this is the direct child of the operator,
39  * i.e., not a sub-condition
40  */
42  int sub_counter,
43  bool is_main /* = false */)
44 : parent_(parent), sub_counter_(sub_counter), is_main_(is_main)
45 {
46 }
47 
48 /** Translate an Atom into a vector of strings.
49  * Note that this does not return a CLIPS fact because we do not store atoms
50  * (parameter names or constants) as separate facts. This needs to be further
51  * processed by the caller instead.
52  * @param a The atom to translate into a string.
53  * @return A vector that only contains the atom as is.
54  */
55 vector<string>
57 {
58  return vector<string>({a});
59 }
60 
61 /** Translate a Predicate into a vector of strings.
62  * This creates proper CLIPS precondition fact strings for the Predicate and all
63  * its arguments. For compound formulae (e.g., conjunctions), this also
64  * translates all sub-formulae recursively.
65  * @param p The predicate to translate.
66  * @return A vector of strings, each string is a properly formed CLIPS fact.
67  */
68 vector<string>
70 {
71  vector<string> res;
72  stringstream namestream;
73  namestream << parent_ << sub_counter_;
74  string name = namestream.str();
75  if (p.function == "and" || p.function == "not" || p.function == "or") {
76  string type;
77  if (p.function == "and") {
78  type = "conjunction";
79  } else if (p.function == "or") {
80  type = "disjunction";
81  } else if (p.function == "not") {
82  type = "negation";
83  }
84  res.push_back(string("(domain-precondition"
85  " (name "
86  + name
87  + ")"
88  " (part-of "
89  + parent_
90  + ")"
91  " (type "
92  + type
93  + ")"
94  ")"));
95  uint sub_counter = 1;
96  for (Expression &sub : p.arguments) {
97  vector<string> args =
98  boost::apply_visitor(PreconditionToCLIPSFactVisitor(name, sub_counter++), sub);
99  res.insert(res.end(), args.begin(), args.end());
100  }
101  return res;
102  } else {
103  // We expect p.function to be a predicate name.
104  string new_parent;
105  if (is_main_) {
106  // Special case: this is the main precondition, but it's an atomic
107  // condition. Add an additional condition so we never have an atomic
108  // precondition as the main precondition.
109  res.push_back(string("(domain-precondition"
110  " (part-of "
111  + parent_
112  + ")"
113  " (name "
114  + name
115  + ")"
116  " (type conjunction)"
117  ")"));
118  // Also adapt parent and name, the parent is now the new precondition
119  // above.
120  new_parent = name;
121  stringstream child_name;
122  child_name << name << 1;
123  name = child_name.str();
124  } else {
125  new_parent = parent_;
126  }
127  string params = "";
128  string constants = "";
129  for (auto &p : p.arguments) {
130  vector<string> p_strings = boost::apply_visitor(PreconditionToCLIPSFactVisitor(name, 0), p);
131  if (p_strings.size() != 1) {
132  throw PddlParserException("Unexpected parameter length, expected exactly one");
133  }
134  string p_string = p_strings[0];
135  if (p_string[0] == '?') {
136  // It's really a parameter.
137  if (p_string.length() <= 1) {
138  throw PddlParserException("Invalid parameter name " + p_string);
139  }
140  params += " " + p_string.substr(1);
141  constants += " nil";
142  } else {
143  // It's a constant.
144  params += " c";
145  constants += " " + p_string;
146  }
147  }
148  string predicate_string;
149  if (p.function == "=") {
150  // It's not a predicate but an equality.
151  predicate_string = " (equality TRUE)";
152  } else {
153  predicate_string = " (predicate " + p.function + ")";
154  }
155 
156  res.push_back(string("(domain-atomic-precondition"
157  " (part-of "
158  + new_parent
159  + ")"
160  " (name "
161  + name + ")" + predicate_string + " (param-names (create$" + params
162  + "))"
163  " (param-constants (create$"
164  + constants
165  + "))"
166  ")"));
167  return res;
168  }
169 }
pddl_parser::Predicate::arguments
std::vector< Expression > arguments
The arguments of the predicate or the subformulae of the compound formula.
Definition: pddl_ast.h:72
pddl_parser::Predicate
Definition: pddl_ast.h:63
PreconditionToCLIPSFactVisitor::PreconditionToCLIPSFactVisitor
PreconditionToCLIPSFactVisitor(const std::string &parent, int sub_counter, bool is_main=false)
Constructor.
Definition: precondition_visitor.cpp:40
PreconditionToCLIPSFactVisitor::operator()
std::vector< std::string > operator()(pddl_parser::Atom &a) const
Translate an Atom into a vector of strings.
Definition: precondition_visitor.cpp:55
pddl_parser::Predicate::function
Atom function
The name of the predicate for atomic formulae, 'and' for a conjunction, 'or' for a disjunction,...
Definition: pddl_ast.h:68
pddl_parser::PddlParserException
Definition: pddl_parser.h:49