选择一组边创建最大图,假设某些边与其他边互斥

时间:2015-10-21 03:06:06

标签: r graph igraph

我正在努力确定如何最好地解决这个问题。

给定一组节点以及可以连接它们的多种冲突方式,我需要选择一组非冲突关系,以便最大数量的节点保持连接状态。

实施例

这是一个包含忽略冲突的所有可能关系(边)的图表。例如,该图像没有描绘边缘彼此的依赖性。 Example Graph Structure

附加到特定节点的所有边缘彼此依赖。为简单起见,每条边都暗示它连接的每个节点的属性如A ... Z.如果连接节点3和16的边缘指定属性3-B和16-F,则将16连接到其他节点的所有边缘必须具有属性16-F。类似地,将3连接到其他节点的所有边必须具有属性3-B。

当将属性F指定给节点16时,这是相同的图。该属性删除大多数边,留下一条边连接16-4,一条边连接16-3。这在16-42之间没有留下任何边缘。

(两张图片中左边16点。) Graph structure specifying 16-F

此图像未说明连接3-42的边将指定节点42的属性,例如42-X。这将进一步限制到42的连接并进一步分解图形。我没有展示这个,因为这是我的问题所在。

我正在寻求建议。

  1. 这是一个已知问题吗?你能指点我参考吗?
  2. 如何 你会接近这个问题吗?我最好的想法是迭代, 从每个边缘开始,超过所有可能的属性。评估每个 分区和查找哪个保留最大的网络。这个 听起来很有挑战性,我可以帮忙。
  3. 如果这是解决方案,那么可以使用R中的igraph指定“边缘属性约束”并拉出生成的碎片图。
  4. 我在这里有dput图表:

    df = structure(list(nodeA = c(3L, 4L, 42L, 43L, 44L, 29L, 30L, 29L,   30L, 3L, 4L, 6L, 43L, 44L, 43L, 44L, 29L, 30L, 29L, 30L, 52L,   29L, 30L, 35L, 25L, 35L, 25L, 43L, 44L, 29L, 30L, 3L, 4L, 43L,   44L, 29L, 30L, 25L, 29L, 30L, 42L, 3L, 4L, 17L, 43L, 44L, 29L,   30L, 29L, 30L, 17L, 17L, 29L, 30L, 6L, 43L, 44L, 29L, 30L, 52L,   35L, 35L, 25L, 25L, 24L, 24L, 43L, 44L, 29L, 30L, 35L, 35L, 25L,   25L, 24L, 24L, 43L, 44L, 29L, 30L, 35L, 35L, 25L, 25L, 24L, 24L,   52L, 42L, 3L, 42L, 42L, 3L, 4L, 42L, 25L, 42L, 25L, 3L, 4L, 42L,   3L, 4L, 17L, 35L, 3L, 4L, 35L, 43L, 44L, 29L, 30L, 35L, 35L,   35L, 52L, 25L, 25L, 24L, 24L, 35L, 29L, 30L, 3L, 4L, 43L, 44L,   29L, 30L, 25L, 29L, 30L, 52L, 43L, 44L, 29L, 30L, 25L, 29L, 30L,   3L, 4L, 43L, 44L, 29L, 30L, 52L, 43L, 44L, 43L, 44L, 29L, 30L,   3L, 4L, 43L, 44L, 29L, 30L, 52L, 52L, 43L, 44L, 29L, 30L, 35L,   52L, 52L, 3L, 4L, 43L, 44L, 29L, 30L, 52L, 43L, 44L, 29L, 30L,   43L, 44L, 29L, 30L, 17L, 17L, 42L, 42L, 43L, 44L, 29L, 30L, 43L,   44L, 29L, 30L, 43L, 44L, 29L, 30L, 3L, 4L, 25L, 25L, 16L, 16L,   3L, 4L, 43L, 44L, 24L, 3L, 4L, 52L, 52L, 17L, 35L, 35L, 35L,   17L, 3L, 4L, 6L, 35L, 42L, 42L, 42L, 42L, 3L, 4L, 17L, 25L, 17L,   17L, 29L, 30L, 25L, 3L, 4L, 29L, 30L, 3L, 4L, 17L, 17L, 17L,   35L, 3L, 4L, 17L, 17L, 17L, 29L, 30L, 43L, 44L, 43L, 44L, 29L,   30L, 17L, 6L, 43L, 44L, 29L, 30L, 43L, 44L, 29L, 30L, 43L, 44L,   29L, 30L, 3L, 43L, 44L, 29L, 30L, 3L, 43L, 44L, 29L, 30L, 17L,   17L, 42L, 42L, 25L, 42L, 25L, 43L, 44L, 29L, 30L, 42L, 17L, 17L,   42L, 42L, 43L, 44L, 29L, 30L, 25L, 29L, 30L, 43L, 44L, 29L, 30L,   43L, 44L, 29L, 30L, 25L, 29L, 30L, 43L, 44L, 29L, 30L, 43L, 44L,   29L, 30L, 43L, 44L, 29L, 30L, 25L, 25L, 25L, 25L), nodeB = c(16L,   16L, 17L, 24L, 24L, 25L, 25L, 35L, 35L, 16L, 16L, 17L, 24L, 24L,   24L, 24L, 25L, 25L, 25L, 25L, 35L, 35L, 35L, 43L, 43L, 44L, 44L,   24L, 24L, 25L, 25L, 16L, 16L, 24L, 24L, 25L, 25L, 35L, 35L, 35L,   16L, 16L, 16L, 24L, 24L, 24L, 25L, 25L, 35L, 35L, 43L, 44L, 52L,   52L, 17L, 24L, 24L, 25L, 25L, 35L, 43L, 44L, 29L, 30L, 43L, 44L,   24L, 24L, 25L, 25L, 43L, 44L, 29L, 30L, 43L, 44L, 24L, 24L, 25L,   25L, 43L, 44L, 29L, 30L, 43L, 44L, 17L, 24L, 42L, 43L, 44L, 16L,   16L, 17L, 35L, 17L, 35L, 16L, 16L, 52L, 16L, 16L, 6L, 25L, 16L,   16L, 52L, 24L, 24L, 25L, 25L, 43L, 44L, 25L, 25L, 29L, 30L, 43L,   44L, 17L, 42L, 42L, 16L, 16L, 24L, 24L, 25L, 25L, 35L, 35L, 35L,   35L, 24L, 24L, 25L, 25L, 35L, 35L, 35L, 16L, 16L, 24L, 24L, 25L,   25L, 35L, 17L, 17L, 24L, 24L, 25L, 25L, 16L, 16L, 24L, 24L, 25L,   25L, 25L, 35L, 24L, 24L, 25L, 25L, 25L, 29L, 30L, 16L, 16L, 24L,   24L, 25L, 25L, 35L, 24L, 24L, 25L, 25L, 24L, 24L, 25L, 25L, 43L,   44L, 3L, 4L, 24L, 24L, 25L, 25L, 24L, 24L, 25L, 25L, 24L, 24L,   25L, 25L, 16L, 16L, 35L, 35L, 3L, 4L, 16L, 16L, 17L, 17L, 17L,   16L, 16L, 29L, 30L, 6L, 25L, 29L, 30L, 42L, 16L, 16L, 25L, 52L,   16L, 16L, 16L, 16L, 16L, 16L, 24L, 35L, 43L, 44L, 52L, 52L, 35L,   16L, 16L, 52L, 52L, 16L, 16L, 24L, 43L, 44L, 25L, 16L, 16L, 24L,   43L, 44L, 52L, 52L, 17L, 17L, 24L, 24L, 25L, 25L, 52L, 42L, 24L,   24L, 25L, 25L, 24L, 24L, 25L, 25L, 24L, 24L, 25L, 25L, 42L, 24L,   24L, 25L, 25L, 42L, 24L, 24L, 25L, 25L, 43L, 44L, 4L, 17L, 35L,   17L, 35L, 24L, 24L, 25L, 25L, 16L, 43L, 44L, 4L, 4L, 24L, 24L,   25L, 25L, 35L, 35L, 35L, 24L, 24L, 25L, 25L, 24L, 24L, 25L, 25L,   35L, 35L, 35L, 24L, 24L, 25L, 25L, 24L, 24L, 25L, 25L, 24L, 24L,   25L, 25L, 35L, 35L, 35L, 35L), attributeA = c(25L, 25L, 130L,   110L, 110L, 110L, 110L, 113L, 113L, 43L, 43L, 71L, 5L, 5L, 127L,   127L, 5L, 5L, 127L, 127L, 72L, 130L, 130L, 137L, 140L, 137L,   140L, 6L, 6L, 6L, 6L, 56L, 56L, 137L, 137L, 137L, 137L, 130L,   140L, 140L, 29L, 68L, 68L, 56L, 143L, 143L, 143L, 143L, 146L,   146L, 43L, 43L, 45L, 45L, 46L, 80L, 80L, 80L, 80L, 47L, 11L,   11L, 80L, 80L, 80L, 80L, 84L, 84L, 84L, 84L, 14L, 14L, 84L, 84L,   84L, 84L, 90L, 90L, 90L, 90L, 18L, 18L, 90L, 90L, 90L, 90L, 110L,   37L, 122L, 114L, 114L, 108L, 108L, 58L, 27L, 136L, 109L, 26L,   26L, 115L, 111L, 111L, 78L, 109L, 112L, 112L, 78L, 114L, 114L,   114L, 114L, 37L, 37L, 47L, 73L, 114L, 114L, 114L, 114L, 128L,   111L, 111L, 125L, 125L, 54L, 54L, 54L, 54L, 45L, 58L, 58L, 143L,   55L, 55L, 55L, 55L, 126L, 136L, 136L, 44L, 44L, 56L, 56L, 56L,   56L, 145L, 68L, 68L, 57L, 57L, 57L, 57L, 128L, 128L, 58L, 58L,   58L, 58L, 143L, 146L, 59L, 59L, 59L, 59L, 126L, 70L, 70L, 129L,   129L, 60L, 60L, 60L, 60L, 73L, 61L, 61L, 61L, 61L, 62L, 62L,   62L, 62L, 124L, 124L, 91L, 91L, 63L, 63L, 63L, 63L, 64L, 64L,   64L, 64L, 65L, 65L, 65L, 65L, 135L, 135L, 58L, 136L, 127L, 127L,   57L, 57L, 143L, 143L, 68L, 138L, 138L, 143L, 143L, 80L, 136L,   126L, 126L, 109L, 139L, 139L, 128L, 80L, 110L, 112L, 113L, 30L,   141L, 141L, 135L, 70L, 125L, 125L, 126L, 126L, 142L, 69L, 69L,   128L, 128L, 144L, 144L, 138L, 128L, 128L, 142L, 145L, 145L, 139L,   129L, 129L, 130L, 130L, 121L, 121L, 79L, 79L, 79L, 79L, 91L,   109L, 82L, 82L, 82L, 82L, 86L, 86L, 86L, 86L, 88L, 88L, 88L,   88L, 97L, 92L, 92L, 92L, 92L, 118L, 94L, 94L, 94L, 94L, 107L,   107L, 89L, 138L, 111L, 140L, 113L, 116L, 116L, 116L, 116L, 1L,   134L, 134L, 92L, 19L, 135L, 135L, 135L, 135L, 128L, 138L, 138L,   136L, 136L, 136L, 136L, 137L, 137L, 137L, 137L, 130L, 140L, 140L,   138L, 138L, 138L, 138L, 139L, 139L, 139L, 139L, 140L, 140L, 140L,   140L, 138L, 140L, 144L, 146L), attributeB = c(1L, 1L, 1L, 1L,   1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,   3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L,   5L, 5L, 5L, 5L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L,   7L, 7L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L,   11L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 17L, 17L,   17L, 17L, 17L, 17L, 18L, 18L, 18L, 18L, 19L, 19L, 19L, 19L, 19L,   23L, 23L, 23L, 23L, 24L, 24L, 25L, 25L, 25L, 27L, 27L, 28L, 28L,   29L, 29L, 29L, 36L, 36L, 36L, 36L, 36L, 36L, 37L, 37L, 37L, 37L,   37L, 37L, 38L, 38L, 38L, 41L, 41L, 41L, 41L, 41L, 41L, 41L, 41L,   41L, 41L, 42L, 42L, 42L, 42L, 42L, 42L, 42L, 43L, 43L, 43L, 43L,   43L, 43L, 43L, 44L, 44L, 44L, 44L, 44L, 44L, 45L, 45L, 45L, 45L,   45L, 45L, 45L, 45L, 46L, 46L, 46L, 46L, 46L, 46L, 46L, 47L, 47L,   47L, 47L, 47L, 47L, 47L, 48L, 48L, 48L, 48L, 49L, 49L, 49L, 49L,   49L, 49L, 50L, 50L, 50L, 50L, 50L, 50L, 51L, 51L, 51L, 51L, 52L,   52L, 52L, 52L, 54L, 54L, 54L, 55L, 56L, 56L, 56L, 56L, 56L, 56L,   57L, 58L, 58L, 58L, 58L, 59L, 59L, 59L, 59L, 59L, 60L, 60L, 60L,   60L, 62L, 63L, 64L, 65L, 66L, 66L, 66L, 66L, 66L, 66L, 66L, 66L,   67L, 68L, 68L, 68L, 68L, 70L, 70L, 70L, 70L, 70L, 71L, 72L, 72L,   72L, 72L, 72L, 72L, 72L, 77L, 77L, 78L, 78L, 78L, 78L, 79L, 80L,   81L, 81L, 81L, 81L, 85L, 85L, 85L, 85L, 87L, 87L, 87L, 87L, 89L,   91L, 91L, 91L, 91L, 92L, 93L, 93L, 93L, 93L, 96L, 96L, 97L, 108L,   108L, 110L, 110L, 115L, 115L, 115L, 115L, 117L, 117L, 117L, 118L,   122L, 125L, 125L, 125L, 125L, 125L, 125L, 125L, 126L, 126L, 126L,   126L, 127L, 127L, 127L, 127L, 127L, 127L, 127L, 128L, 128L, 128L,   128L, 129L, 129L, 129L, 129L, 130L, 130L, 130L, 130L, 135L, 137L,   141L, 143L)), .Names = c("nodeA", "nodeB", "attributeA", "attributeB"  ), row.names = c(3L, 4L, 5L, 7L, 8L, 9L, 10L, 12L, 13L, 18L,   19L, 20L, 24L, 25L, 26L, 27L, 28L, 29L, 31L, 32L, 35L, 36L, 37L,   38L, 39L, 40L, 41L, 52L, 53L, 54L, 55L, 59L, 60L, 62L, 63L, 64L,   65L, 71L, 72L, 73L, 78L, 82L, 83L, 86L, 87L, 88L, 89L, 90L, 96L,   97L, 98L, 99L, 108L, 109L, 112L, 114L, 115L, 116L, 117L, 120L,   121L, 122L, 129L, 131L, 134L, 135L, 141L, 142L, 143L, 144L, 146L,   147L, 153L, 154L, 156L, 157L, 163L, 164L, 165L, 166L, 168L, 169L,   175L, 176L, 178L, 179L, 183L, 186L, 187L, 188L, 189L, 196L, 197L,   198L, 201L, 204L, 206L, 208L, 209L, 213L, 216L, 217L, 221L, 222L,   225L, 226L, 230L, 241L, 242L, 243L, 244L, 248L, 249L, 255L, 256L,   259L, 260L, 264L, 265L, 272L, 276L, 277L, 284L, 285L, 287L, 288L,   289L, 290L, 292L, 293L, 294L, 295L, 303L, 304L, 305L, 306L, 308L,   309L, 310L, 315L, 316L, 318L, 319L, 320L, 321L, 325L, 333L, 334L,   336L, 337L, 338L, 339L, 347L, 348L, 350L, 351L, 352L, 353L, 354L,   359L, 365L, 366L, 367L, 368L, 369L, 373L, 374L, 381L, 382L, 384L,   385L, 386L, 387L, 390L, 395L, 396L, 397L, 398L, 406L, 407L, 408L,   409L, 411L, 412L, 416L, 417L, 421L, 422L, 423L, 424L, 430L, 431L,   432L, 433L, 438L, 439L, 440L, 441L, 447L, 448L, 450L, 452L, 454L,   455L, 456L, 457L, 458L, 459L, 468L, 472L, 473L, 476L, 477L, 481L,   483L, 484L, 485L, 488L, 493L, 494L, 495L, 501L, 504L, 508L, 511L,   512L, 513L, 514L, 516L, 518L, 519L, 520L, 523L, 524L, 526L, 528L,   529L, 534L, 535L, 538L, 539L, 540L, 543L, 544L, 550L, 555L, 556L,   558L, 561L, 562L, 564L, 565L, 576L, 577L, 582L, 583L, 584L, 585L,   590L, 594L, 596L, 597L, 598L, 599L, 605L, 606L, 607L, 608L, 613L,   614L, 615L, 616L, 620L, 622L, 623L, 624L, 625L, 629L, 631L, 632L,   633L, 634L, 643L, 644L, 647L, 657L, 660L, 665L, 666L, 673L, 674L,   675L, 676L, 691L, 692L, 693L, 696L, 700L, 705L, 706L, 707L, 708L,   711L, 712L, 713L, 720L, 721L, 722L, 723L, 728L, 729L, 730L, 731L,   733L, 734L, 735L, 741L, 742L, 743L, 744L, 750L, 751L, 752L, 753L,   759L, 760L, 761L, 762L, 772L, 777L, 787L, 790L), class = "data.frame")
    
    library(igraph)
    g = graph.data.frame(df)
    plot(g, vertex.size = 6, edge.arrow.mode=1, edge.arrow.size = 0)
    
    > head(df)
      nodeA nodeB attributeA attributeB
    1     3    16         25          1
    4     4    16         25          1
    5    42    17        130          1
    7    43    24        110          1
    8    44    24        110          1
    9    29    25        110          1
    

    在上面,第1行attributeA是节点3的专有属性,因此连接到节点3的所有其他边必须具有属性25.类似地,attributeB表示连接到节点16的所有边必须具有属性1.第1行不一定是边缘,但是没有必要保留边缘冲突。

    Subset for playing

    感谢阅读!

