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
00038
00039
00040
00041
00042
00043 #include <stdio.h>
00044 #include "econfig.h"
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
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
00088
00089
00090
00091
00092
00093
00094
00095
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
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
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
00228
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
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
00316
00317
00318 if ((line->total >= dbl_LINE_LEN) && (var >= 4))
00319 {
00320
00321
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;
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
00575
00576
00577
00578
00579
00580
00581
00582
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
00664
00665
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
00685
00686
00687 int dbl_ILLread_lp (
00688 dbl_qsline_reader * file,
00689 const char *dbl_fname,
00690 dbl_rawlpdata * lp)
00691 {
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
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;
00877
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
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
01078
01079
01080
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 {
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
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
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;
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 );
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 }