如何在调用 Reduce 包中的集成命令时使用符号表达式

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

由于Symbolics.jl没有集成命令,我使用Reduce.jl进行集成。

在命令本身中将被积函数作为文字表达式传递时,Reduce 工作正常,如下所示

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

但是当先将被积函数放在一个变量中,然后在调用中使用这个变量时,它不起作用。我尝试使用 eval() 但 Julia 挂了。

这是一个完整的 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)))

工作正常。但是我想让被积函数成为一个变量。

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

         :(integrand * x)

这意味着它没有从外部看到变量integrand。所以我尝试在它周围添加 eval

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

但现在 Julia 被绞死了。

这两个包必须更好地协同工作,否则如果我不能在 Reduce 内部的命令中使用 Reduce 包外部的变量,这将使其使用非常受限。例如,我想使用 Symbolics 构建一些符号表达式,然后在 Reduce 包中的集成命令中使用它们。

有办法解决这个问题吗?

我知道 Symbolics 使用的 x 和 Reduce 使用的 x 是不同的。例如,在新的 Julia 会话中,我可以输入第一件事

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

它可以工作,无需先使用 @variables x。看起来 Reduce 使用它自己的符号符号而不需要先声明它们。

但是要在Reduce 之外构建一个带有x 的符号表达式,首先需要使用@variables x。这可能是问题的原因。我不知道。

所以对于初学者来说,当你写的时候

:(int(integrand, x))

这称为 quote,它生成一个名为 Expr 的 Julia 对象。它与 Symbolics 或 Reduce 无关,而是语言的内置部分(Reduce 恰好用来表示符号表达式)。

每当你在 :(...) 的括号之间写任何东西时,它就像在 "..."" 之间写字符串一样,它只是你在其中编写的代码的引用:().

这很重要,因为这意味着您刚刚构建的 Expr 或您可能传递给此 Expr 的任何程序都无法通过任何方式知道在这种特殊情况下,什么你真正想做的是 interpolate 一个叫做 integrand 的变量的值变成这个 Expr.

你总是可以用 $ 将一个 Expr 插入另一个(就像 interpolating a variable into a string),所以如果你写了

julia> using Reduce

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

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

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

这会按预期工作。 (顺便说一句,是的,@variables 纯粹是一个 Symbolics.jl 的东西;它没有更广泛的减少或 Expr 的意义。)

但是,您似乎希望能够将 Symbolics.jl 表达式插入 Expr,而不仅仅是将另一个 Expr 插入 Expr。然而,令我惊喜的是,这似乎 只是工作 使用相同的插值语法:

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)))

最后,我认为值得注意的是,据我所知,Symbolics 和 Reduce 这两个包根本就不是为相互协作而设计的。您可以实现它的事实基本上是 Reduce 选择使用 Julia 的内置 Expr 类型作为其符号表达式类型这一事实的怪癖。

在这种情况下,如果您稍微想一想,希望您会清楚为什么 eval 在这里无法帮助您;在这种情况下,如果有任何与您想要的完全相反的东西;它可以接受一个 Expr 并对其求值,这恰好让你 (因为巧合的是,求值函数是你创建符号表达式的方式)——但恰恰相反。