在MATLAB中构造邻接矩阵

在MATLAB中构造邻接矩阵,matlab,matrix,graph-theory,Matlab,Matrix,Graph Theory,考虑布置在大小为N×M的网格上的一组点。 我试图建立邻接矩阵,这样 相邻点是相连的 例如,在带有图形的3x3网格中: 1-2-3 | | | 4-5-6 | | | 7-8-9 我们应该有相应的邻接矩阵: +---+------------------------------------------------------+ | | 1 2 3 4 5 6 7 8 9 | +---+-------------------

考虑布置在大小为N×M的网格上的一组点。 我试图建立邻接矩阵,这样 相邻点是相连的

例如,在带有图形的3x3网格中:

1-2-3
| | |
4-5-6
| | |
7-8-9
我们应该有相应的邻接矩阵:

+---+------------------------------------------------------+
|   |   1     2     3     4     5     6     7     8     9  |
+---+------------------------------------------------------+
| 1 |   0     1     0     1     0     0     0     0     0  |
| 2 |   1     0     1     0     1     0     0     0     0  |
| 3 |   0     1     0     0     0     1     0     0     0  |
| 4 |   1     0     0     0     1     0     1     0     0  |
| 5 |   0     1     0     1     0     1     0     1     0  |
| 6 |   0     0     1     0     1     0     0     0     1  |
| 7 |   0     0     0     1     0     0     0     1     0  |
| 8 |   0     0     0     0     1     0     1     0     1  |
| 9 |   0     0     0     0     0     1     0     1     0  |
+---+------------------------------------------------------+
作为奖励,该解决方案应适用于4个和8个连接的相邻点,即:

   o             o  o  o
o  X  o   vs.    o  X  o
   o             o  o  o
这是我到目前为止掌握的代码:

N = 3; M = 3;
adj = zeros(N*M);

for i=1:N
    for j=1:M
        k = sub2ind([N M],i,j);
        if i>1
            ii=i-1; jj=j;
            adj(k,sub2ind([N M],ii,jj)) = 1; 
        end
        if i<N
            ii=i+1; jj=j;
            adj(k,sub2ind([N M],ii,jj)) = 1; 
        end
        if j>1
            ii=i; jj=j-1;
            adj(k,sub2ind([N M],ii,jj)) = 1; 
        end
        if j<M
            ii=i; jj=j+1;
            adj(k,sub2ind([N M],ii,jj)) = 1; 
        end
    end
end
N=3;M=3;
调整=零(N*M);
对于i=1:N
对于j=1:M
k=sub2ind([nm],i,j);
如果i>1
ii=i-1;jj=j;
形容词(k,sub2ind([nm],ii,jj))=1;
结束
如果i1
ii=i;jj=j-1;
形容词(k,sub2ind([nm],ii,jj))=1;
结束

如果图中每个节点的j,则在右侧添加一个连接,向下添加一个连接。检查你没有超出你的范围。考虑下面的函数来构造邻接矩阵。< /P>
function  adj = AdjMatrixLattice4( N, M )
    % Size of adjacency matrix
    MN = M*N;
    adj = zeros(MN,MN);

    % number nodes as such
    %  [1]---[2]-- .. --[M]
    %   |     |          |
    % [M+1]-[M+2]- .. -[2*M]
    %   :     :          :
    %   []    []   ..  [M*N]     

    for i=1:N
        for j=1:N
            A = M*(i-1)+j;          %Node # for (i,j) node
            if(j<N)                
                B = M*(i-1)+j+1;    %Node # for node to the right
                adj(A,B) = 1;
                adj(B,A) = 1;
            end
            if(i<M)
                B = M*i+j;          %Node # for node below
                adj(A,B) = 1;       
                adj(B,A) = 1;
            end            
        end
    end    
end

您当前的代码看起来并没有那么糟糕。无论如何,您需要迭代所有相邻对。如果您确实需要优化代码,我建议:

  • 在节点索引i上循环,其中
    1m
  • 对角边也有类似的规则

这将简化为单个循环(但N*M次迭代次数相同),不调用sub2ind(),循环中只有两个if语句。

