def numerical_gradient(iobj, pos0, delta_t=0.01 / 10.0 / 10.0, order=5): check_vector3(pos0) assert issubclass(type(iobj), vector3.ImplicitFunction) m = order # sample points: -m,...,-1,0,1,2,...,+m sample_points = range(-m, m + 1) n = m * 2 + 1 x0 = 0 findiff_weights = weights(k=1, x0=x0, xs=np.array(sample_points) * delta_t) pos = repeat_vect3(1, pos0) pos3 = np.tile(pos, (3 * n, 1)) assert not issubclass(pos.dtype.type, np.integer) dx = repeat_vect3(1, make_vector3(1, 0, 0)) dy = repeat_vect3(1, make_vector3(0, 1, 0)) dz = repeat_vect3(1, make_vector3(0, 0, 1)) dxyz = [dx, dy, dz] ci = 0 for d in range(3): for i in sample_points: dd = dxyz[d] pos3[ci, :] = pos3[ci, :] + (dd * delta_t * float(i)) ci += 1 v = iobj.implicitFunction(pos3) v3 = np.reshape(v, (3, n), order='C') Lipchitz_beta = 1 # order. Keep it 1 d0 = np.abs(np.diff(v3, axis=1)) nonsmooth_ness = d0 / (np.abs(delta_t)**Lipchitz_beta) d = np.abs(np.diff(v3, n=1, axis=1)) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1, keepdims=True), (1, d.shape[1])) d = np.abs(d) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1, keepdims=True), (1, d.shape[1])) if (np.max(np.ravel(nonsmooth_ness))) > 100 * 10: print "warning: nonsmooth ", """ Calculating the numerical derivative using finite difference (convolution with weights) """ # convolusion grad_cnv = np.dot(v3, findiff_weights) # Detecting sharp edges (non-smooth points, i.e. corners and edges and ridges) if np.max(np.abs(grad_cnv)) > 100: pass return grad_cnv.reshape(1, 3)
def test_gradients_using_numerical_gradient(self): def blend2(): m1 = np.eye(4) * 1 m1[0:3, 3] = [0, 1, 0] m1[3, 3] = 1 m2 = np.eye(4) * 2 m2[0:3, 3] = [2.5, 0, 0] m2[3, 3] = 1 iobj_v = vector3.SimpleBlend(vector3.Ellipsoid(m1), vector3.Ellipsoid(m2)) return iobj_v iobj_v = blend2() self.check_gradient_function(iobj_v, objname="blend2") examples_list = example_objects.get_all_examples([2]) for example_name in examples_list: sys.stderr.write("example_name = ", example_name) iobj = example_objects.make_example_vectorized(example_name) self.check_gradient_function(iobj, objname=example_name) """ numerical """ x = make_vector3(0, 2, 0) g2 = numerical_gradient(iobj_v, x) g = iobj_v.implicitGradient(repeat_vect3(1, x)) np.set_printoptions( formatter={'all': lambda x: '' + ("%2.19f" % (x, ))}) err = np.sum(np.abs(g - g2), axis=1) err_max = np.max(np.abs(g - g2), axis=1) err_rel = np.sum(np.abs(g - g2), axis=1) / np.mean(np.abs(g)) sys.stderr.write(err, err_max, err_rel) # print(err) self.assertTrue(np.all(err < NUMERICAL_GRADIENT_TOLERANCE))
def test_unit_cube1(self): """ Points inside or outside the unit cube [0,1]^3 """ count_inside = 0 count_outside = 0 my_cube = UnitCube1() for i in range(100): my_point = np.array( [np.random.randn(), np.random.randn(), np.random.randn()]) * 0.5 + 0.5 is_inside = ((my_point[0] >= 0 - 0.5) and (my_point[0] <= 1.0 - 0.5) and (my_point[1] >= 0 - 0.5) and (my_point[1] <= 1.0 - 0.5) and (my_point[2] >= 0 - 0.5) and (my_point[2] <= 1.0 - 0.5)) if is_inside: count_inside += 1 else: count_outside += 1 v2 = my_cube.implicitFunction((repeat_vect3(1, my_point)).reshape(3)) self.assertEqual(is_inside, v2 >= 0, 'A point on surface is wrongly classified') print "point count: inside, outside = ", count_inside, ",", count_outside
def check_gradient_function_point1(self, iobj, x, tolerance, objname): """Tests the gradient using numerical method, verify with analytical and vectorized-analytical""" assert iobj is not None if iobj is not None: g_numer_vec = numerical_gradient(iobj, x) from vector3 import ImplicitFunction assert issubclass(type(iobj), ImplicitFunction) g_vec = iobj.implicitGradient(repeat_vect3(1, x)) np.set_printoptions( formatter={'all': lambda x: '' + ("%2.7f" % (x, ))}) self.check_two_vectors( g_vec, g_numer_vec, tolerance, "vec numerical versus analytical gradients (%s)" % (objname, ))
def test_ellipsoid_random_points(self): """Testing hundreds of random points on a sphere of size RADIUS""" for i in range(0, 30): RADIUS = 3 POW = 4 # higher POW will get points more toward parallel to axes N = 500 rcenter = make_random_vector3(1000, 1.0) centers_a = repeat_vect3(N, rcenter) r0 = make_random_vector3_vectorized(N, RADIUS, POW) r = r0 + centers_a assert r.shape[1] == 3 xa = r m = np.eye(4) * RADIUS m[0:3, 3] = rcenter m[3, 3] = 1 expected_grad = -r0 check_vector3_vectorized(expected_grad) self.ellipsoid_point_and_gradient_vectorized(m, xa, expected_grad)
def numerical_gradient(iobj, pos0, delta_t=0.01/10.0/10.0, order=5): check_vector3(pos0) assert issubclass(type(iobj), vector3.ImplicitFunction) m = order _VERBOSE = False import finite_diff_weights sample_points = range(-m, m+1) n = m*2+1 x0 = 0 findiff_weights = finite_diff_weights.weights(k=1, x0=x0, xs=np.array(sample_points) * delta_t) pos0_3 = repeat_vect3(1, pos0) pos = np.tile(pos0_3, (3*n, 1)) assert not issubclass(pos.dtype.type, np.integer) dx = repeat_vect3(1, make_vector3(1, 0, 0)) dy = repeat_vect3(1, make_vector3(0, 1, 0)) dz = repeat_vect3(1, make_vector3(0, 0, 1)) dxyz = [dx, dy, dz] ci = 0 for d in range(3): for i in sample_points: dd = dxyz[d] pos[ci, :] = pos[ci, :] + (dd * delta_t * float(i)) ci += 1 v = iobj.implicitFunction(pos) v3 = np.reshape(v, (3, n), order='C') Lipchitz_beta = 1 d0 = np.abs(np.diff(v3, axis=1)) nonsmooth_ness = d0 / (np.abs(delta_t)**Lipchitz_beta) d = np.abs(np.diff(v3, n=1, axis=1)) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1, keepdims=True), (1, d.shape[1])) d = np.abs(d) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1, keepdims=True), (1, d.shape[1])) if(np.max(np.ravel(nonsmooth_ness))) > 100*10: print "warning: nonsmooth ", """ Calculating the numerical derivative using finite difference (convolution with weights) """ grad_cnv = np.dot(v3, findiff_weights) if np.max(np.abs(grad_cnv)) > 100: pass if _VERBOSE: np.set_printoptions(formatter={'all': lambda x: ''+("%2.19f" % (x,))}) """ Calculating the numerical derivative using 'mean of diff' """ grad_mean = np.mean(-np.diff(v3, axis=1) / delta_t, axis=1) if _VERBOSE: sys.stderr.write("grad_mean: ", grad_mean) sys.stderr.write("grad_convolusion: ", grad_cnv) if False: g = iobj.implicitGradient(pos0_3) if _VERBOSE: sys.stderr.write("grad_analytical: ", g) sys.stderr.write("Errors:") sys.stderr.write("conv error: ", g - grad_cnv) sys.stderr.write("to be continued") return grad_cnv
def test_ellipsoid_certain_points(self): """ Ellipsoid using vectorized calculations """ N = 10 _x = make_vector3(0, 0, 1) xa = repeat_vect3(N, _x) m = np.eye(4) # makeMatrix4( 1,0,0,0, 0,1,0,0, 0,0,1,0 ) m[0, 0] = 1 ga2 = repeat_vect3(N, make_vector3(0, 0, -1)) self.ellipsoid_point_and_gradient_vectorized(m, xa, ga2) m = np.eye(4) self.ellipsoid_point_and_gradient_vectorized( m, repeat_vect3(N, make_vector3(0, 1, 0)), repeat_vect3(N, make_vector3(0, -1, 0))) m = np.eye(4) self.ellipsoid_point_and_gradient_vectorized( m, repeat_vect3(N, make_vector3(1, 0, 0)), repeat_vect3(N, make_vector3(-1, 0, 0))) xa = repeat_vect3(N, make_vector3(0, 0, 2)) m = np.eye(4) m[2, 2] = 2 self.ellipsoid_point_and_gradient_vectorized( m, xa, repeat_vect3(N, make_vector3(0, 0, -1))) xa = repeat_vect3(N, make_vector3(2, 0, 0)) m = np.eye(4) m[0, 0] = 2 self.ellipsoid_point_and_gradient_vectorized( m, xa, repeat_vect3(N, make_vector3(-1, 0, 0))) xa = repeat_vect3(N, make_vector3(0, 2, 0)) m = np.eye(4) m[0, 0] = 2 m[1, 1] = 2 m[2, 2] = 2 self.ellipsoid_point_and_gradient_vectorized( m, xa, repeat_vect3(N, make_vector3(0, -2, 0)))