我有这个简单的方法来计算向量集合的加权平均值
function meanw{T <: Number}(x::AbstractArray{AbstractVector{T}, 1}, w::AbstractVector{T})
x̄ = sum(x .* w)
x̃ = map(z -> z - x̄, x)
x̄, x̃
end
但是当我尝试使用它时,调度与我的方法不匹配。
ERROR: `meanw` has no method matching meanw(::Array{Array{Float64,1},1}, ::Array{Float64,1})
我怀疑在涉及嵌套时我误解了如何使用类型限制。我应该如何重写此功能以匹配我的收藏?
P.S。
我知道矢量和数组是相同的,但差异化使得函数的使用方式更加清晰。
答案 0 :(得分:4)
因此,如果您重写代码以使用具体的类型
function meanw{T <: Number}(x::Array{Vector{T}, 1}, w::Vector{T})
x̄ = sum(x .* w)
x̃ = map(z -> z - x̄, x)
x̄, x̃
end
这也有效
function meanw{T <: Number}(x::Array{Vector{T}, 1}, w::AbstractVector{T})
x̄ = sum(x .* w)
x̃ = map(z -> z - x̄, x)
x̄, x̃
end
这不起作用
function meanw{T <: Number}(x::Array{AbstractVector{T}, 1}, w::AbstractVector{T})
x̄ = sum(x .* w)
x̃ = map(z -> z - x̄, x)
x̄, x̃
end
这又行了
function meanw{T <: Number}(x::AbstractArray{Vector{T}, 1}, w::AbstractVector{T})
x̄ = sum(x .* w)
x̃ = map(z -> z - x̄, x)
x̄, x̃
end
我们在这里遇到的问题在parametric types
下的Julia手册中有所描述最后一点非常重要:
即使Float64&lt;:Real我们也没有Point {Float64}&lt;: 点{实}。
换句话说,在类型理论的说法中,朱莉娅的类型 参数是不变的,而不是协变(甚至是 逆变)。这是出于实际原因:而任何实例 Point {Float64}在概念上可能就像Point {Real}的实例一样 好吧,这两种类型在记忆中有不同的表现形式:
这实际上有效吗
function meanw{T <: Number, V <: AbstractVector}(x::AbstractArray{V, 1}, w::AbstractVector{T})
x̄ = sum(x .* w)
x̃ = map(z -> z - x̄, x)
x̄, x̃
end
但真正的问题是你为什么要这样做? 只要输入是良好类型且函数本身是类型稳定的,Julia编译器即使没有类型注释也能够生成有效的代码。类型注释仅用于多次发送,而合同用于指定函数实际可以处理的内容,但由于广泛的类型系统,这在Julia中是非常困难的。
答案 1 :(得分:2)
根本问题是
julia> Vector{Vector} <: Vector{AbstractArray}
false
你正在传递矢量向量。我将其重写为
function meanw{T<:Number,S<:Number}(x::Vector{Array{T}}, w::Vector{S})
x̄ = sum(x .* w)
x̃ = map(z -> z - x̄, x)
x̄, x̃
end
例如,允许Float64
x
和Int
w
。或者不要限制它 - 无论如何它可能是不必要的,因为它不会使它变得更快并且只是一种防御性的编码事物。
答案 2 :(得分:1)
Julia是一种快速发展的语言,每一代人都会推出新功能,并且需要对Q&amp; As As进行审核。
重要强>
julia> VERSION
v"0.6.0-dev.2259"
Julia的一个先进功能是其调度系统。 (excellent reading about multiple dispatch)。 现在,由于this merge(2017-1-16 v0.6.0),用户可以从三角调度 (read why is it useful?)的新功能中受益。 在这里,我们需要解决为两个参数编写泛型方法的问题:
w
x
@wallnuss的答案涉及4种方法都可以。这是第一个:
function meanw{T <: Number}(x::Array{Vector{T}, 1}, w::Vector{T})
info("both are Vector for the same element-type: $T")
end
julia> meanw([[1],[2]], [1])
INFO: both are Vector for the same element-type: Int32
以上非常具体主要是因为它不包括AbstractVector
的不同子类型,例如:
julia> (typeof(spzeros(3)) |> supertype |> supertype) <: AbstractVector #=> true
所以定义了第二个:
function meanw{T <: Number}(x::Array{Vector{T}, 1}, w::AbstractVector{T})
info("an Array of Vectors and an AbstractVector sub-type both with the same element-type: $T") #
end
以上:
julia> meanw([[1.],[2]], spzeros(3))
INFO: an Array of Vectors and an AbstractVector sub-type both with the same element-type: Float64
更通用的方法:
function meanw{T <: Number}(x::AbstractArray{Vector{T}, 1}, w::AbstractVector{T})
info("an AbstractVector subtype of Vectors and an AbstractVector sub-type both with the same element-type $T")
end
即使采用最新方法,也无法完成某些方案:
julia> meanw([spzeros(3) for i=1:3], spzeros(3)) #=> Error
julia> meanw([[1],[2]],[1.]) #=> Error
因此,以上所有内容都更具体。
function meanw{T <: Number, V <: AbstractVector}(x::AbstractArray{V, 1}, w::AbstractVector{T})
info("an AbstractVector of AbstractVector sub-type with Any element and an AbstractVector sub-type of Number")
end
似乎最后一种方法涵盖了所有可能的情况,但它比可能需要的更通用。:
julia> meanw([[""],[2]],[1.]) #=> Not enough restriction for element type of first AbstractVector
INFO: an AbstractVector of AbstractVector sub-type with Any element and an AbstractVector sub-type of Number
现在有了新的三角形功能,我们可以写:
function meanw{T <: Number, V <: AbstractVector{T}}(x::AbstractArray{V, 1}, w::AbstractVector{T})
info("an AbstractVector of AbstractVector sub-type and an AbstractVector subtype both for same sub-type of Number (triangular)")
end
检查方法优先级:
julia> methods(meanw)
# 5 methods for generic function "meanw":
meanw{T<:Number}(x::Array{Array{T,1},1}, w::Array{T,1}) in Main at REPL[1]:2
meanw{T<:Number}(x::Array{Array{T,1},1}, w::AbstractArray{T,1}) in Main at REPL[22]:2
meanw{T<:Number}(x::AbstractArray{Array{T,1},1}, w::AbstractArray{T,1}) in Main at REPL[24]:2
meanw{T<:Number,V<:AbstractArray{T<:Number,1}}(x::AbstractArray{V,1}, w::AbstractArray{T,1}) in Main at REPL[41]:2
meanw{T<:Number,V<:(AbstractArray{T,1} where T)}(x::AbstractArray{V,1}, w::AbstractArray{T,1}) in Main at REPL[39]:2
最新的方法已经占据了第四位,因为它比前者更具体。
julia> meanw([spzeros(3) for i=1:3], spzeros(3))
INFO: an AbstractVector of AbstractVector sub-type and an AbstractVector subtype both for a same sub-type of Number (triangular)
但是meanw([[2],[2]],[1.])
仍然针对更通用的方法(第5节)。我们定义另一种方法:
function meanw{T <: Number, W <: Number, V <: AbstractVector{W}}(x::AbstractArray{V, 1}, w::AbstractVector{T})
info("an AbstractVector of AbstractVector sub-type and an AbstractVector sub-type both for Number (triangular)")
end
julia> meanw([[2],[2]],[1.])
INFO: an AbstractVector of AbstractVector sub-type and an AbstractVector sub-type both for Number (triangular)