ILOG CPLEX 11.0 User's Manual > Languages and APIs > ILOG CPLEX Callable Library > Using Surplus Arguments for Array Allocations

Most of the ILOG CPLEX query routines in the Callable Library require your application to allocate memory for one or more arrays that will contain the results of the query. In many cases, your application--the calling program--does not know the size of these arrays in advance. For example, in a call to CPXgetcols requesting the matrix data for a range of columns, your application needs to pass the arrays cmatind and cmatval for ILOG CPLEX to populate with matrix coefficients and row indices. However, unless your application has carefully kept track of the number of nonzeros in each column throughout the problem specification and, if applicable, throughout its modification, the actual length of these arrays remains unknown.

Fortunately, the ILOG CPLEX query routines in the Callable Library contain a surplus_p argument that, when used in conjunction with the array length arguments, enables you first to call the query routine to discover the length of the required array. Then, when the length is known, your application can properly allocate these arrays. Afterwards, your application makes a second call to the query routine with the correct array lengths to obtain the requested data.

For example, consider a program that needs to call CPXgetcols to access a range of columns. Here is the list of arguments for CPXgetcols.

CPXgetcols (CPXENVptr env, 
            CPXLPptr lp, 
            int *nzcnt_p,
            int *cmatbeg, 
            int *cmatind, 
            double *cmatval,
            int cmatspace, 
            int *surplus_p,
            int begin, 
            int end);

The arrays cmatind and cmatval require one element for each nonzero matrix coefficient in the requested range of columns. The required length of these arrays, specified in cmatspace, remains unknown at the time of the query. Your application--the calling program--can discover the length of these arrays by first calling CPXgetcols with a value of 0 for cmatspace. This call will return an error status of CPXERR_NEGATIVE_SURPLUS indicating a shortfall of the array length specified in cmatspace (in this case, 0); it will also return the actual number of matrix nonzeros in the requested range of columns. CPXgetcols deposits this shortfall as a negative number in the integer pointed to by surplus_p. Your application can then negate this shortfall and allocate the arrays cmatind and cmatval sufficiently long to contain all the requested matrix elements.

The following sample of code illustrates this procedure. The first call to CPXgetcols passes a value of 0 (zero) for cmatspace in order to obtain the shortfall in cmatsz. The sample then uses the shortfall to allocate the arrays cmatind and cmatval properly; then it calls CPXgetcols again to obtain the actual matrix coefficients and row indices.

status = CPXgetcols (env, lp, &nzcnt, cmatbeg, NULL, NULL,
                     0, &cmatsz, 0, numcols - 1);
if ( status != CPXERR_NEGATIVE_SURPLUS ) {
   if ( status != 0 ) {
      CPXmsg (cpxerror, 
              "CPXgetcols for surplus failed, status = %d\n", status);
      goto TERMINATE;
   }
   CPXmsg (cpxwarning, 
           "All columns in range [%d, %d] are empty.\n",
           0, (numcols - 1));
}
cmatsz   = -cmatsz;
cmatind  = (int *) malloc ((unsigned) (1 + cmatsz)*sizeof(int));
cmatval  = (double *) malloc ((unsigned) (1 + cmatsz)*sizeof(double));
if ( cmatind == NULL || cmatval == NULL ) {
   CPXmsg (cpxerror, "CPXgetcol mallocs failed\n");
   status = 1;
   goto TERMINATE;
}
status = CPXgetcols (env, lp, &nzcnt, cmatbeg, cmatind, cmatval,
                     cmatsz, &surplus, 0, numcols - 1);
if ( status ) {
   CPXmsg (cpxerror, "CPXgetcols failed, status = %d\n", status);
   goto TERMINATE;
}

That sample code (or your application) does not need to set the length of the array cmatbeg. The array cmatbeg has one element for each column in the requested range. Since this length is known ahead of time, your application does not need to call a query routine to calculate it. More generally, query routines use surplus arguments in this way only for the length of any array required to store problem data of unknown length. Problem data in this category include nonzero matrix entries, row and column names, other problem data names, special ordered sets (SOS), priority orders, and MIP start information.