mt_gomory.c

Go to the documentation of this file.
00001 /* MTgomory "multi tableau gomory cut" provides an implementation for gomory
00002  * cuts derived from multiple tableau rows in the spirit of the work of
00003  * Andersen et al (IPCO 2007), Cornuejols (es presented in George Nemhauser
00004  * Birthday Conference in Atlanta 2007) and Gomory (presented in the same
00005  * conference).
00006  *
00007  * Copyright (C) 2007 Daniel Espinoza.
00008  * 
00009  * This library is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License as published by the
00011  * Free Software Foundation; either version 2.1 of the License, or (at your
00012  * option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful, but 
00015  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
00016  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
00017  * License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public License
00020  * along with this library; if not, write to the Free Software Foundation,
00021  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
00022  * */
00023 /* ========================================================================= */
00024 #include <math.h>
00025 #include "EGlib.h"
00026 #include "mt_gomory.h"
00027 #include "mt_tableau.h"
00028 /** @file 
00029  * @ingroup MTgomory */
00030 /** @addtogroup MTgomory */
00031 /** @{ */
00032 /* ========================================================================= */
00033 int MTgomoryCut(const int nrows, 
00034                 const int ncols,
00035                 const double*const rowval,
00036                 const int*const rowind,
00037                 const int*const rowbeg,
00038                 const double*const f,
00039                 const double*const base,
00040                 double*const cutval,
00041                 double*const work)
00042 {
00043   int rval = 0,redo,pos,sense;
00044   register int i,j;
00045   EGgcIt_t gc;
00046   double ratio = 0;
00047   #if MT_DEBUG_LVL +5 <= DEBUG
00048   FILE* fout = EGsfopen("cur_tableau.txt","w+");
00049   rval = MTwriteRTableau(fout, nrows, ncols, rowval, rowind, rowbeg, f);
00050   CHECKRVALG(rval,CLEANUP);
00051   fclose(fout);
00052   #endif
00053   memset(&gc,0,sizeof(EGgcIt_t));
00054   /* check for basic assumptions in the function */
00055   if(MT_DEBUG_LVL <= DEBUG)
00056   {
00057     for(i = nrows ; i-- ; )
00058     {
00059       TESTG((rval=(fabs(base[i])<MT_ZERO_TOL)), CLEANUP, 
00060             "coefficient %d in base is %.12lf<%.12lf, and is considered"
00061             " as zero!", i, base[i], MT_ZERO_TOL);
00062       TESTG((rval=(f[i]<=(-0x1p-1+MT_ZERO_TOL))), CLEANUP, 
00063             "%d-th fractional value is outside bounds %lf <= %lf", 
00064             i, f[i], (-0x1p-1+MT_ZERO_TOL));
00065       TESTG((rval=(f[i]>=(0x1p-1-MT_ZERO_TOL))), CLEANUP, 
00066             "%d-th fractional value is outside bounds %lf >= %lf", 
00067             i, f[i], (0x1p-1-MT_ZERO_TOL));
00068     }
00069   }
00070   /* allocate memory */
00071   EGgcItInit(&gc,nrows);
00072   /* compute work[j] = col[j]*c and initialize cut coefficient */
00073   for( j = ncols ; j-- ; )
00074   {
00075     cutval[j]=0.0;
00076     work[j]=0.0;
00077   }
00078   work[ncols] = 0;
00079   for( j = nrows ; j-- ; )
00080   {
00081     /* compute in work[ncols] = 1/2 *base -f* \sigma * base */
00082     MESSAGE(MT_VERB_LVL+5,"j=%d, work[ncols]=%.6lf", j, work[ncols]);
00083     sense = ((EGgcItGetTuple(&gc))[j]);
00084     if(sense) work[ncols] += (0.5-f[j])*base[j];
00085     else work[ncols] += (0.5+f[j])*base[j];
00086     /* compute in work [i] col_i * \sigma * base */
00087     for( i = rowbeg[j] ; i < rowbeg[j+1] ;i++)
00088     {
00089       if(MT_VERB_LVL) ratio = work[rowind[i]];
00090       if(sense) work[rowind[i]] += base[j]*rowval[i];
00091       else work[rowind[i]] -= base[j]*rowval[i];
00092       MESSAGE(MT_VERB_LVL+5, "updating for row %d work[%d] from %lf to "
00093               "%lf", j, rowind[i], ratio, work[rowind[i]]);
00094     }
00095   }
00096   /* now we start computing the coefficients */
00097   do{
00098     if(MT_VERB_LVL+7 <= DEBUG)
00099     {
00100       const int*const tuple = EGgcItGetTuple(&gc);
00101       const int sz = EGgcItGetSize(&gc);
00102       fprintf(stderr,"Sign Patter: ");
00103       for( i = 0 ; i < sz ; i++)
00104       {
00105         fprintf(stderr,"%s",tuple[i]?"+":"-");
00106       }
00107       fprintf(stderr," work[ncols]=%.6lf\n",work[ncols]);
00108     }
00109     TESTG((rval=(work[ncols]<0)), CLEANUP, "Imposible!, n/2-base*sigma*f"
00110           " (%.6lf) < 0",work[ncols]);
00111     for( i = ncols ; i-- ; )
00112     {
00113       ratio = work[i]/work[ncols];
00114       if((work[i]>MT_ZERO_TOL) && (cutval[i]<ratio))
00115       {
00116         cutval[i] = ratio;
00117         MESSAGE(MT_VERB_LVL+7,"cutval[%d]=%lf, %lf/%lf=%lf", i, cutval[i], 
00118                 work[i], work[ncols], ratio);
00119       }
00120     }
00121     redo = EGgcItNext(&gc);
00122     if(!redo) break;
00123     /* now we should re-compute work[*] */
00124     pos = EGgcItGetChange(&gc);
00125     sense = ((EGgcItGetTuple(&gc))[pos]);
00126     if(sense)
00127     {
00128       work[ncols] -= 2*base[pos]*f[pos];
00129       for( i = rowbeg[pos] ; i < rowbeg[pos+1] ;i++)
00130         work[rowind[i]] += 2*base[pos]*rowval[i];
00131     }
00132     else
00133     {
00134       work[ncols] += 2*base[pos]*f[pos];
00135       for( i = rowbeg[pos] ; i < rowbeg[pos+1] ;i++)
00136         work[rowind[i]] -= 2*base[pos]*rowval[i];
00137     }
00138   }while(1);
00139   CLEANUP:
00140   EGgcItClear(&gc);
00141   return rval;
00142 }
00143 
00144 /* ========================================================================= */
00145 /** @} */
00146 /* end of mt_gomory.c */

Generated on Mon Oct 26 09:16:29 2009 for MTgomory by  doxygen 1.4.6