ste*_*bat 5 performance struct abstract-type julia union-types
我有两个名为CreationOperator和的具体类型AnnihilationOperator,我想定义一个新的具体类型,它表示一串运算符和一个与其相乘的实数系数。
我发现定义一个抽象类型很自然FermionicOperator, 和 都CreationOperator从中AnnihilationOperator继承,即
abstract type FermionicOperator end
struct CreationOperator <: FermionicOperator
...
end
struct AnnihilationOperator <: FermionicOperator
...
end
Run Code Online (Sandbox Code Playgroud)
因为我可以用 类型的签名定义许多函数,例如算术运算(我正在构建一个代数系统,所以我必须在运算符上function(op1::FermionicOperator, op2::FermionicOperator) = ...定义诸如 、 等操作*) 。
然后我会继续定义一个具体类型+OperatorString
struct OperatorString
coef::Float64
ops::Vector{FermionicOperator}
end
Run Code Online (Sandbox Code Playgroud)
然而,根据 Julia 手册,我认为这OperatorString对于性能来说并不理想,因为编译器对此一无所知FermionicOperator,因此涉及的函数OperatorString将效率低下(并且我将有许多操作运算符字符串的函数)。
我找到了以下解决方案,但是我不确定它的含义以及它是否真的有所作为。
我没有将其定义FermionicOperator为抽象类型,而是将其定义为UnionofCreationOperator和AnnihilationOperator,即
struct CreationOperator
...
end
struct AnnihilationOperator
...
end
FermionicOperator = Union{CreationOperator,AnnihilationOperator}
Run Code Online (Sandbox Code Playgroud)
这仍然允许使用 形式的函数function(op1::FermionicOperator, op2::FermionicOperator) = ...,但同时,根据我的理解,它Union{CreationOperator,AnnihilationOperator}是一种具体类型,这样OperatorString定义良好,并且编译器可以在这种情况下进行优化。
我特别怀疑,因为我还考虑使用内置Expr结构来定义我的运算符字符串(实际上它会更通用),其字段args是具有抽象类型元素的向量:与我的第一次设计尝试非常相似。然而,在实现算术运算时,Expr我感觉自己做了一些“错误”的事情,最好定义自己的类型。
如果您的ops字段是一个向量,在任何给定实例中,该向量要么是 allCreationOperators要么 all AnnihilationOperators,那么建议的解决方案是使用参数化结构。
abstract type FermionicOperator end
struct CreationOperator <: FermionicOperator
...
end
struct AnnihilationOperator <: FermionicOperator
...
end
struct OperatorString{T<:FermionicOperator}
coef::Float64
ops::Vector{T}
function OperatorString(coef::Float64, ops::Vector{T}) where {T<:FermionicOperator}
return new{T}(coef, ops)
end
end
Run Code Online (Sandbox Code Playgroud)
如果您的字段是一个向量,在任何给定实例中,该向量可能是和ops的混合 ,那么您可以使用并集。由于联合很小(2 种类型),因此您的代码将保持高性能。CreationOperatorsAnnihilationOperators
struct CreationOperator
value::Int
end
struct AnnihilationOperator
value::Int
end
const Fermionic = Union{CreationOperator, AnnihilationOperator}
struct OperatorString
coef::Float64
ops::Vector{Fermionic}
function OperatorString(coef::Float64, ops::Vector{Fermionic})
return new(coef, ops)
end
end
Run Code Online (Sandbox Code Playgroud)
尽管没有显示,但即使使用这种Union方法,您可能也想使用抽象类型——只是为了将来函数分派的简单性和灵活性。它有助于开发强大的多调度驱动逻辑。