idrave / FOND-ASP

5 stars 1 forks source link

FOND-ASP: FOND+ via ASP

This repo contains the FOND-ASP planner reported in:

The FOND-ASP planning system is able is able to solve FOND+ planning problems: FOND problems with explicit conditional fairness conditions. This includes dual FOND problems (fair and unfair actions) and QNP, all integrated.

The FOND-ASP is written in Answer Set Programming (ASP) using ASP Clingo system.

Setup

To run the system, you will need to have Clingo installed. In Potassco webpage you can find information about how to set it up. The recommended installation is through a Conda environment running:

$ conda install -c potassco clingo

Independently of the setup method used, you should be able to run from command line:

$ clingo -h

Having Clingo installed, you can get and setup FOND-ASP as follows:

$ git clone https://github.com/idrave/fond-asp.git
$ cd fond-asp
$ pip install -r requirements.txt

Finally, install the planner as an editable project:

$ pip install -e .  # install as editable project as per setup.py

Effectively this adds the folder to sys.path variable which is used by Python to search for modules. This means you can now use/run the planner from anywhere, as it is installed as a packge, and any change in the source of the planner will be seen automatically.

For example:

$ python -m fcfond.main -h
usage: main.py [-h] [-list [LIST]] [-pddl PDDL [PDDL ...]] [-clingo CLINGO [CLINGO ...]] [-out OUT] [-log] [-notrack] [-stats]
               [-planner PLANNER | --fondp | --fondpshow | --fondpnoshow | --strong | --strongcyclic | --dual | --index] [-k K] [--expgoal] [--atoms] [-n N] [-t T]
               [-timeout TIMEOUT] [-memout MEMOUT]
               [experiments [experiments ...]]
...

You can check it has been installed as follows:

$ pip ip freeze | grep fond
-e git+git@github.com:idrave/FOND-ASP.git@a1777855e1b31723601490f0522b704adc39afd0#egg=fcfondplanner

To remove the package:

$ pip uninstall fcfondplanner

Using a Python Pipenv environment

You might want to apply the above steps inside an independent python environment. Here is one way using Pipenv.

First install Clingo, by compiling and installing it via CMAKE as per instructions.

Next, install FOND-ASP and setup a Python environment:

$ git clone git@github.com:idrave/FOND-ASP.git
$ pipenv shell  // create a new environment
(fond-asp) $

Pipenv would have created a new environment, here named "fond-asp".

Next, install in the environment the dependencies stored in Pipfile:

$ pipenv install

Note that Pipfile makes reference to the fond-asp repo via the git@ protocol, so we require ssh authentication to GitHub for this to work (so that Pipenv will be able to bring the dependency from the repo).

After this, all the dependencies would have been downloaded and stored them under a folder like ~/.local/share/virtualenvs/aspplanner-HxHD4kSc

There is one more thing that needs to be installed: the Python Clingo component into the recently created Pipenv environment. When Clingo was installed, its Python component where installed under the users' path ~/.local/lib/python3.8/site-packages/. This include a clingo.cpython-38-x86_64-linux-gnu.so file and clingo/ folder; copy them both to your Pipenv environment:

$ cp -a ~/.local/lib/python3.8/site-packages/clingo  ~/.local/share/virtualenvs/fond-asp.git-HxHD4kSc/lib/python3.8/site-packages/

Now clingo is part of the Pipenv environment, and all is ready to run.

PDDL and ASP specifications of FOND+ problems

PDDL specifications

To specify a FOND+ task, the PDDL is extended to allow the specification of conditional fairness.

A fairness expression allow to define PDDL problems with custom fairness assumptions for the FOND-ASP planner and has the form:

((:fairness :a ...  :b ...)

where the ground actions following :a and :b represent the sets of actions A and B, respectively, describing a FOND+ constraint [A, B]: if any action in A is applied infinitely often in a state, all its effects will ensue infinitely often along that state, provided all the actions in B are executed finitely often.

For example:

(:fairness
        :a (go-right up) (go-right center) (go-right down)
        :b (go-left up) (go-left center) (go-left down)))

