如何将 Reduce 输出转换为 Julia 符号表达式?
how to convert Reduce output to Julia symbolic expression?
在 Julia 中,我使用 Reduce 包进行集成,因为 Julia Symbolics.jl 中没有集成命令。
但我不知道如何将输出(反导数)转换为 Julia 符号表达式,因此我可以在 Julia 符号中使用它,而不是使用 Reduce 包。
这是我试过的
_
_ _ _(_)_ | 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 Symbolics
julia> using Reduce
julia> @variables x
1-element Vector{Num}:
x
#use Reduce to do the integration
julia> output = :(int(sin(x),x)) |> rcall
:(-(cos(x)))
julia> typeof(output)
Expr
现在,我想使用 Julia Symbolics 将输出 -cos(x)
用作符号表达式。如何转换?
现在它按原样给出错误
julia> Symbolics.simplify(output^2)
ERROR: MethodError: no method matching ^(::Expr, ::Int64)
Closest candidates are:
^(::Union{AbstractChar, AbstractString}, ::Integer) at G:\nabbasi\data\CDROM\JULIA_language\julia-1.7.1-win64\julia-1.7.1\share\julia\base\strings\basic.jl:721
^(::LinearAlgebra.Diagonal, ::Integer) at G:\nabbasi\data\CDROM\JULIA_language\julia-1.7.1-win64\julia-1.7.1\share\julia\stdlib\v1.7\LinearAlgebra\src\diagonal.jl:196
^(::LinearAlgebra.Diagonal, ::Real) at G:\nabbasi\data\CDROM\JULIA_language\julia-1.7.1-win64\julia-1.7.1\share\julia\stdlib\v1.7\LinearAlgebra\src\diagonal.jl:195
...
Stacktrace:
[1] literal_pow(f::typeof(^), x::Expr, #unused#::Val{2})
@ Base .\intfuncs.jl:325
[2] top-level scope
@ REPL[9]:1
这是相同的输出,但现在是 Julia Symbolics 表达式:
julia> f=-cos(x)
-cos(x)
julia> typeof(f)
Num
julia> Symbolics.simplify( f^2)
cos(x)^2
如何将 Reduce 表达式的输出转换为 Julia Symbolics 表达式,以便进一步处理?
可以将 Reduce 输出转换为字符串
julia> g=string(output)
"-(cos(x))"
但现在不知道如何将上面的字符串转换为Symbolics 表达式。 parse
不起作用。可能有不同的命令?
参考资料
所以看起来这两个包(Reduce 和 Symbolics)在它们的符号表达式中使用了相当不同的格式。 Reduce 使用 Julia 的原生 Expr
类型,与用于表示 Julia 代码本身的类型相同,而 Symbolics 使用一种方法,在一个或多个指定为 @variables
的特殊变量上调用函数将 return 记录对这些变量执行的操作的对象:
julia> using Reduce, Symbolics
julia> a = :(-(cos(x)))
:(-(cos(x)))
julia> @variables x;
julia> b = -(cos(x))
-cos(x)
julia> typeof(a)
Expr
julia> typeof(b)
Num
要查看和比较这两个不同对象 a
和 b
中的实际内容,我们可以使用 Julia 非常有用的 dump
函数:
julia> dump(a)
Expr
head: Symbol call
args: Array{Any}((2,))
1: Symbol -
2: Expr
head: Symbol call
args: Array{Any}((2,))
1: Symbol cos
2: Symbol x
julia> dump(b)
Num
val: SymbolicUtils.Mul{Real, Int64, Dict{Any, Number}, Nothing}
coeff: Int64 -1
dict: Dict{Any, Number}
slots: Array{UInt8}((16,)) UInt8[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]
keys: Array{Any}((16,))
1: #undef
2: #undef
3: #undef
4: #undef
5: #undef
...
12: #undef
13: SymbolicUtils.Term{Real, Nothing}
f: cos (function of type typeof(cos))
arguments: Array{SymbolicUtils.Sym{Real, Base.ImmutableDict{DataType, Any}}}((1,))
1: SymbolicUtils.Sym{Real, Base.ImmutableDict{DataType, Any}}
name: Symbol x
metadata: Base.ImmutableDict{DataType, Any}
parent: Base.ImmutableDict{DataType, Any}
key: Symbolics.VariableSource <: Any
value: Tuple{Symbol, Symbol}
metadata: Nothing nothing
hash: Base.RefValue{UInt64}
x: UInt64 0xd47301bdec8cde1c
14: #undef
15: #undef
16: #undef
vals: Array{Number}((16,)) Number[#undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, 1, #undef, #undef, #undef]
ndel: Int64 0
count: Int64 1
age: UInt64 0x0000000000000001
idxfloor: Int64 13
maxprobe: Int64 0
sorted_args_cache: Base.RefValue{Any}
x: Array{Any}((2,))
1: Int64 -1
2: SymbolicUtils.Term{Real, Nothing}
f: cos (function of type typeof(cos))
arguments: Array{SymbolicUtils.Sym{Real, Base.ImmutableDict{DataType, Any}}}((1,))
1: SymbolicUtils.Sym{Real, Base.ImmutableDict{DataType, Any}}
name: Symbol x
metadata: Base.ImmutableDict{DataType, Any}
parent: Base.ImmutableDict{DataType, Any}
key: Symbolics.VariableSource <: Any
value: Tuple{Symbol, Symbol}
metadata: Nothing nothing
hash: Base.RefValue{UInt64}
x: UInt64 0xd47301bdec8cde1c
hash: Base.RefValue{UInt64}
x: UInt64 0x0000000000000000
metadata: Nothing nothing
而且确实很不一样
但这并不是说您不能同时使用这两个包。由于 Expr
是用于将 Julia 代码表示为数据的类型,因此您需要做的就是 评估 Expr
以获得与您拥有的结果相同的结果调用其中的函数(不过,换一种方式是另一回事!)。所以我们可以这样写:
julia> output = :(int(sin(x),x)) |> rcall
:(-(cos(x)))
julia> output = eval(output)
-cos(x)
julia> Symbolics.simplify(output^2)
cos(x)^2
或者,您可以将 ^2
添加到 output
,同时通过使用 Julia 的多种操作 Expr
的方法之一将其保持在 Expr
形式,并且仅稍后 eval
当你需要将它传递给 Symbolics
:
julia> output = :(int(sin(x),x)) |> rcall
:(-(cos(x)))
julia> output_squared = :($output^2) # interpolate one Expr into another
:((-(cos(x))) ^ 2)
julia> Symbolics.simplify(eval(output_squared))
cos(x)^2
可能还有更多我不知道的高效方法,因为我没有广泛使用这两个包,并且使用 eval
可以说是有点 hack。但是,如果 Reduce 表达式中的函数定义为 Symbolics 知道的 Julia 函数(并且只要您在正确的范围内评估它们),这应该可以正常工作。
在 Julia 中,我使用 Reduce 包进行集成,因为 Julia Symbolics.jl 中没有集成命令。
但我不知道如何将输出(反导数)转换为 Julia 符号表达式,因此我可以在 Julia 符号中使用它,而不是使用 Reduce 包。
这是我试过的
_
_ _ _(_)_ | 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 Symbolics
julia> using Reduce
julia> @variables x
1-element Vector{Num}:
x
#use Reduce to do the integration
julia> output = :(int(sin(x),x)) |> rcall
:(-(cos(x)))
julia> typeof(output)
Expr
现在,我想使用 Julia Symbolics 将输出 -cos(x)
用作符号表达式。如何转换?
现在它按原样给出错误
julia> Symbolics.simplify(output^2)
ERROR: MethodError: no method matching ^(::Expr, ::Int64)
Closest candidates are:
^(::Union{AbstractChar, AbstractString}, ::Integer) at G:\nabbasi\data\CDROM\JULIA_language\julia-1.7.1-win64\julia-1.7.1\share\julia\base\strings\basic.jl:721
^(::LinearAlgebra.Diagonal, ::Integer) at G:\nabbasi\data\CDROM\JULIA_language\julia-1.7.1-win64\julia-1.7.1\share\julia\stdlib\v1.7\LinearAlgebra\src\diagonal.jl:196
^(::LinearAlgebra.Diagonal, ::Real) at G:\nabbasi\data\CDROM\JULIA_language\julia-1.7.1-win64\julia-1.7.1\share\julia\stdlib\v1.7\LinearAlgebra\src\diagonal.jl:195
...
Stacktrace:
[1] literal_pow(f::typeof(^), x::Expr, #unused#::Val{2})
@ Base .\intfuncs.jl:325
[2] top-level scope
@ REPL[9]:1
这是相同的输出,但现在是 Julia Symbolics 表达式:
julia> f=-cos(x)
-cos(x)
julia> typeof(f)
Num
julia> Symbolics.simplify( f^2)
cos(x)^2
如何将 Reduce 表达式的输出转换为 Julia Symbolics 表达式,以便进一步处理?
可以将 Reduce 输出转换为字符串
julia> g=string(output)
"-(cos(x))"
但现在不知道如何将上面的字符串转换为Symbolics 表达式。 parse
不起作用。可能有不同的命令?
参考资料
所以看起来这两个包(Reduce 和 Symbolics)在它们的符号表达式中使用了相当不同的格式。 Reduce 使用 Julia 的原生 Expr
类型,与用于表示 Julia 代码本身的类型相同,而 Symbolics 使用一种方法,在一个或多个指定为 @variables
的特殊变量上调用函数将 return 记录对这些变量执行的操作的对象:
julia> using Reduce, Symbolics
julia> a = :(-(cos(x)))
:(-(cos(x)))
julia> @variables x;
julia> b = -(cos(x))
-cos(x)
julia> typeof(a)
Expr
julia> typeof(b)
Num
要查看和比较这两个不同对象 a
和 b
中的实际内容,我们可以使用 Julia 非常有用的 dump
函数:
julia> dump(a)
Expr
head: Symbol call
args: Array{Any}((2,))
1: Symbol -
2: Expr
head: Symbol call
args: Array{Any}((2,))
1: Symbol cos
2: Symbol x
julia> dump(b)
Num
val: SymbolicUtils.Mul{Real, Int64, Dict{Any, Number}, Nothing}
coeff: Int64 -1
dict: Dict{Any, Number}
slots: Array{UInt8}((16,)) UInt8[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]
keys: Array{Any}((16,))
1: #undef
2: #undef
3: #undef
4: #undef
5: #undef
...
12: #undef
13: SymbolicUtils.Term{Real, Nothing}
f: cos (function of type typeof(cos))
arguments: Array{SymbolicUtils.Sym{Real, Base.ImmutableDict{DataType, Any}}}((1,))
1: SymbolicUtils.Sym{Real, Base.ImmutableDict{DataType, Any}}
name: Symbol x
metadata: Base.ImmutableDict{DataType, Any}
parent: Base.ImmutableDict{DataType, Any}
key: Symbolics.VariableSource <: Any
value: Tuple{Symbol, Symbol}
metadata: Nothing nothing
hash: Base.RefValue{UInt64}
x: UInt64 0xd47301bdec8cde1c
14: #undef
15: #undef
16: #undef
vals: Array{Number}((16,)) Number[#undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, 1, #undef, #undef, #undef]
ndel: Int64 0
count: Int64 1
age: UInt64 0x0000000000000001
idxfloor: Int64 13
maxprobe: Int64 0
sorted_args_cache: Base.RefValue{Any}
x: Array{Any}((2,))
1: Int64 -1
2: SymbolicUtils.Term{Real, Nothing}
f: cos (function of type typeof(cos))
arguments: Array{SymbolicUtils.Sym{Real, Base.ImmutableDict{DataType, Any}}}((1,))
1: SymbolicUtils.Sym{Real, Base.ImmutableDict{DataType, Any}}
name: Symbol x
metadata: Base.ImmutableDict{DataType, Any}
parent: Base.ImmutableDict{DataType, Any}
key: Symbolics.VariableSource <: Any
value: Tuple{Symbol, Symbol}
metadata: Nothing nothing
hash: Base.RefValue{UInt64}
x: UInt64 0xd47301bdec8cde1c
hash: Base.RefValue{UInt64}
x: UInt64 0x0000000000000000
metadata: Nothing nothing
而且确实很不一样
但这并不是说您不能同时使用这两个包。由于 Expr
是用于将 Julia 代码表示为数据的类型,因此您需要做的就是 评估 Expr
以获得与您拥有的结果相同的结果调用其中的函数(不过,换一种方式是另一回事!)。所以我们可以这样写:
julia> output = :(int(sin(x),x)) |> rcall
:(-(cos(x)))
julia> output = eval(output)
-cos(x)
julia> Symbolics.simplify(output^2)
cos(x)^2
或者,您可以将 ^2
添加到 output
,同时通过使用 Julia 的多种操作 Expr
的方法之一将其保持在 Expr
形式,并且仅稍后 eval
当你需要将它传递给 Symbolics
:
julia> output = :(int(sin(x),x)) |> rcall
:(-(cos(x)))
julia> output_squared = :($output^2) # interpolate one Expr into another
:((-(cos(x))) ^ 2)
julia> Symbolics.simplify(eval(output_squared))
cos(x)^2
可能还有更多我不知道的高效方法,因为我没有广泛使用这两个包,并且使用 eval
可以说是有点 hack。但是,如果 Reduce 表达式中的函数定义为 Symbolics 知道的 Julia 函数(并且只要您在正确的范围内评估它们),这应该可以正常工作。