Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 哪些算法可以用来解决这个相似性最小化平衡问题?_Algorithm_Sorting_Grouping_Partitioning_Minimization - Fatal编程技术网

Algorithm 哪些算法可以用来解决这个相似性最小化平衡问题?

Algorithm 哪些算法可以用来解决这个相似性最小化平衡问题?,algorithm,sorting,grouping,partitioning,minimization,Algorithm,Sorting,Grouping,Partitioning,Minimization,我到处都找过了,但显然我找不到正确的关键字来搜索合适的解决方案,所以问题来了: * 我有一组p元素[a,B…Y,Z],和一个PxP值矩阵 表示每对元素之间的相似性(因此 主对角线为100%,每隔一个单元格有一个介于0%和0%之间的数字 100%). 我想把这个集合分成N个元素的组,这样 该解决方案倾向于最小化组的平均内部相似性 * 你们能告诉我怎么做吗?我曾尝试研究过标准的划分算法,但大多数算法都不适用,因为权重取决于对,而不是个体 谢谢 不幸的是,这个问题是NP难的,这意味着不太可能有一个

我到处都找过了,但显然我找不到正确的关键字来搜索合适的解决方案,所以问题来了:


*

我有一组p元素[a,B…Y,Z],和一个PxP值矩阵 表示每对元素之间的相似性(因此 主对角线为100%,每隔一个单元格有一个介于0%和0%之间的数字 100%). 我想把这个集合分成N个元素的组,这样 该解决方案倾向于最小化组的平均内部相似性

*


你们能告诉我怎么做吗?我曾尝试研究过标准的划分算法,但大多数算法都不适用,因为权重取决于对,而不是个体


谢谢

不幸的是,这个问题是NP难的,这意味着不太可能有一个多项式时间算法来解决每个实例的最优性。我将从最大二等分中减去。在这个问题的决策问题变体中,我们给出了一个图G和一个数字k,并要求将G的顶点划分为两个大小相等的部分,以便两部分之间的边数至少为k。通过对更一般的最大割问题的简化,证明了最大二分法是NP难的,其中两个部分不需要有相同数量的顶点

给定一个图G=(V,E)和数字k,则缩减为:

  • 如果(i,j)是G中的边,则创建一个矩阵X,其中X[i][j]=X[j][i]=1,否则为0
  • 选择N=| V |/2。(这将导致输出2个组。)
在这个构造的输入上运行任何精确的算法来解决你的问题,并让这个算法给出的最优解具有平均相似性y。y=(y1+y2)/2,其中y1和y2是各组的平均相似性。让我们调用第一组z1中相似无序对的数量(即无序对(i,j),使得X[i][j]=1)。因为我们需要处理的唯一相似性分数是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)+nedgesweengroups(Y)=E |,因此,最小化组内边的数量与最大化组间边的数量是相同的

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


这意味着,给定任何多项式时间算法来解决你的问题,以及NP-难最大对分问题的任何实例,我们可以在多项式时间内构造你的问题的一个实例,解决它,并将解决方案转换为原始最大对分问题的解——即,这意味着我们可以在多项式时间内解决一个NP难问题。这意味着你的问题本身就是NP难问题。

如果我没有完全误解你的问题,而你想要一个糟糕的解决方法,那就是: 暴力手段:

  • Get P choose(P/N)组合,其中P是元素数,N是要划分到的组数
  • 计算1中返回的每个组合的“内部相似性”
  • 从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
    
    def getValues(矩阵):
    值=[]
    计数=1
    而((len(矩阵)-计数)>0):
    j=计数
    对于范围内的i(len(矩阵)-计数):
    附加值(矩阵[count-1][j])
    j+=1
    计数+=1
    返回值
    def c(阵列、当前、结束、k、n、梳=[]):
    “”“获取列表长度n的组合并选择k元素”“”
    如果comb为None:
    梳=[]
    elif n==1:
    梳=[]
    如果((arr.count(1)不是k)和(curr