Sympy and MathML... ideas?

869 views
Skip to first unread message

peibol

unread,
Jul 2, 2013, 11:50:43 AM7/2/13
to sy...@googlegroups.com
Hi all:

Is there no support for importing MathML expressions into Sympy yet?

As the issue is still open, maybe someone knows a workaround for what I'm trying to do. My web application renders some mathematical exercises, so as the students are able to enter a solution and check if it's right or not. I'm using sympy to manipulate expressions and calculate the result (can be algebraic or arithmetic manipulations). My problem now is that if the feature of importing MathML isn't available yet, I don't know how to validate the results. Students enter the results in MathML, but it differs slightly from the one Sympy produces (no mrows for example). Ideally I'd also like to consider semantics, for example, if the soultion is 'x^2+x', x+x^2 is also right.

There is mathdom, but I haven't managed to parse a mathML string yet...

Any ideas?
Thanks
Pablo

Stefan Krastanov

unread,
Jul 2, 2013, 12:17:19 PM7/2/13
to sy...@googlegroups.com
This is probably not very helpful, but why require the students to
write their results in MathML? It is not a very natural way to write
expression. On the other hand, if you use valid python expression it
would probably be much easier.

peibol

unread,
Jul 2, 2013, 12:22:23 PM7/2/13
to sy...@googlegroups.com
Hehe, they don't write the expression in MathML, I'm not that kind of demon. 

They enter expressions in a textarea by means of http://mathdox.org/formulaeditor/, from which I can get the openmath or the (presentation) mathml .The web app is for K12 students, well 12-16 years old, so I think this way to enter mathematical expressions is one of the easiest...

Stefan Krastanov

unread,
Jul 2, 2013, 12:35:37 PM7/2/13
to sy...@googlegroups.com
I am sorry, I do not think there is an out-of-the-box way to do this currently.

What I can suggest is to use the xml2dict python library to parse the
openmath xml and then write your own small routine for traversing the
dictionary and transforming it into a sympy expression.

If you do this I am sure that the sympy team would be very interested
to have your work merged.
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Ondřej Čertík

unread,
Jul 2, 2013, 1:03:09 PM7/2/13
to sympy
On Tue, Jul 2, 2013 at 10:35 AM, Stefan Krastanov
<krastano...@gmail.com> wrote:
> I am sorry, I do not think there is an out-of-the-box way to do this currently.
>
> What I can suggest is to use the xml2dict python library to parse the
> openmath xml and then write your own small routine for traversing the
> dictionary and transforming it into a sympy expression.
>
> If you do this I am sure that the sympy team would be very interested
> to have your work merged.

Absolutely. Pablo, if you would send us a PR that could do that,
that would be awesome.

Ondrej

Aaron Meurer

unread,
Jul 2, 2013, 1:38:08 PM7/2/13
to sy...@googlegroups.com
Just to be clear, is this presentation mathml or content mathml? I
believe the latter would be much easier to parse.

Aaron Meurer

peibol

unread,
Jul 2, 2013, 1:53:28 PM7/2/13
to sy...@googlegroups.com
The mathdox box produces Presentation Mathml.

Sympy produces Content Mathml in the printing module, but there is the c2p function in utils module that converts Content Mathml into Presentation Mathml.

So I'm trying the xml2dict parsing with presentation mathml... I think that once I have the dict, at least for easy expressions like fractions, with addings, algebraic... it's nothing more than a -sophisticated- replacement with some parenthesis abuse.

peibol

unread,
Jul 2, 2013, 2:32:10 PM7/2/13
to sy...@googlegroups.com
I think xml2dict cannot accomplish it, since I get the same key for multiple values...

For example: mathml_prueba='''<mrow> <mfrac> <mrow> <mn>3</mn> </mrow> <mrow> <mn>5</mn> </mrow> </mfrac> </mrow> '''

I get the following dict: 
{'mrow': {'mfrac': {'mrow': [{'mn': '3'}, {'mn': '5'}]}}}
Notice the merged 'mrow' key...

Any suggestion for a xml lib to parse the expression?

Ondřej Čertík

unread,
Jul 2, 2013, 3:01:00 PM7/2/13
to sympy
On Tue, Jul 2, 2013 at 12:32 PM, peibol <pab...@gmail.com> wrote:
> I think xml2dict cannot accomplish it, since I get the same key for multiple
> values...
>
> For example: mathml_prueba='''<mrow> <mfrac> <mrow> <mn>3</mn> </mrow>
> <mrow> <mn>5</mn> </mrow> </mfrac> </mrow> '''
>
> I get the following dict:
> {'mrow': {'mfrac': {'mrow': [{'mn': '3'}, {'mn': '5'}]}}}
> Notice the merged 'mrow' key...
>
> Any suggestion for a xml lib to parse the expression?

