I am trying to solve a Pacman-style problem with a planner, using PDDL. I assume there are many food in the given map. I use exists to check if here is any other food in the map, but it does not work; why is that?
Here is my problem file:
(define
(problem pacman-level-1)
(:domain pacman_simple)
;; problem map
;; | 1 | 2 | 3 |
;; -|---|---|---|
;; a| P | G | F |
;; b| _ | _ | _ |
;; |---|---|---|
(:objects
a1 a2 a3 b1 b2 b3 - cell
pacman - pacman
ghost - ghost
food1 - food
food2 - food
nofood - nofood
)
(:init
(at a1 pacman)
(at a2 ghost)
(status a1 nofood)
(status a2 nofood)
(status a3 food1)
(status b1 nofood)
(status b2 nofood)
(status b3 food2)
(adjacent a1 a2) (adjacent a1 b1)
(adjacent a2 a1) (adjacent a2 b2) (adjacent a2 a3)
(adjacent a3 a2) (adjacent a3 b3)
(adjacent b1 a1) (adjacent b1 b2)
(adjacent b2 b1) (adjacent b2 a2) (adjacent b2 b3)
(adjacent b3 b2) (adjacent b3 a3)
(same a1 a1)
(same a2 a2)
(same a3 a3)
(same b1 b1)
(same b2 b2)
(same b3 b3)
)
(:goal
(and
(eatallfood)
)
)
)
and the following is my domain file:
(define
(domain pacman_simple)
(:requirements :strips :typing :equality :adl :conditional-effects)
(:types
cell subject - object
pacman ghost - subject
food nofood - cellstatus
)
(:constants
F - food
NF - nofood
)
(:predicates
(adjacent ?c - cell ?c - cell)
(at ?c - cell ?s - subject)
(status ?c - cell ?s - cellstatus)
(eatallfood)
(same ?c1 ?c2 - cell)
)
(:action move
:parameters (?from - cell ?to - cell ?p - pacman ?g - ghost ?nf - nofood ?f - food)
:vars
(
?x - food
)
:precondition
(and
(adjacent ?from ?to)
(at ?from ?p)
(status ?from ?nf)
(not
(at ?to ?p)
)
(not
(at ?to ?g)
)
(not
(eatallfood)
)
)
:effect
(and
(at ?to ?p)
(status ?to ?nf)
(not
(at ?from ?p)
)
(when (not
(exists (?c - cell)
(and
(and
(not (same ?to ?c))
(status ?c ?f)
)
)
)
)
(and
(eatallfood)
)
)
)
)
)
error message: ff: goal can be simplified to FALSE. No plan will solve it
I think the problem is your use of when, which FastForward might not be able to deal with. You could try rephrasing your problem without it.
You have six cells. Just introduce a predicate (food <cell>), which you set to true initially, as in
(food a1) (food a2) ...
The the effect of moving would be (not (food ?to)), ie the food in that cell gets removed.
You then need to rephrase your goal to
(and (not (food a1)) (not (food a2)) ...)
That is less elegant, but should do the trick.
The move action should probably look like this:
(:action move
:parameters (?from - cell ?to - cell ?p - pacman ?g - ghost)
:precondition (and
(adjacent ?from ?to)
(at ?from ?p)
(not (at ?to ?g)))
:effect (and
(at ?to ?p)
(not (at ?from ?p))
(not (food ?to))))
Related
I am trying to solve a Pacman problem using PDDL. The main thing I need to do is soft code the power duration without using functions or fluents. It returns no error but somehow I feel like it inits Powerlose(n2, n0). I never init Powerlose(n2, n0) or change Powerlose in the effect. But the initial value it gives to c is n2. So what's wrong? Thanks in advance.
You can check the problem and domain through this link:
http://editor.planning.domains/#edit_session=bD5G0tIIl1vyWDf
I tried to use exists statement instead of Powerlose(cPlus1, c) on line 34 of the domain file, it does not work. It still init c with n2. I am so confused.
Here is my domain file:
(define
(domain pacman_hard)
(:requirements :strips :typing :equality :adl)
(:types
pos int
)
(:predicates
(PacmanAt ?p - pos)
(GhostAt ?p - pos)
(FoodAt ?p - pos)
(CapsuleAt ?p - pos)
(PowerCurr ?n - int)
(PowerLose ?n1 ?n2 - int)
(PowerGain ?n1 ?n2 - int)
(Adjacent ?p1 ?p2 - pos)
)
(:action move
:parameters (?posCurr ?posNext - pos ?cPlus1 ?c ?MaxPower - int)
:precondition (and
(and
; check if there is any food left,
; which guarantees all ghosts are eaten before last food
(exists (?p - pos) (FoodAt ?p))
(PacmanAt ?posCurr)
(Adjacent ?posCurr ?posNext)
(PowerCurr ?cPlus1)
(PowerGain ?cPlus1 ?MaxPower)
)
(or
(PowerLose ?cPlus1 ?c) ;powered
(not (GhostAt ?posNext))
)
)
:effect (and
(PacmanAt ?posNext)
(not (PacmanAt ?posCurr))
; update power status accordingly/with priority
; first reduce the time of power
(when (PowerLose ?cPlus1 ?c); could minus 1
(and
(not (PowerCurr ?cPlus1))
(PowerCurr ?c)
(not (GhostAt ?posNext))
)
)
; refresh the power time if in next pos its a capsule
(when (CapsuleAt ?posNext)
(and
(not (PowerCurr ?cPlus1))
(not (PowerCurr ?c))
(PowerCurr ?MaxPower)
)
)
(not (FoodAt ?posNext))
(not (CapsuleAt ?posNext))
)
)
)
The problem file:
problem map
| 1 | 2 | 3 | 4 | 5 |
-|---|--- ---|---|---|
a| P | _ | _ | G | F |
b| _ | C | _ | G | C |
|---|---|---|---|---|
(define
(problem pacman-level-1)
(:domain pacman_hard)
(:objects
a1 a2 a3 a4 a5 b1 b2 b3 b4 b5 - pos
n0 n1 n2 - int
)
(:init
(PacmanAt a1)
(GhostAt a4)
(GhostAt b4)
(CapsuleAt b2)
(CapsuleAt b5)
(FoodAt a5)
(PowerCurr n0)
(PowerLose n1 n0)
(PowerLose n2 n1)
(PowerGain n0 n2)
(PowerGain n1 n2)
(PowerGain n2 n2)
(Adjacent a1 a2)
(Adjacent a1 b1)
(Adjacent b1 a1)
(Adjacent b1 b2)
(Adjacent a2 a1)
(Adjacent a2 b2)
(Adjacent a2 a3)
(Adjacent b2 a2)
(Adjacent b2 b1)
(Adjacent b2 b3)
(Adjacent a3 a2)
(Adjacent a3 b3)
(Adjacent a3 a4)
(Adjacent b3 b2)
(Adjacent b3 a3)
(Adjacent b3 b4)
(Adjacent a4 a3)
(Adjacent a4 b4)
(Adjacent a4 a5)
(Adjacent b4 b3)
(Adjacent b4 a4)
(Adjacent b4 b5)
(Adjacent a5 a4)
(Adjacent a5 b5)
(Adjacent b5 b4)
(Adjacent b5 a5)
)
(:goal
; this would guarantee the pacman has eaten all food and ghosts.
(forall (?p - pos)
(and (not (FoodAt ?p)) (not (GhostAt ?p)))
)
)
)
The plan it returns:
(move a1 b1 n0 n2 n2)
(move b1 b2 n0 n2 n2)
(move b2 b3 n2 n2 n2)
(move b3 b4 n2 n1 n2)
(move b4 a4 n1 n0 n2)
(move a4 a5 n0 n2 n2)
The correct plan:
(move a1 b1) (move b1 b2) (move b2 b3) (move b3 b4) (move b4 b5) (move b5 b4) (move b4 a4) (move a4 a5)
As an aside, it's always useful to specify what planner (and it's configuration) that you're using.
I loaded your problem into the online editor:
http://editor.planning.domains/#read_session=A1Dk7n8YAz
It gave a similar plan (at least start of plan) when I tried solving. I'd suggest doing the same (Solve button is at the top), and looking at the plan. The right side shows the grounded action. First thing to notice is that your Powerlose precondition is part of an or clause, and the other part is certainly satisfied (i.e., (ghostat b1) is false). So that aspect of the precondition is satisfied.
Hopefully, this clears up what might be going on!
The result produced by the SMT solver is:
(or (and (>= c1 2) (<= c1 4) (= (+ c0 c1 c2) 5) (= (+ c0 c1) 4))
(and (>= c1 1) (<= c1 3) (= (+ c0 c1 c2) 5) (= (+ c0 c1) 4)))
But I am expecting something like:
(and (>= c1 1) (<= c1 4) (= (+ c0 c1 c2) 5) (= (+ c0 c1) 4)
can someone guide me to achieve this with Z3 solver?
Link : http://rise4fun.com/Z3/1Xz3
Z3 does not support this kind of simplification. It does not support simplification into a "normal form". Recall that the main interface to Z3 is to check whether a formula is satisfiable or unsatisfiable.
You can ask many queries to the SMT solver to extract a conjunction which is equivalent to a formula in case you are able to identify which literals should be tested for membership in the conjunction. This is not always possible to do in a syntactic way as your example suggests.
Two arrays A,B are given of same length (not sorted).
Make pairs of their entries (one from A and one from B), such that average difference in the entries (|a1-b1|,|a2-b2|,....) is minimum.
I have thought of sorting them and then making pairs of same index entries.
Will this work ?
If yes, how ? else some other solution with proof.
I'm assuming that this problem can be formally stated as follows: given two n-element vectors A and B, find permutations A' of A and B' of B so as to minimize the L1 norm of A' - B'.
If so, then your proposed algorithm is correct. Suppose that we have a solution with an inversion, that is, a1 matched with b2 and a2 matched with b1 such that a1 < a2 and b1 < b2. The contribution of these pairs to the L1 norm is
|a1 - b2| + |a2 - b1| >= |a1 - b1| + |a2 - b2|,
where the inequality follows from an inelegant case argument that we defer for the moment. Accordingly, by rematching a1 with b1 and a2 with b2, we decrease the number of inversions without increasing the cost. It follows by induction that the matching with no inversions is optimal.
Case argument: symmetrically (by interchanging A and B), there are three possible interleavings.
(1) a1 <= a2 <= b1 <= b2
(2) a1 <= b1 <= a2 <= b2
(3) a1 <= b1 <= b2 <= a2
In case (1),
|a1 - b2| + |a2 - b1| = b2 - a1 + b1 - a2
= b1 - a1 + b2 - a2
= |a1 - b1| + |a2 - b2|.
In case (2),
|a1 - b2| + |a2 - b1| = b2 - a1 + a2 - b1
>= b2 - a1 + a2 - b1 - 2 (a2 - b1)
= b1 - a1 + b2 - a2
= |a1 - b1| + |a2 - b2|.
In case (3),
|a1 - b2| + |a2 - b1| = b2 - a1 + a2 - b1
>= b2 - a1 + a2 - b1 - 2 (b2 - b1)
= b1 - a1 + a2 - b2
= |a1 - b1| + |a2 - b2|.
Edit: misread the question, the below describes why the sum of differences is maximized when you sort the two lists in opposite order
Here is another way to see that the algorithm you described gives you the optimal solution. Note that when you write out |x - y| it equals either x - y or y - x. Thus,
|a_1 - b_1| + |a_2 - b_2| + ... + |a_n - b_n|
can be thought of as summing the numbers a_1, ..., a_n, b_1, ... , b_n, except that exactly n of them have their sign flipped. Clearly, this is maximized when you choose to negate the n smallest numbers out of a_1, ..., a_n, b_1, ..., b_n. And indeed, that is exactly what your algorithm does.
Ok, Say, I got a table that have 3 columns: c1, c2, c3
C1 - C2 - C3
A2 - B2 - N2
K1 - B2 - N1
K1 - B3 - N1
L1 - A2 - C1
Ok, when users search for any combination of A1, A2, A3, B1, B2, ... then the system can be able to pick the rows with the closet match (it means as long as the word appears in 1 column, the system will pick it, the more words appear in more columns the closer it matches) & order them according to the closest match
Ex1: a user searches for "K1 A2 C1 N1", the system will show:
K1 - B2 - N1
K1 - B3 - N1
A2 - B2 - N2
L1 - A2 - C1
Ex2: a user searches for "K1 A2 C1 N2 B2", the system will show:
A2 - B2 - N2
L1 - A2 - C1
K1 - B2 - N1
K1 - B3 - N1
My solution is to split the search string into separate words & then search each of these words against the columns in the table. But I am not sure it is the optimum query since the DB have to search in many loops.
So if u r expert in DB, then what is the best query in this scenario?
select c1
,c2
,c3
,case when c1 in ('K1','A2','C1','N1') then 1 else 0 end
+case when c2 in ('K1','A2','C1','N1') then 1 else 0 end
+case when c3 in ('K1','A2','C1','N1') then 1 else 0 end as sortweight
from theTable
where c1 in ('K1','A2','C1','N1')
or c2 in ('K1','A2','C1','N1')
or c3 in ('K1','A2','C1','N1') order by sortweight desc
,c1
,c2
,c3
Someone from other forum suggested the above query
Is there a way to loop over multiple lists in parallel in a makefile or CMake file?
I would like to do something like the following in CMake, except AFAICT this syntax isn't supported:
set(a_values a0 a1 a2)
set(b_values b0 b1 b2)
foreach(a in a_values b in b_values)
do_something_with(a b)
endforeach(a b)
This would execute:
do_something_with(a0 b0)
do_something_with(a1 b1)
do_something_with(a2 b2)
I would accept an answer in either CMake or Make, though CMake would be preferred. Thanks!
Here you go:
set(list1 1 2 3 4 5)
set(list2 6 7 8 9 0)
list(LENGTH list1 len1)
math(EXPR len2 "${len1} - 1")
foreach(val RANGE ${len2})
list(GET list1 ${val} val1)
list(GET list2 ${val} val2)
message(STATUS "${val1} ${val2}")
endforeach()
As of CMake 3.17, the foreach() loop supports a ZIP_LISTS option to iterate through two (or more) lists simultaneously:
set(a_values a0 a1 a2)
set(b_values b0 b1 b2)
foreach(a b IN ZIP_LISTS a_values b_values)
message("${a} ${b}")
endforeach()
This prints:
a0 b0
a1 b1
a2 b2
In make you can use the GNUmake table toolkit to achieve this by handling the two lists as 1-column tables:
include gmtt/gmtt.mk
# declare the lists as tables with one column
list_a := 1 a0 a1 a2 a3 a4 a5
list_b := 1 b0 b1 b2
# note: list_b is shorter and will be filled up with a default value
joined_list := $(call join-tbl,$(list_a),$(list_b), /*nil*/)
$(info $(joined_list))
# Apply a function (simply output "<tuple(,)>") on each table row, i.e. tuple
$(info $(call map-tbl,$(joined_list),<tuple($$1,$$2)>))
Output:
2 a0 b0 a1 b1 a2 b2 a3 /*nil*/ a4 /*nil*/ a5 /*nil*/
<tuple(a0,b0)><tuple(a1,b1)><tuple(a2,b2)><tuple(a3,/*nil*/)><tuple(a4,/*nil*/)><tuple(a5,/*nil*/)>