Note that the fairness constraints should mention only ground actions. So, when operators have arguments, the relevant grounded instances must be listed in the fairness constraints. For example:

 (:fairness
        :a (go-right p1) (go-right p2) (go-right p3)
        :b (go-left p1) (go-left p2) (go-left p3)))

which is equivalent to:

 (:fairness
        :a (go-right p1) (go-right p2) (go-right p3)
        :b (go-left p1) (go-left p2) (go-left p3)))
 (:fairness
        :a (go-right p2)
        :b (go-left p1) (go-left p2) (go-left p3)))
 (:fairness
        :a (go-right p3)
        :b (go-left p1) (go-left p2) (go-left p3)))

To specify fairness constraints where B is empty, the :b section is fully omitted:

(:fairness
        :a (go-up down p3 p2)
           (go-up p3 p2 p1)
           (go-up p2 p1 up)
           (go-down up p1 p2)
           (go-down p1 p2 p3)
           (go-down p2 p3 down))

ASP Encoding

It is also possible to specify a FOND+ problem directly in ASP format, by means of a set of facts using the following distinguished atoms:

In fact, when the system receives (extended) PDDL files, the problem is first translated to an ASP encoding using the above atoms. The id/2 predicate is used to describe the states and actions assigned to each identifier (genearlly an integer). If no name is associated to an id, then the id is used as name.

For example, here is a linear problem with four states and one two non-deterministic actions, with just c being fair and usable to achieve the goal:

% A linear problem with 2 non-deterministic actions
%
% (1) --a--> 2 --b--> 3 --c/d--> [4]
%            ^        |
%            |       c/d
%            |        |
%             --------
%
%  Plan should be
%       plan(1,a) plan(2,b) plan(3,d)
%
%  in the last step, only d is good
%       action c cannot be used as it is not guaranteed to be fair in the precense of b

state(1;2;3;4).
action(a;b;c;d).

transition(1,a,2).
transition(2,b,3).
transition(3,c,4).
transition(3,c,2).
transition(3,d,4).
transition(3,d,2).

initialState(1).
goal(4).

id(action(a), a).
id(action(b), b).
id(action(c), c).
id(action(d), d).

id(state(1), 1).
id(state(2), 2).
id(state(3), 3).
id(state(4), 4).

% c is fair without B
con_A(c, 1).
con_B(b, 1).

% d is always fair
con_A(d, 2).

The output of a solver should be atoms policy(S, A) specifying the action A to be applied in state S. In our sample experiments, the states and actions are represented as integers. To make the output more human readable, one can include the following rule in our program:

#show policy(State, Action): policy(IdS, IdA), id(state(State), IdS), id(action(Action), IdA), reach(IdS).

Running FOND-ASP

Once installed as an editable module, we can execute the planner by using -m fcfond.main from anywhere:

$ python -m fcfond.main -h

The most common way to use the planner to solve FOND+ tasks is by running it over input PDDL files as follows:

$ python -m fcfond.main -pddl DOMAIN PROBLEM

where DOMAIN and PROBLEM are the PDDL files encoding the planning domain and problem to be solved.

For example, to solve the 7th problem of the Doors benchmark using the default FOND+ solver implemented in fcfond/planner_clingo/fondplus_show_pretty.lp, show the statistics (-stats), and leave the result files under folder output.fondasp/:

$ python -m fcfond.main -stats -out output.doors -pddl domains/pddl/fond-sat/doors/domain.pddl domains/pddl/fond-sat/doors/p07.pddl

