Generate function with keyword arguments from `Symbolics` expression

In what is now clearly a fool’s errand, I’m trying to copy and type out equations from publications, render them as LaTeX and then transform them into Julia code, with as little room for accidental errors as possible. (My modest progress towards this goal is on GitHub (Pluto.jl notebook), which also contains some “motivation” as to “why”…)

I generate Julia-functions from Symbolics.jl expressions. Using build_function, I get a function that takes an array as argument, such that I have to remember the order of inputs. On the other hand, I can get a keyword-argument-function using SymbolicUtils.jl’s utilities Func and toexpr. I have two questions:

  1. Is it a good idea? E.g., how would you “plot an expression” such as mx + b (imagine it’s much more complicated) given, say, m=2.; b = 3.; x=range(<something>)? Would you compile it to a function (I do that in my notebook)? Would you directly use substitute a bunch of times?

  2. I’m trying to have variable names that match publications, which require superscripts, etc., and render in LaTeX correctly. This can (but shouldn’t? What do you think?) be done with a dirty hack: @variables var"{x^{p}_{q}}". The problem is that this name is ugly to type ever again. One can assign (abbr = var"{x^{p}_{q}}") and continue to use an alias. However, when I generate a keyword argument function with Func and toexpr, I have to specify default values for all keyword arguments (I guess that’s not so bad?) and I have to call the keyword arguments with the “proper and non-customizable” variable names, in particular, I cannot use the abbr alias. Is there a way to customize the keyword arguments of Func? Do I have to manually change the AST output of toexpr?

Sorry if this question sounds like it should be more focused. My smaller technical problems almost certainly really stem from from a bad high-level approach to the bigger problem, which is how to work with Symbolics expressions?.

@shashi who does most of the build_function stuff is not on the Discourse very often, so I would suggest opening an issue on Github.

All this sounds fine to me. You gotta do what you gotta do.

Would you directly use substitute a bunch of times?

If you’re calling it > 100 times, you may want it to be fast, so in that case I’d use either build_function or toexpr.

As you noted the tradeoff between the two are build_function is quite rigid, and Func allows you to customize more and have keyword arguments.

As for the variable names, that’s personal taste and depends on how far you’re willing to go for presentation’s sake.

Thanks a lot for your responses!

Overall, my impression is that Pluto notebooks are now pretty close to a viable replacement for “write and publish papers” in my field. Although traditional Journals would not allow such submissions (yet?), even a supplement can go a long way. If there are people interested in seeing how far one can go with replacing papers by Pluto notebooks, I’m happy to discuss or contribute!

To try this out, I replicated parts of a published paper (I use its results in my research) as a Julia notebook. It still needs a lot more polish but using my wonky function to “substitute all the equations into each other”, I managed to reproduce the expected numeric result. I’m still planing to try reproducing some optimizations from the paper (let’s see where Julia’s SciML ecosystem takes me) and plots (should work fine).

In the paper, around 30 variables (most require superscripts to represent in LaTeX) are defined and used ion around 30 equations. The equations are mathematically trivial (arithmetic, roots, logarithms, factorials). The challenge is making sure there are no typos (even the original authors seem to have struggled with this) and that the equations in the paper are consistent with any code used for simulations and optimizations. For this, LaTeX rendering, as well as doing away with the separation of paper and simulation program, should help a lot.

While typing out the equations, I came to the conclusion that @variables var"{crazy_latex_syntax}" is too limiting and does not scale well. There are too many variables to keep track of and having an alias for each one is not the way to go. Is there some way to specify a desired LaTeX representation as a “tagged on attribute” to a Symbolics.jl variable? What would it take to make that work? (I guess the obvious solution would be “stop using superscripts”, which one might try in “ones own” papers…)

This could also be solved by customizing the behavior of Latexify.jl (such customization should become possible once Latexify.jl/Issue#123 is solved), which I’ve also asked about. However, I think such LaTeX representations are really a part of the variable definition and specified within Symbolics.jl. I imagine something like a special type acting like Num, except when rendering as Latex (and perhaps some safety checks). Maybe one could write something like

# Not real Julia code! Just wishful thinking
@latex_variables x_mu1_plus => L"x_{\mu_{1}}^{+}", <etc...>

Unfortunately, I don’t know how to make a new type X that behaves like an existing type Y in all circumstances except Z. Julia doesn’t allow deriving from concrete types, has no (and should’t have) universal default conversions…