PDDL - invalid predicates and correct usage of forall - artificial-intelligence

I am new to pddl planning and now I am trying to create a domain and problem file as an exercise.
Short domain description: I have a couple of cars which can be taken and put at places A and B. The task is simple: take all the cars from place A and move them to place B.
I created the following domain file:
(define (domain test) ; Domain name must match problem's
; Define what the planner must support to execute this domain
; Only domain requirements are currently supported
( :requirements
:strips
:negative-preconditions
:equality
:typing
:adl
)
(:types
car
place
)
(:predicates
(at ?o - car ?p - place )
(taken ?o - car )
)
(:action take
:parameters (?o1 - car ?o2 - place )
:precondition (and
(at ?o1 ?o2)
(not (taken ?o1))
)
:effect (and
(not (at ?o1 ?o2 ))
(taken ?o1)
)
)
(:action put
:parameters (?o1 - car ?o2 - place )
:precondition (and
(not (at ?o1 ?o2))
(taken ?o1)
)
:effect (and
(at ?o1 ?o2)
(not (taken ?o1) )
)
)
(:action takeAll
:parameters ()
:precondition (forall (?c - car ?p - place)
(and
(at ?c ?p)
(not (taken ?c))
)
)
:effect (forall (?c - car)
(taken ?c)
)
)
)
The problem file looks like this:
(define (problem test)
(:domain test)
(:objects
c1 - car
c2 - car
c3 - car
A - place
B - place
)
(:init
(at c1 A)
(at c2 A)
(at c3 A)
(not (taken c1))
(not (taken c2))
(not (taken c3))
)
(:goal (and
(at c1 B)
(at c2 B)
(at c3 B)
)
)
)
I am using the online planner and solver available here
and I am wondering why it outputs that I have several invalid predicates
test
takeall precondition contains ["forall", ["?c", "-", "car", "?p", "-", "place"], ["and", ["at", "?c", "?p"], ["not", ["taken", "?c"]]]], not a valid predicate
takeall effect contains ["forall", ["?c", "-", "car"], ["taken", "?c"]], not a valid predicate
:equality requirement is unnecessary
test
Initial state contains ["not", ["taken", "c1"]], not a valid predicate
Initial state contains ["not", ["taken", "c2"]], not a valid predicate
Initial state contains ["not", ["taken", "c3"]], not a valid predicate
Could someone explain to me what exactly I am doing wrong?
With the takeAll action I wanted to experiment a bit with forall. And it should be interpreted like this: the preconditions says that all objects of type car are not in a state taken and are at some place.
The effect should be that all cars are in a state taken.
The shortest solution should be (according to my common sense) takeAll, put(c1, B), (put c2, B), (put c3, B)
I appreciate your help!

You're doing classical planning, which means that the initial state only needs to specify what's true (everything else is assumed to be false). Remove those negative fluents from your init, and it may work out.

Related

AHK: Copying a block of text into an array, modifying, and transferring to another array

