跳到内容

根据 Davidson 和 Harel 的模拟退火算法,将图的顶点放置在平面上。

用法

layout_with_dh(
  graph,
  coords = NULL,
  maxiter = 10,
  fineiter = max(10, log2(vcount(graph))),
  cool.fact = 0.75,
  weight.node.dist = 1,
  weight.border = 0,
  weight.edge.lengths = edge_density(graph)/10,
  weight.edge.crossings = 1 - sqrt(edge_density(graph)),
  weight.node.edge.dist = 0.2 * (1 - edge_density(graph))
)

with_dh(...)

参数

graph

要布局的图。边的方向被忽略。

坐标

顶点的可选起始位置。如果此参数不为 NULL,则它应该是一个合适的起始坐标矩阵。

maxiter

第一阶段要执行的迭代次数。

fineiter

微调阶段的迭代次数。

cool.fact

冷却因子。

weight.node.dist

能量函数中节点-节点距离分量的权重。

weight.border

能量函数中距边界分量的权重。如果允许顶点位于边界上,则可以设置为零。

weight.edge.lengths

能量函数中边长分量的权重。

weight.edge.crossings

能量函数中边交叉分量的权重。

weight.node.edge.dist

能量函数中节点-边距离分量的权重。

...

传递给 layout_with_dh()

一个包含两列的矩阵,包含顶点的 x 和 y 坐标

x

顶点的 x 坐标。

y

顶点的 y 坐标。

详细信息

此函数实现了 Davidson 和 Harel 的算法,请参阅 Ron Davidson, David Harel: Drawing Graphs Nicely Using Simulated Annealing. ACM Transactions on Graphics 15(4), pp. 301-331, 1996。

该算法使用模拟退火和复杂的能量函数,不幸的是,对于不同的图,能量函数很难参数化。原始出版物没有透露任何参数值,下面的参数值是通过实验确定的。

该算法包括两个阶段,一个退火阶段和一个微调阶段。第二阶段没有模拟退火。

我们的实现试图尽可能地遵循原始出版物。唯一的重大区别是坐标被明确地保持在布局矩形的范围内。

参考文献

Ron Davidson, David Harel: Drawing Graphs Nicely Using Simulated Annealing. ACM Transactions on Graphics 15(4), pp. 301-331, 1996.

作者

Gabor Csardi csardi.gabor@gmail.com

示例


set.seed(42)
## Figures from the paper
g_1b <- make_star(19, mode = "undirected") + path(c(2:19, 2)) +
  path(c(seq(2, 18, by = 2), 2))
plot(g_1b, layout = layout_with_dh)


g_2 <- make_lattice(c(8, 3)) + edges(1, 8, 9, 16, 17, 24)
plot(g_2, layout = layout_with_dh)


g_3 <- make_empty_graph(n = 70)
plot(g_3, layout = layout_with_dh)


g_4 <- make_empty_graph(n = 70, directed = FALSE) + edges(1:70)
plot(g_4, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)


g_5a <- make_ring(24)
plot(g_5a, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)


g_5b <- make_ring(40)
plot(g_5b, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)


g_6 <- make_lattice(c(2, 2, 2))
plot(g_6, layout = layout_with_dh)


g_7 <- graph_from_literal(1:3:5 - -2:4:6)
plot(g_7, layout = layout_with_dh, vertex.label = V(g_7)$name)


g_8 <- make_ring(5) + make_ring(10) + make_ring(5) +
  edges(
    1, 6, 2, 8, 3, 10, 4, 12, 5, 14,
    7, 16, 9, 17, 11, 18, 13, 19, 15, 20
  )
plot(g_8, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)


g_9 <- make_lattice(c(3, 2, 2))
plot(g_9, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)


g_10 <- make_lattice(c(6, 6))
plot(g_10, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)


g_11a <- make_tree(31, 2, mode = "undirected")
plot(g_11a, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)


g_11b <- make_tree(21, 4, mode = "undirected")
plot(g_11b, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)


g_12 <- make_empty_graph(n = 37, directed = FALSE) +
  path(1:5, 10, 22, 31, 37:33, 27, 16, 6, 1) + path(6, 7, 11, 9, 10) + path(16:22) +
  path(27:31) + path(2, 7, 18, 28, 34) + path(3, 8, 11, 19, 29, 32, 35) +
  path(4, 9, 20, 30, 36) + path(1, 7, 12, 14, 19, 24, 26, 30, 37) +
  path(5, 9, 13, 15, 19, 23, 25, 28, 33) + path(3, 12, 16, 25, 35, 26, 22, 13, 3)
plot(g_12, layout = layout_with_dh, vertex.size = 5, vertex.label = NA)