def test_len(): """Test of the length special method (__len__) of Dual class.""" # Test for string special method with scalar Dual objects x = Dual(2) y = Dual(2, [0, 1]) try: assert len(x) == 1 assert len(y) == 1 except AssertionError as e: print(e) raise AssertionError
def test_repr(): """Test of the representation special method (__repr__) of Dual class.""" # Test for representation special method with scalar Dual objects x = Dual(2) y = Dual(2, [0, 1]) try: assert repr(x) == 'Dual(2,1)' assert repr(y) == 'Dual(2,[0, 1])' except AssertionError as e: print(e) raise AssertionError
def test_str(): """Test of the string special method (__str__) of Dual class.""" # Test for string special method with scalar Dual objects x = Dual(2) y = Dual(2, [0, 1]) try: assert str(x) == 'Forward-mode Dual Object ( Values: 2, Derivatives: 1 )' assert str(y) == 'Forward-mode Dual Object ( Values: 2, Derivatives: [0, 1] )' except AssertionError as e: print(e) raise AssertionError
def relu( x: Union[Rnode, Dual, float]) -> Union[Rnode, Dual, float, List[float]]: """Calculates the output of the relu function on the input. Parameters: x : array_like, Rnode object, or Dual Object. Returns: y : array_like, Rnode object, or Dual Object. The output of the relu function on each element of x. """ try: a = max(0, x.value) b = np.where(a > 0, 1, 0) z = Rnode(a) x.children.append((b, z)) return z except AttributeError: try: a = max(0, x.val) b = np.where(a > 0, 1, 0) return Dual(a, b * x.der) except AttributeError: return max(0, x)
def relu6( x: Union[Rnode, Dual, float]) -> Union[Rnode, Dual, float, List[float]]: """Calculates the output of the relu6 function on the input. Parameters: x : array_like, Rnode object, or Dual Object. Returns: y : array_like, Rnode object, or Dual Object. The output of the relu6 function on each element of x. """ try: a = float(max(0, x.value)) b = np.where(0.0 < a < 6.0, 1, 0) if a > 6.0: # clip output to a maximum of 6 a = 6.0 z = Rnode(a) x.children.append((b, z)) return z except AttributeError: try: a = float(max(0, x.val)) b = np.where(0.0 < a < 6.0, 1, 0) if a > 6.0: # clip output to a maximum of 6 a = 6.0 return Dual(a, b * x.der) except AttributeError: return min(max(0, x), 6)
def test_cosh(): """Test of cosh method.""" # Test for sin with Rnode objects x = Rnode(1.0) z = Elem.cosh(x) z.grad_value = 1.0 try: assert z.value == np.cosh(x.value) assert x.grad() == np.sinh(x.value) except AssertionError as e: print(e) # Test for cosh with two Dual objects val = Dual(3, [4, 1]) z = Elem.cosh(val) try: assert z.val == np.cosh(val.val) assert z.der[0] == np.sinh(val.val) * val.der[0] assert z.der[1] == np.sinh(val.val) * val.der[1] except AssertionError as e: print(e) raise AssertionError # Test for cosh with int, x = 3 fx = Elem.cosh(x) try: assert fx == np.cosh(x) except AssertionError as e: print(e) raise AssertionError
def test_tanh(): """Test of tanh method.""" # Test for sin with Rnode objects x = Rnode(1.0) z = Elem.tanh(x) z.grad_value = 1.0 try: assert z.value == np.tanh(x.value) assert x.grad() == 1 / np.cosh(x.value)**2 except AssertionError as e: print(e) # Test for tan with two Dual objects val = Dual(3, [4, 1]) z = Elem.tanh(val) der = val.der / (np.cosh(val.val))**2 try: assert z.val == np.tanh(val.val) assert np.all(z.der == der) except AssertionError as e: print(e) raise AssertionError # Test for tanh with int, x = 3 fx = Elem.tanh(x) try: assert fx == np.tanh(x) except AssertionError as e: print(e) raise AssertionError
def test_power(): """Test of power method.""" # Test for power with two Dual objects x = Dual(3, [4, 1]) z = Elem.power(x, 2) result = x**2 try: assert z.val == np.power(x.val, 2) assert z.der[0] == result.der[0] assert z.der[1] == result.der[1] except AssertionError as e: print(e) raise AssertionError # Test for power with double x = 3.0 fx = Elem.power(x, 2.0) try: assert fx == 9.0 except AssertionError as e: print(e) raise AssertionError
def arccos( x: Union[Rnode, Dual, float]) -> Union[Rnode, Dual, float, List[float]]: """Calculates the inverse cosine of the input. Parameters: x : array_like, Rnode object, or Dual Object. Returns: y : array_like, Rnode object, or Dual Object. The inverse cosine of each element of x. """ try: z = Rnode(np.arccos(x.value)) temp = 1 - x.value**2 # print("temp is " + str(temp)) if temp <= 0: raise ValueError('Domain of sqrt is {x >= 0}') x.children.append((-1 / np.sqrt(temp), z)) return z except AttributeError: try: return Dual(np.arccos(x.val), -1 / np.sqrt(1 - x.val**2) * np.asarray(x.der)) except AttributeError: return np.arccos(x)
def test_relu6(): """Test of relu6 method.""" # Test for sin with Rnode objects x = Rnode(7.0) z = Elem.relu6(x) z.grad_value = 1.0 a = max(0, x.value) b = np.where(0.0 < a < 6.0, 1, 0) if a > 6.0: # clip output to a maximum of 6 a = 6.0 try: assert z.value == a assert x.grad() == b except AssertionError as e: print(e) # Test for relu6 with two Dual objects x = Dual(8, [4, 1]) z = Elem.relu6(x) a = max(0, x.val) b = np.where(0.0 < a < 6.0, 1, 0) print(b) if a > 6: # clip output to a maximum of 6 a = 6 result = Dual(a, b * x.der) try: assert z.val == result.val assert np.all(z.der == result.der) except AssertionError as e: print(e) raise AssertionError # Test for tanh with int, x = 3 fx = Elem.relu6(x) try: assert fx == min(max(0, x), 6) except AssertionError as e: print(e) raise AssertionError
def test_radd(): """Test of reverse addition special method (__radd__) of Dual class.""" # Test for reverse addition with scalar Dual object and float value x = Dual(1.5) fx = 1.5 + x try: assert fx.val == 3.0 assert fx.der == 1.0 except AssertionError as e: print(e) raise AssertionError
def test_rpow(): """Test of the reverse power special method (__rpow__) of Dual class.""" # Test for reverse power special method with scalar Dual object and float value x = Dual(2) fx = 2 ** x try: assert fx.val == 4.0 assert fx.der == pytest.approx(2.77, 0.001) except AssertionError as e: print(e) raise AssertionError
def test_pos(): """Test of the positive special method (__pos__) of Dual class.""" # Test for positive special method with scalar Dual object x = Dual(5) fx = +x try: assert fx.val == 5.0 assert fx.der == 1.0 except AssertionError as e: print(e) raise AssertionError
def test_neg(): """Test of the negation special method (__neg__) of Dual class.""" # Test for negation with scalar Dual object x = Dual(5) fx = -x try: assert fx.val == -5.0 assert fx.der == -1.0 except AssertionError as e: print(e) raise AssertionError
def test_rtruediv(): """Test of the reverse division special method (__rtruediv__) of Dual class.""" # Test for reverse division with scalar Dual object and float value x = Dual(5) fx = 1 / x try: assert fx.val == 0.2 assert fx.der == -0.04 except AssertionError as e: print(e) raise AssertionError
def test_rsub(): """Test of reverse subtraction special method (__rsub__) of Dual class.""" # Test for reverse subtraction with scalar Dual object and float value x = Dual(5) fx = 5.5 - x try: assert fx.val == 0.5 assert fx.der == 4.5 except AssertionError as e: print(e) raise AssertionError
def test_rmul(): """Test of reverse multiplication special method (__rmul__) of Dual class.""" # Test for reverse multiplication with scalar Dual object and float value x = Dual(5) fx = 0.5 * x try: assert fx.val == 2.5 assert fx.der == 0.5 except AssertionError as e: print(e) raise AssertionError
def test_relu(): """Test of relu method.""" # Test for sin with Rnode objects x = Rnode(1.0) z = Elem.relu(x) z.grad_value = 1.0 a = max(0, x.value) b = np.where(a > 0, 1, 0) try: assert z.value == a assert x.grad() == b except AssertionError as e: print(e) # Test for relu with two Dual objects x = Dual(3, [4, 1]) z = Elem.relu(x) a = max(0, x.val) b = np.where(a > 0, 1, 0) result = Dual(a, b * x.der) try: assert z.val == result.val assert np.all(z.der == result.der) except AssertionError as e: print(e) raise AssertionError # Test for tanh with int, x = 3 fx = Elem.relu(x) try: assert fx == max(0, x) except AssertionError as e: print(e) raise AssertionError
def test_log2(): """Test of log2 method.""" # Test for sin with Rnode objects x = Rnode(1.0) z = Elem.log2(x) z.grad_value = 1.0 try: assert z.value == np.log2(x.value) assert x.grad() == 1 / (x.value * np.log(2)) except AssertionError as e: print(e) # Test for log2 with two Dual objects val1 = Dual(3, [4, 1]) val2 = Dual(2, [3, 1]) val = val1 * val2 z = Elem.log2(val) try: assert z.val == np.log2(val.val) assert z.der[0] == 1 / (val.val * np.log(2)) * val.der[0] assert z.der[1] == 1 / (val.val * np.log(2)) * val.der[1] except AssertionError as e: print(e) raise AssertionError # Test for log2 with invalid Dual objects with pytest.raises(ValueError, match=r".* logarithm .*"): Elem.log2(Dual(-1, [4, 1])) # Test for log2 with int, x = 3 fx = Elem.log2(x) try: assert fx == np.log2(x) except AssertionError as e: print(e) raise AssertionError
def test_neq(): """Test of the not equal special method (__neq__) of Dual class.""" # Test for not equal special method with scalar Dual object and float value x = Dual(2) try: assert (x != 2) == False assert (x != 1) == True except AssertionError as e: print(e) raise AssertionError # Test for equality special method with two scalar Dual object x = Dual(2, [1, 0]) y = Dual(2, [1, 0]) z = Dual(2, [0, 1]) try: assert (x != y) == False assert (x != z) == True except AssertionError as e: print(e) raise AssertionError
def test_sin(): """Test of sin method.""" # Test for sin with Rnode objects x = Rnode(1.0) z = Elem.sin(x) z.grad_value = 1.0 try: assert z.value == np.sin(x.value) assert x.grad() == np.cos(x.value) except AssertionError as e: print(e) raise AssertionError # Test for sin with two Dual objects val1 = Dual(3, [4, 1]) val2 = Dual(2, [3, 1]) val = val1 + val2 z = Elem.sin(val) try: assert z.val == np.sin(val.val) assert z.der[0] == np.cos(val.val) * val.der[0] assert z.der[1] == np.cos(val.val) * val.der[1] except AssertionError as e: print(e) raise AssertionError # Test for sin with int x = 3 fx = Elem.sin(x) try: assert fx == np.sin(x) except AssertionError as e: print(e) raise AssertionError
def test_sub(): """Test of subtraction special method (__sub__) of Dual class.""" # Test for subtraction with scalar Dual object and float value x = Dual(5) fx = x - 0.5 try: assert fx.val == 4.5 assert fx.der == 0.5 except AssertionError as e: print(e) raise AssertionError # Test for subtraction with two scalar Dual object x = Dual(2.0) y = Dual(1.0) fx = x - y try: assert fx.val == 1.0 assert fx.der == 0 except AssertionError as e: print(e) raise AssertionError
def test_truediv(): """Test of the division special method (__truediv__) of Dual class.""" # Test for division with scalar Dual object and float value x = Dual(5) fx = x / 2 try: assert fx.val == 2.5 assert fx.der == 0.5 except AssertionError as e: print(e) raise AssertionError # Test for division with two scalar Dual object x = Dual(2.0) y = Dual(1.0) fx = x / y try: assert fx.val == 2.0 assert fx.der == -1.0 except AssertionError as e: print(e) raise AssertionError
def test_mul(): """Test of multiplication special method (__mul__) of Dual class.""" # Test for multiplication with scalar Dual object and float value x = Dual(5) fx = x * 0.5 try: assert fx.val == 2.5 assert fx.der == 0.5 except AssertionError as e: print(e) raise AssertionError # Test for multiplication with two scalar Dual object x = Dual(2.0) y = Dual(1.0) fx = x * y try: assert fx.val == 2.0 assert fx.der == 3.0 except AssertionError as e: print(e) raise AssertionError
def test_add(): """Test of addition special method (__add__) of Dual class.""" # Test for addition with scalar Dual object and float value x = Dual(2) fx = x + 3.5 try: assert fx.val == 5.5 assert fx.der == 1.0 except AssertionError as e: print(e) raise AssertionError # Test for addition with two scalar Dual object x = Dual(2.0) y = Dual(1.0) fx = x + y try: assert fx.val == 3.0 assert fx.der == 2.0 except AssertionError as e: print(e) raise AssertionError
def test_lt(): """Test of the less than special method (__lt__) of Dual class.""" # Test for less than special method with scalar Dual object and float value x = Dual(2) try: assert (x < 3) == True assert (x < 1) == False except AssertionError as e: print(e) raise AssertionError # Test for less than special method with two scalar Dual object a = Dual(2, [1, 0]) b = Dual(2, [1, 0]) c = Dual(2, [0, 1]) d = Dual(1, [0, 1]) try: assert (a < b) == False assert (a < c) == False assert (d < a) == True except AssertionError as e: print(e) raise AssertionError
def test_ge(): """Test of the greater than or equal to special method (__ge__) of Dual class.""" # Test for greater than or equal to special method with scalar Dual object and float value x = Dual(2) try: assert (x >= 3) == False assert (x >= 1) == True except AssertionError as e: print(e) raise AssertionError # Test for greater than or equal to special method with two scalar Dual object a = Dual(2, [1,0]) b = Dual(2, [1,0]) c = Dual(2, [0,1]) d = Dual(1, [0,1]) try: assert (a >= b) == True assert (a >= c) == True assert (d >= a) == False except AssertionError as e: print(e) raise AssertionError
def test_le(): """Test of the less than or equal to special method (__le__) of Dual class.""" # Test for less than or equal to special method with scalar Dual object and float value x = Dual(2) try: assert (x <= 3) == True assert (x <= 2) == True assert (x <= 1) == False except AssertionError as e: print(e) raise AssertionError # Test for less than or equal to special method with two scalar Dual object a = Dual(2, [1,0]) b = Dual(2, [1,0]) c = Dual(2, [0,1]) d = Dual(1, [0,1]) try: assert (a <= b) == True assert (a <= c) == True assert (a <= d) == False except AssertionError as e: print(e) raise AssertionError
def test_arccos(): """Test of arccos method.""" # Test for arccos with Rnode objects x = Rnode(0.11) z = Elem.arccos(x) z.grad_value = 1.0 temp = 1 - x.value**2 print(temp) if temp <= 0: raise ValueError('Domain of sqrt is {x >= 0}') try: assert z.value == np.arccos(x.value) assert x.grad() == -1 / np.sqrt(temp) except AssertionError as e: print(e) # Test for arccos with invalid Rnode objects with pytest.raises(ValueError, match=r".* sqrt .*"): x = Rnode(2.0) z = Elem.arccos(x) Elem.arcsin(x) z.grad_value = 1.0 # Test for arccos with two Dual objects # arccos() input (-1,1) x = Dual(0.2, [0.4, 0.1]) z = Elem.arccos(x) print(z) der = -1 / np.sqrt(1 - x.val**2) * np.asarray(x.der) try: assert z.val == np.arccos(x.val) assert np.all(z.der == der) except AssertionError as e: print(e) raise AssertionError # Test for arccos with int x = 0.1 fx = Elem.arccos(x) try: assert fx == np.arccos(x) except AssertionError as e: print(e) raise AssertionError
def cos(x: Union[Rnode, Dual, float]) -> Union[Rnode, Dual, float, List[float]]: """Calculate cosine of the input in radians. Parameters: x : array_like, Rnode object, or Dual Object. Angle, in radians (2 pi rad equals 360 degrees). Returns: y : array_like, Rnode object, or Dual Object. The cosine of each element of x. """ try: z = Rnode(np.cos(x.value)) x.children.append((-np.sin(x.value), z)) return z except AttributeError: try: return Dual(np.cos(x._val), -np.sin(x._val) * np.asarray(x._der)) except AttributeError: return np.cos(x) # Default to numpy implementation