lxml seems to be able to parse the expression:

http://nbviewer.ipython.org/5912034

Ondrej

peibol

unread,
Jul 2, 2013, 3:32:22 PM7/2/13
to sy...@googlegroups.com
Thanks, I'll try to make my function the more generic I can.

peibol

unread,
Jul 3, 2013, 7:38:44 AM7/3/13
to sy...@googlegroups.com
It will be something like that. For the moment, I'm just implemented the basics of presentation mathml. I will add features as I need them.

After running it, sympify should be called. What do you think about it?

def parseMML(mmlinput):
from lxml import etree
from StringIO import *
from lxml import objectify
mmlinput= mmlinput.replace(' xmlns="', ' xmlnamespace="')
parser = etree.XMLParser(ns_clean=True,remove_pis=True,remove_comments=True)
tree   = etree.parse(StringIO(mmlinput), parser)
objectify.deannotate(tree,cleanup_namespaces=True,xsi=True,xsi_nil=True)
mmlinput=etree.tostring(tree.getroot())
exppy="" #this is the python expression
symvars=[]  #these are symbolic variables which can eventually take part in the expression
events = ("start", "end")
level = 0
context = etree.iterparse(StringIO(mmlinput),events=events)
for action, elem in context:
if (action=='start') and (elem.tag=='mfrac'):
level += 1
mmlaux=etree.tostring(elem[0])
(a,b)=parseMML(mmlaux)
symvars.append(b)
exppy+=a
exppy+='/'
mmlaux=etree.tostring(elem[1])
(a,b)=parseMML(mmlaux)
symvars.append(b)
exppy+=a
if (action=='end') and (elem.tag=='mfrac'):
level -= 1
if level:
continue
if (action=='start') and (elem.tag=='mrow'):
exppy+='('
if (action=='end') and (elem.tag=='mrow'):
exppy+=')'
if action=='start' and elem.tag=='mn': #this is a number
exppy+=elem.text
if action=='start' and elem.tag=='mi': #this is a variable
exppy+=elem.text
symvars.append(elem.text) #we'll return the variable, so sympy can sympify it afterwards
if action=='start' and elem.tag=='mo': #this is a operation
exppy+=elem.text
return (exppy, symvars)


With the example: mmlinput='''<?xml version="1.0"?> <math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/1998/Math/MathML http://www.w3.org/Math/XMLSchema/mathml2/mathml2.xsd"> <mrow> <mfrac> <mrow> <mn>3</mn> </mrow> <mrow> <mn>57</mn> </mrow> </mfrac> </mrow> </math>'''

We get:
exppy='((3)/(57))'

Ondřej Čertík

unread,
Jul 3, 2013, 11:48:09 AM7/3/13
to sympy
Pablo,
I think that's a great start. I assume you pass the expression to
sympify() and obtain a SymPy expression as a result.

Aaron, I think we should have this in sympy, what do you think? We can
install lxml in .travis.yml and have this tested. If so, I can help
you Pablo with sending a PR and get it setup.

Ondrej

Aaron Meurer

unread,
Jul 3, 2013, 11:49:39 AM7/3/13
to sy...@googlegroups.com
Yes, definitely. Eventually, I would like to have a nice framework to
make parsing things like this easier and have a nicer, more extensible
API, but for now, I think even simple parsers like this are better
than nothing.

Aaron Meurer

Ondřej Čertík

unread,
Jul 3, 2013, 12:18:02 PM7/3/13
to sympy
Excellent.

Pablo, can you please send a PR with this? We'll then improve it there
and I can help with setting up the tests. Please ask if you get stuck.

Ondrej

peibol

unread,
Jul 3, 2013, 12:54:47 PM7/3/13
to sy...@googlegroups.com
Sure. Call me stupid, but what's a PR? I'll need some help with the procedure.

Are you using GIT or what?

Ondřej Čertík

unread,
Jul 3, 2013, 12:57:21 PM7/3/13
to sympy
Hi Pablo,

sorry for my shortcut. :) PR = pull request, here is how it works:

https://help.github.com/articles/using-pull-requests

yes we use git and github. Start by:

git clone https://github.com/sympy/sympy

and try to follow the help article. Please ask if you get stuck.

Using git and github is a great way to do development, you can use it
for any other project as well, not just sympy.

Ondrej

peibol

unread,
Jul 3, 2013, 12:59:36 PM7/3/13
to sy...@googlegroups.com
Ok, I'll try tonight.
Reply all
Reply to author
Forward
0 new messages