def test_abs_pow_exp_arctan_sqrt_div_scalar(self): value1 = 9 value2 = 12 var1 = Variable(value1, 0.4) var2 = Variable(value2, 0.88) equation = abs(var1**2 + np.exp(np.arctan(var2))) / np.sqrt( 2 * var1**3) expected_numerator_value = abs(value1**2 + np.exp(np.arctan(value2))) expected_numerator_derivative = 0.4 * 2 * value1 + ( 0.88 * (1 / (1 + value2**2)) * np.exp(np.arctan(value2))) expected_denominator_value = np.sqrt(2 * value1**3) expected_denominator_derivative = (2 * 0.4 * 3 * value1**2) * (0.5 * (2 * value1**3)**-0.5) expected_derivative = ( (expected_numerator_derivative * expected_denominator_value) - (expected_numerator_value * expected_denominator_derivative)) / ( expected_denominator_value**2) self.assertAlmostEqual( expected_numerator_value / expected_denominator_value, equation.value) self.assertAlmostEqual(expected_derivative, equation.derivative)
def test__lt__vector(self): var1 = Variable(1, np.array([2, 3, 4])) var2 = Variable(2, 5 * np.ones(3)) self.assertAlmostEqual(var1 < var2, (True, True)) var1 = Variable(1, np.array([2, 3, 4])) var2 = Variable(2, 4 * np.ones(3)) self.assertAlmostEqual(var1 < var2, (True, False))
def test__gt__vector(self): var1 = Variable(5, np.array([6, 6, 6])) var2 = Variable(2, 5 * np.ones(3)) self.assertAlmostEqual(var1 > var2, (True, True)) var1 = Variable(1, np.array([8, 5, 4])) var2 = Variable(2, 3 * np.ones(3)) self.assertAlmostEqual(var1 > var2, (False, True))
def test_abs_scalar(self): var = Variable(-12, 9) zero_var = Variable(0, 0.5) result = abs(var) self.assertAlmostEqual(12, result.value) self.assertAlmostEqual(var.derivative * -1, result.derivative) with self.assertRaises(ValueError) as e: abs(zero_var)
def test__mul__scalar_two_variable_objects(self): var1 = Variable(5.0, 1.0) var2 = Variable(2.0, 2.0) mult = var1 * var2 mult_reverse_order = var2 * var1 self.assertAlmostEqual(10.0, mult.value) self.assertAlmostEqual(12, mult.derivative) self.assertAlmostEqual(10.0, mult_reverse_order.value) self.assertAlmostEqual(12, mult_reverse_order.derivative)
def test_polynomial_multivariate(self): x = Variable(3, np.array([1, 0])) y = Variable(2, np.array([0, 1])) f = 1 + 3 * x**2 + 4 * x + 3 * y**3 + y / 7 x = 3 y = 2 self.assertAlmostEqual(f.value, 1 + 3 * x**2 + 4 * x + 3 * y**3 + y / 7) self.assertAlmostEqual(f.derivative[0], 6 * 3 + 4) self.assertAlmostEqual(f.derivative[1], 9 * 4 + 1 / 7)
def test__add__scalar_two_variable_objects(self): var1 = Variable(10.1, 2.1) var2 = Variable(9, 3) summation = var1 + var2 summation_reverse_order = var2 + var1 self.assertAlmostEqual(19.1, summation.value) self.assertAlmostEqual(19.1, summation_reverse_order.value) self.assertAlmostEqual(5.1, summation.derivative) self.assertAlmostEqual(5.1, summation_reverse_order.derivative)
def test_neg(self): var1 = Variable(9, 2) negation1 = -var1 var2 = Variable(-8, -1) negation2 = -var2 self.assertAlmostEqual(-9, negation1.value) self.assertAlmostEqual(-2, negation1.derivative) self.assertAlmostEqual(8, negation2.value) self.assertAlmostEqual(1, negation2.derivative)
def test__truediv__scalar_two_variable_objects(self): var1 = Variable(20.0, 2.0) var2 = Variable(10.0, 5.0) divided = var1 / var2 divided_reverse_order = var2 / var1 self.assertAlmostEqual(2, divided.value) self.assertAlmostEqual(-0.8, divided.derivative) self.assertAlmostEqual(.5, divided_reverse_order.value) self.assertAlmostEqual(.2, divided_reverse_order.derivative)
def test_pow_exception(self): with self.assertRaises(TypeError): result = Variable(6, 6.7)**'string' with self.assertRaises(ValueError): result = Variable(-1, 6.7)**45.7 with self.assertRaises(ValueError): result = Variable(0, 6)**-2 with self.assertRaises(ValueError): result = (-0.7)**Variable(2, 4) with self.assertRaises(ValueError): result = 0**Variable(-2, 0.45)
def test_power_abs_multivariate(self): x = Variable(5, np.array([1, 0])) y = Variable(3, np.array([0, 1])) f = abs(-x**(2 * y - 1)) x = 5 y = 3 self.assertAlmostEqual(f.value, abs(x**(2 * y - 1))) expected_derx = x**(y * 4 - 3) * (2 * y - 1) / abs(x**(2 * y - 1)) expected_dery = 2 * x**(4 * y - 2) * np.log(x) / abs(x**(2 * y - 1)) self.assertAlmostEqual(f.derivative[0], expected_derx) self.assertAlmostEqual(f.derivative[1], expected_dery)
def test_rational_multivariate(self): x = Variable(1, np.array([1, 0])) y = Variable(-2, np.array([0, 1])) f = 2 - 1 / (x * y * 5) + x**y - x / y - 1 x = 1 y = -2 self.assertAlmostEqual(f.value, 2 - 1 / (x * y * 5) + x**y - x / y - 1) self.assertAlmostEqual(f.derivative[0], y * x**(y - 1) + 1 / (5 * x**2 * y) - 1 / y) self.assertAlmostEqual( f.derivative[1], x**y * np.log(x) + x / y**2 + 1 / (5 * x * y**2))
def test_sub_sin_and_arcsin_scalar(self): value1 = -0.10 value2 = 1.51 var1 = Variable(value1, 5) var2 = Variable(value2, 3) equation = np.arcsin(var1) - np.sin(var2) expected_derivative = 1 * 5 / np.sqrt(1 - value1**2) - 3 * np.cos(value2) self.assertAlmostEqual( np.arcsin(value1) - np.sin(value2), equation.value) self.assertAlmostEqual(expected_derivative, equation.derivative)
def test_sub_scalar_two_variable_objects(self): var1 = Variable(10.1, 2.1) var2 = Variable(9, 3) substraction = var1 - var2 substraction_reverse_order = var2 - var1 self.assertAlmostEqual(1.1, round(substraction.value, 1)) self.assertAlmostEqual(-1.1, round(substraction_reverse_order.value, 1)) self.assertAlmostEqual(-0.9, round(substraction.derivative, 1)) self.assertAlmostEqual(0.9, round(substraction_reverse_order.derivative, 1))
def test_large_rational_poly_function_scalar(self): x = Variable(-0.6, 1) equation = 2 + 0.1 * x**(-6) + 0.7 * x**(5) - x**(10) self.assertAlmostEqual(4.08286, equation.value, places=4) self.assertAlmostEqual(21.98784, equation.derivative, places=4) x = Variable(0.6, 1) equation = 2 + 0.1 * x**(-0.6) + 0.7 * x**(1.2) - x**(10) self.assertAlmostEqual(2.509028, equation.value, places=4) self.assertAlmostEqual(0.52177, equation.derivative, places=4)
def test_add_cos_and_arccos_scalar(self): value1 = 0.92 value2 = 1.42 var1 = Variable(value1, 4) var2 = Variable(value2, 2) equation = np.arccos(var1) + np.cos(var2) expected_derivative = ( -1) * 4 / np.sqrt(1 - value1**2) - 2 * np.sin(value2) self.assertAlmostEqual( np.arccos(value1) + np.cos(value2), equation.value) self.assertAlmostEqual(expected_derivative, equation.derivative)
def test_log_with_base2_and_base5_multivariate(self): x = Variable(2, np.array([1, 0])) y = Variable(3, np.array([0, 1])) f = (x * y).log(2) + y.log(5) x = 2 y = 3 self.assertAlmostEqual( f.value, np.log(x * y) / np.log(2) + np.log(y) / np.log(5)) expected_derx = y / (x * y * np.log(2)) expected_dery = x / (x * y * np.log(2)) + 1 / (y * np.log(5)) self.assertAlmostEqual(f.derivative[0], expected_derx) self.assertAlmostEqual(f.derivative[1], expected_dery)
def test_mul_tanh_and_arctan_scalar(self): value1 = 5.0 value2 = 2.0 var1 = Variable(value1, 1) var2 = Variable(value2, 2) equation = np.arctan(var1) * np.tanh(var2) expected_derivative = np.arctan(value1) * ( 1 / (np.cosh(value2)**2) * 2) + np.tanh(value2) * (1 / (1 + value1**2) * 1) self.assertAlmostEqual( np.arctan(value1) * np.tanh(value2), equation.value) self.assertAlmostEqual(expected_derivative, equation.derivative)
def test_arccos_scalar_invalid_value(self): with self.assertRaises(ValueError) as e: var = Variable(18, 2) np.arccos(var) self.assertEqual( "Inputs to arccos should be in (-1, 1) for the derivative to be defined.", str(e.exception)) with self.assertRaises(ValueError) as e: var = Variable(-18, 2) np.arccos(var) self.assertEqual( "Inputs to arccos should be in (-1, 1) for the derivative to be defined.", str(e.exception))
def test_abs_vector(self): var = Variable(-12, np.array([7, 8])) x = Variable(-34, np.array([2, 0.5])) y = Variable(4, np.array([2.5, 0.5])) equation = np.cos(x) + np.sin(y) result = abs(var) equation_result = abs(equation) self.assertAlmostEqual(12, result.value) self.assertAlmostEqual(np.abs(equation.value), equation_result.value) np.testing.assert_array_almost_equal(var.derivative * -1, result.derivative) np.testing.assert_array_almost_equal(equation.derivative * -1, equation_result.derivative)
def test__pow__scalar(self): var = Variable(4, 3) result = var**3 reverse_result = 3**var combined_result = var**Variable(5, 0.7) self.assertAlmostEqual(4**3, result.value) self.assertAlmostEqual(var.derivative * 3 * (4**2), result.derivative) self.assertAlmostEqual(3**4, reverse_result.value) self.assertAlmostEqual(var.derivative * np.log(3) * (3**var.value), reverse_result.derivative) self.assertAlmostEqual(4**5, combined_result.value) self.assertAlmostEqual(4**5 * ((5 * 3 / 4) + (np.log(4) * 0.7)), combined_result.derivative)
def test_hyperbolic_multivariate(self): x = Variable(2.1, np.array([1, 0])) y = Variable(-1, np.array([0, 1])) f = -np.sinh(-x * y) + np.cosh(x / (x + y)) - np.tanh(1 - y) x = 2.1 y = -1 self.assertAlmostEqual( f.value, -np.sinh(-x * y) + np.cosh(x / (x + y)) - np.tanh(1 - y)) expected_derx = y * np.cosh(-x * y) + y * np.sinh(x / (x + y)) / (x + y)**2 expected_dery = x * np.cosh(-x * y) - x * np.sinh( x / (x + y)) / (x + y)**2 + 1 / np.cosh(1 - y)**2 self.assertAlmostEqual(f.derivative[0], expected_derx) self.assertAlmostEqual(f.derivative[1], expected_dery)
def test_log_exception(self): with self.assertRaises(ValueError) as e: Variable(-23, 9).log() self.assertEqual("Values for log should be greater than zero.", str(e.exception)) with self.assertRaises(ValueError) as e: Variable(4, 5).log(1) self.assertEqual( "Base should be greater than zero and not equal to 1.", str(e.exception)) with self.assertRaises(ValueError): Variable(4, 5).log(-2) self.assertEqual( "Base should be greater than zero and not equal to 1.", str(e.exception))
def test_exp_vector(self): var = Variable(5, np.array([1.5, 5.9])) x = Variable(3, np.array([5, 6])) y = Variable(1, np.array([-4, 3])) result = var.exp() equation = x + y**2 equation_result = equation.exp() self.assertAlmostEqual(np.exp(5), result.value) self.assertAlmostEqual(np.exp(equation.value), equation_result.value) np.testing.assert_array_almost_equal( np.exp(5) * np.array([1.5, 5.9]), result.derivative) np.testing.assert_array_almost_equal( np.exp(equation.value) * equation.derivative, equation_result.derivative)
def test_sqrt_vector(self): var = Variable(4, np.array([-1, 7])) x = Variable(4, np.array([9, 4])) y = Variable(0.1, np.array([0.5, 0.7])) equation = x - abs(y) result = var.sqrt() equation_result = equation.sqrt() self.assertAlmostEqual(np.sqrt(4), result.value) self.assertAlmostEqual(np.sqrt(equation.value), equation_result.value) np.testing.assert_array_almost_equal( (var.derivative * 0.5) * np.power(var.value, -0.5), result.derivative) np.testing.assert_array_almost_equal( (equation.derivative * 0.5) * np.power(equation.value, -0.5), equation_result.derivative)
def test_nested_function_composition_scalar(self): x = Variable(1.4, 1) equation = np.sin(np.log(np.cos(x**2 + 4)**5)) self.assertAlmostEqual(-0.262679, equation.value, places=4) self.assertAlmostEqual(4.52433, equation.derivative, places=4) equation = np.tan(x**(np.sinh(np.sqrt(x)))) self.assertAlmostEqual(-13.4525518, equation.value, places=4) self.assertAlmostEqual(392.29116, equation.derivative, places=4) equation = np.sqrt(x + np.exp(x / 2 - x**3 / 11)) self.assertAlmostEqual(1.723127, equation.value, places=4) self.assertAlmostEqual(0.27444, equation.derivative, places=4) equation = np.sqrt(x + np.exp(x / 2 - x**3 / 11)) self.assertAlmostEqual(1.723127, equation.value, places=4) self.assertAlmostEqual(0.27444, equation.derivative, places=4) equation = np.log(x**0.1 * np.cosh(x / (x**2 - x**3))) self.assertAlmostEqual(1.15394, equation.value, places=4) self.assertAlmostEqual(-5.35443, equation.derivative, places=4) equation = 3.5**(np.arcsin(x / 3) + 7) self.assertAlmostEqual(11820.37366, equation.value, places=4) self.assertAlmostEqual(5581.02262, equation.derivative, places=4) equation = np.arccos(np.arctan(-x**(1 / 3))) self.assertAlmostEqual(2.57059, equation.value, places=4) self.assertAlmostEqual(0.21888, equation.derivative, places=4) equation = np.sin(x)**(np.tanh(np.arccos(1 / x))) self.assertAlmostEqual(0.99051, equation.value, places=4) self.assertAlmostEqual(0.10492, equation.derivative, places=4)
def test_derivative_setter_numpy_array(self): var1 = Variable(1.2, np.array([0, 2.1, 0])) var1.derivative = np.array([0, 0, 1]) self.assertTrue(all(var1.derivative == np.array([0, 0, 1]))) with self.assertRaises(TypeError) as e: var = Variable(10.2, np.array([[0], [2], [0]])) self.assertEqual( 'Input derivative seed should be an int, float, or a 1D numpy array of ints/floats.', str(e.exception)) with self.assertRaises(TypeError) as e: var = Variable(10.2, np.array([1.1, 2, "s"])) self.assertEqual( 'Input derivative seed array contains non int/float values', str(e.exception))
def test_sub_and_cos_scalar(self): value = np.pi / 3 var = Variable(value, 1) equation = var - np.cos(var) self.assertAlmostEqual(value - np.cos(value), equation.value) self.assertAlmostEqual(1 + 1 * np.sin(value), equation.derivative)
def test_differentiate_univariate_vector_function(self): def func(x): f1 = x.logistic() f2 = x.log(base=2) f3 = x**2 f4 = 1 - x return np.array([f1, f2, f3, f4]) x = Variable(2, 1) val, der = differentiate(func, np.array([2])) val_expected = np.array([1 / (1 + np.exp(-2)), np.log2(2), 4, -1]) f1_der = [np.exp(-2) / (1 + np.exp(-2))**2] f2_der = [1 / (np.log(2) * 2)] f3_der = [2 * 2] f4_der = [-1] derivative_expected = np.array([f1_der, f2_der, f3_der, f4_der]) np.testing.assert_array_almost_equal(val, val_expected) np.testing.assert_array_almost_equal(der, derivative_expected) def func(x): f1 = x[0].logistic() f2 = x[0].log(base=2) f3 = x[0]**2 f4 = 1 - x[0] return np.array([f1, f2, f3, f4]) val, der = differentiate(func, np.array([2]), scalar=False) np.testing.assert_array_almost_equal(val, val_expected) np.testing.assert_array_almost_equal(der, derivative_expected)
def test_sqrt_scalar(self): var = Variable(4, -1) result = var.sqrt() self.assertAlmostEqual(np.sqrt(4), result.value) self.assertAlmostEqual((-1 * 0.5) * np.power(4, -0.5), result.derivative)