I am new to PDDL and AI planning area. I am actually creating a plan for a humanoid interacting with a human in a scenario. The scenario is as follows
Human enters the room (where robot and some objects are present in the room)
Robot detects human
Greets human after detecting
Then human asks for a cup
Robot assumes that human wants to drink coffee and responds to human on what time human took medication (there should be a gap of 1 hour for medication and coffee)
Human responds with the time
If the time matches to 1 hour gap, Robot responds that it will find cup
Robot detects the cup on the table
Robot responds to human that cup is on the table
Human picks the cup
Robot greets the human after detecting that the human is holding the cup
My PDDL domain file logic is as follows:
(define (domain sp)
(:requirements :typing :strips :adl)
(:types location agent item - object
robot human speak - agent
room - location
fruit cup table - item
clear polite listenatt - speak)
(:predicates
(at ?o - object ?l - location)
(detected_human ?p - human ?l - room)
(greeted ?r - robot ?p - human)
(detected_cup ?c - cup ?l - room)
(holded ?c - cup ?p - human)
(medichecked ?r - robot ?p - human)
(human_asked ?p - human)
(robot_responded ?r - robot ?cl - clear ?pl - polite)
)
(:action detect_human
:parameters (?p - human ?r - robot ?l - location)
:precondition (at ?r ?l)
:effect (detected_human ?p ?l)
)
(:action detect_cup
:parameters (?p - human ?c - cup ?r - robot ?l - location )
:precondition (and (detected_human ?p ?l)
(human_asked ?p)
(medichecked ?r ?p)
)
:effect (detected_cup ?c ?l)
)
(:action greet
:parameters (?r - robot ?p - human ?l - location ?pl - polite ?cl - clear)
:precondition (and (at ?r ?l) (detected_human ?p ?l))
:effect (and (greeted ?r ?p) (robot_responded ?r ?cl ?pl))
)
(:action hold
:parameters (?c - cup ?p - human ?l - location ?r - robot ?cl - clear ?pl - polite)
:precondition (and (detected_human ?p ?l)
(detected_cup ?c ?l)
(robot_responded ?r ?cl ?pl)
(medichecked ?r ?p)
)
:effect (holded ?c ?p)
)
(:action check_medi
:parameters (?p - human ?l - location ?r - robot)
:precondition (human_asked ?p)
:effect (medichecked ?r ?p)
)
(:action human_ask
:parameters (?p - human ?l - location ?r - robot)
:precondition (and (detected_human ?p ?l) (greeted ?r ?p))
:effect (human_asked ?p)
)
(:action robot_respond
:parameters (?p - human ?l - location ?r - robot ?cl - clear ?pl - polite ?c -cup)
:precondition (and (at ?r ?l) (detected_human ?p ?l))
:effect (and (when (human_asked ?p) (robot_responded ?r ?cl ?pl))
(when (detected_cup ?c ?l) (robot_responded ?r ?cl ?pl)))
)
)
My PDDL problem file is as follows:
(define (problem test12)
(:domain sp)
(:objects person0 - Human
pepper0 - Robot
apple - Fruit
cup0 - Cup
table0 - Table
room0 - Room
clear0 - Clear
polite0 - Polite)
(:init
(at pepper0 room0)
)
(:goal (holded cup0 person0)
)
currently it generates the following plan:
plan-found
(detect_human person0 pepper0 room0)
(greet pepper0 person0 room0 polite0 clear0)
(human_ask person0 room0 pepper0)
(check_medi person0 room0 pepper0)
(detect_cup person0 cup0 pepper0 room0)
(hold cup0 person0 room0 pepper0 clear0 polite0)
I wanted the expected plan to be something like this:
plan-found
(detect_human person0 pepper0 room0)
(greet pepper0 person0 room0 polite0 clear0)
(human_ask person0 room0 pepper0)
(robot_respond person0 polite0 clear0 room0)
(check_medi person0 room0 pepper0)
(robot_respond person0 polite0 clear0 room0)
(detect_cup person0 cup0 pepper0 room0)
(robot_respond person0 polite0 clear0 room0)
(hold cup0 person0 room0 pepper0 clear0 polite0)
I am not sure why the robot_respond action is never coming in the plan even though it is given in the effects and preconditions.
I appreciate if any direction on this problem. Its been more than a week I am struggling to get the logic correct.
It’s indispensable for the action ‘robot-response’? I mean it looks like you didn’t set any effects in action ‘robot-response’ as a condition for others or possibly the same predicate ‘(robot-responsed)’ can be satisfied in action ‘greet’?
I am creating a program that works with geographic information. I have data that contains what geographic units touch each other. The function that fails is intended to add neighboring units to an array based on population (for example, it starts with a unit, then adds the most populous neighboring unit to the array, and then adds the most populous unit that touches one of the units in the array, and continues this until it reaches a population limit). The way I am doing this is using a for loop, and then using an array of the total units that have been sorted by population. I then find the index of the first (and therefore most populous) neighbor using the intersection between the neighbors of the units in the array and the neighbors of each unit in the array of total units. The following is my code (please excuse the clunkiness):
func createDistrict () {
if useBoard.isEmpty == false {
useBoard.sort(by: {$0.population > $1.population})
var maxPop = useBoard.first!.population
district.removeAll()
district.append(useBoard.first!)
useBoard.removeFirst()
for i in 0...useBoard.count - 1 {
if useBoard.indices.contains(i) {
if useBoard[i] == nil || district.map({$0.population}).reduce(0,+) > districtMax {
break
}
} else {
break
}
useBoard.sort(by: {$0.population > $1.population})
var superArray:[Precinct] = []
district.forEach { (z) in
superArray += z.neighbors
Array(Set(superArray))
}
var nextPre = useBoard.firstIndex { (l) -> Bool in
Set(l.neighbors).intersection(Set(superArray)).isEmpty == false
}
if nextPre == nil {
break
}else {
var temporary = Set(useBoard[nextPre!].neighbors).intersection(Set(superArray))
var newString = ""
var newTemp = Array(temporary)
for t in 0...newTemp.count - 1 {
var next = useBoard.firstIndex { (k) -> Bool in
k == newTemp[t]
}
newString.append("\(newTemp[t]) (\(next)), ")
}
print("\(useBoard[nextPre!].precinctID) (\(nextPre!)) touches \(newString)")
}
district.append(useBoard[nextPre!])
useBoard.remove(at: nextPre!)
}
}
district.forEach { (p) in
print("\(p.precinctID)")
}
}
In this function, var nextPre = useBoard.firstIndex { (l) -> Bool in Set(l.neighbors).intersection(Set(superArray)).isEmpty == false} is used to find the index of the most populous neighbor. However, when I test it using print, I get an incorrect output. In the following excerpt, the values in the parentheses are just the indices and don't really matter. The output:
2104 (8) touches 1987 (Optional(710)), 2676 (Optional(1591)),
2387 (10) touches 2105 (Optional(2140)),
2274 (11) touches 2273 (Optional(52)), 2386 (Optional(236)),
2275 (14) touches 2276 (Optional(22)), 2105 (Optional(2138)), 2273 (Optional(51)),
2276 (21) touches 2389 (Optional(1638)), 2273 (Optional(50)), 2274 (nil), 2275 (nil), 2277 (Optional(2771)), 2386 (Optional(234)),
2067 (35) touches 2404 (Optional(76)), 2212 (Optional(944)),
2406 (40) touches 2404 (Optional(75)), 2070 (Optional(1771)),
2440 (42) touches 2212 (Optional(942)), 2388 (Optional(497)), 2441 (Optional(1364)),
2273 (46) touches 2386 (Optional(230)), 2276 (nil), 2064 (Optional(384)), 2275 (nil), 2105 (Optional(2133)), 2274 (nil), 2387 (nil),
1795 (55) touches 1891 (Optional(1212)),
1908 (41) touches 2638 (Optional(2568)), 1869 (Optional(474)),
2404 (70) touches 2212 (Optional(938)), 2070 (Optional(1766)), 2069 (Optional(365)), 2068 (Optional(581)), 1743 (Optional(2453)), 2405 (Optional(2442)), 2387 (nil), 2105 (Optional(2130)), 2284 (Optional(2792)),
2736 (70) touches 2548 (Optional(1314)), 2420 (Optional(1305)),
1798 (52) touches 2419 (Optional(270)),
1907 (45) touches 1912 (Optional(1611)), 2737 (Optional(2082)),
As you can see, the neighbors are off by 1. For example, 2104 is the first unit. Then 2387 touches 2105, which is 2104 + 1. Then 2274 touches 2386, which is 2387 - 1. Then 2275 touches 2105, which is 2104 + 1. The .intersection should find the first unit that touches the units in the array, yet it finds the first unit that touches a unit's name + 1. I have no idea how this is occurring, as the geographic units are stored in a custom object, not an integer or any other number variable. Here is the custom object:
class Precinct {
var precinctID:String
var population:Int
var neighbors:[Precinct]
init(precinctID:String, population:Int, neighbors:[Precinct]){
self.precinctID = precinctID
self.population = population
self.neighbors = neighbors
}
}
extension Precinct: Equatable {
static func == (lhs: Precinct, rhs: Precinct) -> Bool {
return lhs.precinctID == rhs.precinctID && lhs.population == rhs.population && lhs.neighbors == rhs.neighbors
}
}
extension Precinct: Hashable {
var hashValue: Int {
return precinctID.hashValue ^ population.hashValue
}
}
extension Precinct: CustomStringConvertible {
var description: String {
return "\(precinctID)"
}
}
What's going wrong and how can I fix it? Thanks.
The problem is due to the fact that you are removing elements of useBoard while at the same time iterating over useBoard. You are printing the indices "\(newTemp[t]) (\(next)), " and then five lines later removing an index; before repeating the process. While you can change the values of a collection you are iterating over, never change the size of the collection at the same time.
A first step may be to copy useBoard before running the outer loop. Keep it constant so that you iterate over all of its contents but use the copy for all of your logic. I have trouble following the intent of your code.
As far as the hash, that is not your problem. However it is not ideal. Swift provides a default hash that is almost always better. Just allow Swift to synthesize its own algorithm by changing that extension to this.
extension Precinct: Hashable {}
There are a couple of issues. Please remove the call to sort useBoard within the outer loop. That has no effect because useBoard was already sorted before entering the loop. Also Array(Set(superArray)) is not doing anything for you.
Good luck.
I'm having trouble switching to an iterate version of some loop code:
(defun get-bound-?vars-1 (tree)
(loop for item in tree
when (consp item)
if (member (car item) '(exists forall doall))
nconc (delete-if-not #'?varp
(alexandria:flatten (second item)))
else nconc (get-bound-?vars item)))
My corresponding iterate translation:
(defun get-bound-?vars-2 (tree)
(iter (for item in tree)
(when (consp item)
(if (member (car item) '(exists forall doall))
(nconc (delete-if-not #'?varp
(alexandria:flatten (second item))))
(nconc (get-bound-?vars item))))))
As test case:
(defparameter *tree*
'(if (exists (?t transmitter)
(and (connecting ?t ?connector)
(bind (color ?t $hue))))
(if (not (exists ((?t1 ?t2) transmitter)
(and (connecting ?t1 ?connector)
(connecting ?t2 ?connector)
(bind (color ?t1 $hue1))
(bind (color ?t2 $hue2))
(not (eql $hue1 $hue2)))))
(activate-connector! ?connector $hue))))
Then loop OK:
(get-bound-?vars-1 *tree*) => (?T ?T1 ?T2)
But iterate not OK:
(get-bound-?vars-2 *tree*) => NIL
Thanks for any pointers.
In the driverlog domain in PDDL we have specified links and paths.
(define (domain driverlog)
(:requirements :typing)
(:types location locatable - object
driver truck obj - locatable
)
(:predicates
(at ?obj - locatable ?loc - location)
(in ?obj1 - obj ?obj - truck)
(driving ?d - driver ?v - truck)
(link ?x ?y - location) (path ?x ?y - location)
(empty ?v - truck)
)
And the way that it's defined in the problem is:
(define (problem DLOG-2-2-2)
(:domain driverlog)
(:objects
driver1 - driver
driver2 - driver
truck1 - truck
truck2 - truck
package1 - obj
package2 - obj
s0 - location
s1 - location
s2 - location
p1-0 - location
p1-2 - location
)
(:init
(at driver1 s2)
(at driver2 s2)
(at truck1 s0)
(empty truck1)
(at truck2 s0)
(empty truck2)
(at package1 s0)
(at package2 s0)
(path s1 p1-0)
(path p1-0 s1)
(path s0 p1-0)
(path p1-0 s0)
(path s1 p1-2)
(path p1-2 s1)
(path s2 p1-2)
(path p1-2 s2)
(link s0 s1)
(link s1 s0)
(link s0 s2)
(link s2 s0)
(link s2 s1)
(link s1 s2)
)
What's the difference between paths and links? I've tried to create a similar problem but omitting the path and I keep getting Unsolvable Problem. How can I properly define a path?
Thanks!
These are user-defined predicates:
(define (domain driverlog)
...
(:predicates
...
(link ?x ?y - location) (path ?x ?y - location)
...
)
)
so their semantics can be deduced by inspecting the corresponding model.
Both link and path are binary predicates that put in relation two locations, presumably when it's possible to move from one place to the other. This connection is unidirectional.
I read, from the source code, that the following actions are defined:
(:action DRIVE-TRUCK
:parameters
(?truck
?loc-from
?loc-to
?driver)
:precondition
(and (TRUCK ?truck) (LOCATION ?loc-from) (LOCATION ?loc-to) (DRIVER ?driver)
(at ?truck ?loc-from)
(driving ?driver ?truck) (link ?loc-from ?loc-to))
:effect
(and (not (at ?truck ?loc-from)) (at ?truck ?loc-to)))
(:action WALK
:parameters
(?driver
?loc-from
?loc-to)
:precondition
(and (DRIVER ?driver) (LOCATION ?loc-from) (LOCATION ?loc-to)
(at ?driver ?loc-from) (path ?loc-from ?loc-to))
:effect
(and (not (at ?driver ?loc-from)) (at ?driver ?loc-to)))
So it seems that two locations have a link if it is possible to DRIVE-TRUCK from one place to the other, and two locations have a path if it is possible to WALK from one place to the other.
There is really nothing else to say about it.
The reason why you keep getting UNSAT is because you placed the drivers and the trucks in two different locations:
(at driver1 s2)
(at driver2 s2)
(at truck1 s0)
(at truck2 s0)
Since the only connection among s0 and s2 is a link, the drivers cannot possibly reach the truck (and vice-versa). This is because a precondition of DRIVE-TRUCK is (driving ?driver ?truck), which is only set by BOARD-TRUCK if the driver is in the same location of the truck.
You can solve this issue by creating a path among s0 and s2. However, this seems to be against the naming convention of the model, which interconnects sX using links only. A better solution is to change the initial state and put a truck in the same location of each driver, or at least in a location that is reachable by the WALK action.
I've written a domain and a test problem in PDDL, but apparently the graphplan implementation can't find a plan. Here's the domain:
(define (domain aperture)
(:requirements :strips :typing :negative-preconditions)
(:types
cube
hallway room - location
)
(:predicates
(at ?l - location)
(has ?c - cube)
(connected ?l1 - location ?l2 - location)
(in ?c - cube ?l - location)
)
(:action enter
:parameters (?h - hallway ?r - room)
:precondition (and (connected ?h ?r) (connected ?r ?h) (at ?h)
(not (at ?r)))
:effect (and (at ?r) (not (at ?h)))
)
(:action exit
:parameters (?r - room ?h - hallway)
:precondition (and (connected ?r ?h) (connected ?h ?r) (at ?r)
(not (at ?h)))
:effect (and (at ?h) (not (at ?r)))
)
(:action move
:parameters (?h1 ?h2 - hallway)
:precondition (and (connected ?h1 ?h2) (connected ?h2 ?h1)
(at ?h1) (not (at ?h2)))
:effect (and (at ?h2) (not (at ?h1)))
)
(:action pickup
:parameters (?c - cube ?l - location)
:precondition (and (at ?l) (not (has ?c)) (in ?c ?l))
:effect (and (has ?c) (not (in ?c ?l)))
)
(:action drop
:parameters (?c - cube ?l - location)
:precondition (and (at ?l) (has ?c) (not (in ?c ?l)))
:effect (and (not (has ?c)) (in ?c ?l))
)
)
and here's the problem:
(define (problem pb1)
(:domain aperture)
(:requirements :strips :typing)
(:objects h1 - hallway
h2 - hallway
h3 - hallway
r1 - room
c1 - cube)
(:init (at h1)
(connected h1 h2)
(connected h2 h1)
(connected h2 h3)
(connected h3 h2)
(connected h2 r1)
(connected r1 h2)
(in c1 r1)
)
(:goal (and
(has c1)
)
)
)
For this particular problem the set of states for the solution should be:
move(h1,h2)
enter(h2,r1)
pickup(c1,r1)
but, as I've said, the graphplan implementation that I'm using (graphplan) can't find any plan.
I was able to find a solution plan using strips. However, I had to tweak your domain slightly. Specifically, I changed the domain actions "pickup" and "drop" to replace the parameter type "location" with "room". With this change, I was able to find the following solution:
1. move h1 h2
2. enter h2 r1
3. pickup c1 r1
Maybe this could be the reason graphplan was unable to find a solution as well? Here are the modified domain and problem pddl files.
domain.pddl
(define (domain aperture)
(:requirements :strips :typing :negative-preconditions)
(:types
cube
hallway room - location
)
(:action enter
:parameters (?h - hallway ?r - room)
:precondition (and (connected ?h ?r) (connected ?r ?h) (at ?h)
(not (at ?r)))
:effect (and (at ?r) (not (at ?h)))
)
(:action exit
:parameters (?r - room ?h - hallway)
:precondition (and (connected ?r ?h) (connected ?h ?r) (at ?r)
(not (at ?h)))
:effect (and (at ?h) (not (at ?r)))
)
(:action move
:parameters (?h1 - hallway ?h2 - hallway)
:precondition (and (connected ?h1 ?h2) (connected ?h2 ?h1)
(at ?h1) (not (at ?h2)))
:effect (and (at ?h2) (not (at ?h1)))
)
(:action pickup
:parameters (?c - cube ?l - room)
:precondition (and (at ?l) (not (has ?c)) (in ?c ?l))
:effect (and (has ?c) (not (in ?c ?l)))
)
(:action drop
:parameters (?c - cube ?l - room)
:precondition (and (at ?l) (has ?c) (not (in ?c ?l)))
:effect (and (not (has ?c)) (in ?c ?l))
)
)
problem.pddl
(define (problem pb1)
(:domain aperture)
(:objects h1 - hallway
h2 - hallway
h3 - hallway
r1 - room
c1 - cube)
(:init (at h1)
(connected h1 h2)
(connected h2 h1)
(connected h2 h3)
(connected h3 h2)
(connected h2 r1)
(connected r1 h2)
(in c1 r1)
)
(:goal (and
(has c1)
)
)
)