2 个答案:

答案 0 :(得分:2)

  

这是一个已知问题吗?你能指点我参考吗?

这是一个非常有趣的问题,而不是我之前遇到过的问题。

  

你会如何解决这个问题?

我会从整数编程的角度来解决这个问题。决策变量将用于选择每个节点的属性(仅允许标记有两个端点属性的边)。此外,我们将选择一个我们期望在大型连接组件中的“根节点”,并且我们将从该根节点向外创建流。每个其他节点将具有需求1,并且流仅可能在有效边上。我们将最大化从根节点推出的流量;这将是大组件中其他节点的数量。

为了实现这个公式,我会创建两类变量:

  • 节点属性变量:对于每个节点i和属性a,我会创建一个二进制变量z_ia,如果节点{{1}则为1 }分配属性i,否则分配0。
  • 流量变量:对于从节点ai的每条边(我假设数据框中的“from”为j,而“to”为在您的数据框中nodeA,变量nodeB表示从x_iji的流量(负值表示从j到{{1}的流量})。

我们还有许多不同的限制:

  • 每个节点只有1个属性:这可以通过j为每个节点i实现,其中\sum_{a\in A} z_ia = 1是所有属性的集合。< / LI>
  • 如果边缘无效,边缘流量为0 :对于iA的每个边缘,属性为ij,我们将分别abx_ij <= n*z_iax_ij <= n*z_jb。在所有四个约束中,x_ij >= -n*z_ia是节点的总数。如果x_ij >= -n*z_jbn,这些约束将强制x_ij=0,否则将无法约束。
  • 到任何非根节点的净流量属于[0,1] :此约束确保所有流出必须来自根,因此节点只有在连接到的时才能获得流量根。对于每个非根节点z_ia=0,边缘从节点集z_jb=0传入,边缘传递到节点集i,这些约束的格式为I和{{1} }。

目标是最大化根节点O的流量。如果\sum_{j\in I} x_ji - \sum_{j\in O} x_ij >= 0来自集合\sum_{j\in I} x_ji - \sum_{j\in O} x_ij <= 1中的节点的传入边缘以及集合r中的节点的传出边缘,则此目标(我们最大化)为r

有了这些变量和约束,您需要做的就是指定根节点I并解决;假设O位于最大的组件中,解决方案将指示最佳的节点属性分配。如果为每个根节点\sum_{j\in O} x_ji - \sum_{j\in I} x_ij重新求解,则最终会得到全局最优赋值。

在R:

中使用r包实现此方法的以下内容
r

它可以解决原始图中节点子集的问题,但是当你包含越来越多的节点时,它变得非常慢:

r

那次跑了15秒。为了加快速度,您可以考虑切换到更强大的求解器,如cplex或gurobi。这些求解器可以免费用于学术用途,但不是免费的。

  

如果这是解决方案,那么可以使用R中的igraph来指定“边缘属性约束”并拉出生成的碎片图。

是的,根据属性,您可以轻松地对图表进行子集和绘图。对于我在上面解决的5节点示例:

lpSolve

enter image description here

答案 1 :(得分:1)

在解决这个问题时,我偶然发现了一个更简单的解决方案。似乎我对这个问题的表述让答案很难看出来。

问题的核心是:当一个节点应用两个不同的约束时,它实际上变成了两个不同的节点。

以这种方式构建挑战允许我们为每组约束快速构建图形。然后我们可以快速检查这些,查看大小,并(如我原来的问题所需)选择保留最大图形的约束集。

g = graph.data.frame(df); plot(g, vertex.size = 6, edge.arrow.mode=1, edge.arrow.size = 0)

Initial Graph

# Combine the node and the rule into a new, unique node id referencing both the node and the constraint
df.split = c(df[,1:2]) + df[,3:4]*1E3 

# Keep track of edge numbers in this dataset for later
df.split = cbind(df.split, row = seq(nrow(df))) 

g.split = graph.data.frame(df.split); plot(g.split, vertex.size = 6, edge.arrow.mode=1, edge.arrow.size = 0)

Graph with nodes as node+constraint

# Decompose into unlinked sub graphs and count the edges in each
g.list = decompose.graph(g.split)
g.list.nodenum = sapply(g.list, ecount)  

head(g.list.nodenum[order(g.list.nodenum, decreasing=T)])
[1] 9 8 5 5 5 5

# Select the largest subgraph
g.sub = g.list[[order(g.list.nodenum, decreasing=T)[1]]]
plot(g.sub)

Largest subgraph

# Find what edges these were in the original dataset
originaledges = E(g.sub)$row
originaledges
[1] 129 157 130 158 131 159 212 213 132

# Play with the resulting graph, the largest graph which obeys constraints at all nodes.
df.largest = df[originaledges,]

df.largest
    nodeA nodeB attributeA attributeB
292    25    35         45         41
352    29    25         58         45
293    29    35         58         41
353    30    25         58         45
294    30    35         58         41
354    52    25        143         45
476    52    29        143         58
477    52    30        143         58
295    52    35        143         41

g.largest = graph.data.frame(df.largest); plot(g.largest, vertex.size = 6, edge.arrow.mode=1, edge.arrow.size = 0)

Largest non-conflicting subgraph

希望有一天这会帮助某人!