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 a quantified formula to a vector of strings.
49  * Not implemented yet.
50  * @param q The quantified formula to translate into a string.
51  * @return An empty vector.
52  */
53 vector<string>
55 {
56  throw PddlParserException("QuantifiedFormulas are not supported in CLIPS yet.");
57  return vector<string>();
58 }
59 
60 /** Translate an Atom into a vector of strings.
61  * Note that this does not return a CLIPS fact because we do not store atoms
62  * (parameter names or constants) as separate facts. This needs to be further
63  * processed by the caller instead.
64  * @param a The atom to translate into a string.
65  * @return A vector that only contains the atom as is.
66  */
67 vector<string>
69 {
70  return vector<string>({a});
71 }
72 
73 /** Translate a Predicate into a vector of strings.
74  * This creates proper CLIPS precondition fact strings for the Predicate and all
75  * its arguments. For compound formulae (e.g., conjunctions), this also
76  * translates all sub-formulae recursively.
77  * @param p The predicate to translate.
78  * @return A vector of strings, each string is a properly formed CLIPS fact.
79  */
80 vector<string>
82 {
83  vector<string> res;
84  stringstream namestream;
85  namestream << parent_ << sub_counter_;
86  string name = namestream.str();
87  if (p.function == "and" || p.function == "not" || p.function == "or") {
88  string type;
89  if (p.function == "and") {
90  type = "conjunction";
91  } else if (p.function == "or") {
92  type = "disjunction";
93  } else if (p.function == "not") {
94  type = "negation";
95  }
96 
97  res.push_back(string("(pddl-formula"
98  " (id "
99  + name
100  + ")"
101  " (part-of "
102  + parent_
103  + ")"
104  " (type "
105  + type
106  + ")"
107  ")"));
108  uint sub_counter = 1;
109  for (Expression &sub : p.arguments) {
110  vector<string> args =
111  boost::apply_visitor(PreconditionToCLIPSFactVisitor(name, sub_counter++), sub.expression);
112  res.insert(res.end(), args.begin(), args.end());
113  }
114  return res;
115  } else {
116  // We expect p.function to be a predicate name.
117  string new_parent;
118  if (is_main_) {
119  // Special case: this is the main precondition, but it's an atomic
120  // condition. Add an additional condition so we never have an atomic
121  // precondition as the main precondition.
122  res.push_back(string("(pddl-formula"
123  " (part-of "
124  + parent_
125  + ")"
126  " (id "
127  + name
128  + ")"
129  " (type conjunction)"
130  ")"));
131  // Also adapt parent and name, the parent is now the new precondition
132  // above.
133  new_parent = name;
134  stringstream child_name;
135  child_name << name << 1;
136  name = child_name.str();
137  } else {
138  new_parent = parent_;
139  }
140  string params = "";
141  string constants = "";
142  for (auto &p : p.arguments) {
143  vector<string> p_strings =
144  boost::apply_visitor(PreconditionToCLIPSFactVisitor(name, 0), p.expression);
145  if (p_strings.size() != 1) {
146  throw PddlParserException("Unexpected parameter length, expected exactly one");
147  }
148  string p_string = p_strings[0];
149  if (p_string[0] == '?') {
150  // It's really a parameter.
151  if (p_string.length() <= 1) {
152  throw PddlParserException("Invalid parameter name " + p_string);
153  }
154  params += " " + p_string.substr(1);
155  constants += " nil";
156  } else {
157  // It's a constant.
158  params += " c";
159  constants += " " + p_string;
160  }
161  }
162  string predicate_string;
163  string predicate_string_new;
164  if (p.function == "=") {
165  // It's not a predicate but an equality.
166  predicate_string = " (predicate EQUALITY)";
167  } else {
168  predicate_string = " (predicate " + p.function + ")";
169  }
170  // create parent atomic formula for predicate
171  res.push_back(string("(pddl-formula"
172  " (part-of "
173  + new_parent
174  + ")"
175  " (id "
176  + name + "-atom"
177  + ")"
178  " (type atom)"
179  ")"));
180 
181  res.push_back(string("(pddl-predicate"
182  " (part-of "
183  + name + "-atom"
184  + ")"
185  " (id "
186  + name + ")" + predicate_string + " (param-names (create$" + params
187  + "))"
188  " (param-constants (create$"
189  + constants
190  + "))"
191  ")"));
192  return res;
193  }
194 }
PreconditionToCLIPSFactVisitor(const std::string &parent, int sub_counter, bool is_main=false)
Constructor.
std::vector< std::string > operator()(pddl_parser::Atom &a) const
Translate an Atom into a vector of strings.
Exception thrown by the parser if an error occurs during parsing.
A PDDL Expression.
Definition: pddl_ast.h:78
expression_t expression
The expression formula.
Definition: pddl_ast.h:82
A PDDL formula (either part of a precondition or an effect(.
Definition: pddl_ast.h:107
std::vector< Expression > arguments
The arguments of the predicate or the subformulae of the compound formula.
Definition: pddl_ast.h:115
Atom function
The name of the predicate for atomic formulae, 'and' for a conjunction, 'or' for a disjunction,...
Definition: pddl_ast.h:111
A PDDL quantified formula.
Definition: pddl_ast.h:89