如何使用Julia在矩阵中查找连接的组件

时间:2015-09-24 22:50:29

标签: python algorithm matrix graph julia

假设我有以下矩阵(在Julia语言中定义):

    mat = [1 1 0 0 0 ; 1 1 0 0 0 ; 0 0 0 0 1 ; 0 0 0 1 1]

将一组具有值'1'的邻居元素视为“组件”,如何识别该矩阵有2个组件以及哪个顶点组成每个组件?

对于上面的矩阵 mat ,我想找到以下结果:

组件1由矩阵的以下元素(行,列)组成:

    (1,1)
    (1,2)
    (2,1)
    (2,2)

组件2由以下元素组成:

    (3,5)
    (4,4)
    (4,5)

我可以使用像this这样的图形算法来识别方形矩阵中的组件。然而,这样的算法不能用于非方形矩阵,就像我在这里提出的那样。

任何想法都会受到高度赞赏。

如果你的建议涉及使用Python库+ PyCall,我是开放的。虽然我更喜欢使用纯Julia解决方案。

此致

3 个答案:

答案 0 :(得分:4)

使用Image.jl的{​​{1}}确实是解决核心问题的最简单方法。但是,您在label_components上的循环可能效率不高:1:maximum(labels),其中O(N*n)N中元素的数量,labels是最大值,因为您访问n labels次的每个元素。

只需两次访问n的每个元素,你会好得多:一次确定最大值,一次将每个非零元素分配给其正确的组:

labels

测试矩阵的输出:

using Images

function collect_groups(labels)
    groups = [Int[] for i = 1:maximum(labels)]
    for (i,l) in enumerate(labels)
        if l != 0
            push!(groups[l], i)
        end
    end
    groups
end

mat = [1 1 0 0 0 ; 1 1 0 0 0 ; 0 0 0 0 1 ; 0 0 0 1 1]

labels = label_components(mat)
groups = collect_groups(labels)

调用像2-element Array{Array{Int64,1},1}: [1,2,5,6] [16,19,20] 这样的库函数有时会很有用,但它也是一种习惯于慢速语言的习惯,值得留下。在朱莉娅,你可以编写自己的循环,它们会很快;更好的是,通常生成的算法更容易理解。 find并没有完全消失。

答案 1 :(得分:1)

答案很简单(虽然我不能提供python代码):

  1. 将所有1收集到列表中
  2. 选择在步骤1中生成的列表的任意元素,并使用任意图遍历算法遍历所有相邻的1并从步骤1中生成的列表中删除访问过的1#
  3. 重复步骤2,直到步骤1中生成的列表为空
  4. 在伪代码中(使用BFS):

    //generate a list with the position of all 1s in the matrix
    list pos
    for int x in [0 , matrix_width[
        for int y in [0 , matrix_height[
            if matrix[x][y] == 1
                add(pos , {x , y})
    
    while NOT isempty(pos)
        //traverse the graph using BFS
        list visited
        list next
    
        add(next , remove(pos , 0))
    
        while NOT isempty(next)
            pair p = remove(next , 0)
            add(visited , p)
            remove(pos , p)
    
            //p is part of the specific graph that is processed in this BFS
            //each repetition of the outer while-loop process a different graph that is part 
            //of the matrix
    
            addall(next , distinct(visited , neighbour1s(p)))
    

答案 2 :(得分:1)

刚从julia-users邮件列表中得到答案,使用Images.jl解决了这个问题,这是一个在Julia中处理图像的库。

他们开发了一个名为" label_components"识别矩阵中的连通分量。

然后我使用名为" findMat"的定制函数。获得每个组件的这种组件矩阵的索引。

答案,朱莉娅语言:

    using Images

    function findMat(mat,value)
        return(collect(zip(ind2sub(size(mat),find( x -> x == value, mat))...)));
    end

    mat = [1 1 0 0 0 ; 1 1 0 0 0 ; 0 0 0 0 1 ; 0 0 0 1 1]

    labels = label_components(mat);

    for c in 1:maximum(labels)
        comp = findMat(labels,c);
        println("Component $c is composed by the following elements (row,col)");       
        println("$comp\n"); 
    end