Advertisement
canezzy

Untitled

Mar 29th, 2019
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.52 KB | None | 0 0
  1. # autograder.py
  2. # -------------
  3. # Licensing Information: You are free to use or extend these projects for
  4. # educational purposes provided that (1) you do not distribute or publish
  5. # solutions, (2) you retain this notice, and (3) you provide clear
  6. # attribution to UC Berkeley, including a link to http://ai.berkeley.edu.
  7. #
  8. # Attribution Information: The Pacman AI projects were developed at UC Berkeley.
  9. # The core projects and autograders were primarily created by John DeNero
  10. # (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu).
  11. # Student side autograding was added by Brad Miller, Nick Hay, and
  12. # Pieter Abbeel (pabbeel@cs.berkeley.edu).
  13.  
  14.  
  15. # imports from python standard library
  16. import grading
  17. import imp
  18. import optparse
  19. import os
  20. import re
  21. import sys
  22. import projectParams
  23. import random
  24. random.seed(0)
  25. try:
  26. from pacman import GameState
  27. except:
  28. pass
  29.  
  30. # register arguments and set default values
  31. def readCommand(argv):
  32. parser = optparse.OptionParser(description = 'Run public tests on student code')
  33. parser.set_defaults(generateSolutions=False, edxOutput=False, gsOutput=False, muteOutput=False, printTestCase=False, noGraphics=False)
  34. parser.add_option('--test-directory',
  35. dest = 'testRoot',
  36. default = 'test_cases',
  37. help = 'Root test directory which contains subdirectories corresponding to each question')
  38. parser.add_option('--student-code',
  39. dest = 'studentCode',
  40. default = projectParams.STUDENT_CODE_DEFAULT,
  41. help = 'comma separated list of student code files')
  42. parser.add_option('--code-directory',
  43. dest = 'codeRoot',
  44. default = "",
  45. help = 'Root directory containing the student and testClass code')
  46. parser.add_option('--test-case-code',
  47. dest = 'testCaseCode',
  48. default = projectParams.PROJECT_TEST_CLASSES,
  49. help = 'class containing testClass classes for this project')
  50. parser.add_option('--generate-solutions',
  51. dest = 'generateSolutions',
  52. action = 'store_true',
  53. help = 'Write solutions generated to .solution file')
  54. parser.add_option('--edx-output',
  55. dest = 'edxOutput',
  56. action = 'store_true',
  57. help = 'Generate edX output files')
  58. parser.add_option('--gradescope-output',
  59. dest = 'gsOutput',
  60. action = 'store_true',
  61. help = 'Generate GradeScope output files')
  62. parser.add_option('--mute',
  63. dest = 'muteOutput',
  64. action = 'store_true',
  65. help = 'Mute output from executing tests')
  66. parser.add_option('--print-tests', '-p',
  67. dest = 'printTestCase',
  68. action = 'store_true',
  69. help = 'Print each test case before running them.')
  70. parser.add_option('--test', '-t',
  71. dest = 'runTest',
  72. default = None,
  73. help = 'Run one particular test. Relative to test root.')
  74. parser.add_option('--question', '-q',
  75. dest = 'gradeQuestion',
  76. default = None,
  77. help = 'Grade one particular question.')
  78. parser.add_option('--no-graphics',
  79. dest = 'noGraphics',
  80. action = 'store_true',
  81. help = 'No graphics display for pacman games.')
  82.  
  83. parser.add_option('-l', '--layout', dest='layout',
  84. help='the LAYOUT_FILE from which to load the map layout',
  85. metavar='LAYOUT_FILE', default='mediumClassic')
  86. parser.add_option('-a', '--pacman', dest='pacman',
  87. help='the agent TYPE in the pacmanAgents module to use',
  88. metavar='TYPE', default='KeyboardAgent')
  89.  
  90. parser.add_option('--check', dest="check")
  91.  
  92. (options, args) = parser.parse_args(argv)
  93. return options
  94.  
  95.  
  96. # confirm we should author solution files
  97. def confirmGenerate():
  98. print 'WARNING: this action will overwrite any solution files.'
  99. print 'Are you sure you want to proceed? (yes/no)'
  100. while True:
  101. ans = sys.stdin.readline().strip()
  102. if ans == 'yes':
  103. break
  104. elif ans == 'no':
  105. sys.exit(0)
  106. else:
  107. print 'please answer either "yes" or "no"'
  108.  
  109.  
  110. # TODO: Fix this so that it tracebacks work correctly
  111. # Looking at source of the traceback module, presuming it works
  112. # the same as the intepreters, it uses co_filename. This is,
  113. # however, a readonly attribute.
  114. def setModuleName(module, filename):
  115. functionType = type(confirmGenerate)
  116. classType = type(optparse.Option)
  117.  
  118. for i in dir(module):
  119. o = getattr(module, i)
  120. if hasattr(o, '__file__'): continue
  121.  
  122. if type(o) == functionType:
  123. setattr(o, '__file__', filename)
  124. elif type(o) == classType:
  125. setattr(o, '__file__', filename)
  126. # TODO: assign member __file__'s?
  127. #print i, type(o)
  128.  
  129.  
  130. #from cStringIO import StringIO
  131.  
  132. def loadModuleString(moduleSource):
  133. # Below broken, imp doesn't believe its being passed a file:
  134. # ValueError: load_module arg#2 should be a file or None
  135. #
  136. #f = StringIO(moduleCodeDict[k])
  137. #tmp = imp.load_module(k, f, k, (".py", "r", imp.PY_SOURCE))
  138. tmp = imp.new_module(k)
  139. exec moduleCodeDict[k] in tmp.__dict__
  140. setModuleName(tmp, k)
  141. return tmp
  142.  
  143. import py_compile
  144.  
  145. def loadModuleFile(moduleName, filePath):
  146. with open(filePath, 'r') as f:
  147. return imp.load_module(moduleName, f, "%s.py" % moduleName, (".py", "r", imp.PY_SOURCE))
  148.  
  149.  
  150. def readFile(path, root=""):
  151. "Read file from disk at specified path and return as string"
  152. with open(os.path.join(root, path), 'r') as handle:
  153. return handle.read()
  154.  
  155.  
  156. #######################################################################
  157. # Error Hint Map
  158. #######################################################################
  159.  
  160. # TODO: use these
  161. ERROR_HINT_MAP = {
  162. 'q1': {
  163. "<type 'exceptions.IndexError'>": """
  164. We noticed that your project threw an IndexError on q1.
  165. While many things may cause this, it may have been from
  166. assuming a certain number of successors from a state space
  167. or assuming a certain number of actions available from a given
  168. state. Try making your code more general (no hardcoded indices)
  169. and submit again!
  170. """
  171. },
  172. 'q3': {
  173. "<type 'exceptions.AttributeError'>": """
  174. We noticed that your project threw an AttributeError on q3.
  175. While many things may cause this, it may have been from assuming
  176. a certain size or structure to the state space. For example, if you have
  177. a line of code assuming that the state is (x, y) and we run your code
  178. on a state space with (x, y, z), this error could be thrown. Try
  179. making your code more general and submit again!
  180.  
  181. """
  182. }
  183. }
  184.  
  185. import pprint
  186.  
  187. def splitStrings(d):
  188. d2 = dict(d)
  189. for k in d:
  190. if k[0:2] == "__":
  191. del d2[k]
  192. continue
  193. if d2[k].find("\n") >= 0:
  194. d2[k] = d2[k].split("\n")
  195. return d2
  196.  
  197.  
  198. def printTest(testDict, solutionDict):
  199. pp = pprint.PrettyPrinter(indent=4)
  200. print "Test case:"
  201. for line in testDict["__raw_lines__"]:
  202. print " |", line
  203. print "Solution:"
  204. for line in solutionDict["__raw_lines__"]:
  205. print " |", line
  206.  
  207.  
  208. def runTest(testName, moduleDict, printTestCase=False, display=None):
  209. import testParser
  210. import testClasses
  211. for module in moduleDict:
  212. setattr(sys.modules[__name__], module, moduleDict[module])
  213.  
  214. testDict = testParser.TestParser(testName + ".test").parse()
  215. solutionDict = testParser.TestParser(testName + ".solution").parse()
  216. test_out_file = os.path.join('%s.test_output' % testName)
  217. testDict['test_out_file'] = test_out_file
  218. testClass = getattr(projectTestClasses, testDict['class'])
  219.  
  220. questionClass = getattr(testClasses, 'Question')
  221. question = questionClass({'max_points': 0}, display)
  222. testCase = testClass(question, testDict)
  223.  
  224. if printTestCase:
  225. printTest(testDict, solutionDict)
  226.  
  227. # This is a fragile hack to create a stub grades object
  228. grades = grading.Grades(projectParams.PROJECT_NAME, [(None,0)])
  229. testCase.execute(grades, moduleDict, solutionDict)
  230.  
  231.  
  232. # returns all the tests you need to run in order to run question
  233. def getDepends(testParser, testRoot, question):
  234. allDeps = [question]
  235. questionDict = testParser.TestParser(os.path.join(testRoot, question, 'CONFIG')).parse()
  236. if 'depends' in questionDict:
  237. depends = questionDict['depends'].split()
  238. for d in depends:
  239. # run dependencies first
  240. allDeps = getDepends(testParser, testRoot, d) + allDeps
  241. return allDeps
  242.  
  243. # get list of questions to grade
  244. def getTestSubdirs(testParser, testRoot, questionToGrade):
  245. problemDict = testParser.TestParser(os.path.join(testRoot, 'CONFIG')).parse()
  246. if questionToGrade != None:
  247. questions = getDepends(testParser, testRoot, questionToGrade)
  248. if len(questions) > 1:
  249. print 'Note: due to dependencies, the following tests will be run: %s' % ' '.join(questions)
  250. return questions
  251. if 'order' in problemDict:
  252. return problemDict['order'].split()
  253. return sorted(os.listdir(testRoot))
  254.  
  255.  
  256. # evaluate student code
  257. def evaluate(generateSolutions, testRoot, moduleDict, exceptionMap=ERROR_HINT_MAP,
  258. edxOutput=False, muteOutput=False, gsOutput=False,
  259. printTestCase=False, questionToGrade=None, display=None):
  260. # imports of testbench code. note that the testClasses import must follow
  261. # the import of student code due to dependencies
  262. import testParser
  263. import testClasses
  264. for module in moduleDict:
  265. setattr(sys.modules[__name__], module, moduleDict[module])
  266.  
  267. questions = []
  268. questionDicts = {}
  269. test_subdirs = getTestSubdirs(testParser, testRoot, questionToGrade)
  270. for q in test_subdirs:
  271. subdir_path = os.path.join(testRoot, q)
  272. if not os.path.isdir(subdir_path) or q[0] == '.':
  273. continue
  274.  
  275. # create a question object
  276. questionDict = testParser.TestParser(os.path.join(subdir_path, 'CONFIG')).parse()
  277. questionClass = getattr(testClasses, questionDict['class'])
  278. question = questionClass(questionDict, display)
  279. questionDicts[q] = questionDict
  280.  
  281. # load test cases into question
  282. tests = filter(lambda t: re.match('[^#~.].*\.test\Z', t), os.listdir(subdir_path))
  283. tests = map(lambda t: re.match('(.*)\.test\Z', t).group(1), tests)
  284. for t in sorted(tests):
  285. test_file = os.path.join(subdir_path, '%s.test' % t)
  286. solution_file = os.path.join(subdir_path, '%s.solution' % t)
  287. test_out_file = os.path.join(subdir_path, '%s.test_output' % t)
  288. testDict = testParser.TestParser(test_file).parse()
  289. if testDict.get("disabled", "false").lower() == "true":
  290. continue
  291. testDict['test_out_file'] = test_out_file
  292. testClass = getattr(projectTestClasses, testDict['class'])
  293. testCase = testClass(question, testDict)
  294. def makefun(testCase, solution_file):
  295. if generateSolutions:
  296. # write solution file to disk
  297. return lambda grades: testCase.writeSolution(moduleDict, solution_file)
  298. else:
  299. # read in solution dictionary and pass as an argument
  300. testDict = testParser.TestParser(test_file).parse()
  301. solutionDict = testParser.TestParser(solution_file).parse()
  302. if printTestCase:
  303. return lambda grades: printTest(testDict, solutionDict) or testCase.execute(grades, moduleDict, solutionDict)
  304. else:
  305. return lambda grades: testCase.execute(grades, moduleDict, solutionDict)
  306. question.addTestCase(testCase, makefun(testCase, solution_file))
  307.  
  308. # Note extra function is necessary for scoping reasons
  309. def makefun(question):
  310. return lambda grades: question.execute(grades)
  311. setattr(sys.modules[__name__], q, makefun(question))
  312. questions.append((q, question.getMaxPoints()))
  313.  
  314. grades = grading.Grades(projectParams.PROJECT_NAME, questions,
  315. gsOutput=gsOutput, edxOutput=edxOutput, muteOutput=muteOutput)
  316. if questionToGrade == None:
  317. for q in questionDicts:
  318. for prereq in questionDicts[q].get('depends', '').split():
  319. grades.addPrereq(q, prereq)
  320.  
  321. grades.grade(sys.modules[__name__], bonusPic = projectParams.BONUS_PIC)
  322. return grades.points
  323.  
  324.  
  325.  
  326. def getDisplay(graphicsByDefault, options=None):
  327. graphics = graphicsByDefault
  328. if options is not None and options.noGraphics:
  329. graphics = False
  330. if graphics:
  331. try:
  332. import graphicsDisplay
  333. return graphicsDisplay.PacmanGraphics(1, frameTime=.05)
  334. except ImportError:
  335. pass
  336. import textDisplay
  337. return textDisplay.NullGraphics()
  338.  
  339.  
  340.  
  341. from search import nullHeuristic
  342. from util import PriorityQueue
  343. from pacman import loadAgent, runGames
  344.  
  345. class SeachTreeNode:
  346.  
  347. def __init__(self, state, action, cost, parent):
  348. self.state = state
  349. self.action = action
  350. self.cost = cost
  351. self.parent = parent
  352.  
  353. def isConsistent(problem, heuristic=nullHeuristic):
  354. visisted = []
  355. data_structure = PriorityQueue()
  356. root = SeachTreeNode(problem.getStartState(), None, 0, None)
  357. data_structure.push(root, 0)
  358.  
  359. while not data_structure.isEmpty():
  360. node = data_structure.pop()
  361.  
  362. if problem.isGoalState(node.state):
  363. break
  364. elif node.state in visisted:
  365. continue
  366. else:
  367. visisted.append(node.state)
  368. successors = problem.getSuccessors(node.state)
  369. for s in successors:
  370. newNode = SeachTreeNode(s[0], s[1], node.cost + s[2], node)
  371. data_structure.push(newNode, newNode.cost + heuristic(newNode.state, problem))
  372.  
  373. if abs(heuristic(newNode.parent.state, problem) - heuristic(newNode.state, problem)) > s[2]:
  374. print("Heuristic is not consistent!\n")
  375. exit(1)
  376. print("Heuristic is consistent!\n")
  377. exit(1)
  378.  
  379. if __name__ == '__main__':
  380. options = readCommand(sys.argv)
  381. if options.generateSolutions:
  382. confirmGenerate()
  383. codePaths = options.studentCode.split(',')
  384.  
  385. moduleDict = {}
  386. for cp in codePaths:
  387. moduleName = re.match('.*?([^/]*)\.py', cp).group(1)
  388. moduleDict[moduleName] = loadModuleFile(moduleName, os.path.join(options.codeRoot, cp))
  389.  
  390. if options.check == "consistency" and "searchAgents" in moduleDict:
  391. agentType = loadAgent(options.pacman, True)
  392. agent = agentType(**{})
  393. agent.searchFunction = lambda prob: isConsistent(prob, agent.heuristic)
  394.  
  395. import layout as l
  396. # layout, pacman, ghosts, display, numGames, record, numTraining = 0, catchExceptions = False, timeout = 30
  397. runGames(l.getLayout(options.layout), agent, [], None, 1, None, 1)
  398. exit(1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement