In [1]:
# Always run this first
# NOTE: Do not define new basic variables in this notebook;
# define them in Variables_Q.ipynb. Use this notebook
# to define new expressions built from those variables.
from __future__ import division # This needs to be here, even though it's in Variables.py
import sys
sys.path.insert(0, '..') # Look for modules in directory above this one
execfile('../Utilities/ExecNotebook.ipy')
#try: execnotebook(VariablesNotebook)
#except: execnotebook('../PNTerms/Variables_Q.ipynb')
This notebook provides a couple examples for how to convert long $\LaTeX$ expression into sympy format, via Mathematica.
The first step is to select the equation you want from the original source (possibly obtained from the "Other Formats" link on the paper's arXiv page), and put it in its own file. Here, we have an example named EMRIGWFlux_7PN.tex taken from Fujita (2012). It is best to copy this exactly, without making any changes
The next step is to run this through perl, and let perl make any necessary replacements. Mathematica won't want any \begin{equation} statements, so we remove them first. Next, we probably want to remove the left-hand side of the equation, which is just the variable name that this expression represents. We correct any mistakes in the original (the use of {\rm ln} instead of \ln, for example), and remove anything else Mathematica won't understand.
In [1]:
%%bash
perl -nlw \
-e 's/\\begin\{eqnarray\*\}//g; s/\\end\{eqnarray\*\}//g; ' `# remove environment for Mathematica` \
-e 's/\{dE\\over dt\}=&&\\left\(\{dE\\over dt\}\\right\)_N//;' `# remove definition statement` \
-e 's/\{\\rm ln\}/\\ln/g;' `# Correct bad notation for logarithm` \
-e 's/\\cr//g; s/\\displaystyle//g;' `# These shouldn't have been in there to begin with` \
-e 's/(\\ln\(.\))(\^\{.\})/($1)$2/g;' `# group logarithm powers correctly` \
-e 's/\\\{/(/g; s/\\\}/)/g; s/\[/(/g; s/\]/)/g;' `# convert braces and brackets to parentheses` \
-e 's/\),/\)/;' `# remove final punctuation` \
-e 'print if /\S/;' `# only print line if nonempty` \
EMRIGWFlux_7PN.tex > EMRIGWFlux_7PN_Simplified.tex
#cat EMRIGWFlux_7PN_Simplified.tex
Next, we just need to run this through Mathematica, which has a good TeX conversion method. Of course, Mathematica's output is weird — all the function names are capitalized; function arguments come in square brackets; etc. So we just replace them in the output. Then, we go through and print the terms at each order, ready to be copied to another notebook. (Or we could just use the sympy object Flux below.)
NOTE: You will need to adjust the MathKernel path below. On Linux, you will need the executable named math instead.
In [4]:
MathKernel='/Applications/Local/Mathematica.app/Contents/MacOS/MathKernel'
FluxCommand = r"""
\[Gamma] = EulerGamma;
\[Zeta] = Zeta;
HornerForm[ToExpression[Import[
"EMRIGWFlux_7PN_Simplified.tex",
"Text"], TeXForm]] >> /tmp/Flux.cpp
Exit[];
"""
! {MathKernel} -run '{FluxCommand}' >& /dev/null
Flux = !cat /tmp/flux.cpp
Flux = ''.join(Flux).replace(' ','').replace('Pi','pi').replace('Log','log').replace('Zeta','zeta').replace('Power','Pow')
Flux = Flux.replace('[','(').replace(']',')').replace('^','**')
Flux = sympify(Flux)
logv = symbols('logv')
FluxDictionary = Poly(Flux.subs('log(v)', logv), Flux.atoms(Symbol).pop()).as_dict()
for key in sorted(FluxDictionary) :
if(key[0]>7) :
print("FluxTerms['IncompleteNonspinning'][{0}] = {1}".format(key[0], FluxDictionary[key].subs(logv, log(v))))
Just for fun, let's look at the actual expression:
In [5]:
Flux
Out[5]:
In [12]:
from sympy import *
ellHat= Symbol('ellHat')
nHat= Symbol('nHat')
lambdaHat= Symbol('lambdaHat')
var('v, m, nu, G, c, x');
In [4]:
def MathematicaToSympy(L):
import re
L = ''.join(L).replace(' ','')
L = L.replace(r'\[ScriptL]','ell')
MathematicaCapitalGreek = re.compile(r'\\ \[ Capital(.*?) \]', re.VERBOSE)
L = MathematicaCapitalGreek.sub(r'\1',L)
MathematicaGreek = re.compile(r'\\ \[ (.*?) \]', re.VERBOSE)
L = MathematicaGreek.sub(lambda m: m.group(1).lower(),L)
OverHat = re.compile(r'OverHat\[ (.*?) \]', re.VERBOSE)
L = OverHat.sub(r'\1Hat',L)
Subscript = re.compile(r'Subscript\[ (.*?), (.*?) \]', re.VERBOSE)
L = Subscript.sub(r'\1_\2',L)
Sqrt = re.compile(r'Sqrt\[ (.*?) \]', re.VERBOSE)
L = Sqrt.sub(r'sqrt(\1)',L)
L = L.replace('Pi','pi').replace('Log','log').replace('Zeta','zeta').replace('Power','Pow')
L = L.replace('^','**')
return L
In [5]:
MathKernel='/Applications/Local/Mathematica.app/Contents/MacOS/MathKernel'
MCommand = r"""
\[Gamma] = EulerGamma;
\[Zeta] = Zeta;
HornerForm[ToExpression[Import[
"AngularMomentum.tex",
"Text"], TeXForm],x] >> /tmp/AngularMomentum.cpp
Exit[];
"""
! {MathKernel} -run '{MCommand}' >& /dev/null
L = !cat /tmp/AngularMomentum.cpp
L = MathematicaToSympy(L)
L = sympify(L).subs('sqrt(x)',v).subs('x',v**2).subs('G',1).subs('c',1).simplify()
In [14]:
L_ellHat = horner( (v*L).simplify().expand().coeff(ellHat) )/v
L_nHat = horner( (v*L).simplify().expand().coeff(nHat) )/v
L_lambdaHat = horner( (v*L).simplify().expand().coeff(lambdaHat) )/v
In [19]:
L_set = [L_ellHat, L_nHat, L_lambdaHat]
for n in range(3,9,2):
print("""AngularMomentum_Spin.AddDerivedVariable('L_SO_{0}',
({1})*ellHat
+ ({2})*nHat
+ ({3})*lambdaHat,
datatype=ellHat.datatype)""".format(n,
(v*L_ellHat/(m**2*nu)).expand().coeff(v**n).simplify(),
(v*L_nHat/(m**2*nu)).expand().coeff(v**n).simplify(),
(v*L_lambdaHat/(m**2*nu)).expand().coeff(v**n).simplify()))
In [148]:
for var in [L_ellHat, L_nHat, L_lambdaHat]:
print ccode(N(var,16))
In [44]:
%%bash --out tmp
perl -nlw \
-e 's/\\begin\{eqnarray\}//g; s/\\end\{eqnarray\}//g; ' `# remove environment for Mathematica` \
-e 's/\\label\{eB6PN\}//;' `# remove equation label` \
-e 's/\\nonumber//g; s/\\biggl//g; s/\\Biggl//g; s/\\left//g; s/\\right//g;' `# remove irrelevant formatting` \
-e 's/\&//g; s/\\\\//g;' `# remove alignments and newlines` \
-e 's/\\\{/(/g; s/\\\}/)/g; s/\[/(/g; s/\]/)/g;' `# convert braces and brackets to parentheses` \
-e 's/\),/\)/;' `# remove final punctuation` \
-e 'print if /\S/;' `# only print line if nonempty` \
BindingEnergy.tex > BindingEnergy_Simplified.tex
cat BindingEnergy_Simplified.tex
In [45]:
tmp
Out[45]:
In [62]:
from __future__ import print_function
Terms = ['E_2', 'E_4', 'E_6', 'E_8', 'E_lnv_8', 'E_10', 'E_lnv_10', 'E_11', 'E_12', 'E_lnv_12']
Expressions = [s[(s.index('=')+1):].replace('\n','') for s in tmp.split('\ne')]
for t,e in zip(Terms,Expressions):
print(e, file=open('/tmp/'+t+'.tex','w+'))
In [107]:
import re
MathKernel='/Applications/Local/Mathematica.app/Contents/MacOS/MathKernel'
BindingEnergyCommand = r"""
\[Gamma] = EulerGamma;
HornerForm[ToExpression[Import[
"/tmp/{0}.tex",
"Text"], TeXForm]] >> /tmp/{0}.cpp
Exit[];
"""
for t in Terms:
! {MathKernel} -run '{BindingEnergyCommand.format(t)}' >& /dev/null
BindingEnergy = !cat /tmp/{t}.cpp
BindingEnergy = ''.join(BindingEnergy).replace(' ','').replace('Pi','pi').replace('Log','log').replace('Nu','nu')
BindingEnergy = BindingEnergy.replace('[','(').replace(']',')').replace('Power','Pow').replace('^','**').replace('\\','')
BindingEnergy = re.sub(r'Subscript\((.*?),([0-9])[.5]*\)\*\*(c|ln)', r'\1_\2__\g<3>1', BindingEnergy)
BindingEnergy = sympify(BindingEnergy)
logv = symbols('logv')
BindingEnergy = BindingEnergy.subs('log(v)', logv)
print("BindingEnergy_NoSpin_B.AddDerivedConstant('{0}', {1})".format(t, BindingEnergy))
print()
In [6]:
import re
from sympy import sympify, symbols
for i in [1]:
BindingEnergy = !cat /tmp/E_lnv_12.cpp
print(BindingEnergy)
BindingEnergy = ''.join(BindingEnergy).replace(' ','').replace('Pi','pi').replace('Log','log').replace('Nu','nu')
print(BindingEnergy)
BindingEnergy = BindingEnergy.replace('[','(').replace(']',')').replace('Power','Pow').replace('^','**').replace('\\','')
print(BindingEnergy)
BindingEnergy = re.sub(r'Subscript\((.*?),([0-9])[.5]*\)\*\*(c|ln)', r'\1_\2__\g<3>1', BindingEnergy)
print(BindingEnergy)
BindingEnergy = sympify(BindingEnergy)
print(BindingEnergy)
logv = symbols('logv')
BindingEnergy = BindingEnergy.subs('log(v)', logv)
print("BindingEnergy_NoSpin_B.AddDerivedConstant('E_lnv_12', {0})".format(BindingEnergy))
print()
In [ ]:
nu*(nu*(11*a_6__ln1/2 + nu*(-11*a_6__ln1/2 + 616/27) + 56386/105) - 1967284/8505)
In [ ]:
11*self.a_7__ln1/3 + nu*(nu*(11*self.a_6__ln1/2 + nu*(-11*self.a_6__ln1/2 + 616/27 + 56386/105) - 1967284/8505))