Symbolics.jl icon indicating copy to clipboard operation
Symbolics.jl copied to clipboard

Documentation: prefered usage of `build_function`

Open scheidan opened this issue 3 years ago • 4 comments

I have a few questions around build_function. I think it is mainly an issue of documentation:

  • Is there a catch with expression=Val{true}? It seems more natural, but the tutorial and the default gives the impression that the preferred way is the use of eval.
  • The manual page does not mention that build_function returns two functions, a 'normal' and an inplace one. This is currently only demonstrated in the tutorial
  • Does build_function also return a normal' and an inplace function for non-Julia targets?
  • Can we speed up build_function if the user could specify if he/she want a 'normal' and an inplace function and not both?

Thanks!

┆Issue is synchronized with this Trello card by Unito

scheidan avatar Mar 09 '21 16:03 scheidan

Is there a catch with expression=Val{true}? It seems more natural, but the tutorial and the default gives the impression that the preferred way is the use of eval.

It uses https://github.com/SciML/RuntimeGeneratedFunctions.jl, which is kind of a hack. There really isn't a downside to it if it's being built from a symbolic engine, but it doesn't truly act like a Julia function well. You cannot stick a closure inside of one for example. So they have a few odd semantics, but build_function kind of keeps that from the user.

The manual page does not mention that build_function returns two functions, a 'normal' and an inplace one. This is currently only demonstrated in the tutorial

Oh, that should get fixed. It's there:

If the rhss is a scalar, the generated function is a function with a scalar output, otherwise if it's an AbstractArray, the output is two functions, one for out-of-place AbstractArray output and a second which is a mutating function. The outputted functions match the given argument order, i.e., f(u,p,args...) for the out-of-place and scalar functions and f!(du,u,p,args..) for the in-place version.

But that's probably not easy enough to read if you didn't see it.

Does build_function also return a normal' and an inplace function for non-Julia targets?

No, that's why it's defined in the per-target docstrings. I think it would be really hard to generally support objects being defined in other runtimes.

Can we speed up build_function if the user could specify if he/she want a 'normal' and an inplace function and not both?

Currently no. But we should work on that.

ChrisRackauckas avatar Mar 09 '21 19:03 ChrisRackauckas

Thanks Chris!

The world-age issue and RuntimeGeneratedFunctions.jl are way above my Julia skills :) So my take-away is that I'll use expression=Val{true} as long everything works.

You're right, the return value of build_function is indeed documented. When I find some time I'll try to find a way to highlight is more.

A few other small points:

  • Does it make sense to run simplify before build_function? I'm asking because the documentation states that build_function already "performs some cleaning to return an expression without extraneous pieces".
  • Documentation of the argument headerfun is missing (for the Julia target)
  • It took me a while to figure out that OOP probably means out-off-place and not object oriented programming :)

scheidan avatar Mar 10 '21 09:03 scheidan

It took me a while to figure out that OOP probably means out-off-place and not object oriented programming :)

We should expand that.

Documentation of the argument headerfun is missing (for the Julia target)

Good point.

Does it make sense to run simplify before build_function? I'm asking because the documentation states that build_function already "performs some cleaning to return an expression without extraneous pieces".

Not always. Simplify can take a non-trivial time. It cleans other things.

ChrisRackauckas avatar Mar 10 '21 12:03 ChrisRackauckas

Adding in case anyone is working on updating the documentation for build_function... It would be nice to expand the tutorial to explain what happens when the symbolic expression is a scalar. Especially since the return type is different (single Expr for a scalar, tuple of Expr for an array), the current tutorial is confusing for a user who tries to follow it but replacing to_compute = [x^2 + y, y^2 + x] with e.g. to_compute = x^2 + y!

johnomotani avatar May 06 '22 08:05 johnomotani