简体   繁体   中英

Sympy and Numpy unable to inverse matrix created using Sympy

I have an equation that has a symbolic variable named a by using Sympy package. using this variable I created a 6 * 6 matrix:

array([[1, exp(-0.04*a**2), exp(-0.16*a**2), exp(-0.36*a**2),
        exp(-0.64*a**2), exp(-1.0*a**2)],
       [exp(-0.04*a**2), 1, exp(-0.04*a**2), exp(-0.16*a**2),
        exp(-0.36*a**2), exp(-0.64*a**2)],
       [exp(-0.16*a**2), exp(-0.04*a**2), 1, exp(-0.04*a**2),
        exp(-0.16*a**2), exp(-0.36*a**2)],
       [exp(-0.36*a**2), exp(-0.16*a**2), exp(-0.04*a**2), 1,
        exp(-0.04*a**2), exp(-0.16*a**2)],
       [exp(-0.64*a**2), exp(-0.36*a**2), exp(-0.16*a**2),
        exp(-0.04*a**2), 1, exp(-0.04*a**2)],
       [exp(-1.0*a**2), exp(-0.64*a**2), exp(-0.36*a**2),
        exp(-0.16*a**2), exp(-0.04*a**2), 1]], dtype=object)

the a variable above is a sympy symbol. Now I want to inverse this matrix. Using numpy I get the following error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-117-3c958037db81> in <module>()
----> 1 inv(np.array(final_result))

D:\datascience\lib\site-packages\numpy\linalg\linalg.py in inv(a)
    526     signature = 'D->D' if isComplexType(t) else 'd->d'
    527     extobj = get_linalg_error_extobj(_raise_linalgerror_singular)
--> 528     ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
    529     return wrap(ainv.astype(result_t, copy=False))
    530 

TypeError: No loop matching the specified signature and casting
was found for ufunc inv

and using the Sympy own syntax to inverse this matrix, which is M ** -1, takes too long and doesn't compute the results. Is there a way to inverse this matrix, using numpy? or pure python syntax?

NumPy is a numerical package, and can not work with SymPy symbols. If I understand correctly, you are using a as a SymPy symbol without assigning it a concrete value. This makes calculating an inverse very hard. For some assignments to a the matrix might even be not invertible. I am afraid SymPy's matrix inversion is not up to such task. Something that might help somewhat, is expressing the numbers as fractions, because reals are difficult to work with symbolically.

If you try out the same with smaller matrices, you'll notice that the result quickly becomes a complicated mess of symbols. It would probably be easier to numerically invert the matrix (with NumPy) for each of the values of a you need.

Another trick to try, is introducing an auxiliary symbol to obtain simpler expressions and afterwards substituting back. Eg first something like M.subs({a**2:-log(b)}) . The obtained inverse matrix might be easier to simplify. Afterwards M.subs({b: exp(-a**2)}) to investigate what happens with the original formulation. Just calculating the determinant of your original matrix with this substitution results in an expression of more than 1000 characters long, that doesn't look to be easy to simplify. There remains little hope that the complete inverse matrix would be a manageable expression.

If you are looking for a symbolic inverse you will need to use SymPy. NumPy only computes numeric inverses, and the algorithms used by it will not work on symbolic matrices.

It looks like the default algorithm used by SymPy is slow with this matrix, but you can try alternate algorithms by passing the method keyword to the inv method of Matrix . The available options are 'GE' (the default), 'LU' , and 'ADJ' .

It can also help to do M.subs(exp(-a**2/25), b) for the calculation. That way the resulting matrix is only powers of b (you will need to use rational numbers instead of floats for this to work). I was able to get an inverse with

a, b = symbols('a b')
M = Matrix([[1, exp(-a**2/25), exp(-4*a**2/25), exp(-9*a**2/25), exp(-16*a**2/25), exp(-a**2)], [exp(-a**2/25), 1, exp(-a**2/25), exp(-4*a**2/25), exp(-9*a**2/25), exp(-16*a**2/25)], [exp(-4*a**2/25), exp(-a**2/25), 1, exp(-a**2/25), exp(-4*a**2/25), exp(-9*a**2/25)], [exp(-9*a**2/25), exp(-4*a**2/25), exp(-a**2/25), 1, exp(-a**2/25), exp(-4*a**2/25)], [exp(-16*a**2/25), exp(-9*a**2/25), exp(-4*a**2/25), exp(-a**2/25), 1, exp(-a**2/25)], [exp(-a**2), exp(-16*a**2/25), exp(-9*a**2/25), exp(-4*a**2/25), exp(-a**2/25), 1]])
M2 = M.subs(exp(-a**2/25), b)
M2inv = simplify(M2.inv('ADJ')) # takes a little time to compute, about 1:30 on my machine
Minv = M2inv.subs(b, exp(-a**2/25))

At the end of the day, you may want to consider if you need the symbolic inverse of the matrix. Is it enough to substitute a numeric value for a then compute the numeric inverse with NumPy? Do you actually need the inverse at all? Usually computing the explicit inverse of a matrix is not a good idea for numeric calculations. It is generally better to use something like numpy.linalg.solve .

Symbolic inverses are in general very complicated expressions and inherently hard to compute. Numeric inverses are extremely numerically unstable and are almost never a good idea to compute to solve whatever problem you are trying to solve.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM