【问题标题】:Adjacency matrix from edge list (preferrably in Matlab)来自边缘列表的邻接矩阵(最好在 Matlab 中)
【发布时间】:2012-03-22 16:34:17
【问题描述】:

我有一个三元组列表(顶点 1、顶点 2、权重),它们表示加权有向图的边缘。由于原型实现是在 Matlab 中进行的,因此这些被导入为 Nx3 矩阵,其中 N 是边数。所以这个的幼稚实现是

id1 = L(:,1);
id2 = L(:,2);
weight = L(:,3);
m = max(max(id1, id2)) % to find the necessary size
V = zeros(m,m)
for i=1:m
   V(id1(i),id2(i)) = weight(i)
end

tribbles 的问题是“id1”和“id2”是不连续的;它们是代码。这给了我三个问题。 (1) 具有太多“幻像”、虚假顶点的巨大矩阵,这会扭曲与该矩阵一起使用的算法的结果;(2) 我需要恢复所述算法结果中的代码(可以这么说如果 id 代码连续 1:m),则微不足道。

Matlab 中的答案是可取的,但我认为我可以从其他语言的答案中破解(只要它们不是“R 具有执行此操作的库”之类的预打包解决方案)。

我是 StackOverflow 的新手,我希望尽快为社区做出有意义的贡献。暂时先谢谢了!

编辑:如果我们在多个顶点的原点处没有顶点,这将是一个解决方案。 (这意味着边源列表和身份列表之间存在 1:1 匹配)

for i=1:n
   for j=1:n
   if id1(i) >0 & i2(j) > 0
       V(i,j) = weight(i);
   end
   end
   end

【问题讨论】:

    标签: matlab adjacency-matrix


    【解决方案1】:

    可以使用sparse函数:

    sparse(id1,id2,weight,m,m)
    

    【讨论】:

    • 这也是一个很好的建议。问题在于,要使此命令正常工作,您需要在每条边的起点和终点顶点中具有相同数量的唯一 ID。否则会出现一致性问题。 “稀疏”本身已经是部分胜利,但给我一个非方阵!我想我需要为所有唯一 ID 创建零加权边缘,才能使这个想法起作用。如果这行得通,我会,嗯,距离解决这是必要步骤的根本问题还有五站之遥。谢谢!
    【解决方案2】:

    如果您的问题是节点 ID 号不连续,为什么不将它们重新映射到连续整数上呢?您需要做的就是创建一个包含所有唯一节点 ID 及其与新 ID 对应关系的字典。

    这与要求您使用命名节点(AustraliaBritainCanadaDenmark...)的情况确实没有什么不同——您首先将它们映射到连续整数.

    【讨论】:

      【解决方案3】:

      您可以使用GRP2IDX 函数将您的id 代码转换为连续的数字,id 可以是数字也可以不是数字,没关系。只需保留映射信息即可。

      [idx1, gname1, gmap1] = grp2idx(id1);
      [idx2, gname2, gmap2] = grp2idx(id2);
      

      您可以使用gmap1(idx1) 恢复原始ID。

      如果您的id1id2 来自同一个集合,您可以将grp2idx 应用于他们的联合:

      [idx, gname,gmap] = grp2idx([id1; id2]);
      idx1 = idx(1:numel(id1));
      idx2 = idx(numel(id1)+1:end);
      

      有关重新排序,请参阅最近的问题 - how to assign a set of coordinates in Matlab?

      您可以使用 ACCUMARRAY 或 SUB2IND 来解决这个问题。

      V = accumarray([idx1 idx2], weight);
      

      V = zeros(max(idx1),max(idx2)); %# or V = zeros(max(idx));
      V(sub2ind(size(V),idx1,idx2)) = weight;
      

      确认您是否有id1id2 的非唯一组合。你必须照顾好它。

      【讨论】:

        【解决方案4】:

        这是另一个解决方案:

        首先将所有顶点 id 放在一起,因为图中可能存在下沉顶点:

        v_id_from = edge_list(:,1);
        v_id_to = edge_list(:,2);
        v_id_all = [v_id_from; v_id_to];
        

        然后找到唯一的顶点id:

        v_id_unique = unique(v_id_all);
        

        现在您可以使用 ismember 函数来获取顶点 id 与其连续索引映射之间的映射:

        [~,from] = ismember(v_id_from, v_id_unique);
        [~,to] = ismember(v_id_to, v_id_unique);
        

        现在您可以使用 sub2ind 来填充邻接矩阵:

        adjacency_matrix = zeros(length(from), length(to));
        linear_ind = sub2ind(size(adjacency_matrix), from, to);
        adjacency_matrix(linear_ind) = edge_list(:,3);
        

        你总是可以从映射的连续 id 回到原来的顶点 id:

        original_vertex_id = v_id_unique(mapped_consecutive_id);
        

        希望这会有所帮助。

        【讨论】:

          【解决方案5】:

          您的第一个解决方案接近您想要的。然而,最好迭代你的边缘列表而不是邻接矩阵。

          edge_indexes = edge_list(:, 1:2);
          n_edges = max(edge_indexes(:));
          adj_matrix = zeros(n_edges);
          for local_edge = edge_list' %transpose in order to iterate by edge
              adj_matrix(local_edge(1), local_edge(2)) = local_edge(3);
          end
          

          【讨论】:

          • 这比我的第一个解决方案优雅得多。然而,问题仍然存在;由于 edge_list(1) 可能类似于 (2430, 305),我仍在制作带有幻象顶点的大矩阵。不过,感谢我的想法发生了 90 度大转弯。这种新的思维模式很可能会引导我找到解决方案。
          猜你喜欢
          • 1970-01-01
          • 2017-08-06
          • 1970-01-01
          • 1970-01-01
          • 2019-09-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-16
          相关资源
          最近更新 更多