17. MA-PDDL I/O Example MA-Logistic

Open In GitHub Open In Colab

This notebook will show the possible interations between the ma-pddl language and the unified_planning usage.

17.1. Setup

We start by installing the library with PIP

[ ]:
!pip install --pre unified-planning[fmap]
[ ]:
from unified_planning.shortcuts import *
from unified_planning.model.multi_agent import *
from collections import namedtuple
from unified_planning.io.ma_pddl_writer import MAPDDLWriter


problem = MultiAgentProblem("ma-logistic")
truck1 = Agent("truck1", problem)
truck2 = Agent("truck2", problem)
airplane = Agent("airplane", problem)

object = UserType("object")
location = UserType("location", object)
vehicle = UserType("vehicle", object)
package = UserType("package", object)
city = UserType("city", object)
airport = UserType("airport", location)
truck_ = UserType("truck_", vehicle)
airplane_ = UserType("airplane_", vehicle)


pos = Fluent("pos", location=location)
at = Fluent("at", BoolType(), object=object, location=location)
In = Fluent("in", BoolType(), package=package, vehicle=vehicle)
on = Fluent("on", BoolType(), object=object)
in_city = Fluent("in_city", BoolType(), location=location, city=city)

truck1.add_public_fluent(pos, default_initial_value=False)
truck1.add_private_fluent(in_city, default_initial_value=False)
truck1.add_public_fluent(on, default_initial_value=False)
truck2.add_public_fluent(pos, default_initial_value=False)
truck2.add_private_fluent(in_city, default_initial_value=False)
truck2.add_public_fluent(on, default_initial_value=False)
airplane.add_public_fluent(pos, default_initial_value=False)
airplane.add_public_fluent(on, default_initial_value=False)
problem.ma_environment.add_fluent(at, default_initial_value=False)
problem.ma_environment.add_fluent(In, default_initial_value=False)


load_truck = InstantaneousAction("load_truck", loc=location, obj=package)
obj = load_truck.parameter("obj")
loc = load_truck.parameter("loc")
load_truck.add_precondition(at(obj, loc))
load_truck.add_precondition(pos(loc))
load_truck.add_effect(at(obj, loc), False)
load_truck.add_effect(on(obj), True)


unload_truck = InstantaneousAction("unload_truck", obj=package, loc=location)
obj = unload_truck.parameter("obj")
loc = unload_truck.parameter("loc")
unload_truck.add_precondition(pos(loc))
unload_truck.add_precondition(on(obj))
unload_truck.add_effect(on(obj), False)
unload_truck.add_effect(at(obj, loc), True)


drive_truck = InstantaneousAction("drive_truck", loc_from=location, loc_to=location, city_=city)
loc_from = drive_truck.parameter("loc_from")
loc_to = drive_truck.parameter("loc_to")
city_ = drive_truck.parameter("city_")
drive_truck.add_precondition(pos(loc_from))
drive_truck.add_precondition(in_city(loc_from, city_))
drive_truck.add_precondition(in_city(loc_to, city_))
drive_truck.add_effect(pos(loc_from), False)
drive_truck.add_effect(pos(loc_to), True)

load_airplane = InstantaneousAction("load_airplane", loc = airport, obj=package)
loc = load_airplane.parameter("loc")
obj = load_airplane.parameter("obj")
load_airplane.add_precondition(at(obj, loc))
load_airplane.add_precondition(pos(loc))
load_airplane.add_effect(at(obj, loc), False)
load_airplane.add_effect(on(obj), True)

unload_airplane = InstantaneousAction("unload_airplane", loc = airport, obj=package)
loc = load_airplane.parameter("loc")
obj = load_airplane.parameter("obj")
unload_airplane.add_precondition(on(obj))
unload_airplane.add_precondition(pos(loc))
unload_airplane.add_effect(on(obj), False)
unload_airplane.add_effect(at(obj, loc), True)

