dbl_basis.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_basis.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
00024 static int TRACE = 0;
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <math.h>
00029 #include "config.h"
00030 #include "dbl_sortrus.h"
00031 #include "dbl_iqsutil.h"
00032 #include "dbl_lpdefs.h"
00033 #include "dbl_qstruct.h"
00034 #include "dbl_qsopt.h"
00035 #include "dbl_basis.h"
00036 #include "dbl_fct.h"
00037 #include "dbl_lp.h"
00038 #include "dbl_lib.h"
00039 #ifdef USEDMALLOC
00040 #include "dmalloc.h"
00041 #endif
00042 
00043 //#define DJZERO_TOLER dbl_PFEAS_TOLER
00044 #define dbl_BASIS_STATS 0
00045 //#define dbl_BASIS_DEBUG 10
00046 #define dbl_BASIS_DEBUG 0
00047 
00048 void dbl_ILLbasis_init_vardata (
00049   dbl_var_data * vd)
00050 {
00051   memset (vd, 0, sizeof (dbl_var_data));
00052   dbl_EGlpNumInitVar (vd->cmax);
00053 }
00054 
00055 void dbl_ILLbasis_clear_vardata (
00056   dbl_var_data * vd)
00057 {
00058   dbl_EGlpNumClearVar (vd->cmax);
00059   memset (vd, 0, sizeof (dbl_var_data));
00060 }
00061 
00062 static void dbl_get_var_info (
00063   dbl_lpinfo * lp,
00064   dbl_var_data * v);
00065 
00066 static int dbl_init_slack_basis (
00067   dbl_lpinfo * lp,
00068   int *vstat,
00069   int *irow,
00070   int *rrow,
00071   int *unitcol,
00072   int *icol,
00073   int *rcol),
00074   dbl_get_initial_basis1 (
00075   dbl_lpinfo * lp,
00076   int *vstat),
00077   dbl_get_initial_basis2 (
00078   dbl_lpinfo * lp,
00079   int *vstat),
00080   dbl_set_basis_indices (
00081   dbl_lpinfo * lp,
00082   int *vstat),
00083   dbl_choose_basis (
00084   int algorithm,
00085   double pinf1,
00086   double dinf1,
00087   double pinf2,
00088   double dinf2);
00089 
00090 void dbl_ILLbasis_init_basisinfo (
00091   dbl_lpinfo * lp)
00092 {
00093   lp->baz = 0;
00094   lp->nbaz = 0;
00095   lp->vstat = 0;
00096   lp->vindex = 0;
00097   lp->f = 0;
00098 }
00099 
00100 void dbl_ILLbasis_free_basisinfo (
00101   dbl_lpinfo * lp)
00102 {
00103   ILL_IFFREE (lp->baz, int);
00104   ILL_IFFREE (lp->nbaz, int);
00105   ILL_IFFREE (lp->vstat, int);
00106   ILL_IFFREE (lp->vindex, int);
00107 
00108   if (lp->f)
00109   {
00110     dbl_ILLfactor_free_factor_work (lp->f);
00111     dbl_EGlpNumClearVar (lp->f->fzero_tol);
00112     dbl_EGlpNumClearVar (lp->f->szero_tol);
00113     dbl_EGlpNumClearVar (lp->f->partial_tol);
00114     dbl_EGlpNumClearVar (lp->f->maxelem_orig);
00115     dbl_EGlpNumClearVar (lp->f->maxelem_factor);
00116     dbl_EGlpNumClearVar (lp->f->maxelem_cur);
00117     dbl_EGlpNumClearVar (lp->f->partial_cur);
00118     ILL_IFFREE (lp->f, dbl_factor_work);
00119   }
00120 }
00121 
00122 int dbl_ILLbasis_build_basisinfo (
00123   dbl_lpinfo * lp)
00124 {
00125   int rval = 0;
00126 
00127   ILL_SAFE_MALLOC (lp->baz, lp->O->nrows, int);
00128   ILL_SAFE_MALLOC (lp->nbaz, lp->O->ncols, int);
00129   ILL_SAFE_MALLOC (lp->vstat, lp->O->ncols, int);
00130   ILL_SAFE_MALLOC (lp->vindex, lp->O->ncols, int);
00131 
00132   lp->fbasisid = -1;
00133 
00134 CLEANUP:
00135   if (rval)
00136     dbl_ILLbasis_free_basisinfo (lp);
00137   EG_RETURN (rval);
00138 }
00139 
00140 int dbl_ILLbasis_load (
00141   dbl_lpinfo * lp,
00142   dbl_ILLlp_basis * B)
00143 {
00144   int rval = 0;
00145   char *cstat = B->cstat;
00146   char *rstat = B->rstat;
00147   int *structmap = lp->O->structmap;
00148   int *rowmap = lp->O->rowmap;
00149   char *sense = lp->O->sense;
00150   int i, j, ncols = lp->O->ncols, nrows = lp->O->nrows, nstruct = lp->O->nstruct;
00151   int basic = 0, nonbasic = 0;
00152 
00153   dbl_ILLbasis_free_basisinfo (lp);
00154   dbl_ILLbasis_init_basisinfo (lp);
00155   rval = dbl_ILLbasis_build_basisinfo (lp);
00156   CHECKRVALG (rval, CLEANUP);
00157 
00158   for (i = 0; i < nstruct; i++)
00159   {
00160     j = structmap[i];
00161     if (cstat[i] == QS_COL_BSTAT_BASIC)
00162     {
00163       lp->vstat[j] = STAT_BASIC;
00164       lp->baz[basic] = j;
00165       lp->vindex[j] = basic;
00166       basic++;
00167     }
00168     else
00169     {
00170       lp->nbaz[nonbasic] = j;
00171       lp->vindex[j] = nonbasic;
00172       nonbasic++;
00173       switch (cstat[i])
00174       {
00175       case QS_COL_BSTAT_LOWER:
00176         lp->vstat[j] = STAT_LOWER;
00177         break;
00178       case QS_COL_BSTAT_UPPER:
00179         lp->vstat[j] = STAT_UPPER;
00180         break;
00181       case QS_COL_BSTAT_FREE:
00182         lp->vstat[j] = STAT_ZERO;
00183         break;
00184       default:
00185         fprintf (stderr, "unknown col basis stat 1: %c\n", cstat[i]);
00186         rval = 1;
00187         goto CLEANUP;
00188       }
00189     }
00190   }
00191 
00192   for (i = 0; i < nrows; i++)
00193   {
00194     j = rowmap[i];
00195     if (sense[i] == 'R')
00196     {
00197       if (rstat[i] == QS_ROW_BSTAT_BASIC)
00198       {
00199         lp->vstat[j] = STAT_BASIC;
00200         lp->baz[basic] = j;
00201         lp->vindex[j] = basic;
00202         basic++;
00203       }
00204       else
00205       {
00206         lp->nbaz[nonbasic] = j;
00207         lp->vindex[j] = nonbasic;
00208         nonbasic++;
00209         switch (rstat[i])
00210         {
00211         case QS_ROW_BSTAT_LOWER:
00212           lp->vstat[j] = STAT_LOWER;
00213           break;
00214         case QS_ROW_BSTAT_UPPER:
00215           lp->vstat[j] = STAT_UPPER;
00216           break;
00217         default:
00218           fprintf (stderr, "unknown range basis stat 2\n");
00219           rval = 1;
00220           goto CLEANUP;
00221         }
00222       }
00223     }
00224     else
00225     {
00226       switch (rstat[i])
00227       {
00228       case QS_ROW_BSTAT_BASIC:
00229         lp->vstat[j] = STAT_BASIC;
00230         lp->baz[basic] = j;
00231         lp->vindex[j] = basic;
00232         basic++;
00233         break;
00234       case QS_ROW_BSTAT_LOWER:
00235         lp->vstat[j] = STAT_LOWER;
00236         lp->nbaz[nonbasic] = j;
00237         lp->vindex[j] = nonbasic;
00238         nonbasic++;
00239         break;
00240       default:
00241         fprintf (stderr, "unknown row basis stat 3\n");
00242         rval = 1;
00243         goto CLEANUP;
00244       }
00245     }
00246   }
00247 
00248   if (basic + nonbasic != ncols)
00249   {
00250     fprintf (stderr, "error in counts in ILLopt_load_basis\n");
00251     rval = 1;
00252     goto CLEANUP;
00253   }
00254 
00255   if (lp->fbasisid != 0)
00256     lp->basisid = 0;
00257   else
00258     lp->basisid = 1;
00259 
00260 CLEANUP:
00261 
00262   EG_RETURN (rval);
00263 }
00264 
00265 int dbl_ILLbasis_tableau_row (
00266   dbl_lpinfo * lp,
00267   int row,
00268   double * brow,
00269   double * trow,
00270   double * rhs,
00271   int strict)
00272 {
00273   int rval = 0;
00274   int i;
00275   int singular = 0;
00276   int indx;
00277   double coef;
00278   double sum;
00279   dbl_svector z, zA;
00280 
00281   dbl_EGlpNumInitVar (coef);
00282   dbl_EGlpNumInitVar (sum);
00283   dbl_EGlpNumZero (sum);
00284 
00285   dbl_ILLsvector_init (&z);
00286   dbl_ILLsvector_init (&zA);
00287 
00288   if (lp->basisid == -1)
00289   {
00290     fprintf (stderr, "dbl_ILLbasis_tableau_row: no basis\n");
00291     rval = E_GENERAL_ERROR;
00292     ILL_CLEANUP;
00293   }
00294   if (lp->fbasisid != lp->basisid)
00295   {                             /* Needs to be changed */
00296     rval = dbl_ILLbasis_factor (lp, &singular);
00297     CHECKRVALG (rval, CLEANUP);
00298     if (singular)
00299     {
00300       MESSAGE (__QS_SB_VERB, "Singular Basis found!");
00301       rval = E_BASIS_SINGULAR;
00302       ILL_CLEANUP;
00303     }
00304   }
00305   if (brow == NULL)
00306   {
00307     fprintf (stderr, "No array for basis inverse row\n");
00308     rval = E_GENERAL_ERROR;
00309     ILL_CLEANUP;
00310   }
00311 
00312   rval = dbl_ILLsvector_alloc (&z, lp->nrows);
00313   CHECKRVALG (rval, CLEANUP);
00314   dbl_ILLfct_compute_zz (lp, &z, row);
00315 
00316   for (i = 0; i < lp->O->nrows; i++)
00317     dbl_EGlpNumZero (brow[i]);
00318   for (i = 0; i < z.nzcnt; i++)
00319   {
00320     indx = z.indx[i];
00321     dbl_EGlpNumCopy (coef, z.coef[i]);
00322     dbl_EGlpNumCopy (brow[indx], coef);
00323     dbl_EGlpNumAddInnProdTo (sum, coef, lp->bz[indx]);
00324   }
00325 
00326   if (rhs != NULL)
00327     dbl_EGlpNumCopy (*rhs, sum);
00328   if (trow != NULL)
00329   {
00330     if (!strict)
00331     {
00332       rval = dbl_ILLsvector_alloc (&zA, lp->ncols);
00333       if (rval)
00334         ILL_CLEANUP;
00335       ILL_IFTRACE ("%s:\n", __func__);
00336       rval = dbl_ILLfct_compute_zA (lp, &z, &zA);
00337       CHECKRVALG (rval, CLEANUP);
00338 
00339       for (i = 0; i < lp->ncols; i++)
00340         dbl_EGlpNumZero (trow[i]);
00341       for (i = 0; i < zA.nzcnt; i++)
00342         dbl_EGlpNumCopy (trow[lp->nbaz[zA.indx[i]]], zA.coef[i]);
00343       dbl_EGlpNumOne (trow[lp->baz[row]]);
00344     }
00345     else
00346     {
00347       dbl_ILLfct_compute_vA (lp, &z, trow);
00348     }
00349   }
00350 
00351 #if dbl_BASIS_DEBUG > 0
00352   if (rhs != NULL && trow != NULL)
00353   {
00354     double *tr = NULL;
00355 
00356     dbl_EGlpNumZero (sum);
00357     if (strict)
00358       tr = trow;
00359     else
00360     {
00361       tr = dbl_EGlpNumAllocArray (lp->ncols);
00362       dbl_ILLfct_compute_vA (lp, &z, tr);
00363     }
00364     for (i = 0; i < lp->nrows; i++)
00365       if (dbl_EGlpNumIsGreatZero (tr[lp->baz[i]]))
00366         dbl_EGlpNumAddTo (sum, tr[lp->baz[i]]);
00367       else
00368         dbl_EGlpNumSubTo (sum, tr[lp->baz[i]]);
00369     dbl_EGlpNumCopy (coef, dbl_oneLpNum);
00370     dbl_EGlpNumSubTo (coef, sum);
00371     if (dbl_EGlpNumIsLessZero (coef))
00372       dbl_EGlpNumSign (coef);
00373     if (dbl_EGlpNumIsLess (dbl_PIVZ_TOLER, coef))
00374       fprintf (stderr, "tableau: bas computed = %.12f\n", dbl_EGlpNumToLf (sum));
00375     if (!strict)
00376       dbl_EGlpNumFreeArray (tr);
00377 #if dbl_BASIS_DEBUG > 1
00378     dbl_EGlpNumZero (sum);
00379     for (i = 0; i < lp->ncols; i++)
00380     {
00381       if (lp->vstat[i] == STAT_BASIC)
00382         dbl_EGlpNumAddInnProdTo (sum, lp->xbz[lp->vindex[i]], trow[i]);
00383       else if (lp->vstat[i] == STAT_UPPER)
00384         dbl_EGlpNumAddInnProdTo (sum, lp->uz[i], trow[i]);
00385       else if (lp->vstat[i] == STAT_LOWER)
00386         dbl_EGlpNumAddInnProdTo (sum, lp->lz[i], trow[i]);
00387     }
00388     dbl_EGlpNumSet (coef, 1e-10);
00389     if (dbl_EGlpNumIsNeq (sum, *rhs, coef))
00390       fprintf (stderr, "tableau rhs = %.9f, computed = %.9f\n",
00391                dbl_EGlpNumToLf (*rhs), dbl_EGlpNumToLf (sum));
00392 #endif
00393   }
00394 #endif
00395 
00396 CLEANUP:
00397   dbl_ILLsvector_free (&z);
00398   dbl_ILLsvector_free (&zA);
00399   dbl_EGlpNumClearVar (coef);
00400   dbl_EGlpNumClearVar (sum);
00401   return rval;
00402 }
00403 
00404 static void dbl_get_var_info (
00405   dbl_lpinfo * lp,
00406   dbl_var_data * v)
00407 {
00408   int i = 0;
00409 
00410   v->nartif = 0;
00411   v->nslacks = 0;
00412   v->nfree = 0;
00413   v->nbndone = 0;
00414   v->nbounded = 0;
00415   v->nfixed = 0;
00416   dbl_EGlpNumCopy (v->cmax, dbl_NINFTY);
00417 
00418   for (i = 0; i < lp->ncols; i++)
00419   {
00420     switch (lp->vtype[i])
00421     {
00422     case VARTIFICIAL:
00423       v->nartif++;
00424       break;
00425     case VFREE:
00426       v->nfree++;
00427       break;
00428     case VLOWER:
00429     case VUPPER:
00430       if (lp->vclass[i] == CLASS_LOGICAL)
00431         v->nslacks++;
00432       else
00433         v->nbndone++;
00434       break;
00435 
00436     case VFIXED:
00437       v->nfixed++;
00438     case VBOUNDED:
00439       if (lp->vclass[i] == CLASS_LOGICAL)
00440         v->nslacks++;
00441       else
00442         v->nbounded++;
00443       break;
00444     }
00445     dbl_EGlpNumSetToMaxAbs (v->cmax, lp->cz[i]);
00446   }
00447 
00448 #if dbl_BASIS_STATS > 0
00449   printf ("cols = %d, acols = %d, total  = %d, nrows = %d, nlog = %d\n",
00450           lp->ncols, lp->ncols - lp->nrows,
00451           v->nartif + v->nfree + v->nslacks + v->nbndone + v->nbounded,
00452           lp->nrows, v->nartif + v->nslacks);
00453 #endif
00454 }
00455 
00456 static int dbl_init_slack_basis (
00457   dbl_lpinfo * lp,
00458   int *vstat,
00459   int *irow,
00460   int *rrow,
00461   int *unitcol,
00462   int *icol,
00463   int *rcol)
00464 {
00465   int j, r, vt;
00466   int nslacks = 0;
00467 
00468   for (j = 0; j < lp->ncols; j++)
00469   {
00470     r = lp->matind[lp->matbeg[j]];
00471     vt = lp->vtype[j];
00472 
00473     if ((vt == VUPPER || vt == VLOWER || vt == VBOUNDED || vt == VFIXED) &&
00474         lp->vclass[j] == CLASS_LOGICAL)
00475     {
00476 
00477       vstat[j] = STAT_BASIC;
00478       irow[r] = 1;
00479       rrow[r] = 1;
00480       unitcol[r] = j;
00481       if (icol != NULL)
00482       {
00483         icol[j] = 1;
00484         rcol[j] = 1;
00485       }
00486       nslacks++;
00487     }
00488     else if (vt == VARTIFICIAL)
00489     {
00490       unitcol[r] = j;
00491       vstat[j] = STAT_UPPER;
00492     }
00493     else if (vt == VFREE)
00494       vstat[j] = STAT_ZERO;
00495     else if (vt == VFIXED || vt == VUPPER)
00496       vstat[j] = STAT_UPPER;
00497     else if (vt == VLOWER)
00498       vstat[j] = STAT_LOWER;
00499     else if (vt == VBOUNDED)
00500     {
00501       if (fabs (dbl_EGlpNumToLf (lp->lz[j])) < fabs (dbl_EGlpNumToLf (lp->uz[j])))
00502         vstat[j] = STAT_LOWER;
00503       else
00504         vstat[j] = STAT_UPPER;
00505     }
00506   }
00507   return nslacks;
00508 }
00509 
00510 static int dbl_primal_col_select (
00511   dbl_lpinfo * lp,
00512   int *vstat,
00513   int *irow,
00514   int *rrow,
00515   int *unitcol,
00516   double * v,
00517   int *perm,
00518   int *porder,
00519   int nbelem,
00520   int pcols)
00521 {
00522   int i, j, k, tr, r = 0;
00523   int mcnt, mbeg;
00524   int *matbeg = lp->matbeg;
00525   int *matcnt = lp->matcnt;
00526   int *matind = lp->matind;
00527   double *matval = lp->matval;
00528   double alpha, val, maxelem;
00529 
00530   dbl_EGlpNumInitVar (alpha);
00531   dbl_EGlpNumInitVar (val);
00532   dbl_EGlpNumInitVar (maxelem);
00533 
00534   for (k = 0; k < pcols; k++)
00535   {
00536     j = porder[perm[k]];
00537     mcnt = matcnt[j];
00538     mbeg = matbeg[j];
00539 
00540     dbl_EGlpNumCopy (alpha, dbl_NINFTY);
00541     dbl_EGlpNumCopy (maxelem, dbl_NINFTY);
00542 
00543     for (i = 0; i < mcnt; i++)
00544     {
00545       dbl_EGlpNumCopyAbs (val, matval[mbeg + i]);
00546       if (dbl_EGlpNumIsLess (maxelem, val))
00547         dbl_EGlpNumCopy (maxelem, val);
00548       if (rrow[matind[mbeg + i]] == 0 && dbl_EGlpNumIsLess (alpha, val))
00549       {
00550         dbl_EGlpNumCopy (alpha, val);
00551         r = matind[mbeg + i];
00552       }
00553     }
00554     dbl_EGlpNumCopy (val, maxelem);
00555     dbl_EGlpNumMultTo (val, dbl_PARAM_IBASIS_RPIVOT);
00556     if (dbl_EGlpNumIsLess (val, alpha))
00557     {
00558       vstat[j] = STAT_BASIC;
00559       nbelem++;
00560       irow[r] = 1;
00561       dbl_EGlpNumCopy (v[r], alpha);
00562       for (i = 0; i < mcnt; i++)
00563         if (dbl_EGlpNumIsNeqqZero (matval[mbeg + i]))
00564           rrow[matind[mbeg + i]]++;
00565     }
00566     else
00567     {
00568       dbl_EGlpNumCopy (alpha, dbl_NINFTY);
00569       for (i = 0; i < mcnt; i++)
00570       {
00571         tr = matind[mbeg + i];
00572         dbl_EGlpNumCopyAbs (val, matval[mbeg + i]);
00573         dbl_EGlpNumDivTo (val, dbl_PARAM_IBASIS_RTRIANG);
00574         if (dbl_EGlpNumIsNeqq (v[tr], dbl_INFTY) && dbl_EGlpNumIsLess (v[tr], val))
00575         {
00576           dbl_EGlpNumZero (alpha);
00577           break;
00578         }
00579         dbl_EGlpNumCopyAbs (val, matval[mbeg + i]);
00580         if (irow[tr] == 0 && dbl_EGlpNumIsLess (alpha, val))
00581         {
00582           dbl_EGlpNumCopy (alpha, val);
00583           r = tr;
00584         }
00585       }
00586       if (dbl_EGlpNumIsNeqqZero (alpha) && dbl_EGlpNumIsNeqq (alpha, dbl_NINFTY))
00587       {
00588         vstat[j] = STAT_BASIC;
00589         nbelem++;
00590         irow[r] = 1;
00591         dbl_EGlpNumCopy (v[r], alpha);
00592         for (i = 0; i < mcnt; i++)
00593           if (dbl_EGlpNumIsNeqqZero (matval[mbeg + i]))
00594             rrow[matind[mbeg + i]]++;
00595       }
00596     }
00597   }
00598 #if dbl_BASIS_STATS > 0
00599   printf ("nartifs = %d\n", lp->nrows - nbelem);
00600 #endif
00601 
00602   if (nbelem < lp->nrows)
00603   {
00604     for (i = 0; i < lp->nrows; i++)
00605     {
00606       if (irow[i] == 0)
00607       {
00608         if (unitcol[i] != -1)
00609         {
00610           vstat[unitcol[i]] = STAT_BASIC;
00611           nbelem++;
00612         }
00613         else
00614         {
00615           fprintf (stderr, "Error: Not enough artificials\n");
00616           return -1;
00617         }
00618       }
00619     }
00620   }
00621   dbl_EGlpNumClearVar (alpha);
00622   dbl_EGlpNumClearVar (val);
00623   dbl_EGlpNumClearVar (maxelem);
00624   return nbelem;
00625 }
00626 
00627 /* This is an implementation of the initial basis procedure
00628    in: "Implementing the simplex method: the initial basis", by
00629    Bob Bixby.
00630    Goals: choose initial variables to go into basis which satisfy:
00631    1) vars are slacks, 2) vars have freedom to move
00632    3) initial submatrix is nonsingular, 4) low objective function
00633    contribution.
00634 */
00635 static int dbl_get_initial_basis1 (
00636   dbl_lpinfo * lp,
00637   int *vstat)
00638 {
00639   int rval = 0;
00640   int i, j, tot1 = 0, tot2 = 0;
00641   int nbelem = 0, nslacks = 0;
00642   int tfree = 0, tbndone = 0;
00643   int tbounded = 0;
00644   int *irow = NULL, *rrow = NULL;
00645   int *perm = NULL, *porder = NULL;
00646   int *unitcol = NULL;
00647   double cmax;
00648   double *v = NULL;
00649   double *qpenalty = NULL;
00650   dbl_var_data vd;
00651 
00652   dbl_ILLbasis_init_vardata (&vd);
00653   dbl_EGlpNumInitVar (cmax);
00654 
00655   dbl_get_var_info (lp, &vd);
00656   if (!dbl_EGlpNumIsNeqqZero (vd.cmax))
00657     dbl_EGlpNumOne (cmax);
00658   else
00659   {
00660     dbl_EGlpNumCopy (cmax, vd.cmax);
00661     dbl_EGlpNumMultUiTo (cmax, 1000);
00662   }
00663 
00664   ILL_SAFE_MALLOC (irow, lp->nrows, int);
00665   ILL_SAFE_MALLOC (rrow, lp->nrows, int);
00666 
00667   v = dbl_EGlpNumAllocArray (lp->nrows);
00668   ILL_SAFE_MALLOC (unitcol, lp->nrows, int);
00669 
00670   for (i = 0; i < lp->nrows; i++)
00671   {
00672     unitcol[i] = -1;
00673     dbl_EGlpNumCopy (v[i], dbl_INFTY);
00674     irow[i] = 0;
00675     rrow[i] = 0;
00676   }
00677 
00678   nslacks = dbl_init_slack_basis (lp, vstat, irow, rrow, unitcol, NULL, NULL);
00679   if (nslacks != vd.nslacks)
00680   {
00681     printf ("complain: incorrect basis info(slacks)\n");
00682     rval = E_SIMPLEX_ERROR;
00683     ILL_CLEANUP;
00684   }
00685   if (nslacks == lp->nrows)
00686     ILL_CLEANUP;
00687   nbelem = nslacks;
00688   if (nbelem < lp->nrows)
00689   {
00690     for (i = 0; i < lp->nrows; i++)
00691     {
00692       if (irow[i] == 0)
00693       {
00694         if (unitcol[i] != -1)
00695         {
00696           vstat[unitcol[i]] = STAT_BASIC;
00697           nbelem++;
00698         }
00699         else
00700         {
00701           fprintf (stderr, "Error: Not enough artificials\n");
00702           return -1;
00703         }
00704       }
00705     }
00706   }
00707   ILL_CLEANUP;
00708 
00709   tot1 = vd.nfree + vd.nbndone;
00710   tot2 = vd.nfree + vd.nbndone + vd.nbounded;
00711   ILL_SAFE_MALLOC (perm, tot2, int);
00712   ILL_SAFE_MALLOC (porder, tot2, int);
00713 
00714   qpenalty = dbl_EGlpNumAllocArray (tot2);
00715 
00716   for (j = 0; j < lp->ncols; j++)
00717   {
00718     if (vstat[j] == STAT_BASIC)
00719       continue;
00720 
00721     switch (lp->vtype[j])
00722     {
00723     case VFREE:
00724       porder[tfree] = j;
00725       perm[tfree] = tfree;
00726       dbl_EGlpNumCopyFrac (qpenalty[tfree], lp->cz[j], cmax);
00727       tfree++;
00728       break;
00729 
00730     case VLOWER:
00731     case VUPPER:
00732       porder[vd.nfree + tbndone] = j;
00733       perm[vd.nfree + tbndone] = tbndone;
00734       dbl_EGlpNumCopyFrac (qpenalty[vd.nfree + tbndone], lp->cz[j], cmax);
00735       if (lp->vtype[j] == VLOWER)
00736         dbl_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], lp->lz[j]);
00737       else
00738         dbl_EGlpNumSubTo (qpenalty[vd.nfree + tbndone], lp->uz[j]);
00739       tbndone++;
00740       break;
00741 
00742     case VFIXED:
00743     case VBOUNDED:
00744       porder[tot1 + tbounded] = j;
00745       perm[tot1 + tbounded] = tbounded;
00746       dbl_EGlpNumCopyFrac (qpenalty[tot1 + tbndone], lp->cz[j], cmax);
00747       dbl_EGlpNumAddTo (qpenalty[tot1 + tbndone], lp->lz[j]);
00748       dbl_EGlpNumSubTo (qpenalty[tot1 + tbndone], lp->uz[j]);
00749       tbounded++;
00750       break;
00751     }
00752   }
00753   if (tfree != vd.nfree || tbndone != vd.nbndone || tbounded != vd.nbounded)
00754   {
00755     printf ("complain: incorrect basis info \n");
00756     rval = E_SIMPLEX_ERROR;
00757     ILL_CLEANUP;
00758   }
00759 
00760   dbl_ILLutil_EGlpNum_perm_quicksort (perm, qpenalty, vd.nfree);
00761   dbl_ILLutil_EGlpNum_perm_quicksort (perm + vd.nfree, qpenalty + vd.nfree,
00762                                   vd.nbndone);
00763   dbl_ILLutil_EGlpNum_perm_quicksort (perm + tot1, qpenalty + tot1, vd.nbounded);
00764 
00765   for (i = 0; i < vd.nbndone; i++)
00766     perm[vd.nfree + i] += vd.nfree;
00767   for (i = 0; i < vd.nbounded; i++)
00768     perm[tot1 + i] += tot1;
00769 
00770   nbelem =
00771     dbl_primal_col_select (lp, vstat, irow, rrow, unitcol, v, perm, porder, nbelem,
00772                        tot2);
00773   if (nbelem != lp->nrows)
00774   {
00775     printf ("complain: incorrect final basis size\n");
00776     rval = E_SIMPLEX_ERROR;
00777     ILL_CLEANUP;
00778   }
00779 
00780 CLEANUP:
00781   dbl_EGlpNumClearVar (cmax);
00782   if (rval)
00783     dbl_ILLbasis_free_basisinfo (lp);
00784   ILL_IFFREE (irow, int);
00785   ILL_IFFREE (rrow, int);
00786 
00787   dbl_EGlpNumFreeArray (v);
00788   ILL_IFFREE (perm, int);
00789   ILL_IFFREE (porder, int);
00790   ILL_IFFREE (unitcol, int);
00791 
00792   dbl_EGlpNumFreeArray (qpenalty);
00793   dbl_ILLbasis_clear_vardata (&vd);
00794   EG_RETURN (rval);
00795 }
00796 
00797 static int dbl_get_initial_basis2 (
00798   dbl_lpinfo * lp,
00799   int *vstat)
00800 {
00801   int rval = 0;
00802   int i, j, k, tot1, tot2;
00803   int rbeg, rcnt, mcnt;
00804   int nbelem = 0, nslacks = 0;
00805   int tfree = 0, tbndone = 0;
00806   int tbounded = 0;
00807   int *irow = NULL, *rrow = NULL;
00808   int *perm = NULL, *porder = NULL;
00809   int *unitcol = NULL;
00810   double *v = NULL;
00811   double *qpenalty = NULL;
00812   int col = 0, s_i = 0, selc = 0;
00813   int *icol = NULL, *rcol = NULL;
00814   int *plen = NULL;
00815   double *dj = NULL;
00816   dbl_var_data vd;
00817   double seldj;
00818   double selv;
00819   double c_dj;
00820   double cmax;
00821 
00822   dbl_EGlpNumInitVar (seldj);
00823   dbl_EGlpNumInitVar (selv);
00824   dbl_EGlpNumInitVar (c_dj);
00825   dbl_EGlpNumInitVar (cmax);
00826   dbl_EGlpNumZero (c_dj);
00827   dbl_EGlpNumZero (selv);
00828   dbl_EGlpNumZero (seldj);
00829   dbl_ILLbasis_init_vardata (&vd);
00830 
00831   dbl_get_var_info (lp, &vd);
00832 
00833   ILL_SAFE_MALLOC (irow, lp->nrows, int);
00834   ILL_SAFE_MALLOC (rrow, lp->nrows, int);
00835 
00836   v = dbl_EGlpNumAllocArray (lp->nrows);
00837   ILL_SAFE_MALLOC (unitcol, lp->nrows, int);
00838   ILL_SAFE_MALLOC (icol, lp->ncols, int);
00839   ILL_SAFE_MALLOC (rcol, lp->ncols, int);
00840 
00841   dj = dbl_EGlpNumAllocArray (lp->ncols);
00842 
00843   for (i = 0; i < lp->nrows; i++)
00844   {
00845     unitcol[i] = -1;
00846     dbl_EGlpNumCopy (v[i], dbl_INFTY);
00847     irow[i] = 0;
00848     rrow[i] = 0;
00849   }
00850   /* assign all d_j */
00851   for (i = 0; i < lp->ncols; i++)
00852   {
00853     icol[i] = 0;
00854     rcol[i] = 0;
00855     dbl_EGlpNumCopy (dj[i], lp->cz[i]);
00856   }
00857 
00858   nslacks = dbl_init_slack_basis (lp, vstat, irow, rrow, unitcol, icol, rcol);
00859   if (nslacks != vd.nslacks)
00860   {
00861     printf ("complain: incorrect basis info\n");
00862     rval = E_SIMPLEX_ERROR;
00863     ILL_CLEANUP;
00864   }
00865   if (nslacks == lp->nrows)
00866     ILL_CLEANUP;
00867   nbelem = nslacks;
00868 
00869   /* allocate maximum required space for perm etc. */
00870   ILL_SAFE_MALLOC (perm, lp->ncols, int);
00871   ILL_SAFE_MALLOC (porder, lp->ncols, int);
00872   ILL_SAFE_MALLOC (plen, lp->nrows, int);
00873 
00874   qpenalty = dbl_EGlpNumAllocArray (lp->ncols);
00875 
00876   /* find all unit rows and record lengths */
00877   for (i = 0; i < lp->nrows; i++)
00878   {
00879     if (irow[i] != 1)
00880     {
00881       rbeg = lp->rowbeg[i];
00882       rcnt = lp->rowcnt[i];
00883       for (j = 0; j < rcnt; j++)
00884       {
00885         dbl_EGlpNumCopyAbs (cmax, lp->rowval[rbeg + j]);
00886         if (dbl_EGlpNumIsNeqq (cmax, dbl_oneLpNum))
00887           break;
00888       }
00889       if (j == rcnt)
00890       {
00891         perm[s_i] = s_i;
00892         porder[s_i] = i;
00893         plen[s_i] = rcnt;
00894         s_i++;
00895       }
00896     }
00897   }
00898 
00899   /*sort all unit rows */
00900   dbl_ILLutil_int_perm_quicksort (perm, plen, s_i);
00901 
00902   /* now go through the unit rows */
00903   for (k = 0; k < s_i; k++)
00904   {
00905     i = porder[perm[k]];
00906     rbeg = lp->rowbeg[i];
00907     rcnt = lp->rowcnt[i];
00908     selc = -1;
00909     dbl_EGlpNumCopy (seldj, dbl_INFTY);
00910     dbl_EGlpNumZero (selv);
00911 
00912     /* for every row s_i, compute min {d_j : d_j <0 , j is u or l or fr} */
00913     for (j = 0; j < rcnt; j++)
00914     {
00915       col = lp->rowind[rbeg + j];
00916       if (rcol[col] == 1)
00917         break;
00918       if (dbl_EGlpNumIsLessZero (dj[col]))
00919       {
00920         if (dbl_EGlpNumIsLess (dj[col], seldj))
00921         {
00922           selc = col;
00923           dbl_EGlpNumCopy (seldj, dj[col]);
00924           dbl_EGlpNumCopy (selv, lp->rowval[rbeg + j]);
00925         }
00926       }
00927     }
00928     /* select pivot element and update all d_j's */
00929     if (selc != -1)
00930     {
00931       nbelem++;
00932       irow[i] = 1;
00933       rrow[i] = 1;
00934       icol[selc] = 1;
00935       dbl_EGlpNumCopyFrac (c_dj, dj[selc], selv);
00936       vstat[selc] = STAT_BASIC;
00937       for (j = 0; j < rcnt; j++)
00938       {
00939         col = lp->rowind[rbeg + j];
00940         dbl_EGlpNumSubInnProdTo (dj[col], lp->rowval[rbeg + j], c_dj);
00941         rcol[col] = 1;
00942       }
00943     }
00944   }
00945 #if dbl_BASIS_STATS > 0
00946   printf ("unit rows = %d\n", s_i);
00947   printf ("nslacks %d, unit rows selected = %d\n", nslacks, nbelem - nslacks);
00948 #endif
00949   /* now go through remaining cols with dj = 0 */
00950   tot1 = vd.nfree + vd.nbndone;
00951 
00952   if (!dbl_EGlpNumIsNeqqZero (vd.cmax))
00953     dbl_EGlpNumOne (cmax);
00954   else
00955   {
00956     dbl_EGlpNumCopy (cmax, vd.cmax);
00957     dbl_EGlpNumMultUiTo (cmax, 1000);
00958   }
00959   for (j = 0; j < lp->ncols; j++)
00960   {
00961     if (vstat[j] == STAT_BASIC)
00962       continue;
00963     if (icol[j] == 1 || dbl_EGlpNumIsNeqZero (dj[j], dbl_BD_TOLER))
00964       continue;
00965     mcnt = lp->matcnt[j];
00966 
00967     dbl_EGlpNumSet (c_dj, (double) mcnt);
00968     switch (lp->vtype[j])
00969     {
00970     case VFREE:
00971       porder[tfree] = j;
00972       perm[tfree] = tfree;
00973       dbl_EGlpNumCopyFrac (qpenalty[tfree], lp->cz[j], cmax);
00974       dbl_EGlpNumAddTo (qpenalty[tfree], c_dj);
00975       tfree++;
00976       break;
00977 
00978     case VLOWER:
00979     case VUPPER:
00980       porder[vd.nfree + tbndone] = j;
00981       perm[vd.nfree + tbndone] = tbndone;
00982       dbl_EGlpNumCopyFrac (qpenalty[vd.nfree + tbndone], lp->cz[j], cmax);
00983       dbl_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], c_dj);
00984       if (lp->vtype[j] == VLOWER)
00985         dbl_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], lp->lz[j]);
00986       else
00987         dbl_EGlpNumSubTo (qpenalty[vd.nfree + tbndone], lp->uz[j]);
00988       tbndone++;
00989       break;
00990 
00991     case VFIXED:
00992     case VBOUNDED:
00993       porder[tot1 + tbounded] = j;
00994       perm[tot1 + tbounded] = tbounded;
00995       dbl_EGlpNumCopyFrac (qpenalty[tot1 + tbounded], lp->cz[j], cmax);
00996       dbl_EGlpNumAddTo (qpenalty[tot1 + tbounded], lp->lz[j]);
00997       dbl_EGlpNumSubTo (qpenalty[tot1 + tbounded], lp->uz[j]);
00998       dbl_EGlpNumAddTo (qpenalty[tot1 + tbounded], c_dj);
00999       tbounded++;
01000       break;
01001     }
01002   }
01003 #if dbl_BASIS_STATS > 0
01004   printf ("bfree %d, bone %d, bbnd %d\n", tfree, tbndone, tbounded);
01005 #endif
01006 
01007   dbl_ILLutil_EGlpNum_perm_quicksort (perm, qpenalty, tfree);
01008   dbl_ILLutil_EGlpNum_perm_quicksort (perm + vd.nfree, qpenalty + vd.nfree,
01009                                   tbndone);
01010   dbl_ILLutil_EGlpNum_perm_quicksort (perm + tot1, qpenalty + tot1, tbounded);
01011 
01012   tot2 = tfree + tbndone;
01013   for (i = 0; i < tbndone; i++)
01014   {
01015     perm[tfree + i] = perm[vd.nfree + i] + tfree;
01016     porder[tfree + i] = porder[vd.nfree + i];
01017   }
01018   for (i = 0; i < tbounded; i++)
01019   {
01020     perm[tot2 + i] = perm[tot1 + i] + tot2;
01021     porder[tot2 + i] = porder[tot1 + i];
01022   }
01023   tot2 += tbounded;
01024 
01025   nbelem =
01026     dbl_primal_col_select (lp, vstat, irow, rrow, unitcol, v, perm, porder, nbelem,
01027                        tot2);
01028   if (nbelem != lp->nrows)
01029   {
01030     printf ("complain: incorrect final basis size\n");
01031     rval = E_SIMPLEX_ERROR;
01032     ILL_CLEANUP;
01033   }
01034 
01035 CLEANUP:
01036   if (rval)
01037     dbl_ILLbasis_free_basisinfo (lp);
01038 
01039   ILL_IFFREE (irow, int);
01040   ILL_IFFREE (rrow, int);
01041 
01042   dbl_EGlpNumFreeArray (v);
01043   ILL_IFFREE (unitcol, int);
01044   ILL_IFFREE (icol, int);
01045   ILL_IFFREE (rcol, int);
01046 
01047   dbl_EGlpNumFreeArray (dj);
01048   ILL_IFFREE (perm, int);
01049   ILL_IFFREE (porder, int);
01050   ILL_IFFREE (plen, int);
01051 
01052   dbl_EGlpNumFreeArray (qpenalty);
01053   dbl_EGlpNumClearVar (seldj);
01054   dbl_EGlpNumClearVar (selv);
01055   dbl_EGlpNumClearVar (c_dj);
01056   dbl_EGlpNumClearVar (cmax);
01057   dbl_ILLbasis_clear_vardata (&vd);
01058   EG_RETURN (rval);
01059 }
01060 
01061 static int dbl_set_basis_indices (
01062   dbl_lpinfo * lp,
01063   int *vstat)
01064 {
01065   int i, b = 0, nb = 0;
01066   int vs;
01067 
01068   for (i = 0; i < lp->ncols; i++)
01069   {
01070     vs = vstat[i];
01071     lp->vstat[i] = vs;
01072 
01073     if (vs == STAT_BASIC)
01074     {
01075       lp->baz[b] = i;
01076       lp->vindex[i] = b;
01077       b++;
01078     }
01079     else if (vs == STAT_UPPER || vs == STAT_LOWER || vs == STAT_ZERO)
01080     {
01081       lp->nbaz[nb] = i;
01082       lp->vindex[i] = nb;
01083       nb++;
01084     }
01085     else
01086     {
01087       fprintf (stderr, "Error in basis creation\n");
01088       return E_SIMPLEX_ERROR;
01089     }
01090   }
01091   if (b != lp->nrows)
01092   {
01093     fprintf (stderr, "Error 2 in basis creation\n");
01094     return E_SIMPLEX_ERROR;
01095   }
01096   else if (nb != lp->nnbasic)
01097   {
01098     fprintf (stderr, "Error 3 in basis creation\n");
01099     return E_SIMPLEX_ERROR;
01100   }
01101   return 0;
01102 }
01103 
01104 int dbl_ILLbasis_get_initial (
01105   dbl_lpinfo * lp,
01106   int algorithm)
01107 {
01108   int rval = 0;
01109   int *vstat = NULL;
01110 
01111   dbl_ILLbasis_free_basisinfo (lp);
01112   dbl_ILLbasis_init_basisinfo (lp);
01113   rval = dbl_ILLbasis_build_basisinfo (lp);
01114   CHECKRVALG (rval, CLEANUP);
01115 
01116   ILL_SAFE_MALLOC (vstat, lp->ncols, int);
01117 
01118   if (algorithm == PRIMAL_SIMPLEX)
01119     rval = dbl_get_initial_basis1 (lp, vstat);
01120   else
01121     rval = dbl_get_initial_basis2 (lp, vstat);
01122 
01123   if (rval == E_SIMPLEX_ERROR)
01124   {
01125     FILE *f = fopen ("bad.lp", "w");
01126     int tval = dbl_ILLwrite_lp_file (lp->O, f, NULL);
01127 
01128     if (tval)
01129     {
01130       fprintf (stderr, "Error writing bad lp\n");
01131     }
01132     if (f != NULL)
01133       fclose (f);
01134   }
01135   CHECKRVALG (rval, CLEANUP);
01136 
01137   rval = dbl_set_basis_indices (lp, vstat);
01138   CHECKRVALG (rval, CLEANUP);
01139   lp->basisid = 0;
01140 
01141 CLEANUP:
01142   ILL_IFFREE (vstat, int);
01143 
01144   EG_RETURN (rval);
01145 }
01146 
01147 static int dbl_choose_basis (
01148   int algorithm,
01149   double pinf1,
01150   double dinf1,
01151   double pinf2,
01152   double dinf2)
01153 {
01154 /* We changed the constant definitions outside here, the actual numbers are
01155  * asigned in dbl_lpdata.c. the values are as follows:
01156  * dbl_CB_EPS = 0.001;
01157  * dbl_CB_PRI_RLIMIT = 0.25;
01158  * dbl_CB_INF_RATIO = 10.0; 
01159  * */
01160   int choice = 1;
01161   double rp, rd;
01162 
01163   if (algorithm == PRIMAL_SIMPLEX)
01164   {
01165     dbl_EGlpNumInitVar (rp);
01166     dbl_EGlpNumInitVar (rd);
01167     dbl_EGlpNumCopyDiff (rp, pinf1, pinf2);
01168     dbl_EGlpNumCopyDiff (rd, dinf1, dinf2);
01169     if (dbl_EGlpNumIsLeq (rp, dbl_CB_EPS) && dbl_EGlpNumIsLeq (rd, dbl_CB_EPS))
01170       choice = 1;
01171     else
01172     {
01173       dbl_EGlpNumSign (rp);
01174       dbl_EGlpNumSign (rd);
01175       if (dbl_EGlpNumIsLeq (rp, dbl_CB_EPS) && dbl_EGlpNumIsLeq (rd, dbl_CB_EPS))
01176         choice = 2;
01177       else if (dbl_EGlpNumIsLess (pinf1, pinf2) && dbl_EGlpNumIsLess (dinf2, dinf1))
01178       {
01179         choice = 1;
01180         dbl_EGlpNumCopyFrac (rp, pinf1, pinf2);
01181         dbl_EGlpNumCopyFrac (rd, dinf2, dinf1);
01182         dbl_EGlpNumMultTo (rd, dbl_CB_INF_RATIO);
01183         if (dbl_EGlpNumIsLess (dbl_CB_PRI_RLIMIT, rp) && (dbl_EGlpNumIsLess (rd, rp)))
01184           choice = 2;
01185       }
01186       else if (dbl_EGlpNumIsLess (pinf2, pinf1) && dbl_EGlpNumIsLess (dinf1, dinf2))
01187       {
01188         choice = 2;
01189         dbl_EGlpNumCopyFrac (rp, pinf2, pinf1);
01190         dbl_EGlpNumCopyFrac (rd, dinf1, dinf2);
01191         dbl_EGlpNumMultTo (rd, dbl_CB_INF_RATIO);
01192         if (dbl_EGlpNumIsLess (dbl_CB_PRI_RLIMIT, rp) && dbl_EGlpNumIsLess (rd, rp))
01193           choice = 1;
01194       }
01195       else
01196         choice = 1;
01197     }
01198     dbl_EGlpNumClearVar (rp);
01199     dbl_EGlpNumClearVar (rd);
01200   }
01201   ILL_IFTRACE ("%s:%d\n", __func__, choice);
01202   return choice;
01203 }
01204 
01205 int dbl_ILLbasis_get_cinitial (
01206   dbl_lpinfo * lp,
01207   int algorithm)
01208 {
01209   int rval = 0;
01210   int *vstat1 = NULL;
01211   int *vstat2 = NULL;
01212   int singular;
01213   int choice = 0;
01214 
01215 #if dbl_BASIS_STATS > 0
01216   int i, nz1 = 0, nz2 = 0;
01217 #endif
01218   double pinf1, pinf2, dinf1, dinf2;
01219   dbl_feas_info fi;
01220 
01221   dbl_EGlpNumInitVar (pinf1);
01222   dbl_EGlpNumInitVar (pinf2);
01223   dbl_EGlpNumInitVar (dinf1);
01224   dbl_EGlpNumInitVar (dinf2);
01225   dbl_EGlpNumInitVar (fi.totinfeas);
01226 
01227   dbl_ILLbasis_free_basisinfo (lp);
01228   dbl_ILLbasis_init_basisinfo (lp);
01229   rval = dbl_ILLbasis_build_basisinfo (lp);
01230   CHECKRVALG (rval, CLEANUP);
01231 
01232   ILL_SAFE_MALLOC (vstat1, lp->ncols, int);
01233   ILL_SAFE_MALLOC (vstat2, lp->ncols, int);
01234 
01235   if (algorithm != PRIMAL_SIMPLEX)
01236   {
01237     rval = dbl_get_initial_basis2 (lp, vstat2);
01238     CHECKRVALG (rval, CLEANUP);
01239     rval = dbl_set_basis_indices (lp, vstat2);
01240     lp->basisid = 0;
01241     ILL_CLEANUP;
01242   }
01243 
01244   rval = dbl_get_initial_basis1 (lp, vstat1);
01245   CHECKRVALG (rval, CLEANUP);
01246   rval = dbl_get_initial_basis2 (lp, vstat2);
01247   CHECKRVALG (rval, CLEANUP);
01248   lp->basisid = 0;
01249 
01250   /* handle first basis */
01251   rval = dbl_set_basis_indices (lp, vstat1);
01252   CHECKRVALG (rval, CLEANUP);
01253 #if dbl_BASIS_STATS > 0
01254   for (i = 0; i < lp->nrows; i++)
01255     nz1 += lp->matcnt[lp->baz[i]];
01256 #endif
01257   rval = dbl_ILLbasis_factor (lp, &singular);
01258   if (singular)
01259     MESSAGE (__QS_SB_VERB, "Singular Basis found!");
01260   CHECKRVALG (rval, CLEANUP);
01261 
01262   dbl_ILLfct_compute_piz (lp);
01263   dbl_ILLfct_compute_dz (lp);
01264   dbl_ILLfct_dual_adjust (lp, dbl_zeroLpNum);
01265   dbl_ILLfct_compute_xbz (lp);
01266 
01267   dbl_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
01268   dbl_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
01269   dbl_EGlpNumCopy (pinf1, lp->pinfeas);
01270   dbl_EGlpNumCopy (dinf1, lp->dinfeas);
01271   /*
01272    * dbl_ILLfct_compute_pobj (lp);  obj1p = lp->objval;
01273    * dbl_ILLfct_compute_dobj (lp);  obj1d = lp->objval;
01274    */
01275 
01276   /* handle second basis */
01277   rval = dbl_set_basis_indices (lp, vstat2);
01278   CHECKRVALG (rval, CLEANUP);
01279 #if dbl_BASIS_STATS > 0
01280   for (i = 0; i < lp->nrows; i++)
01281     nz2 += lp->matcnt[lp->baz[i]];
01282 #endif
01283   rval = dbl_ILLbasis_factor (lp, &singular);
01284   if (singular)
01285     MESSAGE (__QS_SB_VERB, "Singular Basis found!");
01286   CHECKRVALG (rval, CLEANUP);
01287 
01288   dbl_ILLfct_compute_piz (lp);
01289   dbl_ILLfct_compute_dz (lp);
01290   dbl_ILLfct_dual_adjust (lp, dbl_zeroLpNum);
01291   dbl_ILLfct_compute_xbz (lp);
01292 
01293   dbl_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
01294   dbl_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
01295   dbl_EGlpNumCopy (pinf2, lp->pinfeas);
01296   dbl_EGlpNumCopy (dinf2, lp->dinfeas);
01297 
01298 #if dbl_BASIS_STATS > 0
01299   printf ("b1: nz %d pinf %.2f dinf %.2f\n", nz1, dbl_EGlpNumToLf (pinf1),
01300           dbl_EGlpNumToLf (dinf1));
01301   printf ("b2: nz %d pinf %.2f dinf %.2f\n", nz2, dbl_EGlpNumToLf (pinf2),
01302           dbl_EGlpNumToLf (dinf2));
01303 #endif
01304   choice = dbl_choose_basis (algorithm, pinf1, dinf1, pinf2, dinf2);
01305   if (choice == 1)
01306   {
01307     lp->fbasisid = -1;
01308     rval = dbl_set_basis_indices (lp, vstat1);
01309     CHECKRVALG (rval, CLEANUP);
01310   }
01311 
01312 CLEANUP:
01313   if (rval == E_SIMPLEX_ERROR)
01314   {
01315     FILE *fil = fopen ("bad.lp", "w");
01316     int tval = dbl_ILLwrite_lp_file (lp->O, fil, NULL);
01317 
01318     if (tval)
01319     {
01320       fprintf (stderr, "Error writing bad lp\n");
01321     }
01322     if (fil != NULL)
01323       fclose (fil);
01324   }
01325   ILL_IFFREE (vstat1, int);
01326   ILL_IFFREE (vstat2, int);
01327 
01328   dbl_EGlpNumClearVar (pinf1);
01329   dbl_EGlpNumClearVar (pinf2);
01330   dbl_EGlpNumClearVar (dinf1);
01331   dbl_EGlpNumClearVar (dinf2);
01332   dbl_EGlpNumClearVar (fi.totinfeas);
01333   EG_RETURN (rval);
01334 }
01335 
01336 int dbl_ILLbasis_factor (
01337   dbl_lpinfo * lp,
01338   int *singular)
01339 {
01340   int rval = 0;
01341   int i;
01342   int eindex;
01343   int lindex;
01344   int ltype;
01345   int lvstat;
01346   int nsing = 0;
01347   int *singr = 0;
01348   int *singc = 0;
01349 
01350   *singular = 0;
01351   do
01352   {
01353     if (lp->f)
01354     {
01355       dbl_ILLfactor_free_factor_work (lp->f);
01356     }
01357     else
01358     {
01359       ILL_SAFE_MALLOC (lp->f, 1, dbl_factor_work);
01360       dbl_EGlpNumInitVar (lp->f->fzero_tol);
01361       dbl_EGlpNumInitVar (lp->f->szero_tol);
01362       dbl_EGlpNumInitVar (lp->f->partial_tol);
01363       dbl_EGlpNumInitVar (lp->f->maxelem_orig);
01364       dbl_EGlpNumInitVar (lp->f->maxelem_factor);
01365       dbl_EGlpNumInitVar (lp->f->maxelem_cur);
01366       dbl_EGlpNumInitVar (lp->f->partial_cur);
01367       dbl_ILLfactor_init_factor_work (lp->f);
01368     }
01369     rval = dbl_ILLfactor_create_factor_work (lp->f, lp->O->nrows);
01370     CHECKRVALG (rval, CLEANUP);
01371 
01372     rval = dbl_ILLfactor (lp->f, lp->baz, lp->matbeg, lp->matcnt,
01373                       lp->matind, lp->matval, &nsing, &singr, &singc);
01374     CHECKRVALG (rval, CLEANUP);
01375 
01376     if (nsing != 0)
01377     {
01378       *singular = 1;
01379       MESSAGE (__QS_SB_VERB, "Found singular basis!");
01380       for (i = 0; i < nsing; i++)
01381       {
01382         eindex = lp->vindex[lp->O->rowmap[singr[i]]];
01383         lindex = singc[i];
01384         ltype = lp->vtype[lp->baz[lindex]];
01385 
01386         if (ltype == VBOUNDED || ltype == VLOWER || ltype == VARTIFICIAL)
01387           lvstat = STAT_LOWER;
01388         else if (ltype == VUPPER)
01389           lvstat = STAT_UPPER;
01390         else
01391           lvstat = STAT_ZERO;
01392 
01393         dbl_ILLfct_update_basis_info (lp, eindex, lindex, lvstat);
01394         lp->basisid++;
01395       }
01396       ILL_IFFREE (singr, int);
01397       ILL_IFFREE (singc, int);
01398     }
01399 
01400   } while (nsing != 0);
01401 
01402   lp->fbasisid = lp->basisid;
01403 
01404 CLEANUP:
01405   ILL_IFFREE (singr, int);
01406   ILL_IFFREE (singc, int);
01407 
01408   if (rval)
01409     fprintf (stderr, "Error: unknown in %s\n", __func__);
01410   EG_RETURN (rval);
01411 }
01412 
01413 int dbl_ILLbasis_refactor (
01414   dbl_lpinfo * lp)
01415 {
01416   int sing = 0;
01417   int rval = 0;
01418 
01419   rval = dbl_ILLbasis_factor (lp, &sing);
01420   if (sing)
01421   {
01422     MESSAGE (__QS_SB_VERB, "Singular Basis found!");
01423     rval = QS_LP_CHANGE_PREC;
01424     return rval;
01425   }
01426   EG_RETURN (rval);
01427 }
01428 
01429 void dbl_ILLbasis_column_solve (
01430   dbl_lpinfo * lp,
01431   dbl_svector * rhs,
01432   dbl_svector * soln)
01433 {
01434   dbl_ILLfactor_ftran (lp->f, rhs, soln);
01435 }
01436 
01437 void dbl_ILLbasis_column_solve_update (
01438   dbl_lpinfo * lp,
01439   dbl_svector * rhs,
01440   dbl_svector * upd,
01441   dbl_svector * soln)
01442 {
01443   dbl_ILLfactor_ftran_update (lp->f, rhs, upd, soln);
01444 }
01445 
01446 void dbl_ILLbasis_row_solve (
01447   dbl_lpinfo * lp,
01448   dbl_svector * rhs,
01449   dbl_svector * soln)
01450 {
01451   dbl_ILLfactor_btran (lp->f, rhs, soln);
01452 }
01453 
01454 int dbl_ILLbasis_update (
01455   dbl_lpinfo * lp,
01456   dbl_svector * y,
01457   int lindex,
01458   int *refactor,
01459   int *singular)
01460 {
01461 #if 0                           /* To always refactor, change 0 to 1 */
01462   *refactor = 1;
01463   return dbl_ILLbasis_factor (lp, singular);
01464 #else
01465 
01466   int rval = 0;
01467 
01468   *refactor = 0;
01469   rval = dbl_ILLfactor_update (lp->f, y, lindex, refactor);
01470   if (rval == E_FACTOR_BLOWUP || rval == E_UPDATE_SINGULAR_ROW
01471       || rval == E_UPDATE_SINGULAR_COL)
01472   {
01473 /* Bico - comment out for dist
01474        fprintf(stderr, "Warning: numerically bad basis in dbl_ILLfactor_update\n");
01475 */
01476     *refactor = 1;
01477     rval = 0;
01478   }
01479   if (rval == E_UPDATE_NOSPACE)
01480   {
01481     *refactor = 1;
01482     rval = 0;
01483   }
01484 
01485   if (*refactor)
01486   {
01487     rval = dbl_ILLbasis_factor (lp, singular);
01488     if (*singular)
01489       MESSAGE (__QS_SB_VERB, "Singular Basis found!");
01490   }
01491   if (rval)
01492   {
01493     FILE *eout = 0;
01494     int tval;
01495 
01496     printf ("write bad lp to factor.lp\n");
01497     fflush (stdout);
01498     eout = fopen ("factor.lp", "w");
01499     if (!eout)
01500     {
01501       fprintf (stderr, "could not open file to write bad factor lp\n");
01502     }
01503     else
01504     {
01505       tval = dbl_ILLwrite_lp_file (lp->O, eout, NULL);
01506       if (tval)
01507       {
01508         fprintf (stderr, "error while writing bad factor lp\n");
01509       }
01510       fclose (eout);
01511     }
01512 
01513     printf ("write bad basis to factor.bas\n");
01514     fflush (stdout);
01515     tval = dbl_ILLlib_writebasis (lp, 0, "factor.bas");
01516     if (tval)
01517     {
01518       fprintf (stderr, "error while writing factor basis\n");
01519     }
01520   }
01521 
01522   EG_RETURN (rval);
01523 #endif
01524 }

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