Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

mipex1.c

00001 /*------------------------------------------------------------------------*/
00002 /*  File: examples/src/mipex1.c                                           */
00003 /*  Version 9.0                                                           */
00004 /*------------------------------------------------------------------------*/
00005 /*  Copyright (C) 1997-2003 by ILOG.                                      */
00006 /*  All Rights Reserved.                                                  */
00007 /*  Permission is expressly granted to use this example in the            */
00008 /*  course of developing applications that use ILOG products.             */
00009 /*------------------------------------------------------------------------*/
00010 
00011 /* mipex1.c - Entering and optimizing a MIP problem */
00012 
00013 /* Bring in the CPLEX function declarations and the C library 
00014    header file stdio.h with the include of cplex.h. */
00015 
00016 #include <ilcplex/cplex.h>
00017 
00018 /* Bring in the declarations for the string functions */
00019 
00020 #include <string.h>
00021 #include <stdlib.h>
00022 
00023 /* Include declaration for function at end of program */
00024 
00025 static int
00026    setproblemdata (char **probname_p, int *numcols_p, int *numrows_p, 
00027                    int *objsen_p, double **obj_p, double **rhs_p, 
00028                    char **sense_p, int **matbeg_p, int **matcnt_p, 
00029                    int **matind_p, double **matval_p, 
00030                    double **lb_p, double **ub_p, char **ctype_p);
00031 
00032 static void
00033    free_and_null (char **ptr);
00034 
00035 
00036 /* The problem we are optimizing will have 3 rows, 4 columns 
00037    and 9 nonzeros.  */
00038 
00039 #define NUMROWS    3
00040 #define NUMCOLS    4
00041 #define NUMNZ      9
00042 
00043 
00044 int
00045 main (void)
00046 {
00047 /* Declare pointers for the variables and arrays that will contain
00048    the data which define the LP problem.  The setproblemdata() routine
00049    allocates space for the problem data.  */
00050 
00051    char     *probname = NULL;  
00052    int      numcols;
00053    int      numrows;
00054    int      objsen;
00055    double   *obj = NULL;
00056    double   *rhs = NULL;
00057    char     *sense = NULL;
00058    int      *matbeg = NULL;
00059    int      *matcnt = NULL;
00060    int      *matind = NULL;
00061    double   *matval = NULL;
00062    double   *lb = NULL;
00063    double   *ub = NULL;
00064    char     *ctype = NULL;
00065 
00066    /* Declare and allocate space for the variables and arrays where we will
00067       store the optimization results including the status, objective value,
00068       variable values, and row slacks. */
00069 
00070    int      solstat;
00071    double   objval;
00072    double   x[NUMCOLS];
00073    double   slack[NUMROWS];
00074 
00075 
00076    CPXENVptr     env = NULL;
00077    CPXLPptr      lp = NULL;
00078    int           status;
00079    int           i, j;
00080    int           cur_numrows, cur_numcols;
00081 
00082    /* Initialize the CPLEX environment */
00083 
00084    env = CPXopenCPLEX (&status);
00085 
00086    /* If an error occurs, the status value indicates the reason for
00087       failure.  A call to CPXgeterrorstring will produce the text of
00088       the error message.  Note that CPXopenCPLEX produces no output,
00089       so the only way to see the cause of the error is to use
00090       CPXgeterrorstring.  For other CPLEX routines, the errors will
00091       be seen if the CPX_PARAM_SCRIND indicator is set to CPX_ON.  */
00092 
00093    if ( env == NULL ) {
00094       char  errmsg[1024];
00095       fprintf (stderr, "Could not open CPLEX environment.\n");
00096       CPXgeterrorstring (env, status, errmsg);
00097       fprintf (stderr, "%s", errmsg);
00098       goto TERMINATE;
00099    }
00100 
00101    /* Turn on output to the screen */
00102 
00103    status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
00104    if ( status ) {
00105       fprintf (stderr, 
00106                "Failure to turn on screen indicator, error %d.\n", status);
00107       goto TERMINATE;
00108    }
00109 
00110    /* Fill in the data for the problem.  */
00111 
00112    status = setproblemdata (&probname, &numcols, &numrows, &objsen, &obj, 
00113                             &rhs, &sense, &matbeg, &matcnt, &matind, &matval, 
00114                             &lb, &ub, &ctype);
00115    if ( status ) {
00116       fprintf (stderr, "Failed to build problem data arrays.\n");
00117       goto TERMINATE;
00118    }
00119 
00120    /* Create the problem. */
00121 
00122    lp = CPXcreateprob (env, &status, probname);
00123 
00124    /* A returned pointer of NULL may mean that not enough memory
00125       was available or there was some other problem.  In the case of 
00126       failure, an error message will have been written to the error 
00127       channel from inside CPLEX.  In this example, the setting of
00128       the parameter CPX_PARAM_SCRIND causes the error message to
00129       appear on stdout.  */
00130 
00131    if ( lp == NULL ) {
00132       fprintf (stderr, "Failed to create LP.\n");
00133       goto TERMINATE;
00134    }
00135 
00136    /* Now copy the problem data into the lp */
00137 
00138    status = CPXcopylp (env, lp, numcols, numrows, objsen, obj, rhs, 
00139                        sense, matbeg, matcnt, matind, matval,
00140                        lb, ub, NULL);
00141 
00142    if ( status ) {
00143       fprintf (stderr, "Failed to copy problem data.\n");
00144       goto TERMINATE;
00145    }
00146 
00147    /* Now copy the ctype array */
00148 
00149    status = CPXcopyctype (env, lp, ctype);
00150    if ( status ) {
00151       fprintf (stderr, "Failed to copy ctype\n");
00152       goto TERMINATE;
00153    }
00154 
00155 
00156    /* Optimize the problem and obtain solution. */
00157 
00158    status = CPXmipopt (env, lp);
00159    if ( status ) {
00160       fprintf (stderr, "Failed to optimize MIP.\n");
00161       goto TERMINATE;
00162    }
00163 
00164    solstat = CPXgetstat (env, lp);
00165 
00166    /* Write the output to the screen. */
00167 
00168    printf ("\nSolution status = %d\n", solstat);
00169     
00170    status = CPXgetmipobjval (env, lp, &objval);
00171    if ( status ) {
00172       fprintf (stderr,"No MIP objective value available.  Exiting...\n");
00173       goto TERMINATE;
00174    }
00175 
00176    printf ("Solution value  = %f\n\n", objval);
00177 
00178    /* The size of the problem should be obtained by asking CPLEX what
00179       the actual size is, rather than using what was passed to CPXcopylp.
00180       cur_numrows and cur_numcols store the current number of rows and
00181       columns, respectively.  */
00182 
00183    cur_numrows = CPXgetnumrows (env, lp);
00184    cur_numcols = CPXgetnumcols (env, lp);
00185 
00186    status = CPXgetmipx (env, lp, x, 0, cur_numcols-1);
00187    if ( status ) {
00188       fprintf (stderr, "Failed to get optimal integer x.\n");
00189       goto TERMINATE;
00190    }
00191 
00192    status = CPXgetmipslack (env, lp, slack, 0, cur_numrows-1);
00193    if ( status ) {
00194       fprintf (stderr, "Failed to get optimal slack values.\n");
00195       goto TERMINATE;
00196    }
00197 
00198    for (i = 0; i < cur_numrows; i++) {
00199       printf ("Row %d:  Slack = %10f\n", i, slack[i]);
00200    }
00201 
00202    for (j = 0; j < cur_numcols; j++) {
00203       printf ("Column %d:  Value = %10f\n", j, x[j]);
00204    }
00205 
00206    /* Finally, write a copy of the problem to a file. */
00207 
00208    status = CPXwriteprob (env, lp, "mipex1.lp", NULL);
00209    if ( status ) {
00210       fprintf (stderr, "Failed to write LP to disk.\n");
00211       goto TERMINATE;
00212    }
00213    
00214    
00215 TERMINATE:
00216 
00217    /* Free up the problem as allocated by CPXcreateprob, if necessary */
00218 
00219    if ( lp != NULL ) {
00220       status = CPXfreeprob (env, &lp);
00221       if ( status ) {
00222          fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status);
00223       }
00224    }
00225 
00226    /* Free up the CPLEX environment, if necessary */
00227 
00228    if ( env != NULL ) {
00229       status = CPXcloseCPLEX (&env);
00230 
00231       /* Note that CPXcloseCPLEX produces no output,
00232          so the only way to see the cause of the error is to use
00233          CPXgeterrorstring.  For other CPLEX routines, the errors will
00234          be seen if the CPX_PARAM_SCRIND indicator is set to CPX_ON. */
00235 
00236       if ( status ) {
00237          char  errmsg[1024];
00238          fprintf (stderr, "Could not close CPLEX environment.\n");
00239          CPXgeterrorstring (env, status, errmsg);
00240          fprintf (stderr, "%s", errmsg);
00241       }
00242    }
00243      
00244    /* Free up the problem data arrays, if necessary. */
00245 
00246    free_and_null ((char **) &probname);
00247    free_and_null ((char **) &obj);
00248    free_and_null ((char **) &rhs);
00249    free_and_null ((char **) &sense);
00250    free_and_null ((char **) &matbeg);
00251    free_and_null ((char **) &matcnt);
00252    free_and_null ((char **) &matind);
00253    free_and_null ((char **) &matval);
00254    free_and_null ((char **) &lb);
00255    free_and_null ((char **) &ub);
00256    free_and_null ((char **) &ctype);
00257 
00258    return (status);
00259 
00260 }  /* END main */
00261 
00262 
00263 /* This function fills in the data structures for the mixed integer program:
00264 
00265       Maximize
00266        obj: x1 + 2 x2 + 3 x3 + x4
00267       Subject To
00268        c1: - x1 + x2 + x3 + 10x4  <= 20
00269        c2: x1 - 3 x2 + x3         <= 30
00270        c3:       x2       - 3.5x4  = 0
00271       Bounds
00272        0 <= x1 <= 40
00273        2 <= x4 <= 3
00274       Integers
00275         x4
00276       End
00277  */
00278 
00279 
00280 static int
00281 setproblemdata (char **probname_p, int *numcols_p, int *numrows_p, 
00282                 int *objsen_p, double **obj_p, double **rhs_p, 
00283                 char **sense_p, int **matbeg_p, int **matcnt_p, 
00284                 int **matind_p, double **matval_p, 
00285                 double **lb_p, double **ub_p, char **ctype_p)
00286 {
00287    char     *zprobname = NULL;     /* Problem name <= 16 characters */        
00288    double   *zobj = NULL;
00289    double   *zrhs = NULL;
00290    char     *zsense = NULL;
00291    int      *zmatbeg = NULL;
00292    int      *zmatcnt = NULL;
00293    int      *zmatind = NULL;
00294    double   *zmatval = NULL;
00295    double   *zlb = NULL;
00296    double   *zub = NULL;
00297    char     *zctype = NULL;
00298    int      status = 0;
00299 
00300    zprobname = (char *) malloc (16 * sizeof(char)); 
00301    zobj      = (double *) malloc (NUMCOLS * sizeof(double));
00302    zrhs      = (double *) malloc (NUMROWS * sizeof(double));
00303    zsense    = (char *) malloc (NUMROWS * sizeof(char)); 
00304    zmatbeg   = (int *) malloc (NUMCOLS * sizeof(int));   
00305    zmatcnt   = (int *) malloc (NUMCOLS * sizeof(int));   
00306    zmatind   = (int *) malloc (NUMNZ * sizeof(int));   
00307    zmatval   = (double *) malloc (NUMNZ * sizeof(double));
00308    zlb       = (double *) malloc (NUMCOLS * sizeof(double));
00309    zub       = (double *) malloc (NUMCOLS * sizeof(double));
00310    zctype    = (char *) malloc (NUMCOLS * sizeof(char)); 
00311  
00312    if ( zprobname == NULL || zobj    == NULL ||
00313         zrhs      == NULL || zsense  == NULL ||
00314         zmatbeg   == NULL || zmatcnt == NULL ||
00315         zmatind   == NULL || zmatval == NULL ||
00316         zlb       == NULL || zub     == NULL ||
00317         zctype    == NULL                       )  {
00318       status = 1;
00319       goto TERMINATE;
00320    }
00321 
00322    strcpy (zprobname, "example");
00323 
00324    /* The code is formatted to make a visual correspondence 
00325       between the mathematical linear program and the specific data
00326       items.   */
00327 
00328      zobj[0]  = 1.0;   zobj[1]   = 2.0;  zobj[2]    = 3.0;    zobj[3] = 1.0;  
00329 
00330    zmatbeg[0] = 0;    zmatbeg[1] = 2;    zmatbeg[2] = 5;   zmatbeg[3] = 7;
00331    zmatcnt[0] = 2;    zmatcnt[1] = 3;    zmatcnt[2] = 2;   zmatcnt[3] = 2;
00332       
00333    zmatind[0] = 0;    zmatind[2] = 0;    zmatind[5] = 0;   zmatind[7] = 0;
00334    zmatval[0] = -1.0; zmatval[2] = 1.0;  zmatval[5] = 1.0; zmatval[7] = 10.0;
00335 
00336    zmatind[1] = 1;    zmatind[3] = 1;    zmatind[6] = 1;     
00337    zmatval[1] = 1.0;  zmatval[3] = -3.0; zmatval[6] = 1.0;   
00338 
00339                       zmatind[4] = 2;                      zmatind[8] = 2;
00340                       zmatval[4] = 1.0;                    zmatval[8] = -3.5;
00341 
00342    zlb[0] = 0.0;   zlb[1] = 0.0;      zlb[2] = 0.0;     zlb[3] = 2.0;
00343    zub[0] = 40.0;  zub[1] = CPX_INFBOUND; zub[2] = CPX_INFBOUND; zub[3] = 3.0;
00344 
00345     zctype[0] = 'C';    zctype[1] = 'C';   zctype[2] = 'C';   zctype[3] = 'I';
00346 
00347   /* The right-hand-side values don't fit nicely on a line above.  So put
00348      them here.  */
00349 
00350    zsense[0] = 'L';
00351    zrhs[0]   = 20.0;
00352 
00353    zsense[1] = 'L';
00354    zrhs[1]   = 30.0;
00355 
00356    zsense[2] = 'E';
00357    zrhs[2]   = 0.0;
00358 
00359 TERMINATE:
00360 
00361    if ( status ) {
00362       free_and_null ((char **) &zprobname);
00363       free_and_null ((char **) &zobj);
00364       free_and_null ((char **) &zrhs);
00365       free_and_null ((char **) &zsense);
00366       free_and_null ((char **) &zmatbeg);
00367       free_and_null ((char **) &zmatcnt);
00368       free_and_null ((char **) &zmatind);
00369       free_and_null ((char **) &zmatval);
00370       free_and_null ((char **) &zlb);
00371       free_and_null ((char **) &zub);
00372       free_and_null ((char **) &zctype);
00373    }
00374    else {
00375       *numcols_p   = NUMCOLS;
00376       *numrows_p   = NUMROWS;
00377       *objsen_p    = CPX_MAX;   /* The problem is maximization */
00378    
00379       *probname_p  = zprobname;
00380       *obj_p       = zobj;
00381       *rhs_p       = zrhs;
00382       *sense_p     = zsense;
00383       *matbeg_p    = zmatbeg;
00384       *matcnt_p    = zmatcnt;
00385       *matind_p    = zmatind;
00386       *matval_p    = zmatval;
00387       *lb_p        = zlb;
00388       *ub_p        = zub;
00389       *ctype_p     = zctype;
00390    }
00391    return (status);
00392 
00393 }  /* END setproblemdata */
00394 
00395 
00396 
00397 /* This simple routine frees up the pointer *ptr, and sets *ptr to NULL */
00398 
00399 static void
00400 free_and_null (char **ptr)
00401 {
00402    if ( *ptr != NULL ) {
00403       free (*ptr);
00404       *ptr = NULL;
00405    }
00406 } /* END free_and_null */  

Generated on Tue Nov 16 15:18:17 2004 for SCIL by doxygen1.2.16