【问题标题】:Which algorithms can be used to solve this similarity minimizing equilibrium prob?哪些算法可以用来解决这种相似性最小化平衡概率?
【发布时间】:2016-10-26 09:46:19
【问题描述】:

我到处寻找,但显然我似乎无法找到正确的关键字来搜索合适的解决方案,所以问题就出在这里:


*

我有一组 P 元素 [A, B ....Y, Z] 和一个 PxP 值矩阵 表示每对元素之间的相似性(所以 主对角线为 100%,其他每个单元格都有一个介于 0% 和 100%)。我想将此集合划分为 N 个元素的组,以便 该解决方案倾向于最小化组的平均内部相似度

.*


你们能给我一些关于如何做到这一点的见解吗?我曾尝试研究标准分区算法,但其中大多数不适用,因为权重取决于对,而不是个人。

谢谢!!

【问题讨论】:

  • 这听起来 NP-complete。它类似于clique cover problem,但我没有看到明显的减少。无论如何,您可能不得不接受一个好的但不完美的解决方案。我不确定哪种启发式或近似算法是合适的。
  • 一个好的但不完美的解决方案就足够了!我自己也有一些可能的算法,但我想知道是否有任何已知的方法可以解决这个问题。
  • 对最后一条语句(“pairs”)的评论。这个问题其实可以认为是一个“标准”的分区问题,即:将{1,..,P}分成N个分区S_1,..,S_N,以最小化对应矩阵中所有上对角元素的总和。这意味着您有一个可以优化的直接目标函数(可能使用动态编程,但我不确定)。 P 和 N 有多大?
  • 而且您并没有严格地寻找最佳方案:我喜欢模拟退火来解决此类问题,因为它在概念上很简单。一个从一个随机解决方案(或者更好,一些适当的启发式或贪心解决方案)开始,然后定义一组移动(例如,将随机粒子从分区 i 放入分区 j,或交换两个随机粒子),然后让它在最佳。对于 Bening 问题,这可以很好地工作,而对于困难问题,它比蛮力更糟糕。

标签: algorithm sorting grouping partitioning minimization


【解决方案1】:

不幸的是,这个问题是 NP 难题,这意味着不可能有一个多项式时间算法可以将每个实例都解决到最优。我将减少最大二分法。在这个问题的决策问题变体中,我们得到一个图 G 和一个数字 k,并要求将 G 的顶点划分为两个大小相等的部分,使得两个部分之间的边数至少为 k。 These slides 表明最大二分法是 NP-hard 通过从更一般的最大切割问题中减少的,其中 2 个部分不需要具有相同数量的顶点。

给定一个图 G = (V, E) 和数字 k,减少是:

  • 创建一个矩阵 X,其中 X[i][j] = X[j][i] = 1 如果 (i, j) 是 G 中的一条边,否则为 0。
  • 选择 N = |V|/2。 (这将导致输出 2 个组。)

在这个构造的输入上针对您的问题运行任何精确的算法,并让该算法提供的最优解具有平均相似度 y。 y = (y1+y2)/2,其中 y1 和 y2 是每组的平均相似度。我们将第一组中相似无序对的数量(即无序对 (i, j) 使得 X[i][j] = 1)称为 z1。由于我们需要处理的唯一相似度分数是 1 和 0,因此 y1 只是 z1 除以第一组中无序对的总数,即 (|V|/2)(|V|/2-1 )/2,所以 y1 = 2*z1/((|V|/2)(|V|/2-1))。对于 y2 也是如此。因此,就 z1 和 z2 而言,y = (z1+z2)/((|V|/2)(|V|/2-1))。由于分母是一个常数,通过最大化平均组内相似度 y,您的算法也会最大化 z1+z2,即最大化组内相似对的总数。

要注意的关键是,在任何解决方案中,原始图的每条边都必须出现在其中一个组内或两个不同组之间:也就是说,对于任何解决方案 Y,nEdgesWithinAGroup(Y) + nEdgesBetweenGroups( Y) = |E|,因此最小化组内边数与最大化组间边数相同。

