|
| 1 | +import numpy as np |
| 2 | + |
| 3 | +#Preconditioner generator - returns our preconditioner and its coefficients (the preconditioner is of the form aI + b e^Te) |
| 4 | +#n = number of data points |
| 5 | +#c = shape parameter for the RBFs - we are safe to use 1 here, but feel free to adjust to your liking. |
| 6 | +#distribution - if your data is uniformly distributed in the unit hypercube/unit sphere, select accordingly. Otherwise we take k=1. |
| 7 | + |
| 8 | +def precon_generator(n,c,RBF,distribution): |
| 9 | + if distribution == 'cube': |
| 10 | + k=1 |
| 11 | + if distribution =='ball': |
| 12 | + k=np.sqrt(2) |
| 13 | + else: |
| 14 | + k=1 |
| 15 | + |
| 16 | + if RBF == 'Gaussian': |
| 17 | + phi_rt2 = Gaussian(k,c) |
| 18 | + if RBF == 'MQ': |
| 19 | + phi_rt2 = MQ(k,c) |
| 20 | + if RBF == 'MQ_inv': |
| 21 | + phi_rt2 = MQ_inv(k,c) |
| 22 | + if RBF == 'Quadratic_inv': |
| 23 | + phi_rt2 = Quadratic_inv(k,c) |
| 24 | + const_1 = phi_rt2 / ((phi_rt2-c)*(c-phi_rt2+n*phi_rt2)) |
| 25 | + const_2 = 1 / (phi_rt2-c) |
| 26 | + |
| 27 | + preconditioner = const_1 * np.ones((n,n)) - const_2 * np.eye(n) |
| 28 | + |
| 29 | + return preconditioner, const_1, const_2 |
| 30 | + |
| 31 | +#A function that evaluates our interpolant using |
| 32 | +#coefficients - generated from the PCG algorithm output |
| 33 | +#centers - the same centers we used to generate the coefficients |
| 34 | +#x_value - the point we want to evaluate our interpolant at |
| 35 | +#RBF_type - make sure to use the same RBF type as the one used to generate the interpolant. |
| 36 | + |
| 37 | +#returns the value of the interpolant. |
| 38 | + |
| 39 | +def interp(coefficients, centers, x_value, RBF_type): |
| 40 | + if RBF_type == 'Gaussian': |
| 41 | + center_vector = [Gaussian(x_value - center,1) for center in centers] |
| 42 | + if RBF_type == 'MQ': |
| 43 | + center_vector = [MQ(x_value - center,1) for center in centers] |
| 44 | + if RBF_type == 'MQ_inv': |
| 45 | + center_vector = [MQ_inv(x_value - center,1) for center in centers] |
| 46 | + if RBF_type == 'Quadratic_inv': |
| 47 | + center_vector = [Quadratic_inv(x_value - center,1) for center in centers] |
| 48 | + |
| 49 | + return coefficients.T @ center_vector |
| 50 | + |
| 51 | + |
| 52 | +#RBF functions - note that our algorithm is not certain to converge for the multiquadric (MQ) as the interpolation matrix generated is not positive definite. |
| 53 | +def MQ(point,c): |
| 54 | + return np.sqrt(c**2+np.linalg.norm(point)) |
| 55 | + |
| 56 | +def Gaussian(point, c): |
| 57 | + return np.exp(-c * np.linalg.norm(point)) |
| 58 | + |
| 59 | +def MQ_inv(point,c): |
| 60 | + return 1/np.sqrt(c**2+np.linalg.norm(point)) |
| 61 | + |
| 62 | +def Quadratic_inv(point,c): |
| 63 | + return 1/(c**2+np.linalg.norm(point)) |
| 64 | + |
| 65 | +#interpolation matrix generator |
| 66 | +def interpolation_matrix_generator(RBF_type, data): |
| 67 | + phi = np.ones((len(data),len(data))) |
| 68 | + for i, point in enumerate(data): |
| 69 | + for j, center in enumerate(data): |
| 70 | + phi[i,j] = np.linalg.norm(point-center) |
| 71 | + |
| 72 | + if RBF_type == 'Gaussian': |
| 73 | + vectorized_function = np.vectorize(Gaussian) |
| 74 | + if RBF_type == 'MQ': |
| 75 | + vectorized_function = np.vectorize(MQ) |
| 76 | + if RBF_type == 'MQ_inv': |
| 77 | + vectorized_function = np.vectorize(MQ_inv) |
| 78 | + if RBF_type == 'Quadratic_inv': |
| 79 | + vectorized_function = np.vectorize(Quadratic_inv) |
| 80 | + |
| 81 | + return vectorized_function(phi,1) |
| 82 | + |
| 83 | + |
| 84 | +#data generator for a range of underlying distributions. |
| 85 | +def points_in_unit_ball(n,d): |
| 86 | + cube = np.random.standard_normal(size=(n, d)) |
| 87 | + norms = np.linalg.norm(cube,axis=1) |
| 88 | + surface_sphere = cube/norms[:,np.newaxis] |
| 89 | + scales = np.random.uniform(0,1, size= n) |
| 90 | + points = surface_sphere * (scales[:, np.newaxis])**(1/d) |
| 91 | + return points |
| 92 | + |
| 93 | +def points_integer_grid(n,d, s_min, s_max): |
| 94 | + points = np.random.randint(s_min,s_max, size = (n,d)) |
| 95 | + return points |
| 96 | + |
| 97 | +def points_in_cube(n,d,normalised): |
| 98 | + points = np.random.uniform(0,1,size=(n,d)) |
| 99 | + if normalised == 'no': |
| 100 | + return points |
| 101 | + if normalised == 'yes': |
| 102 | + return points/np.sqrt(d/6-17/120) |
| 103 | + |
| 104 | +def points_normal(n,d): |
| 105 | + points = np.random.normal(0,1,size=(n,d)) |
| 106 | + return points |
| 107 | + |
0 commit comments