Initializing help system before first use

Implementation with Xpress Optimizer

The following program folioqp.c loads the QP problem into Xpress Optimizer and solves it. Notice that the quadratic part of the objective function must be specified in triangular form, that is, either the lower or the upper triangle of the original matrix. Here we have chosen the upper triangle, which means that instead of 4·frac2·frac4 + 4·frac4·frac2 we only specify the sum of these terms, 8·frac2·frac4. Due to the input conventions of the Optimizer the values of the main diagonal also need to be multiplied with 2. As with the matrix coefficients, only quadratic terms with non-zero coefficients are specified to the Optimizer (hence the spaces in the array definitions below).

#include <stdio.h>
#include <stdlib.h>
#include "xprs.h"

int main(int argc, char **argv)
{
 XPRSprob prob;
 int s, status;
 double objval, *sol;

 /* Problem parameters */
 int ncol = 10;
 int nrow = 3;
 int nqt  = 43;

 /* Row data */
 char rowtype[] = {'G','E','G'};
 double rhs[]   = {0.5, 1,  9};

 /* Column data */
 double obj[] = {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
 double lb[]  = {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
 double ub[]  = {0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3,0.3};

 /* Matrix coefficient data */
 int colbeg[]    = {0,    3,     6,     9,    12, 14, 16, 18, 20,  22,  24};
 int rowidx[]    = {0,1,2,0,1, 2,0,1, 2,0,1, 2,1,2,1,2,1,2,1,2,1, 2,1,2};
 double matval[] = {1,1,5,1,1,17,1,1,26,1,1,12,1,8,1,9,1,7,1,6,1,31,1,21};

 /* QP problem data */
 int qcol1[]   = {0,
                    1,1,1,1,1,1,1,1,1,
                      2,2,2,2,2,  2,2,
                        3,  3,3,  3,3,
                          4,4,4,4,4,4,
                            5,5,5,5,5,
                              6,6,6,6,
                                7,7,7,
                                  8,8,
                                    9};
 int qcol2[]   = {0,
                    1,2,3,4,5,6,7,8,9,
                      2,3,4,5,6,  8,9,
                        3,  5,6,  8,9,
                          4,5,6,7,8,9,
                            5,6,7,8,9,
                              6,7,8,9,
                                7,8,9,
                                  8,9,
                                    9};
 double qval[] = {0.1,
                      19,-2, 4,1,   1, 1,0.5, 10,  5,
                         28, 1,2,   1, 1,     -2, -1,
                            22,     1, 2,      3,  4,
                               4,-1.5,-2, -1,  1,  1,
                                  3.5, 2,0.5,  1,1.5,
                                       5,0.5,  1,2.5,
                                           1,0.5,0.5,
                                              25,  8,
                                                  16};
 for(s=0;s<nqt;s++) qval[s]*=2;

 XPRSinit(NULL);                         /* Initialize Xpress Optimizer */
 XPRScreateprob(&prob);                  /* Create a new problem */
                                         /* Load the problem matrix */
 XPRSloadqp(prob, "FolioQP", ncol, nrow, rowtype, rhs, NULL,
            obj, colbeg, NULL, rowidx, matval, lb, ub,
            nqt, qcol1, qcol2, qval);

 XPRSchgobjsense(prob, XPRS_OBJ_MINIMIZE);  /* Set sense to maximization */
 XPRSlpoptimize(prob, "");               /* Solve the problem */

 XPRSgetintattrib(prob, XPRS_LPSTATUS, &status);   /* Get solution status */

 if(status == XPRS_LP_OPTIMAL)
 {
  XPRSgetdblattrib(prob, XPRS_LPOBJVAL, &objval);  /* Get objective value */
  printf("Minimum variance: %g\n", objval);

  sol = (double *)malloc(ncol*sizeof(double));
  XPRSgetlpsol(prob, sol, NULL, NULL, NULL);       /* Get primal solution */
  for(s=0;s<ncol;s++) printf("%d: %g%%\n", s, sol[s]*100);
 }

 XPRSdestroyprob(prob);                  /* Delete the problem */
 XPRSfree();                             /* Terminate Xpress */

 return 0;
}

A QP problem is loaded into the Optimizer with the function XPRSloadqp. This function takes the same arguments as function XPRSloadlp with four additional arguments at the end for the quadratic part of the objective function: the number of quadratic terms, nqt, the column numbers of the variables in every quadratic term (qcol1 and qcol2) and their coefficient, qval.

If we wish to load a Mixed Integer Quadratic Programming (MIQP) problem, then we need to use the function XPRSloadqglobal that takes the same arguments as XPRSloadqp plus the nine arguments for MIP problems introduced with function XPRSloadglobal in the previous chapter.

As opposed to the previous examples we now minimize the objective function. Notice that for solving and solution access we use the same functions as for LP problems. When solving MIQP problems, correspondingly we need to use the MIP solving and solution functions presented in Chapter 16.

Executing this program produces the following output:

Minimum variance: 0.557394
0: 30%
1: 7.15401%
2: 7.38237%
3: 5.46362%
4: 12.6561%
5: 5.91283%
6: 0.333491%
7: 29.9979%
8: 1.0997%
9: 6.97039e-06%

All but the last share are selected into the portfolio (the value printed for 9 is so close to 0 that Xpress Optimizer interprets it as 0 with its default tolerance settings).