2016-03-19 118 views
0

這是我們模擬那些roomba吸塵器機器人的作業。無論如何,我會非常感謝runSimulation函數的一些幫助。它在while循環中啓動到一個無限循環。據我所知,它在while循環的條件下計算的值是正確的,但是每次while循環被測試時它們都被初始化了嗎?我不這麼認爲,但可能是錯的。所以這個模擬函數實例化了一個寬度和高度的房間以及num_robots的機器人,並且模擬運行直到地板被清理,直到達到min_coverage。 runSimulation的結果是達到min_coverage所需的平均時間步驟。提前致謝!Python - RunSimulation函數中的無限循環

Simulating robots 

import math 
import random 

import ps2_visualize 
import pylab 


from ps2_verify_movement27 import testRobotMovement 



class Position(object): 
""" 
A Position represents a location in a two-dimensional room. 
""" 
def __init__(self, x, y): 
    """ 
    Initializes a position with coordinates (x, y). 
    """ 
    self.x = x 
    self.y = y 

def getX(self): 
    return self.x 

def getY(self): 
    return self.y 

def getNewPosition(self, angle, speed): 
    """ 
    Computes and returns the new Position after a single clock-tick has 
    passed, with this object as the current position, and with the 
    specified angle and speed. 

    Does NOT test whether the returned position fits inside the room. 

    angle: number representing angle in degrees, 0 <= angle < 360 
    speed: positive float representing speed 

    Returns: a Position object representing the new position. 
    """ 
    old_x, old_y = self.getX(), self.getY() 
    angle = float(angle) 
    # Compute the change in position 
    delta_y = speed * math.cos(math.radians(angle)) 
    delta_x = speed * math.sin(math.radians(angle)) 
    # Add that to the existing position 
    new_x = old_x + delta_x 
    new_y = old_y + delta_y 
    return Position(new_x, new_y) 

def __str__(self): 
    return "(%0.2f, %0.2f)" % (self.x, self.y) 



class RectangularRoom(object): 
""" 
A RectangularRoom represents a rectangular region containing clean or dirty 
tiles. 

A room has a width and a height and contains (width * height) tiles. At any 
particular time, each of these tiles is either clean or dirty. 
""" 
def __init__(self, width, height): 
    """ 
    Initializes a rectangular room with the specified width and height. 

    Initially, no tiles in the room have been cleaned. 

    width: an integer > 0 
    height: an integer > 0 
    """ 

    self.width = width 
    self.height = height 

    self.tiles = [[False] * self.height for i in range(self.width)] 


def cleanTileAtPosition(self, pos): 
    """ 
    Mark the tile under the position POS as cleaned. 

    Assumes that POS represents a valid position inside this room. 

    pos: a Position - pos is a tuple (x, y) 
    """ 


    (x_tile, y_tile) = (int(math.floor(pos.getX())), int(math.floor(pos.getY()))) 

    #print (x_tile, y_tile) 

    self.tiles[x_tile][y_tile] = True 



def isTileCleaned(self, m, n): 
    """ 
    Return True if the tile (m, n) has been cleaned. 

    Assumes that (m, n) represents a valid tile inside the room. 

    m: an integer 
    n: an integer 
    returns: True if (m, n) is cleaned, False otherwise 
    """ 
    self.m = m 
    self.n = n 

    if self.tiles[self.m][self.n] == True: 
     return True 
    else: 
     return False 

def getNumTiles(self): 
    """ 
    Return the total number of tiles in the room. 

    returns: an integer 
    """ 

    return self.width*self.height 

def getNumCleanedTiles(self): 
    """ 
    Return the total number of clean tiles in the room. 

    returns: an integer 
    """ 
    numCleanTiles = 0 

    for row in range(self.width): 
     for column in range(self.height): 
      if self.tiles[row][column] == True: 
       numCleanTiles +=1 

    return numCleanTiles 

def getRandomPosition(self): 
    """ 
    Return a random position inside the room. 

    returns: a Position object. 
    """ 
    # 
    return Position(random.randrange(0, self.width), random.randrange(0, self.height)) 

def isPositionInRoom(self, pos): 
    """ 
    Return True if pos is inside the room. 

    pos: a Position object. 
    returns: True if pos is in the room, False otherwise. 
    """ 
    if 0 <= pos.getX() < self.width and 0 <= pos.getY() < self.height: 
     return True 
    else: 
     return False 


class Robot(object): 
""" 
Represents a robot cleaning a particular room. 

At all times the robot has a particular position and direction in the room. 
The robot also has a fixed speed. 

Subclasses of Robot should provide movement strategies by implementing 
updatePositionAndClean(), which simulates a single time-step. 
""" 
def __init__(self, room, speed): 
    """ 
    Initializes a Robot with the given speed in the specified room. The 
    robot initially has a random direction and a random position in the 
    room. The robot cleans the tile it is on. 

    room: a RectangularRoom object. 
    speed: a float (speed > 0) 
    """ 
    #raise NotImplementedError 

    self.room = room 
    self.speed = speed 

    self.position = self.room.getRandomPosition() 

    self.direction = random.randint(0, 359) 

    self.room.cleanTileAtPosition(self.position) 

def getRobotPosition(self): 
    """ 
    Return the position of the robot. 

    returns: a Position object giving the robot's position. 
    """ 
    return self.position 

def getRobotDirection(self): 
    """ 
    Return the direction of the robot. 

    returns: an integer d giving the direction of the robot as an angle in 
    degrees, 0 <= d < 360. 
    """ 
    d = self.direction 
    return d 

def setRobotPosition(self, position): 
    """ 
    Set the position of the robot to POSITION. 

    position: a Position object. 
    """ 
    self.position = position 
    return self.position 

