def test_linear_algebra(self): a_scalar = AD(1, [1., 0]) b_scalar = AD(2, [0, 1.]) A = np.array([[a_scalar, a_scalar]]) B = np.array([[b_scalar, b_scalar]]).T C = np.dot(A, B) npc.assert_equal(C, [[AD(4, [4., 2])]]) # `matmul` not supported for `dtype=object` (#11332). `np.dot` should # be used instead. with self.assertRaises(TypeError): C2 = np.matmul(A, B) # Type mixing Bf = np.array([[2., 2]]).T C2 = np.dot(A, Bf) # Leverages implicit casting. npc.assert_equal(C2, [[AD(4, [4., 0])]]) # Other methods. X = np.array([[a_scalar, b_scalar], [b_scalar, a_scalar]]) npc.assert_equal(np.trace(X), AD(2, [2., 0])) # `inv` is a ufunc that we must implement, if possible. However, given # that this is currently `dtype=object`, it would be extremely unwise # to do so. See #8116 for alternative. with self.assertRaises(TypeError): Y = np.linalg.inv(X) # Use workaround for inverse. For now, just check values. X_float = npc.to_float(X) Xinv_float = np.linalg.inv(X_float) Xinv = drake_math.inv(X) np.testing.assert_equal(npc.to_float(Xinv), Xinv_float)
def check_overload(self, overload): # TODO(eric.cousineau): Consider comparing against `numpy` ufunc # methods. import pydrake.math as drake_math unary = [ (drake_math.log, math.log), (drake_math.abs, math.fabs), (drake_math.exp, math.exp), (drake_math.sqrt, math.sqrt), (drake_math.sin, math.sin), (drake_math.cos, math.cos), (drake_math.tan, math.tan), (drake_math.asin, math.asin), (drake_math.acos, math.acos), (drake_math.atan, math.atan), (drake_math.sinh, math.sinh), (drake_math.cosh, math.cosh), (drake_math.tanh, math.tanh), (drake_math.ceil, math.ceil), (drake_math.floor, math.floor), ] binary = [ (drake_math.min, min), (drake_math.max, max), (drake_math.pow, pow), (drake_math.atan2, math.atan2), ] # Arbitrary values to test overloads with. args_float_all = [0.1, 0.2] def check_eval(functions, nargs): # Generate arguments. args_float = args_float_all[:nargs] args_T = list(map(overload.to_type, args_float)) # Check each supported function. for f_drake, f_builtin in functions: if not overload.supports(f_drake): continue debug_print("- Functions: ", qualname(f_drake), qualname(f_builtin)) y_builtin = f_builtin(*args_float) y_float = f_drake(*args_float) debug_print(" - - Float Eval:", repr(y_builtin), repr(y_float)) self.assertEqual(y_float, y_builtin) self.assertIsInstance(y_float, float) # Test method current overload, and ensure value is accurate. y_T = f_drake(*args_T) y_T_float = overload.to_float(y_T) debug_print(" - - Overload Eval:", repr(y_T), repr(y_T_float)) self.assertIsInstance(y_T, overload.T) # - Ensure the translated value is accurate. self.assertEqual(y_T_float, y_float) debug_print("\n\nOverload: ", qualname(type(overload))) float_overload = FloatOverloads() # Check each number of arguments. debug_print("Unary:") check_eval(unary, 1) debug_print("Binary:") check_eval(binary, 2) # Check specialized linear / array algebra. if overload.supports(drake_math.inv): f_drake, f_builtin = drake_math.inv, np.linalg.inv X_float = np.eye(2) Y_builtin = f_builtin(X_float) Y_float = f_drake(X_float) self.assertIsInstance(Y_float[0, 0].item(), float) np.testing.assert_equal(Y_builtin, Y_float) to_type_array = np.vectorize(overload.to_type) to_float_array = np.vectorize(overload.to_float) X_T = to_type_array(X_float) Y_T = drake_math.inv(X_T) self.assertIsInstance(Y_T[0, 0], overload.T) np.testing.assert_equal(to_float_array(Y_T), Y_float)
def check_overload(self, overload): # TODO(eric.cousineau): Consider comparing against `numpy` ufunc # methods. import pydrake.math as drake_math unary = [ (drake_math.log, math.log), (drake_math.abs, math.fabs), (drake_math.exp, math.exp), (drake_math.sqrt, math.sqrt), (drake_math.sin, math.sin), (drake_math.cos, math.cos), (drake_math.tan, math.tan), (drake_math.asin, math.asin), (drake_math.acos, math.acos), (drake_math.atan, math.atan), (drake_math.sinh, math.sinh), (drake_math.cosh, math.cosh), (drake_math.tanh, math.tanh), (drake_math.ceil, math.ceil), (drake_math.floor, math.floor), ] binary = [ (drake_math.min, min), (drake_math.max, max), (drake_math.pow, pow), (drake_math.atan2, math.atan2), ] # Arbitrary values to test overloads with. args_float_all = [0.1, 0.2] def check_eval(functions, nargs): # Generate arguments. args_float = args_float_all[:nargs] args_T = list(map(overload.to_type, args_float)) # Check each supported function. for f_drake, f_builtin in functions: if not overload.supports(f_drake): continue debug_print( "- Functions: ", qualname(f_drake), qualname(f_builtin)) y_builtin = f_builtin(*args_float) y_float = f_drake(*args_float) debug_print(" - - Float Eval:", repr(y_builtin), repr(y_float)) self.assertEqual(y_float, y_builtin) self.assertIsInstance(y_float, float) # Test method current overload, and ensure value is accurate. y_T = f_drake(*args_T) y_T_float = overload.to_float(y_T) debug_print(" - - Overload Eval:", repr(y_T), repr(y_T_float)) self.assertIsInstance(y_T, overload.T) # - Ensure the translated value is accurate. self.assertEqual(y_T_float, y_float) debug_print("\n\nOverload: ", qualname(type(overload))) float_overload = FloatOverloads() # Check each number of arguments. debug_print("Unary:") check_eval(unary, 1) debug_print("Binary:") check_eval(binary, 2) # Check specialized linear / array algebra. if overload.supports(drake_math.inv): f_drake, f_builtin = drake_math.inv, np.linalg.inv X_float = np.eye(2) Y_builtin = f_builtin(X_float) Y_float = f_drake(X_float) self.assertIsInstance(Y_float[0, 0].item(), float) np.testing.assert_equal(Y_builtin, Y_float) to_type_array = np.vectorize(overload.to_type) to_float_array = np.vectorize(overload.to_float) X_T = to_type_array(X_float) Y_T = drake_math.inv(X_T) self.assertIsInstance(Y_T[0, 0], overload.T) np.testing.assert_equal(to_float_array(Y_T), Y_float)