Commit 45f2a690 by Peter Baratta

Commented on high level functions

parent 26f7b984
...@@ -154,8 +154,9 @@ def my_sympify(expr, normphase=False, matrix=False, abcsym=False, do_qubit=False ...@@ -154,8 +154,9 @@ def my_sympify(expr, normphase=False, matrix=False, abcsym=False, do_qubit=False
class formula(object): class formula(object):
''' '''
Representation of a mathematical formula object. Accepts mathml math expression for constructing, Representation of a mathematical formula object. Accepts mathml math expression
and can produce sympy translation. The formula may or may not include an assignment (=). for constructing, and can produce sympy translation. The formula may or may not
include an assignment (=).
''' '''
def __init__(self, expr, asciimath='', options=None): def __init__(self, expr, asciimath='', options=None):
self.expr = expr.strip() self.expr = expr.strip()
...@@ -194,8 +195,12 @@ class formula(object): ...@@ -194,8 +195,12 @@ class formula(object):
def preprocess_pmathml(self, xml): def preprocess_pmathml(self, xml):
''' '''
Pre-process presentation MathML from ASCIIMathML to make it more acceptable for SnuggleTeX, and also Pre-process presentation MathML from ASCIIMathML to make it more
to accomodate some sympy conventions (eg hat(i) for \hat{i}). acceptable for SnuggleTeX, and also to accomodate some sympy
conventions (eg hat(i) for \hat{i}).
This method would be a good spot to look for an integral and convert
it, if possible...
''' '''
if type(xml) == str or type(xml) == unicode: if type(xml) == str or type(xml) == unicode:
...@@ -266,6 +271,9 @@ class formula(object): ...@@ -266,6 +271,9 @@ class formula(object):
''' '''
Return sympy expression for the math formula. Return sympy expression for the math formula.
The math formula is converted to Content MathML then that is parsed. The math formula is converted to Content MathML then that is parsed.
This is a recursive function, called on every CMML node. Support for
more functions can be added by modifying opdict, abould halfway down
''' '''
if self.the_sympy: return self.the_sympy if self.the_sympy: return self.the_sympy
......
...@@ -157,13 +157,33 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None ...@@ -157,13 +157,33 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
''' '''
Check a symbolic mathematical expression using sympy. Check a symbolic mathematical expression using sympy.
The input may be presentation MathML. Uses formula. The input may be presentation MathML. Uses formula.
This is the default Symbolic Response checking function
Desc of args:
expect is a sympy string representing the correct answer. It is interpreted
using my_sympify (from formula.py), which reads strings as sympy input
(e.g. 'integrate(x^2, (x,1,2))' would be valid, and evaluate to give 1.5)
ans is student-typed answer. It is expected to be ascii math, but the code
below would support a sympy string.
dynamath is the PMathML string converted by MathJax. It is used if
evaluation with ans is not sufficient.
options is a string with these possible substrings, set as an xml property
of the problem:
-matrix - make a sympy matrix, rather than a list of lists, if possible
-qubit - passed to my_sympify
-imaginary - used in formla, presumably to signal to use i as sqrt(-1)?
-numerical - force numerical comparison.
''' '''
msg = '' msg = ''
# msg += '<p/>abname=%s' % abname # msg += '<p/>abname=%s' % abname
# msg += '<p/>adict=%s' % (repr(adict).replace('<','&lt;')) # msg += '<p/>adict=%s' % (repr(adict).replace('<','&lt;'))
threshold = 1.0e-3 threshold = 1.0e-3 # for numerical comparison (also with matrices)
DEBUG = debug DEBUG = debug
if xml is not None: if xml is not None:
...@@ -184,13 +204,17 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None ...@@ -184,13 +204,17 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
msg += '<p>Error %s in parsing OUR expected answer "%s"</p>' % (err, expect) msg += '<p>Error %s in parsing OUR expected answer "%s"</p>' % (err, expect)
return {'ok': False, 'msg': make_error_message(msg)} return {'ok': False, 'msg': make_error_message(msg)}
###### Sympy input #######
# if expected answer is a number, try parsing provided answer as a number also # if expected answer is a number, try parsing provided answer as a number also
try: try:
fans = my_sympify(str(ans), matrix=do_matrix, do_qubit=do_qubit) fans = my_sympify(str(ans), matrix=do_matrix, do_qubit=do_qubit)
except Exception, err: except Exception, err:
fans = None fans = None
if hasattr(fexpect, 'is_number') and fexpect.is_number and fans and hasattr(fans, 'is_number') and fans.is_number: # do a numerical comparison if both expected and answer are numbers
if (hasattr(fexpect, 'is_number') and fexpect.is_number and fans
and hasattr(fans, 'is_number') and fans.is_number):
if abs(abs(fans - fexpect) / fexpect) < threshold: if abs(abs(fans - fexpect) / fexpect) < threshold:
return {'ok': True, 'msg': msg} return {'ok': True, 'msg': msg}
else: else:
...@@ -208,6 +232,8 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None ...@@ -208,6 +232,8 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
msg += '<p>You entered: %s</p>' % to_latex(fans) msg += '<p>You entered: %s</p>' % to_latex(fans)
return {'ok': True, 'msg': msg} return {'ok': True, 'msg': msg}
###### PMathML input ######
# convert mathml answer to formula # convert mathml answer to formula
try: try:
if dynamath: if dynamath:
...@@ -216,6 +242,7 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None ...@@ -216,6 +242,7 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
mmlans = None mmlans = None
if not mmlans: if not mmlans:
return {'ok': False, 'msg': '[symmath_check] failed to get MathML for input; dynamath=%s' % dynamath} return {'ok': False, 'msg': '[symmath_check] failed to get MathML for input; dynamath=%s' % dynamath}
f = formula(mmlans, options=options) f = formula(mmlans, options=options)
# get sympy representation of the formula # get sympy representation of the formula
...@@ -238,7 +265,7 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None ...@@ -238,7 +265,7 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
msg += '<hr>' msg += '<hr>'
return {'ok': False, 'msg': make_error_message(msg)} return {'ok': False, 'msg': make_error_message(msg)}
# compare with expected # do numerical comparison with expected
if hasattr(fexpect, 'is_number') and fexpect.is_number: if hasattr(fexpect, 'is_number') and fexpect.is_number:
if hasattr(fsym, 'is_number') and fsym.is_number: if hasattr(fsym, 'is_number') and fsym.is_number:
if abs(abs(fsym - fexpect) / fexpect) < threshold: if abs(abs(fsym - fexpect) / fexpect) < threshold:
...@@ -250,6 +277,10 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None ...@@ -250,6 +277,10 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
# msg += "<p>cmathml = <pre>%s</pre></p>" % str(f.cmathml).replace('<','&lt;') # msg += "<p>cmathml = <pre>%s</pre></p>" % str(f.cmathml).replace('<','&lt;')
return {'ok': False, 'msg': make_error_message(msg)} return {'ok': False, 'msg': make_error_message(msg)}
# Here is a good spot for adding calls to X.simplify() or X.expand(),
# allowing equivalence over binomial expansion or trig identities
# exactly the same?
if fexpect == fsym: if fexpect == fsym:
return {'ok': True, 'msg': msg} return {'ok': True, 'msg': msg}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment