Python - runSimulation函数中的无限循环

时间:2016-03-19 07:11:43

标签: python class loops instance infinite

这是我们模拟那些roomba真空吸尘器机器人的任务。无论如何,我真的很感激runSimulation功能的一些帮助。它在while循环中启动到无限循环。据我所知,在while循环条件下计算的值是正确的,但是每次测试while循环时它们是否都被初始化了?我不这么认为,但可能是错的。因此,此模拟函数实例化宽度和高度的房间以及num_robots的机器人,并且模拟运行直到清洁地板直到达到min_coverage。 runSimulation的结果是达到min_coverage所需的平均时间步长。提前谢谢!

 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()

1 个答案:

答案 0 :(得分:0)

当您使用runSimulation num_robots参数调用1时,它实际上根本不会制作任何机器人,因此无法清除任何机器人。

罪魁祸首就是这个循环:

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

这几乎都是错的。您无法分配robot列表中的任何索引,因为它从空开始。并且你总是比你想要的时间少一些循环(如果num_robots1,则为零次)。你可能想要更像的东西:

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