如果您注意到,您正在创建的邻接矩阵有一个独特的模式。具体地说,它们是对称的,并且是对称的。您可以利用这一事实,使用函数(或者,如果您想要创建稀疏矩阵,则使用函数)轻松创建矩阵。以下是如何使用上面的示例矩阵为每种情况创建邻接矩阵:

4-连通邻居: 您将得到以下矩阵:

adj =

     0  1  0  1  0  0  0  0  0
     1  0  1  0  1  0  0  0  0
     0  1  0  0  0  1  0  0  0
     1  0  0  0  1  0  1  0  0
     0  1  0  1  0  1  0  1  0
     0  0  1  0  1  0  0  0  1
     0  0  0  1  0  0  0  1  0
     0  0  0  0  1  0  1  0  1
     0  0  0  0  0  1  0  1  0
adj =

     0  1  0  1  1  0  0  0  0
     1  0  1  1  1  1  0  0  0
     0  1  0  0  1  1  0  0  0
     1  1  0  0  1  0  1  1  0
     1  1  1  1  0  1  1  1  1
     0  1  1  0  1  0  0  1  1
     0  0  0  1  1  0  0  1  0
     0  0  0  1  1  1  1  0  1
     0  0  0  0  1  1  0  1  0

8-连接邻居: 您将得到以下矩阵:

adj =

     0  1  0  1  0  0  0  0  0
     1  0  1  0  1  0  0  0  0
     0  1  0  0  0  1  0  0  0
     1  0  0  0  1  0  1  0  0
     0  1  0  1  0  1  0  1  0
     0  0  1  0  1  0  0  0  1
     0  0  0  1  0  0  0  1  0
     0  0  0  0  1  0  1  0  1
     0  0  0  0  0  1  0  1  0
adj =

     0  1  0  1  1  0  0  0  0
     1  0  1  1  1  1  0  0  0
     0  1  0  0  1  1  0  0  0
     1  1  0  0  1  0  1  1  0
     1  1  1  1  0  1  1  1  1
     0  1  1  0  1  0  0  1  1
     0  0  0  1  1  0  0  1  0
     0  0  0  1  1  1  1  0  1
     0  0  0  0  1  1  0  1  0

为了好玩,这里有一个通过计算网格上所有点对之间的距离来构造邻接矩阵的解决方案(显然不是最有效的方法)

下面是一些代码,用于可视化邻接矩阵和连接点的图形:

%# plot adjacency matrix
subplot(121), spy(adj)

