# Is there a way to specify that \sqrt{}s should be avoided in favor of exponents when using the latex() function?

Background: I'm using Sage to do some computations for a LaTeX document I'm preparing. My preferred approach is to include the script directly in the markup, using SageTeX to parse the code and print the results in TeX-readable form. The computations relevant to this question result in a longish list of numbers, most of which are of the form something*sqrt(pi). My intention is to include this list in a table, which I'm constructing using a little Python script I wrote. The script takes a lists of TeX-formatted strings and returns a string with the markup for a table with those strings as rows.

The problem: When I call the latex() function on the list elements to prepare them for serialization into the table, I get results like this: \frac{3}{7} \sqrt{7} \sqrt{\pi}. This is not at all how I would type this if I were "TeXifying" it myself---I'd much prefer \frac{3}{7} \sqrt{7 \pi}. Even \frac{3}{7} (7 \pi)^{1/2} would be preferable IMO.

Obviously, I could just generate a table and then copy-paste it into my document, tweaking where necessary. I could also try writing a little Python function to massage the output into the desired form. But it made me wonder if there is any way to control or customize the output of latex() beyond the basic delimiter-setting functions I found in the docs, and I think that'd be worthwhile to know in any event.

Specific question: Is there a way to "tell" Sage to avoid using \sqrt{} in its LaTeX output in favor of fractional exponents?

edit retag close merge delete

1

( 2021-04-01 11:10:42 +0100 )edit

As far as I can tell, Sage doesn't allow to "prettify" expression at the math level. For exemple, it insists to replace radicals in a denominator by radicals in the numerator divided by their squares in the denominator (i. e. replaces $\displaystyle\frac{1}{\sqrt{x}}$ by $\displaystyle\frac{\sqrt{x}}{x}$). The usual argument for that behaviour is that there is no algorithmic definition of a "pretty" expression...

It can even be asinine in the extreme :

sage: w0,w1,w2=(SR.wild(u) for u in range(3))
sage: (sqrt(3)*sqrt(x)).subs(sqrt(w0)*sqrt(w1)==sqrt(w0*w1))
sqrt(3)*sqrt(x)


You could probably do that by substituting regexes of the latex form, but this is probably highly non-trivial...

( 2021-04-01 15:22:32 +0100 )edit

Thanks, Emmanuel---this is what I feared. I imagine writing a fully satisfactory solution to this problem that worked on all types of expressions, even one limited to just my personal stylistic preferences, would be a daunting task indeed, and almost certainly not worth the effort when copy-pasting is always an option. Fortunately for me, @dsejas has taken the time to write up a very nice and reasonably short home-baked solution to this problem that works for the use-cases I mentioned.

( 2021-04-03 03:04:11 +0100 )edit

Sort by ยป oldest newest most voted

Hello, @perfectly_odd! I concur with @Emmanuel Charpentier in that there seems to be a direct way to "prettify". However, there are a few things that you can do in order to make your results smaller.

1. Use sympy's latex() function: You can import sympy and call its latex() function with the root_notation option set to False. Here is an example:

import sympy as sym
expr = 3/7*sqrt(2)*sqrt(pi)*(5)^(8/7) + 2
sym.latex(expr._sympy_(), root_notation=False)


This will return $2 + \frac{15 \cdot 2^{\frac{1}{2}} \cdot 5^{\frac{1}{7}} \pi^{\frac{1}{2}}}{7}$, which is not exactly what you wanted, but at least will eliminate the radicals, making your expressions shorter.

In order to use this with sageTeX, you can use the following LaTeX code right after your \begin{document}:

\begin{sagesilent}
import sympy as sym
def prettify(expr):
return sym.latex(expr._sympy_(), root_notation=False)
\end{sagesilent}


The _sympy_() method is necessary to convert Sage's objects to Sympy's syntax.

Then, you just need to use sageTeX's \sagestr{} command. For example, \sagestr(prettify(expr)) in our case. You can also this directly in your Sage/Python script.

2. Define a couple of functions that take care of this purpose: This is quite difficult (not a surprise, considering that there is no such thing in Sage by default!) However, considering that the expressions your are working with seem to be relatively simple, this is doable. I have written a quite complicated piece of software that should (in theory) work for you. You can take a look at it here. Consider that this code is not verified and it is possible that it won't work with very complicated expressions. It has been tested just with a few examples. Although I have written a quite complicated code in order to cover any reasonably complex expression, and I have tested it with some examples that are a little bit more complex than the one in your question, there is no guarantee that I will work flawlessly. However, if you feel brave enough, feel free to use it; but test it first! It is heavily commented in case you need to modify it or really want to understand it. (Unfortunately, I don't know your level of programming experience.) Perhaps the code can be improved, but unfortunately, I didn't have more free time available to expend on this matter.

In order to use this code, you can put it in a sagesilent environment in your LaTeX document, and call it with something like \sagestr{prettify(expr)}, where expr is some expression. Also,you can use it directly in your Sage/Python script.

3. You could use LaTeX tweaks: If your expressions are way too large for a LaTeX table, you can use the \small command (or some of its brothers) in order to make the expressions occupy less space (this is barely noticeable in the case of \small). This can be programmed in your Sage/Python script. I would also recommend using \small for the whole table (i.e., surround your table with \bgroup\small and \egroup.) If more space is needed, use the landscape package (or any of its brothers, like lscape.) If even more space is needed, use the longtable package (or any of its brothers, like supertabular.)

I hope this helps!

more

Just as a comment: I seem to remember something called "Abstract Syntax Tree" in programming, and something called "Expression Tree Walker" in Sage. I am not 100% sure, but it is my understanding that these are very useful in cases like this one you pose. These options work very similarly to option 2 above. However, I have two problems with this: (1) This is way beyond my current knowledge in programming (for now, at least), so I cannot help you with that. (Perhaps, even this is a nonsense idea.) (2) I believe this is overkill and extremely difficult for just simplifying expressions like the ones you need. Perhaps somebody more versed in Sage and programming can help you with this.

( 2021-04-02 02:26:38 +0100 )edit

Thanks for the amazing response, @dsejas! I fully expected to have to write something like this myself if it came down to it, and was merely hoping for a nudge in the right direction if an easier solution existed. I've done some preliminary testing of your code, and it looks like it works for the cases I need it to. It seems very "tweakable" too---I'm sure it wouldn't be too hard to modify if some corner case comes up that it doesn't handle correctly. I'll add it to my rapidly-expanding library of Sage helpers and hacks.

Thanks for the tip about SymPy's latex() function as well; as you said, it doesn't exactly support the format I want, but it's still useful to know about. And once again, thanks for spending the time to code, comment, and test the solution you posted!

( 2021-04-03 02:54:32 +0100 )edit