我有两种具体的类型,分别称为CreationOperator
和AnnihilationOperator
,我想定义一个新的具体类型,该类型代表一串运算符和一个将其相乘的实系数。
我很自然地定义了一个抽象类型FermionicOperator
,CreationOperator
和AnnihilationOperator
都从中继承,即
abstract type FermionicOperator end
struct CreationOperator <: FermionicOperator
...
end
struct AnnihilationOperator <: FermionicOperator
...
end
因为我可以定义许多类型为function(op1::FermionicOperator, op2::FermionicOperator) = ...
的签名的函数,例如算术运算(我正在构建代数系统,所以我必须定义诸如*
,{{1} }等)。
然后我继续定义一个具体的类型+
OperatorString
但是,根据Julia手册,我认为struct OperatorString
coef::Float64
ops::Vector{FermionicOperator}
end
对于性能不是理想的,因为编译器对OperatorString
一无所知,因此涉及FermionicOperator
的函数将效率低下(并且我将有许多函数可操作运算符的字符串)。
我找到了以下解决方案,但是我不确定其含义以及它是否真的有所帮助。
我没有将OperatorString
定义为抽象类型,而是将其定义为FermionicOperator
和Union
的{{1}},即
CreationOperator
这仍然允许使用AnnihilationOperator
形式的函数,但是据我了解,同时struct CreationOperator
...
end
struct AnnihilationOperator
...
end
FermionicOperator = Union{CreationOperator,AnnihilationOperator}
是一种具体类型,因此function(op1::FermionicOperator, op2::FermionicOperator) = ...
的定义很明确,在这种情况下,编译器可以优化事情。
我尤其感到怀疑,因为我也考虑过使用内置的Union{CreationOperator,AnnihilationOperator}
结构来定义我的运算符字符串(实际上会更通用),其字段OperatorString
是一个向量抽象类型的元素:非常类似于我的第一次设计尝试。但是,在Expr
上执行算术运算时,我感到自己做错了事,最好定义自己的类型。
答案 0 :(得分:0)
如果您的ops
字段是一个向量,在任何给定实例中都是CreationOperators
或全部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
如果您的ops
字段是一个矢量,在任何给定的情况下,它可能是CreationOperators
和AnnihilationOperators
的混合,那么您可以使用联合。因为联合很小(两种类型),所以您的代码将保持高性能。
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
尽管未显示,但即使使用Union
方法,您也可能希望使用抽象类型-只是为了将来函数分配中的简化和灵活性。这对开发鲁棒的多调度驱动逻辑很有帮助。