minimize in metric pddl - dsl

I created the pddl domain for the figure here
However, when trying to reach the node number 7 the output of the Metric-ff planner is cost = 21 insted of 15
also for the node 5 the cost = 16 insted of 10
it seems it minimizes the number of steps insted of the cost
can some one help?
(define (problem petriproblem)
(:domain petri)
(:objects
token - token
spring summer fall winter - place
)
(:init
(at token spring)
(= (initial-token token) 3)
(connected token spring summer)
(connected token summer fall)
(connected token fall winter)
(connected token winter spring)
(= (required-token spring summer) 1)
(= (required-token summer fall) 1)
(= (required-token fall winter) 1)
(= (total-tokens-used) 0) )
(:goal
(at token winter)
)
(:metric minimize
(total-tokens-used)
)
)
------------------------------------------------------------------------
(define (problem nodes)
(:domain petri)
(:objects
token - token
node1 node2 node3 node4 node5 node6 node7 - place
)
(:init
(at token node1)
(= (initial-token token) 1000)
(connected token node1 node2)
(connected token node2 node4)
(connected token node3 node5)
(connected token node4 node3)
(connected token node4 node5)
(connected token node4 node6)
(connected token node4 node7)
(connected token node6 node7)
(= (required-token node1 node2) 2)
(= (required-token node2 node4) 4)
(= (required-token node3 node5) 2)
(= (required-token node4 node3) 2)
(= (required-token node4 node5) 10)
(= (required-token node4 node6) 4)
(= (required-token node4 node7) 15)
(= (required-token node6 node7) 5)
(= (total-tokens-used) 0)
)
(:goal
(at token node5)
)
(:metric minimize
(total-tokens-used)
)
)

Related

How to access sub-struct variables in Racket (Lisp/Scheme)

