def test_auto_diff_square(self): """Test automatic differentiation using dual numbers for the square function. f(x) = x^2 f'(x) = d/dx f(x) = 2x """ ga = GeometricAlgebra(metric=dual_metric) one = ga.from_scalar(1.0) five = ga.from_scalar(5.0) eps = ga.from_tensor_with_kind(tf.ones(1), kind="pseudoscalar") x = one + eps # f(1) = 1^2 = 1, f'(1) = 2 x_squared = ga.geom_prod(x, x) self.assertTensorsEqual(ga.select_blades_with_name(x_squared, ""), 1.0) self.assertTensorsEqual(ga.select_blades_with_name(x_squared, "0"), 2.0) y = five + eps # f(5) = 5^2 = 25, f'(5) = 10 y_squared = ga.geom_prod(y, y) self.assertTensorsEqual(ga.select_blades_with_name(y_squared, ""), 25.0) self.assertTensorsEqual(ga.select_blades_with_name(y_squared, "0"), 10.0)
def test_mul_inverse(self): ga = GeometricAlgebra(metric=dual_metric) # a = 2 a = ga.from_tensor_with_kind(tf.fill([1], 2.0), kind="scalar") # b = 3 + 3e0 b = ga.from_tensor_with_kind(tf.fill([2], 3.0), kind="mv") # a * b = 2 * (3 + 3e0) = 6 + 6e0 c = ga.geom_prod(a, b) self.assertTensorsEqual(c, ga.from_scalar(6.0) + 6.0 * ga.e("0")) # a^-1 = 1 / 2 a_inv = ga.inverse(a) self.assertTensorsEqual(ga.select_blades_with_name(a_inv, ""), 0.5) # c = a * b # => a_inv * c = b self.assertTensorsEqual(ga.geom_prod(a_inv, c), b) # Since a is scalar, should commute too. # => c * a_inv = b self.assertTensorsEqual(ga.geom_prod(c, a_inv), b) # b is not simply invertible (because it does not square to a scalar) # and will throw an exception self.assertRaises(Exception, ga.simple_inverse, b) # b is invertible with the shirokov inverse b_inv = ga.inverse(b) self.assertTensorsEqual(ga.geom_prod(b, b_inv), 1 * ga.e(""))