Namespace(atoms=False, clingo=None, experiments=[], expgoal=False, k=None, list=None, log=False, memout=8000000000.0, n=1, notrack=False, out='output.doors', pddl=['domains/pddl/fond-sat/doors/domain.pddl', 'domains/pddl/fond-sat/doors/p07.pddl'], planner=None, stats=True, t=1, timeout=1800.0)
Pddl processed. Start ASP solver.
Command ['clingo', PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/fondplus_show_pretty.lp'), 'output.doors/proc_p07.lp', '-n', '1', '-t', '1', '--single-shot']
ASP Solved. Processing output
Output processed.
Problem: p07
States: 1530
Actions: 16
Pre-processing time: 2.479
Sat: True
Models: 1
Calls: 1
Time: 14.368
Solve Time: 0.07
1st Model Time: 0.05
Unsat Time: 0.02
CPU Time: 13.674
Result: True
Max Memory: 628.512

  Problem  States  Actions  Pre-processing time   Sat Models  Calls    Time  Solve Time  1st Model Time  Unsat Time  CPU Time Result  Max Memory
0     p07    1530       16                2.479  True      1      1  14.368        0.07            0.05        0.02    13.674   True     628.512

In this example, the solution will amount to a strong plan because no conditional fairness pairs have been specified. See below to use a specialized version that will solve it much faster.

When given a PDDL file as above, the system will run in two phases. In the first phase, the PDDL is translated into an ASP flat encoding of the state space. By default, the number of states encoded is incrementally tracked and reported; that can be switched off via -notrack. In the second phase, the encoded flat representation of the PDDL problem is solved against a FOND+ planner solver (or a specialized one if option -planner is used).

After execution, the planner will leave the following files in the output folder (output/ by default, but can be specified via option -out):

When using option -stats as above, stats will be reported including various time statistics:

There are two major aspects that can be changed in the above default use of FOND-ASP:

  1. Specify a specialized planner solver via option -planner. There are a few of these planners available.
  2. Run the system directly on a Clingo ASP flat encoding of the planning task via option -clingo. This will save the pre-processing time of converting the PDDL specification into an ASP flat encoding.

Planners/Solvers available

The default FOND+ system of the planner uses ASP planner program fcfond/planner_clingo/fondplus_pretty.lp, which pretty prints the policy found as rules N: S A. This solver takes a FOND+ problem, including conditional fairness specifications.

We can specify alternative planner solvers via the option --planner PLANNER. The deafult system is equivalent to running:

$ python -m fcfond.main -planner fcfond/planner_clingo/fondplus_show_pretty.lp -pddl DOMAIN PROBLEM

The core program for FOND+ is located on file fcfond/planner_clingo/fondplus_core.lp. If called directly, all the model will be reported. A couple of wrappers on top of it are defined with different printing styles:

Specialized planners are provided in fcfond/planner_clingo/specialized to solve FOND problems under the two standard semantics: strong plans under adversarial semantics and strong-cyclic plans under state-action fairness, as well as dual-FOND (mixing adversarial and fair actions). The benchmark from the FOND-SAT planning system are included in this repo under domains/pddl/fond-sat/. See details of these planners below.

Incomplete planner versions are provided in folder fcfond/planner_clingo/incomplete.

Finally, two more special planners are available:

Pure Strong under adversarial semantics

The ASP program fcfond/planner_clingo/specialized/planner_strong.lp provides a specialized planner under pure strong planning under adversarial semantics for non-determinism. Solutions are conditional plans where the length of each run to the goal is bounded in advanced.

The use of this solver can be activated by using option --strong directly:

$ python -m fcfond.main --strong -pddl DOMAIN PROBLEM 

This is equivalent to running:

$ python -m fcfond.main --planner fcfond/planner_clingo/specialized/planner_strong.lp -pddl DOMAIN PROBLEM

For example, if we re-run the above problem 7 of Doors with this specialized solver:

$ python -m fcfond.main --strong -stats -out output.doors -pddl domains/pddl/fond-sat/doors/domain.pddl domains/pddl/fond-sat/doors/p07.pddl
Namespace(atoms=False, clingo=None, experiments=[], expgoal=False, k=None, list=None, log=False, memout=8000000000.0, n=1, notrack=False, out='output.doors', pddl=['domains/pddl/fond-sat/doors/domain.pddl', 'domains/pddl/fond-sat/doors/p07.pddl'], planner=PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/specialized/planner_strong.lp'), stats=True, t=1, timeout=1800.0)
Pddl processed. Start ASP solver.
Command ['clingo', PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/specialized/planner_strong.lp'), 'output.doors/proc_p07.lp', '-n', '1', '-t', '1', '--single-shot']
ASP Solved. Processing output
Output processed.
Problem: p07
States: 1530
Actions: 16
Pre-processing time: 2.311
Sat: True
Models: 1+
Calls: 1
Time: 0.375
Solve Time: 0.0
1st Model Time: 0.0
Unsat Time: 0.0
CPU Time: 0.366
Result: True
Max Memory: 62.188

  Problem  States  Actions  Pre-processing time   Sat Models  Calls   Time  Solve Time  1st Model Time  Unsat Time  CPU Time Result  Max Memory
0     p07    1530       16                2.311  True     1+      1  0.375         0.0             0.0         0.0     0.366   True      62.188

Observe this takes significantly less than when the full FOND+ solver has been used as per above.

Importantly, when this specialization is used, no (:fairness ) statements are required, as the semantics is already fixed in the planner used (as adversarial semantics).

Nonetheless, one can still solve strong standard FOND planning problems by just running the default FOND+ planner solver on the original (non-deterministic) PDDL files with no (:fairness :a ... b: ...) clauses: every non-determinism is assumed of adversarial type.

Pure Strong-cyclic under state-fair semantics

A specialized planner for solving FOND problem under the state-action fairness assumption, and under which plans are strong-cyclic policies, is provided by ASP program fcfond/planner_clingo/specialized/planner_strongcyclic.lp

So, to solve a FOND problem using the specialized planner for pure strong-cyclic planning (state-action fairness) semantics we can use the --strongcyclic option:

$ python -m fcfond.main --strongcyclic -pddl DOMAIN PROBLEM 

which is equivalent to:

$ python -m fcfond.main --planner fcfond/planner_clingo/specialized/planner_strongcyclic.lp -pddl DOMAIN PROBLEM 

For example:

$ python -m fcfond.main --strongcyclic -stats -pddl domains/pddl/fond-sat/beam-walk/domain.pddl domains/pddl/fond-sat/beam-walk/p01.pddl

Pddl processed. Start ASP solver.
Command ['clingo', PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/specialized/planner_strongcyclic.lp'), 'output/proc_p01.lp', '-n', '1', '-t', '1', '--single-shot']
ASP Solved. Processing output
Output processed.
Problem: p01
States: 8
Actions: 7
Pre-processing time: 0.007
Sat: True
Models: 1+
Calls: 1
Time: 0.002
Solve Time: 0.0
1st Model Time: 0.0
Unsat Time: 0.0
CPU Time: 0.002
Result: True
Max Memory: 38.232

  Problem  States  Actions  Pre-processing time   Sat Models  Calls   Time  Solve Time  1st Model Time  Unsat Time  CPU Time Result  Max Memory
0     p01       8        7                0.007  True     1+      1  0.002         0.0             0.0         0.0     0.002   True      38.232

As with strong planning, when this specialization is used, no (:fairness ) statements are required, as the semantics is already fixed in the planner used (as adversarial semantics).

Nonetheless, one can still solve standard strong-cyclic FOND problems by just running the default FOND+ planner solver on the original (non-deterministic) PDDL files extended to include corresponding fairness constraints for each non-deterministic ground action a of the form [A={a},B=empty]. This means one (:fairness :a GROUND_ACTION) for each ground action in the problem needs to be included.

Dual FOND: mix of adversarial and fair actions

Finally, a specialized planner for Dual-FOND planning is provided in fcfond/planner_clingo/specialized/dualfond.lp. This planner solver can be directly activated by using option --dual.

This is a conditional planner for Dual-FOND problems, where some actions are adversarial and other actions are fair (in all states).

The fair actions must be indicated in the PDDL description of the problem using (:fairness :a GROUND_ACTION) clauses. Any action not appearing in any such clause will be assumed to be adversarial.

Running against an ASP encoding

While the above examples make use of PDDL specifications (as domain and problem .pddl files), it is also possible to directly specify a problem encoded via a collection of ASP facts (see above) above using option --clingo.

For example:

$ python -m fcfond.main -clingo domains/clingo/clear.lp -out output.clear
['clingo', PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/fondplus.lp'), 'domains/clingo/clear.lp', '-n', '1', '-t', '1']
Status:  Finished

The results will be left in folder clear/.

NOTE: Since when given a PDDL encoding, the FOND-ASP system will translate it to an ASP encoding, one could use that encoding later on; for example:

$ python -m fcfond.main -clingo output/proc_p01.lp

Finally, at the extreme, one can directly use the Clingo solver to run a particular planner directly on a particular ASP encoding of a problem:

$ clingo PLANNER DOMAIN

In this case, no planner and no specific encoding provided in this repo will be used. For example:

$ python -m fcfond.main --strongcyclic -out output.beamwalk -pddl domains/pddl/fond-sat/beam-walk/domain.pddl domains/pddl/fond-sat/beam-walk/p01.pddl

$ clingo fcfond/planner_clingo/specialized/planner_strongcyclic.lp output.beamwalk/proc_p01.lp

clingo version 5.5.1 (47cb64b)
Reading from ...go/specialized/planner_strongcyclic.lp ...
Solving...
Answer: 1
policy("<next-fwd(p0,p1),next-fwd(p1,p2),next-fwd(p2,p3),next-bwd(p1,p0),next-bwd(p2,p1),next-bwd(p3,p2),ladder-at(p0),position(p0)>","climb(p0)") policy("<next-fwd(p0,p1),next-fwd(p1,p2),next-fwd(p2,p3),next-bwd(p1,p0),next-bwd(p2,p1),next-bwd(p3,p2),ladder-at(p0),position(p0),up()>","walk-on-beam(p0,p1)") policy("<next-fwd(p0,p1),next-fwd(p1,p2),next-fwd(p2,p3),next-bwd(p1,p0),next-bwd(p2,p1),next-bwd(p3,p2),ladder-at(p0),position(p1),up()>","walk-on-beam(p1,p2)") policy("<next-fwd(p0,p1),next-fwd(p1,p2),next-fwd(p2,p3),next-bwd(p1,p0),next-bwd(p2,p1),next-bwd(p3,p2),ladder-at(p0),position(p1)>","walk(p1,p0)") policy("<next-fwd(p0,p1),next-fwd(p1,p2),next-fwd(p2,p3),next-bwd(p1,p0),next-bwd(p2,p1),next-bwd(p3,p2),ladder-at(p0),position(p2),up()>","walk-on-beam(p2,p3)") policy("<next-fwd(p0,p1),next-fwd(p1,p2),next-fwd(p2,p3),next-bwd(p1,p0),next-bwd(p2,p1),next-bwd(p3,p2),ladder-at(p0),position(p2)>","walk(p2,p1)") policy("<next-fwd(p0,p1),next-fwd(p1,p2),next-fwd(p2,p3),next-bwd(p1,p0),next-bwd(p2,p1),next-bwd(p3,p2),ladder-at(p0),position(p3)>","walk(p3,p2)")
SATISFIABLE

Models       : 1+
Calls        : 1
Time         : 0.003s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.003s

Running the experiments

To run the built-in set of experiments using the FOND-ASP planner for FOND+ dual problems use:

$ python -m fcfond.main EXPERIMENTS -out OUTPUT

Where EXPERIMENTS is one or more available experiments for the planner. Some available experiments and sub-experiments (which can also be run independently) are:

To get a list of more available experiments type

$ python -m fcfond.main -list [LIST]

Where LIST can be one of the experiment lists above.

The results will be left under folder OUTPUT and will include:

Here is an example running the QNP problems:

$ python -m fcfond.main qnp
qnp
['clear_qnp', 'on_qnp', 'gripper_qnp', 'delivery_qnp']
clear_qnp
Pddl processed
['clingo', PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/fondplus.lp'), 'output/qnp/all/proc_clear.lp', '-n', '1', '-t', '1']
Status:  Finished
on_qnp
Pddl processed
['clingo', PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/fondplus.lp'), 'output/qnp/all/proc_on.lp', '-n', '1', '-t', '1']
Status:  Finished
gripper_qnp
Pddl processed
['clingo', PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/fondplus.lp'), 'output/qnp/all/proc_gripper.lp', '-n', '1', '-t', '1']
Status:  Finished
delivery_qnp
Pddl processed
['clingo', PosixPath('/home/ssardina/git/soft/planning/FOND/FOND-ASP.git/fcfond/planner_clingo/fondplus.lp'), 'output/qnp/all/proc_delivery.lp', '-n', '1', '-t', '1']
Status:  Finished