def parse_and_eval(string, values=[]): expr, variables = parse_webwork(string) try: if expr: if len(variables) == 0: etree = eval_parsed(expr) return etree, {} if len(variables) != len(values): return expr, variables # if the number of values does # not match number of variables, # return the description of the # variables. else: # if number of values matches # number of variables then # substitute values for # variables and call parser # again on numerical expression. subs_string = substitute(string, variables, values) subs_expr, variables = parse_webwork(subs_string) assert len(variables) == 0 if subs_expr: etree = eval_parsed(subs_expr) return etree, {} else: raise Exception except: log.error('Exception in parse_and_eval, string=%s, parsed=%s' % (string, str(expr))) traceback.print_exc(file=sys.stdout) return None
def find_matches(answer, attempt): logger.debug('find_matches recieved answer=' + str(answer) + ' attempt=' + str(attempt)) attempt_parsed = parse_webwork(attempt) logger.debug('calling eval_parsed on on' + str(attempt_parsed)) attempt_tree = eval_parsed(attempt_parsed) logger.debug('calling flatten on' + str(attempt_tree)) attempt_list = flatten(attempt_tree, 't') logger.debug('attempt list:\n' + str(attempt_list)) answer_parsed = parse_webwork(answer) logger.debug('calling eval_parsed on on' + str(answer_parsed)) answer_tree = eval_parsed(answer_parsed) logger.debug('calling flatten on' + str(answer_tree)) answer_list = flatten(answer_tree, 'c') logger.debug('answer list\n' + str(answer_list)) combined_list = sorted(answer_list + attempt_list, key=lambda x: x[0]) logger.debug('combined list\n' + str(combined_list)) Hits = find_Hits(combined_list) logger.debug('Hits:\n' + str(Hits)) final_matches = find_dominating_hits(Hits, answer, attempt) return final_matches
def parse_and_eval(string,values=[]): expr,variables = parse_webwork(string) try: if expr: if len(variables)==0: etree = eval_parsed(expr) return etree,{} if len(variables)!=len(values): return expr,variables # if the number of values does # not match number of variables, # return the description of the # variables. else: # if number of values matches # number of variables then # substitute values for # variables and call parser # again on numerical expression. subs_string=substitute(string,variables,values) subs_expr,variables=parse_webwork(subs_string) assert len(variables)==0; if subs_expr: etree=eval_parsed(subs_expr) return etree,{} else: raise Exception except: log.error('Exception in parse_and_eval, string=%s, parsed=%s'%(string,str(expr))) traceback.print_exc(file=sys.stdout) return None
def from_string(cls, string): """ Creates expression tree from a string. Throws webwork_parser.WebworkParseException on failure """ data = webwork_parser.parse_webwork(string) return cls(data)
def parse_and_collect_numbers(string): try: parse_tree = parse_webwork(string) eval_tree = eval_parsed(parse_tree) eval_numbers = Collect_numbers(eval_tree) return set(eval_numbers.keys()) except: return set()
def parse_and_eval(string, variables=None): expr = parse_webwork(string) if expr: try: etree = eval_parsed(expr, variables) return expr, etree except: return (None, None) else: return (None, None)
def parse_and_collect_numbers(string): try: parse_tree, variables = parse_webwork(string) if len(variables)==0: eval_tree = eval_parsed(parse_tree) eval_numbers = Collect_numbers(eval_tree) return set(eval_numbers.keys()) else: return Eval_with_Variables(string,variables) except: return set()
def parsed(string): expr = parse_webwork(string) if expr: try: etree = eval_parsed(expr) nums = Collect_numbers(etree) return etree, nums except: return (None, None) else: return (None, None)
def parse_and_collect_numbers(string): try: parse_tree, variables = parse_webwork(string) if len(variables) == 0: eval_tree = eval_parsed(parse_tree) eval_numbers = Collect_numbers(eval_tree) return set(eval_numbers.keys()) else: return Eval_with_Variables(string, variables) except: return set()
def parse_eval(string): """ Given an expression, return it's parse tree and it's evaluation tree """ expr = parse_webwork(string) if expr: try: etree = eval_parsed(expr) return expr, etree except: return (None, None) else: return (None, None)
def parse_pg_file(pg_file): answer_re = re.compile(".*\[_+\]{(.*)}") compute_re = re.compile("Compute\(\"(.*)\"\)") with open(os.path.expanduser(pg_file), 'r') as f: for line in f: m = answer_re.match(line) if m: print line print m.group(1) mc = compute_re.match(m.group(1)) if mc: print mc.group(1) parsed = parse_webwork(mc.group(1)) print parsed
def post(self): ''' Parses an expression and returns the parsed data structure. Sample arguments: expression="1+1" Response: [['+', [0,2]], 1, 1] ''' expression = self.get_argument('expression') etree = parse_webwork(expression) if etree: self.write(json.dumps(etree)) else: logger.error("Failed to parse expression '%s'", expression) self.set_status(400) self.write(json.dumps({'error': 'Error parsing expression %s' % expression}))
def post(self): ''' Parses an expression and returns the parsed data structure. Sample arguments: expression="1+1" Response: [['+', [0,2]], 1, 1] ''' expression = self.get_argument('expression') etree = parse_webwork(expression) if etree: self.write(json.dumps(etree)) else: logger.error("Failed to parse expression '%s'", expression) self.set_status(400) self.write( json.dumps( {'error': 'Error parsing expression %s' % expression}))
# e3=webwork_parser.parse_webwork('C(6*7*5,5^3)+9/(31+18)') # print e3 # We want to cluster all incorrect attempts # For each incorrect attempt: # Parse answer expression into tree # (Discard unparseable expressions or something) # Stick parse tree into a list trees = [] part = 0 for i, a in answers.iteritems(): if df.scores[i][part] == '0': # Only consider incorrect answers try: expr = webwork_parser.parse_webwork(a[part]) n = ExpressionNode(expr) trees.append(n) except webwork_parser.WebworkParseException: pass print len(trees), 'incorrect expressions parsed' """ K Medoids Algorithm 1. Initialize: randomly select k of the n data points as the medoids 2. Associate each data point to the closest medoid. 3. For each medoid m 1. For each non-medoid data point o
def get(self): ''' Parses all expressions for a given question Sample arguments: course='CSE103_Fall14', set_id='Week1', problem_id=1, part_id=1 include_finished=0 Response: ... ''' # Get correct answers logger.debug('Starting get') self.answer_exps = {} course = self.get_argument('course') set_id = self.get_argument('set_id') problem_id = self.get_argument('problem_id') part_id = int(self.get_argument('part_id')) include_finished = (int(self.get_argument('include_finished', 1)) == 1) source_file = conn.query(''' select source_file from {course}_problem where problem_id={problem_id} and set_id="{set_id}"; '''.format(course=course, set_id=set_id, problem_id=problem_id))[0]['source_file'] pg_path = os.path.join(webwork_dir, 'courses', course, 'templates', source_file) with open(pg_path, 'r') as fin: pg_file = fin.read() # name problem_id set_id user_id value user_variables = conn.query('''SELECT * from {course}_user_variables WHERE set_id="{set_id}" AND problem_id = {problem_id}; '''.format(course=course, set_id=set_id, problem_id=problem_id)) self.variables_df = pd.DataFrame(user_variables) if len(self.variables_df) == 0: logger.warn("No user variables saved for assignment %s, please run the save_answers script", set_id) # raise tornado.web.HTTPError(500) answer_re = re.compile('\[__+\]{(?:Compute\(")?(.+?)(?:"\))?}') answer_boxes = answer_re.findall(pg_file) self.part_answer = answer_boxes[part_id-1] self.answer_ptree = parse_webwork(self.part_answer) # Get attempts by part if include_finished: query = '''SELECT * from {course}_answers_by_part WHERE set_id="{set_id}" AND problem_id = {problem_id} AND part_id={part_id}; '''.format(course=course, set_id=set_id, problem_id=problem_id, part_id=part_id) else: # This self join query idea comes from http://stackoverflow.com/a/4519302/90551 # You can do this more clearly with subqueries but it's super slow query = '''SELECT abp.* FROM {course}_answers_by_part as abp LEFT JOIN {course}_answers_by_part AS abp2 ON abp.problem_id = abp2.problem_id AND abp.set_id = abp2.set_id AND abp.part_id = abp2.part_id AND abp.user_id = abp2.user_id AND abp2.score = '1' WHERE abp.set_id='{set_id}' AND abp.problem_id={problem_id} AND abp.part_id={part_id} AND abp2.user_id IS NULL; '''.format(course=course, set_id=set_id, problem_id=problem_id, part_id=part_id) logger.debug('Before sending SQL') answers = conn.query(query) logger.debug('After sending SQL') all_correct_terms = set() correct_terms_map = defaultdict(lambda: defaultdict(list)) incorrect_terms_map = defaultdict(lambda: defaultdict(list)) # Parse and evaluate all answers for a in answers: # {'user_id': u'acpatel', 'timestamp': datetime.datetime(2014, 10, 12, 2, 10, 19), 'id': 284488L, 'score': u'1', 'answer_string': u'C(55,6)', 'part_id': 2L, 'problem_id': 10L, 'set_id': u'Week2', 'answer_id': 199326L} user_id = a['user_id'] ans = self.answer_for_student(user_id) if a['score'] != '1': etree, nums = parsed(a['answer_string']) if etree and nums: correct_terms = self.correct_terms(nums, ans) all_correct_terms |= set(correct_terms) # logger.debug(set(correct_terms)) if a['user_id'] not in correct_terms_map[str(sorted(correct_terms))][a['answer_string']]: correct_terms_map[str(sorted(correct_terms))][a['answer_string']].append(a['user_id']) out = {} out['correct'] = correct_terms_map out['correct_terms'] = sorted(all_correct_terms) out['incorrect'] = incorrect_terms_map out['answer_ptree'] = str(self.answer_ptree) self.write(json.dumps(out, default=serialize_datetime)) logger.debug('Finished')
# variables. else: # if number of values matches # number of variables then # substitute values for # variables and call parser # again on numerical expression. subs_string = substitute(string, variables, values) subs_expr, variables = parse_webwork(subs_string) assert len(variables) == 0 if subs_expr: etree = eval_parsed(subs_expr) return etree, {} else: raise Exception except: log.error('Exception in parse_and_eval, string=%s, parsed=%s' % (string, str(expr))) traceback.print_exc(file=sys.stdout) return None if __name__ == "__main__": string = sys.argv[1] print 'input:::', string tree, variables = parse_webwork(string) print 'output:::', tree, variables eval_tree = eval_parsed(tree) print 'Eval_tree:::', eval_tree
def parse_and_collect_numbers(string): try: parse_tree = parse_webwork(string) eval_tree = eval_parsed(parse_tree) eval_numbers = Collect_numbers(eval_tree) return set(eval_numbers.keys()) except: return set() def parse_and_eval(string, variables=None): expr = parse_webwork(string) if expr: try: etree = eval_parsed(expr, variables) return expr, etree except: return (None, None) else: return (None, None) if __name__ == "__main__": string = sys.argv[1] print 'input:::', string tree = parse_webwork(string) print 'output:::', tree eval_tree = eval_parsed(tree) print 'Eval_tree:::', eval_tree
# not match number of variables, # return the description of the # variables. else: # if number of values matches # number of variables then # substitute values for # variables and call parser # again on numerical expression. subs_string=substitute(string,variables,values) subs_expr,variables=parse_webwork(subs_string) assert len(variables)==0; if subs_expr: etree=eval_parsed(subs_expr) return etree,{} else: raise Exception except: log.error('Exception in parse_and_eval, string=%s, parsed=%s'%(string,str(expr))) traceback.print_exc(file=sys.stdout) return None if __name__=="__main__": string=sys.argv[1] print 'input:::',string tree,variables=parse_webwork(string) print 'output:::',tree, variables eval_tree=eval_parsed(tree) print 'Eval_tree:::',eval_tree
def get(self): ''' Parses all expressions for a given question Sample arguments: course='CSE103_Fall14', set_id='Week1', problem_id=1, part_id=1 include_finished=0 Response: ... ''' # Get correct answers logger.debug('Starting get') self.answer_exps = {} course = self.get_argument('course') set_id = self.get_argument('set_id') problem_id = self.get_argument('problem_id') part_id = int(self.get_argument('part_id')) include_finished = (int(self.get_argument('include_finished', 1)) == 1) source_file = conn.query(''' select source_file from {course}_problem where problem_id={problem_id} and set_id="{set_id}"; '''.format(course=course, set_id=set_id, problem_id=problem_id))[0]['source_file'] pg_path = os.path.join(webwork_dir, 'courses', course, 'templates', source_file) with open(pg_path, 'r') as fin: pg_file = fin.read() # name problem_id set_id user_id value user_variables = conn.query('''SELECT * from {course}_user_variables WHERE set_id="{set_id}" AND problem_id = {problem_id}; '''.format(course=course, set_id=set_id, problem_id=problem_id)) self.variables_df = pd.DataFrame(user_variables) if len(self.variables_df) == 0: logger.warn( "No user variables saved for assignment %s, please run the save_answers script", set_id) # raise tornado.web.HTTPError(500) answer_re = re.compile('\[__+\]{(?:Compute\(")?(.+?)(?:"\))?}') answer_boxes = answer_re.findall(pg_file) self.part_answer = answer_boxes[part_id - 1] self.answer_ptree = parse_webwork(self.part_answer) # Get attempts by part if include_finished: query = '''SELECT * from {course}_answers_by_part WHERE set_id="{set_id}" AND problem_id = {problem_id} AND part_id={part_id}; '''.format(course=course, set_id=set_id, problem_id=problem_id, part_id=part_id) else: # This self join query idea comes from http://stackoverflow.com/a/4519302/90551 # You can do this more clearly with subqueries but it's super slow query = '''SELECT abp.* FROM {course}_answers_by_part as abp LEFT JOIN {course}_answers_by_part AS abp2 ON abp.problem_id = abp2.problem_id AND abp.set_id = abp2.set_id AND abp.part_id = abp2.part_id AND abp.user_id = abp2.user_id AND abp2.score = '1' WHERE abp.set_id='{set_id}' AND abp.problem_id={problem_id} AND abp.part_id={part_id} AND abp2.user_id IS NULL; '''.format(course=course, set_id=set_id, problem_id=problem_id, part_id=part_id) logger.debug('Before sending SQL') answers = conn.query(query) logger.debug('After sending SQL') all_correct_terms = set() correct_terms_map = defaultdict(lambda: defaultdict(list)) incorrect_terms_map = defaultdict(lambda: defaultdict(list)) # Parse and evaluate all answers for a in answers: # {'user_id': u'acpatel', 'timestamp': datetime.datetime(2014, 10, 12, 2, 10, 19), 'id': 284488L, 'score': u'1', 'answer_string': u'C(55,6)', 'part_id': 2L, 'problem_id': 10L, 'set_id': u'Week2', 'answer_id': 199326L} user_id = a['user_id'] ans = self.answer_for_student(user_id) if a['score'] != '1': etree, nums = parsed(a['answer_string']) if etree and nums: correct_terms = self.correct_terms(nums, ans) all_correct_terms |= set(correct_terms) # logger.debug(set(correct_terms)) if a['user_id'] not in correct_terms_map[str( sorted(correct_terms))][a['answer_string']]: correct_terms_map[str( sorted(correct_terms))][a['answer_string']].append( a['user_id']) out = {} out['correct'] = correct_terms_map out['correct_terms'] = sorted(all_correct_terms) out['incorrect'] = incorrect_terms_map out['answer_ptree'] = str(self.answer_ptree) self.write(json.dumps(out, default=serialize_datetime)) logger.debug('Finished')