Exemple #1
0
    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 = RbfSettings()
        for i in range(50):
            dim = random.randint(1, 20)
            num_points = random.randint(10, 50)
            node_pos = np.array(
                [[random.uniform(-100, 100) for j in range(dim)]
                 for k in range(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)
                self.assertIsInstance(mat, np.matrix)
                self.assertAlmostEqual(np.max(mat - mat.transpose()),
                                       0.0,
                                       msg='RBF matrix is not symmetric')
                size = num_points + 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)
Exemple #2
0
 def test_get_degree_polynomial(self):
     """Verify that the degree is always between 0 and 1."""
     settings = RbfSettings()
     for rbf_type in self.rbf_types:
         settings.rbf = rbf_type
         degree = ru.get_degree_polynomial(settings)
         self.assertTrue(degree == 0 or degree == 1)
def get_model_quality_estimate_clp(settings, n, k, node_pos, node_val,
                                   num_iterations):
    """Compute an estimate of model quality using LPs with Clp.

    Computes an estimate of model quality, performing
    cross-validation. This version does not use all interpolation
    nodes, but rather only the best num_iterations ones, and it uses a
    sequence of LPs instead of a brute-force calculation. It should be
    much faster than the brute-force calculation, as each LP in the
    sequence requires only two pivots. The solver is COIN-OR Clp.

    Parameters
    ----------
    settings : :class:`rbfopt_settings.RbfSettings`
        Global and algorithmic settings.

    n : int
        Dimension of the problem, i.e. the space where the point lives.

    k : int
        Number of nodes, i.e. interpolation points.

    node_pos : 2D numpy.ndarray[float]
        Location of current interpolation nodes (one on each row).

    node_val : 1D numpy.ndarray[float]
        List of values of the function at the nodes.

    num_iterations : int
        Number of nodes on which quality should be tested.
    
    Returns
    -------
    float
        An estimate of the leave-one-out cross-validation error, which
        can be interpreted as a measure of model quality.

    Raises
    ------
    RuntimeError
        If the LPs cannot be solved.

    ValueError
        If some settings are not supported.
    """
    assert(isinstance(node_pos, np.ndarray))
    assert(isinstance(node_val, np.ndarray))
    assert(isinstance(settings, RbfSettings))
    assert(len(node_val) == k)
    assert(len(node_pos) == k)
    assert(num_iterations <= k)
    assert(cpx_available)
    # We cannot find a leave-one-out interpolant if the following
    # condition is not met.
    assert(k > n + 1)

    # Get size of polynomial part of the matrix (p) and sign of obj
    # function (sign)
    if (ru.get_degree_polynomial(settings) == 1):
        p = n + 1
        sign = 1
    elif (ru.get_degree_polynomial(settings) == 0):
        p = 1
        sign = -1
    else:
        raise ValueError('RBF type ' + settings.rbf + ' not supported')

    # Sort interpolation nodes by increasing objective function value
    sorted_idx = node_val.argsort()

    # Initialize the arrays used for the cross-validation
    cv_node_pos = node_pos[sorted_idx]
    cv_node_val = node_val[sorted_idx]

    # Compute the RBF matrix, and the two submatrices of interest
    Amat = ru.get_rbf_matrix(settings, n, k, cv_node_pos)
    Phimat = Amat[:k, :k]
    Pmat = Amat[:k, k:]
    identity = np.matrix(np.identity(k))

    # Instantiate model
    model = CyLPModel()

    # Add variables: lambda, h, slacks
    rbf_lambda = model.addVariable('rbf_lambda', k)
    rbf_h = model.addVariable('rbf_h', p)
    slack = model.addVariable('slack', k)

    # Add constraints: interpolation conditions, unisolvence
    F = CyLPArray(cv_node_val)
    zeros = CyLPArray([0] * p)
    ones = CyLPArray([1] * p)
    if (p > 1):
        # We can use matrix form
        model += (Phimat * rbf_lambda + Pmat * rbf_h + identity * slack == F)
        model += (Pmat.transpose() * rbf_lambda == zeros)
    else:
        # Workaround for one dimensional variables: one row at a time
        for i in range(k):
            model += Phimat[i, :] * rbf_lambda + rbf_h + slack[i] == F[i]
        model += (Pmat.transpose() * rbf_lambda == zeros)

    # Add objective
    obj = CyLPArray([sign*val for val in node_val])
    model.objective = obj * rbf_lambda
                           
    # Create LP, suppress output, and set bounds
    lp = clp.CyClpSimplex(model)
    lp.logLevel = 0
    infinity = lp.getCoinInfinity()
    for i in range(k + p):
        lp.setColumnLower(i, -infinity)
        lp.setColumnUpper(i, infinity)
    for i in range(k):
        lp.setColumnLower(k + p + i, 0.0)
        lp.setColumnUpper(k + p + i, 0.0)

    # Estimate of the model error
    loo_error = 0.0

    for i in range(num_iterations):
        # Fix lambda[i] to zero
        lp.setColumnLower(i, 0.0)
        lp.setColumnUpper(i, 0.0)
        # Set slack[i] to unconstrained
        lp.setColumnLower(k + p + i, -infinity)
        lp.setColumnUpper(k + p + i, infinity)

        lp.dual(startFinishOptions = 'sx')

        if (not lp.getStatusCode() == 0):
            raise RuntimeError('Could not solve LP with Clp, status ' +
                               lp.getStatusString())

        lambda_sol = lp.primalVariableSolution['rbf_lambda'].tolist()
        h_sol = lp.primalVariableSolution['rbf_h'].tolist()

        # Compute value of the interpolant at the removed node
        predicted_val = ru.evaluate_rbf(settings, cv_node_pos[i], n, k,
                                        cv_node_pos, lambda_sol, h_sol)

        # Update leave-one-out error
        loo_error += abs(predicted_val - cv_node_val[i])

        # Fix lambda[i] to zero
        lp.setColumnLower(i, -infinity)
        lp.setColumnUpper(i, infinity)
        # Set slack[i] to unconstrained
        lp.setColumnLower(k + p + i, 0.0)
        lp.setColumnUpper(k + p + i, 0.0)

    return loo_error/num_iterations
def get_model_quality_estimate_cpx(settings, n, k, node_pos, node_val,
                                   num_iterations):
    """Compute an estimate of model quality using LPs with Cplex.

    Computes an estimate of model quality, performing
    cross-validation. This version does not use all interpolation
    nodes, but rather only the best num_iterations ones, and it uses a
    sequence of LPs instead of a brute-force calculation. It should be
    much faster than the brute-force calculation, as each LP in the
    sequence requires only two pivots. The solver is IBM-ILOG Cplex.

    Parameters
    ----------
    settings : :class:`rbfopt_settings.RbfSettings`
        Global and algorithmic settings.

    n : int
        Dimension of the problem, i.e. the space where the point lives.

    k : int
        Number of nodes, i.e. interpolation points.

    node_pos : 2D numpy.ndarray[float]
        Location of current interpolation nodes (one on each row).

    node_val : 1D numpy.ndarray[float]
        List of values of the function at the nodes.

    num_iterations : int
        Number of nodes on which quality should be tested.
    
    Returns
    -------
    float
        An estimate of the leave-one-out cross-validation error, which
        can be interpreted as a measure of model quality.

    Raises
    ------
    RuntimeError
        If the LPs cannot be solved.

    ValueError
        If some settings are not supported.
    """
    assert(isinstance(node_pos, np.ndarray))
    assert(isinstance(node_val, np.ndarray))
    assert(isinstance(settings, RbfSettings))
    assert(len(node_val) == k)
    assert(len(node_pos) == k)
    assert(num_iterations <= k)
    assert(cpx_available)
    # We cannot find a leave-one-out interpolant if the following
    # condition is not met.
    assert(k > n + 1)

    # Get size of polynomial part of the matrix (p) and sign of obj
    # function (sign)
    if (ru.get_degree_polynomial(settings) == 1):
        p = n + 1
        sign = 1
    elif (ru.get_degree_polynomial(settings) == 0):
        p = 1
        sign = -1
    else:
        raise ValueError('RBF type ' + settings.rbf + ' not supported')

    # Sort interpolation nodes by increasing objective function value
    sorted_idx = node_val.argsort()

    # Initialize the arrays used for the cross-validation
    cv_node_pos = node_pos[sorted_idx]
    cv_node_val = node_val[sorted_idx]

    # Compute the RBF matrix
    Amat = ru.get_rbf_matrix(settings, n, k, cv_node_pos)

    # Instantiate model and suppress output
    lp = cpx.Cplex()
    lp.set_log_stream(None)
    lp.set_error_stream(None)
    lp.set_warning_stream(None)
    lp.set_results_stream(None)
    lp.cleanup(settings.eps_zero)
    lp.parameters.threads.set(1)
    # lp.parameters.simplex.display.set(2)

    # Add variables: lambda, h, slacks
    lp.variables.add(obj = [sign*val for val in node_val],
                     lb = [-cpx.infinity] * k,
                     ub = [cpx.infinity] * k)
    lp.variables.add(lb = [-cpx.infinity] * p,
                     ub = [cpx.infinity] * p)
    lp.variables.add(lb = [0] * k,
                     ub = [0] * k)

    # Add constraints: interpolation conditions, unisolvence
    expr = [cpx.SparsePair(ind = [j for j in range(k + p)] + [k + p + i],
                           val = [Amat[i, j] for j in range(k + p)] + [1.0])
            for i in range(k)]
    lp.linear_constraints.add(lin_expr = expr, senses = ['E'] * k,
                              rhs = cv_node_val)
    expr = [cpx.SparsePair(ind = [j for j in range(k + p)],
                           val = [Amat[i, j] for j in range(k + p)])
            for i in range(k, k + p)]
    lp.linear_constraints.add(lin_expr = expr, senses = ['E'] * p,
                              rhs = [0] * p)

    # Estimate of the model error
    loo_error = 0.0

    for i in range(num_iterations):
        # Fix lambda[i] to zero
        lp.variables.set_lower_bounds(i, 0.0)
        lp.variables.set_upper_bounds(i, 0.0)
        # Set slack[i] to unconstrained
        lp.variables.set_lower_bounds(k + p + i, -cpx.infinity)
        lp.variables.set_upper_bounds(k + p + i, cpx.infinity)

        lp.solve()

        if (not lp.solution.is_primal_feasible()):
            raise RuntimeError('Could not solve LP with Cplex')

        rbf_l = np.array(lp.solution.get_values(0, k - 1))
        rbf_h = np.array(lp.solution.get_values(k, k + p - 1))

        # Compute value of the interpolant at the removed node
        predicted_val = ru.evaluate_rbf(settings, cv_node_pos[i], n, k,
                                        cv_node_pos, rbf_l, rbf_h)

        # Update leave-one-out error
        loo_error += abs(predicted_val - cv_node_val[i])

        # Fix lambda[i] to zero
        lp.variables.set_lower_bounds(i, -cpx.infinity)
        lp.variables.set_upper_bounds(i, cpx.infinity)
        # Set slack[i] to unconstrained
        lp.variables.set_lower_bounds(k + p + i, 0.0)
        lp.variables.set_upper_bounds(k + p + i, 0.0)

    return loo_error/num_iterations
Exemple #5
0
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.RbfSettings`
        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, RbfSettings))
    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)
    model.Qlast = RangeSet(model.q - 1, 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=GAMMA)

    # Variable: the point in the space
    model.x = Var(model.N, domain=Reals, bounds=_x_bounds)

    # Auxiliary variables: the vectors (u, \pi),
    # see equations (6) and (7) in the paper by Costa and Nannicini
    model.u_pi = Var(model.Q, domain=Reals)

    # Auxiliary variable: value of the rbf at a given point
    model.rbfval = Var(domain=Reals)

    # Auxiliary variable: value of the inverse of \mu_k at a given point
    model.mindistsq = Var(domain=NonNegativeReals)

    # Objective function.
    model.OBJ = Objective(rule=_min_msrsm_obj_expression, sense=minimize)

    # Constraints. See definitions below.
    # Constraints. See definitions below.
    if (settings.rbf == 'linear'):
        model.UdefConstraint = Constraint(model.K,
                                          rule=_udef_linear_constraint_rule)
    elif (settings.rbf == 'multiquadric'):
        model.UdefConstraint = Constraint(model.K,
                                          rule=_udef_multiquad_constraint_rule)
    model.NonhomoConstraint = Constraint(model.Qlast,
                                         rule=_nonhomo_constraint_rule)
    model.RbfdefConstraint = Constraint(rule=_rbfdef_constraint_rule)
    model.MdistdefConstraint = Constraint(model.K,
                                          rule=_mdistdef_constraint_rule)

    # Add integer variables if necessary
    if (len(integer_vars) > 0):
        add_integrality_constraints(model, integer_vars)

    return model
Exemple #6
0
def create_min_bump_model(settings, n, k, Phimat, Pmat, node_val,
                          fast_node_index, fast_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 with
    index in fast_node_index deviate by a specified percentage from
    their value.

    Parameters
    ----------
    settings : :class:`rbfopt_settings.RbfSettings`
        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.
    
    fast_node_index : 1D numpy.ndarray[float]
        List of indices of nodes whose function value should be
        considered variable withing the allowed range.
    
    fast_node_err_bounds : List[(float, float)]
        Allowed deviation from node values for nodes affected by
        error. This is a list of pairs (lower, upper) of the same
        length as fast_node_index.

    Returns
    -------
    pyomo.ConcreteModel
        The concrete model describing the problem.
    """
    assert (isinstance(node_val, np.ndarray))
    assert (isinstance(fast_node_index, np.ndarray))
    assert (isinstance(settings, RbfSettings))
    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(fast_node_index) == len(fast_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 (pos, var_index) in enumerate(fast_node_index):
        slack_lower_param[var_index] = float(fast_node_err_bounds[pos][0])
        slack_upper_param[var_index] = float(fast_node_err_bounds[pos][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
Exemple #7
0
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.RbfSettings`
        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, RbfSettings))
    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)
    model.Qlast = RangeSet(model.q - 1, 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=GAMMA)

    # Variable: the point in the space
    model.x = Var(model.N, domain=Reals, bounds=_x_bounds)

    # Auxiliary variables: the vectors (u, \pi),
    # see equations (6) and (7) in the paper by Costa and Nannicini
    model.u_pi = Var(model.Q, domain=Reals)

    # Auxiliary variable: value of the rbf at a given point
    model.rbfval = Var(domain=Reals)

    # Auxiliary variable: value of the inverse of \mu_k at a given point
    model.mu_k_inv = Var(domain=Reals)

    # Objective function.
    model.OBJ = Objective(rule=_max_h_k_obj_expression, sense=maximize)

    # Constraints. See definitions below.
    if (settings.rbf == 'linear'):
        model.UdefConstraint = Constraint(model.K,
                                          rule=_udef_linear_constraint_rule)
    elif (settings.rbf == 'multiquadric'):
        model.UdefConstraint = Constraint(model.K,
                                          rule=_udef_multiquad_constraint_rule)
    model.NonhomoConstraint = Constraint(model.Qlast,
                                         rule=_nonhomo_constraint_rule)
    model.RbfdefConstraint = Constraint(rule=_rbfdef_constraint_rule)
    model.MukdefConstraint = Constraint(rule=_mukdef_constraint_rule)

    # Add integer variables if necessary
    if (len(integer_vars) > 0):
        add_integrality_constraints(model, integer_vars)

    return model
