Guest User

ps6.py

a guest
May 12th, 2014
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.93 KB | None | 0 0
  1. # Problem Set 6: Simulating robots
  2. # Name:
  3. # Collaborators:
  4. # Time:
  5.  
  6. import math
  7. import random
  8.  
  9. import ps6_visualize
  10. import pylab
  11.  
  12. # === Provided classes
  13.  
  14. class Position(object):
  15. """
  16. A Position represents a location in a two-dimensional room.
  17. """
  18. def __init__(self, x, y):
  19. """
  20. Initializes a position with coordinates (x, y).
  21. """
  22. self.x = x
  23. self.y = y
  24. def getX(self):
  25. return self.x
  26. def getY(self):
  27. return self.y
  28. def getNewPosition(self, angle, speed):
  29. """
  30. Computes and returns the new Position after a single clock-tick has
  31. passed, with this object as the current position, and with the
  32. specified angle and speed.
  33.  
  34. Does NOT test whether the returned position fits inside the room.
  35.  
  36. angle: float representing angle in degrees, 0 <= angle < 360
  37. speed: positive float representing speed
  38.  
  39. Returns: a Position object representing the new position.
  40. """
  41. old_x, old_y = self.getX(), self.getY()
  42. # Compute the change in position
  43. delta_y = speed * math.cos(math.radians(angle))
  44. delta_x = speed * math.sin(math.radians(angle))
  45. # Add that to the existing position
  46. new_x = old_x + delta_x
  47. new_y = old_y + delta_y
  48. return Position(new_x, new_y)
  49.  
  50. def __eq__(self, pos):
  51. if self.getX() == pos.getX() and self.getY() == pos.getY():
  52. return True
  53. else:
  54. return False
  55.  
  56. # === Problems 1
  57.  
  58. class RectangularRoom(object):
  59. """
  60. A RectangularRoom represents a rectangular region containing clean or dirty
  61. tiles.
  62.  
  63. A room has a width and a height and contains (width * height) tiles. At any
  64. particular time, each of these tiles is either clean or dirty.
  65. """
  66. def __init__(self, width, height):
  67. """
  68. Initializes a rectangular room with the specified width and height.
  69.  
  70. Initially, no tiles in the room have been cleaned.
  71.  
  72. width: an integer > 0
  73. height: an integer > 0
  74. """
  75. self.width = int(width)
  76. self.height = int(height)
  77.  
  78. # Tiles are a list of positions
  79. self.tiles = []
  80. for i in range(self.width):
  81. for j in range(self.height):
  82. self.tiles.append(Position(i,j))
  83.  
  84. self.dirty_tiles = self.tiles[:]
  85.  
  86. # # I'm a dirty, dirty whore
  87. # def addTile(self, x, y):
  88. # self.tiles.append(Position(x,y))
  89.  
  90. def cleanTileAtPosition(self, pos):
  91. """
  92. Mark the tile under the position POS as cleaned.
  93.  
  94. Assumes that POS represents a valid position inside this room.
  95.  
  96. pos: a Position
  97. """
  98. x = math.floor(pos.getX())
  99. y = math.floor(pos.getY())
  100. tile_pos = Position(x,y)
  101. if tile_pos in self.dirty_tiles:
  102. self.dirty_tiles.remove(tile_pos)
  103.  
  104. def tileList(self, tiles):
  105. tiles_list = []
  106. for t in tiles:
  107. tiles_list.append(str(t.getX())+","+str(t.getY()))
  108. return tiles_list
  109.  
  110.  
  111. def getDirtyTiles(self):
  112. """
  113. Returns a list of dirty tiles
  114. """
  115. return self.tileList(self.dirty_tiles)
  116.  
  117.  
  118. def getCleanTiles(self):
  119. clean_tiles = self.tiles[:]
  120. for tile in self.dirty_tiles:
  121. clean_tiles.remove(tile)
  122. return self.tileList(clean_tiles)
  123.  
  124. def isTileCleaned(self, pos):
  125. """
  126. Return True if the tile (m, n) has been cleaned.
  127.  
  128. Assumes that (m, n) represents a valid tile inside the room.
  129.  
  130. m: an integer
  131. n: an integer
  132. returns: True if (m, n) is cleaned, False otherwise
  133. """
  134. #is_clean = Position(m, n)
  135. x = math.floor(pos.getX())
  136. y = math.floor(pos.getY())
  137. tile_pos = Position(x,y)
  138. return tile_pos not in self.dirty_tiles
  139.  
  140. def getNumTiles(self):
  141. """
  142. Return the total number of tiles in the room.
  143.  
  144. returns: an integer
  145. """
  146. return len(self.tiles)
  147.  
  148. def getNumCleanedTiles(self):
  149. """
  150. Return the total number of clean tiles in the room.
  151.  
  152. returns: an integer
  153. """
  154. return len(self.tiles) - len(self.dirty_tiles)
  155.  
  156. def getRandomPosition(self):
  157. """
  158. Return a random position inside the room.
  159.  
  160. returns: a Position object.
  161. """
  162. return self.tiles[random.randint(0,len(self.tiles))]
  163.  
  164. def isPositionInRoom(self, pos):
  165. """
  166. Return True if pos is inside the room.
  167.  
  168. pos: a Position object.
  169. returns: True if pos is in the room, False otherwise.
  170. """
  171. # Check for position out of rectangle bounds
  172. #if pos.getX() > self.width or pos.getY() > self.height:
  173. # return False
  174. #if pos.getX() < 0 or pos.getY() < 0:
  175. # return False
  176. #return True
  177. return ((0 <= pos.getX() < self.width) and (0 <= pos.getY() < self.height))
  178.  
  179.  
  180. class Robot(object):
  181. """
  182. Represents a robot cleaning a particular room.
  183.  
  184. At all times the robot has a particular position and direction in the room.
  185. The robot also has a fixed speed.
  186.  
  187. Subclasses of Robot should provide movement strategies by implementing
  188. updatePositionAndClean(), which simulates a single time-step.
  189. """
  190. def __init__(self, room, speed, name="Little Jimmy"):
  191. """
  192. Initializes a Robot with the given speed in the specified room. The
  193. robot initially has a random direction and a random position in the
  194. room. The robot cleans the tile it is on.
  195.  
  196. room: a RectangularRoom object.
  197. speed: a float (speed > 0)
  198. """
  199. self.name = name
  200. self.room = room
  201. self.speed = float(speed)
  202. self.position = Position(0,0)
  203. self.direction = random.randint(0,359)
  204.  
  205. def getRobotPosition(self):
  206. """
  207. Return the position of the robot.
  208.  
  209. returns: a Position object giving the robot's position.
  210. """
  211. return self.position
  212.  
  213. def getRobotDirection(self):
  214. """
  215. Return the direction of the robot.
  216.  
  217. returns: an integer d giving the direction of the robot as an angle in
  218. degrees, 0 <= d < 360.
  219. """
  220. return self.direction
  221.  
  222. def setRobotPosition(self, position):
  223. """
  224. Set the position of the robot to POSITION.
  225.  
  226. position: a Position object.
  227. """
  228. self.position = position
  229.  
  230. def setRobotDirection(self, direction):
  231. """
  232. Set the direction of the robot to DIRECTION.
  233.  
  234. direction: integer representing an angle in degrees
  235. """
  236. self.direction = direction
  237.  
  238. def updatePositionAndClean(self):
  239. """
  240. Simulate the raise passage of a single time-step.
  241.  
  242. Move the robot to a new position and mark the tile it is on as having
  243. been cleaned.
  244. """
  245. raise NotImplementedError
  246.  
  247.  
  248. ## === Problem 2
  249. class StandardRobot(Robot):
  250. """
  251. A StandardRobot is a Robot with the standard movement strategy.
  252.  
  253. At each time-step, a StandardRobot attempts to move in its current direction; when
  254. it hits a wall, it chooses a new direction randomly.
  255. """
  256. def updatePositionAndClean(self):
  257. """
  258. Simulate the passage of a single time-step.
  259.  
  260. Move the robot to a new position and mark the tile it is on as having
  261. been cleaned.
  262. """
  263.  
  264. move_position = self.position.getNewPosition(self.direction, self.speed)
  265. if self.room.isPositionInRoom(move_position):
  266. self.setRobotPosition(move_position)
  267. if not self.room.isTileCleaned(self.position):
  268. self.room.cleanTileAtPosition(self.position)
  269. else:
  270. self.setRobotDirection(random.randint(0,359))
  271.  
  272. class RandomWalkRobot(Robot):
  273. """
  274. A RandomWalkRobot is a robot with the "random walk" movement strategy: it
  275. chooses a new direction at random after each time-step.
  276. """
  277. def updatePositionAndClean(self):
  278. """
  279. Simulate the passage of a single time-step.
  280.  
  281. Move the robot to a new position and mark the tile it is on as having
  282. been cleaned.
  283. """
  284. cur_pos = self.getRobotPosition()
  285. cur_dir = self.getRobotDirection()
  286. self.setRobotDirection(random.randrange(360))
  287. new_pos = cur_pos.getNewPosition(cur_dir, self.speed)
  288. if self.room.isPositionInRoom(new_pos):
  289. self.setRobotPosition(new_pos)
  290. self.room.cleanTileAtPosition(new_pos)
  291.  
  292. ## === Problem 3
  293. def runSimulation(num_robots, speed, width, height, min_coverage, num_trials,
  294. robot_type, vflag=False):
  295. """
  296. Runs NUM_TRIALS trials of the simulation and returns the mean number of
  297. time-steps needed to clean the fraction MIN_COVERAGE of the room.
  298.  
  299. The simulation is run with NUM_ROBOTS robots of type ROBOT_TYPE, each with
  300. speed SPEED, in a room of dimensions WIDTH x HEIGHT.
  301.  
  302. num_robots: an int (num_robots > 0)
  303. speed: a float (speed > 0)
  304. width: an int (width > 0)
  305. height: an int (height > 0)
  306. min_coverage: a float (0 <= min_coverage <= 1.0)
  307. num_trials: an int (num_trials > 0)
  308. robot_type: class of robot to be instantiated (e.g. Robot or
  309. RandomWalkRobot)
  310. """
  311. sim_room = RectangularRoom(width, height)
  312. robot_hive = []
  313. time_steps = 0
  314. robot_id = 1000
  315.  
  316. for trial in range(num_trials):
  317. if vflag:
  318. anim = ps6_visualize.RobotVisualization(num_robots, width, height)
  319.  
  320. for robot in range(num_robots):
  321. robot_hive.append(robot_type(sim_room, speed, "jimmy-"+str(robot_id)))
  322. robot_id += 1
  323.  
  324. while (sim_room.getNumCleanedTiles()/float(sim_room.getNumTiles())) < min_coverage:
  325. for robot in robot_hive:
  326. robot.updatePositionAndClean()
  327. time_steps += 1
  328.  
  329. if vflag:
  330. anim.update(sim_room, robot_hive)
  331.  
  332. if vflag:
  333. anim.done()
  334. return time_steps / num_trials
  335.  
  336.  
  337.  
  338. ## === Problem 4
  339. ##
  340. ## 1) How long does it take to clean 80% of a 20x20 room with each of 1-10 robots?
  341. ##
  342. ## 2. how long doesn it take two robots to clean 80% or rooms with dimensions
  343. ## 20x20, 25x16, 40x10, 50x8, and 100x4?
  344.  
  345. def showPlot1(title, x_label, y_label):
  346. """
  347. Produces a plot showing dependence of cleaning time on number of robots.
  348. """
  349. num_robot_range = range(1, 11)
  350. times1 = []
  351. times2 = []
  352. for num_robots in num_robot_range:
  353. print "Plotting", num_robots, "robots..."
  354. times1.append(runSimulation(num_robots, 1.0, 20, 20, 0.8, 100, StandardRobot, True))
  355. times2.append(runSimulation(num_robots, 1.0, 20, 20, 0.8, 20, RandomWalkRobot, True))
  356. pylab.plot(num_robot_range, times1)
  357. pylab.plot(num_robot_range, times2)
  358. pylab.title(title)
  359. pylab.legend(('StandardRobot', 'RandomWalkRobot'))
  360. pylab.xlabel(x_label)
  361. pylab.ylabel(y_label)
  362. pylab.show()
  363.  
  364.  
  365. #def showPlot2():
  366. # """
  367. # Produces a plot showing dependence of cleaning time on room shape.
  368. # """
  369. # raise NotImplementedError
  370.  
  371. ## === Problem 5
  372. #
  373. #class RandomWalkRobot(Robot):
  374. # """
  375. # A RandomWalkRobot is a robot with the "random walk" movement strategy: it
  376. # chooses a new direction at random after each time-step.
  377. # """
  378. # raise NotImplementedError
  379. #
  380. #
  381. ## === Problem 6
  382. #
  383. ## For the parameters tested below (cleaning 80% of a 20x20 square room),
  384. ## RandomWalkRobots take approximately twice as long to clean the same room as
  385. ## StandardRobots do.
  386. #def showPlot3():
  387. # """
  388. # Produces a plot comparing the two robot strategies.
  389. # """
  390. # raise NotImplementedError
Advertisement
Add Comment
Please, Sign In to add comment