How to use Symbolics expression in a call to the integrate command in Reduce package

Viewed 158

Since Symbolics.jl does not have integrate command, I am using Reduce.jl to do the integration.

Reduce works ok when passing the integrand as literal expression in the command itself as follows

:(int(sin(x),x)) |> rcall

But when putting the integrand in a variable first, and then using this variable inside the call, it does not work. I tried using eval() but Julia hanged.

Here is a complete MWE

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.7.1 (2021-12-22)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> using Reduce

julia> :(int( sin(x),x)) |> rcall
:(-(cos(x)))

Works fine. But I wanted to make the integrand a variable.

julia>  using Symbolics
julia> @variables x
julia> integrand = sin(x)
julia> :(int( integrand ,x)) |> rcall

         :(integrand * x)

Which means it did not see the variable integrand from outside. So I tried adding eval around it

julia> :(int( eval(integrand) ,x)) |> rcall

But now Julia hanged.

These two packages have to work together better otherwise If I can't use variables from outside Reduce package in the commands inside Reduce, this will make it very limited to use. For example, I wanted to build some symbolic expressions using Symbolics and then use them in integrate command in Reduce package.

Is there a way around this?

I do know that the x used by Symbolics and the x used by Reduce are different. For example, from fresh Julia session, I can type first thing

:(int(sin(x),x)) |> rcall

And it works, without having to use @variables x first. It looks like Reduce uses it own symbolic symbols without the need to declare them first.

But to build a symbolic expression with x outside Reduce, one needs to first use @variables x. This could be the cause the problem. I do not know.

1 Answers

So for starters when you write

:(int(integrand, x))

this is called a quote, which produces a Julia object called an Expr. It's nothing to do with either Symbolics or Reduce, but rather a built-in part of the language (which Reduce just happens to use to represent symbolic expressions).

Whenever you write anything between the parens of :(...), it's much like writing as string between the "s of "..." which is just a quote of the code you wrote inside the :().

This is important because it means that neither the Expr your have just constructed, nor any program you may pass this Expr to have any way of knowing that, in this particular case, what you really wanted to do was to interpolate the value of a variable called integrand into this Expr.

You can always interpolate one Expr into another with $ (just like interpolating a variable into a string), so if you had written

julia> using Reduce

julia> integrand = :(sin(x))
:(sin(x))

julia> :(int( $integrand, x))
:(int(sin(x), x))

julia> :(int( $integrand, x)) |> rcall
:(-(cos(x)))

This would have worked as desired. (And as an aside, yes, @variables is purely a Symbolics.jl thing; it has no meaning to Reduce or to Exprs more broadly.)

However, it looks like you want to be able to interpolate a Symbolics.jl expression into an Expr, not just another Expr into an Expr. To my pleasant surprise however, this appears to just work with the same interpolation syntax:

julia> using Symbolics

julia> @variables x;

julia> integrand = sin(x)
sin(x)

julia> :(int( $integrand, x))
:(int(sin(x), x))

julia> using Reduce

julia> :(int( $integrand, x)) |> rcall
:(-(cos(x)))

Finally, I think it is worth noting that, as far as I know, neither of these packages Symbolics and Reduce were designed to work with each other at all. The fact that you can make it happen is basically a quirk of the fact that Reduce chose to use Julia's built-in Expr type as its symbolic expression type.

In this context, if you think about it for a minute, hopefully it will be clear why eval cannot help you here; if anything that's the exact opposite of what you want in this case; it can take an Expr and evaluate it, which, happens to let you turn an Expr into a symbolics expression (because evaluating functions is, coincidentally, how you create symbolics expressions) -- but very much not the reverse.

Related