/hw2/scratch/hw2_part2_sol1.py

https://github.com/andrewdyates/CSE-630
Python | 304 lines | 194 code | 47 blank | 63 comment | 88 complexity | 4a262a3bac50522101b311219fdb9d83 MD5 | raw file
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import sys
  4. # GLOBAL AGENT STATES
  5. item1 = 0 # int >= 0, 0: empty
  6. item2 = 0 # int >= 0, 0: empty
  7. hand = 0 # int >= 0, 0: empty
  8. def ReflexAgentWithState(\
  9. belta_current, belta_next, beltb_current, beltb_next, power):
  10. """Return two-belt conveyor action based on agent perception.
  11. Args:
  12. belta_current: int >= -1
  13. belta_next: int >= -1
  14. beltb_current: int >= -1
  15. beltb_next: int >= -1
  16. power: int >= 0
  17. Returns:
  18. str of ACTION
  19. """
  20. global item1
  21. global item2
  22. global hand
  23. items = [
  24. (1, item1),
  25. (2, item2),
  26. ]
  27. items.sort(key=lambda x: x[1])
  28. belts = [
  29. (('A', 0), belta_current),
  30. (('A', 1), belta_next),
  31. (('B', 0), beltb_current),
  32. (('B', 1), beltb_next),
  33. ]
  34. belts.sort(key=lambda x: x[1], reverse=True)
  35. # Place hand in empty slot: this is free
  36. # =====================
  37. if hand:
  38. if item1 == 0:
  39. item1 = hand
  40. hand = 0
  41. return "FILL_ITEM1"
  42. elif item2 == 0:
  43. item2 = hand
  44. hand = 0
  45. return "FILL_ITEM2"
  46. else:
  47. raise Exception, "No slot for hand item. Error State."
  48. # Handle terminal cases
  49. # =====================
  50. # no power; nothing in hand
  51. if power == 0:
  52. return "STOP"
  53. # end of belts
  54. if belta_current == beltb_current == -1:
  55. return "STOP"
  56. # Handle low power edge cases (empty hand)
  57. # ===========================
  58. if power == 1:
  59. # if a slot is available, get best current item
  60. if item1 == 0 or item2 == 0:
  61. if belta_current > beltb_current:
  62. hand = belta_current
  63. return "PICKUP_A"
  64. else:
  65. hand = beltb_current
  66. return "PICKUP_B"
  67. else:
  68. return "STOP"
  69. elif power == 2:
  70. # 2+1 power to move and get new item, consider best current items
  71. if item1 != 0 and item2 != 0:
  72. if max(belta_current, beltb_current) > min(item1, item2):
  73. if items[0][0] == 1:
  74. item1 = 0
  75. return "DROP_ITEM1"
  76. else:
  77. item2 = 0
  78. return "DROP_ITEM2"
  79. else:
  80. # not enough power to move, drop, pick
  81. return "STOP"
  82. # 2 power and both empty
  83. if item1 == 0 and item2 == 0:
  84. # if sum of current items is greater than best item in next row
  85. if belta_current + beltb_current > belts[0][1] and belts[0][0][1] == 1:
  86. if belta_current > beltb_current:
  87. hand = belta_current
  88. return "PICKUP_A"
  89. else:
  90. hand = beltb_current
  91. return "PICKUP_B"
  92. # 2 power and can only move one belt
  93. if (item1 == 0 or item2 == 0) and belts[0][0][1] == 1:
  94. return "ADVANCE_%s" % belts[0][0][0]
  95. elif power == 3:
  96. # pick up best current item if an opening exists
  97. if max(belta_current, beltb_current) > items[0][1]:
  98. if item1 == 0 or item2 == 0:
  99. if belta_current > beltb_current:
  100. hand = belta_current
  101. return "PICKUP_A"
  102. else:
  103. hand = beltb_current
  104. return "PICKUP_B"
  105. elif power == 4:
  106. # 4+1 power to get 2 items and move, consider both current items
  107. if min(belta_current, beltb_current) > max(item1, item2):
  108. # if no empty slot
  109. if item1 != 0 and item2 != 0:
  110. if items[0][0] == 1:
  111. item1 = 0
  112. return "DROP_ITEM1"
  113. if items[0][0] == 2:
  114. item2 = 0
  115. return "DROP_ITEM2"
  116. # Pick the second most desirable if:
  117. # ===========================
  118. # = second_want is current
  119. # = most_want is next in the same row
  120. # = second_want is also a better item
  121. # = the same item is not available in another row
  122. if belts[1][0][1] == 0 and belts[0][0][1] == 1 and \
  123. belts[0][0][0] == belts[1][0][0] and belts[1][1] > items[0][1] and \
  124. belts[1][1] > belts[2][1]:
  125. # make space if necessary
  126. if items[0][1] != 0:
  127. if items[0][0] == 1:
  128. item1 = 0
  129. return "DROP_ITEM1"
  130. elif items[0][0] == 2:
  131. item2 = 0
  132. return "DROP_ITEM2"
  133. else:
  134. # else pickup second most desirable
  135. hand = belts[1][1]
  136. return "PICKUP_%s" % belts[1][0][0]
  137. # Move a belt if:
  138. # ===========================
  139. # = current is empty
  140. # = next is not end
  141. if belta_current == 0 and belta_next != -1:
  142. return "ADVANCE_A"
  143. if beltb_current == 0 and beltb_next != -1:
  144. return "ADVANCE_B"
  145. # Best Item Handling
  146. # ===========================
  147. # best item is a better item if:
  148. # = best belt item > least held item
  149. if belts[0][1] > items[0][1]:
  150. # Two best items edge cases
  151. # -------------------------
  152. if belts[0][1] == belts[1][1]:
  153. print "!!!1"
  154. # if both on same row, advance that row
  155. if belts[0][0][0] == belts[1][0][0]:
  156. return "ADVANCE_%s" % belts[0][0][0]
  157. # if one is next, advance to make it current
  158. elif belts[0][0][1] != belts[1][0][1]:
  159. if belts[0][0][1] == 1:
  160. return "ADVANCE_%s" % belts[0][0][0]
  161. else:
  162. return "ADVANCE_%s" % belts[1][0][0]
  163. # if both are current, try to advance a belt
  164. elif belts[0][0][1] == belts[1][0][1] == 0:
  165. if belta_current != -1:
  166. return "ADVANCE_A"
  167. elif beltb_current != -1:
  168. return "ADVANCE_B"
  169. # try to get the best item if it is current and better
  170. # - drop the lowest item if no slot is available
  171. # - pick up
  172. if belts[0][0][1] == 0:
  173. # if no empty slot, drop lowest item
  174. if not (item1 == 0 or item2 == 0):
  175. if items[0][0] == 1:
  176. item1 = 0
  177. return "DROP_ITEM1"
  178. else:
  179. item2 = 0
  180. return "DROP_ITEM2"
  181. else:
  182. hand = belts[0][1]
  183. return "PICKUP_%s" % belts[0][0][0]
  184. # else best and better item is next; move that belt
  185. else:
  186. return "ADVANCE_%s" % belts[0][0][0]
  187. # best belt item is not at least as good as least held item
  188. # current visible state is optimal
  189. # try new state by moving belta, then beltb
  190. if belta_next > 0:
  191. return "ADVANCE_A"
  192. elif beltb_next > 0:
  193. return "ADVANCE_B"
  194. elif belta_next == 0:
  195. return "ADVANCE_A"
  196. elif beltb_next == 0:
  197. return "ADVANCE_B"
  198. # optimal configuration, and both belts are near end
  199. elif belta_next == beltb_next == -1:
  200. return "STOP"
  201. def main(args=None):
  202. if args is None:
  203. args = sys.argv
  204. try:
  205. with open(args[1]) as f:
  206. belt_a = map(int, f.readlines())
  207. with open(args[2]) as f:
  208. belt_b = map(int, f.readlines())
  209. except Exception, e:
  210. print "Usage: cmd filename_a filename_b"
  211. raise
  212. # fix belts so that both have at least two appending -1
  213. belt_a.extend([-1, -1])
  214. belt_b.extend([-1, -1])
  215. print "Belts are:"
  216. print "A: ", belt_a
  217. print "B: ", belt_b
  218. print
  219. # RUN AGENT
  220. a = 0
  221. b = 0
  222. run = True
  223. power = 20
  224. belt_a = [4, 21, -1, -1]
  225. belt_b = [4, 20, -1, -1]
  226. while (run):
  227. perceptions = (belt_a[a], belt_a[a+1], belt_b[b], belt_b[b+1], power)
  228. states = (item1, item2, hand)
  229. print "INPUT PERCEPTION: %d %d %d %d %d" % perceptions
  230. print "AGENT STATE: %d, %d, %d" % states
  231. action = ReflexAgentWithState(*perceptions)
  232. print "OUTPUT ACTION: %s" % action
  233. print
  234. if action == "ADVANCE_A":
  235. a += 1
  236. power -= 1
  237. elif action == "ADVANCE_B":
  238. b += 1
  239. power -= 1
  240. elif action == "PICKUP_A":
  241. belt_a[a] = 0
  242. power -= 1
  243. elif action == "PICKUP_B":
  244. belt_b[b] = 0
  245. power -= 1
  246. elif "DROP_ITEM" in action:
  247. power -= 1
  248. elif "FILL_ITEM" in action:
  249. pass
  250. elif action == "STOP":
  251. run = False
  252. print "======"
  253. print "FINAL STATE: %d, %d, %d" % states
  254. print "FINAL SUM: %s" % (item1 + item2)
  255. if __name__ == '__main__':
  256. main(sys.argv)