Finite State Automata are state machines. They exist in some state until some percept (input) comes along to trigger them to move to another state. As we saw with the locking mechanism, the correct number transitions the state to the next state. The incorrect number resets it back to the beginning.
The goal of this exercise is to model a state machine. This means defining a couple states (3-4 hopefully) and the transitions between them. Then, you should have a function which should handle these transitions. Finally, you should test the transitions with a series of percepts/inputs. I have demonstrated below with a Bunny FSA
First, I plan out my Bunny FSA.
In [7]:
class Bunny:
def __init__(self):
self.hungry = False
self.angry = False
def feed(self):
self.hungry = False
def time_passes(self):
self.hungry = True
self.angry = False
def get_angry(self):
self.angry = True
def get_spoiled(self):
self.angry = False
def user_perceive(self):
something = input("Give me a percept: ")
self.perceive(something)
def fancy_perceive(self, percept, x=8):
all_funcs = {"feed": self.feed,
"time": self.time_passes}
def perceive(self, percept):
""" see the world, change the state """
print("Euclid is experiencing {}".format(percept))
if percept == "feed":
self.feed()
elif percept == "time":
self.time_passes()
elif percept == "ignore":
self.get_angry()
elif percept == "spoiled":
self.get_spoiled()
else:
raise NotImplementedError
def act(self):
""" see the state, change the world """
pass
def get_state(self):
if self.hungry:
return "state1<hungry>"
elif self.angry:
return "state3<angry>"
else:
return "state2<content>"
def report(self):
print("Euclid is {}".format(self.get_state()))
In [11]:
euclid = Bunny()
kitchendoor = Door()
print("Initial state")
euclid.report()
percept1 = {"type": "sound", "values": []}
percepts = ['time', 'time', 'ignore', 'feed', 'spoiled']
for percept in percepts:
print("{:^30}".format("~-"*10))
euclid.perceive(percept)
euclid.report()