dbl_lp.c

Go to the documentation of this file.
00001 /****************************************************************************/
00002 /*                                                                          */
00003 /*  This file is part of QSopt_ex.                                          */
00004 /*                                                                          */
00005 /*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
00006 /*  and Daniel Espinoza                                                     */
00007 /*                                                                          */
00008 /*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
00009 /*  copyright in QSopt.                                                     */
00010 /*                                                                          */
00011 /*  This code may be used under the terms of the GNU General Public License */
00012 /*  (Version 2.1 or later) as published by the Free Software Foundation.    */
00013 /*                                                                          */
00014 /*  Alternatively, use is granted for research purposes only.               */
00015 /*                                                                          */
00016 /*  It is your choice of which of these two licenses you are operating      */
00017 /*  under.                                                                  */
00018 /*                                                                          */
00019 /*  We make no guarantees about the correctness or usefulness of this code. */
00020 /*                                                                          */
00021 /****************************************************************************/
00022 
00023 /* RCS_INFO = "$RCSfile: dbl_lp.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
00024 
00025 /****************************************************************************/
00026 /*                                                                          */
00027 /*               Routines for Reading and Writing LP Files                  */
00028 /*                                                                          */
00029 /*  EXPORTED FUNCTIONS                                                      */
00030 /*                                                                          */
00031 /*        int dbl_ILLwrite_lp (FILE *out, dbl_ILLlpdata *lp)                        */
00032 /*        int dbl_ILLread_lp (dbl_qsline_reader f, const char *dbl_fname, dbl_rawlpdata *lp)*/
00033 /*        int dbl_ILLis_lp_name_char (char c, int pos)                          */
00034 /*        int dbl_ILLread_constraint_expr(dbl_ILLread_lp_state *state,              */
00035 /*          dbl_rawlpdata *lp, int rowind, int allowNew)                        */
00036 /*        int dbl_ILLread_constraint_name (dbl_ILLread_lp_state *state,             */
00037 /*          char **rowname)                                                 */
00038 /*        int dbl_ILLread_one_constraint (dbl_ILLread_lp_state *state,              */
00039 /*          const char *rowname, dbl_rawlpdata *lp, int allowNewCols)           */
00040 /*                                                                          */
00041 /****************************************************************************/
00042 
00043 #include <stdio.h>
00044 #include "econfig.h"
00045 /* from the cplex manual: 
00046  
00047     not exceed 16 characters, all of which must be alphanumeric
00048     (a-z, A-Z, 0-9) or one of these symbols: ! " # $ % & ( ) / ,
00049     . ; ? @ _ ` ' { } | ~. Longer names will be truncated to 16
00050     characters. A variable name can not begin with a number or a
00051     period. 
00052 
00053     The letter E or e, alone or followed by other valid symbols,
00054     or followed by another E or e, should be avoided as this
00055     notation is reserved for exponential entries. Thus, variables
00056     can not be named e9, E-24, E8cats, or other names that could
00057     be interpreted as an exponent. Even variable names such as
00058     eels or example can cause a read error, depending on their
00059     placement in an input line. 
00060 
00061     Also, the following characters are not valid in variable
00062     names (in order to allow for quadratic objective
00063     information): ^, *, [ and ]. 
00064 */
00065 /* OUR DEFINTION:
00066  * -) variables consist of a-z A-Z 0-9 !"#$%(),;.?@_`'{}|~ 
00067  *    don't start with a digit or '.'
00068  * return  0 for variable 
00069  * return -1 for keyword 
00070  * return  1 otherwise 
00071  */
00072 
00073 
00074 int dbl_ILLis_lp_name_char (
00075   int c,
00076   int pos)
00077 {
00078   return ((('a' <= c) && (c <= 'z')) ||
00079           (('A' <= c) && (c <= 'Z')) ||
00080           ((pos > 0) && ('0' <= c) && (c <= '9')) ||
00081           ((pos > 0) && (c == '.')) ||
00082           (strchr ("!\"#$%&()/,;?@_`'{}|~", c) != NULL));
00083 }
00084 
00085 
00086 /* 
00087  * -) anything after '\' is comment 
00088  * -) Problem is optional and comes first
00089  * -) Minimize, Maximize, ... comes after Problem
00090  * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~ 
00091  */
00092 
00093 /*  NOTES                                                                   */
00094 /*   
00095  *    don't start with a digit or '.'
00096  */
00097 
00098 static const int dbl_LINE_LEN = 64;
00099 
00100 #include "dbl_iqsutil.h"
00101 #include "dbl_lp.h"
00102 #include "dbl_rawlp.h"
00103 #include "dbl_read_lp.h"
00104 #include "dbl_write_lp.h"
00105 #ifdef USEDMALLOC
00106 #include "dmalloc.h"
00107 #endif
00108 //extern double dbl_SZERO_TOLER;
00109 static int TRACE = 0;
00110 
00111 static int dbl_read_problem_name (
00112   dbl_ILLread_lp_state * state,
00113   dbl_rawlpdata * lp);
00114 static int dbl_read_minmax (
00115   dbl_ILLread_lp_state * state,
00116   dbl_rawlpdata * lp);
00117 static int dbl_read_objective (
00118   dbl_ILLread_lp_state * state,
00119   dbl_rawlpdata * lp);
00120 static int dbl_read_objective (
00121   dbl_ILLread_lp_state * state,
00122   dbl_rawlpdata * lp);
00123 static int dbl_read_constraints (
00124   dbl_ILLread_lp_state * state,
00125   dbl_rawlpdata * lp,
00126   int allowNewCols);
00127 static int dbl_read_colname (
00128   dbl_ILLread_lp_state * state,
00129   ILLsymboltab * coltab,
00130   int mustHave);
00131 static int dbl_read_integer (
00132   dbl_ILLread_lp_state * state,
00133   dbl_rawlpdata * lp);
00134 static int dbl_read_bounds (
00135   dbl_ILLread_lp_state * state,
00136   dbl_rawlpdata * lp);
00137 static int dbl_add_var (
00138   dbl_rawlpdata * lp,
00139   dbl_ILLread_lp_state * state,
00140   double coef,
00141   int row,
00142   int allowNew);
00143 
00144 /*------------------------------------------------------------------------ 
00145  * dbl_ILLwrite_lp and support routines
00146  */
00147 static int dbl_fix_names (
00148   dbl_qserror_collector * collector,
00149   char **names,
00150   int nnames,
00151   const char *extra,
00152   int prefix,
00153   char ***newnames);
00154 static void dbl_write_objective (
00155   dbl_ILLlpdata * lp,
00156   const char *objname,
00157   char **colnames);
00158 static int dbl_write_row (
00159   dbl_ILLlpdata * lp,
00160   dbl_ILLlp_rows * lprows,
00161   int i,
00162   char **rownames,
00163   char **colnames,
00164   int *colInRow,
00165   double * colCoef);
00166 static int dbl_write_bounds (
00167   dbl_ILLlpdata * lp,
00168   char **colnames);
00169 static void dbl_write_intvars (
00170   dbl_ILLlpdata * lp,
00171   char **colnames);
00172 
00173 int dbl_ILLwrite_lp (
00174   dbl_ILLlpdata * lp,
00175   dbl_qserror_collector * collector)
00176 {
00177   int rval = 0;
00178   int i;
00179   dbl_ILLlp_rows lp_rows, *lprows = NULL;
00180   char **colnames = (char **) NULL;
00181   char **rownames = (char **) NULL;
00182   double *colCoef = NULL;
00183   int *colInRow = NULL;
00184   const char *objname;
00185 
00186   ILL_FAILfalse (lp, "called without data\n");
00187   if (lp->nstruct == 0 || lp->nrows == 0)
00188   {
00189     EG_RETURN (rval);
00190   }
00191   ILL_FAILfalse (lp->colnames != NULL, "lp->colnames != NULL");
00192   ILL_FAILfalse (lp->rownames != NULL, "lp->rownames != NULL");
00193   ILL_FAILfalse (lp->nstruct == lp->coltab.tablesize,
00194                  "lp coltab has nstruct entries");
00195   if (lp->objname == (char *) NULL)
00196   {
00197     ILL_FAILfalse (lp->nrows == lp->rowtab.tablesize,
00198                    "lp rowtab should have nrows entries");
00199   }
00200   else
00201   {
00202     ILL_FAILfalse (lp->nrows + 1 == lp->rowtab.tablesize,
00203                    "lp rowtab should have nrows+1 entries");
00204     ILL_FAILfalse (ILLsymboltab_contains (&lp->rowtab, lp->objname),
00205                    "rowtab must contain objname");
00206   }
00207 
00208   rval = dbl_fix_names (collector, lp->colnames, lp->nstruct, NULL, 'x', &colnames);
00209   CHECKRVALG (rval, CLEANUP);
00210 
00211   rval = dbl_fix_names (collector, lp->rownames, lp->nrows,
00212                     (lp->objname) ? lp->objname : "obj", 'c', &rownames);
00213   CHECKRVALG (rval, CLEANUP);
00214   objname = rownames[lp->nrows];
00215 
00216   ILL_FAILtrue (objname == NULL, "OOps, that should never happen");
00217   CHECKRVALG (rval, CLEANUP);
00218 
00219   if (lp->sos.matcols > 0)
00220   {
00221     rval +=
00222       dbl_ILLdata_error (collector, "Can't express SOS information in LP format.");
00223   }
00224 
00225   dbl_write_objective (lp, objname, colnames);
00226 
00227   /* Note, dbl_ILLlp_rows_init returns cols ordered by structmap, so we may use 
00228    * colnames[i] when pulling i from the matrix data.  */
00229 
00230   lprows = &lp_rows;
00231   if (dbl_ILLlp_rows_init (lprows, lp, 0) != 0)
00232   {
00233     rval += 1;
00234     ILL_FAILtrue (rval, "dbl_ILLlp_rows_init failed\n");
00235   }
00236 
00237   colCoef = dbl_EGlpNumAllocArray (lp->nstruct);
00238   ILL_SAFE_MALLOC (colInRow, lp->nstruct, int);
00239 
00240   for (i = 0; i < lp->nstruct; i++)
00241   {
00242     colInRow[i] = -1;
00243   }
00244 
00245   dbl_ILLprint_report (lp, "Subject To\n");
00246   for (i = 0; i < lp->nrows; i++)
00247   {
00248     if (lprows->rowcnt[i] == 0)
00249     {
00250       /*
00251        * dbl_ILLdata_warn (collector, "Not printing  empty row \"%s\".", rownames[i]);
00252        */
00253       continue;
00254     }
00255     rval += dbl_write_row (lp, lprows, i, rownames, colnames, colInRow, colCoef);
00256   }
00257 
00258   rval += dbl_write_bounds (lp, colnames);
00259 
00260   if (lp->intmarker != NULL)
00261   {
00262     dbl_write_intvars (lp, colnames);
00263   }
00264 
00265   dbl_ILLprint_report (lp, "End\n");
00266 CLEANUP:
00267   if (lprows != NULL)
00268   {
00269     dbl_ILLlp_rows_clear (lprows);
00270   }
00271   ILLfree_names (colnames, lp->nstruct);
00272   ILLfree_names (rownames, lp->nrows + 1);
00273   dbl_EGlpNumFreeArray (colCoef);
00274   ILL_IFFREE (colInRow, int);
00275 
00276   EG_RETURN (rval);
00277 }
00278 
00279 static void dbl_write_objective (
00280   dbl_ILLlpdata * lp,
00281   const char *objname,
00282   char **colnames)
00283 {
00284   int ri, i, k, var;
00285   dbl_ILLwrite_lp_state ln, *line = &ln;
00286 
00287   if (lp->probname != NULL)
00288   {
00289     dbl_ILLprint_report (lp, "Problem\n %s\n", lp->probname);
00290   }
00291   if (lp->objsense == dbl_ILL_MIN)
00292   {
00293     dbl_ILLprint_report (lp, "Minimize\n");
00294   }
00295   else
00296   {
00297     dbl_ILLprint_report (lp, "Maximize\n");
00298   }
00299   dbl_ILLwrite_lp_state_init (line, NULL);
00300   dbl_ILLwrite_lp_state_append (line, " ");
00301   dbl_ILLwrite_lp_state_append (line, objname);
00302   dbl_ILLwrite_lp_state_append (line, ": ");
00303   dbl_ILLwrite_lp_state_save_start (line);
00304 
00305   for (ri = 0, var = 0; ri < lp->nstruct; ri++)
00306   {
00307     i = lp->structmap[ri];
00308     if (dbl_EGlpNumIsNeqqZero (lp->obj[i]))
00309     {
00310       dbl_ILLwrite_lp_state_append_coef (line, lp->obj[i], var);
00311       dbl_ILLwrite_lp_state_append (line, " ");
00312       dbl_ILLwrite_lp_state_append (line, colnames[ri]);
00313       var++;
00314 
00315       /* we put a least 4 terms on a line 
00316        * and then we stop after dbl_LINE_LEN or more characters 
00317        */
00318       if ((line->total >= dbl_LINE_LEN) && (var >= 4))
00319       {
00320         /* see whether there is another term 
00321          * if so append a '+' and print line */
00322         k = ri + 1;
00323         while (k < lp->nstruct)
00324         {
00325           if (dbl_EGlpNumIsLessZero (lp->obj[lp->structmap[k]]))
00326           {
00327             break;
00328           }
00329           else
00330           {
00331             if (dbl_EGlpNumIsGreatZero (lp->obj[lp->structmap[k]]))
00332             {
00333               dbl_ILLwrite_lp_state_append (line, " +");
00334               break;
00335             }
00336           }
00337           k++;
00338         }
00339         var = 0;                /* next line does not need to prefix coef with '+' */
00340         dbl_ILLprint_report (lp, "%s\n", line->buf);
00341         dbl_ILLwrite_lp_state_start (line);
00342       }
00343     }
00344   }
00345   if (var > 0)
00346   {
00347     dbl_ILLprint_report (lp, "%s\n", line->buf);
00348   }
00349 }
00350 
00351 static void dbl_write_the_expr (
00352   dbl_ILLlpdata * lp,
00353   dbl_ILLwrite_lp_state * line,
00354   char *rowname,
00355   dbl_ILLlp_rows * lprows,
00356   int row,
00357   char **colnames,
00358   int *colInRow,
00359   double * colCoef,
00360   int ncols)
00361 {
00362   int var, firstVar, k, i;
00363   double *coef;
00364 
00365   dbl_ILLwrite_lp_state_init (line, NULL);
00366   if (rowname != NULL)
00367   {
00368     dbl_ILLwrite_lp_state_append (line, " ");
00369     dbl_ILLwrite_lp_state_append (line, rowname);
00370     dbl_ILLwrite_lp_state_append (line, ": ");
00371   }
00372   else
00373   {
00374     dbl_ILLwrite_lp_state_append (line, "   ");
00375   }
00376   dbl_ILLwrite_lp_state_save_start (line);
00377 
00378   for (k = lprows->rowbeg[row];
00379        k < lprows->rowbeg[row] + lprows->rowcnt[row]; k++)
00380   {
00381     i = lprows->rowind[k];
00382     colInRow[i] = row;
00383     dbl_EGlpNumCopy (colCoef[i], lprows->rowval[k]);
00384   }
00385   var = 0;
00386   firstVar = 1;
00387   for (i = 0; i < ncols; i++)
00388   {
00389     if (colInRow[i] == row)
00390     {
00391       if (dbl_EGlpNumIsNeqqZero (colCoef[i]))
00392       {
00393         coef = &(colCoef[i]);
00394         if (line->total >= dbl_LINE_LEN)
00395         {
00396           dbl_ILLprint_report (lp, "%s\n", line->buf);
00397           dbl_ILLwrite_lp_state_start (line);
00398           if ((!firstVar) && !dbl_EGlpNumIsLessZero (*coef))
00399           {
00400             dbl_ILLwrite_lp_state_append (line, " +");
00401           }
00402           var = 0;
00403         }
00404 
00405         dbl_ILLwrite_lp_state_append_coef (line, *coef, var);
00406         dbl_ILLwrite_lp_state_append (line, " ");
00407         dbl_ILLwrite_lp_state_append (line, colnames[i]);
00408         var++;
00409         firstVar = 0;
00410       }
00411     }
00412   }
00413 }
00414 
00415 static int dbl_write_row (
00416   dbl_ILLlpdata * lp,
00417   dbl_ILLlp_rows * lprows,
00418   int i,
00419   char **rownames,
00420   char **colnames,
00421   int *colInRow,
00422   double * colCoef)
00423 {
00424   dbl_ILLwrite_lp_state ln, *line = &ln;
00425   int rval = 0;
00426   double ntmp;
00427 
00428   dbl_write_the_expr (lp, line, rownames[i], lprows, i, colnames,
00429                   colInRow, colCoef, lp->nstruct);
00430 
00431   switch (lp->sense[i])
00432   {
00433   case 'G':
00434     dbl_ILLwrite_lp_state_append (line, " >= ");
00435     dbl_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
00436     break;
00437   case 'L':
00438     dbl_ILLwrite_lp_state_append (line, " <= ");
00439     dbl_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
00440     break;
00441   case 'E':
00442     dbl_ILLwrite_lp_state_append (line, " = ");
00443     dbl_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
00444     break;
00445   case 'R':
00446     ILL_FAILtrue (!lp->rangeval, "RANGE constraints without values\n");
00447     dbl_EGlpNumInitVar (ntmp);
00448     dbl_ILLwrite_lp_state_append (line, " >= ");
00449     dbl_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
00450 
00451     dbl_ILLwrite_lp_state_append (line, " \t\\ RANGE (");
00452     dbl_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
00453     dbl_ILLwrite_lp_state_append (line, ", ");
00454     dbl_EGlpNumCopySum (ntmp, lp->rhs[i], lp->rangeval[i]);
00455     dbl_ILLwrite_lp_state_append_number (line, ntmp);
00456     dbl_ILLwrite_lp_state_append (line, ")");
00457     dbl_ILLprint_report (lp, "%s\n", line->buf);
00458 
00459     dbl_write_the_expr (lp, line, NULL, lprows, i,
00460                     colnames, colInRow, colCoef, lp->nstruct);
00461     dbl_ILLwrite_lp_state_append (line, " <= ");
00462     dbl_ILLwrite_lp_state_append_number (line, ntmp);
00463     dbl_EGlpNumClearVar (ntmp);
00464     break;
00465   default:
00466     ILL_FAILtrue (1, "Unknown row sense\n");
00467   }
00468 
00469   dbl_ILLprint_report (lp, "%s\n", line->buf);
00470 CLEANUP:
00471   EG_RETURN (rval);
00472 }
00473 
00474 static int dbl_write_bounds (
00475   dbl_ILLlpdata * lp,
00476   char **colnames)
00477 {
00478   int ri, i, rval = 0;
00479   int prtLower, prtUpper;
00480   dbl_ILLwrite_lp_state l, *line = &l;
00481 
00482   ILL_FAILtrue (lp->lower == NULL || lp->upper == NULL,
00483                 "Should not call dbl_write_bounds when lower or upper are NULL");
00484   ri = dbl_ILLraw_first_nondefault_bound (lp);
00485   if (ri != lp->nstruct)
00486   {
00487     dbl_ILLprint_report (lp, "Bounds\n");
00488     dbl_ILLwrite_lp_state_init (line, " ");
00489     dbl_ILLwrite_lp_state_save_start (line);
00490 
00491     for (ri = ri; ri < lp->nstruct; ri++)
00492     {
00493       dbl_ILLwrite_lp_state_start (line);
00494       i = lp->structmap[ri];
00495       if (dbl_EGlpNumIsEqqual (lp->lower[i], lp->upper[i]))
00496       {
00497         dbl_ILLwrite_lp_state_append (line, " ");
00498         dbl_ILLwrite_lp_state_append (line, colnames[ri]);
00499         dbl_ILLwrite_lp_state_append (line, " = ");
00500         dbl_ILLwrite_lp_state_append_number (line, lp->upper[i]);
00501         dbl_ILLprint_report (lp, "%s\n", line->buf);
00502         continue;
00503       }
00504       if ((dbl_EGlpNumIsEqqual (lp->lower[i], dbl_ILL_MINDOUBLE)) &&
00505           (dbl_EGlpNumIsEqqual (lp->upper[i], dbl_ILL_MAXDOUBLE)))
00506       {
00507         dbl_ILLwrite_lp_state_append (line, colnames[ri]);
00508         dbl_ILLwrite_lp_state_append (line, " free");
00509         dbl_ILLprint_report (lp, "%s\n", line->buf);
00510         continue;
00511       }
00512       prtLower = !dbl_ILLraw_default_lower (lp, i);
00513       prtUpper = !dbl_ILLraw_default_upper (lp, i);
00514       if (prtLower || prtUpper)
00515       {
00516         if (prtLower)
00517         {
00518           dbl_ILLwrite_lp_state_append_number (line, lp->lower[i]);
00519           dbl_ILLwrite_lp_state_append (line, " <= ");
00520         }
00521         if (prtLower || prtUpper)
00522         {
00523           dbl_ILLwrite_lp_state_append (line, colnames[ri]);
00524         }
00525         if (prtUpper)
00526         {
00527           dbl_ILLwrite_lp_state_append (line, " <= ");
00528           dbl_ILLwrite_lp_state_append_number (line, lp->upper[i]);
00529         }
00530         dbl_ILLprint_report (lp, "%s\n", line->buf);
00531       }
00532     }
00533   }
00534 CLEANUP:
00535   EG_RETURN (rval);
00536 }
00537 
00538 static void dbl_write_intvars (
00539   dbl_ILLlpdata * lp,
00540   char **colnames)
00541 {
00542   dbl_ILLwrite_lp_state ln, *line = &ln;
00543   int var, j;
00544 
00545   dbl_ILLprint_report (lp, "Integer\n");
00546   dbl_ILLwrite_lp_state_init (line, " ");
00547   dbl_ILLwrite_lp_state_save_start (line);
00548 
00549   for (j = 0, var = 0; j < lp->nstruct; j++)
00550   {
00551     if (lp->intmarker[j])
00552     {
00553       if (var > 0)
00554       {
00555         dbl_ILLwrite_lp_state_append (line, " ");
00556       }
00557       dbl_ILLwrite_lp_state_append (line, colnames[j]);
00558       var++;
00559       if (line->total >= dbl_LINE_LEN)
00560       {
00561         dbl_ILLprint_report (lp, "%s\n", line->buf);
00562         dbl_ILLwrite_lp_state_init (line, " ");
00563         var = 0;
00564       }
00565     }
00566   }
00567   if (var > 0)
00568   {
00569     dbl_ILLprint_report (lp, "%s\n", line->buf);
00570   }
00571 }
00572 
00573 /* ------------------------------------------------------------ */
00574 /* fix up names that are numbers, i.e. prefix with x X x_ or X_ */
00575 
00576 /* 
00577  * redefine names that start with [0-9]; i.e. give a prefix of 
00578  *         "x" | "X" | "x_" | "X_"  
00579  *         or if all these are already taken prefix with "X"<number>
00580  *         make sure names contain solely the characters: 
00581  *            [a-zA-Z0-9] and ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~
00582  *         rename names with 'bad' chars to <x X x_ X_><number>
00583  */
00584 static int dbl_fix_names (
00585   dbl_qserror_collector * collector,
00586   char **names,
00587   int nnames,
00588   const char *extra,
00589   int pref,
00590   char ***newnames)
00591 {
00592   ILLsymboltab symt, *symtab = NULL;
00593   int rval = 0, i, j, n, ind, hit;
00594   char **n_names = NULL;
00595   const char *old_name;
00596   char buf[ILL_namebufsize];
00597   char p1[2], p2[3];
00598 
00599   p1[0] = pref;
00600   p1[1] = '\0';
00601   p2[0] = pref;
00602   p2[1] = '_';
00603   p2[2] = '\0';
00604 
00605   ILL_SAFE_MALLOC (n_names, nnames + 1, char *);
00606 
00607   for (i = 0; i < nnames; i++)
00608   {
00609     n_names[i] = (char *) NULL;
00610   }
00611 
00612   for (i = 0; i <= nnames; i++)
00613   {
00614     if (i == nnames)
00615     {
00616       if (extra == NULL)
00617         break;
00618       old_name = extra;
00619     }
00620     else
00621       old_name = names[i];
00622 
00623     n = strlen (old_name);
00624     strcpy (buf, old_name);
00625     if (!dbl_ILLis_lp_name_char (buf[0], 1))
00626     {
00627       sprintf (buf, "%d", i);
00628     }
00629     else
00630     {
00631       for (j = 1; j < n; j++)
00632       {
00633         if (!dbl_ILLis_lp_name_char (buf[j], j))
00634         {
00635           sprintf (buf, "%d", i);
00636           break;
00637         }
00638       }
00639     }
00640 
00641     if (!dbl_ILLis_lp_name_char (buf[0], 0))
00642     {
00643       if (symtab == NULL)
00644       {
00645         symtab = &symt;
00646         ILLsymboltab_init (symtab);
00647         ILLsymboltab_create (symtab, nnames + 1);
00648         for (j = 0; j < nnames; j++)
00649         {
00650           ILLsymboltab_register (symtab, names[j], -1, &ind, &hit);
00651           ILL_FAILfalse (ind == j, "ind == j");
00652         }
00653         if (extra != NULL)
00654           ILLsymboltab_register (symtab, extra, -1, &ind, &hit);
00655       }
00656       rval = ILLsymboltab_uname (symtab, buf, p1, p2);
00657       CHECKRVALG (rval, CLEANUP);
00658       rval = ILLsymboltab_rename (symtab, i, buf);
00659       CHECKRVALG (rval, CLEANUP);
00660 
00661       dbl_ILL_UTIL_STR (n_names[i], buf);
00662       /*
00663        * dbl_ILLdata_warn (collector,
00664        * "\"%s\" is not a valid name in LP format; %s\"%s\".",
00665        * old_name, "renaiming to ", buf);
00666        */
00667     }
00668     else
00669     {
00670       dbl_ILL_UTIL_STR (n_names[i], old_name);
00671     }
00672   }
00673 
00674 CLEANUP:
00675   if (symtab != NULL)
00676   {
00677     ILLsymboltab_free (symtab);
00678   }
00679   *newnames = n_names;
00680   EG_RETURN (rval);
00681 }
00682 
00683 /* 
00684  * end ILLlpdata_lpwrite 
00685  * ---------------------------------------------------------------------- */
00686 
00687 int dbl_ILLread_lp (
00688   dbl_qsline_reader * file,
00689   const char *dbl_fname,
00690   dbl_rawlpdata * lp)
00691 {
00692 /* file format: 
00693  *     optional problem name (this is in addition to the bix format) 
00694  *     min or max 
00695  *     objective fct 
00696  *     constraints (mandatory !) 
00697  *     optional bounds 
00698  *     optional integer (also new) 
00699  *
00700  * as opposed to the official bix-format: 
00701  *     no blanks in variable names 
00702  *     there may be several bound defs on the same line; 
00703  *     bound definitions may cross line boundaries
00704  *     constraints that have no name get generated names:
00705  *             if constraint i has not name we take the first name from the 
00706  *             following list that is not in use:
00707  *                  c<i>,  C<i>, or c<i>_0, c<i>_1, c<i>_2, ...
00708  */
00709   int rval = 0;
00710   dbl_ILLread_lp_state lpstate, *state = &lpstate;
00711 
00712   const char *bnds[3], *integer[3], *end[2];
00713 
00714   bnds[0] = "BOUNDS";
00715   bnds[1] = "BOUND";
00716   bnds[2] = NULL;
00717   integer[0] = "INTEGER";
00718   integer[1] = "INT";
00719   integer[2] = NULL;
00720   end[0] = "END";
00721   end[1] = NULL;
00722 
00723   rval = dbl_ILLread_lp_state_init (state, file, dbl_fname, 0);
00724   CHECKRVALG (rval, CLEANUP);
00725 
00726   dbl_ILLinit_rawlpdata (lp, file->error_collector);
00727   rval = ILLsymboltab_create (&lp->rowtab, 100) ||
00728     ILLsymboltab_create (&lp->coltab, 100);
00729   CHECKRVALG (rval, CLEANUP);
00730 
00731   if (dbl_ILLread_lp_state_next_field (state))
00732   {
00733     rval = dbl_ILLlp_error (state, "Empty file.\n");
00734   }
00735   if (rval == 0)
00736     rval = dbl_read_problem_name (state, lp);
00737   if (rval == 0)
00738     rval = dbl_read_minmax (state, lp);
00739   if (rval == 0)
00740     rval = dbl_read_objective (state, lp);
00741   if (rval == 0)
00742     rval = dbl_read_constraints (state, lp, 1);
00743   if ((rval == 0) && (lp->ncols == 0 || lp->nrows == 0))
00744   {
00745     rval = dbl_ILLlp_error (state,
00746                         "Problem must contain at least one %s.\n",
00747                         "non empty constraint");
00748   }
00749   CHECKRVALG (rval, CLEANUP);
00750 
00751   if (dbl_ILLread_lp_state_keyword (state, bnds) == 0)
00752   {
00753     rval = dbl_read_bounds (state, lp);
00754   }
00755   CHECKRVALG (rval, CLEANUP);
00756 
00757   if (dbl_ILLread_lp_state_keyword (state, integer) == 0)
00758   {
00759     rval = dbl_read_integer (state, lp);
00760   }
00761   CHECKRVALG (rval, CLEANUP);
00762 
00763   rval = dbl_ILLread_lp_state_keyword (state, end);
00764   if (rval != 0)
00765   {
00766     if (state->eof)
00767     {
00768       rval = dbl_ILLlp_error (state, "Missing \"End\" at end of file.\n");
00769     }
00770     else
00771     {
00772       rval = dbl_ILLlp_error (state, "\"%s\" unknown keyword\n", state->field);
00773     }
00774   }
00775   if (rval == 0)
00776   {
00777     rval = dbl_ILLraw_fill_in_rownames (lp) || dbl_ILLraw_fill_in_bounds (lp);
00778   }
00779 
00780 CLEANUP:
00781   dbl_EGlpNumClearVar (lpstate.bound_val);
00782   EG_RETURN (rval);
00783 }
00784 
00785 static int dbl_read_problem_name (
00786   dbl_ILLread_lp_state * state,
00787   dbl_rawlpdata * lp)
00788 {
00789   int rval = 0;
00790 
00791   if (!state->fieldOnFirstCol)
00792   {
00793     rval = dbl_ILLlp_error (state,
00794                         "Keyword \"%s\" not at beginning of line.\n",
00795                         state->field);
00796   }
00797   if (!dbl_ILLutil_strcasecmp (state->field, "PROBLEM") ||
00798       !dbl_ILLutil_strcasecmp (state->field, "PROB"))
00799   {
00800     if (dbl_ILLread_lp_state_next_field (state) != 0)
00801     {
00802       rval = dbl_ILLlp_error (state, "No Problem name field.\n");
00803     }
00804     else
00805     {
00806       ILL_IFFREE (lp->name, char);
00807 
00808       dbl_ILL_UTIL_STR (lp->name, state->field);
00809       ILL_IFTRACE ("ProblemName: %s\n", state->field);
00810       (void) dbl_ILLread_lp_state_next_field (state);
00811     }
00812   }
00813 CLEANUP:
00814   EG_RETURN (rval);
00815 }
00816 
00817 static int dbl_read_minmax (
00818   dbl_ILLread_lp_state * state,
00819   dbl_rawlpdata * lp)
00820 {
00821   int rval = 0;
00822 
00823   if (!state->fieldOnFirstCol)
00824   {
00825     rval = dbl_ILLlp_error (state,
00826                         "Keyword \"%s\" not at beginning of line.\n",
00827                         state->field);
00828   }
00829   if (!dbl_ILLutil_strcasecmp (state->field, "MAX") ||
00830       !dbl_ILLutil_strcasecmp (state->field, "MAXIMUM") ||
00831       !dbl_ILLutil_strcasecmp (state->field, "MAXIMIZE"))
00832   {
00833     lp->objsense = dbl_ILL_MAX;
00834   }
00835   else
00836   {
00837     if (!dbl_ILLutil_strcasecmp (state->field, "MIN") ||
00838         !dbl_ILLutil_strcasecmp (state->field, "MINIMUM") ||
00839         !dbl_ILLutil_strcasecmp (state->field, "MINIMIZE"))
00840     {
00841       lp->objsense = dbl_ILL_MIN;
00842     }
00843     else
00844     {
00845       dbl_ILLread_lp_state_prev_field (state);
00846       rval = dbl_ILLlp_error (state, "Expecting \"%s\" or \"%s\" keyword.\n",
00847                           "Minimize", "Maximize");
00848     }
00849   }
00850   EG_RETURN (rval);
00851 }
00852 
00853 int dbl_ILLread_constraint_expr (
00854   dbl_ILLread_lp_state * state,
00855   dbl_rawlpdata * lp,
00856   int rowind,
00857   int allowNew)
00858 {
00859   int rval = 0;
00860   char firstTerm, haveCoef;
00861   const char *name;
00862   double sign, coef;
00863   double ntmp;
00864 
00865   dbl_EGlpNumInitVar (ntmp);
00866   dbl_EGlpNumInitVar (sign);
00867   dbl_EGlpNumInitVar (coef);
00868 
00869   firstTerm = 1;
00870   while (1)
00871   {
00872     if (dbl_ILLread_lp_state_sign (state, &sign) != 0)
00873     {
00874       if (!firstTerm)
00875       {
00876         break;                  /* we've ssen at least one term, 
00877                                  * this is the constraint's end */
00878       }
00879     }
00880     haveCoef = dbl_ILLread_lp_state_possible_coef (state, &coef, dbl_oneLpNum);
00881     if (dbl_ILLread_lp_state_next_var (state) == 0)
00882     {
00883       dbl_EGlpNumCopy (ntmp, coef);
00884       dbl_EGlpNumMultTo (ntmp, sign);
00885       rval = dbl_add_var (lp, state, ntmp, rowind, allowNew);
00886       CHECKRVALG (rval, CLEANUP);
00887     }
00888     else
00889     {
00890       if (haveCoef == 0)
00891       {
00892         return dbl_ILLlp_error (state, "Coefficient without variable.\n");
00893       }
00894       else
00895       {
00896         break;
00897       }
00898     }
00899     firstTerm = 0;
00900   }
00901 CLEANUP:
00902   if ((rval == 0) && firstTerm)
00903   {
00904     name = dbl_ILLraw_rowname (lp, rowind);
00905     if (name != NULL)
00906     {
00907       dbl_ILLlp_warn (state,
00908                   "No terms in constraint expression for \"%s\".\n", name);
00909     }
00910     else
00911     {
00912       dbl_ILLlp_warn (state, "No terms in constraint expression.\n");
00913     }
00914   }
00915   dbl_EGlpNumClearVar (ntmp);
00916   dbl_EGlpNumClearVar (sign);
00917   dbl_EGlpNumClearVar (coef);
00918   EG_RETURN (rval);
00919 }
00920 
00921 static int dbl_read_objective (
00922   dbl_ILLread_lp_state * state,
00923   dbl_rawlpdata * lp)
00924 {
00925   int rval = 0;
00926   char objname[ILL_namebufsize];
00927   char *name;
00928 
00929   ILL_FAILfalse (lp->nrows == 0, "objective should be first row");
00930   dbl_ILLread_lp_state_skip_blanks (state, 1);
00931   if (dbl_ILLread_lp_state_has_colon (state))
00932   {
00933     if (dbl_ILLread_lp_state_next_var (state) != 0)
00934     {
00935       rval = dbl_ILLlp_error (state, "Bad objective function name.\n");
00936     }
00937     name = state->field;
00938     if (rval == 0)
00939     {
00940       if (dbl_ILLread_lp_state_colon (state) != 0)
00941       {
00942         rval = dbl_ILLlp_error (state, "':' must follow constraint row name.\n");
00943       }
00944     }
00945   }
00946   else
00947   {
00948     name = NULL;
00949   }
00950 
00951   if (rval == 0)
00952   {
00953     ILL_FAILfalse (lp->rowtab.tablesize == 0,
00954                    "objective row is first in symbol tab");
00955     if (name == NULL)
00956     {
00957       strcpy (objname, "obj");
00958       dbl_ILLlp_warn (state, "Empty obj name; using \"%s\".\n", objname);
00959     }
00960     else
00961     {
00962       strcpy (objname, name);
00963     }
00964     rval = dbl_ILLraw_add_row (lp, objname, 'N', dbl_zeroLpNum);
00965     lp->objindex = lp->nrows - 1;
00966     CHECKRVALG (rval, CLEANUP);
00967     rval = dbl_ILLread_constraint_expr (state, lp, lp->objindex, 1);
00968   }
00969 CLEANUP:
00970   EG_RETURN (rval);
00971 }
00972 
00973 int dbl_ILLread_constraint_name (
00974   dbl_ILLread_lp_state * state,
00975   char **rowname)
00976 {
00977   int rval = 0;
00978 
00979   *rowname = NULL;
00980 
00981   /* if there is a ':' on the line: look for constraint row name */
00982   if (dbl_ILLread_lp_state_has_colon (state))
00983   {
00984     if (dbl_ILLread_lp_state_next_var (state) != 0)
00985     {
00986       rval = dbl_ILLlp_error (state, "Bad constraint row name.\n");
00987     }
00988     else
00989     {
00990       *rowname = state->field;
00991       if (dbl_ILLread_lp_state_colon (state) != 0)
00992       {
00993         rval = dbl_ILLlp_error (state, "':' must follow constraint row name.\n");
00994       }
00995     }
00996   }
00997   return rval;
00998 }
00999 
01000 int dbl_ILLread_one_constraint (
01001   dbl_ILLread_lp_state * state,
01002   const char *rowname,
01003   dbl_rawlpdata * lp,
01004   int allowNewCols)
01005 {
01006   int rval = 0;
01007   int rowind;
01008   char sense;
01009   double d;
01010 
01011   dbl_EGlpNumInitVar (d);
01012 
01013   if ((rowname != NULL) &&
01014       (ILLsymboltab_lookup (&lp->rowtab, rowname, &rowind) == 0))
01015   {
01016     rval = dbl_ILLlp_error (state, "Repeated row name \"%s\".\n", rowname);
01017     CHECKRVALG (rval, CLEANUP);
01018   }
01019   rowind = lp->nrows;
01020   rval = rval || dbl_ILLraw_add_row (lp, rowname, 'N', dbl_zeroLpNum);
01021 
01022   rval = rval || dbl_ILLread_constraint_expr (state, lp, rowind, allowNewCols);
01023   rval = rval || dbl_ILLread_lp_state_sense (state);
01024   sense = state->sense_val;
01025   if (rval == 0)
01026   {
01027     rval = dbl_ILLread_lp_state_value (state, &d);
01028     if (rval)
01029     {
01030       (void) dbl_ILLlp_error (state, "No right hand side value in constraint.\n");
01031     }
01032   }
01033   if (rval == 0)
01034   {
01035     lp->rowsense[rowind] = sense;
01036     dbl_EGlpNumCopy (lp->rhs[rowind], d);
01037     ILL_IFTRACE ("SENSE \"%s\": %c %f\n",
01038                  dbl_ILLraw_rowname (lp, rowind), sense, dbl_EGlpNumToLf (d));
01039   }
01040 CLEANUP:
01041   dbl_EGlpNumClearVar (d);
01042   EG_RETURN (rval);
01043 }
01044 
01045 static int dbl_read_constraints (
01046   dbl_ILLread_lp_state * state,
01047   dbl_rawlpdata * lp,
01048   int allowNewCols)
01049 {
01050   int rval = 0;
01051   char *rowname = NULL;
01052 
01053   if (dbl_ILLcheck_subject_to (state) != 0)
01054   {
01055     return dbl_ILLlp_error (state, "Constraint section expected.\n");
01056   }
01057   while (rval == 0)
01058   {
01059     rval = dbl_ILLread_constraint_name (state, &rowname);
01060     if (rval == 0)
01061     {
01062       rval = dbl_ILLread_one_constraint (state, rowname, lp, allowNewCols);
01063     }
01064     if (rval == 0)
01065     {
01066       if (dbl_ILLread_lp_state_next_constraint (state) != 0)
01067       {
01068         break;
01069       }
01070     }
01071   }
01072   dbl_ILLread_lp_state_next_field (state);
01073   EG_RETURN (rval);
01074 }
01075 
01076 /* 
01077  * return -2 iff next is not a variable and not a keyword
01078  * return -1 iff next is a keyword and !mustHave 
01079  * return 1  iff unknown column name or mustHave and keyword 
01080  * return 0  for success
01081  */
01082 static int dbl_read_colname (
01083   dbl_ILLread_lp_state * state,
01084   ILLsymboltab * coltab,
01085   int mustHave)
01086 {
01087   int rval = 0;
01088   int colind = ILL_SYM_NOINDEX;
01089 
01090   rval = dbl_ILLread_lp_state_next_var (state);
01091   if (mustHave && (rval != 0))
01092   {
01093     return dbl_ILLlp_error (state, "Expecting a column name.\n");
01094   }
01095   if (rval != 0)
01096   {
01097     return (rval == -1) ? rval : -2;
01098   }
01099   if (ILLsymboltab_lookup (coltab, state->field, &colind))
01100   {
01101     dbl_ILLread_lp_state_prev_field (state);
01102     return dbl_ILLlp_error (state, "\"%s\" is not a column name.\n", state->field);
01103   }
01104   state->column_index = colind;
01105   return 0;
01106 }
01107 
01108 static int dbl_read_integer (
01109   dbl_ILLread_lp_state * state,
01110   dbl_rawlpdata * lp)
01111 {
01112   int rval = 0;
01113   ILLsymboltab *coltab = &lp->coltab;
01114 
01115   ILL_FAILfalse (lp->intmarker, "Programming error");
01116 
01117   while ((rval = dbl_read_colname (state, coltab, 0)) == 0)
01118   {
01119     ILL_FAILtrue (state->column_index == ILL_SYM_NOINDEX, "Programming error");
01120     lp->intmarker[state->column_index] = 1;
01121   }
01122 CLEANUP:
01123   if (rval == -1)
01124   {                             /* last try for a colname gave us a keyword */
01125     rval = 0;
01126   }
01127   else
01128   {
01129     rval = dbl_ILLlp_error (state, "Expecting a column name.");
01130   }
01131   dbl_ILLread_lp_state_next_field (state);
01132   EG_RETURN (rval);
01133 }
01134 
01135 static int dbl_read_bounds (
01136   dbl_ILLread_lp_state * state,
01137   dbl_rawlpdata * lp)
01138 {
01139   int rval = 0;
01140   int colind, haveBound;
01141   char sense;
01142   const char *msg;
01143   ILLsymboltab *coltab;
01144 
01145   dbl_ILLraw_init_bounds (lp);
01146   coltab = &lp->coltab;
01147 
01148   while (1)
01149   {
01150     colind = -1;
01151     haveBound = 0;
01152     if (dbl_ILLread_lp_state_possible_bound_value (state))
01153     {
01154       /* this must be for a lower bound */
01155       dbl_ILLtest_lp_state_bound_sense (state);
01156       if (state->sense_val != 'L')
01157       {
01158         rval = dbl_ILLlp_error (state, "Expecting \"<=\".\n");
01159         break;
01160       }
01161       rval = dbl_read_colname (state, coltab, 1);
01162       if (rval != 0)
01163       {
01164         break;
01165       }
01166       colind = state->column_index;
01167       /* add lower bound value */
01168       msg = dbl_ILLraw_set_lowerBound (lp, colind, state->bound_val);
01169       dbl_ILLlp_warn (state, msg);
01170       haveBound = 1;
01171     }
01172     if (colind == -1)
01173     {
01174       rval = dbl_read_colname (state, coltab, 0);
01175       colind = state->column_index;
01176       if (rval != 0)
01177       {
01178         if (rval == -1)
01179         {
01180           rval = 0;             /* found a keyword and that's OK */
01181         }
01182         else if (rval == -2)
01183         {
01184           rval = dbl_ILLlp_error (state, "Expecting a column name.\n");
01185         }
01186         break;
01187       }
01188     }
01189     ILL_FAILtrue (colind == -1, "must have a valid colname");
01190     dbl_ILLtest_lp_state_bound_sense (state);
01191     if (state->sense_val != ' ')
01192     {
01193       sense = state->sense_val;
01194       if ((sense != 'L') && (sense != 'E'))
01195       {
01196         rval = dbl_ILLlp_error (state, "Expecting \"<=\" or \"=\".\n");
01197         break;
01198       }
01199       if (dbl_ILLread_lp_state_possible_bound_value (state))
01200       {
01201         if (sense == 'E')
01202         {
01203           msg = dbl_ILLraw_set_fixedBound (lp, colind, state->bound_val);
01204         }
01205         else
01206         {
01207           msg = dbl_ILLraw_set_upperBound (lp, colind, state->bound_val);
01208         }
01209         dbl_ILLlp_warn (state, msg);
01210         haveBound = 1;
01211       }
01212       else
01213       {
01214         rval = dbl_ILLlp_error (state, "Expecting bound value.\n");
01215         break;
01216       }
01217     }
01218     else
01219     {
01220       if (dbl_ILLtest_lp_state_next_is (state, "FREE"))
01221       {
01222         msg = dbl_ILLraw_set_unbound (lp, colind);
01223         dbl_ILLlp_warn (state, msg);
01224         haveBound = 1;
01225       }
01226       else
01227       {
01228         if (!haveBound)
01229         {
01230           rval = dbl_ILLlp_error (state, "Not a bound expression.\n");
01231           break;
01232         }
01233       }
01234     }
01235     ILL_IFTRACE ("BOUNDS: %f <= %s <= %f\n", dbl_EGlpNumToLf (lp->lower[colind]),
01236                  dbl_ILLraw_colname (lp, colind), dbl_EGlpNumToLf (lp->upper[colind]));
01237   }
01238   dbl_ILLread_lp_state_next_field (state);
01239 CLEANUP:
01240   EG_RETURN (rval);
01241 }
01242 
01243 static int dbl_add_var (
01244   dbl_rawlpdata * lp,
01245   dbl_ILLread_lp_state * state,
01246   double coef,
01247   int row,
01248   int allowNew)
01249 {
01250   char *var = state->field;
01251   int rval = 0;
01252   int colind;
01253 
01254   if (ILLsymboltab_lookup (&lp->coltab, var, &colind) != 0)
01255   {
01256     if (!allowNew)
01257     {
01258       rval = dbl_ILLlp_error (state, "Unknown col name \"%s\".\n", var);
01259     }
01260     CHECKRVALG (rval, CLEANUP);
01261     rval = dbl_ILLraw_add_col (lp, var, 0 /* not an integer var */ );
01262     colind = lp->ncols - 1;
01263     CHECKRVALG (rval, CLEANUP);
01264   }
01265   ILL_IFTRACE ("dbl_add_var: \"%s\" coef=%f row=%s\n",
01266                var, dbl_EGlpNumToLf (coef), dbl_ILLraw_rowname (lp, row));
01267   rval = dbl_ILLraw_add_col_coef (lp, colind, row, coef);
01268 CLEANUP:
01269   EG_RETURN (rval);
01270 }

Generated on Wed Apr 22 09:16:09 2009 for QSopt_ex by  doxygen 1.5.2