繁体   English   中英

给定无向图中的边,在最大化图的度数的同时限制最大图度的算法是什么?

[英]Given edges in a undirected graph, what is an algorithm for limiting the maximum degree of the graph while maximizing the degree of the graph?

这是为了我对蛋白质折叠的研究(所以我想从技术上讲是一个学校项目)

摘要:我有一个加权无向图的边缘。 图的每个顶点都有1到20个ish边缘。 我想修整此图,以使顶点的边缘不超过6个。 我还希望该图保留尽可能多的连接性(最大程度)。

背景:我使用scipy库对蛋白质中的原子进行Delaunay镶嵌(本质上是点云)。 我用它来创建一个列表,列出彼此接触的所有残基对(我存储了它们之间的距离)。 此列表包含每对(两次)以及两对之间的距离。 (残基包含许多原子,因此我使用它们的平均位置来获得残基的位置)

pairs
[(ALA 1, GLU 2, 2.7432), (ALA 1, GLU 2, 2.7432), (ALA 4, ASP 27, 4.8938), (ALA 4, ASP 27, 4.8938) ... ]

我尝试过的(可以工作,但不完全是我想要的)只是存储六个最近的联系人。 (我对残基名称进行排序,以便以后可以使用集合)

for contact in residue.contacts[:6]:
    pairs.append( tuple( sorted([residue.name, contact.name], key=lambda r: r.name) + [residue.dist[contact]] ) )

然后删除所有不往复的联系人。 (我想从技术上来说就是添加联系人)

new_pairs = []
counter=collections.Counter(pairs)
for key, val in counter.items():
    if val == 2:
        new_pairs.append(key)

这行得通,但是我丢失了一些我想保留的信息。 我将这个问题称为图论问题,因为我觉得这个问题已经在该领域解决了。

我以为贪婪算法可能会起作用:

while run_greedy:
    # find the residue with the maximum number of neighbors
    # find that residues pair with the maximum number of neighbors but only if the pair exists in pairs
    # remove that pair from pairs

    # if maximum_degree <= 6: run_greedy = False

贪婪算法有效吗? 有已知的算法可以很好地做到这一点吗? 是否有一个图书馆可以做到这一点(我更愿意更改数据格式以适合该图书馆)?

我希望这是足够的信息,在此先感谢您的帮助。

编辑这是背包问题的一个变体:您逐个添加边,并希望在构建的图不超过给定度的同时最大化边的数量。

以下解决方案使用动态编程。

m[i, d]e_0, ..., e_{i-1}的边的最大子集创建最大度<= d的子图。

  • m[i, 0] = {}
  • m[0, d] = {}
  • 如果图的度数<= d m[i, d] = m[i-1, d] + {e_i}
  • m[i, d] = m[i-1, d-1] + {e_i}边比m[i-1][d] ,则m[i, d] = m[i-1, d-1] + {e_i} ,否则m[i-1][d]

因此,该算法(未经测试):

for i in 0..N:
    m[i][0] = {}
for d in 1..K:
    m[0][d] = {}

for d in 1..K:
    for i in 1..N:
        G1 = m[i-1][d] + {e_i}
        if D(G1) == d: # can add e_i with degree <= k
            m[i][d] = G1
        else:
            m[i][d] = max(m[i-1][d-1] + {e_i}, m[i-1][d]) # key=cardinal

解决方案是: m[N-1][K-1] 时间复杂度为O(KN^2) (简化的循环: KN +图形的最大降幅( N或更小))

先前的答案

TLDR; 我不知道如何找到最佳解决方案,但是贪婪的算法可能会给您令人满意的结果。

问题

让我根据您的问题和代码来重述该问题:您希望从图形中删除最少数量的边,以将图形的最大程度减少到6 这是获得最大的子图G'GD(u) <= 6 for all u in G'

我发现的最接近的想法是图的K核心 ,但这不是完全相同的问题。

你的方法

您的方法显然不是最佳方法,因为您最多保留每个顶点的6边并使用这些边重新创建图形。 拿图ABC

A -> 1. B, 2. C
B -> 1. C, 2. A
C -> 1. A, 2. B

如果尝试使用您的方法将此图的最大程度减小为1 ,则第一遍将删除ABBA的第二个邻居), BAAB的第二个邻居)和CBB是第二个) C邻居):

A -> 1. B
B -> 1. C
C -> 1. A

为了确保图形没有方向,第二遍将删除所有剩余的边(和顶点)。

最佳减少量为:

A -> 1. B
B -> 1. A

ABC任何其他一对顶点。

一些策略

让:

  • k = 6
  • D(u) = max(d(u)-k, 0)k之上的邻居k0
  • w(uv) (resp s(uv) )=边缘的弱点(强点):最低(最高)
  • m(uv) = min(D(u), D(v))
  • M(uv) = max(D(u), D(v))

S = sum(D(u) for u in G) 目的是使S = 0同时去除最少数量的边。 如果删除:

(1)浮边: m(uv) > 0 ,然后S减小2 (两个端点都松开1度)

(2)下陷边缘: m(uv) = 0M(uv) > 0 ,然后S减小1 (弱端点的度已经<= 6

(3)下沉边缘: M(uv) = 0 ,则S不变

请注意,在以下情况下,浮动边缘可能会成为下沉边缘:1.其弱端点的度数为k+1 2.删除连接到该端点的另一条边。 同样,下沉的边缘也会下沉。

您必须删除浮动边缘,同时避免创建下沉边缘,因为删除浮动边缘会更有效地降低S K为移除的浮动边的数量,为L为移除的沉降边的数量(我们不移除沉没的边),使S = 0 我们想要2*K + L >= S 显然,这样做的想法是使L尽可能小,因为我们希望去除少量的边( K + L )。

我怀疑您会找到最佳的贪婪算法,因为一切都取决于删除的顺序,而且当前删除的远程后果很难预测。

但是您可以使用一般策略来限制下沉边缘的创建:

  1. 除非您别无选择,否则不要移除m(uv) = 1边。
  2. 如果必须删除m(uv) = 1的边缘,请选择其弱端点的浮动边缘较少的边缘(它们将变为下陷边缘)。

一种算法

这是实现此策略的贪婪算法:

while {u, v in G | m(u-v) > 0} is not empty: // remove floating edges first
    remove the edge u-v with:
        1. the maxmimum m(u-v)
        2. w(u-v) has the minimum of neighbors t with D(t) > 0
        3. s(u-v) has the minimum of neighbors t with D(t) > 0

remove all edges from {u, v in G | M(u-v) > 0} // clean up sinking edges
clean orphan vertices

终止算法终止是因为我们在每次迭代中都删除了一条边,因此{u in G | D(u) > 0} {u in G | D(u) > 0}在某些时候将变为空。

注意:每次删除后,您都可以使用堆并更新m(uv)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM