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.
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
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.
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))
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:
state(S)
: S
is a state (where S
is just an id, e.g., an integer or atom)initialState(S)
: S
is the initial stategoal(S)
: S
is a goal stateaction(A)
: A
is an actiontransition(S1, A, S2)
: there is a transition from state S1
to state S2
applying action A
con_A(A, I)
: action A
belongs to set of constraints A_I
con_B(A, I)
: action A
belongs to set of constraints B_I
id(state(N), S)
: N
is the description name (atom/integer/string) of state with id S
(atom/term/integer).id(action(N), A)
: N
is the description name (atom/integer/string) of action with id A
(atom/term/integer).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).
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
):
proc_p07.lp
: the full planning problem encoded as a set of ASP facts; see below for atoms used. This can be re-used to run the planner directly on this encoding and avoid a re-encoding.stdout-encode.txt
: the standard output of the encoding phase from PDDL to ASP.stdout-asp.txt
: the standard output of the ASP solver, which shows a successful policy, if any has been found, via atoms policy(S, A)
specifying the action A
to be applied in state S
.metrics.csv
: the statistic of the solving task (e.g., time, no of models, etc.).When using option -stats
as above, stats will be reported including various time statistics:
Pre-processing Time
: time FOND-ASP took to pre-process the input before sending it to ASP solver.Time
: total time that Clingo ASP system took to run, as reported in stdout-asp.txt
by Clingo itself. This includes Clingo pre-processing, grounding, and solving time of the input ASP.CPU Time
: Clingo solve time considering all threads used. When only one thread is used, it should equal Time
.Solve Time
: time that took Clingo took to just solve the problem, without considering Clingo's pre-procesing and grounding.1st Model Time
: time it took Clingo to find the first solution model.There are two major aspects that can be changed in the above default use of FOND-ASP:
-planner
. There are a few of these planners available.-clingo
. This will save the pre-processing time of converting the PDDL specification into an ASP flat encoding.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:
fcfond/planner_clingo/fondplus_noshow.lp
: silent solver, nothing is reported; just result.fcfond/planner_clingo/fondplus_show_simple.lp
: only the plan/2
predicate is show, which represents policy/2
in the core solver, but with the states and actions id translated, if available via predicate id/2
.fcfond/planner_clingo/fondplus_show_pretty.lp
: besides reporting the plan/2
interface predicate, the policy is printed formatted for human readability. This relies on Clingo Python-API to extract, process, and print models.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:
fcfond/planner_clingo/fondplus_multi.lp
: a simple example how we can solve it in multi-shot fashion, by solving the problem first, and then grouding the plan/2
predicate. Seems to run faster in some cases.fcfond/planner_clingo/fondp_index.lp
is a bounded version of the FOND+ solver that uses a bound k
on the grounding of the program to limit the recursive procedure searching for terminating states. Such bound can be specified using command line option -k N
, where N
is a positive integer. Note that this planner may not find a valid policy if the bound is too low for the problem being solved.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.
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.
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.
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
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:
qnp
clear_qnp
on_qnp
gripper_qnp
delivery_qnp
ltl
list
double-list
tree
graph
minlist
member-tree
swamp
foot
footXX
, for an odd XX
from 03
to 21
sequential
sequential
sequential
sequentialXX
, for XX
from 02
to 10
nested
nestedXX
, for XX
from 02
to 10
unfair_qnp
: QNPs without terminating solutionfond_sat
: several domains of pure strong and pure strong cyclic planningTo 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:
stdout.txt
: file containing the standard output given by Clingo solver when run over the domains. This shows the resulting policy, among other types of information.metrics.csv
: contains a summary of several performance metrics..lp
files with Clingo symbols corresponding to the input domains.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