00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <math.h>
00025 #include "EGlib.h"
00026 #include "mt_gomory.h"
00027 #include "mt_tableau.h"
00028
00029
00030
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
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
00071 EGgcItInit(&gc,nrows);
00072
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
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
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
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
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