Julia 中具有抽象类型字段或具体类型 Union 的结构?

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为抽象类型,而是将其定义为UnionofCreationOperatorAnnihilationOperator,即

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我感觉自己做了一些“错误”的事情,最好定义自己的类型。

Jef*_*off 4

如果您的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方法,您可能也想使用抽象类型——只是为了将来函数分派的简单性和灵活性。它有助于开发强大的多调度驱动逻辑。