Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

from __future__ import print_function, division 

 

from .matexpr import MatrixExpr, ShapeError, Identity 

from sympy.core.sympify import _sympify 

from sympy.core.compatibility import range 

from sympy.matrices import MatrixBase 

from sympy.core import S 

 

 

class MatPow(MatrixExpr): 

 

    def __new__(cls, base, exp): 

        base = _sympify(base) 

        if not base.is_Matrix: 

            raise TypeError("Function parameter should be a matrix") 

        exp = _sympify(exp) 

        return super(MatPow, cls).__new__(cls, base, exp) 

 

    @property 

    def base(self): 

        return self.args[0] 

 

    @property 

    def exp(self): 

        return self.args[1] 

 

    @property 

    def shape(self): 

        return self.base.shape 

 

    def _entry(self, i, j): 

        A = self.doit() 

        if isinstance(A, MatPow): 

            # We still have a MatPow, make an explicit MatMul out of it. 

            if not A.base.is_square: 

                raise ShapeError("Power of non-square matrix %s" % A.base) 

            elif A.exp.is_Integer and A.exp.is_positive: 

                A = MatMul(*[A.base for k in range(A.exp)]) 

            #elif A.exp.is_Integer and self.exp.is_negative: 

            # Note: possible future improvement: in principle we can take 

            # positive powers of the inverse, but carefully avoid recursion, 

            # perhaps by adding `_entry` to Inverse (as it is our subclass). 

            # T = A.base.as_explicit().inverse() 

            # A = MatMul(*[T for k in range(-A.exp)]) 

            else: 

                raise NotImplementedError(("(%d, %d) entry" % (int(i), int(j))) 

                    + " of matrix power either not defined or not implemented") 

        return A._entry(i, j) 

 

 

    def doit(self, **kwargs): 

        deep = kwargs.get('deep', True) 

        if deep: 

            args = [arg.doit(**kwargs) for arg in self.args] 

        else: 

            args = self.args 

        base = args[0] 

        exp = args[1] 

        if isinstance(base, MatrixBase) and exp.is_number: 

            if exp is S.One: 

                return base 

            return base**exp 

        # Note: just evaluate cases we know, return unevaluated on others. 

        # E.g., MatrixSymbol('x', n, m) to power 0 is not an error. 

        if exp.is_zero and base.is_square: 

            return Identity(base.shape[0]) 

        elif exp is S.One: 

            return base 

        return MatPow(base, exp) 

 

 

from .matmul import MatMul