## Scalar differentiation


```python
import sympy

a = sympy.Symbol('a')
b = sympy.Symbol('b')
e = (a + 2*b)**5

print("\nExpression : ")
pprint(e)
print("\n\nDifferentiating w.r.t. a:")
pprint(e.diff(a))
print("\n\nDifferentiating w.r.t. b:")
pprint(e.diff(b))
print("\n\nSecond derivative of the above result w.r.t. a:")
pprint(e.diff(b).diff(a, 2))
print("\n\nExpanding the above result:")
pprint(e.expand().diff(b).diff(a, 2))
```

    
    Expression : 
             5
    (a + 2⋅b) 
    
    
    Differentiating w.r.t. a:
               4
    5⋅(a + 2⋅b) 
    
    
    Differentiating w.r.t. b:
                4
    10⋅(a + 2⋅b) 
    
    
    Second derivative of the above result w.r.t. a:
                 2
    120⋅(a + 2⋅b) 
    
    
    Expanding the above result:
        ⎛ 2              2⎞
    120⋅⎝a  + 4⋅a⋅b + 4⋅b ⎠


## Approximate differentiation


```python
from sympy import *
from sympy.printing.str import StrPrinter
from sympy.printing.latex import LatexPrinter

 
 
#####  M  E  T  H  O  D  S
 
 
 
def matrices(names):
    ''' Call with  A,B,C = matrix('A B C') '''
    return symbols(names,commutative=False)
 
 
# Transformations
 
d = Function("d",commutative=False)
inv = Function("inv",commutative=False)
 
class t(Function):
    ''' The transposition, with special rules
        t(A+B) = t(A) + t(B) and t(AB) = t(B)t(A) '''
    is_commutative = False
    def __new__(cls,arg):
        if arg.is_Add:
            return Add(*[t(A) for A in arg.args])
        elif arg.is_Mul:
            L = len(arg.args)
            return Mul(*[t(arg.args[L-i-1]) for i in range(L)])
        else:
            return Function.__new__(cls,arg)
 
 
# Differentiation
 
MATRIX_DIFF_RULES = { 
         
        # e =expression, s = a list of symbols respsect to which
        # we want to differentiate
         
        Symbol : lambda e,s : d(e) if s.has(e) else 0,
        Add :  lambda e,s : Add(*[matDiff(arg,s) for arg in e.args]),
        Mul :  lambda e,s : Mul(matDiff(e.args[0],s),Mul(*e.args[1:]))
                      +  Mul(e.args[0],matDiff(Mul(*e.args[1:]),s)) ,
        t :   lambda e,s : t( matDiff(e.args[0],s) ),
        inv : lambda e,s : - e * matDiff(e.args[0],s) * e
}
 
def matDiff(expr,symbols):
    if expr.__class__ in MATRIX_DIFF_RULES.keys():
        return  MATRIX_DIFF_RULES[expr.__class__](expr,symbols)
    else:
        return 0
 
 
 
#####  C  O  S  M  E  T  I  C  S
 
 
# Console mode
 
class matStrPrinter(StrPrinter):
    ''' Nice printing for console mode : X¯¹, X', ∂X '''
     
    def _print_inv(self, expr):
        if expr.args[0].is_Symbol:
            return  self._print(expr.args[0]) +'¯¹'
        else:
            return '(' +  self._print(expr.args[0]) + ')¯¹'
     
    def _print_t(self, expr):
        return  self._print(expr.args[0]) +"'"
     
    def _print_d(self, expr):
        if expr.args[0].is_Symbol:
            return '∂'+  self._print(expr.args[0])
        else:
            return '∂('+  self._print(expr.args[0]) +')'   
 
def matPrint(m):
    mem = Basic.__str__ 
    Basic.__str__ = lambda self: matStrPrinter().doprint(self)
    print(str(m).replace('*',''))
    Basic.__str__ = mem
 
 
# Latex mode
 
class matLatPrinter(LatexPrinter):
    ''' Printing instructions for latex : X^{-1},  X^T, \partial X '''
     
    def _print_inv(self, expr):
        if expr.args[0].is_Symbol:
            return self._print(expr.args[0]) +'^{-1}'
        else:
            return '(' + self._print(expr.args[0]) + ')^{-1}'
    def _print_t(self, expr):
        return  self._print(expr.args[0]) +'^T'
     
    def _print_d(self, expr):
        if expr.args[0].is_Symbol:
            return '\partial '+ self._print(expr.args[0])
        else:
            return '\partial ('+ self._print(expr.args[0]) +')'
 
def matLatex(expr, profile=None, **kargs):
    if profile is not None:
        profile.update(kargs)
    else:
        profile = kargs
    return matLatPrinter(profile).doprint(expr)
```

$ H = X {(X^T S^{-1} X)}^{-1} X^T S^{-1} $

How much is $\displaystyle \frac{\partial H}{\partial X}$?


```python
X, S = matrices("X S")
H = X * inv(t(X) * inv(S) * X) * t(X) * inv(S)
```