def setRobotDirection(self, direction): 
    """ 
    Set the direction of the robot to DIRECTION. 

    direction: integer representing an angle in degrees 
    """ 
    self.direction = direction 
    return self.direction 

def updatePositionAndClean(self): 
    """ 
    Simulate the raise passage of a single time-step. 

    Move the robot to a new position and mark the tile it is on as having 
    been cleaned. 
    """ 
    raise NotImplementedError # don't change this! 



class StandardRobot(Robot): 
""" 
A StandardRobot is a Robot with the standard movement strategy. 

At each time-step, a StandardRobot attempts to move in its current 
direction; when it would hit a wall, it *instead* chooses a new direction 
randomly. 
""" 

def updatePositionAndClean(self): 
    """ 
    Simulate the raise passage of a single time-step. 

    Move the robot to a new position and mark the tile it is on as having 
    been cleaned. 
    """ 

    newPosition = self.position.getNewPosition(self.direction, self.speed) 

    if 0 <= newPosition.getX() <= self.room.width and 0 <= newPosition.getY() <= self.room.height: 
     self.setRobotPosition(newPosition) 
     self.room.cleanTileAtPosition(self.position) 
    else: 
     self.setRobotDirection(random.randint(0, 359)) 


    # Uncomment this line to see your implementation of StandardRobot in action! 
    #testRobotMovement(StandardRobot, RectangularRoom) 



def runSimulation(num_robots, speed, width, height, min_coverage, num_trials, 
       robot_type): 
""" 
Runs NUM_TRIALS trials of the simulation and returns the mean number of 
time-steps needed to clean the fraction MIN_COVERAGE of the room. 

The simulation is run with NUM_ROBOTS robots of type ROBOT_TYPE, each with 
speed SPEED, in a room of dimensions WIDTH x HEIGHT. 

num_robots: an int (num_robots > 0) 
speed: a float (speed > 0) 
width: an int (width > 0) 
height: an int (height > 0) 
min_coverage: a float (0 <= min_coverage <= 1.0) 
num_trials: an int (num_trials > 0) 
robot_type: class of robot to be instantiated (e.g. StandardRobot or 
      RandomWalkRobot) 
""" 

numTimeStepsList = [] 

for i in range(num_trials): 
    room1 = RectangularRoom(width, height) 
    numTimeSteps = 0 
    robot = [] 

    for n in range(num_robots-1): 
     robot[n] = robot_type(room1, speed) 

    while (1.0 - float(room1.getNumCleanedTiles())/float(room1.getNumTiles())) >= min_coverage:  
     for n in range(num_robots-1): 
      robot[n].updatePositionAndClean() 
      numTimeSteps += 1 
      #print numTimeSteps 

    numTimeStepsList.append(numTimeSteps) 
#print numTimeStepsList 
return sum(numTimeStepsList)/len(numTimeStepsList)  




#raise NotImplementedError 

# Uncomment this line to see how much your simulation takes on average 
print runSimulation(1, 1.0, 10, 10, 0.75, 30, StandardRobot) 



class RandomWalkRobot(Robot): 
""" 
A RandomWalkRobot is a robot with the "random walk" movement strategy: it 
chooses a new direction at random at the end of each time-step. 
""" 
def updatePositionAndClean(self): 
    """ 
    Simulate the passage of a single time-step. 

    Move the robot to a new position and mark the tile it is on as having 
    been cleaned. 
    """ 
    raise NotImplementedError 


def showPlot1(title, x_label, y_label): 
""" 
What information does the plot produced by this function tell you? 
""" 
num_robot_range = range(1, 11) 
times1 = [] 
times2 = [] 
for num_robots in num_robot_range: 
    print "Plotting", num_robots, "robots..." 
    times1.append(runSimulation(num_robots, 1.0, 20, 20, 0.8, 20, StandardRobot)) 
    times2.append(runSimulation(num_robots, 1.0, 20, 20, 0.8, 20, RandomWalkRobot)) 
pylab.plot(num_robot_range, times1) 
pylab.plot(num_robot_range, times2) 
pylab.title(title) 
pylab.legend(('StandardRobot', 'RandomWalkRobot')) 
pylab.xlabel(x_label) 
pylab.ylabel(y_label) 
pylab.show() 


def showPlot2(title, x_label, y_label): 
""" 
What information does the plot produced by this function tell you? 
""" 
aspect_ratios = [] 
times1 = [] 
times2 = [] 
for width in [10, 20, 25, 50]: 
    height = 300/width 
    print "Plotting cleaning time for a room of width:", width, "by height:", height 
    aspect_ratios.append(float(width)/height) 
    times1.append(runSimulation(2, 1.0, width, height, 0.8, 200, StandardRobot)) 
    times2.append(runSimulation(2, 1.0, width, height, 0.8, 200, RandomWalkRobot)) 
pylab.plot(aspect_ratios, times1) 
pylab.plot(aspect_ratios, times2) 
pylab.title(title) 
pylab.legend(('StandardRobot', 'RandomWalkRobot')) 
pylab.xlabel(x_label) 
pylab.ylabel(y_label) 
pylab.show() 

回答

0

當你調用runSimulation1一個num_robots的說法,它實際上並沒有讓所有的任何機器人,所以從來都沒有得到清潔。

罪魁禍首是這個循環:

for n in range(num_robots-1): 
    robot[n] = robot_type(room1, speed) 

這幾乎是完全錯誤的。您無法指定robot列表中的任何索引,因爲它開始爲空。而且你總是循環的次數少於你應該的次數(如果num_robots1則爲0次)。你可能想要更類似於:

for _ in range(num_robots): 
    robot.append(robot_type(room1, speed)) 
+0

傻我!當然是。感謝那。 – Berwhale