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 "mt_T1.h"
00025
00026
00027
00028
00029
00030 int MTt1Cut(const MTrowmatrix_t*const tb,
00031 MTlp_t*const lp,
00032 MTcutHeap_t*const cuth,
00033 const double*const f,
00034 double*const cutval,
00035 double*const work,
00036 const int cut_style)
00037 {
00038 const int nrows = tb->nrows;
00039 const int ncols = tb->ncols;
00040 const double*const rowval = tb->rowval;
00041 const int*const rowind = tb->rowind;
00042 const int*const rowbeg = tb->rowbeg;
00043 int rval=0,pos,sense,redo, cur_tabrow = nrows;
00044 int*active = EGsMalloc(int,ncols);
00045 int nactive = 0, status;
00046 MTcut_t*cut = 0;
00047 register int i,j;
00048 EGgcIt_t gc;
00049 double ratio = 0;
00050 #if MT_DEBUG_LVL +5 <= DEBUG
00051 FILE* fout = EGsfopen("cur_tableau.txt","w+");
00052 rval = MTwriteRTableau(fout, nrows, ncols, rowval, rowind, rowbeg, f);
00053 CHECKRVALG(rval,CLEANUP);
00054 fclose(fout);
00055 #endif
00056 memset(&gc,0,sizeof(EGgcIt_t));
00057
00058 if(MT_DEBUG_LVL <= DEBUG)
00059 {
00060 for(i = nrows ; i-- ; )
00061 {
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
00072 memset(active,0,sizeof(int)*((size_t)ncols));
00073 for( i = rowbeg[nrows] ; i-- ;) active[rowind[i]] = 1;
00074 for(nactive=0, i = 0 ; i < ncols ; i++)
00075 if(active[i]) active[nactive++] = i;
00076 MESSAGE(MT_VERB_LVL,"Active cols %.3lf%%",100*((double)nactive)/ncols);
00077
00078 REDO:
00079 EGgcItInit(&gc,cur_tabrow);
00080 for( i = ncols ; i-- ; ) work[i] = 0.0;
00081 work[ncols] = 0.5*cur_tabrow;
00082
00083
00084 for( j = cur_tabrow ; j-- ; )
00085 {
00086 sense = ((EGgcItGetTuple(&gc))[j]);
00087 if(sense){
00088 work[ncols] -= f[j];
00089 for( i = rowbeg[j] ; i < rowbeg[j+1] ; i++)
00090 work[rowind[i]] += rowval[i];
00091 }
00092 else
00093 {
00094 work[ncols] += f[j];
00095 for( i = rowbeg[j] ; i < rowbeg[j+1] ; i++)
00096 work[rowind[i]] -= rowval[i];
00097 }
00098 }
00099
00100 do
00101 {
00102 TESTG((rval=(work[ncols]<0)), CLEANUP, "Imposible!, n/2-sigma*f"
00103 " (%.6lf) < 0",work[ncols]);
00104
00105 for( i = ncols ; i-- ; ) cutval[i] = work[i] > MT_ZERO_TOL ? work[i]/work[ncols]:0.0;
00106 for( j = cur_tabrow ; j-- ; )
00107 {
00108 sense = ((EGgcItGetTuple(&gc))[j]);
00109 if(sense)
00110 {
00111 for( i = rowbeg[j] ; i < rowbeg[j+1] ; i++)
00112 {
00113 if((rowval[i] < -MT_ZERO_TOL) &&
00114 ((ratio = rowval[i]/(-0.5-f[j])) > cutval[rowind[i]]))
00115 cutval[rowind[i]] = ratio;
00116 }
00117 }
00118 else
00119 {
00120 for( i = rowbeg[j] ; i < rowbeg[j+1] ; i++)
00121 {
00122 if((rowval[i] > MT_ZERO_TOL) &&
00123 ((ratio = rowval[i]/(0.5-f[j])) > cutval[rowind[i]]))
00124 cutval[rowind[i]] = ratio;
00125 }
00126 }
00127 }
00128
00129 cut = MTcutHeap_get_free_cut(cuth);
00130 rval = MTraw_to_uncomplemented_cut( lp, cutval, nactive, active, cut, &status);
00131 CHECKRVALG(rval,CLEANUP);
00132 if(status) goto NEXT;
00133
00134 rval = MTcutHeap_add_cut(lp,cuth);
00135 CHECKRVALG(rval,CLEANUP);
00136
00137 NEXT:
00138 redo = EGgcItNext(&gc);
00139 if(!redo) break;
00140
00141 pos = EGgcItGetChange(&gc);
00142 sense = ((EGgcItGetTuple(&gc))[pos]);
00143 if(sense)
00144 {
00145 work[ncols] -= 2*f[pos];
00146 for( i = rowbeg[pos] ; i < rowbeg[pos+1] ; i++)
00147 work[rowind[i]] += 2*rowval[i];
00148 }
00149 else
00150 {
00151 work[ncols] += 2*f[pos];
00152 for( i = rowbeg[pos] ; i < rowbeg[pos+1] ; i++)
00153 work[rowind[i]] -= 2*rowval[i];
00154 }
00155 }while(1);
00156 EGgcItClear(&gc);
00157 if(cut_style && cur_tabrow > 2)
00158 {
00159 cur_tabrow--;
00160 EGgcItClear(&gc);
00161 goto REDO;
00162 }
00163 CLEANUP:
00164 EGgcItClear(&gc);
00165 EGfree(active);
00166 return rval;
00167 }
00168
00169 int MTt1_ccbk(CPXCENVptr env,
00170 void*cbdata,
00171 int wherefrom,
00172 void*cbhandle,
00173 int*useraction_p)
00174 {
00175 MTgomory_ccbk_t*const data=(MTgomory_ccbk_t*)cbhandle;
00176 MTcutHeap_t*const cuth = &(data->cuth);
00177 MTcut_t*cut=0;
00178 int rval = 0, action = 0;
00179 CPXLPptr lp = 0;
00180 int ncols,nrows;
00181
00182 MESSAGE(MT_VERB_LVL,"Entering");
00183 *useraction_p = CPX_CALLBACK_DEFAULT;
00184
00185 rval = MTccbk_info_process(&(data->info), env, cbdata, wherefrom, &action);
00186 CHECKRVALG(rval,CLEANUP);
00187 if(action) goto CLEANUP;
00188
00189 rval = CPXgetcallbacknodelp (env, cbdata, wherefrom, &lp);
00190 MTcplexCHECKRVALG(env,rval,CLEANUP);
00191
00192 if(MT_VERB_LVL +5 <= DEBUG)
00193 {
00194 rval = CPXwriteprob(env,lp,"node_lp.lp.gz","LP");
00195 MTcplexCHECKRVALG(env,rval,CLEANUP);
00196 }
00197
00198 rval = MTlp_load_problem(env, &(data->lp), lp, cbdata, wherefrom);
00199 CHECKRVALG(rval,CLEANUP);
00200
00201 ncols = CPXgetnumcols(env,lp);
00202 nrows = CPXgetnumrows(env,lp);
00203 MESSAGE(MT_VERB_LVL+3,"Problem has %d vars and %d constr",ncols,nrows);
00204
00205 rval = EGmax(nrows,ncols);
00206 MTgomory_ccbk_rsz(data,nrows,ncols+nrows,rval);
00207
00208 rval = MTget_sol(&(data->lp), env, lp, cbdata, wherefrom, &(data->sol));
00209 CHECKRVALG(rval,CLEANUP);
00210
00211 if(MT_VERB_LVL + 10 <= DEBUG)
00212 MTdisplay_lp(&(data->lp), &(data->sol), stderr);
00213
00214 rval = MTget_best_k_tableau_rows( &(data->lp), &(data->sol),
00215 data->info.max_rows, env, lp,
00216 &(data->tb), data->f);
00217 CHECKRVALG(rval,CLEANUP);
00218 if(!data->tb.nrows) goto CLEANUP;
00219
00220 rval = MTt1Cut( &(data->tb), &(data->lp), cuth, data->f,
00221 data->extcut, data->work, data->info.cut_style);
00222 CHECKRVALG(rval,CLEANUP);
00223
00224 data->info.added_cuts += MTcutHeap_get_ncuts(cuth);
00225 data->info.node_cuts += MTcutHeap_get_ncuts(cuth);
00226
00227 while((cut=MTcutHeap_pop_cut(cuth)))
00228 {
00229 rval = MTuncomplemented_to_complemented_cut(&(data->lp), &(data->sol), cut);
00230 CHECKRVALG(rval,CLEANUP);
00231
00232 if(MT_DEBUG_LVL + 10 <= DEBUG)
00233 {
00234 rval = MTcplex_test_cut(cut, &(data->lp));
00235 CHECKRVALG(rval,CLEANUP);
00236 }
00237 rval = CPXcutcallbackaddlocal( env, cbdata, wherefrom, cut->nz, cut->rhs,
00238 cut->sense , cut->cutind, cut->cutval);
00239 MTcplexCHECKRVALG(env,rval,CLEANUP);
00240 MESSAGE(MT_VERB_LVL, "Node %zd LP:(%d,%d,%d) Constr: %d nz, %.2lf rhs,"
00241 " ratio %.2lf, violation (>0) %lf", data->info.node_cnt,
00242 data->lp.nrows, data->lp.ncols, data->lp.nz, cut->nz, cut->rhs,
00243 cut->max_abs/cut->min_abs, cut->violation);
00244 }
00245 CLEANUP:
00246 MESSAGE(MT_VERB_LVL,"Done, status %d",rval);
00247 return rval;
00248 }
00249
00250
00251