Issue517

Title Add ability of translate to output of PDDL files for debugging purpose
Priority wish Status resolved
Superseder Nosy List gabi, jendrik, kcleung, malte
Assigned To kcleung Keywords
Optional summary

Created on 2015-03-13.01:44:59 by kcleung, last changed by malte.

Messages
msg4085 (view) Author: malte Date: 2015-03-17.22:04:00
(PS: Please leave the tracker status fields for our use. The "priority" and
"status" fields serve a particular purpose internally.)
msg4084 (view) Author: malte Date: 2015-03-17.22:02:00
> The typed_list_to_string function aims at grouping different parameters with
> same type together when printing PDDL in the :types section.  For example:
> a - Foo  b - Foo c - Foo
>
> will become:
>
> a b c - Foo

I see. In the future, if you need something like this, check out
itertools.groupby in the Python standard library.
msg4083 (view) Author: malte Date: 2015-03-17.22:00:15
> First of all, I do intend to give a PDDL representation of the final transformed
> task.  The only reason I invoke the PDDL dump before the transformation is to
> make sure my dump code is working, then I still call it after the
> transformation.  Therefore it should still serve import purpose for many people.

The task after grounding and PDDL conversion uses different classes from the
ones that your code worked on. It is a completely different representation, so
your methods will not be useful for printing the result of that conversion. The
PDDL representation is only used on the input side of the translator, not on the
output side.
msg4082 (view) Author: kcleung Date: 2015-03-17.21:51:20
First of all, I do intend to give a PDDL representation of the final transformed
task.  The only reason I invoke the PDDL dump before the transformation is to
make sure my dump code is working, then I still call it after the
transformation.  Therefore it should still serve import purpose for many people.

Also I have successfully fixed the predicate argument reordering bug and pushed
into my branch.  Could you please have a look at:


https://bitbucket.org/kcleung/hg.fast-downward.org/branch/translate-writeout-pddl

If my code behaves correctly, I am sure that it will be very useful for others
to have a PDDL representation of the transformed code.



The typed_list_to_string function aims at grouping different parameters with
same type together when printing PDDL in the :types section.  For example:

a - Foo  b - Foo c - Foo

will become:

a b c - Foo

Thank you very much for raising the problem of the use of typed_list_to_string
to me.  I will remove its use in all places except the :types and :objects section.
msg4078 (view) Author: malte Date: 2015-03-17.15:47:57
I had a look at your code and added some small comments directly in bitbucket.
(Don't know if you received notifications automatically.)

The reason for the reordering of predicate names is your function
typed_list_to_string, which returns the argument in an unpredictable order based
on iterating over a dictionary (which has no well-defined order, similar to
unordered_map in C++). Generally speaking, the grouping of related arguments
that typed_list_to_string performs can only work if you also do exactly the same
reordering in all uses of the same kind of object.  It's not clear to me what
typed_list_to_string wants to accomplish (or why it is enough to handle direct
basetypes but not all supertypes), but reordering arguments in this way sounds
like a dangerous idea to in general and shouldn't be the default behaviour of
what is essentially a dump method.

Independently of the current bug, thanks for offering up the code, but I think
we wouldn't integrate it in the medium term. I initially misunderstood what is
dumped: I thought it would be a PDDL representation of the final transformed
(SAS+) task, which I think many people would be interested in. But dumping the
PDDL code before there have been significant transformations is less useful, and
for now, I think we don't want to take on the maintenance burden. (We hope to
make some structural changes to the translator in the not-too-far future, and
for this I think it's easier if we don't need to maintain the new code.) After
this change, we might revisit this.

(Closing this to remove it from our TODO list, but feel free to continue the
discussion.)
msg4066 (view) Author: florian Date: 2015-03-17.09:11:50
Sorry, I don't have any free capacity left to work on this right now, so I'm
taking myself off the nosy list.
msg4065 (view) Author: kcleung Date: 2015-03-17.02:55:59
I have implemented the PDDL unparser feature in translate:

