Fawkes API Fawkes Development Version
test_pddl_parser.cpp
1/***************************************************************************
2 * test_skill_parser.cpp - Tests for ExecutionTimeEstimator::Skill
3 *
4 * Created: 23-10-2020
5 * Copyright 2021 Tarik Viehmann <viehmann@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#include "../pddl_exception.h"
21#include "../pddl_parser.h"
22
23#include <gtest/gtest.h>
24
25#include <filesystem>
26#include <fstream>
27#include <sstream>
28
29using namespace pddl_parser;
30
31TEST(PddlParserTest, TypingTest)
32{
33 auto benchmarks = {R"delim(
34(define (domain action-arg-pred-missmatch)
35 (:requirements :strips :typing)
36 (:types
37 obj-a - object
38 obj-b - object
39 )
40 (:predicates
41 (pred ?r - obj-a)
42 )
43 (:action test-action
44 :parameters (?t - obj-b)
45 :precondition (pred ?t)
46 :effect (not (pred ?t))
47 )
48))delim",
49 R"delim(
50 (define (domain typing-disabled-but-type-defined)
51 (:requirements :strips)
52 (:types
53 obj-a - object
54 )
55 (:predicates
56 (pred ?r)
57 )
58 (:action test-action
59 :parameters (?t)
60 :precondition (pred ?t)
61 :effect (not (pred ?t))
62 )
63))delim",
64 R"delim(
65(define (domain typing-disabled-but-type-constant)
66 (:requirements :strips)
67 (:constants
68 TEST_CONST - object
69 )
70 (:predicates
71 (pred ?r)
72 )
73 (:action test-action
74 :parameters (?t)
75 :precondition (pred ?t)
76 :effect (not (pred ?t))
77 )
78))delim",
79 R"delim(
80(define (domain typing-disabled-but-type-param)
81 (:requirements :strips)
82 (:predicates
83 (pred ?r)
84 )
85 (:action test-action
86 :parameters (?t - object)
87 :precondition (pred ?t)
88 :effect (not (pred ?t))
89 )
90))delim",
91 R"delim(
92(define (domain action-unknown-type-in-pred)
93 (:requirements :strips :typing)
94 (:types
95 obj-a - object
96 )
97 (:predicates
98 (pred ?r - obj-b)
99 )
100 (:action test-action
101 :parameters (?t - obj-a)
102 :precondition (pred ?t)
103 :effect (not (pred ?t))
104 )
105))delim",
106 R"delim(
107(define (domain action-unknown-type-in-param)
108 (:requirements :strips :typing)
109 (:types
110 obj-a - object
111 )
112 (:predicates
113 (pred ?r - obj-a)
114 )
115 (:action test-action
116 :parameters (?t - obj-b)
117 :precondition (pred ?t)
118 :effect (not (pred ?t))
119 )
120))delim",
121 R"delim(
122(define (domain action-unknown-type-in-constant)
123 (:requirements :strips :typing)
124 (:types
125 obj-a - object
126 )
127 (:constants
128 TEST_CONST - obj-b
129 )
130 (:predicates
131 (pred ?r - obj-a)
132 )
133 (:action test-action
134 :parameters (?t - obj-a)
135 :precondition (pred ?t)
136 :effect (not (pred ?t))
137 )
138))delim",
139 R"delim(
140(define (domain action-constant-missmatch)
141 (:requirements :strips :typing)
142 (:types
143 obj-a - object
144 obj-b - object
145 )
146 (:constants
147 TEST_CONST - obj-b
148 )
149 (:predicates
150 (pred ?r - obj-a)
151 )
152 (:action test-action
153 :parameters (?t - obj-a)
154 :precondition (pred TEST_CONST)
155 :effect (not (pred ?t))
156 )
157))delim"};
158 for (const auto &s : benchmarks) {
159 EXPECT_THROW(
160 {
161 PddlParser p;
162 p.parseDomain(s);
163 },
165 }
166}
167
168TEST(PddlParserTest, MinimalDomain)
169{
170 PddlParser p;
171 Domain d;
172 EXPECT_NO_THROW(d = p.parseDomain(R"delim(
173(define (domain test-domain)
174 (:requirements)
175 (:predicates
176 (pred)
177 )
178 (:action test-action
179 :parameters (?t)
180 :precondition (pred)
181 :effect (not (pred))
182 )
183))delim"););
184
185 ASSERT_EQ(d.requirements.size(), 0);
186 ASSERT_EQ(d.types.size(), 0);
187 ASSERT_EQ(d.constants.size(), 0);
188 ASSERT_EQ(d.predicates.size(), 1);
189 ASSERT_EQ(d.functions.size(), 0);
190 ASSERT_EQ(d.actions.size(), 1);
191 ASSERT_EQ(d.actions[0].name, "test-action");
192 ASSERT_EQ(d.actions[0].action_params.size(), 1);
193 // action precondition correctly parsed?
194 ASSERT_EQ(d.actions[0].precondition.type, ExpressionType::PREDICATE);
195 ASSERT_EQ(boost::get<Predicate>(d.actions[0].precondition.expression).function, "pred");
196 ASSERT_EQ(boost::get<Predicate>(d.actions[0].precondition.expression).arguments.size(), 0);
197 // action effect correctly parsed?
198 ASSERT_EQ(d.actions[0].effect.type, ExpressionType::BOOL);
199 ASSERT_EQ(boost::get<Predicate>(d.actions[0].effect.expression).function, "not");
200 ASSERT_EQ(boost::get<Predicate>(d.actions[0].effect.expression).arguments.size(), 1);
201 ASSERT_EQ(boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].type,
202 ExpressionType::PREDICATE);
203 ASSERT_EQ(boost::get<Predicate>(
204 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
205 .function,
206 "pred");
207 ASSERT_EQ(boost::get<Predicate>(
208 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
209 .arguments.size(),
210 0);
211}
212
213TEST(PddlParserTest, DurativeAction)
214{
215 PddlParser p;
216 Domain d;
217 EXPECT_NO_THROW(d = p.parseDomain(R"delim(
218(define (domain test-durative-action)
219 (:requirements :strips :durative-actions)
220 (:predicates
221 (pred ?r)
222 )
223 (:durative-action test-action
224 :parameters (?t)
225 :duration (= ?duration 5.5)
226 :condition (and (at start (pred ?t))
227 (over all (pred ?t)))
228 :effect (and (at end (not (pred ?t)))
229 (at start (pred ?t)))
230 )
231))delim"););
232 ASSERT_EQ(d.requirements.size(), 2);
233 ASSERT_EQ(d.types.size(), 0);
234 ASSERT_EQ(d.constants.size(), 0);
235 ASSERT_EQ(d.predicates.size(), 1);
236 ASSERT_EQ(d.functions.size(), 0);
237 ASSERT_EQ(d.actions.size(), 1);
238 ASSERT_EQ(d.actions[0].name, "test-action");
239 ASSERT_EQ(d.actions[0].duration.type, ExpressionType::VALUE);
240 ASSERT_EQ(boost::get<Atom>(d.actions[0].duration.expression), "5.5");
241 ASSERT_EQ(d.actions[0].action_params.size(), 1);
242 // action precondition correctly parsed?
243 ASSERT_EQ(d.actions[0].precondition.type, ExpressionType::BOOL);
244 ASSERT_EQ(boost::get<Predicate>(d.actions[0].precondition.expression).function, "and");
245 ASSERT_EQ(boost::get<Predicate>(d.actions[0].precondition.expression).arguments.size(), 2);
246 ASSERT_EQ(boost::get<Predicate>(
247 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[0].expression)
248 .function,
249 "at start");
250 ASSERT_EQ(boost::get<Predicate>(
251 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[0].expression)
252 .arguments.size(),
253 1);
254 ASSERT_EQ(boost::get<Predicate>(
255 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[0].expression)
256 .arguments[0]
257 .type,
258 ExpressionType::PREDICATE);
259 ASSERT_EQ(boost::get<Predicate>(
260 boost::get<Predicate>(
261 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[0].expression)
262 .arguments[0]
263 .expression)
264 .function,
265 "pred");
266 ASSERT_EQ(boost::get<Predicate>(
267 boost::get<Predicate>(
268 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[0].expression)
269 .arguments[0]
270 .expression)
271 .arguments.size(),
272 1);
273 ASSERT_EQ(boost::get<Predicate>(
274 boost::get<Predicate>(
275 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[0].expression)
276 .arguments[0]
277 .expression)
278 .arguments[0]
279 .type,
280 ExpressionType::ATOM);
281 ASSERT_EQ(boost::get<Predicate>(
282 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[1].expression)
283 .function,
284 "over all");
285 ASSERT_EQ(boost::get<Predicate>(
286 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[1].expression)
287 .arguments.size(),
288 1);
289 ASSERT_EQ(boost::get<Predicate>(
290 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[1].expression)
291 .arguments[0]
292 .type,
293 ExpressionType::PREDICATE);
294 ASSERT_EQ(boost::get<Predicate>(
295 boost::get<Predicate>(
296 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[1].expression)
297 .arguments[0]
298 .expression)
299 .function,
300 "pred");
301 ASSERT_EQ(boost::get<Predicate>(
302 boost::get<Predicate>(
303 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[1].expression)
304 .arguments[0]
305 .expression)
306 .arguments.size(),
307 1);
308 ASSERT_EQ(boost::get<Predicate>(
309 boost::get<Predicate>(
310 boost::get<Predicate>(d.actions[0].precondition.expression).arguments[1].expression)
311 .arguments[0]
312 .expression)
313 .arguments[0]
314 .type,
315 ExpressionType::ATOM);
316 // action effect correctly parsed?
317 ASSERT_EQ(boost::get<Predicate>(d.actions[0].effect.expression).function, "and");
318 ASSERT_EQ(boost::get<Predicate>(d.actions[0].effect.expression).arguments.size(), 2);
319 ASSERT_EQ(boost::get<Predicate>(
320 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
321 .function,
322 "at end");
323 ASSERT_EQ(boost::get<Predicate>(
324 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
325 .arguments.size(),
326 1);
327 ASSERT_EQ(boost::get<Predicate>(
328 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
329 .arguments[0]
330 .type,
331 ExpressionType::BOOL);
332 ASSERT_EQ(boost::get<Predicate>(
333 boost::get<Predicate>(
334 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
335 .arguments[0]
336 .expression)
337 .function,
338 "not");
339 ASSERT_EQ(boost::get<Predicate>(
340 boost::get<Predicate>(
341 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
342 .arguments[0]
343 .expression)
344 .arguments.size(),
345 1);
346 ASSERT_EQ(boost::get<Predicate>(
347 boost::get<Predicate>(
348 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
349 .arguments[0]
350 .expression)
351 .arguments[0]
352 .type,
353 ExpressionType::PREDICATE);
354 ASSERT_EQ(boost::get<Predicate>(
355 boost::get<Predicate>(
356 boost::get<Predicate>(
357 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
358 .arguments[0]
359 .expression)
360 .arguments[0]
361 .expression)
362 .function,
363 "pred");
364 ASSERT_EQ(boost::get<Predicate>(
365 boost::get<Predicate>(
366 boost::get<Predicate>(
367 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
368 .arguments[0]
369 .expression)
370 .arguments[0]
371 .expression)
372 .arguments.size(),
373 1);
374 ASSERT_EQ(boost::get<Predicate>(
375 boost::get<Predicate>(
376 boost::get<Predicate>(
377 boost::get<Predicate>(d.actions[0].effect.expression).arguments[0].expression)
378 .arguments[0]
379 .expression)
380 .arguments[0]
381 .expression)
382 .arguments[0]
383 .type,
384 ExpressionType::ATOM);
385 ASSERT_EQ(boost::get<Predicate>(
386 boost::get<Predicate>(d.actions[0].effect.expression).arguments[1].expression)
387 .function,
388 "at start");
389 ASSERT_EQ(boost::get<Predicate>(
390 boost::get<Predicate>(d.actions[0].effect.expression).arguments[1].expression)
391 .arguments.size(),
392 1);
393 ASSERT_EQ(boost::get<Predicate>(
394 boost::get<Predicate>(d.actions[0].effect.expression).arguments[1].expression)
395 .arguments[0]
396 .type,
397 ExpressionType::PREDICATE);
398 ASSERT_EQ(boost::get<Predicate>(
399 boost::get<Predicate>(
400 boost::get<Predicate>(d.actions[0].effect.expression).arguments[1].expression)
401 .arguments[0]
402 .expression)
403 .function,
404 "pred");
405 ASSERT_EQ(boost::get<Predicate>(
406 boost::get<Predicate>(
407 boost::get<Predicate>(d.actions[0].effect.expression).arguments[1].expression)
408 .arguments[0]
409 .expression)
410 .arguments.size(),
411 1);
412 ASSERT_EQ(boost::get<Predicate>(
413 boost::get<Predicate>(
414 boost::get<Predicate>(d.actions[0].effect.expression).arguments[1].expression)
415 .arguments[0]
416 .expression)
417 .arguments[0]
418 .type,
419 ExpressionType::ATOM);
420}
421
422TEST(PddlParserTest, Functions)
423{
424 EXPECT_NO_THROW(PddlParser p; p.parseDomain(R"delim(
425(define (domain test-functions)
426 (:requirements :strips :numeric-fluents)
427 (:predicates
428 (pred ?r)
429 )
430 (:functions
431 (func ?r)
432 )
433 (:action test-action
434 :parameters (?t)
435 :precondition (and (pred ?t)
436 (= (func ?t) 1.1))
437 :effect (increase (pred ?t) (pred ?t))
438 )
439))delim"););
440}
441TEST(PddlParserTest, IPC2014)
442{
443 using recursive_directory_iterator = std::filesystem::recursive_directory_iterator;
444 std::vector<std::string> domains;
445 std::string domain_suffix = "domain.pddl";
446 for (const auto &dir : recursive_directory_iterator(std::string(SRCDIR) + "/ipc2014")) {
447 std::string dirEntry = dir.path().stem().string();
448 std::string file_ending = dir.path().extension().string();
449 if (file_ending == ".pddl" && dirEntry.find("domain") != std::string::npos) {
450 domains.push_back(dir.path().string());
451 }
452 }
453 for (const auto &s : domains) {
454 EXPECT_NO_THROW(std::ifstream t(s); if (t.fail()) {
455 FAIL() << " Failed to read file: " << s;
456 } std::stringstream buffer;
457 buffer << t.rdbuf();
458 PddlParser p;
459 p.parseDomain(buffer.str()););
460 }
461}
Parse a PDDL domain file or problem.
Definition: pddl_parser.h:34
static Domain parseDomain(const std::string &pddl_domain)
Parse the PDDL domain.
Definition: pddl_parser.cpp:72
Exception thrown by the parser if declared type does not match the defined one.
A structured representation of a PDDL domain.
Definition: pddl_ast.h:157
std::vector< Action > actions
A list of actions defined in the domain.
Definition: pddl_ast.h:173
pairs_multi_consts constants
A typed list of constants defined in the domain.
Definition: pddl_ast.h:165
pairs_type types
A list of types with their super types.
Definition: pddl_ast.h:163
std::vector< predicate_type > predicates
A list of predicate names in the domain, including the types of their arguments.
Definition: pddl_ast.h:169
std::vector< std::string > requirements
A list of PDDL features required by the domain.
Definition: pddl_ast.h:161
std::vector< Function > functions
A list of numeric functions in the domain.
Definition: pddl_ast.h:171