I'm trying to write an AM/PM clock conversion function to a 24 hour clock (military time), but there's a struct and sub-struct that have variables I can't figure out how to pull. Neither 24HourClock-hours or AM/PM-hours is working to pull the hours or minutes variable out of the AM/PM instance of time that goes as the parameter of each of the two versions of the function.
The following two functions are two separate attempts at the same function:
(define (AM/PM->24HourClock2 time)
(cond
[(isAM? time) (24HourClock (24HourClock-hours 24HourClock-minutes))]
[else (24HourClock (+ 24HourClock-hours 12) 24HourClock-minutes)]))
(define (AM/PM->24HourClock time)
(cond
[(isAM? time) (24HourClock (AM/PM-hours AM/PM-minutes))]
[else (24HourClock (+ AM/PM-hours 12) AM/PM-minutes)]))
This one attempts to use a lambda function to access the sub-members:
(define (AM/PM->24HourClock time)
(lambda (hr min meridiem)
(cond
[(isAM? time) (24HourClock (hr min))]
[else (24HourClock (+ hr 12) min)]))
But here's the output:
Here's the earlier code that makes it reproducible:
#lang slideshow
(struct 24HourClock (hours minutes)
#:transparent
#:mutable
#:guard (lambda (hours minutes err_name)
(if (not (and (>= hours 0) (< hours 24)))
(error err_name "Hours must be between 0 and 24")
(if (not (and (>= minutes 0) (< minutes 60)))
(error err_name "Minutes must be between 0 and 60")
(values hours minutes)))))
(struct AM/PM 24HourClock (meridiem)
#:transparent
#:mutable
#:guard (lambda (hours minutes meridiem err_name)
(if (not(and(and(number? hours)(> hours 0)(<= hours 12)(number? minutes))))
(error err_name "Hours must be between 1 and 12 : 0")
(if [not (and(string? meridiem)(or
(equal? meridiem "am")
(equal? meridiem "AM")
(equal? meridiem "pm")
(equal? meridiem "PM")))]
(error err_name "Invalid value for meridiem")
(values hours minutes meridiem)))))
(define (isAM? time)
(or (equal? (AM/PM-meridiem time) "AM")
(equal? (AM/PM-meridiem time) "am")))
It should be rather
(define (AM/PM->24HourClock2 time)
(cond
[(isAM? time) (24HourClock (AM/PM-hours time) (AM/PM-minutes time))]
[else (24HourClock (+ (AM/PM-hours time) 12) (AM/PM-minutes time))]))
(define (AM/PM->24HourClock time)
(let ((hr (AM/PM-hours time))
(min (AM/PM-minutes time))
(mer (AM/PM-meridiem time)))
(cond
[(isAM? time) (24HourClock hr min)]
[else (24HourClock (+ hr 12) min)])))
But since AM/PM-hours and AM/PM-minutes are not defined when defining like you did here with 24HourClock as super class, you have to write:
(define (AM/PM->24HourClock2 time)
(cond
[(isAM? time) (24HourClock (24HourClock-hours time) (24HourClock-minutes time))]
[else (24HourClock (+ (24HourClock-hours time) 12) (24HourClock-minutes time))]))
(define (AM/PM->24HourClock time)
(let ((hr (24HourClock-hours time))
(min (24HourClock-minutes time))
(mer (AM/PM-meridiem time)))
(cond
[(isAM? time) (24HourClock hr min)]
[else (24HourClock (+ hr 12) min)])))
Your problem is that you think struct-slot is itself the value of slot in struct. But it isn't. It is just the getter function for the slot in struct. Therefore, you have to do (struct-slot instance) to get the value of slot in the instance which is of the type struct.
If you want AM/PM->24HourClock, then time is of the type AM/PM.
This is all code put together, it's the same as your response and what was shown:
#lang slideshow
(struct 24HourClock (hours minutes) #:transparent #:mutable
#:guard (lambda (hours minutes err_name)
(if (not (and (>= hours 0) (< hours 24)))
(error err_name "Hours must be between 0 and 24")
(if (not (and (>= minutes 0) (< minutes 60)))
(error err_name "Minutes must be between 0 and 60")
(values hours minutes)))))
(struct AM/PM 24HourClock (meridiem) #:transparent #:mutable
#:guard (lambda (hours minutes meridiem err_name)
(if (not(and(and(number? hours)(> hours 0)(<= hours 12)(number? minutes))))
(error err_name "Hours must be between 1 and 12 : 0")
(if [not (and(string? meridiem)(or
(equal? meridiem "am")
(equal? meridiem "AM")
(equal? meridiem "pm")
(equal? meridiem "PM")))]
(error err_name "Invalid value for meridiem")
(values hours minutes meridiem)))))
(define (isAM? time)
(or (equal? (AM/PM-meridiem time) "AM")
(equal? (AM/PM-meridiem time) "am")))
(define (AM/PM->24HourClock time)
(let ((hr (AM/PM-hours time))
(min (AM/PM-minutes time))
(cond
[(isAM? time) (24HourClock hr min)]
[else (24HourClock (+ hr 12) min)])))
Here's what I use for test cases:
;=======================
; Test Cases
;=======================
; (24HourClock 0 20)
; (24HourClock 24 20)
; (24HourClock 11 60)
; (AM/PM 0 20 "AM")
; (AM/PM 1 20 "Am")
; (AM/PM 2 20 "am")
; (is-AM? 2 20 "am")
; (AM/PM->24HourClock (AM/PM 0 10 "AM"))
; (AM/PM->24HourClock (AM/PM 12 10 "am"))

PDDL temporal modelling help: how to change numeric value in the background?

I'm trying to model and RTS game (AOE2) for an optimal build order and plan using OPTIC. My thought is to represent villagers (workers) as a function, then resources increase depending on the number of villagers. This action works, but I believe is inefficient and the plans are not optimal:
(:durative-action collect_resource
:parameters (?r - resource) ;wood, food etc.
:duration (= ?duration 10)
:condition (and
(at start (> (workers ?r) 0))
(at start (idle ?r))
)
:effect (and
(at start (not (idle ?r)))
(at start (working ?r))
(at end (idle ?r))
(at end (not (working ?r)))
(at end (increase (amount ?r) (* (collect_rate ?r)(workers ?r))))
)
)
I tried this PDDL Durative-Action: Flexible duration, but OPTIC doesn't support non-linear numeric conditions:
(increase (amount ?r) (* (#t)(* (collect_rate ?r)(workers ?r)))
Does anyone have any suggestions for a better approach?
EDIT (error message):
Unfortunately, the planner does not supported non-linear numeric conditions,
effects, or duration constraints, but one or more of these is present in
the problem you have provided. Specifically, the sub-expression:
(3*(workers lumber1)) * (#t)
... was encountered. To use this planner with your problem, you will have
to reformulate it to avoid these.
Domain:
(define (domain aoe2)
(:requirements :strips :typing :fluents :durative-actions :timed-initial-literals)
(:types
location society - object
resource building - location
town_center barracks - building
lumber berries sheep gold - resource
)
(:predicates
(working ?l - location)
(idle ?l - location)
)
(:functions
(idle_villagers ?s - society)
(train_villager_time ?s - society)
(workers ?r - resource)
(walk_time ?r - resource)
(collect_rate ?r - resource)
(amount ?r - resource)
)
(:durative-action train_villager
:parameters (?tc - town_center ?s - society)
:duration (= ?duration (train_villager_time ?s))
:condition (and
(at start (idle ?tc))
)
:effect (and
(at start (not (idle ?tc)))
(at start (working ?tc))
(at end (idle ?tc))
(at end (not (working ?tc)))
(at end (increase (idle_villagers ?s) 1))
)
)
(:durative-action send_idle_to_resource
:parameters (?r - resource ?s - society)
:duration (= ?duration (walk_time ?r))
:condition (and
(at start (> (idle_villagers ?s) 0))
)
:effect (and
(at start (decrease (idle_villagers ?s) 1))
(at end (increase (workers ?r) 1))
)
)
(:action send_resource_to_idle
:parameters (?r - resource ?s - society)
:precondition (and
(> (workers ?r) 0)
)
:effect (and
(increase (idle_villagers ?s) 1)
(decrease (workers ?r) 1)
)
)
(:durative-action collect_resource
:parameters (?r - resource)
:duration (= ?duration 10)
:condition (and
(at start (> (workers ?r) 0))
(at start (idle ?r))
)
:effect (and
(at start (not (idle ?r)))
(at start (working ?r))
(at end (idle ?r))
(at end (not (working ?r)))
(at end (increase (amount ?r) (* (collect_rate ?r)(workers ?r))))
)
)
)
Problem
(define (problem dark_age)
(:domain aoe2)
(:requirements :strips :typing :fluents :durative-actions :timed-initial-literals)
(:objects
tc1 - town_center
mysociety - society
lumber1 - lumber
sheep1 - sheep
)
(:init
(= (train_villager_time mysociety) 25)
(= (idle_villagers mysociety) 0)
(idle tc1)
(= (workers lumber1) 0)
(= (walk_time lumber1) 5)
(= (collect_rate lumber1) 3)
(= (amount lumber1) 0)
(idle lumber1)
(= (workers sheep1) 5)
(= (walk_time sheep1) 0)
(= (collect_rate sheep1) 3)
(= (amount sheep1) 0)
(idle sheep1)
)
(:goal
(and
; (= (idle_villagers mysociety) 1)
; (> (workers lumber1) 1)
(> (amount lumber1) 600)
(> (amount sheep1) 600)
)
)
)

Not overwriting *standard-input* prevents multi-threading

I have a Common Lisp program that behaves differently depending on how I use *standard-input*. Here are the details:
(if input-stream?
(process)
(with-open-file (*standard-input* up :element-type 'unsigned-byte)
(process)))
The process function starts multiple threads. Each thread reads part of the standard input, writes it in a file (all within a lock) and processes the resulting files in parallel (out of the lock). In fact it processes the resulting files in parallel only in case input-stream? is false otherwise it processes them sequentially.
(defun process ()
(let ((psize 4194304)
(stream *standard-input*)
(result-lock (bt:make-lock))
(input-stream-lock (bt:make-lock))
eof)
(flet ((add-job (fname)
(make-thread
#'(lambda ()
(do () (eof)
(when (bt:with-lock-held (input-stream-lock)
(unless eof
(setq eof (write-input-stream-to-file stream fname psize))
t))
(sleep 0.1)
(bt:with-lock-held (result-lock)
(display-progress))))))))
(mapcar
#'join-thread
(loop for i from 1 to 10
collect (add-job
(make-pathname :directory "/tmp"
:name "test"
:type (princ-to-string i))))))))
(let ((counter 0))
(defun display-progress ()
(if (zerop (mod (incf counter) 10))
(format t " ~a " counter)
(write-char #\+))))
(defun write-input-stream-to-file (stream fname psize-bytes)
(with-open-file (out fname
:direction :output
:element-type 'unsigned-byte
:if-exists :supersede)
(do ((byte (read-byte stream nil nil)
(read-byte stream nil nil))
(offset 0 (1+ offset)))
((or (= offset psize-bytes) (null byte)) (not byte))
(write-byte byte out))))
If we create a FIFO (with mkfifo), copy the file to it and run the program with it instead, we again observe parallelism.
The above program is built as a command line utility with ECL and runs on Linux. I run it in one of the following ways:
cat "bigfile" | my-program
my-program "bigfile"
Parallelism happens only in case 2.
The question is why the difference?
Update:
I had mistake in my question. Now it is OK.
Added the process function and described how I run the program

Why isn't a very big Spark stage using all available executors?

I am running a Spark job with some very big stages (e.g. >20k tasks), and am running it with 1k to 2k executors.
In some cases, a stage will appear to run unstably: many available executors become idle over time, despite still being in the middle of a stage with many unfinished tasks. From the user perspective, it appears that tasks are finishing, but executors that have finished a given task do not get a new task assigned to them. As a result, the stage takes longer than it should, and a lot of executor CPU-hours are being wasted on idling. This seems to mostly (only?) happen during input stages, where data is being read from HDFS.
Example Spark stderr log during an unstable period -- notice that the number of running tasks decreases over time until it almost reaches zero, then suddenly jumps back up to >1k running tasks:
[Stage 0:==============================> (17979 + 1070) / 28504]
[Stage 0:==============================> (18042 + 1019) / 28504]
[Stage 0:===============================> (18140 + 921) / 28504]
[Stage 0:===============================> (18222 + 842) / 28504]
[Stage 0:===============================> (18263 + 803) / 28504]
[Stage 0:===============================> (18282 + 786) / 28504]
[Stage 0:===============================> (18320 + 751) / 28504]
[Stage 0:===============================> (18566 + 508) / 28504]
[Stage 0:================================> (18791 + 284) / 28504]
[Stage 0:================================> (18897 + 176) / 28504]
[Stage 0:================================> (18940 + 134) / 28504]
[Stage 0:================================> (18972 + 107) / 28504]
[Stage 0:=================================> (19035 + 47) / 28504]
[Stage 0:=================================> (19067 + 17) / 28504]
[Stage 0:================================> (19075 + 1070) / 28504]
[Stage 0:================================> (19107 + 1039) / 28504]
[Stage 0:================================> (19165 + 982) / 28504]
[Stage 0:=================================> (19212 + 937) / 28504]
[Stage 0:=================================> (19251 + 899) / 28504]
[Stage 0:=================================> (19355 + 831) / 28504]
[Stage 0:=================================> (19481 + 708) / 28504]
This is what the stderr looks like when a stage is running stably -- the number of running tasks remains roughly constant, because new tasks are assigned to executors as they finish their previous tasks:
[Stage 1:===================> (11599 + 2043) / 28504]
[Stage 1:===================> (11620 + 2042) / 28504]
[Stage 1:===================> (11656 + 2044) / 28504]
[Stage 1:===================> (11692 + 2045) / 28504]
[Stage 1:===================> (11714 + 2045) / 28504]
[Stage 1:===================> (11741 + 2047) / 28504]
[Stage 1:===================> (11771 + 2047) / 28504]
[Stage 1:===================> (11818 + 2047) / 28504]
Under what circumstances would this happen, and how can I avoid this behavior?
NB: I am using dynamic allocation, but I'm pretty sure this is unrelated to this problem -- e.g., during an unstable period, in the Spark Application Master UI I can see that the expected number of executors are "Active", but are not running "Active Tasks."
I've seen behavior like this from spark when the amount of time taken per task is very low. For some reason, the scheduler seems to assume that the job will complete faster without the extra distribution overhead, since each task is completing so quickly.
A couple of things to try:
Try .coalesce() to reduce the number of partitions, so that each partition takes longer to run (granted, this could cause a shuffle step and may increase overall job
time, you'll have to expiriment)
Tweak the spark.locality.wait* settings here. If each task takes less than the default wait times of 3s, then perhaps the scheduler is just trying to keep the existing slots full and never has a chance to allocate more slots.
I've yet to track down exactly what causes this issue, so these are only speculations and hunches based on my own observations in my own (much smaller) cluster.

compilation unit aborted, caught 1 fatal ERROR condition?

I have some common lisp code that is behaving oddly. It's a TCP client/server application.
Unless I add (sleep 0.01) or similar at the end of my code, I get the following utterly unhelpful error message after my program completes. It is a very short-lived program, simply hosting a TCP server and testing that it can be connected to.
;; compilation unit aborted; caught 1 fatal ERROR condition
This doesn't happen every time, maybe 80% of the runs cause this. There is no context, no explanation.
Code to reproduce the problem:
(defmacro with-gensyms ((&rest names) &body body)
`(let ,(loop for n in names collect `(,n (gensym)))
,#body))
(defmacro kilobytes (qty)
(* qty 1024))
(defun is-sequence (sequence)
(or (listp sequence) (vectorp sequence)))
(defmacro append-to (seq values)
(with-gensyms (cached-values)
`(let ((,cached-values ,values))
(cond
((is-sequence ,cached-values)
(setf ,seq (append ,seq (coerce ,cached-values 'list))))
(t
(setf ,seq (append ,seq (list ,cached-values))))))))
(defmacro remove-from (seq value)
(with-gensyms (cached-value)
`(let ((,cached-value ,value))
(delete-if (lambda (value) (equalp value ,cached-value)) ,seq))))
(defclass tcp-server ()
((server-socket :initform nil)
(server-threads :initform (list))))
(defgeneric start-server (this &key port bind-address buffer-length))
(defmethod start-server ((this tcp-server) &key (port 0) (bind-address #(127 0 0 1)) (buffer-length (kilobytes 10)))
(with-slots (server-socket server-threads) this
(when server-socket
(error "Server already running"))
(let ((backlog 5))
(setf server-socket (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp))
(sb-bsd-sockets:socket-bind server-socket bind-address port)
(sb-bsd-sockets:socket-listen server-socket backlog)
(flet ((handle-connection (client-socket)
(let ((buffer (make-array buffer-length :element-type '(unsigned-byte 8) :fill-pointer t)))
(catch 'eof
(loop
while (sb-bsd-sockets:socket-open-p client-socket)
do (let ((length (nth-value 1 (sb-bsd-sockets:socket-receive client-socket buffer nil))))
(when (eq 0 length)
(throw 'eof nil)))))
(sb-bsd-sockets::socket-close client-socket)
(remove-from server-threads sb-thread:*current-thread*))))
(sb-thread:make-thread
(lambda ()
(loop
while (and server-socket (sb-bsd-sockets:socket-open-p server-socket))
do
(let ((client-socket (sb-bsd-sockets:socket-accept server-socket))) ;; Listen for incoming connections
(append-to server-threads
(sb-thread:make-thread #'handle-connection :name "Connection handler" :arguments client-socket)))) ;; Spawn a process to handle the connection))
(remove-from server-threads sb-thread:*current-thread*))
:name "Server")))
nil))
(defun start-tcp-server (&key (port 0) (bind-address #(127 0 0 1)) (buffer-length (kilobytes 10)))
(let ((server (make-instance 'tcp-server)))
(start-server server :port port :bind-address bind-address :buffer-length buffer-length)
server))
(defgeneric stop-server (this))
(defmethod stop-server ((this tcp-server))
(with-slots (server-socket server-threads) this
(unless server-socket
(error "Server not running"))
(sb-bsd-sockets:socket-close server-socket)
(setf server-socket nil)
(loop for thread in (reverse server-threads)
; do (sb-thread:interrupt-thread thread 'sb-thread:abort-thread))
do (sb-thread:terminate-thread thread))
(loop for thread in (reverse server-threads)
do (sb-thread:join-thread thread :default nil))))
(defgeneric server-running? (this))
(defmethod server-running? ((this tcp-server))
(if (slot-value this 'server-socket) t nil))
(defgeneric server-port (this))
(defmethod server-port ((this tcp-server))
(nth-value 1 (sb-bsd-sockets:socket-name (slot-value this 'server-socket))))
(let ((server-instance nil))
(defun deltabackup-start-server (&key (port 0) (bind-address #(127 0 0 1)) (buffer-length (kilobytes 10)))
(setf server-instance (start-tcp-server :port port
:bind-address bind-address
:buffer-length buffer-length))
nil)
(defun deltabackup-stop-server ()
(unless server-instance
(error "Server not running"))
(stop-server server-instance)
(setf server-instance nil))
(defun deltabackup-server-running? ()
(server-running? server-instance))
(defun deltabackup-server-port ()
(server-port server-instance)))
(defmacro with-tcp-client-connection (address port socket-var &body body-forms)
(with-gensyms (client-socket)
`(let* ((,client-socket (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp))
(,socket-var ,client-socket)) ; duplicate this, to prevent body-form modifying the original
(sb-bsd-sockets:socket-connect ,client-socket ,address ,port)
(unless ,client-socket
(error "Failed to connect"))
,#body-forms
(sb-bsd-sockets:socket-close ,client-socket))))
(defmacro with-running-server ( (&optional (port 0)) &body body-forms)
`(progn
(deltabackup-start-server :port ,port)
(unless (deltabackup-server-running?)
(error "Server did not run"))
,#body-forms
(deltabackup-stop-server)))
(with-running-server ()
(with-tcp-client-connection #(127 0 0 1) (deltabackup-server-port) client-socket
client-socket))
Using SBCL common lisp.
The reason you get such a vague error message is that you're running directly from the command line and the error is happening in a thread. If you can get the error to happen in EMACS under SLIME, you'll get more detailed error information.
I ran your program from SLIME like this:
CL-USER> (loop repeat 100 do (load "/tmp/stackoverflow.lisp"))
...and got the following error in SLIME:
Socket error in "accept": EBADF (Bad file descriptor)
[Condition of type SB-BSD-SOCKETS:BAD-FILE-DESCRIPTOR-ERROR]
So, something is going wrong on the server's end when you try to accept the connection. My theory is you have a race condition. In the server thread, you have this:
(loop
while (and server-socket (sb-bsd-sockets:socket-open-p server-socket))
do
(let ((client-socket (sb-bsd-sockets:socket-accept server-socket))) ;; Listen for incoming connections
....))
...and in the client thread, you do this:
(defmethod stop-server ((this tcp-server))
(with-slots (server-socket server-threads) this
(unless server-socket
(error "Server not running"))
(sb-bsd-sockets:socket-close server-socket)
It is possible for sb-bsd-sockets:socket-close to be called and to finish between the call to socket-open-p and socket-accept in the server thread, so that socket-accept gets called on a closed socket.

Resources