如何在不使用python对象的情况下使用lapack编写用于计算矩阵逆和在cython中求解的函数?

时间:2019-03-09 16:48:32

标签: python scipy cython linear-algebra lapack

我正在尝试编写Cython函数以计算逆并获得线性系统的解。我知道这就是Numpy所做的。但是我需要在我用Cython编写的另一个循环中使用这些函数。因此,我不想在循环中使用Python对象。

我写了一个逆解函数,它们有时会起作用。但是其他时候他们失败了。我想我可能会误解一些基本知识。无论如何,这是一个MWE。所有文件都在同一目录中。首先,文件exports.run = function run(bot, msg) { }

mopp.pxd

然后,一个包含包装程序的文件称为#cython: boundscheck=False, wraparound=False, nonecheck=False from scipy.linalg.cython_lapack cimport dgetri, dgetrf, dgesv cimport cython cdef inline void solve_c(double[:, ::1] A, double[:, ::1] B, double[:, ::1] out, int[::1] ipiv, double[:, ::1] Awork): '''solve system A*X=B [WARNING: Not working for B with 2+ columns] Parameters ---------- A : memoryview n x n B : memoryview n x r out : memoryview n x r, for output storage ipiv : memoryview length n integer vector Awork : memoryview n x n vector to use for work ''' cdef int LDA = A.shape[0], N = A.shape[1] cdef int LDB = B.shape[0], NRHS = B.shape[1] cdef int info Awork[...] = A out[...] = B dgesv(&N, &NRHS, &Awork[0,0], &LDA, &ipiv[0], &out[0,0], &LDB, &info) cdef inline void inv_c(double[:, ::1] A, double[:, ::1] B, double[:, ::1] work, int[::1] ipiv): '''invert float type square matrix A [WARNING: Not working randomly?] Parameters ---------- A : memoryview (numpy array) n x n array to invert B : memoryview (numpy array) n x n array to use within the function, function will modify this matrix in place to become the inverse of A work : memoryview (numpy array) n x n array to use within the function ipiv : memoryview (numpy array) length n array to use within function ''' cdef int n = A.shape[0], info, lwork B[...] = A dgetrf(&n, &n, &B[0, 0], &n, &ipiv[0], &info) dgetri(&n, &B[0,0], &n, &ipiv[0], &work[0,0], &lwork, &info)

mopp_wrappers.pyx

我有关联的设置文件#cython: boundscheck=False, wraparound=False, nonecheck=False, cdivision=True from mopp cimport inv_c, solve_c import numpy as np def inv(A, B, work, ipiv): inv_c(A, B, work, ipiv) def solve(A, B, out, ipiv, Awork): solve_c(A, B, out, ipiv, Awork)

setup.py

然后我在终端中运行以下命令进行编译:

from distutils.core import setup
from Cython.Build import cythonize

setup(name="mopp_wrappers", ext_modules=cythonize('mopp_wrappers.pyx', annotate=True))

最后,我用python setup.py build_ext --inplace 测试了Python中的函数。我只是不明白为什么这些功能在某些情况下会起作用,而在另一些情况下却无法。

test.py

我得到以下输出:

import numpy as np
from mopp_wrappers import inv, solve

def mysolve(A, b):
    out = np.zeros((A.shape[0], b.shape[1]))
    ipiv = np.zeros(3, dtype=np.int32)
    Awork = np.zeros(A.shape)

    solve(A, b, out, ipiv, Awork)

    return out

def myinv(A):
    B = np.zeros(A.shape)
    work = np.zeros(A.shape)
    ipiv = np.zeros(A.shape[0], dtype=np.int32)

    inv(A, B, work, ipiv)

    return B

np.random.seed(100)

M = np.random.multivariate_normal(mean=np.zeros(3), cov=np.eye(3), size=20)

A = M.T.dot(M)

# inverse is the same
print('Successful computation of inverse:')
print(np.linalg.inv(A))
print(myinv(A))
print('')

# inverse is different
B = np.zeros(A.shape)
work = np.zeros(A.shape)
ipiv = np.zeros(A.shape[0], dtype=np.int32)

inv(A, B, work, ipiv)

print('Failure to compute inverse:')
print(B)
print(np.linalg.inv(A))
print('')


# solution is the same
b = np.array([1,2,3]).reshape((-1, 1)).astype(float)

print('Successful computation of solution, 1-dim b matrix')
print(mysolve(A, b))
print(np.linalg.solve(A, b))
print('')

# solution is different
b = np.hstack([b, b])
print('Failure to compute solution, 2-dim b matrix')
print(mysolve(A, b))
print(np.linalg.solve(A, b))

0 个答案:

没有答案