【问题标题】:Transforming lattice into graph?将点阵转换为图形?
【发布时间】:2016-02-27 17:24:55
【问题描述】:

假设我有一个 d 乘以 Z 且间距相等的点格,我怎样才能有效地将其转换为一个图,其中节点是点,并且当且仅当这些点相邻时,两点之间是一条边?

例如:假设给定整数平方中的点,对应于正方形的顶点... 我们如何将其转换为 4 x 4 矩阵(或图形),条目为 1 或 0 是否存在连接两个节点的边(对应于整数平方中的点)

这个例子很简单,原因有两个:

  • 这些点位于 R 平方中,因此输入是一个二维数组(通常输入是一个 d 维数组;d>1
  • 大多数点以一种明显的方式连接...但是模式(至少我发现)在 d 维度上变得不那么明显了,每个轴上有更多的点....(如果我们采用位于立方体边缘的 8 个点)。

我正在寻找一个代码,它可以在给定任何这样的数组(作为输入)的情况下实现这一点,并输出一个(必要对称的)矩阵,表示图上节点之间的边。

我使用 R 编程(并且愿意学习 Python)。

Ps.s:我为奇怪的语法道歉......这个交换显然与 LaTeX 不兼容......:0

【问题讨论】:

  • Latex 语法在 stackoverflow 上似乎不像在其他 stackexchange 网站上那样工作,所以请解决问题...
  • 完成了,现在都清理干净了,再次感谢:)

标签: python r matrix graph


【解决方案1】:

这可以像这样在 Python 中实现:

from itertools import product

def print_lattice_edges(lattice):
    """prints all edges of a lattice, given as a list of lists of coordinates"""
    for idim, dim_coords in enumerate(lattice):
        for other_coords in product(*lattice[:idim] + lattice[idim+1:]):
            for coord1, coord2 in zip(dim_coords[:-1], dim_coords[1:]):
                edge1 = other_coords[:idim] + (coord1,) + other_coords[idim:]
                edge2 = other_coords[:idim] + (coord2,) + other_coords[idim:]
                print edge1, '->', edge2

解释:

  • 第一次循环遍历所有维度,选择该维度的所有坐标

  • 通过删除选定的维度创建一个新晶格,并使用itertools.product对剩余维度的所有可能坐标组合的Cartesian product进行迭代

  • 对于选定的维度,遍历所有可能的连续坐标对。

  • 通过将所选维度的坐标放回笛卡尔积中的正确位置来生成边缘的两个坐标。

如果您的应用程序涉及数百万个点并且速度是一个问题,您可以通过使用numpy 生成笛卡尔积来做类似的事情。

一些快速测试:

In [23]: print_lattice_edges([[0, 1], [0, 1]])  # your example
(0, 0) -> (1, 0)
(0, 1) -> (1, 1)
(0, 0) -> (0, 1)
(1, 0) -> (1, 1)

In [24]: print_lattice_edges([[0, 1], [3, 4, 5]])  # 2x3 points, 7 edges
(0, 3) -> (1, 3)
(0, 4) -> (1, 4)
(0, 5) -> (1, 5)
(0, 3) -> (0, 4)
(0, 4) -> (0, 5)
(1, 3) -> (1, 4)
(1, 4) -> (1, 5)

In [25]: print_lattice_edges([[0, 1], [0, 1], [0, 1]])  # cube, 12 edges
(0, 0, 0) -> (1, 0, 0)
(0, 0, 1) -> (1, 0, 1)
(0, 1, 0) -> (1, 1, 0)
(0, 1, 1) -> (1, 1, 1)
(0, 0, 0) -> (0, 1, 0)
(0, 0, 1) -> (0, 1, 1)
(1, 0, 0) -> (1, 1, 0)
(1, 0, 1) -> (1, 1, 1)
(0, 0, 0) -> (0, 0, 1)
(0, 1, 0) -> (0, 1, 1)
(1, 0, 0) -> (1, 0, 1)
(1, 1, 0) -> (1, 1, 1)

【讨论】:

  • 完美!非常感谢 Bas(我是 python 新手,所以这对我来说不是那么直观)
  • 小问题(因为我对 Python 还是很陌生),如果我想在彼此一定距离内(在 R 中)内的任意两个节点之间有一条边,而不是只在相邻节点之间,怎么可能我修改上面的代码?
  • @CSA 很难快速解释,最好单独问一个问题。做到这一点的“蛮力”方式是for c1 in all_possible_coords: for c2 in all_possible_coords: if distanced(c1, c2) < R: add_edge(c1, c2)。请注意,此算法会循环所有可能的组合,因此需要 O(npoints^2) 操作,这对于大问题可能会很慢。我的答案中的解决方案仅适用于O(npoints * ndim),如果ndim 很小,这没问题。
  • 酷,感谢您的反馈,我很快就会就此发布一个新问题。再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-01
  • 2021-02-28
相关资源
最近更新 更多