From 4ba7935b2d7e6e05feb5da4625989cfd0311f74e Mon Sep 17 00:00:00 2001 From: Kaivalya Rawal Date: Tue, 7 Mar 2017 03:26:36 +0530 Subject: [PATCH 1/2] fix bold look on github's ipython view --- agents.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents.ipynb b/agents.ipynb index 7976b12b2..8eba9f07e 100644 --- a/agents.ipynb +++ b/agents.ipynb @@ -8,7 +8,7 @@ "\n", "An agent, as defined in 2.1 is anything that can perceive its environment through sensors, and act upon that environment through actuators based on its agent program. This can be a dog, robot, or even you. As long as you can perceive the environment and act on it, you are an agent. This notebook will explain how to implement a simple agent, create an environment, and create a program that helps the agent act on the environment based on its percepts.\n", "\n", - "Before moving on, review the Agent and Environment classes in [agents.py](https://github.com/aimacode/aima-python/blob/master/agents.py).\n", + "Before moving on, review the Agent and Environment classes in [agents.py](https://github.com/aimacode/aima-python/blob/master/agents.py).\n", "\n", "Let's begin by importing all the functions from the agents.py module and creating our first agent - a blind dog." ] From af72f143b3b838830ae64d80b5ae621a526f05a8 Mon Sep 17 00:00:00 2001 From: Kaivalya Rawal Date: Tue, 7 Mar 2017 03:27:26 +0530 Subject: [PATCH 2/2] standardise docstrings --- agents.py | 121 ++++++++++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 62 deletions(-) diff --git a/agents.py b/agents.py index 650dfe97b..abd7b9f7a 100644 --- a/agents.py +++ b/agents.py @@ -55,16 +55,16 @@ def __repr__(self): return '<{}>'.format(getattr(self, '__name__', self.__class__.__name__)) def is_alive(self): - "Things that are 'alive' should return true." + """Things that are 'alive' should return true.""" return hasattr(self, 'alive') and self.alive def show_state(self): - "Display the agent's internal state. Subclasses should override." + """Display the agent's internal state. Subclasses should override.""" print("I don't know how to show_state.") def display(self, canvas, x, y, width, height): + """Display an image of this Thing on the canvas.""" # Do we need this? - "Display an image of this Thing on the canvas." pass @@ -89,7 +89,7 @@ def __init__(self, program=None): self.performance = 0 if program is None: def program(percept): - return eval(input('Percept={}; action? ' .format(percept))) + return eval(input('Percept={}; action? '.format(percept))) assert isinstance(program, collections.Callable) self.program = program @@ -129,14 +129,14 @@ def program(percept): def RandomAgentProgram(actions): - "An agent that chooses an action at random, ignoring all percepts." + """An agent that chooses an action at random, ignoring all percepts.""" return lambda percept: random.choice(actions) # ______________________________________________________________________________ def SimpleReflexAgentProgram(rules, interpret_input): - "This agent takes action based solely on the percept. [Figure 2.10]" + """This agent takes action based solely on the percept. [Figure 2.10]""" def program(percept): state = interpret_input(percept) rule = rule_match(state, rules) @@ -146,7 +146,7 @@ def program(percept): def ModelBasedReflexAgentProgram(rules, update_state, model): - "This agent takes action based on the percept and state. [Figure 2.8]" + """This agent takes action based on the percept and state. [Figure 2.8]""" def program(percept): program.state = update_state(program.state, program.action, percept, model) rule = rule_match(program.state, rules) @@ -157,7 +157,7 @@ def program(percept): def rule_match(state, rules): - "Find the first rule that matches state." + """Find the first rule that matches state.""" for rule in rules: if rule.matches(state): return rule @@ -168,12 +168,12 @@ def rule_match(state, rules): def RandomVacuumAgent(): - "Randomly choose one of the actions from the vacuum environment." + """Randomly choose one of the actions from the vacuum environment.""" return Agent(RandomAgentProgram(['Right', 'Left', 'Suck', 'NoOp'])) def TableDrivenVacuumAgent(): - "[Figure 2.3]" + """[Figure 2.3]""" table = {((loc_A, 'Clean'),): 'Right', ((loc_A, 'Dirty'),): 'Suck', ((loc_B, 'Clean'),): 'Left', @@ -189,7 +189,7 @@ def TableDrivenVacuumAgent(): def ReflexVacuumAgent(): - "A reflex agent for the two-state vacuum environment. [Figure 2.8]" + """A reflex agent for the two-state vacuum environment. [Figure 2.8]""" def program(percept): location, status = percept if status == 'Dirty': @@ -202,11 +202,11 @@ def program(percept): def ModelBasedVacuumAgent(): - "An agent that keeps track of what locations are clean or dirty." + """An agent that keeps track of what locations are clean or dirty.""" model = {loc_A: None, loc_B: None} def program(percept): - "Same as ReflexVacuumAgent, except if everything is clean, do NoOp." + """Same as ReflexVacuumAgent, except if everything is clean, do NoOp.""" location, status = percept model[location] = status # Update the model here if model[loc_A] == model[loc_B] == 'Clean': @@ -242,32 +242,29 @@ def thing_classes(self): return [] # List of classes that can go into environment def percept(self, agent): - ''' - Return the percept that the agent sees at this point. - (Implement this.) - ''' + """Return the percept that the agent sees at this point. (Implement this.)""" raise NotImplementedError def execute_action(self, agent, action): - "Change the world to reflect this action. (Implement this.)" + """Change the world to reflect this action. (Implement this.)""" raise NotImplementedError def default_location(self, thing): - "Default location to place a new thing with unspecified location." + """Default location to place a new thing with unspecified location.""" return None def exogenous_change(self): - "If there is spontaneous change in the world, override this." + """If there is spontaneous change in the world, override this.""" pass def is_done(self): - "By default, we're done when we can't find a live agent." + """By default, we're done when we can't find a live agent.""" return not any(agent.is_alive() for agent in self.agents) def step(self): """Run the environment for one time step. If the actions and exogenous changes are independent, this method will - do. If there are interactions between them, you'll need to + do. If there are interactions between them, you'll need to override this method.""" if not self.is_done(): actions = [] @@ -281,14 +278,14 @@ def step(self): self.exogenous_change() def run(self, steps=1000): - "Run the Environment for given number of time steps." + """Run the Environment for given number of time steps.""" for step in range(steps): if self.is_done(): return self.step() def list_things_at(self, location, tclass=Thing): - "Return all things exactly at a given location." + """Return all things exactly at a given location.""" return [thing for thing in self.things if thing.location == location and isinstance(thing, tclass)] @@ -317,19 +314,19 @@ def delete_thing(self, thing): except ValueError as e: print(e) print(" in Environment delete_thing") - print(" Thing to be removed: {} at {}" .format(thing, thing.location)) - print(" from list: {}" .format([(thing, thing.location) for thing in self.things])) + print(" Thing to be removed: {} at {}".format(thing, thing.location)) + print(" from list: {}".format([(thing, thing.location) for thing in self.things])) if thing in self.agents: self.agents.remove(thing) class Direction(): - '''A direction class for agents that want to move in a 2D plane + """A direction class for agents that want to move in a 2D plane Usage: d = Direction("down") To change directions: d = d + "right" or d = d + Direction.R #Both do the same thing Note that the argument to __add__ must be a string and not a Direction object. - Also, it (the argument) can only be right or left.''' + Also, it (the argument) can only be right or left.""" R = "right" L = "left" @@ -396,7 +393,7 @@ def __init__(self, width=10, height=10): perceptible_distance = 1 def things_near(self, location, radius=None): - "Return all things within radius of location." + """Return all things within radius of location.""" if radius is None: radius = self.perceptible_distance radius2 = radius * radius @@ -404,7 +401,7 @@ def things_near(self, location, radius=None): if distance2(location, thing.location) <= radius2] def percept(self, agent): - '''By default, agent perceives things within a default radius.''' + """By default, agent perceives things within a default radius.""" return self.things_near(agent.location) def execute_action(self, agent, action): @@ -428,8 +425,8 @@ def default_location(self, thing): return (random.choice(self.width), random.choice(self.height)) def move_to(self, thing, destination): - '''Move a thing to a new location. Returns True on success or False if there is an Obstacle. - If thing is holding anything, they move with him.''' + """Move a thing to a new location. Returns True on success or False if there is an Obstacle. + If thing is holding anything, they move with him.""" thing.bump = self.some_things_at(destination, Obstacle) if not thing.bump: thing.location = destination @@ -449,9 +446,8 @@ def move_to(self, thing, destination): # obs.thing_added(thing) def add_thing(self, thing, location=(1, 1), exclude_duplicate_class_items=False): - '''Adds things to the world. - If (exclude_duplicate_class_items) then the item won't be added if the location - has at least one item of the same class.''' + """Adds things to the world. If (exclude_duplicate_class_items) then the item won't be + added if the location has at least one item of the same class.""" if (self.is_inbounds(location)): if (exclude_duplicate_class_items and any(isinstance(t, thing.__class__) for t in self.list_things_at(location))): @@ -459,12 +455,12 @@ def add_thing(self, thing, location=(1, 1), exclude_duplicate_class_items=False) super(XYEnvironment, self).add_thing(thing, location) def is_inbounds(self, location): - '''Checks to make sure that the location is inbounds (within walls if we have walls)''' + """Checks to make sure that the location is inbounds (within walls if we have walls)""" x,y = location return not (x < self.x_start or x >= self.x_end or y < self.y_start or y >= self.y_end) def random_location_inbounds(self, exclude=None): - '''Returns a random location that is inbounds (within walls if we have walls)''' + """Returns a random location that is inbounds (within walls if we have walls)""" location = (random.randint(self.x_start, self.x_end), random.randint(self.y_start, self.y_end)) if exclude is not None: while(location == exclude): @@ -472,7 +468,7 @@ def random_location_inbounds(self, exclude=None): return location def delete_thing(self, thing): - '''Deletes thing, and everything it is holding (if thing is an agent)''' + """Deletes thing, and everything it is holding (if thing is an agent)""" if isinstance(thing, Agent): for obj in thing.holding: super(XYEnvironment, self).delete_thing(obj) @@ -484,7 +480,7 @@ def delete_thing(self, thing): obs.thing_deleted(thing) def add_walls(self): - '''Put walls around the entire perimeter of the grid.''' + """Put walls around the entire perimeter of the grid.""" for x in range(self.width): self.add_thing(Wall(), (x, 0)) self.add_thing(Wall(), (x, self.height - 1)) @@ -506,7 +502,7 @@ def add_observer(self, observer): self.observers.append(observer) def turn_heading(self, heading, inc): - "Return the heading to the left (inc=+1) or right (inc=-1) of heading." + """Return the heading to the left (inc=+1) or right (inc=-1) of heading.""" return turn_heading(heading, inc) @@ -526,7 +522,8 @@ class Wall(Obstacle): # Continuous environment class ContinuousWorld(Environment): - """ Model for Continuous World.""" + """Model for Continuous World.""" + def __init__(self, width=10, height=10): super(ContinuousWorld, self).__init__() self.width = width @@ -537,8 +534,9 @@ def add_obstacle(self, coordinates): class PolygonObstacle(Obstacle): + def __init__(self, coordinates): - """ Coordinates is a list of tuples.""" + """Coordinates is a list of tuples.""" super(PolygonObstacle, self).__init__() self.coordinates = coordinates @@ -604,7 +602,7 @@ def thing_classes(self): TableDrivenVacuumAgent, ModelBasedVacuumAgent] def percept(self, agent): - "Returns the agent's location, and the location status (Dirty/Clean)." + """Returns the agent's location, and the location status (Dirty/Clean).""" return (agent.location, self.status[agent.location]) def execute_action(self, agent, action): @@ -622,7 +620,7 @@ def execute_action(self, agent, action): self.status[agent.location] = 'Clean' def default_location(self, thing): - "Agents start in either location at random." + """Agents start in either location at random.""" return random.choice([loc_A, loc_B]) # ______________________________________________________________________________ @@ -632,7 +630,7 @@ def default_location(self, thing): class Gold(Thing): def __eq__(self, rhs): - '''All Gold are equal''' + """All Gold are equal""" return rhs.__class__ == Gold pass @@ -648,7 +646,6 @@ class Pit(Thing): class Breeze(Thing): pass - class Arrow(Thing): pass @@ -671,7 +668,7 @@ class Explorer(Agent): direction = Direction("right") def can_grab(self, thing): - '''Explorer can only grab gold''' + """Explorer can only grab gold""" return thing.__class__ == Gold @@ -684,7 +681,7 @@ def __init__(self, agent_program, width=6, height=6): self.init_world(agent_program) def init_world(self, program): - '''Spawn items to the world based on probabilities from the book''' + """Spawn items to the world based on probabilities from the book""" "WALLS" self.add_walls() @@ -715,7 +712,7 @@ def init_world(self, program): self.add_thing(Explorer(program), (1, 1), True) def get_world(self, show_walls=True): - '''Returns the items in the world''' + """Returns the items in the world""" result = [] x_start, y_start = (0, 0) if show_walls else (1, 1) x_end, y_end = (self.width, self.height) if show_walls else (self.width - 1, self.height - 1) @@ -727,16 +724,16 @@ def get_world(self, show_walls=True): return result def percepts_from(self, agent, location, tclass=Thing): - '''Returns percepts from a given location, and replaces some items with percepts from chapter 7.''' + """Returns percepts from a given location, and replaces some items with percepts from chapter 7.""" thing_percepts = { Gold: Glitter(), Wall: Bump(), Wumpus: Stench(), Pit: Breeze()} - '''Agents don't need to get their percepts''' + """Agents don't need to get their percepts""" thing_percepts[agent.__class__] = None - '''Gold only glitters in its cell''' + """Gold only glitters in its cell""" if location != agent.location: thing_percepts[Gold] = None @@ -746,8 +743,8 @@ def percepts_from(self, agent, location, tclass=Thing): return result if len(result) else [None] def percept(self, agent): - '''Returns things in adjacent (not diagonal) cells of the agent. - Result format: [Left, Right, Up, Down, Center / Current location]''' + """Returns things in adjacent (not diagonal) cells of the agent. + Result format: [Left, Right, Up, Down, Center / Current location]""" x, y = agent.location result = [] result.append(self.percepts_from(agent, (x - 1, y))) @@ -756,7 +753,7 @@ def percept(self, agent): result.append(self.percepts_from(agent, (x, y + 1))) result.append(self.percepts_from(agent, (x, y))) - '''The wumpus gives out a a loud scream once it's killed.''' + """The wumpus gives out a a loud scream once it's killed.""" wumpus = [thing for thing in self.things if isinstance(thing, Wumpus)] if len(wumpus) and not wumpus[0].alive and not wumpus[0].screamed: result[-1].append(Scream()) @@ -765,8 +762,8 @@ def percept(self, agent): return result def execute_action(self, agent, action): - '''Modify the state of the environment based on the agent's actions. - Performance score taken directly out of the book.''' + """Modify the state of the environment based on the agent's actions. + Performance score taken directly out of the book.""" if isinstance(agent, Explorer) and self.in_danger(agent): return @@ -794,7 +791,7 @@ def execute_action(self, agent, action): agent.performance += 1000 if Gold() in agent.holding else 0 self.delete_thing(agent) elif action == 'Shoot': - '''The arrow travels straight down the path the agent is facing''' + """The arrow travels straight down the path the agent is facing""" if agent.has_arrow: arrow_travel = agent.direction.move_forward(agent.location) while(self.is_inbounds(arrow_travel)): @@ -807,7 +804,7 @@ def execute_action(self, agent, action): agent.has_arrow = False def in_danger(self, agent): - '''Checks if Explorer is in danger (Pit or Wumpus), if he is, kill him''' + """Checks if Explorer is in danger (Pit or Wumpus), if he is, kill him""" for thing in self.list_things_at(agent.location): if isinstance(thing, Pit) or (isinstance(thing, Wumpus) and thing.alive): agent.alive = False @@ -817,8 +814,8 @@ def in_danger(self, agent): return False def is_done(self): - '''The game is over when the Explorer is killed - or if he climbs out of the cave only at (1,1).''' + """The game is over when the Explorer is killed + or if he climbs out of the cave only at (1,1).""" explorer = [agent for agent in self.agents if isinstance(agent, Explorer) ] if len(explorer): if explorer[0].alive: @@ -845,7 +842,7 @@ def compare_agents(EnvFactory, AgentFactories, n=10, steps=1000): def test_agent(AgentFactory, steps, envs): - "Return the mean score of running an agent in each of the envs, for steps" + """Return the mean score of running an agent in each of the envs, for steps""" def score(env): agent = AgentFactory() env.add_thing(agent)