Q1
Can I use "not" in my rules?
A1
You can use negation, for example applied to a fluent, in your rules,
but remember that your precondition rules should not begin with
negation that is applied to predicate with variables, if variables
have not yet been assigned any value. This means that you have to call
other predicates first, such that they will retrieve values to
variables and, subsequently, you can write negations of predicates
at the end of your rule. Recall that a body of each rule is simply
conjunction of logical statements and its logical meaning remains
the same if you rearrange predicates so that those which have no
negation at front of them will be called at the beginning of your rule.
You can review the slide 16
"Caution: variables and negation"
from the "Prolog basics" that we discussed at the beginning of this
course: this slide illustrates my explanations.
Q2
Can I submit my solutions of the 5th assignment earlier?
I have other work to do in the end of November.
A2
Yes, you are welcome to submit your solutions earlier.
If you submit them before 9pm, Sunday, November 26,
you will get extra 10% bonus to your mark for the 5th assignment!
However, check first whether your programs work correctly.
If you lose, say, 20 points due to errors, but submit early, then you
get in total only (100 - 20) *1.1 = 88 points.
Q3
For part 1, one of the goal states took me 4 minutes (without declarative
heuristics) to execute even though in the question, it suggests that
it should run a few seconds only. The solution is correct. But am I doing
something wrong?
I don't consider my computer to be slow.
A3
Make sure you are using types for all variables, e.g., soap(P), or
washer(W), and so on, read assignment carfully for available types.
There might be a minor bug in your program that slows down
search that your program does. Print your program and read it
very carefully. Compare your program with the specification given
in the assignment and clarified on this Web page (see above).
If this does not help, put it away, and read again next day.
In some cases, you can spot a bug just by reading your program
afresh, or with one of your friends. As an alternative approach,
you can try to solve several easier, but related planning problems.
For example, try goal states that can be reached with fewer actions.
In other words, try to solve planning problems
that are easier than that one which takes a long time for your
computer to solve. For each of this intermediate goal state,
record how much time it takes your program to compute a plan.
You may notice, that some planning problems can be solved fast, but
others takes long time. This may give you an idea that a delay can be
due to a particular action, and consequently, may be your precondition
rule, or other rules for this action are wrong. To check your precondition
rules, query whether an action is possible to do after a sequence of some
other actions. If you get intuitively wrong answers, then some of
your rules are wrong. You may have bugs in precondition rules, in
successor state rules, or both. Also, when you
try a few different goals (with the same initial state) you may catch a
bug, if you will see that your program does not compute a plan
that it is supposed to compute for some of the goal states. However,
exploring different goal states takes time. So, first try to read your
program and find a bug. Another useful debuging trick is to try
specific sequences of actions, and see if they lead to the goal states
as expected. If intuitively you expect a sequence of actions to be a
plan solving a problem, but your program says "no", then there is
a bug somewhere. You can try to trace a query using combination of
"creep" (if you would like to see every step) and "skip" (if you would
like to skip some rules altogether when you know there is no bug there).
ECLiPSe Prolog has a nice graphical debugger.
By exploring different sequences of actions, you
can usually locate a bug quickly.
Q4
When writing rules for fluents, are we allowed to use fluents for
defining other fluents? for example using fluent "f1" and "f2" for
defining fluent "f3" ?
A4
No, you
cannot write rules
that compute whether a fluent is true in a situation
Note that rather than saying that we
define fluent, we say that we write a SSA for a fluent.
Recall that there are two types of SSAs that you have to write.
First, rules that say when a fluent
becomes true in the next situation
thanks to an action A. Sometimes, we say in this case, that an
action A has a positive effect on this fluent.
Second, rules
that say that a fluent remains true in
the next situation, if it is true in the current situation, and the
most recent action A is not one of those which have a negative
effect on the fluent (i.e., not one of those, which can make it false).
Q5
If I run a query like "poss(actionName(arg1,arg2),S)" should it take a long time
to find a solution?
A5
All simple testing queries should be instanteneous. If any of them takes
more than a few seconds, there is a bug in your program. This applies
only to queries that have no variables, i.e., where arguments are
instantiated properly. However, note that S is a variable in your query
?- poss(actionName(arg1,arg2),S).This is wrong. You should type a list of actions instead of S, or simply [], if you are testing if action "actionName(arg1,arg2)" is possible initially. Otherwise, if you have a variable S in this query, you are asking your program to plan for a sequence of actions that leads to a state where "actionName(arg1,arg2)" is possible. Basically, you are asking your program to solve a planning problem. This may take a long time even if your program is not buggy, sine there are no means to guarantee that S is built out of legal_move actions. I would expect that this query may not be answered at all even by a correct program because it will do infinite recursion over lists of situations. So, you should better avoid queries that use predicate poss with S as a variable argument. In contrast, a query like
?- poss(actionName(arg1,arg2),[act1, act2]).should be answered immediately if your program is correct, where act1 and act2 are kind of place holders for action terms.
Q6
Can I introduce new predicates and use them in precondition rules
or successor state rules?
A6
No. You are not allowed to introduce any new predicates.
You can use only the predicate given to you in the assignment.
Q7
In the 'dining philosophers' problem (part 2) of Assignment 5, the
description of the "waiting" fluent indicates that
"He [the philosopher] switches from thinking to waiting by picking up a fork,
or from eating to waiting by putting down one of his two forks...".
Then in the "happy" fluent, it indicates that the philosopher
"becomes happy after eating in the previous situation as soon as he
puts down at least one of his forks."
It seems to me that these two fluents have the same requirement.
If the philosopher is eating, then puts down a fork, it appears that he
could go into either waiting or happy. I would intuitively think
that he should be happy after eating, and not go back to waiting, but
the description doesn't indicate that to me.
A7
The fluents "happy" and "waiting" serve different purposes and
they have different dynamics. Note that when an eating
philosopher puts down one of his forks, he becomes both waiting and happy.
This follows from specifications that you quoted. However, once
a philosopher has become happy, he remains happy forever.
However, if a waiting philosopher puts down his last fork, he becomes
thinking, not waiting. In other words, the philosopher can undergo transitions
eating --> waiting --> thinking. Also, if a waiting philosopher
(who holds only 1 fork) picks up the second fork, then he can try
to eat. If the conditions
are right, he may become eating again, and then he will no longer be waiting.
In other words, the following transitions are possible:
thinking --> waiting --> eating. This demonstrates that "waiting"
is a kind of intermediate transient experience between thinking and
eating.
Now the differences between "waiting" and "happy" should be clear:
"happy" is a kind of absorbing feeling that can be reached only from
"eating", but once a philoshoper got into this feeling, he cannot become
unhappy. In other words, there is a transition eating--> happy,
and all subsequent actions lead from "happy" back to "happy". (If I could,
I should draw a kind of loop or cyclic arrow around the node "happy".)
In case, if you are wondering what is the purpose of introducing
the fluent "happy", then notice that it serves as a kind of label for the fact
that a philospher has eaten once. This label is convenient, when we formulate
a goal state saying that there should be a situation when all philosophers
are not hungry, i.e., when all of them had a chance to eat at least once.
Without the fluent "happy" we cannot specify such goal state. So, the fluent
"happy" is a somewhat auxiliary fluent that serves technical purposes.
Q8
In Question 2, one of the conditions for the eating(P,S) fluent is:
"If a waiting philosopher is trying to eat when 2 other philosophers
are already eating, he cannot eat, but keeps waiting."
However, there are only three philosophers and three forks in the
initialization file -- so this will never happen. With three
forks, it's only possible for one philosopher to be eating at once.
Are we expected to test our program with a higher number of philosophers?
For example, with seven philosophers and seven forks?
A8
You have to write your precondition rules and SSA rules without
regard to what initial or goal states are given to you. This is because
your precondition rules and SSA rules should be applicable to any
number of philosophers and forks. This is the main advantage of the
situations and fluents approach over a simple-minded approach when
state is represented using a list. All examples that we discussed
have general precondition rules and SSA rules, including the coins on
the desk and tiles on the grid. Once you have correct rules, you can test
them on specific instances of the planning problem. It is up to you
which instances you might wish to try, but if you do testing with 7
philosophers, choose a goal state that can be easily reached from
your initial state. You are expected to test only simple instances
like those given in the assignment. In any case, the TA will be
testing your programs using his own instance of a planning problem,
e.g., with 4 or 5 philosophers. Also, the TA will be reading and testing your rules.
If they are not general, or if they do not implement specifications
from the assignment, then you may lose marks.
Q9
For Question 1 Part (a) of Assignment 5, should we be checking
if the variable is a certain type?
For example, for hasSoap(W,S), should we be doing washer(W) and soap(S)?
And if so, should these conditions be in both the precondition axioms
and the successor-state axioms?
A9
Yes, you have to add types to the precondition axioms. However, notice that
S is a situation variable,
but you are supposed to use P as a variable for soap in the 5th assignment.
Note usually you do not need types in the SSA rules.
Q10
In part 1, for situations like such as when adding soap to the washer with
addSoap(P,W) (assuming all its preconditions are met),
should we no longer be holding P?
A10
Yes, this is stated in the assignment when the meaning of the fluent
holding(P,S) is expained: see the top half of the 2nd page.
Once you have added a soap (or a softener), you are no longer holding it,
and consequently, you cannot put it away.
Q11
When testing the following query:
?- poss(washClothes(cl1, w1), [addSoftener(sft1, w1), fetch(sft1, cbd1), addSoap(p1, w1), fetch(p1,cbd1), move(cl1, w1, h1)]). Yes (0.00s cpu, solution 1, maybe more)We get the answer yes quickly, but when doing the query:
Q12
Do the soap and softener need to be put away after they are used?
Or are they the "pod" type that can
simply be tossed in (versus a bottle that must be poured and returned)?
If the soap and softener do not need to be put away, then
I'm not sure what the purpose of the putAway action would be.
A12
No, the robot does not have to put the soap and softener away,
i.e., they are not in the bottle. Please note this is related
to Q10/A10 above.
Anyway, the pair of actions fetch/putAway is a usual example of
a reversible action, and it is included to avoid hard-coding of
solutions to the laundry-related planning problems. Each
solution to the planning problem should involve a fair amount of reasoning.
Let your program discover a solution.
Q13
Can you fold something in a container? There is no constraint saying you can not.
A13
For simplicity, let's assume that clothes can be folded
anywhere, e.g., even if they are in a container.
Q14
The actions fetch(O,C) and putAway(O,C) are defined only for cupboards,
but can they apply to any container?
A14
Yes, this would be a natural extension of the application domain. You might
wish to explore the case when actions fetch or put away apply to any container,
not only to a cupboard. But this is not required.
Q15
Can we say waiting(P,S):- not thinking and not eating ?
If not, how can we approach this specification?
A15
You cannot write rules like this: see Q4/A4 above.
Write SSA rules for each fluent "f", as explained in the class and in the assignment, e.g.,
f(X, [ A | S]) :- A=actionInitiatesFluent(X,Y), conditionsPos(S).
/* how fluent becomes true */
f(X, [ A | S]) :- not A=actionTerminatesFluent(X,Y), conditionsNeg(S).
/* when fluent remains true */
where conditionsPos(S), conditionsNeg(S) can include same fluent "f",
or any other given fluents, or a formula composed from the given fluents.
Note that in the head of SSA rules you have to write fluent "f" with respect to
next situation [A | S], but in the bodies of these rules the fluents can
mention only the current situation S. We discussed in class that SSAs
are recursive rules that reduce a query about any given list of actions to
a query wrt to a shorter list of actions that has one action A less.
Therefore, each recursive query about a fluent wrt a given list of action
terminates and consults the values of the fluents given in the initial situation
represented as the empty list []. We discussed many examples of
SSA rules in class. Ask other students for copies of their lecture notes,
if you missed classes.
Q16
I read the QA and I think you said that we cannot use other fluents in
the bodies of our fluents, but I am just wondering how would we complete
the question, since most of the fluents are dependent on the truth of
other fluents.
A16
Read Q15/A15 above. All SSA rules must use only the fluents given to you in the assignment.
The SSA for the fluent "f" can use in the rule body any given fluents wrt S.
However, the declarative heurisitc rules for the predicate "useless"
can use the library predicates that we discussed in class, if they can help.
Q17
For our useless predicate, we are running into issues with what we can say is useless in terms of
reaching the goal state. For example, [...skip...]
This useless predicate would make our program run within the
appropriate time frame, however, this will also make it impossible [..skip...]
A17
You can write any domain specific declarative heuristics, as long as
they are general enough, i.e., they are always applicable to this domain.
Moreover, they must not prevent the program from solving any reasonable
and realistic planning problems with related, but different goals.
In other words, the rules defining the predicate "useless" should
work with any "real life" and sensible initial and goal states.
Q18
For some reason I get the same solution multiple times when I press 'more',
for both parts of the assignment.
A18
The planner should not be repeating solutions. Each time you should be getting
a new correct plan. Check if there are bugs in your program.
Make sure you compile the main program that loads by itself
the corresponding "init" part.
Q19
In the action definitions, you mention that for move(C,F,T),
"The container T can be a dresser, or a hamper, or a washer, or a dryer that is empty."
However, in one of the goals given for the question:
goal_state(S) :- clean(cl1,S), clean(cl2,S), not wet(cl1,S), not wet(cl2,S), folded(cl1,S), folded(cl2,S), in(cl1,dresser,S), in(cl2,dresser,S).both cl1 and cl2 are in the dresser. Given that they do not start there, this means that they must have be put there using move(C,F,T). How can we move both clothes, if the dresser becomes not-empty as we move the first into it?
Q20
A20