dbl_lib.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_lib.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
00024 //static int TRACE = 0;
00025 
00026 /****************************************************************************/
00027 /*                                                                          */
00028 /*               Interface Routines to Core LP Solver                       */
00029 /*                                                                          */
00030 /*  EXPORTED FUNCTIONS                                                      */
00031 /*                                                                          */
00032 /*    int dbl_ILLlib_optimize (dbl_lpinfo *lp, dbl_ILLlp_basis *B, dbl_price_info *pinf,    */
00033 /*            int algo, int *status, int simplex_display)                   */
00034 /*    int dbl_ILLlib_cache_solution (dbl_lpinfo *lp, dbl_ILLlp_cache *C)                */
00035 /*    int dbl_ILLlib_solution (dbl_lpinfo *lp, dbl_ILLlp_cache *C, double *val,         */
00036 /*            double *x, double *pi, double *slack, double *rc)             */
00037 /*    int dbl_ILLlib_get_x (dbl_lpinfo *lp, dbl_ILLlp_cache *C, double *x)              */
00038 /*    int dbl_ILLlib_get_slack (dbl_lpinfo *lp, dbl_ILLlp_cache *C, double *slack)      */
00039 /*    int dbl_ILLlib_objval (dbl_lpinfo *lp, dbl_ILLlp_cache *C, double *val)           */
00040 /*    int dbl_ILLlib_newrow (dbl_lpinfo *lp, dbl_ILLlp_basis *B, double rhs,            */
00041 /*            char sense, double range, const char *name)                   */
00042 /*        -range can specify a rangeval for the row (if sense is not 'R',   */
00043 /*         then range is ignored); it should be 0 if no range is needed;    */
00044 /*         if sense is 'R' but no rangeval array exists for the LP, the     */
00045 /*         array will be allocated and initialized.                         */
00046 /*    int dbl_ILLlib_newrows (dbl_lpinfo *lp, dbl_ILLlp_basis *B, int num, double *rhs, */
00047 /*            char *sense, double *range, const char **names)               */
00048 /*        -range is an array specifying the rangevals for the rows; range   */
00049 /*         should be NULL if no rangevals are needed.                       */
00050 /*    int dbl_ILLlib_addrow (dbl_lpinfo *lp, dbl_ILLlp_basis *B, int cnt, int *ind,     */
00051 /*            double *val, double rhs, char sense, double range,            */
00052 /*            const char *name)                                             */
00053 /*    int dbl_ILLlib_addrows (dbl_lpinfo *lp, dbl_ILLlp_basis *B, int num,              */
00054 /*            int *rmatcnt, int *rmatbeg, int *rmatind, double *rmatval,    */
00055 /*            double *rhs, char *sense, double *range, const char **names,  */
00056 /*            int *factorok)                                                */
00057 /*    int dbl_ILLlib_delrows (dbl_lpinfo *lp, dbl_ILLlp_basis *B,                       */
00058 /*            int num, int *dellist, int *basis_ok)                         */
00059 /*    int dbl_ILLlib_newcol (dbl_lpinfo *lp, dbl_ILLlp_basis *B,                        */
00060 /*            double obj, double lower, double upper, const char *name,     */
00061 /*            int factorok)                                                 */
00062 /*    int dbl_ILLlib_newcols (dbl_lpinfo *lp, dbl_ILLlp_basis *B,                       */
00063 /*            int num, double *obj, double *lower, double *upper,           */
00064 /*            const char **names, int factorok)                             */
00065 /*    int dbl_ILLlib_addcol (dbl_lpinfo *lp, dbl_ILLlp_basis *B,                        */
00066 /*            int cnt, int *ind, double *val, double obj, double lower,     */
00067 /*            double upper, const char *name, int factorok)                 */
00068 /*    int dbl_ILLlib_addcols (dbl_lpinfo *lp, dbl_ILLlp_basis *B,                       */
00069 /*            int num, int *cmatcnt, int *cmatbeg, int *cmatind,            */
00070 /*            double *cmatval, double *obj, double *lower, double *upper,   */
00071 /*            const char **names, int factorok)                             */
00072 /*    int dbl_ILLlib_delcols (dbl_lpinfo *lp, dbl_ILLlp_basis *B, int num, int *dellist */
00073 /*            int *basis_ok)                                                */
00074 /*    int dbl_ILLlib_chgcoef (dbl_lpinfo *lp, int rowindex, int colindex,           */
00075 /*            double coef)                                                  */
00076 /*    int dbl_ILLlib_chgsense (dbl_lpinfo *lp, int num, int *rowlist, char *sense)  */
00077 /*    int dbl_ILLlib_getrows (dbl_lpinfo *lp, int num, int *rowlist, int **rowcnt,  */
00078 /*            int **rowbeg, int **rowind, double **rowval, double **rhs,    */
00079 /*            char **sense, char ***names)                                  */
00080 /*    int dbl_ILLlib_getcols (dbl_lpinfo *lp, int num, int *collist, int **colcnt,  */
00081 /*            int **colbeg, int **colind, double **colval, double **obj,    */
00082 /*            double **lower, double **upper, char ***names)                */
00083 /*    int dbl_ILLlib_getobj (dbl_lpinfo *lp, double *obj)                           */
00084 /*    int dbl_ILLlib_chgobj (dbl_lpinfo *lp, int indx, double coef)                 */
00085 /*    int dbl_ILLlib_getrhs (dbl_lpinfo *lp, double *rhs)                           */
00086 /*    int dbl_ILLlib_chgrhs (dbl_lpinfo *lp, int indx, double coef)                 */
00087 /*    int dbl_ILLlib_getintflags (dbl_lpinfo *lp, int *intflags)                    */
00088 /*    int dbl_ILLlib_rownames (dbl_lpinfo *lp, char **rownames)                     */
00089 /*    int dbl_ILLlib_colnames (dbl_lpinfo *lp, char **colnames)                     */
00090 /*    int dbl_ILLlib_colindex (dbl_lpinfo *lp, char *name, int *colindex)           */
00091 /*    int dbl_ILLlib_rowindex (dbl_lpinfo *lp, char *name, int *rowindex)           */
00092 /*    int dbl_ILLlib_chgbnd  (dbl_lpinfo *lp, int indx, char lu, double bnd)        */
00093 /*    int dbl_ILLlib_chgbnds (dbl_lpinfo *lp, int cnt, int *indx, char *lu,         */
00094 /*            double *bnd)                                                  */
00095 /*    int dbl_ILLlib_getbnd (dbl_lpinfo *lp, int indx, char lu, double *bnd)        */
00096 /*    int dbl_ILLlib_getbnds (dbl_lpinfo *lp, double *lower, double *upper)         */
00097 /*    int dbl_ILLlib_strongbranch (dbl_lpinfo *lp, dbl_price_info *pinf,                */
00098 /*      int *candidatelist, int ncand, double *xlist, double *downpen,      */
00099 /*      double *uppen, int iterations, double objbound)                     */
00100 /*    int dbl_ILLlib_getbasis (dbl_lpinfo *lp, char *cstat, char *rstat)            */
00101 /*    int dbl_ILLlib_loadbasis (dbl_ILLlp_basis *B, int nstruct, int nrows,         */
00102 /*      char *cstat, char *rstat)                                           */
00103 /*    int dbl_ILLlib_readbasis (dbl_lpinfo *lp, dbl_ILLlp_basis *B, char *dbl_fname)        */
00104 /*    int dbl_ILLlib_writebasis (dbl_lpinfo *lp, const char *dbl_fname)                 */
00105 /*    int dbl_ILLlib_getrownorms (dbl_lpinfo *lp, dbl_price_info *pinf,                 */
00106 /*            double *rownorms)                                             */
00107 /*    int dbl_ILLlib_loadrownorms (dbl_lpinfo *lp, dbl_price_info *pinf,                */
00108 /*            double *rownorms)                                             */
00109 /*    int dbl_ILLlib_recompute_rownorms (dbl_lpinfo *lp, dbl_price_info *pinf)          */
00110 /*    int dbl_ILLlib_print_x (FILE *fd, dbl_lpinfo *lp, dbl_ILLlp_cache *C, double *x,  */
00111 /*            int nonZerosOnly)                                             */
00112 /*    int dbl_ILLlib_print_x (dbl_lpinfo *lp, dbl_ILLlp_cache *C)                       */
00113 /*    int dbl_ILLlib_iter (dbl_lpinfo *lp)                                          */
00114 /*                                                                          */
00115 /*  NOTES                                                                   */
00116 /*                                                                          */
00117 /*                                                                          */
00118 /****************************************************************************/
00119 
00120 #include "econfig.h"
00121 #include "dbl_iqsutil.h"
00122 #include "dbl_lpdata.h"
00123 #include "dbl_lpdefs.h"
00124 #include "dbl_simplex.h"
00125 #include "dbl_price.h"
00126 #include "dbl_basis.h"
00127 #include "dbl_lib.h"
00128 #include "dbl_qstruct.h"
00129 #include "dbl_qsopt.h"
00130 #include "dbl_lp.h"
00131 #include "dbl_mps.h"
00132 #ifdef USEDMALLOC
00133 #include "dmalloc.h"
00134 #endif
00135 
00136 static void dbl_check_pinf (
00137   dbl_price_info * pinf,
00138   int *it_exists);
00139 
00140 static int dbl_matrix_addrow (
00141   dbl_ILLmatrix * A,
00142   int rowcnt,
00143   int *rowind,
00144   double * rowval),
00145   dbl_matrix_addrow_end (
00146   dbl_ILLmatrix * A,
00147   int row,
00148   int rowcnt,
00149   int *rowind,
00150   double * rowval),
00151   dbl_matrix_addcoef (
00152   dbl_lpinfo * lp,
00153   dbl_ILLmatrix * A,
00154   int row,
00155   int col,
00156   double val),
00157   dbl_matrix_addcol (
00158   dbl_ILLmatrix * A,
00159   int colcnt,
00160   int *colind,
00161   double * colval),
00162   dbl_delcols_work (
00163   dbl_lpinfo * lp,
00164   char *colmark),
00165   dbl_reset_colindex (
00166   dbl_lpinfo * lp),
00167   dbl_reset_rowindex (
00168   dbl_lpinfo * lp);
00169 
00170 int dbl_ILLlib_optimize (
00171   dbl_lpinfo * lp,
00172   dbl_ILLlp_basis * B,
00173   dbl_price_info * pinf,
00174   int algo,
00175   int *status,
00176   int simplex_display,
00177   itcnt_t*itcnt)
00178 {
00179   int rval = 0;
00180   int sol_status;
00181 
00182   if (status)
00183     *status = QS_LP_UNSOLVED;
00184 
00185   /* dbl_ILLprice_free_pricing_info (pinf); *//* Should be removed later */
00186 
00187   rval = dbl_ILLsimplex (lp, algo, B, pinf, &sol_status, simplex_display, itcnt);
00188   CHECKRVALG (rval, CLEANUP);
00189 
00190   if (status)
00191     *status = sol_status;
00192 
00193 CLEANUP:
00194 
00195   if (rval == E_SIMPLEX_ERROR)
00196   {
00197     FILE *eout = 0;
00198     int tval;
00199 
00200     printf ("write bad lp to error.lp\n");
00201     fflush (stdout);
00202     eout = fopen ("error.lp", "w");
00203     if (!eout)
00204     {
00205       fprintf (stderr, "could not open file to write bad lp\n");
00206     }
00207     else
00208     {
00209       tval = dbl_ILLwrite_lp (lp->O, NULL);
00210       if (tval)
00211       {
00212         fprintf (stderr, "error while writing bad lp\n");
00213       }
00214       fclose (eout);
00215     }
00216 
00217     printf ("write bad basis to error.bas\n");
00218     fflush (stdout);
00219     tval = dbl_ILLlib_writebasis (lp, 0, "error.bas");
00220     if (tval)
00221     {
00222       fprintf (stderr, "error while writing bad basis\n");
00223     }
00224   }
00225   if (rval == QS_LP_CHANGE_PREC)
00226   {
00227     MESSAGE (__QS_SB_VERB, "Changing dbl_precision");
00228     return rval;
00229   }
00230   MESSAGE (rval ? 0 : 1000, "Error code %d", rval);
00231   EG_RETURN (rval);
00232 }
00233 
00234 int dbl_ILLlib_cache_solution (
00235   dbl_lpinfo * lp,
00236   dbl_ILLlp_cache * C)
00237 {
00238   int rval = 0;
00239 
00240   if (C)
00241   {
00242     if (C->nstruct != lp->O->nstruct || C->nrows != lp->O->nrows)
00243     {
00244       fprintf (stderr, "lp_cache does not match size of lp\n");
00245       rval = 1;
00246       ILL_CLEANUP;
00247     }
00248     rval = dbl_ILLlib_solution (lp, 0, &(C->val), C->x, C->pi, C->slack, C->rc);
00249     CHECKRVALG (rval, CLEANUP);
00250   }
00251 
00252 CLEANUP:
00253 
00254   EG_RETURN (rval);
00255 }
00256 
00257 int dbl_ILLlib_solution (
00258   dbl_lpinfo * lp,
00259   dbl_ILLlp_cache * C,
00260   double * val,
00261   double * x,
00262   double * pi,
00263   double * slack,
00264   double * rc)
00265 {
00266   int i, rval = 0;
00267   double *tempx = 0;
00268   double *temprc = 0;
00269   int ncols = lp->O->ncols;
00270   int nrows = lp->O->nrows;
00271   int nstruct = lp->O->nstruct;
00272   dbl_ILLlpdata *qslp = lp->O;
00273 
00274   if (C)
00275   {
00276     if (C->nrows != nrows || C->nstruct != nstruct)
00277     {
00278       fprintf (stderr, "cache mismatch in dbl_ILLlib_solution\n");
00279       rval = 0;
00280       ILL_CLEANUP;
00281     }
00282     if (val)
00283     {
00284       dbl_EGlpNumCopy (*val, C->val);
00285     }
00286     if (x)
00287     {
00288       for (i = 0; i < nstruct; i++)
00289       {
00290         dbl_EGlpNumCopy (x[i], C->x[i]);
00291       }
00292     }
00293     if (pi)
00294     {
00295       for (i = 0; i < nrows; i++)
00296       {
00297         dbl_EGlpNumCopy (pi[i], C->pi[i]);
00298       }
00299     }
00300     if (slack)
00301     {
00302       for (i = 0; i < nrows; i++)
00303       {
00304         dbl_EGlpNumCopy (slack[i], C->slack[i]);
00305       }
00306     }
00307     if (rc)
00308     {
00309       for (i = 0; i < nstruct; i++)
00310       {
00311         dbl_EGlpNumCopy (rc[i], C->rc[i]);
00312       }
00313     }
00314   }
00315   else
00316   {
00317     if (x || slack)
00318       tempx = dbl_EGlpNumAllocArray (ncols);
00319 
00320     if (rc)
00321       temprc = dbl_EGlpNumAllocArray (ncols);
00322 
00323     rval = dbl_ILLsimplex_solution (lp, tempx, pi, temprc, val);
00324     CHECKRVALG (rval, CLEANUP);
00325 
00326     if (x)
00327     {
00328       for (i = 0; i < nstruct; i++)
00329       {
00330         dbl_EGlpNumCopy (x[i], tempx[qslp->structmap[i]]);
00331       }
00332     }
00333     if (slack)
00334     {
00335       for (i = 0; i < nrows; i++)
00336       {
00337         dbl_EGlpNumCopy (slack[i], tempx[qslp->rowmap[i]]);
00338       }
00339     }
00340 
00341     if (rc)
00342     {
00343       for (i = 0; i < nstruct; i++)
00344       {
00345         dbl_EGlpNumCopy (rc[i], temprc[qslp->structmap[i]]);
00346       }
00347     }
00348 
00349 
00350     if (lp->O->objsense == dbl_ILL_MAX)
00351     {                           /* Reverse signs for max prob */
00352       if (val)
00353       {
00354         dbl_EGlpNumSign (*val);
00355       }
00356       if (pi)
00357       {
00358         for (i = 0; i < nrows; i++)
00359         {
00360           dbl_EGlpNumSign (pi[i]);
00361         }
00362       }
00363       if (rc)
00364       {
00365         for (i = 0; i < nstruct; i++)
00366         {
00367           dbl_EGlpNumSign (rc[i]);
00368         }
00369       }
00370     }
00371   }
00372 
00373 CLEANUP:
00374 
00375   dbl_EGlpNumFreeArray (tempx);
00376   dbl_EGlpNumFreeArray (temprc);
00377   EG_RETURN (rval);
00378 }
00379 
00380 int dbl_ILLlib_get_x (
00381   dbl_lpinfo * lp,
00382   dbl_ILLlp_cache * C,
00383   double * x)
00384 {
00385   int rval = 0;
00386 
00387   rval = dbl_ILLlib_solution (lp, C, 0, x, 0, 0, 0);
00388   CHECKRVALG (rval, CLEANUP);
00389 
00390 CLEANUP:
00391 
00392   EG_RETURN (rval);
00393 }
00394 
00395 int dbl_ILLlib_get_slack (
00396   dbl_lpinfo * lp,
00397   dbl_ILLlp_cache * C,
00398   double * slack)
00399 {
00400   int rval = 0;
00401 
00402   rval = dbl_ILLlib_solution (lp, C, 0, 0, 0, slack, 0);
00403   CHECKRVALG (rval, CLEANUP);
00404 
00405 CLEANUP:
00406 
00407   EG_RETURN (rval);
00408 }
00409 
00410 
00411 int dbl_ILLlib_objval (
00412   dbl_lpinfo * lp,
00413   dbl_ILLlp_cache * C,
00414   double * val)
00415 {
00416   int rval = 0;
00417 
00418   if (lp->basisstat.optimal)
00419   {
00420     rval = dbl_ILLlib_solution (lp, C, val, 0, 0, 0, 0);
00421     CHECKRVALG (rval, CLEANUP);
00422   }
00423   else
00424   {
00425     dbl_EGlpNumCopy (*val, lp->dobjval);  /* Ask Sanjeeb */
00426   }
00427 
00428 CLEANUP:
00429 
00430   EG_RETURN (rval);
00431 }
00432 
00433 int dbl_ILLlib_tableau (
00434   dbl_lpinfo * lp,
00435   int row,
00436   double * binv,
00437   double * tabrow)
00438 {
00439   int rval = 0;
00440   int i;
00441   int ncols = lp->O->ncols;
00442   int nrows = lp->O->nrows;
00443   int nstruct = lp->O->nstruct;
00444   double *brow = 0;
00445   double *trow = 0;
00446   dbl_ILLlpdata *qslp = lp->O;
00447 
00448   if (row < 0 || row >= qslp->nrows)
00449   {
00450     fprintf (stderr, "dbl_ILLlib_tableau called with bad row: %d\n", row);
00451     rval = 1;
00452     ILL_CLEANUP;
00453   }
00454   brow = dbl_EGlpNumAllocArray (nrows);
00455 
00456   if (tabrow)
00457     trow = dbl_EGlpNumAllocArray (ncols);
00458 
00459   rval = dbl_ILLbasis_tableau_row (lp, row, brow, trow, 0, 0);
00460   CHECKRVALG (rval, CLEANUP);
00461 
00462   if (binv)
00463   {
00464     for (i = 0; i < nrows; i++)
00465     {
00466       dbl_EGlpNumCopy (binv[i], brow[i]);
00467     }
00468   }
00469 
00470   if (tabrow)
00471   {
00472     for (i = 0; i < nstruct; i++)
00473     {
00474       dbl_EGlpNumCopy (tabrow[i], trow[qslp->structmap[i]]);
00475     }
00476     for (i = 0; i < nrows; i++)
00477     {
00478       dbl_EGlpNumCopy (tabrow[nstruct + i], trow[qslp->rowmap[i]]);
00479     }
00480   }
00481 
00482 CLEANUP:
00483 
00484   dbl_EGlpNumFreeArray (brow);
00485   dbl_EGlpNumFreeArray (trow);
00486   EG_RETURN (rval);
00487 }
00488 
00489 int dbl_ILLlib_basis_order (
00490   dbl_lpinfo * lp,
00491   int *header)
00492 {
00493   int rval = 0;
00494   int i, j;
00495   int ncols = lp->O->ncols;
00496   int nrows = lp->O->nrows;
00497   int nstruct = lp->O->nstruct;
00498   dbl_ILLlpdata *qslp = lp->O;
00499   int *invmap = 0;
00500 
00501   ILL_SAFE_MALLOC (invmap, ncols, int);
00502 
00503   for (j = 0; j < nstruct; j++)
00504   {
00505     invmap[qslp->structmap[j]] = j;
00506   }
00507   for (i = 0; i < nrows; i++)
00508   {
00509     invmap[qslp->rowmap[i]] = nstruct + i;
00510   }
00511 
00512   for (i = 0; i < nrows; i++)
00513   {
00514     header[i] = invmap[lp->baz[i]];
00515   }
00516 
00517 CLEANUP:
00518 
00519   ILL_IFFREE (invmap, int);
00520 
00521   EG_RETURN (rval);
00522 }
00523 
00524 int dbl_ILLlib_chgbnd (
00525   dbl_lpinfo * lp,
00526   int indx,
00527   int lu,
00528   double bnd)
00529 {
00530   int rval = 0;
00531   int col;
00532 
00533   if (!lp)
00534   {
00535     fprintf (stderr, "dbl_ILLlib_chgbnd called without an lp\n");
00536     rval = 1;
00537     ILL_CLEANUP;
00538   }
00539 
00540   if (indx < 0 || indx > lp->O->nstruct)
00541   {
00542     fprintf (stderr, "dbl_ILLlib_chgbnd called with bad indx: %d\n", indx);
00543     rval = 1;
00544     ILL_CLEANUP;
00545   }
00546 
00547   if (lp->O->sinfo)
00548   {                             /* Presolve LP is no longer valid, free the data */
00549     dbl_ILLlp_sinfo_free (lp->O->sinfo);
00550     ILL_IFFREE (lp->O->sinfo, dbl_ILLlp_sinfo);
00551   }
00552 
00553   col = lp->O->structmap[indx];
00554 
00555   switch (lu)
00556   {
00557   case 'L':
00558     dbl_EGlpNumCopy (lp->O->lower[col], bnd);
00559     break;
00560   case 'U':
00561     dbl_EGlpNumCopy (lp->O->upper[col], bnd);
00562     break;
00563   case 'B':
00564     dbl_EGlpNumCopy (lp->O->lower[col], bnd);
00565     dbl_EGlpNumCopy (lp->O->upper[col], bnd);
00566     break;
00567   default:
00568     fprintf (stderr, "dbl_ILLlib_chgbnd called with lu: %c\n", lu);
00569     rval = 1;
00570     ILL_CLEANUP;
00571   }
00572 
00573 CLEANUP:
00574 
00575   EG_RETURN (rval);
00576 }
00577 
00578 int dbl_ILLlib_chgbnds (
00579   dbl_lpinfo * lp,
00580   int cnt,
00581   int *indx,
00582   char *lu,
00583   double * bnd)
00584 {
00585   int rval = 0;
00586   int i;
00587 
00588   for (i = 0; i < cnt; i++)
00589   {
00590     rval = dbl_ILLlib_chgbnd (lp, indx[i], lu[i], bnd[i]);
00591     if (rval)
00592       ILL_CLEANUP;
00593   }
00594 
00595 CLEANUP:
00596 
00597   EG_RETURN (rval);
00598 }
00599 
00600 int dbl_ILLlib_getbnd (
00601   dbl_lpinfo * lp,
00602   int indx,
00603   int lu,
00604   double * bnd)
00605 {
00606   int rval = 0;
00607   int col;
00608 
00609   if (!lp)
00610   {
00611     fprintf (stderr, "dbl_ILLlib_getbnd called without an lp\n");
00612     rval = 1;
00613     ILL_CLEANUP;
00614   }
00615 
00616   if (indx < 0 || indx > lp->O->nstruct)
00617   {
00618     fprintf (stderr, "dbl_ILLlib_getbnd called with bad indx: %d\n", indx);
00619     rval = 1;
00620     ILL_CLEANUP;
00621   }
00622 
00623   col = lp->O->structmap[indx];
00624 
00625   switch (lu)
00626   {
00627   case 'L':
00628     dbl_EGlpNumCopy (*bnd, lp->O->lower[col]);
00629     break;
00630   case 'U':
00631     dbl_EGlpNumCopy (*bnd, lp->O->upper[col]);
00632     break;
00633   default:
00634     fprintf (stderr, "dbl_ILLlib_getbnd called with lu: %c\n", lu);
00635     rval = 1;
00636     ILL_CLEANUP;
00637   }
00638 
00639 CLEANUP:
00640 
00641   EG_RETURN (rval);
00642 }
00643 
00644 int dbl_ILLlib_getbnds_list ( 
00645   dbl_lpinfo *lp,
00646   int num,
00647   int*collist, 
00648   double *lower,
00649   double *upper)
00650 {
00651     int rval = 0;
00652     dbl_ILLlpdata *qslp;
00653     int nstruct;
00654     int j, col;
00655 
00656     if (!lp) {
00657         fprintf (stderr, "dbl_ILLlib_getbnds_list called without an lp\n");
00658         rval = 1; ILL_CLEANUP;
00659     }
00660 
00661     qslp = lp->O;
00662     nstruct = qslp->nstruct;
00663     for (j = 0; j < num ; j++) {
00664     if(collist[j]<0|| collist[j] >= nstruct)
00665       {
00666         fprintf (stderr, "dbl_ILLlib_getbnds_list collist[%d] = %d out "
00667                   "of range\n", j, collist[j]);
00668       }
00669       col = qslp->structmap[collist[j]];
00670       if (lower)
00671         dbl_EGlpNumCopy(lower[j], qslp->lower[col]);
00672       if (upper)
00673         dbl_EGlpNumCopy(upper[j], qslp->upper[col]);
00674     }
00675 
00676 CLEANUP:
00677 
00678   EG_RETURN(rval);    
00679 }
00680 
00681 
00682 int dbl_ILLlib_getbnds (
00683   dbl_lpinfo * lp,
00684   double * lower,
00685   double * upper)
00686 {
00687   int rval = 0;
00688   dbl_ILLlpdata *qslp;
00689   int nstruct;
00690   int j, col;
00691 
00692   if (!lp)
00693   {
00694     fprintf (stderr, "dbl_ILLlib_getbnd called without an lp\n");
00695     rval = 1;
00696     ILL_CLEANUP;
00697   }
00698 
00699   qslp = lp->O;
00700   nstruct = qslp->nstruct;
00701 
00702   for (j = 0; j < nstruct; j++)
00703   {
00704     col = qslp->structmap[j];
00705     if (lower)
00706       dbl_EGlpNumCopy (lower[j], qslp->lower[col]);
00707     if (upper)
00708       dbl_EGlpNumCopy (upper[j], qslp->upper[col]);
00709   }
00710 
00711 CLEANUP:
00712 
00713   EG_RETURN (rval);
00714 }
00715 
00716 int dbl_ILLlib_strongbranch (
00717   dbl_lpinfo * lp,
00718   dbl_price_info * pinf,
00719   int *candidatelist,
00720   int ncand,
00721   double * xlist,
00722   double * downpen,
00723   double * uppen,
00724   int iterations,
00725   double objbound,
00726   itcnt_t*itcnt)
00727 {
00728   int rval = 0;
00729   int i, k, status, have_norms;
00730   int olditer = lp->maxiter;
00731   int nstruct = lp->O->nstruct;
00732   int nrows = lp->O->nrows;
00733   double *myx = 0;
00734   double xi, t, oldbnd;
00735   dbl_price_info lpinf;
00736   dbl_ILLlp_basis B, origB;
00737 
00738   dbl_EGlpNumInitVar (lpinf.htrigger);
00739   dbl_EGlpNumInitVar (xi);
00740   dbl_EGlpNumInitVar (t);
00741   dbl_EGlpNumInitVar (oldbnd);
00742   dbl_EGlpNumZero (oldbnd);
00743   dbl_ILLlp_basis_init (&B);
00744   dbl_ILLlp_basis_init (&origB);
00745   dbl_ILLprice_init_pricing_info (&lpinf);
00746   lpinf.dI_price = QS_PRICE_DSTEEP;
00747   lpinf.dII_price = QS_PRICE_DSTEEP;
00748 
00749   if (xlist == 0)
00750   {
00751     myx = dbl_EGlpNumAllocArray (nstruct);
00752     rval = dbl_ILLlib_get_x (lp, 0, myx);
00753     CHECKRVALG (rval, CLEANUP);
00754   }
00755 
00756   rval = dbl_ILLlp_basis_alloc (&origB, nstruct, nrows);
00757   CHECKRVALG (rval, CLEANUP);
00758 
00759   rval = dbl_ILLlib_getbasis (lp, origB.cstat, origB.rstat);
00760   CHECKRVALG (rval, CLEANUP);
00761 
00762   dbl_check_pinf (pinf, &have_norms);
00763   if (have_norms == 0)
00764   {
00765     origB.rownorms = dbl_EGlpNumAllocArray (nrows);
00766     rval = dbl_ILLlib_getrownorms (lp, pinf, origB.rownorms);
00767     CHECKRVALG (rval, CLEANUP);
00768   }
00769   else
00770   {
00771     lp->basisid = -1;
00772     rval = dbl_ILLlib_optimize (lp, 0, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
00773     CHECKRVALG (rval, CLEANUP);
00774   }
00775 
00776   rval = dbl_ILLlp_basis_alloc (&B, nstruct, nrows);  /* Note: B and orgiB may */
00777   /* differ.               */
00778   CHECKRVALG (rval, CLEANUP);
00779 
00780   rval = dbl_ILLlib_getbasis (lp, B.cstat, B.rstat);
00781   CHECKRVALG (rval, CLEANUP);
00782   B.rownorms = dbl_EGlpNumAllocArray (nrows);
00783 
00784   if (have_norms == 0)
00785   {
00786     rval = dbl_ILLlib_getrownorms (lp, pinf, B.rownorms);
00787     CHECKRVALG (rval, CLEANUP);
00788   }
00789   else
00790   {
00791     rval = dbl_ILLlib_getrownorms (lp, &lpinf, B.rownorms);
00792     CHECKRVALG (rval, CLEANUP);
00793   }
00794 
00795   lp->maxiter = iterations;
00796 
00797   for (i = 0; i < ncand; i++)
00798   {
00799     k = candidatelist[i];
00800     rval = dbl_ILLlib_getbnd (lp, k, 'U', &oldbnd);
00801     CHECKRVALG (rval, CLEANUP);
00802     if (xlist)
00803       dbl_EGlpNumCopy (xi, xlist[i]);
00804     else
00805       dbl_EGlpNumCopy (xi, myx[k]);
00806     dbl_EGlpNumFloor (t, xi);
00807     if (dbl_EGlpNumIsLessDbl (t, 0.1) && dbl_EGlpNumIsGreaDbl (t, -0.1))
00808       dbl_EGlpNumZero (t);
00809 
00810     rval = dbl_ILLlib_chgbnd (lp, k, 'U', t);
00811     CHECKRVALG (rval, CLEANUP);
00812 
00813     rval = dbl_ILLlib_optimize (lp, &B, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
00814     CHECKRVALG (rval, CLEANUP);
00815 
00816     dbl_EGlpNumCopy (downpen[i], lp->dobjval);
00817     rval = dbl_ILLlib_chgbnd (lp, k, 'U', oldbnd);
00818     CHECKRVALG (rval, CLEANUP);
00819 
00820     rval = dbl_ILLlib_getbnd (lp, k, 'L', &oldbnd);
00821     CHECKRVALG (rval, CLEANUP);
00822     dbl_EGlpNumCeil (t, xi);
00823     if (dbl_EGlpNumIsLessDbl (t, 1.1) && dbl_EGlpNumIsGreaDbl (t, 0.9))
00824       dbl_EGlpNumOne (t);
00825     rval = dbl_ILLlib_chgbnd (lp, k, 'L', t);
00826     CHECKRVALG (rval, CLEANUP);
00827 
00828     rval = dbl_ILLlib_optimize (lp, &B, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
00829     CHECKRVALG (rval, CLEANUP);
00830 
00831     dbl_EGlpNumCopy (uppen[i], lp->dobjval);
00832     rval = dbl_ILLlib_chgbnd (lp, k, 'L', oldbnd);
00833     CHECKRVALG (rval, CLEANUP);
00834   }
00835 
00836   if (lp->O->objsense == dbl_ILL_MAX)
00837   {
00838 
00839   }
00840   else
00841   {
00842     for (i = 0; i < ncand; i++)
00843     {
00844       if (dbl_EGlpNumIsLess (objbound, downpen[i]))
00845         dbl_EGlpNumCopy (downpen[i], objbound);
00846       if (dbl_EGlpNumIsLess (objbound, uppen[i]))
00847         dbl_EGlpNumCopy (uppen[i], objbound);
00848     }
00849   }
00850 
00851   /* Restore the old optimal solution */
00852 
00853   lp->maxiter = olditer;
00854   rval = dbl_ILLlib_optimize (lp, &origB, pinf, DUAL_SIMPLEX, &status, 0, itcnt);
00855   CHECKRVALG (rval, CLEANUP);
00856 
00857 CLEANUP:
00858 
00859   dbl_EGlpNumClearVar (xi);
00860   dbl_EGlpNumClearVar (t);
00861   dbl_EGlpNumClearVar (oldbnd);
00862   lp->maxiter = olditer;
00863   dbl_ILLprice_free_pricing_info (&lpinf);
00864   dbl_ILLlp_basis_free (&B);
00865   dbl_ILLlp_basis_free (&origB);
00866   if (xlist == 0)
00867     dbl_EGlpNumFreeArray (myx);
00868   dbl_EGlpNumClearVar (lpinf.htrigger);
00869   EG_RETURN (rval);
00870 }
00871 
00872 #define dbl_EXTRA_ROWS (100)
00873 #define dbl_EXTRA_COLS (100)
00874 #define dbl_EXTRA_MAT  (1000)
00875 
00876 int dbl_ILLlib_newrow (
00877   dbl_lpinfo * lp,
00878   dbl_ILLlp_basis * B,
00879   double rhs,
00880   int sense,
00881   double range,
00882   const char *name)
00883 {
00884   int rval = 0;
00885 
00886   rval = dbl_ILLlib_addrow (lp, B, 0, 0, 0, rhs, sense, range, name);
00887   CHECKRVALG (rval, CLEANUP);
00888 
00889 CLEANUP:
00890 
00891   EG_RETURN (rval);
00892 }
00893 
00894 int dbl_ILLlib_newrows (
00895   dbl_lpinfo * lp,
00896   dbl_ILLlp_basis * B,
00897   int num,
00898   double * rhs,
00899   char *sense,
00900   double * range,
00901   const char **names)
00902 {
00903   int rval = 0;
00904   int *rmatcnt = 0;
00905   int *rmatbeg = 0;
00906   int i;
00907 
00908   if (!num)
00909     ILL_CLEANUP;
00910 
00911   ILL_SAFE_MALLOC (rmatcnt, num, int);
00912 
00913   ILL_SAFE_MALLOC (rmatbeg, num, int);
00914 
00915   for (i = 0; i < num; i++)
00916   {
00917     rmatcnt[i] = 0;
00918     rmatbeg[i] = 0;
00919   }
00920 
00921   rval = dbl_ILLlib_addrows (lp, B, num, rmatcnt, rmatbeg, 0, 0, rhs, sense,
00922                          range, names, 0);
00923   CHECKRVALG (rval, CLEANUP);
00924 
00925 CLEANUP:
00926 
00927   ILL_IFFREE (rmatcnt, int);
00928   ILL_IFFREE (rmatbeg, int);
00929 
00930   EG_RETURN (rval);
00931 }
00932 
00933 int dbl_ILLlib_addrows (
00934   dbl_lpinfo * lp,
00935   dbl_ILLlp_basis * B,
00936   int num,
00937   int *rmatcnt,
00938   int *rmatbeg,
00939   int *rmatind,
00940   double * rmatval,
00941   double * rhs,
00942   char *sense,
00943   double * range,
00944   const char **names,
00945   int *factorok)
00946 {
00947   int rval = 0;
00948   int i, j, total, bsing;
00949   int *imap = 0;
00950   int *bbeg = 0;
00951   int *bcnt = 0;
00952   int *bindi = 0;
00953   int *rindi = 0;
00954   int *jstat = 0;
00955   double *bval = 0;
00956   double rng;
00957   int badfactor = 0;
00958 
00959   dbl_EGlpNumInitVar (rng);
00960 
00961   if (B == 0 || B->rownorms == 0)
00962   {
00963     if (factorok)
00964       *factorok = 0;
00965   }
00966 
00967   if (B)
00968     dbl_EGlpNumFreeArray (B->colnorms);
00969 
00970   if (B && B->rownorms && factorok && *factorok == 1)
00971   {
00972     int *structmap = lp->O->structmap;
00973 
00974     lp->matbeg = lp->O->A.matbeg;
00975     lp->matcnt = lp->O->A.matcnt;
00976     lp->matind = lp->O->A.matind;
00977     lp->matval = lp->O->A.matval;
00978 
00979     lp->nrows = lp->O->nrows;
00980     lp->ncols = lp->O->ncols;
00981     if (B->rownorms_size < lp->O->nrows + num)
00982       dbl_EGlpNumReallocArray (&(B->rownorms), lp->O->nrows + num);
00983 
00984     ILL_SAFE_MALLOC (bcnt, num, int);
00985     ILL_SAFE_MALLOC (bbeg, num, int);
00986     ILL_SAFE_MALLOC (imap, lp->O->nstruct, int);
00987 
00988     ILL_SAFE_MALLOC (jstat, lp->ncols, int);
00989 
00990     for (i = 0; i < lp->ncols; i++)
00991     {
00992       jstat[i] = -1;
00993     }
00994     for (i = 0; i < lp->O->nstruct; i++)
00995     {
00996       jstat[structmap[i]] = i;
00997     }
00998 
00999     for (i = 0; i < lp->O->nstruct; i++)
01000     {
01001       imap[i] = -1;
01002     }
01003     for (i = 0; i < lp->O->nrows; i++)
01004     {
01005       if (jstat[lp->baz[i]] != -1)
01006       {
01007         imap[jstat[lp->baz[i]]] = i;
01008       }
01009     }
01010 
01011     for (i = 0, total = 0; i < num; i++)
01012     {
01013       bcnt[i] = 0;
01014       bbeg[i] = total;
01015       for (j = 0; j < rmatcnt[i]; j++)
01016       {
01017         if (imap[rmatind[rmatbeg[i] + j]] != -1)
01018         {
01019           bcnt[i]++;
01020           total++;
01021         }
01022       }
01023     }
01024     if (total)
01025     {
01026       ILL_SAFE_MALLOC (bindi, total, int);
01027 
01028       bval = dbl_EGlpNumAllocArray (total);
01029     }
01030     for (i = 0, total = 0; i < num; i++)
01031     {
01032       for (j = 0; j < rmatcnt[i]; j++)
01033       {
01034         if (imap[rmatind[rmatbeg[i] + j]] != -1)
01035         {
01036           dbl_EGlpNumCopy (bval[total], rmatval[rmatbeg[i] + j]);
01037           bindi[total] = imap[rmatind[rmatbeg[i] + j]];
01038           total++;
01039         }
01040       }
01041     }
01042 
01043     rval = dbl_ILLprice_get_new_rownorms (lp, num, B->rownorms + lp->O->nrows,
01044                                       bcnt, bbeg, bindi, bval);
01045     CHECKRVALG (rval, CLEANUP);
01046 
01047     ILL_IFFREE (bcnt, int);
01048     ILL_IFFREE (bbeg, int);
01049     ILL_IFFREE (bindi, int);
01050 
01051     dbl_EGlpNumFreeArray (bval);
01052     ILL_IFFREE (imap, int);
01053 
01054     badfactor = 1;
01055   }
01056 
01057   for (i = 0; i < num; i++)
01058   {
01059     if (range)
01060       dbl_EGlpNumCopy (rng, range[i]);
01061     else
01062       dbl_EGlpNumZero (rng);
01063     if (names)
01064     {
01065       rval = dbl_ILLlib_addrow (lp, B, rmatcnt[i], rmatind + rmatbeg[i],
01066                             rmatval + rmatbeg[i], rhs[i], sense[i], rng,
01067                             names[i]);
01068     }
01069     else
01070     {
01071       rval = dbl_ILLlib_addrow (lp, B, rmatcnt[i], rmatind + rmatbeg[i],
01072                             rmatval + rmatbeg[i], rhs[i], sense[i], rng, 0);
01073     }
01074     CHECKRVALG (rval, CLEANUP);
01075   }
01076 
01077 
01078   if (B && B->rownorms && (factorok && *factorok == 0))
01079   {
01080     lp->matbeg = lp->O->A.matbeg;
01081     lp->matcnt = lp->O->A.matcnt;
01082     lp->matind = lp->O->A.matind;
01083     lp->matval = lp->O->A.matval;
01084     lp->nrows = lp->O->nrows;
01085     lp->ncols = lp->O->ncols;
01086     lp->bz = lp->O->rhs;
01087     lp->nnbasic = lp->ncols - lp->nrows;
01088 
01089     rval = dbl_ILLbasis_load (lp, B);
01090     CHECKRVALG (rval, CLEANUP);
01091 
01092     if (lp->f)
01093       dbl_ILLfactor_free_factor_work (lp->f);
01094 
01095     rval = dbl_ILLbasis_factor (lp, &bsing);
01096     CHECKRVALG (rval, CLEANUP);
01097     if (bsing)
01098       MESSAGE (__QS_SB_VERB, "Singular Basis found!");
01099     *factorok = 1;
01100 
01101     if (B->rownorms_size < lp->O->nrows)
01102       dbl_EGlpNumReallocArray (&(B->rownorms), lp->O->nrows);
01103 
01104     ILL_SAFE_MALLOC (rindi, lp->O->nrows /* num */ , int);
01105 
01106     for (i = 0; i < num; i++)
01107     {
01108       rindi[i] = lp->O->nrows - num + i;
01109     }
01110 
01111     rval = dbl_ILLprice_get_dsteep_norms (lp, num, rindi,
01112                                       B->rownorms + lp->O->nrows - num);
01113     CHECKRVALG (rval, CLEANUP);
01114   }
01115 
01116   if (factorok != 0 && badfactor == 1)
01117   {
01118     *factorok = 0;
01119   }
01120 
01121 
01122 CLEANUP:
01123 
01124   ILL_IFFREE (bcnt, int);
01125   ILL_IFFREE (bbeg, int);
01126   ILL_IFFREE (bindi, int);
01127 
01128   dbl_EGlpNumFreeArray (bval);
01129   ILL_IFFREE (imap, int);
01130   ILL_IFFREE (jstat, int);
01131   ILL_IFFREE (rindi, int);
01132 
01133   dbl_EGlpNumClearVar (rng);
01134   EG_RETURN (rval);
01135 }
01136 
01137 int dbl_ILLlib_addrow (
01138   dbl_lpinfo * lp,
01139   dbl_ILLlp_basis * B,
01140   int cnt,
01141   int *ind,
01142   double * val,
01143   double rhs,
01144   int sense,
01145   double range,
01146   const char *name)
01147 {
01148   int rval = 0;
01149   dbl_ILLlpdata *qslp;
01150   dbl_ILLmatrix *A;
01151   int i, nrows, ncols;
01152   char buf[ILL_namebufsize];
01153   int tind[1];
01154   double tval[1];
01155   int *tempind = 0;
01156   int pind, hit;
01157 
01158   dbl_EGlpNumInitVar (tval[0]);
01159 
01160   if (!lp)
01161   {
01162     fprintf (stderr, "dbl_ILLlib_addrow called without an lp\n");
01163     rval = 1;
01164     ILL_CLEANUP;
01165   }
01166 
01167   qslp = lp->O;
01168   A = &qslp->A;
01169 
01170   if (qslp->rA)
01171   {                             /* After an addrow call, needs to be updated */
01172     dbl_ILLlp_rows_clear (qslp->rA);
01173     ILL_IFFREE (qslp->rA, dbl_ILLlp_rows);
01174   }
01175 
01176   if (qslp->sinfo)
01177   {                             /* Presolve LP is no longer valid, free the data */
01178     dbl_ILLlp_sinfo_free (qslp->sinfo);
01179     ILL_IFFREE (qslp->sinfo, dbl_ILLlp_sinfo);
01180   }
01181 
01182   nrows = qslp->nrows;
01183   ncols = qslp->ncols;
01184 
01185   /* If the row has a range, create the rangeval array if needed  */
01186 
01187   if (sense == 'R' && !(qslp->rangeval) && qslp->rowsize > 0)
01188   {
01189     qslp->rangeval = dbl_EGlpNumAllocArray (qslp->rowsize);
01190     for (i = 0; i < qslp->nrows; i++)
01191     {
01192       dbl_EGlpNumZero (qslp->rangeval[i]);
01193     }
01194   }
01195 
01196   /* Add the row to the row structures */
01197 
01198   if (qslp->rowsize < nrows + 1)
01199   {
01200     dbl_EGlpNumReallocArray (&(qslp->rhs), qslp->rowsize + dbl_EXTRA_ROWS);
01201     qslp->sense = EGrealloc (qslp->sense,
01202                              sizeof (char) * (qslp->rowsize + dbl_EXTRA_ROWS));
01203     //rval = ILLutil_reallocrus_count ((void **) &(qslp->sense),
01204     //                                 qslp->rowsize + dbl_EXTRA_ROWS, sizeof (char));
01205     //CHECKRVALG(rval,CLEANUP);
01206 
01207     qslp->rowmap = EGrealloc (qslp->rowmap,
01208                               sizeof (int) * (qslp->rowsize + dbl_EXTRA_ROWS));
01209     //rval = ILLutil_reallocrus_count ((void **) &(qslp->rowmap),
01210     //                                 qslp->rowsize + dbl_EXTRA_ROWS, sizeof (int));
01211     //CHECKRVALG(rval,CLEANUP);
01212 
01213     if (qslp->rangeval || sense == 'R')
01214       dbl_EGlpNumReallocArray (&(qslp->rangeval), qslp->rowsize + dbl_EXTRA_ROWS);
01215 
01216     qslp->rownames = EGrealloc (qslp->rownames,
01217                                 sizeof (char *) * (qslp->rowsize + dbl_EXTRA_ROWS));
01218     //rval = ILLutil_reallocrus_count ((void **) &(qslp->rownames),
01219     //                                 qslp->rowsize + dbl_EXTRA_ROWS,
01220     //                                 sizeof (char *));
01221     //CHECKRVALG(rval,CLEANUP);
01222     qslp->rowsize += dbl_EXTRA_ROWS;
01223   }
01224 
01225   dbl_EGlpNumCopy (qslp->rhs[nrows], rhs);
01226   qslp->sense[nrows] = sense;
01227   qslp->rowmap[nrows] = ncols;  /* this will be the new logical */
01228   if (qslp->rangeval)
01229   {
01230     if (sense == 'R')
01231       dbl_EGlpNumCopy (qslp->rangeval[nrows], range);
01232     else
01233       dbl_EGlpNumZero (qslp->rangeval[nrows]);
01234   }
01235   ILL_FAILtrue (qslp->rownames == NULL, "must always be non NULL");
01236   dbl_ILLlib_findName (qslp, 1 /*row */ , name, nrows, buf);
01237   dbl_ILL_UTIL_STR (qslp->rownames[nrows], buf);
01238   ILLsymboltab_register (&qslp->rowtab, buf, qslp->nrows, &pind, &hit);
01239   ILL_FAILfalse (hit == 0, "must be new");
01240 
01241 
01242   /* Add the logical variable to the column structures */
01243 
01244   if (qslp->colsize < ncols + 1)
01245   {
01246     dbl_EGlpNumReallocArray (&(qslp->lower), qslp->colsize + dbl_EXTRA_COLS);
01247     dbl_EGlpNumReallocArray (&(qslp->upper), qslp->colsize + dbl_EXTRA_COLS);
01248     dbl_EGlpNumReallocArray (&(qslp->obj), qslp->colsize + dbl_EXTRA_COLS);
01249     qslp->colsize += dbl_EXTRA_COLS;
01250   }
01251 
01252   dbl_EGlpNumZero (qslp->obj[ncols]);
01253   dbl_EGlpNumZero (qslp->lower[ncols]);
01254   if (sense == 'E')
01255   {
01256     dbl_EGlpNumZero (qslp->upper[ncols]); /* Artificial */
01257   }
01258   else if (sense == 'R')
01259   {
01260     dbl_EGlpNumCopy (qslp->upper[ncols], range);  /* Range      */
01261   }
01262   else
01263   {
01264     dbl_EGlpNumCopy (qslp->upper[ncols], dbl_ILL_MAXDOUBLE);  /* Slack      */
01265   }
01266 
01267   /* Add new row and new logical col to matrix */
01268 
01269   /* Need to map the structural indices to their proper place */
01270 
01271   if (cnt)
01272   {
01273     ILL_SAFE_MALLOC (tempind, cnt, int);
01274 
01275     for (i = 0; i < cnt; i++)
01276     {
01277       tempind[i] = qslp->structmap[ind[i]];
01278     }
01279   }
01280 
01281   rval = dbl_matrix_addrow (A, cnt, tempind, val);
01282   CHECKRVALG (rval, CLEANUP);
01283 
01284   tind[0] = nrows;
01285   dbl_EGlpNumOne (*tval);
01286   if (sense == 'G' || sense == 'R')
01287     dbl_EGlpNumSign (*tval);
01288 
01289   rval = dbl_matrix_addcol (A, 1, tind, tval);
01290   CHECKRVALG (rval, CLEANUP);
01291 
01292   if (B != 0)
01293   {
01294     B->rstat = EGrealloc (B->rstat, sizeof (char) * (nrows + 1));
01295     //rval = ILLutil_reallocrus_count ((void **) &(B->rstat), nrows + 1,
01296     //                                 sizeof (char));
01297     //CHECKRVALG(rval,CLEANUP);
01298     B->rstat[nrows] = QS_ROW_BSTAT_BASIC;
01299   }
01300 
01301 #if 0
01302   lp->basisid = -1;             /* To get optimizer to reload the basis */
01303 #endif
01304 
01305   qslp->ncols++;
01306   qslp->nrows++;
01307   qslp->nzcount += (cnt + 1);
01308 
01309   if (B != 0)
01310   {
01311     B->nrows++;
01312   }
01313 
01314 CLEANUP:
01315   ILL_IFFREE (tempind, int);
01316 
01317   dbl_EGlpNumClearVar (tval[0]);
01318   EG_RETURN (rval);
01319 }
01320 
01321 int dbl_ILLlib_delrows (
01322   dbl_lpinfo * lp,
01323   dbl_ILLlp_basis * B,
01324   dbl_ILLlp_cache * C,
01325   int num,
01326   int *dellist,
01327   int *basis_ok,
01328   int *cache_ok)
01329 {
01330   int rval = 0;
01331   int i, j, k, nrows, ncols, nstruct, spot, dk, bok = 0, cok = 0;
01332   dbl_ILLlpdata *qslp;
01333   dbl_ILLmatrix *A;
01334   char *rowmark = 0;
01335   char *colmark = 0;
01336   int *newrowindex = 0;
01337   int *newcolindex = 0;
01338   int *ind, *beg, *cnt;
01339   double *val;
01340 
01341   if (!lp)
01342   {
01343     fprintf (stderr, "dbl_ILLlib_delrows called without an lp\n");
01344     rval = 1;
01345     ILL_CLEANUP;
01346   }
01347 
01348   if (num <= 0)
01349   {
01350     if (basis_ok)
01351       *basis_ok = 1;
01352     if (cache_ok)
01353       *cache_ok = 1;
01354     ILL_CLEANUP;
01355   }
01356 
01357   if (basis_ok)
01358     *basis_ok = 0;
01359   if (cache_ok)
01360     *cache_ok = 0;
01361 
01362   qslp = lp->O;
01363   A = &qslp->A;
01364 
01365   if (qslp->rA)
01366   {                             /* After a delrow call, needs to be updated */
01367     dbl_ILLlp_rows_clear (qslp->rA);
01368     ILL_IFFREE (qslp->rA, dbl_ILLlp_rows);
01369   }
01370 
01371   nrows = A->matrows;
01372   ncols = A->matcols;
01373   ind = A->matind;
01374   beg = A->matbeg;
01375   cnt = A->matcnt;
01376   val = A->matval;
01377   nstruct = qslp->nstruct;
01378 
01379   ILL_SAFE_MALLOC (rowmark, nrows, char);
01380 
01381   for (i = 0; i < nrows; i++)
01382   {
01383     rowmark[i] = 0;
01384   }
01385   for (i = 0; i < num; i++)
01386   {
01387     rowmark[dellist[i]] = 1;
01388   }
01389 
01390 
01391   /* Try to update the basis */
01392 
01393   if (B)
01394   {
01395     bok = 1;
01396     cok = 1;
01397     for (i = 0; i < num; i++)
01398     {
01399       j = dellist[i];
01400       if (B->rstat[j] == QS_ROW_BSTAT_LOWER ||
01401           B->rstat[j] == QS_ROW_BSTAT_UPPER)
01402       {
01403         bok = 0;
01404         break;
01405       }
01406       if (C && dbl_EGlpNumIsLess (dbl_DFEAS_TOLER, C->pi[j]))
01407       {
01408 /*
01409                 printf ("XXXX: Postive pi (%f) at basic row\n", C->pi[j]);
01410                 fflush (stdout);
01411 */
01412         cok = 0;
01413       }
01414     }
01415     if (bok == 1)
01416     {
01417       dbl_EGlpNumFreeArray (B->colnorms);
01418       if (B->rownorms)
01419       {
01420         for (i = 0, k = 0; i < nstruct; i++)
01421         {
01422           if (B->cstat[i] == QS_COL_BSTAT_BASIC)
01423             k++;
01424         }
01425         for (i = 0, j = k; i < nrows; i++)
01426         {
01427           if (B->rstat[i] == QS_ROW_BSTAT_BASIC)
01428           {
01429             if (rowmark[i] == 0)
01430             {
01431               dbl_EGlpNumCopy (B->rownorms[k++], B->rownorms[j]);
01432             }
01433             j++;
01434           }
01435         }
01436         if (k != nrows - num)
01437         {
01438           fprintf (stderr, "error in  dbl_ILLlib_delrows\n");
01439           rval = 1;
01440           ILL_CLEANUP;
01441         }
01442       }
01443 
01444       for (i = 0, j = 0; i < nrows; i++)
01445       {
01446         if (rowmark[i] == 0)
01447         {
01448           B->rstat[j++] = B->rstat[i];
01449         }
01450       }
01451       B->nrows = j;
01452 
01453       if (C && cok == 1)
01454       {
01455         for (i = 0, j = 0; i < nrows; i++)
01456         {
01457           if (rowmark[i] == 0)
01458           {
01459             dbl_EGlpNumCopy (C->pi[j], C->pi[i]);
01460             dbl_EGlpNumCopy (C->slack[j++], C->slack[i]);
01461           }
01462         }
01463         C->nrows = j;
01464         if (cache_ok)
01465           *cache_ok = 1;
01466       }
01467       if (basis_ok)
01468         *basis_ok = 1;
01469     }
01470   }
01471 
01472   ILL_SAFE_MALLOC (newrowindex, nrows, int);
01473 
01474 
01475   /* Delete the marked rows */
01476 
01477   ILL_FAILtrue (qslp->rownames == NULL, "must always be non NULL");
01478   for (i = 0, j = 0; i < nrows; i++)
01479   {
01480     if (rowmark[i] == 0)
01481     {
01482       if (i != j)
01483       {
01484         dbl_EGlpNumCopy (qslp->rhs[j], qslp->rhs[i]);
01485         qslp->sense[j] = qslp->sense[i];
01486         if (qslp->rangeval)
01487           dbl_EGlpNumCopy (qslp->rangeval[j], qslp->rangeval[i]);
01488         if (qslp->rownames)
01489           qslp->rownames[j] = qslp->rownames[i];
01490       }
01491       newrowindex[i] = j++;
01492     }
01493     else
01494     {
01495       if (qslp->rownames)
01496       {
01497         rval = ILLsymboltab_delete (&qslp->rowtab, qslp->rownames[i]);
01498         CHECKRVALG (rval, CLEANUP);
01499         ILL_IFFREE (qslp->rownames[i], char);
01500       }
01501     }
01502   }
01503 
01504 
01505   /* Delete the logicals */
01506 
01507   ILL_SAFE_MALLOC (colmark, ncols, char);
01508 
01509   for (i = 0; i < ncols; i++)
01510   {
01511     colmark[i] = 0;
01512   }
01513   for (i = 0; i < num; i++)
01514   {
01515     colmark[qslp->rowmap[dellist[i]]] = 1;
01516   }
01517 
01518   rval = dbl_delcols_work (lp, colmark);
01519   CHECKRVALG (rval, CLEANUP);
01520 
01521   A->matcols -= num;
01522   qslp->ncols -= num;
01523 
01524 
01525   /* Pack the rowmap  */
01526 
01527   for (i = 0, j = 0; i < nrows; i++)
01528   {
01529     if (rowmark[i] == 0)
01530     {
01531       qslp->rowmap[j++] = qslp->rowmap[i];
01532     }
01533   }
01534 
01535   /* Remove the entries to deleted rows, and update the indices */
01536 
01537   for (i = 0; i < ncols - num; i++)
01538   {
01539     dk = 0;
01540     spot = beg[i];
01541     for (j = 0; j < cnt[i]; j++)
01542     {
01543       if (rowmark[ind[beg[i] + j]] == 1)
01544       {
01545         dk++;
01546       }
01547       else
01548       {
01549         dbl_EGlpNumCopy (val[spot], val[beg[i] + j]);
01550         ind[spot] = newrowindex[ind[beg[i] + j]];
01551         spot++;
01552       }
01553     }
01554     for (; spot < beg[i] + cnt[i]; spot++)
01555     {
01556       ind[spot] = -1;
01557     }
01558 
01559     cnt[i] -= dk;
01560     if (cnt[i] == 0)
01561     {
01562       ind[beg[i]] = 1;          /* we always mark the empty cols */
01563     }
01564   }
01565 
01566   A->matrows -= num;
01567   qslp->nrows -= num;
01568 
01569 #if 0
01570   lp->basisid = -1;             /* To get optimizer to reload the basis */
01571 #endif
01572 
01573   /* if the base is OK, we MUST load the status variables again */
01574   if(bok)
01575   {
01576     rval = dbl_ILLbasis_load( lp, B);
01577     CHECKRVALG (rval, CLEANUP);
01578   }
01579 CLEANUP:
01580 
01581   ILL_IFFREE (rowmark, char);
01582   ILL_IFFREE (colmark, char);
01583   ILL_IFFREE (newcolindex, int);
01584   ILL_IFFREE (newrowindex, int);
01585 
01586   EG_RETURN (rval);
01587 }
01588 
01589 int dbl_ILLlib_delcols (
01590   dbl_lpinfo * lp,
01591   dbl_ILLlp_basis * B,
01592   int num,
01593   int *dellist,
01594   int *basis_ok)
01595 {
01596   int rval = 0;
01597   int i, j, bok = 0, ncols;
01598   char *colmark = 0;
01599   dbl_ILLlpdata *qslp;
01600 
01601   if (!lp)
01602   {
01603     fprintf (stderr, "dbl_ILLlib_delcols called without an lp\n");
01604     rval = 1;
01605     ILL_CLEANUP;
01606   }
01607 
01608   if (basis_ok)
01609     *basis_ok = 0;
01610 
01611   if (num <= 0)
01612   {
01613     *basis_ok = 1;
01614     ILL_CLEANUP;
01615   }
01616 
01617   qslp = lp->O;
01618   ncols = qslp->A.matcols;
01619 
01620   if (qslp->rA)
01621   {                             /* After a delcol call, needs to be updated */
01622     dbl_ILLlp_rows_clear (qslp->rA);
01623     ILL_IFFREE (qslp->rA, dbl_ILLlp_rows);
01624   }
01625 
01626   ILL_SAFE_MALLOC (colmark, ncols, char);
01627 
01628   for (i = 0; i < ncols; i++)
01629   {
01630     colmark[i] = 0;
01631   }
01632   for (i = 0; i < num; i++)
01633   {
01634     colmark[qslp->structmap[dellist[i]]] = 1;
01635   }
01636 
01637   if (B)
01638   {
01639     B->nstruct -= num;
01640     bok = 1;
01641     for (i = 0; i < num; i++)
01642     {
01643       j = dellist[i];
01644       if (B->cstat[j] == QS_COL_BSTAT_BASIC)
01645       {
01646         bok = 0;
01647         //printf ("BONG\n");
01648         //fflush (stdout);
01649         break;
01650       }
01651     }
01652     if (bok == 1)
01653     {
01654       dbl_EGlpNumFreeArray (B->colnorms);
01655       for (i = 0, j = 0; i < qslp->nstruct; i++)
01656       {
01657         if (colmark[qslp->structmap[i]] == 0)
01658         {
01659           B->cstat[j++] = B->cstat[i];
01660         }
01661       }
01662       if (basis_ok)
01663         *basis_ok = 1;
01664     }
01665   }
01666 
01667   rval = dbl_delcols_work (lp, colmark);
01668   CHECKRVALG (rval, CLEANUP);
01669 
01670 
01671   qslp->A.matcols -= num;
01672   qslp->ncols -= num;
01673   qslp->nstruct -= num;
01674 
01675   /* if the base is OK, we MUST load the status variables again */
01676   if(bok)
01677   {
01678     rval = dbl_ILLbasis_load( lp, B);
01679     CHECKRVALG (rval, CLEANUP);
01680   }
01681 #if 0
01682   lp->basisid = -1;             /* To get optimizer to reload the basis */
01683 #endif
01684 
01685 CLEANUP:
01686 
01687   ILL_IFFREE (colmark, char);
01688 
01689   EG_RETURN (rval);
01690 }
01691 
01692 static int dbl_matrix_getcoef (
01693   dbl_ILLmatrix *A, 
01694   int row,
01695   int col,
01696   double*val)
01697 {
01698   int i;
01699   int rval = 0;
01700   if (row >= A->matrows || row < 0)
01701   {
01702     fprintf (stderr, "illegal row index in dbl_matrix_getcoef\n");
01703     rval= 1;
01704     ILL_CLEANUP;
01705   }
01706 
01707   if (col >= A->matcols || col < 0)
01708   {
01709     fprintf (stderr, "illegal col index in dbl_matrix_getcoef\n");
01710     rval= 1;
01711     ILL_CLEANUP;
01712   }
01713 
01714   /* by default value is zero */
01715   dbl_EGlpNumZero(*val);
01716   for (i = A->matbeg[col]; i < A->matbeg[col] + A->matcnt[col]; i++)
01717   {
01718     if (A->matind[i] == row)
01719     {
01720       dbl_EGlpNumCopy(*val, A->matval[i]);
01721       ILL_CLEANUP;
01722     }
01723   }
01724 
01725 CLEANUP:
01726 
01727   EG_RETURN(rval);
01728 }
01729 
01730 static int dbl_delcols_work (
01731   dbl_lpinfo * lp,
01732   char *colmark)
01733 {
01734   int rval = 0;
01735   int i, j, k, nrows, ncols;
01736   dbl_ILLlpdata *qslp;
01737   dbl_ILLmatrix *A;
01738   int *newcolindex = 0;
01739   int *ind, *beg, *cnt;
01740 
01741   /* Allows logicals to be deleted, to handle call from delcols. */
01742 
01743   qslp = lp->O;
01744   A = &qslp->A;
01745   nrows = A->matrows;
01746   ncols = A->matcols;
01747   ind = A->matind;
01748   beg = A->matbeg;
01749   cnt = A->matcnt;
01750 
01751   ILL_SAFE_MALLOC (newcolindex, ncols, int);
01752 
01753   /* Delete the columns */
01754 
01755   for (i = 0, j = 0; i < ncols; i++)
01756   {
01757     if (colmark[i] == 0)
01758     {
01759       if (i != j)
01760       {
01761         beg[j] = beg[i];
01762         cnt[j] = cnt[i];
01763         dbl_EGlpNumCopy (qslp->obj[j], qslp->obj[i]);
01764         dbl_EGlpNumCopy (qslp->lower[j], qslp->lower[i]);
01765         dbl_EGlpNumCopy (qslp->upper[j], qslp->upper[i]);
01766       }
01767       newcolindex[i] = j++;
01768     }
01769     else
01770     {
01771       for (k = 0; k < cnt[i]; k++)
01772       {
01773         ind[beg[i] + k] = -1;
01774       }
01775       newcolindex[i] = -1;
01776     }
01777   }
01778 
01779   /* Update the struct arrays */
01780 
01781   for (i = 0, j = 0; i < qslp->nstruct; i++)
01782   {
01783     k = qslp->structmap[i];
01784     if (colmark[k] == 0)
01785     {
01786       qslp->structmap[j] = newcolindex[k];
01787       qslp->colnames[j] = qslp->colnames[i];
01788       if (qslp->intmarker)
01789         qslp->intmarker[j] = qslp->intmarker[i];
01790       j++;
01791     }
01792     else
01793     {
01794       rval = ILLsymboltab_delete (&qslp->coltab, qslp->colnames[i]);
01795       CHECKRVALG (rval, CLEANUP);
01796       ILL_IFFREE (qslp->colnames[i], char);
01797     }
01798   }
01799 
01800   /* Update the rowmap: note if logicals deleted, map will be -1 */
01801 
01802   for (i = 0; i < nrows; i++)
01803   {
01804     qslp->rowmap[i] = newcolindex[qslp->rowmap[i]];
01805   }
01806 
01807 CLEANUP:
01808 
01809   ILL_IFFREE (newcolindex, int);
01810 
01811   EG_RETURN (rval);
01812 }
01813 
01814 int dbl_ILLlib_getcoef (
01815   dbl_lpinfo *lp,
01816   int rowindex,
01817   int colindex,
01818   double* coef)
01819 { 
01820   int rval = 0;
01821   dbl_ILLlpdata *qslp;
01822   dbl_ILLmatrix *A;
01823   int nrows, nstruct, j;
01824   if (!lp)
01825   {
01826     fprintf (stderr, "dbl_ILLlib_chgcoef called without an lp\n");
01827     rval = 1;
01828     ILL_CLEANUP;
01829   }
01830 
01831   qslp = lp->O;
01832   A = &qslp->A;
01833   nrows = qslp->nrows;
01834   nstruct = qslp->nstruct;
01835 
01836   if (rowindex < 0 || rowindex >= nrows || colindex < 0 || colindex >= nstruct)
01837   {
01838     fprintf (stderr, "dbl_ILLlib_getcoef called with out-of-range index\n");
01839     rval = 1;
01840     ILL_CLEANUP;
01841   }
01842   
01843   j = qslp->structmap[colindex];
01844   rval = dbl_matrix_getcoef (A, rowindex, j, coef);
01845   CHECKRVALG(rval, CLEANUP);
01846 
01847 CLEANUP:
01848 
01849   EG_RETURN (rval);
01850 }
01851 
01852 int dbl_ILLlib_chgcoef (
01853   dbl_lpinfo * lp,
01854   int rowindex,
01855   int colindex,
01856   double coef)
01857 {
01858   int rval = 0;
01859   dbl_ILLlpdata *qslp;
01860   dbl_ILLmatrix *A;
01861   int nrows, nstruct, j;
01862 
01863   if (!lp)
01864   {
01865     fprintf (stderr, "dbl_ILLlib_chgcoef called without an lp\n");
01866     rval = 1;
01867     ILL_CLEANUP;
01868   }
01869 
01870   qslp = lp->O;
01871   A = &qslp->A;
01872 
01873   nrows = qslp->nrows;
01874   nstruct = qslp->nstruct;
01875 
01876   if (rowindex < 0 || rowindex >= nrows || colindex < 0 || colindex >= nstruct)
01877   {
01878     fprintf (stderr, "dbl_ILLlib_chgcoef called with out-of-range index\n");
01879     rval = 1;
01880     ILL_CLEANUP;
01881   }
01882 
01883   if (qslp->rA)
01884   {                             /* After a chgcoef call, needs to be updated */
01885     dbl_ILLlp_rows_clear (qslp->rA);
01886     ILL_IFFREE (qslp->rA, dbl_ILLlp_rows);
01887   }
01888 
01889   if (qslp->sinfo)
01890   {                             /* Presolve LP is no longer valid, free the data */
01891     dbl_ILLlp_sinfo_free (qslp->sinfo);
01892     ILL_IFFREE (qslp->sinfo, dbl_ILLlp_sinfo);
01893   }
01894 
01895   j = qslp->structmap[colindex];
01896 
01897   rval = dbl_matrix_addcoef (lp, A, rowindex, j, coef);
01898   CHECKRVALG (rval, CLEANUP);
01899 
01900 CLEANUP:
01901 
01902   EG_RETURN (rval);
01903 }
01904 
01905 int dbl_ILLlib_chgsense (
01906   dbl_lpinfo * lp,
01907   int num,
01908   int *rowlist,
01909   char *sense)
01910 {
01911   int rval = 0;
01912   int i, j, k;
01913   dbl_ILLlpdata *qslp = lp->O;
01914   dbl_ILLmatrix *A = &(lp->O->A);
01915 
01916   for (i = 0; i < num; i++)
01917   {
01918     j = qslp->rowmap[rowlist[i]];
01919     if (A->matcnt[j] != 1)
01920     {
01921       fprintf (stderr, "logical variable is not a singleton\n");
01922       rval = 1;
01923       ILL_CLEANUP;
01924     }
01925     k = A->matbeg[j];
01926     switch (sense[i])
01927     {
01928     case 'R':                 /* Range constraint, we will set its upper bound
01929                                  once we call dbl_QSchange_range, by default it 
01930                                  will be zero, i.e. an equation. */
01931       qslp->sense[rowlist[i]] = 'R';
01932       dbl_EGlpNumZero(qslp->lower[j]);
01933       dbl_EGlpNumZero(qslp->upper[j]);
01934       dbl_EGlpNumOne(A->matval[k]);
01935       break;
01936     case 'E':                 /* Artificial */
01937       qslp->sense[rowlist[i]] = 'E';
01938       dbl_EGlpNumZero (qslp->lower[j]);
01939       dbl_EGlpNumZero (qslp->upper[j]);
01940       dbl_EGlpNumOne (A->matval[k]);
01941       break;
01942     case 'G':                 /* Surplus   */
01943       qslp->sense[rowlist[i]] = 'G';
01944       dbl_EGlpNumZero (qslp->lower[j]);
01945       dbl_EGlpNumCopy (qslp->upper[j], dbl_ILL_MAXDOUBLE);
01946       dbl_EGlpNumOne (A->matval[k]);
01947       dbl_EGlpNumSign (A->matval[k]);
01948       break;
01949     case 'L':                 /* Slack     */
01950       qslp->sense[rowlist[i]] = 'L';
01951       dbl_EGlpNumZero (qslp->lower[j]);
01952       dbl_EGlpNumCopy (qslp->upper[j], dbl_ILL_MAXDOUBLE);
01953       dbl_EGlpNumOne (A->matval[k]);
01954       break;
01955     default:
01956       fprintf (stderr, "illegal sense %c in dbl_ILLlib_chgsense\n", sense[i]);
01957       rval = 1;
01958       ILL_CLEANUP;
01959     }
01960   }
01961 
01962 CLEANUP:
01963 
01964   EG_RETURN (rval);
01965 }
01966 
01967 int dbl_ILLlib_getsenses (
01968   dbl_lpinfo *lp,
01969   char *senses)
01970 {
01971   dbl_ILLlpdata *qslp;
01972   int nrows, i;
01973   int rval = 0;
01974 
01975   if (!lp) {
01976     fprintf (stderr, "ILLlib_getsense called without an LP\n");
01977     rval = 1;
01978     ILL_CLEANUP;
01979   }
01980 
01981   qslp = lp->O;
01982   nrows = qslp->nrows;
01983 
01984   for (i = 0; i < nrows; i++)
01985   {
01986     senses[i] = qslp->sense[i];
01987   } 
01988 
01989 CLEANUP:
01990 
01991     EG_RETURN(rval);
01992 }
01993 
01994 int dbl_ILLlib_newcol (
01995   dbl_lpinfo * lp,
01996   dbl_ILLlp_basis * B,
01997   double obj,
01998   double lower,
01999   double upper,
02000   const char *name,
02001   int factorok)
02002 {
02003   int rval = 0;
02004 
02005   rval = dbl_ILLlib_addcol (lp, B, 0, 0, 0, obj, lower, upper, name, factorok);
02006   CHECKRVALG (rval, CLEANUP);
02007 
02008 CLEANUP:
02009 
02010   EG_RETURN (rval);
02011 }
02012 
02013 int dbl_ILLlib_newcols (
02014   dbl_lpinfo * lp,
02015   dbl_ILLlp_basis * B,
02016   int num,
02017   double * obj,
02018   double * lower,
02019   double * upper,
02020   const char **names,
02021   int factorok)
02022 {
02023   int rval = 0;
02024   int *cmatcnt = 0;
02025   int *cmatbeg = 0;
02026   int i;
02027 
02028   ILL_SAFE_MALLOC (cmatcnt, num, int);
02029 
02030   ILL_SAFE_MALLOC (cmatbeg, num, int);
02031 
02032   for (i = 0; i < num; i++)
02033   {
02034     cmatcnt[i] = 0;
02035     cmatbeg[i] = 0;
02036   }
02037 
02038   rval = dbl_ILLlib_addcols (lp, B, num, cmatcnt, cmatbeg, 0,
02039                          0, obj, lower, upper, names, factorok);
02040   CHECKRVALG (rval, CLEANUP);
02041 
02042 
02043 CLEANUP:
02044 
02045   ILL_IFFREE (cmatcnt, int);
02046   ILL_IFFREE (cmatbeg, int);
02047 
02048   EG_RETURN (rval);
02049 }
02050 
02051 int dbl_ILLlib_addcols (
02052   dbl_lpinfo * lp,
02053   dbl_ILLlp_basis * B,
02054   int num,
02055   int *cmatcnt,
02056   int *cmatbeg,
02057   int *cmatind,
02058   double * cmatval,
02059   double * obj,
02060   double * lower,
02061   double * upper,
02062   const char **names,
02063   int factorok)
02064 {
02065   int rval = 0;
02066   int i;
02067 
02068   for (i = 0; i < num; i++)
02069   {
02070     if (names)
02071     {
02072       rval = dbl_ILLlib_addcol (lp, B, cmatcnt[i], cmatind + cmatbeg[i],
02073                             cmatval + cmatbeg[i], obj[i], lower[i],
02074                             upper[i], names[i], factorok);
02075     }
02076     else
02077     {
02078       rval = dbl_ILLlib_addcol (lp, B, cmatcnt[i], cmatind + cmatbeg[i],
02079                             cmatval + cmatbeg[i], obj[i], lower[i],
02080                             upper[i], 0, factorok);
02081     }
02082     CHECKRVALG (rval, CLEANUP);
02083   }
02084 
02085 CLEANUP:
02086 
02087   EG_RETURN (rval);
02088 }
02089 
02090 int dbl_ILLlib_addcol (
02091   dbl_lpinfo * lp,
02092   dbl_ILLlp_basis * B,
02093   int cnt,
02094   int *ind,
02095   double * val,
02096   double obj,
02097   double lower,
02098   double upper,
02099   const char *name,
02100   int factorok)
02101 {
02102   int rval = 0;
02103   dbl_ILLlpdata *qslp;
02104   dbl_ILLmatrix *A;
02105   int ncols;
02106   char buf[ILL_namebufsize];
02107   int pind, hit;
02108   double l, u;
02109 
02110   dbl_EGlpNumInitVar (l);
02111   dbl_EGlpNumInitVar (u);
02112 
02113   if (!lp)
02114   {
02115     fprintf (stderr, "dbl_ILLlib_addcol called without an lp\n");
02116     rval = 1;
02117     ILL_CLEANUP;
02118   }
02119 
02120   qslp = lp->O;
02121   A = &qslp->A;
02122   ncols = qslp->ncols;
02123 
02124   if (qslp->rA)
02125   {                             /* After an addcol call, needs to be updated */
02126     dbl_ILLlp_rows_clear (qslp->rA);
02127     ILL_IFFREE (qslp->rA, dbl_ILLlp_rows);
02128   }
02129 
02130   if (qslp->sinfo)
02131   {                             /* Presolve LP is no longer valid, free the data */
02132     dbl_ILLlp_sinfo_free (qslp->sinfo);
02133     ILL_IFFREE (qslp->sinfo, dbl_ILLlp_sinfo);
02134   }
02135 
02136 
02137   /* Add the new variable to the column structures */
02138 
02139   if (qslp->colsize < ncols + 1)
02140   {
02141     dbl_EGlpNumReallocArray (&(qslp->lower), qslp->colsize + dbl_EXTRA_COLS);
02142     dbl_EGlpNumReallocArray (&(qslp->upper), qslp->colsize + dbl_EXTRA_COLS);
02143     dbl_EGlpNumReallocArray (&(qslp->obj), qslp->colsize + dbl_EXTRA_COLS);
02144     qslp->colsize += dbl_EXTRA_COLS;
02145   }
02146 
02147   dbl_EGlpNumCopy (qslp->obj[ncols], obj);
02148   dbl_EGlpNumCopy (qslp->lower[ncols], lower);
02149   dbl_EGlpNumCopy (qslp->upper[ncols], upper);
02150 
02151   /*  Add the variable to the structural arrays */
02152 
02153   if (qslp->structsize < qslp->nstruct + 1)
02154   {
02155     qslp->structmap = EGrealloc (qslp->structmap,
02156                                  sizeof (int) * (qslp->structsize +
02157                                                  dbl_EXTRA_COLS));
02158     //rval = ILLutil_reallocrus_count ((void **) &(qslp->structmap),
02159     //                                 qslp->structsize + dbl_EXTRA_COLS,
02160     //                                 sizeof (int));
02161     //CHECKRVALG(rval,CLEANUP);
02162 
02163     qslp->colnames = EGrealloc (qslp->colnames,
02164                                 sizeof (char *) * (qslp->structsize +
02165                                                    dbl_EXTRA_COLS));
02166     //rval = ILLutil_reallocrus_count ((void **) &(qslp->colnames),
02167     //                                 qslp->structsize + dbl_EXTRA_COLS,
02168     //                                 sizeof (char *));
02169     //CHECKRVALG(rval,CLEANUP);
02170 
02171     if (qslp->intmarker)
02172     {
02173       qslp->intmarker = EGrealloc (qslp->intmarker,
02174                                    sizeof (char) * (qslp->structsize +
02175                                                     dbl_EXTRA_COLS));
02176       //rval = ILLutil_reallocrus_count ((void **) &(qslp->intmarker),
02177       //                                 qslp->structsize + dbl_EXTRA_COLS,
02178       //                                 sizeof (char));
02179       //CHECKRVALG(rval,CLEANUP);
02180     }
02181     qslp->structsize += dbl_EXTRA_COLS;
02182   }
02183 
02184   qslp->structmap[qslp->nstruct] = ncols;
02185   if (qslp->intmarker)
02186   {
02187     /* NOTE: If we want to add integer variables, this is the place. */
02188     qslp->intmarker[qslp->nstruct] = (char) 0;
02189   }
02190 
02191   ILL_FAILtrue (qslp->colnames == NULL, "must always be non NULL");
02192   dbl_ILLlib_findName (qslp, 0 /*isRow */ , name, qslp->nstruct, buf);
02193   ILLsymboltab_register (&qslp->coltab, buf, qslp->nstruct, &pind, &hit);
02194   ILL_FAILfalse ((pind == qslp->nstruct) && (hit == 0), "must be new");
02195   dbl_ILL_UTIL_STR (qslp->colnames[qslp->nstruct], buf);
02196 
02197 
02198   /*  Add col to the matrix */
02199 
02200   rval = dbl_matrix_addcol (A, cnt, ind, val);
02201   CHECKRVALG (rval, CLEANUP);
02202 
02203 
02204   if (B)
02205   {
02206     B->cstat = EGrealloc (B->cstat, sizeof (char) * (qslp->nstruct + 1));
02207     //rval = ILLutil_reallocrus_count ((void **) &(B->cstat),
02208     //                                 qslp->nstruct + 1, sizeof (char));
02209     //CHECKRVALG(rval,CLEANUP);
02210     if (dbl_EGlpNumIsEqual (lower, dbl_ILL_MINDOUBLE, dbl_oneLpNum) &&
02211         dbl_EGlpNumIsEqual (upper, dbl_ILL_MAXDOUBLE, dbl_oneLpNum))
02212     {
02213       B->cstat[qslp->nstruct] = QS_COL_BSTAT_FREE;
02214     }
02215     else if (dbl_EGlpNumIsEqual (upper, dbl_ILL_MAXDOUBLE, dbl_oneLpNum))
02216     {
02217       B->cstat[qslp->nstruct] = QS_COL_BSTAT_LOWER;
02218     }
02219     //else if (lower == dbl_ILL_MAXDOUBLE)
02220     else if (dbl_EGlpNumIsEqual (lower, dbl_ILL_MAXDOUBLE, dbl_oneLpNum))
02221     {
02222       B->cstat[qslp->nstruct] = QS_COL_BSTAT_UPPER;
02223     }
02224     else
02225     {
02226       /*l = fabs (lower);
02227        * u = fabs (upper); */
02228       dbl_EGlpNumCopyAbs (l, lower);
02229       dbl_EGlpNumCopyAbs (u, upper);
02230       if (dbl_EGlpNumIsLess (l, u))
02231       {
02232         B->cstat[qslp->nstruct] = QS_COL_BSTAT_LOWER;
02233       }
02234       else
02235       {
02236         B->cstat[qslp->nstruct] = QS_COL_BSTAT_UPPER;
02237       }
02238     }
02239 
02240     /* UPDATE THE PINF dbl_PRIMAL NORMS */
02241     dbl_EGlpNumFreeArray (B->colnorms);
02242   }
02243 
02244   if (factorok == 0)
02245   {
02246 #if 0
02247     lp->basisid = -1;           /* To get optimizer to reload the basis */
02248 #endif
02249   }
02250   else
02251   {
02252     if (!lp->nbaz || !lp->vindex || !lp->vstat)
02253     {
02254       fprintf (stderr, "ERROR: factorok set without a current basis\n");
02255       rval = 1;
02256       ILL_CLEANUP;
02257     }
02258 
02259     lp->nbaz = EGrealloc (lp->nbaz, sizeof (int) * (qslp->nstruct + 1));
02260     //rval = ILLutil_reallocrus_count ((void **) &(lp->nbaz),
02261     //                                 qslp->nstruct + 1, sizeof (int));
02262     //CHECKRVALG(rval,CLEANUP);
02263 
02264     lp->vindex = EGrealloc (lp->vindex, sizeof (int) * (qslp->ncols + 1));
02265     //rval = ILLutil_reallocrus_count ((void **) &(lp->vindex),
02266     //                                 qslp->ncols + 1, sizeof (int));
02267     //CHECKRVALG(rval,CLEANUP);
02268 
02269     lp->vstat = EGrealloc (lp->vstat, sizeof (int) * (qslp->ncols + 1));
02270     //rval = ILLutil_reallocrus_count ((void **) &(lp->vstat),
02271     //                                 qslp->ncols + 1, sizeof (int));
02272 
02273 
02274     lp->nbaz[qslp->nstruct] = qslp->ncols;
02275     lp->vindex[qslp->ncols] = qslp->nstruct;
02276 
02277     if (dbl_EGlpNumIsEqual (lower, dbl_ILL_MINDOUBLE, dbl_oneLpNum) &&
02278         dbl_EGlpNumIsEqual (upper, dbl_ILL_MAXDOUBLE, dbl_oneLpNum))
02279     {
02280       lp->vstat[qslp->ncols] = STAT_ZERO;
02281     }
02282     else if (dbl_EGlpNumIsEqual (upper, dbl_ILL_MAXDOUBLE, dbl_oneLpNum))
02283     {
02284       lp->vstat[qslp->ncols] = STAT_LOWER;
02285     }
02286     //else if (lower == dbl_ILL_MAXDOUBLE)
02287     else if (dbl_EGlpNumIsEqual (lower, dbl_ILL_MAXDOUBLE, dbl_oneLpNum))
02288     {
02289       lp->vstat[qslp->ncols] = STAT_UPPER;
02290     }
02291     else
02292     {
02293       /*l = fabs (lower);
02294        * u = fabs (upper); */
02295       dbl_EGlpNumCopyAbs (l, lower);
02296       dbl_EGlpNumCopyAbs (u, upper);
02297       if (dbl_EGlpNumIsLess (l, u))
02298       {
02299         lp->vstat[qslp->ncols] = STAT_LOWER;
02300       }
02301       else
02302       {
02303         lp->vstat[qslp->ncols] = STAT_UPPER;
02304       }
02305     }
02306   }
02307 
02308 
02309   qslp->ncols++;
02310   qslp->nstruct++;
02311   (qslp->nzcount) += cnt;
02312 
02313   if (B)
02314   {
02315     B->nstruct++;
02316   }
02317 
02318 CLEANUP:
02319   dbl_EGlpNumClearVar (l);
02320   dbl_EGlpNumClearVar (u);
02321   EG_RETURN (rval);
02322 }
02323 
02324 static int dbl_matrix_addrow (
02325   dbl_ILLmatrix * A,
02326   int rowcnt,
02327   int *rowind,
02328   double * rowval)
02329 {
02330   int rval = 0;
02331   int i, j, k, ind, memo, stop, delta = 0;
02332 
02333   /* matsize will be the length of the array.                   */
02334   /* matfree will keep track of the free space at end of array. */
02335 
02336   for (i = 0; i < rowcnt; i++)
02337   {
02338     if (rowind[i] >= A->matcols || rowind[i] < 0)
02339     {
02340       fprintf (stderr, "illegal col index in dbl_matrix_addrow\n");
02341       rval = 1;
02342       ILL_CLEANUP;
02343     }
02344   }
02345 
02346   for (i = 0; i < rowcnt; i++)
02347   {
02348     j = rowind[i];
02349     if (A->matcnt[j] > 0 &&
02350         (A->matbeg[j] + A->matcnt[j] + 1 > A->matsize ||
02351          A->matind[A->matbeg[j] + A->matcnt[j]] != -1))
02352     {
02353       delta += (A->matcnt[j] + 2);  /* 1 for the new coef and 1 for */
02354       /* an extra space               */
02355     }
02356   }
02357 
02358   if (delta < A->matfree)
02359   {
02360     for (i = 0; i < rowcnt; i++)
02361     {
02362       j = rowind[i];
02363       if (A->matcnt[j] == 0)
02364       {
02365         A->matind[A->matbeg[j]] = A->matrows;
02366         dbl_EGlpNumCopy (A->matval[A->matbeg[j]], rowval[i]);
02367         A->matcnt[j] = 1;
02368       }
02369       else if (A->matind[A->matbeg[j] + A->matcnt[j]] == -1)
02370       {
02371         /* Since A->matfree is positive, we know that we are not */
02372         /* sitting at the end of the array.                      */
02373         A->matind[A->matbeg[j] + A->matcnt[j]] = A->matrows;
02374         dbl_EGlpNumCopy (A->matval[A->matbeg[j] + A->matcnt[j]], rowval[i]);
02375         if ((A->matbeg[j] + A->matcnt[j]) == (A->matsize - A->matfree))
02376         {
02377           A->matfree--;         /* at end of used space */
02378         }
02379         (A->matcnt[j])++;
02380       }
02381       else
02382       {
02383         ind = A->matsize - A->matfree + 1;  /* leave space for -1 */
02384         memo = ind;
02385         stop = A->matbeg[j] + A->matcnt[j];
02386         for (k = A->matbeg[j]; k < stop; k++)
02387         {
02388           if (ind >= A->matsize)
02389           {
02390             printf ("WHAT: %d, %d\n", A->matsize, ind);
02391             fflush (stdout);
02392             exit (1);
02393           }
02394           A->matind[ind] = A->matind[k];
02395           dbl_EGlpNumCopy (A->matval[ind], A->matval[k]);
02396           A->matind[k] = -1;
02397           ind++;
02398         }
02399         A->matind[ind] = A->matrows;
02400         dbl_EGlpNumCopy (A->matval[ind], rowval[i]);
02401         A->matbeg[j] = memo;
02402         (A->matcnt[j])++;
02403         (A->matfree) -= (A->matcnt[j] + 1);
02404       }
02405     }
02406   }
02407   else
02408   {
02409     rval = dbl_matrix_addrow_end (A, A->matrows, rowcnt, rowind, rowval);
02410     CHECKRVALG (rval, CLEANUP);
02411   }
02412   A->matrows++;
02413 
02414 CLEANUP:
02415 
02416   EG_RETURN (rval);
02417 }
02418 
02419 static int dbl_matrix_addrow_end (
02420   dbl_ILLmatrix * A,
02421   int row,
02422   int rowcnt,
02423   int *rowind,
02424   double * rowval)
02425 {
02426   int rval = 0;
02427   int i, j, k, start, stop, total;
02428   int *newbeg = 0;
02429   int *newind = 0;
02430   double *newval = 0;
02431   int ncols = A->matcols;
02432 
02433   if (A->matcolsize > 0)
02434   {
02435     ILL_SAFE_MALLOC (newbeg, A->matcolsize, int);
02436   }
02437   ILL_SAFE_MALLOC (newind, A->matsize + rowcnt + dbl_EXTRA_MAT, int);
02438 
02439   newval = dbl_EGlpNumAllocArray (A->matsize + rowcnt + dbl_EXTRA_MAT);
02440 
02441   A->matsize += (rowcnt + dbl_EXTRA_MAT);
02442 
02443   for (i = 0; i < rowcnt; i++)
02444   {
02445     A->matcnt[rowind[i]]++;
02446   }
02447   for (total = 0, j = 0; j < ncols; j++)
02448   {
02449     newbeg[j] = total;
02450     if (A->matcnt[j] > 0)
02451       total += A->matcnt[j];
02452     else
02453       total += 1;
02454   }
02455   for (i = 0; i < rowcnt; i++)
02456   {
02457     A->matcnt[rowind[i]]--;
02458   }
02459   for (j = total; j < A->matsize; j++)
02460   {
02461     newind[j] = -1;
02462   }
02463   A->matfree = A->matsize - total;
02464 
02465   for (j = 0; j < ncols; j++)
02466   {
02467     if (A->matcnt[j] > 0)
02468     {
02469       stop = A->matbeg[j] + A->matcnt[j];
02470       start = newbeg[j];
02471       for (k = A->matbeg[j]; k < stop; k++)
02472       {
02473         newind[start] = A->matind[k];
02474         dbl_EGlpNumCopy (newval[start], A->matval[k]);
02475         start++;
02476       }
02477     }
02478     else
02479     {
02480       newind[newbeg[j]] = 1;
02481     }
02482   }
02483   for (i = 0; i < rowcnt; i++)
02484   {
02485     j = rowind[i];
02486     newind[newbeg[j] + A->matcnt[j]] = row;
02487     dbl_EGlpNumCopy (newval[newbeg[j] + A->matcnt[j]], rowval[i]);
02488     (A->matcnt[j])++;
02489   }
02490 
02491   ILL_IFFREE (A->matbeg, int);
02492   ILL_IFFREE (A->matind, int);
02493 
02494   dbl_EGlpNumFreeArray (A->matval);
02495 
02496   A->matbeg = newbeg;
02497   A->matind = newind;
02498   A->matval = newval;
02499 
02500 CLEANUP:
02501 
02502   if (rval)
02503   {
02504     ILL_IFFREE (newbeg, int);
02505     ILL_IFFREE (newind, int);
02506 
02507     dbl_EGlpNumFreeArray (newval);
02508   }
02509 
02510   EG_RETURN (rval);
02511 }
02512 
02513 static int dbl_matrix_addcoef (
02514   dbl_lpinfo * lp,
02515   dbl_ILLmatrix * A,
02516   int row,
02517   int col,
02518   double val)
02519 {
02520   int i, k, delta, ind, stop, memo;
02521   int tind[1];
02522   double tval[1];
02523   int rval = 0;
02524 
02525   dbl_EGlpNumInitVar (tval[0]);
02526   dbl_EGlpNumCopy (tval[0], val);
02527 
02528   if (row >= A->matrows || row < 0)
02529   {
02530     fprintf (stderr, "illegal row index in dbl_matrix_addcoef\n");
02531     rval = 1;
02532     ILL_CLEANUP;
02533   }
02534 
02535   if (col >= A->matcols || col < 0)
02536   {
02537     fprintf (stderr, "illegal col index in dbl_matrix_addcoef\n");
02538     rval = 1;
02539     ILL_CLEANUP;
02540   }
02541 
02542   for (i = A->matbeg[col]; i < A->matbeg[col] + A->matcnt[col]; i++)
02543   {
02544     if (A->matind[i] == row)
02545     {
02546       dbl_EGlpNumCopy (A->matval[i], val);
02547       ILL_CLEANUP;
02548     }
02549   }
02550 
02551   /* The coef is new, we need to add it to A */
02552 
02553   lp->O->nzcount++;
02554   delta = A->matcnt[col] + 2;
02555 
02556   if (A->matcnt[col] == 0)
02557   {
02558     /* First entry, always a free space */
02559     A->matind[A->matbeg[col]] = row;
02560     dbl_EGlpNumCopy (A->matval[A->matbeg[col]], val);
02561     A->matcnt[col] = 1;
02562   }
02563   else if (A->matbeg[col] + A->matcnt[col] < A->matsize &&
02564            A->matind[A->matbeg[col] + A->matcnt[col]] == -1)
02565   {
02566     /* Free space in the column */
02567     A->matind[A->matbeg[col] + A->matcnt[col]] = row;
02568     dbl_EGlpNumCopy (A->matval[A->matbeg[col] + A->matcnt[col]], val);
02569     if ((A->matbeg[col] + A->matcnt[col]) == (A->matsize - A->matfree))
02570     {
02571       A->matfree--;
02572     }
02573     (A->matcnt[col])++;
02574   }
02575   else if (A->matfree > delta)
02576   {
02577     /* Enough space to move column to end of array */
02578     ind = A->matsize - A->matfree + 1;
02579     memo = ind;
02580     stop = A->matbeg[col] + A->matcnt[col];
02581     for (k = A->matbeg[col]; k < stop; k++)
02582     {
02583       A->matind[ind] = A->matind[k];
02584       dbl_EGlpNumCopy (A->matval[ind], A->matval[k]);
02585       A->matind[k] = -1;
02586       ind++;
02587     }
02588     A->matind[ind] = row;
02589     dbl_EGlpNumCopy (A->matval[ind], val);
02590 
02591     A->matbeg[col] = memo;
02592     (A->matcnt[col])++;
02593     (A->matfree) -= (A->matcnt[col] + 1);
02594   }
02595   else
02596   {
02597     /* Need to malloc space to move column to end of array */
02598 
02599     tind[0] = col;
02600 
02601     rval = dbl_matrix_addrow_end (A, row, 1, tind, tval);
02602     CHECKRVALG (rval, CLEANUP);
02603   }
02604 
02605 CLEANUP:
02606 
02607   dbl_EGlpNumClearVar (tval[0]);
02608   EG_RETURN (rval);
02609 }
02610 
02611 static int dbl_matrix_addcol (
02612   dbl_ILLmatrix * A,
02613   int colcnt,
02614   int *colind,
02615   double * colval)
02616 {
02617   int rval = 0;
02618   int i, ind;
02619 
02620   for (i = 0; i < colcnt; i++)
02621   {
02622     if (colind[i] >= A->matrows || colind[i] < 0)
02623     {
02624       fprintf (stderr, "illegal row index in dbl_matrix_addcol\n");
02625       rval = 1;
02626       ILL_CLEANUP;
02627     }
02628   }
02629 
02630   if (A->matcolsize < A->matcols + 1)
02631   {
02632     A->matbeg =
02633       EGrealloc (A->matbeg, sizeof (int) * (A->matcolsize + dbl_EXTRA_COLS));
02634     //rval = ILLutil_reallocrus_count ((void **) &(A->matbeg),
02635     //                                 A->matcolsize + dbl_EXTRA_COLS, sizeof (int));
02636     //CHECKRVALG(rval,CLEANUP);
02637 
02638     A->matcnt =
02639       EGrealloc (A->matcnt, sizeof (int) * (A->matcolsize + dbl_EXTRA_COLS));
02640     //rval = ILLutil_reallocrus_count ((void **) &(A->matcnt),
02641     //                                 A->matcolsize + dbl_EXTRA_COLS, sizeof (int));
02642     //CHECKRVALG(rval,CLEANUP);
02643 
02644     (A->matcolsize) += dbl_EXTRA_COLS;
02645   }
02646 
02647   if (A->matfree < colcnt + 1)
02648   {
02649     A->matind = EGrealloc (A->matind,
02650                            sizeof (int) * (A->matsize + colcnt + dbl_EXTRA_MAT +
02651                                            1));
02652     //rval = ILLutil_reallocrus_count ((void **) &(A->matind),
02653     //                                 A->matsize + colcnt + dbl_EXTRA_MAT + 1,
02654     //                                 sizeof (int));
02655     //CHECKRVALG(rval,CLEANUP);
02656     dbl_EGlpNumReallocArray (&(A->matval), A->matsize + colcnt + dbl_EXTRA_MAT + 1);
02657 
02658     for (i = 0; i < colcnt + dbl_EXTRA_MAT + 1; i++)
02659     {
02660       A->matind[A->matsize + i] = -1;
02661     }
02662     A->matsize += (colcnt + dbl_EXTRA_MAT + 1);
02663     A->matfree += (colcnt + dbl_EXTRA_MAT + 1);
02664   }
02665 
02666   ind = A->matsize - A->matfree;
02667   A->matbeg[A->matcols] = ind;
02668   A->matcnt[A->matcols] = colcnt;
02669   if (colcnt == 0)
02670   {
02671     A->matind[ind] = 1;         /* Dummy value to stop columns from stealing */
02672     /* this space in addrows.                    */
02673     A->matfree -= 1;
02674   }
02675   else
02676   {
02677     for (i = 0; i < colcnt; i++)
02678     {
02679       dbl_EGlpNumCopy (A->matval[ind], colval[i]);
02680       A->matind[ind] = colind[i];
02681       ind++;
02682     }
02683     A->matfree -= colcnt;
02684   }
02685   A->matcols++;
02686 
02687 CLEANUP:
02688 
02689   EG_RETURN (rval);
02690 }
02691 
02692 int dbl_ILLlib_getrows (
02693   dbl_lpinfo * lp,
02694   int num,
02695   int *rowlist,
02696   int **rowcnt,
02697   int **rowbeg,
02698   int **rowind,
02699   double ** rowval,
02700   double ** rhs,
02701   char **sense,
02702   double ** range,
02703   char ***names)
02704 {
02705   int rval = 0;
02706   int *allbeg = 0;
02707   int *allcnt = 0;
02708   int *allind = 0;
02709   double *allval = 0;
02710   int i, row, k, start, stop, len, tcnt, cnt = 0;
02711   dbl_ILLlpdata *qslp;
02712   dbl_ILLlp_rows lprows;
02713 
02714   if (rowcnt) *rowcnt = 0;
02715   if (rowbeg) *rowbeg = 0;
02716   if (rowind) *rowind = 0;
02717   if (rowval) *rowval = 0;
02718   if (rhs) *rhs = 0;
02719   if (range) *range = 0;
02720   if (sense) *sense = 0;
02721   if (names) *names = 0;
02722 
02723   if (!lp)
02724   {
02725     fprintf (stderr, "dbl_ILLlib_getrows called without an LP\n");
02726     rval = 1;
02727     ILL_CLEANUP;
02728   }
02729 
02730   if (!num)
02731     ILL_CLEANUP;
02732 
02733   qslp = lp->O;
02734 
02735   rval = dbl_ILLlp_rows_init (&lprows, qslp, 0);
02736   CHECKRVALG (rval, CLEANUP);
02737   allbeg = lprows.rowbeg;
02738   allcnt = lprows.rowcnt;
02739   allind = lprows.rowind;
02740   allval = lprows.rowval;
02741 
02742   for (i = 0; i < num; i++)
02743   {
02744     cnt += allcnt[rowlist[i]];
02745   }
02746 
02747   if (rowcnt)
02748   {
02749     ILL_SAFE_MALLOC (*rowcnt, num, int);
02750 
02751     for (i = 0; i < num; i++)
02752     {
02753       (*rowcnt)[i] = allcnt[rowlist[i]];
02754     }
02755   }
02756 
02757   if (rowbeg)
02758   {
02759     ILL_SAFE_MALLOC (*rowbeg, num, int);
02760 
02761     tcnt = 0;
02762     for (i = 0; i < num; i++)
02763     {
02764       (*rowbeg)[i] = tcnt;
02765       tcnt += allcnt[rowlist[i]];
02766     }
02767   }
02768 
02769   if (cnt && rowind)
02770   {
02771     ILL_SAFE_MALLOC (*rowind, cnt, int);
02772 
02773     tcnt = 0;
02774     for (i = 0; i < num; i++)
02775     {
02776       row = rowlist[i];
02777       start = allbeg[row];
02778       stop = start + allcnt[row];
02779       for (k = start; k < stop; k++)
02780       {
02781         (*rowind)[tcnt++] = allind[k];
02782       }
02783     }
02784   }
02785 
02786   if (cnt && rowval)
02787   {
02788     *rowval = dbl_EGlpNumAllocArray (cnt);
02789     tcnt = 0;
02790     for (i = 0; i < num; i++)
02791     {
02792       row = rowlist[i];
02793       start = allbeg[row];
02794       stop = start + allcnt[row];
02795       for (k = start; k < stop; k++)
02796       {
02797         dbl_EGlpNumCopy ((*rowval)[tcnt++], allval[k]);
02798       }
02799     }
02800   }
02801 
02802   if (rhs)
02803   {
02804     *rhs = dbl_EGlpNumAllocArray (num);
02805     for (i = 0; i < num; i++)
02806     {
02807       dbl_EGlpNumCopy ((*rhs)[i], qslp->rhs[rowlist[i]]);
02808     }
02809   }
02810 
02811   if (range)
02812   {
02813     *range = dbl_EGlpNumAllocArray(num);
02814     if(qslp->rangeval)
02815     {
02816       for(i = 0; i < num ; i++)
02817       {
02818         dbl_EGlpNumCopy((*range)[i], qslp->rangeval[rowlist[i]]);
02819       }
02820     }
02821     else
02822     {
02823       for(i = 0; i < num ; i++)
02824       {
02825         dbl_EGlpNumZero((*range)[i]);
02826       }
02827     }
02828   }
02829 
02830   if (sense)
02831   {
02832     ILL_SAFE_MALLOC (*sense, num, char);
02833 
02834     for (i = 0; i < num; i++)
02835     {
02836       (*sense)[i] = qslp->sense[rowlist[i]];
02837     }
02838   }
02839 
02840   if (names)
02841   {
02842     if (qslp->rownames == 0)
02843     {
02844       fprintf (stderr, "LP does not have row names\n");
02845       rval = 1;
02846       ILL_CLEANUP;
02847     }
02848     ILL_SAFE_MALLOC (*names, num, char *);
02849 
02850     for (i = 0; i < num; i++)
02851     {
02852       (*names)[i] = 0;
02853     }
02854     for (i = 0; i < num; i++)
02855     {
02856       len = strlen (qslp->rownames[rowlist[i]]) + 1;
02857       ILL_SAFE_MALLOC ((*names)[i], len, char);
02858 
02859       strcpy ((*names)[i], qslp->rownames[rowlist[i]]);
02860     }
02861   }
02862 
02863 CLEANUP:
02864 
02865   ILL_IFFREE (allbeg, int);
02866   ILL_IFFREE (allcnt, int);
02867   ILL_IFFREE (allind, int);
02868 
02869   dbl_EGlpNumFreeArray (allval);
02870 
02871   if (rval)
02872   {
02873     if (rowcnt)
02874       ILL_IFFREE (*rowcnt, int);
02875 
02876     if (rowbeg)
02877       ILL_IFFREE (*rowbeg, int);
02878 
02879     if (rowind)
02880       ILL_IFFREE (*rowind, int);
02881 
02882     if (rowval)
02883       dbl_EGlpNumFreeArray (*rowval);
02884     if (rhs)
02885       dbl_EGlpNumFreeArray (*rhs);
02886     if (sense)
02887       ILL_IFFREE (*sense, char);
02888 
02889     if (names && (*names))
02890     {
02891       for (i = 0; i < num; i++)
02892       {
02893         ILL_IFFREE ((*names)[i], char);
02894       }
02895       ILL_IFFREE (*names, char *);
02896     }
02897   }
02898 
02899   EG_RETURN (rval);
02900 }
02901 
02902 int dbl_ILLlib_getcols (
02903   dbl_lpinfo * lp,
02904   int num,
02905   int *collist,
02906   int **colcnt,
02907   int **colbeg,
02908   int **colind,
02909   double ** colval,
02910   double ** obj,
02911   double ** lower,
02912   double ** upper,
02913   char ***names)
02914 {
02915   int rval = 0;
02916   int i, col, k, start, stop, len, tcnt, cnt = 0;
02917   dbl_ILLlpdata *qslp;
02918   dbl_ILLmatrix *A;
02919   int *tlist = 0;
02920 
02921   if (colcnt)
02922     *colcnt = 0;
02923   if (colbeg)
02924     *colbeg = 0;
02925   if (colind)
02926     *colind = 0;
02927   if (colval)
02928     *colval = 0;
02929   if (lower)
02930     *lower = 0;
02931   if (upper)
02932     *upper = 0;
02933   if (obj)
02934     *obj = 0;
02935   if (names)
02936     *names = 0;
02937 
02938   if (!lp)
02939   {
02940     fprintf (stderr, "dbl_ILLlib_getcols called without an LP\n");
02941     rval = 1;
02942     ILL_CLEANUP;
02943   }
02944 
02945   if (!num)
02946     ILL_CLEANUP;
02947 
02948   qslp = lp->O;
02949   A = &(qslp->A);
02950 
02951   ILL_SAFE_MALLOC (tlist, num, int);
02952 
02953   for (i = 0; i < num; i++)
02954   {
02955     tlist[i] = qslp->structmap[collist[i]];
02956   }
02957 
02958   for (i = 0; i < num; i++)
02959   {
02960     cnt += A->matcnt[tlist[i]];
02961   }
02962 
02963   if (colcnt)
02964   {
02965     ILL_SAFE_MALLOC (*colcnt, num, int);
02966 
02967     for (i = 0; i < num; i++)
02968     {
02969       (*colcnt)[i] = A->matcnt[tlist[i]];
02970     }
02971   }
02972 
02973   if (colbeg)
02974   {
02975     ILL_SAFE_MALLOC (*colbeg, num, int);
02976 
02977     tcnt = 0;
02978     for (i = 0; i < num; i++)
02979     {
02980       (*colbeg)[i] = tcnt;
02981       tcnt += A->matcnt[tlist[i]];
02982     }
02983   }
02984 
02985   if (cnt && colind)
02986   {
02987     ILL_SAFE_MALLOC (*colind, cnt, int);
02988 
02989     tcnt = 0;
02990     for (i = 0; i < num; i++)
02991     {
02992       col = tlist[i];
02993       start = A->matbeg[col];
02994       stop = start + A->matcnt[col];
02995       for (k = start; k < stop; k++)
02996       {
02997         (*colind)[tcnt++] = A->matind[k];
02998       }
02999     }
03000   }
03001 
03002   if (cnt && colval)
03003   {
03004     *colval = dbl_EGlpNumAllocArray (cnt);
03005     tcnt = 0;
03006     for (i = 0; i < num; i++)
03007     {
03008       col = tlist[i];
03009       start = A->matbeg[col];
03010       stop = start + A->matcnt[col];
03011       for (k = start; k < stop; k++)
03012       {
03013         dbl_EGlpNumCopy ((*colval)[tcnt++], A->matval[k]);
03014       }
03015     }
03016   }
03017 
03018   if (obj)
03019   {
03020     *obj = dbl_EGlpNumAllocArray (num);
03021     for (i = 0; i < num; i++)
03022     {
03023       dbl_EGlpNumCopy ((*obj)[i], qslp->obj[tlist[i]]);
03024     }
03025   }
03026 
03027   if (lower)
03028   {
03029     *lower = dbl_EGlpNumAllocArray (num);
03030     for (i = 0; i < num; i++)
03031     {
03032       dbl_EGlpNumCopy ((*lower)[i], qslp->lower[tlist[i]]);
03033     }
03034   }
03035 
03036   if (upper)
03037   {
03038     *upper = dbl_EGlpNumAllocArray (num);
03039     for (i = 0; i < num; i++)
03040     {
03041       dbl_EGlpNumCopy ((*upper)[i], qslp->upper[tlist[i]]);
03042     }
03043   }
03044 
03045   if (names)
03046   {
03047     if (qslp->colnames == 0)
03048     {
03049       fprintf (stderr, "LP does not have col names\n");
03050       rval = 1;
03051       ILL_CLEANUP;
03052     }
03053     ILL_SAFE_MALLOC (*names, num, char *);
03054 
03055     for (i = 0; i < num; i++)
03056     {
03057       (*names)[i] = 0;
03058     }
03059     for (i = 0; i < num; i++)
03060     {
03061       len = strlen (qslp->colnames[collist[i]]) + 1;
03062       ILL_SAFE_MALLOC ((*names)[i], len, char);
03063 
03064       strcpy ((*names)[i], qslp->colnames[collist[i]]);
03065     }
03066   }
03067 
03068 CLEANUP:
03069 
03070   if (rval)
03071   {
03072     if (colcnt)
03073       ILL_IFFREE (*colcnt, int);
03074 
03075     if (colbeg)
03076       ILL_IFFREE (*colbeg, int);
03077 
03078     if (colind)
03079       ILL_IFFREE (*colind, int);
03080 
03081     if (colval)
03082       dbl_EGlpNumFreeArray (*colval);
03083     if (obj)
03084       dbl_EGlpNumFreeArray (*obj);
03085     if (lower)
03086       dbl_EGlpNumFreeArray (*lower);
03087     if (upper)
03088       dbl_EGlpNumFreeArray (*upper);
03089     if (names && (*names))
03090     {
03091       for (i = 0; i < num; i++)
03092       {
03093         ILL_IFFREE ((*names)[i], char);
03094       }
03095       ILL_IFFREE (*names, char *);
03096     }
03097   }
03098   ILL_IFFREE (tlist, int);
03099 
03100   EG_RETURN (rval);
03101 }
03102 
03103 int dbl_ILLlib_getobj_list (
03104   dbl_lpinfo *lp,
03105   int num,
03106   int* collist,
03107   double* obj)
03108 {
03109   const int*const structmap = lp->O->structmap;
03110   dbl_ILLlpdata *qslp;
03111   int nstruct, j, col;
03112   int rval = 0;
03113   
03114   if (!lp)
03115   {
03116     fprintf (stderr, "dbl_ILLlib_getobj_list called without an LP\n");
03117     rval = 1;
03118     ILL_CLEANUP;
03119   }
03120   
03121   qslp = lp->O;
03122   nstruct = qslp->nstruct;
03123   
03124   for (j = 0; j < num; j++)
03125   {
03126     col = collist[j];
03127     if(col<0 || col >= nstruct)
03128     {
03129       fprintf(stderr, "dbl_ILLlib_getobj_list collist[%d] = %d outside"
03130               " valid range\n", j, col);
03131       rval = 1;
03132       ILL_CLEANUP;
03133     }
03134     dbl_EGlpNumCopy(obj[j],qslp->obj[structmap[col]]);
03135   }  
03136 
03137 CLEANUP:
03138 
03139   EG_RETURN (rval);
03140 }
03141 
03142 
03143 int dbl_ILLlib_getobj (
03144   dbl_lpinfo * lp,
03145   double * obj)
03146 {
03147   const int*const structmap = lp->O->structmap;
03148   dbl_ILLlpdata *qslp;
03149   int nstruct, j;
03150   int rval = 0;
03151 
03152   if (!lp)
03153   {
03154     fprintf (stderr, "dbl_ILLlib_getobj called without an LP\n");
03155     rval = 1;
03156     ILL_CLEANUP;
03157   }
03158 
03159   qslp = lp->O;
03160   nstruct = qslp->nstruct;
03161 
03162   for (j = 0; j < nstruct; j++)
03163   {
03164     dbl_EGlpNumCopy (obj[j], qslp->obj[structmap[j]]);
03165   }
03166 
03167 CLEANUP:
03168 
03169   EG_RETURN (rval);
03170 }
03171 
03172 int dbl_ILLlib_chgobj (
03173   dbl_lpinfo * lp,
03174   int indx,
03175   double coef)
03176 {
03177   int rval = 0;
03178   int col;
03179 
03180   if (!lp)
03181   {
03182     fprintf (stderr, "dbl_ILLlib_chgobj called without an lp\n");
03183     rval = 1;
03184     ILL_CLEANUP;
03185   }
03186 
03187   if (indx < 0 || indx >= lp->O->nstruct)
03188   {
03189     fprintf (stderr, "dbl_ILLlib_chgrhs called with bad indx: %d\n", indx);
03190     rval = 1;
03191     ILL_CLEANUP;
03192   }
03193 
03194   if (lp->O->sinfo)
03195   {                             /* Presolve LP is no longer valid, free the data */
03196     dbl_ILLlp_sinfo_free (lp->O->sinfo);
03197     ILL_IFFREE (lp->O->sinfo, dbl_ILLlp_sinfo);
03198   }
03199 
03200   col = lp->O->structmap[indx];
03201   dbl_EGlpNumCopy (lp->O->obj[col], coef);
03202 
03203 CLEANUP:
03204 
03205   EG_RETURN (rval);
03206 }
03207 
03208 int dbl_ILLlib_getrhs (
03209   dbl_lpinfo * lp,
03210   double * rhs)
03211 {
03212   dbl_ILLlpdata *qslp;
03213   int nrows, i;
03214   int rval = 0;
03215 
03216   if (!lp)
03217   {
03218     fprintf (stderr, "dbl_ILLlib_getrhs called without an LP\n");
03219     rval = 1;
03220     ILL_CLEANUP;
03221   }
03222 
03223   qslp = lp->O;
03224   nrows = qslp->nrows;
03225 
03226   for (i = 0; i < nrows; i++)
03227   {
03228     dbl_EGlpNumCopy (rhs[i], qslp->rhs[i]);
03229   }
03230 
03231 CLEANUP:
03232 
03233   EG_RETURN (rval);
03234 }
03235 
03236 int dbl_ILLlib_chgrange (
03237   dbl_lpinfo *lp,
03238   int indx,
03239   double coef)
03240 {
03241   register int i;
03242   int rval = 0;
03243   dbl_ILLlpdata *qslp;
03244   
03245   if (!lp)
03246   {
03247     fprintf (stderr, "dbl_ILLlib_chgrhs called without an lp\n");
03248     rval = 1;
03249     ILL_CLEANUP;
03250   }
03251   
03252   if (indx < 0 || indx >= lp->O->nrows)
03253   {
03254     fprintf (stderr, "dbl_ILLlib_chgrhs called with bad indx: %d\n", indx);
03255     rval = 1;
03256     ILL_CLEANUP;
03257   }
03258   
03259   if (lp->O->sinfo)
03260   {/* Presolve LP is no longer valid, free the data */
03261     dbl_ILLlp_sinfo_free (lp->O->sinfo);
03262     ILL_IFFREE (lp->O->sinfo, dbl_ILLlp_sinfo);
03263   }
03264   
03265   qslp = lp->O;
03266   if(qslp->rangeval == 0)
03267   {
03268     qslp->rangeval = dbl_EGlpNumAllocArray(qslp->rowsize);
03269     for( i = qslp->nrows ; i-- ; )
03270     {
03271       dbl_EGlpNumZero(qslp->rangeval[i]);
03272     }
03273   }
03274   
03275   if(qslp->sense[indx] != 'R')
03276   {
03277     fprintf(stderr,"setting range for non-range constraint\n");
03278     rval = 1;
03279     ILL_CLEANUP;
03280   }
03281   
03282   dbl_EGlpNumCopy(qslp->rangeval[indx], coef);
03283 
03284 CLEANUP:
03285 
03286   EG_RETURN (rval);
03287 }
03288 
03289 
03290 int dbl_ILLlib_chgrhs (
03291   dbl_lpinfo * lp,
03292   int indx,
03293   double coef)
03294 {
03295   int rval = 0;
03296 
03297   if (!lp)
03298   {
03299     fprintf (stderr, "dbl_ILLlib_chgrhs called without an lp\n");
03300     rval = 1;
03301     ILL_CLEANUP;
03302   }
03303 
03304   if (indx < 0 || indx >= lp->O->nrows)
03305   {
03306     fprintf (stderr, "dbl_ILLlib_chgrhs called with bad indx: %d\n", indx);
03307     rval = 1;
03308     ILL_CLEANUP;
03309   }
03310 
03311   if (lp->O->sinfo)
03312   {                             /* Presolve LP is no longer valid, free the data */
03313     dbl_ILLlp_sinfo_free (lp->O->sinfo);
03314     ILL_IFFREE (lp->O->sinfo, dbl_ILLlp_sinfo);
03315   }
03316 
03317   dbl_EGlpNumCopy (lp->O->rhs[indx], coef);
03318 
03319 CLEANUP:
03320 
03321   EG_RETURN (rval);
03322 }
03323 
03324 int dbl_ILLlib_rownames (
03325   dbl_lpinfo * lp,
03326   char **rownames)
03327 {
03328   dbl_ILLlpdata *qslp;
03329   int nrows, len, i, rcount = 0;
03330   int rval = 0;
03331 
03332   if (!lp)
03333   {
03334     fprintf (stderr, "dbl_ILLlib_rownames called without an LP\n");
03335     rval = 1;
03336     ILL_CLEANUP;
03337   }
03338   if (!rownames)
03339   {
03340     fprintf (stderr, "dbl_ILLlib_rownames called with NULL rownames\n");
03341     rval = 1;
03342     ILL_CLEANUP;
03343   }
03344 
03345   qslp = lp->O;
03346   nrows = qslp->nrows;
03347 
03348   if (qslp->rownames == 0)
03349   {
03350     fprintf (stderr, "LP does not have rownames assigned\n");
03351     rval = 1;
03352     ILL_CLEANUP;
03353   }
03354 
03355   for (i = 0; i < nrows; i++)
03356   {
03357     len = strlen (qslp->rownames[i]) + 1;
03358     ILL_SAFE_MALLOC (rownames[i], len, char);
03359 
03360     strcpy (rownames[i], qslp->rownames[i]);
03361     rcount++;
03362   }
03363 
03364 CLEANUP:
03365 
03366   if (rval)
03367   {
03368     for (i = 0; i < rcount; i++)
03369     {
03370       ILL_IFFREE (rownames[i], char);
03371     }
03372   }
03373   EG_RETURN (rval);
03374 }
03375 
03376 int dbl_ILLlib_getintflags (
03377   dbl_lpinfo * lp,
03378   int *intflags)
03379 {
03380   int j, nstruct, rval = 0;
03381   dbl_ILLlpdata *qslp;
03382 
03383   if (!lp)
03384   {
03385     fprintf (stderr, "dbl_ILLlib_getintflags called without an LP\n");
03386     rval = 1;
03387     ILL_CLEANUP;
03388   }
03389 
03390   qslp = lp->O;
03391   nstruct = qslp->nstruct;
03392 
03393   if (qslp->intmarker == 0)
03394   {
03395     for (j = 0; j < nstruct; j++)
03396     {
03397       intflags[j] = 0;
03398     }
03399   }
03400   else
03401   {
03402     for (j = 0; j < nstruct; j++)
03403     {
03404       if (qslp->intmarker[j])
03405       {
03406         intflags[j] = 1;
03407       }
03408       else
03409       {
03410         intflags[j] = 0;
03411       }
03412     }
03413   }
03414 
03415 CLEANUP:
03416 
03417   EG_RETURN (rval);
03418 }
03419 
03420 int dbl_ILLlib_colnames (
03421   dbl_lpinfo * lp,
03422   char **colnames)
03423 {
03424   dbl_ILLlpdata *qslp;
03425   int nstruct, len, i, ccount = 0;
03426   int rval = 0;
03427 
03428   if (!lp)
03429   {
03430     fprintf (stderr, "dbl_ILLlib_colnames called without an LP\n");
03431     rval = 1;
03432     ILL_CLEANUP;
03433   }
03434   if (!colnames)
03435   {
03436     fprintf (stderr, "dbl_ILLlib_colnames called with NULL colnames\n");
03437     rval = 1;
03438     ILL_CLEANUP;
03439   }
03440 
03441   qslp = lp->O;
03442   nstruct = qslp->nstruct;
03443 
03444   if (qslp->colnames == 0)
03445   {
03446     fprintf (stderr, "LP does not have colnames assigned\n");
03447     rval = 1;
03448     ILL_CLEANUP;
03449   }
03450 
03451   for (i = 0; i < nstruct; i++)
03452   {
03453     len = strlen (qslp->colnames[i]) + 1;
03454     ILL_SAFE_MALLOC (colnames[i], len, char);
03455 
03456     strcpy (colnames[i], qslp->colnames[i]);
03457     ccount++;
03458   }
03459 
03460 
03461 CLEANUP:
03462 
03463   if (rval)
03464   {
03465     for (i = 0; i < ccount; i++)
03466     {
03467       ILL_IFFREE (colnames[i], char);
03468     }
03469   }
03470 
03471   EG_RETURN (rval);
03472 }
03473 
03474 static int dbl_reset_colindex (
03475   dbl_lpinfo * lp)
03476 {
03477   int rval = 0;
03478   int test;
03479   dbl_ILLlpdata *qslp = lp->O;
03480 
03481   test = ILLsymboltab_index_ok (&qslp->coltab);
03482   if (!test)
03483   {
03484     rval = ILLsymboltab_index_reset (&qslp->coltab, qslp->nstruct,
03485                                      qslp->colnames);
03486     CHECKRVALG (rval, CLEANUP);
03487   }
03488 
03489 CLEANUP:
03490 
03491   EG_RETURN (rval);
03492 }
03493 
03494 static int dbl_reset_rowindex (
03495   dbl_lpinfo * lp)
03496 {
03497   int rval = 0;
03498   int test;
03499   dbl_ILLlpdata *qslp = lp->O;
03500 
03501   test = ILLsymboltab_index_ok (&qslp->rowtab);
03502   if (!test)
03503   {
03504     rval = ILLsymboltab_index_reset (&qslp->rowtab, qslp->nrows,
03505                                      qslp->rownames);
03506     CHECKRVALG (rval, CLEANUP);
03507   }
03508 
03509 CLEANUP:
03510 
03511   EG_RETURN (rval);
03512 }
03513 
03514 int dbl_ILLlib_colindex (
03515   dbl_lpinfo * lp,
03516   const char *name,
03517   int *colindex)
03518 {
03519   int rval = 0;
03520   dbl_ILLlpdata *qslp;
03521 
03522   *colindex = -1;
03523 
03524   if (!lp)
03525   {
03526     fprintf (stderr, "dbl_ILLlib_colindex called without an LP\n");
03527     rval = 1;
03528     ILL_CLEANUP;
03529   }
03530 
03531   qslp = lp->O;
03532 
03533   rval = dbl_reset_colindex (lp);
03534   CHECKRVALG (rval, CLEANUP);
03535 
03536   rval = ILLsymboltab_getindex (&qslp->coltab, name, colindex);
03537   CHECKRVALG (rval, CLEANUP);
03538 
03539 CLEANUP:
03540 
03541   EG_RETURN (rval);
03542 }
03543 
03544 int dbl_ILLlib_rowindex (
03545   dbl_lpinfo * lp,
03546   const char *name,
03547   int *rowindex)
03548 {
03549   int rval = 0;
03550   dbl_ILLlpdata *qslp;
03551 
03552   *rowindex = -1;
03553 
03554   if (!lp)
03555   {
03556     fprintf (stderr, "dbl_ILLlib_rowindex called without an LP\n");
03557     rval = 1;
03558     ILL_CLEANUP;
03559   }
03560 
03561   qslp = lp->O;
03562 
03563   rval = dbl_reset_rowindex (lp);
03564   CHECKRVALG (rval, CLEANUP);
03565 
03566   rval = ILLsymboltab_getindex (&qslp->rowtab, name, rowindex);
03567   CHECKRVALG (rval, CLEANUP);
03568 
03569 CLEANUP:
03570 
03571   EG_RETURN (rval);
03572 }
03573 
03574 int dbl_ILLlib_getbasis (
03575   dbl_lpinfo * lp,
03576   char *cstat,
03577   char *rstat)
03578 {
03579   int rval = 0;
03580   int i, j, nrows;
03581   dbl_ILLlpdata *qslp;
03582 
03583   if (!lp)
03584   {
03585     fprintf (stderr, "dbl_ILLlib_getbasis called without an LP\n");
03586     rval = 1;
03587     ILL_CLEANUP;
03588   }
03589 
03590   if (lp->basisid == -1)
03591   {
03592     fprintf (stderr, "dbl_ILLlib_getbasis called with modifed LP\n");
03593     rval = 1;
03594     ILL_CLEANUP;
03595   }
03596 
03597   nrows = lp->O->nrows;
03598   qslp = lp->O;
03599 
03600   for (i = 0; i < qslp->nstruct; i++)
03601   {
03602     j = qslp->structmap[i];
03603     switch (lp->vstat[j])
03604     {
03605     case STAT_BASIC:
03606       cstat[i] = QS_COL_BSTAT_BASIC;
03607       break;
03608     case STAT_LOWER:
03609       cstat[i] = QS_COL_BSTAT_LOWER;
03610       break;
03611     case STAT_UPPER:
03612       cstat[i] = QS_COL_BSTAT_UPPER;
03613       break;
03614     case STAT_ZERO:
03615       cstat[i] = QS_COL_BSTAT_FREE;
03616       break;
03617     default:
03618       fprintf (stderr, "unknown vstat in dbl_ILLlib_getbasis: %d\n", lp->vstat[j]);
03619       rval = 1;
03620       ILL_CLEANUP;
03621     }
03622   }
03623 
03624   for (i = 0; i < nrows; i++)
03625   {
03626     j = qslp->rowmap[i];
03627     if (qslp->rangeval && dbl_EGlpNumIsNeqqZero (qslp->rangeval[i]))
03628     {
03629       switch (lp->vstat[j])
03630       {
03631       case STAT_BASIC:
03632         rstat[i] = QS_ROW_BSTAT_BASIC;
03633         break;
03634       case STAT_LOWER:
03635         rstat[i] = QS_ROW_BSTAT_LOWER;
03636         break;
03637       case STAT_UPPER:
03638         rstat[i] = QS_ROW_BSTAT_UPPER;
03639         break;
03640       default:
03641         fprintf (stderr, "unknown vstat in dbl_ILLlib_getbasis 2\n");
03642         rval = 1;
03643         ILL_CLEANUP;
03644       }
03645     }
03646     else
03647     {
03648       switch (lp->vstat[j])
03649       {
03650       case STAT_BASIC:
03651         rstat[i] = QS_ROW_BSTAT_BASIC;
03652         break;
03653       case STAT_UPPER:
03654       case STAT_LOWER:
03655         rstat[i] = QS_ROW_BSTAT_LOWER;
03656         break;
03657       default:
03658         fprintf (stderr, "unknown vstat in dbl_ILLlib_getbasis 3: %d, %d\n",
03659                  i, lp->vstat[j]);
03660         rval = 1;
03661         ILL_CLEANUP;
03662       }
03663     }
03664   }
03665 
03666 CLEANUP:
03667 
03668   EG_RETURN (rval);
03669 }
03670 
03671 int dbl_ILLlib_loadbasis (
03672   dbl_ILLlp_basis * B,
03673   int nstruct,
03674   int nrows,
03675   char *cstat,
03676   char *rstat)
03677 {
03678   int i;
03679   int rval = 0;
03680 
03681   dbl_ILLlp_basis_init (B);
03682 
03683   if (!cstat || !rstat)
03684   {
03685     rval = 1;
03686     CHECKRVALG (rval, CLEANUP);
03687   }
03688 
03689   rval = dbl_ILLlp_basis_alloc (B, nstruct, nrows);
03690   CHECKRVALG (rval, CLEANUP);
03691 
03692   for (i = 0; i < nstruct; i++)
03693   {
03694     B->cstat[i] = cstat[i];
03695   }
03696   for (i = 0; i < nrows; i++)
03697   {
03698     B->rstat[i] = rstat[i];
03699   }
03700 
03701 CLEANUP:
03702 
03703   EG_RETURN (rval);
03704 }
03705 
03706 #define dbl_READ_BASIS_XL 0
03707 #define dbl_READ_BASIS_XU 1
03708 #define dbl_READ_BASIS_LL 2
03709 #define dbl_READ_BASIS_UL 3
03710 
03711 int dbl_ILLlib_readbasis (
03712   dbl_lpinfo * lp,
03713   dbl_ILLlp_basis * B,
03714   const char *dbl_fname)
03715 {
03716   int rval = 0;
03717   dbl_ILLlpdata *qslp = lp->O;
03718   int nstruct = qslp->nstruct;
03719   int nrows = qslp->nrows;
03720   int i, j, end = 0, sec, havename = 0;
03721   int rowtype, row, col;
03722   char *bname = 0;
03723   FILE *file_in = 0;
03724   dbl_ILLread_mps_state state;
03725   dbl_qsline_reader *in = NULL;
03726 
03727   dbl_ILLlp_basis_init (B);
03728 
03729   ILL_SAFE_MALLOC (B->cstat, qslp->nstruct, char);
03730   ILL_SAFE_MALLOC (B->rstat, qslp->nrows, char);
03731 
03732   B->nstruct = nstruct;
03733   B->nrows = nrows;
03734 
03735   for (j = 0; j < nstruct; j++)
03736   {
03737     B->cstat[j] = QS_COL_BSTAT_LOWER;
03738   }
03739   for (i = 0; i < nrows; i++)
03740   {
03741     B->rstat[i] = QS_ROW_BSTAT_BASIC;
03742   }
03743 
03744   file_in = fopen (dbl_fname, "r");
03745   if (file_in == 0)
03746   {
03747     fprintf (stderr, "unable to open %s for reading\n", dbl_fname);
03748     rval = 1;
03749     ILL_CLEANUP;
03750   }
03751 
03752   in = dbl_ILLline_reader_new ((dbl_qsread_line_fct) fgets, file_in);
03753   rval = dbl_ILLmps_state_init (&state, in, dbl_fname);
03754   CHECKRVALG (rval, CLEANUP);
03755 
03756   while (dbl_ILLmps_next_line (&state) == 0)
03757   {
03758     if (dbl_ILLmps_empty_key (&state))
03759     {
03760 
03761       /* Get the XL XU LL UL line */
03762 
03763       if (!havename)
03764       {
03765         rval = dbl_ILLmps_error (&state, "BASIS data before NAME\n");
03766         ILL_CLEANUP;
03767       }
03768 
03769       if (!strcmp (state.field, "XL"))
03770       {
03771         rowtype = dbl_READ_BASIS_XL;
03772       }
03773       else if (!strcmp (state.field, "XU"))
03774       {
03775         rowtype = dbl_READ_BASIS_XU;
03776       }
03777       else if (!strcmp (state.field, "LL"))
03778       {
03779         rowtype = dbl_READ_BASIS_LL;
03780       }
03781       else if (!strcmp (state.field, "UL"))
03782       {
03783         rowtype = dbl_READ_BASIS_UL;
03784       }
03785       else
03786       {
03787         rval = dbl_ILLmps_error (&state, "BASIS \"%s\" is invalid\n", state.field);
03788         ILL_CLEANUP;
03789       }
03790 
03791       if (dbl_ILLmps_next_field (&state) == 0)
03792       {
03793 
03794         rval = dbl_ILLlib_colindex (lp, (const char *) state.field, &col);
03795         CHECKRVALG (rval, CLEANUP);
03796         if (col == -1)
03797         {
03798           rval = dbl_ILLmps_error (&state, "BASIS col not in LP\n");
03799           ILL_CLEANUP;
03800         }
03801 
03802         if (rowtype == dbl_READ_BASIS_XL || rowtype == dbl_READ_BASIS_XU)
03803         {
03804           if (dbl_ILLmps_next_field (&state) == 0)
03805           {
03806             rval = dbl_ILLlib_rowindex (lp, (const char *) state.field, &row);
03807             CHECKRVALG (rval, CLEANUP);
03808             if (row == -1)
03809             {
03810               rval = dbl_ILLmps_error (&state, "BASIS row not in LP\n");
03811               ILL_CLEANUP;
03812             }
03813             if (rowtype == dbl_READ_BASIS_XL)
03814             {
03815               B->cstat[col] = QS_COL_BSTAT_BASIC;
03816               B->rstat[row] = QS_ROW_BSTAT_LOWER;
03817 
03818             }
03819             else
03820             {
03821               B->cstat[col] = QS_COL_BSTAT_BASIC;
03822               B->rstat[row] = QS_ROW_BSTAT_UPPER;
03823             }
03824           }
03825           else
03826           {
03827             rval = dbl_ILLmps_error (&state, "BASIS line needs row and column\n");
03828             ILL_CLEANUP;
03829           }
03830         }
03831         else
03832         {
03833           if (rowtype == dbl_READ_BASIS_LL)
03834           {
03835             B->cstat[col] = QS_COL_BSTAT_LOWER;
03836           }
03837           else
03838           {
03839             B->cstat[col] = QS_COL_BSTAT_UPPER;
03840           }
03841         }
03842       }
03843       else
03844       {
03845         rval = dbl_ILLmps_error (&state, "BASIS line has no row/column\n");
03846         ILL_CLEANUP;
03847       }
03848     }
03849     else
03850     {
03851       /* found a section indicator in col 1 */
03852       if (!strcmp (state.key, dbl_ILLmps_section_name[ILL_MPS_ENDATA]))
03853       {
03854         end = 1;
03855         break;                  /* done reading */
03856       }
03857 
03858       sec = dbl_ILLutil_index (dbl_ILLmps_section_name, state.key);
03859       if (sec < 0 || sec != ILL_MPS_NAME)
03860       {
03861         rval = dbl_ILLmps_error (&state, "BASIS \"%s\" is not a key\n", state.key);
03862         ILL_CLEANUP;
03863       }
03864 
03865       if (havename)
03866       {
03867         rval = dbl_ILLmps_error (&state, "BASIS two name sections\n");
03868         ILL_CLEANUP;
03869       }
03870 
03871       havename = 1;
03872 
03873       if (dbl_ILLmps_empty_field (&state))
03874       {
03875         dbl_ILLmps_warn (&state, "BASIS blank NAME.");
03876       }
03877       else
03878       {
03879         dbl_ILL_UTIL_STR (bname, state.field);
03880         printf ("Basis Name: %s\n", bname);
03881         fflush (stdout);
03882         if (strcmp (bname, qslp->probname))
03883         {
03884           dbl_ILLmps_warn (&state, "BASIS name does not match LP.");
03885         }
03886       }
03887     }
03888   }
03889 
03890   if (!end)
03891   {
03892     dbl_ILLmps_warn (&state, "Missing ENDATA in basis file.");
03893   }
03894   if (!dbl_ILLmps_next_line (&state))
03895   {
03896     dbl_ILLmps_warn (&state, "Ignoring text after ENDATA.");
03897   }
03898 
03899   if (!havename)
03900   {
03901     rval = dbl_ILLmps_error (&state, "BASIS no name section\n");
03902     ILL_CLEANUP;
03903   }
03904 
03905   /* Correct the free variables */
03906 
03907   for (j = 0; j < nstruct; j++)
03908   {
03909     col = lp->O->structmap[j];
03910     if (dbl_EGlpNumIsEqqual (qslp->lower[col], dbl_ILL_MINDOUBLE) &&
03911         dbl_EGlpNumIsEqqual (qslp->upper[col], dbl_ILL_MAXDOUBLE) &&
03912         B->cstat[j] == QS_COL_BSTAT_LOWER)
03913     {
03914       B->cstat[j] = QS_COL_BSTAT_FREE;
03915     }
03916   }
03917 
03918 CLEANUP:
03919 
03920   if (file_in)
03921     fclose (file_in);
03922   dbl_ILLline_reader_free (in);
03923 
03924   if (rval)
03925   {
03926     dbl_ILLlp_basis_free (B);
03927   }
03928   ILL_IFFREE (bname, char);
03929 
03930   EG_RETURN (rval);
03931 }
03932 
03933 int dbl_ILLlib_writebasis (
03934   dbl_lpinfo * lp,
03935   dbl_ILLlp_basis * B,
03936   const char *dbl_fname)
03937 {
03938   int rval = 0;
03939   FILE *out = 0;
03940   char *cstat = 0;
03941   char *rstat = 0;
03942   dbl_ILLlpdata *qslp;
03943   int i, j, nstruct, nrows;
03944 
03945   /* NOTE: non-basic free variables are encoded as non-basic at lower */
03946 
03947   if (!lp)
03948   {
03949     fprintf (stderr, "dbl_ILLlib_writebasis called without an LP\n");
03950     rval = 1;
03951     ILL_CLEANUP;
03952   }
03953   if (!B && lp->basisid == -1)
03954   {
03955     fprintf (stderr, "dbl_ILLlib_writebasis called with unsolved LP\n");
03956     rval = 1;
03957     ILL_CLEANUP;
03958   }
03959 
03960   qslp = lp->O;
03961   nstruct = qslp->nstruct;
03962   nrows = qslp->nrows;
03963 
03964   out = fopen (dbl_fname, "w");
03965   if (out == 0)
03966   {
03967     fprintf (stderr, "unable to open %s for writing\n", dbl_fname);
03968     rval = 1;
03969     ILL_CLEANUP;
03970   }
03971 
03972   if (B)
03973   {
03974     cstat = B->cstat;
03975     rstat = B->rstat;
03976   }
03977   else
03978   {
03979     ILL_SAFE_MALLOC (cstat, nstruct, char);
03980     ILL_SAFE_MALLOC (rstat, nrows, char);
03981 
03982     rval = dbl_ILLlib_getbasis (lp, cstat, rstat);
03983     CHECKRVALG (rval, CLEANUP);
03984   }
03985 
03986   fprintf (out, "NAME    %s\n", qslp->probname);
03987 
03988   /* Pick out the non-basic rows and find a matching basic column */
03989 
03990   i = 0;
03991   j = 0;
03992   do
03993   {
03994     while (i < nrows && rstat[i] == QS_ROW_BSTAT_BASIC)
03995     {
03996       i++;
03997     }
03998     if (i < nrows)
03999     {
04000       while (j < nstruct && cstat[j] != QS_COL_BSTAT_BASIC)
04001       {
04002         j++;
04003       }
04004       if (j == nstruct)
04005       {
04006         /* No basic column to match the non-basic row */
04007         fprintf (stderr, "No basic column to match non-basic row %d\n", i);
04008         rval = 1;
04009         goto CLEANUP;
04010       }
04011 
04012       if (rstat[i] == QS_ROW_BSTAT_LOWER)
04013       {
04014         fprintf (out, " XL %s %s\n", qslp->colnames[j], qslp->rownames[i]);
04015       }
04016       else
04017       {
04018         fprintf (out, " XU %s %s\n", qslp->colnames[j], qslp->rownames[i]);
04019       }
04020       i++;
04021       j++;
04022     }
04023   } while (i < nrows);
04024 
04025   /* Now go through and output the non-basic cols at upper bound */
04026 
04027   for (j = 0; j < nstruct; j++)
04028   {
04029     if (cstat[j] == QS_COL_BSTAT_UPPER)
04030     {
04031       fprintf (out, " UL %s\n", qslp->colnames[j]);
04032     }
04033   }
04034 
04035   fprintf (out, "ENDATA\n");
04036 
04037 CLEANUP:
04038 
04039   if (out)
04040     fclose (out);
04041   if (!B)
04042   {
04043     ILL_IFFREE (cstat, char);
04044     ILL_IFFREE (rstat, char);
04045   }
04046   EG_RETURN (rval);
04047 }
04048 
04049 int dbl_ILLlib_getrownorms (
04050   dbl_lpinfo * lp,
04051   dbl_price_info * pinf,
04052   double * rownorms)
04053 {
04054   int rval = 0;
04055   int i, j, basic = 0;
04056   dbl_ILLlpdata *qslp = lp->O;
04057   int nstruct = lp->O->nstruct;
04058   int nrows = lp->O->nrows;
04059 
04060   dbl_check_pinf (pinf, &rval);
04061   if (rval)
04062   {
04063 /*
04064         fprintf (stderr, "dual steepest dbl_edge norms not available\n");
04065 */
04066     ILL_CLEANUP;
04067   }
04068 
04069   for (i = 0; i < nstruct; i++)
04070   {
04071     j = qslp->structmap[i];
04072     if (lp->vstat[j] == STAT_BASIC)
04073     {
04074       dbl_EGlpNumCopy (rownorms[basic++], pinf->dsinfo.norms[lp->vindex[j]]);
04075     }
04076   }
04077   for (i = 0; i < nrows; i++)
04078   {
04079     j = qslp->rowmap[i];
04080     if (lp->vstat[j] == STAT_BASIC)
04081     {
04082       dbl_EGlpNumCopy (rownorms[basic++], pinf->dsinfo.norms[lp->vindex[j]]);
04083     }
04084   }
04085 
04086   if (basic != nrows)
04087   {
04088     fprintf (stderr, "error in dbl_ILLlib_getrownorms\n");
04089     rval = 1;
04090     ILL_CLEANUP;
04091   }
04092 
04093 CLEANUP:
04094 
04095 /*
04096     EG_RETURN(rval);
04097 */
04098   return rval;                  /* Don't want error message */
04099 }
04100 
04101 int dbl_ILLlib_loadrownorms (
04102   dbl_lpinfo * lp,
04103   dbl_price_info * pinf,
04104   double * rownorms)
04105 {
04106   int rval = 0;
04107 
04108   rval = dbl_ILLprice_load_rownorms (lp, rownorms, pinf);
04109   CHECKRVALG (rval, CLEANUP);
04110 
04111 CLEANUP:
04112 
04113   EG_RETURN (rval);
04114 }
04115 
04116 int dbl_ILLlib_recompute_rownorms (
04117   dbl_lpinfo * lp,
04118   dbl_price_info * pinf)
04119 {
04120   int rval = 0;
04121 
04122   rval = dbl_ILLprice_build_pricing_info (lp, pinf, DUAL_PHASEII);
04123   CHECKRVALG (rval, CLEANUP);
04124 
04125 CLEANUP:
04126 
04127   EG_RETURN (rval);
04128 }
04129 
04130 int dbl_ILLlib_iter (
04131   dbl_lpinfo * lp)
04132 {
04133   int iter = 0;
04134 
04135   if (lp && lp->cnts)
04136   {
04137     iter = lp->cnts->pI_iter + lp->cnts->pII_iter +
04138       lp->cnts->dI_iter + lp->cnts->dII_iter;
04139   }
04140 
04141   return iter;
04142 }
04143 
04144 //#define dbl_PRINT_TOL 0.000001
04145 #define dbl_PRINT_TOL dbl_PFEAS_TOLER
04146 
04147 int dbl_ILLlib_print_x (
04148   FILE * fd,
04149   dbl_lpinfo * lp,
04150   dbl_ILLlp_cache * C,
04151   double * x,
04152   int nonZerosOnly)
04153 {
04154   int rval = 0;
04155   int j;
04156   dbl_ILLlpdata *qslp = lp->O;
04157   double *dx, *myx = 0;
04158   char *strtmp;
04159 
04160   /* If x is not specified, grab the LP solution */
04161 
04162   if (!x)
04163   {
04164     myx = dbl_EGlpNumAllocArray (lp->ncols);
04165     rval = dbl_ILLlib_get_x (lp, C, myx);
04166     CHECKRVALG (rval, CLEANUP);
04167     dx = myx;
04168   }
04169   else
04170   {
04171     dx = x;
04172   }
04173 
04174   fprintf (fd, "Solution Values\n");
04175   for (j = 0; j < qslp->nstruct; j++)
04176   {
04177     /*if (!nonZerosOnly || dx[j] > dbl_PRINT_TOL || dx[j] < -dbl_PRINT_TOL) */
04178     if (!nonZerosOnly || dbl_EGlpNumIsNeqZero (dx[j], dbl_PRINT_TOL))
04179     {
04180       strtmp = dbl_EGlpNumGetStr (dx[j]);
04181       ILL_FAILfalse (qslp->colnames[j] != NULL, "no NULL names PLEASE!");
04182       fprintf (fd, "%s = %s\n", qslp->colnames[j], strtmp);
04183       fflush (fd);
04184       EGfree (strtmp);
04185     }
04186   }
04187 
04188 CLEANUP:
04189   dbl_EGlpNumFreeArray (myx);
04190   EG_RETURN (rval);
04191 }
04192 
04193 int dbl_ILLlib_findName (
04194   dbl_ILLlpdata * qslp,
04195   int forRow,
04196   const char *name,
04197   int id,
04198   char buf[ILL_namebufsize])
04199 {
04200   ILLsymboltab *tab;
04201   const char *mode;
04202   const char *p1, *p2;
04203   int sind, rval = 0;
04204 
04205   id++;
04206   tab = (forRow) ? &qslp->rowtab : &qslp->coltab;
04207   if (tab->tablesize == 0)
04208     ILLsymboltab_create (tab, 100);
04209   p1 = (forRow) ? "c" : "x";
04210   p2 = (forRow) ? "c_" : "x_";
04211   mode = (forRow) ? "row" : "column";
04212   if (name == 0)
04213   {
04214     ILLsymboltab_unique_name (tab, id, p1, buf);
04215     /*
04216      * fprintf(stderr, "Generating %s name \"%s\".\n", mode, buf); 
04217      */
04218   }
04219   else
04220   {
04221     strcpy (buf, name);
04222   }
04223   if (!ILLsymboltab_lookup (tab, buf, &sind))
04224   {
04225     rval = ILLsymboltab_uname (&qslp->rowtab, buf, p1, p2);
04226     if (name != NULL)
04227     {
04228       fprintf (stderr, "Changing %s name \"%s\" to \"%s\".\n", mode, name, buf);
04229     }
04230     CHECKRVALG (rval, CLEANUP);
04231   }
04232 CLEANUP:
04233   EG_RETURN (rval);
04234 }
04235 
04236 int dbl_ILLwrite_lp_file (
04237   dbl_ILLlpdata * lp,
04238   FILE * out,
04239   dbl_qserror_collector * c)
04240 {
04241   int rval = 0;
04242   qsstring_reporter rep;
04243 
04244   ILLstring_reporter_copy (&rep, &lp->reporter);
04245   ILLstring_reporter_init (&lp->reporter, (qsreport_string_fct) fprintf, out);
04246   rval = dbl_ILLwrite_lp (lp, c);
04247   ILLstring_reporter_copy (&lp->reporter, &rep);
04248   return rval;
04249 }
04250 
04251 static void dbl_check_pinf (
04252   dbl_price_info * pinf,
04253   int *it_exists)
04254 {
04255   if (!pinf || pinf->dI_price != QS_PRICE_DSTEEP ||
04256       pinf->dII_price != QS_PRICE_DSTEEP || pinf->dsinfo.norms == 0)
04257   {
04258     *it_exists = 1;
04259   }
04260   else
04261   {
04262     *it_exists = 0;
04263   }
04264 }
04265 
04266 #if 0
04267 static int test_matrix (
04268   dbl_ILLmatrix * A)
04269 {
04270   int rval = 0;
04271   int i, j, k;
04272   int ncols = A->matcols;
04273   int nrows = A->matrows;
04274   int matsize = A->matsize;
04275   int *mbeg = A->matbeg;
04276   int *mcnt = A->matcnt;
04277   int *mind = A->matind;
04278   int *tempi = 0;
04279 
04280 
04281   if (matsize == 0)
04282     ILL_CLEANUP;
04283 
04284   ILL_SAFE_MALLOC (tempi, matsize, int);
04285 
04286   for (i = 0; i < matsize; i++)
04287     tempi[i] = 0;
04288 
04289   for (i = 0; i < ncols; i++)
04290   {
04291     for (j = 0; j < mcnt[i]; j++)
04292     {
04293       k = mind[mbeg[i] + j];
04294       if (k < 0 || k >= nrows)
04295       {
04296         printf ("ERROR IN MATRIX: %d\n", k);
04297         printf ("ncols = %d, bad col = %d\n", ncols, i);
04298         printf ("bad cnt = %d, bad index = %d\n", mcnt[i], mbeg[i] + j);
04299         printf ("matcolsize = %d, matsize = %d\n", A->matcolsize, A->matsize);
04300         rval = 1;
04301         ILL_CLEANUP;
04302       }
04303       if (tempi[mbeg[i] + j] != 0)
04304       {
04305         printf ("ERROR: over written matrix\n");
04306         printf ("ncols = %d, bad col = %d\n", ncols, i);
04307         printf ("nrows = %d\n", nrows);
04308         printf ("bad cnt = %d, bad index = %d\n", mcnt[i], mbeg[i] + j);
04309         rval = 1;
04310         ILL_CLEANUP;
04311       }
04312       else
04313       {
04314         tempi[mbeg[i] + j] = 1;
04315       }
04316     }
04317   }
04318 
04319   for (i = A->matsize - A->matfree; i < A->matsize; i++)
04320   {
04321     if (tempi[i] != 0)
04322     {
04323       printf ("ERROR: free space is being used\n");
04324       rval = 1;
04325       ILL_CLEANUP;
04326     }
04327   }
04328 
04329 CLEANUP:
04330 
04331   ILL_IFFREE (tempi, int);
04332 
04333   EG_RETURN (rval);
04334 }
04335 #endif

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