Prepare mathematica output to be parsed in Python
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.
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 ) )