Giter VIP home page Giter VIP logo

aquaplanning's Introduction

Aquaplanning – QUick Automated Planning

Aquaplanning is a Java framework for Automated Planning, developed by Tomáš Balyo and Dominik Schreiber for the lecture Automated Planning and Scheduling at Karlsruhe Institute of Technology (KIT). It is meant as a simple, but extensible and reasonably powerful planning environment for PDDL problems, for educational and any other means.

Features

Here we give an overview on what Aquaplanning can do.

Problem Models

Aquaplanning supports PDDL (Planning Domain Description Language) files as an input for planning domains and problems. The supported subset of PDDL is roughly on par with Fast Downward, today's prototypical state-of-the-art classical planner. This means that the following features are implemented as of now (i.e. problems with these features can be parsed, grounded, and solved):

  • Basic STRIPS planning with typing
  • Negative conditions (preconditions / effects / goals)
  • Equality (as a universal predicate (= obj1 obj2))
  • Conditional effects (when (condition) (additional-effect))
  • Universal and existential quantifications
  • All ADL features, i.e. disjunctive conditions with or, imply, and non-atomic not expressions
  • Action costs (in its basic form (:function total-cost - number), with constant positive cost per operator)
  • Derived predicates (as long as the resulting ground axioms are not directly recursing on themselves)

In addition, Aquaplanning supports the following aspects of numeric planning:

  • Numeric fluents (a.k.a. functions), e.g. (capacity ?truck)
  • Numeric expressions in preconditions, e.g. (> (capacity ?truck) 0)
  • Numeric effects, e.g. (decrease (capacity ?truck) 1)

For planning problems using these features (or any subset), a full representation of the read problem is available in the form of Java objects after parsing, as well as a separate ground representation after grounding the problem.

Preprocessing and Grounding

For processing PDDL input, a parser generated from this ANTLR grammar for PDDL is used.

Parsed problems will first be simplified in a preprocessing step: notably, all quantifications are eliminated into flat conjunctions / disjunctions, and complex logical expressions can be transformed into Disjunctive Normal Form (DNF) in order to split disjunctive operators into multiple conjunctive operators, if desired. Derived predicates and conditional effects remain an explicit part of the problem representation, also during planning. Equality predicates can be compiled out (simplifying some preconditions) or can be kept just like normal predicates.

For grounding purposes, Aquaplanning traverses the problem's delete-relaxed planning graph. As the grounding does not exhaustively test all possible argument combinations for each operator but only a small subset, both run times and produced problem volume are usually quite reasonable.

Planning

The following planners are implemented:

  • A generic state space forward search with a few common search strategies (BFS, DFS, A*, Weighted A*, Best-first, random choice) and a couple of heuristics to guide the heuristic search strategies searches. (Not all heuristics support all of the mentioned PDDL features.)
  • Some planning algorithms based on incremental SAT solving. (Does not support conditional effects, derived predicates, or numeric planning.)

The following types of planning are generally supported w.r.t. the problem representation, but there are no (notable) realizations of it yet:

  • Parallel planning. (There is an easy and generic interface for implementing portfolio-style planners.)
  • Optimal planning. (Optimal plans can only be found if all actions have equal cost and either incremental SAT with step size 1 or forward search with a (nearly) admissible heuristic is used.)
  • Lifted planning.

Post-Processing

Aquaplanning features an interface for anytime plan optimization procedures, but there are no notable realizations of it yet.

At the end of the pipeline, a tiny plan validator can be employed to ensure the planner's correctness.

Building and installing

The framework is written from scratch and thus does not rely on any Planning-related frameworks. It does depend on antlr4 (for the parsing of PDDL files), Picocli for argument parsing, and sat4j as a SAT solver backend. We use Maven as a build system to resolve these dependencies (package maven in Debian-based Linux distributions). In the base directory, run mvn package which will create a runnable jar file in target/aquaplanning-<version>-jar-with-dependencies.jar. You can launch the application with java -jar <runnable-jar>. JUnit tests are disabled by default (as they potentially take a long time); you can re-enable them by appending -DskipTests=false to the build command.

Usage

Aquaplanning can be used as an off-the-shelf planner; you can specify a domain file and a problem file as arguments (in that order), and it will attempt to parse, ground, and solve the problem. You can try the files provided in the testfiles/ directory. All available options will be displayed when running the .jar without any arguments or with the --help flag.

When you want to use your own planner, implement the Planner interface and take a look at the DefaultPlanner class as a point of reference.

If you find any bugs or you consider something to be missing, please let us know. We appreciate receiving issues and/or pull requests!

aquaplanning's People

Contributors

biotomas avatar domschrei avatar femigr avatar froleyks avatar jtrautmann avatar marvinwilliams avatar patrickhegemann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

aquaplanning's Issues

Null Pointer Exception during grounding

Using the minimum example provided below, the following output is put out by Aquaplanning.
I believe it is caused by Operator.setEffect(AbstractCondition) not being called with a valid condition.

