9
$\begingroup$

Update

Thanks to answer below by Carl Woll, I've put my notebook where it contains all the settings and code needed to use for better Latex formatting if others want to use it. This will save you the time having to type all this.

To use, simply download and open the notebook and do evaluate->Notebook the very first thing after you start Mathematica.

Now in any other notebooks when you do TeXForm[] it will use the new formatting which will make the Latex generated better looking for the special functions and for the inverse trig functions.

I've added many special functions, but there are still more to add, feel free to add more yourself if you need others not listed.

Here is the notebook


I have been using the great answer by @CarlWoll in Is it possible to change/customize some conversions done by TeXForm? for sometime. Now in V 13.1 I found some problems. (I am not quite sure if this problem was there all the time, and I just never had an example ode which showed the problem, or it is due to upgrading to version 13.1).

But now, using the same code to convert some solutions to Latex, the Latex generated from TeXForm do not compile using TeXLive.

I will give below all the code from the answer above in one place to reproduce the problem, and the Latex error it generates.

I hope there is a solution to this, as without this, the Latex generated directly is not as good. I use Carl's fix to change special functions names to make them easy to read in the latex.

Here is MWE. This below is the same exact code by Carl from the above answer.

Initial /: Verbatim[TagSetDelayed][Initial[sym_], lhs_, rhs_] := 
 With[{new = Block[{sym}, TagSetDelayed[sym, lhs, rhs];
     First@Language`ExtendedDefinition[sym, "ExcludedContexts" -> {}]], 
   protect = Unprotect[sym]}, sym;
  Replace[new, Rule[values_, n : Except[{}]] :> (values[sym] = Prepend[values[sym], n]), {2}];
  Protect@protect;]

System`Convert`TeXFormDump`maketex[s_String] /; ! StringMatchQ[s, "\"" ~~ ___ ~~ "\""] && 
   SyntaxQ[s, TeXForm] := Replace[s, {n_ /; StringMatchQ[n, NumberString] :> n, 
   w_?wordQ :> "\\operatorname{" <> w <> "}"}]

wordQ[s_String] := Length@StringSplit[s, WordBoundary] == 1

Initial[Convert`TeX`ExpressionToTeX] /: 
 Convert`TeX`ExpressionToTeX[e__] /; ! TrueQ@$TeX := 
 Block[{$TeX = True}, Convert`TeX`ExpressionToTeX[e]]

Initial[EllipticF]/:MakeBoxes[EllipticF[a_,b_],TraditionalForm]/;$TeX:=MakeBoxes[Defer[EllipticF][a,b],TraditionalForm];

With the above evaluated, the following shows the problem

sol = DSolve[(a/2 - 6*y[x]^2)*y'[x]^2 + (-b - a*y[x] + 4*y[x]^3)*     y''[x] == 0, y[x], x]
TeXForm[sol]

\operatorname{Solve}\left[\frac{2 \sqrt{\frac{y(x)-\operatorname{Root}\left[4 #1^3-#1 a-b\&,1\right]}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]-\operatorname{Root}\left[4 #1^3-#1 a-b\&,1\right]}}
   \sqrt{\frac{y(x)-\operatorname{Root}\left[4 #1^3-#1 a-b\&,2\right]}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]-\operatorname{Root}\left[4 #1^3-#1 a-b\&,2\right]}} \left(y(x)-\operatorname{Root}\left[4 #1^3-#1
   a-b\&,3\right]\right) \operatorname{EllipticF}\left(\sin ^{-1}\left(\sqrt{\frac{\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]-y(x)}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]-\operatorname{Root}\left[4
   #1^3-#1 a-b\&,2\right]}}\right),\frac{\operatorname{Root}\left[4 #1^3-#1 a-b\&,2\right]-\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,1\right]-\operatorname{Root}\left[4
   #1^3-#1 a-b\&,3\right]}\right)}{c_1 \sqrt{2 a y(x)+2 b-8 y(x)^3} \sqrt{\frac{y(x)-\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,2\right]-\operatorname{Root}\left[4 #1^3-#1
   a-b\&,3\right]}}}=x+c_2,y(x)\right]

After copying the above to my latex editor

\documentclass[12pt]{article}
\usepackage{amsmath}
\begin{document}

\[
\operatorname{Solve}\left[\frac{2 \sqrt{\frac{y(x)-\operatorname{Root}\left[4 #1^3-#1 a-b\&,1\right]}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]-\operatorname{Root}\left[4 #1^3-#1 a-b\&,1\right]}}
   \sqrt{\frac{y(x)-\operatorname{Root}\left[4 #1^3-#1 a-b\&,2\right]}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]-\operatorname{Root}\left[4 #1^3-#1 a-b\&,2\right]}} \left(y(x)-\operatorname{Root}\left[4 #1^3-#1
   a-b\&,3\right]\right) \operatorname{EllipticF}\left(\sin ^{-1}\left(\sqrt{\frac{\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]-y(x)}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]-\operatorname{Root}\left[4
   #1^3-#1 a-b\&,2\right]}}\right),\frac{\operatorname{Root}\left[4 #1^3-#1 a-b\&,2\right]-\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,1\right]-\operatorname{Root}\left[4
   #1^3-#1 a-b\&,3\right]}\right)}{c_1 \sqrt{2 a y(x)+2 b-8 y(x)^3} \sqrt{\frac{y(x)-\operatorname{Root}\left[4 #1^3-#1 a-b\&,3\right]}{\operatorname{Root}\left[4 #1^3-#1 a-b\&,2\right]-\operatorname{Root}\left[4 #1^3-#1
   a-b\&,3\right]}}}=x+c_2,y(x)\right]
\]
\end{document}

and compiling it, gives the error

>lualatex foo.tex
This is LuaHBTeX, Version 1.15.1 (TeX Live 2023/dev) 
 restricted system commands enabled.
(./foo.tex
LaTeX2e <2022-06-01> patch level 5
 L3 programming layer <2022-07-04>
(/usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls
Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
(/usr/local/texlive/2022/texmf-dist/tex/latex/base/size12.clo))
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-luatex.def)
(./foo.aux) (/usr/local/texlive/2022/texmf-dist/tex/latex/base/ts1cmr.fd)
! You can't use `macro parameter character #' in math mode.
<argument> y(x)-\operatorname {Root}\left [4 ##
                                    1^3-##1 a-b\&,1\right ]
l.18    a-b\&,3\right]}}}
                       =x+c_2,y(x)\right]
? 

The problem is in # being used in math mode. Compare the above latex with the one that would have been generated before, (ie without using the above modification)

sol=DSolve[(a/2-6*y[x]^2)*y'[x]^2+(-b-a*y[x]+4*y[x]^3)*y''[x]==0,y[x],x];
TeXForm[sol]

gives

\text{Solve}\left[\frac{2 \sqrt{\frac{y(x)-\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1} a-b\&,1\right]}{\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1} a-b\&,3\right]-\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1}
   a-b\&,1\right]}} \sqrt{\frac{y(x)-\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1} a-b\&,2\right]}{\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1} a-b\&,3\right]-\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1}
   a-b\&,2\right]}} \left(y(x)-\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1} a-b\&,3\right]\right) F\left(\sin ^{-1}\left(\sqrt{\frac{\text{Root}\left[4 \text{$\#$1}^3-a
   \text{$\#$1}-b\&,3\right]-y(x)}{\text{Root}\left[4 \text{$\#$1}^3-a \text{$\#$1}-b\&,3\right]-\text{Root}\left[4 \text{$\#$1}^3-a \text{$\#$1}-b\&,2\right]}}\right)|\frac{\text{Root}\left[4 \text{$\#$1}^3-a
   \text{$\#$1}-b\&,2\right]-\text{Root}\left[4 \text{$\#$1}^3-a \text{$\#$1}-b\&,3\right]}{\text{Root}\left[4 \text{$\#$1}^3-a \text{$\#$1}-b\&,1\right]-\text{Root}\left[4 \text{$\#$1}^3-a
   \text{$\#$1}-b\&,3\right]}\right)}{c_1 \sqrt{2 a y(x)+2 b-8 y(x)^3} \sqrt{\frac{y(x)-\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1} a-b\&,3\right]}{\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1}
   a-b\&,2\right]-\text{Root}\left[4 \text{$\#$1}^3-\text{$\#$1} a-b\&,3\right]}}}=x+c_2,y(x)\right]

The above compiles OK. Notice all the # are now inside \text{$\#$1} and so do not give error when compiled.

Question is: How can use Carl fix without having this problem in the Latex generated?

V 13.1 on windows 10.

$\endgroup$

2 Answers 2

5
$\begingroup$

Try the following modification to maketex instead:

System`Convert`TeXFormDump`maketex[TemplateBox[a_, tag_?fullformQ]] := System`Convert`TeXFormDump`maketex[
    RowBox[{operatorName[convertTag @ tag], "(", RowBox[Riffle[a, ","]], ")"}]
]

System`Convert`TeXFormDump`maketex[operatorName[tag_]] := "\\operatorname{"<>tag<>"}"

convertTag[s_] := s;
convertTag["EllipticPi3"] = "EllipticPi";

fullformQ[_]=False;
fullformQ["AppellF1"]=True;
fullformQ["EllipticPi3"]=True;

Then:

AppellF1[a,b,c,d,e,f]//TeXForm

\operatorname{AppellF1}(a,b,c,d,e,f)

and:

EllipticPi[a,b,c]//TeXForm

\operatorname{EllipticPi}(a,b,c)

For the inverse trig functions, you will need to use the Initial[Convert`TeX`ExpressionToTeX] code so that ArcSin formatting in normal TraditionalForm doesn't get messed up. Then:

Unprotect[ArcSin];
ArcSin /: MakeBoxes[ArcSin[x_], TraditionalForm] /; $TeX := RowBox[{"arcsin", "(", MakeBoxes[x, TraditionalForm], ")"}]
Protect[ArcSin];

should do what you want:

ArcSin[x]//TeXForm

\arcsin (x)

$\endgroup$
8
  • $\begingroup$ wow Carl! Amazing. I was about to post another question on this topic but your solution seems to have solved all these issues in a very simple way. I will now change all my TeX conversion code now to use the above set up and will try it on my main program to test it more. This should be buildin Mathematica in next version. I suggest adding option to TeXForm. Something like TeXForm[....,LongForm->True] which will now automatically generate \operatorname{} for those special functions which do not have known standard build in Latex names. $\endgroup$
    – Nasser
    Apr 30 at 16:09
  • $\begingroup$ Do you know why it does not work for ArcSin[x]? Here is screen shot !Mathematica graphics do I need to do something other than just adding fullformQ["ArcSin"] = True; ? I am on V 13.2.1 I was hoping to get \operatorname{ArcSin}(x). I would prefer \operatorname{arcsin}(x) actually but will live with UpperCase for now. $\endgroup$
    – Nasser
    Apr 30 at 16:21
  • 1
    $\begingroup$ @Nasser Would \arcsin(x) be ok, or does it have to be \operatorname{arcsin}(x)? $\endgroup$
    – Carl Woll
    Apr 30 at 17:13
  • $\begingroup$ Opps, actually \arcsin(x) would be great. Few years ago when I tried \arcsin(x) it seems not to be part of standard latex, but now I checked. All the arc* functions are now standard in latex. So yes, \arcsin(x) and \arccos(x) etc... will be the best solution for these functions if it is possible to do. Thanks. $\endgroup$
    – Nasser
    Apr 30 at 17:18
  • 1
    $\begingroup$ @Nasser See update $\endgroup$
    – Carl Woll
    Jun 22 at 14:05
4
$\begingroup$

I'll post this workaround. But will keep this open if a better answer will come along.

I just noticed that this is known issue. I Mentioned it 4 years ago in the comment and forgot about it.

May be this will make it more clear what the issue is. It does not look there is a better solution for now.

The solution is not to use the code which converts \text to \operatorname in Carl solution. This resolves the issue. But the Latex will not look as nice, but at least it will show the special functions names more clearly and will compile.

So now

 TeXForm[EllipticF[a, b]]

Will show as

 \text{EllipticF}(a,b)

Instead of

 \operatorname{EllipticF}(a,b)

But now it will compile OK and the problems with # no longer are there. Notice that without these modification, the original TeXForm would have generated

TeXForm[EllipticF[a,b]]

This

F(a|b)

Which is not clear at all what this special function is. And that is the whole reason for doing all of this.

The bottom line is that one needs to remove this code

System`Convert`TeXFormDump`maketex[s_String]/;!StringMatchQ[s,"\""~~___~~"\""]&&SyntaxQ[s,TeXForm]:=Replace[s,{n_/;StringMatchQ[n,NumberString]:>n,w_?wordQ:>"\\operatorname{"<>w<>"}"}]

Here is the full Carl code again to use all in one place to make it more clear after removing the above line which causes the problem

Initial /: Verbatim[TagSetDelayed][Initial[sym_], lhs_, rhs_] := 
 With[{new = Block[{sym}, TagSetDelayed[sym, lhs, rhs];
     First@
      Language`ExtendedDefinition[sym, "ExcludedContexts" -> {}]], 
   protect = Unprotect[sym]}, sym;
  Replace[new, 
   Rule[values_, 
     n : Except[{}]] :> (values[sym] = 
      Prepend[values[sym], n]), {2}];
  Protect@protect;]
    
wordQ[s_String] := Length@StringSplit[s, WordBoundary] == 1

Initial[Convert`TeX`ExpressionToTeX] /: 
 Convert`TeX`ExpressionToTeX[e__] /; ! TrueQ@$TeX := 
 Block[{$TeX = True}, Convert`TeX`ExpressionToTeX[e]]

Now add your own definitions for any special function that you want to show its name in full in the latex. Like this

Initial[EllipticF]/:MakeBoxes[EllipticF[a_,b_],TraditionalForm]/;$TeX:=MakeBoxes[Defer[EllipticF][a,b],TraditionalForm];

And

Initial[LogIntegral]/:MakeBoxes[LogIntegral[a_],TraditionalForm]/;$TeX:=MakeBoxes[Defer[LogIntegral][a],TraditionalForm];

and so on. For each special function you want changed, add another command as the above.

I think Mathematica's TeXForm itself should have option to do this. Something like

TeXForm[...., UseFullNameForSpecialFunctions->True]

There are more problems with TeXForm such as no option to change how arcsin, arccos, etc... show. Now they show as $sin^{-1}$ which is not good at all as it confused this with $\frac{1}{\sin}$. The modern and better way is to use $\arcsin$.

WRI should really fix all these issues in TeXForm one day and devote some of the resources they use on the cloudy things to fixing TeXForm.

Getting good Latex from Mathematica is very important. After all, this is will be the final output used at the end of the day for many people.

Appendix

Here is my full notebook which uses the above with all the definitions I currently use and keep adding to them in case someone wants to use it so they do not have to go through adding all these again one by one. Since it too large to post here and code will get messed up, here is a link to the notebook

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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