fly_airplane = InstantaneousAction("fly_airplane", loc_from=airport, loc_to=airport)
loc_from = fly_airplane.parameter("loc_from")
loc_to = fly_airplane.parameter("loc_to")
fly_airplane.add_precondition(pos(loc_from))
fly_airplane.add_effect(pos(loc_from), False)
fly_airplane.add_effect(pos(loc_to), True)

truck1.add_action(drive_truck)
truck1.add_action(unload_truck)
truck1.add_action(load_truck)
truck2.add_action(drive_truck)
truck2.add_action(unload_truck)
truck2.add_action(load_truck)
airplane.add_action(load_airplane)
airplane.add_action(unload_airplane)
airplane.add_action(fly_airplane)
problem.add_agent(truck1)
problem.add_agent(truck2)
problem.add_agent(airplane)


#problem
obj21 = Object("obj21", package)
obj22 = Object("obj22", package)
obj23 = Object("obj23", package)
obj11 = Object("obj11", package)
obj13 = Object("obj13", package)
obj12 = Object("obj12", package)
apt2 = Object("apt2", airport)
apt1 = Object("apt1", airport)
pos1 = Object("pos1", location)
cit1 = Object("cit1", city)
pos2 = Object("pos2", location)
cit2 = Object("cit2", city)


problem.add_object(obj21)
problem.add_object(obj22)
problem.add_object(obj23)
problem.add_object(obj11)
problem.add_object(obj13)
problem.add_object(obj12)
problem.add_object(apt2)
problem.add_object(apt1)
problem.add_object(pos1)
problem.add_object(cit1)
problem.add_object(pos2)
problem.add_object(cit2)

problem.set_initial_value(Dot(truck1, pos(pos1)), True)
problem.set_initial_value(at(obj11, pos1), True)
problem.set_initial_value(at(obj12, pos1), True)
problem.set_initial_value(at(obj13, pos1), True)
problem.set_initial_value(Dot(truck1, in_city(pos1, cit1)), True)
problem.set_initial_value(Dot(truck1, in_city(apt1, cit1)), True)
problem.set_initial_value(Dot(truck1, pos(pos1)), True)

problem.set_initial_value(Dot(truck2, pos(pos2)), True)
problem.set_initial_value(at(obj21, pos2), True)
problem.set_initial_value(at(obj22, pos2), True)
problem.set_initial_value(at(obj23, pos2), True)
problem.set_initial_value(Dot(truck2, in_city(pos2, cit2)), True)
problem.set_initial_value(Dot(truck2, in_city(apt2, cit2)), True)
problem.set_initial_value(Dot(truck2, pos(pos2)), True)

problem.set_initial_value(Dot(airplane, pos(apt2)), True)
problem.set_initial_value(at(obj11, pos1), True)
problem.set_initial_value(at(obj12, pos1), True)
problem.set_initial_value(at(obj13, pos1), True)
problem.set_initial_value(Dot(airplane, pos(apt2)), True)

problem.add_goal(at(obj11, apt1))
problem.add_goal(at(obj23, pos1))
problem.add_goal(at(obj13, apt1))
problem.add_goal(at(obj21, pos1))

w = MAPDDLWriter(problem)
w.write_ma_domain('logistic')
w.write_ma_problem('logistic')
[ ]:
print(problem)
problem name = ma-logistic

types = [object, location - object, city - object, package - object, vehicle - object, airport - location]

environment fluents = [
  bool at[object=object, location=location - object]
  bool in[package=package - object, vehicle=vehicle - object]
]

