inverse.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. from sympy.core.sympify import _sympify
  2. from sympy.core import S, Basic
  3. from sympy.matrices.common import NonSquareMatrixError
  4. from sympy.matrices.expressions.matpow import MatPow
  5. class Inverse(MatPow):
  6. """
  7. The multiplicative inverse of a matrix expression
  8. This is a symbolic object that simply stores its argument without
  9. evaluating it. To actually compute the inverse, use the ``.inverse()``
  10. method of matrices.
  11. Examples
  12. ========
  13. >>> from sympy import MatrixSymbol, Inverse
  14. >>> A = MatrixSymbol('A', 3, 3)
  15. >>> B = MatrixSymbol('B', 3, 3)
  16. >>> Inverse(A)
  17. A**(-1)
  18. >>> A.inverse() == Inverse(A)
  19. True
  20. >>> (A*B).inverse()
  21. B**(-1)*A**(-1)
  22. >>> Inverse(A*B)
  23. (A*B)**(-1)
  24. """
  25. is_Inverse = True
  26. exp = S.NegativeOne
  27. def __new__(cls, mat, exp=S.NegativeOne):
  28. # exp is there to make it consistent with
  29. # inverse.func(*inverse.args) == inverse
  30. mat = _sympify(mat)
  31. exp = _sympify(exp)
  32. if not mat.is_Matrix:
  33. raise TypeError("mat should be a matrix")
  34. if not mat.is_square:
  35. raise NonSquareMatrixError("Inverse of non-square matrix %s" % mat)
  36. return Basic.__new__(cls, mat, exp)
  37. @property
  38. def arg(self):
  39. return self.args[0]
  40. @property
  41. def shape(self):
  42. return self.arg.shape
  43. def _eval_inverse(self):
  44. return self.arg
  45. def _eval_determinant(self):
  46. from sympy.matrices.expressions.determinant import det
  47. return 1/det(self.arg)
  48. def doit(self, **hints):
  49. if 'inv_expand' in hints and hints['inv_expand'] == False:
  50. return self
  51. arg = self.arg
  52. if hints.get('deep', True):
  53. arg = arg.doit(**hints)
  54. return arg.inverse()
  55. def _eval_derivative_matrix_lines(self, x):
  56. arg = self.args[0]
  57. lines = arg._eval_derivative_matrix_lines(x)
  58. for line in lines:
  59. line.first_pointer *= -self.T
  60. line.second_pointer *= self
  61. return lines
  62. from sympy.assumptions.ask import ask, Q
  63. from sympy.assumptions.refine import handlers_dict
  64. def refine_Inverse(expr, assumptions):
  65. """
  66. >>> from sympy import MatrixSymbol, Q, assuming, refine
  67. >>> X = MatrixSymbol('X', 2, 2)
  68. >>> X.I
  69. X**(-1)
  70. >>> with assuming(Q.orthogonal(X)):
  71. ... print(refine(X.I))
  72. X.T
  73. """
  74. if ask(Q.orthogonal(expr), assumptions):
  75. return expr.arg.T
  76. elif ask(Q.unitary(expr), assumptions):
  77. return expr.arg.conjugate()
  78. elif ask(Q.singular(expr), assumptions):
  79. raise ValueError("Inverse of singular matrix %s" % expr.arg)
  80. return expr
  81. handlers_dict['Inverse'] = refine_Inverse