Alright so the question is hard to word. I've googled this several times, but usually it turns out I'm not googling the right phrases, and the answer is readily available. I do work as a medical biller for a doctors office, and I have to include diagnosis codes for the office visits. In the Electronic Medical Record program, there's a diagnosis list. The first line is the doctors description, I don't care about that. The second line is an ICD-9 code. Those are old, I don't care about those either. The third line (every third line) contains the ICD-10 code. That's what I need. What I'd like to be able to do is grab the whole list, dump it into an array delimited by new lines, and get rid of every element that doesn't contain a specific string. Then, dump all the kept elements into another array (or the same one, but not separated by 3 like they would be after the removals) and remove that prefixed string that I kept elements based on. After that, I need to click a specific spot (I know how to do this), add exactly four of the arrays elements as text (can't figure this out), hit enter, and keep adding and hitting enter until I've entered all of the array. I will post what I've tried cobble together from google searches if anyone wants to see that mess. But a general explanation on how to do this would also be appreciated. Thanks.
first of all, the stuff I'd be copying would look like this (actual example)
Lumbar stenosis - Primary
ICD-9-CM: 724.02
ICD-10-CM: M48.06
Spondylolisthesis of lumbar region
ICD-9-CM: 738.4
ICD-10-CM: M43.16
Lumbar degenerative disc disease
ICD-9-CM: 722.52
ICD-10-CM: M51.36
Chronic bilateral low back pain with bilateral sciatica
ICD-9-CM: 724.2, 724.3, 338.29
ICD-10-CM: M54.42, M54.41, G89.29
Naturally the list would be much longer.
The string I'd look for to keep the lines would be "ICD-10-CM: ", just so you guys know. I DID try using it as a delimiter, in quotes, but got some really quite weird results. It would have made this problem slightly easier to solve had that worked as the delimiter.
Arrays:={}
RealArray:={}
^j::
sendinput, ^c
sleep 20
bigone:=ClipBoard
sleep 2000
;StringReplace, bigone, newbigone, `n, "DLMTR", All
;Arrays:= StrSplit(newbigone, "DLMTR")
StringSplit, Arrays, bigone, `n
k=4
j=1
loop
{
if (k<Arrays.Max_Index)
{
RealArray%j%=Arrays%k%
j++
k++
k++
k++
}
else
return
}
return
^L::
a=0
loop
{
if (a<RealArray.Max_Index)
{
send RealArray%a%
a++
sendinput, {Space}
if(mod(a,5)==0)
sendinput, {enter}
}
else
return
}
Program
^j collects codes containing "ICD-10", ^k pastes the codes formatted 5 per line
^j::copyit()
^l::pasteit()
copyit()
{
sendinput, ^c
sleep 20
bigone := ClipBoard
sleep 100
global matches
matches := []
numMatches := 0
Loop parse, bigone, `n
Loop parse, A_LoopField, `,
if InStr(A_LoopField, "ICD-10")
matches[++numMatches] := trim( substr(A_LoopField, InStr(A_LoopField, ":") + 1), " `t`n`r")
}
pasteit()
{
global matches
for index, element in matches
{
Send %element%{SPACE}
if mod(index,5) == 0
Send {ENTER}
}
}
Input:
Recurrent major depressive disorder, in partial remission
ICD-9-CM: 296.35
ICD-10-CM: F33.1
ICD-10-CM: F33.2
ICD-9-CM: 296.35
ICD-10-CM: F33.3
ICD-10-CM: F33.4
ICD-9-CM: 296.35
ICD-10-CM: F33.5, ICD-10-CM: X432.6, ICD-10-CM: Y232.6
ICD-10-CM: F33.6
ICD-9-CM: 296.35
Output:
F33.1 F33.2 F33.3 F33.4 F33.5
X432.6 Y232.6 F33.6
Without knowing how the underlying program that you are automating works, I can't tell you when to sleep or send extra ENTERs.
Maybe you can query the state of the screen to determine what to do next (e.g., send codes, extra ENTERs, wait).
I identify the screen state by searching for a small image that uniquely identifies the state the program is in. I make the images using Alt+PrintScrn to capture the entire screen and then use pbrush.exe to crop out small a unique identifying image.
; Search screen for image stored in "images/name.png"
; return true if found, false otherwise
find( name )
{
fname := "images\" . name . ".png"
ImageSearch x, y, 0,0,A_ScreenWidth, A_ScreenHeight, *32 %fname%
return ( ErrorLevel = 0 and x >= 0 and y >= 0 )
}
; Wait for image stored in "images/name.png" to appear on the screen
wait_for( name )
{
tooltip Waiting for %name%, 100,0,1
while !find(name)
sleep 100
}
; business/domain logic bot
automate_screen()
{
if ( find( "logon" ))
do_stuff_to_logon()
else if ( find( "payroll_history" ))
do_some_other_stuff()
else if ( find( "payroll_screen1" ))
{
sendplay Type this on screen1{enter}01{enter}
wait_for( "payroll_screen2" )
sendplay Type this on screen2{enter}
}
}
main()
{
loop
{
automate_screen()
sleep 250
}
}

Get column values from a Haskell Database

Here's the problem. Let it be known that I'm very new to Haskell and the declarative language part is totally different from what I'm used to. I've made a database of sorts, and the user can input commands like "Add (User "Name")" or "Create (Table "Funding")". I'm trying to create a function that takes as parameters a list of commands, a User, a Table, a Column name (as a string), and returns a list containing the values in that column if the user has access to them (i.e. somewhere in the list of commands there is one that matches "Allow (User name) (Table "Funds")". We can assume the table exists.
module Database where
type Column = String
data User = User String deriving (Eq, Show)
data Table = Table String deriving (Eq, Show)
data Command =
Add User
| Create Table
| Allow (User, Table)
| Insert (Table, [(Column, Integer)])
deriving (Eq, Show)
-- Useful function for retrieving a value from a list
-- of (label, value) pairs.
lookup' :: Column -> [(Column, Integer)] -> Integer
lookup' c' ((c,i):cvs) = if c == c' then i else lookup' c' cvs
lookupColumn :: [(Column, Integer)] -> [Integer]
lookupColumn ((c, i):cvs) = if null cvs then [i] else [i] ++ lookupColumn cvs
select :: [Command] -> User -> Table -> Column -> Maybe [Integer]
select a b c d = if not (elem (b, c) [(g, h) | Allow (g, h) <- a])
then Nothing
else Just (lookupColumn [(d, x) | Insert (c, [ (d, x ), _ ]) <- a])
I have gotten it to work, but only in very select cases. Right now, the format of the input has to be such that the column we want the values from must be the first column in the table. Example input is below. Running: select example (User "Alice") (Table "Revenue") "Day" returns Just [1,2,3] like it should, but replacing Day with Amount doesn't work.
example = [
Add (User "Alice"),
Add (User "Bob"),
Create (Table "Revenue"),
Insert (Table "Revenue", [("Day", 1), ("Amount", 2400)]),
Insert (Table "Revenue", [("Day", 2), ("Amount", 1700)]),
Insert (Table "Revenue", [("Day", 3), ("Amount", 3100)]),
Allow (User "Alice", Table "Revenue")
]
A bit of explanation about the functions. select is the function which should return the list of integers in that column. Right now, it's only matching the first column, but I'd like it to work with any number of columns, not knowing which column the user wants ahead of time.
[(d, x) | Insert (c, [ (d, x ), _ ]) <- a] returns a list of tuples that match only the first tuple in each list of (Column, Integer) tuples.
lookupColumn takes in a list of tuples and returns a list of the integers within it. Unlike lookup', we know that the list this takes in has only the correct column's (Column, Integer) tuples within it. lookup' can take in a list of any number of tuples, but must check if the column names match first.
Any help at all would be greatly appreciated.
There are a couple strange things in your code; for example:
lookupColumn :: [(Column, Integer)] -> [Integer]
lookupColumn ((c, i):cvs) = if null cvs then [i] else [i] ++ lookupColumn cvs
is much longer to type in every way than the equivalent (and probably faster) map snd.
Furthermore when you're defining your own data structures often tuples are superfluous; you could just write:
data Command = Add User
| Create Table
| Allow User Table
| Insert Table [(Column, Integer)]
deriving (Eq, Show)
The actual problem is the _ in your select statement which explicitly tells Haskell to throw away the second value of the tuple. Instead you want something which grabs all (Column, Integer) pairs that are associated with a table:
getCells :: [Command] -> Table -> [(Column, Integer)]
getCells db t = concat [cis | Insert t' cis <- filter isInsert db, t == t']
where isInsert (Insert _ _) = True
isInsert _ = False
(note that this is using the un-tupled version of Insert that I wrote above). With this the algorithm becomes much easier:
select :: [Command] -> User -> Table -> Column -> Maybe [Integer]
select db user table col
| Allow user table `elem` db = Just [i | (c, i) <- getCells db t, col == c]
| otherwise = Nothing
What's doing the majority of the "work" here? Actually it's just the concat :: [[a]] -> [a] that we used in getCells. By concatenating together all of the (Column, Integer) pairs for all of the rows/cols in the table, we have a really easy time of pulling out only the column that we need.
Todo: stop this code from doing something unexpected when someone says Insert (Table "Revenue") [("Amount", 1), ("Amount", 2400)], which will appear in the output as two rows even though it only comes from one row. You can either normalize-on-input, which will do pretty well, or return [Maybe Integer], giving nulls for the rows which do not have a value (lookup in the standard Prelude will take the place of concat in doing your work for you).

NDB Query Chaining oddity - Order + Inequality?

I just spent a few hours debugging something that seems odd. However, I can't tell if it is a bug or I'm just doing something wrong. Short version, it seems if I have an inequality filter on an NDB query AND an order, they must be the same line.
Note: All the data shown below was created in order, even though I was futzing with the dates in the datastore so some do not have microseconds.
#Q1. Yields the correct results:
q = BlogPost.query().filter(BlogPost.published_date > PUBLISHED_DATE_MIN).order(-BlogPost.published_date)
for p in q.fetch(1000):
print "%s - %s" % (p.published_date, p.title)
# 2014-03-02 21:49:25 - First
# 2014-03-01 22:51:14.998963 - Should be 2nd
# 2014-03-01 21:49:54.273152 - Should be Third
Here is what I initially had. Note: order is on separate line
q = BlogPost.query().filter(BlogPost.published_date > PUBLISHED_DATE_MIN)
q.order(-BlogPost.published_date)
for p in q.fetch(1000):
print "%s - %s" % (p.published_date, p.title)
# 2014-03-01 21:49:54.273152 - Should be Third
# 2014-03-01 22:51:14.998963 - Should be 2nd
# 2014-03-02 21:49:25 - First
The NDB query appears to just be unordered or reverse ordered, however, then I remove the inequality and I get:
q = BlogPost.query() #.filter(BlogPost.published_date > PUBLISHED_DATE_MIN)
q.order(-BlogPost.published_date)
for p in q.fetch(1000):
print "%s - %s" % (p.published_date, p.title)
# 2014-03-02 21:49:25 - First
# 2014-03-01 22:51:14.998963 - Should be 2nd
# 2014-03-01 21:49:54.273152 - Should be Third
I am seeing this behavior in the sdk console as well as the remote console and on the actual appspot when I deploy my code. Is this a bug (not likely) or something I am missing?
When you run q.order(-BlogPost.published_date) it creates and returns a new query which you aren't assigning to anything.
You want to have:
q = q.order(-BlogPost.published_date)

Prolog Database: Why is program only running once?

I got this code that has to run a database as long as N > Order.
My code only runs once :/ ?
display(N) :-
w(Order,_,Word,Class),
N > Order -> (write(Word), write(' '), write(Class)),
nl, fail .
Thanks in advance!
your problem is the way you use ->
First of all, the code is interpreted as:
display(N) :-
( w(Order,_,Word,Class),
N > Order )
) ->
( write(Word),
write(' '),
write(Class)
),
nl, fail .
-> destroys choice points meaning that it will not try to call w/3 again.
You could (probably) make it work like this:
display(N) :-
(w(Order,_,Word,Class),
N > Order )-> (write(Word), write(' '), write(Class)),
nl, fail .
but in the end it's really ugly code and, as you have seen, prone to bugs. A better way is to use forall/2:
display2(N) :-
forall(w(Order, _, Word, Class),
(N > Order ->
writef("%t %t \n", [Word,Class]); true)).
still, this will examine the whole database and print if N>Order. It is a bit unclear from your description if this is the desired behaviour but if you want to stop at the first element that is larger you could do something like:
display2(N) :-
catch((forall(w(Order, _, Word, Class),
(N > Order ->
writef("%t %t \n", [Word,Class]); throw(end))), end, true)).
not the most declarative way to do it but I'm not sure what's the best way to model it without knowing what w/4 is (I assumed that it is some prolog clauses but it could be a predicate accessing a DB though the ODBC layer)
I think you forgot the 'else' branch, and the precedence of (->)/2, that's higher that (,)/2, inhibits the intended order. Try
display(N) :-
w(Order,_,Word,Class),
( N > Order -> write(Word), write(' '), write(Class), nl ; true ),
fail .