agents = [
  Agent name = truck1

private fluents = [
 bool in_city[location=location - object, city=city - object]
]

public fluents = [
 bool pos[location=location - object]
 bool on[object=object]
]

actions = [
 action drive_truck(location - object loc_from, location - object loc_to, city - object city_) {
    preconditions = [
      pos(loc_from)
      in_city(loc_from, city_)
      in_city(loc_to, city_)
    ]
    effects = [
      pos(loc_from) := false
      pos(loc_to) := true
    ]
  }
 action unload_truck(package - object obj, location - object loc) {
    preconditions = [
      pos(loc)
      on(obj)
    ]
    effects = [
      on(obj) := false
      at(obj, loc) := true
    ]
  }
 action load_truck(location - object loc, package - object obj) {
    preconditions = [
      at(obj, loc)
      pos(loc)
    ]
    effects = [
      at(obj, loc) := false
      on(obj) := true
    ]
  }
]


  Agent name = truck2

private fluents = [
 bool in_city[location=location - object, city=city - object]
]

public fluents = [
 bool pos[location=location - object]
 bool on[object=object]
]

actions = [
 action drive_truck(location - object loc_from, location - object loc_to, city - object city_) {
    preconditions = [
      pos(loc_from)
      in_city(loc_from, city_)
      in_city(loc_to, city_)
    ]
    effects = [
      pos(loc_from) := false
      pos(loc_to) := true
    ]
  }
 action unload_truck(package - object obj, location - object loc) {
    preconditions = [
      pos(loc)
      on(obj)
    ]
    effects = [
      on(obj) := false
      at(obj, loc) := true
    ]
  }
 action load_truck(location - object loc, package - object obj) {
    preconditions = [
      at(obj, loc)
      pos(loc)
    ]
    effects = [
      at(obj, loc) := false
      on(obj) := true
    ]
  }
]


  Agent name = airplane

private fluents = [
]

public fluents = [
 bool pos[location=location - object]
 bool on[object=object]
]

actions = [
 action load_airplane(airport - location loc, package - object obj) {
    preconditions = [
      at(obj, loc)
      pos(loc)
    ]
    effects = [
      at(obj, loc) := false
      on(obj) := true
    ]
  }
 action unload_airplane(airport - location loc, package - object obj) {
    preconditions = [
      on(obj)
      pos(loc)
    ]
    effects = [
      on(obj) := false
      at(obj, loc) := true
    ]
  }
 action fly_airplane(airport - location loc_from, airport - location loc_to) {
    preconditions = [
      pos(loc_from)
    ]
    effects = [
      pos(loc_from) := false
      pos(loc_to) := true
    ]
  }
]


]

objects = [
  object: [obj21, obj22, obj23, obj11, obj13, obj12, apt2, apt1, pos1, cit1, pos2, cit2]
  location - object: [apt2, apt1, pos1, pos2]
  city - object: [cit1, cit2]
  package - object: [obj21, obj22, obj23, obj11, obj13, obj12]
  vehicle - object: []
  airport - location: [apt2, apt1]
]

