Blocks-world PDDL Programmatic

Getting started

The framework is released as DLL file to be used on a Desktop platform, therefore it can be easily added and used in any Programmatic project.

Using EmbASP

In the following, we describe an actual usage of the framework by means of a running example; as a use case, we will develop a simple Desktop application to solve the blocks-world problem.

The complete code of this example is freely available here.

../_images/blocks-world.svg

We will make use of the annotation-guided mapping, in order to retrieve the actions constituting a PDDL plan via Programmatic objects.

To this purpose, the following classes are intended to represent possible actions that a blocks-world solution plan can feature:

[Id("pick-up")]
  class PickUp
  {
      [Param(0)]
      private string block;

      [...]
  }
[Id("put-down")]
  class PutDown
  {
      [Param(0)]
      private string block;

      [...]
  }
[Id("stack")]
  class Stack
  {
      [Param(0)]
      private string block1;

      [Param(1)]
      private string block2;

      [...]
  }
[Id("unstack")]
  class Unstack
  {
      [Param(0)]
      private string block1;

      [Param(1)]
      private string block2;

      [...]
  }

At this point, supposing that we are given two files defining the blocks-world domain and a problem instance, we can start deploying our application:

class Program
{
    static void Main(string[] args)
    {
        Handler handler = new DesktopHandler(new SPDDesktopService());

        InputProgram inputDomain = new PDDLInputProgram(PDDLProgramType.DOMAIN);
        inputDomain.AddFilesPath("domain.pddl");

        InputProgram inputProblem = new PDDLInputProgram(PDDLProgramType.PROBLEM);
        inputProblem.AddFilesPath("p01.pddl");

        handler.AddProgram(inputDomain);
        handler.AddProgram(inputProblem);

        try
        {
            PDDLMapper.Instance.RegisterClass(typeof(PickUp));
            PDDLMapper.Instance.RegisterClass(typeof(PutDown));
            PDDLMapper.Instance.RegisterClass(typeof(Stack));
            PDDLMapper.Instance.RegisterClass(typeof(Unstack));

            Plan plan = (Plan)handler.StartSync();

            foreach(object obj in plan.ActionsObjects)
            {
                if (typeof(PickUp).IsInstanceOfType(obj) || typeof(PutDown).IsInstanceOfType(obj) ||
                      typeof(Stack).IsInstanceOfType(obj) || typeof(Unstack).IsInstanceOfType(obj))
                {
                   Console.WriteLine(obj.ToString());
                }
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

The class contains an Handler instance as field, that is initialized with a DesktopHandler using the required parameter SPDDesktopService.

Then it’s set-up the input to the solver; since PDDL requires separate definitions for domain and problem, two PDDLInputProgram are created and then given to the handler.

The next lines inform the PDDLMapper about what classes are intended to map the output actions.

Finally the solver is invoked, and the output is retrieved.

The output actions can be managed accordingly to the user’s desiderata.


For further information, contact embasp@mat.unical.it or visit our website.