将线性求解器限制为仅非负解python

时间:2018-07-02 22:03:47

标签: python scipy mathematical-optimization linear-programming cvxopt

我正在开发一个程序,该程序将针对太阳拍摄的图像的数据立方体转换为每张图片的温度曲线。它通过矩阵的线性优化来工作。

因此,我尝试了两种不同的线性求解器。 Scipy.optimize.linprog单纯形方法。此方法有效,但是非常慢。我发现cvxopt还具有我认为可以正常工作的功能-solvers.lp,但必须对设置进行一些更改。我在约束矩阵中添加了一个mxm形状的矩阵,其对角线为-1。

但是!这种方法给出的解决方案是负面的。我需要一个仅限于非负面解决方案的求解器。我查看cvxpy的原因是可以选择说nonneg = True,但是我不知道如何将他们的示例转换为我正在做的事情。这是工作原理的代码片段。 Res是实际执行线性代数函数的地方。

之后,我添加了程序的一部分,以尝试使用cvxopt。

def DEM_solve(img, Dict, lgtaxis, tolfac):
global basis_funcs
t0 = time.time()
eps = 1e-3
relax = 1
symmbuff = 1.0
adaptive_tolfac = 1
dim = np.array(img).shape
NOCOUNTS = np.where(np.array(img).sum(axis=0) < 10*eps)

ntemp = len(Dict[:,0])
coeffs = np.zeros((dim[2], dim[1], ntemp))
zmax = np.zeros((dim[2], dim[1]))
status = np.zeros((dim[2], dim[1]))
tolmap = np.zeros((dim[2], dim[1]))

zequation = np.zeros(ntemp) #63 elements
zequation[:] = 1.0 #simplex in python is a MINIMIZATION not maximization so the zequation is all +1.0 not -1.0

constraint = np.zeros((ntemp, 8)) # [8 63]
constraint[0:ntemp, 0:4] = Dict # row 1-64 and columns 0-4
constraint[0:ntemp, 4:8] = -Dict # row 1-64 and columns 5-8
constraint = np.transpose(constraint)
B = np.zeros(8)

X, Y = np.meshgrid(np.arange(-int(len(img[0,:,0]))/2, int(len(img[0,0,:])/2)), np.arange(-int(len(img[0,:,0]))/2, int(len(img[0,0,:])/2))) 
xsi, ysi = np.where(np.hypot(X,Y) < 20) #limits number of pixels looked at for now since the solver is so slow
xyzip = list(zip_longest(xsi, ysi))
for i, j in xyzip:
        temp = []
        tol = []
        for k in range(4):
           if img[k][i][j] < 0:
               temp.append(0)
           else:
               temp.append(img[k][i][j])
        for k in temp:
           if k > 1.0:
               tol.append(tolfac*0.8*math.sqrt(k))
           else:
               tol.append(tolfac*0.8)

        B[0:4] = [a+b for a, b in zip(tol, temp)]
        B[4:8] = list(map(lambda x: -x if x > 0 else 0,  map(sub, temp, tol)))


        res = scipy.optimize.linprog(zequation,
                                     A_ub = constraint,
                                     b_ub = B,
                                     options = {'tol': eps*np.max(temp)*8e-4})
        coeff = res.x
        soln = -res.fun
        t1p = time.time()
        if isinstance(coeff, float): #if nan 
            new = [0]*ntemp
            s = 10
        else: # successfully provided a list
            new = [soln] + coeff.tolist()
            s = res.status

        # if one of the new solutions is less than zero
        # make all zero, otherwise keep them
        # if nan befor or < 0 flags as unsuccessful
        if min(new[1:]) < 0:
            coeffs[i][j][0:ntemp] = 0.0
            s = 10
        else:
            coeffs[i][j][0:ntemp-1] = new[1:ntemp]

        zmax[i][j] = new[0]
        status[i][j] = s

if len(NOCOUNTS[0]) != 0:
    status[NOCOUNTS] = 11.0
    for i in range(len(lgtaxis)):
        coeffsnew = np.squeeze(coeffs[:,:,i])
        coeffsnew[NOCOUNTS] = 0.0
        coeffs[:,:,i] = coeffsnew
oem = np.zeros((dim[1], dim[2], len(lgtaxis)))
for i, j in xyzip:
      oem[i, j, :] = np.squeeze(np.matmul(np.squeeze(coeffs[i, j, :]), np.transpose(basis_funcs)))

return(oem)


zequation = np.zeros(ntemp) #63 elements
zequation[:] = 1.0 #simplex in python is a MINIMIZATION not maximization so the zequation is all +1.0 not -1.0
zequation = matrix(zequation)
constraint = np.zeros((ntemp, 8)) # 63 rows by 8 columns
constraint[0:ntemp, 0:4] = Dict # row 1-64 and columns 0-4
constraint[0:ntemp, 4:8] = -Dict # row 1-64 and columns 5-8
identity = np.zeros((ntemp, ntemp))
np.fill_diagonal(identity, -1)
constraint = np.concatenate((constraint, identity), axis = 1)
constraint = matrix(np.transpose(constraint)) # 71 rows by 63 columns
B = np.zeros(8+63)
X, Y = np.meshgrid(np.arange(-int(len(img[0,:,0]))/2, int(len(img[0,0,:])/2)), np.arange(-int(len(img[0,:,0]))/2, int(len(img[0,0,:])/2))) 
xsi, ysi = np.where(np.hypot(X,Y) < 5)
xyzip = list(zip_longest(xsi, ysi))
for i, j in xyzip:
        temp = []
        tol = []
        for k in range(4):
           if img[k][i][j] < 0:
               temp.append(0)
           else:
               temp.append(img[k][i][j])
        for k in temp:
           if k > 1.0:
               tol.append(tolfac*0.8*math.sqrt(k))
           else:
               tol.append(tolfac*0.8)

        B[0:4] = [a+b for a, b in zip(tol, temp)]
        B[4:8] = list(map(lambda x: -x if x > 0 else 0,  map(sub, temp, tol)))
        B[9:] = 0
        B = matrix(B)
        sol = solvers.lp(zequation, constraint, B, solver = 'glpk')
        coeff = list(sol['x'])
        print(coeff)
        soln = sol['primal objective']

0 个答案:

没有答案