initial values = [
  truck1.pos(pos1) := true
  at(obj11, pos1) := true
  at(obj12, pos1) := true
  at(obj13, pos1) := true
  truck1.in_city(pos1, cit1) := true
  truck1.in_city(apt1, cit1) := true
  truck2.pos(pos2) := true
  at(obj21, pos2) := true
  at(obj22, pos2) := true
  at(obj23, pos2) := true
  truck2.in_city(pos2, cit2) := true
  truck2.in_city(apt2, cit2) := true
  airplane.pos(apt2) := true
  at(obj21, apt2) := false
  at(obj22, apt2) := false
  at(obj23, apt2) := false
  at(obj11, apt2) := false
  at(obj13, apt2) := false
  at(obj12, apt2) := false
  at(apt2, apt2) := false
  at(apt1, apt2) := false
  at(pos1, apt2) := false
  at(cit1, apt2) := false
  at(pos2, apt2) := false
  at(cit2, apt2) := false
  at(obj21, apt1) := false
  at(obj22, apt1) := false
  at(obj23, apt1) := false
  at(obj11, apt1) := false
  at(obj13, apt1) := false
  at(obj12, apt1) := false
  at(apt2, apt1) := false
  at(apt1, apt1) := false
  at(pos1, apt1) := false
  at(cit1, apt1) := false
  at(pos2, apt1) := false
  at(cit2, apt1) := false
  at(obj21, pos1) := false
  at(obj22, pos1) := false
  at(obj23, pos1) := false
  at(apt2, pos1) := false
  at(apt1, pos1) := false
  at(pos1, pos1) := false
  at(cit1, pos1) := false
  at(pos2, pos1) := false
  at(cit2, pos1) := false
  at(obj11, pos2) := false
  at(obj13, pos2) := false
  at(obj12, pos2) := false
  at(apt2, pos2) := false
  at(apt1, pos2) := false
  at(pos1, pos2) := false
  at(cit1, pos2) := false
  at(pos2, pos2) := false
  at(cit2, pos2) := false
  truck1.pos(apt2) := false
  truck1.pos(apt1) := false
  truck1.pos(pos2) := false
  truck1.in_city(apt2, cit1) := false
  truck1.in_city(pos2, cit1) := false
  truck1.in_city(apt2, cit2) := false
  truck1.in_city(apt1, cit2) := false
  truck1.in_city(pos1, cit2) := false
  truck1.in_city(pos2, cit2) := false
  truck1.on(obj21) := false
  truck1.on(obj22) := false
  truck1.on(obj23) := false
  truck1.on(obj11) := false
  truck1.on(obj13) := false
  truck1.on(obj12) := false
  truck1.on(apt2) := false
  truck1.on(apt1) := false
  truck1.on(pos1) := false
  truck1.on(cit1) := false
  truck1.on(pos2) := false
  truck1.on(cit2) := false
  truck2.pos(apt2) := false
  truck2.pos(apt1) := false
  truck2.pos(pos1) := false
  truck2.in_city(apt2, cit1) := false
  truck2.in_city(apt1, cit1) := false
  truck2.in_city(pos1, cit1) := false
  truck2.in_city(pos2, cit1) := false
  truck2.in_city(apt1, cit2) := false
  truck2.in_city(pos1, cit2) := false
  truck2.on(obj21) := false
  truck2.on(obj22) := false
  truck2.on(obj23) := false
  truck2.on(obj11) := false
  truck2.on(obj13) := false
  truck2.on(obj12) := false
  truck2.on(apt2) := false
  truck2.on(apt1) := false
  truck2.on(pos1) := false
  truck2.on(cit1) := false
  truck2.on(pos2) := false
  truck2.on(cit2) := false
  airplane.pos(apt1) := false
  airplane.pos(pos1) := false
  airplane.pos(pos2) := false
  airplane.on(obj21) := false
  airplane.on(obj22) := false
  airplane.on(obj23) := false
  airplane.on(obj11) := false
  airplane.on(obj13) := false
  airplane.on(obj12) := false
  airplane.on(apt2) := false
  airplane.on(apt1) := false
  airplane.on(pos1) := false
  airplane.on(cit1) := false
  airplane.on(pos2) := false
  airplane.on(cit2) := false
]

goals = [
  at(obj11, apt1)
  at(obj23, pos1)
  at(obj13, apt1)
  at(obj21, pos1)
]


17.2. MA-PDDL Writer

As the name suggests, MAPDDLWriter offers the capability of dumping a unified_planning MultiAgentProblem in ma-pddl.

There are 3 possible usages of the MAPDDLWriter:

  • printing ma-pddl domain and problem in a different file for each agent (factored domains)

  • getting ma-pddl domain and problem for each agent as a python str

  • printing ma-pddl domain and problem for each agent to STDOUT

17.3. Writing to files

To write the ma-pddl equivalent of a unified_planning MultiAgentProblem to a file we use the MAPDDLWriter.write_ma_domain and MAPDDLWriter.write_ma_problem methods.

[ ]:
w = MAPDDLWriter(problem)
w.write_ma_domain('ma_logistic_directory')
w.write_ma_problem('ma_logistic_directory')

17.3.1. Getting domains and problems as a python strings

To get the ma-pddl equivalent of a unified_planning MultiAgentProblem as a python strings we use the MAPDDLWriter.get_ma_domain_agent('name_of_agent') and MAPDDLWriter.get_ma_problem_agent('name_of_agent') methods. In this way we can get the domain and problem of a particular agent.