由于假设您的问题的算法返回一个具有最小可能 y 的解决方案,并且我们在上面已经确定这也意味着 z1 + z2 的最小可能值,而且后者意味着之间的最大可能数量 -组边,因此两组之间的边数|E| - z1 - z2,是最大可能的。因此,解决原始最大二分问题剩下的就是将该值与给定的 k 值进行比较,如果 >= k 则返回 YES,否则返回 NO。

以上意味着,给定用于解决您的问题的任何多项式时间算法,以及 NP-hard 最大二分问题的任何实例,我们可以在多项式时间内构造您的问题的一个实例,解决它,然后转换解决方案到原始最大二分问题的解决方案——也就是说,它意味着我们可以在多项式时间内解决一个 NP-hard 问题。这意味着您的问题本身就是 NP 难题。

【讨论】:

    【解决方案2】:

    如果我没有完全误解您的问题,并且您想要一种糟糕的方式来解决问题,那就是: 蛮力方法:

    1. 获取 P 选择 (P/N) 组合,其中 P 是元素数,N 是您要划分的组数。
    2. 计算 1 中返回的每个组合的“内部相似度”。
    3. 从 2 中获得 N 最小。

    Python 实现:

    def getValues(matrix):
        values=[]
        count=1
        while ((len(matrix)- count)>0):
            j= count
            for i in range(len(matrix)- count ):
                values.append(matrix[count-1][j ] )
                j+=1
            count+=1
        return values
    
    
    
    def c(arr, curr, end,k ,n , comb=[]):
        """get combinations for list length n and choose k elem"""
        if comb is None:
            comb = []
        elif n ==1 :
            comb = []
        if ((arr.count(1) is not k) and (curr < end)):
            tmparr= [ i for i in arr]
            tmparr[curr]= 1
            c(tmparr, curr+ 1 , end,k ,n + 1 , comb)
            tmparr[curr]= 0
            c(tmparr, curr+ 1 , end,k ,n + 1 , comb)
        if arr.count(1) ==k :
            comb.append(arr)
        if n is 1:
            return comb
    
    
    def combos(l, choose):
        """
        use this w/ c() to get combinations
        """
        arr = [1 for i in l]
        return c(arr,0 , len(l), choose,1 )
    
    
    def getComb(combos, elem):
        """
        EX. combos=[0,1,1] elem=["A","B","C"]
        return ["B","C"]
        """
        result= [ ]
        for i in combos:
            tmp= ""
            for j in range(len(i)):
                if i[j] is 1:
                    tmp+= elem[j]
            result.append(tmp)
        return result
    
    def subSum(sub,d):
        """
        EX. sub = "abc" then return value d["ab"]+d["ac"]+d["bc"]
        sub -- list of string elements
        d -- dictionary
        """
        if( len(sub) is 2):
            return d[sub[0]+ sub [1]]
        sum=0
        for i in range(len(sub)-1) :
            sum+=d [ sub[0]+ sub [i+1] ]
        return sum+ subSum(sub[1:],d)
    
    def contains(a,b):
        for i in a:
            if i in b:
                return True
        return False
    
    
    #**************INPUT HERE**************#
    # elements
    e = ["A","B", "C", "D", "E", "F"] # partition set into N
    N = 2
    
    matrix =[ [100,2,3,4,5,6],
        [ 2, 100,9,16,23 ,30] ,
        [ 44,22,100,11,5 ,2] ,
        [ 11 ,22,33,100, 44, 55],
        [1 ,6,7,13,100, 20 ],
        [1 ,1,2,3,5,100 ] ]
    #**************************************#
    
    
    if len(matrix) is len(e):
        p = getComb(combos(e,(int)(len( matrix)/N)),e)
        q = getComb(combos(e,2),e)
        values = getValues(matrix)
    
        # make lookup for subSum()
        d = {}
        for i in range(len(q)):
            d[q[i]]=values[i]
    
        result=[]
        for i in range(N):
            sums = [subSum(i, d) for i in p]
            m = min(sums)
            s = p[sums.index(m)]
            result.append(s)
            for i in p:
                if contains(s, i):
                    p.remove(i)
    
        print(result)  # this is the answer
    

    【讨论】:

      猜你喜欢
      • 2012-10-19
      • 2017-11-12
      • 2018-06-22
      • 2020-03-12
      • 2023-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      相关资源
      最近更新 更多