```python
import sympy as sp
import numpy as np
```


```python
x, y = [sp.IndexedBase(e) for e in ['x', 'y']]
m = sp.symbols('m', integer=True)
a, b = sp.symbols('a b', real=True)
i = sp.Idx('i', m)
```


```python
loss = (y[i] - (a*x[i] + b))**2
```


```python
loss
```




$\displaystyle \left(- a {x}_{Idx\left(i, \left( 0, \  m - 1\right)\right)} - b + {y}_{Idx\left(i, \left( 0, \  m - 1\right)\right)}\right)^{2}$



Having defined the loss function using indexed variables we might hope that the
implicit summation of repeated indexes might fall through to derivative
but it looks like this isn't the case.

Below we see taking derivative wrt to fit parameters is only applied
to each point rather than the whole sum, which is incorrect.


```python
sp.solve(loss.diff(a), a)
```




    [(-b + y[i])/x[i]]




```python
sp.solve(loss.diff(b), b)
```




    [-a*x[i] + y[i]]



Try adding explicit summation around the loss expression.  This gives the
correct set of equations for derivatives but a solution can't be found.


```python
sp.diff(sp.Sum(loss, i),a)
```




$\displaystyle \sum_{Idx\left(i, \left( 0, \  m - 1\right)\right)=0}^{m - 1} - 2 \left(- a {x}_{Idx\left(i, \left( 0, \  m - 1\right)\right)} - b + {y}_{Idx\left(i, \left( 0, \  m - 1\right)\right)}\right) {x}_{Idx\left(i, \left( 0, \  m - 1\right)\right)}$




```python
sp.diff(sp.Sum(loss, i), b)
```




$\displaystyle \sum_{Idx\left(i, \left( 0, \  m - 1\right)\right)=0}^{m - 1} \left(2 a {x}_{Idx\left(i, \left( 0, \  m - 1\right)\right)} + 2 b - 2 {y}_{Idx\left(i, \left( 0, \  m - 1\right)\right)}\right)$




```python
sp.solve([sp.diff(sp.Sum(loss, i),a), sp.diff(sp.Sum(loss, i),b)], [a, b])
```




    []




```python
sp.solve([loss.expand().diff(a), loss.expand().diff(b)], [a,b])
```




    {a: -b/x[i] + y[i]/x[i]}



MatrixSymbol seems to be the trick


```python
x_2 = sp.MatrixSymbol('x', m, 1)
y_2 = sp.MatrixSymbol('y', m, 1)
a_2 = sp.MatrixSymbol('a', 1, 1)
b_2 = b*sp.OneMatrix(m, 1)
```


```python
err = y_2 - (x_2*a_2 + b_2)
err
```




$\displaystyle - b \mathbb{1} - x a + y$




```python
objective = (err.T * err)
objective
```




$\displaystyle \left(- b \mathbb{1} - a^{T} x^{T} + y^{T}\right) \left(- b \mathbb{1} - x a + y\right)$




```python
objective.diff(a_2)
```




$\displaystyle - 2 x^{T} \left(- b \mathbb{1} - x a + y\right)$




```python
objective.diff(b)
```




$\displaystyle - \left(- b \mathbb{1} - a^{T} x^{T} + y^{T}\right) \mathbb{1} - \mathbb{1} \left(- b \mathbb{1} - x a + y\right)$



Functions of Matrices e.g. generator of rotations


```python
t = sp.symbols('t', real=True)
g = sp.Matrix([[0, -t], [t, 0]])
```


```python
g
```


```python
sp.exp(g)
```




$\displaystyle \left[\begin{matrix}\cos{\left(t \right)} & - \sin{\left(t \right)}\\\sin{\left(t \right)} & \cos{\left(t \right)}\end{matrix}\right]$




```python

```

c0ced813d174d88447ec5e463ff19e84bc3c13b0
ipynb
Jupyter Notebook
scripts/indexed_expressions_20211107.ipynb
mattmcd/PyBayes
c3931cd495f1e96eea7e8f6b5c527403726de7d7
Apache-2.0
scripts/indexed_expressions_20211107.ipynb
mattmcd/PyBayes
c3931cd495f1e96eea7e8f6b5c527403726de7d7
Apache-2.0
scripts/indexed_expressions_20211107.ipynb
mattmcd/PyBayes
c3931cd495f1e96eea7e8f6b5c527403726de7d7
Apache-2.0
Qwen/Qwen-72B
1. YES
2. YES