"if, then, else" in SQLite

Without using custom functions, is it possible in SQLite to do the following. I have two tables, which are linked via common id numbers. In the second table, there are two variables. What I would like to do is be able to return a list of results, consisting of: the row id, and NULL if all instances of those two variables (and there may be more than two) are NULL, 1 if they are all 0 and 2 if one or more is 1.
What I have right now is as follows:
SELECT
a.aid,
(SELECT count(*) from W3S19 b WHERE a.aid=b.aid) as num,
(SELECT count(*) FROM W3S19 c WHERE a.aid=c.aid AND H110 IS NULL AND H112 IS NULL) as num_null,
(SELECT count(*) FROM W3S19 d WHERE a.aid=d.aid AND (H110=1 or H112=1)) AS num_yes
FROM W3 a
So what this requires is to step through each result as follows (rough Python pseudocode):
if row['num_yes'] > 0:
out[aid] = 2
elif row['num_null'] == row['num']:
out[aid] = 'NULL'
else:
out[aid] = 1
Is there an easier way? Thanks!
Use CASE...WHEN, e.g.
CASE x WHEN w1 THEN r1 WHEN w2 THEN r2 ELSE r3 END
Read more from SQLite syntax manual (go to section "The CASE expression").
There's another way, for numeric values, which might be easier for certain specific cases.
It's based on the fact that boolean values is 1 or 0, "if condition" gives a boolean result:
(this will work only for "or" condition, depends on the usage)
SELECT (w1=TRUE)*r1 + (w2=TRUE)*r2 + ...
of course #evan's answer is the general-purpose, correct answer

Resources