连接节点以最大化总边缘重量

时间:2017-04-24 12:06:06

标签: algorithm optimization graph-theory graph-algorithm mathematical-optimization

我正在研究一个可以简化为图形优化问题的问题,如下所示。

  • 给出了一组彩色节点。它们都是未连接的,即图中没有边缘。

  • 边缘将插入节点之间。

  • 一个节点最多只能有4条边

  • 表格提供了边缘利润贡献的规则。

    例如,

    • 连接红色到红色的边缘:利润为10

    • 将红色连接到蓝色的边缘:利润为20

  • 节点总数约为100个。

  • 颜色的总数通常在20到30左右,但它可以高达50个。相应地,利润表(边缘)将是一个很长的列表,但它不会列出所有可能的组合。表中未指定的边的利润假定为零。

问题是优化连接(边缘),使总利润最大化

我想知道这个问题,或许以其他方式,是否已知。如果是这样,请提供可能有帮助的任何指示。感谢。

5 个答案:

答案 0 :(得分:14)

您可以将此转换为找到最大成本的完美匹配的问题,这可以在多项式时间内解决(例如using a variant of the Blossom algorithm

转换是将度数d的每个节点分成d个左节点和d-4个右节点。

对于原始图中的每对顶点u,v,在未连接的顶点u左节点和未连接的顶点v左边节点之间添加一个边,其重量相当于加入u和v的利润。

接下来在每对左右节点之间添加额外的边(权重为0)(对于相同的顶点)。

现在在这个新图中构建最大权重完美匹配。

关键是额外的边缘会消耗除左边节点中的4个以外的所有节点。这意味着每个顶点只能从4个有利可图的边缘中获利。

实施例

假设我们遇到7个彩色节点的问题。我绘制了扩展图的部分,该部分对应于单个绿色节点和单个红色节点的部分。

请注意,有6个左绿色节点,比彩色节点总数少一个。有2个右绿色节点,比左节点数少4个。连接greenleft节点和红色左节点的单个弯曲边缘。如果在完美匹配中选择此弯曲边缘,则意味着红色节点应连接到绿色节点。

enter image description here

答案 1 :(得分:3)

这是针对此问题的线性规划公式:为“利润”表中的每个颜色对分配一个变量(最多需要c *(c + 1)/ 2个变量,其中c是颜色数),使用c约束由“每个节点4个边缘”限制和每个变量的一个约束来限制可能边缘的数量(除了每个边缘颜色至少有4个节点或单色边缘有5个节点),并且最大化变量*利润项的总和。

LP解算器可能会找到此问题的所有整数变量(如果幸运的话)。或者可能存在具有分数变量的解决方案,请参见下面的反例。

当我们得到LP解决方案(其中每个变量表示某些颜色组合的边数)时,我们实际上应该向图中添加边。使用一些策略来避免循环和重复边缘(例如从相同颜色的节点“选择最少连接的节点”)。

反例:5个红色,4个绿色,几个蓝色节点,红绿色边缘获利100,红色红色获利10,红蓝色获得1。 LP解决方案提供20个红绿边(正确),2.5红红边(应为2),红蓝边为零(应为1)。

修复:整数线性编程是解决此问题的正确方法。对于多达50种颜色,我们最多需要1275个变量。对于体面的ILP求解器来说,这应该是相对简单的任务。

答案 2 :(得分:3)

这听起来类似于0-1背包问题,如果将物品放入背包或未放入背包中,则计算最大值。这是一个例子:

def knapsack(numItems, capacity, sizes, values):
  # if no more items left to put in knapsack or knapsack is full
  if (numItems == 0 or capacity == 0):
    return 0

  # if can't fit item into knapsack, try the next item
  if (sizes[numItems-1] > capacity):
    knapsack(numItems-1, capacity, sizes, values)

  # find the max of including or not including item in knapsack
  return max(
    values[values-1] + knapsack(numItems-1,capacity - weights[numitems-1], sizes, values),
    knapsack(numItems-1, capacity, sizes, values))

此处您正在寻找节点与其他节点连接的最大值。连接节点时,结果的值取决于节点的颜色。代码看起来像:

def ConnectNodes(numItems, capacity, sizes, values, nodeColor):
  # if no more items left to connect or capacity is full
  if (numItems == 0 or capacity == 0):
    return 0

  # if can't fit item into knapsack, try the next item
  if (sizes[numItems-1] > capacity):
    ConnectNodes(numItems-1, capacity, sizes, values, nodeColor)

  # find the max of connecting or not connecting node
  return max(
    RulesForProfit(numItems-1, nodeColor) + ConnectNodes(numItems-1,capacity - weights[numitems-1], sizes, values, nodeColor),
    ConnectNodes(numItems-1, capacity, sizes, values, nodeColor))

答案 3 :(得分:2)

您认为可能是贪婪的做法吗?对于所有颜色和相应的颜色A-> colorB值,如果对于每个彩色边缘,您将执行

edge_color  :  sort_in_descending_order(edge_color_To_color_Prices)
example:
    red: red->black  30
         red->white  20
         red->yellow 10
    black: black->green 15
           black->grey 10

迭代直到有新的边缘空间(每个节点4个)和 采取最大可能的边缘值(将其标记为已访问,它将帮助您后者)(我假设 您只能将nodeA与nodeB链接一次)。我们可以假设边缘是 不是你所说的。 在每个节点中,您必须存储这些选定的值,因此当您在已经使用的下一个边缘上进行迭代时,您必须知道所选的边缘(黑色节点必须知道红色选择的红色 - >黑色30)

red: 1st edge: red->black 30 -> stores that in black node list as 
[red,30]
     2nd edge: ...........20 ->...
     3rd edge: ...........10
     4th edge: ...........5
     ---------------------------
     5th edge: ...........4   (after update from black it will be 4th 
edge)
black: 1st edge: black->white   50  > [red,30] 
       2nd edge: .............. 40
       3rd edge: .............. 35
       4th edge: .............. 34
       ---------------------------
       5th edge  .............. 30 (this is our red->black edge)

替换为(black-> white 50)并转到红色节点以使用下一个max更新它(因为我们刚刚删除了red-> black 30 by black-> white 50 - 我们将仅替换它我们按照最小值标准达到黑色节点中边缘的极限 - 我们正在从黑色节点中删除/替换最低价格边缘)

那应该有用

答案 4 :(得分:2)

只是一个想法,没有太多时间来验证它 如何从加权图开始G =(V,E)其中V是您的节点集,权重E是您表中的利润。设O是一个空集,它将是我们的输出。

然后在G上使用匹配算法(Blossom算法)。将这些边添加到O。

使用输入G' =(V,E \ O)重复算法。再次将这些边添加到O。

再重复两次。返回O。

运行时间:
根据维基百科,Blossom算法的运行时间是O(E * V ^(1/2))。由于算法使用4次,因此总运行时间也将为O(E * V ^(1/2))。