latex math code generation ( and parsing )
Mike Marchywka
marchywka at hotmail.com
Tue Dec 27 00:56:18 CET 2022
ok, so I set out to duplicate mathmatica :)
Actually, make a simple algebra aid and give my
scattered math code a "front end."
The first part seems pretty easy- in fact, the hardest
part was giving up an old rationals class I had made
for fixed size 32 or 64 bit ints. After spending days
debugging bizarre math errors, I just wrote a simple
one, as the compiler complained,
predicated on indefinite length ints ( GMP )
and it seems to have fixed the problems. Everything that
is evaluated is indefinite length rationals.
It does some basic manipulations and I gave
it some trig sub rules ( trig to exponential )
and the basic approach seems to work. However,
the latex code genertion needs to be addressed.
You can see the "mikemath" output below but
what I was going to try to do was generate code
like the following where an expression component
like an integral is expressed in terms of commands
named for its parameters like a,b,x,dx etc.
The skeleton is fixed for all integrals but the
parameter commands vary.
This works great when I can limit the scope with "{}"
but this does not nest. Is there a simple latex
command I should use for parameter generation?
Ideally it is human readable for debugging and
editing and ideally it would be parsable for input
back into mikemath lol. If I do this right I should
be able to make all the specs in simple text files making
it easy to extend.
Thanks.
See this scheme for example where the "int" line if
fixed but each integral instance has differnt command
defs but this does not nest.
\begin{equation}
{
\newcommand{\cmda}{x_0}
\newcommand{\cmdb}{x_f}
\newcommand{\cmdx}{\frac{1}{x^2}}
\newcommand{\cmddx}{dx}
\int_{\cmda}^{\cmdb}{\cmdx}{\cmddx}
}
=
{
\newcommand{\cmda}{y_0}
\newcommand{\cmdb}{y_f}
\newcommand{\cmdx}{\frac{Sin(y)}{y}}
\newcommand{\cmddx}{dy}
\int_{\cmda}^{\cmdb}{\cmdx}{\cmddx}
}
={
\newcommand{\cmda}{y_0}
\newcommand{\cmdb}{y_f}
\newcommand{\cmdx}{
{
\newcommand{\cmdcmda}{x_0}
\newcommand{\cmdcmdb}{x_f}
\newcommand{\cmdcmdx}{\frac{1}{x^2}}
\newcommand{\cmdcmddx}{dx}
\int_{\cmdcmda}^{\cmdcmdb}{\cmdcmdx}{\cmdcmddx}
}
}
\newcommand{\cmddx}{dy}
\int_{\cmda}^{\cmdb}{\cmdx}{\cmddx}
}
\end{equation}
Mike math output with a simple trig expression,
two rules to convert to exp and then some rearrangements,
I have to figure out how to deal with non-commutes/associates
and am seeing what I can do with matricies,
./mikemath.h444 x=\setlength{\paperheight}{11in} \makeatletter \makeatother \documentclass[aps,secnumarabic,balancelastpage,amsmath,amssymb,nofootinbib]{revtex4} \input{myskeletonpackages.tex} \usepackage[maxfloats=256]{morefloats} \usepackage{graphicx}\usepackage{listings} \input{mycommands.tex} \newcommand{\mjmeqn}[1]{\begin{equation} #1 \end{equation} } \begin{document}
\mjmeqn{Sin\left(z\right)+Cos\left(y\right)+((3))*(Sin\left(z\right))*(Cos\left(z\right))*(Sin\left(w\right))}
\end{document}
./mikemath.h444 x=\setlength{\paperheight}{11in} \makeatletter \makeatother \documentclass[aps,secnumarabic,balancelastpage,amsmath,amssymb,nofootinbib]{revtex4} \input{myskeletonpackages.tex} \usepackage[maxfloats=256]{morefloats} \usepackage{graphicx}\usepackage{listings} \input{mycommands.tex} \newcommand{\mjmeqn}[1]{\begin{equation} #1 \end{equation} } \begin{document}
\mjmeqn{(Sin\left(w\right))*(Sin\left(z\right))*(Cos\left(z\right))*((3))+(Sin\left(z\right))+(Cos\left(y\right))}
\end{document}
./mikemath.h572 m_ids.dump()= nm=cosexp e1=Cos\left(x\right) e2=((\frac{1}{2}))*(Exp\left(((1\imath ))*(x)\right)+(Exp\left((x)*((-1\imath ))\right))*((1)))
nm=sinexp e1=Sin\left(x\right) e2=((\frac{-1}{2}\imath ))*(Exp\left(((1\imath ))*(x)\right)+(Exp\left((x)*((-1\imath ))\right))*((-1)))
./mikemath.h444 x=\setlength{\paperheight}{11in} \makeatletter \makeatother \documentclass[aps,secnumarabic,balancelastpage,amsmath,amssymb,nofootinbib]{revtex4} \input{myskeletonpackages.tex} \usepackage[maxfloats=256]{morefloats} \usepackage{graphicx}\usepackage{listings} \input{mycommands.tex} \newcommand{\mjmeqn}[1]{\begin{equation} #1 \end{equation} } \begin{document}
\mjmeqn{(((\frac{-1}{2}\imath ))*(Exp\left(((1\imath ))*(w)\right)+(Exp\left((w)*((-1\imath ))\right))*((-1))))*(((\frac{-1}{2}\imath ))*(Exp\left(((1\imath ))*(z)\right)+(Exp\left((z)*((-1\imath ))\right))*((-1))))*(((\frac{1}{2}))*(Exp\left(((1\imath ))*(z)\right)+(Exp\left((z)*((-1\imath ))\right))*((1))))*((3))+(((\frac{-1}{2}\imath ))*(Exp\left(((1\imath ))*(z)\right)+(Exp\left((z)*((-1\imath ))\right))*((-1))))+(((\frac{1}{2}))*(Exp\left(((1\imath ))*(y)\right)+(Exp\left((y)*((-1\imath ))\right))*((1))))}
\end{document}
./mikemath.h444 x=\setlength{\paperheight}{11in} \makeatletter \makeatother \documentclass[aps,secnumarabic,balancelastpage,amsmath,amssymb,nofootinbib]{revtex4} \input{myskeletonpackages.tex} \usepackage[maxfloats=256]{morefloats} \usepackage{graphicx}\usepackage{listings} \input{mycommands.tex} \newcommand{\mjmeqn}[1]{\begin{equation} #1 \end{equation} } \begin{document}
\mjmeqn{(Sin\left(w\right))*(Sin\left(z\right))*(Cos\left(z\right))*((3))+(Sin\left(z\right))+(Cos\left(y\right))}
\end{document}
./mikemath.h444 x=\setlength{\paperheight}{11in} \makeatletter \makeatother \documentclass[aps,secnumarabic,balancelastpage,amsmath,amssymb,nofootinbib]{revtex4} \input{myskeletonpackages.tex} \usepackage[maxfloats=256]{morefloats} \usepackage{graphicx}\usepackage{listings} \input{mycommands.tex} \newcommand{\mjmeqn}[1]{\begin{equation} #1 \end{equation} } \begin{document}
\mjmeqn{(Exp\left((w)*((-1\imath ))+(z)*((-2\imath ))\right))*((\frac{-3}{8}))+(Exp\left((w)*((-1\imath ))+(z)*((2\imath ))\right))*((\frac{3}{8}))+(Exp\left((w)*((1\imath ))+(z)*((-2\imath ))\right))*((\frac{3}{8}))+(Exp\left((w)*((1\imath ))+(z)*((2\imath ))\right))*((\frac{-3}{8}))+(Exp\left((y)*((-1\imath ))\right))*((\frac{1}{2}))+(Exp\left((y)*((1\imath ))\right))*((\frac{1}{2}))+(Exp\left((z)*((-1\imath ))\right))*((\frac{1}{2}\imath ))+(Exp\left((z)*((1\imath ))\right))*((\frac{-1}{2}\imath ))}
\end{document}
./mikemath.h648 eqn=b m_expressions[eqn].dump(flags)=->plus/l->times/l->exp/x->plus/l->times/l m_str_name=var var()=w value()=(0 + 0i)
->plus/l->times/l->exp/x->plus/l->times/r m_str_name=const var()= value()=(0 + -1i)
->plus/l->times/l->exp/x->plus/r->times/l m_str_name=var var()=z value()=(0 + 0i)
->plus/l->times/l->exp/x->plus/r->times/r m_str_name=const var()= value()=(0 + -2i)
->plus/l->times/r m_str_name=const var()= value()=(-3/8 + 0i)
->plus/r->times/l->exp/x->plus/l->times/l m_str_name=var var()=w value()=(0 + 0i)
->plus/r->times/l->exp/x->plus/l->times/r m_str_name=const var()= value()=(0 + -1i)
->plus/r->times/l->exp/x->plus/r->times/l m_str_name=var var()=z value()=(0 + 0i)
->plus/r->times/l->exp/x->plus/r->times/r m_str_name=const var()= value()=(0 + 2i)
->plus/r->times/r m_str_name=const var()= value()=(3/8 + 0i)
->plus/x0->times/l->exp/x->plus/l->times/l m_str_name=var var()=w value()=(0 + 0i)
->plus/x0->times/l->exp/x->plus/l->times/r m_str_name=const var()= value()=(0 + 1i)
->plus/x0->times/l->exp/x->plus/r->times/l m_str_name=var var()=z value()=(0 + 0i)
->plus/x0->times/l->exp/x->plus/r->times/r m_str_name=const var()= value()=(0 + -2i)
->plus/x0->times/r m_str_name=const var()= value()=(3/8 + 0i)
->plus/x1->times/l->exp/x->plus/l->times/l m_str_name=var var()=w value()=(0 + 0i)
->plus/x1->times/l->exp/x->plus/l->times/r m_str_name=const var()= value()=(0 + 1i)
->plus/x1->times/l->exp/x->plus/r->times/l m_str_name=var var()=z value()=(0 + 0i)
->plus/x1->times/l->exp/x->plus/r->times/r m_str_name=const var()= value()=(0 + 2i)
->plus/x1->times/r m_str_name=const var()= value()=(-3/8 + 0i)
->plus/x2->times/l->exp/x->plus/l->times/l m_str_name=var var()=y value()=(0 + 0i)
->plus/x2->times/l->exp/x->plus/l->times/r m_str_name=const var()= value()=(0 + -1i)
->plus/x2->times/r m_str_name=const var()= value()=(1/2 + 0i)
->plus/x3->times/l->exp/x->plus/l->times/l m_str_name=var var()=y value()=(0 + 0i)
->plus/x3->times/l->exp/x->plus/l->times/r m_str_name=const var()= value()=(0 + 1i)
->plus/x3->times/r m_str_name=const var()= value()=(1/2 + 0i)
->plus/x4->times/l->exp/x->plus/l->times/l m_str_name=var var()=z value()=(0 + 0i)
->plus/x4->times/l->exp/x->plus/l->times/r m_str_name=const var()= value()=(0 + -1i)
->plus/x4->times/r m_str_name=const var()= value()=(0 + 1/2i)
->plus/x5->times/l->exp/x->plus/l->times/l m_str_name=var var()=z value()=(0 + 0i)
->plus/x5->times/l->exp/x->plus/l->times/r m_str_name=const var()= value()=(0 + 1i)
->plus/x5->times/r m_str_name=const var()= value()=(0 + -1/2i)
If you are curious , the input is kind of odd RPN lol. Each node
has a list of child names and optional values. I can
do this in my head for now but it should work with many
parsers...
cat ttrig.txt
#viewer launch
err-msg 0
add-exp plus a 0
add-exp sin a 0 l z
add-exp cos a 0 r y
add-exp times a 0 x0
add-exp constant a 0 l x0 3
add-exp sin a 0 r x0 z
add-exp cos a 0 x0 x0 z
add-exp sin a 0 x1 x0 w
list
print-eqn a a
xnom-exp a a a
exp-xnom a a a
print-eqn a a
err-msg 0
load-ident tid.txt
dump-ident
apply-ident c a sinexp
apply-ident b c cosexp
err-msg 0
print-eqn b b 2
print-eqn a a 2
xnom-exp b b b
exp-xnom b b b
print-eqn b b 2
dump-exp b b 2
--
mike marchywka
306 charles cox
canton GA 30115
USA, Earth
marchywka at hotmail.com
404-788-1216
ORCID: 0000-0001-9237-455X
More information about the texhax
mailing list.