[ ]:
w.get_ma_domain_agent('truck1')
w.get_ma_problem_agent('airplane')
'(define (problem ma_logistic-problem)\n (:domain ma_logistic-domain)\n (:objects\n   pos1 pos2 - location\n   cit1 cit2 - city\n   obj21 obj22 obj23 obj11 obj13 obj12 - package\n   apt2 apt1 - airport\n   truck1 - truck1_type\n   truck2 - truck2_type\n   airplane - airplane_type\n )\n (:init\n  (a_pos truck1 pos1)\n  (at_ obj11 pos1)\n  (at_ obj12 pos1)\n  (at_ obj13 pos1)\n  (a_pos truck2 pos2)\n  (at_ obj21 pos2)\n  (at_ obj22 pos2)\n  (at_ obj23 pos2)\n  (a_pos airplane apt2))\n (:goal (and (at_ obj11 apt1) (at_ obj23 pos1) (at_ obj13 apt1) (at_ obj21 pos1)))\n)'

###Printing domain and problem to STDOUT

To print the pddl equivalent of a unified_planning Problem to STDOUT we use the MAPDDLWriter.print_ma_domain_agent('name_of_agent') and MAPDDLWriter.print_ma_problem_agent('name_of_agent') methods.

[ ]:
w.print_ma_domain_agent('truck1')
w.print_ma_problem_agent('airplane')
(define (domain ma_logistic-domain)
 (:requirements :factored-privacy :typing)
 (:types
    object_ ag - object
    truck1_type truck2_type airplane_type - ag
    location city package vehicle - object_
    airport - location
 )
 (:predicates
  (at_ ?object - object_ ?location - location)
  (in ?package - package ?vehicle - vehicle)
  (a_pos ?agent - ag ?location - location)
  (a_on ?agent - ag ?object - object_)
  (:private
   (a_in_city ?agent - ag ?location - location ?city - city)))
 (:action drive_truck
  :parameters ( ?truck1 - truck1_type ?loc_from - location ?loc_to - location ?city_ - city)
  :precondition (and
   (a_pos ?truck1 ?loc_from)
   (a_in_city ?truck1 ?loc_from ?city_)
   (a_in_city ?truck1 ?loc_to ?city_)
  )
  :effect (and
   (not (a_pos ?truck1 ?loc_from))
   (a_pos ?truck1 ?loc_to)
))
 (:action unload_truck
  :parameters ( ?truck1 - truck1_type ?obj - package ?loc - location)
  :precondition (and
   (a_pos ?truck1 ?loc)
   (a_on ?truck1 ?obj)
  )
  :effect (and
   (not (a_on ?truck1 ?obj))
   (at_ ?obj ?loc)
))
 (:action load_truck
  :parameters ( ?truck1 - truck1_type ?loc - location ?obj - package)
  :precondition (and
   (at_ ?obj ?loc)
   (a_pos ?truck1 ?loc)
  )
  :effect (and
   (not (at_ ?obj ?loc))
   (a_on ?truck1 ?obj)
))
)
(define (problem ma_logistic-problem)
 (:domain ma_logistic-domain)
 (:objects
   pos1 pos2 - location
   cit1 cit2 - city
   obj21 obj22 obj23 obj11 obj13 obj12 - package
   apt2 apt1 - airport
   truck1 - truck1_type
   truck2 - truck2_type
   airplane - airplane_type
 )
 (:init
  (a_pos truck1 pos1)
  (at_ obj11 pos1)
  (at_ obj12 pos1)
  (at_ obj13 pos1)
  (a_pos truck2 pos2)
  (at_ obj21 pos2)
  (at_ obj22 pos2)
  (at_ obj23 pos2)
  (a_pos airplane apt2))
 (:goal (and (at_ obj11 apt1) (at_ obj23 pos1) (at_ obj13 apt1) (at_ obj21 pos1)))
)