https://bitbucket.org/kcleung/hg.fast-downward.org/branch/translate-writeout-pddl

and I have tested with:

./translate.py --writeout_reformulated_pddl 
../../benchmarks/barman-opt11-strips/domain.pddl
../../benchmarks/barman-opt11-strips/pfile01-001.pddl

Could you please have a look?

Currently, the problem is that when printing the predicates in domain.pddl, the
order of arguments within a predicate is not preserved.  How can I make sure the
order of arguments in a predicate is always preserved?

The input domain.pddl:

(define (domain barman)
  (:requirements :strips :typing :action-costs)
  (:types hand level beverage dispenser container - object
  	  ingredient cocktail - beverage
          shot shaker - container)
  (:predicates  (ontable ?c - container)
                (holding ?h - hand ?c - container)
		(handempty ?h - hand)
		(empty ?c - container)
                (contains ?c - container ?b - beverage)
		(clean ?c - container)
                (used ?c - container ?b - beverage)
                (dispenses ?d - dispenser ?i - ingredient)
		(shaker-empty-level ?s - shaker ?l - level)
		(shaker-level ?s - shaker ?l - level)
		(next ?l1 ?l2 - level)
		(unshaked ?s - shaker)
		(shaked ?s - shaker)
                (cocktail-part1 ?c - cocktail ?i - ingredient)
                (cocktail-part2 ?c - cocktail ?i - ingredient))

(:functions (total-cost) - number)
		
  (:action grasp
             :parameters (?h - hand ?c - container)
             :precondition (and (ontable ?c) (handempty ?h))
             :effect (and (not (ontable ?c))
	     	     	  (not (handempty ?h))
			  (holding ?h ?c)
			  (increase (total-cost) 1)))

  (:action leave
             :parameters (?h - hand ?c - container)
             :precondition (holding ?h ?c)
             :effect (and (not (holding ?h ?c))
	     	     	  (handempty ?h)
			  (ontable ?c)
			  (increase (total-cost) 1)))
  
  (:action fill-shot
           :parameters (?s - shot ?i - ingredient ?h1 ?h2 - hand ?d - dispenser)
           :precondition (and (holding ?h1 ?s)
                              (handempty ?h2)
	   		      (dispenses ?d ?i)
                              (empty ?s)
			      (clean ?s))
           :effect (and (not (empty ?s))
	   	   	(contains ?s ?i)
	   	   	(not (clean ?s))
			(used ?s ?i)
			(increase (total-cost) 10)))


  (:action refill-shot
           :parameters (?s - shot ?i - ingredient ?h1 ?h2 - hand ?d - dispenser)
           :precondition (and (holding ?h1 ?s)	   		      
                              (handempty ?h2)
	   		      (dispenses ?d ?i)
                              (empty ?s)
			      (used ?s ?i))
           :effect (and (not (empty ?s))
                        (contains ?s ?i)
			(increase (total-cost) 10)))

  (:action empty-shot
           :parameters (?h - hand ?p - shot ?b - beverage)
           :precondition (and (holding ?h ?p)
                              (contains ?p ?b))
           :effect (and (not (contains ?p ?b))
	   	   	(empty ?p)
			(increase (total-cost) 1)))

  (:action clean-shot
  	   :parameters (?s - shot ?b - beverage ?h1 ?h2 - hand)
           :precondition (and (holding ?h1 ?s)
                              (handempty ?h2)	   		      
			      (empty ?s)
                              (used ?s ?b))
           :effect (and (not (used ?s ?b))
	   	   	(clean ?s)
			(increase (total-cost) 1)))

  (:action pour-shot-to-clean-shaker
           :parameters (?s - shot ?i - ingredient ?d - shaker ?h1 - hand ?l ?l1
- level)
           :precondition (and (holding ?h1 ?s)
			      (contains ?s ?i)
                              (empty ?d)
	   		      (clean ?d)                              
                              (shaker-level ?d ?l)
                              (next ?l ?l1))
           :effect (and (not (contains ?s ?i))
	   	   	(empty ?s)
			(contains ?d ?i)
                        (not (empty ?d))
			(not (clean ?d))
			(unshaked ?d)
			(not (shaker-level ?d ?l))
			(shaker-level ?d ?l1)
			(increase (total-cost) 1)))


  (:action pour-shot-to-used-shaker
           :parameters (?s - shot ?i - ingredient ?d - shaker ?h1 - hand ?l ?l1
- level)
           :precondition (and (holding ?h1 ?s)
			      (contains ?s ?i)
                              (unshaked ?d)
                              (shaker-level ?d ?l)
                              (next ?l ?l1))
           :effect (and (not (contains ?s ?i))
                        (contains ?d ?i)
	   	   	(empty ?s)     
  			(not (shaker-level ?d ?l))
			(shaker-level ?d ?l1)
			(increase (total-cost) 1)))

  (:action empty-shaker
           :parameters (?h - hand ?s - shaker ?b - cocktail ?l ?l1 - level)
           :precondition (and (holding ?h ?s)
                              (contains ?s ?b)
			      (shaked ?s)
			      (shaker-level ?s ?l)
			      (shaker-empty-level ?s ?l1))
           :effect (and (not (shaked ?s))
	   	   	(not (shaker-level ?s ?l))
	   	   	(shaker-level ?s ?l1)
			(not (contains ?s ?b))
	   	   	(empty ?s)
			(increase (total-cost) 1)))

  (:action clean-shaker
  	   :parameters (?h1 ?h2 - hand ?s - shaker)
           :precondition (and (holding ?h1 ?s)
                              (handempty ?h2)
                              (empty ?s))
           :effect (and (clean ?s)
			(increase (total-cost) 1)))
  
  (:action shake
  	   :parameters (?b - cocktail ?d1 ?d2 - ingredient ?s - shaker ?h1 ?h2 - hand)
           :precondition (and (holding ?h1 ?s)
                              (handempty ?h2)
			      (contains ?s ?d1)
                              (contains ?s ?d2)
                              (cocktail-part1 ?b ?d1)
			      (cocktail-part2 ?b ?d2)
			      (unshaked ?s))			      
           :effect (and (not (unshaked ?s))
		        (not (contains ?s ?d1))
                        (not (contains ?s ?d2))
	   	   	(shaked ?s)
                        (contains ?s ?b)
			(increase (total-cost) 1)))

  (:action pour-shaker-to-shot
           :parameters (?b - beverage ?d - shot ?h - hand ?s - shaker ?l ?l1 -
level)
           :precondition (and (holding ?h ?s)
			      (shaked ?s)
			      (empty ?d)
			      (clean ?d)
			      (contains ?s ?b)
                              (shaker-level ?s ?l)
                              (next ?l1 ?l))
           :effect (and (not (clean ?d))
	   	   	(not (empty ?d))
			(contains ?d ?b)
			(shaker-level ?s ?l1)
			(not (shaker-level ?s ?l))
			(increase (total-cost) 1)))
 )


