18
$\begingroup$

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?

$\endgroup$
  • 1
    $\begingroup$ FortranForm might get you close to what you want. FortranForm[a x^2 + b x + c] gives c + b*x + a*x**2 $\endgroup$ – rm -rf Jun 13 '15 at 4:15
22
$\begingroup$

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.

$\endgroup$
8
$\begingroup$

Here is a Module I prepared to convert most expressions (including lists) to Numpy. It may not be the most elegant solution, but it works pretty well. Below I also include some examples.

 ToPython[x_, numpyprefix_: "numpy"] := 
 Module[{expression = x, greekrule, PythonForm, 
   numpypre = numpyprefix, lp, rp, a, b},
  (*FUNCTION TO CONVERT MATHEMATICA EXPRESSION TO NUMPY;
  ----------------------------------------------------;
  INPUT ARGUMENTS;
  x: your mathematica expression, it can be numbers, literals, 
  complexes or lists;
  numpy\[LetterSpace]prefix: 
  string defining your Numpy import prefix, e.g.:
  if your used "import numpy as np", 
  your prefix should be the string "np"
  if your used "from numpy import *", 
  your prefix should be the empty string ""
  ;
  OUTPUT;
  the Numpy python-ready expression (to be copied as a string);
  !The formatted expression will be copied ot your clipboard, 
  ready to paste on Python!;
  ------------------------------------------------------;
  Not tested for every possible combination; use at your risk, 
  by Gustavo Wiederhecker*)

  If[numpyprefix == "", sep = "", 
   sep = "."];(*if no prefix is included, 
  the "." separator is not used*)
  lp = "( ";
  rp = " )";
  PythonForm[Rational[a_, b_]] := 
   PythonForm[a] <> "/" <> PythonForm[b];
  PythonForm[Complex[a_, b_]] := 
   "complex" <> lp <> PythonForm[a] <> "," <> PythonForm[b] <> rp;
  PythonForm[Times[a_, b_]] := PythonForm[a] <> " * " <> PythonForm[b];
  PythonForm[Plus[a_, b_]] := 
   lp <> PythonForm[a] <> " + " <> PythonForm[b] <> rp;
  PythonForm[h_[args__]] := 
   numpypre <> sep <> ToLowerCase[PythonForm[h]] <> lp <> 
    PythonForm[args] <> rp;
  PythonForm[Power[a_, b_]] := 
   lp <> PythonForm[a] <> rp <> "**" <> lp <> PythonForm[b] <> rp;
  PythonForm[a_ListQ] := 
   numpypre <> sep <> "array" <> 
    StringReplace[ToString[a], {"{" -> "[", "}" -> "]"}];
  PythonForm[Arg] = numpypre <> sep <> "angle";
  (*Some functions that are note defined in numpy*)

  PythonForm[Csc] := "1/" <> numpypre <> sep <> "sin";
  PythonForm[Sec] := "1/" <> numpypre <> sep <> "cos";
  PythonForm[Cot] := "1/" <> numpypre <> sep <> "tan";
  PythonForm[Csch] := "1/" <> numpypre <> sep <> "sinh";
  PythonForm[Sech] := "1/" <> numpypre <> sep <> "cosh";
  PythonForm[Coth] := "1/" <> numpypre <> sep <> "tanh";
  (*Handling arrays*)

  PythonForm[List[args__]] := 
   numpypre <> sep <> "array" <> lp <> "[" <> 
    Table[PythonForm[{args}[[ii]]] <> ",", {ii, 1, Length@{args}}] <> 
    "]" <> rp;
  (*Pi and E*)
  PythonForm[\[Pi]] = numpypre <> sep <> "pi";
  PythonForm[E] = numpypre <> sep <> "e";
  (*real numbers, engineering notation*)

  PythonForm[r_Real] := 
   Block[{a = MantissaExponent[r]}, 
    If[r >= 0, ToString[N[a[[1]], 6]] <> "e" <> ToString[a[[2]]], 
     "(" <> ToString[N[a[[1]], 6]] <> "e" <> ToString[a[[2]]] <> ")"]];
  (*Greek characters*)

  greekrule = {"\[Alpha]" -> "alpha", "\[Beta]" -> "beta", 
    "\[Gamma]" -> "gamma", "\[Delta]" -> "delta", 
    "\[CurlyEpsilon]" -> "curlyepsilon", "\[Zeta]" -> "zeta", 
    "\[Eta]" -> "eta", "\[Theta]" -> "theta", "\[Iota]" -> "iota", 
    "\[Kappa]" -> "kappa", "\[Lambda]" -> "lambda", "\[Mu]" -> "mu", 
    "\[Nu]" -> "nu", "\[Xi]" -> "xi", "\[Omicron]" -> "omicron", 
    "\[Pi]" -> "pi", "\[Rho]" -> "rho", 
    "\[FinalSigma]" -> "finalsigma", "\[Sigma]" -> "sigma", 
    "\[Tau]" -> "tau", "\[Upsilon]" -> "upsilon", 
    "\[CurlyPhi]" -> "curlyphi", "\[Chi]" -> "chi", "\[Psi]" -> "psi",
     "\[Omega]" -> "omega", "\[CapitalAlpha]" -> "Alpha", 
    "\[CapitalBeta]" -> "Beta", "\[CapitalGamma]" -> "Gamma", 
    "\[CapitalDelta]" -> "Delta", 
    "\[CapitalEpsilon]" -> "CurlyEpsilon", "\[CapitalZeta]" -> "Zeta",
     "\[CapitalEta]" -> "Eta", "\[CapitalTheta]" -> "Theta", 
    "\[CapitalIota]" -> "Iota", "\[CapitalKappa]" -> "Kappa", 
    "\[CapitalLambda]" -> "Lambda", "\[CapitalMu]" -> "Mu", 
    "\[CapitalNu]" -> "Nu", "\[CapitalXi]" -> "Xi", 
    "\[CapitalOmicron]" -> "Omicron", "\[CapitalPi]" -> "Pi", 
    "\[CapitalRho]" -> "Rho", "\[CapitalSigma]" -> "Sigma", 
    "\[CapitalTau]" -> "Tau", "\[CapitalUpsilon]" -> "Upsilon", 
    "\[CapitalPhi]" -> "CurlyPhi", "\[CapitalChi]" -> "Chi", 
    "\[CapitalPsi]" -> "Psi", "\[CapitalOmega]" -> "Omega"};
  (*Everything else*)

  PythonForm[allOther_] := 
   StringReplace[ToString[allOther, FortranForm], greekrule];
  (*Copy results to clipboard*)

  CopyToClipboard[PythonForm[expression]];
  PythonForm[expression]]

Here are some examples that I've tested:

(*Expression examples*)
ToPython[a + b]
ToPython[a*b]
ToPython[a/b]
ToPython[(a + b)/(d + e + g)]
ToPython[(a + b)^(d + e + g)]
ToPython[Exp[a + b]]
ToPython[Sin[(a + b)]/Cos[d + e]]
ToPython[Sin[(a + b)]/Tanh[d + e]]
ToPython[\[Pi] Cosh[a]]
ToPython[Log10[x]]
(*Expression with greek letters*)
ToPython[Sin[\[Alpha] + \[Beta]]]
(*Numeric examples*)
ToPython[2]
ToPython[1/3]
ToPython[1.0/3]
ToPython[2.31]
ToPython[2.31 + 5.3 I]
(*Array handling*)
ToPython[{1, 2, 3}]
ToPython[{{1, 2, 3}}]
ToPython[Cos[{1, 2, 3}]]
(*Example with numpy as np*)
ToPython[\[Pi] Cosh[a]/Sin[b], "np"]
ToPython[Exp[a + b], "np"]
ToPython[Cos[{1, 2, 3}], "np"]
(*Example with numpy as "from numpy import *"*)
ToPython[\[Pi] Cosh[
    a]/Sin[b], ""]
ToPython[Exp[a + b], ""]
ToPython[Cos[{1, 2, 3}], ""]

Here is the output to the code above:

( a + b )
a * b
a * ( b )**( -1 )
( a + b ) * ( ( d + ( e + g ) ) )**( -1 )
( ( a + b ) )**( ( d + ( e + g ) ) )
( numpy.e )**( ( a + b ) )
numpy.1/numpy.cos( ( d + e ) ) * numpy.sin( ( a + b ) )
numpy.1/numpy.tanh( ( d + e ) ) * numpy.sin( ( a + b ) )
numpy.pi * numpy.cosh( a )
( numpy.log( 10 ) )**( -1 ) * numpy.log( x )
numpy.sin( ( alpha + beta ) )
2
1/3
0.333333e0
0.231e1
complex( 0.231e1,0.53e1 )
numpy.array( [1,2,3,] )
numpy.array( [numpy.array( [1,2,3,] ),] )
numpy.array( [numpy.cos( 1 ),numpy.cos( 2 ),numpy.cos( 3 ),] )
np.pi * np.cosh( a ) * np.1/np.sin( b )
( np.e )**( ( a + b ) )
np.array( [np.cos( 1 ),np.cos( 2 ),np.cos( 3 ),] )
pi * cosh( a ) * 1/sin( b )
( e )**( ( a + b ) )
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.