dbl_read_mps.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: read_mps_state.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
00024 
00025 /****************************************************************************/
00026 /*                                                                          */
00027 /*               Routines to Support  Reading MPS Files                     */
00028 /*                                                                          */
00029 /****************************************************************************/
00030 
00031 #include "qs_config.h"
00032 #include "dbl_iqsutil.h"
00033 #include "dbl_rawlp.h"
00034 #include "dbl_read_mps.h"
00035 #include "dbl_read_lp.h"            /* for dbl_ILLget_value */
00036 #include "dbl_format.h"
00037 #ifdef USEDMALLOC
00038 #include "dmalloc.h"
00039 #endif
00040 static int TRACE = 0;
00041 
00042 #define dbl_END_LINE(p)  (((*(p)) == '$' || (*(p)) == '\n' || (*(p)) == '\0') ? 1 : 0)
00043 
00044 static int dbl_mps_skip_comment (
00045   dbl_ILLread_mps_state * state);
00046 static char dbl_ILLmps_next_field_is_number (
00047   dbl_ILLread_mps_state * state);
00048 
00049 int dbl_ILLmps_state_init (
00050   dbl_ILLread_mps_state * state,
00051   dbl_qsline_reader * file,
00052   const char *dbl_fname)
00053 {
00054   int i, rval = 0;
00055 
00056   ILL_FAILtrue (file == 0, "need file");
00057   state->p = 0;
00058   state->file_name = dbl_fname;
00059   state->file = file;
00060 
00061   for (i = 0; i < ILL_MPS_N_SECTIONS; i++)
00062   {
00063     state->section[i] = 0;
00064   }
00065   state->active = ILL_MPS_NONE;
00066   state->intvar = 0;
00067   state->sosvar = 0;
00068   state->line_num = 0;
00069   state->p = 0;
00070 
00071   state->obj = 0;
00072   state->line[0] = '\0';
00073   state->key[0] = '\0';
00074   state->field[0] = '\0';
00075 
00076 CLEANUP:
00077   ILL_RESULT (rval, "dbl_ILLmps_state_init");
00078 }
00079 
00080 int dbl_ILLmps_next_line (
00081   dbl_ILLread_mps_state * state)
00082 {
00083   int rval = 0;
00084 
00085   /* if field 3 or 5 start with $ rest of line is interpreted as comment */
00086   state->line[0] = '\0';
00087   state->p = 0;
00088   while (dbl_ILLline_reader_get (state->line, ILL_namebufsize - 2, state->file)
00089          != 0)
00090   {
00091     state->line_num++;
00092     state->key[0] = '\0';
00093     state->field[0] = '\0';
00094     state->field_num = 1;
00095     state->p = state->line;
00096     if (!dbl_ILL_ISBLANK ((state->line)))
00097     {
00098       if (state->line[0] == '*' || state->line[0] == '\n')
00099       {
00100         continue;               /* comment or blank line */
00101       }
00102       else
00103       {
00104         if (sscanf (state->p, "%s", state->key) == 1)
00105         {
00106           state->p += strlen (state->key);
00107           while (dbl_ILL_ISBLANK (state->p))
00108           {
00109             state->p++;
00110           }
00111           if (sscanf (state->p, "%s", state->field) == 1)
00112           {
00113             state->p += strlen (state->field);
00114           }
00115           else
00116           {
00117             ILL_FAILfalse (state->field[0] == '\0', "sscanf problem?");
00118           }
00119         }
00120         else
00121         {
00122           ILL_FAILfalse (0, "should almost never happen");
00123         }
00124       }
00125     }
00126     else
00127     {
00128       while (dbl_ILL_ISBLANK (state->p))
00129       {
00130         state->p++;
00131       }
00132       if (sscanf (state->p, "%s", state->field) < 1)
00133       {
00134         continue;               /* nothing more on line */
00135       }
00136       else
00137       {
00138         if (state->field[0] == '\0')
00139         {
00140           continue;             /* found empty string */
00141         }
00142         state->p += strlen (state->field);
00143       }
00144     }
00145     return 0;
00146   }
00147 CLEANUP:
00148   return 1;                     /* end of file */
00149 }
00150 
00151 /* fields 3,5,7,... may start with '$' signifying comment 
00152  * ==> if we find a '$' as next non blank and 
00153  *     we read 2,4,6,... fields successfully so far
00154  *     we have a comment 
00155  */
00156 static int dbl_mps_skip_comment (
00157   dbl_ILLread_mps_state * state)
00158 {
00159   int rval;
00160 
00161   while (dbl_ILL_ISBLANK (state->p))
00162   {
00163     state->p++;
00164   }
00165   rval = ((*state->p == '$') && (state->field_num >= 2) &&
00166           (state->field_num % 2 == 0));
00167   return rval;
00168 }
00169 
00170 int dbl_ILLmps_next_field (
00171   dbl_ILLread_mps_state * state)
00172 {
00173   state->field[0] = '\0';
00174   if (!dbl_mps_skip_comment (state))
00175   {
00176     if (sscanf (state->p, "%s", state->field) == 1)
00177     {
00178       state->p += strlen (state->field) + 1;
00179       state->field_num++;
00180       return 0;
00181     }
00182   }
00183   return 1;                     /* no more fields */
00184 }
00185 
00186 static char dbl_get_double (
00187   dbl_ILLread_mps_state * state,
00188   int peek,
00189   double * coef)
00190 {
00191   char ok = 0;
00192   int len, rval = 0;
00193 
00194   ILL_FAILfalse (state != 0, "must have state");
00195   if (dbl_mps_skip_comment (state))
00196     return 0;
00197   len = dbl_ILLget_value (state->p, coef);
00198   if (len > 0)
00199   {
00200     if (!peek)
00201     {
00202       state->p += len;
00203       state->field_num++;
00204     }
00205     ok = 1;
00206   }
00207 CLEANUP:
00208   ILL_RESULT (ok, "dbl_get_double");
00209 }
00210 
00211 int dbl_ILLmps_next_coef (
00212   dbl_ILLread_mps_state * state,
00213   double * coef)
00214 {
00215   int len = 0;
00216 
00217   if (!dbl_mps_skip_comment (state))
00218   {
00219     len = dbl_get_double (state, 0, coef);
00220   }
00221   ILL_RESULT (!(len > 0), "dbl_ILLmps_next_coef");
00222 }
00223 
00224 int dbl_ILLmps_next_bound (
00225   dbl_ILLread_mps_state * state,
00226   double * coef)
00227 {
00228   int len = 0, sign = 1;
00229   char c, *p;
00230 
00231   if (!dbl_mps_skip_comment (state))
00232   {
00233     c = *state->p;
00234     if (c == '-')
00235     {
00236       sign = -1;
00237       len = 1;
00238     }
00239     else
00240     {
00241       if (c == '+')
00242       {
00243         len = 1;
00244       }
00245     }
00246     if (!strncasecmp (state->p + len, "INFINITY", (size_t) 8))
00247     {
00248       len += 8;
00249     }
00250     else
00251     {
00252       if (!strncasecmp (state->p + len, "INF", (size_t) 3))
00253       {
00254         len += 3;
00255       }
00256     }
00257     if (len > 1)
00258     {
00259       state->p += len;
00260       p = state->p;
00261       dbl_mps_skip_comment (state);
00262       if (!dbl_END_LINE (state->p) && p == state->p)
00263       {
00264         /* found no blanks so this INF/INFINITY is the prefix 
00265          * of something else */
00266         state->p -= len;
00267         return 1;               /* no coef found */
00268       }
00269       else
00270       {
00271         if (sign == 1)
00272           dbl_EGlpNumCopy (*coef, dbl_ILL_MAXDOUBLE);
00273         else
00274           dbl_EGlpNumCopy (*coef, dbl_ILL_MINDOUBLE);
00275         state->field_num++;
00276         ILL_RESULT (0, "dbl_ILLmps_next_bound");
00277       }
00278     }
00279     if (dbl_get_double (state, 0, coef))
00280     {
00281       ILL_RESULT (0, "dbl_ILLmps_next_bound");
00282     }
00283     else
00284     {
00285       ILL_RESULT (1, "dbl_ILLmps_next_bound");  /* no coef found */
00286     }
00287   }
00288   ILL_RETURN (1, "dbl_ILLmps_next_bound");
00289 }
00290 
00291 static char dbl_ILLmps_next_field_is_number (
00292   dbl_ILLread_mps_state * state)
00293 {
00294   double d;
00295   int len = 0;
00296 
00297   if (!dbl_mps_skip_comment (state))
00298   {
00299     dbl_EGlpNumInitVar (d);
00300     len = dbl_get_double (state, 1, &d);
00301     dbl_EGlpNumClearVar (d);
00302   }
00303   return (len > 0);
00304 }
00305 
00306 void dbl_ILLmps_check_end_of_line (
00307   dbl_ILLread_mps_state * state)
00308 {
00309   if (!dbl_mps_skip_comment (state))
00310   {
00311     if (!dbl_END_LINE (state->p))
00312     {
00313       dbl_ILLmps_warn (state, "Extra fields on line.");
00314     }
00315   }
00316 }
00317 
00318 void dbl_ILLmps_set_end_of_line (
00319   dbl_ILLread_mps_state * state)
00320 {
00321   *state->p = '\n';
00322 }
00323 
00324 int dbl_ILLmps_set_section (
00325   dbl_ILLread_mps_state * state,
00326   const ILLmps_section sec)
00327 {
00328   int rval = 0;
00329 
00330   ILL_FAILfalse (sec != ILL_MPS_NONE, "must be in a proper section");
00331   if (state->section[sec])
00332   {
00333     rval = dbl_ILLmps_error (state, "Two %s sections.\n", dbl_ILLmps_section_name[sec]);
00334   }
00335   state->section[sec]++;
00336   state->active = sec;
00337 CLEANUP:
00338   ILL_RESULT (rval, "dbl_ILLmps_set_section");
00339 }
00340 
00341 int dbl_ILLmps_int_sos_mode (
00342   dbl_ILLread_mps_state * state)
00343 {
00344   if (!strcmp (state->field, "'INTORG'"))
00345   {
00346     if (state->intvar)
00347     {
00348       return !dbl_ILLmps_error (state, "'INTEND' expected.\n");
00349     }
00350     else
00351     {
00352       state->intvar = 1;
00353       ILL_RESULT (0, "dbl_ILLmps_int_sos_mode");
00354     }
00355   }
00356   if (!strcmp (state->field, "'INTEND'"))
00357   {
00358     if (state->intvar)
00359     {
00360       state->intvar = 0;
00361       ILL_RESULT (0, "dbl_ILLmps_int_sos_mode");
00362     }
00363     else
00364     {
00365       return !dbl_ILLmps_error (state, "'INTORG' expected.\n");
00366     }
00367   }
00368   if (!strcmp (state->field, "'SOSORG'"))
00369   {
00370     if (state->sosvar)
00371     {
00372       return !dbl_ILLmps_error (state, "'SOSEND' expected.\n");
00373     }
00374     else
00375     {
00376       state->sosvar = 1;
00377       ILL_RESULT (0, "dbl_ILLmps_int_sos_mode");
00378     }
00379   }
00380   if (!strcmp (state->field, "'SOSEND'"))
00381   {
00382     if (state->sosvar)
00383     {
00384       state->sosvar = 0;
00385       ILL_RESULT (0, "dbl_ILLmps_int_sos_mode");
00386     }
00387     else
00388     {
00389       return !dbl_ILLmps_error (state, "'SOSORG' expected.\n");
00390     }
00391   }
00392   return dbl_ILLmps_error (state, "%s is not a MARKER field.\n", state->field);
00393 }
00394 
00395 const char *dbl_ILLmps_possibly_blank_name (
00396   const char *field,
00397   dbl_ILLread_mps_state * state,
00398   ILLsymboltab * tab)
00399 {
00400   int ind;
00401 
00402   if (ILLsymboltab_lookup (tab, field, &ind) == 0)
00403   {
00404     /* Possibly a blank identifier on the line */
00405     if (dbl_ILLmps_next_field_is_number (state))
00406     {
00407       /* assume a blank bound ident */
00408       return " ";
00409     }
00410     else
00411     {
00412       return field;
00413     }
00414   }
00415   else
00416   {
00417     return field;
00418   }
00419 }
00420 
00421 int dbl_ILLmps_empty_key (
00422   dbl_ILLread_mps_state * state)
00423 {
00424   return state->key[0] == '\0';
00425 }
00426 
00427 int dbl_ILLmps_empty_field (
00428   dbl_ILLread_mps_state * state)
00429 {
00430   return state->field[0] == '\0';
00431 }
00432 
00433 static void dbl_mps_err (
00434   dbl_ILLread_mps_state * state,
00435   int isError,
00436   const char *format,
00437   va_list args)
00438 {
00439   int rval = 0;
00440   const char *type = (isError) ? "MPS Error" : "MPS Warning";
00441   int errtype, slen, at;
00442   dbl_qsformat_error error;
00443   char error_desc[256];
00444 
00445   ILL_FAILfalse_no_rval (format != 0, "format != 0");
00446   ILL_FAILfalse_no_rval (format[0] != '\0', "format[0] != '0'");
00447   ILL_FAILfalse_no_rval (state != 0, "state != 0");
00448   ILL_FAILfalse_no_rval (state->file != 0, "state->file != 0");
00449 
00450   if (state->p == 0)
00451   {
00452     at = -1;
00453   }
00454   else
00455   {
00456     ILL_FAILfalse (state->p >= state->line, "state->p >= state->line");
00457     at = state->p - state->line;
00458   }
00459   vsprintf (error_desc, format, args);
00460   slen = strlen (error_desc);
00461   if ((slen > 0) && error_desc[slen - 1] != '\n')
00462   {
00463     error_desc[slen] = '\n';
00464     error_desc[slen + 1] = '\0';
00465   }
00466 
00467   if (state->file->error_collector != 0)
00468   {
00469     errtype = (isError) ? QS_MPS_FORMAT_ERROR : QS_MPS_FORMAT_WARN;
00470     dbl_ILLformat_error_create (&error, errtype, error_desc,
00471                             (int) (state->line_num), state->line, at);
00472     dbl_ILLformat_error (state->file->error_collector, &error);
00473     dbl_ILLformat_error_delete (&error);
00474   }
00475   else
00476   {
00477     fprintf (stderr, "%s %d: %s\t", state->file_name, state->line_num,
00478              state->line);
00479     fprintf (stderr, "%s: ", type);
00480     vfprintf (stderr, format, args);
00481     if (format[strlen (format) - 1] != '\n')
00482     {
00483       fprintf (stderr, "\n");
00484     }
00485     fflush (stderr);
00486   }
00487 CLEANUP:
00488   ;
00489 }
00490 
00491 int dbl_ILLmps_error (
00492   dbl_ILLread_mps_state * state,
00493   const char *format,
00494   ...)
00495 {
00496   va_list args;
00497 
00498   va_start (args, format);
00499   dbl_mps_err (state, dbl_TRUE, format, args);
00500   /* ILL_RESULT(1, "dbl_ILLmps_error"); */
00501   return 1;
00502 }
00503 
00504 void dbl_ILLmps_warn (
00505   dbl_ILLread_mps_state * state,
00506   const char *format,
00507   ...)
00508 {
00509   va_list args;
00510 
00511   va_start (args, format);
00512   if (format != 0)
00513   {
00514     dbl_mps_err (state, dbl_FALSE, format, args);
00515   }
00516 }

Generated on Thu Mar 29 09:32:29 2012 for QSopt_ex by  doxygen 1.4.7