Output domain.pddl:

(define (domain barman)
(:requirements :action-costs :strips :typing)
(:types ingredient cocktail  - beverage hand level beverage dispenser container
 - object shot shaker  - container object  - None )
(:predicates   (ontable ?c  - container )
  (holding ?h  - hand ?c  - container )
  (handempty ?h  - hand )
  (empty ?c  - container )
  (contains ?b  - beverage ?c  - container )
  (clean ?c  - container )
  (used ?b  - beverage ?c  - container )
  (dispenses ?i  - ingredient ?d  - dispenser )
  (shaker-empty-level ?l  - level ?s  - shaker )
  (shaker-level ?l  - level ?s  - shaker )
  (next ?l1 ?l2  - level )
  (unshaked ?s  - shaker )
  (shaked ?s  - shaker )
  (cocktail-part1 ?i  - ingredient ?c  - cocktail )
  (cocktail-part2 ?i  - ingredient ?c  - cocktail )
  (= ?x ?y  - object )
)
:(functions   (total-cost) - number)
(:action grasp
  :parameters (?h - hand ?c - container)
:precondition (and (ontable ?c) (handempty ?h))

:effect (and   (not (ontable ?c))   (not (handempty ?h))   (holding ?h ?c)
(increase (total-cost ) 1)))
(:action leave
  :parameters (?h - hand ?c - container)
:effect (and   (not (holding ?h ?c))   (handempty ?h)   (ontable ?c)
(increase (total-cost ) 1)))
(:action fill-shot
  :parameters (?s - shot ?i - ingredient ?h1 - hand ?h2 - hand ?d - dispenser)
:precondition (and (holding ?h1 ?s) (handempty ?h2) (dispenses ?d ?i) (empty ?s)
(clean ?s))

:effect (and   (not (empty ?s))   (contains ?s ?i)   (not (clean ?s))   (used ?s ?i)
(increase (total-cost ) 10)))
(:action refill-shot
  :parameters (?s - shot ?i - ingredient ?h1 - hand ?h2 - hand ?d - dispenser)
:precondition (and (holding ?h1 ?s) (handempty ?h2) (dispenses ?d ?i) (empty ?s)
(used ?s ?i))

:effect (and   (not (empty ?s))   (contains ?s ?i)
(increase (total-cost ) 10)))
(:action empty-shot
  :parameters (?h - hand ?p - shot ?b - beverage)
:precondition (and (holding ?h ?p) (contains ?p ?b))

:effect (and   (not (contains ?p ?b))   (empty ?p)
(increase (total-cost ) 1)))
(:action clean-shot
  :parameters (?s - shot ?b - beverage ?h1 - hand ?h2 - hand)
:precondition (and (holding ?h1 ?s) (handempty ?h2) (empty ?s) (used ?s ?b))

:effect (and   (not (used ?s ?b))   (clean ?s)
(increase (total-cost ) 1)))
(:action pour-shot-to-clean-shaker
  :parameters (?s - shot ?i - ingredient ?d - shaker ?h1 - hand ?l - level ?l1 -
level)
:precondition (and (holding ?h1 ?s) (contains ?s ?i) (empty ?d) (clean ?d)
(shaker-level ?d ?l) (next ?l ?l1))

:effect (and   (not (contains ?s ?i))   (empty ?s)   (contains ?d ?i)   (not
(empty ?d))   (not (clean ?d))   (unshaked ?d)   (not (shaker-level ?d ?l))  
(shaker-level ?d ?l1)
(increase (total-cost ) 1)))
(:action pour-shot-to-used-shaker
  :parameters (?s - shot ?i - ingredient ?d - shaker ?h1 - hand ?l - level ?l1 -
level)
:precondition (and (holding ?h1 ?s) (contains ?s ?i) (unshaked ?d) (shaker-level
?d ?l) (next ?l ?l1))

:effect (and   (not (contains ?s ?i))   (contains ?d ?i)   (empty ?s)   (not
(shaker-level ?d ?l))   (shaker-level ?d ?l1)
(increase (total-cost ) 1)))
(:action empty-shaker
  :parameters (?h - hand ?s - shaker ?b - cocktail ?l - level ?l1 - level)
:precondition (and (holding ?h ?s) (contains ?s ?b) (shaked ?s) (shaker-level ?s
?l) (shaker-empty-level ?s ?l1))

:effect (and   (not (shaked ?s))   (not (shaker-level ?s ?l))   (shaker-level ?s
?l1)   (not (contains ?s ?b))   (empty ?s)
(increase (total-cost ) 1)))
(:action clean-shaker
  :parameters (?h1 - hand ?h2 - hand ?s - shaker)
:precondition (and (holding ?h1 ?s) (handempty ?h2) (empty ?s))

:effect (and   (clean ?s)
(increase (total-cost ) 1)))
(:action shake
  :parameters (?b - cocktail ?d1 - ingredient ?d2 - ingredient ?s - shaker ?h1 -
hand ?h2 - hand)
:precondition (and (holding ?h1 ?s) (handempty ?h2) (contains ?s ?d1) (contains
?s ?d2) (cocktail-part1 ?b ?d1) (cocktail-part2 ?b ?d2) (unshaked ?s))

:effect (and   (not (unshaked ?s))   (not (contains ?s ?d1))   (not (contains ?s
?d2))   (shaked ?s)   (contains ?s ?b)
(increase (total-cost ) 1)))
(:action pour-shaker-to-shot
  :parameters (?b - beverage ?d - shot ?h - hand ?s - shaker ?l - level ?l1 - level)
:precondition (and (holding ?h ?s) (shaked ?s) (empty ?d) (clean ?d) (contains
?s ?b) (shaker-level ?s ?l) (next ?l1 ?l))

:effect (and   (not (clean ?d))   (not (empty ?d))   (contains ?d ?b)  
(shaker-level ?s ?l1)   (not (shaker-level ?s ?l))
(increase (total-cost ) 1)))
msg4052 (view) Author: malte Date: 2015-03-13.14:09:25
I think this would be useful to have.

In general we have to look at code before we know if we can merge it (because it
has to fit the coding style and we must be happy with the implementation
strategy etc. because merging it means we have to maintain it in the future),
but in terms of the functionality this sounds interesting to me.

BTW, when you create a new issue, please feel free to add me to the nosy list
(like you did), but don't add others unless they tell you that they would like
to be added. Everybody at our group at Uni Basel receives a notification about
new issues, and if they are interested, they can add themselves to the nosy list.
msg4050 (view) Author: kcleung Date: 2015-03-13.01:46:09
The unparser will only be invoked by passing an argument at command line, so
will not affect performance
msg4049 (view) Author: kcleung Date: 2015-03-13.01:44:59
I am working with Dr Pat Riddle on a PDDL project.  In translate, we plan to
implement a few extra syntax checking passes and PDDL AST reformulation passes.
 Then we would like to have a flag which allows outputting PDDL files for
debugging purposes, to ensure the reformulation passes behave correctly.

I am now implementing the PDDL unparser, which will write out the domain and
task PDDL files from the AST in task.py.  I believe this will also be useful for
others. Therefore after I complete the unparser, would you guys like to
incorporate the unparser into the mercurial repository?

If so, the unparser is largely consist of pddl_str() for each abstract data type
(such as Action, Task, Condition etc).  I plan to add pddl_str() for each
relevant class, that return the correct PDDL string for that class.  How does
this sound?
History
Date User Action Args
2015-03-17 22:04:00maltesetmessages: + msg4085
2015-03-17 22:02:00maltesetstatus: in-progress -> resolved
priority: feature -> wish
messages: + msg4084
2015-03-17 22:00:15maltesetmessages: + msg4083
2015-03-17 21:51:20kcleungsetstatus: resolved -> in-progress
priority: wish -> feature
messages: + msg4082
2015-03-17 15:47:57maltesetstatus: in-progress -> resolved
priority: feature -> wish
messages: + msg4078
2015-03-17 09:12:36floriansetnosy: - florian
2015-03-17 09:11:50floriansetnosy: malte, gabi, jendrik, florian, kcleung
messages: + msg4066
2015-03-17 02:55:59kcleungsetmessages: + msg4065
2015-03-13 14:09:25maltesetmessages: + msg4052
2015-03-13 01:46:09kcleungsetmessages: + msg4050
2015-03-13 01:44:59kcleungcreate