00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "qs_config.h"
00038 #include "dbl_iqsutil.h"
00039 #include "dbl_read_lp.h"
00040 #include "dbl_lp.h"
00041 #include "dbl_rawlp.h"
00042 #include "dbl_lpdefs.h"
00043 #include "dbl_format.h"
00044 #ifdef USEDMALLOC
00045 #include "dmalloc.h"
00046 #endif
00047 static int TRACE = 0;
00048
00049 #define dbl_END_LINE(p) (((*p) == '\\' || (*p) == '\n' || (*p) == '\0') ? 1 : 0)
00050
00051 static const char *dbl_all_keyword[] = {
00052 "MIN", "MINIMUM", "MINIMIZE",
00053 "MAX", "MAXIMUM", "MAXIMIZE",
00054 "SUBJECT", "ST", "PROBLEM", "PROB",
00055 "BOUNDS", "BOUND", "INTEGER", "END", NULL
00056 };
00057 static int dbl_all_keyword_len[] = {
00058 3, 7, 8,
00059 3, 7, 8,
00060 7, 2, 7, 4,
00061 6, 5, 7, 3, -1
00062 };
00063
00064 int dbl_ILLread_lp_state_init (
00065 dbl_ILLread_lp_state * state,
00066 dbl_qsline_reader * file,
00067 const char *dbl_fname,
00068 int inter)
00069 {
00070 int rval = 0;
00071
00072 ILL_FAILtrue (file == NULL, "need a file");
00073 state->eof = 0;
00074 state->file_name = dbl_fname;
00075 state->dbl_interactive = inter;
00076 state->file = file;
00077 state->line_num = 0;
00078 state->p = state->line;
00079 state->line[0] = '\0';
00080 state->realline[0] = '\0';
00081 state->field[0] = '\0';
00082 state->fieldOnFirstCol = 0;
00083 dbl_EGlpNumInitVar (state->bound_val);
00084 dbl_ILLread_lp_state_skip_blanks (state, 1);
00085 CLEANUP:
00086 ILL_RETURN (rval, "dbl_ILLread_lp_state_init");
00087 }
00088
00089 int dbl_ILLread_lp_state_next_line (
00090 dbl_ILLread_lp_state * state)
00091 {
00092 char *slash;
00093
00094 if (state->eof)
00095 {
00096 return 1;
00097 }
00098 state->line[0] = '\0';
00099 if (state->dbl_interactive)
00100 {
00101 fprintf (stdout, "> ");
00102 fflush (stdout);
00103 }
00104 while (dbl_ILLline_reader_get (state->realline, ILL_namebufsize - 2, state->file)
00105 != (char *) NULL)
00106 {
00107 state->p = state->line;
00108 state->line_num++;
00109 strcpy (state->line, state->realline);
00110 slash = strchr (state->line, '\\');
00111 if (slash != NULL)
00112 {
00113 *slash = '\0';
00114 }
00115 while (dbl_ILL_ISBLANK (state->p))
00116 {
00117 state->p++;
00118 }
00119 if (!dbl_END_LINE (state->p))
00120 {
00121 ILL_IFTRACE ("NEWLINE %s %d: %s",
00122 state->file_name, state->line_num, state->line);
00123 return 0;
00124 }
00125 if (state->dbl_interactive)
00126 {
00127 fprintf (stdout, "> ");
00128 fflush (stdout);
00129 }
00130 }
00131 state->eof = 1;
00132 state->line_num++;
00133 state->field[0] = '\0';
00134 state->line[0] = '\0';
00135 strcpy (state->realline, "\n");
00136 state->p = state->line;
00137 state->fieldOnFirstCol = 0;
00138 return 1;
00139 }
00140
00141 int dbl_ILLread_lp_state_skip_blanks (
00142 dbl_ILLread_lp_state * state,
00143 int wrapLines)
00144 {
00145 while (1)
00146 {
00147 while (dbl_ILL_ISBLANK (state->p))
00148 {
00149 state->p++;
00150 }
00151 if (dbl_END_LINE (state->p))
00152 {
00153 if (wrapLines)
00154 {
00155 if (dbl_ILLread_lp_state_next_line (state) != 0)
00156 {
00157 return 1;
00158 }
00159 }
00160 else
00161 {
00162 return 0;
00163 }
00164 }
00165 else
00166 {
00167 return 0;
00168 }
00169 }
00170 }
00171
00172 static int dbl_next_field (
00173 dbl_ILLread_lp_state * state,
00174 int acrossLines)
00175 {
00176 (void) dbl_ILLread_lp_state_skip_blanks (state, (char) acrossLines);
00177 if (state->eof)
00178 {
00179 return 1;
00180 }
00181 state->fieldOnFirstCol = (state->line == state->p);
00182 if (sscanf (state->p, "%s", state->field) != EOF)
00183 {
00184 state->p += strlen (state->field);
00185 return 0;
00186 }
00187 return 1;
00188 }
00189
00190 int dbl_ILLread_lp_state_next_field_on_line (
00191 dbl_ILLread_lp_state * state)
00192 {
00193 return dbl_next_field (state, 0);
00194 }
00195
00196 int dbl_ILLread_lp_state_next_field (
00197 dbl_ILLread_lp_state * state)
00198 {
00199 return dbl_next_field (state, 1);
00200 }
00201
00202 void dbl_ILLread_lp_state_prev_field (
00203 dbl_ILLread_lp_state * state)
00204 {
00205 if (state->p > state->line)
00206 {
00207 state->p--;
00208 }
00209 while (dbl_ILL_ISBLANK (state->p) && (state->p > state->line))
00210 {
00211 state->p--;
00212 }
00213 while (!dbl_ILL_ISBLANK (state->p) && (state->p > state->line))
00214 {
00215 state->p--;
00216 }
00217 state->fieldOnFirstCol = (state->line == state->p);
00218 }
00219
00220 int dbl_ILLread_lp_state_next_var (
00221 dbl_ILLread_lp_state * state)
00222 {
00223 char *p;
00224 int var_len, i;
00225
00226 if (dbl_ILLread_lp_state_skip_blanks (state, 1))
00227 {
00228 return 1;
00229 }
00230 state->fieldOnFirstCol = (state->line == state->p);
00231 var_len = 0;
00232 p = state->p;
00233 while (1)
00234 {
00235 if (dbl_ILLis_lp_name_char (*p, var_len))
00236 {
00237 p++;
00238 var_len++;
00239 }
00240 else
00241 {
00242 break;
00243 }
00244 }
00245 if (var_len == 0)
00246 {
00247 return 1;
00248 }
00249 if (state->fieldOnFirstCol)
00250 {
00251
00252 for (i = 0; dbl_all_keyword[i] != NULL; i++)
00253 {
00254 if ((var_len == dbl_all_keyword_len[i]) &&
00255 (strncasecmp (dbl_all_keyword[i], state->p, (size_t) (dbl_all_keyword_len[i]))
00256 == 0))
00257 {
00258 return -1;
00259 }
00260 }
00261 }
00262 strncpy (state->field, state->p, (size_t) var_len);
00263 state->field[var_len] = '\0';
00264 state->p = p;
00265 return 0;
00266 }
00267
00268 int dbl_ILLread_lp_state_bad_keyword (
00269 dbl_ILLread_lp_state * state)
00270 {
00271 if (!state->fieldOnFirstCol)
00272 {
00273 return dbl_ILLlp_error (state,
00274 "Keyword \"%s\" not at beginning of line.\n",
00275 state->field);
00276 }
00277 return 0;
00278 }
00279
00280 int dbl_ILLtest_lp_state_keyword (
00281 dbl_ILLread_lp_state * state,
00282 const char *kwd[])
00283 {
00284 int i = 0;
00285
00286 if (!state->eof && state->fieldOnFirstCol)
00287 {
00288 for (i = 0; kwd[i] != NULL; i++)
00289 {
00290 if (strcasecmp (state->field, kwd[i]) == 0)
00291 {
00292 return 0;
00293 }
00294 }
00295 }
00296 return 1;
00297 }
00298
00299 int dbl_ILLread_lp_state_keyword (
00300 dbl_ILLread_lp_state * state,
00301 const char *kwd[])
00302 {
00303 if (state->eof || dbl_ILLread_lp_state_bad_keyword (state))
00304 {
00305 return 1;
00306 }
00307 return dbl_ILLtest_lp_state_keyword (state, kwd);
00308 }
00309
00310
00311 int dbl_ILLread_lp_state_colon (
00312 dbl_ILLread_lp_state * state)
00313 {
00314 if ((dbl_ILLread_lp_state_skip_blanks (state, 1) == 0) && (*state->p == ':'))
00315 {
00316 state->p++;
00317 return 0;
00318 }
00319 return 1;
00320 }
00321
00322 int dbl_ILLread_lp_state_has_colon (
00323 dbl_ILLread_lp_state * state)
00324 {
00325 char *pp;
00326
00327 dbl_ILLread_lp_state_skip_blanks (state, 0);
00328 for (pp = state->p; *pp != '\n'; pp++)
00329 {
00330 if (*pp == ':')
00331 {
00332 return 1;
00333 }
00334 }
00335 return 0;
00336 }
00337
00338 int dbl_ILLread_lp_state_next_constraint (
00339 dbl_ILLread_lp_state * state)
00340 {
00341 int rval;
00342 int ln = state->line_num;
00343
00344 dbl_ILLread_lp_state_skip_blanks (state, 1);
00345 if (state->eof)
00346 {
00347 return 1;
00348 }
00349 if (ln == state->line_num)
00350 {
00351 return dbl_ILLlp_error (state, "Constraints must start on a new line.\n");
00352 }
00353 if (dbl_ILLread_lp_state_next_field (state) == 0)
00354 {
00355 rval = dbl_ILLtest_lp_state_keyword (state, dbl_all_keyword);
00356 dbl_ILLread_lp_state_prev_field (state);
00357 return !rval;
00358 }
00359 return 0;
00360 }
00361
00362
00363 int dbl_ILLread_lp_state_sign (
00364 dbl_ILLread_lp_state * state,
00365 double * sign)
00366 {
00367 char found = 0;
00368
00369 dbl_EGlpNumOne (*sign);
00370 if (dbl_ILLread_lp_state_skip_blanks (state, 1) == 0)
00371 {
00372 if ((*state->p == '+') || (*state->p == '-'))
00373 {
00374 if (*state->p != '+')
00375 dbl_EGlpNumSign (*sign);
00376 state->p++;
00377 found = 1;
00378 }
00379 }
00380 return 1 - found;
00381 }
00382
00383 int dbl_ILLtest_lp_state_next_is (
00384 dbl_ILLread_lp_state * state,
00385 const char *str)
00386 {
00387 dbl_ILLread_lp_state_skip_blanks (state, 0);
00388 if (strncasecmp (state->p, str, strlen (str)) == 0)
00389 {
00390 state->p += strlen (str);
00391 return 1;
00392 }
00393 return 0;
00394 }
00395
00396 int dbl_ILLread_lp_state_value (
00397 dbl_ILLread_lp_state * state,
00398 double * coef)
00399 {
00400 int len = 0;
00401
00402 if (dbl_ILLread_lp_state_skip_blanks (state, 1) != 0)
00403 {
00404 ILL_RESULT (1, "dbl_ILLread_lp_state_value");
00405 }
00406 else
00407 {
00408 state->fieldOnFirstCol = (state->line == state->p);
00409 len = dbl_ILLget_value (state->p, coef);
00410 if (len > 0)
00411 {
00412 state->p += len;
00413 ILL_RESULT (0, "dbl_ILLread_lp_state_value");
00414 }
00415 ILL_RESULT (1, "dbl_ILLread_lp_state_value");
00416 }
00417 }
00418
00419 int dbl_ILLread_lp_state_possible_coef (
00420 dbl_ILLread_lp_state * state,
00421 double * coef,
00422 const double defValue)
00423 {
00424 dbl_EGlpNumCopy (*coef, defValue);
00425 return dbl_ILLread_lp_state_value (state, coef);
00426 }
00427
00428
00429 int dbl_ILLread_lp_state_possible_bound_value (
00430 dbl_ILLread_lp_state * state)
00431 {
00432 double sign;
00433 int len = 0;
00434 char *p = NULL;
00435 int rval = 0;
00436
00437 dbl_EGlpNumInitVar (sign);
00438 (void) dbl_ILLread_lp_state_sign (state, &sign);
00439
00440 if (!strncasecmp (state->p, "INFINITY", (size_t) 8))
00441 {
00442 len = 8;
00443 }
00444 else
00445 {
00446 if (!strncasecmp (state->p, "INF", (size_t) 3))
00447 {
00448 len = 3;
00449 }
00450 }
00451 if (len > 0)
00452 {
00453 state->p += len;
00454 p = state->p;
00455 dbl_ILLread_lp_state_skip_blanks (state, 0);
00456 if (!dbl_END_LINE (p) && p == state->p)
00457 {
00458
00459
00460 state->p -= len;
00461 goto CLEANUP;
00462 return 0;
00463 }
00464 else
00465 {
00466 if (dbl_EGlpNumIsLessZero (sign))
00467 dbl_EGlpNumCopy (state->bound_val, dbl_ILL_MINDOUBLE);
00468 else if (dbl_EGlpNumIsGreatZero (sign))
00469 dbl_EGlpNumCopy (state->bound_val, dbl_ILL_MAXDOUBLE);
00470 else
00471 dbl_EGlpNumZero (state->bound_val);
00472 rval = 1;
00473 goto CLEANUP;
00474 }
00475 }
00476 if (dbl_ILLread_lp_state_value (state, &(state->bound_val)) == 0)
00477 {
00478 dbl_EGlpNumMultTo (state->bound_val, sign);
00479 rval = 1;
00480 goto CLEANUP;
00481 }
00482 CLEANUP:
00483 dbl_EGlpNumClearVar (sign);
00484 return rval;
00485 }
00486
00487 int dbl_ILLtest_lp_state_sense (
00488 dbl_ILLread_lp_state * state,
00489 int all)
00490 {
00491 char c;
00492
00493 state->sense_val = ' ';
00494 if (dbl_ILLread_lp_state_skip_blanks (state, 1) == 0)
00495 {
00496 c = *state->p;
00497 if (!all)
00498 {
00499 if (c == '=')
00500 {
00501 state->p++;
00502 state->sense_val = 'E';
00503 }
00504 else
00505 {
00506 if ((c == '<') && (*(state->p + 1) == '='))
00507 {
00508 state->p += 2;
00509 state->sense_val = 'L';
00510 }
00511 }
00512 }
00513 else
00514 {
00515 c = *state->p;
00516 if ((c == '<') || (c == '>'))
00517 {
00518 state->sense_val = (c == '<') ? 'L' : 'G';
00519 state->p++;
00520 c = *state->p;
00521 if (*state->p == '=')
00522 {
00523 state->p++;
00524 }
00525 }
00526 else
00527 {
00528 if (c == '=')
00529 {
00530 state->p++;
00531 c = *state->p;
00532 if ((c == '<') || (c == '>'))
00533 {
00534 state->sense_val = (c == '<') ? 'L' : 'G';
00535 state->p++;
00536 }
00537 else
00538 {
00539 state->sense_val = 'E';
00540 }
00541 }
00542 }
00543 }
00544 }
00545 return (state->sense_val != ' ');
00546 }
00547
00548 void dbl_ILLtest_lp_state_bound_sense (
00549 dbl_ILLread_lp_state * state)
00550 {
00551 (void) dbl_ILLtest_lp_state_sense (state, 0);
00552 }
00553
00554 int dbl_ILLread_lp_state_sense (
00555 dbl_ILLread_lp_state * state)
00556 {
00557 if (!dbl_ILLtest_lp_state_sense (state, 1))
00558 {
00559 if (dbl_END_LINE (state->p))
00560 {
00561 return dbl_ILLlp_error (state, "Missing row sense at end of line.\n");
00562 }
00563 else
00564 {
00565 if (*state->p != '\0')
00566 {
00567 return dbl_ILLlp_error (state, "\"%c\" is not a row sense.\n", *state->p);
00568 }
00569 else
00570 {
00571 return dbl_ILLlp_error (state, "Missing row sense at end of line.\n");
00572 }
00573 }
00574 }
00575 return 0;
00576 }
00577
00578
00579
00580
00581
00582 static void dbl_ILLread_lp_state_print_at (
00583 dbl_ILLread_lp_state * state)
00584 {
00585 char *p;
00586
00587 if (state->eof)
00588 {
00589 fprintf (stderr, "end of file");
00590 }
00591 else
00592 {
00593 if (*state->p == '\n')
00594 {
00595 fprintf (stderr, "end of line");
00596 }
00597 else
00598 {
00599 p = state->p;
00600 while (dbl_ILL_ISBLANK (p))
00601 {
00602 p++;
00603 }
00604 fprintf (stderr, "%c", '"');
00605 for (; !dbl_ILL_ISBLANK (p) && !dbl_END_LINE (p); p++)
00606 {
00607 fprintf (stderr, "%c", *p);
00608 }
00609 fprintf (stderr, "\"");
00610 }
00611 }
00612 }
00613
00614 static void dbl_lp_err (
00615 dbl_ILLread_lp_state * state,
00616 int isError,
00617 const char *format,
00618 va_list args)
00619 {
00620 int rval = 0;
00621 int errtype, slen, at;
00622 dbl_qsformat_error error;
00623 char error_desc[256];
00624
00625 ILL_FAILfalse (state != NULL, "state != NULL");
00626 ILL_FAILfalse (state->file != NULL, "state->file != NULL");
00627 ILL_FAILfalse (format != NULL, "format != NULL");
00628 ILL_FAILfalse (format[0] != '\0', "format[0] != '0'");
00629
00630 dbl_ILLread_lp_state_skip_blanks (state, 0);
00631 at = state->p - state->line;
00632 vsprintf (error_desc, format, args);
00633 slen = strlen (error_desc);
00634 if ((slen > 0) && error_desc[slen - 1] != '\n')
00635 {
00636 error_desc[slen] = '\n';
00637 error_desc[slen + 1] = '\0';
00638 }
00639
00640 if (state->file->error_collector != NULL)
00641 {
00642 errtype = (isError) ? QS_LP_FORMAT_ERROR : QS_LP_FORMAT_WARN;
00643 dbl_ILLformat_error_create (&error, errtype, error_desc,
00644 state->line_num, state->realline, at);
00645 dbl_ILLformat_error (state->file->error_collector, &error);
00646 dbl_ILLformat_error_delete (&error);
00647 }
00648 else
00649 {
00650 if (!state->dbl_interactive)
00651 {
00652 fprintf (stderr, "%s %d: %s\t", state->file_name, state->line_num,
00653 state->realline);
00654 fprintf (stderr, "%s at ", (isError) ? "LP Error" : "LP Warning");
00655 dbl_ILLread_lp_state_print_at (state);
00656 fprintf (stderr, ": ");
00657 }
00658 else
00659 {
00660 fprintf (stderr, "%s : ", (isError) ? "LP Error" : "LP Warning");
00661 }
00662 fprintf (stderr, error_desc);
00663 fflush (stderr);
00664 }
00665 CLEANUP:;
00666 }
00667
00668 int dbl_ILLlp_error (
00669 dbl_ILLread_lp_state * state,
00670 const char *format,
00671 ...)
00672 {
00673 va_list args;
00674
00675 va_start (args, format);
00676 dbl_lp_err (state, dbl_TRUE, format, args);
00677 return 1;
00678 }
00679
00680 void dbl_ILLlp_warn (
00681 dbl_ILLread_lp_state * state,
00682 const char *format,
00683 ...)
00684 {
00685 va_list args;
00686
00687 va_start (args, format);
00688 if (format != NULL)
00689 {
00690 dbl_lp_err (state, dbl_FALSE, format, args);
00691 }
00692 }
00693
00694
00695 int dbl_ILLget_value (
00696 char *line,
00697 double * coef)
00698 {
00699 #ifdef mpq_READ_LP_STATE_H
00700 mpq_t res;
00701 int rval = 0;
00702
00703 mpq_init (res);
00704 rval = mpq_EGlpNumReadStrXc (res, line);
00705 if (rval == 0)
00706 mpq_set_ui (*coef, 1UL, 1UL);
00707 else
00708 mpq_set (*coef, res);
00709 mpq_clear (res);
00710 return rval;
00711
00712 #else
00713 char field[ILL_namebufsize];
00714 int rval = 0, i;
00715 char c, lastC, *p;
00716 int allowDot, allowExp, allowSign;
00717 double dtmp;
00718
00719 p = line;
00720 c = *p;
00721 i = 0;
00722 lastC = ' ';
00723 allowSign = 1;
00724 allowExp = 0;
00725 allowDot = 1;
00726 while ((('0' <= c) && (c <= '9')) ||
00727 (allowDot && (c == '.')) ||
00728 ((allowExp == 1) && ((c == 'e') || (c == 'E'))) ||
00729 ((allowSign || lastC == 'e' || lastC == 'E') &&
00730 ((c == '+') || (c == '-'))))
00731 {
00732 if (c == '.')
00733 allowDot = 0;
00734 allowSign = 0;
00735
00736 if ((allowExp == 0) && (c >= '0') && (c <= '9'))
00737 {
00738 allowExp = 1;
00739 }
00740 if ((c == 'e') || (c == 'E'))
00741 {
00742 allowExp++;
00743 allowDot = 0;
00744 }
00745 p++;
00746 lastC = c;
00747 c = *p;
00748 i++;
00749 }
00750 if ((lastC == '+') || (lastC == '-'))
00751 {
00752 p--;
00753 i--;
00754 if (p > line)
00755 lastC = *(p - 1);
00756 else
00757 lastC = ' ';
00758 }
00759 if ((lastC == 'e') || (lastC == 'E'))
00760 {
00761 p--;
00762 i--;
00763 }
00764 if (i > 0)
00765 {
00766 strncpy (field, line, (size_t) i);
00767 field[i] = '\0';
00768 rval = !sscanf (field, "%lf%n", &dtmp, &i);
00769 dbl_EGlpNumSet (*coef, dtmp);
00770 ILL_IFTRACE ("%la\n", dbl_EGlpNumToLf (*coef));
00771 if (rval != 0)
00772 {
00773 ILL_RESULT (0, "dbl_ILLget_value");
00774 }
00775 }
00776
00777 return i;
00778 #endif
00779 }
00780
00781 int dbl_ILLcheck_subject_to (
00782 dbl_ILLread_lp_state * state)
00783 {
00784 int rval;
00785 char *p;
00786
00787 if ((rval = dbl_ILLread_lp_state_next_field (state)) == 0)
00788 {
00789 if (strcasecmp (state->field, "ST") == 0)
00790 {
00791 rval = dbl_ILLread_lp_state_bad_keyword (state);
00792 }
00793 else
00794 {
00795 if (strcasecmp (state->field, "SUBJECT") == 0)
00796 {
00797 p = state->p;
00798 while (dbl_ILL_ISBLANK (p))
00799 {
00800 p++;
00801 }
00802 if (!strncasecmp (p, "TO", (size_t) 2))
00803 {
00804 rval = dbl_ILLread_lp_state_bad_keyword (state);
00805 if (rval == 0)
00806 {
00807 state->p = p + 2;
00808 }
00809 }
00810 }
00811 else
00812 {
00813 rval = 1;
00814 }
00815 }
00816 if (rval != 0)
00817 {
00818 dbl_ILLread_lp_state_prev_field (state);
00819 }
00820 else
00821 {
00822 dbl_ILLread_lp_state_skip_blanks (state, 1);
00823 }
00824 }
00825 ILL_RESULT (rval, "check_subject_to");
00826 }