5.3.3. QP Modeling and Optimization in C++ΒΆ

In this chapter, we will use MindOpt C++ API to model and solve the problem in Example of Quadratic Programming.

Include the header file:

24#include "MindoptCpp.h"

Create an optimization model model:

31    /*------------------------------------------------------------------*/
32    /* Step 1. Create environment and model.                            */
33    /*------------------------------------------------------------------*/
34    MDOEnv env = MDOEnv();
35    MDOModel model = MDOModel(env);

Next, we set the optimization sense to minimization via MDOModel::set(). Then, we call MDOModel::addVar() to add four variables, which define upper bounds, lower bounds, names and types. (for more details on MDOModel::set() and MDOModel::addVar(), please refer to C++ API)

42        /* Change to minimization problem. */
43        model.set(MDO_IntAttr_ModelSense, MDO_MINIMIZE);
44
45        /* Add variables. */
46        std::vector<MDOVar> x;
47        x.push_back(model.addVar(0.0, 10.0,         0.0, MDO_CONTINUOUS, "x0"));
48        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, MDO_CONTINUOUS, "x1"));
49        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, MDO_CONTINUOUS, "x2"));
50        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, MDO_CONTINUOUS, "x3"));

We call MDOaddconstr() to input the linear constraints into model:

52        /* Add constraints. */
53        model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], MDO_GREATER_EQUAL, 1.0, "c0");
54        model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3], MDO_EQUAL, 1.0, "c1");

Then, we create a quadratic expression MDOQuadExpr and call MDOQuadExpr::addTerms to set the linear part of the objective function. obj_idx represents the indices of the linear terms, obj_val represents the corresponding non-zero coefficient values in obj_idx, and obj_nnz represents the number of non-zero elements in the linear part.

56        /*Create a QuadExpr. */
57        MDOQuadExpr obj = MDOQuadExpr(0.0);
58
59        /* Add objective linear term: 1 x0 + 1 x1 + 1 x2 + 1 x3 */
60        int    obj_nnz   = 4;
61        MDOVar obj_idx[] = { x[0], x[1], x[2], x[3] };
62        double obj_val[] = { 1.0,  1.0,  1.0,  1.0} ;
63        obj.addTerms(obj_val, obj_idx, obj_nnz);

We call MDOQuadExpr::addTerms to set the quadratic terms of the objective. Here, qo_values represents the coefficients of all the non-zero quadratic terms, while qo_col1 and qo_col2 respectively represent its row and column indices. qo_nnz represents the number of non-zero quadratic terms.

64        /* Add objective quadratic term: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
65        int    qo_nnz      = 5;
66        MDOVar qo_col1[]   = { x[0], x[1], x[2], x[3], x[0] };
67        MDOVar qo_col2[]   = { x[0], x[1], x[2], x[3], x[1] };
68        double qo_values[] = { 0.5,  0.5,  0.5,  0.5,  0.5 };
69        obj.addTerms(qo_values, qo_col1, qo_col2, qo_nnz);

Lastly, we call MDOModel::setObjective to set the objective and the direction to be optimized.

72        model.setObjective(obj, MDO_MINIMIZE);

Once the model is constructed, we call MDOModel::optimize() to solve the problem:

78        model.optimize();

The complete example code is shown in MdoQoEx1.cpp :

  1/**
  2 *  Description
  3 *  -----------
  4 *
  5 *  Linear optimization (row-wise input).
  6 *
  7 *  Formulation
  8 *  -----------
  9 *
 10 *  Minimize
 11 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3 
 12 *         + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
 13 *  Subject To
 14 *   c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
 15 *   c1 : 1 x0 - 1 x2 + 6 x3 = 1
 16 *  Bounds
 17 *    0 <= x0 <= 10
 18 *    0 <= x1
 19 *    0 <= x2
 20 *    0 <= x3
 21 *  End
 22 */
 23#include <iostream>
 24#include "MindoptCpp.h"
 25#include <vector>
 26
 27using namespace std;
 28
 29int main(void)
 30{
 31    /*------------------------------------------------------------------*/
 32    /* Step 1. Create environment and model.                            */
 33    /*------------------------------------------------------------------*/
 34    MDOEnv env = MDOEnv();
 35    MDOModel model = MDOModel(env);
 36    
 37    try 
 38    {
 39        /*------------------------------------------------------------------*/
 40        /* Step 2. Input model.                                             */
 41        /*------------------------------------------------------------------*/
 42        /* Change to minimization problem. */
 43        model.set(MDO_IntAttr_ModelSense, MDO_MINIMIZE);
 44
 45        /* Add variables. */
 46        std::vector<MDOVar> x;
 47        x.push_back(model.addVar(0.0, 10.0,         0.0, MDO_CONTINUOUS, "x0"));
 48        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, MDO_CONTINUOUS, "x1"));
 49        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, MDO_CONTINUOUS, "x2"));
 50        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, MDO_CONTINUOUS, "x3"));
 51
 52        /* Add constraints. */
 53        model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], MDO_GREATER_EQUAL, 1.0, "c0");
 54        model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3], MDO_EQUAL, 1.0, "c1");
 55        
 56        /*Create a QuadExpr. */
 57        MDOQuadExpr obj = MDOQuadExpr(0.0);
 58
 59        /* Add objective linear term: 1 x0 + 1 x1 + 1 x2 + 1 x3 */
 60        int    obj_nnz   = 4;
 61        MDOVar obj_idx[] = { x[0], x[1], x[2], x[3] };
 62        double obj_val[] = { 1.0,  1.0,  1.0,  1.0} ;
 63        obj.addTerms(obj_val, obj_idx, obj_nnz);
 64
 65        /* Add objective quadratic term: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
 66        int    qo_nnz      = 5;
 67        MDOVar qo_col1[]   = { x[0], x[1], x[2], x[3], x[0] };
 68        MDOVar qo_col2[]   = { x[0], x[1], x[2], x[3], x[1] };
 69        double qo_values[] = { 0.5,  0.5,  0.5,  0.5,  0.5 };
 70        obj.addTerms(qo_values, qo_col1, qo_col2, qo_nnz);
 71
 72        model.setObjective(obj, MDO_MINIMIZE);
 73
 74        /*------------------------------------------------------------------*/
 75        /* Step 3. Solve the problem and populate optimization result.                */
 76        /*------------------------------------------------------------------*/
 77        /* Solve the problem. */
 78        model.optimize();
 79
 80        if(model.get(MDO_IntAttr_Status) == MDO_OPTIMAL)
 81        {
 82            cout << "Optimal objective value is: " << model.get(MDO_DoubleAttr_ObjVal) << endl;
 83            cout << "Decision variables:" << endl;
 84            int i = 0;
 85            for (auto v : x)
 86            {
 87                cout << "x[" << i++ << "] = " << v.get(MDO_DoubleAttr_X) << endl;
 88            }
 89        }
 90        else
 91        {
 92            cout<< "No feasible solution." << endl;
 93        }
 94        
 95    }
 96    catch (MDOException& e) 
 97    { 
 98        std::cout << "Error code = " << e.getErrorCode() << std::endl;
 99        std::cout << e.getMessage() << std::endl;
100    } 
101    catch (...) 
102    { 
103        std::cout << "Error during optimization." << std::endl;
104    }
105    
106    return static_cast<int>(MDO_OKAY);
107}