Commit c6545eb0 by Peter Baratta

Begin to document symmath as we go

parent b82212ed
window.SymbolicMathjaxPreprocessor = function () {
this.fn = function (eqn) {
// flags and config
var superscriptsOn = true;
if (superscriptsOn) {
// find instances of "__" and make them superscripts ("^") and tag them
// as such. Specifcally replace instances of "__X" or "__{XYZ}" with
// "^{CHAR$1}", marking superscripts as different from powers
// a zero width space--this is an invisible character that no one would
// use, that gets passed through MathJax and to the server
var c = "\u200b";
eqn = eqn.replace(/__(?:([^\{])|\{([^\}]+)\})/g, '^{' + c + '$1$2}');
// NOTE: MathJax supports '\class{name}{mathcode}' but not for asciimath
// input, which is too bad. This would be preferable to the char tag
}
return eqn;
};
};
#################
Symbolic Response
#################
This document plans to document features that the current symbolic response
supports. In general it allows the input and validation of math expressions,
up to commutativity and some identities.
********
Features
********
This is a partial list of features, to be revised as we go along:
* sub and superscripts: an expression following the ``^`` character
indicates exponentiation. To use superscripts in variables, the syntax
is ``b_x__d`` for the variable ``b`` with subscript ``x`` and super
``d``.
An example of a problem::
<symbolicresponse expect="a_b^c + b_x__d" size="30">
<textline math="1" preprocessorClassName="SymbolicMathjaxPreprocessor" preprocessorSrc="/static/js/capa/symbolic_mathjax_preprocessor.js"/>
</symbolicresponse>
It's a bit of a pain to enter that.
...@@ -248,14 +248,21 @@ class formula(object): ...@@ -248,14 +248,21 @@ class formula(object):
fix_hat(xml) fix_hat(xml)
def flatten_pmathml(xml): def flatten_pmathml(xml):
''' ''' Give the text version of certain PMathML elements
Give the text version of PMathML elements
Sometimes MathML will be given with each letter separated (it
doesn't know if its implicit multiplication or what). From an xml
node, find the (text only) variable name it represents. So it takes
<mrow>
<mi>m</mi>
<mi>a</mi>
<mi>x</mi>
</mrow>
and returns 'max', for easier use later on.
''' '''
tag = gettag(xml) tag = gettag(xml)
if tag == 'mn': return xml.text if tag == 'mn': return xml.text
elif tag == 'mi': return xml.text elif tag == 'mi': return xml.text
# elif tag == 'msub': return '_'.join([flatten_pmathml(y) for y in xml])
# elif tag == 'msup': return '^'.join([flatten_pmathml(y) for y in xml])
elif tag == 'mrow': return ''.join([flatten_pmathml(y) for y in xml]) elif tag == 'mrow': return ''.join([flatten_pmathml(y) for y in xml])
raise Exception, '[flatten_pmathml] unknown tag %s' % tag raise Exception, '[flatten_pmathml] unknown tag %s' % tag
...@@ -263,23 +270,63 @@ class formula(object): ...@@ -263,23 +270,63 @@ class formula(object):
# they have the character \u200b in the superscript # they have the character \u200b in the superscript
# replace them with a__b so snuggle doesn't get confused # replace them with a__b so snuggle doesn't get confused
def fix_superscripts(xml): def fix_superscripts(xml):
''' Look for and replace sup elements with 'X__Y' or 'X_Y__Z'
In the javascript, variables with '__X' in them had an invisible
character inserted into the sup (to distinguish from powers)
E.g. normal:
<msubsup>
<mi>a</mi>
<mi>b</mi>
<mi>c</mi>
</msubsup>
to be interpreted '(a_b)^c' (nothing done by this method)
And modified:
<msubsup>
<mi>b</mi>
<mi>x</mi>
<mrow>
<mo>&#x200B;</mo>
<mi>d</mi>
</mrow>
</msubsup>
to be interpreted 'a_b__c'
also:
<msup>
<mi>x</mi>
<mrow>
<mo>&#x200B;</mo>
<mi>B</mi>
</mrow>
</msup>
to be 'x__B'
'''
for k in xml: for k in xml:
tag = gettag(k) tag = gettag(k)
# match node to a superscript # match things like the last example--
# the second item in msub is an mrow with the first
# character equal to \u200b
if (tag == 'msup' and if (tag == 'msup' and
len(k) == 2 and gettag(k[1]) == 'mrow' and len(k) == 2 and gettag(k[1]) == 'mrow' and
gettag(k[1][0]) == 'mo' and k[1][0].text == u'\u200b'): # whew gettag(k[1][0]) == 'mo' and k[1][0].text == u'\u200b'): # whew
# replace the msup with 'X__Y'
k[1].remove(k[1][0]) k[1].remove(k[1][0])
newk = etree.Element('mi') newk = etree.Element('mi')
newk.text = '%s__%s' % (flatten_pmathml(k[0]), flatten_pmathml(k[1])) newk.text = '%s__%s' % (flatten_pmathml(k[0]), flatten_pmathml(k[1]))
xml.replace(k, newk) xml.replace(k, newk)
# match things like the middle example-
# the third item in msubsup is an mrow with the first
# character equal to \u200b
if (tag == 'msubsup' and if (tag == 'msubsup' and
len(k) == 3 and gettag(k[2]) == 'mrow' and len(k) == 3 and gettag(k[2]) == 'mrow' and
gettag(k[2][0]) == 'mo' and k[2][0].text == u'\u200b'): # whew gettag(k[2][0]) == 'mo' and k[2][0].text == u'\u200b'): # whew
# replace the msubsup with 'X_Y__Z'
k[2].remove(k[2][0]) k[2].remove(k[2][0])
newk = etree.Element('mi') newk = etree.Element('mi')
newk.text = '%s_%s__%s' % (flatten_pmathml(k[0]), flatten_pmathml(k[1]), flatten_pmathml(k[2])) newk.text = '%s_%s__%s' % (flatten_pmathml(k[0]), flatten_pmathml(k[1]), flatten_pmathml(k[2]))
...@@ -316,7 +363,7 @@ class formula(object): ...@@ -316,7 +363,7 @@ class formula(object):
try: try:
xml = self.preprocess_pmathml(self.expr) xml = self.preprocess_pmathml(self.expr)
except Exception, err: except Exception, err:
# print 'Err %s while preprocessing; expr=%s' % (err, self.expr) log.warning('Err %s while preprocessing; expr=%s' % (err, self.expr))
return "<html>Error! Cannot process pmathml</html>" return "<html>Error! Cannot process pmathml</html>"
pmathml = etree.tostring(xml, pretty_print=True) pmathml = etree.tostring(xml, pretty_print=True)
self.the_pmathml = pmathml self.the_pmathml = pmathml
......
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