Exemple #8
0
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.RbfSettings`
        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, RbfSettings))
    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)
    model.Qlast = RangeSet(model.q - 1, 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)

    # Auxiliary variables: the vectors (u, \pi),
    # see equations (6) and (7) in the paper by Costa and Nannicini
    model.u_pi = Var(model.Q, domain=Reals)

    model.OBJ = Objective(rule=_min_rbf_obj_expression, sense=minimize)

    # Constraints. See definitions below.
    if (settings.rbf == 'linear'):
        model.UdefConstraint = Constraint(model.K,
                                          rule=_udef_linear_constraint_rule)
    elif (settings.rbf == 'multiquadric'):
        model.UdefConstraint = Constraint(model.K,
                                          rule=_udef_multiquad_constraint_rule)
    model.NonhomoConstraint = Constraint(model.Qlast,
                                         rule=_nonhomo_constraint_rule)

    # Add integer variables if necessary
    if (len(integer_vars) > 0):
        add_integrality_constraints(model, integer_vars)

    return model
Exemple #9
0
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.RbfSettings`
        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 + 1, k + 1))
    assert (isinstance(settings, RbfSettings))
    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)
    model.Qlast = RangeSet(model.q - 1, model.q - 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 + 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)

    # 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=GAMMA)

    # Variable: the point in the space
    model.x = Var(model.N, domain=Reals, bounds=_x_bounds)

    # Auxiliary variables: the vectors (u, \pi),
    # see equations (6) and (7) in the paper by Costa and Nannicini
    model.u_pi = Var(model.Q, domain=Reals)

    # Objective function. Remember that there should be a constant
    # term \phi(0) at the beginning, but because this is zero in this
    # case we take it out.
    model.OBJ = Objective(rule=_max_one_over_mu_obj_expression, sense=maximize)

    # Constraints. See definitions below.
    if (settings.rbf == 'linear'):
        model.UdefConstraint = Constraint(model.K,
                                          rule=_udef_linear_constraint_rule)
    elif (settings.rbf == 'multiquadric'):
        model.UdefConstraint = Constraint(model.K,
                                          rule=_udef_multiquad_constraint_rule)
    model.NonhomoConstraint = Constraint(model.Qlast,
                                         rule=_nonhomo_constraint_rule)

    # Add integer variables if necessary
    if (len(integer_vars) > 0):
        add_integrality_constraints(model, integer_vars)

    return model