16
$\begingroup$

I obtain a raw input form of:

(1.*(43.013537902165325 + 43.013537902165346*E^(0.003288590604026849*t))^2)/
   (3700.328885722024 + 5.4569682106375694*^-12*E^(0.003288590604026849*t) + 
    3700.328885722026*E^(0.006577181208053698*t))

This is just one of the large lists of expression.

How can I convert mathematica math expression to python math expression?

$\endgroup$
1
  • $\begingroup$ The other big issue is clearly the math.sin() and all that in place of Sin[] $\endgroup$
    – Rho Phi
    Commented Aug 10, 2016 at 15:53

3 Answers 3

23
$\begingroup$

FortranForm gets you close. ( Fortran and Python use the same syntax for most things )

    pw = PageWidth /. Options[$Output];
    SetOptions[$Output, PageWidth ->Infinity];
    FortranForm[ expression  /. E^x_ :> exp[x] ]
    SetOptions[$Output, PageWidth -> pw];

(1.*(43.013537902165325 + 43.013537902165346*exp(0.003288590604026849*t))**2)/(3700.328885722024 + 5.4569682106375694e-12*exp(0.003288590604026849*t) + 3700.328885722026*exp(0.006577181208053698*t))

note we need to set pagewidth because you sure don't want Fortran continuation marks. The E^x_ replacement puts the exponential into python form, you will need to do similar with other functions.

One thing to be careful about, if you have integer rationals in your mathematica expression they give you integer arithmetic in python, which is not likely what you want. In that case you can apply N to the whole works, although that can have other issues.

Edit, refinement:

 FortranForm[ expression  //. {1. y_ -> y, E^x_ -> exp[x]  }]

gets rid of the superfluous 1. multipliers.

$\endgroup$
3
  • $\begingroup$ Many thanks. I have a further question. How to convert 1.? $\endgroup$
    – Ka Wa Yip
    Commented Jun 8, 2015 at 15:37
  • 1
    $\begingroup$ I'm not sure what you mean by convert 1.. Do you want the floating 1. to appear as an integer? $\endgroup$
    – george2079
    Commented Jun 8, 2015 at 16:52
  • 2
    $\begingroup$ (1) I think you should use RuleDelayed in your refinement. (2) You may find x_Real y_ /; x == 1 :> y more robust. $\endgroup$
    – Mr.Wizard
    Commented Jun 8, 2015 at 23:24
8
$\begingroup$

Maybe you could convert expressions from mathematica to latex then use Latex Lambda to get back the python function. Latex Lambda converts latex math notation to lambda functions in Python. So you would input mathematica converted latex expressions and get back the python function.

Example:

Input

     \prod_{i=1}^{n}\frac{\arcsin{\alpha}*\sin{\beta}}{\sqrt{\alpha*\beta}}

Output

{
    "func":"lambda n,ß,α: np.prod([(np.arcsin(α)*np.sin(ß))/(np.sqrt(α*ß)) for i in range(int(1),int(n)+1)])",
    "params":["n", "ß", "α"]
}

Evaluation

>>> import numpy as np
>>> func = lambda n,ß,α: np.prod([(np.arcsin(α)*np.sin(ß))/(np.sqrt(α*ß)) for i in range(int(1),int(n)+1))])
>>> func(4,1,1)
3.05236236307
$\endgroup$
5
$\begingroup$

Using Robert Jacobson's FoxySheep parser, the command-line utility foxy-sheep has a crude translation to Python. See https://pypi.org/project/FoxySheep/ . (And https://github.com/rljacobson/FoxySheep .)

Conversion to Python is done via transforming “InputForm” input to an “FullForm” parse tree, and then that is converted to a Python AST. Finally a Python module is used to dump the Python AST to text.

Why do we go through this more complicated process for translating one string to another?

By keeping the structure as an AST, we can contemplate more powerful transformations and make use of routines that exist for working with Python AST’s.

For example, translating {1,2,3} + 2 into Python, while not handled now, can be done by looking at the types of the operands of plus, and noticing one is a scalar while the other is a list.

Edit:

After writing this, I tried the program on the example above and found I had to extend the code to handle symbols like E and numeric literals with a number-literal exponent.

However after doing that I was able to get this to parse:

$ foxy-sheep -o python -e '(1.*(43.013537902165325 +
43.013537902165346*E^(0.003288590604026849*t))^2)/ 
(3700.328885722024 + 5.4569682106375694*^-12*E^(0.003288590604026849*t) + 
3700.328885722026*E^(0.006577181208053698*t))'
(
 decimal.Decimal(1.0) * (
 decimal.Decimal(43.013537902165325) + 
 decimal.Decimal(43.013537902165346) * math.e ** (
 decimal.Decimal(0.003288590604026849) * t)) ** 2 / (
 decimal.Decimal(3700.328885722024) + 
 decimal.Decimal(5.456968210637569) * 10 ** 12 * math.e ** (
 decimal.Decimal(0.003288590604026849) * t) + 
 decimal.Decimal(3700.328885722026) * math.e **decimal.Decimal(0.006577181208053698) * t))

Above, we output using math.e because the output is for Python. Had the output been either the numpy or sympy variants, constants from those modules would have been used instead.

To see a parse of this expression run:

foxy-sheep -t full -e '(1.*(43.013537902165325 + 43.013537902165346*E^(0.003288590604026849*t))^2)/ (3700.328885722024 + 5.4569682106375694*^-12*E^(0.003288590604026849*t) + 3700.328885722026*E^(0.006577181208053698*t))'

<prog:Prog> [1]
  <expr:Divide> [3]
    0. <expr:Parentheses> [3]
      '('

      1. <expr:Times> [3]
        0. <expr:Number> [1]
          <numberLiteral:NumberBaseTen> [1]
            '1.'

        1. '*'

        2. <expr:Power> [3]
          0. <expr:Parentheses> [3]
            '('

            1. <expr:PlusOp> [3]
              0. <expr:Number> [1]
                <numberLiteral:NumberBaseTen> [1]
                  '43.013537902165325'

              1. '+'

              2. <expr:Times> [3]
...       

Lastly, I should explain that I was tempted to add a translation from Pi to math.pi when adding the translation of E to math.e. (This has since been done).

Right now what's more important is getting the overall framework right than filling out the hundreds of specifics. That said, for those who use and have a specific function that's missing, just open an github issue.

$\endgroup$
1
  • 1
    $\begingroup$ (+1) Note, that this answer suggest the conversion to be done in Python's evironment, not Mathematica's. $\endgroup$ Commented Jul 29, 2020 at 7:43

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