Examine the code that starts on page 79 and carries over onto page 80.
Find the undeclared variables and correct them.
Both parent
and child
are undeclared.
However, only one of these really needs to be used in the code. You can
decide which you would like to use. (The variable child
matches better with the enumerated type Releaser
, which has
possible values PRESENT
and NOT_PRESENT
-- if the
agent has a child present it should nurse that child. On the other hand,
the variable parent
matches better with the method name
checkStateParent()
, in which the agent apparently checks
whether it is a parent or not -- an odd thing to check every couple of
seconds!)
Whichever you decide to use in the code should be declared and used throughout the code. The other should be removed.
Explain how the code conflicts with the statement on page 79 that it "shows what happens in a sequence of behaviors, where the agent eats, then nurses its young, then sleeps, and repeats the sequence." Correct this statement to match the code.
There are at least two major conflicts with this claim.
The code does not describe any particular sequence of actions. Instead, the code shows a set of behaviors and releasers that could result in a particular sequence of actions but could just as well result in other sequences.
For example, if the agent becomes hungry while nursing, it will not complete nursing and move on to sleeping. Instead, it will go back to searching for food and, if food is present, feeding.
Similarly, if nursed
becomes
NOT_PRESENT
(false) while the agent is sleeping and is not
hungry, it will not go back to eating (or searching for food). Instead, it
will either nurse or do nothing, depending on whether or not
child
(or parent
, if you decided to use that
variable name) is PRESENT
.
Note that these two conflicts come together in a particularly bad
way with respect to describing a single sequence of actions that involves
searching for food, feeding, etc. This is because, if the agent is hungry
and food is present, it will repeat the sub-sequence search then eat
(every few seconds) until it is no longer hungry or food is no longer
present (however may repetitions this may take). This sub-sequence may or
may not have sleeping interleaved with it, depending on whether or not
nursed
is PRESENT
(true).
(Besides making it difficult to describe as a sequence, this is
probably a bad set of releasers and behaviors for an agent to have. Going
through a cycle of sleeping, searching for food, and eating all in a matter
of seconds, as can happen with this code, is probably not very restful.
Nor is searching for food when there is an abundance of food already
present, as can happen when the agent is hungry, likely to be a good
approach -- it would probably be better off eating then and only searching
when no food is present. One could also argue that sleeping should only
require having completed nursing if there is a child present. If the agent
has no child, nursing should not be a prerequisite. Only if
nursed
is PRESENT
is necessarily true when
child
is NOT_PRESENT
-- an odd way to represent
this state of affairs in the world -- will this work out well for the
agent.)
A better statement is that this code shows behaviors where the agent variously searches for food, eats, nurses its young, and sleeps, depending on its circumstances.
Explain how the code conflicts with the statement on page 79 that "[i]f the behavior isn't finished, the releasers remain unchanged and no other behavior is triggered." Correct the code to match this statement.
The first step needed to make the code match this statement, is to
make the make the releasers mutually exclusive. So, for example, we can
add the releaser code food==NOT_PRESENT
to
searchForFood()
and the releaser code
hungry==NOT_PRESENT
to sleep
, so that the agent
will only feed when hungry and food is present, rather than interleaving
searching and sleeping.
The second step needed is to prevent other factors from changing the
releasers. In the current set up, it must be the case that something other
than the methods shown cause the agent to become hungry, as none of the
methods show that as a result. We would need to prevent that something
from happening. (This isn't shown in the code, therefore we can't show its
removal in the code.) However, if we do that, we'll also need to have
completion of a behavior cause hungry
to become
PRESENT
, otherwise the agent will never get hungry. So, for
example, a result of completing sleeping could be that the agent is now
hungry. (We could show this as a comment in the code.)
(Note that, while we can make the code match this statement, we probably shouldn't. One of the strengths of the approach is that the agent ought to be able to respond to changes in the environment that aren't simply the result of completing various tasks. What if the agent runs out of food before it is full, for example? So, to have the releasers remain necessarily unchanged until a behavior is finished is in conflict with a sensor-based approach to action.)
Explain how the code conflicts with the statement on page 80 that "[i]f the agent sleeps and wakes up, but isn't hungry ... the agent will just sit there until it gets hungry." Correct this statement to match the code.
First, what does the phrase "wakes up" mean? Presumably it doesn't
just mean that the agent has slept for two seconds and cycled back up to the
top of the loop. Probably it is intended to mean something like "has had
enough sleep for now." Unfortunately, there is no releaser in the code that
relates to this concept. In the code, the agent simply sleeps when it has
finished nursing. The agent will only stop its repeated two second "micro
cat naps" (if you will) when nursed
becomes
NOT_PRESENT
(for some reason left unspecified). However, for
the sake of argument, assume that "wakes up" means that nursed
has become NOT_PRESENT
.
Given this assumption, if the agent wakes up but isn't hungry, it will do nothing iff (if and only if) all of the releaser clauses evaluate to false. However, it is very possible that the releaser clause for nursing will evaluate to true (we know the agent is not hungry and if there is a child present, then this will evaluate to true), in which case the agent will nurse.
A more accurate statement is that if the agent finds that it is time to
nurse (nursed
is NOT_PRESENT
) but there is no
child present and the agent is not hungry, it will do nothing.
(Note that, while that statement matches the code, it shows that the set of behaviors and releasers specified in the code probably represent a poor set up for an agent to follow. If it is time to nurse but no child is present, the agent should probably find the child.)
Examine the code that starts on page 81 and carries over onto page 82.
Find the undeclared variable and correct it. (Note that is same variable was undeclared in the code found entirely on page 80.)
Here, parent
is left undeclared.
On page 82 there is a statement that in this code "each behavior takes control and runs to completion." (This would only be true if the functions called were modified.) This is a problem, claims the author, because "the agent cannot react to a predator until it has finished the sequence of behaviors." Would her proposed solution that "[c]alls to the fleeing behavior could be inserted between each behavior" really make things better? Explain your answer. Would her proposed solution that "fleeing could be processed on an interrupt basis" really make things better? Explain your answer.
Inserting calls to the fleeing behavior between the behaviors listed is unlikely to help an agent. The only cases in which this would help are those in which the predator happens to arrive just after the agent has completed one behavior from the search-feed-nurse-sleep list and before it has begun another of them. This is quite unlikely, assuming that it takes more than a couple of seconds for the agent to actually complete one of these behaviors. Much more likely is that the predator will arrive while the agent is in the middle of one of these behaviors and kill the agent as it continues to search for food, feed, nurse, or sleep.
On the other hand, processing interrupts would certainly help. Interrupts can occur at the rate at which the agent's clock ticks, quite probably fractions of a second, although if the agent's predator detection scheme is in software, it would need to run as a separate process or thread. Nonetheless, multitasking or multithreading this with any of the other behaviors could give the agent at least as good a response time as the previous version of the code (from page 80).
The author claims that starting with an explicit sequence of behaviors then adding fixes, such as processing interrupts, make "the program less general purpose and harder to add [to] and maintain." Comment on this statement, in light of the difficulty the author had in matching code and text for the implicit sequence version that you corrected above.
You are, of course, free to reach your own conclusions here, but I think that some things are pretty clear:
In my opinion, the strength of programming in the reactive paradigm is not that it makes programming particular sequences of actions easy. Rather, it is because we will often want our robots to determine their next actions based on their current percepts, not what they did last, that the reactive paradigm is often appropriate. That is, since we don't know until runtime which sequence the robot should follow, we use the reactive paradigm rather than trying to explicitly program in a sequence.