java -jar ./target/aquaplanning-0.0.1-SNAPSHOT-jar-with-dependencies.jar files/rubikscube/domainminimumproblem.pddl files/rubikscube/problemminimumproblem.pddl 
This is Aquaplanning - QUick Automated Planning.
Parsing ...
Parsing complete.

Grounding ...
An error occurred.
java.lang.NullPointerException
	at edu.kit.aquaplanning.grounding.Preprocessor.instantiateQuantifications(Preprocessor.java:137)
	at edu.kit.aquaplanning.grounding.Preprocessor.simplifyProblem(Preprocessor.java:91)
	at edu.kit.aquaplanning.grounding.Preprocessor.preprocess(Preprocessor.java:58)
	at edu.kit.aquaplanning.grounding.RelaxedPlanningGraphGrounder.ground(RelaxedPlanningGraphGrounder.java:42)
	at edu.kit.aquaplanning.Main.main(Main.java:99)

MinimumExample.zip

Test failures

I ran the TestPlanners test cases as it is without changing anything and the testDerivedPredicates() method returned an error message:

Testing domain "testfiles/derivedPredicates/domain1.pddl", problem "testfiles/derivedPredicates/p1.pddl".
Parsing ...
Grounding ...
Planning ...
0 : (turn4 o4)
1 : (turn4 o3)

[0,286] Error at step 1: Action (turn4 o4) PRE: { { AND (is-any) ¬(eq-o1-or-o2-or-o3 o4) } } POST: { {3} }} is not applicable in state { (_TRUE) }.

In the TestParallelPlanning test as it is without changing anything, the testParallelPlanner() method also returned invalid plans. This might be the same error as the above one. There were error for the rover domain like this one:

Testing planner on /home/jeremias/Programmieren/KIT/APS/aquaplanning/benchmarks/Rover/p03.pddl
[65,457] Error at step 7: Action (calibrate rover0 camera0 objective0 waypoint1) PRE: { {4, 25, 26, 27, 28} } POST: { {29} }} is not applicable in state { (available rover0) (can_traverse rover0 waypoint1 waypoint2) (visible waypoint1 waypoint2) (at rover0 waypoint2) (can_traverse rover0 waypoint1 waypoint5) (visible waypoint1 waypoint5) (available rover1) (at rover1 waypoint2) (can_traverse rover1 waypoint2 waypoint0) (can_traverse rover1 waypoint2 waypoint3) (visible waypoint2 waypoint3) (at rover1 waypoint3) (can_traverse rover1 waypoint2 waypoint5) (visible waypoint2 waypoint5) (equipped_for_imaging rover0) (calibration_target camera0 objective0) (visible_from objective0 waypoint1) (on_board camera0 rover0) (calibration_target camera1 objective0) (on_board camera1 rover0) (can_traverse rover0 waypoint2 waypoint0) (can_traverse rover0 waypoint2 waypoint1) (visible waypoint2 waypoint1) (can_traverse rover0 waypoint5 waypoint1) (visible waypoint5 waypoint1) (can_traverse rover1 waypoint0 waypoint2) (visible waypoint0 waypoint2) (can_traverse rover1 waypoint3 waypoint1) (visible waypoint3 waypoint1) (can_traverse rover1 waypoint3 waypoint2) (visible waypoint3 waypoint2) (can_traverse rover1 waypoint5 waypoint2) (visible waypoint5 waypoint2) (at_soil_sample waypoint5) (equipped_for_soil_analysis rover0) (store_of rover0store rover0) (empty rover0store) (at_rock_sample waypoint3) (equipped_for_rock_analysis rover1) (store_of rover1store rover1) (empty rover1store) (at_rock_sample waypoint5) (visible_from objective0 waypoint2) (visible_from objective0 waypoint5) (supports camera0 high_res) (supports camera1 high_res) (supports camera1 low_res) (can_traverse rover0 waypoint0 waypoint2) (can_traverse rover0 waypoint0 waypoint3) (visible waypoint0 waypoint3) (can_traverse rover0 waypoint0 waypoint4) (visible waypoint0 waypoint4) (can_traverse rover1 waypoint1 waypoint3) (visible waypoint1 waypoint3) (visible_from objective0 waypoint0) (at_lander general waypoint4) (channel_free general) (visible waypoint1 waypoint4) (visible waypoint3 waypoint4) (can_traverse rover0 waypoint3 waypoint0) (visible waypoint3 waypoint0) (can_traverse rover0 waypoint4 waypoint0) (visible waypoint4 waypoint0) (visible_from objective0 waypoint3) (visible_from objective0 waypoint4) (visible waypoint0 waypoint5) (visible waypoint5 waypoint0) (visible waypoint4 waypoint3) (visible waypoint4 waypoint1) (visible waypoint5 waypoint3) (visible waypoint3 waypoint5) (_TRUE) }.
Plan is valid:false

But there were also errors for the childsnack domain, though this looks to me like another problem - like an action from the rover domain was used:

