Skip to main content

Prepare mathematica output to be parsed in Python


I have Mathematica output that I would like to parse in python so I can generate equivalent expressions. So suppose I have the following:


testing2 = 
ExpandAll[
D[(x - A)^2 + (y - B)^2 + (
v - C)^2 + (x + y - (S + v) - D)^2 - λ1*x - λ2*
y - λ3*v - λ4*(x + y - (S + v)) , {{x, y, v}}]]


Then I solve the following system:


Solve[Thread[
testing2 == 0 && -λ1*x == 0 && - λ2*y ==
0 && -λ3*v == 0 && - λ4*(x + y - (S + v)) ==
0], {x, y, v, x, y,
v, λ1, λ2, λ3, λ4}]

Which returns a list of possible solutions. One possible solution is the following:


  {x -> 0, y -> 0, 
v -> 1/2 (C - D - S), λ1 -> -2 A - C - D -

S, λ2 -> -2 B - C - D - S, λ3 -> 0, λ4 ->
0}

Since there are a lot of possible solutions, it is quite difficult to code everything by hand. I was trying to have the output put the multiplication symbol in the appropriate place. If I can do this, then it will be easier to parse the output in python. So suppose Mathematica is outputing 2A, I would like it to output 2*A. Is this possible?



Answer



Since python has pretty close syntax as Fortran, converting the expression to FortranForm is what I usually do in this case.


testing2 = 
ExpandAll[
D[(x - A)^2 + (y - B)^2 + (v - C)^2 + (x + y - (S + v) -
D)^2 - λ1*x - λ2*y - λ3*

v - λ4*(x + y - (S + v)), {{x, y, v}}]]
sols = {x, y, v, x, y,
v, λ1, λ2, λ3, λ4} /.
Solve[Thread[
testing2 == 0 && -λ1*x == 0 && -λ2*y ==
0 && -λ3*v == 0 && -λ4*(x + y - (S + v)) ==
0], {x, y, v, x, y,
v, λ1, λ2, λ3, λ4}]
sols // FortranForm


This is not ideal, but a good starting point for python to work with.


If you have access to Maple. Another solution is using Maple. CodeGeneration is pretty handy in Maple, it can also generate function using numpy and scipy


with(MmaTranslator);
print(??); # input placeholder
e := FromMma("{{0, 0, 0, 0, 0, 0, -2 (A + D + S), -2 (B + D + S), -2 (C - D - S),
0}, {0, 0, 1/2 (C - D - S), 0, 0,
1/2 (C - D - S), -2 A - C - D - S, -2 B - C - D - S, 0, 0}, {0,
0, -S, 0, 0, -S, -2 (A + C + S), -2 (B + C + S), 0,
2 (C - D + S)}, {0, S, 0, 0, S, 0, -2 (A - B + S),
0, -2 (B + C - S), -2 (B + D - S)}, {0, 1/2 (B + C + S),

1/2 (B + C - S), 0, 1/2 (B + C + S),
1/2 (B + C - S), -2 A + B - C - S, 0, 0, -B + C - 2 D + S}, {0,
1/2 (B + D + S), 0, 0, 1/2 (B + D + S), 0, -2 A + B - D - S,
0, -B - 2 C + D + S, 0}, {0, 1/3 (2 B + C + D + S),
1/3 (B + 2 C - D - S), 0, 1/3 (2 B + C + D + S),
1/3 (B + 2 C - D - S), -(2/3) (3 A - B + C + D + S), 0, 0, 0}, {S,
0, 0, S, 0, 0, 0,
2 (A - B - S), -2 (A + C - S), -2 (A + D - S)}, {1/2 (A - B + S),
1/2 (-A + B + S), 0, 1/2 (A - B + S), 1/2 (-A + B + S), 0, 0,
0, -A - B - 2 C + S, -A - B - 2 D + S}, {1/2 (A + C + S), 0,

1/2 (A + C - S), 1/2 (A + C + S), 0, 1/2 (A + C - S), 0,
A - 2 B - C - S, 0, -A + C - 2 D + S}, {1/3 (2 A - B + C + S),
1/3 (-A + 2 B + C + S), 1/3 (A + B + 2 C - S),
1/3 (2 A - B + C + S), 1/3 (-A + 2 B + C + S),
1/3 (A + B + 2 C - S), 0, 0,
0, -(2/3) (A + B - C + 3 D - S)}, {1/2 (A + D + S), 0, 0,
1/2 (A + D + S), 0, 0, 0, A - 2 B - D - S, -A - 2 C + D + S,
0}, {1/3 (2 A - B + D + S), 1/3 (-A + 2 B + D + S), 0,
1/3 (2 A - B + D + S), 1/3 (-A + 2 B + D + S), 0, 0,
0, -(2/3) (A + B + 3 C - D - S), 0}, {1/3 (2 A + C + D + S), 0,

1/3 (A + 2 C - D - S), 1/3 (2 A + C + D + S), 0,
1/3 (A + 2 C - D - S), 0, 2/3 (A - 3 B - C - D - S), 0,
0}, {1/4 (3 A - B + C + D + S), 1/4 (-A + 3 B + C + D + S),
1/4 (A + B + 3 C - D - S), 1/4 (3 A - B + C + D + S),
1/4 (-A + 3 B + C + D + S), 1/4 (A + B + 3 C - D - S), 0, 0, 0, 0}}");
with(CodeGeneration);
Python(e);

