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
Post a Comment