7

I have a software that allows to implement equations and one can write them in-line such as:

==================

x = a_avg + ((x-1)/b_trans)^(-y^(-x))

y = ....

z = .... (something that have a similar form)

... etc, etc

=================

So basically, I have a *.doc full of these equations and I would like to translate them to Latex, so that they would look like this:

$x = a_{avg} + \frac{x-1}{b_{trans}}^{-y^{-x}}$ 

The challenge comes from translation of indexes (e.g. avg, trans) to {} for the subscript or superscript. Also translate ()/() to \frac{}{}. Is anyone aware of such a package that would translate the entire document into list of equations? Or does anyone have any idea how can one do this?

I would appreciate any advice!

Paul

  • 3
    you'd want b_{\mathrm{trans}} (never typeset multi-letter words in math italic) a simple regex replace of _([a-z]*) to _{\\mathrm{\1}} should work in any editor. – David Carlisle Sep 30 '16 at 11:28
  • Thank you David. But I would like to translate the entire document. Not equation by equation. – Physther Sep 30 '16 at 11:32
  • sure but you just apply the same replace globally just as if you change "yes" to "no" it's as easy to change one as all instances in a document – David Carlisle Sep 30 '16 at 11:33
  • Did you see the posting Expanding subscript and subscript capabilities? – Mico Sep 30 '16 at 11:35
  • Please see my much improved answer. – Steven B. Segletes Apr 21 '17 at 19:35
12

if eq.txt contains lines like

x = a_avg + ((x-1)/b_trans)^(-y^(-x))

then a simple edit line such as

 sed -e 's/(/{(/g' -e 's/)/)}/g'  -e 's/\//\\over /g' -e 's/_\([a-z]*\)/_{\\mathrm{\1}}/g' -e 's/.*/$\0$/' eq.txt 

will output

$x = a_{\mathrm{avg}} + {({(x-1)}\over b_{\mathrm{trans}})}^{(-y^{(-x)})}$

for each line

which when typeset as

\documentclass{article}

\begin{document}

$x = a_{\mathrm{avg}} + {({(x-1)}\over b_{\mathrm{trans}})}^{(-y^{(-x)})}$

\end{document}

produces

enter image description here

I used sed here but you could use perl or lua or your editor search/replace.


Actually you need to work a bit harder with the regex on the brackets (note one ) slipped down... ) but this is I hope enough to show the basic idea.

  • 2
    the parentheses around the fraction are totally misplaced. of course, here they aren't necessary, and are even harmful as shown. – barbara beeton Sep 30 '16 at 11:49
  • @barbarabeeton a minor detail:-) – David Carlisle Sep 30 '16 at 11:52
  • Great! I tried and it worked! Thank you so much. I have two more questions. How to replace "" with "\cdot", I added on the "sed" command this: 's/*/\cdot', but it didn't work. I guess the "" symbol is confusing. It says "unknown option to 's' And the second one, is it possible to add a \begin{equation} before every line and \end{equation} after each equation (each other line?) – Physther Sep 30 '16 at 12:02
  • @Paul the cdot ought to work (possibly an encoding issue), and beginequation end equation just replace 4 in what i did above to use the environment form. so where I have $\0$ to put dollars use \\begin{equation}\0\\end{equation} – David Carlisle Sep 30 '16 at 13:07
  • Thank you! I have managed to implement what I wanted. It's a very nice tool! – Physther Sep 30 '16 at 13:59
13

This is an unusual answer, because, while it does convert the OP's code into LaTeX code, that code is stored in a way to be read by the computer and not the human eye. Thus, a more appropriate way to characterize this answer is that it provides an interpreter, written in LaTeX, to convert and present equations provided in a non-LaTeX format. However, the most recent update now has the ability to convert that internal code into a detokenized translation of the relevant LaTeX code.

THIS ANSWER HAS BEEN MUCH UPDATED:

