【问题标题】:Julia: Making a type for a specific size of vectorJulia:为特定大小的向量制作类型
【发布时间】:2018-07-06 21:49:02
【问题描述】:

我正在尝试在 Julia 中为具有三个元素的向量定义一个类型(结构?)。我认为我找到的最接近的东西 Optimally passing dimensions of fixed size array in juliaDeclare the size of an array attribute in a type definition,但是这些都是 pre-0.6,因为不可变不再是一个东西。而且,这似乎是错误的。

用例是我知道我的函数将采用并希望拥有的向量的大小

function myFunc(v::threeVec,u::threeVec)
    Do stuff to u and v
end

进一步搜索引导我构造函数。 https://docs.julialang.org/en/stable/manual/constructors/ 特别是我看到了这个例子

struct OrderedPair
           x::Real
           y::Real
           OrderedPair(x,y) = x > y ? error("out of order") : new(x,y)
       end

但是,这是一个单独的对象,即便如此,我也不确定如何将类似的东西传递给函数。我考虑改用三元组,因为它们的类型为 Tuple(Int,Int,Int) 但是我将对 u 和 v 进行向量/矩阵运算,所以我不必转换它们。

我可以在函数内部检查向量长度,但我在提示中读到,由于调度程序,它更喜欢为此使用类型。对于这个特定的功能,在这种情况下这是一种合理的做法,但在其他用例中,这可能不是一个好主意,所以我现在想以“正确的方式”来做。

【问题讨论】:

  • 我建议您查看github.com/JuliaArrays/StaticArrays.jl,如果它适合您的需求。
  • 这绝对有用,但我希望在不对绑定进行任何特殊声明的情况下传递“正常”向量。
  • StaticArrays.jl 绝对是要走的路。您可以为长度为 3 的静态数组设置类型别名,如您的示例所示,将其命名为 ThreeVec。你可以自己实现一个类型,但鉴于那里有许多数组包,这似乎没有必要。
  • 如果有人可以做一个简单的工作示例,我很乐意将其作为答案,但是我自己在 StaticArrays 方面的工作并不出色。
  • 您能解释一下您对 StaticArrays 的缺失或不便之处。我发现它是一个很棒的包,所以我很好奇你不喜欢它的什么。

标签: vector types julia


【解决方案1】:

有很多方法可以处理这种情况;我将根据您提供的想法在下面概述其中的一些。

选项 1:静态数组

StaticArrays.jl 包提供对固定长度数组的支持。

using StaticArrays
const ThreeVec{T} = SVector{3,T}

function myFunc(u::ThreeVec, v::ThreeVec)
    u .+ v  # example functionality
end

只有当两个参数都是长度为 3 的 SVectors 时,此实现才允许调用 myFunc

julia> myFunc(SVector(1, 2, 3), SVector(4, 5, 6))
3-element SArray{Tuple{3},Int64,1,3}:
 5
 7
 9

julia> myFunc(SVector(1, 2, 3), SVector(4, 5))
ERROR: MethodError: no method matching myFunc(::SArray{Tuple{3},Int64,1,3}, ::SArray{Tuple{2},Int64,1,2})
Closest candidates are:
  myFunc(::SArray{Tuple{3},T,1,3} where T, ::SArray{Tuple{3},T,1,3} where T) at REPL[13]:2

也可以使用内部构造函数定义自定义类型以断言长度正确。但是,除了潜在的低效率之外,这还需要您重载各种方法来支持您的自定义类型,而 StaticArrays 已经处理了这些类型。

选项 2:元组

根据您计划执行的向量/矩阵运算,元组可能已经通过广播本身支持该功能。例如,虽然不能添加元组,但可以在其元素上广播添加。

julia> u = (1, 2, 3);
       v = (4, 5, 6);

julia> u + v  # not allowed
ERROR: MethodError: no method matching +(::Tuple{Int64,Int64,Int64}, ::Tuple{Int64,Int64,Int64})
Closest candidates are:
  +(::Any, ::Any, ::Any, ::Any...) at operators.jl:502
Stacktrace:
 [1] top-level scope at none:0

julia> u .+ v  # element-wise broadcasting
(5, 7, 9)

选项 3:运行时错误

如果您想对内置的Vector 类型进行操作,只要输入无效就可以简单地抛出错误,将错误处理从编译转移到运行时。

function myFunc(u::Vector, v::Vector)
    length(u) == 3 || throw(ArgumentError("Invalid length of (u = $u), should be 3"))
    length(v) == 3 || throw(ArgumentError("Invalid length of (v = $v), should be 3"))
    u .+ v  # example functionality
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-11
    相关资源
    最近更新 更多