Numpy 使用scipy.optimize.root求解稀疏非线性方程组

Numpy 使用scipy.optimize.root求解稀疏非线性方程组,numpy,scipy,sparse-matrix,mathematical-optimization,equation-solving,Numpy,Scipy,Sparse Matrix,Mathematical Optimization,Equation Solving,我想解下面的非线性方程组 def solver(x0, alpha0, K, A, a): ''' x0 - nx1 numpy array. Initial guess on x. alpha0 - nx1 numpy array. Initial guess on alpha. K - nxn numpy.array. A - Length N List of nxn numpy.arrays. a - Length N list of nx1 nump

我想解下面的非线性方程组

def solver(x0, alpha0, K, A, a):
'''
x0     - nx1 numpy array. Initial guess on x.
alpha0 - nx1 numpy array. Initial guess on alpha.
K      - nxn numpy.array.
A      - Length N List of nxn numpy.arrays.
a      - Length N list of nx1 numpy.arrays.
'''

# Establish the function that produces the rhs of the system of equations.
n = K.shape[0]
N = len(A)
def lhs(x_alpha):
    '''
    x_alpha is a concatenation of x and alpha.
    '''

    x = np.ravel(x_alpha[:n])
    alpha = np.ravel(x_alpha[n:])
    lhs_top = np.ravel(K.dot(x))
    for k in xrange(N):
        lhs_top += alpha[k]*(np.ravel(np.dot(A[k], x)) + np.ravel(a[k]))

    lhs_bottom = [0.5*x.dot(np.ravel(A[k].dot(x))) + np.ravel(a[k]).dot(x)
                  for k in xrange(N)]

    lhs = np.array(lhs_top.tolist() + lhs_bottom)

    return lhs

# Solve the system of equations.
x0.shape = (n, 1)
alpha0.shape = (N, 1)
x_alpha_0 = np.vstack((x0, alpha0))
sol = root(lhs, x_alpha_0)
x_alpha_root = sol['x']

# Compute norm of residual.
res = sol['fun']
res_norm = np.linalg.norm(res)

# Break out the x and alpha components.
x_root = x_alpha_root[:n]
alpha_root = x_alpha_root[n:]


return x_root, alpha_root, res_norm
笔记 k和x之间的点表示点积。 第一个方程中的0表示向量0,第二个方程中的0表示定标器0 如果这很重要的话,所有矩阵都是稀疏的。 已知的 K是nxn正定矩阵 每个A_k是一个已知的对称矩阵 每个a_k是一个已知的nx1向量 N是已知的,假设N=50。但我需要一种方法,我可以很容易地改变N。 未知试图解决的问题 x是nx1a向量。 我认为scipy.optimize.root方法适用于1的每个alpha_k,但对于这个方程组来说,避开琐碎的解决方案可能是真正的挑战

def solver(x0, alpha0, K, A, a):
'''
x0     - nx1 numpy array. Initial guess on x.
alpha0 - nx1 numpy array. Initial guess on alpha.
K      - nxn numpy.array.
A      - Length N List of nxn numpy.arrays.
a      - Length N list of nx1 numpy.arrays.
'''

# Establish the function that produces the rhs of the system of equations.
n = K.shape[0]
N = len(A)
def lhs(x_alpha):
    '''
    x_alpha is a concatenation of x and alpha.
    '''

    x = np.ravel(x_alpha[:n])
    alpha = np.ravel(x_alpha[n:])
    lhs_top = np.ravel(K.dot(x))
    for k in xrange(N):
        lhs_top += alpha[k]*(np.ravel(np.dot(A[k], x)) + np.ravel(a[k]))

    lhs_bottom = [0.5*x.dot(np.ravel(A[k].dot(x))) + np.ravel(a[k]).dot(x)
                  for k in xrange(N)]

    lhs = np.array(lhs_top.tolist() + lhs_bottom)

    return lhs

# Solve the system of equations.
x0.shape = (n, 1)
alpha0.shape = (N, 1)
x_alpha_0 = np.vstack((x0, alpha0))
sol = root(lhs, x_alpha_0)
x_alpha_root = sol['x']

# Compute norm of residual.
res = sol['fun']
res_norm = np.linalg.norm(res)

# Break out the x and alpha components.
x_root = x_alpha_root[:n]
alpha_root = x_alpha_root[n:]


return x_root, alpha_root, res_norm
在任何情况下,此函数都使用根来求解方程组

def solver(x0, alpha0, K, A, a):
'''
x0     - nx1 numpy array. Initial guess on x.
alpha0 - nx1 numpy array. Initial guess on alpha.
K      - nxn numpy.array.
A      - Length N List of nxn numpy.arrays.
a      - Length N list of nx1 numpy.arrays.
'''

# Establish the function that produces the rhs of the system of equations.
n = K.shape[0]
N = len(A)
def lhs(x_alpha):
    '''
    x_alpha is a concatenation of x and alpha.
    '''

    x = np.ravel(x_alpha[:n])
    alpha = np.ravel(x_alpha[n:])
    lhs_top = np.ravel(K.dot(x))
    for k in xrange(N):
        lhs_top += alpha[k]*(np.ravel(np.dot(A[k], x)) + np.ravel(a[k]))

    lhs_bottom = [0.5*x.dot(np.ravel(A[k].dot(x))) + np.ravel(a[k]).dot(x)
                  for k in xrange(N)]

    lhs = np.array(lhs_top.tolist() + lhs_bottom)

    return lhs

# Solve the system of equations.
x0.shape = (n, 1)
alpha0.shape = (N, 1)
x_alpha_0 = np.vstack((x0, alpha0))
sol = root(lhs, x_alpha_0)
x_alpha_root = sol['x']

# Compute norm of residual.
res = sol['fun']
res_norm = np.linalg.norm(res)

# Break out the x and alpha components.
x_root = x_alpha_root[:n]
alpha_root = x_alpha_root[n:]


return x_root, alpha_root, res_norm
然而,在toy示例上运行只会产生微不足道的解决方案

# Toy example.
n = 4
N = 2
K = np.matrix([[0.5, 0, 0, 0], [0, 1, 0, 0],[0,0,1,0], [0,0,0,0.5]])
A_1 = np.matrix([[0.98,0,0.46,0.80],[0,0,0.56,0],[0.93,0.82,0,0.27],      
                [0,0,0,0.23]])
A_2 = np.matrix([[0.23, 0,0,0],[0.03,0.01,0,0],[0,0.32,0,0],
      [0.62,0,0,0.45]])
a_1 = np.matrix(scipy.rand(4,1))
a_2 = np.matrix(scipy.rand(4,1))
A = [A_1, A_2]
a = [a_1, a_2]
x0 = scipy.rand(n, 1)
alpha0 = scipy.rand(N, 1)

print 'x0 =', x0
print 'alpha0 =', alpha0

x_root, alpha_root, res_norm = solver(x0, alpha0, K, A, a)

print 'x_root =', x_root
print 'alpha_root =', alpha_root
print 'res_norm =', res_norm
输出为

x0 = [[ 0.00764503]
 [ 0.08058471]
 [ 0.88300129]
 [ 0.85299622]]
alpha0 = [[ 0.67872815]
 [ 0.69693346]]
x_root = [  9.88131292e-324  -4.94065646e-324   0.00000000e+000        
          0.00000000e+000]
alpha_root = [ -4.94065646e-324   0.00000000e+000]
res_norm = 0.0

你看过scipy稀疏linalg解算器吗?展示蛮力方法。我们需要您的代码开始。这可能是完全关闭,但可能适合您的问题。只是一个想法。最小二乘支持稀疏矩阵。docstring有一个根查找的示例,其中包含一些随机注释:1如果您了解有关该问题的更多详细信息,将会有所帮助。非线性有点模糊,它也是非凸的吗?2如果它是非凸的,就不能用cvxopt-Paul的方法来表示。3如果它是凸的,可能可以在cvxopt/cvxpy和co中进行公式化。你会得到一个多项式时间解算器,仍然存在凸的问题,无法在DCP@cvxopt等中进行公式化。4可能我遗漏了一些东西,但这个问题看起来受到约束,我看不到sparse.linalg或最小二乘法解决这个问题。5试试SLSQP。实际上,玩具示例中的A1和A2并不像我给它们的那样对称。我将继续尝试对称矩阵,看看这是否有什么不同。无论如何,这是一个开始。谢谢,有几个问题。1.当你说rhs时,你的意思是lhs对吗。2.计算残差范数的意义是什么?。这个值越接近零,我想我们的解决方案就越好?@JackDawkins我最初将它命名为rhs,作为应该收敛到的值,但我认为你是对的,称它为lhs更具描述性。re:残差的范数-残差是近似根中的错误。它们在绝对值中的最小值为0。如果残差的范数为0,则实际上误差为0。最小化某些残差度量是求解方程组最小二乘法、l1范数最小化等的一种非常常见的方法。