# AutoDiff by Symboic Representation in Julia


```julia
using Symbolics
```


```julia
i(x) = x
f(x) = 3x^2
g(x) = 2x^2
h(x) = x^2
w_vec = [i, h, g, f]

@variables x 
```




\begin{equation}
\left[
\begin{array}{c}
x \\
\end{array}
\right]
\end{equation}





```julia
function forward_fn(w_vec, x, i::Int)
    y = w_vec[i](x)
    i == size(w_vec)[1] ? y : [y; forward_fn(w_vec,y,i+1)] 
end
```




    forward_fn (generic function with 1 method)




```julia
x_vec = forward_fn(w_vec, x, 1)
display(x_vec)
```


\begin{equation}
\left[
\begin{array}{c}
x \\
x^{2} \\
2 x^{4} \\
12 x^{8} \\
\end{array}
\right]
\end{equation}




```julia
function gradient(w_i, x_i_1)
    @variables x
    dy = expand_derivatives(Differential(x)(w_i(x)))
    (substitute(dy, (Dict(x=>x_i_1,))),)
end

function reverse_autodiff(w_vec, x_vec, i::Int)
    i == 1 ? 1 :
        gradient(w_vec[i], x_vec[i-1])[1] * 
            reverse_autodiff(w_vec, x_vec, i-1)
end
```




    reverse_autodiff (generic function with 1 method)




```julia
y_ad = x_vec[end]
display(y_ad)
dy_ad = reverse_autodiff(w_vec, x_vec, size(w_vec)[1])
display(dy_ad)
```


\begin{equation}
12 x^{8}
\end{equation}




\begin{equation}
96 x^{7}
\end{equation}



## Check by theory


```julia
y_th = f(g(h(x)))
display(y_th)
dy_th = expand_derivatives(Differential(x)(y_th))
display(dy_th)
```


\begin{equation}
12 x^{8}
\end{equation}




\begin{equation}
96 x^{7}
\end{equation}



## Check by Zygote


```julia
using Symbolics
using Zygote

f(x) = 3x^2
g(x) = 2x^2
h(x) = x^2
y(x) = f(g(h(x)))
display(y(x))

dy(x) = Zygote.gradient(y,x)[1]
display(dy(x))
```


\begin{equation}
12 x^{8}
\end{equation}




\begin{equation}
96 x^{7}
\end{equation}




```julia
function y(x)
    N = 5
    y = 1
    for i=1:N
        y *= x
    end
    y
end

display(y(x))
dy(x) = Zygote.gradient(y,x)[1]
dy(x)
```


\begin{equation}
x^{5}
\end{equation}






\begin{equation}
5 x^{4}
\end{equation}





```julia
function y(x, N)
    # N = 5
    y = 1
    for i=1:N
        y *= x
    end
    y
end

display(y(x, 5))
dy(x,N) = Zygote.gradient(y,x,N)[1]
dy(x,5)
```


\begin{equation}
x^{5}
\end{equation}






\begin{equation}
5 x^{4}
\end{equation}




## All Codes


```julia
function gradient(w_i, x_i_1) # 1) Newly added
    @variables x
    dy = expand_derivatives(Differential(x)(w_i(x)))
    (substitute(dy, (Dict(x=>x_i_1,))),)
end

function main(w_vec)
    @variables x # 2) Replaced from x = 2.0 
    x_vec = forward_fn(w_vec, x, 1)
    y_ad = x_vec[end]
    dy_ad = reverse_autodiff(w_vec, x_vec, size(w_vec)[1])
    return x_vec, y_ad, dy_ad
end

i(x) = x
f(x) = 3x^2
g(x) = 2x^2
h(x) = x^2
w_vec = [i, h, g, f]
x_vec, y_ad, dy_ad = main(w_vec)
display(x_vec)
display(y_ad)
display(dy_ad)

# 3) Verification code
@variables x
y_th = f(g(h(x)))
display(y_th)
dy_th = expand_derivatives(Differential(x)(y_th))
display(dy_th)
```


\begin{equation}
\left[
\begin{array}{c}
x \\
x^{2} \\
2 x^{4} \\
12 x^{8} \\
\end{array}
\right]
\end{equation}




\begin{equation}
12 x^{8}
\end{equation}




\begin{equation}
96 x^{7}
\end{equation}




\begin{equation}
12 x^{8}
\end{equation}




\begin{equation}
96 x^{7}
\end{equation}




```julia

```

3a1b7ff4c7fffa8397f2aaa76972e1f16fb89f52
ipynb
Jupyter Notebook
diffprog/julia_dp/autodiff_chain_rule-symb.ipynb
jskDr/keraspp_2021
dc46ebb4f4dea48612135136c9837da7c246534a
MIT
2021-09-21T15:35:04.000Z
2021-12-14T12:14:44.000Z
diffprog/julia_dp/autodiff_chain_rule-symb.ipynb
jskDr/keraspp_2021
dc46ebb4f4dea48612135136c9837da7c246534a
MIT
diffprog/julia_dp/autodiff_chain_rule-symb.ipynb
jskDr/keraspp_2021
dc46ebb4f4dea48612135136c9837da7c246534a
MIT
Qwen/Qwen-72B
1. YES
2. YES