def test_rev_mul(): x = Rev_Var(0.5) y = Rev_Var(4.2) z = x * y z.grad_value = 1.0 assert z.value == 2.1 assert x.grad() == pytest.approx(y.value)
def test_rev_rpow(): x = Rev_Var(0.5) a = 3 z = 3**x z.grad_value = 1 assert z.value == pytest.approx(1.7320508075688772) assert x.grad() == pytest.approx(1.902852301792692)
def test_rev_add(): x = Rev_Var(0.5) y = Rev_Var(4.2) z = x + y z.grad_value = 1.0 assert z.value == 4.7 assert y.grad() == 1
def test_rtruediv(): x = Rev_Var(0.5) y = 5 z = x / y z.grad_value = 1.0 assert z.value == 0.1 assert x.grad() == 0.2
def test_tahh(): x = Rev_Var(2.0) z = Rev_Var.tanh(x) z.grad_value = 1 z4 = Rev_Var.tanh(2) assert z.value == pytest.approx(0.964027580075817) assert z4 == (np.exp(2) - np.exp(-2)) / (np.exp(2) + np.exp(-2)) assert x.grad() == pytest.approx(0.07065082485316432)
def test_cosh(): x = Rev_Var(2.0) z = Rev_Var.cosh(x) z.grad_value = 1 z3 = Rev_Var.cosh(2) assert z.value == pytest.approx(3.7621956910836314) assert z3 == pytest.approx(3.7621956910836314) assert x.grad() == pytest.approx(3.626860407847019)
def test_logistic(): x = Rev_Var(3.0) z = Rev_Var.logistic(x) z.grad_value = 1 z2 = Rev_Var.logistic(3.0) assert z.value == pytest.approx(1 / (1 + np.exp(-3))) assert x.grad() == pytest.approx(np.exp(3) / ((1 + np.exp(3))**2)) assert z2 == 1 / (1 + np.exp(-3.0))
def test_sqrt(): x = Rev_Var(2.0) z1 = Rev_Var.sqrt(x) z1.grad_value = 1 z2 = Rev_Var.sqrt(2) assert z1.value == pytest.approx(1.4142135623730951) assert x.grad() == pytest.approx(0.3535533905932738) assert z2 == np.sqrt(2)
def test_logk(): x = Rev_Var(2.0) z2 = Rev_Var.logk(x, 3.0) z2.grad_value = 1 z3 = Rev_Var.logk(2.0, 3.0) assert z2.value == np.log(2) / np.log(3) assert x.grad() == pytest.approx(0.45511961331341866) assert z3 == np.log(2) / np.log(3)
def test_cos(): x = Rev_Var(2.0) y = 2 z = Rev_Var.cos(x) z.grad_value = 1 assert z.value == pytest.approx(-0.4161468365471424) assert x.grad() == pytest.approx(-0.9092974268256817) assert Rev_Var.cos(y) == np.cos(y)
def test_arctan(): x = Rev_Var(0.5) y = 0.25 z = Rev_Var.arctan(x) z.grad_value = 1 assert z.value == pytest.approx(0.46364760900080615) assert x.grad() == pytest.approx(0.8) assert Rev_Var.arctan(y) == np.arctan(y)
def test_arccos(): x = Rev_Var(0.5) y = 0.3 z = Rev_Var.arccos(x) z.grad_value = 1 assert z.value == pytest.approx(1.0471975511965976) assert x.grad() == pytest.approx(-1.1547005383792517) assert Rev_Var.arccos(y) == np.arccos(y)
def test_arcsin(): x = Rev_Var(0.5) y = 0.3 z = Rev_Var.arcsin(x) z.grad_value = 1 assert z.value == pytest.approx(0.5235987755982988) assert x.grad() == pytest.approx(1.1547005383792517) assert Rev_Var.arcsin(y) == np.arcsin(y)
def test_tan(): x = Rev_Var(2.0) y = 2 z = Rev_Var.tan(x) z.grad_value = 1 assert z.value == pytest.approx(-2.185039863261519) assert x.grad() == pytest.approx(5.774399204041917) assert Rev_Var.tan(y) == np.tan(y)
def test_exp(): x = Rev_Var(2.0) z1 = Rev_Var.exp(x) y = 5 z1.grad_value = 1 z2 = Rev_Var.exp(y) assert z1.value == pytest.approx(7.38905609893065) assert z2 == pytest.approx(148.4131591025766) assert x.grad() == pytest.approx(7.38905609893065)
def test_log(): x = Rev_Var(2.0) z1 = Rev_Var.log(x) z1.grad_value = 1 z2 = Rev_Var.log(2.0) assert z1.value == pytest.approx(0.6931471805599453) assert z1.value == np.log(2) assert x.grad() == pytest.approx(0.5) assert z2 == np.log(2)
def test_rev_pow(): x1 = Rev_Var(0.5) x2 = Rev_Var(0.5) y = Rev_Var(4.2) a = 3 z1 = x1**y z1.grad_value = 1 z2 = x2**3 z2.grad_value = 1 assert z1.value == pytest.approx(0.05440941020600775) assert x1.grad() == pytest.approx(0.4570390457304651) assert y.grad() == pytest.approx(-0.03771372928022378) assert z2.value == pytest.approx(0.125) assert x2.grad() == pytest.approx(0.75)
def test_rev_grad(): x = Rev_Var(0.5) y = Rev_Var(4.2) z = x * y + Rev_Var.sin(x) z.grad_value = 1.0 assert z.value == pytest.approx(2.579425538604203) assert x.grad() == pytest.approx(4.2 + np.cos(x.value)) assert y.grad() == pytest.approx(0.5)
def test_truediv(): x = Rev_Var(0.5) y = Rev_Var(4.2) z = x / y z.grad_value = 1.0 assert z.value == pytest.approx(0.11904761904761904) assert x.grad() == pytest.approx(0.23809523809523808) assert y.grad() == pytest.approx(-0.028344671201814057)
def test_rev_sub(): x = Rev_Var(0.5) y = Rev_Var(4.2) a = 3 z1 = y - x z1.grad_value = 1.0 assert z1.value == 3.7 assert x.grad() == -1 assert y.grad() == 1 z2 = y - 3 assert z2.value == pytest.approx(1.2)
def __init__(self, vals, ders, mode=AD_Mode.FORWARD): """ init the AD class INPUT ======= self: an AD class vals: a list of initial value for a list of variables ders: a list of initial derivative for a list of variables mode: the mode for auto-diff, ie, FORWARD or REVERSE RETURNS ======= the output of automatic differentiation for the given vals and ders EXAMPLES ======= >>> ad = AD(np.array([2, 2]), np.array([1, 1]), AD_Mode.FORWARD) >>> print(vars(ad.vars[0]), vars(ad.vars[1])) {'val': 2, 'der': array([1, 0])} {'val': 2, 'der': array([0, 1])} >>> ad = AD(np.array([2, 2]), np.array([1, 1]), AD_Mode.REVERSE) >>> print(vars(ad.vars[0]), vars(ad.vars[1])) {'value': 2, 'children': [], 'grad_value': None} {'value': 2, 'children': [], 'grad_value': None} """ self.mode = mode if self.mode == AD_Mode.FORWARD: assert (len(vals) == len(ders)) self.vars = [] dimen = len(vals) cnt = 0 for val, der in zip(vals, ders): der_list = np.array([0 for i in range(dimen)]) der_list[cnt] = der self.vars.append(Var(val, der_list)) cnt += 1 else: self.vals = vals self.vars = [] for val in self.vals: self.vars.append(Rev_Var(val))
def test_jac_matrix(): f1 = lambda x, y: Rev_Var.log(x) ** Rev_Var.sin(y) f2 = lambda x, y: Rev_Var.sqrt(x) / y ad = AD(np.array([4.12, 5.13]), np.array([1, 1]), AD_Mode.REVERSE) assert np.array_equal(ad.jac_matrix([f1, f2]), np.array([[pytest.approx(-0.11403015), pytest.approx(0.10263124)], [pytest.approx(0.048018), pytest.approx(-0.07712832)]]))
def test_rev_rsub(): x = Rev_Var(0.5) a = 3 z = a - x assert z.value == pytest.approx(2.5)
def test_two_variables(): ad = AD(np.array([2, 2]), np.array([1, 1]), AD_Mode.REVERSE) f1 = lambda x, y: Rev_Var.log(x) ** Rev_Var.sin(y) assert ad.vars[0].value == 2 assert ad.vars[1].value == 2 assert AD.auto_diff(self=ad,func=f1) == Var(pytest.approx(0.7165772257590739),np.array([pytest.approx(0.47001694),pytest.approx(0.10929465)]))
def test_single_variable(): ad = AD(np.array([2]), np.array([1]),AD_Mode.REVERSE) f1 = lambda x: Rev_Var.log(x) ** 2 assert AD.auto_diff(self=ad,func=f1) == Var(pytest.approx(0.4804530139182014),np.array([pytest.approx(0.69314718)]))
def test_expk(): x = Rev_Var(2.0) z = Rev_Var.expk(3.0, x) z.grad_value = 1 assert z.value == pytest.approx(8) assert x.grad() == pytest.approx(12)
def test_rev_rmul(): x = 3 y = Rev_Var(4.2) z = x * y assert z.value == pytest.approx(12.6)
def clear(self): if self.mode == AD_Mode.REVERSE: self.vars = [] for val in self.vals: self.vars.append(Rev_Var(val))
from EasyDiff.ad import AD from EasyDiff.var import Var from EasyDiff.rev_var import Rev_Var from EasyDiff.ad import AD_Mode import numpy as np # test forward mode. # give it a function of your choice func = lambda x, y: Var.log(x)**Var.sin(y) # give the initial values to take the derivatives at ad = AD(vals=np.array([2, 2]), ders=np.array([1, 1]), mode=AD_Mode.FORWARD) # calculate and print the derivatives print("Var.log(x) ** Var.sin(y): {}".format(vars(ad.auto_diff(func)))) # test reverse mode. func = lambda x, y: Rev_Var.log(x)**Rev_Var.sin(y) ad = AD(vals=np.array([2, 2]), ders=np.array([1, 1]), mode=AD_Mode.REVERSE) print("Rev_Var.log(x) ** Rev_Var.sin(y): {}".format(vars(ad.auto_diff(func))))
def test_rev_real_add(): x = Rev_Var(0.5) y = 4.2 z = x + y assert z.value == x.value + y