def test_get_rbf_matrix(self): """Test basic properties of the RBF matrix (e.g. symmetry, size). Verify that the RBF matrix is symmetric and it has the correct size for all types of RBF. """ settings = RbfoptSettings() for i in range(50): dim = np.random.randint(1, 20) num_points = np.random.randint(10, 50) node_pos = np.random.uniform(-100, 100, size=(num_points, dim)) # 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) self.assertIsInstance(mat, np.ndarray) self.assertEqual(len(mat.shape), 2) self.assertAlmostEqual(np.max(mat - mat.transpose()), 0.0, msg='RBF matrix is not symmetric') size = num_points if (ru.get_degree_polynomial(settings) >= 0): size += 1 if (ru.get_degree_polynomial(settings) > 0): size += dim**ru.get_degree_polynomial(settings) self.assertEqual(mat.shape, (size, size)) # Check that exception is raised for unknown RBF types settings.rbf = 'unknown' self.assertRaises(ValueError, ru.get_rbf_matrix, settings, dim, num_points, node_pos)
def test_get_rbf_matrix(self): """Test basic properties of the RBF matrix (e.g. symmetry, size). Verify that the RBF matrix is symmetric and it has the correct size for all types of RBF. """ settings = RbfoptSettings() for i in range(50): dim = np.random.randint(1, 20) num_points = np.random.randint(10, 50) node_pos = np.random.uniform(-100, 100, size=(num_points,dim)) # 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) self.assertIsInstance(mat, np.matrix) self.assertAlmostEqual(np.max(mat - mat.transpose()), 0.0, msg='RBF matrix is not symmetric') size = num_points if (ru.get_degree_polynomial(settings) >= 0): size += 1 if (ru.get_degree_polynomial(settings) > 0): size += dim ** ru.get_degree_polynomial(settings) self.assertEqual(mat.shape, (size, size)) # Check that exception is raised for unknown RBF types settings.rbf = 'unknown' self.assertRaises(ValueError, ru.get_rbf_matrix, settings, dim, num_points, node_pos)
def test_get_degree_polynomial(self): """Verify that the degree is always between 0 and 1.""" settings = RbfoptSettings() for rbf_type in self.rbf_types: settings.rbf = rbf_type degree = ru.get_degree_polynomial(settings) self.assertTrue(-1 <= degree <= 1)
def create_min_msrsm_model(settings, n, k, var_lower, var_upper, integer_vars, node_pos, rbf_lambda, rbf_h, dist_weight, dist_min, dist_max, fmin, fmax): """Create the concrete model to optimize the MSRSM objective. Create the concreate model to minimize a weighted combination of the value of the RBF interpolant and the (negative of the) distance from the closes interpolation node. This is the Global Search Step of the MSRSM method. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes (one on each row). rbf_lambda : 1D numpy.ndarray[float] The lambda coefficients of the RBF interpolant, corresponding to the radial basis functions. List of dimension k. rbf_h : 1D numpy.ndarray[float] The h coefficients of the RBF interpolant, corresponding to the polynomial. List of dimension n+1. dist_weight : float The weight paramater for distance and RBF interpolant value. Must be between 0 and 1. A weight of 1.0 corresponds to using solely distance, 0.0 to objective function. dist_min : float The minimum distance between two interpolation nodes. dist_max : float The maximum distance between two interpolation nodes. fmin : float The minimum value of an interpolation node. fmax : float The maximum value of an interpolation node. Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert (isinstance(var_lower, np.ndarray)) assert (isinstance(var_upper, np.ndarray)) assert (isinstance(integer_vars, np.ndarray)) assert (isinstance(node_pos, np.ndarray)) assert (isinstance(rbf_lambda, np.ndarray)) assert (isinstance(rbf_h, np.ndarray)) assert (len(var_lower) == n) assert (len(var_upper) == n) assert (len(rbf_lambda) == k) assert (len(rbf_h) == 1) assert (len(node_pos) == k) assert (isinstance(settings, RbfoptSettings)) assert (ru.get_degree_polynomial(settings) == 0) assert (0 <= dist_weight <= 1) assert (dist_max >= dist_min >= 0) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Dimension of u_pi model.q = Param(initialize=(k + 1)) model.Q = RangeSet(0, model.q - 1) # Coefficients of the RBF lambda_h_param = {} for i in range(k): lambda_h_param[i] = float(rbf_lambda[i]) for i in range(1): lambda_h_param[k + i] = float(rbf_h[i]) model.lambda_h = Param(model.Q, initialize=lambda_h_param) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Adjust parameters to avoid zero denominators in expressions if (fmax <= fmin + settings.eps_zero): fmax = fmin + 1 if (dist_max <= dist_min + settings.eps_zero): dist_min = dist_max - 1 # Minimum and maximum distance model.dist_min = Param(initialize=dist_min) model.dist_max = Param(initialize=dist_max) # Minimum and maximum of function values interpolation nodes model.fmin = Param(initialize=fmin) model.fmax = Param(initialize=fmax) # Weight of the distance and objective criteria model.dist_weight = Param(initialize=dist_weight) model.obj_weight = Param( initialize=(1.0 if settings.modified_msrsm_score else 1 - dist_weight)) # Value of phi at zero, necessary for shift if (settings.rbf == 'linear'): model.phi_0 = Param(initialize=0.0) elif (settings.rbf == 'multiquadric'): model.phi_0 = Param(initialize=settings.rbf_shape_parameter) model.gamma = Param(initialize=settings.rbf_shape_parameter) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) # Auxiliary variable: value of the minimum distance to the nodes model.mindistsq = Var(domain=NonNegativeReals, bounds=(settings.min_dist, float('inf'))) # Objective function. if (settings.rbf == 'linear'): model.OBJ = Objective(rule=_min_msrsm_obj_expression_linear, sense=minimize) elif (settings.rbf == 'multiquadric'): model.OBJ = Objective(rule=_min_msrsm_obj_expression_mq, sense=minimize) model.MdistdefConstraint = Constraint(model.K, rule=_mdistdef_constraint_rule) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) return model
def create_min_bump_model(settings, n, k, Phimat, Pmat, node_val, node_err_bounds): """Create a model to find RBF coefficients with min bumpiness. Create a quadratic problem to compute the coefficients of the RBF interpolant that minimizes bumpiness and lets all points deviate by a specified amount from their value. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. Phimat : numpy.matrix Matrix Phi, i.e. top left part of the standard RBF matrix. Pmat : numpy.matrix Matrix P, i.e. top right part of the standard RBF matrix. node_val : 1D numpy.ndarray[float] List of values of the function at the nodes. node_err_bounds : 2D numpy.ndarray[float] Allowed deviation from node values for nodes affected by error. This is a matrix with rows (lower_deviation, upper_deviation). Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert (isinstance(settings, RbfoptSettings)) assert (isinstance(node_val, np.ndarray)) assert (isinstance(node_err_bounds, np.ndarray)) assert (len(node_val) == k) assert (isinstance(Phimat, np.matrix)) assert (isinstance(Pmat, np.matrix)) assert (Phimat.shape == (k, k)) assert (Pmat.shape == (k, 1)) assert (len(node_val) == len(node_err_bounds)) assert (ru.get_degree_polynomial(settings) == 0) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Dimension of P matrix model.p = Param(initialize=1) model.P = RangeSet(0, 0) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Node values, i.e. right hand sides of the first set of equations # in the constraints node_val_param = {} for i in range(k): node_val_param[i] = node_val[i] model.node_val = Param(model.K, initialize=node_val_param) # Variable bounds slack_lower_param = {} slack_upper_param = {} for i in np.where(node_err_bounds[:, 1] - node_err_bounds[:, 0] > settings.eps_zero)[0]: slack_lower_param[i] = float(node_err_bounds[i, 0]) slack_upper_param[i] = float(node_err_bounds[i, 1]) model.slack_lower = Param(model.K, initialize=slack_lower_param, default=0.0) model.slack_upper = Param(model.K, initialize=slack_upper_param, default=0.0) # Phi matrix. Phi_param = {} for i in range(k): for j in range(k): if (abs(Phimat[i, j]) != 0.0): Phi_param[i, j] = float(Phimat[i, j]) model.Phi = Param(model.K, model.K, initialize=Phi_param, default=0.0) # P matrix. Pm_param = {} for i in range(k): for j in range(1): if (abs(Pmat[i, j]) != 0.0): Pm_param[i, j] = float(Pmat[i, j]) model.Pm = Param(model.K, model.P, initialize=Pm_param, default=0.0) # Variable: the lambda coefficients of the RBF model.rbf_lambda = Var(model.K, domain=Reals) # Variable: the h coefficients of the RBF model.rbf_h = Var(model.P, domain=Reals) # Variable: the slacks for the equality constraints model.slack = Var(model.K, domain=Reals, bounds=_slack_bounds) # Objective function. model.OBJ = Objective(rule=_min_bump_obj_expression, sense=minimize) # Constraints. See definitions below. model.IntrConstraint = Constraint(model.K, rule=_intr_constraint_rule) model.UnisConstraint = Constraint(model.P, rule=_unis_constraint_rule) return model
def create_max_h_k_model(settings, n, k, var_lower, var_upper, integer_vars, node_pos, rbf_lambda, rbf_h, mat, target_val): """Create the abstract model to maximize h_k. Create the abstract model to maximize h_k, also known as the Global Search Step of the RBF method. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes (one on each row). rbf_lambda : 1D numpy.ndarray[float] The lambda coefficients of the RBF interpolant, corresponding to the radial basis functions. List of dimension k. rbf_h : 1D numpy.ndarray[float] The h coefficients of the RBF interpolant, corresponding to the polynomial. List of dimension n+1. mat: numpy.matrix The matrix necessary for the computation. This is the inverse of the matrix [Phi P; P^T 0], see paper as cited above. Must be a numpy.matrix of dimension ((k+1) x (k+1)) target_val : float Value f* that we want to find in the unknown objective function. Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert (isinstance(var_lower, np.ndarray)) assert (isinstance(var_upper, np.ndarray)) assert (isinstance(integer_vars, np.ndarray)) assert (isinstance(node_pos, np.ndarray)) assert (isinstance(rbf_lambda, np.ndarray)) assert (isinstance(rbf_h, np.ndarray)) assert (len(var_lower) == n) assert (len(var_upper) == n) assert (len(rbf_lambda) == k) assert (len(rbf_h) == 1) assert (len(node_pos) == k) assert (isinstance(mat, np.matrix)) assert (mat.shape == (k + 1, k + 1)) assert (isinstance(settings, RbfoptSettings)) assert (ru.get_degree_polynomial(settings) == 0) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Dimension of the matrix model.q = Param(initialize=(k + 1)) model.Q = RangeSet(0, model.q - 1) # Coefficients of the RBF lambda_h_param = {} for i in range(k): lambda_h_param[i] = float(rbf_lambda[i]) for i in range(1): lambda_h_param[k + i] = float(rbf_h[i]) model.lambda_h = Param(model.Q, initialize=lambda_h_param) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Inverse of the matrix [Phi P; P^T 0]. Because the matrix is # symmetric, we only save the upper right part, while doubling the # off-diagonal elements. Ainv_param = {} for i in range(k + 1): for j in range(i, k + 1): if (abs(mat[i, j]) != 0.0): if (i == j): Ainv_param[i, j] = float(mat[i, j]) else: Ainv_param[i, j] = float(2 * mat[i, j]) model.Ainv = Param(model.Q, model.Q, initialize=Ainv_param, default=0.0) # Target value model.fstar = Param(initialize=target_val) # Value of phi at zero, necessary for shift if (settings.rbf == 'linear'): model.phi_0 = Param(initialize=0.0) elif (settings.rbf == 'multiquadric'): model.phi_0 = Param(initialize=settings.rbf_shape_parameter) model.gamma = Param(initialize=settings.rbf_shape_parameter) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) # Objective function. if (settings.rbf == 'linear'): model.OBJ = Objective(rule=_max_h_k_obj_expression_linear, sense=maximize) elif (settings.rbf == 'multiquadric'): model.OBJ = Objective(rule=_max_h_k_obj_expression_mq, sense=maximize) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) return model
def create_min_rbf_model(settings, n, k, var_lower, var_upper, integer_vars, node_pos, rbf_lambda, rbf_h): """Create the concrete model to minimize the RBF. Create the concrete model to minimize the RBF. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes. rbf_lambda : 1D numpy.ndarray[float] The lambda coefficients of the RBF interpolant, corresponding to the radial basis functions. List of dimension k. rbf_h : 1D numpy.ndarray[float] The h coefficients of the RBF interpolant, corresponding to the polynomial. List of dimension n+1. Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert (isinstance(var_lower, np.ndarray)) assert (isinstance(var_upper, np.ndarray)) assert (isinstance(integer_vars, np.ndarray)) assert (isinstance(node_pos, np.ndarray)) assert (isinstance(rbf_lambda, np.ndarray)) assert (isinstance(rbf_h, np.ndarray)) assert (len(var_lower) == n) assert (len(var_upper) == n) assert (len(rbf_lambda) == k) assert (len(rbf_h) == 1) assert (len(node_pos) == k) assert (isinstance(settings, RbfoptSettings)) assert (ru.get_degree_polynomial(settings) == 0) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Dimension of u_pi model.q = Param(initialize=(k + 1)) model.Q = RangeSet(0, model.q - 1) # Coefficients of the RBF lambda_h_param = {} for i in range(k): lambda_h_param[i] = float(rbf_lambda[i]) for i in range(1): lambda_h_param[k + i] = float(rbf_h[i]) model.lambda_h = Param(model.Q, initialize=lambda_h_param) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) if (settings.rbf == 'linear'): model.OBJ = Objective(rule=_min_rbf_obj_expression_linear, sense=minimize) elif (settings.rbf == 'multiquadric'): model.gamma = Param(initialize=settings.rbf_shape_parameter) model.OBJ = Objective(rule=_min_rbf_obj_expression_mq, sense=minimize) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) return model
def create_max_one_over_mu_model(settings, n, k, var_lower, var_upper, integer_vars, node_pos, mat): """Create the concrete model to maximize 1/\mu. Create the concrete model to maximize :math: `1/\mu`, also known as the InfStep of the RBF method. See paper by Costa and Nannicini, equation (7) pag 4, and the references therein. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes (one on each row). mat: numpy.matrix The matrix necessary for the computation. This is the inverse of the matrix [Phi P; P^T 0], see paper as cited above. Must be a numpy.matrix of dimension ((k+1) x (k+1)) Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert (isinstance(var_lower, np.ndarray)) assert (isinstance(var_upper, np.ndarray)) assert (isinstance(integer_vars, np.ndarray)) assert (isinstance(node_pos, np.ndarray)) assert (len(var_lower) == n) assert (len(var_upper) == n) assert (len(node_pos) == k) assert (isinstance(mat, np.matrix)) assert (mat.shape == (k, k)) assert (isinstance(settings, RbfoptSettings)) assert (ru.get_degree_polynomial(settings) == -1) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Inverse of the matrix [Phi P; P^T 0]. Because the matrix is # symmetric, we only save the upper right part, while doubling the # off-diagonal elements. Ainv_param = {} for i in range(k): for j in range(i, k): if (abs(mat[i, j]) != 0.0): if (i == j): Ainv_param[i, j] = float(mat[i, j]) else: Ainv_param[i, j] = float(2 * mat[i, j]) model.Ainv = Param(model.K, model.K, initialize=Ainv_param, default=0.0) if (settings.rbf == 'gaussian'): model.phi_0 = Param(initialize=1.0) model.gamma = Param(initialize=settings.rbf_shape_parameter) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) # Objective function. if (settings.rbf == 'gaussian'): model.OBJ = Objective(rule=_max_one_over_mu_obj_expression_gaussian, sense=maximize) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) return model
def create_min_rbf_model(settings, n, k, var_lower, var_upper, integer_vars, categorical_info, node_pos, rbf_lambda, rbf_h): """Create the concrete model to minimize the RBF. Create the concrete model to minimize the RBF. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. categorical_info : (1D numpy.ndarray[int], 1D numpy.ndarray[int], List[(int, 1D numpy.ndarray[int])]) or None Information on categorical variables: array of indices of categorical variables in original space, array of indices of noncategorical variables in original space, and expansion of each categorical variable, given as a tuple (original index, indices of expanded variables). node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes (one on each row). rbf_lambda : 1D numpy.ndarray[float] The lambda coefficients of the RBF interpolant, corresponding to the radial basis functions. List of dimension k. rbf_h : 1D numpy.ndarray[float] The h coefficients of the RBF interpolant, corresponding to the polynomial. List of dimension n+1. Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert (isinstance(var_lower, np.ndarray)) assert (isinstance(var_upper, np.ndarray)) assert (isinstance(integer_vars, np.ndarray)) assert (isinstance(node_pos, np.ndarray)) assert (isinstance(rbf_lambda, np.ndarray)) assert (isinstance(rbf_h, np.ndarray)) assert (len(var_lower) == n) assert (len(var_upper) == n) assert (len(rbf_lambda) == k) assert (len(rbf_h) == (n + 1)) assert (len(node_pos) == k) assert (isinstance(settings, RbfoptSettings)) assert (ru.get_degree_polynomial(settings) == 1) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Dimension of u_pi model.q = Param(initialize=(n + k + 1)) model.Q = RangeSet(0, model.q - 1) # Coefficients of the RBF lambda_h_param = {} for i in range(k): lambda_h_param[i] = float(rbf_lambda[i]) for i in range(n + 1): lambda_h_param[k + i] = float(rbf_h[i]) model.lambda_h = Param(model.Q, initialize=lambda_h_param) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) # Objective function if (settings.rbf == 'cubic'): model.OBJ = Objective(rule=_min_rbf_obj_expression_cubic, sense=minimize) elif (settings.rbf == 'thin_plate_spline'): model.OBJ = Objective(rule=_min_rbf_obj_expression_tps, sense=minimize) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) # Add categorical variables if necessary if (categorical_info is not None and categorical_info[2]): add_categorical_constraints(model, *categorical_info) return model
def create_min_msrsm_model(settings, n, k, var_lower, var_upper, integer_vars, node_pos, rbf_lambda, rbf_h, dist_weight, dist_min, dist_max, fmin, fmax): """Create the concrete model to optimize the MSRSM objective. Create the concreate model to minimize a weighted combination of the value of the RBF interpolant and the (negative of the) distance from the closes interpolation node. This is the Global Search Step of the MSRSM method. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes (one on each row). rbf_lambda : 1D numpy.ndarray[float] The lambda coefficients of the RBF interpolant, corresponding to the radial basis functions. List of dimension k. rbf_h : 1D numpy.ndarray[float] The h coefficients of the RBF interpolant, corresponding to the polynomial. List of dimension n+1. dist_weight : float The weight paramater for distance and RBF interpolant value. Must be between 0 and 1. A weight of 1.0 corresponds to using solely distance, 0.0 to objective function. dist_min : float The minimum distance between two interpolation nodes. dist_max : float The maximum distance between two interpolation nodes. fmin : float The minimum value of an interpolation node. fmax : float The maximum value of an interpolation node. Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert(isinstance(var_lower, np.ndarray)) assert(isinstance(var_upper, np.ndarray)) assert(isinstance(integer_vars, np.ndarray)) assert(isinstance(node_pos, np.ndarray)) assert(isinstance(rbf_lambda, np.ndarray)) assert(isinstance(rbf_h, np.ndarray)) assert(len(var_lower) == n) assert(len(var_upper) == n) assert(len(rbf_lambda) == k) assert(len(rbf_h) == 1) assert(len(node_pos) == k) assert(isinstance(settings, RbfoptSettings)) assert(ru.get_degree_polynomial(settings) == 0) assert(0 <= dist_weight <= 1) assert(dist_max >= dist_min >= 0) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Dimension of u_pi model.q = Param(initialize=(k+1)) model.Q = RangeSet(0, model.q - 1) # Coefficients of the RBF lambda_h_param = {} for i in range(k): lambda_h_param[i] = float(rbf_lambda[i]) for i in range(1): lambda_h_param[k+i] = float(rbf_h[i]) model.lambda_h = Param(model.Q, initialize=lambda_h_param) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Adjust parameters to avoid zero denominators in expressions if (fmax <= fmin + settings.eps_zero): fmax = fmin + 1 if (dist_max <= dist_min + settings.eps_zero): dist_min = dist_max - 1 # Minimum and maximum distance model.dist_min = Param(initialize=dist_min) model.dist_max = Param(initialize=dist_max) # Minimum and maximum of function values interpolation nodes model.fmin = Param(initialize=fmin) model.fmax = Param(initialize=fmax) # Weight of the distance and objective criteria model.dist_weight = Param(initialize=dist_weight) model.obj_weight = Param(initialize=(1.0 if settings.modified_msrsm_score else 1 - dist_weight)) # Value of phi at zero, necessary for shift if (settings.rbf == 'linear'): model.phi_0 = Param(initialize=0.0) elif (settings.rbf == 'multiquadric'): model.phi_0 = Param(initialize=settings.rbf_shape_parameter) model.gamma = Param(initialize=settings.rbf_shape_parameter) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) # Auxiliary variable: value of the minimum distance to the nodes model.mindistsq = Var(domain=NonNegativeReals, bounds=(settings.min_dist,float('inf'))) # Objective function. if (settings.rbf == 'linear'): model.OBJ = Objective(rule=_min_msrsm_obj_expression_linear, sense=minimize) elif (settings.rbf == 'multiquadric'): model.OBJ = Objective(rule=_min_msrsm_obj_expression_mq, sense=minimize) model.MdistdefConstraint = Constraint(model.K, rule=_mdistdef_constraint_rule) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) return model
def create_min_bump_model(settings, n, k, Phimat, Pmat, node_val, node_err_bounds): """Create a model to find RBF coefficients with min bumpiness. Create a quadratic problem to compute the coefficients of the RBF interpolant that minimizes bumpiness and lets all points deviate by a specified amount from their value. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. Phimat : numpy.matrix Matrix Phi, i.e. top left part of the standard RBF matrix. Pmat : numpy.matrix Matrix P, i.e. top right part of the standard RBF matrix. node_val : 1D numpy.ndarray[float] List of values of the function at the nodes. node_err_bounds : 2D numpy.ndarray[float] Allowed deviation from node values for nodes affected by error. This is a matrix with rows (lower_deviation, upper_deviation). Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert(isinstance(settings, RbfoptSettings)) assert(isinstance(node_val, np.ndarray)) assert(isinstance(node_err_bounds, np.ndarray)) assert(len(node_val) == k) assert(isinstance(Phimat, np.matrix)) assert(isinstance(Pmat, np.matrix)) assert(Phimat.shape == (k, k)) assert(Pmat.shape == (k, 1)) assert(len(node_val) == len(node_err_bounds)) assert(ru.get_degree_polynomial(settings) == 0) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Dimension of P matrix model.p = Param(initialize=1) model.P = RangeSet(0, 0) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Lower and upper bounds on node values, i.e. bounds for the first # set of equations in the constraints node_val_lower_param = {} node_val_upper_param = {} for i in range(k): node_val_lower_param[i] = float(node_val[i] + node_err_bounds[i, 0]) node_val_upper_param[i] = float(node_val[i] + node_err_bounds[i, 1]) model.node_val_lower = Param(model.K, initialize=node_val_lower_param) model.node_val_upper = Param(model.K, initialize=node_val_upper_param) # Phi matrix. Phi_param = {} for i in range(k): for j in range(k): if (abs(Phimat[i, j]) != 0.0): Phi_param[i, j] = float(Phimat[i, j]) model.Phi = Param(model.K, model.K, initialize=Phi_param, default=0.0) # P matrix. Pm_param = {} for i in range(k): for j in range(1): if (abs(Pmat[i, j]) != 0.0): Pm_param[i, j] = float(Pmat[i, j]) model.Pm = Param(model.K, model.P, initialize=Pm_param, default=0.0) # Variable: the lambda coefficients of the RBF model.rbf_lambda = Var(model.K, domain=Reals) # Variable: the h coefficients of the RBF model.rbf_h = Var(model.P, domain=Reals) # Objective function. model.OBJ = Objective(rule=_min_bump_obj_expression, sense=minimize) # Constraints. See definitions below. model.IntrConstraint = Constraint(model.K, rule=_intr_constraint_rule) model.UnisConstraint = Constraint(model.P, rule=_unis_constraint_rule) return model
def create_max_h_k_model(settings, n, k, var_lower, var_upper, integer_vars, node_pos, rbf_lambda, rbf_h, mat, target_val): """Create the abstract model to maximize h_k. Create the abstract model to maximize h_k, also known as the Global Search Step of the RBF method. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes (one on each row). rbf_lambda : 1D numpy.ndarray[float] The lambda coefficients of the RBF interpolant, corresponding to the radial basis functions. List of dimension k. rbf_h : 1D numpy.ndarray[float] The h coefficients of the RBF interpolant, corresponding to the polynomial. List of dimension n+1. mat: numpy.matrix The matrix necessary for the computation. This is the inverse of the matrix [Phi P; P^T 0], see paper as cited above. Must be a numpy.matrix of dimension ((k+1) x (k+1)) target_val : float Value f* that we want to find in the unknown objective function. Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert(isinstance(var_lower, np.ndarray)) assert(isinstance(var_upper, np.ndarray)) assert(isinstance(integer_vars, np.ndarray)) assert(isinstance(node_pos, np.ndarray)) assert(isinstance(rbf_lambda, np.ndarray)) assert(isinstance(rbf_h, np.ndarray)) assert(len(var_lower) == n) assert(len(var_upper) == n) assert(len(rbf_lambda) == k) assert(len(rbf_h) == 1) assert(len(node_pos) == k) assert(isinstance(mat, np.matrix)) assert(mat.shape == (k+1, k+1)) assert(isinstance(settings, RbfoptSettings)) assert(ru.get_degree_polynomial(settings) == 0) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Dimension of the matrix model.q = Param(initialize=(k+1)) model.Q = RangeSet(0, model.q - 1) # Coefficients of the RBF lambda_h_param = {} for i in range(k): lambda_h_param[i] = float(rbf_lambda[i]) for i in range(1): lambda_h_param[k+i] = float(rbf_h[i]) model.lambda_h = Param(model.Q, initialize=lambda_h_param) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Inverse of the matrix [Phi P; P^T 0]. Because the matrix is # symmetric, we only save the upper right part, while doubling the # off-diagonal elements. Ainv_param = {} for i in range(k+1): for j in range(i, k+1): if (abs(mat[i, j]) != 0.0): if (i == j): Ainv_param[i, j] = float(mat[i, j]) else: Ainv_param[i, j] = float(2*mat[i, j]) model.Ainv = Param(model.Q, model.Q, initialize=Ainv_param, default=0.0) # Target value model.fstar = Param(initialize=target_val) # Value of phi at zero, necessary for shift if (settings.rbf == 'linear'): model.phi_0 = Param(initialize=0.0) elif (settings.rbf == 'multiquadric'): model.phi_0 = Param(initialize=settings.rbf_shape_parameter) model.gamma = Param(initialize=settings.rbf_shape_parameter) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) # Objective function. if (settings.rbf == 'linear'): model.OBJ = Objective(rule=_max_h_k_obj_expression_linear, sense=maximize) elif (settings.rbf == 'multiquadric'): model.OBJ = Objective(rule=_max_h_k_obj_expression_mq, sense=maximize) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) return model
def create_min_rbf_model(settings, n, k, var_lower, var_upper, integer_vars, node_pos, rbf_lambda, rbf_h): """Create the concrete model to minimize the RBF. Create the concrete model to minimize the RBF. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes. rbf_lambda : 1D numpy.ndarray[float] The lambda coefficients of the RBF interpolant, corresponding to the radial basis functions. List of dimension k. rbf_h : 1D numpy.ndarray[float] The h coefficients of the RBF interpolant, corresponding to the polynomial. List of dimension n+1. Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert(isinstance(var_lower, np.ndarray)) assert(isinstance(var_upper, np.ndarray)) assert(isinstance(integer_vars, np.ndarray)) assert(isinstance(node_pos, np.ndarray)) assert(isinstance(rbf_lambda, np.ndarray)) assert(isinstance(rbf_h, np.ndarray)) assert(len(var_lower) == n) assert(len(var_upper) == n) assert(len(rbf_lambda) == k) assert(len(rbf_h) == 1) assert(len(node_pos) == k) assert(isinstance(settings, RbfoptSettings)) assert(ru.get_degree_polynomial(settings) == 0) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Dimension of u_pi model.q = Param(initialize=(k+1)) model.Q = RangeSet(0, model.q - 1) # Coefficients of the RBF lambda_h_param = {} for i in range(k): lambda_h_param[i] = float(rbf_lambda[i]) for i in range(1): lambda_h_param[k+i] = float(rbf_h[i]) model.lambda_h = Param(model.Q, initialize=lambda_h_param) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) if (settings.rbf == 'linear'): model.OBJ = Objective(rule=_min_rbf_obj_expression_linear, sense=minimize) elif (settings.rbf == 'multiquadric'): model.gamma = Param(initialize=settings.rbf_shape_parameter) model.OBJ = Objective(rule=_min_rbf_obj_expression_mq, sense=minimize) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) return model
def create_max_one_over_mu_model(settings, n, k, var_lower, var_upper, integer_vars, node_pos, mat): """Create the concrete model to maximize 1/\mu. Create the concrete model to maximize :math: `1/\mu`, also known as the InfStep of the RBF method. See paper by Costa and Nannicini, equation (7) pag 4, and the references therein. Parameters ---------- settings : :class:`rbfopt_settings.RbfoptSettings` Global and algorithmic settings. n : int The dimension of the problem, i.e. size of the space. k : int Number of nodes, i.e. interpolation points. var_lower : 1D numpy.ndarray[float] Vector of variable lower bounds. var_upper : 1D numpy.ndarray[float] Vector of variable upper bounds. integer_vars : 1D numpy.ndarray[int] List of indices of integer variables. node_pos : 2D numpy.ndarray[float] List of coordinates of the nodes (one on each row). mat: numpy.matrix The matrix necessary for the computation. This is the inverse of the matrix [Phi P; P^T 0], see paper as cited above. Must be a numpy.matrix of dimension ((k+1) x (k+1)) Returns ------- pyomo.ConcreteModel The concrete model describing the problem. """ assert(isinstance(var_lower, np.ndarray)) assert(isinstance(var_upper, np.ndarray)) assert(isinstance(integer_vars, np.ndarray)) assert(isinstance(node_pos, np.ndarray)) assert(len(var_lower) == n) assert(len(var_upper) == n) assert(len(node_pos) == k) assert(isinstance(mat, np.matrix)) assert(mat.shape == (k, k)) assert(isinstance(settings, RbfoptSettings)) assert(ru.get_degree_polynomial(settings) == -1) model = ConcreteModel() # Dimension of the space model.n = Param(initialize=n) model.N = RangeSet(0, model.n - 1) # Number of interpolation nodes model.k = Param(initialize=k) model.K = RangeSet(0, model.k - 1) # Coordinates of the nodes node_param = {} for i in range(k): for j in range(n): node_param[i, j] = float(node_pos[i][j]) model.node = Param(model.K, model.N, initialize=node_param) # Variable bounds var_lower_param = {} var_upper_param = {} for i in range(n): var_lower_param[i] = float(var_lower[i]) var_upper_param[i] = float(var_upper[i]) model.var_lower = Param(model.N, initialize=var_lower_param) model.var_upper = Param(model.N, initialize=var_upper_param) # Inverse of the matrix [Phi P; P^T 0]. Because the matrix is # symmetric, we only save the upper right part, while doubling the # off-diagonal elements. Ainv_param = {} for i in range(k): for j in range(i, k): if (abs(mat[i, j]) != 0.0): if (i == j): Ainv_param[i, j] = float(mat[i, j]) else: Ainv_param[i, j] = float(2*mat[i, j]) model.Ainv = Param(model.K, model.K, initialize=Ainv_param, default=0.0) if (settings.rbf == 'gaussian'): model.phi_0 = Param(initialize=1.0) model.gamma = Param(initialize=settings.rbf_shape_parameter) # Variable: the point in the space model.x = Var(model.N, domain=Reals, bounds=_x_bounds) # Objective function. if (settings.rbf == 'gaussian'): model.OBJ = Objective(rule=_max_one_over_mu_obj_expression_gaussian, sense=maximize) # Add integer variables if necessary if (len(integer_vars)): add_integrality_constraints(model, integer_vars) return model