def test_get_noisy_rbf_coefficients(self): """Check solution of noisy RBF coefficients problem. This function verifies that the solution of the convex problem that computes the RBF coefficients for a noisy interpolant on a small test istance satisfies the (noisy) interpolation conditions. """ ref = [0.0] node_err_bounds = np.array([[0, 0], [0, 0], [-1.0, 1.0], [-1.0, 1.0], [-1.0, 1.0]]) (l, h) = aux.get_noisy_rbf_coefficients(self.settings, self.n, self.k, self.Amat[:self.k, :self.k], self.Amat[:self.k, self.k:], self.node_val, node_err_bounds, self.rbf_lambda, self.rbf_h) for i in range(self.k): if (node_err_bounds[i, 1] - node_err_bounds[i, 0] > 0): # Verify interpolation conditions for noisy nodes val = ru.evaluate_rbf(self.settings, self.node_pos[i], self.n, self.k, self.node_pos, l, h) lb = self.node_val[i] + node_err_bounds[i, 0] ub = self.node_val[i] + node_err_bounds[i, 1] self.assertLessEqual(lb, val, msg='Node value outside bounds') self.assertGreaterEqual(ub, val, msg='Node value outside bounds') else: # Verify interpolation conditions for regular (exact) nodes val = ru.evaluate_rbf(self.settings, self.node_pos[i], self.n, self.k, self.node_pos, l, h) self.assertAlmostEqual(self.node_val[i], val, msg='Node value does not match')
def test_rbf_interpolation(self): """Test interpolation conditions. Verify that the RBF interpolates at points. """ settings = RbfoptSettings() for i in range(20): dim = np.random.randint(1, 20) num_points = np.random.randint(dim + 1, 50) node_pos = np.random.uniform(-100, 100, size=(num_points, dim)) node_val = np.random.uniform(0, 100, num_points) # Possible shapes of the matrix for rbf_type in self.rbf_types: settings.rbf = rbf_type mat = ru.get_rbf_matrix(settings, dim, num_points, node_pos) rbf_l, rbf_h = ru.get_rbf_coefficients(settings, dim, num_points, mat, node_val) for i in range(num_points): value = ru.evaluate_rbf(settings, node_pos[i], dim, num_points, node_pos, rbf_l, rbf_h) self.assertAlmostEqual(value, node_val[i], places=3, msg='Interpolation failed' + 'with rbf ' + rbf_type)
def test_minimize_rbf_random(self): """Check solution of RBF minimization problem on random instances. This function verifies that the solution of the RBF minimization problem on small random problems is always no worse than he best interpolation node. """ for i in range(10): n = np.random.randint(4, 10) k = np.random.randint(n + 1, n + 10) var_lower = np.array([-5] * n) var_upper = np.array([5] * n) integer_vars = np.sort(np.random.choice(n, np.random.randint(n))) node_pos = np.random.uniform(-5, 5, size=(k, n)) node_pos[:, integer_vars] = np.around(node_pos[:, integer_vars]) node_val = np.random.uniform(-10, 10, size=k) best_node_pos = np.argmin(node_val) for rbf_type in self.rbf_types: settings = RbfoptSettings(rbf=rbf_type) A = ru.get_rbf_matrix(settings, n, k, node_pos) rbf_l, rbf_h = ru.get_rbf_coefficients(settings, n, k, A, node_val) sol = aux.minimize_rbf(settings, n, k, var_lower, var_upper, integer_vars, None, node_pos, rbf_l, rbf_h, node_pos[best_node_pos]) val = ru.evaluate_rbf(settings, sol, n, k, node_pos, rbf_l, rbf_h) self.assertLessEqual(val, node_val[best_node_pos] + 1.0e-3, msg='The minimize_rbf solution' + ' is worse than starting point' + ' with rbf ' + rbf_type)
def test_get_model_quality_estimate(self): """Test the get_model_quality_estimate function. """ for rbf in [ 'cubic', 'thin_plate_spline', 'multiquadric', 'linear', 'gaussian' ]: settings = RbfoptSettings(rbf=rbf) error = ru.get_model_quality_estimate(settings, self.n, self.k, self.node_pos, self.node_val, self.k) # Create a copy of the interpolation nodes and values sorted_idx = self.node_val.argsort() sorted_node_val = self.node_val[sorted_idx] # Initialize the arrays used for the cross-validation cv_node_pos = self.node_pos[sorted_idx[1:]] cv_node_val = self.node_val[sorted_idx[1:]] # The node that was left out rm_node_pos = self.node_pos[sorted_idx[0]] rm_node_val = self.node_val[sorted_idx[0]] # Estimate of the model error loo_error = 0.0 for i in range(self.k): # Compute the RBF interpolant with one node left out Amat = ru.get_rbf_matrix(settings, self.n, self.k - 1, cv_node_pos) rbf_l, rbf_h = ru.get_rbf_coefficients(settings, self.n, self.k - 1, Amat, cv_node_val) # Compute value of the interpolant at the removed node predicted_val = ru.evaluate_rbf(settings, rm_node_pos, self.n, self.k - 1, cv_node_pos, rbf_l, rbf_h) # Update leave-one-out error loc = np.searchsorted(sorted_node_val, predicted_val) loo_error += abs(loc - i) # Update the node left out if (i < self.k - 1): tmp = cv_node_pos[i].copy() cv_node_pos[i] = rm_node_pos rm_node_pos = tmp cv_node_val[i], rm_node_val = rm_node_val, cv_node_val[i] self.assertAlmostEqual(loo_error, error, msg='Model selection procedure ' + 'miscomputed the error')
def test_minimize_rbf(self): """Check solution of RBF minimization problem. This function verifies that the solution of the RBF minimization problem on a small test istance is close to one of two pre-computed solution, for all algorithms. It also checks that integer variables are integer valued. """ solutions = { 'Gutmann': [[0.0, 1.0, 2.0], [10.0, 1.0, 2.0]], 'MSRSM': [[0.0, 1.0, 2.0], [10.0, 1.0, 2.0]] } for algorithm in RbfoptSettings._allowed_algorithm: self.settings.algorithm = algorithm references = solutions[algorithm] sol = aux.minimize_rbf(self.settings, self.n, self.k, self.var_lower, self.var_upper, self.integer_vars, None, self.node_pos, self.rbf_lambda, self.rbf_h, self.node_pos[0]) val = ru.evaluate_rbf(self.settings, sol, self.n, self.k, self.node_pos, self.rbf_lambda, self.rbf_h) found_solution = False for ref in references: satisfied = True for i in range(self.n): tolerance = 1.0e-3 lb = ref[i] - tolerance ub = ref[i] + tolerance if (lb > sol[i] or ub < sol[i]): satisfied = False if satisfied: found_solution = True self.assertTrue(found_solution, msg='The minimize_rbf solution' + ' with algorithm {:s}'.format(algorithm) + ' does not match any known local optimum') for i in self.integer_vars: msg = ('Variable {:d} not integer in solution'.format(i) + ' alg {:s} '.format(algorithm)) self.assertAlmostEqual(abs(sol[i] - round(sol[i])), 0.0, msg=msg)
def test_rbf_interpolation_cat(self): """Test interpolation conditions with categorical variables. Verify that the RBF interpolates at points. """ settings = RbfoptSettings() for i in range(20): dim = np.random.randint(5, 15) cat_dim = 8 # We need enough points to ensure the system is not singular num_points = np.random.randint(2 * (dim + cat_dim), 60) node_pos = np.hstack((np.random.uniform(-100, 100, size=(num_points, dim)), np.zeros(shape=(num_points, cat_dim)))) # Pick random categorical values for j in range(num_points): node_pos[j, dim + np.random.choice(4)] = 1 node_pos[j, dim + 4 + np.random.choice(4)] = 1 categorical_info = (np.array([0, 1]), np.array([j + 2 for j in range(dim)]), [(0, 0, np.array([dim + j for j in range(4)])), (1, 0, np.array([dim + 4 + j for j in range(4)]))]) node_val = np.random.uniform(0, 100, num_points) # Possible shapes of the matrix for rbf_type in self.rbf_types: settings.rbf = rbf_type mat = ru.get_rbf_matrix(settings, dim + cat_dim, num_points, node_pos) rbf_l, rbf_h = ru.get_rbf_coefficients(settings, dim + cat_dim, num_points, mat, node_val, categorical_info) for i in range(num_points): value = ru.evaluate_rbf(settings, node_pos[i], dim + cat_dim, num_points, node_pos, rbf_l, rbf_h) self.assertAlmostEqual(value, node_val[i], places=4, msg='Interpolation failed ' + 'with rbf ' + rbf_type)
def test_get_model_quality_estimate(self): """Test the get_model_quality_estimate function. """ for rbf in ['cubic', 'thin_plate_spline', 'multiquadric', 'linear', 'gaussian']: settings = RbfoptSettings(rbf=rbf) error = ru.get_model_quality_estimate( settings, self.n, self.k, self.node_pos, self.node_val, self.k) # Create a copy of the interpolation nodes and values sorted_idx = self.node_val.argsort() sorted_node_val = self.node_val[sorted_idx] # Initialize the arrays used for the cross-validation cv_node_pos = self.node_pos[sorted_idx[1:]] cv_node_val = self.node_val[sorted_idx[1:]] # The node that was left out rm_node_pos = self.node_pos[sorted_idx[0]] rm_node_val = self.node_val[sorted_idx[0]] # Estimate of the model error loo_error = 0.0 for i in range(self.k): # Compute the RBF interpolant with one node left out Amat = ru.get_rbf_matrix(settings, self.n, self.k-1, cv_node_pos) rbf_l, rbf_h = ru.get_rbf_coefficients( settings, self.n, self.k-1, Amat, cv_node_val) # Compute value of the interpolant at the removed node predicted_val = ru.evaluate_rbf(settings, rm_node_pos, self.n, self.k-1, cv_node_pos, rbf_l, rbf_h) # Update leave-one-out error loc = np.searchsorted(sorted_node_val, predicted_val) loo_error += abs(loc - i) # Update the node left out if (i < self.k - 1): tmp = cv_node_pos[i].copy() cv_node_pos[i] = rm_node_pos rm_node_pos = tmp cv_node_val[i], rm_node_val = rm_node_val, cv_node_val[i] self.assertAlmostEqual(loo_error, error, msg='Model selection procedure ' + 'miscomputed the error')
def test_rbf_interpolation(self): """Test interpolation conditions. Verify that the RBF interpolates at points. """ settings = RbfoptSettings() for i in range(20): dim = np.random.randint(1, 20) num_points = np.random.randint(10, 50) node_pos = np.random.uniform(-100, 100, size=(num_points,dim)) node_val = np.random.uniform(0, 100, num_points) # Possible shapes of the matrix for rbf_type in self.rbf_types: settings.rbf = rbf_type mat = ru.get_rbf_matrix(settings, dim, num_points, node_pos) rbf_l, rbf_h = ru.get_rbf_coefficients( settings, dim, num_points, mat, node_val) for i in range(num_points): value = ru.evaluate_rbf(settings, node_pos[i], dim, num_points, node_pos, rbf_l, rbf_h) self.assertAlmostEqual(value, node_val[i], places=4, msg='Interpolation failed' + 'with rbf ' + rbf_type)