PDDL Durative-Action: Flexible duration - ros

I'm implementing a charging action in PDDL2.1 that is based off a function (charge_level). The function value for (charge_level) works and updates ~10Hz.
I want to create an action called charge which continues until the charge_level reaches a threshold. That is
(:durative-action charge
:duration ( CONTINUE UNTIL (> (charge_level) HIGH_THRES)))
:condition (and
(at start ( < (charge_level) LOW_THRES)))
:effect (and
)
))
How might I implement this? I was trying to assign the ?duration variable to charge_level and set :duration (> ?duration HIGH_THRES) but it wouldn't plan successfully.
Thanks in advance!

The answer depends on two aspects of your solution:
capability of the planner you are using
level of abstraction you select for your planning model and for your execution/control
For the first aspect: if your domain also models the discharging effect in other actions, and if your planner supports continuous effects, you could model the action in a similar way to this boil action:
(:durative-action boil-water
:parameters ()
:duration (>= ?duration 0)
:condition (and
(at start (and
(not (boiling))
))
(over all (and
(<= (water-temperature) 100)
))
)
:effect (and
(at start (and
(boiling)
))
(at end (and
(not (boiling))
))
(increase (water-temperature) (* #t 1.0))
)
)
You can fin the full example is here.
The continuous effect (increase (water-temperature) (* #t 1.0)) is what defines how quickly is the temperature changing in time. With that, the planner can reason about how long the action should take. That is why the duration is defined without any upper bound :duration (>= ?duration 0). This is assuming there is another action in the domain or goal in the problem, which require the water-temperature to be of certain numeric value. Otherwise the planner has no reason to add the action to the plan.
Another approach is to use process (and event) as defined in PDDL+.
And regarding the second aspect: if your domain does not really need to reason about the value of the charge_level, you should delegate that to your plan execution infrastructure. In practice, it is much simpler to evaluate a boolean predicate fully_charged based on the condition (> (charge_level) HIGH_THRES)) outside the planner as part of your state inference.

Related

How do I create additional constraints from a model obtained by a solver in z3 Python API?

Once I have a constraint problem, I would like to see if it is satisfiable. Based on the returned model (when it is sat) I would like to add assertions and then run the solver again. However, it seems like I am misunderstanding some of the types/values contained in the returned model. Consider the following example:
solv = z3.Solver()
n = z3.Int("n")
solv.add(n >= 42)
solv.check() # This is satisfiable
model = solv.model()
for var in model:
# do something
solv.add(var == model[var])
solv.check() # This is unsat
I would expect that after the loop i essentially have the two constraints n >= 42 and n == 42, assuming of course that z3 produces the model n=42 in the first call. Despite this, in the second call check() returns unsat. What am I missing?
Sidenote: when replacing solv.add(var == model[var]) with solv.add(var >= model[var]) I get a z3.z3types.Z3Exception: Python value cannot be used as a Z3 integer. Why is that?
When you loop over a model, you do not get a variable that you can directly query. What you get is an internal representation, which can correspond to a constant, or it can correspond to something more complicated like a function or an array. Typically, you should query the model with the variables you have, i.e., with n. (As in model[n].)
You can fix your immediate problem like this:
for var in model:
solve.add(var() == model[var()])
but this'll only work assuming you have simple variables in the model, i.e., no uninterpreted-functions, arrays, or other objects. See this question for a detailed discussion: https://stackoverflow.com/a/11869410/936310
Similarly, your second expression throws an exception because while == is defined over arbitrary objects (though doing the wrong thing here), >= isn't. So, in a sense it's the "right" thing to do to throw an exception here. (That is, == should've thrown an exception as well.) Alas, the Python bindings are loosely typed, meaning it'll try to make sense of what you wrote, not necessarily always doing what you intended along the way.

using arithmetic comparison as a precondition in PDDL

I was looking for a way to set a comparison as a precondition to an action in PDDL. Is there a way to say for example:
(:functions (goal))
(:action CheckLoser
:parameters (?team)
:precondition
(> goals 5)
:effect
(loses ?team)
)
Fast Downward doesn't support using an arithmetic comparison as an action precondition, but the planner Metric-FF does. The latter can be downloaded from here, and it is easy to install:
ensure flex and bison are installed on your system; On Ubuntu just use:
sudo apt-get install bison flex
run make in the source directory
Metric-FF can be executed as follows :
./ff -o path/to/domain.pddl -f path/to/problem.pddl
To solve the problem in the question, I used a variable cost to track the time and allowed an action to occur after a certain amount of time has passed.
My code sample is as follows:
Define a :predicate in the domain file, e.g. (cost ?cost)
Define a :function in the domain file, e.g. (:functions (total-cost ?cost))
Add (cost) in the :objects part of the problem file
In the :init part of the problem file, set the "time" to start as "x", e.g. (= (total-cost ?cost) 0) where "time" is cost and "x" is equal to 0.
Now it is possible to use the arithmetic comparison in any action precondition; e.g. (> (total-cost ?cost) x), where x can be set to any value (including floating point numbers); Note that in this case ?cost must be included in the :parameters section of the said action
Finally, the value of total-cost can be increased (resp. decreased) after every action execution with (increase (total-cost ?cost) x) (resp. (decrease (total-cost ?cost) x)), where x can again be replace with any value.
In PDDL you cannot compare directly, Instead you can define some boolean function with parameters. Specification of such function in precondition means that the function holds true.
eg:
(operation
makebigger
(params
(<a> Object) (<b> Object))
(preconds
(greater <a> <b>))
effects
(greater <b> <a>)))
Something like greater function(written in preorder). Such boolean function that states a precondition will be used in your planning.

Inconsistent behaviour of closures in Common Lisp [duplicate]

Can someone explain the following behavior? Specifically, why does the function return a different list every time? Why isn't some-list initialized to '(0 0 0) every time the function is called?
(defun foo ()
(let ((some-list '(0 0 0)))
(incf (car some-list))
some-list))
Output:
> (foo)
(1 0 0)
> (foo)
(2 0 0)
> (foo)
(3 0 0)
> (foo)
(4 0 0)
Thanks!
EDIT:
Also, what is the recommended way of implementing this function, assuming I want the function to output '(1 0 0) every time?
'(0 0 0) is a literal object, which is assumed to be a constant (albeit not protected from modification). So you're effectively modifying the same object every time. To create different objects at each function call use (list 0 0 0).
So unless you know, what you're doing, you should always use literal lists (like '(0 0 0)) only as constants.
On a side note, defining this function in the sbcl REPL you get the following warning:
caught WARNING:
Destructive function SB-KERNEL:%RPLACA called on constant data.
See also:
The ANSI Standard, Special Operator QUOTE
The ANSI Standard, Section 3.2.2.3
Which gives a good hint towards the problem at hand.
'(0 0 0) in code is literal data. Modifying this data has undefined behavior. Common Lisp implementations may not detect it at runtime (unless data is for example placed in some read-only memory space). But it can have undesirable effects.
you see that this data may be (and often is) shared across various invocations of the same function
one of the more subtle possible errors is this: Common Lisp has been defined with various optimizations which can be done by a compiler in mind. For example a compiler is allowed to reuse data:
Example:
(let ((a '(1 2 3))
(b '(1 2 3)))
(list a b))
In above code snippet the compiler may detect that the literal data of a and b is EQUAL. It may then have both variables point to the same literal data. Modifying it may work, but the change is visible from a and b.
Summary: Modification of literal data is a source of several subtle bugs. Avoid it if possible. Then you need to cons new data objects. Consing in general means the allocation of fresh, new data structures at runtime.
Wanted to write one myself, but I found a good one online:
CommonLisp has first class functions, i.e. functions are objects which
can be created at runtime, and passed as arguments to other functions.
--AlainPicard These first-class functions also have their own state, so they are functors. All Lisp functions are functors; there is no
separation between functions that are "just code" and "function
objects". The state takes the form of captured lexical variable
bindings. You don't need to use LAMBDA to capture bindings; a
top-level DEFUN can do it too: (let ((private-variable 42))
(defun foo ()
...))
The code in the place of ... sees private-variable in its lexical
scope. There is one instance of this variable associated with the one
and only function object that is globally tied to the symbol FOO; the
variable is captured at the time the DEFUN expression is evaluated.
This variable then acts something like a static variable in C. Or,
alternately, you can think of FOO as a "singleton" object with an
"instance variable".
--KazKylheku
Ref
http://c2.com/cgi/wiki?CommonLisp

Bounding universally quantified variable

I would like to know if it is possible to bound the range of values of a universally quantified variable in Z3.
For example, let's assume that I have a variable of type Real called "time" which is used to model the time in the system.
Let's say that I have an assertion which says that the value of some unary function "func1" shall always be between 1 and 100. The function takes the input the time variable. Expressed in Z3, I have encoded the property as following:
ForAll(time, And(func1(time) >= 1, func1(time) <= 100))
Please note that I explicitly need the time variable to be universally quantified, because I want the Z3 go give me unsat if I inject property of following type:
Exists(time, func1(time) == 101)
As far as my understanding goes for Z3, all the constants have mathematical (theoretical) and not computer (practical) implementation i.e. their values are not bound (unfortunately I cannot point to the resource where I have read this at the moment). Assume that with time I model time in my systems, and according to the system constrains it cannot run for more than x hours, which I can use and say that value of time is between 0 and x*60'*60 to give the maximum execution time in seconds. I know that I can assert the allowed values for time with the following assertion:
And(time >= 0, time <= x*60*60)
but will it affect the universal quantification given in 1?
Consequently, this should lead to a situation where if property 2 is injected and for value of time I specify x*60*60 + 1, it should not be unset since the ForAll is valid only for the values of time.
but will it affect the universal quantification given in 1)?
Note that
ForAll(time, And(func1(time) >= 1, func1(time) <= 100))
treats the variable "time" as bound. The formula has the same meaning as:
ForAll(xx, And(func1(xx) >= 1, func1(xx) <= 100))
When you assert the above, the meaning is that any instantiation of xx holds (is asserted). In particular, you can instantiate the quantified variable with the free variable "time" and in particular, you can instantiate with x*60*60+1 producing the assertion:
And(func1(x*60*60+1) >= 1, func1(x*60*60+1) <= 100)
Suppose you wanted to say that
And(func1(xx) >= 1, func1(xx) <= 100))
holds for every value xx between 0 and x*60*60, then you can write:
ForAll(xx, Implies(And(xx >= 0, xx <= x*60*60), And(func1(xx) >= 1, func1(xx) <= 100)))
(unfortunately I cannot point to the resource where I have read this at the moment).
Reasonable logic text books or foundations of computer science books should explain this in depth. Z3 supports a standard first-order many-sorted logic (with background theories).

Arrays and Datatypes in Z3py

I'm actually using Z3py for scheduling solving problems and I'm trying to represent a 2 processors system where 4 process of different execution time must be done.
My actual data are :
Process 1 : Arrival at 0 and execution time of 4
Process 2 : Arrival at 1 and execution time of 3
Process 3 : Arrival at 3 and execution time of 5
Process 4 : Arrival at 1 and execution time of 2
I'm actually trying to represent each process while decomposing each in subprocess of equal time so my datatypes are like this :
Pn = Datatype('Pn')
Pn.declare('1')
Pn.declare('2')
Pn.declare('3')
Pn.declare('4')
Pt = Datatype('Pt')
Pt.declare('1')
Pt.declare('2')
Pt.declare('3')
Pt.declare('4')
Pt.declare('5')
Process = Datatype('Process')
Process.declare('cons' , ('name',Pn) , ('time', Pt))
Process.declare('idle')
where pn and pt are the process name and the part of the process (process 1 is in 4 parts, ...)
But now I don't know how I can represent my processors to add 3 rules I need : unicity (each sub process must be done 1 and only 1 time by only 1 processor) check arrival (the first part of a process can't be processed before it arrived) and order (each part of a process must be processed after the precedent)
So I was thinking of using arrays to represent my 2 processors with this kind of declaration :
P = Array('P', IntSort() , Process)
But when I tried to execute it I got an error message saying :
Traceback (most recent call last):
File "C:\Users\Alexis\Desktop\test.py", line 16, in <module>
P = Array('P', IntSort() , Process)
File "src/api/python\z3.py", line 3887, in Array
File "src/api/python\z3.py", line 3873, in ArraySort
File "src/api/python\z3.py", line 56, in _z3_assert
Z3Exception: 'Z3 sort expected'
And know I don't know how handle it... must I create a new datatype and figure a way to add my rules ? or Is there a way to add datatypes to array which would let me create rules like this :
unicity = ForAll([x,y] , (Implies(x!=y,P[x]!=P[y])))
Thanks in advance
There is a tutorial on using Datatypes from the Python API. A link to the tutorial is:
http://rise4fun.com/Z3Py/tutorialcontent/advanced#h22
It shows how to create a list data-type and use the "create()" method to instantiate a Sort object from the object used when declaring the data-type. For your example, it suffices to add calls to "create()" in the places where you want to use the declared type as a sort.
See: http://rise4fun.com/Z3Py/rQ7t
Regarding the rest of the case study you are looking at: it is certainly possible to express the constrsaints you describe using quantifiers and arrays. You could also consider somewhat more efficient encodings:
Instead of using an array, use a function declaration. So P would be declared as a unary function:
P = Function('P', IntSort(), Process.create()).
Using quantifiers for small finite domain problems may be more of an overhead than a benefit. Writing down the constraints directly as a finite conjunction saves the overhead of instantiating quantifiers possibly repeatedly. That said, some quantified axioms can also be optimized. Z3 automatically compiles axioms of the form: ForAll([x,y], Implies(x != y, P(x) != P(y))) into
an axioms of the form Forall([x], Pinv(P(x)) == x), where "Pinv" is a fresh function. The new axiom still enforces that P is injective but requires only a linear number of instantiations, linear in the number of occurrences of P(t) for some term 't'.
Have fun!

Resources