```python
expr = expand(expand(matDiff(H,X)))
expr
```




    -X*inv(t(X)*inv(S)*X)*t(X)*inv(S)*d(X)*inv(t(X)*inv(S)*X)*t(X)*inv(S) + X*inv(t(X)*inv(S)*X)*t(d(X))*inv(S) - X*inv(t(X)*inv(S)*X)*t(d(X))*inv(S)*X*inv(t(X)*inv(S)*X)*t(X)*inv(S) + d(X)*inv(t(X)*inv(S)*X)*t(X)*inv(S)




```python
matPrint(expr)
```

    -X(X'S¯¹X)¯¹X'S¯¹∂X(X'S¯¹X)¯¹X'S¯¹ + X(X'S¯¹X)¯¹∂X'S¯¹ - X(X'S¯¹X)¯¹∂X'S¯¹X(X'S¯¹X)¯¹X'S¯¹ + ∂X(X'S¯¹X)¯¹X'S¯¹



```python
latex = matLatex(matDiff(H,X))
latex
```




    'X \\left(- (X^T S^{-1} X)^{-1} \\left(X^T S^{-1} \\partial X + \\partial X^T S^{-1} X\\right) (X^T S^{-1} X)^{-1} X^T S^{-1} + (X^T S^{-1} X)^{-1} \\partial X^T S^{-1}\\right) + \\partial X (X^T S^{-1} X)^{-1} X^T S^{-1}'




```python
from IPython.display import Math

Math(latex)
```




$$X \left(- (X^T S^{-1} X)^{-1} \left(X^T S^{-1} \partial X + \partial X^T S^{-1} X\right) (X^T S^{-1} X)^{-1} X^T S^{-1} + (X^T S^{-1} X)^{-1} \partial X^T S^{-1}\right) + \partial X (X^T S^{-1} X)^{-1} X^T S^{-1}$$



## Matrix differentiation

If $E = x^T A x$ then:

$ \displaystyle \frac{\partial E}{\partial x} = x^T (A + A^T) $


```python
x = MatrixSymbol('x', 3, 1)
A = MatrixSymbol('A', 3, 3)

alpha = x.T * A * x
print(alpha)
```

    x.T*A*x



```python
print(Matrix(alpha))
```

    Matrix([[(A[0, 0]*x[0, 0] + A[0, 1]*x[1, 0] + A[0, 2]*x[2, 0])*x[0, 0] + (A[1, 0]*x[0, 0] + A[1, 1]*x[1, 0] + A[1, 2]*x[2, 0])*x[1, 0] + (A[2, 0]*x[0, 0] + A[2, 1]*x[1, 0] + A[2, 2]*x[2, 0])*x[2, 0]]])



```python
print(Matrix(alpha).diff(x[0, 0]))
```

    Matrix([[2*A[0, 0]*x[0, 0] + A[0, 1]*x[1, 0] + A[0, 2]*x[2, 0] + A[1, 0]*x[1, 0] + A[2, 0]*x[2, 0]]])



```python
for expr in derive_by_array(Matrix(alpha), Matrix(x)):
    print(expr)
```

    2*A[0, 0]*x[0, 0] + A[0, 1]*x[1, 0] + A[0, 2]*x[2, 0] + A[1, 0]*x[1, 0] + A[2, 0]*x[2, 0]
    A[0, 1]*x[0, 0] + A[1, 0]*x[0, 0] + 2*A[1, 1]*x[1, 0] + A[1, 2]*x[2, 0] + A[2, 1]*x[2, 0]
    A[0, 2]*x[0, 0] + A[1, 2]*x[1, 0] + A[2, 0]*x[0, 0] + A[2, 1]*x[1, 0] + 2*A[2, 2]*x[2, 0]



```python
expr1 = Matrix(derive_by_array(Matrix(alpha), Matrix(x))).T
expr2 = Matrix(x.T * (A + A.T))
simplify(expr1 - expr2)
```




    Matrix([[0, 0, 0]])




```python

```

39d5ccc51b7e01874ca139196db1d8c422f2d33d
ipynb
Jupyter Notebook
_notebooks/SymPy Demo.ipynb
jilljenn/tryalgo.org
5d62c2457d52817de2f189c71fe73410b2cd5a97
MIT
2016-03-03T18:33:25.000Z
2021-02-06T10:53:48.000Z
_notebooks/SymPy Demo.ipynb
o-ikne/tryalgo.org
efeb139ff9711bbedcd6d72d58e42f0e8e1bf9aa
MIT
2016-02-04T02:44:54.000Z
2021-02-11T18:26:49.000Z
_notebooks/SymPy Demo.ipynb
o-ikne/tryalgo.org
efeb139ff9711bbedcd6d72d58e42f0e8e1bf9aa
MIT
2016-11-24T22:23:50.000Z
2021-01-26T12:49:30.000Z
Qwen/Qwen-72B
1. YES
2. YES