Here is an example from help of Maple


# Translate a procedure involving linear algebra.

detHilbert := proc(M, n :: posint) uses LinearAlgebra;
return Determinant( HilbertMatrix( n ) );
end proc:
Python(detHilbert);
import numpy.linalg
import scipy.linalg

def detHilbert (M, n):
return(numpy.linalg.det(scipy.linalg.hilbert(n)))


Update: sympy method


sympy has now support translate MMA code to sympy. Since this is a pretty new method, I will demonstrate a bit here.


In [1]: from sympy.parsing import mathematica

In [2]: mathematica.parse('Sin[a]^2 27 + 54 x + 36 x^2 + 8 x^3')
Out[2]: 'sin(a)**2 27+54 x+36 x**2+8 x**3'

Noted: sympy does not handle the multiplication correctly now, but I believe this will be solved in the future. The list conversion is not correct as well.


Currently, you can do something like this:


in MMA:



In[178]:= {Sin[a]^2 27 + 54 x + 36 x^2 + 8 x^3, ArcTan[x]} // InputForm

Out[178]//InputForm=
{54*x + 36*x^2 + 8*x^3 + 27*Sin[a]^2, ArcTan[x]}

Copy the output to Python:


In [3]: mathematica.parse('54*x + 36*x^2 + 8*x^3 + 27*Sin[a]^2')
Out[3]: '54*x+36*x**2+8*x**3+27*sin(a)**2'

This result can be further converted to sympy object



In [4]: mathematica.sympify(_)
Out[4]: 8*x**3 + 36*x**2 + 54*x + 27*sin(a)**2

You may also use mathematica function in the module to merge above two functions. But I do not suggest to use the function. Because for parse function, you get the parse result in any case, but mathematica function returns a result only the result is a valid sympy expression. Here is a example of using mathematica function:


In [1]: from sympy.parsing import mathematica as M
In [2]: M.mathematica('4a+8b^2+Cos[9a]')
Out[2]: 4*a + 8*b**2 + cos(9*a)

It is very welcomed if you can improve Mathematica parser in sympy.


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...

Is there a way to do conditional matrix loop using 'continue'

I have the following: n = 3; m = 5; ww = RandomReal[{0, 0.1}, {n, n}]; uu = RandomReal[{0, 1}, {m, n}]; pp = RandomReal[{0, 1}, {n, n}]; ss = RandomInteger[{0, 5}, {m, n}]; Grid[{{"ww", "uu", "pp", "ss"}, {ww // TableForm, uu // TableForm, pp // TableForm, ss // TableForm}}, Spacings -> {5, 2}, Dividers -> All] where I would like to look at every element of matrix ss and produce a matrix tt , with zeroes at the locations in ss which have zeroes, and in all other positions do the following: tt = (-1/Subscript[ww, m]) Log[(1 - uu)/(Subscript[pp, m - 1])], where Subscript[ww, m] is the value at index of ww matrix and where Subscript[pp, m - 1] is the value at index-1 of pp matrix. So for example if the first value ever read from matrix ss happens to be 2, then value taken from matrix ww would be from the row 2, but from pp would be from row 1. Also how to tell difference between a 0 as a valid value from within the matrix elemen...