在python中解决有限制的矩阵

时间:2016-02-17 16:29:42

标签: python numpy linear-algebra linear-programming

这是问题:我有两个向量A(1Xn)和B(1Xm),其中n> m。我正在寻找矩阵T(nXm),这样AT = B. T具有以下属性:T的所有元素都是1或0。 T中每行中的元素总和为1.理想情况下,如果没有完美的解决方案,我希望程序返回最佳解决方案,其中AT-B的多个元素= 0。

以下是一个例子:

import numpy as np

A = np.array([-1.051, 1.069, 0.132, -0.003, -0.001, 0.066, -0.28,
              -0.121, 0.075, 0.006, 0.229, -0.018, -0.213, -0.11])
B = np.array([-1.051, 1.201, -0.003, -0.001, 0.066, -0.121, 0.075,
              -0.045,-0.231, -0.11])

T = np.array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]])

# This should equal a vector of 0's
print A.dot(T)-B  

1 个答案:

答案 0 :(得分:0)

我想出了一些东西,但我认为它并不完全令人满意。我不想走这条路,因为它很笨重。我首先尝试1对1映射,因为这是许多映射的常见解决方案。遗留下来的任何事情我都会迭代所有可能性。这会很快变得混乱。你还会注意到我对numpy很新。我很感激有关如何改进这一点的任何反馈。感谢。

def solver(B,A):

    m=B.size
    n=A.size

    start=np.ones((1,n))
    start=np.concatenate((start,np.zeros((m-1,n))),axis=0).astype(np.int)

    for i in xrange(0,m):
        T=np.roll(start,i,axis=0)
        test=B.dot(T)-A
        if i==0:
            matches=np.absolute(test)<.0001
        else:
            matches=np.vstack((matches,np.absolute(test)<.0001))

    rA=(A-B.dot(matches))[np.absolute(A-B.dot(matches))>.0001]
    Amissing=A-B.dot(matches)
    rB=(B-B*np.sum(matches,axis=1))[np.absolute(B-B*np.sum(matches,axis=1))>.0001]
    Bmissing=B-B*np.sum(matches,axis=1)

    rm=rB.size
    rn=rA.size

    rmxrn = np.arange(rm*rn).reshape(rm,rn)
    dif=np.absolute(rA)
    best=np.zeros(shape=(rm,rn))
    for i in xrange(0, 2**(rm*rn)):
        arr = (i >> rmxrn) % 2
        if np.amax(np.sum(arr,axis=1))>1 or np.sum(arr)>rm:
            continue
        else:
            diftemp=rB.dot(arr)-rA
            besttemp=arr
            if np.sum(np.absolute(diftemp))<np.sum(np.absolute(dif)):            
                dif=diftemp
                best=besttemp
            if np.sum(np.absolute(dif)<.0001)==rn:
                break

    best=best.astype(np.bool)
    matchesT=matches.T
    bestT=best.T

    newbestT=np.zeros(shape=(m,rn)).astype(np.bool).T

    for x in xrange(0,rn):
        counter=0
        for i, value in enumerate(Bmissing):
            if abs(Bmissing[i])>.0001:
                newbestT[x,i]=bestT[x,counter]
                counter=counter+1

    for x in xrange(0,rn):
        counter=0
        for i, value in enumerate(Amissing):
            if abs(Amissing[i])>.0001:
                matchesT[i]=newbestT[counter]
                counter=counter+1

    return(matchesT.T)

A=np.array([-1.051,1.201,-0.003,-0.001,0.066,-0.121,0.075,-0.045,-0.231,-0.11])             
B=np.array([-1.051,1.069,0.132,-0.003,-0.001,0.066,-0.28,-0.121,0.075,0.006,0.229,-0.018,-0.213,-0.11])

print solver(B,A)