Testing planner on /home/jeremias/Programmieren/KIT/APS/aquaplanning/benchmarks/Childsnack/p01.pddl
[126,501] Error at step 6: Action (navigate rover0 waypoint4 waypoint1) PRE: { {0, 1, 2, 3} } POST: { {4} ; NOT {1} }} is not applicable in state { (at_kitchen_bread bread1) (at_kitchen_content content1) (notexist sandw1) (notexist sandw2) (at tray1 kitchen) (at tray2 kitchen) (at tray3 kitchen) (at tray3 table1) (not_allergic_gluten child1) (waiting child1 table1) (_TRUE) }.
Plan is valid:false

Can you confirm these errors?

Error while parsing domain with action costs

I have this code in my domain file:

    (:functions (total-cost) - number)

    (:predicates
        ;...

When trying to solve problems with Aquaplanning I get this error:

Parsing...
line 28:5 no viable alternative at input '(:predicates'
Parsing error in domain.pddl at (line 26, col. 31) until (line 26, col. 31):
Unrecognized or illegal token "(".

Expose faulty element when AST Parsing throws an Exception

So, I'm generally new to planning, so I probably ran a faulty domain file, but it passed the parser stage and crashed during AST Walking.

Now it's hard to see which statement caused the error and thus (if possible) it would be awesome to have a resolution from AST Element -> Source Line/Column. In it's current state I only know that my "FHead" is missing some types, but unfortunately that doesn't help me much.

For reference, here's the problem:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
        at java.util.ArrayList.rangeCheck(ArrayList.java:657)
        at java.util.ArrayList.get(ArrayList.java:433)
        at edu.kit.aquaplanning.parsing.ProblemParser.enterFHead(ProblemParser.java:996)
        at edu.kit.aquaplanning.parsing.PddlHtnParser$FHeadContext.enterRule(PddlHtnParser.java:3247)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.enterRule(ParseTreeWalker.java:42)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:25)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
        at edu.kit.aquaplanning.parsing.ProblemParser.parse(ProblemParser.java:173)
        at edu.kit.aquaplanning.Main.main(Main.java:98)

Domain:

; Numeric planning in practice is rather limited, because planners are limited, even though the spec is not.
; One of these issues is the cost optimization. For Fast-Downward, the cost metric needs to be called "total-cost"
; This domain used "total-distance" before, but apparently that is as illegal as using ":fluents" in the requirements
(define (domain mail)
    (:requirements :typing :negative-preconditions :equality :action-costs) ; Other synonyms for action costs  :numeric-fluents :fluents :action-costs)

    (:types location - object
            letter - object
    )

    (:constants mailbox - location)

    (:predicates
        (at ?l - location); If the Salesman is at the given location
        (canDropAt ?let - letter ?loc - location) ; Can the given letter be dropped at the location loc.
        ; this even allows us to drop letters at various locations
        (deliver ?let - letter) ; Used for the goal "deliver all letters".
        (batched ?let - letter) ; TODO: Use to simulate the stack.
    )

    (:functions
        (distance ?from ?to) - number
        ; Fast-Downward accepted (batch-count) without anything, but this seems to be the official form.
        (batch-count) - number
        (total-cost) - number
    )

    (:action goto
        :parameters (?from - location ?to - location)
        :precondition (and
            (at ?from)
            (not(at ?to)) ; Prevent useless loops/from == to
        )
        :effect (and
            (at ?to)
            (not (at ?from))
            (increase (total-cost) (distance ?from ?to))
        )
    )

    ; This is explicitly modelled, so that we can model things like recharging pauses
    ; TODO: Currently there is no modelling of the stack content, and as such, this method won't be used yet.
    ; The Planner has no reason to pick up letters.
    (:action pickup
        :parameters (?let - letter)
        :precondition (and
            (at mailbox)
            ; TODO: The following line is not supported by fast downward
            (<= (batch-count) 5)
        )
        :effect (and
            ; TODO: The following line is not supported by fast downward
            (increase (batch-count) 1)
        )
    )

    (:action drop
        :parameters (?let - letter ?loc - location)
        :precondition (and
            (at ?loc)
            (canDropAt ?let ?loc)
            ; TODO: The following line is not supported by fast downward
            (> (batch-count) 0)
        )
        :effect (and
            (deliver ?let)
            ; TODO: The following line is not supported by fast downward
            (decrease (batch-count) 1)
        )
    )
)

Thanks in Advance!

Converting a state into a goal

I have a problem maybe somebody can help me with:
Given a GroundPlanningProblem and a State instance, I want to convert the State into a new Goal instance, using all atoms. My approach was getting the atom values by using the State.getAtoms() method. For each of the values, I need to build an Atom instance, so I just used the index in the atoms list as the ID because that seemed to be right. For the name, I first used just an empty string, but this didn't work in all cases. So I wanted to use the GroundPlanningProblem.getAtomNames() method, but it turned out that this list is smaller than the one returned by State.getAtoms(). I don't really understand how this can be. Maybe you could explain it?
But most importantly: Could you maybe explain how one can convert a State into a Goal instance?

SatSolver getters

Hi, this is not an issue, more a pull request without code. Could you provide getters for the solver and model attributes in the SatSolver class? Or at least make these attributes protected? It would be less hacky to extend the SatSolver with some functions if we could access those attributes directly. Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.