【问题标题】:Julia sparse matrix with random 1's具有随机 1 的 Julia 稀疏矩阵
【发布时间】:2018-01-13 11:43:19
【问题描述】:

所以我在 julia 中有一个大小为 N,我需要一个 NxN 稀疏矩阵,其中包含 N 个,在随机位置。解决此问题的最佳方法是什么?

起初我考虑随机生成索引,然后在稀疏矩阵中将这些数字设置为 1,但我最近发现了 sprand 函数,但是我不明白如何正确使用它们或将它们应用于我的问题。我在有限的理解下尝试使用它,它不断生成错误消息。当然,我们总是非常感谢您的帮助 :)

【问题讨论】:

  • sprand.......
  • sparse(rand(1:N, N), rand(1:N, N), ones(N), N, N) 会做到的
  • 这并不总是有效,因为您可以让一些 (i,j) 重复多次,从而得到一个非零元素少于预期的矩阵。
  • 是的。添加了一个更复杂但解决问题的答案。

标签: random julia sparse-matrix


【解决方案1】:

受上面@DanGetz 评论的启发,以下解决方案是使用randperm 的单行函数。我删除了原始答案,因为它不是很有帮助。

sparseN(N) = sparse(randperm(N), randperm(N), ones(N), N, N)

这也非常快:

@time sparseN(10_000);
  0.000558 seconds (30 allocations: 782.563 KiB)

【讨论】:

  • 这是否保证不会重复使用相同的 i,j 元组?
  • 是的,它永远不会重复任何索引,因为 randperm 置换 1:N 唯一值。
【解决方案2】:

维度(N 行)x(M 列)的稀疏矩阵最多具有 NxM 个分量,可以使用 K=[0,N*M) 整数集进行索引。对于 K 中的任何 k,您可以检索元素索引 (i,j),这要归功于欧几里德除法 k = i + j*N(此处为列主要布局)。

要随机采样 K 的 n 个元素(不重复),可以使用 Knuth 算法“算法 S(选择采样技术)”3.4.2,在其书 Vol2., seminumerical-Algorithms

在朱莉娅:

function random_select(n::Int64,K::Int64) 
    @assert 0<=n<=K

    sample=Vector{Int64}(n)
    t=Int64(0)
    m=Int64(0)

    while m<n
        if (K-t)*rand()>=n-m
            t+=1
        else
            m+=1
            sample[m]=t
            t+=1
        end
    end
    sample
end

下一部分简单地检索 I,J 索引以从其坐标形式创建稀疏矩阵:

function create_sparseMatrix(n::Int64,N::Int64,M::Int64)
    @assert (0<=N)&&(0<=M)
    @assert 0<=n<=N*M

    nonZero = random_select(n,N*M)

    # column major: k=i+j*N
    I = map(k->mod(k,N),nonZero)
    J = map(k->div(k,N),nonZero)

    sparse(I+1,J+1,ones(n),N,M)
end

使用示例:一个 4x5 稀疏矩阵,在随机位置有 3 个非零 (=1.0):

julia> create_sparseMatrix(3,4,5)
4×5 SparseMatrixCSC{Float64,Int64} with 3 stored entries:
  [4, 1]  =  1.0
  [3, 2]  =  1.0
  [3, 3]  =  1.0

边界案例测试:

julia> create_sparseMatrix(0,4,5)
4×5 SparseMatrixCSC{Float64,Int64} with 0 stored entries

julia> create_sparseMatrix(4*5,4,5)
4×5 SparseMatrixCSC{Float64,Int64} with 20 stored entries:
  [1, 1]  =  1.0
  [2, 1]  =  1.0
  [3, 1]  =  1.0
  [4, 1]  =  1.0
  ⋮
  [4, 4]  =  1.0
  [1, 5]  =  1.0
  [2, 5]  =  1.0
  [3, 5]  =  1.0
  [4, 5]  =  1.0

【讨论】:

    【解决方案3】:

    坚持单线解决方案:

    using StatsBase
    sparseones(N,M,K) = sparse(
      (x->(first.(x).+1,last.(x).+1))(divrem.(sample(0:N*M-1,K,replace=false),M))...,
      ones(K),N,M
    )
    

    给予:

    julia> sparseones(3,4,5)
    3×4 SparseMatrixCSC{Float64,Int64} with 5 stored entries:
      [1, 1]  =  1.0
      [2, 1]  =  1.0
      [3, 3]  =  1.0
      [2, 4]  =  1.0
      [3, 4]  =  1.0
    

    此方法与之前的答案基本相同,优点是重复使用现有的sample 并且更短。在更大的矩阵上它甚至更快。

    【讨论】:

      猜你喜欢
      • 2015-08-24
      • 1970-01-01
      • 2019-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多