EDITED so that select math operators and greek letters may be parsed without being escaped (e.g., cos x = beta is parsed properly). More can be added.

EDITED so that square bracketes [...] may be used as non-visible grouping characters.

Re-EDITED to automatically convert / into \frac style (thanks to David's description of \over at Practical consequences of using \over vs. \frac?).

EDITED to provide automation.

EDITED to provide translation, as well as interpretive rendering.

INTERPRETING EQUATIONS

This answer automates the process of using a LaTeX macro to interpret equations expressed in a non-LaTeX user syntax. I provide the LaTeX macro \interpreteq{} in which a non-latex equation is passed, parsed in 7 stages, reconstituted, and presented as a LaTeX equation.

The really neat thing about this approach is that the equation input, in the user's non-LaTeX format is parsed into the mathematical "genes" that make up an equation according to the order of operations. Then, each gene is converted into LaTeX format, and the resulting genes are automatically reconstituted into a DNA strand of executable LaTeX code.

However, that DNA strand of executable code is indirectly expressed in the internal representation of the listofitems package, which was used to mathematically slice up the original non-LaTeX equation. This internal representation of the equation (which is quite bizarre to look at), can be displayed, as proof of the method, by way of \detokenize\expandafter{\Z} at the conclusion of the \interpreteq. This will provide the tokens that are actually executed to present to LaTeX form of the equation.

So, for example, take, the user-formatted (non-LaTeX) equation:

x = a_avg + ([x-1] /b_trans)^(-y^[-x])

This string of tokens is parsed by the listofitems package into the \Q list, using the following parsing heirarchy:

\setsepchar[@]{=@(||)||[||]@^@/||*@+||-@_@alpha||beta||pi||cos||sin||tan}

The first layer of parsing is to find instances of =. All code to the left of the = is stored in \Q[1], and all code to the right of [the 1st] = (and to the left of the 2nd =) is stored in \Q[2]. The separator at this level (i.e., the =) is stored in \Qsep[1].

For each piece, \Q[1] and \Q[2], the second level of parsing occurs which looks for all instances of (, ), [, and ]. So, for example, \Q[2,3] indicates that strand of the [non-LaTeX] DNA to the right of the = and prior to the 3rd instance of the paren or bracket separators.

This procedure continues to 7+ levels of parsing according to a PEMDAS order of operations:

  1. =
  2. (, ), [, and ]
  3. ^
  4. / and *
  5. + and -
  6. _
  7. alpha, beta, pi, cos, sin, tan and other functions, as needed

Anything that is not one of the parsable separators will end up in some low-level \Q[.,.,...] gene entry. However, all the parsable separators will end up in a \Qsep[.,.,...] separator-gene entry. And it is these \Qsep entries that require conversion into LaTeX format, and this procedure is carried out by the \QS macro:

\def\QS[#1]{%
  \if+\Qsep[#1]+\else%
  \if-\Qsep[#1]-\else%
  \if/\Qsep[#1]\over\else%
  \if=\Qsep[#1]=\else%
  \if^\Qsep[#1]^\else%
  \if(\Qsep[#1]\bgroup\left(\else%
  \if)\Qsep[#1]\right)\egroup\else%
  \if[\Qsep[#1]\bgroup\else%
  \if]\Qsep[#1]\egroup\else%
  \if*\Qsep[#1]\cdot\else%
  \if_\Qsep[#1]\expandafter\theund\else%
  \csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}

The DNA is then reconstituted as a string of calls to an indexed succession of \Q[] and \QS[] (converted \Qsep[]) genes. They all appear in the original order as sliced. So, for instance, the user-format equation (x = a_avg + ([x-1] /b_trans)^(-y^[-x])), once sliced and converted by \interpreteq, is reconstituted as a DNA strand by way of the following expression:

\Q [1,1,1,1,1,1,1]\QS [1]\Q [2,1,1,1,1,1,1]\QS [2,1,1,1,1,1]\Q [2,1,1,1,1,2,1]\QS
[2,1,1,1,1]\Q [2,1,1,1,2,1,1]\QS [2,1]\Q [2,2,1,1,1,1,1]\QS [2,2]\Q [2,3,1,1,1,1,1]\QS
[2,3,1,1,1]\Q [2,3,1,1,2,1,1]\QS [2,3]\Q [2,4,1,1,1,1,1]\QS [2,4,1,1]\Q [2,4,1,2,1,1,1]\QS
[2,4,1,2,1,1]\Q [2,4,1,2,1,2,1]\QS [2,4]\Q [2,5,1,1,1,1,1]\QS [2,5,1]\Q [2,5,2,1,1,1,1]\QS
[2,5]\Q [2,6,1,1,1,1,1]\QS [2,6,1,1,1]\Q [2,6,1,1,2,1,1]\QS [2,6,1]\Q [2,6,2,1,1,1,1]\QS
[2,6]\Q [2,7,1,1,1,1,1]\QS [2,7,1,1,1]\Q [2,7,1,1,2,1,1]\QS [2,7]\Q [2,8,1,1,1,1,1]\QS
[2,8]\Q [2,9,1,1,1,1,1]

And, based on the genes that are in \Q and \QS, the result looks like that desired, namely

enter image description here

TRANSLATING EQUATIONS

Translation is achieved either in macro form, \translateeq{} or by way of a translation environment of space separated equations

\begin{translateeqs}% NO BLANK LINE IS PERMITTED HERE
EQ1

EQ2

...

EQn
\end{translateeqs}% NO BLANK LINE IS PERMITTED BEFORE HERE

This was achieved merely by temporarily redefining several key macros in the process and using \protected@edef to expand the \Q and \QS genes into their relevant LaTeX code. Then the resulting equations are not rendered as before, but instead presented as detokenized LaTeX code.

The translations can, in practice, be done in a separate document, with the results being copied and pasted from the resulting PDF into a target source document.

THE MWE

The 5 equations that you will see in the MWE below, both interpreted and translated, are input in non-LaTeX form. Notable highlights of the conversion process include the handling of multi-character subscripts without grouping, recognizing a number of textual (not macro) mathematical functions and greek letter names (more can be added), auto-converting / into fractions, auto-sizing parens, converting * into \cdot, etc. Here are the 5 equations:

cos(1/s) = f*g

f(x) = y^(2*x) =beta

f(x) = pi * y^[((2/x)^3 + [B/x_i])^n] =(z/B)^(2/x_i)

f(x) = pi * y^[((2/x)^3 +  B/x_i )^n] =(z/B)^(2/x_i)

x = a_avg + ([x-1] /b_trans)^(-y^[-x])

Here is the MWE:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{listofitems,ifthen}

\def\QS[#1]{%
  \if+\Qsep[#1]+\else%
  \if-\Qsep[#1]-\else%
  \if/\Qsep[#1]\over\else%
  \if=\Qsep[#1]=\else%
  \if^\Qsep[#1]^\else%
  \if(\Qsep[#1]\bgroup\left(\else%
  \if)\Qsep[#1]\right)\egroup\else%
  \if[\Qsep[#1]\bgroup\else%
  \if]\Qsep[#1]\egroup\else%
  \if*\Qsep[#1]\cdot\else%
  \if_\Qsep[#1]\expandafter\theund\else%
  \csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}%

\def\theund#1[#2]{_{\mathrm{#1[#2]}}}%

\setsepchar[@]{=@(||)||[||]@^@/||*@+||-@_@alpha||beta||pi||cos||sin||tan}

\makeatletter

\def\gQ[#1]{\edef\tmp{#1}\expandafter\g@addto@macro\expandafter\Z%
  \expandafter{\expandafter\Q\expandafter[\tmp]}}
\def\gQS[#1]{\edef\tmp{#1}\expandafter\g@addto@macro\expandafter\Z%
  \expandafter{\expandafter\QS\expandafter[\tmp]}}

\makeatother

\newcommand\interpreteq[1]{%
  \def\Z{}%
  \greadlist*\Q{#1}%
  \presentQ%
  \Z%
}

\newcounter{lindex}
\def\presentQ{% =
  \setcounter{lindex}{0}%
  \whiledo{\value{lindex}<\listlen\Q[]}{%
    \stepcounter{lindex}%
    \presentQA[\thelindex]%
    \ifnum\value{lindex}<\listlen\Q[]\relax%
      \gQS[\thelindex]%
    \fi%
  }%
}
\newcounter{lindexA}
\def\presentQA[#1]{% ()
  \setcounter{lindexA}{0}%
  \whiledo{\value{lindexA}<\listlen\Q[#1]}{%
    \stepcounter{lindexA}%
    \presentQB[#1,\thelindexA]%
    \ifnum\value{lindexA}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexA]%
    \fi%
  }
}
\newcounter{lindexB}
\def\presentQB[#1]{% ^
  \setcounter{lindexB}{0}%
  \whiledo{\value{lindexB}<\listlen\Q[#1]}{%
    \stepcounter{lindexB}%
    \presentQC[#1,\thelindexB]%
    \ifnum\value{lindexB}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexB]%
    \fi%
  }
}
\newcounter{lindexC}
\def\presentQC[#1]{% /*
  \setcounter{lindexC}{0}%
  \whiledo{\value{lindexC}<\listlen\Q[#1]}{%
    \stepcounter{lindexC}%
    \presentQD[#1,\thelindexC]%
    \ifnum\value{lindexC}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexC]%
    \fi%
  }
}
\newcounter{lindexD}
\def\presentQD[#1]{% +-
  \setcounter{lindexD}{0}%
  \whiledo{\value{lindexD}<\listlen\Q[#1]}{%
    \stepcounter{lindexD}%
    \presentQE[#1,\thelindexD]%
    \ifnum\value{lindexD}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexD]%
    \fi%
  }
}
\newcounter{lindexE}
\def\presentQE[#1]{% _
  \setcounter{lindexE}{0}%
  \whiledo{\value{lindexE}<\listlen\Q[#1]}{%
    \stepcounter{lindexE}%
    \presentQF[#1,\thelindexE]%
    \ifnum\value{lindexE}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexE]%
    \fi%
  }
}
\newcounter{lindexF}
\def\presentQF[#1]{% alpha beta pi cos sin tan
  \setcounter{lindexF}{0}%
  \whiledo{\value{lindexF}<\listlen\Q[#1]}{%
    \stepcounter{lindexF}%
    \gQ[#1,\thelindexF]%
    \ifnum\value{lindexF}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexF]%
    \fi%
  }
}

% THESE ARE THE REDEFITIIONS FOR TRANSLATION
\usepackage{environ}

\def\QSALT[#1]{%
  \if+\Qsep[#1]+\else%
  \if-\Qsep[#1]-\else%
  \if/\Qsep[#1]\over\else%
  \if=\Qsep[#1]=\else%
  \if^\Qsep[#1]^\else%
  \if(\Qsep[#1]{\left(\else%
  \if)\Qsep[#1]\right)}\else%
  \if[\Qsep[#1]{\else%
  \if]\Qsep[#1]}\else%
  \if*\Qsep[#1]\cdot\else%
  \if_\Qsep[#1]\expandafter\theundALT\else%
  \expandafter\noexpand\csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}%

\def\theundALT#1[#2]{_{\noexpand\mathrm{#1[#2]}}}%

\makeatletter
\newcommand\translateeq[1]{%
  \bgroup%
  \let\QS\QSALT%
  \def\Z{}%
  \greadlist*\Q{#1}%
  \presentQ%
  \protected@edef\ZZ{\Z}
  \par\medskip\noindent%
  \parbox{\linewidth}{\detokenize\expandafter{\ZZ}}%
  \par\medskip%
  \egroup%
}
\makeatother

\NewEnviron{translateeqs}{\expandafter\nexteqn\BODY\par\relax}

\long\def\nexteqn#1\par#2\relax{%
  \translateeq{#1}\ifx\relax#2\else\nexteqn#2\relax\fi%
}
\begin{document}
\textbf{INTERPRETATING EQUATIONS}
\[
\interpreteq{cos(1/s) = f*g}
\]
\[
\interpreteq{f(x) = y^(2*x) =beta}
\]
\[
\interpreteq{f(x) = pi * y^[((2/x)^3 + [B/x_i])^n] =(z/B)^(2/x_i)}
\]
\[
\interpreteq{f(x) = pi * y^[((2/x)^3 +  B/x_i )^n] =(z/B)^(2/x_i)}
\]
\[
\interpreteq{x = a_avg + ([x-1] /b_trans)^(-y^[-x])}
\]

This is the code ``DNA'' that expresses the above equation:

\detokenize\expandafter{\Z}% COPY/PASTE RESULT OF THIS FROM PDF TO BELOW

See?  I copied/pasted it into equation mode and get the same result.
\[
\Q [1,1,1,1,1,1,1]\QS [1]\Q [2,1,1,1,1,1,1]\QS [2,1,1,1,1,1]\Q [2,1,1,1,1,2,1]\QS
[2,1,1,1,1]\Q [2,1,1,1,2,1,1]\QS [2,1]\Q [2,2,1,1,1,1,1]\QS [2,2]\Q [2,3,1,1,1,1,1]\QS
[2,3,1,1,1]\Q [2,3,1,1,2,1,1]\QS [2,3]\Q [2,4,1,1,1,1,1]\QS [2,4,1,1]\Q [2,4,1,2,1,1,1]\QS
[2,4,1,2,1,1]\Q [2,4,1,2,1,2,1]\QS [2,4]\Q [2,5,1,1,1,1,1]\QS [2,5,1]\Q [2,5,2,1,1,1,1]\QS
[2,5]\Q [2,6,1,1,1,1,1]\QS [2,6,1,1,1]\Q [2,6,1,1,2,1,1]\QS [2,6,1]\Q [2,6,2,1,1,1,1]\QS
[2,6]\Q [2,7,1,1,1,1,1]\QS [2,7,1,1,1]\Q [2,7,1,1,2,1,1]\QS [2,7]\Q [2,8,1,1,1,1,1]\QS
[2,8]\Q [2,9,1,1,1,1,1]
\]

\textbf{TRANSLATING EQUATIONS}
\begin{translateeqs}% NO BLANK LINE IS PERMITTED HERE
cos(1/s) = f*g

f(x) = y^(2*x) =beta

f(x) = pi * y^[((2/x)^3 + [B/x_i])^n] =(z/B)^(2/x_i)

f(x) = pi * y^[((2/x)^3 +  B/x_i )^n] =(z/B)^(2/x_i)

x = a_avg + ([x-1] /b_trans)^(-y^[-x])
\end{translateeqs}% NO BLANK LINE IS PERMITTED BEFORE HERE

\translateeq{x = a_avg + ([x-1] /b_trans)^(-y^[-x])}

\end{document}

enter image description here

  • (+1) but ... why? – cfr Sep 30 '16 at 23:16
  • @cfr Well, if I managed to write the nested loop that could fully automate the process, it would allow one to \input equations composed in a different format and present them in the standard LaTeX way. – Steven B. Segletes Sep 30 '16 at 23:21
  • The code wouldn't be very readable, though, would it? – cfr Oct 1 '16 at 1:24
  • 1
    @cfr See my edit (for the 2nd time) to really see what I had in mind from the beginning – Steven B. Segletes Apr 18 '17 at 17:14
  • 1
    Now it makes more sense - thanks for the explanation. Can't upvote again, sadly. – cfr Apr 18 '17 at 18:09

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.