%# plot connected points on grid
[xx yy] = gplot(adj, [X Y]);
subplot(122), plot(xx, yy, 'ks-', 'MarkerFaceColor','r')
axis([0 N+1 0 M+1])
%# add labels
[X Y] = meshgrid(1:N,1:M);
X = reshape(X',[],1) + 0.1; Y = reshape(Y',[],1) + 0.1;
text(X, Y(end:-1:1), cellstr(num2str((1:N*M)')) )

我在搜索同一个问题时发现了这个问题。然而,所提供的解决方案都不适用于我,因为问题的大小需要使用稀疏矩阵类型。以下是我的解决方案,它适用于大规模实例:

function W = getAdjacencyMatrix(I)

[m, n] = size(I);

I_size = m*n;

% 1-off diagonal elements
V = repmat([ones(m-1,1); 0],n, 1);
V = V(1:end-1); % remove last zero

% n-off diagonal elements
U = ones(m*(n-1), 1);

% get the upper triangular part of the matrix
W = sparse(1:(I_size-1),    2:I_size, V, I_size, I_size)...
  + sparse(1:(I_size-m),(m+1):I_size, U, I_size, I_size);

% finally make W symmetric
W = W + W';

刚刚遇到这个问题。我有一个很好的通用m函数(link:)

它可以处理4连接电网(半径1根据L1规范),8连接电网(半径1根据L_infty规范)。
它还可以支持3D(以及任意更高的穹顶网格)。
该函数还可以连接半径=1以外的节点

以下是该功能的标志:


% Construct sparse adjacency matrix (provides ii and jj indices into the
% matrix)
%
% Usage:
%   [ii jj] = sparse_adj_matrix(sz, r, p)
%
% inputs:
%   sz - grid size (determine the number of variables n=prod(sz), and the
%        geometry/dimensionality)
%   r  - the radius around each point for which edges are formed
%   p  - in what p-norm to measure the r-ball, can be 1,2 or 'inf'
%
% outputs
%   ii, jj - linear indices into adjacency matrix (for each pair (m,n)
%   there is also the pair (n,m))
%
% How to construct the adjacency matrix?
% >> A = sparse(ii, jj, ones(1,numel(ii)), prod(sz), prod(sz));
%
%
% Example:
% >> [ii jj] = sparse_adj_matrix([10 20], 1, inf);
% construct indices for 200x200 adjacency matrix for 8-connect graph over a
% grid of 10x20 nodes.
% To visualize the graph:
% >> [r c]=ndgrid(1:10,1:20);
% >> A = sparse(ii, jj, 1, 200, 200);;
% >> gplot(A, [r(:) c(:)]);

不,这不是家庭作业。我的最终目标是绘制这些点,并将连接点之间的线绘制为图形。有趣的是,这些点不必停留在网格上..你错过了这一点,我正在寻找一个解决方案,它将适用于任何N和m(网格大小)的值。我只用3x3作为例子。我想我没有注意到你想要一个完全连通的图。所以现在需要一个函数来根据网格大小生成连接向量。实际上有两个功能,一个用于4连接方案,一个用于8连接方案。请参见上面关于4个连接的答案。8节点的场景更复杂,因为您必须决定连接是否可以相互交叉。没问题。我看到jalexiou更新了他的帖子,他发布的代码是所有当前发布的解决方案中最可读、最直观的代码(尽管它仍然可以进一步优化)。例如,Gnovice的解决方案举例说明了我为什么讨厌Matlab:p。哦,在Matlab中,它可能更有效。祝你好运Shai,假设我有一个二值图像(
100x200
),我想只获得白色像素(
前景
)的有效8邻接,即在某些情况下,
(I,j)
的一些8邻接无效,因为它们可能属于背景。我只想得到前景中的那些。我如何使用您的
sparse_adj_matrix
脚本构建这样一个邻接矩阵?下面的链接中提供了一个二进制图像/掩码图像的示例:@Tin一旦您拥有对
ii
jj
的索引,您就可以选择(使用逻辑索引)只属于白色像素的索引。
function W = getAdjacencyMatrix(I)

[m, n] = size(I);

I_size = m*n;

% 1-off diagonal elements
V = repmat([ones(m-1,1); 0],n, 1);
V = V(1:end-1); % remove last zero

% n-off diagonal elements
U = ones(m*(n-1), 1);

% get the upper triangular part of the matrix
W = sparse(1:(I_size-1),    2:I_size, V, I_size, I_size)...
  + sparse(1:(I_size-m),(m+1):I_size, U, I_size, I_size);

% finally make W symmetric
W = W + W';

% Construct sparse adjacency matrix (provides ii and jj indices into the
% matrix)
%
% Usage:
%   [ii jj] = sparse_adj_matrix(sz, r, p)
%
% inputs:
%   sz - grid size (determine the number of variables n=prod(sz), and the
%        geometry/dimensionality)
%   r  - the radius around each point for which edges are formed
%   p  - in what p-norm to measure the r-ball, can be 1,2 or 'inf'
%
% outputs
%   ii, jj - linear indices into adjacency matrix (for each pair (m,n)
%   there is also the pair (n,m))
%
% How to construct the adjacency matrix?
% >> A = sparse(ii, jj, ones(1,numel(ii)), prod(sz), prod(sz));
%
%
% Example:
% >> [ii jj] = sparse_adj_matrix([10 20], 1, inf);
% construct indices for 200x200 adjacency matrix for 8-connect graph over a
% grid of 10x20 nodes.
% To visualize the graph:
% >> [r c]=ndgrid(1:10,1:20);
% >> A = sparse(ii, jj, 1, 200, 200);;
% >> gplot(A, [r(:) c(:)]);