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
23using namespace std;
24using 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 */
53vector<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 */
67vector<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 */
80vector<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