Implicit VariablesΒΆ
Instead of giving explicitly the variable names, we could also implicitly pass in a vector without listing the variable names. Our GradDog package could solve this issue with no problems by creating the variables on its own. Here comes a demo and as always, we import our graddog module first:
import graddog as gd
from graddog.functions import sin, cos, tan, exp, log
seed4 = [1,2,3]
def f4(v):
return v[0]+3*v[2]**2
gd.trace(f4, seed4)
>>> Computing reverse mode derivatives...
>>> [[ 1. 0. 18.]]
So here we are creating variable seed4 = [1,2,3] and the parameter v in the function f4 indicates that it is sequence object. This implicitly tells our GradDog that to create a list of variables of \(x_{1}\), \(x_{2}\) and \(x_{3}\) with specifed values in seed4. Our f4 specifically defines that the funciton output is \(x_{1} + 3\times x_{3}^{2}\). Similarly, we could also create a function mapping from \(R^{m}\)→\(R^{n}\):
seed5 = [1,2,3]
def f5(v):
return [v[0]+3*v[2]**2, v[1]-v[0], v[2]+sin(v[1])]
gd.trace(f5, seed5)
>>> Computing forward mode derivatives...
>>> [[ 1. 0. 18. ]
[-1. 1. 0. ]
[ 0. -0.41614684 1. ]]
We could also apply same function to differnt variables by simply writing out the formula on the sequence object v itself. For example, v**2 + 2*v + 1 means that we are applying \(f(x) = x^{2} + 2 \times x + 1\) to all the variables created.
seed6 = np.array([1,2,3])
def f6(v):
return v**2 + 2*v + 1
gd.trace(f6, seed6)
>>> Computing forward mode derivatives...
>>> [[4. 0. 0.]
[0. 6. 0.]
[0. 0. 8.]]