如果只给出负面信息,如何计算可能的连接组件的最小数量

时间:2016-08-16 22:43:21

标签: python algorithm graph networkx

前言和设置:

考虑以下迭代聚类过程。为用户提供一组节点。在聚类过程的每次迭代中,用户通过在两个节点之间放置正边缘或负边缘来将两个节点标记为匹配或不匹配。正边缘表示该对节点必须属于同一个集群,同样负边缘表示该节点必须属于不同的集群。当前簇的数量由仅使用正边缘的图的连通分量定义。不允许用户进行无效移动(例如,在正连接组件内放置负边缘)。

在聚类过程的每次迭代中,我想知道可能由进程产生的最大和最小簇数。 最大数量很简单:它只是当前正连接组件的数量。但是,最低限度并不是很明显。

主要问题:

我的问题是关于计算最小数量的集群。给定一组节点,以及表示两个节点必须属于不同集群的一组边,可能的最小集群数是多少?

可能不太优雅的解决方案:

我相信我有一个计算这个数字的算法,但我认为它可以改进(如果它是正确的)。在我当前的算法中,我首先压缩所有正边缘,使得每个正分量仅由单个节点表示。这使我们可以忽略积极的信息。

仅给出一组节点和负面信息:1)选择一个随机节点。 2)找到该节点可以连接的所有其他节点,而不会导致不一致。 3)从图中删除这些节点并将计数增加1。 4)迭代剩余的节点。 5)当图中没有节点时,返回当前计数。

以下python代码对此进行了更多规范:

    import networkx as nx

    def minimum_number_compoments_possible(nodes, negative_edges):
        """
        Find minimum number of connected compoments possible
        Each edge represents that two nodes must be separated

        >>> nodes = [1, 2, 3, 4, 5, 6, 7]
        >>> negative_edges = [(1, 2), (2, 3), (4, 5)]
        >>> minimum_number_compoments_possible(nodes, negative_edges)
        2
        """
        num = 0
        # Create the negative graph
        g_neg = nx.Graph()
        g_neg.add_nodes_from(nodes)
        g_neg.add_edges_from(negative_edges)
        # Initialize unused nodes to be everything
        unused = list(g_neg.nodes())
        # complement of the graph contains all possible positive edges
        g_pos = nx.complement(g_neg)
        # Iterate until we have used all nodes
        while len(unused) > 0:
            # Seed a new "minimum compoment"
            num += 1
            # Grab a random unused node n1
            n1 = unused[0]
            unused.remove(n1)
            neigbs = list(g_pos.neighbors(n1))
            while len(neigbs) > 0:
                # Find node n2, that n1 could be connected to
                n2 = neigbs[0]
                unused.remove(n2)
                # Collapse negative information of n1 and n2
                g_neg = nx.contracted_nodes(g_neg, n1, n2)
                # Compute new possible positive edges
                g_pos = nx.complement(g_neg)
                # Iterate until n1 has no more possible connections
                neigbs = list(g_pos.neighbors(n1))
        return num

这个算法的运行时间应该是O(n ^ 3),其中n是图中边和顶点的总数(除非我犯了错误或节点凝结的事实进入计算; I&# 39; m假设它没有。如果这个算法是正确的,它似乎可以在运行时和简单性方面得到改进,但也许不是。这是我需要帮助的部分。

我需要帮助的部分:

我想知道是否有更优雅的解决方案,或者这个问题是否是已知问题并且具有正确的名称。我最初认为这个属性可能与负图的程度有关,但我没有看到任何明显的东西。

编辑:有些评论提出这个问题可以归结为NP中的问题,在这种情况下我的算法可能不正确。我更多地研究这个问题,但我还没想到反例。

EDIT2 :我确信这是NP完全的,我确实看到减少到最小集团的覆盖面。我找到了一个使用带边的图的反例:[(1,8),(1,9),(1,5),(1,6),(2,4),(2,5),(2) ,6),(2,7),(2,8),(2, 9),(3,4),(3,5),(3,6),(3,7),(3,8),(3,9),(4,8),(4,9) ,(5,7),(5, 8),(5,9),(6,7),(6,8),(6,9)]并随机化所选择的指数而不是仅使用第一个。我的错误算法返回3或4.

我现在的任务是确定是否有适合此任务的良好近似算法。在我的设置中,用户更可能标记具有正边缘的一对节点,因此在大多数情况下,此算法通常仍会产生正确的解决方案。

2 个答案:

答案 0 :(得分:1)

  

我想知道是否有更优雅的解决方案

折叠积极连接的组件。如果存在负循环,那么它是不可满足的。否则,找到结果图的最小颜色(只有负边),并得到一个解决方案。

复杂性很糟糕(着色......),但似乎更容易解释。

编辑:实际上,我很惊讶你有一个O(n ^ 3)算法。我认为着色问题可以减少到你的,与我上面做的对称。

  

如果此问题是已知问题并且具有正确的名称

如果您将其视为整数问题而不是图形问题,则可以将此1-SAT模数称为相等。

“1-SAT”因为它是原子的结合,而“modulo equality”因为你想根据相等/不等于约束为每个节点分配一个数字。

答案 1 :(得分:1)

计算问题中最小数量的聚类是NP完成。

可以将clique cover problem减少到它:给定一个图形,让节点成为图形的顶点,并且当两个节点之间存在负边缘时,并且仅当相应顶点之间没有边缘时在图中。然后找到一组最小的聚类相当于在原始图中找到一个最小的聚集。

另一种方式的减少是相似的:合并具有正边缘的节点,并且当且仅当原始问题中没有负边缘时,构造具有两个节点之间的边的图。然后找到该图的最小集团覆盖等同于在原始节点集中找到最小集群集。

根据派系查找图表的最小覆盖范围是Karp's 21 NP complete problems.

之一