Julia中的抽象参数类型

Julia中的抽象参数类型,julia,Julia,在Julia中,是否可能有两个具有相同名称但被分配不同类型的结构,从而可以区分 我一直在阅读,它似乎正朝着我想要的方向发展,但我无法让它发挥作用 在分子模拟的力场中,存在描述分子扭转角的二面体参数。有不同的种类,例如,让我们把它们限制为两种:适当的和不适当的。我希望有两个结构,都称为二面体,但给定类型“适当”和“不适当”。然后我会有特定于每种类型的方法来计算由于二面体而产生的力。我认为抽象参数类型使我最接近我想要的,但我无法对它们进行排序 abstract type proper end abs

在Julia中,是否可能有两个具有相同名称但被分配不同类型的结构,从而可以区分

我一直在阅读,它似乎正朝着我想要的方向发展,但我无法让它发挥作用

在分子模拟的力场中,存在描述分子扭转角的二面体参数。有不同的种类,例如,让我们把它们限制为两种:适当的和不适当的。我希望有两个结构,都称为二面体,但给定类型“适当”和“不适当”。然后我会有特定于每种类型的方法来计算由于二面体而产生的力。我认为抽象参数类型使我最接近我想要的,但我无法对它们进行排序

abstract type proper end
abstract type improper end

struct Dihedral <: proper
    ai::Int64
    kparam::Vector{Float64}
end

struct Dihedral <: improper
    ai:Int64
    kparam::Float64
end
我的想法是,我可以添加更多类型的二面体,我所需要做的就是添加它们的方法,模拟将自动使用新的二面体方法。如果我尝试创建不同名称的结构,那么我就必须使用If语句将程序定向到正确的结构,然后再定向到正确的方法。。。这是我想要避免的,即

if dihedraltype == "proper"
    struct_proper(...)
elseif dihedraltype =="improper"
    struct_improper() 
elseif dihedraltype == "newStyle"
    struct_newStyle()
end

使用这种方法,我必须在我的代码中找到我调用二面体的所有地方,并添加新类型。。。二面体只是一个例子,有许多“现象”有不同的方法来计算现象。

如果要使用参数类型,我将使用以下方法:

abstract type DihedralType end

struct Proper <: DihedralType
    ai::Int64
    kparam::Vector{Float64}
end

struct Improper <: DihedralType
    ai::Int64
    kparam::Float64
end

struct Dihedral{T<:DihedralType}
    value::T
end

Dihedral(ai::Int64, kparam::Vector{Float64}) = Dihedral(Proper(ai, kparam))
Dihedral(ai::Int64, kparam::Float64) = Dihedral(Improper(ai, kparam))
Dihedral
类型的参数向您传递正在处理的对象类型的信息。然后,一些方法可能是通用的,并调用
二面体
,例如:

julia> ai(d::Dihedral) = d.value.ai
ai (generic function with 1 method)

julia> ai(Dihedral(1, 1.0))
1

julia> ai(Dihedral(1, [1.0, 2.0]))
1

julia> kparam(d::Dihedral) = d.value.kparam
kparam (generic function with 1 method)

julia> kparam(Dihedral(1, 1.0))
1.0

julia> kparam(Dihedral(1, [1.0, 2.0]))
2-element Array{Float64,1}:
 1.0
 2.0
有些可能是特定于类型参数的:

julia> len(d::Dihedral{Proper}) = length(kparam(d))
len (generic function with 1 method)

julia> len(Dihedral(1, [1.0, 2.0]))
2

julia> len(Dihedral(1, 1.0))
ERROR: MethodError: no method matching len(::Dihedral{Improper})
Closest candidates are:
  len(::Dihedral{Proper}) at REPL[15]:1
Stacktrace:
 [1] top-level scope at none:0
这种方法能满足您的期望吗

编辑

实际上,一个更简单的方法可能就足够了(取决于用例)。只需定义:

abstract type AbstractDihedral end

struct Proper <: AbstractDihedral
    ai::Int64
    kparam::Vector{Float64}
end

struct Improper <: AbstractDihedral
    ai::Int64
    kparam::Float64
end

在这种方法中,不需要使用参数化类型。不同之处在于,在参数类型方法中,您可以提取出与“父”结构的所有二面体相同的参数,并在“包装”结构中仅定义二面体特定的参数。在第二种方法中,您每次都要为每个结构定义所有字段。

我认为这是正确的。上周在多伦多的研讨会之后,我进入了朱莉娅,真是太遗憾了。。。也许下次吧哈哈。Fields Institute的数据科学暑期班很可能会在2019年8月19-30日举行,届时50%的材料将是Julia(目前正在获得最终批准)。使用参数化版本或更简单的方法在速度上会有差异吗?这些结构不多,但如果使用不可变结构(如本例中所示),它们将被使用,这应该与编译器能够优化这两种情况相同。但是,如果直接子类型(第二种方法-没有参数化类型)对您来说已经足够了,我建议您使用它,因为编写代码和推理要简单得多。我将采用参数化方法。我会犯更多的错误,这会让我保持谦卑。。。
julia> ai(d::Dihedral) = d.value.ai
ai (generic function with 1 method)

julia> ai(Dihedral(1, 1.0))
1

julia> ai(Dihedral(1, [1.0, 2.0]))
1

julia> kparam(d::Dihedral) = d.value.kparam
kparam (generic function with 1 method)

julia> kparam(Dihedral(1, 1.0))
1.0

julia> kparam(Dihedral(1, [1.0, 2.0]))
2-element Array{Float64,1}:
 1.0
 2.0
julia> len(d::Dihedral{Proper}) = length(kparam(d))
len (generic function with 1 method)

julia> len(Dihedral(1, [1.0, 2.0]))
2

julia> len(Dihedral(1, 1.0))
ERROR: MethodError: no method matching len(::Dihedral{Improper})
Closest candidates are:
  len(::Dihedral{Proper}) at REPL[15]:1
Stacktrace:
 [1] top-level scope at none:0
abstract type AbstractDihedral end

struct Proper <: AbstractDihedral
    ai::Int64
    kparam::Vector{Float64}
end

struct Improper <: AbstractDihedral
    ai::Int64
    kparam::Float64
end
ai(d::AbstractDihedral) = d.ai
kparam(d::AbstractDihedral) = d.kparam
len(d::Proper) = length(d.kparam) # will not work for Improper